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}