Rename Mutex to DeprecatedMutex
[WebKit-https.git] / Source / WebCore / bindings / js / WorkerScriptController.cpp
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2011, 2012 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 "WorkerScriptController.h"
30
31 #include "JSDOMBinding.h"
32 #include "JSDedicatedWorkerGlobalScope.h"
33 #include "ScriptSourceCode.h"
34 #include "WebCoreJSClientData.h"
35 #include "WorkerGlobalScope.h"
36 #include "WorkerObjectProxy.h"
37 #include "WorkerScriptDebugServer.h"
38 #include "WorkerThread.h"
39 #include <bindings/ScriptValue.h>
40 #include <heap/StrongInlines.h>
41 #include <interpreter/Interpreter.h>
42 #include <runtime/Completion.h>
43 #include <runtime/Exception.h>
44 #include <runtime/ExceptionHelpers.h>
45 #include <runtime/Error.h>
46 #include <runtime/JSLock.h>
47
48 using namespace JSC;
49
50 namespace WebCore {
51
52 WorkerScriptController::WorkerScriptController(WorkerGlobalScope* workerGlobalScope)
53     : m_vm(VM::create())
54     , m_workerGlobalScope(workerGlobalScope)
55     , m_workerGlobalScopeWrapper(*m_vm)
56     , m_executionForbidden(false)
57 {
58     initNormalWorldClientData(m_vm.get());
59 }
60
61 WorkerScriptController::~WorkerScriptController()
62 {
63     JSLockHolder lock(vm());
64     m_workerGlobalScopeWrapper.clear();
65     m_vm = nullptr;
66 }
67
68 void WorkerScriptController::initScript()
69 {
70     ASSERT(!m_workerGlobalScopeWrapper);
71
72     JSLockHolder lock(m_vm.get());
73
74     // Explicitly protect the global object's prototype so it isn't collected
75     // when we allocate the global object. (Once the global object is fully
76     // constructed, it can mark its own prototype.)
77     Structure* workerGlobalScopePrototypeStructure = JSWorkerGlobalScopePrototype::createStructure(*m_vm, 0, jsNull());
78     Strong<JSWorkerGlobalScopePrototype> workerGlobalScopePrototype(*m_vm, JSWorkerGlobalScopePrototype::create(*m_vm, 0, workerGlobalScopePrototypeStructure));
79
80     if (m_workerGlobalScope->isDedicatedWorkerGlobalScope()) {
81         Structure* dedicatedContextPrototypeStructure = JSDedicatedWorkerGlobalScopePrototype::createStructure(*m_vm, 0, workerGlobalScopePrototype.get());
82         Strong<JSDedicatedWorkerGlobalScopePrototype> dedicatedContextPrototype(*m_vm, JSDedicatedWorkerGlobalScopePrototype::create(*m_vm, 0, dedicatedContextPrototypeStructure));
83         Structure* structure = JSDedicatedWorkerGlobalScope::createStructure(*m_vm, 0, dedicatedContextPrototype.get());
84
85         m_workerGlobalScopeWrapper.set(*m_vm, JSDedicatedWorkerGlobalScope::create(*m_vm, structure, static_cast<DedicatedWorkerGlobalScope&>(*m_workerGlobalScope)));
86         workerGlobalScopePrototypeStructure->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
87         dedicatedContextPrototypeStructure->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
88         ASSERT(structure->globalObject() == m_workerGlobalScopeWrapper);
89         ASSERT(m_workerGlobalScopeWrapper->structure()->globalObject() == m_workerGlobalScopeWrapper);
90         workerGlobalScopePrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
91         dedicatedContextPrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
92     }
93     ASSERT(m_workerGlobalScopeWrapper->globalObject() == m_workerGlobalScopeWrapper);
94     ASSERT(asObject(m_workerGlobalScopeWrapper->prototype())->globalObject() == m_workerGlobalScopeWrapper);
95 }
96
97 void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
98 {
99     if (isExecutionForbidden())
100         return;
101
102     NakedPtr<Exception> exception;
103     evaluate(sourceCode, exception);
104     if (exception) {
105         JSLockHolder lock(vm());
106         reportException(m_workerGlobalScopeWrapper->globalExec(), exception);
107     }
108 }
109
110 void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, NakedPtr<JSC::Exception>& returnedException)
111 {
112     if (isExecutionForbidden())
113         return;
114
115     initScriptIfNeeded();
116
117     ExecState* exec = m_workerGlobalScopeWrapper->globalExec();
118     JSLockHolder lock(exec);
119
120     JSC::evaluate(exec, sourceCode.jsSourceCode(), m_workerGlobalScopeWrapper->globalThis(), returnedException);
121
122     VM& vm = exec->vm();
123     if ((returnedException && isTerminatedExecutionException(returnedException))
124         || (vm.watchdog && vm.watchdog->didFire())) {
125         forbidExecution();
126         return;
127     }
128
129     if (returnedException) {
130         String errorMessage;
131         int lineNumber = 0;
132         int columnNumber = 0;
133         String sourceURL = sourceCode.url().string();
134         if (m_workerGlobalScope->sanitizeScriptError(errorMessage, lineNumber, columnNumber, sourceURL, sourceCode.cachedScript())) {
135             vm.throwException(exec, createError(exec, errorMessage.impl()));
136             returnedException = vm.exception();
137             vm.clearException();
138         }
139     }
140 }
141
142 void WorkerScriptController::setException(JSC::Exception* exception)
143 {
144     JSC::ExecState* exec = m_workerGlobalScopeWrapper->globalExec();
145     exec->vm().throwException(exec, exception);
146 }
147
148 void WorkerScriptController::scheduleExecutionTermination()
149 {
150     // The mutex provides a memory barrier to ensure that once
151     // termination is scheduled, isExecutionTerminating will
152     // accurately reflect that state when called from another thread.
153     DeprecatedMutexLocker locker(m_scheduledTerminationMutex);
154     if (m_vm->watchdog)
155         m_vm->watchdog->fire();
156 }
157
158 bool WorkerScriptController::isExecutionTerminating() const
159 {
160     // See comments in scheduleExecutionTermination regarding mutex usage.
161     DeprecatedMutexLocker locker(m_scheduledTerminationMutex);
162     if (m_vm->watchdog)
163         return m_vm->watchdog->didFire();
164     return false;
165 }
166
167 void WorkerScriptController::forbidExecution()
168 {
169     ASSERT(m_workerGlobalScope->isContextThread());
170     m_executionForbidden = true;
171 }
172
173 bool WorkerScriptController::isExecutionForbidden() const
174 {
175     ASSERT(m_workerGlobalScope->isContextThread());
176     return m_executionForbidden;
177 }
178
179 void WorkerScriptController::disableEval(const String& errorMessage)
180 {
181     initScriptIfNeeded();
182     JSLockHolder lock(vm());
183
184     m_workerGlobalScopeWrapper->setEvalEnabled(false, errorMessage);
185 }
186
187 void WorkerScriptController::attachDebugger(JSC::Debugger* debugger)
188 {
189     initScriptIfNeeded();
190     debugger->attach(m_workerGlobalScopeWrapper->globalObject());
191 }
192
193 void WorkerScriptController::detachDebugger(JSC::Debugger* debugger)
194 {
195     debugger->detach(m_workerGlobalScopeWrapper->globalObject(), JSC::Debugger::TerminatingDebuggingSession);
196 }
197
198 } // namespace WebCore