2009-03-20 Dmitry Titov <dimich@chromium.org>
authordimich@chromium.org <dimich@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Mar 2009 17:32:05 +0000 (17:32 +0000)
committerdimich@chromium.org <dimich@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 20 Mar 2009 17:32:05 +0000 (17:32 +0000)
        Reviewed by Dimitri Glazkov.

        https://bugs.webkit.org/show_bug.cgi?id=24689
        Add (upstream) V8 bindings for Workers. Mostly style cleaning.

        * bindings/v8/WorkerContextExecutionProxy.cpp: Added.
        * bindings/v8/WorkerContextExecutionProxy.h: Added.
        * bindings/v8/WorkerScriptController.cpp: Added.
        * bindings/v8/WorkerScriptController.h: Added.
        * bindings/v8/V8Index.h: Added. This is just a wrapper for v8_index.h, like V8Proxy.h
        * bindings/v8/V8Proxy.h: Added domObjectMap() function that wraps GetDOMObjectMap().
        * bindings/v8/V8WorkerContextEventListener.cpp:
        (WebCore::V8WorkerContextEventListener::callListenerFunction): TrackEvent() renamed trackEvent()

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@41862 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/bindings/v8/V8Index.h [new file with mode: 0644]
WebCore/bindings/v8/V8Proxy.h
WebCore/bindings/v8/V8WorkerContextEventListener.cpp
WebCore/bindings/v8/WorkerContextExecutionProxy.cpp [new file with mode: 0644]
WebCore/bindings/v8/WorkerContextExecutionProxy.h [new file with mode: 0644]
WebCore/bindings/v8/WorkerScriptController.cpp [new file with mode: 0644]
WebCore/bindings/v8/WorkerScriptController.h [new file with mode: 0644]

index bf67c81..0f5bfee 100644 (file)
@@ -1,3 +1,19 @@
+2009-03-20  Dmitry Titov  <dimich@chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
+        https://bugs.webkit.org/show_bug.cgi?id=24689
+        Add (upstream) V8 bindings for Workers. Mostly style cleaning.
+
+        * bindings/v8/WorkerContextExecutionProxy.cpp: Added.
+        * bindings/v8/WorkerContextExecutionProxy.h: Added.
+        * bindings/v8/WorkerScriptController.cpp: Added.
+        * bindings/v8/WorkerScriptController.h: Added.
+        * bindings/v8/V8Index.h: Added. This is just a wrapper for v8_index.h, like V8Proxy.h
+        * bindings/v8/V8Proxy.h: Added domObjectMap() function that wraps GetDOMObjectMap().
+        * bindings/v8/V8WorkerContextEventListener.cpp:
+        (WebCore::V8WorkerContextEventListener::callListenerFunction): TrackEvent() renamed trackEvent()
+
 2009-03-20  Stephen White  <senorblanco@chromium.org>
 
         Reviewed by Eric Seidel.
diff --git a/WebCore/bindings/v8/V8Index.h b/WebCore/bindings/v8/V8Index.h
new file mode 100644 (file)
index 0000000..58af42e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef V8Index_h
+#define V8Index_h
+
+// FIXME: This is a temporary forwarding header until all bindings have migrated
+// over and v8_index actually becomes V8Index.
+#include "v8_index.h"
+
+#endif // V8Index_h
index ea2b582..c21e0dd 100644 (file)
@@ -49,6 +49,12 @@ namespace WebCore {
         return v8::Local<v8::Boolean>();
     }
 
+    // FIXME: Remove once migration is complete.
+    inline static DOMWrapperMap<void>& domObjectMap()
+    {
+        return GetDOMObjectMap();
+    }
+
     inline v8::Handle<v8::Primitive> throwError(const char* message, V8Proxy::ErrorType type = V8Proxy::TYPE_ERROR)
     {
         V8Proxy::ThrowError(type, message);
index 7d8d924..ba7a2c0 100644 (file)
@@ -88,7 +88,7 @@ v8::Local<v8::Value> V8WorkerContextEventListener::callListenerFunction(v8::Hand
     v8::Handle<v8::Value> parameters[1] = { jsEvent };
     v8::Local<v8::Value> result = handlerFunction->Call(receiver, 1, parameters);
 
-    m_proxy->TrackEvent(event);
+    m_proxy->trackEvent(event);
 
     return result;
 }
diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp b/WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
new file mode 100644 (file)
index 0000000..24802b8
--- /dev/null
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "WorkerContextExecutionProxy.h"
+
+#include "V8Binding.h"
+#include "V8Proxy.h"
+#include "Event.h"
+#include "V8WorkerContextEventListener.h"
+#include "WorkerContext.h"
+#include "WorkerLocation.h"
+#include "WorkerNavigator.h"
+#include "WorkerScriptController.h"
+
+namespace WebCore {
+
+static bool isWorkersEnabled = false;
+
+bool WorkerContextExecutionProxy::isWebWorkersEnabled()
+{
+    return isWorkersEnabled;
+}
+
+void WorkerContextExecutionProxy::setIsWebWorkersEnabled(bool value)
+{
+    isWorkersEnabled = value;
+}
+
+WorkerContextExecutionProxy::WorkerContextExecutionProxy(WorkerContext* workerContext)
+    : m_workerContext(workerContext)
+    , m_recursion(0)
+{
+}
+
+WorkerContextExecutionProxy::~WorkerContextExecutionProxy()
+{
+    dispose();
+}
+
+void WorkerContextExecutionProxy::dispose()
+{
+    // Disconnect all event listeners.
+    for (size_t listenerIndex = 0; listenerIndex < m_listeners.size(); ++listenerIndex)
+       m_listeners[listenerIndex]->disconnect();
+
+    m_listeners.clear();
+
+    // Detach all events from their JS wrappers.
+    for (size_t eventIndex = 0; eventIndex < m_events.size(); ++eventIndex) {
+        Event* event = m_events[eventIndex];
+        if (forgetV8EventObject(event))
+          event->deref();
+    }
+    m_events.clear();
+
+    // Dispose the context.
+    if (!m_context.IsEmpty()) {
+        m_context.Dispose();
+        m_context.Clear();
+    }
+
+    // Remove the wrapping between JS object and DOM object. This is because
+    // the worker context object is going to be disposed immediately when a
+    // worker thread is tearing down. We do not want to re-delete the real object
+    // when JS object is garbage collected.
+    v8::Locker locker;
+    v8::HandleScope scope;
+    v8::Persistent<v8::Object> wrapper = domObjectMap().get(m_workerContext);
+    if (!wrapper.IsEmpty())
+        V8Proxy::SetDOMWrapper(wrapper, V8ClassIndex::INVALID_CLASS_INDEX, NULL);
+    domObjectMap().forget(m_workerContext);
+}
+
+WorkerContextExecutionProxy* WorkerContextExecutionProxy::retrieve()
+{
+    v8::Handle<v8::Context> context = v8::Context::GetCurrent();
+    v8::Handle<v8::Object> global = context->Global();
+    global = V8Proxy::LookupDOMWrapper(V8ClassIndex::WORKERCONTEXT, global);
+    ASSERT(!global.IsEmpty());
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, global);
+    return workerContext->script()->proxy();
+}
+
+void WorkerContextExecutionProxy::initContextIfNeeded()
+{
+    // Bail out if the context has already been initialized.
+    if (!m_context.IsEmpty())
+        return;
+
+    // Create a new environment
+    v8::Persistent<v8::ObjectTemplate> globalTemplate;
+    m_context = v8::Context::New(NULL, globalTemplate);
+
+    // Starting from now, use local context only.
+    v8::Local<v8::Context> context = v8::Local<v8::Context>::New(m_context);
+    v8::Context::Scope scope(context);
+
+    // Allocate strings used during initialization.
+    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::Local<v8::Object> jsWorkerContext = SafeAllocation::NewInstance(workerContextConstructor);
+    // Bail out if allocation failed.
+    if (jsWorkerContext.IsEmpty()) {
+        dispose();
+        return;
+    }
+
+    // Wrap the object.
+    V8Proxy::SetDOMWrapper(jsWorkerContext, V8ClassIndex::ToInt(V8ClassIndex::WORKERCONTEXT), m_workerContext);
+
+    V8Proxy::SetJSWrapperForDOMObject(m_workerContext, v8::Persistent<v8::Object>::New(jsWorkerContext));
+
+    // Insert the object instance as the prototype of the shadow object.
+    v8::Handle<v8::Object> globalObject = m_context->Global();
+    globalObject->Set(implicitProtoString, jsWorkerContext);
+}
+
+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)
+{
+    if (!impl)
+        return v8::Null();
+
+    if (type == V8ClassIndex::WORKERCONTEXT)
+        return WorkerContextToV8Object(static_cast<WorkerContext*>(impl));
+
+    // Non DOM node
+    v8::Persistent<v8::Object> result = domObjectMap().get(impl);
+    if (result.IsEmpty()) {
+        v8::Local<v8::Object> object = toV8(type, type, impl);
+        if (!object.IsEmpty()) {
+            switch (type) {
+            case V8ClassIndex::WORKERLOCATION:
+                static_cast<WorkerLocation*>(impl)->ref();
+                break;
+            case V8ClassIndex::WORKERNAVIGATOR:
+                static_cast<WorkerNavigator*>(impl)->ref();
+                break;
+            default:
+                ASSERT(false);
+            }
+            result = v8::Persistent<v8::Object>::New(object);
+            V8Proxy::SetJSWrapperForDOMObject(impl, result);
+        }
+    }
+    return result;
+}
+
+v8::Handle<v8::Value> WorkerContextExecutionProxy::EventToV8Object(Event* event)
+{
+    if (!event)
+        return v8::Null();
+
+    v8::Handle<v8::Object> wrapper = domObjectMap().get(event);
+    if (!wrapper.IsEmpty())
+        return wrapper;
+
+    V8ClassIndex::V8WrapperType type = V8ClassIndex::EVENT;
+
+    if (event->isMessageEvent())
+        type = V8ClassIndex::MESSAGEEVENT;
+
+    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.
+        return v8::Null();
+    }
+
+    event->ref();  // fast ref
+    V8Proxy::SetJSWrapperForDOMObject(event, v8::Persistent<v8::Object>::New(result));
+
+    return result;
+}
+
+// A JS object of type EventTarget in the worker context can only be WorkerContext.
+v8::Handle<v8::Value> WorkerContextExecutionProxy::EventTargetToV8Object(EventTarget* target)
+{
+    if (!target)
+        return v8::Null();
+
+    WorkerContext* workerContext = target->toWorkerContext();
+    if (workerContext)
+        return WorkerContextToV8Object(workerContext);
+
+    ASSERT_NOT_REACHED();
+    return v8::Handle<v8::Value>();
+}
+
+v8::Handle<v8::Value> WorkerContextExecutionProxy::WorkerContextToV8Object(WorkerContext* workerContext)
+{
+    if (!workerContext)
+        return v8::Null();
+
+    v8::Handle<v8::Context> context = workerContext->script()->proxy()->GetContext();
+
+    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::Function> function;
+    WorkerContextExecutionProxy* proxy = retrieve();
+    if (proxy)
+        function = proxy->GetConstructor(descType);
+    else
+        function = V8Proxy::GetTemplate(descType)->GetFunction();
+
+    v8::Local<v8::Object> instance = SafeAllocation::NewInstance(function);
+    if (!instance.IsEmpty()) {
+        // Avoid setting the DOM wrapper for failed allocations.
+        V8Proxy::SetDOMWrapper(instance, V8ClassIndex::ToInt(cptrType), impl);
+    }
+    return instance;
+}
+
+bool WorkerContextExecutionProxy::forgetV8EventObject(Event* event)
+{
+    if (domObjectMap().contains(event)) {
+        domObjectMap().forget(event);
+        return true;
+    } else
+        return false;
+}
+
+v8::Local<v8::Value> WorkerContextExecutionProxy::evaluate(const String& script, const String& fileName, int baseLine)
+{
+    v8::Locker locker;
+    v8::HandleScope hs;
+
+    initContextIfNeeded();
+    v8::Context::Scope scope(m_context);
+
+    v8::Local<v8::String> scriptString = v8ExternalString(script);
+    v8::Handle<v8::Script> compiledScript = V8Proxy::CompileScript(scriptString, fileName, baseLine);
+    return runScript(compiledScript);
+}
+
+v8::Local<v8::Value> WorkerContextExecutionProxy::runScript(v8::Handle<v8::Script> script)
+{
+    if (script.IsEmpty())
+        return v8::Local<v8::Value>();
+
+    // 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);
+    }
+
+    if (V8Proxy::HandleOutOfMemory())
+        ASSERT(script.IsEmpty());
+
+    if (script.IsEmpty())
+        return v8::Local<v8::Value>();
+
+    // Run the script and keep track of the current recursion depth.
+    v8::Local<v8::Value> result;
+    {
+        m_recursion++;
+        result = script->Run();
+        m_recursion--;
+    }
+
+    // Handle V8 internal error situation (Out-of-memory).
+    if (result.IsEmpty())
+        return v8::Local<v8::Value>();
+
+    return result;
+}
+
+PassRefPtr<V8EventListener> WorkerContextExecutionProxy::FindOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly)
+{
+    if (!object->IsObject())
+        return 0;
+
+    for (size_t index = ; index < m_listeners.size(); ++index) {
+        V8EventListener* el = m_listeners[index];
+        if (el->isInline() == isInline && el->getListenerObject() == object)
+            return el;
+    }
+    if (findOnly)
+        return NULL;
+
+    // Create a new one, and add to cache.
+    RefPtr<V8EventListener> listener = V8WorkerContextEventListener::create(this, v8::Local<v8::Object>::Cast(object), isInline);
+    m_listeners.append(listener.get());
+
+    return listener.release();
+}
+
+void WorkerContextExecutionProxy::RemoveEventListener(V8EventListener* listener)
+{
+    for (size_t index = ; index < m_listeners.size(); ++index) {
+        if (m_listeners[index] == listener) {
+            m_listeners.remove(index);
+            return;
+        }
+    }
+}
+
+void WorkerContextExecutionProxy::trackEvent(Event* event)
+{
+    m_events.append(event);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/bindings/v8/WorkerContextExecutionProxy.h b/WebCore/bindings/v8/WorkerContextExecutionProxy.h
new file mode 100644 (file)
index 0000000..3023666
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef WorkerContextExecutionProxy_h
+#define WorkerContextExecutionProxy_h
+
+#if ENABLE(WORKERS)
+
+#include <v8.h>
+#include "V8Index.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+    class Event;
+    class EventTarget;
+    class V8EventListener;
+    class V8WorkerContextEventListener;
+    class WorkerContext;
+
+    class WorkerContextExecutionProxy {
+    public:
+        WorkerContextExecutionProxy(WorkerContext*);
+        ~WorkerContextExecutionProxy();
+
+        // FIXME: following function sshould have camelCased names once V8 code-generating script is migrated.
+        v8::Local<v8::Context> GetContext() { return v8::Local<v8::Context>::New(m_context); }
+        v8::Local<v8::Function> GetConstructor(V8ClassIndex::V8WrapperType);
+        PassRefPtr<V8EventListener> FindOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly);
+        void RemoveEventListener(V8EventListener*);
+
+        static v8::Handle<v8::Value> ToV8Object(V8ClassIndex::V8WrapperType type, void* impl);
+        static v8::Handle<v8::Value> EventToV8Object(Event* event);
+        static v8::Handle<v8::Value> EventTargetToV8Object(EventTarget* target);
+        static v8::Handle<v8::Value> WorkerContextToV8Object(WorkerContext* wc);
+
+        // Track the event so that we can detach it from the JS wrapper when a worker
+        // terminates. This is needed because we need to be able to dispose these
+        // events and releases references to their event targets: WorkerContext.
+        void trackEvent(Event*);
+
+        // Evaluate a script file in the current execution environment.
+        v8::Local<v8::Value> evaluate(const String& script, const String& fileName, int baseLine);
+
+        // Returns WorkerContext object.
+        WorkerContext* workerContext() { return m_workerContext; }
+
+        // Returns WorkerContextExecutionProxy object of the currently executing context.
+        static WorkerContextExecutionProxy* retrieve();
+
+        // Enables HTML5 worker support.
+        static bool isWebWorkersEnabled();
+        static void setIsWebWorkersEnabled(bool);
+
+    private:
+        void initContextIfNeeded();
+        void dispose();
+
+        // Run an already compiled script.
+        v8::Local<v8::Value> runScript(v8::Handle<v8::Script>);
+
+        static v8::Local<v8::Object> toV8(V8ClassIndex::V8WrapperType descType, V8ClassIndex::V8WrapperType cptrType, void* impl);
+
+        static bool forgetV8EventObject(Event*);
+
+        WorkerContext* m_workerContext;
+        v8::Persistent<v8::Context> m_context;
+        int m_recursion;
+
+        Vector<V8WorkerContextEventListener*> m_listeners;
+        Vector<Event*> m_events;
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerContextExecutionProxy_h
diff --git a/WebCore/bindings/v8/WorkerScriptController.cpp b/WebCore/bindings/v8/WorkerScriptController.cpp
new file mode 100644 (file)
index 0000000..85bee0a
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WORKERS)
+
+#include "WorkerScriptController.h"
+
+#include <v8.h>
+
+#include "ScriptSourceCode.h"
+#include "ScriptValue.h"
+#include "DOMTimer.h"
+#include "WorkerContext.h"
+#include "WorkerContextExecutionProxy.h"
+#include "WorkerObjectProxy.h"
+#include "WorkerThread.h"
+
+namespace WebCore {
+
+WorkerScriptController::WorkerScriptController(WorkerContext* workerContext)
+    : m_workerContext(workerContext)
+    , m_proxy(new WorkerContextExecutionProxy(workerContext))
+    , m_executionForbidden(false)
+{
+}
+
+WorkerScriptController::~WorkerScriptController()
+{
+}
+
+ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
+{
+    {
+        MutexLocker lock(m_sharedDataMutex);
+        if (m_executionForbidden)
+            return ScriptValue();
+    }
+
+    v8::Local<v8::Value> result = m_proxy->evaluate(sourceCode.source(), sourceCode.url().string(), sourceCode.startLine() - 1);
+    m_workerContext->thread()->workerObjectProxy()->reportPendingActivity(m_workerContext->hasPendingActivity());
+    return ScriptValue();
+}
+
+ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, ScriptValue* /* exception */)
+{
+    // FIXME: Need to return an exception.
+    return evaluate(sourceCode);
+}
+
+void WorkerScriptController::forbidExecution()
+{
+    // This function is called from another thread.
+    MutexLocker lock(m_sharedDataMutex);
+    m_executionForbidden = true;
+}
+
+void WorkerScriptController::setException(ScriptValue /* exception */)
+{
+    notImplemented();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/bindings/v8/WorkerScriptController.h b/WebCore/bindings/v8/WorkerScriptController.h
new file mode 100644 (file)
index 0000000..07e224c
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef WorkerScriptController_h
+#define WorkerScriptController_h
+
+#if ENABLE(WORKERS)
+
+#include <wtf/OwnPtr.h>
+#include <wtf/Threading.h>
+
+namespace WebCore {
+
+    class ScriptSourceCode;
+    class ScriptValue;
+    class WorkerContext;
+    class WorkerContextExecutionProxy;
+
+    class WorkerScriptController {
+    public:
+        WorkerScriptController(WorkerContext*);
+        ~WorkerScriptController();
+
+        WorkerContextExecutionProxy* proxy() { return m_proxy.get(); }
+
+        ScriptValue evaluate(const ScriptSourceCode&);
+        ScriptValue evaluate(const ScriptSourceCode&, ScriptValue* exception);
+
+        void setException(ScriptValue);
+
+        void forbidExecution();
+
+    private:
+        WorkerContext* m_workerContext;
+        OwnPtr<WorkerContextExecutionProxy> m_proxy;
+
+        Mutex m_sharedDataMutex;
+        bool m_executionForbidden;
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
+
+#endif // WorkerScriptController_h