From 712955e96abd9606dbc69bf48d9e171c06ce1299 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sun, 22 Jun 2014 18:07:14 +0200 Subject: [PATCH 01/14] Implement a stub Worker interface. Part of #2811. --- .../script/dom/webidls/Worker.webidl | 20 ++++++++++++ src/components/script/dom/worker.rs | 31 +++++++++++++++++++ src/components/script/script.rs | 1 + src/test/content/test_interfaces.html | 1 + 4 files changed, 53 insertions(+) create mode 100644 src/components/script/dom/webidls/Worker.webidl create mode 100644 src/components/script/dom/worker.rs diff --git a/src/components/script/dom/webidls/Worker.webidl b/src/components/script/dom/webidls/Worker.webidl new file mode 100644 index 00000000000..273ab8e5bfd --- /dev/null +++ b/src/components/script/dom/webidls/Worker.webidl @@ -0,0 +1,20 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// http://www.whatwg.org/html/#abstractworker +[NoInterfaceObject/*, Exposed=Window,Worker*/] +interface AbstractWorker { + // attribute EventHandler onerror; +}; + +// http://www.whatwg.org/html/#worker +[Constructor(DOMString scriptURL)/*, Exposed=Window,Worker*/] +interface Worker : EventTarget { + //void terminate(); + + //void postMessage(any message/*, optional sequence transfer*/); + // attribute EventHandler onmessage; +}; +Worker implements AbstractWorker; diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs new file mode 100644 index 00000000000..6c79525a139 --- /dev/null +++ b/src/components/script/dom/worker.rs @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::error::{Fallible, Security}; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::Temporary; +use dom::bindings::utils::{Reflectable, Reflector}; +use dom::eventtarget::EventTarget; + +use servo_util::str::DOMString; + +#[deriving(Encodable)] +pub struct Worker { + eventtarget: EventTarget, +} + +impl Worker { + pub fn Constructor(_global: &GlobalRef, _scriptURL: DOMString) -> Fallible> { + Err(Security) + } +} + +pub trait WorkerMethods { +} + +impl Reflectable for Worker { + fn reflector<'a>(&'a self) -> &'a Reflector { + self.eventtarget.reflector() + } +} diff --git a/src/components/script/script.rs b/src/components/script/script.rs index e5a3ab69867..48b1676a0c4 100644 --- a/src/components/script/script.rs +++ b/src/components/script/script.rs @@ -173,6 +173,7 @@ pub mod dom { pub mod validitystate; pub mod virtualmethods; pub mod window; + pub mod worker; pub mod xmlhttprequest; pub mod xmlhttprequesteventtarget; pub mod xmlhttprequestupload; diff --git a/src/test/content/test_interfaces.html b/src/test/content/test_interfaces.html index 5d851b39092..6fe71e025eb 100644 --- a/src/test/content/test_interfaces.html +++ b/src/test/content/test_interfaces.html @@ -155,6 +155,7 @@ var interfaceNamesInGlobalScope = [ "URLSearchParams", "ValidityState", "Window", + "Worker", "XMLHttpRequest", "XMLHttpRequestUpload", ]; From a345f413cbfefaadced841247ebc074cbd092b84 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sat, 12 Jul 2014 17:25:59 +0200 Subject: [PATCH 02/14] Implement stub classes for WorkerGlobalScope and DedicatedWorkerGlobalScope. Part of #2811. --- .../script/dom/bindings/codegen/Bindings.conf | 3 ++ .../script/dom/dedicatedworkerglobalscope.rs | 33 +++++++++++++++++++ src/components/script/dom/eventtarget.rs | 2 ++ .../webidls/DedicatedWorkerGlobalScope.webidl | 10 ++++++ .../dom/webidls/WorkerGlobalScope.webidl | 27 +++++++++++++++ .../script/dom/workerglobalscope.rs | 25 ++++++++++++++ src/components/script/script.rs | 2 ++ src/test/content/test_interfaces.html | 2 ++ 8 files changed, 104 insertions(+) create mode 100644 src/components/script/dom/dedicatedworkerglobalscope.rs create mode 100644 src/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl create mode 100644 src/components/script/dom/webidls/WorkerGlobalScope.webidl create mode 100644 src/components/script/dom/workerglobalscope.rs diff --git a/src/components/script/dom/bindings/codegen/Bindings.conf b/src/components/script/dom/bindings/codegen/Bindings.conf index ca0f71d9bf7..6fc67b5aab5 100644 --- a/src/components/script/dom/bindings/codegen/Bindings.conf +++ b/src/components/script/dom/bindings/codegen/Bindings.conf @@ -15,6 +15,9 @@ DOMInterfaces = { +'DedicatedWorkerGlobalScope': { + 'createGlobal': True, +}, 'EventListener': { 'nativeType': 'EventListenerBinding::EventListener', }, diff --git a/src/components/script/dom/dedicatedworkerglobalscope.rs b/src/components/script/dom/dedicatedworkerglobalscope.rs new file mode 100644 index 00000000000..1ca6ff21d45 --- /dev/null +++ b/src/components/script/dom/dedicatedworkerglobalscope.rs @@ -0,0 +1,33 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; +use dom::bindings::utils::{Reflectable, Reflector}; +use dom::eventtarget::EventTarget; +use dom::eventtarget::WorkerGlobalScopeTypeId; +use dom::workerglobalscope::DedicatedGlobalScope; +use dom::workerglobalscope::WorkerGlobalScope; + +#[deriving(Encodable)] +pub struct DedicatedWorkerGlobalScope { + workerglobalscope: WorkerGlobalScope, +} + +pub trait DedicatedWorkerGlobalScopeMethods { +} + +impl Reflectable for DedicatedWorkerGlobalScope { + fn reflector<'a>(&'a self) -> &'a Reflector { + self.workerglobalscope.reflector() + } +} + +impl DedicatedWorkerGlobalScopeDerived for EventTarget { + fn is_dedicatedworkerglobalscope(&self) -> bool { + match self.type_id { + WorkerGlobalScopeTypeId(DedicatedGlobalScope) => true, + _ => false + } + } +} diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index 25a50b40ab3..47d09149522 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -12,6 +12,7 @@ use dom::bindings::utils::{Reflectable, Reflector}; use dom::event::Event; use dom::eventdispatcher::dispatch_event; use dom::node::NodeTypeId; +use dom::workerglobalscope::WorkerGlobalScopeId; use dom::xmlhttprequest::XMLHttpRequestId; use dom::virtualmethods::VirtualMethods; use js::jsapi::{JS_CompileUCFunction, JS_GetFunctionObject, JS_CloneFunctionObject}; @@ -34,6 +35,7 @@ pub enum ListenerPhase { pub enum EventTargetTypeId { NodeTargetTypeId(NodeTypeId), WindowTypeId, + WorkerGlobalScopeTypeId(WorkerGlobalScopeId), XMLHttpRequestTargetTypeId(XMLHttpRequestId) } diff --git a/src/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl b/src/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl new file mode 100644 index 00000000000..c0c69219e1e --- /dev/null +++ b/src/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl @@ -0,0 +1,10 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// http://www.whatwg.org/html/#dedicatedworkerglobalscope +[Global/*=Worker,DedicatedWorker*/] +/*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope { + //void postMessage(any message, optional sequence transfer); + // attribute EventHandler onmessage; +}; diff --git a/src/components/script/dom/webidls/WorkerGlobalScope.webidl b/src/components/script/dom/webidls/WorkerGlobalScope.webidl new file mode 100644 index 00000000000..b4670be2eed --- /dev/null +++ b/src/components/script/dom/webidls/WorkerGlobalScope.webidl @@ -0,0 +1,27 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// http://www.whatwg.org/html/#workerglobalscope +//[Exposed=Worker] +interface WorkerGlobalScope : EventTarget { + //readonly attribute WorkerGlobalScope self; + //readonly attribute WorkerLocation location; + + //void close(); + // attribute OnErrorEventHandler onerror; + // attribute EventHandler onlanguagechange; + // attribute EventHandler onoffline; + // attribute EventHandler ononline; + + // also has obsolete members +}; + +// http://www.whatwg.org/html/#WorkerGlobalScope-partial +//[Exposed=Worker] +partial interface WorkerGlobalScope { + //void importScripts(DOMString... urls); + //readonly attribute WorkerNavigator navigator; +}; +//WorkerGlobalScope implements WindowTimers; +//WorkerGlobalScope implements WindowBase64; diff --git a/src/components/script/dom/workerglobalscope.rs b/src/components/script/dom/workerglobalscope.rs new file mode 100644 index 00000000000..61345448133 --- /dev/null +++ b/src/components/script/dom/workerglobalscope.rs @@ -0,0 +1,25 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::utils::{Reflectable, Reflector}; +use dom::eventtarget::EventTarget; + +#[deriving(PartialEq,Encodable)] +pub enum WorkerGlobalScopeId { + DedicatedGlobalScope, +} + +#[deriving(Encodable)] +pub struct WorkerGlobalScope { + pub eventtarget: EventTarget, +} + +pub trait WorkerGlobalScopeMethods { +} + +impl Reflectable for WorkerGlobalScope { + fn reflector<'a>(&'a self) -> &'a Reflector { + self.eventtarget.reflector() + } +} diff --git a/src/components/script/script.rs b/src/components/script/script.rs index 48b1676a0c4..6dba58edd97 100644 --- a/src/components/script/script.rs +++ b/src/components/script/script.rs @@ -75,6 +75,7 @@ pub mod dom { pub mod comment; pub mod console; pub mod customevent; + pub mod dedicatedworkerglobalscope; pub mod document; pub mod documentfragment; pub mod documenttype; @@ -174,6 +175,7 @@ pub mod dom { pub mod virtualmethods; pub mod window; pub mod worker; + pub mod workerglobalscope; pub mod xmlhttprequest; pub mod xmlhttprequesteventtarget; pub mod xmlhttprequestupload; diff --git a/src/test/content/test_interfaces.html b/src/test/content/test_interfaces.html index 6fe71e025eb..cc3c8ddeb88 100644 --- a/src/test/content/test_interfaces.html +++ b/src/test/content/test_interfaces.html @@ -59,6 +59,7 @@ var interfaceNamesInGlobalScope = [ "Comment", "Console", "CustomEvent", + "DedicatedWorkerGlobalScope", // #2823 "Document", "DocumentFragment", "DocumentType", @@ -156,6 +157,7 @@ var interfaceNamesInGlobalScope = [ "ValidityState", "Window", "Worker", + "WorkerGlobalScope", // #2823 "XMLHttpRequest", "XMLHttpRequestUpload", ]; From d8152646f36bc68a8a82287db9f9f511053bbe29 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 15 Jul 2014 19:40:55 +0200 Subject: [PATCH 03/14] Add worker scope variants to the Global enums. --- src/components/script/dom/bindings/global.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/components/script/dom/bindings/global.rs b/src/components/script/dom/bindings/global.rs index 2e34e78e7c3..a82cfc557df 100644 --- a/src/components/script/dom/bindings/global.rs +++ b/src/components/script/dom/bindings/global.rs @@ -6,6 +6,7 @@ use dom::bindings::js::{JS, JSRef, Root}; use dom::bindings::utils::{Reflectable, Reflector}; +use dom::workerglobalscope::WorkerGlobalScope; use dom::window::Window; use page::Page; use script_task::ScriptChan; @@ -16,27 +17,32 @@ use url::Url; pub enum GlobalRef<'a> { Window(JSRef<'a, Window>), + Worker(JSRef<'a, WorkerGlobalScope>), } pub enum GlobalRoot<'a, 'b> { WindowRoot(Root<'a, 'b, Window>), + WorkerRoot(Root<'a, 'b, WorkerGlobalScope>), } #[deriving(Encodable)] pub enum GlobalField { WindowField(JS), + WorkerField(JS), } impl<'a> GlobalRef<'a> { pub fn get_cx(&self) -> *mut JSContext { match *self { Window(ref window) => window.get_cx(), + Worker(_) => fail!("NYI"), } } pub fn as_window<'b>(&'b self) -> &'b JSRef<'b, Window> { match *self { Window(ref window) => window, + Worker(_) => fail!("expected a Window scope"), } } @@ -57,6 +63,7 @@ impl<'a> Reflectable for GlobalRef<'a> { fn reflector<'b>(&'b self) -> &'b Reflector { match *self { Window(ref window) => window.reflector(), + Worker(ref worker) => worker.reflector(), } } } @@ -65,6 +72,7 @@ impl<'a, 'b> GlobalRoot<'a, 'b> { pub fn root_ref<'c>(&'c self) -> GlobalRef<'c> { match *self { WindowRoot(ref window) => Window(window.root_ref()), + WorkerRoot(ref worker) => Worker(worker.root_ref()), } } } @@ -73,12 +81,14 @@ impl GlobalField { pub fn from_rooted(global: &GlobalRef) -> GlobalField { match *global { Window(ref window) => WindowField(JS::from_rooted(window)), + Worker(ref worker) => WorkerField(JS::from_rooted(worker)), } } pub fn root(&self) -> GlobalRoot { match *self { WindowField(ref window) => WindowRoot(window.root()), + WorkerField(ref worker) => WorkerRoot(worker.root()), } } } From 25abe8b289e967b3fcd7bc57040a2432646fb2bd Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Sun, 13 Jul 2014 18:15:24 +0200 Subject: [PATCH 04/14] Parse the URL passed to the Worker constructor. --- src/components/script/dom/worker.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 6c79525a139..5a62f1c37f4 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -2,13 +2,14 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::error::{Fallible, Security}; +use dom::bindings::error::{Fallible, Security, Syntax}; use dom::bindings::global::GlobalRef; use dom::bindings::js::Temporary; use dom::bindings::utils::{Reflectable, Reflector}; use dom::eventtarget::EventTarget; use servo_util::str::DOMString; +use servo_util::url::try_parse_url; #[deriving(Encodable)] pub struct Worker { @@ -16,7 +17,13 @@ pub struct Worker { } impl Worker { - pub fn Constructor(_global: &GlobalRef, _scriptURL: DOMString) -> Fallible> { + pub fn Constructor(global: &GlobalRef, scriptURL: DOMString) -> Fallible> { + // Step 2-4. + let _worker_url = match try_parse_url(scriptURL.as_slice(), Some(global.get_url())) { + Ok(url) => url, + Err(_) => return Err(Syntax), + }; + Err(Security) } } From 2d74f4d8d8c6ee02129dccb5875c82cb63c1c526 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 15 Jul 2014 16:04:26 +0200 Subject: [PATCH 05/14] Spawn a thread for workers. --- src/components/script/dom/worker.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 5a62f1c37f4..09b5072a06d 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -11,6 +11,8 @@ use dom::eventtarget::EventTarget; use servo_util::str::DOMString; use servo_util::url::try_parse_url; +use std::task::TaskBuilder; + #[deriving(Encodable)] pub struct Worker { eventtarget: EventTarget, @@ -19,11 +21,15 @@ pub struct Worker { impl Worker { pub fn Constructor(global: &GlobalRef, scriptURL: DOMString) -> Fallible> { // Step 2-4. - let _worker_url = match try_parse_url(scriptURL.as_slice(), Some(global.get_url())) { + let worker_url = match try_parse_url(scriptURL.as_slice(), Some(global.get_url())) { Ok(url) => url, Err(_) => return Err(Syntax), }; + let name = format!("Web Worker at {}", worker_url); + TaskBuilder::new().named(name).spawn(proc() { + println!("Spawned!"); + }); Err(Security) } } From 7b7303e6bc4309c7f0fefbef2191d38b3759ca50 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 15 Jul 2014 16:36:53 +0200 Subject: [PATCH 06/14] Add a constructor for DedicatedWorkerGlobalScope. --- .../script/dom/dedicatedworkerglobalscope.rs | 17 +++++++++++++++++ src/components/script/dom/workerglobalscope.rs | 10 +++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/components/script/dom/dedicatedworkerglobalscope.rs b/src/components/script/dom/dedicatedworkerglobalscope.rs index 1ca6ff21d45..80c6fd762ba 100644 --- a/src/components/script/dom/dedicatedworkerglobalscope.rs +++ b/src/components/script/dom/dedicatedworkerglobalscope.rs @@ -2,18 +2,35 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding; use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; +use dom::bindings::js::Temporary; use dom::bindings::utils::{Reflectable, Reflector}; use dom::eventtarget::EventTarget; use dom::eventtarget::WorkerGlobalScopeTypeId; use dom::workerglobalscope::DedicatedGlobalScope; use dom::workerglobalscope::WorkerGlobalScope; +use js::jsapi::JSContext; + #[deriving(Encodable)] pub struct DedicatedWorkerGlobalScope { workerglobalscope: WorkerGlobalScope, } +impl DedicatedWorkerGlobalScope { + pub fn new_inherited() -> DedicatedWorkerGlobalScope { + DedicatedWorkerGlobalScope { + workerglobalscope: WorkerGlobalScope::new_inherited(DedicatedGlobalScope), + } + } + + pub fn new(cx: *mut JSContext) -> Temporary { + let scope = box DedicatedWorkerGlobalScope::new_inherited(); + DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope) + } +} + pub trait DedicatedWorkerGlobalScopeMethods { } diff --git a/src/components/script/dom/workerglobalscope.rs b/src/components/script/dom/workerglobalscope.rs index 61345448133..2a76fad7e77 100644 --- a/src/components/script/dom/workerglobalscope.rs +++ b/src/components/script/dom/workerglobalscope.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::utils::{Reflectable, Reflector}; -use dom::eventtarget::EventTarget; +use dom::eventtarget::{EventTarget, WorkerGlobalScopeTypeId}; #[deriving(PartialEq,Encodable)] pub enum WorkerGlobalScopeId { @@ -15,6 +15,14 @@ pub struct WorkerGlobalScope { pub eventtarget: EventTarget, } +impl WorkerGlobalScope { + pub fn new_inherited(type_id: WorkerGlobalScopeId) -> WorkerGlobalScope { + WorkerGlobalScope { + eventtarget: EventTarget::new_inherited(WorkerGlobalScopeTypeId(type_id)), + } + } +} + pub trait WorkerGlobalScopeMethods { } From b11440750b70a302ced4394f5f47be3dff3e413d Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 15 Jul 2014 17:32:52 +0200 Subject: [PATCH 07/14] Load scripts in workers. --- .../script/dom/dedicatedworkerglobalscope.rs | 10 ++++++ src/components/script/dom/worker.rs | 26 ++++++++++++-- src/components/script/script_task.rs | 35 ++++++++++--------- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/components/script/dom/dedicatedworkerglobalscope.rs b/src/components/script/dom/dedicatedworkerglobalscope.rs index 80c6fd762ba..1373c8c5653 100644 --- a/src/components/script/dom/dedicatedworkerglobalscope.rs +++ b/src/components/script/dom/dedicatedworkerglobalscope.rs @@ -10,8 +10,12 @@ use dom::eventtarget::EventTarget; use dom::eventtarget::WorkerGlobalScopeTypeId; use dom::workerglobalscope::DedicatedGlobalScope; use dom::workerglobalscope::WorkerGlobalScope; +use script_task::ScriptTask; use js::jsapi::JSContext; +use js::rust::Cx; + +use std::rc::Rc; #[deriving(Encodable)] pub struct DedicatedWorkerGlobalScope { @@ -29,6 +33,12 @@ impl DedicatedWorkerGlobalScope { let scope = box DedicatedWorkerGlobalScope::new_inherited(); DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope) } + + pub fn init() -> (Rc, Temporary) { + let (_js_runtime, js_context) = ScriptTask::new_rt_and_cx(); + let global = DedicatedWorkerGlobalScope::new(js_context.ptr); + (js_context, global) + } } pub trait DedicatedWorkerGlobalScopeMethods { diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 09b5072a06d..63a1da6ce6c 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -4,10 +4,13 @@ use dom::bindings::error::{Fallible, Security, Syntax}; use dom::bindings::global::GlobalRef; -use dom::bindings::js::Temporary; +use dom::bindings::js::{Temporary, RootCollection}; use dom::bindings::utils::{Reflectable, Reflector}; +use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; use dom::eventtarget::EventTarget; +use script_task::StackRootTLS; +use servo_net::resource_task::load_whole_resource; use servo_util::str::DOMString; use servo_util::url::try_parse_url; @@ -27,8 +30,27 @@ impl Worker { }; let name = format!("Web Worker at {}", worker_url); + let resource_task = global.page().resource_task.deref().clone(); TaskBuilder::new().named(name).spawn(proc() { - println!("Spawned!"); + let roots = RootCollection::new(); + let _stack_roots_tls = StackRootTLS::new(&roots); + + let (filename, source) = match load_whole_resource(&resource_task, worker_url.clone()) { + Err(_) => { + println!("error loading script {}", worker_url); + return; + } + Ok((metadata, bytes)) => { + (metadata.final_url, String::from_utf8(bytes).unwrap()) + } + }; + + let (cx, global) = DedicatedWorkerGlobalScope::init(); + let global = global.root(); + match cx.evaluate_script(global.reflector().get_jsobject(), source, filename.to_str(), 1) { + Ok(_) => (), + Err(_) => println!("evaluate_script failed") + } }); Err(Security) } diff --git a/src/components/script/script_task.rs b/src/components/script/script_task.rs index 5551e9d6869..e173a37f762 100644 --- a/src/components/script/script_task.rs +++ b/src/components/script/script_task.rs @@ -115,10 +115,10 @@ impl ScriptChan { } } -struct StackRootTLS; +pub struct StackRootTLS; impl StackRootTLS { - fn new(roots: &RootCollection) -> StackRootTLS { + pub fn new(roots: &RootCollection) -> StackRootTLS { StackRoots.replace(Some(roots as *RootCollection)); StackRootTLS } @@ -210,6 +210,21 @@ impl ScriptTask { window_size: WindowSizeData) -> Rc { let (js_runtime, js_context) = ScriptTask::new_rt_and_cx(); + unsafe { + // JS_SetWrapObjectCallbacks clobbers the existing wrap callback, + // and JSCompartment::wrap crashes if that happens. The only way + // to retrieve the default callback is as the result of + // JS_SetWrapObjectCallbacks, which is why we call it twice. + let callback = JS_SetWrapObjectCallbacks((*js_runtime).ptr, + None, + Some(wrap_for_same_compartment), + None); + JS_SetWrapObjectCallbacks((*js_runtime).ptr, + callback, + Some(wrap_for_same_compartment), + Some(pre_wrap)); + } + let page = Page::new(id, None, layout_chan, window_size, resource_task.clone(), constellation_chan.clone(), @@ -231,26 +246,12 @@ impl ScriptTask { }) } - fn new_rt_and_cx() -> (js::rust::rt, Rc) { + pub fn new_rt_and_cx() -> (js::rust::rt, Rc) { let js_runtime = js::rust::rt(); assert!({ let ptr: *mut JSRuntime = (*js_runtime).ptr; ptr.is_not_null() }); - unsafe { - // JS_SetWrapObjectCallbacks clobbers the existing wrap callback, - // and JSCompartment::wrap crashes if that happens. The only way - // to retrieve the default callback is as the result of - // JS_SetWrapObjectCallbacks, which is why we call it twice. - let callback = JS_SetWrapObjectCallbacks((*js_runtime).ptr, - None, - Some(wrap_for_same_compartment), - None); - JS_SetWrapObjectCallbacks((*js_runtime).ptr, - callback, - Some(wrap_for_same_compartment), - Some(pre_wrap)); - } let js_context = js_runtime.cx(); assert!({ From 3074b4747aea092345381553f7850c3d2d91888f Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 15 Jul 2014 20:02:30 +0200 Subject: [PATCH 08/14] Store the JSContext in a field on the worker global scope. --- src/components/script/dom/bindings/global.rs | 2 +- .../script/dom/dedicatedworkerglobalscope.rs | 20 ++++++++++--------- src/components/script/dom/worker.rs | 6 +++--- .../script/dom/workerglobalscope.rs | 18 ++++++++++++++++- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/components/script/dom/bindings/global.rs b/src/components/script/dom/bindings/global.rs index a82cfc557df..6d3f9c5cc44 100644 --- a/src/components/script/dom/bindings/global.rs +++ b/src/components/script/dom/bindings/global.rs @@ -35,7 +35,7 @@ impl<'a> GlobalRef<'a> { pub fn get_cx(&self) -> *mut JSContext { match *self { Window(ref window) => window.get_cx(), - Worker(_) => fail!("NYI"), + Worker(ref worker) => worker.get_cx(), } } diff --git a/src/components/script/dom/dedicatedworkerglobalscope.rs b/src/components/script/dom/dedicatedworkerglobalscope.rs index 1373c8c5653..13eb6c958da 100644 --- a/src/components/script/dom/dedicatedworkerglobalscope.rs +++ b/src/components/script/dom/dedicatedworkerglobalscope.rs @@ -12,7 +12,6 @@ use dom::workerglobalscope::DedicatedGlobalScope; use dom::workerglobalscope::WorkerGlobalScope; use script_task::ScriptTask; -use js::jsapi::JSContext; use js::rust::Cx; use std::rc::Rc; @@ -23,21 +22,24 @@ pub struct DedicatedWorkerGlobalScope { } impl DedicatedWorkerGlobalScope { - pub fn new_inherited() -> DedicatedWorkerGlobalScope { + pub fn new_inherited(cx: Rc) -> DedicatedWorkerGlobalScope { DedicatedWorkerGlobalScope { - workerglobalscope: WorkerGlobalScope::new_inherited(DedicatedGlobalScope), + workerglobalscope: WorkerGlobalScope::new_inherited(DedicatedGlobalScope, cx), } } - pub fn new(cx: *mut JSContext) -> Temporary { - let scope = box DedicatedWorkerGlobalScope::new_inherited(); - DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope) + pub fn new(cx: Rc) -> Temporary { + let scope = box DedicatedWorkerGlobalScope::new_inherited(cx.clone()); + DedicatedWorkerGlobalScopeBinding::Wrap(cx.ptr, scope) } - pub fn init() -> (Rc, Temporary) { + pub fn init() -> Temporary { let (_js_runtime, js_context) = ScriptTask::new_rt_and_cx(); - let global = DedicatedWorkerGlobalScope::new(js_context.ptr); - (js_context, global) + DedicatedWorkerGlobalScope::new(js_context.clone()) + } + + pub fn get_rust_cx<'a>(&'a self) -> &'a Rc { + self.workerglobalscope.get_rust_cx() } } diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 63a1da6ce6c..11bbb6f3257 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -45,9 +45,9 @@ impl Worker { } }; - let (cx, global) = DedicatedWorkerGlobalScope::init(); - let global = global.root(); - match cx.evaluate_script(global.reflector().get_jsobject(), source, filename.to_str(), 1) { + let global = DedicatedWorkerGlobalScope::init().root(); + match global.get_rust_cx().evaluate_script( + global.reflector().get_jsobject(), source, filename.to_str(), 1) { Ok(_) => (), Err(_) => println!("evaluate_script failed") } diff --git a/src/components/script/dom/workerglobalscope.rs b/src/components/script/dom/workerglobalscope.rs index 2a76fad7e77..e48c298ada0 100644 --- a/src/components/script/dom/workerglobalscope.rs +++ b/src/components/script/dom/workerglobalscope.rs @@ -2,9 +2,15 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::trace::Untraceable; use dom::bindings::utils::{Reflectable, Reflector}; use dom::eventtarget::{EventTarget, WorkerGlobalScopeTypeId}; +use js::jsapi::JSContext; +use js::rust::Cx; + +use std::rc::Rc; + #[deriving(PartialEq,Encodable)] pub enum WorkerGlobalScopeId { DedicatedGlobalScope, @@ -13,14 +19,24 @@ pub enum WorkerGlobalScopeId { #[deriving(Encodable)] pub struct WorkerGlobalScope { pub eventtarget: EventTarget, + js_context: Untraceable>, } impl WorkerGlobalScope { - pub fn new_inherited(type_id: WorkerGlobalScopeId) -> WorkerGlobalScope { + pub fn new_inherited(type_id: WorkerGlobalScopeId, + cx: Rc) -> WorkerGlobalScope { WorkerGlobalScope { eventtarget: EventTarget::new_inherited(WorkerGlobalScopeTypeId(type_id)), + js_context: Untraceable::new(cx), } } + + pub fn get_rust_cx<'a>(&'a self) -> &'a Rc { + &*self.js_context + } + pub fn get_cx(&self) -> *mut JSContext { + self.js_context.ptr + } } pub trait WorkerGlobalScopeMethods { From 747bfc6f15a4c1dbfb859539835c30f1f74d1cec Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 15 Jul 2014 19:25:34 +0200 Subject: [PATCH 09/14] Implement global.console in workers. --- .../script/dom/webidls/WorkerGlobalScope.webidl | 6 ++++++ src/components/script/dom/workerglobalscope.rs | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/components/script/dom/webidls/WorkerGlobalScope.webidl b/src/components/script/dom/webidls/WorkerGlobalScope.webidl index b4670be2eed..1b20c5eb190 100644 --- a/src/components/script/dom/webidls/WorkerGlobalScope.webidl +++ b/src/components/script/dom/webidls/WorkerGlobalScope.webidl @@ -25,3 +25,9 @@ partial interface WorkerGlobalScope { }; //WorkerGlobalScope implements WindowTimers; //WorkerGlobalScope implements WindowBase64; + +// Proprietary +partial interface WorkerGlobalScope { + [Replaceable] + readonly attribute Console console; +}; diff --git a/src/components/script/dom/workerglobalscope.rs b/src/components/script/dom/workerglobalscope.rs index e48c298ada0..b12e27d708c 100644 --- a/src/components/script/dom/workerglobalscope.rs +++ b/src/components/script/dom/workerglobalscope.rs @@ -3,12 +3,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::trace::Untraceable; +use dom::bindings::global; +use dom::bindings::js::{JS, JSRef, Temporary, OptionalSettable}; use dom::bindings::utils::{Reflectable, Reflector}; +use dom::console::Console; use dom::eventtarget::{EventTarget, WorkerGlobalScopeTypeId}; use js::jsapi::JSContext; use js::rust::Cx; +use std::cell::Cell; use std::rc::Rc; #[deriving(PartialEq,Encodable)] @@ -20,6 +24,7 @@ pub enum WorkerGlobalScopeId { pub struct WorkerGlobalScope { pub eventtarget: EventTarget, js_context: Untraceable>, + console: Cell>>, } impl WorkerGlobalScope { @@ -28,6 +33,7 @@ impl WorkerGlobalScope { WorkerGlobalScope { eventtarget: EventTarget::new_inherited(WorkerGlobalScopeTypeId(type_id)), js_context: Untraceable::new(cx), + console: Cell::new(None), } } @@ -40,6 +46,17 @@ impl WorkerGlobalScope { } pub trait WorkerGlobalScopeMethods { + fn Console(&self) -> Temporary; +} + +impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> { + fn Console(&self) -> Temporary { + if self.console.get().is_none() { + let console = Console::new(&global::Worker(*self)); + self.console.assign(Some(console)); + } + Temporary::new(self.console.get().get_ref().clone()) + } } impl Reflectable for WorkerGlobalScope { From f403135d9eb74e75841ee6add3913b7b2be45dec Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Tue, 15 Jul 2014 22:08:33 +0200 Subject: [PATCH 10/14] Support Worker globals in global_object_for_js_object. --- src/components/script/dom/bindings/utils.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/script/dom/bindings/utils.rs b/src/components/script/dom/bindings/utils.rs index 628debb24ea..36f68a93f3e 100644 --- a/src/components/script/dom/bindings/utils.rs +++ b/src/components/script/dom/bindings/utils.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::PrototypeList; use dom::bindings::codegen::PrototypeList::MAX_PROTO_CHAIN_LENGTH; use dom::bindings::conversions::{FromJSValConvertible, IDLInterface}; -use dom::bindings::global::{GlobalRef, GlobalField, WindowField}; +use dom::bindings::global::{GlobalRef, GlobalField, WindowField, WorkerField}; use dom::bindings::js::{JS, Temporary, Root}; use dom::bindings::trace::Untraceable; use dom::browsercontext; @@ -591,7 +591,12 @@ pub fn global_object_for_js_object(obj: *mut JSObject) -> GlobalField { Err(_) => (), } - fail!("found DOM global that doesn't unwrap to Window") + match FromJSValConvertible::from_jsval(ptr::mut_null(), ObjectOrNullValue(global), ()) { + Ok(worker) => return WorkerField(worker), + Err(_) => (), + } + + fail!("found DOM global that doesn't unwrap to Window or WorkerGlobalScope") } } From 1fbf9f7749e770904a9c31176bd576e7264d9c0a Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Wed, 16 Jul 2014 11:26:50 +0200 Subject: [PATCH 11/14] Implement WorkerGlobalScope.self. --- src/components/script/dom/webidls/WorkerGlobalScope.webidl | 2 +- src/components/script/dom/workerglobalscope.rs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/components/script/dom/webidls/WorkerGlobalScope.webidl b/src/components/script/dom/webidls/WorkerGlobalScope.webidl index 1b20c5eb190..a8e3b92d193 100644 --- a/src/components/script/dom/webidls/WorkerGlobalScope.webidl +++ b/src/components/script/dom/webidls/WorkerGlobalScope.webidl @@ -5,7 +5,7 @@ // http://www.whatwg.org/html/#workerglobalscope //[Exposed=Worker] interface WorkerGlobalScope : EventTarget { - //readonly attribute WorkerGlobalScope self; + readonly attribute WorkerGlobalScope self; //readonly attribute WorkerLocation location; //void close(); diff --git a/src/components/script/dom/workerglobalscope.rs b/src/components/script/dom/workerglobalscope.rs index b12e27d708c..e6f9235723d 100644 --- a/src/components/script/dom/workerglobalscope.rs +++ b/src/components/script/dom/workerglobalscope.rs @@ -46,10 +46,15 @@ impl WorkerGlobalScope { } pub trait WorkerGlobalScopeMethods { + fn Self(&self) -> Temporary; fn Console(&self) -> Temporary; } impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> { + fn Self(&self) -> Temporary { + Temporary::from_rooted(self) + } + fn Console(&self) -> Temporary { if self.console.get().is_none() { let console = Console::new(&global::Worker(*self)); From c40ad756e6295cb6b39dfb98ac85ba5f77a27fcf Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Wed, 16 Jul 2014 11:54:05 +0200 Subject: [PATCH 12/14] Create Worker objects. --- src/components/script/dom/eventtarget.rs | 1 + src/components/script/dom/worker.rs | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/components/script/dom/eventtarget.rs b/src/components/script/dom/eventtarget.rs index 47d09149522..1683f280100 100644 --- a/src/components/script/dom/eventtarget.rs +++ b/src/components/script/dom/eventtarget.rs @@ -35,6 +35,7 @@ pub enum ListenerPhase { pub enum EventTargetTypeId { NodeTargetTypeId(NodeTypeId), WindowTypeId, + WorkerTypeId, WorkerGlobalScopeTypeId(WorkerGlobalScopeId), XMLHttpRequestTargetTypeId(XMLHttpRequestId) } diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 11bbb6f3257..2cfeff53ce0 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -2,12 +2,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use dom::bindings::error::{Fallible, Security, Syntax}; +use dom::bindings::codegen::Bindings::WorkerBinding; +use dom::bindings::error::{Fallible, Syntax}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{Temporary, RootCollection}; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; -use dom::eventtarget::EventTarget; +use dom::eventtarget::{EventTarget, WorkerTypeId}; use script_task::StackRootTLS; use servo_net::resource_task::load_whole_resource; @@ -22,6 +23,18 @@ pub struct Worker { } impl Worker { + pub fn new_inherited() -> Worker { + Worker { + eventtarget: EventTarget::new_inherited(WorkerTypeId), + } + } + + pub fn new(global: &GlobalRef) -> Temporary { + reflect_dom_object(box Worker::new_inherited(), + global, + WorkerBinding::Wrap) + } + pub fn Constructor(global: &GlobalRef, scriptURL: DOMString) -> Fallible> { // Step 2-4. let worker_url = match try_parse_url(scriptURL.as_slice(), Some(global.get_url())) { @@ -52,7 +65,8 @@ impl Worker { Err(_) => println!("evaluate_script failed") } }); - Err(Security) + + Ok(Worker::new(global)) } } From 9524f8daa70dc3d47685a30072ae6ac4972ad9f4 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Thu, 17 Jul 2014 11:49:11 +0200 Subject: [PATCH 13/14] Explicitly spawn a native task for workers. --- src/components/script/dom/worker.rs | 9 ++++++--- src/components/script/script.rs | 1 + 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index 2cfeff53ce0..e7eb502f6e2 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -15,7 +15,8 @@ use servo_net::resource_task::load_whole_resource; use servo_util::str::DOMString; use servo_util::url::try_parse_url; -use std::task::TaskBuilder; +use native; +use rustrt::task::TaskOpts; #[deriving(Encodable)] pub struct Worker { @@ -42,9 +43,11 @@ impl Worker { Err(_) => return Err(Syntax), }; - let name = format!("Web Worker at {}", worker_url); let resource_task = global.page().resource_task.deref().clone(); - TaskBuilder::new().named(name).spawn(proc() { + + let mut task_opts = TaskOpts::new(); + task_opts.name = Some(format!("Web Worker at {}", worker_url).into_maybe_owned()); + native::task::spawn_opts(task_opts, proc() { let roots = RootCollection::new(); let _stack_roots_tls = StackRootTLS::new(&roots); diff --git a/src/components/script/script.rs b/src/components/script/script.rs index 6dba58edd97..1243e27dfdb 100644 --- a/src/components/script/script.rs +++ b/src/components/script/script.rs @@ -30,6 +30,7 @@ extern crate js; extern crate libc; extern crate native; extern crate net; +extern crate rustrt; extern crate serialize; extern crate time; #[phase(plugin)] From ca2a5f150dc4c6bab9850cab719b86477f674b72 Mon Sep 17 00:00:00 2001 From: Ms2ger Date: Thu, 17 Jul 2014 11:50:04 +0200 Subject: [PATCH 14/14] Add a spec link for the Worker constructor. --- src/components/script/dom/worker.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/script/dom/worker.rs b/src/components/script/dom/worker.rs index e7eb502f6e2..d28d4958ab8 100644 --- a/src/components/script/dom/worker.rs +++ b/src/components/script/dom/worker.rs @@ -36,6 +36,7 @@ impl Worker { WorkerBinding::Wrap) } + // http://www.whatwg.org/html/#dom-worker pub fn Constructor(global: &GlobalRef, scriptURL: DOMString) -> Fallible> { // Step 2-4. let worker_url = match try_parse_url(scriptURL.as_slice(), Some(global.get_url())) {