summaryrefslogtreecommitdiffstats
path: root/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/bindings/v8/WorkerContextExecutionProxy.cpp')
-rw-r--r--WebCore/bindings/v8/WorkerContextExecutionProxy.cpp205
1 files changed, 112 insertions, 93 deletions
diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
index c87cdea..f80d88f 100644
--- a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
+++ b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
@@ -35,9 +35,16 @@
#include "WorkerContextExecutionProxy.h"
+#include "DOMCoreException.h"
+#include "DedicatedWorkerContext.h"
+#include "Event.h"
+#include "EventException.h"
+#include "MessagePort.h"
+#include "RangeException.h"
#include "V8Binding.h"
+#include "V8DOMMap.h"
+#include "V8Index.h"
#include "V8Proxy.h"
-#include "Event.h"
#include "V8WorkerContextEventListener.h"
#include "V8WorkerContextObjectEventListener.h"
#include "Worker.h"
@@ -45,48 +52,17 @@
#include "WorkerLocation.h"
#include "WorkerNavigator.h"
#include "WorkerScriptController.h"
+#include "XMLHttpRequest.h"
+#include "XMLHttpRequestException.h"
namespace WebCore {
-static bool isWorkersEnabled = false;
-
static void reportFatalErrorInV8(const char* location, const char* message)
{
// FIXME: We temporarily deal with V8 internal error situations such as out-of-memory by crashing the worker.
CRASH();
}
-static void handleConsoleMessage(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data)
-{
- WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
- if (!proxy)
- return;
-
- WorkerContext* workerContext = proxy->workerContext();
- if (!workerContext)
- return;
-
- v8::Handle<v8::String> errorMessageString = message->Get();
- ASSERT(!errorMessageString.IsEmpty());
- String errorMessage = ToWebCoreString(errorMessageString);
-
- v8::Handle<v8::Value> resourceName = message->GetScriptResourceName();
- bool useURL = (resourceName.IsEmpty() || !resourceName->IsString());
- String resourceNameString = useURL ? workerContext->url() : ToWebCoreString(resourceName);
-
- workerContext->addMessage(ConsoleDestination, JSMessageSource, ErrorMessageLevel, errorMessage, message->GetLineNumber(), resourceNameString);
-}
-
-bool WorkerContextExecutionProxy::isWebWorkersEnabled()
-{
- return isWorkersEnabled;
-}
-
-void WorkerContextExecutionProxy::setIsWebWorkersEnabled(bool value)
-{
- isWorkersEnabled = value;
-}
-
WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext)
: m_workerContext(workerContext)
, m_recursion(0)
@@ -102,8 +78,7 @@ WorkerContextExecutionProxy::~WorkerContextExecutionProxy()
void WorkerContextExecutionProxy::dispose()
{
// Disconnect all event listeners.
- if (m_listeners.get())
- {
+ if (m_listeners.get()) {
for (V8EventListenerList::iterator iterator(m_listeners->begin()); iterator != m_listeners->end(); ++iterator)
static_cast<V8WorkerContextEventListener*>(*iterator)->disconnect();
@@ -127,13 +102,16 @@ void WorkerContextExecutionProxy::dispose()
WorkerContextExecutionProxy* WorkerContextExecutionProxy::retrieve()
{
+ // Happens on frame destruction, check otherwise GetCurrent() will crash.
+ if (!v8::Context::InContext())
+ return 0;
v8::Handle<v8::Context> context = v8::Context::GetCurrent();
v8::Handle<v8::Object> global = context->Global();
- global = V8Proxy::LookupDOMWrapper(V8ClassIndex::WORKERCONTEXT, global);
+ global = V8DOMWrapper::lookupDOMWrapper(V8ClassIndex::WORKERCONTEXT, global);
// Return 0 if the current executing context is not the worker context.
if (global.IsEmpty())
return 0;
- WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global);
+ WorkerContext* workerContext = V8DOMWrapper::convertToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global);
return workerContext->script()->proxy();
}
@@ -149,6 +127,7 @@ void WorkerContextExecutionProxy::initV8IfNeeded()
v8::V8::IgnoreOutOfMemoryException();
v8::V8::SetFatalErrorHandler(reportFatalErrorInV8);
+#ifdef MANUAL_MERGE_REQUIRED
// Set up the handler for V8 error message.
v8::V8::AddMessageListener(handleConsoleMessage);
@@ -156,6 +135,8 @@ void WorkerContextExecutionProxy::initV8IfNeeded()
const int workerThreadPreemptionIntervalMs = 5;
v8::Locker::StartPreemption(workerThreadPreemptionIntervalMs);
#endif
+#else // MANUAL_MERGE_REQUIRED
+#endif // MANUAL_MERGE_REQUIRED
v8Initialized = true;
}
@@ -177,7 +158,7 @@ void WorkerContextExecutionProxy::initContextIfNeeded()
v8::Handle<v8::String> implicitProtoString = v8::String::New("__proto__");
// Create a new JS object and use it as the prototype for the shadow global object.
- v8::Handle<v8::Function> workerContextConstructor = GetConstructor(V8ClassIndex::WORKERCONTEXT);
+ v8::Handle<v8::Function> workerContextConstructor = V8DOMWrapper::getConstructorForContext(V8ClassIndex::DEDICATEDWORKERCONTEXT, context);
v8::Local<v8::Object> jsWorkerContext = SafeAllocation::newInstance(workerContextConstructor);
// Bail out if allocation failed.
if (jsWorkerContext.IsEmpty()) {
@@ -186,9 +167,9 @@ void WorkerContextExecutionProxy::initContextIfNeeded()
}
// Wrap the object.
- V8Proxy::SetDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::WORKERCONTEXT), m_workerContext);
+ V8DOMWrapper::setDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::DEDICATEDWORKERCONTEXT), m_workerContext);
- V8Proxy::SetJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext));
+ V8DOMWrapper::setJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext));
m_workerContext->ref();
// Insert the object instance as the prototype of the shadow object.
@@ -198,45 +179,47 @@ void WorkerContextExecutionProxy::initContextIfNeeded()
m_listeners.set(new V8EventListenerList());
}
-v8::Local<v8::Function> WorkerContextExecutionProxy::GetConstructor(V8ClassIndex::V8WrapperType type)
-{
- // Enter the context of the proxy to make sure that the function is
- // constructed in the context corresponding to this proxy.
- v8::Context::Scope scope(m_context);
- v8::Handle<v8::FunctionTemplate> functionTemplate = V8Proxy::GetTemplate(type);
-
- // Getting the function might fail if we're running out of stack or memory.
- v8::TryCatch tryCatch;
- v8::Local<v8::Function> value = functionTemplate->GetFunction();
- if (value.IsEmpty())
- return v8::Local<v8::Function>();
-
- return value;
-}
-
-v8::Handle<v8::Value> WorkerContextExecutionProxy::ToV8Object(V8ClassIndex::V8WrapperType type, void* impl)
+v8::Handle<v8::Value> WorkerContextExecutionProxy::convertToV8Object(V8ClassIndex::V8WrapperType type, void* impl)
{
if (!impl)
return v8::Null();
- if (type == V8ClassIndex::WORKERCONTEXT)
- return WorkerContextToV8Object(static_cast<WorkerContext*>(impl));
+ if (type == V8ClassIndex::DEDICATEDWORKERCONTEXT)
+ return convertWorkerContextToV8Object(static_cast<WorkerContext*>(impl));
+
+ bool isActiveDomObject = false;
+ switch (type) {
+#define MAKE_CASE(TYPE, NAME) case V8ClassIndex::TYPE:
+ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
+ isActiveDomObject = true;
+ break;
+#undef MAKE_CASE
+ default:
+ break;
+ }
- if (type == V8ClassIndex::WORKER) {
+ if (isActiveDomObject) {
v8::Persistent<v8::Object> result = getActiveDOMObjectMap().get(impl);
if (!result.IsEmpty())
return result;
v8::Local<v8::Object> object = toV8(type, type, impl);
- if (!object.IsEmpty())
- static_cast<Worker*>(impl)->ref();
+ switch (type) {
+#define MAKE_CASE(TYPE, NAME) \
+ case V8ClassIndex::TYPE: static_cast<NAME*>(impl)->ref(); break;
+ ACTIVE_DOM_OBJECT_TYPES(MAKE_CASE)
+#undef MAKE_CASE
+ default:
+ ASSERT_NOT_REACHED();
+ }
+
result = v8::Persistent<v8::Object>::New(object);
- V8Proxy::SetJSWrapperForDOMObject(impl, result);
+ V8DOMWrapper::setJSWrapperForActiveDOMObject(impl, result);
return result;
}
// Non DOM node
- v8::Persistent<v8::Object> result = domObjectMap().get(impl);
+ v8::Persistent<v8::Object> result = getDOMObjectMap().get(impl);
if (result.IsEmpty()) {
v8::Local<v8::Object> object = toV8(type, type, impl);
if (!object.IsEmpty()) {
@@ -247,22 +230,34 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::ToV8Object(V8ClassIndex::V8Wr
case V8ClassIndex::WORKERNAVIGATOR:
static_cast<WorkerNavigator*>(impl)->ref();
break;
+ case V8ClassIndex::DOMCOREEXCEPTION:
+ static_cast<DOMCoreException*>(impl)->ref();
+ break;
+ case V8ClassIndex::RANGEEXCEPTION:
+ static_cast<RangeException*>(impl)->ref();
+ break;
+ case V8ClassIndex::EVENTEXCEPTION:
+ static_cast<EventException*>(impl)->ref();
+ break;
+ case V8ClassIndex::XMLHTTPREQUESTEXCEPTION:
+ static_cast<XMLHttpRequestException*>(impl)->ref();
+ break;
default:
ASSERT(false);
}
result = v8::Persistent<v8::Object>::New(object);
- V8Proxy::SetJSWrapperForDOMObject(impl, result);
+ V8DOMWrapper::setJSWrapperForDOMObject(impl, result);
}
}
return result;
}
-v8::Handle<v8::Value> WorkerContextExecutionProxy::EventToV8Object(Event* event)
+v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventToV8Object(Event* event)
{
if (!event)
return v8::Null();
- v8::Handle<v8::Object> wrapper = domObjectMap().get(event);
+ v8::Handle<v8::Object> wrapper = getDOMObjectMap().get(event);
if (!wrapper.IsEmpty())
return wrapper;
@@ -274,73 +269,79 @@ v8::Handle<v8::Value> WorkerContextExecutionProxy::EventToV8Object(Event* event)
v8::Handle<v8::Object> result = toV8(type, V8ClassIndex::EVENT, event);
if (result.IsEmpty()) {
// Instantiation failed. Avoid updating the DOM object map and return null which
- // is already handled by callers of this function in case the event is NULL.
+ // is already handled by callers of this function in case the event is null.
return v8::Null();
}
event->ref(); // fast ref
- V8Proxy::SetJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result));
+ V8DOMWrapper::setJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result));
return result;
}
-// A JS object of type EventTarget in the worker context can only be Worker or WorkerContext.
-v8::Handle<v8::Value> WorkerContextExecutionProxy::EventTargetToV8Object(EventTarget* target)
+v8::Handle<v8::Value> WorkerContextExecutionProxy::convertEventTargetToV8Object(EventTarget* target)
{
if (!target)
return v8::Null();
- WorkerContext* workerContext = target->toWorkerContext();
+ DedicatedWorkerContext* workerContext = target->toDedicatedWorkerContext();
if (workerContext)
- return WorkerContextToV8Object(workerContext);
+ return convertWorkerContextToV8Object(workerContext);
Worker* worker = target->toWorker();
if (worker)
- return ToV8Object(V8ClassIndex::WORKER, worker);
+ return convertToV8Object(V8ClassIndex::WORKER, worker);
+
+ XMLHttpRequest* xhr = target->toXMLHttpRequest();
+ if (xhr)
+ return convertToV8Object(V8ClassIndex::XMLHTTPREQUEST, xhr);
+
+ MessagePort* mp = target->toMessagePort();
+ if (mp)
+ return convertToV8Object(V8ClassIndex::MESSAGEPORT, mp);
ASSERT_NOT_REACHED();
return v8::Handle<v8::Value>();
}
-v8::Handle<v8::Value> WorkerContextExecutionProxy::WorkerContextToV8Object(WorkerContext* workerContext)
+v8::Handle<v8::Value> WorkerContextExecutionProxy::convertWorkerContextToV8Object(WorkerContext* workerContext)
{
if (!workerContext)
return v8::Null();
- v8::Handle<v8::Context> context = workerContext->script()->proxy()->GetContext();
+ v8::Handle<v8::Context> context = workerContext->script()->proxy()->context();
v8::Handle<v8::Object> global = context->Global();
ASSERT(!global.IsEmpty());
return global;
}
-v8::Local<v8::Object> WorkerContextExecutionProxy::toV8(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl)
+v8::Local<v8::Object> WorkerContextExecutionProxy::toV8(V8ClassIndex::V8WrapperType descriptorType, V8ClassIndex::V8WrapperType cptrType, void* impl)
{
v8::Local<v8::Function> function;
WorkerContextExecutionProxy* proxy = retrieve();
if (proxy)
- function = proxy->GetConstructor(descType);
+ function = V8DOMWrapper::getConstructor(descriptorType, proxy->workerContext());
else
- function = V8Proxy::GetTemplate(descType)->GetFunction();
+ function = V8DOMWrapper::getTemplate(descriptorType)->GetFunction();
v8::Local<v8::Object> instance = SafeAllocation::newInstance(function);
- if (!instance.IsEmpty()) {
+ if (!instance.IsEmpty())
// Avoid setting the DOM wrapper for failed allocations.
- V8Proxy::SetDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl);
- }
+ V8DOMWrapper::setDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl);
return instance;
}
bool WorkerContextExecutionProxy::forgetV8EventObject(Event* event)
{
- if (domObjectMap().contains(event)) {
- domObjectMap().forget(event);
+ if (getDOMObjectMap().contains(event)) {
+ getDOMObjectMap().forget(event);
return true;
- } else
- return false;
+ }
+ return false;
}
-v8::Local<v8::Value> WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine)
+ScriptValue WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine, WorkerContextExecutionState* state)
{
LOCK_V8;
v8::HandleScope hs;
@@ -348,9 +349,27 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::evaluate(const String& script,
initContextIfNeeded();
v8::Context::Scope scope(m_context);
+ v8::TryCatch exceptionCatcher;
+
v8::Local<v8::String> scriptString = v8ExternalString(script);
- v8::Handle<v8::Script> compiledScript = V8Proxy::CompileScript(scriptString, fileName, baseLine);
- return runScript(compiledScript);
+ v8::Handle<v8::Script> compiledScript = V8Proxy::compileScript(scriptString, fileName, baseLine);
+ v8::Local<v8::Value> result = runScript(compiledScript);
+
+ if (exceptionCatcher.HasCaught()) {
+ v8::Local<v8::Message> message = exceptionCatcher.Message();
+ state->hadException = true;
+ state->exception = ScriptValue(exceptionCatcher.Exception());
+ state->errorMessage = toWebCoreString(message->Get());
+ state->lineNumber = message->GetLineNumber();
+ state->sourceURL = toWebCoreString(message->GetScriptResourceName());
+ exceptionCatcher.Reset();
+ } else
+ state->hadException = false;
+
+ if (result.IsEmpty() || result->IsUndefined())
+ return ScriptValue();
+
+ return ScriptValue(result);
}
v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Script> script)
@@ -361,10 +380,10 @@ v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Scrip
// Compute the source string and prevent against infinite recursion.
if (m_recursion >= kMaxRecursionDepth) {
v8::Local<v8::String> code = v8ExternalString("throw RangeError('Recursion too deep')");
- script = V8Proxy::CompileScript(code, "", 0);
+ script = V8Proxy::compileScript(code, "", 0);
}
- if (V8Proxy::HandleOutOfMemory())
+ if (V8Proxy::handleOutOfMemory())
ASSERT(script.IsEmpty());
if (script.IsEmpty())
@@ -416,7 +435,7 @@ PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateObjectEvent
return findOrCreateEventListenerHelper(object, isInline, findOnly, true);
}
-void WorkerContextExecutionProxy::RemoveEventListener(V8EventListener* listener)
+void WorkerContextExecutionProxy::removeEventListener(V8EventListener* listener)
{
m_listeners->remove(listener);
}