diff options
author | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-21 23:48:34 +0000 |
---|---|---|
committer | jianli@chromium.org <jianli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-01-21 23:48:34 +0000 |
commit | 9257d0132435d1248ca586e878ee67b1b8dcdb56 (patch) | |
tree | 5a6f4164d9f25dc7f0f6b0e83b81c37491141b39 | |
parent | a1a61172ee9e1c59f257c4c8c49d4b9eb4c046e9 (diff) | |
download | chromium_src-9257d0132435d1248ca586e878ee67b1b8dcdb56.zip chromium_src-9257d0132435d1248ca586e878ee67b1b8dcdb56.tar.gz chromium_src-9257d0132435d1248ca586e878ee67b1b8dcdb56.tar.bz2 |
Add V8 bindings for Worker.
Review URL: http://codereview.chromium.org/17246
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@8414 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/scoped_handle_win.h | 4 | ||||
-rw-r--r-- | base/thread.h | 5 | ||||
-rw-r--r-- | webkit/build/JavaScriptCore/SConscript | 1 | ||||
-rw-r--r-- | webkit/build/JavaScriptCore/WTF.vcproj | 6 | ||||
-rw-r--r-- | webkit/build/V8Bindings/SConscript | 5 | ||||
-rw-r--r-- | webkit/build/V8Bindings/V8Bindings.vcproj | 32 | ||||
-rw-r--r-- | webkit/build/WebCore/SConscript | 6 | ||||
-rw-r--r-- | webkit/build/WebCore/WebCore.vcproj | 48 | ||||
-rw-r--r-- | webkit/build/port/SConscript | 2 | ||||
-rw-r--r-- | webkit/port/DerivedSources.make | 2 | ||||
-rw-r--r-- | webkit/port/bindings/scripts/CodeGeneratorV8.pm | 17 | ||||
-rw-r--r-- | webkit/port/bindings/v8/Threading.cpp | 96 | ||||
-rw-r--r-- | webkit/port/bindings/v8/V8WorkerCustom.cpp | 276 | ||||
-rw-r--r-- | webkit/port/bindings/v8/WorkerScriptController.cpp | 124 | ||||
-rw-r--r-- | webkit/port/bindings/v8/WorkerScriptController.h | 64 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_custom.h | 16 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_index.cpp | 5 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_index.h | 12 | ||||
-rw-r--r-- | webkit/port/bindings/v8/v8_proxy.cpp | 17 |
19 files changed, 731 insertions, 7 deletions
diff --git a/base/scoped_handle_win.h b/base/scoped_handle_win.h index ead32ac..e9b2532 100644 --- a/base/scoped_handle_win.h +++ b/base/scoped_handle_win.h @@ -130,8 +130,12 @@ class ScopedHDC { private: void Close() { +#ifdef NOGDI + assert(false); +#else if (hdc_) DeleteDC(hdc_); +#endif // NOGDI } HDC hdc_; diff --git a/base/thread.h b/base/thread.h index 93ba037..fd7fea2 100644 --- a/base/thread.h +++ b/base/thread.h @@ -101,6 +101,9 @@ class Thread : PlatformThread::Delegate { // The native thread handle. PlatformThreadHandle thread_handle() { return thread_; } + // The thread ID. + int thread_id() const { return thread_id_; } + protected: // Called just prior to starting the message loop virtual void Init() {} @@ -130,7 +133,7 @@ class Thread : PlatformThread::Delegate { // by the created thread. MessageLoop* message_loop_; - // Our thread's ID. Used for debugging purposes. + // Our thread's ID. int thread_id_; // The name of the thread. Used for debugging purposes. diff --git a/webkit/build/JavaScriptCore/SConscript b/webkit/build/JavaScriptCore/SConscript index 16b228d..f0db07a 100644 --- a/webkit/build/JavaScriptCore/SConscript +++ b/webkit/build/JavaScriptCore/SConscript @@ -156,7 +156,6 @@ wtf_inputs = [ '$WTF_DIR/RandomNumber.cpp', '$WTF_DIR/RefCountedLeakCounter.cpp', '$WTF_DIR/TCSystemAlloc.cpp', - '$WTF_DIR/Threading.cpp', '$WTF_DIR/unicode/UTF8.cpp', '$WTF_DIR/unicode/icu/CollatorICU.cpp', ] diff --git a/webkit/build/JavaScriptCore/WTF.vcproj b/webkit/build/JavaScriptCore/WTF.vcproj index 7515ad7..5467e42 100644 --- a/webkit/build/JavaScriptCore/WTF.vcproj +++ b/webkit/build/JavaScriptCore/WTF.vcproj @@ -334,15 +334,15 @@ > </File> <File - RelativePath="..\..\..\third_party\WebKit\JavaScriptCore\wtf\Threading.cpp" + RelativePath="..\..\..\third_party\WebKit\JavaScriptCore\wtf\Threading.h" > </File> <File - RelativePath="..\..\..\third_party\WebKit\JavaScriptCore\wtf\Threading.h" + RelativePath="..\..\..\third_party\WebKit\JavaScriptCore\wtf\ThreadingWin.cpp" > </File> <File - RelativePath="..\..\..\third_party\WebKit\JavaScriptCore\wtf\ThreadingWin.cpp" + RelativePath="..\..\..\third_party\WebKit\JavaScriptCore\wtf\ThreadSpecific.h" > </File> <File diff --git a/webkit/build/V8Bindings/SConscript b/webkit/build/V8Bindings/SConscript index 11aa400..ceb335f 100644 --- a/webkit/build/V8Bindings/SConscript +++ b/webkit/build/V8Bindings/SConscript @@ -311,6 +311,8 @@ inputs = [ '$DERIVED_DIR/V8WebKitCSSTransformValue.cpp', '$DERIVED_DIR/V8WebKitTransitionEvent.cpp', '$DERIVED_DIR/V8WheelEvent.cpp', + '$DERIVED_DIR/V8Worker.cpp', + '$DERIVED_DIR/V8WorkerLocation.cpp', '$DERIVED_DIR/V8XMLHttpRequest.cpp', '$DERIVED_DIR/V8XMLHttpRequestException.cpp', '$DERIVED_DIR/V8XMLHttpRequestProgressEvent.cpp', @@ -333,6 +335,7 @@ inputs = [ '$PORT_DIR/bindings/v8/ScriptCallStack.cpp', '$PORT_DIR/bindings/v8/ScriptInstance.cpp', '$PORT_DIR/bindings/v8/ScriptValue.cpp', + '$PORT_DIR/bindings/v8/Threading.cpp', '$PORT_DIR/bindings/v8/v8_custom.cpp', '$PORT_DIR/bindings/v8/v8_events.cpp', '$PORT_DIR/bindings/v8/v8_helpers.cpp', @@ -344,7 +347,9 @@ inputs = [ '$PORT_DIR/bindings/v8/v8_vectornodelist.cpp', '$PORT_DIR/bindings/v8/V8CanvasPixelArrayCustom.cpp', '$PORT_DIR/bindings/v8/V8MessagePortCustom.cpp', + '$PORT_DIR/bindings/v8/V8WorkerCustom.cpp', '$PORT_DIR/bindings/v8/V8XMLHttpRequestCustom.cpp', + '$PORT_DIR/bindings/v8/WorkerScriptController.cpp', ] if env.Bit('windows'): diff --git a/webkit/build/V8Bindings/V8Bindings.vcproj b/webkit/build/V8Bindings/V8Bindings.vcproj index 4d038f2..d582d80 100644 --- a/webkit/build/V8Bindings/V8Bindings.vcproj +++ b/webkit/build/V8Bindings/V8Bindings.vcproj @@ -2280,6 +2280,22 @@ > </File> <File + RelativePath="$(IntDir)\DerivedSources\V8Worker.cpp" + > + </File> + <File + RelativePath="$(IntDir)\DerivedSources\V8Worker.h" + > + </File> + <File + RelativePath="$(IntDir)\DerivedSources\V8WorkerLocation.cpp" + > + </File> + <File + RelativePath="$(IntDir)\DerivedSources\V8WorkerLocation.h" + > + </File> + <File RelativePath="$(IntDir)\DerivedSources\V8XMLHttpRequest.cpp" > </File> @@ -2561,6 +2577,10 @@ > </File> <File + RelativePath="..\..\port\bindings\v8\Threading.cpp" + > + </File> + <File RelativePath="..\..\port\bindings\v8\v8_binding.h" > </File> @@ -2625,9 +2645,21 @@ > </File> <File + RelativePath="..\..\port\bindings\v8\V8WorkerCustom.cpp" + > + </File> + <File RelativePath="..\..\port\bindings\v8\V8XMLHttpRequestCustom.cpp" > </File> + <File + RelativePath="..\..\port\bindings\v8\WorkerScriptController.cpp" + > + </File> + <File + RelativePath="..\..\port\bindings\v8\WorkerScriptController.h" + > + </File> </Files> <Globals> </Globals> diff --git a/webkit/build/WebCore/SConscript b/webkit/build/WebCore/SConscript index 69b170d..78b59b4 100644 --- a/webkit/build/WebCore/SConscript +++ b/webkit/build/WebCore/SConscript @@ -174,6 +174,12 @@ input_files = [ '$WEBCORE_DIR/dom/WebKitAnimationEvent.cpp', '$WEBCORE_DIR/dom/WebKitTransitionEvent.cpp', '$WEBCORE_DIR/dom/WheelEvent.cpp', + '$WEBCORE_DIR/dom/Worker.cpp', + '$WEBCORE_DIR/dom/WorkerContext.cpp', + '$WEBCORE_DIR/dom/WorkerLocation.cpp', + '$WEBCORE_DIR/dom/WorkerMessagingProxy.cpp', + '$WEBCORE_DIR/dom/WorkerTask.cpp', + '$WEBCORE_DIR/dom/WorkerThread.cpp', '$WEBCORE_DIR/dom/XMLTokenizer.cpp', '$WEBCORE_DIR/dom/XMLTokenizerLibxml2.cpp', diff --git a/webkit/build/WebCore/WebCore.vcproj b/webkit/build/WebCore/WebCore.vcproj index 6b94985..a628a06 100644 --- a/webkit/build/WebCore/WebCore.vcproj +++ b/webkit/build/WebCore/WebCore.vcproj @@ -4811,6 +4811,54 @@ > </File> <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\Worker.cpp" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\Worker.h" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerContext.cpp" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerContext.h" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerLocation.cpp" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerLocation.h" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerMessagingProxy.cpp" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerMessagingProxy.h" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerTask.cpp" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerTask.h" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerThread.cpp" + > + </File> + <File + RelativePath="..\..\..\third_party\WebKit\WebCore\dom\WorkerThread.h" + > + </File> + <File RelativePath="..\..\..\third_party\WebKit\WebCore\dom\XMLTokenizer.cpp" > </File> diff --git a/webkit/build/port/SConscript b/webkit/build/port/SConscript index e380b3e..295bd60 100644 --- a/webkit/build/port/SConscript +++ b/webkit/build/port/SConscript @@ -223,6 +223,8 @@ idl_files = [ 'dom/WebKitAnimationEvent.idl', 'dom/WebKitTransitionEvent.idl', 'dom/WheelEvent.idl', + 'dom/Worker.idl', + 'dom/WorkerLocation.idl', 'html/CanvasGradient.idl', 'html/CanvasPattern.idl', diff --git a/webkit/port/DerivedSources.make b/webkit/port/DerivedSources.make index 8e0effa..f1cf49d 100644 --- a/webkit/port/DerivedSources.make +++ b/webkit/port/DerivedSources.make @@ -899,6 +899,8 @@ all : \ V8WebKitCSSTransformValue.h \ V8WebKitTransitionEvent.h \ V8WheelEvent.h \ + V8Worker.h \ + V8WorkerLocation.h \ V8XMLHttpRequest.h \ V8XMLHttpRequestException.h \ V8XMLHttpRequestProgressEvent.h \ diff --git a/webkit/port/bindings/scripts/CodeGeneratorV8.pm b/webkit/port/bindings/scripts/CodeGeneratorV8.pm index c63f314..ab6be33 100644 --- a/webkit/port/bindings/scripts/CodeGeneratorV8.pm +++ b/webkit/port/bindings/scripts/CodeGeneratorV8.pm @@ -262,6 +262,8 @@ sub GenerateHeader push(@headerContent, "\n#if ENABLE(SVG)\n"); } elsif (IsVideoClassName($className)) { push(@headerContent, "\n#if ENABLE(VIDEO)\n"); + } elsif (IsWorkerClassName($className)) { + push(@headerContent, "\n#if ENABLE(WORKERS)\n"); } push(@headerContent, "\n#ifndef $className" . "_H"); @@ -310,6 +312,8 @@ END push(@headerContent, "\n#endif // ENABLE(SVG)\n"); } elsif (IsVideoClassName($className)) { push(@headerContent, "\n#endif // ENABLE(VIDEO)\n"); + } elsif (IsWorkerClassName($className)) { + push(@headerContent, "\n#endif // ENABLE(WORKERS)\n"); } } @@ -1000,6 +1004,8 @@ sub GenerateImplementation push(@implFixedHeader, "#if ENABLE(SVG)\n\n"); } elsif (IsVideoClassName($className)) { push(@implFixedHeader, "#if ENABLE(VIDEO)\n\n"); + } elsif (IsWorkerClassName($className)) { + push(@implFixedHeader, "#if ENABLE(WORKERS)\n\n"); } if ($className =~ /^V8SVGAnimated/) { @@ -1323,6 +1329,8 @@ END push(@implContent, "\n#endif // ENABLE(SVG)\n"); } elsif (IsVideoClassName($className)) { push(@implContent, "\n#endif // ENABLE(VIDEO)\n"); + } elsif (IsWorkerClassName($className)) { + push(@implContent, "\n#endif // ENABLE(WORKERS)\n"); } } @@ -1595,6 +1603,15 @@ sub IsVideoClassName return 0; } +sub IsWorkerClassName +{ + my $class = shift; + return 1 if $class eq "V8Worker"; + return 1 if $class eq "V8WorkerLocation"; + + return 0; +} + sub GetNativeType { my $type = shift; diff --git a/webkit/port/bindings/v8/Threading.cpp b/webkit/port/bindings/v8/Threading.cpp new file mode 100644 index 0000000..f005c76 --- /dev/null +++ b/webkit/port/bindings/v8/Threading.cpp @@ -0,0 +1,96 @@ +// 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" + +#include "Threading.h" +#undef LOG + +#include "base/message_loop.h" +#include "base/task.h" + +namespace WTF { + +struct NewThreadContext { + NewThreadContext(ThreadFunction entryPoint, void* data, const char* name) + : entryPoint(entryPoint) + , data(data) + , name(name) + { } + + ThreadFunction entryPoint; + void* data; + std::string name; + + Mutex creationMutex; +}; + +static void* threadEntryPoint(void* contextData) +{ + NewThreadContext* context = reinterpret_cast<NewThreadContext*>(contextData); + + // Block until our creating thread has completed any extra setup work + { + MutexLocker locker(context->creationMutex); + } + + // Run via Chrome's message loop + MessageLoop message_loop; + message_loop.set_thread_name(context->name); + message_loop.PostTask(FROM_HERE, + NewRunnableFunction(context->entryPoint, context->data)); + message_loop.Run(); + + delete context; + + return NULL; +} + +ThreadIdentifier createThread(ThreadFunction entryPoint, void* data, const char* name) +{ + NewThreadContext* context = new NewThreadContext(entryPoint, data, name); + + // Prevent the thread body from executing until we've established the thread identifier + MutexLocker locker(context->creationMutex); + + return createThreadInternal(threadEntryPoint, context, name); +} + +#if PLATFORM(MAC) || PLATFORM(WIN) + +// This function is deprecated but needs to be kept around for backward +// compatibility. Use the 3-argument version of createThread above. + +ThreadIdentifier createThread(ThreadFunction entryPoint, void* data) +{ + return createThread(entryPoint, data, 0); +} +#endif + +} // namespace WTF diff --git a/webkit/port/bindings/v8/V8WorkerCustom.cpp b/webkit/port/bindings/v8/V8WorkerCustom.cpp new file mode 100644 index 0000000..0d44c5a --- /dev/null +++ b/webkit/port/bindings/v8/V8WorkerCustom.cpp @@ -0,0 +1,276 @@ +// Copyright (c) 2008, 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 "v8_binding.h" +#include "v8_custom.h" +#include "v8_events.h" +#include "v8_proxy.h" + +#include "V8Document.h" +#include "V8HTMLDocument.h" + +#include "ExceptionCode.h" +#include "MessagePort.h" +#include "Worker.h" + +namespace WebCore { + +CALLBACK_FUNC_DECL(WorkerConstructor) { + INC_STATS(L"DOM.Worker.Constructor"); + + if (!args.IsConstructCall()) { + V8Proxy::ThrowError(V8Proxy::TYPE_ERROR, + "DOM object constructor cannot be called as a function."); + return v8::Undefined(); + } + + if (args.Length() == 0) { + V8Proxy::ThrowError(V8Proxy::SYNTAX_ERROR, "Not enough arguments"); + return v8::Undefined(); + } + + v8::TryCatch try_catch; + v8::Handle<v8::String> script_url = args[0]->ToString(); + if (try_catch.HasCaught()) { + v8::ThrowException(try_catch.Exception()); + return v8::Undefined(); + } + if (script_url.IsEmpty()) { + return v8::Undefined(); + } + + // Get the document. + Frame* frame = V8Proxy::retrieveFrame(); + if (!frame) + return v8::Undefined(); + Document* document = 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(script_url), document, ec); + + // Setup the standard wrapper object internal fields. + v8::Handle<v8::Object> wrapper_object = args.Holder(); + V8Proxy::SetDOMWrapper( + wrapper_object, V8ClassIndex::WORKER, obj.get()); + + obj->ref(); + V8Proxy::SetJSWrapperForDOMObject( + obj.get(), v8::Persistent<v8::Object>::New(wrapper_object)); + + return wrapper_object; +} + +// TODO(mbelshe) - merge these with XHR's CreateHiddenXHRDependency + +// Use an array to hold dependents. It works like a ref-counted scheme. +// A value can be added more than once to the xhr object. +static void CreateHiddenDependency(v8::Local<v8::Object> object, + v8::Local<v8::Value> value) { + ASSERT(V8Proxy::GetDOMWrapperType(object) == + V8ClassIndex::WORKER); + v8::Local<v8::Value> cache = + object->GetInternalField(V8Custom::kWorkerRequestCacheIndex); + if (cache->IsNull() || cache->IsUndefined()) { + cache = v8::Array::New(); + object->SetInternalField(V8Custom::kWorkerRequestCacheIndex, cache); + } + + v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); + cache_array->Set(v8::Integer::New(cache_array->Length()), value); +} + +static void RemoveHiddenDependency(v8::Local<v8::Object> object, + v8::Local<v8::Value> value) { + ASSERT(V8Proxy::GetDOMWrapperType(object) == V8ClassIndex::WORKER); + v8::Local<v8::Value> cache = + object->GetInternalField(V8Custom::kWorkerRequestCacheIndex); + ASSERT(cache->IsArray()); + v8::Local<v8::Array> cache_array = v8::Local<v8::Array>::Cast(cache); + for (int i = cache_array->Length() - 1; i >= 0; i--) { + v8::Local<v8::Value> cached = cache_array->Get(v8::Integer::New(i)); + if (cached->StrictEquals(value)) { + cache_array->Delete(i); + return; + } + } + + // We should only get here if we try to remove an event listener that was + // never added. +} + +ACCESSOR_GETTER(WorkerOnmessage) { + INC_STATS(L"DOM.Worker.onmessage._get"); + Worker* imp = V8Proxy::ToNativeObject<Worker>( + V8ClassIndex::WORKER, info.Holder()); + if (imp->onmessage()) { + V8ObjectEventListener* listener = + static_cast<V8ObjectEventListener*>(imp->onmessage()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(WorkerOnmessage) { + INC_STATS(L"DOM.Worker.onmessage._set"); + Worker* imp = V8Proxy::ToNativeObject<Worker>( + V8ClassIndex::WORKER, info.Holder()); + V8ObjectEventListener* old_listener = + static_cast<V8ObjectEventListener*>(imp->onmessage()); + if (value->IsNull()) { + if (old_listener) { + v8::Local<v8::Object> old_v8_listener = old_listener->GetListenerObject(); + RemoveHiddenDependency(info.Holder(), old_v8_listener); + } + + // Clear the listener + imp->setOnmessage(0); + + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->scriptExecutionContext()); + if (!proxy) + return; + + RefPtr<EventListener> listener = + proxy->FindOrCreateObjectEventListener(value, false); + if (listener) { + if (old_listener) { + v8::Local<v8::Object> old_v8_listener = + old_listener->GetListenerObject(); + RemoveHiddenDependency(info.Holder(), old_v8_listener); + } + + imp->setOnmessage(listener); + CreateHiddenDependency(info.Holder(), value); + } + } +} + +ACCESSOR_GETTER(WorkerOnerror) { + INC_STATS(L"DOM.Worker.onerror._get"); + Worker* imp = V8Proxy::ToNativeObject<Worker>( + V8ClassIndex::WORKER, info.Holder()); + if (imp->onerror()) { + V8ObjectEventListener* listener = + static_cast<V8ObjectEventListener*>(imp->onerror()); + v8::Local<v8::Object> v8_listener = listener->GetListenerObject(); + return v8_listener; + } + return v8::Undefined(); +} + +ACCESSOR_SETTER(WorkerOnerror) { + INC_STATS(L"DOM.Worker.onerror._set"); + Worker* imp = V8Proxy::ToNativeObject<Worker>( + V8ClassIndex::WORKER, info.Holder()); + V8ObjectEventListener* old_listener = + static_cast<V8ObjectEventListener*>(imp->onerror()); + if (value->IsNull()) { + if (old_listener) { + v8::Local<v8::Object> old_v8_listener = + old_listener->GetListenerObject(); + RemoveHiddenDependency(info.Holder(), old_v8_listener); + } + + // Clear the listener + imp->setOnerror(0); + } else { + V8Proxy* proxy = V8Proxy::retrieve(imp->scriptExecutionContext()); + if (!proxy) + return; + + RefPtr<EventListener> listener = + proxy->FindOrCreateObjectEventListener(value, false); + if (listener) { + if (old_listener) { + v8::Local<v8::Object> old_v8_listener = old_listener->GetListenerObject(); + RemoveHiddenDependency(info.Holder(), old_v8_listener); + } + + imp->setOnerror(listener); + CreateHiddenDependency(info.Holder(), value); + } + } +} + +CALLBACK_FUNC_DECL(WorkerAddEventListener) { + INC_STATS(L"DOM.Worker.addEventListener()"); + Worker* imp = V8Proxy::ToNativeObject<Worker>( + V8ClassIndex::WORKER, args.Holder()); + + V8Proxy* proxy = V8Proxy::retrieve(imp->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(); + imp->addEventListener(type, listener, useCapture); + + CreateHiddenDependency(args.Holder(), args[1]); + } + return v8::Undefined(); +} + +CALLBACK_FUNC_DECL(WorkerRemoveEventListener) { + INC_STATS(L"DOM.Worker.removeEventListener()"); + Worker* imp = V8Proxy::ToNativeObject<Worker>( + V8ClassIndex::WORKER, args.Holder()); + + V8Proxy* proxy = V8Proxy::retrieve(imp->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(); + imp->removeEventListener(type, listener.get(), useCapture); + + RemoveHiddenDependency(args.Holder(), args[1]); + } + + return v8::Undefined(); +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/webkit/port/bindings/v8/WorkerScriptController.cpp b/webkit/port/bindings/v8/WorkerScriptController.cpp new file mode 100644 index 0000000..9e38c04 --- /dev/null +++ b/webkit/port/bindings/v8/WorkerScriptController.cpp @@ -0,0 +1,124 @@ +// Copyright (c) 2008, 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 "ScriptSourceCode.h" +#include "ScriptValue.h" +#include "v8_proxy.h" +#include "WorkerContext.h" +#include "WorkerMessagingProxy.h" +#include "WorkerThread.h" + +namespace WebCore { + +WorkerScriptController::WorkerScriptController(WorkerContext* workerContext) + : m_workerContext(workerContext) + , m_executionForbidden(false) +{ +} + +WorkerScriptController::~WorkerScriptController() +{ + Dispose(); +} + +void WorkerScriptController::Dispose() +{ + if (!m_context.IsEmpty()) { + m_context.Dispose(); + m_context.Clear(); + } +} + +void WorkerScriptController::InitContextIfNeeded() +{ + // Bail out if the context has already been initialized. + if (!m_context.IsEmpty()) + return; + + // Create a new environment + v8::Persistent<v8::ObjectTemplate> global_template; + m_context = v8::Context::New(NULL, global_template); + + // TODO (jianli): to initialize the context. +} + +ScriptValue WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode) +{ + { + MutexLocker lock(m_sharedDataMutex); + if (m_executionForbidden) + return ScriptValue(); + } + + v8::Local<v8::Value> result; + { + v8::Locker locker; + v8::HandleScope hs; + + InitContextIfNeeded(); + v8::Context::Scope scope(m_context); + + v8::Local<v8::String> code = v8ExternalString(sourceCode.source()); + v8::Handle<v8::Script> script = + V8Proxy::CompileScript(code, + sourceCode.url().string(), + sourceCode.startLine() - 1); + + // TODO (jianli): handle infinite recursion. + + result = script->Run(); + + if (V8Proxy::HandleOutOfMemory()) + return ScriptValue(); + } + + m_workerContext->thread()->messagingProxy()-> + reportWorkerThreadActivity(m_workerContext->hasPendingActivity()); + + return ScriptValue(result); +} + +void WorkerScriptController::forbidExecution() +{ + // This function is called from another thread. + MutexLocker lock(m_sharedDataMutex); + m_executionForbidden = true; + + Dispose(); +} + +} // namespace WebCore + +#endif // ENABLE(WORKERS) diff --git a/webkit/port/bindings/v8/WorkerScriptController.h b/webkit/port/bindings/v8/WorkerScriptController.h new file mode 100644 index 0000000..a66e080 --- /dev/null +++ b/webkit/port/bindings/v8/WorkerScriptController.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Apple 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: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 APPLE COMPUTER, INC. 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 "v8.h" + +namespace WebCore { + + class ScriptSourceCode; + class ScriptValue; + class WorkerContext; + + class WorkerScriptController { + public: + WorkerScriptController(WorkerContext*); + ~WorkerScriptController(); + + ScriptValue evaluate(const ScriptSourceCode&); + + void forbidExecution(); + + private: + void InitContextIfNeeded(); + void Dispose(); + + WorkerContext* m_workerContext; + v8::Persistent<v8::Context> m_context; + + Mutex m_sharedDataMutex; + bool m_executionForbidden; + }; + +} // namespace WebCore + +#endif // ENABLE(WORKERS) + +#endif // WorkerScriptController_h diff --git a/webkit/port/bindings/v8/v8_custom.h b/webkit/port/bindings/v8/v8_custom.h index 1dd2858..3d23b26 100644 --- a/webkit/port/bindings/v8/v8_custom.h +++ b/webkit/port/bindings/v8/v8_custom.h @@ -83,6 +83,13 @@ class V8Custom { static const int kMessagePortInternalFieldCount = kDefaultWrapperInternalFieldCount + 2; +#if ENABLE(WORKERS) + static const int kWorkerRequestCacheIndex = + kDefaultWrapperInternalFieldCount + 0; + static const int kWorkerInternalFieldCount = + kDefaultWrapperInternalFieldCount + 1; +#endif + static const int kDOMWindowLocationIndex = kDefaultWrapperInternalFieldCount + 0; static const int kDOMWindowNavigatorIndex = @@ -406,6 +413,15 @@ DECLARE_CALLBACK(SVGElementInstanceAddEventListener) DECLARE_CALLBACK(SVGElementInstanceRemoveEventListener) #endif +// Worker +#if ENABLE(WORKERS) +DECLARE_PROPERTY_ACCESSOR(WorkerOnmessage) +DECLARE_PROPERTY_ACCESSOR(WorkerOnerror) +DECLARE_CALLBACK(WorkerConstructor) +DECLARE_CALLBACK(WorkerAddEventListener) +DECLARE_CALLBACK(WorkerRemoveEventListener) +#endif + #undef DECLARE_INDEXED_ACCESS_CHECK #undef DECLARE_NAMED_ACCESS_CHECK diff --git a/webkit/port/bindings/v8/v8_index.cpp b/webkit/port/bindings/v8/v8_index.cpp index 6f93171..5eb1f81 100644 --- a/webkit/port/bindings/v8/v8_index.cpp +++ b/webkit/port/bindings/v8/v8_index.cpp @@ -354,6 +354,11 @@ #include "V8TimeRanges.h" #endif +#if ENABLE(WORKERS) +#include "V8Worker.h" +#include "V8WorkerLocation.h" +#endif + namespace WebCore { FunctionTemplateFactory V8ClassIndex::GetFactory(V8WrapperType type) { diff --git a/webkit/port/bindings/v8/v8_index.h b/webkit/port/bindings/v8/v8_index.h index 171f690..0f6fc1f 100644 --- a/webkit/port/bindings/v8/v8_index.h +++ b/webkit/port/bindings/v8/v8_index.h @@ -26,6 +26,14 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); #define VIDEO_NONNODE_TYPES(V) #endif +#if ENABLE(WORKERS) +#define WORKER_NONNODE_WRAPPER_TYPES(V) \ + V(WORKER, Worker) \ + V(WORKERLOCATION, WorkerLocation) +#else +#define WORKER_NONNODE_WRAPPER_TYPES(V) +#endif + #define DOM_NODE_TYPES(V) \ V(ATTR, Attr) \ V(CHARACTERDATA, CharacterData) \ @@ -319,8 +327,8 @@ typedef v8::Persistent<v8::FunctionTemplate> (*FunctionTemplateFactory)(); V(XPATHRESULT, XPathResult) \ V(XSLTPROCESSOR, XSLTProcessor) \ ACTIVE_DOM_OBJECT_TYPES(V) \ - VIDEO_NONNODE_TYPES(V) - + VIDEO_NONNODE_TYPES(V) \ + WORKER_NONNODE_WRAPPER_TYPES(V) #define DOM_OBJECT_TYPES(V) \ DOM_OBJECT_TYPES_1(V) \ diff --git a/webkit/port/bindings/v8/v8_proxy.cpp b/webkit/port/bindings/v8/v8_proxy.cpp index b100ae6..913bad2 100644 --- a/webkit/port/bindings/v8/v8_proxy.cpp +++ b/webkit/port/bindings/v8/v8_proxy.cpp @@ -192,6 +192,11 @@ #include "V8SVGPODTypeWrapper.h" #endif // SVG +#if ENABLE(WORKERS) +#include "Worker.h" +#include "WorkerLocation.h" +#endif // WORKERS + #if ENABLE(XPATH) #include "XPathEvaluator.h" #endif @@ -1772,6 +1777,18 @@ v8::Persistent<v8::FunctionTemplate> V8Proxy::GetTemplate( break; } +#if ENABLE(WORKERS) + case V8ClassIndex::WORKER: { + // Reserve one more internal field for keeping event listeners. + v8::Local<v8::ObjectTemplate> instance_template = + desc->InstanceTemplate(); + instance_template->SetInternalFieldCount( + V8Custom::kWorkerInternalFieldCount); + desc->SetCallHandler(USE_CALLBACK(WorkerConstructor)); + break; + } +#endif // WORKERS + // The following objects are created from JavaScript. case V8ClassIndex::DOMPARSER: desc->SetCallHandler(USE_CALLBACK(DOMParserConstructor)); |