2009-04-18 Jian Li <jianli@chromium.org>
authordimich@chromium.org <dimich@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 19 Apr 2009 01:40:40 +0000 (01:40 +0000)
committerdimich@chromium.org <dimich@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 19 Apr 2009 01:40:40 +0000 (01:40 +0000)
        Reviewed by Dimitri Glazkov.

        https://bugs.webkit.org/show_bug.cgi?id=25170
        Upstream V8WorkerCustom.cpp and V8WorkerContextCustom.cpp for V8 bindings.

        * bindings/v8/WorkerContextExecutionProxy.cpp:
        (WebCore::WorkerContextExecutionProxy::findOrCreateEventListener):
        * bindings/v8/WorkerContextExecutionProxy.h:
        * bindings/v8/custom/V8WorkerContextCustom.cpp: Added.
        * bindings/v8/custom/V8WorkerCustom.cpp: Added.

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

WebCore/ChangeLog
WebCore/bindings/v8/WorkerContextExecutionProxy.cpp
WebCore/bindings/v8/WorkerContextExecutionProxy.h
WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp [new file with mode: 0755]
WebCore/bindings/v8/custom/V8WorkerCustom.cpp [new file with mode: 0755]

index 342ac73..c0c5bcd 100644 (file)
@@ -2,6 +2,19 @@
 
         Reviewed by Dimitri Glazkov.
 
+        https://bugs.webkit.org/show_bug.cgi?id=25170
+        Upstream V8WorkerCustom.cpp and V8WorkerContextCustom.cpp for V8 bindings.
+
+        * bindings/v8/WorkerContextExecutionProxy.cpp:
+        (WebCore::WorkerContextExecutionProxy::findOrCreateEventListener):
+        * bindings/v8/WorkerContextExecutionProxy.h:
+        * bindings/v8/custom/V8WorkerContextCustom.cpp: Added.
+        * bindings/v8/custom/V8WorkerCustom.cpp: Added.
+
+2009-04-18  Jian Li  <jianli@chromium.org>
+
+        Reviewed by Dimitri Glazkov.
+
         https://bugs.webkit.org/post_bug.cg://bugs.webkit.org/show_bug.cgi?id=25167 
         Change createHiddenXHRDependency and removeHiddenXHRDependency so that they can be used by other custom code in V8 bindings.
 
index 17cd86d..5be353b 100644 (file)
@@ -396,7 +396,7 @@ PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListen
     return newListener.release();
 }
 
-PassRefPtr<V8EventListener> WorkerContextExecutionProxy::FindOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly)
+PassRefPtr<V8EventListener> WorkerContextExecutionProxy::findOrCreateEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly)
 {
     return findOrCreateEventListenerHelper(object, isInline, findOnly, false);
 }
index e57312a..dad191c 100644 (file)
@@ -56,7 +56,6 @@ namespace WebCore {
         // 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);
@@ -65,6 +64,7 @@ namespace WebCore {
         static v8::Handle<v8::Value> WorkerContextToV8Object(WorkerContext* wc);
 
         // Finds/creates event listener wrappers.
+        PassRefPtr<V8EventListener> findOrCreateEventListener(v8::Local<v8::Value> listener, bool isInline, bool findOnly);
         PassRefPtr<V8EventListener> findOrCreateObjectEventListener(v8::Local<v8::Value> object, bool isInline, bool findOnly);
 
         // Track the event so that we can detach it from the JS wrapper when a worker
diff --git a/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerContextCustom.cpp
new file mode 100755 (executable)
index 0000000..a44f8fb
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * 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 "ExceptionCode.h"
+#include "NotImplemented.h"
+#include "V8Binding.h"
+#include "V8CustomBinding.h"
+#include "V8Proxy.h"
+#include "V8Utilities.h"
+#include "V8WorkerContextEventListener.h"
+#include "WorkerContext.h"
+
+namespace WebCore {
+
+ACCESSOR_GETTER(WorkerContextSelf)
+{
+    INC_STATS(L"DOM.WorkerContext.self._get");
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
+    return WorkerContextExecutionProxy::WorkerContextToV8Object(workerContext);
+}
+
+ACCESSOR_GETTER(WorkerContextOnmessage)
+{
+    INC_STATS(L"DOM.WorkerContext.onmessage._get");
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
+    if (workerContext->onmessage()) {
+        V8WorkerContextEventListener* listener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage());
+        v8::Local<v8::Object> v8Listener = listener->getListenerObject();
+        return v8Listener;
+    }
+    return v8::Undefined();
+}
+
+ACCESSOR_SETTER(WorkerContextOnmessage)
+{
+    INC_STATS(L"DOM.WorkerContext.onmessage._set");
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, info.Holder());
+    V8WorkerContextEventListener* oldListener = static_cast<V8WorkerContextEventListener*>(workerContext->onmessage());
+    if (value->IsNull()) {
+        if (workerContext->onmessage()) {
+            v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
+            removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex);
+        }
+
+        // Clear the listener.
+        workerContext->setOnmessage(0);
+    } else {
+        RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(value), false, false);
+        if (listener) {
+            if (oldListener) {
+                v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
+                removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerContextRequestCacheIndex);
+            }
+
+            workerContext->setOnmessage(listener);
+            createHiddenDependency(info.Holder(), value, V8Custom::kWorkerContextRequestCacheIndex);
+        }
+    }
+}
+
+v8::Handle<v8::Value> SetTimeoutOrInterval(const v8::Arguments& args, bool singleShot)
+{
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder());
+
+    int delay = toInt32(args[1]);
+
+    notImplemented();
+
+    return v8::Undefined();
+}
+
+v8::Handle<v8::Value> ClearTimeoutOrInterval(const v8::Arguments& args)
+{
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder());
+
+    int timerId = toInt32(args[0]);
+    workerContext->removeTimeout(timerId);
+
+    return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(WorkerContextImportScripts)
+{
+    INC_STATS(L"DOM.WorkerContext.importScripts()");
+    notImplemented();
+    return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(WorkerContextSetTimeout)
+{
+    INC_STATS(L"DOM.WorkerContext.setTimeout()");
+    return SetTimeoutOrInterval(args, true);
+}
+
+CALLBACK_FUNC_DECL(WorkerContextClearTimeout) {
+    INC_STATS(L"DOM.WorkerContext.clearTimeout()");
+    return ClearTimeoutOrInterval(args);
+}
+
+CALLBACK_FUNC_DECL(WorkerContextSetInterval) {
+    INC_STATS(L"DOM.WorkerContext.setInterval()");
+    return SetTimeoutOrInterval(args, false);
+}
+
+CALLBACK_FUNC_DECL(WorkerContextClearInterval)
+{
+    INC_STATS(L"DOM.WorkerContext.clearInterval()");
+    return ClearTimeoutOrInterval(args);
+}
+
+CALLBACK_FUNC_DECL(WorkerContextAddEventListener)
+{
+    INC_STATS(L"DOM.WorkerContext.addEventListener()");
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder());
+
+    RefPtr<V8EventListener> listener = workerContext->script()->proxy()->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, false);
+
+    if (listener) {
+        String type = toWebCoreString(args[0]);
+        bool useCapture = args[2]->BooleanValue();
+        workerContext->addEventListener(type, listener, useCapture);
+
+        createHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerContextRequestCacheIndex);
+    }
+    return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(WorkerContextRemoveEventListener)
+{
+    INC_STATS(L"DOM.WorkerContext.removeEventListener()");
+    WorkerContext* workerContext = V8Proxy::ToNativeObject<WorkerContext>(V8ClassIndex::WORKERCONTEXT, args.Holder());
+    WorkerContextExecutionProxy* proxy = workerContext->script()->proxy();
+
+    RefPtr<V8EventListener> listener = proxy->findOrCreateEventListener(v8::Local<v8::Object>::Cast(args[1]), false, true);
+
+    if (listener) {
+        String type = toWebCoreString(args[0]);
+        bool useCapture = args[2]->BooleanValue();
+        workerContext->removeEventListener(type, listener.get(), useCapture);
+
+        removeHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerContextRequestCacheIndex);
+    }
+
+    return v8::Undefined();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)
diff --git a/WebCore/bindings/v8/custom/V8WorkerCustom.cpp b/WebCore/bindings/v8/custom/V8WorkerCustom.cpp
new file mode 100755 (executable)
index 0000000..faca90a
--- /dev/null
@@ -0,0 +1,230 @@
+/*
+ * 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 "Worker.h"
+
+#include "ExceptionCode.h"
+#include "Frame.h"
+#include "V8Binding.h"
+#include "V8CustomBinding.h"
+#include "V8ObjectEventListener.h"
+#include "V8Proxy.h"
+#include "V8Utilities.h"
+#include "WorkerContext.h"
+#include "WorkerContextExecutionProxy.h"
+
+namespace WebCore {
+
+CALLBACK_FUNC_DECL(WorkerConstructor)
+{
+    INC_STATS(L"DOM.Worker.Constructor");
+
+    if (!WorkerContextExecutionProxy::isWebWorkersEnabled()) {
+        return throwError("Worker is not enabled.", V8Proxy::SYNTAX_ERROR);
+    }
+
+    if (!args.IsConstructCall()) {
+        return throwError("DOM object constructor cannot be called as a function.");
+    }
+
+    if (args.Length() == 0) {
+        return throwError("Not enough arguments", V8Proxy::SYNTAX_ERROR);
+    }
+
+    v8::TryCatch tryCatch;
+    v8::Handle<v8::String> scriptUrl = args[0]->ToString();
+    if (tryCatch.HasCaught()) {
+        return throwError(tryCatch.Exception());
+    }
+    if (scriptUrl.IsEmpty())
+        return v8::Undefined();
+
+    // Get the script execution context.
+    ScriptExecutionContext* context = 0;
+    WorkerContextExecutionProxy* proxy = WorkerContextExecutionProxy::retrieve();
+    if (proxy)
+        context = proxy->workerContext();
+    else {
+        Frame* frame = V8Proxy::retrieveFrame();
+        if (!frame)
+            return v8::Undefined();
+        context = frame->document();
+    }
+
+    // Create the worker object.
+    // Note: it's OK to let this RefPtr go out of scope because we also call SetDOMWrapper(), which effectively holds a reference to obj.
+    ExceptionCode ec = 0;
+    RefPtr<Worker> obj = Worker::create(toWebCoreString(scriptUrl), context, ec);
+
+    // Setup the standard wrapper object internal fields.
+    v8::Handle<v8::Object> wrapperObject = args.Holder();
+    V8Proxy::SetDOMWrapper(wrapperObject, V8ClassIndex::WORKER, obj.get());
+
+    obj->ref();
+    V8Proxy::SetJSWrapperForActiveDOMObject(obj.get(), v8::Persistent<v8::Object>::New(wrapperObject));
+
+    return wrapperObject;
+}
+
+ACCESSOR_GETTER(WorkerOnmessage)
+{
+    INC_STATS(L"DOM.Worker.onmessage._get");
+    Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder());
+    if (worker->onmessage()) {
+        V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onmessage());
+        v8::Local<v8::Object> v8Listener = listener->getListenerObject();
+        return v8Listener;
+    }
+    return v8::Undefined();
+}
+
+ACCESSOR_SETTER(WorkerOnmessage)
+{
+    INC_STATS(L"DOM.Worker.onmessage._set");
+    Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder());
+    V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onmessage());
+    if (value->IsNull()) {
+        if (oldListener) {
+            v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
+            removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex);
+        }
+
+        // Clear the listener.
+        worker->setOnmessage(0);
+    } else {
+        V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
+        if (!proxy)
+            return;
+
+        RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false);
+        if (listener) {
+            if (oldListener) {
+                v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
+                removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex);
+            }
+
+            worker->setOnmessage(listener);
+            createHiddenDependency(info.Holder(), value, V8Custom::kWorkerRequestCacheIndex);
+        }
+    }
+}
+
+ACCESSOR_GETTER(WorkerOnerror)
+{
+    INC_STATS(L"DOM.Worker.onerror._get");
+    Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder());
+    if (worker->onerror()) {
+        V8ObjectEventListener* listener = static_cast<V8ObjectEventListener*>(worker->onerror());
+        v8::Local<v8::Object> v8Listener = listener->getListenerObject();
+        return v8Listener;
+    }
+    return v8::Undefined();
+}
+
+ACCESSOR_SETTER(WorkerOnerror)
+{
+    INC_STATS(L"DOM.Worker.onerror._set");
+    Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, info.Holder());
+    V8ObjectEventListener* oldListener = static_cast<V8ObjectEventListener*>(worker->onerror());
+    if (value->IsNull()) {
+        if (oldListener) {
+            v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
+            removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex);
+        }
+
+        // Clear the listener.
+        worker->setOnerror(0);
+    } else {
+        V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
+        if (!proxy)
+            return;
+
+        RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(value, false);
+        if (listener) {
+            if (oldListener) {
+                v8::Local<v8::Object> oldV8Listener = oldListener->getListenerObject();
+                removeHiddenDependency(info.Holder(), oldV8Listener, V8Custom::kWorkerRequestCacheIndex);
+            }
+
+            worker->setOnerror(listener);
+            createHiddenDependency(info.Holder(), value, V8Custom::kWorkerRequestCacheIndex);
+        }
+    }
+}
+
+CALLBACK_FUNC_DECL(WorkerAddEventListener)
+{
+    INC_STATS(L"DOM.Worker.addEventListener()");
+    Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder());
+
+    V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
+    if (!proxy)
+        return v8::Undefined();
+
+    RefPtr<EventListener> listener = proxy->FindOrCreateObjectEventListener(args[1], false);
+    if (listener) {
+        String type = toWebCoreString(args[0]);
+        bool useCapture = args[2]->BooleanValue();
+        worker->addEventListener(type, listener, useCapture);
+
+        createHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerRequestCacheIndex);
+    }
+    return v8::Undefined();
+}
+
+CALLBACK_FUNC_DECL(WorkerRemoveEventListener)
+{
+    INC_STATS(L"DOM.Worker.removeEventListener()");
+    Worker* worker = V8Proxy::ToNativeObject<Worker>(V8ClassIndex::WORKER, args.Holder());
+
+    V8Proxy* proxy = V8Proxy::retrieve(worker->scriptExecutionContext());
+    if (!proxy)
+        return v8::Undefined(); // Probably leaked.
+
+    RefPtr<EventListener> listener = proxy->FindObjectEventListener(args[1], false);
+
+    if (listener) {
+        String type = toWebCoreString(args[0]);
+        bool useCapture = args[2]->BooleanValue();
+        worker->removeEventListener(type, listener.get(), useCapture);
+
+        removeHiddenDependency(args.Holder(), args[1], V8Custom::kWorkerRequestCacheIndex);
+    }
+
+    return v8::Undefined();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WORKERS)