1/*
2 * Copyright (C) 2008, 2009, 2016 Apple Inc. All rights reserved.
3 * Copyright (C) 2009 Google Inc. All Rights Reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
18 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *
26 */
27
28#include "config.h"
29#include "JSWorkerGlobalScopeBase.h"
30
31#include "ActiveDOMCallbackMicrotask.h"
32#include "DOMWrapperWorld.h"
33#include "JSDOMGlobalObjectTask.h"
34#include "JSDedicatedWorkerGlobalScope.h"
35#include "JSMicrotaskCallback.h"
36#include "JSWorkerGlobalScope.h"
37#include "WorkerGlobalScope.h"
38#include "WorkerThread.h"
39#include <JavaScriptCore/JSCInlines.h>
40#include <JavaScriptCore/JSCJSValueInlines.h>
41#include <JavaScriptCore/JSProxy.h>
42#include <JavaScriptCore/Microtask.h>
43#include <wtf/Language.h>
44
45#if ENABLE(SERVICE_WORKER)
46#include "JSServiceWorkerGlobalScope.h"
47#endif
48
49
50namespace WebCore {
51using namespace JSC;
52
53const ClassInfo JSWorkerGlobalScopeBase::s_info = { "WorkerGlobalScope", &JSDOMGlobalObject::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSWorkerGlobalScopeBase) };
54
55const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable = {
56 &supportsRichSourceInfo,
57 &shouldInterruptScript,
58 &javaScriptRuntimeFlags,
59 &queueTaskToEventLoop,
60 &shouldInterruptScriptBeforeTimeout,
61 nullptr, // moduleLoaderImportModule
62 nullptr, // moduleLoaderResolve
63 nullptr, // moduleLoaderFetch
64 nullptr, // moduleLoaderCreateImportMetaProperties
65 nullptr, // moduleLoaderEvaluate
66 &promiseRejectionTracker,
67 &defaultLanguage,
68 nullptr, // compileStreaming
69 nullptr, // instantiateStreaming
70};
71
72JSWorkerGlobalScopeBase::JSWorkerGlobalScopeBase(JSC::VM& vm, JSC::Structure* structure, RefPtr<WorkerGlobalScope>&& impl)
73 : JSDOMGlobalObject(vm, structure, normalWorld(vm), &s_globalObjectMethodTable)
74 , m_wrapped(WTFMove(impl))
75{
76}
77
78void JSWorkerGlobalScopeBase::finishCreation(VM& vm, JSProxy* proxy)
79{
80 m_proxy.set(vm, this, proxy);
81
82 Base::finishCreation(vm, m_proxy.get());
83 ASSERT(inherits(vm, info()));
84}
85
86void JSWorkerGlobalScopeBase::clearDOMGuardedObjects()
87{
88 auto guardedObjects = m_guardedObjects;
89 for (auto& guarded : guardedObjects)
90 guarded->clear();
91}
92
93void JSWorkerGlobalScopeBase::visitChildren(JSCell* cell, SlotVisitor& visitor)
94{
95 JSWorkerGlobalScopeBase* thisObject = jsCast<JSWorkerGlobalScopeBase*>(cell);
96 ASSERT_GC_OBJECT_INHERITS(thisObject, info());
97 Base::visitChildren(thisObject, visitor);
98 visitor.append(thisObject->m_proxy);
99}
100
101void JSWorkerGlobalScopeBase::destroy(JSCell* cell)
102{
103 static_cast<JSWorkerGlobalScopeBase*>(cell)->JSWorkerGlobalScopeBase::~JSWorkerGlobalScopeBase();
104}
105
106ScriptExecutionContext* JSWorkerGlobalScopeBase::scriptExecutionContext() const
107{
108 return m_wrapped.get();
109}
110
111bool JSWorkerGlobalScopeBase::supportsRichSourceInfo(const JSGlobalObject* object)
112{
113 return JSGlobalObject::supportsRichSourceInfo(object);
114}
115
116bool JSWorkerGlobalScopeBase::shouldInterruptScript(const JSGlobalObject* object)
117{
118 return JSGlobalObject::shouldInterruptScript(object);
119}
120
121bool JSWorkerGlobalScopeBase::shouldInterruptScriptBeforeTimeout(const JSGlobalObject* object)
122{
123 return JSGlobalObject::shouldInterruptScriptBeforeTimeout(object);
124}
125
126RuntimeFlags JSWorkerGlobalScopeBase::javaScriptRuntimeFlags(const JSGlobalObject* object)
127{
128 const JSWorkerGlobalScopeBase *thisObject = jsCast<const JSWorkerGlobalScopeBase*>(object);
129 return thisObject->m_wrapped->thread().runtimeFlags();
130}
131
132void JSWorkerGlobalScopeBase::queueTaskToEventLoop(JSGlobalObject& object, Ref<JSC::Microtask>&& task)
133{
134 JSWorkerGlobalScopeBase& thisObject = static_cast<JSWorkerGlobalScopeBase&>(object);
135
136 auto callback = JSMicrotaskCallback::create(thisObject, WTFMove(task));
137 auto& context = thisObject.wrapped();
138 auto microtask = std::make_unique<ActiveDOMCallbackMicrotask>(context.microtaskQueue(), context, [callback = WTFMove(callback)]() mutable {
139 callback->call();
140 });
141
142 context.microtaskQueue().append(WTFMove(microtask));
143}
144
145JSValue toJS(ExecState* exec, JSDOMGlobalObject*, WorkerGlobalScope& workerGlobalScope)
146{
147 return toJS(exec, workerGlobalScope);
148}
149
150JSValue toJS(ExecState*, WorkerGlobalScope& workerGlobalScope)
151{
152 WorkerScriptController* script = workerGlobalScope.script();
153 if (!script)
154 return jsNull();
155 JSWorkerGlobalScope* contextWrapper = script->workerGlobalScopeWrapper();
156 ASSERT(contextWrapper);
157 return contextWrapper->proxy();
158}
159
160JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(VM& vm, JSValue value)
161{
162 if (!value.isObject())
163 return nullptr;
164 const ClassInfo* classInfo = asObject(value)->classInfo(vm);
165 if (classInfo == JSDedicatedWorkerGlobalScope::info())
166 return jsCast<JSDedicatedWorkerGlobalScope*>(asObject(value));
167 if (classInfo == JSProxy::info())
168 return jsDynamicCast<JSDedicatedWorkerGlobalScope*>(vm, jsCast<JSProxy*>(asObject(value))->target());
169 return nullptr;
170}
171
172JSWorkerGlobalScope* toJSWorkerGlobalScope(VM& vm, JSValue value)
173{
174 if (!value.isObject())
175 return nullptr;
176 const ClassInfo* classInfo = asObject(value)->classInfo(vm);
177 if (classInfo == JSDedicatedWorkerGlobalScope::info())
178 return jsCast<JSDedicatedWorkerGlobalScope*>(asObject(value));
179
180#if ENABLE(SERVICE_WORKER)
181 if (classInfo == JSServiceWorkerGlobalScope::info())
182 return jsCast<JSServiceWorkerGlobalScope*>(asObject(value));
183#endif
184
185 if (classInfo == JSProxy::info())
186 return jsDynamicCast<JSWorkerGlobalScope*>(vm, jsCast<JSProxy*>(asObject(value))->target());
187
188 return nullptr;
189}
190
191#if ENABLE(SERVICE_WORKER)
192JSServiceWorkerGlobalScope* toJSServiceWorkerGlobalScope(VM& vm, JSValue value)
193{
194 if (!value.isObject())
195 return nullptr;
196 const ClassInfo* classInfo = asObject(value)->classInfo(vm);
197 if (classInfo == JSServiceWorkerGlobalScope::info())
198 return jsCast<JSServiceWorkerGlobalScope*>(asObject(value));
199 if (classInfo == JSProxy::info())
200 return jsDynamicCast<JSServiceWorkerGlobalScope*>(vm, jsCast<JSProxy*>(asObject(value))->target());
201 return nullptr;
202}
203#endif
204
205} // namespace WebCore
206