diff options
Diffstat (limited to 'components/script')
133 files changed, 886 insertions, 481 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 152cb48fab2..04667508c99 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -42,8 +42,9 @@ git = "https://github.com/servo/rust-cssparser" [dependencies.geom] git = "https://github.com/servo/rust-geom" -[dependencies.hubbub] -git = "https://github.com/servo/rust-hubbub" +[dependencies.html5ever] +git = "https://github.com/servo/html5ever" +branch = "servo" [dependencies.encoding] git = "https://github.com/lifthrasiir/rust-encoding" diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index f4dd6e85d7b..896c65d1c13 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -69,9 +69,7 @@ impl Str for AttrValue { } } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Attr { reflector_: Reflector, local_name: Atom, diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index bca334de6ea..a6e4fcd6ebc 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -4530,7 +4530,6 @@ class CGBindingRoot(CGThing): 'dom::bindings::utils::{FindEnumStringIndex, GetArrayIndexFromId}', 'dom::bindings::utils::{GetPropertyOnPrototype, GetProtoOrIfaceArray}', 'dom::bindings::utils::{HasPropertyOnPrototype, IntVal}', - 'dom::bindings::utils::{jsid_to_str}', 'dom::bindings::utils::{Reflectable}', 'dom::bindings::utils::{squirrel_away_unique}', 'dom::bindings::utils::{ThrowingConstructor, unwrap, unwrap_jsmanaged}', @@ -4544,6 +4543,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible}', 'dom::bindings::conversions::IDLInterface', 'dom::bindings::conversions::{Default, Empty}', + 'dom::bindings::conversions::jsid_to_str', 'dom::bindings::codegen::{PrototypeList, RegisterBindings, UnionTypes}', 'dom::bindings::codegen::Bindings::*', 'dom::bindings::error::{FailureUnknown, Fallible, Error, ErrorResult}', diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index 2afd91fd08b..30bc810e44f 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -7,11 +7,12 @@ use dom::bindings::js::{JS, JSRef, Root}; use dom::bindings::str::ByteString; use dom::bindings::utils::{Reflectable, Reflector}; -use dom::bindings::utils::jsstring_to_str; use dom::bindings::utils::unwrap_jsmanaged; use servo_util::str::DOMString; -use js::jsapi::{JSBool, JSContext, JSObject}; +use js::glue::{RUST_JSID_TO_STRING, RUST_JSID_IS_STRING}; +use js::glue::RUST_JS_NumberValue; +use js::jsapi::{JSBool, JSContext, JSObject, JSString, jsid}; use js::jsapi::{JS_ValueToUint64, JS_ValueToInt64}; use js::jsapi::{JS_ValueToECMAUint32, JS_ValueToECMAInt32}; use js::jsapi::{JS_ValueToUint16, JS_ValueToNumber, JS_ValueToBoolean}; @@ -21,7 +22,7 @@ use js::jsapi::{JS_WrapValue}; use js::jsval::JSVal; use js::jsval::{UndefinedValue, NullValue, BooleanValue, Int32Value, UInt32Value}; use js::jsval::{StringValue, ObjectValue, ObjectOrNullValue}; -use js::glue::RUST_JS_NumberValue; + use libc; use std::default; use std::slice; @@ -252,6 +253,27 @@ impl default::Default for StringificationBehavior { } } +/// Convert the given `JSString` to a `DOMString`. Fails if the string does not +/// contain valid UTF-16. +pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString { + unsafe { + let mut length = 0; + let chars = JS_GetStringCharsAndLength(cx, s, &mut length); + slice::raw::buf_as_slice(chars, length as uint, |char_vec| { + String::from_utf16(char_vec).unwrap() + }) + } +} + +/// Convert the given `jsid` to a `DOMString`. Fails if the `jsid` is not a +/// string, or if the string does not contain valid UTF-16. +pub fn jsid_to_str(cx: *mut JSContext, id: jsid) -> DOMString { + unsafe { + assert!(RUST_JSID_IS_STRING(id) != 0); + jsstring_to_str(cx, RUST_JSID_TO_STRING(id)) + } +} + impl FromJSValConvertible<StringificationBehavior> for DOMString { fn from_jsval(cx: *mut JSContext, value: JSVal, nullBehavior: StringificationBehavior) -> Result<DOMString, ()> { if nullBehavior == Empty && value.is_null() { diff --git a/components/script/dom/bindings/error.rs b/components/script/dom/bindings/error.rs index e2e06d8205a..091a777c430 100644 --- a/components/script/dom/bindings/error.rs +++ b/components/script/dom/bindings/error.rs @@ -34,7 +34,8 @@ pub enum Error { Security, Network, Abort, - Timeout + Timeout, + DataClone } /// The return type for IDL operations that can throw DOM exceptions. diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 18fb7c6e8d8..a7fffe4a11e 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -42,7 +42,6 @@ use std::collections::hashmap::HashMap; use collections::hash::Hash; use style::PropertyDeclarationBlock; use std::comm::{Receiver, Sender}; -use hubbub::hubbub::QuirksMode; use string_cache::{Atom, Namespace}; use js::rust::Cx; use http::headers::response::HeaderCollection as ResponseHeaderCollection; @@ -55,7 +54,9 @@ use servo_msg::constellation_msg::ConstellationChan; use servo_util::smallvec::{SmallVec1, SmallVec}; use servo_util::str::LengthOrPercentageOrAuto; use layout_interface::{LayoutRPC, LayoutChan}; +use dom::node::{Node, TrustedNodeAddress}; use dom::bindings::utils::WindowProxyHandler; +use html5ever::tree_builder::QuirksMode; impl<T: Reflectable> JSTraceable for JS<T> { fn trace(&self, trc: *mut JSTracer) { @@ -207,6 +208,7 @@ untraceable!(ConstellationChan) untraceable!(LayoutChan) untraceable!(WindowProxyHandler) untraceable!(UntrustedNodeAddress) +untraceable!(LengthOrPercentageOrAuto) impl<'a> JSTraceable for &'a str { #[inline] @@ -236,5 +238,12 @@ impl JSTraceable for Box<LayoutRPC+'static> { } } -untraceable!(LengthOrPercentageOrAuto) - +impl JSTraceable for TrustedNodeAddress { + fn trace(&self, s: *mut JSTracer) { + let TrustedNodeAddress(addr) = *self; + let node = addr as *const Node; + unsafe { + JS::from_raw(node).trace(s) + } + } +} diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 082172a1f60..4d94410216f 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -12,7 +12,6 @@ use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Temporary, Root}; use dom::browsercontext; use dom::window; -use servo_util::str::DOMString; use libc; use libc::c_uint; @@ -20,11 +19,9 @@ use std::cell::Cell; use std::mem; use std::cmp::PartialEq; use std::ptr; -use std::slice; use js::glue::{js_IsObjectProxyClass, js_IsFunctionProxyClass, IsProxyHandlerFamily}; use js::glue::{UnwrapObject, GetProxyHandlerExtra}; -use js::glue::{IsWrapper, RUST_JSID_TO_STRING, RUST_JSID_IS_INT}; -use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_INT}; +use js::glue::{IsWrapper, RUST_JSID_IS_INT, RUST_JSID_TO_INT}; use js::jsapi::{JS_AlreadyHasOwnProperty, JS_NewFunction}; use js::jsapi::{JS_DefineProperties, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_GetClass, JS_LinkConstructorAndPrototype, JS_GetStringCharsAndLength}; @@ -37,7 +34,6 @@ use js::jsapi::{JS_ValueToString, JS_GetReservedSlot, JS_SetReservedSlot}; use js::jsapi::{JSContext, JSObject, JSBool, jsid, JSClass}; use js::jsapi::{JSFunctionSpec, JSPropertySpec}; use js::jsapi::{JS_NewGlobalObject, JS_InitStandardClasses}; -use js::jsapi::{JSString}; use js::jsapi::JS_DeletePropertyById2; use js::jsfriendapi::JS_ObjectToOuterObject; use js::jsfriendapi::bindgen::JS_NewObjectWithUniqueType; @@ -161,27 +157,6 @@ pub unsafe fn squirrel_away_unique<T>(x: Box<T>) -> *const T { mem::transmute(x) } -/// Convert the given `JSString` to a `DOMString`. Fails if the string does not -/// contain valid UTF-16. -pub fn jsstring_to_str(cx: *mut JSContext, s: *mut JSString) -> DOMString { - unsafe { - let mut length = 0; - let chars = JS_GetStringCharsAndLength(cx, s, &mut length); - slice::raw::buf_as_slice(chars, length as uint, |char_vec| { - String::from_utf16(char_vec).unwrap() - }) - } -} - -/// Convert the given `jsid` to a `DOMString`. Fails if the `jsid` is not a -/// string, or if the string does not contain valid UTF-16. -pub fn jsid_to_str(cx: *mut JSContext, id: jsid) -> DOMString { - unsafe { - assert!(RUST_JSID_IS_STRING(id) != 0); - jsstring_to_str(cx, RUST_JSID_TO_STRING(id)) - } -} - /// The index of the slot wherein a pointer to the reflected DOM object is /// stored for non-proxy bindings. // We use slot 0 for holding the raw object. This is safe for both diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index 5849b75ff10..f59c690360e 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -15,9 +15,7 @@ pub enum BlobType { FileTypeId } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Blob { reflector_: Reflector, type_: BlobType diff --git a/components/script/dom/browsercontext.rs b/components/script/dom/browsercontext.rs index 9f6041710e3..1a64068bd9d 100644 --- a/components/script/dom/browsercontext.rs +++ b/components/script/dom/browsercontext.rs @@ -65,9 +65,7 @@ impl BrowserContext { } } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct SessionHistoryEntry { document: JS<Document>, children: Vec<BrowserContext> diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index c9a19c3301c..0c665645af6 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -15,9 +15,7 @@ use geom::size::Size2D; use canvas::canvas_render_task::{CanvasMsg, CanvasRenderTask, ClearRect, Close, FillRect, Recreate, StrokeRect}; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct CanvasRenderingContext2D { reflector_: Reflector, global: GlobalField, diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 3a5ebcf6ab6..a5eec3d8dc1 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -15,9 +15,7 @@ use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::node::{CommentNodeTypeId, Node, NodeTypeId, TextNodeTypeId, ProcessingInstructionNodeTypeId, NodeHelpers}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct CharacterData { node: Node, data: DOMRefCell<DOMString>, diff --git a/components/script/dom/comment.rs b/components/script/dom/comment.rs index 8da33dab01f..e55483f39cd 100644 --- a/components/script/dom/comment.rs +++ b/components/script/dom/comment.rs @@ -16,9 +16,7 @@ use dom::node::{CommentNodeTypeId, Node}; use servo_util::str::DOMString; /// An HTML comment. -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Comment { characterdata: CharacterData, } diff --git a/components/script/dom/console.rs b/components/script/dom/console.rs index a62d2ad4047..b2a10f0c071 100644 --- a/components/script/dom/console.rs +++ b/components/script/dom/console.rs @@ -9,9 +9,7 @@ use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Console { reflector_: Reflector } diff --git a/components/script/dom/customevent.rs b/components/script/dom/customevent.rs index b6549f28a16..3cad0e2ddba 100644 --- a/components/script/dom/customevent.rs +++ b/components/script/dom/customevent.rs @@ -17,9 +17,7 @@ use servo_util::str::DOMString; use std::cell::Cell; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct CustomEvent { event: Event, detail: Cell<JSVal>, diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 1f402b73689..1e81f8d9e9f 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -7,6 +7,7 @@ use dom::bindings::codegen::Bindings::DedicatedWorkerGlobalScopeBinding::Dedicat use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::InheritTypes::DedicatedWorkerGlobalScopeDerived; use dom::bindings::codegen::InheritTypes::{EventTargetCast, WorkerGlobalScopeCast}; +use dom::bindings::error::{ErrorResult, DataClone}; use dom::bindings::global; use dom::bindings::js::{JSRef, Temporary, RootCollection}; use dom::bindings::utils::{Reflectable, Reflector}; @@ -25,7 +26,7 @@ use script_task::StackRootTLS; use servo_net::resource_task::{ResourceTask, load_whole_resource}; use js::glue::JS_STRUCTURED_CLONE_VERSION; -use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_WriteStructuredClone}; +use js::jsapi::{JSContext, JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException}; use js::jsval::{JSVal, UndefinedValue}; use js::rust::Cx; @@ -35,9 +36,7 @@ use std::task::TaskBuilder; use native::task::NativeTaskBuilder; use url::Url; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DedicatedWorkerGlobalScope { workerglobalscope: WorkerGlobalScope, receiver: Receiver<ScriptMsg>, @@ -154,16 +153,21 @@ impl DedicatedWorkerGlobalScope { } impl<'a> DedicatedWorkerGlobalScopeMethods for JSRef<'a, DedicatedWorkerGlobalScope> { - fn PostMessage(self, cx: *mut JSContext, message: JSVal) { + fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult { let mut data = ptr::null_mut(); let mut nbytes = 0; - unsafe { - assert!(JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes, - ptr::null(), ptr::null_mut()) != 0); + let result = unsafe { + JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes, + ptr::null(), ptr::null_mut()) + }; + if result == 0 { + unsafe { JS_ClearPendingException(cx); } + return Err(DataClone); } let ScriptChan(ref sender) = self.parent_sender; sender.send(WorkerPostMessage(self.worker, data, nbytes)); + Ok(()) } fn GetOnmessage(self) -> Option<EventHandlerNonNull> { diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 2a4f70fdf95..8d767be9016 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -52,12 +52,12 @@ use dom::range::Range; use dom::treewalker::TreeWalker; use dom::uievent::UIEvent; use dom::window::{Window, WindowHelpers}; -use html::hubbub_html_parser::build_element_from_tag; -use hubbub::hubbub::{QuirksMode, NoQuirks, LimitedQuirks, FullQuirks}; +use parse::html::build_element_from_tag; use servo_util::namespace; use servo_util::str::{DOMString, split_html_space_chars}; -use string_cache::Atom; +use html5ever::tree_builder::{QuirksMode, NoQuirks, LimitedQuirks, Quirks}; +use string_cache::{Atom, QualName}; use url::Url; use std::collections::hashmap::HashMap; @@ -73,9 +73,7 @@ pub enum IsHTMLDocument { NonHTMLDocument, } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Document { node: Node, window: JS<Window>, @@ -428,7 +426,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { fn CompatMode(self) -> DOMString { match self.quirks_mode.get() { LimitedQuirks | NoQuirks => "CSS1Compat".to_string(), - FullQuirks => "BackCompat".to_string() + Quirks => "BackCompat".to_string() } } @@ -494,7 +492,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { return Err(InvalidCharacter); } let local_name = local_name.as_slice().to_ascii_lower(); - Ok(build_element_from_tag(local_name, ns!(HTML), None, self)) + let name = QualName::new(ns!(HTML), Atom::from_slice(local_name.as_slice())); + Ok(build_element_from_tag(name, None, self)) } // http://dom.spec.whatwg.org/#dom-document-createelementns @@ -514,9 +513,9 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { QName => {} } - let (prefix_from_qname, - local_name_from_qname) = get_attribute_parts(qualified_name.as_slice()); - match (&ns, prefix_from_qname.clone(), local_name_from_qname.as_slice()) { + let (prefix_from_qname, local_name_from_qname) + = get_attribute_parts(qualified_name.as_slice()); + match (&ns, prefix_from_qname, local_name_from_qname) { // throw if prefix is not null and namespace is null (&ns!(""), Some(_), _) => { debug!("Namespace can't be null with a non-null prefix"); @@ -538,8 +537,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { } if ns == ns!(HTML) { - Ok(build_element_from_tag(local_name_from_qname.to_string(), ns, - prefix_from_qname.map(|s| s.to_string()), self)) + let name = QualName::new(ns!(HTML), Atom::from_slice(local_name_from_qname)); + Ok(build_element_from_tag(name, prefix_from_qname.map(|s| s.to_string()), self)) } else { Ok(Element::new(local_name_from_qname.to_string(), ns, prefix_from_qname.map(|s| s.to_string()), self)) diff --git a/components/script/dom/documentfragment.rs b/components/script/dom/documentfragment.rs index 8b3b8e6bba6..65fa818e033 100644 --- a/components/script/dom/documentfragment.rs +++ b/components/script/dom/documentfragment.rs @@ -18,9 +18,7 @@ use dom::node::{DocumentFragmentNodeTypeId, Node, NodeHelpers, window_from_node} use dom::nodelist::NodeList; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DocumentFragment { node: Node, } diff --git a/components/script/dom/documenttype.rs b/components/script/dom/documenttype.rs index 683b1c56ae0..f293208d1f9 100644 --- a/components/script/dom/documenttype.rs +++ b/components/script/dom/documenttype.rs @@ -13,9 +13,7 @@ use dom::node::{Node, DoctypeNodeTypeId, NodeHelpers}; use servo_util::str::DOMString; /// The `DOCTYPE` tag. -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DocumentType { node: Node, name: DOMString, diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs index 73dc4c149fe..f3fc0027620 100644 --- a/components/script/dom/domexception.rs +++ b/components/script/dom/domexception.rs @@ -55,14 +55,13 @@ impl DOMErrorName { error::Network => NetworkError, error::Abort => AbortError, error::Timeout => TimeoutError, + error::DataClone => DataCloneError, error::FailureUnknown => fail!(), } } } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DOMException { code: DOMErrorName, reflector_: Reflector diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index 7e23d86f2bc..e2761ea5456 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -22,9 +22,7 @@ use dom::node::Node; use dom::text::Text; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DOMImplementation { document: JS<Document>, reflector_: Reflector, diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs index 7b6bbae3e7c..0ce5487159a 100644 --- a/components/script/dom/domparser.rs +++ b/components/script/dom/domparser.rs @@ -14,9 +14,7 @@ use dom::document::{Document, HTMLDocument, NonHTMLDocument}; use dom::window::Window; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DOMParser { window: JS<Window>, //XXXjdm Document instead? reflector_: Reflector diff --git a/components/script/dom/domrect.rs b/components/script/dom/domrect.rs index 39e9c4cbb0e..258ca71ca1e 100644 --- a/components/script/dom/domrect.rs +++ b/components/script/dom/domrect.rs @@ -10,9 +10,7 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; use servo_util::geometry::Au; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DOMRect { reflector_: Reflector, top: f32, diff --git a/components/script/dom/domrectlist.rs b/components/script/dom/domrectlist.rs index 88ec6d5e148..5b9565fc25e 100644 --- a/components/script/dom/domrectlist.rs +++ b/components/script/dom/domrectlist.rs @@ -10,9 +10,7 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::domrect::DOMRect; use dom::window::Window; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DOMRectList { reflector_: Reflector, rects: Vec<JS<DOMRect>>, diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index a23e5e49bac..a7326fa8e2d 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -15,9 +15,7 @@ use dom::node::window_from_node; use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS}; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct DOMTokenList { reflector_: Reflector, element: JS<Element>, diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d9f995720a8..0ad67d7ee67 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -42,12 +42,10 @@ use servo_util::str::{DOMString, LengthOrPercentageOrAuto}; use std::ascii::StrAsciiExt; use std::default::Default; use std::mem; -use string_cache::{Atom, Namespace}; +use string_cache::{Atom, Namespace, QualName}; use url::UrlParser; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Element { node: Node, local_name: Atom, @@ -399,9 +397,8 @@ pub trait AttributeHandlers { fn get_attributes(self, local_name: &Atom) -> Vec<Temporary<Attr>>; fn set_attribute_from_parser(self, - local_name: Atom, + name: QualName, value: DOMString, - namespace: Namespace, prefix: Option<DOMString>); fn set_attribute(self, name: &Atom, value: AttrValue); fn do_set_attribute(self, local_name: Atom, value: AttrValue, @@ -447,19 +444,24 @@ impl<'a> AttributeHandlers for JSRef<'a, Element> { } fn set_attribute_from_parser(self, - local_name: Atom, + qname: QualName, value: DOMString, - namespace: Namespace, prefix: Option<DOMString>) { + // Don't set if the attribute already exists, so we can handle add_attrs_if_missing + if self.attrs.borrow().iter().map(|attr| attr.root()) + .any(|a| *a.local_name() == qname.local && *a.namespace() == qname.ns) { + return; + } + let name = match prefix { - None => local_name.clone(), + None => qname.local.clone(), Some(ref prefix) => { - let name = format!("{:s}:{:s}", *prefix, local_name.as_slice()); + let name = format!("{:s}:{:s}", *prefix, qname.local.as_slice()); Atom::from_slice(name.as_slice()) }, }; - let value = self.parse_attribute(&namespace, &local_name, value); - self.do_set_attribute(local_name, value, name, namespace, prefix, |_| false) + let value = self.parse_attribute(&qname.ns, &qname.local, value); + self.do_set_attribute(qname.local, value, name, qname.ns, prefix, |_| false) } fn set_attribute(self, name: &Atom, value: AttrValue) { @@ -1084,11 +1086,13 @@ impl<'a> VirtualMethods for JSRef<'a, Element> { impl<'a> style::TElement<'a> for JSRef<'a, Element> { fn get_attr(self, namespace: &Namespace, attr: &Atom) -> Option<&'a str> { self.get_attribute(namespace.clone(), attr).root().map(|attr| { + // This transmute is used to cheat the lifetime restriction. unsafe { mem::transmute(attr.value().as_slice()) } }) } fn get_attrs(self, attr: &Atom) -> Vec<&'a str> { self.get_attributes(attr).iter().map(|attr| attr.root()).map(|attr| { + // This transmute is used to cheat the lifetime restriction. unsafe { mem::transmute(attr.value().as_slice()) } }).collect() } diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 05b3d6af3a5..e61bd15a3b0 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -47,9 +47,7 @@ pub enum EventCancelable { NotCancelable } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Event { type_id: EventTypeId, reflector_: Reflector, diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index e51272cff6b..3a764c66a9d 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -65,9 +65,7 @@ pub struct EventListenerEntry { listener: EventListenerType } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct EventTarget { type_id: EventTargetTypeId, reflector_: Reflector, diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs index cb42537f63f..d6a056cb04b 100644 --- a/components/script/dom/file.rs +++ b/components/script/dom/file.rs @@ -10,9 +10,7 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::blob::{Blob, BlobType, FileTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct File { blob: Blob, name: DOMString, diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs index 140ff809125..cd6dbf65143 100644 --- a/components/script/dom/formdata.rs +++ b/components/script/dom/formdata.rs @@ -25,9 +25,7 @@ pub enum FormDatum { FileData(JS<File>) } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct FormData { data: RefCell<HashMap<DOMString, Vec<FormDatum>>>, reflector_: Reflector, diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index aad63f98ba8..72c5d2fe7ae 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -21,9 +21,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLAnchorElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlappletelement.rs b/components/script/dom/htmlappletelement.rs index eeb7eb35188..4360d288b2c 100644 --- a/components/script/dom/htmlappletelement.rs +++ b/components/script/dom/htmlappletelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLAppletElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlaudioelement.rs b/components/script/dom/htmlaudioelement.rs index 9eed3b6c1db..216b255816a 100644 --- a/components/script/dom/htmlaudioelement.rs +++ b/components/script/dom/htmlaudioelement.rs @@ -13,9 +13,7 @@ use dom::htmlmediaelement::HTMLMediaElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLAudioElement { htmlmediaelement: HTMLMediaElement } diff --git a/components/script/dom/htmlbaseelement.rs b/components/script/dom/htmlbaseelement.rs index 7bf12bb0822..a91b6bd9791 100644 --- a/components/script/dom/htmlbaseelement.rs +++ b/components/script/dom/htmlbaseelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLBaseElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs index 7c0c0c17711..948a7192aa0 100644 --- a/components/script/dom/htmlbodyelement.rs +++ b/components/script/dom/htmlbodyelement.rs @@ -20,9 +20,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::DOMString; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLBodyElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlbrelement.rs b/components/script/dom/htmlbrelement.rs index 74811afe074..e2716c39357 100644 --- a/components/script/dom/htmlbrelement.rs +++ b/components/script/dom/htmlbrelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLBRElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs index ec2377297f3..e5b7a0da216 100644 --- a/components/script/dom/htmlbuttonelement.rs +++ b/components/script/dom/htmlbuttonelement.rs @@ -20,9 +20,7 @@ use std::ascii::OwnedStrAsciiExt; use servo_util::str::DOMString; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLButtonElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 69a96a086fc..af239a55ebe 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -28,9 +28,7 @@ use std::default::Default; static DefaultWidth: u32 = 300; static DefaultHeight: u32 = 150; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLCanvasElement { htmlelement: HTMLElement, context: MutNullableJS<CanvasRenderingContext2D>, diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs index abd8b6857aa..6b62904c830 100644 --- a/components/script/dom/htmlcollection.rs +++ b/components/script/dom/htmlcollection.rs @@ -29,9 +29,7 @@ pub enum CollectionTypeId { Live(JS<Node>, Box<CollectionFilter+'static>) } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLCollection { collection: CollectionTypeId, reflector_: Reflector, diff --git a/components/script/dom/htmldataelement.rs b/components/script/dom/htmldataelement.rs index 58e2ad90f73..33dfbfd7bd7 100644 --- a/components/script/dom/htmldataelement.rs +++ b/components/script/dom/htmldataelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLDataElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmldatalistelement.rs b/components/script/dom/htmldatalistelement.rs index 3363997142b..210c22b33a3 100644 --- a/components/script/dom/htmldatalistelement.rs +++ b/components/script/dom/htmldatalistelement.rs @@ -16,9 +16,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId, window_from_node}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLDataListElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmldirectoryelement.rs b/components/script/dom/htmldirectoryelement.rs index f1cd840e298..21c675458b9 100644 --- a/components/script/dom/htmldirectoryelement.rs +++ b/components/script/dom/htmldirectoryelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLDirectoryElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmldivelement.rs b/components/script/dom/htmldivelement.rs index d35ad9dc4be..899c35f571a 100644 --- a/components/script/dom/htmldivelement.rs +++ b/components/script/dom/htmldivelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLDivElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmldlistelement.rs b/components/script/dom/htmldlistelement.rs index 643f7e81263..38828fb3957 100644 --- a/components/script/dom/htmldlistelement.rs +++ b/components/script/dom/htmldlistelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLDListElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 00ea736a07f..36488d9a2f9 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -20,9 +20,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::DOMString; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLElement { element: Element } diff --git a/components/script/dom/htmlembedelement.rs b/components/script/dom/htmlembedelement.rs index e8de6bbd08a..f99d0f821df 100644 --- a/components/script/dom/htmlembedelement.rs +++ b/components/script/dom/htmlembedelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLEmbedElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlfieldsetelement.rs b/components/script/dom/htmlfieldsetelement.rs index 4ec69852e95..d4be6a3f00e 100644 --- a/components/script/dom/htmlfieldsetelement.rs +++ b/components/script/dom/htmlfieldsetelement.rs @@ -21,9 +21,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::{DOMString, StaticStringVec}; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLFieldSetElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlfontelement.rs b/components/script/dom/htmlfontelement.rs index 5f11a672cc4..3edf195f2dc 100644 --- a/components/script/dom/htmlfontelement.rs +++ b/components/script/dom/htmlfontelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLFontElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index ed18eb109f2..49c3486a186 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -30,9 +30,7 @@ use url::UrlParser; use url::form_urlencoded::serialize; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLFormElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlframeelement.rs b/components/script/dom/htmlframeelement.rs index 76a8b190cb1..23448387033 100644 --- a/components/script/dom/htmlframeelement.rs +++ b/components/script/dom/htmlframeelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLFrameElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlframesetelement.rs b/components/script/dom/htmlframesetelement.rs index 168ab8f73ec..9afa3ca02ef 100644 --- a/components/script/dom/htmlframesetelement.rs +++ b/components/script/dom/htmlframesetelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLFrameSetElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlheadelement.rs b/components/script/dom/htmlheadelement.rs index 51cbf9f9b88..b4bff814681 100644 --- a/components/script/dom/htmlheadelement.rs +++ b/components/script/dom/htmlheadelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLHeadElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlheadingelement.rs b/components/script/dom/htmlheadingelement.rs index 1f91a89abee..c52c7cf7c0f 100644 --- a/components/script/dom/htmlheadingelement.rs +++ b/components/script/dom/htmlheadingelement.rs @@ -23,9 +23,7 @@ pub enum HeadingLevel { Heading6, } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLHeadingElement { htmlelement: HTMLElement, level: HeadingLevel, diff --git a/components/script/dom/htmlhrelement.rs b/components/script/dom/htmlhrelement.rs index 95400b2713d..ec71ea141bd 100644 --- a/components/script/dom/htmlhrelement.rs +++ b/components/script/dom/htmlhrelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLHRElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlhtmlelement.rs b/components/script/dom/htmlhtmlelement.rs index f3cd408a31d..dddde174b73 100644 --- a/components/script/dom/htmlhtmlelement.rs +++ b/components/script/dom/htmlhtmlelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLHtmlElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 108fbbe4dc2..230a78df5b2 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -39,9 +39,7 @@ enum SandboxAllowance { AllowPopups = 0x20 } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLIFrameElement { htmlelement: HTMLElement, size: Cell<Option<IFrameSize>>, diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index c706fcfcd7e..0128ebe0a3e 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -24,9 +24,7 @@ use url::{Url, UrlParser}; use std::cell::RefCell; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLImageElement { htmlelement: HTMLElement, image: RefCell<Option<Url>>, diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 776ff10244d..cee45dcfa72 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -2,6 +2,7 @@ * 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::cell::DOMRefCell; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::EventBinding::EventMethods; @@ -27,7 +28,6 @@ use string_cache::Atom; use std::ascii::OwnedStrAsciiExt; use std::cell::{Cell, RefCell}; -use std::mem; static DEFAULT_SUBMIT_VALUE: &'static str = "Submit"; static DEFAULT_RESET_VALUE: &'static str = "Reset"; @@ -44,15 +44,13 @@ enum InputType { InputPassword } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLInputElement { htmlelement: HTMLElement, input_type: Cell<InputType>, checked: Cell<bool>, uncommitted_value: RefCell<Option<String>>, - value: RefCell<Option<String>>, + value: DOMRefCell<Option<String>>, size: Cell<u32>, } @@ -71,7 +69,7 @@ impl HTMLInputElement { input_type: Cell::new(InputText), checked: Cell::new(false), uncommitted_value: RefCell::new(None), - value: RefCell::new(None), + value: DOMRefCell::new(None), size: Cell::new(DEFAULT_INPUT_SIZE), } } @@ -91,21 +89,17 @@ pub trait LayoutHTMLInputElementHelpers { impl LayoutHTMLInputElementHelpers for HTMLInputElement { #[allow(unrooted_must_root)] unsafe fn get_value_for_layout(&self) -> String { - unsafe fn get_raw_value(input: &HTMLInputElement) -> Option<String> { - mem::transmute::<&RefCell<Option<String>>, &Option<String>>(&input.value).clone() - } - match self.input_type.get() { InputCheckbox | InputRadio => "".to_string(), InputFile | InputImage => "".to_string(), - InputButton(ref default) => get_raw_value(self) + InputButton(ref default) => self.value.borrow_for_layout().clone() .or_else(|| default.map(|v| v.to_string())) .unwrap_or_else(|| "".to_string()), InputPassword => { - let raw = get_raw_value(self).unwrap_or_else(|| "".to_string()); + let raw = self.value.borrow_for_layout().clone().unwrap_or_else(|| "".to_string()); String::from_char(raw.len(), '*') } - _ => get_raw_value(self).unwrap_or_else(|| "".to_string()), + _ => self.value.borrow_for_layout().clone().unwrap_or_else(|| "".to_string()), } } diff --git a/components/script/dom/htmllabelelement.rs b/components/script/dom/htmllabelelement.rs index 59fe5479f53..f1932dc3ad3 100644 --- a/components/script/dom/htmllabelelement.rs +++ b/components/script/dom/htmllabelelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLLabelElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmllegendelement.rs b/components/script/dom/htmllegendelement.rs index 2d4725528ab..5e98fa5b986 100644 --- a/components/script/dom/htmllegendelement.rs +++ b/components/script/dom/htmllegendelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLLegendElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmllielement.rs b/components/script/dom/htmllielement.rs index f4d789ec549..16bbd46833f 100644 --- a/components/script/dom/htmllielement.rs +++ b/components/script/dom/htmllielement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLLIElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 13c4bf3b513..5abde3469e0 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -21,9 +21,7 @@ use std::ascii::StrAsciiExt; use url::UrlParser; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLLinkElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlmapelement.rs b/components/script/dom/htmlmapelement.rs index 0cca9e14a84..e11c6bdf5c0 100644 --- a/components/script/dom/htmlmapelement.rs +++ b/components/script/dom/htmlmapelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLMapElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 54ff9308672..3cc03a64d1c 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -12,9 +12,7 @@ use dom::htmlelement::HTMLElement; use dom::node::ElementNodeTypeId; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLMediaElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index 4a38ebfbc3a..fda51c6d277 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLMetaElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlmeterelement.rs b/components/script/dom/htmlmeterelement.rs index 76e2f9400d0..bb88e499444 100644 --- a/components/script/dom/htmlmeterelement.rs +++ b/components/script/dom/htmlmeterelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLMeterElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlmodelement.rs b/components/script/dom/htmlmodelement.rs index 0fa5e2e0cd2..e1cc1af706e 100644 --- a/components/script/dom/htmlmodelement.rs +++ b/components/script/dom/htmlmodelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLModElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs index a7de41d3599..4e4789ea3cc 100644 --- a/components/script/dom/htmlobjectelement.rs +++ b/components/script/dom/htmlobjectelement.rs @@ -25,9 +25,7 @@ use string_cache::Atom; use url::Url; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLObjectElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlolistelement.rs b/components/script/dom/htmlolistelement.rs index 82c67341c31..8b1fdbe01d1 100644 --- a/components/script/dom/htmlolistelement.rs +++ b/components/script/dom/htmlolistelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLOListElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmloptgroupelement.rs b/components/script/dom/htmloptgroupelement.rs index e7fe66c2e0d..fac03df2f77 100644 --- a/components/script/dom/htmloptgroupelement.rs +++ b/components/script/dom/htmloptgroupelement.rs @@ -18,9 +18,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::DOMString; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLOptGroupElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs index 1493e5cecef..648ec90f605 100644 --- a/components/script/dom/htmloptionelement.rs +++ b/components/script/dom/htmloptionelement.rs @@ -22,9 +22,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::{DOMString, split_html_space_chars}; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLOptionElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmloutputelement.rs b/components/script/dom/htmloutputelement.rs index 0b9f0b0d872..4622fe02f98 100644 --- a/components/script/dom/htmloutputelement.rs +++ b/components/script/dom/htmloutputelement.rs @@ -15,9 +15,7 @@ use dom::node::{Node, ElementNodeTypeId, window_from_node}; use dom::validitystate::ValidityState; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLOutputElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlparagraphelement.rs b/components/script/dom/htmlparagraphelement.rs index 66a70b6963f..a6d7b346b3a 100644 --- a/components/script/dom/htmlparagraphelement.rs +++ b/components/script/dom/htmlparagraphelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLParagraphElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlparamelement.rs b/components/script/dom/htmlparamelement.rs index 7845a767512..a7ceff0b1b3 100644 --- a/components/script/dom/htmlparamelement.rs +++ b/components/script/dom/htmlparamelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLParamElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlpreelement.rs b/components/script/dom/htmlpreelement.rs index 89799212226..7a25822a569 100644 --- a/components/script/dom/htmlpreelement.rs +++ b/components/script/dom/htmlpreelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLPreElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlprogresselement.rs b/components/script/dom/htmlprogresselement.rs index 65db0e536af..18bd90869b6 100644 --- a/components/script/dom/htmlprogresselement.rs +++ b/components/script/dom/htmlprogresselement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLProgressElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlquoteelement.rs b/components/script/dom/htmlquoteelement.rs index f028b3d9c5d..5dcdd92250a 100644 --- a/components/script/dom/htmlquoteelement.rs +++ b/components/script/dom/htmlquoteelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLQuoteElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index e4c268d5713..b970596fbdd 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -18,9 +18,7 @@ use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec}; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLScriptElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs index 011254600d3..39d14b11935 100644 --- a/components/script/dom/htmlselectelement.rs +++ b/components/script/dom/htmlselectelement.rs @@ -21,9 +21,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::DOMString; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLSelectElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlsourceelement.rs b/components/script/dom/htmlsourceelement.rs index 8a7578febdf..900b581f358 100644 --- a/components/script/dom/htmlsourceelement.rs +++ b/components/script/dom/htmlsourceelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLSourceElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlspanelement.rs b/components/script/dom/htmlspanelement.rs index fba53a8b795..2a5ff463513 100644 --- a/components/script/dom/htmlspanelement.rs +++ b/components/script/dom/htmlspanelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLSpanElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 46c631fc730..f4d6a315638 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -17,9 +17,7 @@ use layout_interface::{AddStylesheetMsg, LayoutChan}; use servo_util::str::DOMString; use style::Stylesheet; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLStyleElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltablecaptionelement.rs b/components/script/dom/htmltablecaptionelement.rs index e1ecf1914ce..90380f37eb9 100644 --- a/components/script/dom/htmltablecaptionelement.rs +++ b/components/script/dom/htmltablecaptionelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableCaptionElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmltablecellelement.rs b/components/script/dom/htmltablecellelement.rs index 6bd2d735695..18795031400 100644 --- a/components/script/dom/htmltablecellelement.rs +++ b/components/script/dom/htmltablecellelement.rs @@ -18,9 +18,7 @@ use servo_util::str; use std::cell::Cell; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableCellElement { htmlelement: HTMLElement, width: Cell<LengthOrPercentageOrAuto>, diff --git a/components/script/dom/htmltablecolelement.rs b/components/script/dom/htmltablecolelement.rs index 03caf0e22b8..f9761151dc1 100644 --- a/components/script/dom/htmltablecolelement.rs +++ b/components/script/dom/htmltablecolelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableColElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltabledatacellelement.rs b/components/script/dom/htmltabledatacellelement.rs index 11b8b117a2c..535f2e4ffd5 100644 --- a/components/script/dom/htmltabledatacellelement.rs +++ b/components/script/dom/htmltabledatacellelement.rs @@ -13,9 +13,7 @@ use dom::htmltablecellelement::HTMLTableCellElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableDataCellElement { htmltablecellelement: HTMLTableCellElement, } diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs index e33a44cdd58..b39c8ebb3e3 100644 --- a/components/script/dom/htmltableelement.rs +++ b/components/script/dom/htmltableelement.rs @@ -17,9 +17,7 @@ use dom::htmltablecaptionelement::HTMLTableCaptionElement; use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltableheadercellelement.rs b/components/script/dom/htmltableheadercellelement.rs index eae776a6903..03ae8a83d7e 100644 --- a/components/script/dom/htmltableheadercellelement.rs +++ b/components/script/dom/htmltableheadercellelement.rs @@ -13,9 +13,7 @@ use dom::htmltablecellelement::HTMLTableCellElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableHeaderCellElement { htmltablecellelement: HTMLTableCellElement, } diff --git a/components/script/dom/htmltablerowelement.rs b/components/script/dom/htmltablerowelement.rs index 45f1f06fe28..64bd1e66c11 100644 --- a/components/script/dom/htmltablerowelement.rs +++ b/components/script/dom/htmltablerowelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableRowElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltablesectionelement.rs b/components/script/dom/htmltablesectionelement.rs index f4a26c709ec..d10e4b82b44 100644 --- a/components/script/dom/htmltablesectionelement.rs +++ b/components/script/dom/htmltablesectionelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTableSectionElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltemplateelement.rs b/components/script/dom/htmltemplateelement.rs index 9e959937ec6..c0a125109dc 100644 --- a/components/script/dom/htmltemplateelement.rs +++ b/components/script/dom/htmltemplateelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTemplateElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 37fd0544f4f..274c2b08ee1 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -18,9 +18,7 @@ use dom::virtualmethods::VirtualMethods; use servo_util::str::DOMString; use string_cache::Atom; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTextAreaElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltimeelement.rs b/components/script/dom/htmltimeelement.rs index 4cf70e20214..3f21071fd2b 100644 --- a/components/script/dom/htmltimeelement.rs +++ b/components/script/dom/htmltimeelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTimeElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmltitleelement.rs b/components/script/dom/htmltitleelement.rs index 5e7d8fbd1b3..ef8b70aa4fa 100644 --- a/components/script/dom/htmltitleelement.rs +++ b/components/script/dom/htmltitleelement.rs @@ -16,9 +16,7 @@ use dom::node::{Node, NodeHelpers, ElementNodeTypeId}; use dom::text::Text; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTitleElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmltrackelement.rs b/components/script/dom/htmltrackelement.rs index f1ae254b365..ae1a164ad05 100644 --- a/components/script/dom/htmltrackelement.rs +++ b/components/script/dom/htmltrackelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLTrackElement { htmlelement: HTMLElement, } diff --git a/components/script/dom/htmlulistelement.rs b/components/script/dom/htmlulistelement.rs index bd417aef8ca..5909dbfc3ae 100644 --- a/components/script/dom/htmlulistelement.rs +++ b/components/script/dom/htmlulistelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLUListElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlunknownelement.rs b/components/script/dom/htmlunknownelement.rs index 1194346baa9..d8a338afb82 100644 --- a/components/script/dom/htmlunknownelement.rs +++ b/components/script/dom/htmlunknownelement.rs @@ -13,9 +13,7 @@ use dom::htmlelement::HTMLElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLUnknownElement { htmlelement: HTMLElement } diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs index 6e7080aca68..4bec140ecf1 100644 --- a/components/script/dom/htmlvideoelement.rs +++ b/components/script/dom/htmlvideoelement.rs @@ -13,9 +13,7 @@ use dom::htmlmediaelement::HTMLMediaElement; use dom::node::{Node, ElementNodeTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct HTMLVideoElement { htmlmediaelement: HTMLMediaElement } diff --git a/components/script/dom/location.rs b/components/script/dom/location.rs index 008a7deb3e9..79d1a9e404a 100644 --- a/components/script/dom/location.rs +++ b/components/script/dom/location.rs @@ -15,9 +15,7 @@ use servo_util::str::DOMString; use std::rc::Rc; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Location { reflector_: Reflector, page: Rc<Page>, diff --git a/components/script/dom/messageevent.rs b/components/script/dom/messageevent.rs index 0f21a0b8096..a090a2f279e 100644 --- a/components/script/dom/messageevent.rs +++ b/components/script/dom/messageevent.rs @@ -18,9 +18,7 @@ use servo_util::str::DOMString; use js::jsapi::JSContext; use js::jsval::JSVal; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct MessageEvent { event: Event, data: JSVal, diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs index 2ecfaa06ca5..a4d3a0a9e09 100644 --- a/components/script/dom/mouseevent.rs +++ b/components/script/dom/mouseevent.rs @@ -19,9 +19,7 @@ use servo_util::str::DOMString; use std::cell::Cell; use std::default::Default; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct MouseEvent { mouseevent: UIEvent, screen_x: Cell<i32>, diff --git a/components/script/dom/namednodemap.rs b/components/script/dom/namednodemap.rs index c0304510c68..1bfe7034198 100644 --- a/components/script/dom/namednodemap.rs +++ b/components/script/dom/namednodemap.rs @@ -11,9 +11,7 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::element::Element; use dom::window::Window; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct NamedNodeMap { reflector_: Reflector, owner: JS<Element>, diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index f3ae6421564..5824817f895 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -11,9 +11,7 @@ use dom::navigatorinfo::NavigatorInfo; use dom::window::Window; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Navigator { reflector_: Reflector, } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 5b2e3191ce6..724f9423bb3 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -44,9 +44,9 @@ use dom::text::Text; use dom::virtualmethods::{VirtualMethods, vtable_for}; use dom::window::Window; use geom::rect::Rect; -use html::hubbub_html_parser::build_element_from_tag; +use parse::html::build_element_from_tag; use layout_interface::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC, - LayoutChan, ReapLayoutDataMsg, TrustedNodeAddress}; + LayoutChan, ReapLayoutDataMsg}; use devtools_traits::NodeInfo; use script_traits::UntrustedNodeAddress; use servo_util::geometry::Au; @@ -56,7 +56,7 @@ use style::{parse_selector_list_from_str, matches}; use js::jsapi::{JSContext, JSObject, JSTracer, JSRuntime}; use js::jsfriendapi; use libc; -use libc::uintptr_t; +use libc::{uintptr_t, c_void}; use std::cell::{Cell, RefCell, Ref, RefMut}; use std::default::Default; use std::iter::{Map, Filter}; @@ -65,15 +65,14 @@ use style; use style::ComputedValues; use sync::Arc; use uuid; +use string_cache::QualName; // // The basic Node structure // /// An HTML node. -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Node { /// The JavaScript reflector for this node. eventtarget: EventTarget, @@ -949,15 +948,15 @@ pub trait RawLayoutNodeHelpers { impl RawLayoutNodeHelpers for Node { #[inline] unsafe fn get_hover_state_for_layout(&self) -> bool { - (*self.unsafe_get_flags()).contains(InHoverState) + self.flags.get().contains(InHoverState) } #[inline] unsafe fn get_disabled_state_for_layout(&self) -> bool { - (*self.unsafe_get_flags()).contains(InDisabledState) + self.flags.get().contains(InDisabledState) } #[inline] unsafe fn get_enabled_state_for_layout(&self) -> bool { - (*self.unsafe_get_flags()).contains(InEnabledState) + self.flags.get().contains(InEnabledState) } #[inline] fn type_id_for_layout(&self) -> NodeTypeId { @@ -1532,8 +1531,12 @@ impl Node { }, ElementNodeTypeId(..) => { let element: JSRef<Element> = ElementCast::to_ref(node).unwrap(); - let element = build_element_from_tag(element.local_name().as_slice().to_string(), - element.namespace().clone(), Some(element.prefix().as_slice().to_string()), *document); + let name = QualName { + ns: element.namespace().clone(), + local: element.local_name().clone() + }; + let element = build_element_from_tag(name, + Some(element.prefix().as_slice().to_string()), *document); NodeCast::from_temporary(element) }, TextNodeTypeId => { @@ -1612,11 +1615,6 @@ impl Node { } } - #[inline] - pub unsafe fn unsafe_get_flags(&self) -> *const NodeFlags { - mem::transmute(&self.flags) - } - pub fn collect_text_contents<'a, T: Iterator<JSRef<'a, Node>>>(mut iterator: T) -> String { let mut content = String::new(); for node in iterator { @@ -2166,6 +2164,13 @@ impl Reflectable for Node { } } +/// The address of a node known to be valid. These are sent from script to layout, +/// and are also used in the HTML parser interface. + +#[allow(raw_pointer_deriving)] +#[deriving(Clone, PartialEq, Eq)] +pub struct TrustedNodeAddress(pub *const c_void); + pub fn document_from_node<T: NodeBase+Reflectable>(derived: JSRef<T>) -> Temporary<Document> { let node: JSRef<Node> = NodeCast::from_ref(derived); node.owner_doc() diff --git a/components/script/dom/nodeiterator.rs b/components/script/dom/nodeiterator.rs index 27656da9433..e6d2e982d43 100644 --- a/components/script/dom/nodeiterator.rs +++ b/components/script/dom/nodeiterator.rs @@ -8,9 +8,7 @@ use dom::bindings::global::GlobalRef; use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct NodeIterator { reflector_: Reflector } diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index f2da3a0c4ba..9bac5ef2c9a 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -17,9 +17,7 @@ pub enum NodeListType { Children(JS<Node>) } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct NodeList { list_type: NodeListType, reflector_: Reflector, diff --git a/components/script/dom/performance.rs b/components/script/dom/performance.rs index ae6fb7061cc..a8e6561f0d5 100644 --- a/components/script/dom/performance.rs +++ b/components/script/dom/performance.rs @@ -13,9 +13,7 @@ use time; pub type DOMHighResTimeStamp = f64; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Performance { reflector_: Reflector, timing: JS<PerformanceTiming>, diff --git a/components/script/dom/performancetiming.rs b/components/script/dom/performancetiming.rs index 0c8b6a60008..7a93343e87b 100644 --- a/components/script/dom/performancetiming.rs +++ b/components/script/dom/performancetiming.rs @@ -9,9 +9,7 @@ use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct PerformanceTiming { reflector_: Reflector, navigationStart: u64, diff --git a/components/script/dom/processinginstruction.rs b/components/script/dom/processinginstruction.rs index 19017ae9050..7b2c5f22ba6 100644 --- a/components/script/dom/processinginstruction.rs +++ b/components/script/dom/processinginstruction.rs @@ -14,9 +14,7 @@ use dom::node::{Node, ProcessingInstructionNodeTypeId}; use servo_util::str::DOMString; /// An HTML processing instruction node. -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct ProcessingInstruction { characterdata: CharacterData, target: DOMString, diff --git a/components/script/dom/progressevent.rs b/components/script/dom/progressevent.rs index 52d1f6f35ff..54b902994ea 100644 --- a/components/script/dom/progressevent.rs +++ b/components/script/dom/progressevent.rs @@ -13,9 +13,7 @@ use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::event::{Event, ProgressEventTypeId}; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct ProgressEvent { event: Event, length_computable: bool, diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs index a611604e6bb..99b48cea700 100644 --- a/components/script/dom/range.rs +++ b/components/script/dom/range.rs @@ -11,9 +11,7 @@ use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::document::Document; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Range { reflector_: Reflector } diff --git a/components/script/dom/screen.rs b/components/script/dom/screen.rs index ad4250ee1c6..dd3bc911cc3 100644 --- a/components/script/dom/screen.rs +++ b/components/script/dom/screen.rs @@ -9,9 +9,7 @@ use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Screen { reflector_: Reflector, } diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs new file mode 100644 index 00000000000..c4d594186c8 --- /dev/null +++ b/components/script/dom/servohtmlparser.rs @@ -0,0 +1,105 @@ +/* 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/. */ + +//! The bulk of the HTML parser integration is in `script::parse::html`. +//! This module is mostly about its interaction with DOM memory management. + +use dom::bindings::codegen::Bindings::ServoHTMLParserBinding; +use dom::bindings::global; +use dom::bindings::trace::JSTraceable; +use dom::bindings::js::{JS, JSRef, Temporary}; +use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; +use dom::node::TrustedNodeAddress; +use dom::document::Document; +use parse::html::JSMessage; + +use std::default::Default; +use std::cell::RefCell; +use url::Url; +use js::jsapi::JSTracer; +use html5ever::tokenizer; +use html5ever::tree_builder; +use html5ever::tree_builder::{TreeBuilder, TreeBuilderOpts}; + +#[must_root] +#[jstraceable] +pub struct Sink { + pub js_chan: Sender<JSMessage>, + pub base_url: Option<Url>, + pub document: JS<Document>, +} + +pub type Tokenizer = tokenizer::Tokenizer<TreeBuilder<TrustedNodeAddress, Sink>>; + +// NB: JSTraceable is *not* auto-derived. +// You must edit the impl below if you add fields! +#[must_root] +#[privatize] +pub struct ServoHTMLParser { + reflector_: Reflector, + tokenizer: RefCell<Tokenizer>, +} + +impl ServoHTMLParser { + #[allow(unrooted_must_root)] + pub fn new(js_chan: Sender<JSMessage>, base_url: Option<Url>, document: JSRef<Document>) + -> Temporary<ServoHTMLParser> { + let window = document.window().root(); + let sink = Sink { + js_chan: js_chan, + base_url: base_url, + document: JS::from_rooted(document), + }; + + let tb = TreeBuilder::new(sink, TreeBuilderOpts { + ignore_missing_rules: true, + .. Default::default() + }); + + let tok = tokenizer::Tokenizer::new(tb, Default::default()); + + let parser = ServoHTMLParser { + reflector_: Reflector::new(), + tokenizer: RefCell::new(tok), + }; + + reflect_dom_object(box parser, &global::Window(*window), ServoHTMLParserBinding::Wrap) + } + + #[inline] + pub fn tokenizer<'a>(&'a self) -> &'a RefCell<Tokenizer> { + &self.tokenizer + } +} + +impl Reflectable for ServoHTMLParser { + fn reflector<'a>(&'a self) -> &'a Reflector { + &self.reflector_ + } +} + +struct Tracer { + trc: *mut JSTracer, +} + +impl tree_builder::Tracer<TrustedNodeAddress> for Tracer { + fn trace_handle(&self, node: TrustedNodeAddress) { + node.trace(self.trc); + } +} + +impl JSTraceable for ServoHTMLParser { + fn trace(&self, trc: *mut JSTracer) { + let tracer = Tracer { + trc: trc, + }; + let tracer = &tracer as &tree_builder::Tracer<TrustedNodeAddress>; + + self.reflector_.trace(trc); + let tokenizer = self.tokenizer.borrow(); + let tree_builder = tokenizer.sink(); + tree_builder.trace_handles(tracer); + tree_builder.sink().trace(trc); + } +} diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index a409c70d1bf..073a5721fa1 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -18,9 +18,7 @@ use servo_util::str::DOMString; use js::jsapi::JSContext; use js::jsval::{JSVal, NullValue}; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct TestBinding { reflector: Reflector, global: GlobalField, diff --git a/components/script/dom/text.rs b/components/script/dom/text.rs index b8fea7c23cb..1843bf58d21 100644 --- a/components/script/dom/text.rs +++ b/components/script/dom/text.rs @@ -16,9 +16,7 @@ use dom::node::{Node, TextNodeTypeId}; use servo_util::str::DOMString; /// An HTML text node. -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Text { characterdata: CharacterData, } diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs index f9100dd15be..44a62f60baa 100644 --- a/components/script/dom/treewalker.rs +++ b/components/script/dom/treewalker.rs @@ -21,9 +21,7 @@ use dom::node::{Node, NodeHelpers}; use std::cell::Cell; // http://dom.spec.whatwg.org/#interface-treewalker -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct TreeWalker { reflector_: Reflector, root_node: JS<Node>, diff --git a/components/script/dom/uievent.rs b/components/script/dom/uievent.rs index d5dd2cfc4df..6a55f6ccbf8 100644 --- a/components/script/dom/uievent.rs +++ b/components/script/dom/uievent.rs @@ -19,9 +19,7 @@ use servo_util::str::DOMString; use std::cell::Cell; use std::default::Default; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct UIEvent { event: Event, view: MutNullableJS<Window>, diff --git a/components/script/dom/urlsearchparams.rs b/components/script/dom/urlsearchparams.rs index 8174fafcc98..98cfc2a5792 100644 --- a/components/script/dom/urlsearchparams.rs +++ b/components/script/dom/urlsearchparams.rs @@ -20,9 +20,7 @@ use std::collections::hashmap::HashMap; use std::fmt::radix; use std::ascii::OwnedStrAsciiExt; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct URLSearchParams { data: RefCell<HashMap<DOMString, Vec<DOMString>>>, reflector_: Reflector, diff --git a/components/script/dom/validitystate.rs b/components/script/dom/validitystate.rs index ef76ac433e1..f8ce174229f 100644 --- a/components/script/dom/validitystate.rs +++ b/components/script/dom/validitystate.rs @@ -8,9 +8,7 @@ use dom::bindings::js::{JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::window::Window; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct ValidityState { reflector_: Reflector, state: u8, diff --git a/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl b/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl index dbf2891f72a..2fd34392dc9 100644 --- a/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl +++ b/components/script/dom/webidls/DedicatedWorkerGlobalScope.webidl @@ -5,6 +5,7 @@ // http://www.whatwg.org/html/#dedicatedworkerglobalscope [Global/*=Worker,DedicatedWorker*/] /*sealed*/ interface DedicatedWorkerGlobalScope : WorkerGlobalScope { + [Throws] void postMessage(any message/*, optional sequence<Transferable> transfer*/); attribute EventHandler onmessage; }; diff --git a/components/script/dom/webidls/ServoHTMLParser.webidl b/components/script/dom/webidls/ServoHTMLParser.webidl new file mode 100644 index 00000000000..02ad2667a96 --- /dev/null +++ b/components/script/dom/webidls/ServoHTMLParser.webidl @@ -0,0 +1,9 @@ +/* -*- 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/. */ + +// FIXME: find a better way to hide this from content (#3688) +[NoInterfaceObject] +interface ServoHTMLParser { +}; diff --git a/components/script/dom/webidls/Worker.webidl b/components/script/dom/webidls/Worker.webidl index 2228c203781..aa8a1c1e5d3 100644 --- a/components/script/dom/webidls/Worker.webidl +++ b/components/script/dom/webidls/Worker.webidl @@ -14,6 +14,7 @@ interface AbstractWorker { interface Worker : EventTarget { //void terminate(); + [Throws] void postMessage(any message/*, optional sequence<Transferable> transfer*/); attribute EventHandler onmessage; }; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 2090cd0819d..044a6f6fabe 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -44,9 +44,7 @@ use std::default::Default; use std::rc::Rc; use time; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Window { eventtarget: EventTarget, script_chan: ScriptChan, diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index f7feec1929f..05a65318c69 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::WorkerBinding; use dom::bindings::codegen::Bindings::WorkerBinding::WorkerMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::InheritTypes::EventTargetCast; -use dom::bindings::error::{Fallible, Syntax}; +use dom::bindings::error::{Fallible, Syntax, ErrorResult, DataClone}; use dom::bindings::global::{GlobalRef, GlobalField}; use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::trace::JSTraceable; @@ -20,7 +20,7 @@ use servo_util::str::DOMString; use js::glue::JS_STRUCTURED_CLONE_VERSION; use js::jsapi::{JSContext, JS_AddObjectRoot, JS_RemoveObjectRoot, JSTracer}; -use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone}; +use js::jsapi::{JS_ReadStructuredClone, JS_WriteStructuredClone, JS_ClearPendingException}; use js::jsval::{JSVal, UndefinedValue}; use url::UrlParser; @@ -31,9 +31,7 @@ use std::ptr; pub struct TrustedWorkerAddress(pub *const c_void); untraceable!(TrustedWorkerAddress) -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct Worker { eventtarget: EventTarget, refcount: Cell<uint>, @@ -133,17 +131,22 @@ impl Worker { } impl<'a> WorkerMethods for JSRef<'a, Worker> { - fn PostMessage(self, cx: *mut JSContext, message: JSVal) { + fn PostMessage(self, cx: *mut JSContext, message: JSVal) -> ErrorResult { let mut data = ptr::null_mut(); let mut nbytes = 0; - unsafe { - assert!(JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes, - ptr::null(), ptr::null_mut()) != 0); + let result = unsafe { + JS_WriteStructuredClone(cx, message, &mut data, &mut nbytes, + ptr::null(), ptr::null_mut()) + }; + if result == 0 { + unsafe { JS_ClearPendingException(cx); } + return Err(DataClone); } self.addref(); let ScriptChan(ref sender) = self.sender; sender.send(DOMMessage(data, nbytes)); + Ok(()) } fn GetOnmessage(self) -> Option<EventHandlerNonNull> { diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 69f2c926320..5c352739c98 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -32,9 +32,7 @@ pub enum WorkerGlobalScopeId { DedicatedGlobalScope, } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct WorkerGlobalScope { eventtarget: EventTarget, worker_url: Url, diff --git a/components/script/dom/workerlocation.rs b/components/script/dom/workerlocation.rs index 145ba8c8f93..01583b54692 100644 --- a/components/script/dom/workerlocation.rs +++ b/components/script/dom/workerlocation.rs @@ -14,9 +14,7 @@ use servo_util::str::DOMString; use url::Url; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct WorkerLocation { reflector_: Reflector, url: Url, diff --git a/components/script/dom/workernavigator.rs b/components/script/dom/workernavigator.rs index 6cc02c0e3fa..98e5672fa85 100644 --- a/components/script/dom/workernavigator.rs +++ b/components/script/dom/workernavigator.rs @@ -11,9 +11,7 @@ use dom::navigatorinfo::NavigatorInfo; use dom::workerglobalscope::WorkerGlobalScope; use servo_util::str::DOMString; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct WorkerNavigator { reflector_: Reflector, } diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 1e96b701d1e..02f7070ad3c 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -102,9 +102,7 @@ enum SyncOrAsync<'a> { } -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct XMLHttpRequest { eventtarget: XMLHttpRequestEventTarget, ready_state: Cell<XMLHttpRequestState>, diff --git a/components/script/dom/xmlhttprequesteventtarget.rs b/components/script/dom/xmlhttprequesteventtarget.rs index 0b9c9e7a75f..79e70123a4d 100644 --- a/components/script/dom/xmlhttprequesteventtarget.rs +++ b/components/script/dom/xmlhttprequesteventtarget.rs @@ -11,9 +11,7 @@ use dom::bindings::utils::{Reflectable, Reflector}; use dom::eventtarget::{EventTarget, EventTargetHelpers, XMLHttpRequestTargetTypeId}; use dom::xmlhttprequest::XMLHttpRequestId; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct XMLHttpRequestEventTarget { eventtarget: EventTarget, } diff --git a/components/script/dom/xmlhttprequestupload.rs b/components/script/dom/xmlhttprequestupload.rs index 7e11df328a8..78635ea306c 100644 --- a/components/script/dom/xmlhttprequestupload.rs +++ b/components/script/dom/xmlhttprequestupload.rs @@ -11,9 +11,7 @@ use dom::eventtarget::{EventTarget, XMLHttpRequestTargetTypeId}; use dom::xmlhttprequest::{XMLHttpRequestUploadTypeId}; use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget; -#[jstraceable] -#[must_root] -#[privatize] +#[dom_struct] pub struct XMLHttpRequestUpload { eventtarget: XMLHttpRequestEventTarget } diff --git a/components/script/layout_interface.rs b/components/script/layout_interface.rs index a3c8de5a66a..735893f497a 100644 --- a/components/script/layout_interface.rs +++ b/components/script/layout_interface.rs @@ -6,14 +6,10 @@ /// coupling between these two components, and enables the DOM to be placed in a separate crate /// from layout. -use dom::bindings::js::JS; -use dom::bindings::trace::JSTraceable; -use dom::node::{Node, LayoutDataRef}; +use dom::node::LayoutDataRef; use geom::point::Point2D; use geom::rect::Rect; -use js::jsapi::JSTracer; -use libc::c_void; use script_traits::{ScriptControlChan, OpaqueScriptLayoutChannel, UntrustedNodeAddress}; use servo_msg::constellation_msg::WindowSizeData; use servo_util::geometry::Au; @@ -23,6 +19,8 @@ use std::owned::BoxAny; use style::Stylesheet; use url::Url; +pub use dom::node::TrustedNodeAddress; + /// Asynchronous messages that script can send to layout. pub enum Msg { /// Adds the given stylesheet to the document. @@ -70,20 +68,6 @@ pub trait LayoutRPC { fn mouse_over(&self, node: TrustedNodeAddress, point: Point2D<f32>) -> Result<MouseOverResponse, ()>; } -/// The address of a node known to be valid. These must only be sent from content -> layout, -/// because we do not trust layout. -pub struct TrustedNodeAddress(pub *const c_void); - -impl JSTraceable for TrustedNodeAddress { - fn trace(&self, s: *mut JSTracer) { - let TrustedNodeAddress(addr) = *self; - let node = addr as *const Node; - unsafe { - JS::from_raw(node).trace(s) - } - } -} - pub struct ContentBoxResponse(pub Rect<Au>); pub struct ContentBoxesResponse(pub Vec<Rect<Au>>); pub struct HitTestResponse(pub UntrustedNodeAddress); diff --git a/components/script/lib.rs b/components/script/lib.rs index 8053937f275..e03801f5217 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -20,7 +20,7 @@ extern crate devtools_traits; extern crate cssparser; extern crate collections; extern crate geom; -extern crate hubbub; +extern crate html5ever; extern crate encoding; extern crate http; extern crate js; @@ -191,6 +191,7 @@ pub mod dom { pub mod progressevent; pub mod range; pub mod screen; + pub mod servohtmlparser; pub mod text; pub mod treewalker; pub mod uievent; @@ -210,9 +211,8 @@ pub mod dom { pub mod testbinding; } -/// Parsers for HTML and CSS. -pub mod html { - pub mod hubbub_html_parser; +pub mod parse { + pub mod html; } pub mod layout_interface; diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs new file mode 100644 index 00000000000..829d5d0c40b --- /dev/null +++ b/components/script/parse/html.rs @@ -0,0 +1,521 @@ +/* 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::attr::AttrHelpers; +use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; +use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; +use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLScriptElementCast}; +use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root}; +use dom::document::{Document, DocumentHelpers}; +use dom::element::{AttributeHandlers, ElementHelpers}; +use dom::htmlelement::HTMLElement; +use dom::htmlheadingelement::{Heading1, Heading2, Heading3, Heading4, Heading5, Heading6}; +use dom::htmlformelement::HTMLFormElement; +use dom::htmlscriptelement::HTMLScriptElementHelpers; +use dom::node::{Node, NodeHelpers, TrustedNodeAddress}; +use dom::servohtmlparser; +use dom::servohtmlparser::ServoHTMLParser; +use dom::types::*; +use page::Page; + +use encoding::all::UTF_8; +use encoding::types::{Encoding, DecodeReplace}; + +use servo_net::resource_task::{Load, LoadData, Payload, Done, ResourceTask, load_whole_resource}; +use servo_msg::constellation_msg::LoadData as MsgLoadData; +use servo_util::task::spawn_named; +use servo_util::str::DOMString; +use std::ascii::StrAsciiExt; +use std::comm::{channel, Sender, Receiver}; +use std::str::MaybeOwned; +use url::{Url, UrlParser}; +use http::headers::HeaderEnum; +use time; +use html5ever::Attribute; +use html5ever::tree_builder::{TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText}; +use string_cache::QualName; + +pub struct JSFile { + pub data: String, + pub url: Option<Url>, +} + +pub type JSResult = Vec<JSFile>; + +pub enum HTMLInput { + InputString(String), + InputUrl(Url), +} + +pub enum JSMessage { + JSTaskNewFile(Url), + JSTaskNewInlineScript(String, Option<Url>), + JSTaskExit +} + +/// Messages generated by the HTML parser upon discovery of additional resources +pub enum HtmlDiscoveryMessage { + HtmlDiscoveredScript(JSResult) +} + +pub struct HtmlParserResult { + pub discovery_port: Receiver<HtmlDiscoveryMessage>, +} + +fn js_script_listener(to_parent: Sender<HtmlDiscoveryMessage>, + from_parent: Receiver<JSMessage>, + resource_task: ResourceTask) { + let mut result_vec = vec!(); + + loop { + match from_parent.recv_opt() { + Ok(JSTaskNewFile(url)) => { + match load_whole_resource(&resource_task, url.clone()) { + Err(_) => { + error!("error loading script {:s}", url.serialize()); + } + Ok((metadata, bytes)) => { + let decoded = UTF_8.decode(bytes.as_slice(), DecodeReplace).unwrap(); + result_vec.push(JSFile { + data: decoded.to_string(), + url: Some(metadata.final_url), + }); + } + } + } + Ok(JSTaskNewInlineScript(data, url)) => { + result_vec.push(JSFile { data: data, url: url }); + } + Ok(JSTaskExit) | Err(()) => { + break; + } + } + } + + assert!(to_parent.send_opt(HtmlDiscoveredScript(result_vec)).is_ok()); +} + +// Parses an RFC 2616 compliant date/time string, and returns a localized +// date/time string in a format suitable for document.lastModified. +fn parse_last_modified(timestamp: &str) -> String { + let format = "%m/%d/%Y %H:%M:%S"; + + // RFC 822, updated by RFC 1123 + match time::strptime(timestamp, "%a, %d %b %Y %T %Z") { + Ok(t) => return t.to_local().strftime(format), + Err(_) => () + } + + // RFC 850, obsoleted by RFC 1036 + match time::strptime(timestamp, "%A, %d-%b-%y %T %Z") { + Ok(t) => return t.to_local().strftime(format), + Err(_) => () + } + + // ANSI C's asctime() format + match time::strptime(timestamp, "%c") { + Ok(t) => t.to_local().strftime(format), + Err(_) => String::from_str("") + } +} + +pub fn build_element_from_tag(name: QualName, + prefix: Option<DOMString>, + document: JSRef<Document>) -> Temporary<Element> { + if name.ns != ns!(HTML) { + return Element::new(name.local.as_slice().to_string(), name.ns, None, document); + } + + macro_rules! make( + ($ctor:ident $(, $arg:expr)*) => ({ + let obj = $ctor::new(name.local.as_slice().to_string(), prefix, document $(, $arg)*); + ElementCast::from_temporary(obj) + }) + ) + + // This is a big match, and the IDs for inline-interned atoms are not very structured. + // Perhaps we should build a perfect hash from those IDs instead. + match name.local { + atom!("a") => make!(HTMLAnchorElement), + atom!("abbr") => make!(HTMLElement), + atom!("acronym") => make!(HTMLElement), + atom!("address") => make!(HTMLElement), + atom!("applet") => make!(HTMLAppletElement), + atom!("area") => make!(HTMLAreaElement), + atom!("article") => make!(HTMLElement), + atom!("aside") => make!(HTMLElement), + atom!("audio") => make!(HTMLAudioElement), + atom!("b") => make!(HTMLElement), + atom!("base") => make!(HTMLBaseElement), + atom!("bdi") => make!(HTMLElement), + atom!("bdo") => make!(HTMLElement), + atom!("bgsound") => make!(HTMLElement), + atom!("big") => make!(HTMLElement), + atom!("blockquote") => make!(HTMLElement), + atom!("body") => make!(HTMLBodyElement), + atom!("br") => make!(HTMLBRElement), + atom!("button") => make!(HTMLButtonElement), + atom!("canvas") => make!(HTMLCanvasElement), + atom!("caption") => make!(HTMLTableCaptionElement), + atom!("center") => make!(HTMLElement), + atom!("cite") => make!(HTMLElement), + atom!("code") => make!(HTMLElement), + atom!("col") => make!(HTMLTableColElement), + atom!("colgroup") => make!(HTMLTableColElement), + atom!("data") => make!(HTMLDataElement), + atom!("datalist") => make!(HTMLDataListElement), + atom!("dd") => make!(HTMLElement), + atom!("del") => make!(HTMLModElement), + atom!("details") => make!(HTMLElement), + atom!("dfn") => make!(HTMLElement), + atom!("dir") => make!(HTMLDirectoryElement), + atom!("div") => make!(HTMLDivElement), + atom!("dl") => make!(HTMLDListElement), + atom!("dt") => make!(HTMLElement), + atom!("em") => make!(HTMLElement), + atom!("embed") => make!(HTMLEmbedElement), + atom!("fieldset") => make!(HTMLFieldSetElement), + atom!("figcaption") => make!(HTMLElement), + atom!("figure") => make!(HTMLElement), + atom!("font") => make!(HTMLFontElement), + atom!("footer") => make!(HTMLElement), + atom!("form") => make!(HTMLFormElement), + atom!("frame") => make!(HTMLFrameElement), + atom!("frameset") => make!(HTMLFrameSetElement), + atom!("h1") => make!(HTMLHeadingElement, Heading1), + atom!("h2") => make!(HTMLHeadingElement, Heading2), + atom!("h3") => make!(HTMLHeadingElement, Heading3), + atom!("h4") => make!(HTMLHeadingElement, Heading4), + atom!("h5") => make!(HTMLHeadingElement, Heading5), + atom!("h6") => make!(HTMLHeadingElement, Heading6), + atom!("head") => make!(HTMLHeadElement), + atom!("header") => make!(HTMLElement), + atom!("hgroup") => make!(HTMLElement), + atom!("hr") => make!(HTMLHRElement), + atom!("html") => make!(HTMLHtmlElement), + atom!("i") => make!(HTMLElement), + atom!("iframe") => make!(HTMLIFrameElement), + atom!("img") => make!(HTMLImageElement), + atom!("input") => make!(HTMLInputElement), + atom!("ins") => make!(HTMLModElement), + atom!("isindex") => make!(HTMLElement), + atom!("kbd") => make!(HTMLElement), + atom!("label") => make!(HTMLLabelElement), + atom!("legend") => make!(HTMLLegendElement), + atom!("li") => make!(HTMLLIElement), + atom!("link") => make!(HTMLLinkElement), + atom!("main") => make!(HTMLElement), + atom!("map") => make!(HTMLMapElement), + atom!("mark") => make!(HTMLElement), + atom!("marquee") => make!(HTMLElement), + atom!("meta") => make!(HTMLMetaElement), + atom!("meter") => make!(HTMLMeterElement), + atom!("nav") => make!(HTMLElement), + atom!("nobr") => make!(HTMLElement), + atom!("noframes") => make!(HTMLElement), + atom!("noscript") => make!(HTMLElement), + atom!("object") => make!(HTMLObjectElement), + atom!("ol") => make!(HTMLOListElement), + atom!("optgroup") => make!(HTMLOptGroupElement), + atom!("option") => make!(HTMLOptionElement), + atom!("output") => make!(HTMLOutputElement), + atom!("p") => make!(HTMLParagraphElement), + atom!("param") => make!(HTMLParamElement), + atom!("pre") => make!(HTMLPreElement), + atom!("progress") => make!(HTMLProgressElement), + atom!("q") => make!(HTMLQuoteElement), + atom!("rp") => make!(HTMLElement), + atom!("rt") => make!(HTMLElement), + atom!("ruby") => make!(HTMLElement), + atom!("s") => make!(HTMLElement), + atom!("samp") => make!(HTMLElement), + atom!("script") => make!(HTMLScriptElement), + atom!("section") => make!(HTMLElement), + atom!("select") => make!(HTMLSelectElement), + atom!("small") => make!(HTMLElement), + atom!("source") => make!(HTMLSourceElement), + atom!("spacer") => make!(HTMLElement), + atom!("span") => make!(HTMLSpanElement), + atom!("strike") => make!(HTMLElement), + atom!("strong") => make!(HTMLElement), + atom!("style") => make!(HTMLStyleElement), + atom!("sub") => make!(HTMLElement), + atom!("summary") => make!(HTMLElement), + atom!("sup") => make!(HTMLElement), + atom!("table") => make!(HTMLTableElement), + atom!("tbody") => make!(HTMLTableSectionElement), + atom!("td") => make!(HTMLTableDataCellElement), + atom!("template") => make!(HTMLTemplateElement), + atom!("textarea") => make!(HTMLTextAreaElement), + atom!("th") => make!(HTMLTableHeaderCellElement), + atom!("time") => make!(HTMLTimeElement), + atom!("title") => make!(HTMLTitleElement), + atom!("tr") => make!(HTMLTableRowElement), + atom!("tt") => make!(HTMLElement), + atom!("track") => make!(HTMLTrackElement), + atom!("u") => make!(HTMLElement), + atom!("ul") => make!(HTMLUListElement), + atom!("var") => make!(HTMLElement), + atom!("video") => make!(HTMLVideoElement), + atom!("wbr") => make!(HTMLElement), + _ => make!(HTMLUnknownElement), + } +} + +trait SinkHelpers { + fn get_or_create(&self, child: NodeOrText<TrustedNodeAddress>) -> Temporary<Node>; +} + +impl SinkHelpers for servohtmlparser::Sink { + fn get_or_create(&self, child: NodeOrText<TrustedNodeAddress>) -> Temporary<Node> { + match child { + AppendNode(n) => Temporary::new(unsafe { JS::from_trusted_node_address(n) }), + AppendText(t) => { + let doc = self.document.root(); + let text = Text::new(t, *doc); + NodeCast::from_temporary(text) + } + } + } +} + +impl<'a> TreeSink<TrustedNodeAddress> for servohtmlparser::Sink { + fn get_document(&mut self) -> TrustedNodeAddress { + let doc = self.document.root(); + let node: JSRef<Node> = NodeCast::from_ref(*doc); + node.to_trusted_node_address() + } + + fn same_node(&self, x: TrustedNodeAddress, y: TrustedNodeAddress) -> bool { + x == y + } + + fn elem_name(&self, target: TrustedNodeAddress) -> QualName { + let node: Root<Node> = unsafe { JS::from_trusted_node_address(target).root() }; + let elem: JSRef<Element> = ElementCast::to_ref(*node) + .expect("tried to get name of non-Element in HTML parsing"); + QualName { + ns: elem.get_namespace().clone(), + local: elem.get_local_name().clone(), + } + } + + fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>) + -> TrustedNodeAddress { + let doc = self.document.root(); + let elem = build_element_from_tag(name, None, *doc).root(); + + for attr in attrs.into_iter() { + elem.set_attribute_from_parser(attr.name, attr.value, None); + } + + let node: JSRef<Node> = NodeCast::from_ref(*elem); + node.to_trusted_node_address() + } + + fn create_comment(&mut self, text: String) -> TrustedNodeAddress { + let doc = self.document.root(); + let comment = Comment::new(text, *doc); + let node: Root<Node> = NodeCast::from_temporary(comment).root(); + node.to_trusted_node_address() + } + + fn append_before_sibling(&mut self, + sibling: TrustedNodeAddress, + new_node: NodeOrText<TrustedNodeAddress>) -> Result<(), NodeOrText<TrustedNodeAddress>> { + // If there is no parent, return the node to the parser. + let sibling: Root<Node> = unsafe { JS::from_trusted_node_address(sibling).root() }; + let parent = match sibling.parent_node() { + Some(p) => p.root(), + None => return Err(new_node), + }; + + let child = self.get_or_create(new_node).root(); + assert!(parent.InsertBefore(*child, Some(*sibling)).is_ok()); + Ok(()) + } + + fn parse_error(&mut self, msg: MaybeOwned<'static>) { + error!("Parse error: {:s}", msg); + } + + fn set_quirks_mode(&mut self, mode: QuirksMode) { + let doc = self.document.root(); + doc.set_quirks_mode(mode); + } + + fn append(&mut self, parent: TrustedNodeAddress, child: NodeOrText<TrustedNodeAddress>) { + let parent: Root<Node> = unsafe { JS::from_trusted_node_address(parent).root() }; + let child = self.get_or_create(child).root(); + + // FIXME(#3701): Use a simpler algorithm and merge adjacent text nodes + assert!(parent.AppendChild(*child).is_ok()); + } + + fn append_doctype_to_document(&mut self, name: String, public_id: String, system_id: String) { + let doc = self.document.root(); + let doc_node: JSRef<Node> = NodeCast::from_ref(*doc); + let doctype = DocumentType::new(name, Some(public_id), Some(system_id), *doc); + let node: Root<Node> = NodeCast::from_temporary(doctype).root(); + + assert!(doc_node.AppendChild(*node).is_ok()); + } + + fn add_attrs_if_missing(&mut self, target: TrustedNodeAddress, attrs: Vec<Attribute>) { + let node: Root<Node> = unsafe { JS::from_trusted_node_address(target).root() }; + let elem: JSRef<Element> = ElementCast::to_ref(*node) + .expect("tried to set attrs on non-Element in HTML parsing"); + for attr in attrs.into_iter() { + elem.set_attribute_from_parser(attr.name, attr.value, None); + } + } + + fn remove_from_parent(&mut self, _target: TrustedNodeAddress) { + error!("remove_from_parent not implemented!"); + } + + fn mark_script_already_started(&mut self, _node: TrustedNodeAddress) { + error!("mark_script_already_started not implemented!"); + } + + fn complete_script(&mut self, node: TrustedNodeAddress) { + let node: Root<Node> = unsafe { JS::from_trusted_node_address(node).root() }; + let script: Option<JSRef<HTMLScriptElement>> = + HTMLScriptElementCast::to_ref(*node); + let script = match script { + Some(script) if script.is_javascript() => script, + _ => return, + }; + + let script_element: JSRef<Element> = ElementCast::from_ref(script); + match script_element.get_attribute(ns!(""), &atom!("src")).root() { + Some(src) => { + debug!("found script: {:s}", src.deref().Value()); + let mut url_parser = UrlParser::new(); + match self.base_url { + None => (), + Some(ref base_url) => { + url_parser.base_url(base_url); + } + }; + match url_parser.parse(src.deref().value().as_slice()) { + Ok(new_url) => self.js_chan.send(JSTaskNewFile(new_url)), + Err(e) => debug!("Parsing url {:s} failed: {:?}", src.deref().Value(), e) + }; + } + None => { + let scriptnode: JSRef<Node> = NodeCast::from_ref(script); + let data = Node::collect_text_contents(scriptnode.children()); + debug!("script data = {:?}", data); + self.js_chan.send(JSTaskNewInlineScript(data, self.base_url.clone())); + } + } + } +} + +// The url from msg_load_data is ignored here +pub fn parse_html(page: &Page, + document: JSRef<Document>, + input: HTMLInput, + resource_task: ResourceTask, + msg_load_data: Option<MsgLoadData>) + -> HtmlParserResult { + // Spawn a JS parser to receive JavaScript. + let (discovery_chan, discovery_port) = channel(); + let resource_task2 = resource_task.clone(); + let js_result_chan = discovery_chan.clone(); + let (js_chan, js_msg_port) = channel(); + spawn_named("parse_html:js", proc() { + js_script_listener(js_result_chan, js_msg_port, resource_task2.clone()); + }); + + let (base_url, load_response) = match input { + InputUrl(ref url) => { + // Wait for the LoadResponse so that the parser knows the final URL. + let (input_chan, input_port) = channel(); + let mut load_data = LoadData::new(url.clone()); + msg_load_data.map(|m| { + load_data.headers = m.headers; + load_data.method = m.method; + load_data.data = m.data; + }); + resource_task.send(Load(load_data, input_chan)); + + let load_response = input_port.recv(); + + debug!("Fetched page; metadata is {:?}", load_response.metadata); + + load_response.metadata.headers.as_ref().map(|headers| { + let header = headers.iter().find(|h| + h.header_name().as_slice().to_ascii_lower() == "last-modified".to_string() + ); + + match header { + Some(h) => document.set_last_modified( + parse_last_modified(h.header_value().as_slice())), + None => {}, + }; + }); + + let base_url = load_response.metadata.final_url.clone(); + + { + // Store the final URL before we start parsing, so that DOM routines + // (e.g. HTMLImageElement::update_image) can resolve relative URLs + // correctly. + *page.mut_url() = Some((base_url.clone(), true)); + } + + (Some(base_url), Some(load_response)) + }, + InputString(_) => { + match *page.url() { + Some((ref page_url, _)) => (Some(page_url.clone()), None), + None => (None, None), + } + }, + }; + + let parser = ServoHTMLParser::new(js_chan.clone(), base_url.clone(), document).root(); + let parser: JSRef<ServoHTMLParser> = *parser; + + match input { + InputString(s) => { + parser.tokenizer().borrow_mut().feed(s); + } + InputUrl(url) => { + let load_response = load_response.unwrap(); + match load_response.metadata.content_type { + Some((ref t, _)) if t.as_slice().eq_ignore_ascii_case("image") => { + let page = format!("<html><body><img src='{:s}' /></body></html>", base_url.as_ref().unwrap().serialize()); + parser.tokenizer().borrow_mut().feed(page); + }, + _ => { + for msg in load_response.progress_port.iter() { + match msg { + Payload(data) => { + // FIXME: use Vec<u8> (html5ever #34) + let data = String::from_utf8(data).unwrap(); + parser.tokenizer().borrow_mut().feed(data); + } + Done(Err(err)) => { + fail!("Failed to load page URL {:s}, error: {:s}", url.serialize(), err); + } + Done(Ok(())) => break, + } + } + } + } + } + } + + parser.tokenizer().borrow_mut().end(); + + debug!("finished parsing"); + js_chan.send(JSTaskExit); + + HtmlParserResult { + discovery_port: discovery_port, + } +} diff --git a/components/script/script_task.rs b/components/script/script_task.rs index 17259132eb6..214d666d636 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -27,8 +27,7 @@ use dom::node::{ElementNodeTypeId, Node, NodeHelpers}; use dom::window::{Window, WindowHelpers}; use dom::worker::{Worker, TrustedWorkerAddress}; use dom::xmlhttprequest::{TrustedXHRAddress, XMLHttpRequest, XHRProgress}; -use html::hubbub_html_parser::{InputString, InputUrl, HtmlParserResult, HtmlDiscoveredScript}; -use html::hubbub_html_parser; +use parse::html::{InputString, InputUrl, HtmlParserResult, HtmlDiscoveredScript, parse_html}; use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowForDisplay}; use layout_interface; use page::{Page, IterablePage, Frame}; @@ -781,16 +780,9 @@ impl ScriptTask { // Parse HTML. // // Note: We can parse the next document in parallel with any previous documents. - let html_parsing_result = - hubbub_html_parser::parse_html(&*page, - *document, - parser_input, - self.resource_task.clone(), - Some(load_data)); - - let HtmlParserResult { - discovery_port - } = html_parsing_result; + let HtmlParserResult { discovery_port } + = parse_html(&*page, *document, parser_input, self.resource_task.clone(), + Some(load_data)); { // Create the root frame. |