| Index: src/bootstrapper.cc
|
| ===================================================================
|
| --- src/bootstrapper.cc (revision 539)
|
| +++ src/bootstrapper.cc (working copy)
|
| @@ -275,7 +275,9 @@
|
| bool InstallExtension(const char* name);
|
| bool InstallExtension(v8::RegisteredExtension* current);
|
| bool InstallSpecialObjects();
|
| - bool ConfigureGlobalObject(v8::Handle<v8::ObjectTemplate> global_template);
|
| + bool ConfigureApiObject(Handle<JSObject> object,
|
| + Handle<ObjectTemplateInfo> object_template);
|
| + bool ConfigureGlobalObjects(v8::Handle<v8::ObjectTemplate> global_template);
|
|
|
| // Migrates all properties from the 'from' object to the 'to'
|
| // object and overrides the prototype in 'to' with the one from
|
| @@ -337,11 +339,30 @@
|
| }
|
|
|
|
|
| +static void SetObjectPrototype(Handle<JSObject> object, Handle<Object> proto) {
|
| + // object.__proto__ = proto;
|
| + Handle<Map> old_to_map = Handle<Map>(object->map());
|
| + Handle<Map> new_to_map = Factory::CopyMapDropTransitions(old_to_map);
|
| + new_to_map->set_prototype(*proto);
|
| + object->set_map(*new_to_map);
|
| +}
|
| +
|
| +
|
| +void Bootstrapper::DetachGlobal(Handle<Context> env) {
|
| + JSGlobalProxy::cast(env->global_proxy())->set_context(*Factory::null_value());
|
| + SetObjectPrototype(Handle<JSObject>(env->global_proxy()),
|
| + Factory::null_value());
|
| + env->set_global_proxy(env->global());
|
| + env->global()->set_global_receiver(env->global());
|
| +}
|
| +
|
| +
|
| Genesis::~Genesis() {
|
| ASSERT(current_ == this);
|
| current_ = previous_;
|
| }
|
|
|
| +
|
| static Handle<JSFunction> InstallFunction(Handle<JSObject> target,
|
| const char* name,
|
| InstanceType type,
|
| @@ -431,7 +452,6 @@
|
| global_context_ =
|
| Handle<Context>::cast(
|
| GlobalHandles::Create(*Factory::NewGlobalContext()));
|
| - Top::set_security_context(*global_context());
|
| Top::set_context(*global_context());
|
|
|
| // Allocate the message listeners object.
|
| @@ -506,55 +526,101 @@
|
| }
|
|
|
| { // --- G l o b a l ---
|
| - Handle<String> global_name = Factory::LookupAsciiSymbol("global");
|
| - Handle<JSFunction> global_function;
|
|
|
| - if (global_template.IsEmpty()) {
|
| - Handle<String> name = Handle<String>(Heap::empty_symbol());
|
| - Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
|
| - global_function = Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
|
| - JSGlobalObject::kSize, code, true);
|
| - // Change the constructor property of the prototype of the
|
| - // hidden global function to refer to the Object function.
|
| - Handle<JSObject> prototype =
|
| - Handle<JSObject>(
|
| - JSObject::cast(global_function->instance_prototype()));
|
| - SetProperty(prototype, Factory::constructor_symbol(),
|
| - Top::object_function(), NONE);
|
| - } else {
|
| - Handle<ObjectTemplateInfo> data = v8::Utils::OpenHandle(*global_template);
|
| - Handle<FunctionTemplateInfo> global_constructor =
|
| - Handle<FunctionTemplateInfo>(
|
| - FunctionTemplateInfo::cast(data->constructor()));
|
| - global_function = Factory::CreateApiFunction(global_constructor, true);
|
| - }
|
| + // Step 1: create a fresh inner JSGlobalObject
|
| + Handle<JSGlobalObject> object;
|
| + {
|
| + Handle<JSFunction> js_global_function;
|
| + Handle<ObjectTemplateInfo> js_global_template;
|
| + if (!global_template.IsEmpty()) {
|
| + // Get prototype template of the global_template
|
| + Handle<ObjectTemplateInfo> data =
|
| + v8::Utils::OpenHandle(*global_template);
|
| + Handle<FunctionTemplateInfo> global_constructor =
|
| + Handle<FunctionTemplateInfo>(
|
| + FunctionTemplateInfo::cast(data->constructor()));
|
| + Handle<Object> proto_template(global_constructor->prototype_template());
|
| + if (!proto_template->IsUndefined()) {
|
| + js_global_template =
|
| + Handle<ObjectTemplateInfo>::cast(proto_template);
|
| + }
|
| + }
|
|
|
| - SetExpectedNofProperties(global_function, 100);
|
| - global_function->shared()->set_instance_class_name(*global_name);
|
| - global_function->initial_map()->set_needs_access_check();
|
| + if (js_global_template.is_null()) {
|
| + Handle<String> name = Handle<String>(Heap::empty_symbol());
|
| + Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
|
| + js_global_function =
|
| + Factory::NewFunction(name, JS_GLOBAL_OBJECT_TYPE,
|
| + JSGlobalObject::kSize, code, true);
|
| + // Change the constructor property of the prototype of the
|
| + // hidden global function to refer to the Object function.
|
| + Handle<JSObject> prototype =
|
| + Handle<JSObject>(
|
| + JSObject::cast(js_global_function->instance_prototype()));
|
| + SetProperty(prototype, Factory::constructor_symbol(),
|
| + Top::object_function(), NONE);
|
| + } else {
|
| + Handle<FunctionTemplateInfo> js_global_constructor(
|
| + FunctionTemplateInfo::cast(js_global_template->constructor()));
|
| + js_global_function =
|
| + Factory::CreateApiFunction(js_global_constructor,
|
| + Factory::InnerGlobalObject);
|
| + }
|
|
|
| - Handle<JSGlobalObject> object;
|
| - if (global_object.location() != NULL) {
|
| - ASSERT(global_object->IsJSGlobalObject());
|
| - object =
|
| - ReinitializeJSGlobalObject(
|
| - global_function,
|
| - Handle<JSGlobalObject>::cast(global_object));
|
| - } else {
|
| - object =
|
| - Handle<JSGlobalObject>::cast(Factory::NewJSObject(global_function,
|
| - TENURED));
|
| + js_global_function->initial_map()->set_is_hidden_prototype();
|
| + SetExpectedNofProperties(js_global_function, 100);
|
| + object = Handle<JSGlobalObject>::cast(
|
| + Factory::NewJSObject(js_global_function, TENURED));
|
| }
|
|
|
| // Set the global context for the global object.
|
| object->set_global_context(*global_context());
|
|
|
| - // Security setup: Set the security token of the global object to
|
| - // its global context. This makes the security check between two
|
| - // different contexts fail by default even in case of global
|
| - // object reinitialization.
|
| - object->set_security_token(*global_context());
|
| + // Step 2: create or re-initialize the outer global object.
|
| + Handle<JSGlobalProxy> global_proxy;
|
| + {
|
| + Handle<JSFunction> global_proxy_function;
|
| + if (global_template.IsEmpty()) {
|
| + Handle<String> name = Handle<String>(Heap::empty_symbol());
|
| + Handle<Code> code = Handle<Code>(Builtins::builtin(Builtins::Illegal));
|
| + global_proxy_function =
|
| + Factory::NewFunction(name, JS_GLOBAL_PROXY_TYPE,
|
| + JSGlobalProxy::kSize, code, true);
|
| + } else {
|
| + Handle<ObjectTemplateInfo> data =
|
| + v8::Utils::OpenHandle(*global_template);
|
| + Handle<FunctionTemplateInfo> global_constructor(
|
| + FunctionTemplateInfo::cast(data->constructor()));
|
| + global_proxy_function =
|
| + Factory::CreateApiFunction(global_constructor,
|
| + Factory::OuterGlobalObject);
|
| + }
|
|
|
| + Handle<String> global_name = Factory::LookupAsciiSymbol("global");
|
| + global_proxy_function->shared()->set_instance_class_name(*global_name);
|
| + global_proxy_function->initial_map()->set_is_access_check_needed();
|
| +
|
| + // Set global_proxy.__proto__ to js_global after ConfigureGlobalObjects
|
| +
|
| + if (global_object.location() != NULL) {
|
| + ASSERT(global_object->IsJSGlobalProxy());
|
| + global_proxy =
|
| + ReinitializeJSGlobalProxy(
|
| + global_proxy_function,
|
| + Handle<JSGlobalProxy>::cast(global_object));
|
| + } else {
|
| + global_proxy = Handle<JSGlobalProxy>::cast(
|
| + Factory::NewJSObject(global_proxy_function, TENURED));
|
| + }
|
| +
|
| + // Security setup: Set the security token of the global object to
|
| + // its the inner global. This makes the security check between two
|
| + // different contexts fail by default even in case of global
|
| + // object reinitialization.
|
| + object->set_global_receiver(*global_proxy);
|
| + global_proxy->set_context(*global_context());
|
| + }
|
| +
|
| { // --- G l o b a l C o n t e x t ---
|
| // use the empty function as closure (no scope info)
|
| global_context()->set_closure(*empty_function);
|
| @@ -564,6 +630,9 @@
|
| // set extension and global object
|
| global_context()->set_extension(*object);
|
| global_context()->set_global(*object);
|
| + global_context()->set_global_proxy(*global_proxy);
|
| + // use inner global object as security token by default
|
| + global_context()->set_security_token(*object);
|
| }
|
|
|
| Handle<JSObject> global = Handle<JSObject>(global_context()->global());
|
| @@ -835,6 +904,7 @@
|
| TENURED));
|
| builtins->set_builtins(*builtins);
|
| builtins->set_global_context(*global_context());
|
| + builtins->set_global_receiver(*builtins);
|
|
|
| // Setup the 'global' properties of the builtins object. The
|
| // 'global' property that refers to the global object is the only
|
| @@ -932,13 +1002,11 @@
|
| SetupLazy(Handle<JSFunction>(global_context()->date_function()),
|
| Natives::GetIndex("date"),
|
| Top::global_context(),
|
| - Handle<Context>(Top::context()->runtime_context()),
|
| - Handle<Context>(Top::security_context()));
|
| + Handle<Context>(Top::context()->runtime_context()));
|
| SetupLazy(Handle<JSFunction>(global_context()->regexp_function()),
|
| Natives::GetIndex("regexp"),
|
| Top::global_context(),
|
| - Handle<Context>(Top::context()->runtime_context()),
|
| - Handle<Context>(Top::security_context()));
|
| + Handle<Context>(Top::context()->runtime_context()));
|
|
|
| } else if (strlen(FLAG_natives_file) != 0) {
|
| // Otherwise install natives from natives file if file exists and
|
| @@ -1004,14 +1072,14 @@
|
|
|
| bool Genesis::InstallSpecialObjects() {
|
| HandleScope scope;
|
| - Handle<JSGlobalObject> global(
|
| + Handle<JSGlobalObject> js_global(
|
| JSGlobalObject::cast(global_context()->global()));
|
| // Expose the natives in global if a name for it is specified.
|
| if (FLAG_expose_natives_as != NULL && strlen(FLAG_expose_natives_as) != 0) {
|
| Handle<String> natives_string =
|
| Factory::LookupAsciiSymbol(FLAG_expose_natives_as);
|
| - SetProperty(global, natives_string,
|
| - Handle<JSObject>(global->builtins()), DONT_ENUM);
|
| + SetProperty(js_global, natives_string,
|
| + Handle<JSObject>(js_global->builtins()), DONT_ENUM);
|
| }
|
|
|
| // Expose the debug global object in global if a name for it is specified.
|
| @@ -1020,18 +1088,16 @@
|
| // debugger but without tanking the whole context.
|
| if (!Debug::Load())
|
| return true;
|
| - Handle<JSGlobalObject> debug_global =
|
| - Handle<JSGlobalObject>(
|
| - JSGlobalObject::cast(Debug::debug_context()->global()));
|
| + // Set the security token for the debugger context to the same as
|
| + // the shell global context to allow calling between these (otherwise
|
| + // exposing debug global object doesn't make much sense).
|
| + Debug::debug_context()->set_security_token(
|
| + global_context()->security_token());
|
| +
|
| Handle<String> debug_string =
|
| Factory::LookupAsciiSymbol(FLAG_expose_debug_as);
|
| - SetProperty(global, debug_string,
|
| - Handle<JSObject>(debug_global), DONT_ENUM);
|
| -
|
| - // Set the security token for the debugger global object to the same as
|
| - // the shell global object to allow calling between these (otherwise
|
| - // exposing debug global object doesn't make much sense).
|
| - debug_global->set_security_token(global->security_token());
|
| + SetProperty(js_global, debug_string,
|
| + Handle<Object>(Debug::debug_context()->global_proxy()), DONT_ENUM);
|
| }
|
|
|
| return true;
|
| @@ -1122,25 +1188,52 @@
|
| }
|
|
|
|
|
| -bool Genesis::ConfigureGlobalObject(
|
| - v8::Handle<v8::ObjectTemplate> global_template) {
|
| - Handle<JSObject> global = Handle<JSObject>(global_context()->global());
|
| - if (!global_template.IsEmpty()) {
|
| - Handle<ObjectTemplateInfo> data = v8::Utils::OpenHandle(*global_template);
|
| - bool pending_exception = false;
|
| - Handle<JSObject> obj =
|
| - Execution::InstantiateObject(data, &pending_exception);
|
| - if (pending_exception) {
|
| - ASSERT(Top::has_pending_exception());
|
| - Top::clear_pending_exception();
|
| - return false;
|
| +bool Genesis::ConfigureGlobalObjects(
|
| + v8::Handle<v8::ObjectTemplate> global_proxy_template) {
|
| + Handle<JSObject> global_proxy(
|
| + JSObject::cast(global_context()->global_proxy()));
|
| + Handle<JSObject> js_global(JSObject::cast(global_context()->global()));
|
| +
|
| + if (!global_proxy_template.IsEmpty()) {
|
| + // Configure the outer global object.
|
| + Handle<ObjectTemplateInfo> outer_data =
|
| + v8::Utils::OpenHandle(*global_proxy_template);
|
| + if (!ConfigureApiObject(global_proxy, outer_data)) return false;
|
| +
|
| + // Configure the inner global object.
|
| + Handle<FunctionTemplateInfo> outer_constructor(
|
| + FunctionTemplateInfo::cast(outer_data->constructor()));
|
| + if (!outer_constructor->prototype_template()->IsUndefined()) {
|
| + Handle<ObjectTemplateInfo> inner_data(
|
| + ObjectTemplateInfo::cast(outer_constructor->prototype_template()));
|
| + if (!ConfigureApiObject(js_global, inner_data)) return false;
|
| }
|
| - TransferObject(obj, global);
|
| }
|
| +
|
| + SetObjectPrototype(global_proxy, js_global);
|
| return true;
|
| }
|
|
|
| +
|
| +bool Genesis::ConfigureApiObject(Handle<JSObject> object,
|
| + Handle<ObjectTemplateInfo> object_template) {
|
| + ASSERT(!object_template.is_null());
|
| + ASSERT(object->IsInstanceOf(
|
| + FunctionTemplateInfo::cast(object_template->constructor())));
|
|
|
| + bool pending_exception = false;
|
| + Handle<JSObject> obj =
|
| + Execution::InstantiateObject(object_template, &pending_exception);
|
| + if (pending_exception) {
|
| + ASSERT(Top::has_pending_exception());
|
| + Top::clear_pending_exception();
|
| + return false;
|
| + }
|
| + TransferObject(obj, object);
|
| + return true;
|
| +}
|
| +
|
| +
|
| void Genesis::TransferNamedProperties(Handle<JSObject> from,
|
| Handle<JSObject> to) {
|
| if (from->HasFastProperties()) {
|
| @@ -1331,8 +1424,9 @@
|
|
|
| MakeFunctionInstancePrototypeWritable();
|
| BuildSpecialFunctionTable();
|
| - if (!ConfigureGlobalObject(global_template)) return;
|
|
|
| + if (!ConfigureGlobalObjects(global_template)) return;
|
| +
|
| if (!InstallExtensions(extensions)) return;
|
|
|
| if (!InstallSpecialObjects()) return;
|
|
|