[api] expose API for adding per-context Intrinsics to Templates
Add mechanism for adding per-context ECMAScript intrinsics to Template objects, which may be instantiated in multiple contexts. BUG= LOG=N R=jochen@chromium.org, verwaest@chromium.org Review URL: https://codereview.chromium.org/1409593002 Cr-Commit-Position: refs/heads/master@{#31450}
This commit is contained in:
parent
d3a1fa0be0
commit
1be2b46c85
16
include/v8.h
16
include/v8.h
@ -4008,6 +4008,15 @@ class V8_EXPORT External : public Value {
|
||||
};
|
||||
|
||||
|
||||
#define V8_INTRINSICS_LIST(F) F(ArrayProto_values, array_values_iterator)
|
||||
|
||||
enum Intrinsic {
|
||||
#define V8_DECL_INTRINSIC(name, iname) k##name,
|
||||
V8_INTRINSICS_LIST(V8_DECL_INTRINSIC)
|
||||
#undef V8_DECL_INTRINSIC
|
||||
};
|
||||
|
||||
|
||||
// --- Templates ---
|
||||
|
||||
|
||||
@ -4077,6 +4086,13 @@ class V8_EXPORT Template : public Data {
|
||||
Local<AccessorSignature> signature = Local<AccessorSignature>(),
|
||||
AccessControl settings = DEFAULT);
|
||||
|
||||
/**
|
||||
* During template instantiation, sets the value with the intrinsic property
|
||||
* from the correct context.
|
||||
*/
|
||||
void SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic,
|
||||
PropertyAttribute attribute = None);
|
||||
|
||||
private:
|
||||
Template();
|
||||
|
||||
|
@ -148,6 +148,20 @@ class AccessCheckDisableScope {
|
||||
};
|
||||
|
||||
|
||||
Object* GetIntrinsic(Isolate* isolate, v8::Intrinsic intrinsic) {
|
||||
Handle<Context> native_context = isolate->native_context();
|
||||
DCHECK(!native_context.is_null());
|
||||
switch (intrinsic) {
|
||||
#define GET_INTRINSIC_VALUE(name, iname) \
|
||||
case v8::k##name: \
|
||||
return native_context->iname();
|
||||
V8_INTRINSICS_LIST(GET_INTRINSIC_VALUE)
|
||||
#undef GET_INTRINSIC_VALUE
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
|
||||
Handle<TemplateInfo> data) {
|
||||
auto property_list = handle(data->property_list(), isolate);
|
||||
@ -162,23 +176,40 @@ MaybeHandle<JSObject> ConfigureInstance(Isolate* isolate, Handle<JSObject> obj,
|
||||
int i = 0;
|
||||
for (int c = 0; c < data->number_of_properties(); c++) {
|
||||
auto name = handle(Name::cast(properties.get(i++)), isolate);
|
||||
PropertyDetails details(Smi::cast(properties.get(i++)));
|
||||
PropertyAttributes attributes = details.attributes();
|
||||
PropertyKind kind = details.kind();
|
||||
auto bit = handle(properties.get(i++), isolate);
|
||||
if (bit->IsSmi()) {
|
||||
PropertyDetails details(Smi::cast(*bit));
|
||||
PropertyAttributes attributes = details.attributes();
|
||||
PropertyKind kind = details.kind();
|
||||
|
||||
if (kind == kData) {
|
||||
auto prop_data = handle(properties.get(i++), isolate);
|
||||
if (kind == kData) {
|
||||
auto prop_data = handle(properties.get(i++), isolate);
|
||||
|
||||
RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
|
||||
prop_data, attributes),
|
||||
JSObject);
|
||||
} else {
|
||||
auto getter = handle(properties.get(i++), isolate);
|
||||
auto setter = handle(properties.get(i++), isolate);
|
||||
RETURN_ON_EXCEPTION(isolate,
|
||||
DefineAccessorProperty(isolate, obj, name, getter,
|
||||
setter, attributes),
|
||||
JSObject);
|
||||
}
|
||||
} else {
|
||||
// Intrinsic data property --- Get appropriate value from the current
|
||||
// context.
|
||||
PropertyDetails details(Smi::cast(properties.get(i++)));
|
||||
PropertyAttributes attributes = details.attributes();
|
||||
DCHECK_EQ(kData, details.kind());
|
||||
|
||||
v8::Intrinsic intrinsic =
|
||||
static_cast<v8::Intrinsic>(Smi::cast(properties.get(i++))->value());
|
||||
auto prop_data = handle(GetIntrinsic(isolate, intrinsic), isolate);
|
||||
|
||||
RETURN_ON_EXCEPTION(isolate, DefineDataProperty(isolate, obj, name,
|
||||
prop_data, attributes),
|
||||
JSObject);
|
||||
} else {
|
||||
auto getter = handle(properties.get(i++), isolate);
|
||||
auto setter = handle(properties.get(i++), isolate);
|
||||
RETURN_ON_EXCEPTION(isolate,
|
||||
DefineAccessorProperty(isolate, obj, name, getter,
|
||||
setter, attributes),
|
||||
JSObject);
|
||||
}
|
||||
}
|
||||
return obj;
|
||||
@ -377,6 +408,19 @@ void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
|
||||
}
|
||||
|
||||
|
||||
void ApiNatives::AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
|
||||
Handle<Name> name, v8::Intrinsic intrinsic,
|
||||
PropertyAttributes attributes) {
|
||||
const int kSize = 4;
|
||||
auto value = handle(Smi::FromInt(intrinsic), isolate);
|
||||
auto intrinsic_marker = isolate->factory()->true_value();
|
||||
PropertyDetails details(attributes, DATA, 0, PropertyCellType::kNoCell);
|
||||
auto details_handle = handle(details.AsSmi(), isolate);
|
||||
Handle<Object> data[kSize] = {name, intrinsic_marker, details_handle, value};
|
||||
AddPropertyToPropertyList(isolate, info, kSize, data);
|
||||
}
|
||||
|
||||
|
||||
void ApiNatives::AddAccessorProperty(Isolate* isolate,
|
||||
Handle<TemplateInfo> info,
|
||||
Handle<Name> name, Handle<Object> getter,
|
||||
|
@ -44,6 +44,10 @@ class ApiNatives {
|
||||
Handle<Name> name, Handle<Object> value,
|
||||
PropertyAttributes attributes);
|
||||
|
||||
static void AddDataProperty(Isolate* isolate, Handle<TemplateInfo> info,
|
||||
Handle<Name> name, v8::Intrinsic intrinsic,
|
||||
PropertyAttributes attributes);
|
||||
|
||||
static void AddAccessorProperty(Isolate* isolate, Handle<TemplateInfo> info,
|
||||
Handle<Name> name, Handle<Object> getter,
|
||||
Handle<Object> setter,
|
||||
|
12
src/api.cc
12
src/api.cc
@ -1352,6 +1352,18 @@ void Template::SetNativeDataProperty(v8::Local<Name> name,
|
||||
}
|
||||
|
||||
|
||||
void Template::SetIntrinsicDataProperty(Local<Name> name, Intrinsic intrinsic,
|
||||
PropertyAttribute attribute) {
|
||||
auto templ = Utils::OpenHandle(this);
|
||||
i::Isolate* isolate = templ->GetIsolate();
|
||||
ENTER_V8(isolate);
|
||||
i::HandleScope scope(isolate);
|
||||
i::ApiNatives::AddDataProperty(isolate, templ, Utils::OpenHandle(*name),
|
||||
intrinsic,
|
||||
static_cast<PropertyAttributes>(attribute));
|
||||
}
|
||||
|
||||
|
||||
void ObjectTemplate::SetAccessor(v8::Local<String> name,
|
||||
AccessorGetterCallback getter,
|
||||
AccessorSetterCallback setter,
|
||||
|
@ -10382,7 +10382,9 @@ class TemplateInfo: public Struct {
|
||||
static const int kPropertyListOffset = kNumberOfProperties + kPointerSize;
|
||||
static const int kPropertyAccessorsOffset =
|
||||
kPropertyListOffset + kPointerSize;
|
||||
static const int kHeaderSize = kPropertyAccessorsOffset + kPointerSize;
|
||||
static const int kPropertyIntrinsicsOffset =
|
||||
kPropertyAccessorsOffset + kPointerSize;
|
||||
static const int kHeaderSize = kPropertyIntrinsicsOffset + kPointerSize;
|
||||
|
||||
private:
|
||||
DISALLOW_IMPLICIT_CONSTRUCTORS(TemplateInfo);
|
||||
|
@ -21921,3 +21921,36 @@ TEST(AccessCheckedIsConcatSpreadable) {
|
||||
ExpectTrue("result.length === 1");
|
||||
ExpectTrue("object[Symbol.isConcatSpreadable] === undefined");
|
||||
}
|
||||
|
||||
|
||||
TEST(ObjectTemplateIntrinsics) {
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
LocalContext env;
|
||||
|
||||
Local<ObjectTemplate> object_template = v8::ObjectTemplate::New(isolate);
|
||||
object_template->SetIntrinsicDataProperty(v8_str("values"),
|
||||
v8::kArrayProto_values);
|
||||
Local<Object> object = object_template->NewInstance();
|
||||
|
||||
env->Global()->Set(v8_str("obj1"), object);
|
||||
ExpectString("typeof obj1.values", "function");
|
||||
|
||||
auto values = Local<Function>::Cast(object->Get(v8_str("values")));
|
||||
auto fn = v8::Utils::OpenHandle(*values);
|
||||
auto ctx = v8::Utils::OpenHandle(*env.local());
|
||||
CHECK_EQ(fn->GetCreationContext(), *ctx);
|
||||
|
||||
{
|
||||
LocalContext env2;
|
||||
Local<Object> object2 = object_template->NewInstance();
|
||||
env2->Global()->Set(v8_str("obj2"), object2);
|
||||
ExpectString("typeof obj2.values", "function");
|
||||
CHECK_NE(*object->Get(v8_str("values")), *object2->Get(v8_str("values")));
|
||||
|
||||
auto values2 = Local<Function>::Cast(object2->Get(v8_str("values")));
|
||||
auto fn2 = v8::Utils::OpenHandle(*values2);
|
||||
auto ctx2 = v8::Utils::OpenHandle(*env2.local());
|
||||
CHECK_EQ(fn2->GetCreationContext(), *ctx2);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user