diff options
Diffstat (limited to 'components/script/dom')
43 files changed, 277 insertions, 326 deletions
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index d5a00e6c1fa..36de48a1f9b 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -15,10 +15,10 @@ use dom::element::{AttributeMutation, Element}; use dom::virtualmethods::vtable_for; use dom::window::Window; use std::borrow::ToOwned; -use std::cell::Ref; use std::mem; use string_cache::{Atom, Namespace}; use style::attr::{AttrIdentifier, AttrValue}; +use style::refcell::Ref; // https://dom.spec.whatwg.org/#interface-attr #[dom_struct] diff --git a/components/script/dom/bindings/cell.rs b/components/script/dom/bindings/cell.rs deleted file mode 100644 index d1b40af5b1a..00000000000 --- a/components/script/dom/bindings/cell.rs +++ /dev/null @@ -1,139 +0,0 @@ -/* 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/. */ - -//! A shareable mutable container for the DOM. - -use dom::bindings::trace::JSTraceable; -use js::jsapi::JSTracer; -use std::cell::{BorrowError, BorrowMutError, Ref, RefCell, RefMut}; -use style::thread_state; -use style::thread_state::SCRIPT; - -/// A mutable field in the DOM. -/// -/// This extends the API of `core::cell::RefCell` to allow unsafe access in -/// certain situations, with dynamic checking in debug builds. -#[derive(Clone, HeapSizeOf)] -pub struct DOMRefCell<T> { - value: RefCell<T>, -} - -// Functionality specific to Servo's `DOMRefCell` type -// =================================================== - -impl<T> DOMRefCell<T> { - /// Return a reference to the contents. - /// - /// For use in the layout thread only. - #[allow(unsafe_code)] - pub unsafe fn borrow_for_layout(&self) -> &T { - debug_assert!(thread_state::get().is_layout()); - &*self.value.as_ptr() - } - - /// Borrow the contents for the purpose of GC tracing. - /// - /// This succeeds even if the object is mutably borrowed, - /// so you have to be careful in trace code! - #[allow(unsafe_code)] - pub unsafe fn borrow_for_gc_trace(&self) -> &T { - // FIXME: IN_GC isn't reliable enough - doesn't catch minor GCs - // https://github.com/servo/servo/issues/6389 - // debug_assert!(thread_state::get().contains(SCRIPT | IN_GC)); - &*self.value.as_ptr() - } - - /// Borrow the contents for the purpose of script deallocation. - /// - #[allow(unsafe_code)] - pub unsafe fn borrow_for_script_deallocation(&self) -> &mut T { - debug_assert!(thread_state::get().contains(SCRIPT)); - &mut *self.value.as_ptr() - } - - /// Version of the above that we use during restyle while the script thread - /// is blocked. - pub fn borrow_mut_for_layout(&self) -> RefMut<T> { - debug_assert!(thread_state::get().is_layout()); - self.value.borrow_mut() - } -} - -impl<T: JSTraceable> JSTraceable for DOMRefCell<T> { - fn trace(&self, trc: *mut JSTracer) { - unsafe { - (*self).borrow_for_gc_trace().trace(trc) - } - } -} - -// Functionality duplicated with `core::cell::RefCell` -// =================================================== -impl<T> DOMRefCell<T> { - /// Create a new `DOMRefCell` containing `value`. - pub fn new(value: T) -> DOMRefCell<T> { - DOMRefCell { - value: RefCell::new(value), - } - } - - - /// Immutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// # Panics - /// - /// Panics if this is called off the script thread. - /// - /// Panics if the value is currently mutably borrowed. - pub fn borrow(&self) -> Ref<T> { - self.try_borrow().expect("DOMRefCell<T> already mutably borrowed") - } - - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// # Panics - /// - /// Panics if this is called off the script thread. - /// - /// Panics if the value is currently borrowed. - pub fn borrow_mut(&self) -> RefMut<T> { - self.try_borrow_mut().expect("DOMRefCell<T> already borrowed") - } - - /// Attempts to immutably borrow the wrapped value. - /// - /// The borrow lasts until the returned `Ref` exits scope. Multiple - /// immutable borrows can be taken out at the same time. - /// - /// Returns `None` if the value is currently mutably borrowed. - /// - /// # Panics - /// - /// Panics if this is called off the script thread. - pub fn try_borrow(&self) -> Result<Ref<T>, BorrowError<T>> { - debug_assert!(thread_state::get().is_script()); - self.value.try_borrow() - } - - /// Mutably borrows the wrapped value. - /// - /// The borrow lasts until the returned `RefMut` exits scope. The value - /// cannot be borrowed while this borrow is active. - /// - /// Returns `None` if the value is currently borrowed. - /// - /// # Panics - /// - /// Panics if this is called off the script thread. - pub fn try_borrow_mut(&self) -> Result<RefMut<T>, BorrowMutError<T>> { - debug_assert!(thread_state::get().is_script()); - self.value.try_borrow_mut() - } -} diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 7842e08bfa7..cf918feb8e3 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -18,6 +18,7 @@ from WebIDL import ( BuiltinTypes, IDLBuiltinType, IDLNullValue, + IDLNullableType, IDLType, IDLInterfaceMember, IDLUndefinedValue, @@ -1349,7 +1350,10 @@ def getRetvalDeclarationForType(returnType, descriptorProvider): if returnType.isAny(): return CGGeneric("JSVal") if returnType.isObject() or returnType.isSpiderMonkeyInterface(): - return CGGeneric("*mut JSObject") + result = CGGeneric("NonZero<*mut JSObject>") + if returnType.nullable(): + result = CGWrapper(result, pre="Option<", post=">") + return result if returnType.isSequence(): result = getRetvalDeclarationForType(innerSequenceType(returnType), descriptorProvider) result = CGWrapper(result, pre="Vec<", post=">") @@ -4552,6 +4556,8 @@ class CGProxySpecialOperation(CGPerSignatureCall): signature = operation.signatures()[0] (returnType, arguments) = signature + if operation.isGetter() and not returnType.nullable(): + returnType = IDLNullableType(returnType.location, returnType) # We pass len(arguments) as the final argument so that the # CGPerSignatureCall won't do any argument conversion of its own. @@ -4574,8 +4580,6 @@ class CGProxySpecialOperation(CGPerSignatureCall): self.cgRoot.prepend(instantiateJSToNativeConversionTemplate( template, templateValues, declType, argument.identifier.name)) self.cgRoot.prepend(CGGeneric("rooted!(in(cx) let value = desc.value);")) - elif operation.isGetter(): - self.cgRoot.prepend(CGGeneric("let mut found = false;")) def getArguments(self): def process(arg): @@ -4584,10 +4588,6 @@ class CGProxySpecialOperation(CGPerSignatureCall): argVal += ".r()" return argVal args = [(a, process(a)) for a in self.arguments] - if self.idlNode.isGetter(): - args.append((FakeArgument(BuiltinTypes[IDLBuiltinType.Types.boolean], - self.idlNode), - "&mut found")) return args def wrap_return_value(self): @@ -4595,7 +4595,7 @@ class CGProxySpecialOperation(CGPerSignatureCall): return "" wrap = CGGeneric(wrapForType(**self.templateValues)) - wrap = CGIfWrapper("found", wrap) + wrap = CGIfWrapper("let Some(result) = result", wrap) return "\n" + wrap.define() @@ -4971,7 +4971,7 @@ class CGDOMJSProxyHandler_hasOwn(CGAbstractExternMethod): " let this = UnwrapProxy(proxy);\n" + " let this = &*this;\n" + CGIndenter(CGProxyIndexedGetter(self.descriptor)).define() + "\n" + - " *bp = found;\n" + + " *bp = result.is_some();\n" + " return true;\n" + "}\n\n") else: @@ -4987,7 +4987,7 @@ if RUST_JSID_IS_STRING(id) { } if !has_on_proto { %s - *bp = found; + *bp = result.is_some(); return true; } } @@ -5271,7 +5271,9 @@ class CGInterfaceTrait(CGThing): infallible = 'infallible' in descriptor.getExtendedAttributes(operation) if operation.isGetter(): - arguments = method_arguments(descriptor, rettype, arguments, trailing=("found", "&mut bool")) + if not rettype.nullable(): + rettype = IDLNullableType(rettype.location, rettype) + arguments = method_arguments(descriptor, rettype, arguments) # If this interface 'supports named properties', then we # should be able to access 'supported property names' @@ -5323,6 +5325,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries enums = [] return CGImports(cgthings, descriptors, callbacks, dictionaries, enums, [ + 'core::nonzero::NonZero', 'js', 'js::JSCLASS_GLOBAL_SLOT_COUNT', 'js::JSCLASS_IS_DOMJSCLASS', diff --git a/components/script/dom/bindings/iterable.rs b/components/script/dom/bindings/iterable.rs index 20eb84bffde..a3092ed73b6 100644 --- a/components/script/dom/bindings/iterable.rs +++ b/components/script/dom/bindings/iterable.rs @@ -6,6 +6,7 @@ //! Implementation of `iterable<...>` and `iterable<..., ...>` WebIDL declarations. +use core::nonzero::NonZero; use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyAndValueResult; use dom::bindings::codegen::Bindings::IterableIteratorBinding::IterableKeyOrValueResult; use dom::bindings::error::Fallible; @@ -95,38 +96,41 @@ impl<T: Reflectable + JSTraceable + Iterable> IterableIterator<T> { /// Return the next value from the iterable object. #[allow(non_snake_case)] - pub fn Next(&self, cx: *mut JSContext) -> Fallible<*mut JSObject> { + pub fn Next(&self, cx: *mut JSContext) -> Fallible<NonZero<*mut JSObject>> { let index = self.index.get(); rooted!(in(cx) let mut value = UndefinedValue()); rooted!(in(cx) let mut rval = ptr::null_mut()); - if index >= self.iterable.get_iterable_length() { - return dict_return(cx, rval.handle_mut(), true, value.handle()) - .map(|_| rval.handle().get()); - } - let result = match self.type_ { - IteratorType::Keys => { - unsafe { - self.iterable.get_key_at_index(index).to_jsval(cx, value.handle_mut()); + let result = if index >= self.iterable.get_iterable_length() { + dict_return(cx, rval.handle_mut(), true, value.handle()) + } else { + match self.type_ { + IteratorType::Keys => { + unsafe { + self.iterable.get_key_at_index(index).to_jsval(cx, value.handle_mut()); + } + dict_return(cx, rval.handle_mut(), false, value.handle()) } - dict_return(cx, rval.handle_mut(), false, value.handle()) - } - IteratorType::Values => { - unsafe { - self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut()); + IteratorType::Values => { + unsafe { + self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut()); + } + dict_return(cx, rval.handle_mut(), false, value.handle()) } - dict_return(cx, rval.handle_mut(), false, value.handle()) - } - IteratorType::Entries => { - rooted!(in(cx) let mut key = UndefinedValue()); - unsafe { - self.iterable.get_key_at_index(index).to_jsval(cx, key.handle_mut()); - self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut()); + IteratorType::Entries => { + rooted!(in(cx) let mut key = UndefinedValue()); + unsafe { + self.iterable.get_key_at_index(index).to_jsval(cx, key.handle_mut()); + self.iterable.get_value_at_index(index).to_jsval(cx, value.handle_mut()); + } + key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle()) } - key_and_value_return(cx, rval.handle_mut(), key.handle(), value.handle()) } }; self.index.set(index + 1); - result.map(|_| rval.handle().get()) + result.map(|_| { + assert!(!rval.is_null()); + unsafe { NonZero::new(rval.get()) } + }) } } diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs index 439016ee15b..02d5c9c8bef 100644 --- a/components/script/dom/bindings/mod.rs +++ b/components/script/dom/bindings/mod.rs @@ -128,8 +128,9 @@ //! return `Err()` from the method with the appropriate [error value] //! (error/enum.Error.html). +pub use style::domrefcell as cell; + pub mod callback; -pub mod cell; pub mod conversions; pub mod error; pub mod global; diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index d6969f38d6c..507e19e4bcb 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -88,6 +88,7 @@ use std::sync::mpsc::{Receiver, Sender}; use std::time::SystemTime; use string_cache::{Atom, Namespace, QualName}; use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto}; +use style::domrefcell::DOMRefCell; use style::element_state::*; use style::properties::PropertyDeclarationBlock; use style::selector_impl::{PseudoElement, ElementSnapshot}; @@ -172,6 +173,13 @@ impl<T: JSTraceable> JSTraceable for UnsafeCell<T> { } } +impl<T: JSTraceable> JSTraceable for DOMRefCell<T> { + fn trace(&self, trc: *mut JSTracer) { + unsafe { + (*self).borrow_for_gc_trace().trace(trc) + } + } +} impl JSTraceable for Heap<*mut JSObject> { fn trace(&self, trc: *mut JSTracer) { diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 09d4a8f04e1..61cc2520165 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -5,7 +5,7 @@ use canvas_traits::{Canvas2dMsg, CanvasCommonMsg, CanvasMsg}; use canvas_traits::{CompositionOrBlending, FillOrStrokeStyle, FillRule}; use canvas_traits::{LineCapStyle, LineJoinStyle, LinearGradientStyle}; -use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap}; +use canvas_traits::{RadialGradientStyle, RepetitionStyle, byte_swap, byte_swap_and_premultiply}; use cssparser::Color as CSSColor; use cssparser::{Parser, RGBA}; use dom::bindings::cell::DOMRefCell; @@ -47,6 +47,7 @@ use std::str::FromStr; use std::{cmp, fmt}; use unpremultiplytable::UNPREMULTIPLY_TABLE; use url::Url; +use util::opts; #[must_root] #[derive(JSTraceable, Clone, HeapSizeOf)] @@ -299,7 +300,14 @@ impl CanvasRenderingContext2D { Some((mut data, size)) => { // Pixels come from cache in BGRA order and drawImage expects RGBA so we // have to swap the color values - byte_swap(&mut data); + if opts::get().use_webrender { + // Webrender doesn't pre-multiply alpha when decoding + // images, but canvas expects the images to be + // pre-multiplied alpha. + byte_swap_and_premultiply(&mut data); + } else { + byte_swap(&mut data); + } let size = Size2D::new(size.width as f64, size.height as f64); (data, size) }, @@ -1092,7 +1100,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D { dirtyY: Finite<f64>, dirtyWidth: Finite<f64>, dirtyHeight: Finite<f64>) { - let data = imagedata.get_data_array(&self.global().r()); + let data = imagedata.get_data_array(); let offset = Point2D::new(*dx, *dy); let image_data_size = Size2D::new(imagedata.Width() as f64, imagedata.Height() as f64); diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 01f11e3ac50..979e9a70434 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -19,7 +19,7 @@ use dom::element::Element; use dom::node::{Node, NodeDamage}; use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; -use std::cell::Ref; +use style::refcell::Ref; use util::opts; // https://dom.spec.whatwg.org/#characterdata diff --git a/components/script/dom/crypto.rs b/components/script/dom/crypto.rs index 6e0351d37ee..165a3834227 100644 --- a/components/script/dom/crypto.rs +++ b/components/script/dom/crypto.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 core::nonzero::NonZero; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CryptoBinding; use dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods; @@ -43,7 +44,8 @@ impl CryptoMethods for Crypto { fn GetRandomValues(&self, _cx: *mut JSContext, input: *mut JSObject) - -> Fallible<*mut JSObject> { + -> Fallible<NonZero<*mut JSObject>> { + assert!(!input.is_null()); let mut data = match unsafe { array_buffer_view_data::<u8>(input) } { Some(data) => data, None => { @@ -62,7 +64,7 @@ impl CryptoMethods for Crypto { self.rng.borrow_mut().fill_bytes(&mut data); - Ok(input) + Ok(unsafe { NonZero::new(input) }) } } diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 076a2283b67..c048446d813 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -14,12 +14,13 @@ use dom::element::Element; use dom::node::{Node, NodeDamage, window_from_node}; use dom::window::Window; use std::ascii::AsciiExt; -use std::cell::Ref; use std::slice; +use std::sync::Arc; use string_cache::Atom; use style::parser::ParserContextExtraData; use style::properties::{PropertyDeclaration, Shorthand, Importance}; use style::properties::{is_supported_property, parse_one_declaration, parse_style_attribute}; +use style::refcell::Ref; use style::selector_impl::PseudoElement; // http://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface @@ -100,18 +101,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item fn Item(&self, index: u32) -> DOMString { - let index = index as usize; - let elem = self.owner.upcast::<Element>(); - let style_attribute = elem.style_attribute().borrow(); - style_attribute.as_ref().and_then(|declarations| { - declarations.declarations.get(index) - }).map(|&(ref declaration, importance)| { - let mut css = declaration.to_css_string(); - if importance.important() { - css += " !important"; - } - DOMString::from(css) - }).unwrap_or_else(DOMString::new) + self.IndexedGetter(index).unwrap_or_default() } // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue @@ -333,10 +323,19 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { } // https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface - fn IndexedGetter(&self, index: u32, found: &mut bool) -> DOMString { - let rval = self.Item(index); - *found = index < self.Length(); - rval + fn IndexedGetter(&self, index: u32) -> Option<DOMString> { + let index = index as usize; + let elem = self.owner.upcast::<Element>(); + let style_attribute = elem.style_attribute().borrow(); + style_attribute.as_ref().and_then(|declarations| { + declarations.declarations.get(index) + }).map(|&(ref declaration, importance)| { + let mut css = declaration.to_css_string(); + if importance.important() { + css += " !important"; + } + DOMString::from(css) + }) } // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext @@ -367,7 +366,7 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { *element.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() { None // Step 2 } else { - Some(decl_block) + Some(Arc::new(decl_block)) }; element.sync_property_with_attrs_style(); let node = element.upcast::<Node>(); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index cbd4b2ac253..4322e348c92 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.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 core::nonzero::NonZero; use document_loader::{DocumentLoader, LoadType}; use dom::activation::{ActivationSource, synthetic_click_activation}; use dom::attr::Attr; @@ -110,18 +111,18 @@ use script_traits::{TouchEventType, TouchId}; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::boxed::FnBox; -use std::cell::{Cell, Ref, RefMut}; +use std::cell::Cell; use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::default::Default; use std::iter::once; use std::mem; -use std::ptr; use std::rc::Rc; use std::sync::Arc; use string_cache::{Atom, QualName}; use style::attr::AttrValue; use style::context::ReflowGoal; +use style::refcell::{Ref, RefMut}; use style::selector_impl::ElementSnapshot; use style::str::{split_html_space_chars, str_join}; use style::stylesheets::Stylesheet; @@ -221,6 +222,9 @@ pub struct Document { /// For each element that has had a state or attribute change since the last restyle, /// track the original condition of the element. modified_elements: DOMRefCell<HashMap<JS<Element>, ElementSnapshot>>, + /// This flag will be true if layout suppressed a reflow attempt that was + /// needed in order for the page to be painted. + needs_paint: Cell<bool>, /// http://w3c.github.io/touch-events/#dfn-active-touch-point active_touch_points: DOMRefCell<Vec<JS<Touch>>>, /// Navigation Timing properties: @@ -376,6 +380,10 @@ impl Document { } } + pub fn needs_paint(&self) -> bool { + self.needs_paint.get() + } + pub fn needs_reflow(&self) -> bool { // FIXME: This should check the dirty bit on the document, // not the document element. Needs some layout changes to make @@ -384,7 +392,8 @@ impl Document { Some(root) => { root.upcast::<Node>().is_dirty() || root.upcast::<Node>().has_dirty_descendants() || - !self.modified_elements.borrow().is_empty() + !self.modified_elements.borrow().is_empty() || + self.needs_paint() } None => false, } @@ -1602,6 +1611,8 @@ pub enum DocumentSource { pub trait LayoutDocumentHelpers { unsafe fn is_html_document_for_layout(&self) -> bool; unsafe fn drain_modified_elements(&self) -> Vec<(LayoutJS<Element>, ElementSnapshot)>; + unsafe fn needs_paint_from_layout(&self); + unsafe fn will_paint(&self); } #[allow(unsafe_code)] @@ -1618,6 +1629,16 @@ impl LayoutDocumentHelpers for LayoutJS<Document> { let result = elements.drain().map(|(k, v)| (k.to_layout(), v)).collect(); result } + + #[inline] + unsafe fn needs_paint_from_layout(&self) { + (*self.unsafe_get()).needs_paint.set(true) + } + + #[inline] + unsafe fn will_paint(&self) { + (*self.unsafe_get()).needs_paint.set(false) + } } /// https://url.spec.whatwg.org/#network-scheme @@ -1723,6 +1744,7 @@ impl Document { base_element: Default::default(), appropriate_template_contents_owner_document: Default::default(), modified_elements: DOMRefCell::new(HashMap::new()), + needs_paint: Cell::new(false), active_touch_points: DOMRefCell::new(Vec::new()), dom_loading: Cell::new(Default::default()), dom_interactive: Cell::new(Default::default()), @@ -2689,8 +2711,9 @@ impl DocumentMethods for Document { self.set_body_attribute(&atom!("text"), value) } + #[allow(unsafe_code)] // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter - fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool) -> *mut JSObject { + fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString) -> Option<NonZero<*mut JSObject>> { #[derive(JSTraceable, HeapSizeOf)] struct NamedElementFilter { name: Atom, @@ -2756,23 +2779,24 @@ impl DocumentMethods for Document { .peekable(); if let Some(first) = elements.next() { if elements.peek().is_none() { - *found = true; // TODO: Step 2. // Step 3. - return first.reflector().get_jsobject().get(); + return unsafe { + Some(NonZero::new(first.reflector().get_jsobject().get())) + }; } } else { - *found = false; - return ptr::null_mut(); + return None; } } // Step 4. - *found = true; let filter = NamedElementFilter { name: name, }; let collection = HTMLCollection::create(self.window(), root, box filter); - collection.reflector().get_jsobject().get() + unsafe { + Some(NonZero::new(collection.reflector().get_jsobject().get())) + } } // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:supported-property-names diff --git a/components/script/dom/domrectlist.rs b/components/script/dom/domrectlist.rs index adb246158f4..86774a49ff3 100644 --- a/components/script/dom/domrectlist.rs +++ b/components/script/dom/domrectlist.rs @@ -52,8 +52,7 @@ impl DOMRectListMethods for DOMRectList { } // check-tidy: no specs after this line - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<DOMRect>> { - *found = index < self.rects.len() as u32; + fn IndexedGetter(&self, index: u32) -> Option<Root<DOMRect>> { self.Item(index) } } diff --git a/components/script/dom/domstringmap.rs b/components/script/dom/domstringmap.rs index c5e534d242e..11479d6b5df 100644 --- a/components/script/dom/domstringmap.rs +++ b/components/script/dom/domstringmap.rs @@ -47,10 +47,8 @@ impl DOMStringMapMethods for DOMStringMap { } // https://html.spec.whatwg.org/multipage/#dom-domstringmap-nameditem - fn NamedGetter(&self, name: DOMString, found: &mut bool) -> DOMString { - let attr = self.element.get_custom_attr(name); - *found = attr.is_some(); - attr.unwrap_or_default() + fn NamedGetter(&self, name: DOMString) -> Option<DOMString> { + self.element.get_custom_attr(name) } // https://html.spec.whatwg.org/multipage/#the-domstringmap-interface:supported-property-names diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index 364b6366282..c1c09de94c2 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -171,9 +171,7 @@ impl DOMTokenListMethods for DOMTokenList { } // check-tidy: no specs after this line - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<DOMString> { - let item = self.Item(index); - *found = item.is_some(); - item + fn IndexedGetter(&self, index: u32) -> Option<DOMString> { + self.Item(index) } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 2d57ddab4d6..193fb16b937 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -70,13 +70,12 @@ use html5ever::serialize::SerializeOpts; use html5ever::serialize::TraversalScope; use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode}; use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks}; -use ref_filter_map::ref_filter_map; -use selectors::matching::{ElementFlags, matches}; +use selectors::matching::{ElementFlags, MatchingReason, matches}; use selectors::matching::{HAS_SLOW_SELECTOR, HAS_EDGE_CHILD_SELECTOR, HAS_SLOW_SELECTOR_LATER_SIBLINGS}; use selectors::parser::{AttrSelector, NamespaceConstraint, parse_author_origin_selector_list_from_str}; use std::ascii::AsciiExt; use std::borrow::Cow; -use std::cell::{Cell, Ref}; +use std::cell::Cell; use std::convert::TryFrom; use std::default::Default; use std::fmt; @@ -90,6 +89,7 @@ use style::parser::ParserContextExtraData; use style::properties::longhands::{self, background_image, border_spacing, font_family, overflow_x, font_size}; use style::properties::{DeclaredValue, Importance}; use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute}; +use style::refcell::Ref; use style::selector_impl::{NonTSPseudoClass, ServoSelectorImpl}; use style::selector_matching::DeclarationBlock; use style::sink::Push; @@ -109,7 +109,7 @@ pub struct Element { prefix: Option<DOMString>, attrs: DOMRefCell<Vec<JS<Attr>>>, id_attribute: DOMRefCell<Option<Atom>>, - style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>, + style_attribute: DOMRefCell<Option<Arc<PropertyDeclarationBlock>>>, attr_list: MutNullableHeap<JS<NamedNodeMap>>, class_list: MutNullableHeap<JS<DOMTokenList>>, state: Cell<ElementState>, @@ -297,7 +297,7 @@ pub trait LayoutElementHelpers { #[allow(unsafe_code)] unsafe fn html_element_in_html_document_for_layout(&self) -> bool; fn id_attribute(&self) -> *const Option<Atom>; - fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock>; + fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>>; fn local_name(&self) -> &Atom; fn namespace(&self) -> &Namespace; fn get_checked_state_for_layout(&self) -> bool; @@ -329,7 +329,10 @@ impl LayoutElementHelpers for LayoutJS<Element> { #[inline] fn from_declaration(rule: PropertyDeclaration) -> DeclarationBlock { DeclarationBlock::from_declarations( - Arc::new(vec![(rule, Importance::Normal)]), + Arc::new(PropertyDeclarationBlock { + declarations: vec![(rule, Importance::Normal)], + important_count: 0, + }), Importance::Normal) } @@ -615,7 +618,7 @@ impl LayoutElementHelpers for LayoutJS<Element> { } #[allow(unsafe_code)] - fn style_attribute(&self) -> *const Option<PropertyDeclarationBlock> { + fn style_attribute(&self) -> *const Option<Arc<PropertyDeclarationBlock>> { unsafe { (*self.unsafe_get()).style_attribute.borrow_for_layout() } @@ -704,7 +707,7 @@ impl Element { self.attrs.borrow() } - pub fn style_attribute(&self) -> &DOMRefCell<Option<PropertyDeclarationBlock>> { + pub fn style_attribute(&self) -> &DOMRefCell<Option<Arc<PropertyDeclarationBlock>>> { &self.style_attribute } @@ -774,7 +777,8 @@ impl Element { matching }); if let Some(index) = index { - Arc::make_mut(&mut declarations.declarations).remove(index); + let declarations = Arc::make_mut(declarations); + declarations.declarations.remove(index); if importance.unwrap().important() { declarations.important_count -= 1; } @@ -796,7 +800,8 @@ impl Element { { // Usually, the reference count will be 1 here. But transitions could make it greater // than that. - let existing_declarations = Arc::make_mut(&mut declaration_block.declarations); + let declaration_block = Arc::make_mut(declaration_block); + let existing_declarations = &mut declaration_block.declarations; 'outer: for incoming_declaration in declarations { for existing_declaration in &mut *existing_declarations { @@ -829,10 +834,10 @@ impl Element { 0 }; - *inline_declarations = Some(PropertyDeclarationBlock { - declarations: Arc::new(declarations.into_iter().map(|d| (d, importance)).collect()), + *inline_declarations = Some(Arc::new(PropertyDeclarationBlock { + declarations: declarations.into_iter().map(|d| (d, importance)).collect(), important_count: important_count, - }); + })); } update(self, declarations, importance); @@ -847,7 +852,8 @@ impl Element { if let &mut Some(ref mut block) = &mut *inline_declarations { // Usually, the reference counts of `from` and `to` will be 1 here. But transitions // could make them greater than that. - let declarations = Arc::make_mut(&mut block.declarations); + let block = Arc::make_mut(block); + let declarations = &mut block.declarations; for &mut (ref declaration, ref mut importance) in declarations { if properties.iter().any(|p| declaration.name() == **p) { match (*importance, new_importance) { @@ -871,7 +877,7 @@ impl Element { pub fn get_inline_style_declaration(&self, property: &Atom) -> Option<Ref<(PropertyDeclaration, Importance)>> { - ref_filter_map(self.style_attribute.borrow(), |inline_declarations| { + Ref::filter_map(self.style_attribute.borrow(), |inline_declarations| { inline_declarations.as_ref().and_then(|declarations| { declarations.declarations .iter() @@ -2000,7 +2006,7 @@ impl ElementMethods for Element { match parse_author_origin_selector_list_from_str(&selectors) { Err(()) => Err(Error::Syntax), Ok(ref selectors) => { - Ok(matches(selectors, &Root::from_ref(self), None)) + Ok(matches(selectors, &Root::from_ref(self), None, MatchingReason::Other)) } } } @@ -2018,7 +2024,7 @@ impl ElementMethods for Element { let root = self.upcast::<Node>(); for element in root.inclusive_ancestors() { if let Some(element) = Root::downcast::<Element>(element) { - if matches(selectors, &element, None) { + if matches(selectors, &element, None, MatchingReason::Other) { return Ok(Some(element)); } } @@ -2102,8 +2108,11 @@ impl VirtualMethods for Element { *self.style_attribute.borrow_mut() = mutation.new_value(attr).map(|value| { let win = window_from_node(self); - parse_style_attribute(&value, &doc.base_url(), win.css_error_reporter(), - ParserContextExtraData::default()) + Arc::new(parse_style_attribute( + &value, + &doc.base_url(), + win.css_error_reporter(), + ParserContextExtraData::default())) }); if node.is_in_doc() { node.dirty(NodeDamage::NodeStyleDamaged); diff --git a/components/script/dom/filelist.rs b/components/script/dom/filelist.rs index 4f8e976f5f7..8adbe1ed467 100644 --- a/components/script/dom/filelist.rs +++ b/components/script/dom/filelist.rs @@ -55,9 +55,7 @@ impl FileListMethods for FileList { } // check-tidy: no specs after this line - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<File>> { - let item = self.Item(index); - *found = item.is_some(); - item + fn IndexedGetter(&self, index: u32) -> Option<Root<File>> { + self.Item(index) } } diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 45c1916f928..73b51962fe4 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -273,11 +273,10 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement { // Step 3. let raw_data = match *self.context.borrow() { Some(CanvasContext::Context2d(ref context)) => { - let window = window_from_node(self); let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64), Finite::wrap(self.Width() as f64), Finite::wrap(self.Height() as f64))); - image_data.get_data_array(&GlobalRef::Window(window.r())) + image_data.get_data_array() } None => { // Each pixel is fully-transparent black. diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs index 95134556bc0..2f226590719 100644 --- a/components/script/dom/htmlcollection.rs +++ b/components/script/dom/htmlcollection.rs @@ -317,17 +317,13 @@ impl HTMLCollectionMethods for HTMLCollection { } // https://dom.spec.whatwg.org/#dom-htmlcollection-item - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> { - let maybe_elem = self.Item(index); - *found = maybe_elem.is_some(); - maybe_elem + fn IndexedGetter(&self, index: u32) -> Option<Root<Element>> { + self.Item(index) } // check-tidy: no specs after this line - fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<Root<Element>> { - let maybe_elem = self.NamedItem(name); - *found = maybe_elem.is_some(); - maybe_elem + fn NamedGetter(&self, name: DOMString) -> Option<Root<Element>> { + self.NamedItem(name) } // https://dom.spec.whatwg.org/#interface-htmlcollection diff --git a/components/script/dom/htmlformcontrolscollection.rs b/components/script/dom/htmlformcontrolscollection.rs index 9229b854b26..e52a541225f 100644 --- a/components/script/dom/htmlformcontrolscollection.rs +++ b/components/script/dom/htmlformcontrolscollection.rs @@ -77,10 +77,8 @@ impl HTMLFormControlsCollectionMethods for HTMLFormControlsCollection { } // https://html.spec.whatwg.org/multipage/#dom-htmlformcontrolscollection-nameditem - fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<RadioNodeListOrElement> { - let maybe_elem = self.NamedItem(name); - *found = maybe_elem.is_some(); - maybe_elem + fn NamedGetter(&self, name: DOMString) -> Option<RadioNodeListOrElement> { + self.NamedItem(name) } // https://html.spec.whatwg.org/multipage/#the-htmlformcontrolscollection-interface:supported-property-names @@ -93,7 +91,7 @@ impl HTMLFormControlsCollectionMethods for HTMLFormControlsCollection { // https://github.com/servo/servo/issues/5875 // // https://dom.spec.whatwg.org/#dom-htmlcollection-item - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> { - self.collection.IndexedGetter(index, found) + fn IndexedGetter(&self, index: u32) -> Option<Root<Element>> { + self.collection.IndexedGetter(index) } } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index db9e3cb8d41..fa16618b564 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -230,9 +230,9 @@ impl HTMLFormElementMethods for HTMLFormElement { } // https://html.spec.whatwg.org/multipage/#dom-form-item - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Element>> { + fn IndexedGetter(&self, index: u32) -> Option<Root<Element>> { let elements = self.Elements(); - elements.IndexedGetter(index, found) + elements.IndexedGetter(index) } } diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index b8c2cd423fa..e6f86f41d86 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -79,7 +79,7 @@ impl HTMLMetaElement { if !content.is_empty() { if let Some(translated_rule) = ViewportRule::from_meta(&**content) { *self.stylesheet.borrow_mut() = Some(Arc::new(Stylesheet { - rules: vec![CSSRule::Viewport(translated_rule)], + rules: vec![CSSRule::Viewport(Arc::new(translated_rule))], origin: Origin::Author, media: None, // Viewport constraints are always recomputed on resize; they don't need to diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs index 737bc67bd4c..9183a78de0c 100644 --- a/components/script/dom/htmloptionelement.rs +++ b/components/script/dom/htmloptionelement.rs @@ -6,6 +6,7 @@ use dom::attr::Attr; use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::Bindings::HTMLOptionElementBinding; use dom::bindings::codegen::Bindings::HTMLOptionElementBinding::HTMLOptionElementMethods; +use dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementBinding::HTMLSelectElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; @@ -14,6 +15,8 @@ use dom::characterdata::CharacterData; use dom::document::Document; use dom::element::{AttributeMutation, Element}; use dom::htmlelement::HTMLElement; +use dom::htmlformelement::HTMLFormElement; +use dom::htmloptgroupelement::HTMLOptGroupElement; use dom::htmlscriptelement::HTMLScriptElement; use dom::htmlselectelement::HTMLSelectElement; use dom::node::{Node, UnbindContext}; @@ -110,6 +113,19 @@ impl HTMLOptionElementMethods for HTMLOptionElement { self.upcast::<Node>().SetTextContent(Some(value)) } + // https://html.spec.whatwg.org/multipage/#dom-option-form + fn GetForm(&self) -> Option<Root<HTMLFormElement>> { + let parent = self.upcast::<Node>().GetParentNode().and_then(|p| + if p.is::<HTMLOptGroupElement>() { + p.upcast::<Node>().GetParentNode() + } else { + Some(p) + } + ); + + parent.and_then(|p| p.downcast::<HTMLSelectElement>().and_then(|s| s.GetForm())) + } + // https://html.spec.whatwg.org/multipage/#attr-option-value fn Value(&self) -> DOMString { let element = self.upcast::<Element>(); diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs index abcb9b5640b..0959a52eb32 100644 --- a/components/script/dom/imagedata.rs +++ b/components/script/dom/imagedata.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 core::nonzero::NonZero; use dom::bindings::codegen::Bindings::ImageDataBinding; use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; use dom::bindings::global::GlobalRef; @@ -37,6 +38,7 @@ impl ImageData { unsafe { let cx = global.get_cx(); let js_object: *mut JSObject = JS_NewUint8ClampedArray(cx, width * height * 4); + assert!(!js_object.is_null()); if let Some(vec) = data { let mut is_shared = false; @@ -52,12 +54,13 @@ impl ImageData { } #[allow(unsafe_code)] - pub fn get_data_array(&self, global: &GlobalRef) -> Vec<u8> { + pub fn get_data_array(&self) -> Vec<u8> { unsafe { - let cx = global.get_cx(); let mut is_shared = false; + assert!(!self.data.get().is_null()); let data: *const uint8_t = - JS_GetUint8ClampedArrayData(self.Data(cx), &mut is_shared, ptr::null()) as *const uint8_t; + JS_GetUint8ClampedArrayData(self.data.get(), &mut is_shared, ptr::null()) as *const uint8_t; + assert!(!data.is_null()); assert!(!is_shared); let len = self.Width() * self.Height() * 4; slice::from_raw_parts(data, len as usize).to_vec() @@ -80,8 +83,10 @@ impl ImageDataMethods for ImageData { self.height } + #[allow(unsafe_code)] // https://html.spec.whatwg.org/multipage/#dom-imagedata-data - fn Data(&self, _: *mut JSContext) -> *mut JSObject { - self.data.get() + fn Data(&self, _: *mut JSContext) -> NonZero<*mut JSObject> { + assert!(!self.data.get().is_null()); + unsafe { NonZero::new(self.data.get()) } } } diff --git a/components/script/dom/mimetypearray.rs b/components/script/dom/mimetypearray.rs index 96fc48c86d0..de820f6d06a 100644 --- a/components/script/dom/mimetypearray.rs +++ b/components/script/dom/mimetypearray.rs @@ -46,12 +46,12 @@ impl MimeTypeArrayMethods for MimeTypeArray { } // https://html.spec.whatwg.org/multipage/#dom-mimetypearray-item - fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<MimeType>> { + fn IndexedGetter(&self, _index: u32) -> Option<Root<MimeType>> { None } // check-tidy: no specs after this line - fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<MimeType>> { + fn NamedGetter(&self, _name: DOMString) -> Option<Root<MimeType>> { None } diff --git a/components/script/dom/namednodemap.rs b/components/script/dom/namednodemap.rs index 10b6b8982ae..9edc1b1e93b 100644 --- a/components/script/dom/namednodemap.rs +++ b/components/script/dom/namednodemap.rs @@ -85,17 +85,13 @@ impl NamedNodeMapMethods for NamedNodeMap { } // https://dom.spec.whatwg.org/#dom-namednodemap-item - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Attr>> { - let item = self.Item(index); - *found = item.is_some(); - item + fn IndexedGetter(&self, index: u32) -> Option<Root<Attr>> { + self.Item(index) } // check-tidy: no specs after this line - fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<Root<Attr>> { - let item = self.GetNamedItem(name); - *found = item.is_some(); - item + fn NamedGetter(&self, name: DOMString) -> Option<Root<Attr>> { + self.GetNamedItem(name) } // https://heycam.github.io/webidl/#dfn-supported-property-names diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index 75bd2c13c23..61936c59e5f 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -107,4 +107,10 @@ impl NavigatorMethods for Navigator { fn ServiceWorker(&self) -> Root<ServiceWorkerContainer> { self.serviceWorker.or_init(|| ServiceWorkerContainer::new(self.global().r())) } + + // https://html.spec.whatwg.org/multipage/#dom-navigator-cookieenabled + fn CookieEnabled(&self) -> bool { + true + } + } diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 49aa8242b34..555c7719fb1 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -63,7 +63,7 @@ use script_layout_interface::message::Msg; use script_layout_interface::{HTMLCanvasData, OpaqueStyleAndLayoutData}; use script_layout_interface::{LayoutNodeType, LayoutElementType, TrustedNodeAddress}; use script_traits::UntrustedNodeAddress; -use selectors::matching::matches; +use selectors::matching::{MatchingReason, matches}; use selectors::parser::Selector; use selectors::parser::parse_author_origin_selector_list_from_str; use std::borrow::ToOwned; @@ -319,7 +319,7 @@ impl<'a> Iterator for QuerySelectorIterator { // (instead of passing `None`)? Probably. self.iterator.by_ref().filter_map(|node| { if let Some(element) = Root::downcast(node) { - if matches(selectors, &element, None) { + if matches(selectors, &element, None, MatchingReason::Other) { return Some(Root::upcast(element)); } } @@ -711,7 +711,7 @@ impl Node { // Step 3. Ok(ref selectors) => { Ok(self.traverse_preorder().filter_map(Root::downcast).find(|element| { - matches(selectors, element, None) + matches(selectors, element, None, MatchingReason::Other) })) } } diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index 2503378187e..8f8a5515592 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -75,10 +75,8 @@ impl NodeListMethods for NodeList { } // https://dom.spec.whatwg.org/#dom-nodelist-item - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Node>> { - let item = self.Item(index); - *found = item.is_some(); - item + fn IndexedGetter(&self, index: u32) -> Option<Root<Node>> { + self.Item(index) } } diff --git a/components/script/dom/plugin.rs b/components/script/dom/plugin.rs index dc4ca4fe42d..222e9a2840a 100644 --- a/components/script/dom/plugin.rs +++ b/components/script/dom/plugin.rs @@ -45,12 +45,12 @@ impl PluginMethods for Plugin { } // https://html.spec.whatwg.org/multipage/#dom-plugin-item - fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<MimeType>> { + fn IndexedGetter(&self, _index: u32) -> Option<Root<MimeType>> { unreachable!() } // check-tidy: no specs after this line - fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<MimeType>> { + fn NamedGetter(&self, _name: DOMString) -> Option<Root<MimeType>> { unreachable!() } diff --git a/components/script/dom/pluginarray.rs b/components/script/dom/pluginarray.rs index aabba4928a4..aa6b779280d 100644 --- a/components/script/dom/pluginarray.rs +++ b/components/script/dom/pluginarray.rs @@ -50,12 +50,12 @@ impl PluginArrayMethods for PluginArray { } // https://html.spec.whatwg.org/multipage/#dom-pluginarray-item - fn IndexedGetter(&self, _index: u32, _found: &mut bool) -> Option<Root<Plugin>> { + fn IndexedGetter(&self, _index: u32) -> Option<Root<Plugin>> { None } // check-tidy: no specs after this line - fn NamedGetter(&self, _name: DOMString, _found: &mut bool) -> Option<Root<Plugin>> { + fn NamedGetter(&self, _name: DOMString) -> Option<Root<Plugin>> { None } diff --git a/components/script/dom/radionodelist.rs b/components/script/dom/radionodelist.rs index d88fc69eacd..9bbdae00c85 100644 --- a/components/script/dom/radionodelist.rs +++ b/components/script/dom/radionodelist.rs @@ -105,7 +105,7 @@ impl RadioNodeListMethods for RadioNodeList { // https://github.com/servo/servo/issues/5875 // // https://dom.spec.whatwg.org/#dom-nodelist-item - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Node>> { - self.node_list.IndexedGetter(index, found) + fn IndexedGetter(&self, index: u32) -> Option<Root<Node>> { + self.node_list.IndexedGetter(index) } } diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index d6d1e1968f8..7827cdb6b15 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -136,10 +136,8 @@ impl StorageMethods for Storage { } // check-tidy: no specs after this line - fn NamedGetter(&self, name: DOMString, found: &mut bool) -> Option<DOMString> { - let item = self.GetItem(name); - *found = item.is_some(); - item + fn NamedGetter(&self, name: DOMString) -> Option<DOMString> { + self.GetItem(name) } fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult { diff --git a/components/script/dom/stylesheetlist.rs b/components/script/dom/stylesheetlist.rs index 1b7eb643e50..721ac06525c 100644 --- a/components/script/dom/stylesheetlist.rs +++ b/components/script/dom/stylesheetlist.rs @@ -46,9 +46,7 @@ impl StyleSheetListMethods for StyleSheetList { } // check-tidy: no specs after this line - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<StyleSheet>>{ - let item = self.Item(index); - *found = item.is_some(); - item + fn IndexedGetter(&self, index: u32) -> Option<Root<StyleSheet>> { + self.Item(index) } } diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index 9143c8b0188..21439c0b19a 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -4,6 +4,7 @@ // check-tidy: no specs after this line +use core::nonzero::NonZero; use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; use dom::bindings::codegen::Bindings::FunctionBinding::Function; use dom::bindings::codegen::Bindings::TestBindingBinding; @@ -26,6 +27,7 @@ use dom::bindings::weakref::MutableWeakRef; use dom::blob::{Blob, BlobImpl}; use dom::url::URL; use js::jsapi::{HandleObject, HandleValue, JSContext, JSObject}; +use js::jsapi::{JS_NewPlainObject, JS_NewUint8ClampedArray}; use js::jsval::{JSVal, NullValue}; use std::borrow::ToOwned; use std::ptr; @@ -137,10 +139,24 @@ impl TestBindingMethods for TestBinding { ByteStringOrLong::ByteString(ByteString::new(vec!())) } fn SetUnion9Attribute(&self, _: ByteStringOrLong) {} - fn ArrayAttribute(&self, _: *mut JSContext) -> *mut JSObject { NullValue().to_object_or_null() } + #[allow(unsafe_code)] + fn ArrayAttribute(&self, cx: *mut JSContext) -> NonZero<*mut JSObject> { + unsafe { + rooted!(in(cx) let array = JS_NewUint8ClampedArray(cx, 16)); + assert!(!array.is_null()); + NonZero::new(array.get()) + } + } fn AnyAttribute(&self, _: *mut JSContext) -> JSVal { NullValue() } fn SetAnyAttribute(&self, _: *mut JSContext, _: HandleValue) {} - fn ObjectAttribute(&self, _: *mut JSContext) -> *mut JSObject { panic!() } + #[allow(unsafe_code)] + fn ObjectAttribute(&self, cx: *mut JSContext) -> NonZero<*mut JSObject> { + unsafe { + rooted!(in(cx) let obj = JS_NewPlainObject(cx)); + assert!(!obj.is_null()); + NonZero::new(obj.get()) + } + } fn SetObjectAttribute(&self, _: *mut JSContext, _: *mut JSObject) {} fn GetBooleanAttributeNullable(&self) -> Option<bool> { Some(false) } @@ -193,7 +209,7 @@ impl TestBindingMethods for TestBinding { fn SetInterfaceAttributeWeak(&self, url: Option<&URL>) { self.url.set(url); } - fn GetObjectAttributeNullable(&self, _: *mut JSContext) -> *mut JSObject { ptr::null_mut() } + fn GetObjectAttributeNullable(&self, _: *mut JSContext) -> Option<NonZero<*mut JSObject>> { None } fn SetObjectAttributeNullable(&self, _: *mut JSContext, _: *mut JSObject) {} fn GetUnionAttributeNullable(&self) -> Option<HTMLElementOrLong> { Some(HTMLElementOrLong::Long(0)) @@ -242,7 +258,9 @@ impl TestBindingMethods for TestBinding { Blob::new(self.global().r(), BlobImpl::new_from_bytes(vec![]), "".to_owned()) } fn ReceiveAny(&self, _: *mut JSContext) -> JSVal { NullValue() } - fn ReceiveObject(&self, _: *mut JSContext) -> *mut JSObject { panic!() } + fn ReceiveObject(&self, cx: *mut JSContext) -> NonZero<*mut JSObject> { + self.ObjectAttribute(cx) + } fn ReceiveUnion(&self) -> HTMLElementOrLong { HTMLElementOrLong::Long(0) } fn ReceiveUnion2(&self) -> EventOrString { EventOrString::String(DOMString::new()) } fn ReceiveUnion3(&self) -> StringOrLongSequence { StringOrLongSequence::LongSequence(vec![]) } @@ -283,7 +301,9 @@ impl TestBindingMethods for TestBinding { fn ReceiveNullableInterface(&self) -> Option<Root<Blob>> { Some(Blob::new(self.global().r(), BlobImpl::new_from_bytes(vec![]), "".to_owned())) } - fn ReceiveNullableObject(&self, _: *mut JSContext) -> *mut JSObject { ptr::null_mut() } + fn ReceiveNullableObject(&self, cx: *mut JSContext) -> Option<NonZero<*mut JSObject>> { + self.GetObjectAttributeNullable(cx) + } fn ReceiveNullableUnion(&self) -> Option<HTMLElementOrLong> { Some(HTMLElementOrLong::Long(0)) } diff --git a/components/script/dom/testbindingiterable.rs b/components/script/dom/testbindingiterable.rs index 1e462a98531..2ad0df6dbb6 100644 --- a/components/script/dom/testbindingiterable.rs +++ b/components/script/dom/testbindingiterable.rs @@ -34,10 +34,8 @@ impl TestBindingIterable { impl TestBindingIterableMethods for TestBindingIterable { fn Add(&self, v: DOMString) { self.vals.borrow_mut().push(v); } fn Length(&self) -> u32 { self.vals.borrow().len() as u32 } - fn GetItem(&self, n: u32) -> DOMString { self.vals.borrow().get(n as usize).unwrap().clone() } - fn IndexedGetter(&self, n: u32, found: &mut bool) -> DOMString { - let s = self.GetItem(n); - *found = true; - s + fn GetItem(&self, n: u32) -> DOMString { self.IndexedGetter(n).unwrap_or_default() } + fn IndexedGetter(&self, n: u32) -> Option<DOMString> { + self.vals.borrow().get(n as usize).cloned() } } diff --git a/components/script/dom/testbindingproxy.rs b/components/script/dom/testbindingproxy.rs index 3308639305c..45e66bc5919 100644 --- a/components/script/dom/testbindingproxy.rs +++ b/components/script/dom/testbindingproxy.rs @@ -23,10 +23,10 @@ impl TestBindingProxyMethods for TestBindingProxy { fn SetItem(&self, _: u32, _: DOMString) -> () {} fn RemoveItem(&self, _: DOMString) -> () {} fn Stringifier(&self) -> DOMString { DOMString::new() } - fn IndexedGetter(&self, _: u32, _: &mut bool) -> DOMString { DOMString::new() } + fn IndexedGetter(&self, _: u32) -> Option<DOMString> { None } fn NamedDeleter(&self, _: DOMString) -> () {} fn IndexedSetter(&self, _: u32, _: DOMString) -> () {} fn NamedSetter(&self, _: DOMString, _: DOMString) -> () {} - fn NamedGetter(&self, _: DOMString, _: &mut bool) -> DOMString { DOMString::new() } + fn NamedGetter(&self, _: DOMString) -> Option<DOMString> { None } } diff --git a/components/script/dom/textencoder.rs b/components/script/dom/textencoder.rs index 84100e723ba..674243dded8 100644 --- a/components/script/dom/textencoder.rs +++ b/components/script/dom/textencoder.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 core::nonzero::NonZero; use dom::bindings::codegen::Bindings::TextEncoderBinding; use dom::bindings::codegen::Bindings::TextEncoderBinding::TextEncoderMethods; use dom::bindings::error::{Error, Fallible}; @@ -70,16 +71,17 @@ impl TextEncoderMethods for TextEncoder { #[allow(unsafe_code)] // https://encoding.spec.whatwg.org/#dom-textencoder-encode - fn Encode(&self, cx: *mut JSContext, input: USVString) -> *mut JSObject { + fn Encode(&self, cx: *mut JSContext, input: USVString) -> NonZero<*mut JSObject> { unsafe { let encoded = self.encoder.encode(&input.0, EncoderTrap::Strict).unwrap(); let length = encoded.len() as u32; - let js_object: *mut JSObject = JS_NewUint8Array(cx, length); + rooted!(in(cx) let js_object = JS_NewUint8Array(cx, length)); + assert!(!js_object.is_null()); let mut is_shared = false; - let js_object_data: *mut uint8_t = JS_GetUint8ArrayData(js_object, &mut is_shared, ptr::null()); + let js_object_data: *mut uint8_t = JS_GetUint8ArrayData(js_object.get(), &mut is_shared, ptr::null()); assert!(!is_shared); ptr::copy_nonoverlapping(encoded.as_ptr(), js_object_data, length as usize); - js_object + NonZero::new(js_object.get()) } } } diff --git a/components/script/dom/touchlist.rs b/components/script/dom/touchlist.rs index ae5313e855e..14bb8a68766 100644 --- a/components/script/dom/touchlist.rs +++ b/components/script/dom/touchlist.rs @@ -42,9 +42,7 @@ impl TouchListMethods for TouchList { } /// https://w3c.github.io/touch-events/#widl-TouchList-item-getter-Touch-unsigned-long-index - fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<Root<Touch>> { - let item = self.Item(index); - *found = item.is_some(); - item + fn IndexedGetter(&self, index: u32) -> Option<Root<Touch>> { + self.Item(index) } } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 5ff793527ec..aadf03d4211 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use canvas_traits::{CanvasCommonMsg, CanvasMsg, byte_swap}; +use core::nonzero::NonZero; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes}; @@ -305,8 +306,7 @@ impl WebGLRenderingContext { // complexity is worth it. let (pixels, size) = match source { ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::ImageData(image_data) => { - let global = self.global(); - (image_data.get_data_array(&global.r()), image_data.get_size()) + (image_data.get_data_array(), image_data.get_size()) }, ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLImageElement(image) => { let img_url = match image.get_url() { @@ -632,8 +632,9 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.14 - fn GetExtension(&self, _cx: *mut JSContext, _name: DOMString) -> *mut JSObject { - 0 as *mut JSObject + fn GetExtension(&self, _cx: *mut JSContext, _name: DOMString) + -> Option<NonZero<*mut JSObject>> { + None } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 diff --git a/components/script/dom/webidls/HTMLOptionElement.webidl b/components/script/dom/webidls/HTMLOptionElement.webidl index a5c7c3295da..d4bc5bcdc83 100644 --- a/components/script/dom/webidls/HTMLOptionElement.webidl +++ b/components/script/dom/webidls/HTMLOptionElement.webidl @@ -9,7 +9,7 @@ [Exposed=(Window,Worker)] interface HTMLOptionElement : HTMLElement { attribute boolean disabled; - //readonly attribute HTMLFormElement? form; + readonly attribute HTMLFormElement? form; attribute DOMString label; attribute boolean defaultSelected; attribute boolean selected; diff --git a/components/script/dom/webidls/Navigator.webidl b/components/script/dom/webidls/Navigator.webidl index 493c4ba34e4..ba24348b7f8 100644 --- a/components/script/dom/webidls/Navigator.webidl +++ b/components/script/dom/webidls/Navigator.webidl @@ -14,6 +14,7 @@ Navigator implements NavigatorLanguage; //Navigator implements NavigatorContentUtils; //Navigator implements NavigatorStorageUtils; Navigator implements NavigatorPlugins; +Navigator implements NavigatorCookies; // https://html.spec.whatwg.org/multipage/#navigatorid [NoInterfaceObject, Exposed=(Window,Worker)] @@ -52,3 +53,9 @@ interface NavigatorPlugins { [SameObject] readonly attribute MimeTypeArray mimeTypes; boolean javaEnabled(); }; + +// https://html.spec.whatwg.org/multipage/#navigatorcookies +[NoInterfaceObject, Exposed=(Window,Worker)] +interface NavigatorCookies { + readonly attribute boolean cookieEnabled; +}; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index cd00390a305..b6bf6a35643 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -1200,9 +1200,11 @@ impl Window { if !for_display || self.Document().needs_reflow() { issued_reflow = self.force_reflow(goal, query_type, reason); - // If window_size is `None`, we don't reflow, so the document stays dirty. - // Otherwise, we shouldn't need a reflow immediately after a reflow. + // If window_size is `None`, we don't reflow, so the document stays + // dirty. Otherwise, we shouldn't need a reflow immediately after a + // reflow, except if we're waiting for a deferred paint. assert!(!self.Document().needs_reflow() || + (!for_display && self.Document().needs_paint()) || self.window_size.get().is_none() || self.suppress_reflow.get()); } else { diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs index 5f6b6e1919c..1a00f67b80c 100644 --- a/components/script/dom/xmldocument.rs +++ b/components/script/dom/xmldocument.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 core::nonzero::NonZero; use document_loader::DocumentLoader; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::XMLDocumentBinding::{self, XMLDocumentMethods}; @@ -87,7 +88,7 @@ impl XMLDocumentMethods for XMLDocument { } // https://html.spec.whatwg.org/multipage/#dom-tree-accessors:dom-document-nameditem-filter - fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString, found: &mut bool) -> *mut JSObject { - self.upcast::<Document>().NamedGetter(_cx, name, found) + fn NamedGetter(&self, _cx: *mut JSContext, name: DOMString) -> Option<NonZero<*mut JSObject>> { + self.upcast::<Document>().NamedGetter(_cx, name) } } |