| Index: src/api-natives.cc
|
| diff --git a/src/api-natives.cc b/src/api-natives.cc
|
| index fdf2c81d87f6f8b865e2db95a28848667fe42526..f09f42d5f0480f76b8d6ac4c0e54efb0f6a9314e 100644
|
| --- a/src/api-natives.cc
|
| +++ b/src/api-natives.cc
|
| @@ -371,12 +371,43 @@
|
| return handle(JSFunction::cast(element), isolate);
|
| }
|
| }
|
| -
|
| // Enter a new scope. Recursion could otherwise create a lot of handles.
|
| HandleScope scope(isolate);
|
| -
|
| - auto function =
|
| - ApiNatives::CreateApiFunction(isolate, data, JS_API_OBJECT_TYPE);
|
| + Handle<JSObject> prototype;
|
| + if (!data->remove_prototype()) {
|
| + auto prototype_templ = handle(data->prototype_template(), isolate);
|
| + if (prototype_templ->IsUndefined(isolate)) {
|
| + prototype = isolate->factory()->NewJSObject(isolate->object_function());
|
| + } else {
|
| + ASSIGN_RETURN_ON_EXCEPTION(
|
| + isolate, prototype,
|
| + InstantiateObject(isolate,
|
| + Handle<ObjectTemplateInfo>::cast(prototype_templ),
|
| + Handle<JSReceiver>(), data->hidden_prototype()),
|
| + JSFunction);
|
| + }
|
| + auto parent = handle(data->parent_template(), isolate);
|
| + if (!parent->IsUndefined(isolate)) {
|
| + Handle<JSFunction> parent_instance;
|
| + ASSIGN_RETURN_ON_EXCEPTION(
|
| + isolate, parent_instance,
|
| + InstantiateFunction(isolate,
|
| + Handle<FunctionTemplateInfo>::cast(parent)),
|
| + JSFunction);
|
| + // TODO(dcarney): decide what to do here.
|
| + Handle<Object> parent_prototype;
|
| + ASSIGN_RETURN_ON_EXCEPTION(
|
| + isolate, parent_prototype,
|
| + JSObject::GetProperty(parent_instance,
|
| + isolate->factory()->prototype_string()),
|
| + JSFunction);
|
| + MAYBE_RETURN(JSObject::SetPrototype(prototype, parent_prototype, false,
|
| + Object::THROW_ON_ERROR),
|
| + MaybeHandle<JSFunction>());
|
| + }
|
| + }
|
| + auto function = ApiNatives::CreateApiFunction(
|
| + isolate, data, prototype, ApiNatives::JavaScriptObjectType);
|
| if (!name.is_null() && name->IsString()) {
|
| function->shared()->set_name(*name);
|
| }
|
| @@ -502,17 +533,20 @@
|
| array.add(isolate, property);
|
| }
|
|
|
| +
|
| Handle<JSFunction> ApiNatives::CreateApiFunction(
|
| - Isolate* isolate, Handle<FunctionTemplateInfo> obj, InstanceType type) {
|
| + Isolate* isolate, Handle<FunctionTemplateInfo> obj,
|
| + Handle<Object> prototype, ApiInstanceType instance_type) {
|
| Handle<SharedFunctionInfo> shared =
|
| FunctionTemplateInfo::GetOrCreateSharedFunctionInfo(isolate, obj);
|
| - DCHECK(shared->IsApiFunction());
|
| Handle<JSFunction> result =
|
| isolate->factory()->NewFunctionFromSharedFunctionInfo(
|
| shared, isolate->native_context());
|
|
|
| if (obj->remove_prototype()) {
|
| result->set_map(*isolate->sloppy_function_without_prototype_map());
|
| + DCHECK(prototype.is_null());
|
| + DCHECK(result->shared()->IsApiFunction());
|
| DCHECK(!result->has_initial_map());
|
| DCHECK(!result->has_prototype());
|
| DCHECK(!result->IsConstructor());
|
| @@ -522,81 +556,78 @@
|
| // Down from here is only valid for API functions that can be used as a
|
| // constructor (don't set the "remove prototype" flag).
|
|
|
| - // Set up function.prototype.
|
| - Handle<JSObject> prototype;
|
| - auto prototype_templ = handle(obj->prototype_template(), isolate);
|
| - if (type != JS_API_OBJECT_TYPE || prototype_templ->IsUndefined(isolate)) {
|
| + if (obj->read_only_prototype()) {
|
| + result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
|
| + }
|
| +
|
| + if (prototype->IsTheHole(isolate)) {
|
| prototype = isolate->factory()->NewFunctionPrototype(result);
|
| } else {
|
| - prototype = internal::InstantiateObject(
|
| - isolate, Handle<ObjectTemplateInfo>::cast(prototype_templ),
|
| - Handle<JSReceiver>(), obj->hidden_prototype())
|
| - .ToHandleChecked();
|
| -
|
| JSObject::AddProperty(Handle<JSObject>::cast(prototype),
|
| isolate->factory()->constructor_string(), result,
|
| DONT_ENUM);
|
| }
|
| - // Set up function.prototype.__proto__.
|
| - auto parent = handle(obj->parent_template(), isolate);
|
| - if (!parent->IsUndefined(isolate)) {
|
| - Handle<JSFunction> parent_instance =
|
| - internal::InstantiateFunction(
|
| - isolate, Handle<FunctionTemplateInfo>::cast(parent))
|
| - .ToHandleChecked();
|
| - Handle<Object> parent_prototype =
|
| - JSFunction::GetPrototype(isolate, parent_instance);
|
| - CHECK(JSObject::SetPrototype(prototype, parent_prototype, false,
|
| - Object::THROW_ON_ERROR)
|
| - .IsJust());
|
| - }
|
| -
|
| - if (obj->read_only_prototype()) {
|
| - result->set_map(*isolate->sloppy_function_with_readonly_prototype_map());
|
| - }
|
| -
|
| - // Set up the function's initial map.
|
| +
|
| int internal_field_count = 0;
|
| if (!obj->instance_template()->IsUndefined(isolate)) {
|
| - Handle<ObjectTemplateInfo> instance_template(
|
| + Handle<ObjectTemplateInfo> instance_template = Handle<ObjectTemplateInfo>(
|
| ObjectTemplateInfo::cast(obj->instance_template()));
|
| internal_field_count =
|
| Smi::cast(instance_template->internal_field_count())->value();
|
| }
|
|
|
| + // TODO(svenpanne) Kill ApiInstanceType and refactor things by generalizing
|
| + // JSObject::GetHeaderSize.
|
| int instance_size = kPointerSize * internal_field_count;
|
| - switch (type) {
|
| - case JS_API_OBJECT_TYPE:
|
| - if (obj->needs_access_check() ||
|
| - !obj->named_property_handler()->IsUndefined(isolate) ||
|
| - !obj->indexed_property_handler()->IsUndefined(isolate)) {
|
| + InstanceType type;
|
| + switch (instance_type) {
|
| + case JavaScriptObjectType:
|
| + if (!obj->needs_access_check() &&
|
| + obj->named_property_handler()->IsUndefined(isolate) &&
|
| + obj->indexed_property_handler()->IsUndefined(isolate)) {
|
| + type = JS_API_OBJECT_TYPE;
|
| + } else {
|
| type = JS_SPECIAL_API_OBJECT_TYPE;
|
| }
|
| instance_size += JSObject::kHeaderSize;
|
| break;
|
| - case JS_GLOBAL_OBJECT_TYPE:
|
| + case GlobalObjectType:
|
| + type = JS_GLOBAL_OBJECT_TYPE;
|
| instance_size += JSGlobalObject::kSize;
|
| break;
|
| - case JS_GLOBAL_PROXY_TYPE:
|
| + case GlobalProxyType:
|
| + type = JS_GLOBAL_PROXY_TYPE;
|
| instance_size += JSGlobalProxy::kSize;
|
| break;
|
| default:
|
| UNREACHABLE();
|
| + type = JS_OBJECT_TYPE; // Keep the compiler happy.
|
| break;
|
| }
|
|
|
| Handle<Map> map =
|
| isolate->factory()->NewMap(type, instance_size, FAST_HOLEY_SMI_ELEMENTS);
|
| - JSFunction::SetInitialMap(result, map, prototype);
|
| -
|
| - if (obj->undetectable()) map->set_is_undetectable();
|
| - if (obj->needs_access_check()) map->set_is_access_check_needed(true);
|
| + JSFunction::SetInitialMap(result, map, Handle<JSObject>::cast(prototype));
|
| +
|
| + // Mark as undetectable if needed.
|
| + if (obj->undetectable()) {
|
| + map->set_is_undetectable();
|
| + }
|
| +
|
| + // Mark as needs_access_check if needed.
|
| + if (obj->needs_access_check()) {
|
| + map->set_is_access_check_needed(true);
|
| + }
|
| +
|
| + // Set interceptor information in the map.
|
| if (!obj->named_property_handler()->IsUndefined(isolate)) {
|
| map->set_has_named_interceptor();
|
| }
|
| if (!obj->indexed_property_handler()->IsUndefined(isolate)) {
|
| map->set_has_indexed_interceptor();
|
| }
|
| +
|
| + // Mark instance as callable in the map.
|
| if (!obj->instance_call_handler()->IsUndefined(isolate)) {
|
| map->set_is_callable();
|
| map->set_is_constructor(true);
|
|
|