[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:
caitpotter88 2015-10-21 13:14:27 -07:00 committed by Commit bot
parent d3a1fa0be0
commit 1be2b46c85
6 changed files with 124 additions and 13 deletions

View File

@ -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();

View File

@ -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,

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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);
}
}