bool WindowProxy::setupWindowPrototypeChain() { // Associate the window wrapper object and its prototype chain with the // corresponding native DOMWindow object. // The full structure of the global object's prototype chain is as follows: // // global proxy object [1] // -- has prototype --> global object (window wrapper object) [2] // -- has prototype --> Window.prototype // -- has prototype --> WindowProperties [3] // -- has prototype --> EventTarget.prototype // -- has prototype --> Object.prototype // -- has prototype --> null // // [1] Global proxy object is as known as "outer global object". It's an // empty object and remains after navigation. When navigated, points to // a different global object as the prototype object. // [2] Global object is as known as "inner global object" or "window wrapper // object". The prototype chain between global proxy object and global // object is NOT observable from user JavaScript code. All other // prototype chains are observable. Global proxy object and global object // together appear to be the same single JavaScript object. See also: // https://wiki.mozilla.org/Gecko:SplitWindow // global object (= window wrapper object) provides most of Window's DOM // attributes and operations. Also global variables defined by user // JavaScript are placed on this object. When navigated, a new global // object is created together with a new v8::Context, but the global proxy // object doesn't change. // [3] WindowProperties is a named properties object of Window interface. DOMWindow* window = m_frame->domWindow(); const WrapperTypeInfo* wrapperTypeInfo = window->wrapperTypeInfo(); v8::Local<v8::Context> context = m_scriptState->context(); // The global proxy object. Note this is not the global object. v8::Local<v8::Object> globalProxy = context->Global(); // The global object, aka window wrapper object. v8::Local<v8::Object> windowWrapper = globalProxy->GetPrototype().As<v8::Object>(); windowWrapper = V8DOMWrapper::associateObjectWithWrapper( m_isolate, window, wrapperTypeInfo, windowWrapper); // The prototype object of Window interface. v8::Local<v8::Object> windowPrototype = windowWrapper->GetPrototype().As<v8::Object>(); RELEASE_ASSERT(!windowPrototype.IsEmpty()); V8DOMWrapper::setNativeInfo(m_isolate, windowPrototype, wrapperTypeInfo, window); // The named properties object of Window interface. v8::Local<v8::Object> windowProperties = windowPrototype->GetPrototype().As<v8::Object>(); RELEASE_ASSERT(!windowProperties.IsEmpty()); V8DOMWrapper::setNativeInfo(m_isolate, windowProperties, wrapperTypeInfo, window); // TODO(keishi): Remove installPagePopupController and implement // PagePopupController in another way. V8PagePopupControllerBinding::installPagePopupController(context, windowWrapper); return true; }
bool WindowProxy::installDOMWindow() { DOMWindow* window = m_frame->domWindow(); const WrapperTypeInfo* wrapperTypeInfo = window->wrapperTypeInfo(); v8::Local<v8::Object> windowWrapper; v8::Local<v8::Function> constructor = m_scriptState->perContextData()->constructorForType(wrapperTypeInfo); if (constructor.IsEmpty()) return false; if (!V8ObjectConstructor::newInstance(m_isolate, constructor).ToLocal(&windowWrapper)) return false; windowWrapper = V8DOMWrapper::associateObjectWithWrapper(m_isolate, window, wrapperTypeInfo, windowWrapper); V8DOMWrapper::setNativeInfo(v8::Local<v8::Object>::Cast(windowWrapper->GetPrototype()), wrapperTypeInfo, window); // Install the windowWrapper as the prototype of the innerGlobalObject. // The full structure of the global object is as follows: // // outerGlobalObject (Empty object, remains after navigation) // -- has prototype --> innerGlobalObject (Holds global variables, changes during navigation) // -- has prototype --> DOMWindow instance // -- has prototype --> Window.prototype // -- has prototype --> EventTarget.prototype // -- has prototype --> Object.prototype // // Note: Much of this prototype structure is hidden from web content. The // outer, inner, and DOMWindow instance all appear to be the same // JavaScript object. v8::Local<v8::Context> context = m_scriptState->context(); v8::Local<v8::Object> innerGlobalObject = toInnerGlobalObject(m_scriptState->context()); V8DOMWrapper::setNativeInfo(innerGlobalObject, wrapperTypeInfo, window); if (!v8CallBoolean(innerGlobalObject->SetPrototype(context, windowWrapper))) return false; // TODO(keishi): Remove installPagePopupController and implement // PagePopupController in another way. V8PagePopupControllerBinding::installPagePopupController(context, windowWrapper); return true; }