62 WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext)
63 : m_workerContext(workerContext)
64 , m_disableEvalPending(String())
65 {
66 V8Initializer::initializeWorker();
67 }
68
69 WorkerContextExecutionProxy::~WorkerContextExecutionProxy()
70 {
71 dispose();
72 }
73
74 void WorkerContextExecutionProxy::dispose()
75 {
76 m_perContextData.clear();
77 m_context.clear();
78 }
79
80 bool WorkerContextExecutionProxy::initializeIfNeeded()
81 {
82 // Bail out if the context has already been initialized.
83 if (!m_context.isEmpty())
84 return true;
85
86 // Create a new environment
87 v8::Persistent<v8::ObjectTemplate> globalTemplate;
88 m_context.adopt(v8::Context::New(0, globalTemplate));
89 if (m_context.isEmpty())
90 return false;
91
92 // Starting from now, use local context only.
93 v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context.get());
94
95 v8::Context::Scope scope(context);
96
97 m_perContextData = V8PerContextData::create(m_context.get());
98 if (!m_perContextData->init()) {
99 dispose();
100 return false;
101 }
102
103 // Set DebugId for the new context.
104 context->SetEmbedderData(0, v8::String::New("worker"));
105
106 // Create a new JS object and use it as the prototype for the shadow global object.
107 WrapperTypeInfo* contextType = &V8DedicatedWorkerContext::info;
108 #if ENABLE(SHARED_WORKERS)
109 if (!m_workerContext->isDedicatedWorkerContext())
110 contextType = &V8SharedWorkerContext::info;
111 #endif
112 v8::Handle<v8::Function> workerContextConstructor = m_perContextData->constructorForType(contextType);
113 v8::Local<v8::Object> jsWorkerContext = V8ObjectConstructor::newInstance(workerContextConstructor);
114 // Bail out if allocation failed.
115 if (jsWorkerContext.IsEmpty()) {
116 dispose();
117 return false;
118 }
119
120 // Wrap the object.
121 V8DOMWrapper::createDOMWrapper(PassRefPtr<WorkerContext>(m_workerContext), contextType, jsWorkerContext);
122
123 // Insert the object instance as the prototype of the shadow object.
124 v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_context->Global()->GetPrototype());
125 globalObject->SetPrototype(jsWorkerContext);
126
127 return true;
128 }
129
130 ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition, WorkerContextExecutionState* state)
131 {
132 V8GCController::checkMemoryUsage();
133
134 v8::HandleScope hs;
135
136 if (!initializeIfNeeded())
137 return ScriptValue();
138
139 if (!m_disableEvalPending.isEmpty()) {
140 m_context->AllowCodeGenerationFromStrings(false);
141 m_context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_disableEvalPending));
142 m_disableEvalPending = String();
143 }
144
145 v8::Context::Scope scope(m_context.get());
146
147 v8::TryCatch exceptionCatcher;
148
149 v8::Local<v8::String> scriptString = v8ExternalString(script);
150 v8::Handle<v8::Script> compiledScript = ScriptSourceCode::compileScript(scriptString, fileName, scriptStartPosition);
151 v8::Local<v8::Value> result = ScriptRunner::runCompiledScript(compiledScript, m_workerContext);
152
153 if (!exceptionCatcher.CanContinue()) {
154 m_workerContext->script()->forbidExecution();
155 return ScriptValue();
156 }
157
158 if (exceptionCatcher.HasCaught()) {
159 v8::Local<v8::Message> message = exceptionCatcher.Message();
160 state->hadException = true;
161 state->errorMessage = toWebCoreString(message->Get());
162 state->lineNumber = message->GetLineNumber();
163 state->sourceURL = toWebCoreString(message->GetScriptResourceName());
164 if (m_workerContext->sanitizeScriptError(state->errorMessage, state->lineNumber, state->sourceURL))
165 state->exception = throwError(v8GeneralError, state->errorMessage.utf8().data());
166 else
167 state->exception = ScriptValue(exceptionCatcher.Exception());
168
169 exceptionCatcher.Reset();
170 } else
171 state->hadException = false;
172
173 if (result.IsEmpty() || result->IsUndefined())
174 return ScriptValue();
175
176 return ScriptValue(result);
177 }
178
179 void WorkerContextExecutionProxy::setEvalAllowed(bool enable, const String& errorMessage)
180 {
181 m_disableEvalPending = enable ? String() : errorMessage;
182 }
183