void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior)
{
    if (!isContextInitialized())
        return;

    v8::HandleScope handleScope(m_isolate);
    v8::Local<v8::Context> context = m_scriptState->context();
    if (m_frame->isLocalFrame()) {
        LocalFrame* frame = toLocalFrame(m_frame);
        // The embedder could run arbitrary code in response to the willReleaseScriptContext callback, so all disposing should happen after it returns.
        frame->loader().client()->willReleaseScriptContext(context, m_world->worldId());
        InspectorInstrumentation::willReleaseScriptContext(frame, m_scriptState.get());
    }

    m_document.clear();

    if (behavior == DetachGlobal)
        m_scriptState->detachGlobalObject();

    m_scriptState->disposePerContextData();

    // It's likely that disposing the context has created a lot of
    // garbage. Notify V8 about this so it'll have a chance of cleaning
    // it up when idle.
    V8GCForContextDispose::instance().notifyContextDisposed(m_frame->isMainFrame());
}
Esempio n. 2
0
v8::Local<v8::Object> WindowProxy::globalIfNotDetached() {
  if (!isContextInitialized())
    return v8::Local<v8::Object>();
  ASSERT(m_scriptState->contextIsValid());
  ASSERT(m_global == m_scriptState->context()->Global());
  return m_global.newLocal(m_isolate);
}
bool WorkerScriptController::initializeContextIfNeeded()
{
    v8::HandleScope handleScope(isolate());

    if (isContextInitialized())
        return true;

    v8::Local<v8::Context> context = v8::Context::New(isolate());
    if (context.IsEmpty())
        return false;

    m_scriptState = ScriptState::create(context, m_world);

    ScriptState::Scope scope(m_scriptState.get());

    // Name new context for debugging.
    WorkerScriptDebugServer::setContextDebugData(context);

    // Create a new JS object and use it as the prototype for the shadow global object.
    const WrapperTypeInfo* wrapperTypeInfo = m_workerGlobalScope.wrapperTypeInfo();
    v8::Local<v8::Function> workerGlobalScopeConstructor = m_scriptState->perContextData()->constructorForType(wrapperTypeInfo);
    v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance(isolate(), workerGlobalScopeConstructor);
    if (jsWorkerGlobalScope.IsEmpty()) {
        m_scriptState->disposePerContextData();
        return false;
    }

    V8DOMWrapper::associateObjectWithWrapper(isolate(), &m_workerGlobalScope, wrapperTypeInfo, jsWorkerGlobalScope);

    // Insert the object instance as the prototype of the shadow object.
    v8::Local<v8::Object> globalObject = v8::Local<v8::Object>::Cast(m_scriptState->context()->Global()->GetPrototype());
    return v8CallBoolean(globalObject->SetPrototype(context, jsWorkerGlobalScope));
}
void WindowProxy::clearForClose()
{
    if (!isContextInitialized())
        return;

    disposeContext(DoNotDetachGlobal);
}
Esempio n. 5
0
bool WindowProxy::initialize()
{
    TRACE_EVENT0("v8", "WindowProxy::initialize");
    TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "InitializeWindow");

    ScriptForbiddenScope::AllowUserAgentScript allowScript;

    v8::HandleScope handleScope(m_isolate);

    createContext();

    if (!isContextInitialized())
        return false;

    ScriptState::Scope scope(m_scriptState.get());
    v8::Handle<v8::Context> context = m_scriptState->context();
    if (m_global.isEmpty()) {
        m_global.set(m_isolate, context->Global());
        if (m_global.isEmpty()) {
            disposeContext(DoNotDetachGlobal);
            return false;
        }
    }

    if (!installDOMWindow()) {
        disposeContext(DoNotDetachGlobal);
        return false;
    }

    updateDocument();
    m_frame->loaderClient()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId());
    return true;
}
void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin)
{
    ASSERT(m_world->isMainWorld());
    if (!isContextInitialized())
        return;
    setSecurityToken(origin);
}
Esempio n. 7
0
bool WindowProxy::initialize() {
  TRACE_EVENT0("v8", "WindowProxy::initialize");
  SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.Binding.InitializeWindowProxy");

  ScriptForbiddenScope::AllowUserAgentScript allowScript;

  v8::HandleScope handleScope(m_isolate);

  createContext();

  if (!isContextInitialized())
    return false;

  ScriptState::Scope scope(m_scriptState.get());
  v8::Local<v8::Context> context = m_scriptState->context();
  if (m_global.isEmpty()) {
    m_global.set(m_isolate, context->Global());
    if (m_global.isEmpty()) {
      disposeContext(DoNotDetachGlobal);
      return false;
    }
  }

  if (!setupWindowPrototypeChain()) {
    disposeContext(DoNotDetachGlobal);
    return false;
  }

  SecurityOrigin* origin = 0;
  if (m_world->isMainWorld()) {
    // ActivityLogger for main world is updated within updateDocument().
    updateDocument();
    origin = m_frame->securityContext()->getSecurityOrigin();
    // FIXME: Can this be removed when CSP moves to browser?
    ContentSecurityPolicy* csp =
        m_frame->securityContext()->contentSecurityPolicy();
    context->AllowCodeGenerationFromStrings(
        csp->allowEval(0, ContentSecurityPolicy::SuppressReport));
    context->SetErrorMessageForCodeGenerationFromStrings(
        v8String(m_isolate, csp->evalDisabledErrorMessage()));
  } else {
    updateActivityLogger();
    origin = m_world->isolatedWorldSecurityOrigin();
    setSecurityToken(origin);
  }

  // All interfaces must be registered to V8PerContextData.
  // So we explicitly call constructorForType for the global object.
  V8PerContextData::from(context)->constructorForType(
      &V8Window::wrapperTypeInfo);

  if (m_frame->isLocalFrame()) {
    LocalFrame* frame = toLocalFrame(m_frame);
    MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame,
                                                   origin);
    frame->loader().client()->didCreateScriptContext(
        context, m_world->extensionGroup(), m_world->worldId());
  }
  return true;
}
Esempio n. 8
0
// Create a new environment and setup the global object.
//
// The global object corresponds to a DOMWindow instance. However, to
// allow properties of the JS DOMWindow instance to be shadowed, we
// use a shadow object as the global object and use the JS DOMWindow
// instance as the prototype for that shadow object. The JS DOMWindow
// instance is undetectable from JavaScript code because the __proto__
// accessors skip that object.
//
// The shadow object and the DOMWindow instance are seen as one object
// from JavaScript. The JavaScript object that corresponds to a
// DOMWindow instance is the shadow object. When mapping a DOMWindow
// instance to a V8 object, we return the shadow object.
//
// To implement split-window, see
//   1) https://bugs.webkit.org/show_bug.cgi?id=17249
//   2) https://wiki.mozilla.org/Gecko:SplitWindow
//   3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639
// we need to split the shadow object further into two objects:
// an outer window and an inner window. The inner window is the hidden
// prototype of the outer window. The inner window is the default
// global object of the context. A variable declared in the global
// scope is a property of the inner window.
//
// The outer window sticks to a LocalFrame, it is exposed to JavaScript
// via window.window, window.self, window.parent, etc. The outer window
// has a security token which is the domain. The outer window cannot
// have its own properties. window.foo = 'x' is delegated to the
// inner window.
//
// When a frame navigates to a new page, the inner window is cut off
// the outer window, and the outer window identify is preserved for
// the frame. However, a new inner window is created for the new page.
// If there are JS code holds a closure to the old inner window,
// it won't be able to reach the outer window via its global object.
bool WindowProxy::initializeIfNeeded()
{
    if (isContextInitialized())
        return true;

    return initialize();
}
Esempio n. 9
0
bool WindowProxy::initialize()
{
    TRACE_EVENT0("v8", "WindowProxy::initialize");
    TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "InitializeWindow");
    SCOPED_BLINK_UMA_HISTOGRAM_TIMER("Blink.Binding.InitializeWindowProxy");

    ScriptForbiddenScope::AllowUserAgentScript allowScript;

    v8::HandleScope handleScope(m_isolate);

    createContext();

    if (!isContextInitialized())
        return false;

    ScriptState::Scope scope(m_scriptState.get());
    v8::Local<v8::Context> context = m_scriptState->context();
    if (m_global.isEmpty()) {
        m_global.set(m_isolate, context->Global());
        if (m_global.isEmpty()) {
            disposeContext(DoNotDetachGlobal);
            return false;
        }
    }

    if (!setupWindowPrototypeChain()) {
        disposeContext(DoNotDetachGlobal);
        return false;
    }

    SecurityOrigin* origin = 0;
    if (m_world->isMainWorld()) {
        // ActivityLogger for main world is updated within updateDocument().
        updateDocument();
        origin = m_frame->securityContext()->getSecurityOrigin();
        // FIXME: Can this be removed when CSP moves to browser?
        ContentSecurityPolicy* csp = m_frame->securityContext()->contentSecurityPolicy();
        context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport));
        context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage()));
    } else {
        updateActivityLogger();
        origin = m_world->isolatedWorldSecurityOrigin();
        setSecurityToken(origin);
    }
    if (m_frame->isLocalFrame()) {
        LocalFrame* frame = toLocalFrame(m_frame);
        MainThreadDebugger::instance()->contextCreated(m_scriptState.get(), frame, origin);
        frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId());
    }
    // If Origin Trials have been registered before the V8 context was ready,
    // then inject them into the context now
    ExecutionContext* executionContext = m_scriptState->getExecutionContext();
    if (executionContext) {
        OriginTrialContext* originTrialContext = OriginTrialContext::from(executionContext);
        if (originTrialContext)
            originTrialContext->initializePendingFeatures();
    }
    return true;
}
Esempio n. 10
0
void WindowProxy::clearDocumentProperty()
{
    ASSERT(isContextInitialized());
    if (!m_world->isMainWorld())
        return;
    v8::HandleScope handleScope(m_isolate);
    m_scriptState->context()->Global()->ForceDelete(v8AtomicString(m_isolate, "document"));
}
Esempio n. 11
0
void WindowProxy::clearForNavigation() {
  if (!isContextInitialized())
    return;

  ScriptState::Scope scope(m_scriptState.get());

  disposeContext(DetachGlobal);
}
Esempio n. 12
0
void WindowProxy::updateDocument()
{
    ASSERT(m_world->isMainWorld());
    if (!isGlobalInitialized())
        return;
    if (!isContextInitialized())
        return;
    updateDocumentProperty();
}
void WorkerScriptController::dispose()
{
    m_rejectedPromises->dispose();
    m_rejectedPromises.release();

    m_world->dispose();

    if (isContextInitialized())
        m_scriptState->disposePerContextData();
}
// Create a new environment and setup the global object.
//
// The global object corresponds to a DOMWindow instance. However, to
// allow properties of the JS DOMWindow instance to be shadowed, we
// use a shadow object as the global object and use the JS DOMWindow
// instance as the prototype for that shadow object. The JS DOMWindow
// instance is undetectable from JavaScript code because the __proto__
// accessors skip that object.
//
// The shadow object and the DOMWindow instance are seen as one object
// from JavaScript. The JavaScript object that corresponds to a
// DOMWindow instance is the shadow object. When mapping a DOMWindow
// instance to a V8 object, we return the shadow object.
//
// To implement split-window, see
//   1) https://bugs.webkit.org/show_bug.cgi?id=17249
//   2) https://wiki.mozilla.org/Gecko:SplitWindow
//   3) https://bugzilla.mozilla.org/show_bug.cgi?id=296639
// we need to split the shadow object further into two objects:
// an outer window and an inner window. The inner window is the hidden
// prototype of the outer window. The inner window is the default
// global object of the context. A variable declared in the global
// scope is a property of the inner window.
//
// The outer window sticks to a LocalFrame, it is exposed to JavaScript
// via window.window, window.self, window.parent, etc. The outer window
// has a security token which is the domain. The outer window cannot
// have its own properties. window.foo = 'x' is delegated to the
// inner window.
//
// When a frame navigates to a new page, the inner window is cut off
// the outer window, and the outer window identify is preserved for
// the frame. However, a new inner window is created for the new page.
// If there are JS code holds a closure to the old inner window,
// it won't be able to reach the outer window via its global object.
bool WindowProxy::initializeIfNeeded()
{
    if (isContextInitialized())
        return true;

    DOMWrapperWorld::setWorldOfInitializingWindow(m_world.get());
    bool result = initialize();
    DOMWrapperWorld::setWorldOfInitializingWindow(0);
    return result;
}
Esempio n. 15
0
void WindowProxy::updateDocument() {
  ASSERT(m_world->isMainWorld());
  if (!isGlobalInitialized())
    return;
  if (!isContextInitialized())
    return;
  updateActivityLogger();
  updateDocumentProperty();
  updateSecurityOrigin(m_frame->securityContext()->getSecurityOrigin());
}
Esempio n. 16
0
v8::Local<v8::Object> WindowProxy::releaseGlobal()
{
    ASSERT(!isContextInitialized());
    // If a ScriptState was created, the context was initialized at some point.
    // Make sure the global object was detached from the proxy by calling clearForNavigation().
    if (m_scriptState)
        ASSERT(m_scriptState->isGlobalObjectDetached());
    v8::Local<v8::Object> global = m_global.newLocal(m_isolate);
    m_global.clear();
    return global;
}
Esempio n. 17
0
void WorkerOrWorkletScriptController::disposeContextIfNeeded() {
  if (!isContextInitialized())
    return;

  if (m_globalScope->isWorkerGlobalScope() ||
      m_globalScope->isThreadedWorkletGlobalScope()) {
    ScriptState::Scope scope(m_scriptState.get());
    WorkerThreadDebugger* debugger = WorkerThreadDebugger::from(m_isolate);
    debugger->contextWillBeDestroyed(m_globalScope->thread(),
                                     m_scriptState->context());
  }
  m_scriptState->disposePerContextData();
}
bool WindowProxy::initialize()
{
    TRACE_EVENT0("v8", "WindowProxy::initialize");
    TRACE_EVENT_SCOPED_SAMPLING_STATE("blink", "InitializeWindow");

    ScriptForbiddenScope::AllowUserAgentScript allowScript;

    v8::HandleScope handleScope(m_isolate);

    createContext();

    if (!isContextInitialized())
        return false;

    ScriptState::Scope scope(m_scriptState.get());
    v8::Local<v8::Context> context = m_scriptState->context();
    if (m_global.isEmpty()) {
        m_global.set(m_isolate, context->Global());
        if (m_global.isEmpty()) {
            disposeContext(DoNotDetachGlobal);
            return false;
        }
    }

    if (!installDOMWindow()) {
        disposeContext(DoNotDetachGlobal);
        return false;
    }

    SecurityOrigin* origin = 0;
    if (m_world->isMainWorld()) {
        // ActivityLogger for main world is updated within updateDocument().
        updateDocument();
        origin = m_frame->securityContext()->securityOrigin();
        // FIXME: Can this be removed when CSP moves to browser?
        ContentSecurityPolicy* csp = m_frame->securityContext()->contentSecurityPolicy();
        context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport));
        context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage()));
    } else {
        updateActivityLogger();
        origin = m_world->isolatedWorldSecurityOrigin();
        setSecurityToken(origin);
    }
    if (m_frame->isLocalFrame()) {
        LocalFrame* frame = toLocalFrame(m_frame);
        MainThreadDebugger::initializeContext(context, m_world->worldId());
        InspectorInstrumentation::didCreateScriptContext(frame, m_scriptState.get(), origin, m_world->worldId());
        frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId());
    }
    return true;
}
void WindowProxy::namedItemAdded(HTMLDocument* document, const AtomicString& name)
{
    ASSERT(m_world->isMainWorld());

    if (!isContextInitialized() || !m_scriptState->contextIsValid())
        return;

    ScriptState::Scope scope(m_scriptState.get());
    ASSERT(!m_document.isEmpty());
    v8::Local<v8::Context> context = m_scriptState->context();
    v8::Local<v8::Object> documentHandle = m_document.newLocal(m_isolate);
    checkDocumentWrapper(documentHandle, document);
    documentHandle->SetAccessor(context, v8String(m_isolate, name), getter);
}
WorkerScriptController::~WorkerScriptController()
{
    m_rejectedPromises->dispose();
    m_rejectedPromises.clear();

    m_world->dispose();

    // The corresponding call to didStartRunLoop() is in WorkerThread::initialize().
    // See http://webkit.org/b/83104#c14 for why this is here.
    m_workerGlobalScope.thread()->didStopRunLoop();

    if (isContextInitialized())
        m_scriptState->disposePerContextData();
}
void WindowProxy::namedItemRemoved(HTMLDocument* document, const AtomicString& name)
{
    ASSERT(m_world->isMainWorld());

    if (!isContextInitialized())
        return;

    if (document->hasNamedItem(name) || document->hasExtraNamedItem(name))
        return;

    ScriptState::Scope scope(m_scriptState.get());
    ASSERT(!m_document.isEmpty());
    v8::Local<v8::Object> documentHandle = m_document.newLocal(m_isolate);
    checkDocumentWrapper(documentHandle, document);
    documentHandle->Delete(m_isolate->GetCurrentContext(), v8String(m_isolate, name));
}
WorkerScriptController::~WorkerScriptController()
{
    ThreadState::current()->removeInterruptor(m_interruptor.get());

    m_world->dispose();

    // The corresponding call to didStartWorkerRunLoop is in
    // WorkerThread::workerThread().
    // See http://webkit.org/b/83104#c14 for why this is here.
    blink::Platform::current()->didStopWorkerRunLoop(blink::WebWorkerRunLoop(&m_workerGlobalScope.thread()->runLoop()));

    if (isContextInitialized())
        m_scriptState->disposePerContextData();

    ThreadState::current()->addCleanupTask(IsolateCleanupTask::create(m_isolate));
}
Esempio n. 23
0
void WindowProxy::clearForNavigation()
{
    if (!isContextInitialized())
        return;

    ScriptState::Scope scope(m_scriptState.get());

    m_document.clear();

    // Clear the document wrapper cache before turning on access checks on
    // the old LocalDOMWindow wrapper. This way, access to the document wrapper
    // will be protected by the security checks on the LocalDOMWindow wrapper.
    clearDocumentProperty();

    v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(m_global.newLocal(m_isolate), m_isolate);
    ASSERT(!windowWrapper.IsEmpty());
    windowWrapper->TurnOnAccessCheck();
    disposeContext(DetachGlobal);
}
Esempio n. 24
0
void WindowProxy::disposeContext(GlobalDetachmentBehavior behavior)
{
    if (!isContextInitialized())
        return;

    v8::HandleScope handleScope(m_isolate);
    v8::Handle<v8::Context> context = m_scriptState->context();
    m_frame->loaderClient()->willReleaseScriptContext(context, m_world->worldId());

    if (behavior == DetachGlobal)
        context->DetachGlobal();

    m_scriptState->disposePerContextData();

    // It's likely that disposing the context has created a lot of
    // garbage. Notify V8 about this so it'll have a chance of cleaning
    // it up when idle.
    V8GCForContextDispose::instanceTemplate().notifyContextDisposed();
}
bool WorkerScriptController::initializeContextIfNeeded()
{
    v8::HandleScope handleScope(m_isolate);

    if (isContextInitialized())
        return true;

    v8::Handle<v8::Context> context = v8::Context::New(m_isolate);
    if (context.IsEmpty())
        return false;

    m_scriptState = ScriptState::create(context, m_world);

    ScriptState::Scope scope(m_scriptState.get());

    // Set DebugId for the new context.
    context->SetEmbedderData(0, v8AtomicString(m_isolate, "worker"));

    // Create a new JS object and use it as the prototype for the shadow global object.
    const WrapperTypeInfo* contextType = &V8DedicatedWorkerGlobalScope::wrapperTypeInfo;
    if (m_workerGlobalScope.isServiceWorkerGlobalScope())
        contextType = &V8ServiceWorkerGlobalScope::wrapperTypeInfo;
    else if (!m_workerGlobalScope.isDedicatedWorkerGlobalScope())
        contextType = &V8SharedWorkerGlobalScope::wrapperTypeInfo;
    v8::Handle<v8::Function> workerGlobalScopeConstructor = m_scriptState->perContextData()->constructorForType(contextType);
    v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance(m_isolate, workerGlobalScopeConstructor);
    if (jsWorkerGlobalScope.IsEmpty()) {
        m_scriptState->disposePerContextData();
        return false;
    }

    V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtrWillBeRawPtr<WorkerGlobalScope>(&m_workerGlobalScope), contextType, jsWorkerGlobalScope, m_isolate, WrapperConfiguration::Dependent);

    // Insert the object instance as the prototype of the shadow object.
    v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_scriptState->context()->Global()->GetPrototype());
    globalObject->SetPrototype(jsWorkerGlobalScope);

    return true;
}
WindowProxy::~WindowProxy()
{
    // clearForClose() or clearForNavigation() must be invoked before destruction starts.
    ASSERT(!isContextInitialized());
}
Esempio n. 27
0
void WindowProxy::updateSecurityOrigin(SecurityOrigin* origin)
{
    if (!isContextInitialized())
        return;
    setSecurityToken(origin);
}
Esempio n. 28
0
bool WorkerOrWorkletScriptController::initializeContextIfNeeded() {
  v8::HandleScope handleScope(m_isolate);

  if (isContextInitialized())
    return true;

  // Create a new v8::Context with the worker/worklet as the global object
  // (aka the inner global).
  ScriptWrappable* scriptWrappable = m_globalScope->getScriptWrappable();
  const WrapperTypeInfo* wrapperTypeInfo = scriptWrappable->wrapperTypeInfo();
  v8::Local<v8::FunctionTemplate> globalInterfaceTemplate =
      wrapperTypeInfo->domTemplate(m_isolate, *m_world);
  if (globalInterfaceTemplate.IsEmpty())
    return false;
  v8::Local<v8::ObjectTemplate> globalTemplate =
      globalInterfaceTemplate->InstanceTemplate();
  v8::Local<v8::Context> context;
  {
    // Initialize V8 extensions before creating the context.
    Vector<const char*> extensionNames;
    if (m_globalScope->isServiceWorkerGlobalScope() &&
        Platform::current()->allowScriptExtensionForServiceWorker(
            toWorkerGlobalScope(m_globalScope.get())->url())) {
      const V8Extensions& extensions = ScriptController::registeredExtensions();
      extensionNames.reserveInitialCapacity(extensions.size());
      for (const auto* extension : extensions)
        extensionNames.push_back(extension->name());
    }
    v8::ExtensionConfiguration extensionConfiguration(extensionNames.size(),
                                                      extensionNames.data());

    V8PerIsolateData::UseCounterDisabledScope useCounterDisabled(
        V8PerIsolateData::from(m_isolate));
    context =
        v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate);
  }
  if (context.IsEmpty())
    return false;

  m_scriptState = ScriptState::create(context, m_world);

  ScriptState::Scope scope(m_scriptState.get());

  // The global proxy object.  Note this is not the global object.
  v8::Local<v8::Object> globalProxy = context->Global();
  V8DOMWrapper::setNativeInfo(m_isolate, globalProxy, wrapperTypeInfo,
                              scriptWrappable);

  // The global object, aka worker/worklet wrapper object.
  v8::Local<v8::Object> globalObject =
      globalProxy->GetPrototype().As<v8::Object>();
  globalObject = V8DOMWrapper::associateObjectWithWrapper(
      m_isolate, scriptWrappable, wrapperTypeInfo, globalObject);

  // All interfaces must be registered to V8PerContextData.
  // So we explicitly call constructorForType for the global object.
  V8PerContextData::from(context)->constructorForType(wrapperTypeInfo);

  // Name new context for debugging. For main thread worklet global scopes
  // this is done once the context is initialized.
  if (m_globalScope->isWorkerGlobalScope() ||
      m_globalScope->isThreadedWorkletGlobalScope()) {
    WorkerThreadDebugger* debugger = WorkerThreadDebugger::from(m_isolate);
    debugger->contextCreated(m_globalScope->thread(), context);
  }

  return true;
}