/* 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 https://mozilla.org/MPL/2.0/. */ //! The core DOM types. Defines the basic DOM hierarchy as well as all the HTML elements. use std::borrow::Cow; use std::cell::{Cell, LazyCell, UnsafeCell}; use std::default::Default; use std::f64::consts::PI; use std::ops::Range; use std::slice::from_ref; use std::{cmp, fmt, iter}; use app_units::Au; use base::id::{BrowsingContextId, PipelineId}; use bitflags::bitflags; use devtools_traits::NodeInfo; use dom_struct::dom_struct; use embedder_traits::UntrustedNodeAddress; use euclid::default::{Rect, Size2D, Vector2D}; use html5ever::serialize::HtmlSerializer; use html5ever::{Namespace, Prefix, QualName, ns, serialize as html_serialize}; use js::jsapi::JSObject; use js::rust::HandleObject; use libc::{self, c_void, uintptr_t}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use net_traits::image_cache::Image; use pixels::ImageMetadata; use script_bindings::codegen::InheritTypes::DocumentFragmentTypeId; use script_layout_interface::{ GenericLayoutData, HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType, QueryMsg, SVGSVGData, StyleData, TrustedNodeAddress, }; use script_traits::DocumentActivity; use selectors::matching::{ MatchingContext, MatchingForInvalidation, MatchingMode, NeedsSelectorFlags, matches_selector_list, }; use selectors::parser::SelectorList; use servo_arc::Arc; use servo_config::pref; use servo_url::ServoUrl; use smallvec::SmallVec; use style::context::QuirksMode; use style::dom::OpaqueNode; use style::properties::ComputedValues; use style::selector_parser::{SelectorImpl, SelectorParser}; use style::stylesheets::{Stylesheet, UrlExtraData}; use uuid::Uuid; use xml5ever::serialize as xml_serialize; use crate::conversions::Convert; use crate::document_loader::DocumentLoader; use crate::dom::attr::Attr; use crate::dom::bindings::cell::{DomRefCell, Ref, RefMut}; use crate::dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use crate::dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::CSSStyleDeclarationMethods; use crate::dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use crate::dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use crate::dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; use crate::dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods; use crate::dom::bindings::codegen::Bindings::NodeBinding::{ GetRootNodeOptions, NodeConstants, NodeMethods, }; use crate::dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use crate::dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::ShadowRoot_Binding::ShadowRootMethods; use crate::dom::bindings::codegen::Bindings::ShadowRootBinding::{ ShadowRootMode, SlotAssignmentMode, }; use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use crate::dom::bindings::codegen::UnionTypes::NodeOrString; use crate::dom::bindings::conversions::{self, DerivedFrom}; use crate::dom::bindings::error::{Error, ErrorResult, Fallible}; use crate::dom::bindings::inheritance::{ Castable, CharacterDataTypeId, ElementTypeId, EventTargetTypeId, HTMLElementTypeId, NodeTypeId, SVGElementTypeId, SVGGraphicsElementTypeId, TextTypeId, }; use crate::dom::bindings::refcounted::Trusted; use crate::dom::bindings::reflector::{DomObject, DomObjectWrap, reflect_dom_object_with_proto}; use crate::dom::bindings::root::{Dom, DomRoot, DomSlice, LayoutDom, MutNullableDom, ToLayout}; use crate::dom::bindings::str::{DOMString, USVString}; use crate::dom::bindings::xmlname::namespace_from_domstring; use crate::dom::characterdata::{CharacterData, LayoutCharacterDataHelpers}; use crate::dom::cssstylesheet::CSSStyleSheet; use crate::dom::customelementregistry::{CallbackReaction, try_upgrade_element}; use crate::dom::document::{Document, DocumentSource, HasBrowsingContext, IsHTMLDocument}; use crate::dom::documentfragment::DocumentFragment; use crate::dom::documenttype::DocumentType; use crate::dom::element::{CustomElementCreationMode, Element, ElementCreator, SelectorWrapper}; use crate::dom::event::{Event, EventBubbles, EventCancelable}; use crate::dom::eventtarget::EventTarget; use crate::dom::globalscope::GlobalScope; use crate::dom::htmlbodyelement::HTMLBodyElement; use crate::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutHTMLCanvasElementHelpers}; use crate::dom::htmlcollection::HTMLCollection; use crate::dom::htmlelement::HTMLElement; use crate::dom::htmliframeelement::{HTMLIFrameElement, HTMLIFrameElementLayoutMethods}; use crate::dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers}; use crate::dom::htmlinputelement::{HTMLInputElement, InputType, LayoutHTMLInputElementHelpers}; use crate::dom::htmllinkelement::HTMLLinkElement; use crate::dom::htmlslotelement::{HTMLSlotElement, Slottable}; use crate::dom::htmlstyleelement::HTMLStyleElement; use crate::dom::htmltextareaelement::{HTMLTextAreaElement, LayoutHTMLTextAreaElementHelpers}; use crate::dom::htmlvideoelement::{HTMLVideoElement, LayoutHTMLVideoElementHelpers}; use crate::dom::mutationobserver::{Mutation, MutationObserver, RegisteredObserver}; use crate::dom::nodelist::NodeList; use crate::dom::pointerevent::{PointerEvent, PointerId}; use crate::dom::processinginstruction::ProcessingInstruction; use crate::dom::range::WeakRangeVec; use crate::dom::raredata::NodeRareData; use crate::dom::servoparser::{ServoParser, serialize_html_fragment}; use crate::dom::shadowroot::{IsUserAgentWidget, LayoutShadowRootHelpers, ShadowRoot}; use crate::dom::stylesheetlist::StyleSheetListOwner; use crate::dom::svgsvgelement::{LayoutSVGSVGElementHelpers, SVGSVGElement}; use crate::dom::text::Text; use crate::dom::virtualmethods::{VirtualMethods, vtable_for}; use crate::dom::window::Window; use crate::script_runtime::CanGc; use crate::script_thread::ScriptThread; // // The basic Node structure // /// An HTML node. #[dom_struct] pub struct Node { /// The JavaScript reflector for this node. eventtarget: EventTarget, /// The parent of this node. parent_node: MutNullableDom, /// The first child of this node. first_child: MutNullableDom, /// The last child of this node. last_child: MutNullableDom, /// The next sibling of this node. next_sibling: MutNullableDom, /// The previous sibling of this node. prev_sibling: MutNullableDom, /// The document that this node belongs to. owner_doc: MutNullableDom, /// Rare node data. rare_data: DomRefCell>>, /// The live count of children of this node. children_count: Cell, /// A bitfield of flags for node items. flags: Cell, /// The maximum version of any inclusive descendant of this node. inclusive_descendants_version: Cell, /// Style data for this node. This is accessed and mutated by style /// passes and is used to lay out this node and populate layout data. #[no_trace] style_data: DomRefCell>>, /// Layout data for this node. This is populated during layout and can /// be used for incremental relayout and script queries. #[no_trace] layout_data: DomRefCell>>, } impl fmt::Debug for Node { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if matches!(self.type_id(), NodeTypeId::Element(_)) { let el = self.downcast::().unwrap(); el.fmt(f) } else { write!(f, "[Node({:?})]", self.type_id()) } } } /// Flags for node items #[derive(Clone, Copy, JSTraceable, MallocSizeOf)] pub(crate) struct NodeFlags(u16); bitflags! { impl NodeFlags: u16 { /// Specifies whether this node is in a document. /// /// const IS_IN_A_DOCUMENT_TREE = 1 << 0; /// Specifies whether this node needs style recalc on next reflow. const HAS_DIRTY_DESCENDANTS = 1 << 1; /// Specifies whether or not there is an authentic click in progress on /// this element. const CLICK_IN_PROGRESS = 1 << 2; /// Specifies whether this node is focusable and whether it is supposed /// to be reachable with using sequential focus navigation."] const SEQUENTIALLY_FOCUSABLE = 1 << 3; // There are two free bits here. /// Specifies whether the parser has set an associated form owner for /// this element. Only applicable for form-associatable elements. const PARSER_ASSOCIATED_FORM_OWNER = 1 << 6; /// Whether this element has a snapshot stored due to a style or /// attribute change. /// /// See the `style::restyle_hints` module. const HAS_SNAPSHOT = 1 << 7; /// Whether this element has already handled the stored snapshot. const HANDLED_SNAPSHOT = 1 << 8; /// Whether this node participates in a shadow tree. const IS_IN_SHADOW_TREE = 1 << 9; /// Specifies whether this node's shadow-including root is a document. /// /// const IS_CONNECTED = 1 << 10; /// Whether this node has a weird parser insertion mode. i.e whether setting innerHTML /// needs extra work or not const HAS_WEIRD_PARSER_INSERTION_MODE = 1 << 11; /// Whether this node serves as the text container for editable content of /// or