script/dom/workers/sharedworker.rs
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
5use dom_struct::dom_struct;
6use js::context::JSContext;
7use js::rust::HandleObject;
8
9use crate::dom::bindings::codegen::Bindings::SharedWorkerBinding::SharedWorkerMethods;
10use crate::dom::bindings::codegen::UnionTypes::{
11 StringOrSharedWorkerOptions, TrustedScriptURLOrUSVString,
12};
13use crate::dom::bindings::error::{Error, Fallible};
14use crate::dom::bindings::inheritance::Castable;
15use crate::dom::bindings::reflector::reflect_dom_object_with_proto_and_cx;
16use crate::dom::bindings::root::{Dom, DomRoot};
17use crate::dom::eventtarget::EventTarget;
18use crate::dom::globalscope::GlobalScope;
19use crate::dom::messageport::MessagePort;
20use crate::dom::trustedtypes::trustedscripturl::TrustedScriptURL;
21use crate::dom::window::Window;
22use crate::script_runtime::CanGc;
23
24/// <https://html.spec.whatwg.org/multipage/#shared-workers-and-the-sharedworker-interface>
25#[dom_struct]
26pub(crate) struct SharedWorker {
27 eventtarget: EventTarget,
28 /// The outside port returned to the creator's global.
29 port: Dom<MessagePort>,
30}
31
32impl SharedWorker {
33 fn new_inherited(port: &MessagePort) -> SharedWorker {
34 SharedWorker {
35 eventtarget: EventTarget::new_inherited(),
36 port: Dom::from_ref(port),
37 }
38 }
39
40 fn new(
41 global: &GlobalScope,
42 proto: Option<HandleObject>,
43 port: &MessagePort,
44 cx: &mut js::context::JSContext,
45 ) -> DomRoot<SharedWorker> {
46 reflect_dom_object_with_proto_and_cx(
47 Box::new(SharedWorker::new_inherited(port)),
48 global,
49 proto,
50 cx,
51 )
52 }
53}
54
55impl SharedWorkerMethods<crate::DomTypeHolder> for SharedWorker {
56 /// <https://html.spec.whatwg.org/multipage/#dom-sharedworker>
57 fn Constructor(
58 cx: &mut JSContext,
59 window: &Window,
60 proto: Option<HandleObject>,
61 script_url: TrustedScriptURLOrUSVString,
62 options: StringOrSharedWorkerOptions,
63 ) -> Fallible<DomRoot<SharedWorker>> {
64 let global = window.upcast::<GlobalScope>();
65
66 // Step 1. Let compliantScriptURL be the result of invoking the get trusted type
67 // compliant string algorithm with TrustedScriptURL, this's relevant global object,
68 // scriptURL, "SharedWorker constructor", and "script".
69 let compliant_script_url = TrustedScriptURL::get_trusted_type_compliant_string(
70 cx,
71 global,
72 script_url,
73 "SharedWorker constructor",
74 )?;
75
76 // Step 2. If options is a DOMString, set options to a new SharedWorkerOptions
77 // dictionary whose name member is set to the value of options and whose other
78 // members are set to their default values.
79 match options {
80 StringOrSharedWorkerOptions::String(name) => {
81 // TODO: The name will be used later.
82 let _worker_name = name;
83 },
84 StringOrSharedWorkerOptions::SharedWorkerOptions(_opts) => {
85 // TODO: Extract name from opts when implementing the registry phase.
86 },
87 }
88
89 // Step 3. Let outsideSettings be this's relevant settings object.
90 // (outsideSettings is `global` throughout.)
91
92 // Step 4. Let urlRecord be the result of encoding-parsing a URL given
93 // compliantScriptURL, relative to outsideSettings.
94 // Step 5. If urlRecord is failure, then throw a "SyntaxError" DOMException.
95 let Ok(_worker_url) = global.encoding_parse_a_url(&compliant_script_url.str()) else {
96 return Err(Error::Syntax(None));
97 };
98
99 // Step 6. Let outsidePort be a new MessagePort in outsideSettings's realm.
100 let outside_port = MessagePort::new(global, CanGc::from_cx(cx));
101 global.track_message_port(&outside_port, None);
102
103 // Step 7. Set this's port to outsidePort.
104 // (Stored via SharedWorker::new below.)
105
106 // TODO Step 8. Let callerIsSecureContext be true if outsideSettings is a secure
107 // context; otherwise, false.
108
109 // TODO Step 9. Let outsideStorageKey be the result of running obtain a storage key
110 // for non-storage purposes given outsideSettings.
111
112 // TODO Step 10. Let worker be this.
113
114 // TODO Step 11
115
116 Ok(SharedWorker::new(global, proto, &outside_port, cx))
117 }
118
119 /// <https://html.spec.whatwg.org/multipage/#dom-sharedworker-port>
120 fn Port(&self) -> DomRoot<MessagePort> {
121 // The port getter steps are to return this's port.
122 DomRoot::from_ref(&*self.port)
123 }
124
125 // <https://html.spec.whatwg.org/multipage/#handler-abstractworker-onerror>
126 event_handler!(error, GetOnerror, SetOnerror);
127}