script/dom/
mod.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
5//! The implementation of the DOM.
6//!
7//! The DOM is comprised of interfaces (defined by specifications using
8//! [WebIDL](https://heycam.github.io/webidl/)) that are implemented as Rust
9//! structs in submodules of this module. Its implementation is documented
10//! below.
11//!
12//! A DOM object and its reflector
13//! ==============================
14//!
15//! The implementation of an interface `Foo` in Servo's DOM involves two
16//! related but distinct objects:
17//!
18//! * the **DOM object**: an instance of the Rust struct `dom::foo::Foo`
19//!   (marked with the `#[dom_struct]` attribute) on the Rust heap;
20//! * the **reflector**: a `JSObject` allocated by SpiderMonkey, that owns the
21//!   DOM object.
22//!
23//! Memory management
24//! =================
25//!
26//! Reflectors of DOM objects, and thus the DOM objects themselves, are managed
27//! by the SpiderMonkey Garbage Collector. Thus, keeping alive a DOM object
28//! is done through its reflector.
29//!
30//! For more information, see:
31//!
32//! * rooting pointers on the stack:
33//!   the [`Root`](bindings/root/struct.Root.html) smart pointer;
34//! * tracing pointers in member fields: the [`Dom`](bindings/root/struct.Dom.html),
35//!   [`MutNullableDom`](bindings/root/struct.MutNullableDom.html) and
36//!   [`MutDom`](bindings/root/struct.MutDom.html) smart pointers and
37//!   [the tracing implementation](bindings/trace/index.html);
38//! * rooting pointers from across thread boundaries or in channels: the
39//!   [`Trusted`](bindings/refcounted/struct.Trusted.html) smart pointer;
40//!
41//! Inheritance
42//! ===========
43//!
44//! Rust does not support struct inheritance, as would be used for the
45//! object-oriented DOM APIs. To work around this issue, Servo stores an
46//! instance of the superclass in the first field of its subclasses. (Note that
47//! it is stored by value, rather than in a smart pointer such as `Dom<T>`.)
48//!
49//! This implies that a pointer to an object can safely be cast to a pointer
50//! to all its classes.
51//!
52//! This invariant is enforced by the lint in
53//! `plugins::lints::inheritance_integrity`.
54//!
55//! Interfaces which either derive from or are derived by other interfaces
56//! implement the `Castable` trait, which provides three methods `is::<T>()`,
57//! `downcast::<T>()` and `upcast::<T>()` to cast across the type hierarchy
58//! and check whether a given instance is of a given type.
59//!
60//! ```ignore
61//! use dom::bindings::inheritance::Castable;
62//! use dom::element::Element;
63//! use dom::htmlelement::HTMLElement;
64//! use dom::htmlinputelement::HTMLInputElement;
65//!
66//! if let Some(elem) = node.downcast::<Element> {
67//!     if elem.is::<HTMLInputElement>() {
68//!         return elem.upcast::<HTMLElement>();
69//!     }
70//! }
71//! ```
72//!
73//! Furthermore, when discriminating a given instance against multiple
74//! interface types, code generation provides a convenient TypeId enum
75//! which can be used to write `match` expressions instead of multiple
76//! calls to `Castable::is::<T>`. The `type_id()` method of an instance is
77//! provided by the farthest interface it derives from, e.g. `EventTarget`
78//! for `HTMLMediaElement`. For convenience, that method is also provided
79//! on the `Node` interface to avoid unnecessary upcasts to `EventTarget`.
80//!
81//! ```ignore
82//! use dom::bindings::inheritance::{EventTargetTypeId, NodeTypeId};
83//!
84//! match *node.type_id() {
85//!     EventTargetTypeId::Node(NodeTypeId::CharacterData(_)) => ...,
86//!     EventTargetTypeId::Node(NodeTypeId::Element(_)) => ...,
87//!     ...,
88//! }
89//! ```
90//!
91//! Construction
92//! ============
93//!
94//! DOM objects of type `T` in Servo have two constructors:
95//!
96//! * a `T::new_inherited` static method that returns a plain `T`, and
97//! * a `T::new` static method that returns `DomRoot<T>`.
98//!
99//! (The result of either method can be wrapped in `Result`, if that is
100//! appropriate for the type in question.)
101//!
102//! The latter calls the former, boxes the result, and creates a reflector
103//! corresponding to it by calling `dom::bindings::utils::reflect_dom_object`
104//! (which yields ownership of the object to the SpiderMonkey Garbage Collector).
105//! This is the API to use when creating a DOM object.
106//!
107//! The former should only be called by the latter, and by subclasses'
108//! `new_inherited` methods.
109//!
110//! DOM object constructors in JavaScript correspond to a `T::Constructor`
111//! static method. This method is always fallible.
112//!
113//! Destruction
114//! ===========
115//!
116//! When the SpiderMonkey Garbage Collector discovers that the reflector of a
117//! DOM object is garbage, it calls the reflector's finalization hook. This
118//! function deletes the reflector's DOM object, calling its destructor in the
119//! process.
120//!
121//! Mutability and aliasing
122//! =======================
123//!
124//! Reflectors are JavaScript objects, and as such can be freely aliased. As
125//! Rust does not allow mutable aliasing, mutable borrows of DOM objects are
126//! not allowed. In particular, any mutable fields use `Cell` or `DomRefCell`
127//! to manage their mutability.
128//!
129//! `Reflector` and `DomObject`
130//! =============================
131//!
132//! Every DOM object has a `Reflector` as its first (transitive) member field.
133//! This contains a `*mut JSObject` that points to its reflector.
134//!
135//! The `FooBinding::Wrap` function creates the reflector, stores a pointer to
136//! the DOM object in the reflector, and initializes the pointer to the reflector
137//! in the `Reflector` field.
138//!
139//! The `DomObject` trait provides a `reflector()` method that returns the
140//! DOM object's `Reflector`. It is implemented automatically for DOM structs
141//! through the `#[dom_struct]` attribute.
142//!
143//! Implementing methods for a DOM object
144//! =====================================
145//!
146//! * `dom::bindings::codegen::Bindings::FooBinding::FooMethods` for methods
147//!   defined through IDL;
148//! * `&self` public methods for public helpers;
149//! * `&self` methods for private helpers.
150//!
151//! Accessing fields of a DOM object
152//! ================================
153//!
154//! All fields of DOM objects are private; accessing them from outside their
155//! module is done through explicit getter or setter methods.
156//!
157//! Inheritance and casting
158//! =======================
159//!
160//! All DOM interfaces part of an inheritance chain (i.e. interfaces
161//! that derive others or are derived from) implement the trait `Castable`
162//! which provides both downcast and upcasts.
163//!
164//! ```ignore
165//! # use script::dom::bindings::inheritance::Castable;
166//! # use script::dom::element::Element;
167//! # use script::dom::node::Node;
168//! # use script::dom::htmlelement::HTMLElement;
169//! fn f(element: &Element) {
170//!     let base = element.upcast::<Node>();
171//!     let derived = element.downcast::<HTMLElement>().unwrap();
172//! }
173//! ```
174//!
175//! Adding a new DOM interface
176//! ==========================
177//!
178//! Adding a new interface `Foo` requires at least the following:
179//!
180//! * adding the new IDL file at `components/script/dom/webidls/Foo.webidl`;
181//! * creating `components/script/dom/foo.rs`;
182//! * listing `foo.rs` in `components/script/dom/mod.rs`;
183//! * defining the DOM struct `Foo` with a `#[dom_struct]` attribute, a
184//!   superclass or `Reflector` member, and other members as appropriate;
185//! * implementing the
186//!   `dom::bindings::codegen::Bindings::FooBinding::FooMethods` trait for
187//!   `Foo`;
188//! * adding/updating the match arm in create_element in
189//!   `components/script/dom/create.rs` (only applicable to new types inheriting
190//!   from `HTMLElement`)
191//!
192//! More information is available in the [bindings module](bindings/index.html).
193//!
194//! Accessing DOM objects from layout
195//! =================================
196//!
197//! Layout code can access the DOM through the
198//! [`LayoutDom`](bindings/root/struct.LayoutDom.html) smart pointer. This does not
199//! keep the DOM object alive; we ensure that no DOM code (Garbage Collection
200//! in particular) runs while layout is accessing the DOM.
201//!
202//! Methods accessible to layout are implemented on `LayoutDom<Foo>` using
203//! `LayoutFooHelpers` traits.
204
205#[macro_use]
206pub(crate) mod macros;
207
208#[allow(unused_imports)]
209pub(crate) mod types {
210    include!(concat!(env!("OUT_DIR"), "/InterfaceTypes.rs"));
211}
212
213pub(crate) mod abortcontroller;
214pub(crate) mod abortsignal;
215#[allow(dead_code)]
216pub(crate) mod abstractrange;
217pub(crate) mod activation;
218pub(crate) mod animationevent;
219pub(crate) mod attr;
220pub(crate) mod audio;
221pub(crate) use self::audio::*;
222pub(crate) mod beforeunloadevent;
223pub(crate) mod bindings;
224pub(crate) mod blob;
225#[cfg(feature = "bluetooth")]
226pub(crate) mod bluetooth;
227#[cfg(feature = "bluetooth")]
228pub(crate) use self::bluetooth::*;
229pub(crate) mod broadcastchannel;
230pub(crate) mod bytelengthqueuingstrategy;
231mod canvas;
232pub(crate) use self::canvas::*;
233pub(crate) mod cdatasection;
234pub(crate) mod characterdata;
235pub(crate) mod client;
236pub(crate) mod clipboard;
237pub(crate) mod clipboardevent;
238pub(crate) mod clipboarditem;
239pub(crate) mod closeevent;
240pub(crate) mod comment;
241pub(crate) mod compositionevent;
242pub(crate) mod compressionstream;
243pub(crate) mod console;
244pub(crate) mod cookiestore;
245pub(crate) mod countqueuingstrategy;
246mod create;
247pub(crate) mod credentialmanagement;
248pub(crate) use self::credentialmanagement::*;
249pub(crate) mod crypto;
250pub(crate) mod cryptokey;
251pub(crate) mod csp;
252pub(crate) mod csppolicyviolationreport;
253pub(crate) mod css;
254pub(crate) use self::css::*;
255pub(crate) mod customelementregistry;
256pub(crate) mod customevent;
257pub(crate) mod customstateset;
258pub(crate) mod datatransfer;
259pub(crate) mod datatransferitem;
260pub(crate) mod datatransferitemlist;
261pub(crate) mod debuggeradddebuggeeevent;
262pub(crate) mod debuggergetpossiblebreakpointsevent;
263pub(crate) mod debuggerglobalscope;
264pub(crate) mod decompressionstream;
265pub(crate) mod defaultteereadrequest;
266pub(crate) mod defaultteeunderlyingsource;
267pub(crate) mod dissimilaroriginlocation;
268pub(crate) mod dissimilaroriginwindow;
269#[allow(dead_code)]
270pub(crate) mod document;
271mod document_embedder_controls;
272pub(crate) mod document_event_handler;
273pub(crate) mod documentfragment;
274pub(crate) mod documentorshadowroot;
275pub(crate) mod documenttype;
276pub(crate) mod domexception;
277pub(crate) mod domimplementation;
278pub(crate) mod dommatrix;
279pub(crate) mod dommatrixreadonly;
280pub(crate) mod domparser;
281pub(crate) mod dompoint;
282pub(crate) mod dompointreadonly;
283pub(crate) mod domquad;
284pub(crate) mod domrect;
285pub(crate) mod domrectlist;
286pub(crate) mod domrectreadonly;
287pub(crate) mod domstringlist;
288pub(crate) mod domstringmap;
289pub(crate) mod domtokenlist;
290pub(crate) mod dynamicmoduleowner;
291#[allow(dead_code)]
292pub(crate) mod element;
293pub(crate) mod elementinternals;
294pub(crate) mod errorevent;
295pub(crate) mod event;
296pub(crate) mod eventsource;
297pub(crate) mod eventtarget;
298pub(crate) mod extendableevent;
299pub(crate) mod extendablemessageevent;
300pub(crate) mod fetchlaterresult;
301pub(crate) mod file;
302pub(crate) mod filelist;
303pub(crate) mod filereader;
304pub(crate) mod filereadersync;
305pub(crate) mod focusevent;
306pub(crate) mod formdata;
307pub(crate) mod formdataevent;
308pub(crate) mod gamepad;
309pub(crate) use self::gamepad::*;
310pub(crate) mod geolocation;
311pub(crate) use self::geolocation::*;
312#[allow(dead_code)]
313pub(crate) mod globalscope;
314pub(crate) mod hashchangeevent;
315pub(crate) mod headers;
316pub(crate) mod history;
317pub(crate) mod html;
318pub(crate) use self::html::*;
319pub(crate) mod indexeddb;
320pub(crate) use self::indexeddb::*;
321pub(crate) mod inputevent;
322pub(crate) mod intersectionobserver;
323pub(crate) mod intersectionobserverentry;
324pub(crate) mod keyboardevent;
325pub(crate) mod location;
326pub(crate) mod mediadeviceinfo;
327pub(crate) mod mediadevices;
328pub(crate) mod mediaerror;
329pub(crate) mod mediafragmentparser;
330pub(crate) mod medialist;
331pub(crate) mod mediametadata;
332pub(crate) mod mediaquerylist;
333pub(crate) mod mediaquerylistevent;
334pub(crate) mod mediasession;
335pub(crate) mod mediastream;
336pub(crate) mod mediastreamtrack;
337pub(crate) mod messagechannel;
338pub(crate) mod messageevent;
339#[allow(dead_code)]
340pub(crate) mod messageport;
341pub(crate) mod mimetype;
342pub(crate) mod mimetypearray;
343pub(crate) mod mouseevent;
344pub(crate) mod mutationobserver;
345pub(crate) mod mutationrecord;
346pub(crate) mod namednodemap;
347pub(crate) mod navigationpreloadmanager;
348pub(crate) mod navigator;
349pub(crate) mod navigatorinfo;
350#[allow(dead_code)]
351pub(crate) mod node;
352pub(crate) mod nodeiterator;
353#[allow(dead_code)]
354pub(crate) mod nodelist;
355pub(crate) mod notification;
356pub(crate) mod pagetransitionevent;
357pub(crate) mod paintsize;
358pub(crate) mod paintworkletglobalscope;
359pub(crate) mod performance;
360#[allow(dead_code)]
361pub(crate) mod performanceentry;
362pub(crate) mod performancemark;
363pub(crate) mod performancemeasure;
364pub(crate) mod performancenavigation;
365pub(crate) mod performancenavigationtiming;
366#[allow(dead_code)]
367pub(crate) mod performanceobserver;
368pub(crate) mod performanceobserverentrylist;
369pub(crate) mod performancepainttiming;
370pub(crate) mod performanceresourcetiming;
371pub(crate) mod permissions;
372pub(crate) mod permissionstatus;
373pub(crate) mod pipelineid;
374pub(crate) mod plugin;
375pub(crate) mod pluginarray;
376#[allow(dead_code)]
377pub(crate) mod pointerevent;
378pub(crate) mod popstateevent;
379pub(crate) mod processinginstruction;
380pub(crate) mod processingoptions;
381pub(crate) mod progressevent;
382#[allow(dead_code)]
383pub(crate) mod promise;
384pub(crate) mod promisenativehandler;
385pub(crate) mod promiserejectionevent;
386pub(crate) mod quotaexceedederror;
387pub(crate) mod radionodelist;
388pub(crate) mod range;
389pub(crate) mod raredata;
390#[allow(dead_code)]
391pub(crate) mod readablebytestreamcontroller;
392pub(crate) mod readablestream;
393pub(crate) mod readablestreambyobreader;
394pub(crate) mod readablestreambyobrequest;
395pub(crate) mod readablestreamdefaultcontroller;
396pub(crate) mod readablestreamdefaultreader;
397pub(crate) mod readablestreamgenericreader;
398pub(crate) mod reportingendpoint;
399pub(crate) mod reportingobserver;
400pub(crate) mod request;
401pub(crate) mod resizeobserver;
402pub(crate) mod resizeobserverentry;
403pub(crate) mod resizeobserversize;
404pub(crate) mod response;
405pub(crate) mod screen;
406mod scrolling_box;
407pub(crate) mod securitypolicyviolationevent;
408pub(crate) mod selection;
409pub(crate) mod servointernals;
410#[allow(dead_code)]
411pub(crate) mod servoparser;
412pub(crate) mod shadowroot;
413pub(crate) mod staticrange;
414pub(crate) mod storage;
415pub(crate) mod storageevent;
416pub(crate) mod submitevent;
417pub(crate) mod subtlecrypto;
418pub(crate) mod svg;
419pub(crate) use self::svg::*;
420#[cfg(feature = "testbinding")]
421mod testing;
422#[cfg(feature = "testbinding")]
423pub(crate) use self::testing::*;
424pub(crate) mod text;
425pub(crate) mod textcontrol;
426pub(crate) mod textdecoder;
427pub(crate) mod textdecodercommon;
428pub(crate) mod textdecoderstream;
429pub(crate) mod textencoder;
430pub(crate) mod textencoderstream;
431pub(crate) mod texttrack;
432pub(crate) mod texttrackcue;
433pub(crate) mod texttrackcuelist;
434pub(crate) mod texttracklist;
435#[allow(dead_code)]
436pub(crate) mod timeranges;
437pub(crate) mod touch;
438pub(crate) mod touchevent;
439pub(crate) mod touchlist;
440pub(crate) mod trackevent;
441pub(crate) mod transitionevent;
442pub(crate) mod treewalker;
443pub(crate) mod trustedhtml;
444pub(crate) mod trustedscript;
445pub(crate) mod trustedscripturl;
446pub(crate) mod trustedtypepolicy;
447pub(crate) mod trustedtypepolicyfactory;
448pub(crate) mod uievent;
449pub(crate) mod underlyingsourcecontainer;
450pub(crate) mod url;
451pub(crate) mod urlhelper;
452pub(crate) mod urlpattern;
453pub(crate) mod urlsearchparams;
454pub(crate) mod userscripts;
455pub(crate) mod validation;
456pub(crate) mod validitystate;
457pub(crate) mod values;
458pub(crate) mod videotrack;
459pub(crate) mod videotracklist;
460pub(crate) mod virtualmethods;
461pub(crate) mod visibilitystateentry;
462pub(crate) mod vttcue;
463pub(crate) mod vttregion;
464pub(crate) mod webgl;
465pub(crate) use self::webgl::extensions::ext::*;
466pub(crate) use self::webgl::*;
467pub(crate) mod websocket;
468#[cfg(feature = "webxr")]
469mod webxr;
470#[cfg(feature = "webxr")]
471pub(crate) use self::webxr::*;
472#[cfg(feature = "webgpu")]
473pub(crate) mod webgpu;
474#[cfg(feature = "webgpu")]
475pub(crate) use self::webgpu::*;
476#[cfg(not(feature = "webgpu"))]
477pub(crate) mod gpucanvascontext;
478pub(crate) mod webrtc;
479pub(crate) use self::webrtc::*;
480pub(crate) mod transformstream;
481pub(crate) mod transformstreamdefaultcontroller;
482pub(crate) mod wheelevent;
483#[allow(dead_code)]
484pub(crate) mod window;
485#[allow(dead_code)]
486pub(crate) mod windowproxy;
487pub(crate) mod workers;
488pub(crate) use self::workers::*;
489pub(crate) mod worklet;
490pub(crate) mod workletglobalscope;
491pub(crate) mod writablestream;
492pub(crate) mod writablestreamdefaultcontroller;
493pub(crate) mod writablestreamdefaultwriter;
494pub(crate) mod xmldocument;
495pub(crate) mod xmlhttprequest;
496pub(crate) mod xmlhttprequesteventtarget;
497pub(crate) mod xmlhttprequestupload;
498pub(crate) mod xmlserializer;
499pub(crate) mod xpathevaluator;
500pub(crate) mod xpathexpression;
501pub(crate) mod xpathresult;