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.
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);
}
// 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> 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
--- /dev/null
+/*
+ * 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)
--- /dev/null
+/*
+ * 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)