• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2011 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 COMPUTER, 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 COMPUTER, 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 
30 #if ENABLE(WORKERS)
31 
32 #include "WorkerScriptController.h"
33 
34 #include "JSDedicatedWorkerContext.h"
35 #include "JSSharedWorkerContext.h"
36 #include "ScriptSourceCode.h"
37 #include "ScriptValue.h"
38 #include "WebCoreJSClientData.h"
39 #include "WorkerContext.h"
40 #include "WorkerObjectProxy.h"
41 #include "WorkerThread.h"
42 #include <interpreter/Interpreter.h>
43 #include <runtime/Completion.h>
44 #include <runtime/Completion.h>
45 #include <runtime/Error.h>
46 #include <runtime/JSLock.h>
47 
48 using namespace JSC;
49 
50 namespace WebCore {
51 
WorkerScriptController(WorkerContext * workerContext)52 WorkerScriptController::WorkerScriptController(WorkerContext* workerContext)
53     : m_globalData(JSGlobalData::create(ThreadStackTypeSmall))
54     , m_workerContext(workerContext)
55     , m_workerContextWrapper(*m_globalData)
56     , m_executionForbidden(false)
57 {
58     initNormalWorldClientData(m_globalData.get());
59 }
60 
~WorkerScriptController()61 WorkerScriptController::~WorkerScriptController()
62 {
63     m_workerContextWrapper.clear(); // Unprotect the global object.
64     m_globalData->clearBuiltinStructures();
65     m_globalData->heap.destroy();
66 }
67 
initScript()68 void WorkerScriptController::initScript()
69 {
70     ASSERT(!m_workerContextWrapper);
71 
72     JSLock lock(SilenceAssertionsOnly);
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* workerContextPrototypeStructure = JSWorkerContextPrototype::createStructure(*m_globalData, jsNull());
78     Strong<JSWorkerContextPrototype> workerContextPrototype(*m_globalData, new (m_globalData.get()) JSWorkerContextPrototype(*m_globalData, 0, workerContextPrototypeStructure));
79 
80     if (m_workerContext->isDedicatedWorkerContext()) {
81         Structure* dedicatedContextPrototypeStructure = JSDedicatedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get());
82         Strong<JSDedicatedWorkerContextPrototype> dedicatedContextPrototype(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContextPrototype(*m_globalData, 0, dedicatedContextPrototypeStructure));
83         Structure* structure = JSDedicatedWorkerContext::createStructure(*m_globalData, dedicatedContextPrototype.get());
84 
85         m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSDedicatedWorkerContext(*m_globalData, structure, m_workerContext->toDedicatedWorkerContext()));
86         workerContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
87         dedicatedContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
88 #if ENABLE(SHARED_WORKERS)
89     } else {
90         ASSERT(m_workerContext->isSharedWorkerContext());
91         Structure* sharedContextPrototypeStructure = JSSharedWorkerContextPrototype::createStructure(*m_globalData, workerContextPrototype.get());
92         Strong<JSSharedWorkerContextPrototype> sharedContextPrototype(*m_globalData, new (m_globalData.get()) JSSharedWorkerContextPrototype(*m_globalData, 0, sharedContextPrototypeStructure));
93         Structure* structure = JSSharedWorkerContext::createStructure(*m_globalData, sharedContextPrototype.get());
94 
95         m_workerContextWrapper.set(*m_globalData, new (m_globalData.get()) JSSharedWorkerContext(*m_globalData, structure, m_workerContext->toSharedWorkerContext()));
96         workerContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
97         sharedContextPrototype->putAnonymousValue(*m_globalData, 0, m_workerContextWrapper.get());
98 #endif
99     }
100 }
101 
evaluate(const ScriptSourceCode & sourceCode)102 ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
103 {
104     if (isExecutionForbidden())
105         return ScriptValue();
106 
107     ScriptValue exception;
108     ScriptValue result(evaluate(sourceCode, &exception));
109     if (exception.jsValue()) {
110         JSLock lock(SilenceAssertionsOnly);
111         reportException(m_workerContextWrapper->globalExec(), exception.jsValue());
112     }
113     return result;
114 }
115 
evaluate(const ScriptSourceCode & sourceCode,ScriptValue * exception)116 ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* exception)
117 {
118     if (isExecutionForbidden())
119         return ScriptValue();
120 
121     initScriptIfNeeded();
122     JSLock lock(SilenceAssertionsOnly);
123 
124     ExecState* exec = m_workerContextWrapper->globalExec();
125     m_workerContextWrapper->globalData().timeoutChecker.start();
126     Completion comp = JSC::evaluate(exec, exec->dynamicGlobalObject()->globalScopeChain(), sourceCode.jsSourceCode(), m_workerContextWrapper.get());
127     m_workerContextWrapper->globalData().timeoutChecker.stop();
128 
129 
130     ComplType completionType = comp.complType();
131 
132     if (completionType == Terminated || m_workerContextWrapper->globalData().terminator.shouldTerminate()) {
133         forbidExecution();
134         return ScriptValue();
135     }
136 
137     if (completionType == Normal || completionType == ReturnValue)
138         return ScriptValue(*m_globalData, comp.value());
139 
140     if (completionType == Throw) {
141         String errorMessage;
142         int lineNumber = 0;
143         String sourceURL = sourceCode.url().string();
144         if (m_workerContext->sanitizeScriptError(errorMessage, lineNumber, sourceURL))
145             *exception = ScriptValue(*m_globalData, throwError(exec, createError(exec, errorMessage.impl())));
146         else
147             *exception = ScriptValue(*m_globalData, comp.value());
148     }
149     return ScriptValue();
150 }
151 
setException(ScriptValue exception)152 void WorkerScriptController::setException(ScriptValue exception)
153 {
154     throwError(m_workerContextWrapper->globalExec(), exception.jsValue());
155 }
156 
scheduleExecutionTermination()157 void WorkerScriptController::scheduleExecutionTermination()
158 {
159     m_globalData->terminator.terminateSoon();
160 }
161 
forbidExecution()162 void WorkerScriptController::forbidExecution()
163 {
164     ASSERT(m_workerContext->isContextThread());
165     m_executionForbidden = true;
166 }
167 
isExecutionForbidden() const168 bool WorkerScriptController::isExecutionForbidden() const
169 {
170     ASSERT(m_workerContext->isContextThread());
171     return m_executionForbidden;
172 }
173 
174 } // namespace WebCore
175 
176 #endif // ENABLE(WORKERS)
177