diff options
Diffstat (limited to 'components/script')
126 files changed, 1971 insertions, 1599 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index 293c2aefe02..05af21f1dc1 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -70,13 +70,14 @@ script_traits = {path = "../script_traits"} selectors = "0.15" serde = "0.8" servo_atoms = {path = "../atoms"} +servo_config = {path = "../config", features = ["servo"] } +servo_geometry = {path = "../geometry" } servo_url = {path = "../url", features = ["servo"] } smallvec = "0.1" style = {path = "../style"} style_traits = {path = "../style_traits"} time = "0.1.12" url = {version = "1.2", features = ["heap_size", "query_encoding"]} -util = {path = "../util"} uuid = {version = "0.3.1", features = ["v4"]} websocket = "0.17" xml5ever = {version = "0.2", features = ["unstable"]} diff --git a/components/script/dom/abstractworker.rs b/components/script/dom/abstractworker.rs index ee8ee31abc0..8d92680fbed 100644 --- a/components/script/dom/abstractworker.rs +++ b/components/script/dom/abstractworker.rs @@ -31,7 +31,7 @@ impl<T: DomObject> SimpleWorkerErrorHandler<T> { #[derive(Copy, Clone)] pub struct SharedRt { - pub rt: *mut JSRuntime + rt: *mut JSRuntime } impl SharedRt { @@ -47,10 +47,6 @@ impl SharedRt { JS_RequestInterruptCallback(self.rt); } } - - pub fn rt(&self) -> *mut JSRuntime { - self.rt - } } #[allow(unsafe_code)] unsafe impl Send for SharedRt {} diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index 8b9587c9151..c44cfd4367d 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -6,8 +6,7 @@ use devtools_traits::AttrInfo; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap}; -use dom::bindings::js::{LayoutJS, Root, RootedReference}; +use dom::bindings::js::{LayoutJS, MutNullableJS, Root, RootedReference}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::element::{AttributeMutation, Element}; @@ -28,7 +27,7 @@ pub struct Attr { value: DOMRefCell<AttrValue>, /// the element that owns this attribute. - owner: MutNullableHeap<JS<Element>>, + owner: MutNullableJS<Element>, } impl Attr { @@ -48,7 +47,7 @@ impl Attr { prefix: prefix, }, value: DOMRefCell::new(value), - owner: MutNullableHeap::new(owner), + owner: MutNullableJS::new(owner), } } diff --git a/components/script/dom/beforeunloadevent.rs b/components/script/dom/beforeunloadevent.rs index c79ca70c28e..d9162002016 100644 --- a/components/script/dom/beforeunloadevent.rs +++ b/components/script/dom/beforeunloadevent.rs @@ -2,6 +2,8 @@ * 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/. */ +#![allow(dead_code)] + use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BeforeUnloadEventBinding; use dom::bindings::codegen::Bindings::BeforeUnloadEventBinding::BeforeUnloadEventMethods; diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index dc39048ab40..d68b1adf33e 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -4260,7 +4260,9 @@ class CGUnionConversionStruct(CGThing): return CGWrapper( CGIndenter(jsConversion, 4), - pre="unsafe fn TryConvertTo%s(cx: *mut JSContext, value: HandleValue) -> %s {\n" % (t.name, returnType), + # TryConvertToObject is unused, but not generating it while generating others is tricky. + pre="#[allow(dead_code)] unsafe fn TryConvertTo%s(cx: *mut JSContext, value: HandleValue) -> %s {\n" + % (t.name, returnType), post="\n}") def define(self): @@ -5603,7 +5605,7 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries 'dom::globalscope::GlobalScope', 'mem::heap_size_of_raw_self_and_children', 'libc', - 'util::prefs::PREFS', + 'servo_config::prefs::PREFS', 'std::borrow::ToOwned', 'std::cmp', 'std::mem', diff --git a/components/script/dom/bindings/constant.rs b/components/script/dom/bindings/constant.rs index 7d453a1fd09..42f10055080 100644 --- a/components/script/dom/bindings/constant.rs +++ b/components/script/dom/bindings/constant.rs @@ -20,6 +20,7 @@ pub struct ConstantSpec { /// Representation of an IDL constant value. #[derive(Clone)] +#[allow(dead_code)] pub enum ConstantVal { /// `long` constant. IntVal(i32), diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index adfe242b5f8..18a2deb8f0f 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -56,8 +56,8 @@ use js::jsval::{ObjectValue, StringValue}; use js::rust::{ToString, get_object_class, is_dom_class, is_dom_object, maybe_wrap_value}; use libc; use num_traits::Float; +use servo_config::opts; use std::{char, mem, ptr, slice}; -use util::opts; /// A trait to check whether a given `JSObject` implements an IDL interface. pub trait IDLInterface { diff --git a/components/script/dom/bindings/guard.rs b/components/script/dom/bindings/guard.rs index 114045a62e8..25a52fbe84c 100644 --- a/components/script/dom/bindings/guard.rs +++ b/components/script/dom/bindings/guard.rs @@ -5,7 +5,7 @@ //! Machinery to conditionally expose things. use js::jsapi::{HandleObject, JSContext}; -use util::prefs::PREFS; +use servo_config::prefs::PREFS; /// A container with a condition. pub struct Guard<T: Clone + Copy> { diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index fa7999ebcb1..bdd2b81ce37 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -229,20 +229,6 @@ impl LayoutJS<Node> { } } - -/// A trait to be implemented for JS-managed types that can be stored in -/// mutable member fields. -/// -/// Do not implement this trait yourself. -pub trait HeapGCValue: JSTraceable { -} - -impl HeapGCValue for Heap<JSVal> { -} - -impl<T: DomObject> HeapGCValue for JS<T> { -} - /// A holder that provides interior mutability for GC-managed JSVals. /// /// Must be used in place of traditional interior mutability to ensure proper @@ -293,20 +279,20 @@ impl MutHeapJSVal { /// on `JS<T>`. #[must_root] #[derive(JSTraceable)] -pub struct MutHeap<T: HeapGCValue> { - val: UnsafeCell<T>, +pub struct MutJS<T: DomObject> { + val: UnsafeCell<JS<T>>, } -impl<T: DomObject> MutHeap<JS<T>> { - /// Create a new `MutHeap`. - pub fn new(initial: &T) -> MutHeap<JS<T>> { +impl<T: DomObject> MutJS<T> { + /// Create a new `MutJS`. + pub fn new(initial: &T) -> MutJS<T> { debug_assert!(thread_state::get().is_script()); - MutHeap { + MutJS { val: UnsafeCell::new(JS::from_ref(initial)), } } - /// Set this `MutHeap` to the given value. + /// Set this `MutJS` to the given value. pub fn set(&self, val: &T) { debug_assert!(thread_state::get().is_script()); unsafe { @@ -314,7 +300,7 @@ impl<T: DomObject> MutHeap<JS<T>> { } } - /// Get the value in this `MutHeap`. + /// Get the value in this `MutJS`. pub fn get(&self) -> Root<T> { debug_assert!(thread_state::get().is_script()); unsafe { @@ -323,14 +309,14 @@ impl<T: DomObject> MutHeap<JS<T>> { } } -impl<T: HeapGCValue> HeapSizeOf for MutHeap<T> { +impl<T: DomObject> HeapSizeOf for MutJS<T> { fn heap_size_of_children(&self) -> usize { // See comment on HeapSizeOf for JS<T>. 0 } } -impl<T: DomObject> PartialEq for MutHeap<JS<T>> { +impl<T: DomObject> PartialEq for MutJS<T> { fn eq(&self, other: &Self) -> bool { unsafe { *self.val.get() == *other.val.get() @@ -338,7 +324,7 @@ impl<T: DomObject> PartialEq for MutHeap<JS<T>> { } } -impl<T: DomObject + PartialEq> PartialEq<T> for MutHeap<JS<T>> { +impl<T: DomObject + PartialEq> PartialEq<T> for MutJS<T> { fn eq(&self, other: &T) -> bool { unsafe { **self.val.get() == *other @@ -354,15 +340,15 @@ impl<T: DomObject + PartialEq> PartialEq<T> for MutHeap<JS<T>> { /// on `JS<T>`. #[must_root] #[derive(JSTraceable)] -pub struct MutNullableHeap<T: HeapGCValue> { - ptr: UnsafeCell<Option<T>>, +pub struct MutNullableJS<T: DomObject> { + ptr: UnsafeCell<Option<JS<T>>>, } -impl<T: DomObject> MutNullableHeap<JS<T>> { - /// Create a new `MutNullableHeap`. - pub fn new(initial: Option<&T>) -> MutNullableHeap<JS<T>> { +impl<T: DomObject> MutNullableJS<T> { + /// Create a new `MutNullableJS`. + pub fn new(initial: Option<&T>) -> MutNullableJS<T> { debug_assert!(thread_state::get().is_script()); - MutNullableHeap { + MutNullableJS { ptr: UnsafeCell::new(initial.map(JS::from_ref)), } } @@ -400,7 +386,7 @@ impl<T: DomObject> MutNullableHeap<JS<T>> { } } - /// Set this `MutNullableHeap` to the given value. + /// Set this `MutNullableJS` to the given value. pub fn set(&self, val: Option<&T>) { debug_assert!(thread_state::get().is_script()); unsafe { @@ -416,7 +402,7 @@ impl<T: DomObject> MutNullableHeap<JS<T>> { } } -impl<T: DomObject> PartialEq for MutNullableHeap<JS<T>> { +impl<T: DomObject> PartialEq for MutNullableJS<T> { fn eq(&self, other: &Self) -> bool { unsafe { *self.ptr.get() == *other.ptr.get() @@ -424,7 +410,7 @@ impl<T: DomObject> PartialEq for MutNullableHeap<JS<T>> { } } -impl<'a, T: DomObject> PartialEq<Option<&'a T>> for MutNullableHeap<JS<T>> { +impl<'a, T: DomObject> PartialEq<Option<&'a T>> for MutNullableJS<T> { fn eq(&self, other: &Option<&T>) -> bool { unsafe { *self.ptr.get() == other.map(JS::from_ref) @@ -432,17 +418,17 @@ impl<'a, T: DomObject> PartialEq<Option<&'a T>> for MutNullableHeap<JS<T>> { } } -impl<T: HeapGCValue> Default for MutNullableHeap<T> { +impl<T: DomObject> Default for MutNullableJS<T> { #[allow(unrooted_must_root)] - fn default() -> MutNullableHeap<T> { + fn default() -> MutNullableJS<T> { debug_assert!(thread_state::get().is_script()); - MutNullableHeap { + MutNullableJS { ptr: UnsafeCell::new(None), } } } -impl<T: HeapGCValue> HeapSizeOf for MutNullableHeap<T> { +impl<T: DomObject> HeapSizeOf for MutNullableJS<T> { fn heap_size_of_children(&self) -> usize { // See comment on HeapSizeOf for JS<T>. 0 diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs index 27504efda7c..4e7920828dd 100644 --- a/components/script/dom/bindings/mod.rs +++ b/components/script/dom/bindings/mod.rs @@ -129,6 +129,10 @@ //! return `Err()` from the method with the appropriate [error value] //! (error/enum.Error.html). +#![allow(unsafe_code)] +#![deny(missing_docs)] +#![deny(non_snake_case)] + pub mod callback; pub mod cell; pub mod constant; @@ -153,7 +157,7 @@ pub mod weakref; pub mod xmlname; /// Generated JS-Rust bindings. -#[allow(missing_docs, non_snake_case)] +#[allow(dead_code, missing_docs, non_snake_case)] pub mod codegen { #[allow(unrooted_must_root)] pub mod Bindings { diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index d7984939e28..896c2af5b24 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -286,6 +286,12 @@ impl Into<Vec<u8>> for DOMString { } } +impl<'a> Into<Cow<'a, str>> for DOMString { + fn into(self) -> Cow<'a, str> { + self.0.into() + } +} + impl Extend<char> for DOMString { fn extend<I>(&mut self, iterable: I) where I: IntoIterator<Item=char> { self.0.extend(iterable) diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 4c650719bff..850bef189c7 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -48,7 +48,6 @@ use euclid::length::Length as EuclidLength; use euclid::rect::Rect; use euclid::size::Size2D; use html5ever::tokenizer::buffer_queue::BufferQueue; -use html5ever::tree_builder::QuirksMode; use html5ever_atoms::{Prefix, LocalName, Namespace, QualName}; use hyper::header::Headers; use hyper::method::Method; @@ -59,7 +58,6 @@ use js::glue::{CallObjectTracer, CallUnbarrieredObjectTracer, CallValueTracer}; use js::jsapi::{GCTraceKindToAscii, Heap, JSObject, JSTracer, TraceKind}; use js::jsval::JSVal; use js::rust::Runtime; -use libc; use msg::constellation_msg::{FrameId, FrameType, PipelineId}; use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceThreads}; use net_traits::filemanager_thread::RelativePos; @@ -82,7 +80,7 @@ use serde::{Deserialize, Serialize}; use servo_atoms::Atom; use servo_url::ServoUrl; use smallvec::SmallVec; -use std::cell::{Cell, UnsafeCell}; +use std::cell::{Cell, RefCell, UnsafeCell}; use std::collections::{BTreeMap, HashMap, HashSet, VecDeque}; use std::hash::{BuildHasher, Hash}; use std::ops::{Deref, DerefMut}; @@ -93,13 +91,14 @@ use std::sync::atomic::{AtomicBool, AtomicUsize}; use std::sync::mpsc::{Receiver, Sender}; use std::time::{SystemTime, Instant}; use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto}; +use style::context::QuirksMode; use style::element_state::*; use style::font_face::FontFaceRule; use style::keyframes::Keyframe; use style::media_queries::MediaList; use style::properties::PropertyDeclarationBlock; use style::selector_parser::{PseudoElement, Snapshot}; -use style::stylesheets::{CssRules, KeyframesRule, MediaRule, NamespaceRule, StyleRule}; +use style::stylesheets::{CssRules, KeyframesRule, MediaRule, NamespaceRule, StyleRule, ImportRule}; use style::values::specified::Length; use style::viewport::ViewportRule; use time::Duration; @@ -526,6 +525,12 @@ unsafe impl JSTraceable for RwLock<KeyframesRule> { } } +unsafe impl JSTraceable for RwLock<ImportRule> { + unsafe fn trace(&self, _trc: *mut JSTracer) { + // Do nothing. + } +} + unsafe impl JSTraceable for RwLock<MediaRule> { unsafe fn trace(&self, _trc: *mut JSTracer) { // Do nothing. @@ -568,27 +573,16 @@ unsafe impl JSTraceable for RwLock<MediaList> { } } -/// Homemade trait object for JSTraceable things -struct TraceableInfo { - pub ptr: *const libc::c_void, - pub trace: unsafe fn(obj: *const libc::c_void, tracer: *mut JSTracer), -} - /// Holds a set of JSTraceables that need to be rooted pub struct RootedTraceableSet { - set: Vec<TraceableInfo>, + set: Vec<*const JSTraceable>, } -#[allow(missing_docs)] // FIXME -mod dummy { // Attributes don’t apply through the macro. - use std::cell::RefCell; - use std::rc::Rc; - use super::RootedTraceableSet; +thread_local!( /// TLV Holds a set of JSTraceables that need to be rooted - thread_local!(pub static ROOTED_TRACEABLES: Rc<RefCell<RootedTraceableSet>> = - Rc::new(RefCell::new(RootedTraceableSet::new()))); -} -pub use self::dummy::ROOTED_TRACEABLES; + static ROOTED_TRACEABLES: RefCell<RootedTraceableSet> = + RefCell::new(RootedTraceableSet::new()); +); impl RootedTraceableSet { fn new() -> RootedTraceableSet { @@ -597,12 +591,12 @@ impl RootedTraceableSet { } } - unsafe fn remove<T: JSTraceable>(traceable: &T) { + unsafe fn remove(traceable: *const JSTraceable) { ROOTED_TRACEABLES.with(|ref traceables| { let mut traceables = traceables.borrow_mut(); let idx = match traceables.set.iter() - .rposition(|x| x.ptr == traceable as *const T as *const _) { + .rposition(|x| *x == traceable) { Some(idx) => idx, None => unreachable!(), }; @@ -610,25 +604,15 @@ impl RootedTraceableSet { }); } - unsafe fn add<T: JSTraceable>(traceable: &T) { + unsafe fn add(traceable: *const JSTraceable) { ROOTED_TRACEABLES.with(|ref traceables| { - unsafe fn trace<T: JSTraceable>(obj: *const libc::c_void, tracer: *mut JSTracer) { - let obj: &T = &*(obj as *const T); - obj.trace(tracer); - } - - let mut traceables = traceables.borrow_mut(); - let info = TraceableInfo { - ptr: traceable as *const T as *const libc::c_void, - trace: trace::<T>, - }; - traceables.set.push(info); + traceables.borrow_mut().set.push(traceable); }) } unsafe fn trace(&self, tracer: *mut JSTracer) { - for info in &self.set { - (info.trace)(info.ptr, tracer); + for traceable in &self.set { + (**traceable).trace(tracer); } } } @@ -640,11 +624,11 @@ impl RootedTraceableSet { /// If you have an arbitrary number of DomObjects to root, use rooted_vec!. /// If you know what you're doing, use this. #[derive(JSTraceable)] -pub struct RootedTraceable<'a, T: 'a + JSTraceable> { +pub struct RootedTraceable<'a, T: 'static + JSTraceable> { ptr: &'a T, } -impl<'a, T: JSTraceable> RootedTraceable<'a, T> { +impl<'a, T: JSTraceable + 'static> RootedTraceable<'a, T> { /// Root a JSTraceable thing for the life of this RootedTraceable pub fn new(traceable: &'a T) -> RootedTraceable<'a, T> { unsafe { @@ -656,7 +640,7 @@ impl<'a, T: JSTraceable> RootedTraceable<'a, T> { } } -impl<'a, T: JSTraceable> Drop for RootedTraceable<'a, T> { +impl<'a, T: JSTraceable + 'static> Drop for RootedTraceable<'a, T> { fn drop(&mut self) { unsafe { RootedTraceableSet::remove(self.ptr); @@ -686,15 +670,29 @@ impl<T: JSTraceable> RootableVec<T> { /// A vector of items that are rooted for the lifetime 'a. #[allow_unrooted_interior] -pub struct RootedVec<'a, T: 'a + JSTraceable> { +pub struct RootedVec<'a, T: 'static + JSTraceable> { root: &'a mut RootableVec<T>, } -impl<'a, T: JSTraceable + DomObject> RootedVec<'a, JS<T>> { +impl<'a, T: 'static + JSTraceable> RootedVec<'a, T> { /// Create a vector of items of type T that is rooted for /// the lifetime of this struct - pub fn new<I: Iterator<Item = Root<T>>>(root: &'a mut RootableVec<JS<T>>, iter: I) - -> RootedVec<'a, JS<T>> { + pub fn new(root: &'a mut RootableVec<T>) -> Self { + unsafe { + RootedTraceableSet::add(root); + } + RootedVec { + root: root, + } + } +} + +impl<'a, T: 'static + JSTraceable + DomObject> RootedVec<'a, JS<T>> { + /// Create a vector of items of type JS<T> that is rooted for + /// the lifetime of this struct + pub fn from_iter<I>(root: &'a mut RootableVec<JS<T>>, iter: I) -> Self + where I: Iterator<Item = Root<T>> + { unsafe { RootedTraceableSet::add(root); } @@ -705,7 +703,7 @@ impl<'a, T: JSTraceable + DomObject> RootedVec<'a, JS<T>> { } } -impl<'a, T: JSTraceable> Drop for RootedVec<'a, T> { +impl<'a, T: JSTraceable + 'static> Drop for RootedVec<'a, T> { fn drop(&mut self) { self.clear(); unsafe { diff --git a/components/script/dom/bluetooth.rs b/components/script/dom/bluetooth.rs index 5a657eb6459..dcbb398a4ee 100644 --- a/components/script/dom/bluetooth.rs +++ b/components/script/dom/bluetooth.rs @@ -2,8 +2,8 @@ * 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 bluetooth_traits::{BluetoothError, BluetoothRequest}; -use bluetooth_traits::{BluetoothResponse, BluetoothResponseListener, BluetoothResponseResult}; +use bluetooth_traits::{BluetoothError, BluetoothRequest, GATTType}; +use bluetooth_traits::{BluetoothResponse, BluetoothResponseResult}; use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; use bluetooth_traits::scanfilter::{BluetoothScanfilter, BluetoothScanfilterSequence}; use bluetooth_traits::scanfilter::{RequestDeviceoptions, ServiceUUIDSequence}; @@ -13,22 +13,21 @@ use dom::bindings::codegen::Bindings::BluetoothBinding::{self, BluetoothDataFilt use dom::bindings::codegen::Bindings::BluetoothBinding::{BluetoothMethods, RequestDeviceOptions}; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::codegen::UnionTypes::StringOrUnsignedLong; -use dom::bindings::error::Error::{self, NotFound, Security, Type}; +use dom::bindings::error::Error::{self, Network, NotFound, Security, Type}; use dom::bindings::error::Fallible; -use dom::bindings::js::{JS, MutHeap, Root}; +use dom::bindings::js::{MutJS, Root}; use dom::bindings::refcounted::{Trusted, TrustedPromise}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; -use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; use dom::bluetoothdevice::BluetoothDevice; -use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; +use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID, UUID}; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::promise::Promise; use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use js::jsapi::{JSAutoCompartment, JSContext}; -use network_listener::{NetworkListener, PreInvoke}; +use script_thread::Runnable; use std::collections::HashMap; use std::rc::Rc; use std::str::FromStr; @@ -62,9 +61,7 @@ pub trait AsyncBluetoothListener { fn handle_response(&self, result: BluetoothResponse, cx: *mut JSContext, promise: &Rc<Promise>); } -impl<Listener: AsyncBluetoothListener + DomObject> PreInvoke for BluetoothContext<Listener> {} - -impl<Listener: AsyncBluetoothListener + DomObject> BluetoothResponseListener for BluetoothContext<Listener> { +impl<T: AsyncBluetoothListener + DomObject> BluetoothContext<T> { #[allow(unrooted_must_root)] fn response(&mut self, response: BluetoothResponseResult) { let promise = self.promise.take().expect("bt promise is missing").root(); @@ -86,7 +83,7 @@ impl<Listener: AsyncBluetoothListener + DomObject> BluetoothResponseListener for #[dom_struct] pub struct Bluetooth { eventtarget: EventTarget, - device_instance_map: DOMRefCell<HashMap<String, MutHeap<JS<BluetoothDevice>>>>, + device_instance_map: DOMRefCell<HashMap<String, MutJS<BluetoothDevice>>>, } impl Bluetooth { @@ -107,6 +104,10 @@ impl Bluetooth { self.global().as_window().bluetooth_thread() } + pub fn get_device_map(&self) -> &DOMRefCell<HashMap<String, MutJS<BluetoothDevice>>> { + &self.device_instance_map + } + // https://webbluetoothcg.github.io/web-bluetooth/#request-bluetooth-devices fn request_bluetooth_devices(&self, p: &Rc<Promise>, @@ -183,17 +184,84 @@ pub fn response_async<T: AsyncBluetoothListener + DomObject + 'static>( promise: Some(TrustedPromise::new(promise.clone())), receiver: Trusted::new(receiver), })); - let listener = NetworkListener { - context: context, - task_source: task_source, - wrapper: None, - }; ROUTER.add_route(action_receiver.to_opaque(), box move |message| { - listener.notify_response(message.to().unwrap()); + struct ListenerRunnable<T: AsyncBluetoothListener + DomObject> { + context: Arc<Mutex<BluetoothContext<T>>>, + action: BluetoothResponseResult, + } + + impl<T: AsyncBluetoothListener + DomObject> Runnable for ListenerRunnable<T> { + fn handler(self: Box<Self>) { + let this = *self; + let mut context = this.context.lock().unwrap(); + context.response(this.action); + } + } + + let runnable = box ListenerRunnable { + context: context.clone(), + action: message.to().unwrap(), + }; + + let result = task_source.queue_wrapperless(runnable); + if let Err(err) = result { + warn!("failed to deliver network data: {:?}", err); + } }); action_sender } +#[allow(unrooted_must_root)] +// https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren +pub fn get_gatt_children<T, F> ( + attribute: &T, + single: bool, + uuid_canonicalizer: F, + uuid: Option<StringOrUnsignedLong>, + instance_id: String, + connected: bool, + child_type: GATTType) + -> Rc<Promise> + where T: AsyncBluetoothListener + DomObject + 'static, + F: FnOnce(StringOrUnsignedLong) -> Fallible<UUID> { + let p = Promise::new(&attribute.global()); + let p_cx = p.global().get_cx(); + + let result_uuid = if let Some(u) = uuid { + // Step 1. + let canonicalized = match uuid_canonicalizer(u) { + Ok(canonicalized_uuid) => canonicalized_uuid.to_string(), + Err(e) => { + p.reject_error(p_cx, e); + return p; + } + }; + // Step 2. + if uuid_is_blocklisted(canonicalized.as_ref(), Blocklist::All) { + p.reject_error(p_cx, Security); + return p; + } + Some(canonicalized) + } else { + None + }; + + // Step 3 - 4. + if !connected { + p.reject_error(p_cx, Network); + return p; + } + + // TODO: Step 5: Implement representedDevice internal slot for BluetoothDevice. + + // Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_descriptor function + // and in handle_response function. + let sender = response_async(&p, attribute); + attribute.global().as_window().bluetooth_thread().send( + BluetoothRequest::GetGATTChildren(instance_id, result_uuid, single, child_type, sender)).unwrap(); + return p; +} + // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothlescanfilterinit-canonicalizing fn canonicalize_filter(filter: &BluetoothLEScanFilterInit) -> Fallible<BluetoothScanfilter> { // Step 1. @@ -400,16 +468,11 @@ impl AsyncBluetoothListener for Bluetooth { if let Some(existing_device) = device_instance_map.get(&device.id.clone()) { return promise.resolve_native(promise_cx, &existing_device.get()); } - let ad_data = BluetoothAdvertisingData::new(&self.global(), - device.appearance, - device.tx_power, - device.rssi); let bt_device = BluetoothDevice::new(&self.global(), DOMString::from(device.id.clone()), device.name.map(DOMString::from), - &ad_data, &self); - device_instance_map.insert(device.id, MutHeap::new(&bt_device)); + device_instance_map.insert(device.id, MutJS::new(&bt_device)); // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetooth-requestdevice // Step 5. promise.resolve_native(promise_cx, &bt_device); diff --git a/components/script/dom/bluetoothadvertisingdata.rs b/components/script/dom/bluetoothadvertisingdata.rs deleted file mode 100644 index 878f4fe82ec..00000000000 --- a/components/script/dom/bluetoothadvertisingdata.rs +++ /dev/null @@ -1,61 +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/. */ - -use dom::bindings::codegen::Bindings::BluetoothAdvertisingDataBinding; -use dom::bindings::codegen::Bindings::BluetoothAdvertisingDataBinding::BluetoothAdvertisingDataMethods; -use dom::bindings::js::Root; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; -use dom::globalscope::GlobalScope; - -// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothadvertisingdata -#[dom_struct] -pub struct BluetoothAdvertisingData { - reflector_: Reflector, - appearance: Option<u16>, - tx_power: Option<i8>, - rssi: Option<i8>, -} - -impl BluetoothAdvertisingData { - pub fn new_inherited(appearance: Option<u16>, - tx_power: Option<i8>, - rssi: Option<i8>) - -> BluetoothAdvertisingData { - BluetoothAdvertisingData { - reflector_: Reflector::new(), - appearance: appearance, - tx_power: tx_power, - rssi: rssi, - } - } - - pub fn new(global: &GlobalScope, - appearance: Option<u16>, - txPower: Option<i8>, - rssi: Option<i8>) - -> Root<BluetoothAdvertisingData> { - reflect_dom_object(box BluetoothAdvertisingData::new_inherited(appearance, - txPower, - rssi), - global, - BluetoothAdvertisingDataBinding::Wrap) - } -} - -impl BluetoothAdvertisingDataMethods for BluetoothAdvertisingData { - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingdata-appearance - fn GetAppearance(&self) -> Option<u16> { - self.appearance - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingdata-txpower - fn GetTxPower(&self) -> Option<i8> { - self.tx_power - } - - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingdata-rssi - fn GetRssi(&self) -> Option<i8> { - self.rssi - } -} diff --git a/components/script/dom/bluetoothadvertisingevent.rs b/components/script/dom/bluetoothadvertisingevent.rs new file mode 100644 index 00000000000..cc65aa4cd96 --- /dev/null +++ b/components/script/dom/bluetoothadvertisingevent.rs @@ -0,0 +1,126 @@ +/* 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::bindings::codegen::Bindings::BluetoothAdvertisingEventBinding::{self, BluetoothAdvertisingEventInit}; +use dom::bindings::codegen::Bindings::BluetoothAdvertisingEventBinding::BluetoothAdvertisingEventMethods; +use dom::bindings::codegen::Bindings::EventBinding::EventBinding::EventMethods; +use dom::bindings::error::Fallible; +use dom::bindings::inheritance::Castable; +use dom::bindings::js::{JS, Root, RootedReference}; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::bluetoothdevice::BluetoothDevice; +use dom::event::{Event, EventBubbles, EventCancelable}; +use dom::globalscope::GlobalScope; +use dom::window::Window; +use servo_atoms::Atom; + +// https://webbluetoothcg.github.io/web-bluetooth/#bluetoothadvertisingevent +#[dom_struct] +pub struct BluetoothAdvertisingEvent { + event: Event, + device: JS<BluetoothDevice>, + name: Option<DOMString>, + appearance: Option<u16>, + tx_power: Option<i8>, + rssi: Option<i8>, +} + +impl BluetoothAdvertisingEvent { + pub fn new_inherited(device: &BluetoothDevice, + name: Option<DOMString>, + appearance: Option<u16>, + tx_power: Option<i8>, + rssi: Option<i8>) + -> BluetoothAdvertisingEvent { + BluetoothAdvertisingEvent { + event: Event::new_inherited(), + device: JS::from_ref(device), + name: name, + appearance: appearance, + tx_power: tx_power, + rssi: rssi, + } + } + + pub fn new(global: &GlobalScope, + type_: Atom, + bubbles: EventBubbles, + cancelable: EventCancelable, + device: &BluetoothDevice, + name: Option<DOMString>, + appearance: Option<u16>, + txPower: Option<i8>, + rssi: Option<i8>) + -> Root<BluetoothAdvertisingEvent> { + let ev = reflect_dom_object(box BluetoothAdvertisingEvent::new_inherited(device, + name, + appearance, + txPower, + rssi), + global, + BluetoothAdvertisingEventBinding::Wrap); + { + let event = ev.upcast::<Event>(); + event.init_event(type_, bool::from(bubbles), bool::from(cancelable)); + } + ev + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-bluetoothadvertisingevent + pub fn Constructor(window: &Window, + type_: DOMString, + init: &BluetoothAdvertisingEventInit) + -> Fallible<Root<BluetoothAdvertisingEvent>> { + let global = window.upcast::<GlobalScope>(); + let device = init.device.r(); + let name = init.name.clone(); + let appearance = init.appearance.clone(); + let txPower = init.txPower.clone(); + let rssi = init.rssi.clone(); + let bubbles = EventBubbles::from(init.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.cancelable); + Ok(BluetoothAdvertisingEvent::new(global, + Atom::from(type_), + bubbles, + cancelable, + device, + name, + appearance, + txPower, + rssi)) + } +} + +impl BluetoothAdvertisingEventMethods for BluetoothAdvertisingEvent { + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-device + fn Device(&self) -> Root<BluetoothDevice> { + Root::from_ref(&*self.device) + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-name + fn GetName(&self) -> Option<DOMString> { + self.name.clone() + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-appearance + fn GetAppearance(&self) -> Option<u16> { + self.appearance + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-txpower + fn GetTxPower(&self) -> Option<i8> { + self.tx_power + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothadvertisingevent-rssi + fn GetRssi(&self) -> Option<i8> { + self.rssi + } + + // https://dom.spec.whatwg.org/#dom-event-istrusted + fn IsTrusted(&self) -> bool { + self.event.IsTrusted() + } +} diff --git a/components/script/dom/bluetoothdevice.rs b/components/script/dom/bluetoothdevice.rs index b257b82f343..d56970c0d98 100644 --- a/components/script/dom/bluetoothdevice.rs +++ b/components/script/dom/bluetoothdevice.rs @@ -2,17 +2,20 @@ * 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 bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg, BluetoothServiceMsg}; +use bluetooth_traits::{BluetoothCharacteristicMsg, BluetoothDescriptorMsg}; +use bluetooth_traits::{BluetoothRequest, BluetoothResponse, BluetoothServiceMsg}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; -use dom::bindings::js::{JS, Root, MutHeap, MutNullableHeap}; +use dom::bindings::error::Error; +use dom::bindings::error::ErrorResult; +use dom::bindings::inheritance::Castable; +use dom::bindings::js::{MutJS, MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; -use dom::bluetooth::Bluetooth; -use dom::bluetoothadvertisingdata::BluetoothAdvertisingData; +use dom::bluetooth::{AsyncBluetoothListener, Bluetooth, response_async}; use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothremotegattcharacteristic::BluetoothRemoteGATTCharacteristic; use dom::bluetoothremotegattdescriptor::BluetoothRemoteGATTDescriptor; @@ -20,8 +23,12 @@ use dom::bluetoothremotegattserver::BluetoothRemoteGATTServer; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; +use dom::promise::Promise; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::JSContext; +use std::cell::Cell; use std::collections::HashMap; - +use std::rc::Rc; // https://webbluetoothcg.github.io/web-bluetooth/#bluetoothdevice #[dom_struct] @@ -29,47 +36,48 @@ pub struct BluetoothDevice { eventtarget: EventTarget, id: DOMString, name: Option<DOMString>, - ad_data: MutHeap<JS<BluetoothAdvertisingData>>, - gatt: MutNullableHeap<JS<BluetoothRemoteGATTServer>>, - context: MutHeap<JS<Bluetooth>>, - attribute_instance_map: (DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTService>>>>, - DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTCharacteristic>>>>, - DOMRefCell<HashMap<String, MutHeap<JS<BluetoothRemoteGATTDescriptor>>>>), + gatt: MutNullableJS<BluetoothRemoteGATTServer>, + context: MutJS<Bluetooth>, + attribute_instance_map: (DOMRefCell<HashMap<String, MutJS<BluetoothRemoteGATTService>>>, + DOMRefCell<HashMap<String, MutJS<BluetoothRemoteGATTCharacteristic>>>, + DOMRefCell<HashMap<String, MutJS<BluetoothRemoteGATTDescriptor>>>), + watching_advertisements: Cell<bool>, } impl BluetoothDevice { pub fn new_inherited(id: DOMString, name: Option<DOMString>, - ad_data: &BluetoothAdvertisingData, context: &Bluetooth) -> BluetoothDevice { BluetoothDevice { eventtarget: EventTarget::new_inherited(), id: id, name: name, - ad_data: MutHeap::new(ad_data), gatt: Default::default(), - context: MutHeap::new(context), + context: MutJS::new(context), attribute_instance_map: (DOMRefCell::new(HashMap::new()), DOMRefCell::new(HashMap::new()), DOMRefCell::new(HashMap::new())), + watching_advertisements: Cell::new(false), } } pub fn new(global: &GlobalScope, id: DOMString, name: Option<DOMString>, - adData: &BluetoothAdvertisingData, context: &Bluetooth) -> Root<BluetoothDevice> { reflect_dom_object(box BluetoothDevice::new_inherited(id, name, - adData, context), global, BluetoothDeviceBinding::Wrap) } + fn get_context(&self) -> Root<Bluetooth> { + self.context.get() + } + pub fn get_or_create_service(&self, service: &BluetoothServiceMsg, server: &BluetoothRemoteGATTServer) @@ -84,7 +92,7 @@ impl BluetoothDevice { DOMString::from(service.uuid.clone()), service.is_primary, service.instance_id.clone()); - service_map.insert(service.instance_id.clone(), MutHeap::new(&bt_service)); + service_map.insert(service.instance_id.clone(), MutJS::new(&bt_service)); return bt_service; } @@ -113,10 +121,17 @@ impl BluetoothDevice { DOMString::from(characteristic.uuid.clone()), &properties, characteristic.instance_id.clone()); - characteristic_map.insert(characteristic.instance_id.clone(), MutHeap::new(&bt_characteristic)); + characteristic_map.insert(characteristic.instance_id.clone(), MutJS::new(&bt_characteristic)); return bt_characteristic; } + pub fn is_represented_device_null(&self) -> bool { + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothRequest::IsRepresentedDeviceNull(self.Id().to_string(), sender)).unwrap(); + receiver.recv().unwrap() + } + pub fn get_or_create_descriptor(&self, descriptor: &BluetoothDescriptorMsg, characteristic: &BluetoothRemoteGATTCharacteristic) @@ -130,9 +145,67 @@ impl BluetoothDevice { characteristic, DOMString::from(descriptor.uuid.clone()), descriptor.instance_id.clone()); - descriptor_map.insert(descriptor.instance_id.clone(), MutHeap::new(&bt_descriptor)); + descriptor_map.insert(descriptor.instance_id.clone(), MutJS::new(&bt_descriptor)); return bt_descriptor; } + + fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> { + self.global().as_window().bluetooth_thread() + } + + // https://webbluetoothcg.github.io/web-bluetooth/#clean-up-the-disconnected-device + #[allow(unrooted_must_root)] + pub fn clean_up_disconnected_device(&self) { + // Step 1. + self.Gatt().set_connected(false); + + // TODO: Step 2: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer. + + // Step 3: We don't need `context`, we get the attributeInstanceMap from the device. + // https://github.com/WebBluetoothCG/web-bluetooth/issues/330 + + // Step 4. + let mut service_map = self.attribute_instance_map.0.borrow_mut(); + let service_ids = service_map.drain().map(|(id, _)| id).collect(); + + let mut characteristic_map = self.attribute_instance_map.1.borrow_mut(); + let characteristic_ids = characteristic_map.drain().map(|(id, _)| id).collect(); + + let mut descriptor_map = self.attribute_instance_map.2.borrow_mut(); + let descriptor_ids = descriptor_map.drain().map(|(id, _)| id).collect(); + + // Step 5, 6.4, 7. + // TODO: Step 6: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic. + let _ = self.get_bluetooth_thread().send( + BluetoothRequest::SetRepresentedToNull(service_ids, characteristic_ids, descriptor_ids)); + + // Step 8. + self.upcast::<EventTarget>().fire_bubbling_event(atom!("gattserverdisconnected")); + } + + // https://webbluetoothcg.github.io/web-bluetooth/#garbage-collect-the-connection + #[allow(unrooted_must_root)] + pub fn garbage_collect_the_connection(&self) -> ErrorResult { + // Step 1: TODO: Check if other systems using this device. + + // Step 2. + let context = self.get_context(); + for (id, device) in context.get_device_map().borrow().iter() { + // Step 2.1 - 2.2. + if id == &self.Id().to_string() { + if device.get().Gatt().Connected() { + return Ok(()); + } + // TODO: Step 2.3: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer. + } + } + + // Step 3. + let (sender, receiver) = ipc::channel().unwrap(); + self.get_bluetooth_thread().send( + BluetoothRequest::GATTServerDisconnect(String::from(self.Id()), sender)).unwrap(); + receiver.recv().unwrap().map_err(Error::from) + } } impl BluetoothDeviceMethods for BluetoothDevice { @@ -146,11 +219,6 @@ impl BluetoothDeviceMethods for BluetoothDevice { self.name.clone() } - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-addata - fn AdData(&self) -> Root<BluetoothAdvertisingData> { - self.ad_data.get() - } - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-gatt fn Gatt(&self) -> Root<BluetoothRemoteGATTServer> { // TODO: Step 1 - 2: Implement the Permission API. @@ -159,6 +227,46 @@ impl BluetoothDeviceMethods for BluetoothDevice { }) } + #[allow(unrooted_must_root)] + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchadvertisements + fn WatchAdvertisements(&self) -> Rc<Promise> { + let p = Promise::new(&self.global()); + let sender = response_async(&p, self); + // TODO: Step 1. + // Note: Steps 2 - 3 are implemented in components/bluetooth/lib.rs in watch_advertisements function + // and in handle_response function. + self.get_bluetooth_thread().send( + BluetoothRequest::WatchAdvertisements(String::from(self.Id()), sender)).unwrap(); + return p; + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-unwatchadvertisements + fn UnwatchAdvertisements(&self) -> () { + // Step 1. + self.watching_advertisements.set(false) + // TODO: Step 2. + } + + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-watchingadvertisements + fn WatchingAdvertisements(&self) -> bool { + self.watching_advertisements.get() + } + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdeviceeventhandlers-ongattserverdisconnected event_handler!(gattserverdisconnected, GetOngattserverdisconnected, SetOngattserverdisconnected); } + +impl AsyncBluetoothListener for BluetoothDevice { + fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) { + match response { + // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothdevice-unwatchadvertisements + BluetoothResponse::WatchAdvertisements(_result) => { + // Step 3.1. + self.watching_advertisements.set(true); + // Step 3.2. + promise.resolve_native(promise_cx, &()); + }, + _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())), + } + } +} diff --git a/components/script/dom/bluetoothremotegattcharacteristic.rs b/components/script/dom/bluetoothremotegattcharacteristic.rs index eb41e6ec1db..b4b9941343b 100644 --- a/components/script/dom/bluetoothremotegattcharacteristic.rs +++ b/components/script/dom/bluetoothremotegattcharacteristic.rs @@ -2,7 +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 bluetooth_traits::{BluetoothRequest, BluetoothResponse}; +use bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType}; use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BluetoothCharacteristicPropertiesBinding:: @@ -16,10 +16,10 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::Bluetoo use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; use dom::bindings::error::Error::{self, InvalidModification, Network, NotSupported, Security}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutHeap, Root}; +use dom::bindings::js::{MutJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::{ByteString, DOMString}; -use dom::bluetooth::{AsyncBluetoothListener, response_async}; +use dom::bluetooth::{AsyncBluetoothListener, get_gatt_children, response_async}; use dom::bluetoothcharacteristicproperties::BluetoothCharacteristicProperties; use dom::bluetoothremotegattservice::BluetoothRemoteGATTService; use dom::bluetoothuuid::{BluetoothDescriptorUUID, BluetoothUUID}; @@ -38,9 +38,9 @@ pub const MAXIMUM_ATTRIBUTE_LENGTH: usize = 512; #[dom_struct] pub struct BluetoothRemoteGATTCharacteristic { eventtarget: EventTarget, - service: MutHeap<JS<BluetoothRemoteGATTService>>, + service: MutJS<BluetoothRemoteGATTService>, uuid: DOMString, - properties: MutHeap<JS<BluetoothCharacteristicProperties>>, + properties: MutJS<BluetoothCharacteristicProperties>, value: DOMRefCell<Option<ByteString>>, instance_id: String, } @@ -53,9 +53,9 @@ impl BluetoothRemoteGATTCharacteristic { -> BluetoothRemoteGATTCharacteristic { BluetoothRemoteGATTCharacteristic { eventtarget: EventTarget::new_inherited(), - service: MutHeap::new(service), + service: MutJS::new(service), uuid: uuid, - properties: MutHeap::new(properties), + properties: MutJS::new(properties), value: DOMRefCell::new(None), instance_id: instance_id, } @@ -102,83 +102,18 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetDescriptor(&self, descriptor: BluetoothDescriptorUUID) -> Rc<Promise> { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::descriptor(descriptor) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Service().Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedService internal slot for BluetoothRemoteGATTService. - - // Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_descriptor function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetDescriptor(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, true, BluetoothUUID::descriptor, Some(descriptor), self.get_instance_id(), + self.Service().Device().Gatt().Connected(), GATTType::Descriptor) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetDescriptors(&self, descriptor: Option<BluetoothDescriptorUUID>) -> Rc<Promise> { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - let mut uuid: Option<String> = None; - if let Some(d) = descriptor { - // Step 1. - uuid = match BluetoothUUID::descriptor(d) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Service().Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedService internal slot for BluetoothRemoteGATTService. - - // Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_descriptors function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetDescriptors(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::descriptor, descriptor, self.get_instance_id(), + self.Service().Device().Gatt().Connected(), GATTType::Descriptor) } // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-value @@ -204,8 +139,6 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris return p; } - // TODO: Step 3 - 4: Implement representedCharacteristic internal slot for BluetoothRemoteGATTCharacteristic. - // TODO: Step 5: Implement the `connection-checking-wrapper` algorithm for BluetoothRemoteGATTServer. // Step 5.1. @@ -214,8 +147,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris return p; } - // Note: Remaining substeps of Step 5 are implemented in components/bluetooth/lib.rs in readValue function - // and in handle_response function. + // Note: Steps 3 - 4 and the remaining substeps of Step 5 are implemented in components/bluetooth/lib.rs + // in readValue function and in handle_response function. let sender = response_async(&p, self); self.get_bluetooth_thread().send( BluetoothRequest::ReadValue(self.get_instance_id(), sender)).unwrap(); @@ -246,8 +179,6 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris return p; } - // TODO: Step 5 - 6: Implement representedCharacteristic internal slot for BluetoothRemoteGATTCharacteristic. - // TODO: Step 7: Implement the `connection-checking-wrapper` algorithm for BluetoothRemoteGATTServer. // Step 7.1. @@ -258,8 +189,8 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris return p; } - // Note: Remaining substeps of Step 7 are implemented in components/bluetooth/lib.rs in writeValue function - // and in handle_response function. + // Note: Steps 5 - 6 and the remaining substeps of Step 7 are implemented in components/bluetooth/lib.rs + // in writeValue function and in handle_response function. let sender = response_async(&p, self); self.get_bluetooth_thread().send( BluetoothRequest::WriteValue(self.get_instance_id(), value, sender)).unwrap(); @@ -278,8 +209,6 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris return p; } - // TODO: Step 2 - 3: Implement representedCharacteristic internal slot for BluetoothRemoteGATTCharacteristic. - // Step 4. if !(self.Properties().Notify() || self.Properties().Indicate()) { @@ -295,7 +224,7 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris return p; } - // Note: Steps 7 - 11 are implemented in components/bluetooth/lib.rs in enable_notification function + // Note: Steps 2 - 3, 7 - 11 are implemented in components/bluetooth/lib.rs in enable_notification function // and in handle_response function. let sender = response_async(&p, self); self.get_bluetooth_thread().send( @@ -311,11 +240,10 @@ impl BluetoothRemoteGATTCharacteristicMethods for BluetoothRemoteGATTCharacteris let p = Promise::new(&self.global()); let sender = response_async(&p, self); - // TODO: Step 1 - 4: Implement representedCharacteristic internal slot and - // `active notification context set` for BluetoothRemoteGATTCharacteristic, + // TODO: Step 3 - 4: Implement `active notification context set` for BluetoothRemoteGATTCharacteristic, - // Note: Part of Step 4 and Step 5 are implemented in components/bluetooth/lib.rs in enable_notification - // function and in handle_response function. + // Note: Steps 1 - 2, and part of Step 4 and Step 5 are implemented in components/bluetooth/lib.rs + // in enable_notification function and in handle_response function. self.get_bluetooth_thread().send( BluetoothRequest::EnableNotification(self.get_instance_id(), false, @@ -331,17 +259,13 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTCharacteristic { fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) { let device = self.Service().Device(); match response { - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptor // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. - BluetoothResponse::GetDescriptor(descriptor) => { - let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self); - promise.resolve_native(promise_cx, &bt_descriptor); - }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattcharacteristic-getdescriptors - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - // Step 7. - BluetoothResponse::GetDescriptors(descriptors_vec) => { + BluetoothResponse::GetDescriptors(descriptors_vec, single) => { + if single { + promise.resolve_native(promise_cx, &device.get_or_create_descriptor(&descriptors_vec[0], &self)); + return; + } let mut descriptors = vec!(); for descriptor in descriptors_vec { let bt_descriptor = device.get_or_create_descriptor(&descriptor, &self); diff --git a/components/script/dom/bluetoothremotegattdescriptor.rs b/components/script/dom/bluetoothremotegattdescriptor.rs index c31fae99070..b96a20c4a21 100644 --- a/components/script/dom/bluetoothremotegattdescriptor.rs +++ b/components/script/dom/bluetoothremotegattdescriptor.rs @@ -13,7 +13,7 @@ use dom::bindings::codegen::Bindings::BluetoothRemoteGATTDescriptorBinding::Blue use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; use dom::bindings::error::Error::{self, InvalidModification, Network, Security}; -use dom::bindings::js::{JS, MutHeap, Root}; +use dom::bindings::js::{MutJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::str::{ByteString, DOMString}; use dom::bluetooth::{AsyncBluetoothListener, response_async}; @@ -28,7 +28,7 @@ use std::rc::Rc; #[dom_struct] pub struct BluetoothRemoteGATTDescriptor { reflector_: Reflector, - characteristic: MutHeap<JS<BluetoothRemoteGATTCharacteristic>>, + characteristic: MutJS<BluetoothRemoteGATTCharacteristic>, uuid: DOMString, value: DOMRefCell<Option<ByteString>>, instance_id: String, @@ -41,7 +41,7 @@ impl BluetoothRemoteGATTDescriptor { -> BluetoothRemoteGATTDescriptor { BluetoothRemoteGATTDescriptor { reflector_: Reflector::new(), - characteristic: MutHeap::new(characteristic), + characteristic: MutJS::new(characteristic), uuid: uuid, value: DOMRefCell::new(None), instance_id: instance_id, @@ -103,11 +103,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { return p; } - // TODO: Step 3 - 4: Implement representedDescriptor internal slot for BluetoothRemoteGATTDescriptor. - // TODO: Step 5: Implement the `connection-checking-wrapper` algorithm for BluetoothRemoteGATTServer. - // Note: Substeps of Step 5 are implemented in components/bluetooth/lib.rs in readValue function - // and in handle_response function. + // Note: Steps 3 - 4 and substeps of Step 5 are implemented in components/bluetooth/lib.rs + // in readValue function and in handle_response function. let sender = response_async(&p, self); self.get_bluetooth_thread().send( BluetoothRequest::ReadValue(self.get_instance_id(), sender)).unwrap(); @@ -138,11 +136,9 @@ impl BluetoothRemoteGATTDescriptorMethods for BluetoothRemoteGATTDescriptor { return p; } - // TODO: Step 5 - 6: Implement representedCharacteristic internal slot for BluetoothRemoteGATTCharacteristic. - // TODO: Step 7: Implement the `connection-checking-wrapper` algorithm for BluetoothRemoteGATTServer. - // Note: Substeps of Step 7 are implemented in components/bluetooth/lib.rs in writeValue function - // and in handle_response function. + // Note: Steps 5 - 6 and substeps of Step 7 are implemented in components/bluetooth/lib.rs + // in writeValue function and in handle_response function. let sender = response_async(&p, self); self.get_bluetooth_thread().send( BluetoothRequest::WriteValue(self.get_instance_id(), value, sender)).unwrap(); diff --git a/components/script/dom/bluetoothremotegattserver.rs b/components/script/dom/bluetoothremotegattserver.rs index d9d57ae51f1..e81aae08abe 100644 --- a/components/script/dom/bluetoothremotegattserver.rs +++ b/components/script/dom/bluetoothremotegattserver.rs @@ -2,21 +2,20 @@ * 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 bluetooth_traits::{BluetoothRequest, BluetoothResponse}; -use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; +use bluetooth_traits::{BluetoothRequest, BluetoothResponse, GATTType}; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; -use dom::bindings::error::Error::{self, Network, Security}; +use dom::bindings::error::Error; use dom::bindings::error::ErrorResult; -use dom::bindings::js::{JS, MutHeap, Root}; +use dom::bindings::js::{MutJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; -use dom::bluetooth::{AsyncBluetoothListener, response_async}; +use dom::bluetooth::{AsyncBluetoothListener, get_gatt_children, response_async}; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothuuid::{BluetoothServiceUUID, BluetoothUUID}; use dom::globalscope::GlobalScope; use dom::promise::Promise; -use ipc_channel::ipc::{self, IpcSender}; +use ipc_channel::ipc::IpcSender; use js::jsapi::JSContext; use std::cell::Cell; use std::rc::Rc; @@ -25,7 +24,7 @@ use std::rc::Rc; #[dom_struct] pub struct BluetoothRemoteGATTServer { reflector_: Reflector, - device: MutHeap<JS<BluetoothDevice>>, + device: MutJS<BluetoothDevice>, connected: Cell<bool>, } @@ -33,7 +32,7 @@ impl BluetoothRemoteGATTServer { pub fn new_inherited(device: &BluetoothDevice) -> BluetoothRemoteGATTServer { BluetoothRemoteGATTServer { reflector_: Reflector::new(), - device: MutHeap::new(device), + device: MutJS::new(device), connected: Cell::new(false), } } @@ -47,6 +46,10 @@ impl BluetoothRemoteGATTServer { fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> { self.global().as_window().bluetooth_thread() } + + pub fn set_connected(&self, connected: bool) { + self.connected.set(connected); + } } impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { @@ -67,17 +70,14 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { let p = Promise::new(&self.global()); let sender = response_async(&p, self); - // TODO: Step 2: Implement representedDevice internal slot for BluetoothDevice. - // TODO: Step 3: Check if the UA is currently using the Bluetooth system. // TODO: Step 4: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer. - // TODO: Step 5.1 - 5.2: Implement activeAlgorithms, representedDevice internal slots - // and the` garbage-collect the connection` algorithm. + // TODO: Step 5.1 - 5.2: Implement activeAlgorithms internal slot for BluetoothRemoteGATTServer. - // Note: Steps 5.1.1 and 5.1.3 are in components/bluetooth/lib.rs in the gatt_server_connect function. - // Steps 5.2.4 - 5.2.5 are in response function. + // Note: Steps 2, 5.1.1 and 5.1.3 are in components/bluetooth/lib.rs in the gatt_server_connect function. + // Steps 5.2.3 - 5.2.5 are in response function. self.get_bluetooth_thread().send( BluetoothRequest::GATTServerConnect(String::from(self.Device().Id()), sender)).unwrap(); // Step 5: return promise. @@ -90,135 +90,63 @@ impl BluetoothRemoteGATTServerMethods for BluetoothRemoteGATTServer { // Step 2. if !self.Connected() { - return Ok(()); + return Ok(()) } - let (sender, receiver) = ipc::channel().unwrap(); - self.get_bluetooth_thread().send( - BluetoothRequest::GATTServerDisconnect(String::from(self.Device().Id()), sender)).unwrap(); - let server = receiver.recv().unwrap(); - - // TODO: Step 3: Implement the `clean up the disconnected device` algorithm. - // TODO: Step 4: Implement representedDevice internal slot for BluetoothDevice. + // Step 3. + self.Device().clean_up_disconnected_device(); - // TODO: Step 5: Implement the `garbage-collect the connection` algorithm. - match server { - Ok(connected) => { - self.connected.set(connected); - Ok(()) - }, - Err(error) => { - Err(Error::from(error)) - }, - } + // Step 4 - 5: + self.Device().garbage_collect_the_connection() } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice fn GetPrimaryService(&self, service: BluetoothServiceUUID) -> Rc<Promise> { // TODO: Step 1: Implement the Permission API and the allowedServices BluetoothDevice internal slot. - // Subsequent steps are relative to https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::service(service) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedDevice internal slot for BluetoothDevice. - - // Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_primary_service function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetPrimaryService(String::from(self.Device().Id()), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, true, BluetoothUUID::service, Some(service), String::from(self.Device().Id()), + self.Device().Gatt().Connected(), GATTType::PrimaryService) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices fn GetPrimaryServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> { // TODO: Step 1: Implement the Permission API and the allowedServices BluetoothDevice internal slot. - // Subsequent steps are relative to https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - let mut uuid: Option<String> = None; - if let Some(s) = service { - // Step 1. - uuid = match BluetoothUUID::service(s) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedDevice internal slot for BluetoothDevice. + // Step 2. + get_gatt_children(self, false, BluetoothUUID::service, service, String::from(self.Device().Id()), + self.Connected(), GATTType::PrimaryService) - // Note: Steps 6 - 7 are implemented in components/bluetooth/lib.rs in get_primary_services function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetPrimaryServices(String::from(self.Device().Id()), uuid, sender)).unwrap(); - return p; } } impl AsyncBluetoothListener for BluetoothRemoteGATTServer { fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) { - let device = self.Device(); match response { // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-connect BluetoothResponse::GATTServerConnect(connected) => { + // Step 5.2.3 + if self.Device().is_represented_device_null() { + if let Err(e) = self.Device().garbage_collect_the_connection() { + return promise.reject_error(promise_cx, Error::from(e)); + } + return promise.reject_error(promise_cx, Error::Network); + } + // Step 5.2.4. self.connected.set(connected); // Step 5.2.5. promise.resolve_native(promise_cx, self); }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservice // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. - BluetoothResponse::GetPrimaryService(service) => { - let bt_service = device.get_or_create_service(&service, &self); - promise.resolve_native(promise_cx, &bt_service); - }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattserver-getprimaryservices - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - // Step 7. - BluetoothResponse::GetPrimaryServices(services_vec) => { + BluetoothResponse::GetPrimaryServices(services_vec, single) => { + let device = self.Device(); + if single { + promise.resolve_native(promise_cx, &device.get_or_create_service(&services_vec[0], &self)); + return; + } let mut services = vec!(); for service in services_vec { let bt_service = device.get_or_create_service(&service, &self); diff --git a/components/script/dom/bluetoothremotegattservice.rs b/components/script/dom/bluetoothremotegattservice.rs index f4aed154c7c..304cbb7d5b9 100644 --- a/components/script/dom/bluetoothremotegattservice.rs +++ b/components/script/dom/bluetoothremotegattservice.rs @@ -2,24 +2,22 @@ * 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 bluetooth_traits::{BluetoothRequest, BluetoothResponse}; -use bluetooth_traits::blocklist::{Blocklist, uuid_is_blocklisted}; +use bluetooth_traits::{BluetoothResponse, GATTType}; use dom::bindings::codegen::Bindings::BluetoothDeviceBinding::BluetoothDeviceMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServerBinding::BluetoothRemoteGATTServerMethods; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding; use dom::bindings::codegen::Bindings::BluetoothRemoteGATTServiceBinding::BluetoothRemoteGATTServiceMethods; use dom::bindings::codegen::Bindings::EventHandlerBinding::EventHandlerNonNull; -use dom::bindings::error::Error::{self, Network, Security}; -use dom::bindings::js::{JS, MutHeap, Root}; -use dom::bindings::reflector::{DomObject, reflect_dom_object}; +use dom::bindings::error::Error; +use dom::bindings::js::{MutJS, Root}; +use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; -use dom::bluetooth::{AsyncBluetoothListener, response_async}; +use dom::bluetooth::{AsyncBluetoothListener, get_gatt_children}; use dom::bluetoothdevice::BluetoothDevice; use dom::bluetoothuuid::{BluetoothCharacteristicUUID, BluetoothServiceUUID, BluetoothUUID}; use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::promise::Promise; -use ipc_channel::ipc::IpcSender; use js::jsapi::JSContext; use std::rc::Rc; @@ -27,7 +25,7 @@ use std::rc::Rc; #[dom_struct] pub struct BluetoothRemoteGATTService { eventtarget: EventTarget, - device: MutHeap<JS<BluetoothDevice>>, + device: MutJS<BluetoothDevice>, uuid: DOMString, is_primary: bool, instance_id: String, @@ -41,7 +39,7 @@ impl BluetoothRemoteGATTService { -> BluetoothRemoteGATTService { BluetoothRemoteGATTService { eventtarget: EventTarget::new_inherited(), - device: MutHeap::new(device), + device: MutJS::new(device), uuid: uuid, is_primary: is_primary, instance_id: instance_id, @@ -62,10 +60,6 @@ impl BluetoothRemoteGATTService { BluetoothRemoteGATTServiceBinding::Wrap) } - fn get_bluetooth_thread(&self) -> IpcSender<BluetoothRequest> { - self.global().as_window().bluetooth_thread() - } - fn get_instance_id(&self) -> String { self.instance_id.clone() } @@ -89,173 +83,39 @@ impl BluetoothRemoteGATTServiceMethods for BluetoothRemoteGATTService { #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetCharacteristic(&self, characteristic: BluetoothCharacteristicUUID) -> Rc<Promise> { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::characteristic(characteristic) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedService internal slot for BluetootRemoteGATTService. - - // Note: Steps 6 - 7 are implemented is components/bluetooth/lib.rs in get_characteristic function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetCharacteristic(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, true, BluetoothUUID::characteristic, Some(characteristic), self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::Characteristic) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetCharacteristics(&self, characteristic: Option<BluetoothCharacteristicUUID>) -> Rc<Promise> { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - let mut uuid: Option<String> = None; - if let Some(c) = characteristic { - // Step 1. - uuid = match BluetoothUUID::characteristic(c) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedService internal slot for BluetootRemoteGATTService. - - // Note: Steps 6 - 7 are implemented is components/bluetooth/lib.rs in get_characteristics function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetCharacteristics(self.get_instance_id(), uuid, sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::characteristic, characteristic, self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::Characteristic) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetIncludedService(&self, service: BluetoothServiceUUID) -> Rc<Promise> { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - - // Step 1. - let uuid = match BluetoothUUID::service(service) { - Ok(uuid) => uuid.to_string(), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedService internal slot for BluetootRemoteGATTService. - - // Note: Steps 6 - 7 are implemented is components/bluetooth/lib.rs in get_included_service function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetIncludedService(self.get_instance_id(), - uuid, - sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::service, Some(service), self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::IncludedService) } #[allow(unrooted_must_root)] // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren fn GetIncludedServices(&self, service: Option<BluetoothServiceUUID>) -> Rc<Promise> { - let p = Promise::new(&self.global()); - let p_cx = p.global().get_cx(); - let mut uuid: Option<String> = None; - if let Some(s) = service { - // Step 1. - uuid = match BluetoothUUID::service(s) { - Ok(uuid) => Some(uuid.to_string()), - Err(e) => { - p.reject_error(p_cx, e); - return p; - } - }; - if let Some(ref uuid) = uuid { - // Step 2. - if uuid_is_blocklisted(uuid.as_ref(), Blocklist::All) { - p.reject_error(p_cx, Security); - return p; - } - } - }; - - // Step 3 - 4. - if !self.Device().Gatt().Connected() { - p.reject_error(p_cx, Network); - return p; - } - - // TODO: Step 5: Implement representedService internal slot for BluetootRemoteGATTService. - - // Note: Steps 6 - 7 are implemented is components/bluetooth/lib.rs in get_included_services function - // and in handle_response function. - let sender = response_async(&p, self); - self.get_bluetooth_thread().send( - BluetoothRequest::GetIncludedServices(self.get_instance_id(), - uuid, - sender)).unwrap(); - return p; + get_gatt_children(self, false, BluetoothUUID::service, service, self.get_instance_id(), + self.Device().Gatt().Connected(), GATTType::IncludedService) } // https://webbluetoothcg.github.io/web-bluetooth/#dom-serviceeventhandlers-onserviceadded @@ -272,17 +132,14 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService { fn handle_response(&self, response: BluetoothResponse, promise_cx: *mut JSContext, promise: &Rc<Promise>) { let device = self.Device(); match response { - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristic // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. - BluetoothResponse::GetCharacteristic(characteristic) => { - let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self); - promise.resolve_native(promise_cx, &bt_characteristic); - }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getcharacteristics - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - // Step 7. - BluetoothResponse::GetCharacteristics(characteristics_vec) => { + BluetoothResponse::GetCharacteristics(characteristics_vec, single) => { + if single { + promise.resolve_native(promise_cx, + &device.get_or_create_characteristic(&characteristics_vec[0], &self)); + return; + } let mut characteristics = vec!(); for characteristic in characteristics_vec { let bt_characteristic = device.get_or_create_characteristic(&characteristic, &self); @@ -290,31 +147,19 @@ impl AsyncBluetoothListener for BluetoothRemoteGATTService { } promise.resolve_native(promise_cx, &characteristics); }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservice // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren // Step 7. - BluetoothResponse::GetIncludedService(service) => { - let s = - BluetoothRemoteGATTService::new(&self.global(), - &self.device.get(), - DOMString::from(service.uuid), - service.is_primary, - service.instance_id); - promise.resolve_native(promise_cx, &s); - }, - // https://webbluetoothcg.github.io/web-bluetooth/#dom-bluetoothremotegattservice-getincludedservices - // https://webbluetoothcg.github.io/web-bluetooth/#getgattchildren - // Step 7. - BluetoothResponse::GetIncludedServices(services_vec) => { - let s: Vec<Root<BluetoothRemoteGATTService>> = - services_vec.into_iter() - .map(|service| BluetoothRemoteGATTService::new(&self.global(), - &self.device.get(), - DOMString::from(service.uuid), - service.is_primary, - service.instance_id)) - .collect(); - promise.resolve_native(promise_cx, &s); + BluetoothResponse::GetIncludedServices(services_vec, single) => { + if single { + promise.resolve_native(promise_cx, &device.get_or_create_service(&services_vec[0], &device.Gatt())); + return; + } + let mut services = vec!(); + for service in services_vec { + let bt_service = device.get_or_create_service(&service, &device.Gatt()); + services.push(bt_service); + } + promise.resolve_native(promise_cx, &services); }, _ => promise.reject_error(promise_cx, Error::Type("Something went wrong...".to_owned())), } diff --git a/components/script/dom/browsingcontext.rs b/components/script/dom/browsingcontext.rs index 76b8badbe76..1a7f26253a0 100644 --- a/components/script/dom/browsingcontext.rs +++ b/components/script/dom/browsingcontext.rs @@ -4,7 +4,7 @@ use dom::bindings::conversions::{ToJSValConvertible, root_from_handleobject}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference}; use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor}; use dom::bindings::reflector::{DomObject, MutDomObject, Reflector}; use dom::bindings::trace::JSTraceable; @@ -43,7 +43,7 @@ pub struct BrowsingContext { /// The current active document. /// Note that the session history is stored in the constellation, /// in the script thread we just track the current active document. - active_document: MutNullableHeap<JS<Document>>, + active_document: MutNullableJS<Document>, /// The containing iframe element, if this is a same-origin iframe frame_element: Option<JS<Element>>, diff --git a/components/script/dom/characterdata.rs b/components/script/dom/characterdata.rs index 01f11e3ac50..a2c456317dc 100644 --- a/components/script/dom/characterdata.rs +++ b/components/script/dom/characterdata.rs @@ -19,8 +19,8 @@ use dom::element::Element; use dom::node::{Node, NodeDamage}; use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; +use servo_config::opts; use std::cell::Ref; -use util::opts; // https://dom.spec.whatwg.org/#characterdata #[dom_struct] diff --git a/components/script/dom/client.rs b/components/script/dom/client.rs index 496a13d32dc..d9d43ce7e01 100644 --- a/components/script/dom/client.rs +++ b/components/script/dom/client.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::Bindings::ClientBinding::{ClientMethods, Wrap}; use dom::bindings::codegen::Bindings::ClientBinding::FrameType; -use dom::bindings::js::{JS, Root, MutNullableHeap}; +use dom::bindings::js::{Root, MutNullableJS}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::{DOMString, USVString}; use dom::serviceworker::ServiceWorker; @@ -16,7 +16,7 @@ use uuid::Uuid; #[dom_struct] pub struct Client { reflector_: Reflector, - active_worker: MutNullableHeap<JS<ServiceWorker>>, + active_worker: MutNullableJS<ServiceWorker>, url: ServoUrl, frame_type: FrameType, #[ignore_heap_size_of = "Defined in uuid"] diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs index 42a3c8158a1..7c9a9eeea9c 100644 --- a/components/script/dom/create.rs +++ b/components/script/dom/create.rs @@ -78,7 +78,7 @@ use dom::htmlunknownelement::HTMLUnknownElement; use dom::htmlvideoelement::HTMLVideoElement; use dom::svgsvgelement::SVGSVGElement; use html5ever_atoms::{Prefix, QualName}; -use util::prefs::PREFS; +use servo_config::prefs::PREFS; fn create_svg_element(name: QualName, prefix: Option<DOMString>, @@ -244,7 +244,7 @@ fn create_html_element(name: QualName, local_name!("span") => make!(HTMLSpanElement), local_name!("strike") => make!(HTMLElement), local_name!("strong") => make!(HTMLElement), - local_name!("style") => make!(HTMLStyleElement), + local_name!("style") => make!(HTMLStyleElement, creator), local_name!("sub") => make!(HTMLElement), local_name!("summary") => make!(HTMLElement), local_name!("sup") => make!(HTMLElement), diff --git a/components/script/dom/crypto.rs b/components/script/dom/crypto.rs index 4120456c77c..57b561e8a58 100644 --- a/components/script/dom/crypto.rs +++ b/components/script/dom/crypto.rs @@ -6,7 +6,6 @@ use core::nonzero::NonZero; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CryptoBinding; use dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods; -use dom::bindings::conversions::array_buffer_view_data; use dom::bindings::error::{Error, Fallible}; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflector, reflect_dom_object}; @@ -46,9 +45,10 @@ impl CryptoMethods for Crypto { input: *mut JSObject) -> Fallible<NonZero<*mut JSObject>> { assert!(!input.is_null()); - let mut data = match array_buffer_view_data::<u8>(input) { - Some(data) => data, - None => { + typedarray!(in(_cx) let mut array_buffer_view: ArrayBufferView = input); + let mut data = match array_buffer_view.as_mut() { + Ok(x) => x.as_mut_slice(), + Err(_) => { return Err(Error::Type("Argument to Crypto.getRandomValues is not an ArrayBufferView" .to_owned())); } diff --git a/components/script/dom/cssgroupingrule.rs b/components/script/dom/cssgroupingrule.rs index e8651c551d3..b793b04b28c 100644 --- a/components/script/dom/cssgroupingrule.rs +++ b/components/script/dom/cssgroupingrule.rs @@ -2,17 +2,15 @@ * 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::codegen::Bindings::CSSGroupingRuleBinding; use dom::bindings::codegen::Bindings::CSSGroupingRuleBinding::CSSGroupingRuleMethods; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; -use dom::bindings::reflector::{DomObject, reflect_dom_object}; +use dom::bindings::js::{MutNullableJS, Root}; +use dom::bindings::reflector::DomObject; use dom::bindings::str::DOMString; use dom::cssrule::CSSRule; use dom::cssrulelist::{CSSRuleList, RulesSource}; use dom::cssstylesheet::CSSStyleSheet; -use dom::window::Window; use parking_lot::RwLock; use std::sync::Arc; use style::stylesheets::CssRules as StyleCssRules; @@ -22,7 +20,7 @@ pub struct CSSGroupingRule { cssrule: CSSRule, #[ignore_heap_size_of = "Arc"] rules: Arc<RwLock<StyleCssRules>>, - rulelist: MutNullableHeap<JS<CSSRuleList>>, + rulelist: MutNullableJS<CSSRuleList>, } impl CSSGroupingRule { @@ -31,18 +29,10 @@ impl CSSGroupingRule { CSSGroupingRule { cssrule: CSSRule::new_inherited(parent_stylesheet), rules: rules, - rulelist: MutNullableHeap::new(None), + rulelist: MutNullableJS::new(None), } } - #[allow(unrooted_must_root)] - pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet, - rules: Arc<RwLock<StyleCssRules>>) -> Root<CSSGroupingRule> { - reflect_dom_object(box CSSGroupingRule::new_inherited(parent_stylesheet, rules), - window, - CSSGroupingRuleBinding::Wrap) - } - fn rulelist(&self) -> Root<CSSRuleList> { let parent_stylesheet = self.upcast::<CSSRule>().parent_stylesheet(); self.rulelist.or_init(|| CSSRuleList::new(self.global().as_window(), diff --git a/components/script/dom/cssimportrule.rs b/components/script/dom/cssimportrule.rs new file mode 100644 index 00000000000..582a6f597f9 --- /dev/null +++ b/components/script/dom/cssimportrule.rs @@ -0,0 +1,53 @@ +/* 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::bindings::codegen::Bindings::CSSImportRuleBinding; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::cssrule::{CSSRule, SpecificCSSRule}; +use dom::cssstylesheet::CSSStyleSheet; +use dom::window::Window; +use parking_lot::RwLock; +use std::sync::Arc; +use style::stylesheets::ImportRule; +use style_traits::ToCss; + +#[dom_struct] +pub struct CSSImportRule { + cssrule: CSSRule, + #[ignore_heap_size_of = "Arc"] + import_rule: Arc<RwLock<ImportRule>>, +} + +impl CSSImportRule { + fn new_inherited(parent_stylesheet: &CSSStyleSheet, + import_rule: Arc<RwLock<ImportRule>>) + -> Self { + CSSImportRule { + cssrule: CSSRule::new_inherited(parent_stylesheet), + import_rule: import_rule, + } + } + + #[allow(unrooted_must_root)] + pub fn new(window: &Window, + parent_stylesheet: &CSSStyleSheet, + import_rule: Arc<RwLock<ImportRule>>) -> Root<Self> { + reflect_dom_object(box Self::new_inherited(parent_stylesheet, import_rule), + window, + CSSImportRuleBinding::Wrap) + } +} + +impl SpecificCSSRule for CSSImportRule { + fn ty(&self) -> u16 { + use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleConstants; + CSSRuleConstants::IMPORT_RULE + } + + fn get_css(&self) -> DOMString { + self.import_rule.read().to_css_string().into() + } +} diff --git a/components/script/dom/csskeyframesrule.rs b/components/script/dom/csskeyframesrule.rs index 46ed79435c1..1c94e0e99fb 100644 --- a/components/script/dom/csskeyframesrule.rs +++ b/components/script/dom/csskeyframesrule.rs @@ -5,8 +5,9 @@ use cssparser::Parser; use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding; use dom::bindings::codegen::Bindings::CSSKeyframesRuleBinding::CSSKeyframesRuleMethods; +use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::csskeyframerule::CSSKeyframeRule; @@ -15,6 +16,7 @@ use dom::cssrulelist::{CSSRuleList, RulesSource}; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use parking_lot::RwLock; +use servo_atoms::Atom; use std::sync::Arc; use style::keyframes::{Keyframe, KeyframeSelector}; use style::parser::ParserContextExtraData; @@ -26,7 +28,7 @@ pub struct CSSKeyframesRule { cssrule: CSSRule, #[ignore_heap_size_of = "Arc"] keyframesrule: Arc<RwLock<KeyframesRule>>, - rulelist: MutNullableHeap<JS<CSSRuleList>>, + rulelist: MutNullableJS<CSSRuleList>, } impl CSSKeyframesRule { @@ -35,7 +37,7 @@ impl CSSKeyframesRule { CSSKeyframesRule { cssrule: CSSRule::new_inherited(parent_stylesheet), keyframesrule: keyframesrule, - rulelist: MutNullableHeap::new(None), + rulelist: MutNullableJS::new(None), } } @@ -101,6 +103,27 @@ impl CSSKeyframesRuleMethods for CSSKeyframesRule { self.rulelist().item(idx as u32) }).and_then(Root::downcast) } + + // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name + fn Name(&self) -> DOMString { + DOMString::from(&*self.keyframesrule.read().name) + } + + // https://drafts.csswg.org/css-animations/#dom-csskeyframesrule-name + fn SetName(&self, value: DOMString) -> ErrorResult { + // https://github.com/w3c/csswg-drafts/issues/801 + // Setting this property to a CSS-wide keyword or `none` will + // throw a Syntax Error. + match_ignore_ascii_case! { value, + "initial" => return Err(Error::Syntax), + "inherit" => return Err(Error::Syntax), + "unset" => return Err(Error::Syntax), + "none" => return Err(Error::Syntax), + _ => () + } + self.keyframesrule.write().name = Atom::from(value); + Ok(()) + } } impl SpecificCSSRule for CSSKeyframesRule { diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs index 0e1fc145e7d..b6b04dde9d8 100644 --- a/components/script/dom/cssmediarule.rs +++ b/components/script/dom/cssmediarule.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::Bindings::CSSMediaRuleBinding; use dom::bindings::codegen::Bindings::CSSMediaRuleBinding::CSSMediaRuleMethods; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::cssgroupingrule::CSSGroupingRule; @@ -22,7 +22,7 @@ pub struct CSSMediaRule { cssrule: CSSGroupingRule, #[ignore_heap_size_of = "Arc"] mediarule: Arc<RwLock<MediaRule>>, - medialist: MutNullableHeap<JS<MediaList>>, + medialist: MutNullableJS<MediaList>, } impl CSSMediaRule { @@ -32,7 +32,7 @@ impl CSSMediaRule { CSSMediaRule { cssrule: CSSGroupingRule::new_inherited(parent_stylesheet, list), mediarule: mediarule, - medialist: MutNullableHeap::new(None), + medialist: MutNullableJS::new(None), } } diff --git a/components/script/dom/cssrule.rs b/components/script/dom/cssrule.rs index 603354c8621..8323d7e22b0 100644 --- a/components/script/dom/cssrule.rs +++ b/components/script/dom/cssrule.rs @@ -2,13 +2,13 @@ * 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::codegen::Bindings::CSSRuleBinding; use dom::bindings::codegen::Bindings::CSSRuleBinding::CSSRuleMethods; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root}; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::Reflector; use dom::bindings::str::DOMString; use dom::cssfontfacerule::CSSFontFaceRule; +use dom::cssimportrule::CSSImportRule; use dom::csskeyframerule::CSSKeyframeRule; use dom::csskeyframesrule::CSSKeyframesRule; use dom::cssmediarule::CSSMediaRule; @@ -42,13 +42,6 @@ impl CSSRule { } } - #[allow(unrooted_must_root)] - pub fn new(window: &Window, parent_stylesheet: &CSSStyleSheet) -> Root<CSSRule> { - reflect_dom_object(box CSSRule::new_inherited(parent_stylesheet), - window, - CSSRuleBinding::Wrap) - } - pub fn as_specific(&self) -> &SpecificCSSRule { if let Some(rule) = self.downcast::<CSSStyleRule>() { rule as &SpecificCSSRule @@ -64,6 +57,8 @@ impl CSSRule { rule as &SpecificCSSRule } else if let Some(rule) = self.downcast::<CSSKeyframeRule>() { rule as &SpecificCSSRule + } else if let Some(rule) = self.downcast::<CSSImportRule>() { + rule as &SpecificCSSRule } else { unreachable!() } @@ -75,6 +70,7 @@ impl CSSRule { rule: StyleCssRule) -> Root<CSSRule> { // be sure to update the match in as_specific when this is updated match rule { + StyleCssRule::Import(s) => Root::upcast(CSSImportRule::new(window, parent_stylesheet, s)), StyleCssRule::Style(s) => Root::upcast(CSSStyleRule::new(window, parent_stylesheet, s)), StyleCssRule::FontFace(s) => Root::upcast(CSSFontFaceRule::new(window, parent_stylesheet, s)), StyleCssRule::Keyframes(s) => Root::upcast(CSSKeyframesRule::new(window, parent_stylesheet, s)), diff --git a/components/script/dom/cssrulelist.rs b/components/script/dom/cssrulelist.rs index 988f839a87a..f667638b022 100644 --- a/components/script/dom/cssrulelist.rs +++ b/components/script/dom/cssrulelist.rs @@ -6,7 +6,7 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CSSRuleListBinding; use dom::bindings::codegen::Bindings::CSSRuleListBinding::CSSRuleListMethods; use dom::bindings::error::{Error, ErrorResult, Fallible}; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::csskeyframerule::CSSKeyframeRule; use dom::cssrule::CSSRule; @@ -38,7 +38,7 @@ pub struct CSSRuleList { parent_stylesheet: JS<CSSStyleSheet>, #[ignore_heap_size_of = "Arc"] rules: RulesSource, - dom_rules: DOMRefCell<Vec<MutNullableHeap<JS<CSSRule>>>> + dom_rules: DOMRefCell<Vec<MutNullableJS<CSSRule>>> } pub enum RulesSource { @@ -51,10 +51,10 @@ impl CSSRuleList { pub fn new_inherited(parent_stylesheet: &CSSStyleSheet, rules: RulesSource) -> CSSRuleList { let dom_rules = match rules { RulesSource::Rules(ref rules) => { - rules.read().0.iter().map(|_| MutNullableHeap::new(None)).collect() + rules.read().0.iter().map(|_| MutNullableJS::new(None)).collect() } RulesSource::Keyframes(ref rules) => { - rules.read().keyframes.iter().map(|_| MutNullableHeap::new(None)).collect() + rules.read().keyframes.iter().map(|_| MutNullableJS::new(None)).collect() } }; @@ -92,7 +92,7 @@ impl CSSRuleList { let parent_stylesheet = &*self.parent_stylesheet; let dom_rule = CSSRule::new_specific(&window, parent_stylesheet, new_rule); - self.dom_rules.borrow_mut().insert(index, MutNullableHeap::new(Some(&*dom_rule))); + self.dom_rules.borrow_mut().insert(index, MutNullableJS::new(Some(&*dom_rule))); Ok((idx)) } @@ -158,7 +158,7 @@ impl CSSRuleList { if let RulesSource::Rules(..) = self.rules { panic!("Can only call append_lazy_rule with keyframes-backed CSSRules"); } - self.dom_rules.borrow_mut().push(MutNullableHeap::new(None)); + self.dom_rules.borrow_mut().push(MutNullableJS::new(None)); } } diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index c6280597b17..7cd63aa12b0 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -3,6 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::Bindings::CSSStyleDeclarationBinding::{self, CSSStyleDeclarationMethods}; +use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root}; @@ -12,12 +13,11 @@ use dom::element::Element; use dom::node::{Node, NodeDamage, window_from_node}; use dom::window::Window; use parking_lot::RwLock; -use servo_atoms::Atom; use std::ascii::AsciiExt; use std::sync::Arc; use style::parser::ParserContextExtraData; -use style::properties::{Shorthand, Importance, PropertyDeclarationBlock}; -use style::properties::{is_supported_property, parse_one_declaration, parse_style_attribute}; +use style::properties::{Importance, PropertyDeclarationBlock, PropertyId, LonghandId, ShorthandId}; +use style::properties::{parse_one_declaration, parse_style_attribute}; use style::selector_parser::PseudoElement; use style_traits::ToCss; @@ -25,11 +25,59 @@ use style_traits::ToCss; #[dom_struct] pub struct CSSStyleDeclaration { reflector_: Reflector, - owner: JS<Element>, + owner: CSSStyleOwner, readonly: bool, pseudo: Option<PseudoElement>, } +#[derive(HeapSizeOf, JSTraceable)] +#[must_root] +pub enum CSSStyleOwner { + Element(JS<Element>), + CSSStyleRule(JS<Window>, + #[ignore_heap_size_of = "Arc"] + Arc<RwLock<PropertyDeclarationBlock>>), +} + +impl CSSStyleOwner { + fn style_attribute(&self) -> Option<Arc<RwLock<PropertyDeclarationBlock>>> { + match *self { + CSSStyleOwner::Element(ref el) => { + if let Some(ref pdb) = *el.style_attribute().borrow() { + Some(pdb.clone()) + } else { + None + } + } + CSSStyleOwner::CSSStyleRule(_, ref pdb) => { + Some(pdb.clone()) + } + } + } + + fn window(&self) -> Root<Window> { + match *self { + CSSStyleOwner::Element(ref el) => window_from_node(&**el), + CSSStyleOwner::CSSStyleRule(ref window, _) => Root::from_ref(&**window), + } + } + + fn flush_style(&self, pdb: &PropertyDeclarationBlock) { + if let CSSStyleOwner::Element(ref el) = *self { + el.set_style_attr(pdb.to_css_string()); + } + } + + fn dirty(&self) { + match *self { + CSSStyleOwner::Element(ref el) => + el.upcast::<Node>().dirty(NodeDamage::NodeStyleDamaged), + CSSStyleOwner::CSSStyleRule(ref window, _) => + window.Document().invalidate_stylesheets(), + } + } +} + #[derive(PartialEq, HeapSizeOf)] pub enum CSSModificationAccess { ReadWrite, @@ -37,33 +85,35 @@ pub enum CSSModificationAccess { } macro_rules! css_properties( - ( $([$getter:ident, $setter:ident, $cssprop:expr]),* ) => ( + ( $([$getter:ident, $setter:ident, $id:expr],)* ) => ( $( fn $getter(&self) -> DOMString { - self.GetPropertyValue(DOMString::from($cssprop)) + self.get_property_value($id) } fn $setter(&self, value: DOMString) -> ErrorResult { - self.SetPropertyValue(DOMString::from($cssprop), value) + self.set_property($id, value, DOMString::new()) } )* ); ); impl CSSStyleDeclaration { - pub fn new_inherited(owner: &Element, + #[allow(unrooted_must_root)] + pub fn new_inherited(owner: CSSStyleOwner, pseudo: Option<PseudoElement>, modification_access: CSSModificationAccess) -> CSSStyleDeclaration { CSSStyleDeclaration { reflector_: Reflector::new(), - owner: JS::from_ref(owner), + owner: owner, readonly: modification_access == CSSModificationAccess::Readonly, pseudo: pseudo, } } + #[allow(unrooted_must_root)] pub fn new(global: &Window, - owner: &Element, + owner: CSSStyleOwner, pseudo: Option<PseudoElement>, modification_access: CSSModificationAccess) -> Root<CSSStyleDeclaration> { @@ -74,108 +124,59 @@ impl CSSStyleDeclaration { CSSStyleDeclarationBinding::Wrap) } - fn get_computed_style(&self, property: &Atom) -> Option<DOMString> { - let node = self.owner.upcast::<Node>(); - if !node.is_in_doc() { - // TODO: Node should be matched against the style rules of this window. - // Firefox is currently the only browser to implement this. - return None; + fn get_computed_style(&self, property: PropertyId) -> DOMString { + match self.owner { + CSSStyleOwner::CSSStyleRule(..) => + panic!("get_computed_style called on CSSStyleDeclaration with a CSSStyleRule owner"), + CSSStyleOwner::Element(ref el) => { + let node = el.upcast::<Node>(); + if !node.is_in_doc() { + // TODO: Node should be matched against the style rules of this window. + // Firefox is currently the only browser to implement this. + return DOMString::new(); + } + let addr = node.to_trusted_node_address(); + window_from_node(node).resolved_style_query(addr, self.pseudo.clone(), property) + } } - let addr = node.to_trusted_node_address(); - window_from_node(&*self.owner).resolved_style_query(addr, self.pseudo.clone(), property) - } -} - -impl CSSStyleDeclarationMethods for CSSStyleDeclaration { - // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length - fn Length(&self) -> u32 { - let elem = self.owner.upcast::<Element>(); - let len = match *elem.style_attribute().borrow() { - Some(ref lock) => lock.read().declarations.len(), - None => 0, - }; - len as u32 - } - - // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item - fn Item(&self, index: u32) -> DOMString { - self.IndexedGetter(index).unwrap_or_default() } - // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue - fn GetPropertyValue(&self, mut property: DOMString) -> DOMString { + fn get_property_value(&self, id: PropertyId) -> DOMString { if self.readonly { // Readonly style declarations are used for getComputedStyle. - property.make_ascii_lowercase(); - let property = Atom::from(property); - return self.get_computed_style(&property).unwrap_or(DOMString::new()); + return self.get_computed_style(id); } - let style_attribute = self.owner.style_attribute().borrow(); - let style_attribute = if let Some(ref lock) = *style_attribute { - lock.read() + if let Some(ref lock) = self.owner.style_attribute() { + let mut string = String::new(); + lock.read().property_value_to_css(&id, &mut string).unwrap(); + DOMString::from(string) } else { // No style attribute is like an empty style attribute: no matching declaration. - return DOMString::new() - }; - - let mut string = String::new(); - style_attribute.property_value_to_css(&property, &mut string).unwrap(); - DOMString::from(string) - } - - // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority - fn GetPropertyPriority(&self, property: DOMString) -> DOMString { - let style_attribute = self.owner.style_attribute().borrow(); - let style_attribute = if let Some(ref lock) = *style_attribute { - lock.read() - } else { - // No style attribute is like an empty style attribute: no matching declaration. - return DOMString::new() - }; - - if style_attribute.property_priority(&property).important() { - DOMString::from("important") - } else { - // Step 4 DOMString::new() } } - // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty - fn SetProperty(&self, - property: DOMString, - value: DOMString, - priority: DOMString) - -> ErrorResult { + fn set_property(&self, id: PropertyId, value: DOMString, priority: DOMString) -> ErrorResult { // Step 1 if self.readonly { return Err(Error::NoModificationAllowed); } - // Step 3 - if !is_supported_property(&property) { - return Ok(()); - } - - let mut style_attribute = self.owner.style_attribute().borrow_mut(); - if value.is_empty() { // Step 4 - let empty; - { - let mut style_attribute = if let Some(ref lock) = *style_attribute { - lock.write() + let empty = { + if let Some(ref lock) = self.owner.style_attribute() { + let mut style_attribute = lock.write(); + style_attribute.remove_property(&id); + style_attribute.declarations.is_empty() } else { // No style attribute is like an empty style attribute: nothing to remove. return Ok(()) - }; - - style_attribute.remove_property(&property); - empty = style_attribute.declarations.is_empty() - } - if empty { - *style_attribute = None; + } + }; + if let (&CSSStyleOwner::Element(ref el), true) = (&self.owner, empty) { + *el.style_attribute().borrow_mut() = None; } } else { // Step 5 @@ -186,29 +187,28 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { }; // Step 6 - let window = window_from_node(&*self.owner); + let window = self.owner.window(); let declarations = - parse_one_declaration(&property, &value, &window.get_url(), window.css_error_reporter(), + parse_one_declaration(id, &value, &window.get_url(), window.css_error_reporter(), ParserContextExtraData::default()); // Step 7 - let declarations = if let Ok(declarations) = declarations { - declarations - } else { - return Ok(()); + let declarations = match declarations { + Ok(declarations) => declarations, + Err(_) => return Ok(()) }; // Step 8 // Step 9 - match *style_attribute { + match self.owner.style_attribute() { Some(ref lock) => { let mut style_attribute = lock.write(); for declaration in declarations { style_attribute.set_parsed_declaration(declaration, importance); } - self.owner.set_style_attr(style_attribute.to_css_string()); + self.owner.flush_style(&style_attribute); } - ref mut option @ None => { + None => { let important_count = if importance.important() { declarations.len() as u32 } else { @@ -218,16 +218,80 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { declarations: declarations.into_iter().map(|d| (d, importance)).collect(), important_count: important_count, }; - self.owner.set_style_attr(block.to_css_string()); - *option = Some(Arc::new(RwLock::new(block))); + if let CSSStyleOwner::Element(ref el) = self.owner { + el.set_style_attr(block.to_css_string()); + *el.style_attribute().borrow_mut() = Some(Arc::new(RwLock::new(block))); + } else { + panic!("set_property called on a CSSStyleDeclaration with a non-Element owner"); + } } } } - let node = self.owner.upcast::<Node>(); - node.dirty(NodeDamage::NodeStyleDamaged); + self.owner.dirty(); Ok(()) } +} + +impl CSSStyleDeclarationMethods for CSSStyleDeclaration { + // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-length + fn Length(&self) -> u32 { + self.owner.style_attribute().as_ref().map_or(0, |lock| lock.read().declarations.len() as u32) + } + + // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-item + fn Item(&self, index: u32) -> DOMString { + self.IndexedGetter(index).unwrap_or_default() + } + + // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertyvalue + fn GetPropertyValue(&self, property: DOMString) -> DOMString { + let id = if let Ok(id) = PropertyId::parse(property.into()) { + id + } else { + // Unkwown property + return DOMString::new() + }; + self.get_property_value(id) + } + + // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-getpropertypriority + fn GetPropertyPriority(&self, property: DOMString) -> DOMString { + let id = if let Ok(id) = PropertyId::parse(property.into()) { + id + } else { + // Unkwown property + return DOMString::new() + }; + + if let Some(ref lock) = self.owner.style_attribute() { + if lock.read().property_priority(&id).important() { + DOMString::from("important") + } else { + // Step 4 + DOMString::new() + } + } else { + // No style attribute is like an empty style attribute: no matching declaration. + DOMString::new() + } + } + + // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setproperty + fn SetProperty(&self, + property: DOMString, + value: DOMString, + priority: DOMString) + -> ErrorResult { + // Step 3 + let id = if let Ok(id) = PropertyId::parse(property.into()) { + id + } else { + // Unknown property + return Ok(()) + }; + self.set_property(id, value, priority) + } // https://dev.w3.org/csswg/cssom/#dom-cssstyledeclaration-setpropertypriority fn SetPropertyPriority(&self, property: DOMString, priority: DOMString) -> ErrorResult { @@ -237,9 +301,12 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { } // Step 2 & 3 - if !is_supported_property(&property) { - return Ok(()); - } + let id = if let Ok(id) = PropertyId::parse(property.into()) { + id + } else { + // Unkwown property + return Ok(()) + }; // Step 4 let importance = match &*priority { @@ -248,19 +315,14 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { _ => return Ok(()), }; - let style_attribute = self.owner.style_attribute().borrow(); - if let Some(ref lock) = *style_attribute { + if let Some(ref lock) = self.owner.style_attribute() { let mut style_attribute = lock.write(); // Step 5 & 6 - match Shorthand::from_name(&property) { - Some(shorthand) => style_attribute.set_importance(shorthand.longhands(), importance), - None => style_attribute.set_importance(&[&*property], importance), - } + style_attribute.set_importance(&id, importance); - self.owner.set_style_attr(style_attribute.to_css_string()); - let node = self.owner.upcast::<Node>(); - node.dirty(NodeDamage::NodeStyleDamaged); + self.owner.flush_style(&style_attribute); + self.owner.dirty(); } Ok(()) } @@ -277,31 +339,33 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { return Err(Error::NoModificationAllowed); } - let mut style_attribute = self.owner.style_attribute().borrow_mut(); + let id = if let Ok(id) = PropertyId::parse(property.into()) { + id + } else { + // Unkwown property, cannot be there to remove. + return Ok(DOMString::new()) + }; + let mut string = String::new(); - let empty; - { - let mut style_attribute = if let Some(ref lock) = *style_attribute { - lock.write() + let empty = { + if let Some(ref lock) = self.owner.style_attribute() { + let mut style_attribute = lock.write(); + // Step 3 + style_attribute.property_value_to_css(&id, &mut string).unwrap(); + + // Step 4 & 5 + style_attribute.remove_property(&id); + self.owner.flush_style(&style_attribute); + style_attribute.declarations.is_empty() } else { // No style attribute is like an empty style attribute: nothing to remove. return Ok(DOMString::new()) - }; - - // Step 3 - style_attribute.property_value_to_css(&property, &mut string).unwrap(); - - // Step 4 & 5 - style_attribute.remove_property(&property); - self.owner.set_style_attr(style_attribute.to_css_string()); - empty = style_attribute.declarations.is_empty() - } - if empty { - *style_attribute = None; + } + }; + if let (&CSSStyleOwner::Element(ref el), true) = (&self.owner, empty) { + *el.style_attribute().borrow_mut() = None; } - - let node = self.owner.upcast::<Node>(); - node.dirty(NodeDamage::NodeStyleDamaged); + self.owner.dirty(); // Step 6 Ok(DOMString::from(string)) @@ -319,11 +383,8 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // https://dev.w3.org/csswg/cssom/#the-cssstyledeclaration-interface 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(|lock| { - lock.read().declarations.get(index).map(|entry| { + self.owner.style_attribute().as_ref().and_then(|lock| { + lock.read().declarations.get(index as usize).map(|entry| { let (ref declaration, importance) = *entry; let mut css = declaration.to_css_string(); if importance.important() { @@ -336,19 +397,13 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext fn CssText(&self) -> DOMString { - let elem = self.owner.upcast::<Element>(); - let style_attribute = elem.style_attribute().borrow(); - - if let Some(lock) = style_attribute.as_ref() { - DOMString::from(lock.read().to_css_string()) - } else { - DOMString::new() - } + self.owner.style_attribute().as_ref().map_or(DOMString::new(), |lock| + DOMString::from(lock.read().to_css_string())) } // https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-csstext fn SetCssText(&self, value: DOMString) -> ErrorResult { - let window = window_from_node(self.owner.upcast::<Node>()); + let window = self.owner.window(); // Step 1 if self.readonly { @@ -358,15 +413,16 @@ impl CSSStyleDeclarationMethods for CSSStyleDeclaration { // Step 3 let decl_block = parse_style_attribute(&value, &window.get_url(), window.css_error_reporter(), ParserContextExtraData::default()); - *self.owner.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() { - self.owner.set_style_attr(String::new()); - None // Step 2 - } else { - self.owner.set_style_attr(decl_block.to_css_string()); - Some(Arc::new(RwLock::new(decl_block))) - }; - let node = self.owner.upcast::<Node>(); - node.dirty(NodeDamage::NodeStyleDamaged); + if let CSSStyleOwner::Element(ref el) = self.owner { + *el.style_attribute().borrow_mut() = if decl_block.declarations.is_empty() { + el.set_style_attr(String::new()); + None // Step 2 + } else { + el.set_style_attr(decl_block.to_css_string()); + Some(Arc::new(RwLock::new(decl_block))) + }; + } + self.owner.dirty(); Ok(()) } diff --git a/components/script/dom/cssstylerule.rs b/components/script/dom/cssstylerule.rs index 091704f42d5..3e23864ae61 100644 --- a/components/script/dom/cssstylerule.rs +++ b/components/script/dom/cssstylerule.rs @@ -2,11 +2,12 @@ * 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::codegen::Bindings::CSSStyleRuleBinding; -use dom::bindings::js::Root; -use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::codegen::Bindings::CSSStyleRuleBinding::{self, CSSStyleRuleMethods}; +use dom::bindings::js::{JS, MutNullableJS, Root}; +use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::cssrule::{CSSRule, SpecificCSSRule}; +use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSStyleOwner}; use dom::cssstylesheet::CSSStyleSheet; use dom::window::Window; use parking_lot::RwLock; @@ -19,6 +20,7 @@ pub struct CSSStyleRule { cssrule: CSSRule, #[ignore_heap_size_of = "Arc"] stylerule: Arc<RwLock<StyleRule>>, + style_decl: MutNullableJS<CSSStyleDeclaration>, } impl CSSStyleRule { @@ -27,6 +29,7 @@ impl CSSStyleRule { CSSStyleRule { cssrule: CSSRule::new_inherited(parent_stylesheet), stylerule: stylerule, + style_decl: Default::default(), } } @@ -49,3 +52,16 @@ impl SpecificCSSRule for CSSStyleRule { self.stylerule.read().to_css_string().into() } } + +impl CSSStyleRuleMethods for CSSStyleRule { + // https://drafts.csswg.org/cssom/#dom-cssstylerule-style + fn Style(&self) -> Root<CSSStyleDeclaration> { + self.style_decl.or_init(|| { + CSSStyleDeclaration::new(self.global().as_window(), + CSSStyleOwner::CSSStyleRule(JS::from_ref(self.global().as_window()), + self.stylerule.read().block.clone()), + None, + CSSModificationAccess::ReadWrite) + }) + } +} diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs index 106b9b5805d..908cfad2cd5 100644 --- a/components/script/dom/cssstylesheet.rs +++ b/components/script/dom/cssstylesheet.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::CSSStyleSheetBinding; use dom::bindings::codegen::Bindings::CSSStyleSheetBinding::CSSStyleSheetMethods; use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods; use dom::bindings::error::{ErrorResult, Fallible}; -use dom::bindings::js::{JS, Root, MutNullableHeap}; +use dom::bindings::js::{JS, MutNullableJS, Root}; use dom::bindings::reflector::{reflect_dom_object, DomObject}; use dom::bindings::str::DOMString; use dom::cssrulelist::{CSSRuleList, RulesSource}; @@ -20,7 +20,7 @@ use style::stylesheets::Stylesheet as StyleStyleSheet; pub struct CSSStyleSheet { stylesheet: StyleSheet, owner: JS<Element>, - rulelist: MutNullableHeap<JS<CSSRuleList>>, + rulelist: MutNullableJS<CSSRuleList>, #[ignore_heap_size_of = "Arc"] style_stylesheet: Arc<StyleStyleSheet>, } @@ -34,7 +34,7 @@ impl CSSStyleSheet { CSSStyleSheet { stylesheet: StyleSheet::new_inherited(type_, href, title), owner: JS::from_ref(owner), - rulelist: MutNullableHeap::new(None), + rulelist: MutNullableJS::new(None), style_stylesheet: stylesheet, } } diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 96ee1f871eb..911847aadb8 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -38,8 +38,8 @@ use std::mem::replace; use std::sync::{Arc, Mutex}; use std::sync::atomic::AtomicBool; use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel}; +use std::thread; use style::thread_state; -use util::thread::spawn_named; /// Set the `worker` field of a related DedicatedWorkerGlobalScope object to a particular /// value for the duration of this object's lifetime. This ensures that the related Worker @@ -160,7 +160,7 @@ impl DedicatedWorkerGlobalScope { let name = format!("WebWorker for {}", serialized_worker_url); let top_level_frame_id = FrameId::installed(); - spawn_named(name, move || { + thread::Builder::new().name(name).spawn(move || { thread_state::initialize(thread_state::SCRIPT | thread_state::IN_WORKER); if let Some(top_level_frame_id) = top_level_frame_id { @@ -243,7 +243,7 @@ impl DedicatedWorkerGlobalScope { global.handle_event(event); } }, reporter_name, parent_sender, CommonScriptMsg::CollectReports); - }); + }).expect("Thread spawning failed"); } pub fn script_chan(&self) -> Box<ScriptChan + Send> { diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 9704b4ba0ab..6f8f2435311 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -24,7 +24,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::{FrameRequestCallback, Scro use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId}; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, LayoutJS, MutNullableJS, Root}; use dom::bindings::js::RootedReference; use dom::bindings::num::Finite; use dom::bindings::refcounted::{Trusted, TrustedPromise}; @@ -91,8 +91,9 @@ use encoding::EncodingRef; use encoding::all::UTF_8; use euclid::point::Point2D; use gfx_traits::ScrollRootId; -use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks, QuirksMode}; use html5ever_atoms::{LocalName, QualName}; +use hyper::header::{Header, SetCookie}; +use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{JSContext, JSObject, JSRuntime}; use js::jsapi::JS_GetRuntime; @@ -113,6 +114,7 @@ use script_traits::{ScriptMsg as ConstellationMsg, TouchpadPressurePhase}; use script_traits::{TouchEventType, TouchId}; use script_traits::UntrustedNodeAddress; use servo_atoms::Atom; +use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -126,14 +128,13 @@ use std::rc::Rc; use std::sync::Arc; use std::time::{Duration, Instant}; use style::attr::AttrValue; -use style::context::ReflowGoal; +use style::context::{QuirksMode, ReflowGoal}; use style::restyle_hints::RestyleHint; use style::selector_parser::{RestyleDamage, Snapshot}; use style::str::{split_html_space_chars, str_join}; use style::stylesheets::Stylesheet; use time; use url::percent_encoding::percent_decode; -use util::prefs::PREFS; pub enum TouchEventResult { Processed(bool), @@ -184,8 +185,8 @@ pub struct Document { window: JS<Window>, /// https://html.spec.whatwg.org/multipage/#concept-document-bc browsing_context: Option<JS<BrowsingContext>>, - implementation: MutNullableHeap<JS<DOMImplementation>>, - location: MutNullableHeap<JS<Location>>, + implementation: MutNullableJS<DOMImplementation>, + location: MutNullableJS<Location>, content_type: DOMString, last_modified: Option<String>, encoding: Cell<EncodingRef>, @@ -197,29 +198,29 @@ pub struct Document { tag_map: DOMRefCell<HashMap<LocalName, JS<HTMLCollection>>>, tagns_map: DOMRefCell<HashMap<QualName, JS<HTMLCollection>>>, classes_map: DOMRefCell<HashMap<Vec<Atom>, JS<HTMLCollection>>>, - images: MutNullableHeap<JS<HTMLCollection>>, - embeds: MutNullableHeap<JS<HTMLCollection>>, - links: MutNullableHeap<JS<HTMLCollection>>, - forms: MutNullableHeap<JS<HTMLCollection>>, - scripts: MutNullableHeap<JS<HTMLCollection>>, - anchors: MutNullableHeap<JS<HTMLCollection>>, - applets: MutNullableHeap<JS<HTMLCollection>>, + images: MutNullableJS<HTMLCollection>, + embeds: MutNullableJS<HTMLCollection>, + links: MutNullableJS<HTMLCollection>, + forms: MutNullableJS<HTMLCollection>, + scripts: MutNullableJS<HTMLCollection>, + anchors: MutNullableJS<HTMLCollection>, + applets: MutNullableJS<HTMLCollection>, /// List of stylesheets associated with nodes in this document. |None| if the list needs to be refreshed. stylesheets: DOMRefCell<Option<Vec<StylesheetInDocument>>>, /// Whether the list of stylesheets has changed since the last reflow was triggered. stylesheets_changed_since_reflow: Cell<bool>, - stylesheet_list: MutNullableHeap<JS<StyleSheetList>>, + stylesheet_list: MutNullableJS<StyleSheetList>, ready_state: Cell<DocumentReadyState>, /// Whether the DOMContentLoaded event has already been dispatched. domcontentloaded_dispatched: Cell<bool>, /// The element that has most recently requested focus for itself. - possibly_focused: MutNullableHeap<JS<Element>>, + possibly_focused: MutNullableJS<Element>, /// The element that currently has the document focus context. - focused: MutNullableHeap<JS<Element>>, + focused: MutNullableJS<Element>, /// The script element that is currently executing. - current_script: MutNullableHeap<JS<HTMLScriptElement>>, + current_script: MutNullableJS<HTMLScriptElement>, /// https://html.spec.whatwg.org/multipage/#pending-parsing-blocking-script - pending_parsing_blocking_script: MutNullableHeap<JS<HTMLScriptElement>>, + pending_parsing_blocking_script: MutNullableJS<HTMLScriptElement>, /// Number of stylesheets that block executing the next parser-inserted script script_blocking_stylesheets_count: Cell<u32>, /// https://html.spec.whatwg.org/multipage/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing @@ -245,14 +246,14 @@ pub struct Document { /// Tracks all outstanding loads related to this document. loader: DOMRefCell<DocumentLoader>, /// The current active HTML parser, to allow resuming after interruptions. - current_parser: MutNullableHeap<JS<ServoParser>>, + current_parser: MutNullableJS<ServoParser>, /// When we should kick off a reflow. This happens during parsing. reflow_timeout: Cell<Option<u64>>, /// The cached first `base` element with an `href` attribute. - base_element: MutNullableHeap<JS<HTMLBaseElement>>, + base_element: MutNullableJS<HTMLBaseElement>, /// This field is set to the document itself for inert documents. /// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document - appropriate_template_contents_owner_document: MutNullableHeap<JS<Document>>, + appropriate_template_contents_owner_document: MutNullableJS<Document>, /// Information on elements needing restyle to ship over to the layout thread when the /// time comes. pending_restyles: DOMRefCell<HashMap<JS<Element>, PendingRestyle>>, @@ -280,7 +281,7 @@ pub struct Document { /// https://html.spec.whatwg.org/multipage/#dom-document-referrer referrer: Option<String>, /// https://html.spec.whatwg.org/multipage/#target-element - target_element: MutNullableHeap<JS<Element>>, + target_element: MutNullableJS<Element>, /// https://w3c.github.io/uievents/#event-type-dblclick #[ignore_heap_size_of = "Defined in std"] last_click_info: DOMRefCell<Option<(Instant, Point2D<f32>)>>, @@ -293,7 +294,7 @@ pub struct Document { /// See also: https://github.com/servo/servo/issues/10110 dom_count: Cell<u32>, /// Entry node for fullscreen. - fullscreen_element: MutNullableHeap<JS<Element>>, + fullscreen_element: MutNullableJS<Element>, } #[derive(JSTraceable, HeapSizeOf)] @@ -488,7 +489,7 @@ impl Document { pub fn set_quirks_mode(&self, mode: QuirksMode) { self.quirks_mode.set(mode); - if mode == Quirks { + if mode == QuirksMode::Quirks { self.window.layout_chan().send(Msg::SetQuirksMode).unwrap(); } } @@ -1036,7 +1037,7 @@ impl Document { pub fn handle_mouse_move_event(&self, js_runtime: *mut JSRuntime, client_point: Option<Point2D<f32>>, - prev_mouse_over_target: &MutNullableHeap<JS<Element>>) { + prev_mouse_over_target: &MutNullableJS<Element>) { let client_point = match client_point { None => { // If there's no point, there's no target under the mouse @@ -1521,8 +1522,11 @@ impl Document { /// https://html.spec.whatwg.org/multipage/#run-the-animation-frame-callbacks pub fn run_the_animation_frame_callbacks(&self) { - let mut animation_frame_list = - mem::replace(&mut *self.animation_frame_list.borrow_mut(), vec![]); + rooted_vec!(let mut animation_frame_list); + mem::swap( + &mut *animation_frame_list, + &mut *self.animation_frame_list.borrow_mut()); + self.running_animation_callbacks.set(true); let timing = self.window.Performance().Now(); @@ -1538,7 +1542,7 @@ impl Document { // message quickly followed by an AnimationCallbacksPresent message. if self.animation_frame_list.borrow().is_empty() { mem::swap(&mut *self.animation_frame_list.borrow_mut(), - &mut animation_frame_list); + &mut *animation_frame_list); let global_scope = self.window.upcast::<GlobalScope>(); let event = ConstellationMsg::ChangeRunningAnimationsState(global_scope.pipeline_id(), AnimationState::NoAnimationCallbacksPresent); @@ -1772,6 +1776,7 @@ pub trait LayoutDocumentHelpers { unsafe fn drain_pending_restyles(&self) -> Vec<(LayoutJS<Element>, PendingRestyle)>; unsafe fn needs_paint_from_layout(&self); unsafe fn will_paint(&self); + unsafe fn quirks_mode(&self) -> QuirksMode; } #[allow(unsafe_code)] @@ -1798,6 +1803,11 @@ impl LayoutDocumentHelpers for LayoutJS<Document> { unsafe fn will_paint(&self) { (*self.unsafe_get()).needs_paint.set(false) } + + #[inline] + unsafe fn quirks_mode(&self) -> QuirksMode { + (*self.unsafe_get()).quirks_mode() + } } /// https://url.spec.whatwg.org/#network-scheme @@ -1855,7 +1865,7 @@ impl Document { last_modified: last_modified, url: DOMRefCell::new(url), // https://dom.spec.whatwg.org/#concept-document-quirks - quirks_mode: Cell::new(NoQuirks), + quirks_mode: Cell::new(QuirksMode::NoQuirks), // https://dom.spec.whatwg.org/#concept-document-encoding encoding: Cell::new(UTF_8), is_html_document: is_html_document == IsHTMLDocument::HTMLDocument, @@ -1872,7 +1882,7 @@ impl Document { applets: Default::default(), stylesheets: DOMRefCell::new(None), stylesheets_changed_since_reflow: Cell::new(false), - stylesheet_list: MutNullableHeap::new(None), + stylesheet_list: MutNullableJS::new(None), ready_state: Cell::new(ready_state), domcontentloaded_dispatched: Cell::new(domcontentloaded_dispatched), possibly_focused: Default::default(), @@ -1907,11 +1917,11 @@ impl Document { origin: origin, referrer: referrer, referrer_policy: Cell::new(referrer_policy), - target_element: MutNullableHeap::new(None), + target_element: MutNullableJS::new(None), last_click_info: DOMRefCell::new(None), ignore_destructive_writes_counter: Default::default(), dom_count: Cell::new(1), - fullscreen_element: MutNullableHeap::new(None), + fullscreen_element: MutNullableJS::new(None), } } @@ -2298,8 +2308,8 @@ impl DocumentMethods for Document { // https://dom.spec.whatwg.org/#dom-document-compatmode fn CompatMode(&self) -> DOMString { DOMString::from(match self.quirks_mode.get() { - LimitedQuirks | NoQuirks => "CSS1Compat", - Quirks => "BackCompat", + QuirksMode::LimitedQuirks | QuirksMode::NoQuirks => "CSS1Compat", + QuirksMode::Quirks => "BackCompat", }) } @@ -2667,7 +2677,7 @@ impl DocumentMethods for Document { None => DOMString::new(), Some(ref title) => { // Steps 3-4. - let value = Node::collect_text_contents(title.children()); + let value = title.child_text_content(); DOMString::from(str_join(split_html_space_chars(&value), " ")) }, } @@ -2957,11 +2967,15 @@ impl DocumentMethods for Document { return Err(Error::Security); } - let url = self.url(); - let _ = self.window - .upcast::<GlobalScope>() - .resource_threads() - .send(SetCookiesForUrl(url, String::from(cookie), NonHTTP)); + let header = Header::parse_header(&[cookie.into()]); + if let Ok(SetCookie(cookies)) = header { + let cookies = cookies.into_iter().map(Serde).collect(); + let _ = self.window + .upcast::<GlobalScope>() + .resource_threads() + .send(SetCookiesForUrl(self.url(), cookies, NonHTTP)); + } + Ok(()) } diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs index 2a5946193b6..7428a986c48 100644 --- a/components/script/dom/domexception.rs +++ b/components/script/dom/domexception.rs @@ -29,13 +29,11 @@ pub enum DOMErrorName { SecurityError = DOMExceptionConstants::SECURITY_ERR, NetworkError = DOMExceptionConstants::NETWORK_ERR, AbortError = DOMExceptionConstants::ABORT_ERR, - URLMismatchError = DOMExceptionConstants::URL_MISMATCH_ERR, TypeMismatchError = DOMExceptionConstants::TYPE_MISMATCH_ERR, QuotaExceededError = DOMExceptionConstants::QUOTA_EXCEEDED_ERR, TimeoutError = DOMExceptionConstants::TIMEOUT_ERR, InvalidNodeTypeError = DOMExceptionConstants::INVALID_NODE_TYPE_ERR, DataCloneError = DOMExceptionConstants::DATA_CLONE_ERR, - EncodingError, } #[dom_struct] @@ -62,11 +60,7 @@ impl DOMException { impl DOMExceptionMethods for DOMException { // https://heycam.github.io/webidl/#dfn-DOMException fn Code(&self) -> u16 { - match self.code { - // https://heycam.github.io/webidl/#dfn-throw - DOMErrorName::EncodingError => 0, - code => code as u16, - } + self.code as u16 } // https://heycam.github.io/webidl/#idl-DOMException-error-names @@ -93,14 +87,12 @@ impl DOMExceptionMethods for DOMException { DOMErrorName::SecurityError => "The operation is insecure.", DOMErrorName::NetworkError => "A network error occurred.", DOMErrorName::AbortError => "The operation was aborted.", - DOMErrorName::URLMismatchError => "The given URL does not match another URL.", DOMErrorName::TypeMismatchError => "The given type does not match any expected type.", DOMErrorName::QuotaExceededError => "The quota has been exceeded.", DOMErrorName::TimeoutError => "The operation timed out.", DOMErrorName::InvalidNodeTypeError => "The supplied node is incorrect or has an incorrect ancestor for this operation.", DOMErrorName::DataCloneError => "The object can not be cloned.", - DOMErrorName::EncodingError => "The encoding operation (either encoded or decoding) failed." }; DOMString::from(message) diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index 7556e64d0a7..cbc69b318df 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -155,20 +155,17 @@ impl DOMImplementationMethods for DOMImplementation { doc_html.AppendChild(&doc_head).unwrap(); // Step 6. - match title { - None => (), - Some(title_str) => { - // Step 6.1. - let doc_title = - Root::upcast::<Node>(HTMLTitleElement::new(local_name!("title"), - None, - &doc)); - doc_head.AppendChild(&doc_title).unwrap(); - - // Step 6.2. - let title_text = Text::new(title_str, &doc); - doc_title.AppendChild(title_text.upcast()).unwrap(); - } + if let Some(title_str) = title { + // Step 6.1. + let doc_title = + Root::upcast::<Node>(HTMLTitleElement::new(local_name!("title"), + None, + &doc)); + doc_head.AppendChild(&doc_title).unwrap(); + + // Step 6.2. + let title_text = Text::new(title_str, &doc); + doc_title.AppendChild(title_text.upcast()).unwrap(); } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 4a94f345b02..d9c2f6907e7 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -22,7 +22,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId}; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap}; +use dom::bindings::js::{JS, LayoutJS, MutNullableJS}; use dom::bindings::js::{Root, RootedReference}; use dom::bindings::refcounted::{Trusted, TrustedPromise}; use dom::bindings::reflector::DomObject; @@ -51,9 +51,11 @@ use dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers}; use dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers}; use dom::htmllabelelement::HTMLLabelElement; use dom::htmllegendelement::HTMLLegendElement; +use dom::htmllinkelement::HTMLLinkElement; use dom::htmlobjectelement::HTMLObjectElement; use dom::htmloptgroupelement::HTMLOptGroupElement; use dom::htmlselectelement::HTMLSelectElement; +use dom::htmlstyleelement::HTMLStyleElement; use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementLayoutHelpers}; use dom::htmltableelement::{HTMLTableElement, HTMLTableElementLayoutHelpers}; use dom::htmltablerowelement::{HTMLTableRowElement, HTMLTableRowElementLayoutHelpers}; @@ -75,7 +77,6 @@ use html5ever::serialize; use html5ever::serialize::SerializeOpts; use html5ever::serialize::TraversalScope; use html5ever::serialize::TraversalScope::{ChildrenOnly, IncludeNode}; -use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks}; use html5ever_atoms::{Prefix, LocalName, Namespace, QualName}; use js::jsapi::{HandleValue, JSAutoCompartment}; use parking_lot::RwLock; @@ -96,8 +97,7 @@ use std::rc::Rc; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; -use style::context::ReflowGoal; -use style::dom::TRestyleDamage; +use style::context::{QuirksMode, ReflowGoal}; use style::element_state::*; use style::matching::{common_style_affecting_attributes, rare_style_affecting_attributes}; use style::parser::ParserContextExtraData; @@ -110,6 +110,7 @@ use style::sink::Push; use style::stylist::ApplicableDeclarationBlock; use style::values::CSSFloat; use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage}; +use stylesheet_loader::StylesheetOwner; // TODO: Update focus state when the top-level browsing context gains or loses system focus, // and when the element enters or leaves a browsing context container. @@ -126,8 +127,8 @@ pub struct Element { id_attribute: DOMRefCell<Option<Atom>>, #[ignore_heap_size_of = "Arc"] style_attribute: DOMRefCell<Option<Arc<RwLock<PropertyDeclarationBlock>>>>, - attr_list: MutNullableHeap<JS<NamedNodeMap>>, - class_list: MutNullableHeap<JS<DOMTokenList>>, + attr_list: MutNullableJS<NamedNodeMap>, + class_list: MutNullableJS<DOMTokenList>, state: Cell<ElementState>, atomic_flags: AtomicElementFlags, } @@ -398,7 +399,7 @@ impl LayoutElementHelpers for LayoutJS<Element> { PropertyDeclaration::BackgroundImage(DeclaredValue::Value( background_image::SpecifiedValue(vec![ background_image::single_value::SpecifiedValue(Some( - specified::Image::for_cascade(Some(url.into()), specified::url::UrlExtraData { }) + specified::Image::for_cascade(url.into(), specified::url::UrlExtraData { }) )) ]))))); } @@ -1095,8 +1096,8 @@ impl Element { let quirks_mode = document_from_node(self).quirks_mode(); let is_equal = |lhs: &Atom, rhs: &Atom| { match quirks_mode { - NoQuirks | LimitedQuirks => lhs == rhs, - Quirks => lhs.eq_ignore_ascii_case(&rhs), + QuirksMode::NoQuirks | QuirksMode::LimitedQuirks => lhs == rhs, + QuirksMode::Quirks => lhs.eq_ignore_ascii_case(&rhs), } }; self.get_attribute(&ns!(), &local_name!("class")) @@ -1276,7 +1277,7 @@ impl Element { // Step 7 if *self.root_element() == *self { - if doc.quirks_mode() != Quirks { + if doc.quirks_mode() != QuirksMode::Quirks { win.scroll(x, y, behavior); } @@ -1285,7 +1286,7 @@ impl Element { // Step 9 if doc.GetBody().r() == self.downcast::<HTMLElement>() && - doc.quirks_mode() == Quirks && + doc.quirks_mode() == QuirksMode::Quirks && !self.potentially_scrollable() { win.scroll(x, y, behavior); return; @@ -1656,7 +1657,7 @@ impl ElementMethods for Element { // Step 5 if *self.root_element() == *self { - if doc.quirks_mode() == Quirks { + if doc.quirks_mode() == QuirksMode::Quirks { return 0.0; } @@ -1666,7 +1667,7 @@ impl ElementMethods for Element { // Step 7 if doc.GetBody().r() == self.downcast::<HTMLElement>() && - doc.quirks_mode() == Quirks && + doc.quirks_mode() == QuirksMode::Quirks && !self.potentially_scrollable() { return win.ScrollY() as f64; } @@ -1707,7 +1708,7 @@ impl ElementMethods for Element { // Step 7 if *self.root_element() == *self { - if doc.quirks_mode() != Quirks { + if doc.quirks_mode() != QuirksMode::Quirks { win.scroll(win.ScrollX() as f64, y, behavior); } @@ -1716,7 +1717,7 @@ impl ElementMethods for Element { // Step 9 if doc.GetBody().r() == self.downcast::<HTMLElement>() && - doc.quirks_mode() == Quirks && + doc.quirks_mode() == QuirksMode::Quirks && !self.potentially_scrollable() { win.scroll(win.ScrollX() as f64, y, behavior); return; @@ -1748,7 +1749,7 @@ impl ElementMethods for Element { // Step 5 if *self.root_element() == *self { - if doc.quirks_mode() != Quirks { + if doc.quirks_mode() != QuirksMode::Quirks { // Step 6 return win.ScrollX() as f64; } @@ -1758,7 +1759,7 @@ impl ElementMethods for Element { // Step 7 if doc.GetBody().r() == self.downcast::<HTMLElement>() && - doc.quirks_mode() == Quirks && + doc.quirks_mode() == QuirksMode::Quirks && !self.potentially_scrollable() { return win.ScrollX() as f64; } @@ -1799,7 +1800,7 @@ impl ElementMethods for Element { // Step 7 if *self.root_element() == *self { - if doc.quirks_mode() == Quirks { + if doc.quirks_mode() == QuirksMode::Quirks { return; } @@ -1809,7 +1810,7 @@ impl ElementMethods for Element { // Step 9 if doc.GetBody().r() == self.downcast::<HTMLElement>() && - doc.quirks_mode() == Quirks && + doc.quirks_mode() == QuirksMode::Quirks && !self.potentially_scrollable() { win.scroll(x, win.ScrollY() as f64, behavior); return; @@ -2421,6 +2422,18 @@ impl Element { }) } + pub fn as_stylesheet_owner(&self) -> Option<&StylesheetOwner> { + if let Some(s) = self.downcast::<HTMLStyleElement>() { + return Some(s as &StylesheetOwner) + } + + if let Some(l) = self.downcast::<HTMLLinkElement>() { + return Some(l as &StylesheetOwner) + } + + None + } + // https://html.spec.whatwg.org/multipage/#category-submit pub fn as_maybe_validatable(&self) -> Option<&Validatable> { let element = match self.upcast::<Node>().type_id() { @@ -2663,15 +2676,11 @@ impl Element { self.set_enabled_state(false); return; } - match ancestor.children() - .find(|child| child.is::<HTMLLegendElement>()) { - Some(ref legend) => { - // XXXabinader: should we save previous ancestor to avoid this iteration? - if node.ancestors().any(|ancestor| ancestor == *legend) { - continue; - } - }, - None => (), + if let Some(ref legend) = ancestor.children().find(|n| n.is::<HTMLLegendElement>()) { + // XXXabinader: should we save previous ancestor to avoid this iteration? + if node.ancestors().any(|ancestor| ancestor == *legend) { + continue; + } } self.set_disabled_state(true); self.set_enabled_state(false); diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index d67d1f64e78..d471c25d873 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -6,7 +6,7 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::EventBinding; use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethods}; use dom::bindings::error::Fallible; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; @@ -80,8 +80,8 @@ impl From<bool> for EventCancelable { #[dom_struct] pub struct Event { reflector_: Reflector, - current_target: MutNullableHeap<JS<EventTarget>>, - target: MutNullableHeap<JS<EventTarget>>, + current_target: MutNullableJS<EventTarget>, + target: MutNullableJS<EventTarget>, type_: DOMRefCell<Atom>, phase: Cell<EventPhase>, canceled: Cell<bool>, diff --git a/components/script/dom/eventdispatcher.rs b/components/script/dom/eventdispatcher.rs index d5e4bf51338..bdec56532dc 100644 --- a/components/script/dom/eventdispatcher.rs +++ b/components/script/dom/eventdispatcher.rs @@ -156,15 +156,11 @@ pub fn dispatch_event(target: &EventTarget, dispatch_to_listeners(event, target, event_path.r()); // Default action. - let target = event.GetTarget(); - match target { - Some(ref target) => { - if let Some(node) = target.downcast::<Node>() { - let vtable = vtable_for(&node); - vtable.handle_event(event); - } + if let Some(target) = event.GetTarget() { + if let Some(node) = target.downcast::<Node>() { + let vtable = vtable_for(&node); + vtable.handle_event(event); } - None => {} } // Step 10-12. diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index bb57ad5d9de..9b5c39b013c 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::FileReaderBinding::{self, FileReaderConsta use dom::bindings::codegen::UnionTypes::StringOrObject; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; @@ -34,9 +34,9 @@ use servo_atoms::Atom; use std::cell::Cell; use std::ptr; use std::sync::Arc; +use std::thread; use task_source::TaskSource; use task_source::file_reading::{FileReadingTaskSource, FileReadingRunnable, FileReadingTask}; -use util::thread::spawn_named; #[derive(PartialEq, Clone, Copy, JSTraceable, HeapSizeOf)] pub enum FileReaderFunction { @@ -86,7 +86,7 @@ pub enum FileReaderResult { pub struct FileReader { eventtarget: EventTarget, ready_state: Cell<FileReaderReadyState>, - error: MutNullableHeap<JS<DOMException>>, + error: MutNullableJS<DOMException>, result: DOMRefCell<Option<FileReaderResult>>, generation_id: Cell<GenerationId>, } @@ -96,7 +96,7 @@ impl FileReader { FileReader { eventtarget: EventTarget::new_inherited(), ready_state: Cell::new(FileReaderReadyState::Empty), - error: MutNullableHeap::new(None), + error: MutNullableJS::new(None), result: DOMRefCell::new(None), generation_id: Cell::new(GenerationId(0)), } @@ -401,9 +401,10 @@ impl FileReader { let wrapper = global.get_runnable_wrapper(); let task_source = global.file_reading_task_source(); - spawn_named("file reader async operation".to_owned(), move || { + thread::Builder::new().name("file reader async operation".to_owned()).spawn(move || { perform_annotated_read_operation(gen_id, load_data, blob_contents, fr, task_source, wrapper) - }); + }).expect("Thread spawning failed"); + Ok(()) } diff --git a/components/script/dom/focusevent.rs b/components/script/dom/focusevent.rs index 1eb3983737d..c7e48531479 100644 --- a/components/script/dom/focusevent.rs +++ b/components/script/dom/focusevent.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::FocusEventBinding::FocusEventMethods; use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods; use dom::bindings::error::Fallible; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{MutNullableJS, Root, RootedReference}; use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; use dom::event::{EventBubbles, EventCancelable}; @@ -20,7 +20,7 @@ use std::default::Default; #[dom_struct] pub struct FocusEvent { uievent: UIEvent, - related_target: MutNullableHeap<JS<EventTarget>>, + related_target: MutNullableJS<EventTarget>, } impl FocusEvent { diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs index 19436804b19..ae08bc0e5fd 100644 --- a/components/script/dom/globalscope.rs +++ b/components/script/dom/globalscope.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::conversions::root_from_object; use dom::bindings::error::{ErrorInfo, report_pending_exception}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::DomObject; use dom::bindings::str::DOMString; use dom::crypto::Crypto; @@ -50,7 +50,7 @@ use timers::{OneshotTimers, TimerCallback}; #[dom_struct] pub struct GlobalScope { eventtarget: EventTarget, - crypto: MutNullableHeap<JS<Crypto>>, + crypto: MutNullableJS<Crypto>, next_worker_id: Cell<WorkerId>, /// Pipeline id associated with this global. diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index f92290b2c97..52c355f2bab 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding::HTMLAnchorElemen use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::str::{DOMString, USVString}; use dom::document::Document; use dom::domtokenlist::DOMTokenList; @@ -28,15 +28,15 @@ use html5ever_atoms::LocalName; use net_traits::ReferrerPolicy; use num_traits::ToPrimitive; use script_traits::MozBrowserEvent; +use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::default::Default; use style::attr::AttrValue; -use util::prefs::PREFS; #[dom_struct] pub struct HTMLAnchorElement { htmlelement: HTMLElement, - rel_list: MutNullableHeap<JS<DOMTokenList>>, + rel_list: MutNullableJS<DOMTokenList>, url: DOMRefCell<Option<ServoUrl>>, } diff --git a/components/script/dom/htmlareaelement.rs b/components/script/dom/htmlareaelement.rs index b8df3806a3f..79240885167 100644 --- a/components/script/dom/htmlareaelement.rs +++ b/components/script/dom/htmlareaelement.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::Bindings::HTMLAreaElementBinding; use dom::bindings::codegen::Bindings::HTMLAreaElementBinding::HTMLAreaElementMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::str::DOMString; use dom::document::Document; use dom::domtokenlist::DOMTokenList; @@ -19,7 +19,7 @@ use style::attr::AttrValue; #[dom_struct] pub struct HTMLAreaElement { htmlelement: HTMLElement, - rel_list: MutNullableHeap<JS<DOMTokenList>>, + rel_list: MutNullableJS<DOMTokenList>, } impl HTMLAreaElement { diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index b9d7731d652..b174d2ec9a8 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -13,7 +13,7 @@ use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRendering use dom::bindings::conversions::ConversionResult; use dom::bindings::error::{Error, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::js::{JS, LayoutJS, Root}; use dom::bindings::num::Finite; use dom::bindings::str::DOMString; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; @@ -47,8 +47,6 @@ pub enum CanvasContext { WebGL(JS<WebGLRenderingContext>), } -impl HeapGCValue for CanvasContext {} - #[dom_struct] pub struct HTMLCanvasElement { htmlelement: HTMLElement, diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs index 959265e82e0..eacffd6cded 100644 --- a/components/script/dom/htmlcollection.rs +++ b/components/script/dom/htmlcollection.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::Bindings::HTMLCollectionBinding; use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, Root, MutNullableHeap}; +use dom::bindings::js::{JS, Root, MutNullableJS}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bindings::trace::JSTraceable; @@ -59,7 +59,7 @@ pub struct HTMLCollection { // the length of the collection, and a cursor into the collection. // FIXME: make the cached cursor element a weak pointer cached_version: Cell<u64>, - cached_cursor_element: MutNullableHeap<JS<Element>>, + cached_cursor_element: MutNullableJS<Element>, cached_cursor_index: Cell<OptionU32>, cached_length: Cell<OptionU32>, } @@ -73,7 +73,7 @@ impl HTMLCollection { filter: filter, // Default values for the cache cached_version: Cell::new(root.inclusive_descendants_version()), - cached_cursor_element: MutNullableHeap::new(None), + cached_cursor_element: MutNullableJS::new(None), cached_cursor_index: Cell::new(OptionU32::none()), cached_length: Cell::new(OptionU32::none()), } diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index d4490357650..6725fdb5dfb 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -13,9 +13,9 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::inheritance::{ElementTypeId, HTMLElementTypeId, NodeTypeId}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference}; use dom::bindings::str::DOMString; -use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration}; +use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSStyleOwner}; use dom::document::{Document, FocusType}; use dom::domstringmap::DOMStringMap; use dom::element::{AttributeMutation, Element}; @@ -40,8 +40,8 @@ use style::element_state::*; #[dom_struct] pub struct HTMLElement { element: Element, - style_decl: MutNullableHeap<JS<CSSStyleDeclaration>>, - dataset: MutNullableHeap<JS<DOMStringMap>>, + style_decl: MutNullableJS<CSSStyleDeclaration>, + dataset: MutNullableJS<DOMStringMap>, } impl HTMLElement { @@ -115,7 +115,10 @@ impl HTMLElementMethods for HTMLElement { fn Style(&self) -> Root<CSSStyleDeclaration> { self.style_decl.or_init(|| { let global = window_from_node(self); - CSSStyleDeclaration::new(&global, self.upcast::<Element>(), None, CSSModificationAccess::ReadWrite) + CSSStyleDeclaration::new(&global, + CSSStyleOwner::Element(JS::from_ref(self.upcast())), + None, + CSSModificationAccess::ReadWrite) }) } diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 90abdbafefd..a0a34b081c8 100755 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -13,7 +13,7 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM use dom::bindings::codegen::Bindings::HTMLTextAreaElementBinding::HTMLTextAreaElementMethods; use dom::bindings::conversions::DerivedFrom; use dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId}; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::DomObject; use dom::bindings::str::DOMString; @@ -61,7 +61,7 @@ pub struct GenerationId(u32); pub struct HTMLFormElement { htmlelement: HTMLElement, marked_for_reset: Cell<bool>, - elements: MutNullableHeap<JS<HTMLFormControlsCollection>>, + elements: MutNullableJS<HTMLFormControlsCollection>, generation_id: Cell<GenerationId> } @@ -85,10 +85,6 @@ impl HTMLFormElement { document, HTMLFormElementBinding::Wrap) } - - pub fn generation_id(&self) -> GenerationId { - self.generation_id.get() - } } impl HTMLFormElementMethods for HTMLFormElement { @@ -662,6 +658,7 @@ impl HTMLFormElement { #[derive(JSTraceable, HeapSizeOf, Clone)] pub enum FormDatumValue { + #[allow(dead_code)] File(Root<File>), String(DOMString) } @@ -701,6 +698,7 @@ pub enum FormMethod { } #[derive(HeapSizeOf)] +#[allow(dead_code)] pub enum FormSubmittableElement { ButtonElement(Root<HTMLButtonElement>), InputElement(Root<HTMLInputElement>), diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 44323e1c1ef..53c7e34f94f 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -19,7 +19,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethod use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; +use dom::bindings::js::{LayoutJS, MutNullableJS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::DomObject; use dom::bindings::str::DOMString; @@ -48,13 +48,13 @@ use script_traits::{IFrameLoadInfo, IFrameLoadInfoWithData, LoadData}; use script_traits::{MozBrowserEvent, NewLayoutInfo, ScriptMsg as ConstellationMsg}; use script_traits::IFrameSandboxState::{IFrameSandboxed, IFrameUnsandboxed}; use servo_atoms::Atom; +use servo_config::prefs::PREFS; +use servo_config::servo_version; use servo_url::ServoUrl; use std::cell::Cell; use style::attr::{AttrValue, LengthOrPercentageOrAuto}; use style::context::ReflowGoal; use task_source::TaskSource; -use util::prefs::PREFS; -use util::servo_version; bitflags! { #[derive(JSTraceable, HeapSizeOf)] @@ -80,7 +80,7 @@ pub struct HTMLIFrameElement { htmlelement: HTMLElement, frame_id: FrameId, pipeline_id: Cell<Option<PipelineId>>, - sandbox: MutNullableHeap<JS<DOMTokenList>>, + sandbox: MutNullableJS<DOMTokenList>, sandbox_allowance: Cell<Option<SandboxAllowance>>, load_blocker: DOMRefCell<Option<LoadBlocker>>, visibility: Cell<bool>, diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 90cf630e9fe..eb344ef0a79 100755 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -13,7 +13,7 @@ use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementM use dom::bindings::codegen::Bindings::KeyboardEventBinding::KeyboardEventMethods; use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{JS, LayoutJS, MutNullableJS, Root, RootedReference}; use dom::bindings::str::DOMString; use dom::document::Document; use dom::element::{AttributeMutation, Element, LayoutElementHelpers, RawLayoutElementHelpers}; @@ -94,7 +94,7 @@ pub struct HTMLInputElement { // https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag value_dirty: Cell<bool>, - filelist: MutNullableHeap<JS<FileList>>, + filelist: MutNullableJS<FileList>, } #[derive(JSTraceable)] @@ -150,7 +150,7 @@ impl HTMLInputElement { SelectionDirection::None)), activation_state: DOMRefCell::new(InputActivationState::new()), value_dirty: Cell::new(false), - filelist: MutNullableHeap::new(None), + filelist: MutNullableJS::new(None), } } diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs index 1985e511c4d..ee4ee4718cf 100644 --- a/components/script/dom/htmllinkelement.rs +++ b/components/script/dom/htmllinkelement.rs @@ -3,65 +3,54 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use cssparser::Parser as CssParser; -use document_loader::LoadType; use dom::attr::Attr; use dom::bindings::cell::DOMRefCell; -use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods; +use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListBinding::DOMTokenListMethods; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding; use dom::bindings::codegen::Bindings::HTMLLinkElementBinding::HTMLLinkElementMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; -use dom::bindings::refcounted::Trusted; -use dom::bindings::reflector::DomObject; +use dom::bindings::js::{MutNullableJS, Root, RootedReference}; use dom::bindings::str::DOMString; use dom::cssstylesheet::CSSStyleSheet; use dom::document::Document; use dom::domtokenlist::DOMTokenList; use dom::element::{AttributeMutation, Element, ElementCreator}; -use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::htmlelement::HTMLElement; use dom::node::{Node, document_from_node, window_from_node}; use dom::stylesheet::StyleSheet as DOMStyleSheet; use dom::virtualmethods::VirtualMethods; -use encoding::EncodingRef; -use encoding::all::UTF_8; use html5ever_atoms::LocalName; -use hyper::header::ContentType; -use hyper::mime::{Mime, TopLevel, SubLevel}; -use hyper_serde::Serde; -use ipc_channel::ipc; -use ipc_channel::router::ROUTER; -use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError, ReferrerPolicy}; -use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType}; -use network_listener::{NetworkListener, PreInvoke}; -use script_layout_interface::message::Msg; +use net_traits::ReferrerPolicy; use script_traits::{MozBrowserEvent, ScriptMsg as ConstellationMsg}; -use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::borrow::ToOwned; use std::cell::Cell; use std::default::Default; -use std::mem; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use style::attr::AttrValue; -use style::media_queries::{MediaList, parse_media_query_list}; -use style::parser::ParserContextExtraData; +use style::media_queries::parse_media_query_list; use style::str::HTML_SPACE_CHARACTERS; -use style::stylesheets::{Stylesheet, Origin}; +use style::stylesheets::Stylesheet; +use stylesheet_loader::{StylesheetLoader, StylesheetContextSource, StylesheetOwner}; unsafe_no_jsmanaged_fields!(Stylesheet); #[dom_struct] pub struct HTMLLinkElement { htmlelement: HTMLElement, - rel_list: MutNullableHeap<JS<DOMTokenList>>, + rel_list: MutNullableJS<DOMTokenList>, #[ignore_heap_size_of = "Arc"] stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, - cssom_stylesheet: MutNullableHeap<JS<CSSStyleSheet>>, + cssom_stylesheet: MutNullableJS<CSSStyleSheet>, /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts parser_inserted: Cell<bool>, + /// The number of loads that this link element has triggered (could be more + /// than one because of imports) and have not yet finished. + pending_loads: Cell<u32>, + /// Whether any of the loads have failed. + any_failed_load: Cell<bool>, } impl HTMLLinkElement { @@ -72,7 +61,9 @@ impl HTMLLinkElement { rel_list: Default::default(), parser_inserted: Cell::new(creator == ElementCreator::ParserCreated), stylesheet: DOMRefCell::new(None), - cssom_stylesheet: MutNullableHeap::new(None), + cssom_stylesheet: MutNullableJS::new(None), + pending_loads: Cell::new(0), + any_failed_load: Cell::new(false), } } @@ -86,6 +77,12 @@ impl HTMLLinkElement { HTMLLinkElementBinding::Wrap) } + pub fn set_stylesheet(&self, s: Arc<Stylesheet>) { + assert!(self.stylesheet.borrow().is_none()); + *self.stylesheet.borrow_mut() = Some(s); + } + + pub fn get_stylesheet(&self) -> Option<Arc<Stylesheet>> { self.stylesheet.borrow().clone() } @@ -231,8 +228,11 @@ impl HTMLLinkElement { // Step 2. let url = match document.base_url().join(href) { - Err(e) => return debug!("Parsing url {} failed: {}", href, e), Ok(url) => url, + Err(e) => { + debug!("Parsing url {} failed: {}", href, e); + return; + } }; let element = self.upcast::<Element>(); @@ -246,50 +246,13 @@ impl HTMLLinkElement { let mut css_parser = CssParser::new(&mq_str); let media = parse_media_query_list(&mut css_parser); - // TODO: #8085 - Don't load external stylesheets if the node's mq doesn't match. - let elem = Trusted::new(self); - - let context = Arc::new(Mutex::new(StylesheetContext { - elem: elem, + // TODO: #8085 - Don't load external stylesheets if the node's mq + // doesn't match. + let loader = StylesheetLoader::for_element(self.upcast()); + loader.load(StylesheetContextSource::LinkElement { + url: url, media: Some(media), - data: vec!(), - metadata: None, - url: url.clone(), - })); - - let (action_sender, action_receiver) = ipc::channel().unwrap(); - let listener = NetworkListener { - context: context, - task_source: document.window().networking_task_source(), - wrapper: Some(document.window().get_runnable_wrapper()) - }; - ROUTER.add_route(action_receiver.to_opaque(), box move |message| { - listener.notify_fetch(message.to().unwrap()); }); - - if self.parser_inserted.get() { - document.increment_script_blocking_stylesheet_count(); - } - - let referrer_policy = match self.RelList().Contains("noreferrer".into()) { - true => Some(ReferrerPolicy::NoReferrer), - false => document.get_referrer_policy(), - }; - - let request = RequestInit { - url: url.clone(), - type_: RequestType::Style, - destination: Destination::Style, - credentials_mode: CredentialsMode::Include, - use_url_credentials: true, - origin: document.url(), - pipeline_id: Some(self.global().pipeline_id()), - referrer_url: Some(document.url()), - referrer_policy: referrer_policy, - .. RequestInit::default() - }; - - document.fetch_async(LoadType::Stylesheet(url), request, action_sender); } fn handle_favicon_url(&self, rel: &str, href: &str, sizes: &Option<String>) { @@ -310,92 +273,37 @@ impl HTMLLinkElement { } } -/// The context required for asynchronously loading an external stylesheet. -struct StylesheetContext { - /// The element that initiated the request. - elem: Trusted<HTMLLinkElement>, - media: Option<MediaList>, - /// The response body received to date. - data: Vec<u8>, - /// The response metadata received to date. - metadata: Option<Metadata>, - /// The initial URL requested. - url: ServoUrl, -} - -impl PreInvoke for StylesheetContext {} - -impl FetchResponseListener for StylesheetContext { - fn process_request_body(&mut self) {} +impl StylesheetOwner for HTMLLinkElement { + fn increment_pending_loads_count(&self) { + self.pending_loads.set(self.pending_loads.get() + 1) + } - fn process_request_eof(&mut self) {} + fn load_finished(&self, succeeded: bool) -> Option<bool> { + assert!(self.pending_loads.get() > 0, "What finished?"); + if !succeeded { + self.any_failed_load.set(true); + } - fn process_response(&mut self, - metadata: Result<FetchMetadata, NetworkError>) { - self.metadata = metadata.ok().map(|m| { - match m { - FetchMetadata::Unfiltered(m) => m, - FetchMetadata::Filtered { unsafe_, .. } => unsafe_ - } - }); - if let Some(ref meta) = self.metadata { - if let Some(Serde(ContentType(Mime(TopLevel::Text, SubLevel::Css, _)))) = meta.content_type { - } else { - self.elem.root().upcast::<EventTarget>().fire_event(atom!("error")); - } + self.pending_loads.set(self.pending_loads.get() - 1); + if self.pending_loads.get() != 0 { + return None; } - } - fn process_response_chunk(&mut self, mut payload: Vec<u8>) { - self.data.append(&mut payload); + let any_failed = self.any_failed_load.get(); + self.any_failed_load.set(false); + Some(any_failed) } - fn process_response_eof(&mut self, status: Result<(), NetworkError>) { - let elem = self.elem.root(); - let document = document_from_node(&*elem); - let mut successful = false; - - if status.is_ok() { - let metadata = match self.metadata.take() { - Some(meta) => meta, - None => return, - }; - let is_css = metadata.content_type.map_or(false, |Serde(ContentType(Mime(top, sub, _)))| - top == TopLevel::Text && sub == SubLevel::Css); - - let data = if is_css { mem::replace(&mut self.data, vec!()) } else { vec!() }; - - // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding - let environment_encoding = UTF_8 as EncodingRef; - let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); - let final_url = metadata.final_url; - - let win = window_from_node(&*elem); - - let sheet = Arc::new(Stylesheet::from_bytes( - &data, final_url, protocol_encoding_label, Some(environment_encoding), - Origin::Author, self.media.take().unwrap(), win.css_error_reporter(), - ParserContextExtraData::default())); - - let win = window_from_node(&*elem); - win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap(); - - *elem.stylesheet.borrow_mut() = Some(sheet); - document.invalidate_stylesheets(); - - // FIXME: Revisit once consensus is reached at: https://github.com/whatwg/html/issues/1142 - successful = metadata.status.map_or(false, |(code, _)| code == 200); - } + fn parser_inserted(&self) -> bool { + self.parser_inserted.get() + } - if elem.parser_inserted.get() { - document.decrement_script_blocking_stylesheet_count(); + fn referrer_policy(&self) -> Option<ReferrerPolicy> { + if self.RelList().Contains("noreferrer".into()) { + return Some(ReferrerPolicy::NoReferrer) } - document.finish_load(LoadType::Stylesheet(self.url.clone())); - - let event = if successful { atom!("load") } else { atom!("error") }; - - elem.upcast::<EventTarget>().fire_event(event); + None } } diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs index 778c0d6b560..fd327404b4d 100644 --- a/components/script/dom/htmlmediaelement.rs +++ b/components/script/dom/htmlmediaelement.rs @@ -13,7 +13,7 @@ use dom::bindings::codegen::Bindings::HTMLMediaElementBinding::HTMLMediaElementM use dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorConstants::*; use dom::bindings::codegen::Bindings::MediaErrorBinding::MediaErrorMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{Root, MutNullableHeap, JS}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::DomObject; use dom::bindings::str::DOMString; @@ -218,7 +218,7 @@ pub struct HTMLMediaElement { current_src: DOMRefCell<String>, generation_id: Cell<u32>, first_data_load: Cell<bool>, - error: MutNullableHeap<JS<MediaError>>, + error: MutNullableJS<MediaError>, paused: Cell<bool>, autoplaying: Cell<bool>, video: DOMRefCell<Option<VideoMedia>>, @@ -243,11 +243,6 @@ impl HTMLMediaElement { } } - #[inline] - pub fn htmlelement(&self) -> &HTMLElement { - &self.htmlelement - } - // https://html.spec.whatwg.org/multipage/#internal-pause-steps fn internal_pause_steps(&self) { // Step 1 @@ -437,6 +432,7 @@ impl HTMLMediaElement { } // https://html.spec.whatwg.org/multipage/#concept-media-load-algorithm + #[allow(unreachable_code)] fn resource_selection_algorithm_sync(&self, base_url: ServoUrl) { // TODO step 5 (populate pending text tracks) @@ -446,7 +442,7 @@ impl HTMLMediaElement { ResourceSelectionMode::Object } else if let Some(attr) = self.upcast::<Element>().get_attribute(&ns!(), &local_name!("src")) { ResourceSelectionMode::Attribute(attr.Value().to_string()) - } else if false { + } else if false { // TODO: when implementing this remove #[allow(unreachable_code)] above. // TODO <source> child ResourceSelectionMode::Children(panic!()) } else { diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index bcf112cce94..cf9d078e39f 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::HTMLMetaElementBinding; use dom::bindings::codegen::Bindings::HTMLMetaElementBinding::HTMLMetaElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{MutNullableJS, Root, RootedReference}; use dom::bindings::str::DOMString; use dom::cssstylesheet::CSSStyleSheet; use dom::document::Document; @@ -19,6 +19,7 @@ use dom::node::{Node, UnbindContext, document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; use parking_lot::RwLock; +use servo_config::prefs::PREFS; use std::ascii::AsciiExt; use std::sync::Arc; use std::sync::atomic::AtomicBool; @@ -32,7 +33,7 @@ pub struct HTMLMetaElement { htmlelement: HTMLElement, #[ignore_heap_size_of = "Arc"] stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, - cssom_stylesheet: MutNullableHeap<JS<CSSStyleSheet>>, + cssom_stylesheet: MutNullableJS<CSSStyleSheet>, } impl HTMLMetaElement { @@ -42,7 +43,7 @@ impl HTMLMetaElement { HTMLMetaElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document), stylesheet: DOMRefCell::new(None), - cssom_stylesheet: MutNullableHeap::new(None), + cssom_stylesheet: MutNullableJS::new(None), } } @@ -89,7 +90,7 @@ impl HTMLMetaElement { } fn apply_viewport(&self) { - if !::util::prefs::PREFS.get("layout.viewport.enabled").as_boolean().unwrap_or(false) { + if !PREFS.get("layout.viewport.enabled").as_boolean().unwrap_or(false) { return; } let element = self.upcast::<Element>(); diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index bccde70bb88..9558d9c4b41 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -713,7 +713,7 @@ impl HTMLScriptElementMethods for HTMLScriptElement { // https://html.spec.whatwg.org/multipage/#dom-script-text fn Text(&self) -> DOMString { - Node::collect_text_contents(self.upcast::<Node>().children()) + self.upcast::<Node>().child_text_content() } // https://html.spec.whatwg.org/multipage/#dom-script-text diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs index ad66f2b05f3..25977da8095 100755 --- a/components/script/dom/htmlselectelement.rs +++ b/components/script/dom/htmlselectelement.rs @@ -14,7 +14,7 @@ use dom::bindings::codegen::UnionTypes::HTMLElementOrLong; use dom::bindings::codegen::UnionTypes::HTMLOptionElementOrHTMLOptGroupElement; //use dom::bindings::error::ErrorResult; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::str::DOMString; use dom::document::Document; use dom::element::{AttributeMutation, Element}; @@ -31,6 +31,7 @@ use dom::validation::Validatable; use dom::validitystate::{ValidityState, ValidationFlags}; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; +use std::iter; use style::attr::AttrValue; use style::element_state::*; @@ -58,7 +59,7 @@ impl CollectionFilter for OptionsFilter { #[dom_struct] pub struct HTMLSelectElement { htmlelement: HTMLElement, - options: MutNullableHeap<JS<HTMLOptionsCollection>>, + options: MutNullableJS<HTMLOptionsCollection>, } static DEFAULT_SELECT_SIZE: u32 = 0; @@ -84,10 +85,25 @@ impl HTMLSelectElement { HTMLSelectElementBinding::Wrap) } + // https://html.spec.whatwg.org/multipage/#concept-select-option-list + fn list_of_options(&self) -> impl Iterator<Item=Root<HTMLOptionElement>> { + self.upcast::<Node>() + .children() + .flat_map(|node| { + if node.is::<HTMLOptionElement>() { + let node = Root::downcast::<HTMLOptionElement>(node).unwrap(); + Choice3::First(iter::once(node)) + } else if node.is::<HTMLOptGroupElement>() { + Choice3::Second(node.children().filter_map(Root::downcast)) + } else { + Choice3::Third(iter::empty()) + } + }) + } + // https://html.spec.whatwg.org/multipage/#the-select-element:concept-form-reset-control pub fn reset(&self) { - let node = self.upcast::<Node>(); - for opt in node.traverse_preorder().filter_map(Root::downcast::<HTMLOptionElement>) { + for opt in self.list_of_options() { opt.set_selectedness(opt.DefaultSelected()); opt.set_dirtiness(false); } @@ -103,8 +119,7 @@ impl HTMLSelectElement { let mut first_enabled: Option<Root<HTMLOptionElement>> = None; let mut last_selected: Option<Root<HTMLOptionElement>> = None; - let node = self.upcast::<Node>(); - for opt in node.traverse_preorder().filter_map(Root::downcast::<HTMLOptionElement>) { + for opt in self.list_of_options() { if opt.Selected() { opt.set_selectedness(false); last_selected = Some(Root::from_ref(&opt)); @@ -127,11 +142,10 @@ impl HTMLSelectElement { } pub fn push_form_data(&self, data_set: &mut Vec<FormDatum>) { - let node = self.upcast::<Node>(); if self.Name().is_empty() { return; } - for opt in node.traverse_preorder().filter_map(Root::downcast::<HTMLOptionElement>) { + for opt in self.list_of_options() { let element = opt.upcast::<Element>(); if opt.Selected() && element.enabled_state() { data_set.push(FormDatum { @@ -146,9 +160,8 @@ impl HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#concept-select-pick pub fn pick_option(&self, picked: &HTMLOptionElement) { if !self.Multiple() { - let node = self.upcast::<Node>(); let picked = picked.upcast(); - for opt in node.traverse_preorder().filter_map(Root::downcast::<HTMLOptionElement>) { + for opt in self.list_of_options() { if opt.upcast::<HTMLElement>() != picked { opt.set_selectedness(false); } @@ -271,9 +284,7 @@ impl HTMLSelectElementMethods for HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#dom-select-value fn Value(&self) -> DOMString { - self.upcast::<Node>() - .traverse_preorder() - .filter_map(Root::downcast::<HTMLOptionElement>) + self.list_of_options() .filter(|opt_elem| opt_elem.Selected()) .map(|opt_elem| opt_elem.Value()) .next() @@ -282,9 +293,7 @@ impl HTMLSelectElementMethods for HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#dom-select-value fn SetValue(&self, value: DOMString) { - let mut opt_iter = self.upcast::<Node>() - .traverse_preorder() - .filter_map(Root::downcast::<HTMLOptionElement>); + let mut opt_iter = self.list_of_options(); // Reset until we find an <option> with a matching value for opt in opt_iter.by_ref() { if opt.Value() == value { @@ -302,9 +311,7 @@ impl HTMLSelectElementMethods for HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#dom-select-selectedindex fn SelectedIndex(&self) -> i32 { - self.upcast::<Node>() - .traverse_preorder() - .filter_map(Root::downcast::<HTMLOptionElement>) + self.list_of_options() .enumerate() .filter(|&(_, ref opt_elem)| opt_elem.Selected()) .map(|(i, _)| i as i32) @@ -314,9 +321,7 @@ impl HTMLSelectElementMethods for HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#dom-select-selectedindex fn SetSelectedIndex(&self, index: i32) { - let mut opt_iter = self.upcast::<Node>() - .traverse_preorder() - .filter_map(Root::downcast::<HTMLOptionElement>); + let mut opt_iter = self.list_of_options(); for opt in opt_iter.by_ref().take(index as usize) { opt.set_selectedness(false); } @@ -394,3 +399,23 @@ impl Validatable for HTMLSelectElement { true } } + +enum Choice3<I, J, K> { + First(I), + Second(J), + Third(K), +} + +impl<I, J, K, T> Iterator for Choice3<I, J, K> + where I: Iterator<Item=T>, J: Iterator<Item=T>, K: Iterator<Item=T> +{ + type Item = T; + + fn next(&mut self) -> Option<T> { + match *self { + Choice3::First(ref mut i) => i.next(), + Choice3::Second(ref mut j) => j.next(), + Choice3::Third(ref mut k) => k.next(), + } + } +} diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs index 5a61d6f5b3a..2507f7bee35 100644 --- a/components/script/dom/htmlstyleelement.rs +++ b/components/script/dom/htmlstyleelement.rs @@ -8,46 +8,59 @@ use dom::bindings::codegen::Bindings::HTMLStyleElementBinding; use dom::bindings::codegen::Bindings::HTMLStyleElementBinding::HTMLStyleElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::str::DOMString; use dom::cssstylesheet::CSSStyleSheet; use dom::document::Document; -use dom::element::Element; +use dom::element::{Element, ElementCreator}; +use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::node::{ChildrenMutation, Node, document_from_node, window_from_node}; use dom::stylesheet::StyleSheet as DOMStyleSheet; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; +use net_traits::ReferrerPolicy; use script_layout_interface::message::Msg; +use std::cell::Cell; use std::sync::Arc; use style::media_queries::parse_media_query_list; use style::parser::ParserContextExtraData; use style::stylesheets::{Stylesheet, Origin}; +use stylesheet_loader::{StylesheetLoader, StylesheetOwner}; #[dom_struct] pub struct HTMLStyleElement { htmlelement: HTMLElement, #[ignore_heap_size_of = "Arc"] stylesheet: DOMRefCell<Option<Arc<Stylesheet>>>, - cssom_stylesheet: MutNullableHeap<JS<CSSStyleSheet>>, + cssom_stylesheet: MutNullableJS<CSSStyleSheet>, + /// https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts + parser_inserted: Cell<bool>, + pending_loads: Cell<u32>, + any_failed_load: Cell<bool>, } impl HTMLStyleElement { fn new_inherited(local_name: LocalName, prefix: Option<DOMString>, - document: &Document) -> HTMLStyleElement { + document: &Document, + creator: ElementCreator) -> HTMLStyleElement { HTMLStyleElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document), stylesheet: DOMRefCell::new(None), - cssom_stylesheet: MutNullableHeap::new(None), + cssom_stylesheet: MutNullableJS::new(None), + parser_inserted: Cell::new(creator == ElementCreator::ParserCreated), + pending_loads: Cell::new(0), + any_failed_load: Cell::new(false), } } #[allow(unrooted_must_root)] pub fn new(local_name: LocalName, prefix: Option<DOMString>, - document: &Document) -> Root<HTMLStyleElement> { - Node::reflect_node(box HTMLStyleElement::new_inherited(local_name, prefix, document), + document: &Document, + creator: ElementCreator) -> Root<HTMLStyleElement> { + Node::reflect_node(box HTMLStyleElement::new_inherited(local_name, prefix, document, creator), document, HTMLStyleElementBinding::Wrap) } @@ -68,10 +81,19 @@ impl HTMLStyleElement { let data = node.GetTextContent().expect("Element.textContent must be a string"); let mq = parse_media_query_list(&mut CssParser::new(&mq_str)); - let sheet = Stylesheet::from_str(&data, url, Origin::Author, mq, win.css_error_reporter(), + let loader = StylesheetLoader::for_element(self.upcast()); + let sheet = Stylesheet::from_str(&data, url, Origin::Author, mq, + Some(&loader), + win.css_error_reporter(), ParserContextExtraData::default()); + let sheet = Arc::new(sheet); + // No subresource loads were triggered, just fire the load event now. + if self.pending_loads.get() == 0 { + self.upcast::<EventTarget>().fire_event(atom!("load")); + } + win.layout_chan().send(Msg::AddStylesheet(sheet.clone())).unwrap(); *self.stylesheet.borrow_mut() = Some(sheet); let doc = document_from_node(self); @@ -121,6 +143,37 @@ impl VirtualMethods for HTMLStyleElement { } } +impl StylesheetOwner for HTMLStyleElement { + fn increment_pending_loads_count(&self) { + self.pending_loads.set(self.pending_loads.get() + 1) + } + + fn load_finished(&self, succeeded: bool) -> Option<bool> { + assert!(self.pending_loads.get() > 0, "What finished?"); + if !succeeded { + self.any_failed_load.set(true); + } + + self.pending_loads.set(self.pending_loads.get() - 1); + if self.pending_loads.get() != 0 { + return None; + } + + let any_failed = self.any_failed_load.get(); + self.any_failed_load.set(false); + Some(any_failed) + } + + fn parser_inserted(&self) -> bool { + self.parser_inserted.get() + } + + fn referrer_policy(&self) -> Option<ReferrerPolicy> { + None + } +} + + impl HTMLStyleElementMethods for HTMLStyleElement { // https://drafts.csswg.org/cssom/#dom-linkstyle-sheet fn GetSheet(&self) -> Option<Root<DOMStyleSheet>> { diff --git a/components/script/dom/htmltablecellelement.rs b/components/script/dom/htmltablecellelement.rs index b4bd885d4ed..4a6ca5ca9b1 100644 --- a/components/script/dom/htmltablecellelement.rs +++ b/components/script/dom/htmltablecellelement.rs @@ -34,11 +34,6 @@ impl HTMLTableCellElement { htmlelement: HTMLElement::new_inherited(tag_name, prefix, document), } } - - #[inline] - pub fn htmlelement(&self) -> &HTMLElement { - &self.htmlelement - } } impl HTMLTableCellElementMethods for HTMLTableCellElement { diff --git a/components/script/dom/htmltableelement.rs b/components/script/dom/htmltableelement.rs index e533c9acdcd..741b53c38ac 100644 --- a/components/script/dom/htmltableelement.rs +++ b/components/script/dom/htmltableelement.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::HTMLTableElementBinding::HTMLTableElementM use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{JS, LayoutJS, MutNullableJS, Root, RootedReference}; use dom::bindings::str::DOMString; use dom::document::Document; use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; @@ -31,7 +31,7 @@ pub struct HTMLTableElement { htmlelement: HTMLElement, border: Cell<Option<u32>>, cellspacing: Cell<Option<u32>>, - tbodies: MutNullableHeap<JS<HTMLCollection>>, + tbodies: MutNullableJS<HTMLCollection>, } #[allow(unrooted_must_root)] diff --git a/components/script/dom/htmltablerowelement.rs b/components/script/dom/htmltablerowelement.rs index b95aba1c3e0..c6b04648dc2 100644 --- a/components/script/dom/htmltablerowelement.rs +++ b/components/script/dom/htmltablerowelement.rs @@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding::HTMLTableS use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{LayoutJS, MutNullableJS, Root, RootedReference}; use dom::bindings::str::DOMString; use dom::document::Document; use dom::element::{Element, RawLayoutElementHelpers}; @@ -36,7 +36,7 @@ impl CollectionFilter for CellsFilter { #[dom_struct] pub struct HTMLTableRowElement { htmlelement: HTMLElement, - cells: MutNullableHeap<JS<HTMLCollection>>, + cells: MutNullableJS<HTMLCollection>, } impl HTMLTableRowElement { diff --git a/components/script/dom/htmltemplateelement.rs b/components/script/dom/htmltemplateelement.rs index 7ee8d03b163..1c9b2c0aacd 100644 --- a/components/script/dom/htmltemplateelement.rs +++ b/components/script/dom/htmltemplateelement.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding; use dom::bindings::codegen::Bindings::HTMLTemplateElementBinding::HTMLTemplateElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::str::DOMString; use dom::document::Document; use dom::documentfragment::DocumentFragment; @@ -21,7 +21,7 @@ pub struct HTMLTemplateElement { htmlelement: HTMLElement, /// https://html.spec.whatwg.org/multipage/#template-contents - contents: MutNullableHeap<JS<DocumentFragment>>, + contents: MutNullableJS<DocumentFragment>, } impl HTMLTemplateElement { @@ -31,7 +31,7 @@ impl HTMLTemplateElement { HTMLTemplateElement { htmlelement: HTMLElement::new_inherited(local_name, prefix, document), - contents: MutNullableHeap::new(None), + contents: MutNullableJS::new(None), } } diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 47b9bb6ee0b..fd5b42fa25c 100755 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -39,6 +39,7 @@ pub struct HTMLTextAreaElement { htmlelement: HTMLElement, #[ignore_heap_size_of = "#7193"] textinput: DOMRefCell<TextInput<IpcSender<ConstellationMsg>>>, + placeholder: DOMRefCell<DOMString>, // https://html.spec.whatwg.org/multipage/#concept-textarea-dirty value_changed: Cell<bool>, } @@ -58,7 +59,12 @@ impl LayoutHTMLTextAreaElementHelpers for LayoutJS<HTMLTextAreaElement> { #[allow(unrooted_must_root)] #[allow(unsafe_code)] unsafe fn get_value_for_layout(self) -> String { - String::from((*self.unsafe_get()).textinput.borrow_for_layout().get_content()) + let text = (*self.unsafe_get()).textinput.borrow_for_layout().get_content(); + String::from(if text.is_empty() { + (*self.unsafe_get()).placeholder.borrow_for_layout().clone() + } else { + text + }) } #[allow(unrooted_must_root)] @@ -105,6 +111,7 @@ impl HTMLTextAreaElement { htmlelement: HTMLElement::new_inherited_with_state(IN_ENABLED_STATE | IN_READ_WRITE_STATE, local_name, prefix, document), + placeholder: DOMRefCell::new(DOMString::new()), textinput: DOMRefCell::new(TextInput::new( Lines::Multiple, DOMString::new(), chan, None, None, SelectionDirection::None)), value_changed: Cell::new(false), @@ -119,6 +126,14 @@ impl HTMLTextAreaElement { document, HTMLTextAreaElementBinding::Wrap) } + + fn update_placeholder_shown_state(&self) { + let has_placeholder = !self.placeholder.borrow().is_empty(); + let has_value = !self.textinput.borrow().is_empty(); + let el = self.upcast::<Element>(); + el.set_placeholder_shown_state(has_placeholder && !has_value); + el.set_placeholder_shown_state(has_placeholder); + } } impl HTMLTextAreaElementMethods for HTMLTextAreaElement { @@ -270,11 +285,6 @@ impl HTMLTextAreaElementMethods for HTMLTextAreaElement { impl HTMLTextAreaElement { - // https://html.spec.whatwg.org/multipage/#concept-fe-mutable - pub fn mutable(&self) -> bool { - // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-fe-mutable - !(self.Disabled() || self.ReadOnly()) - } pub fn reset(&self) { // https://html.spec.whatwg.org/multipage/#the-textarea-element:concept-form-reset-control self.SetValue(self.DefaultValue()); @@ -311,6 +321,16 @@ impl VirtualMethods for HTMLTextAreaElement { } } }, + local_name!("placeholder") => { + { + let mut placeholder = self.placeholder.borrow_mut(); + placeholder.clear(); + if let AttributeMutation::Set(_) = mutation { + placeholder.push_str(&attr.value()); + } + } + self.update_placeholder_shown_state(); + }, local_name!("readonly") => { let el = self.upcast::<Element>(); match mutation { @@ -375,10 +395,14 @@ impl VirtualMethods for HTMLTextAreaElement { document_from_node(self).request_focus(self.upcast()); } else if event.type_() == atom!("keydown") && !event.DefaultPrevented() { if let Some(kevent) = event.downcast::<KeyboardEvent>() { - match self.textinput.borrow_mut().handle_keydown(kevent) { + // This can't be inlined, as holding on to textinput.borrow_mut() + // during self.implicit_submission will cause a panic. + let action = self.textinput.borrow_mut().handle_keydown(kevent); + match action { KeyReaction::TriggerDefaultAction => (), KeyReaction::DispatchInput => { self.value_changed.set(true); + self.update_placeholder_shown_state(); if event.IsTrusted() { let window = window_from_node(self); diff --git a/components/script/dom/htmltimeelement.rs b/components/script/dom/htmltimeelement.rs index 84794443e02..c5286dd685f 100644 --- a/components/script/dom/htmltimeelement.rs +++ b/components/script/dom/htmltimeelement.rs @@ -2,14 +2,11 @@ * 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::codegen::Bindings::ElementBinding::ElementBinding::ElementMethods; use dom::bindings::codegen::Bindings::HTMLTimeElementBinding; use dom::bindings::codegen::Bindings::HTMLTimeElementBinding::HTMLTimeElementMethods; -use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; use dom::bindings::str::DOMString; use dom::document::Document; -use dom::element::Element; use dom::htmlelement::HTMLElement; use dom::node::Node; use html5ever_atoms::LocalName; @@ -38,18 +35,7 @@ impl HTMLTimeElement { impl HTMLTimeElementMethods for HTMLTimeElement { // https://html.spec.whatwg.org/multipage/#dom-time-datetime - //make_getter!(DateTime, "datetime"); - fn DateTime(&self) -> DOMString { - let element = self.upcast::<Element>(); - if element.has_attribute(&local_name!("datetime")) { - return element.get_string_attribute(&local_name!("datetime")) - } else { - match element.GetInnerHTML() { - Ok(x) => x, - _ => DOMString::new(), - } - } - } + make_getter!(DateTime, "datetime"); // https://html.spec.whatwg.org/multipage/#dom-time-datetime make_setter!(SetDateTime, "datetime"); diff --git a/components/script/dom/htmltitleelement.rs b/components/script/dom/htmltitleelement.rs index f3ec357cb56..6dde6a6203b 100644 --- a/components/script/dom/htmltitleelement.rs +++ b/components/script/dom/htmltitleelement.rs @@ -8,11 +8,9 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; use dom::bindings::str::DOMString; -use dom::characterdata::CharacterData; use dom::document::Document; use dom::htmlelement::HTMLElement; use dom::node::{ChildrenMutation, Node}; -use dom::text::Text; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; @@ -41,13 +39,7 @@ impl HTMLTitleElement { impl HTMLTitleElementMethods for HTMLTitleElement { // https://html.spec.whatwg.org/multipage/#dom-title-text fn Text(&self) -> DOMString { - let mut content = String::new(); - for child in self.upcast::<Node>().children() { - if let Some(text) = child.downcast::<Text>() { - content.push_str(&text.upcast::<CharacterData>().data()); - } - } - DOMString::from(content) + self.upcast::<Node>().child_text_content() } // https://html.spec.whatwg.org/multipage/#dom-title-text diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index 99b06bae39d..f2174bdd552 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -537,14 +537,15 @@ macro_rules! document_and_element_event_handlers( #[macro_export] macro_rules! rooted_vec { (let mut $name:ident) => { - rooted_vec!(let mut $name <- ::std::iter::empty()) + let mut root = $crate::dom::bindings::trace::RootableVec::new_unrooted(); + let mut $name = $crate::dom::bindings::trace::RootedVec::new(&mut root); }; (let $name:ident <- $iter:expr) => { - let mut __root = $crate::dom::bindings::trace::RootableVec::new_unrooted(); - let $name = $crate::dom::bindings::trace::RootedVec::new(&mut __root, $iter); + let mut root = $crate::dom::bindings::trace::RootableVec::new_unrooted(); + let $name = $crate::dom::bindings::trace::RootedVec::from_iter(&mut root, $iter); }; (let mut $name:ident <- $iter:expr) => { - let mut __root = $crate::dom::bindings::trace::RootableVec::new_unrooted(); - let mut $name = $crate::dom::bindings::trace::RootedVec::new(&mut __root, $iter); + let mut root = $crate::dom::bindings::trace::RootableVec::new_unrooted(); + let mut $name = $crate::dom::bindings::trace::RootedVec::from_iter(&mut root, $iter); } } diff --git a/components/script/dom/mediaquerylist.rs b/components/script/dom/mediaquerylist.rs index 86f67cdd8a1..db96a4760cd 100644 --- a/components/script/dom/mediaquerylist.rs +++ b/components/script/dom/mediaquerylist.rs @@ -9,12 +9,15 @@ use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use dom::bindings::codegen::Bindings::MediaQueryListBinding::{self, MediaQueryListMethods}; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root}; +use dom::bindings::reflector::DomObject; use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; use dom::bindings::trace::JSTraceable; use dom::bindings::weakref::{WeakRef, WeakRefVec}; use dom::document::Document; +use dom::event::Event; use dom::eventtarget::EventTarget; +use dom::mediaquerylistevent::MediaQueryListEvent; use euclid::scale_factor::ScaleFactor; use js::jsapi::JSTracer; use std::cell::Cell; @@ -136,8 +139,14 @@ impl WeakMediaQueryListVec { /// https://drafts.csswg.org/cssom-view/#evaluate-media-queries-and-report-changes pub fn evaluate_and_report_changes(&self) { for mql in self.cell.borrow().iter() { - if let MediaQueryListMatchState::Changed(_) = mql.root().unwrap().evaluate_changes() { - mql.root().unwrap().upcast::<EventTarget>().fire_event(atom!("change")); + let mql = mql.root().unwrap(); + if let MediaQueryListMatchState::Changed(_) = mql.evaluate_changes() { + let event = MediaQueryListEvent::new(&mql.global(), + atom!("change"), + false, false, + mql.Media(), + mql.Matches()); + event.upcast::<Event>().fire(mql.upcast::<EventTarget>()); } } } diff --git a/components/script/dom/mediaquerylistevent.rs b/components/script/dom/mediaquerylistevent.rs new file mode 100644 index 00000000000..8edd2fa3ab2 --- /dev/null +++ b/components/script/dom/mediaquerylistevent.rs @@ -0,0 +1,76 @@ +/* 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::bindings::codegen::Bindings::EventBinding::EventMethods; +use dom::bindings::codegen::Bindings::MediaQueryListEventBinding; +use dom::bindings::codegen::Bindings::MediaQueryListEventBinding::MediaQueryListEventInit; +use dom::bindings::codegen::Bindings::MediaQueryListEventBinding::MediaQueryListEventMethods; +use dom::bindings::error::Fallible; +use dom::bindings::inheritance::Castable; +use dom::bindings::js::Root; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::str::DOMString; +use dom::event::Event; +use dom::globalscope::GlobalScope; +use dom::window::Window; +use servo_atoms::Atom; +use std::cell::Cell; + +// https://drafts.csswg.org/cssom-view/#dom-mediaquerylistevent-mediaquerylistevent +#[dom_struct] +pub struct MediaQueryListEvent { + event: Event, + media: DOMString, + matches: Cell<bool> +} + +impl MediaQueryListEvent { + pub fn new_initialized(global: &GlobalScope, + media: DOMString, + matches: bool) -> Root<MediaQueryListEvent> { + let ev = box MediaQueryListEvent { + event: Event::new_inherited(), + media: media, + matches: Cell::new(matches) + }; + reflect_dom_object(ev, global, MediaQueryListEventBinding::Wrap) + } + + pub fn new(global: &GlobalScope, type_: Atom, + bubbles: bool, cancelable: bool, + media: DOMString, matches: bool) -> Root<MediaQueryListEvent> { + let ev = MediaQueryListEvent::new_initialized(global, media, matches); + { + let event = ev.upcast::<Event>(); + event.init_event(type_, bubbles, cancelable); + } + ev + } + + pub fn Constructor(window: &Window, type_: DOMString, + init: &MediaQueryListEventInit) + -> Fallible<Root<MediaQueryListEvent>> { + let global = window.upcast::<GlobalScope>(); + Ok(MediaQueryListEvent::new(global, Atom::from(type_), + init.parent.bubbles, init.parent.cancelable, + init.media.clone(), init.matches)) + } +} + +impl MediaQueryListEventMethods for MediaQueryListEvent { + // https://drafts.csswg.org/cssom-view/#dom-mediaquerylistevent-media + fn Media(&self) -> DOMString { + self.media.clone() + } + + // https://drafts.csswg.org/cssom-view/#dom-mediaquerylistevent-matches + fn Matches(&self) -> bool { + self.matches.get() + } + + // https://dom.spec.whatwg.org/#dom-event-istrusted + fn IsTrusted(&self) -> bool { + self.upcast::<Event>().IsTrusted() + } +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 5bc19eab627..4f94ac8309f 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -32,8 +32,8 @@ //! * rooting pointers on the stack: //! the [`Root`](bindings/js/struct.Root.html) smart pointer; //! * tracing pointers in member fields: the [`JS`](bindings/js/struct.JS.html), -//! [`MutNullableHeap`](bindings/js/struct.MutNullableHeap.html) and -//! [`MutHeap`](bindings/js/struct.MutHeap.html) smart pointers and +//! [`MutNullableJS`](bindings/js/struct.MutNullableJS.html) and +//! [`MutJS`](bindings/js/struct.MutJS.html) smart pointers and //! [the tracing implementation](bindings/trace/index.html); //! * rooting pointers from across thread boundaries or in channels: the //! [`Trusted`](bindings/refcounted/struct.Trusted.html) smart pointer; @@ -217,13 +217,10 @@ pub mod abstractworkerglobalscope; pub mod activation; pub mod attr; pub mod beforeunloadevent; -mod create; -#[allow(unsafe_code)] -#[deny(missing_docs, non_snake_case)] pub mod bindings; pub mod blob; pub mod bluetooth; -pub mod bluetoothadvertisingdata; +pub mod bluetoothadvertisingevent; pub mod bluetoothcharacteristicproperties; pub mod bluetoothdevice; pub mod bluetoothremotegattcharacteristic; @@ -240,10 +237,12 @@ pub mod client; pub mod closeevent; pub mod comment; pub mod console; +mod create; pub mod crypto; pub mod css; pub mod cssfontfacerule; pub mod cssgroupingrule; +pub mod cssimportrule; pub mod csskeyframerule; pub mod csskeyframesrule; pub mod cssmediarule; @@ -370,6 +369,7 @@ pub mod location; pub mod mediaerror; pub mod medialist; pub mod mediaquerylist; +pub mod mediaquerylistevent; pub mod messageevent; pub mod mimetype; pub mod mimetypearray; diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs index 2b39d555204..3b0e3fb1710 100644 --- a/components/script/dom/mouseevent.rs +++ b/components/script/dom/mouseevent.rs @@ -7,16 +7,16 @@ use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods; use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods; use dom::bindings::error::Fallible; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{MutNullableJS, Root, RootedReference}; use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; use dom::uievent::UIEvent; use dom::window::Window; +use servo_config::prefs::PREFS; use std::cell::Cell; use std::default::Default; -use util::prefs::PREFS; #[dom_struct] pub struct MouseEvent { @@ -30,7 +30,7 @@ pub struct MouseEvent { alt_key: Cell<bool>, meta_key: Cell<bool>, button: Cell<i16>, - related_target: MutNullableHeap<JS<EventTarget>>, + related_target: MutNullableJS<EventTarget>, } impl MouseEvent { diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index 9318e437ad5..b7d781f5eb0 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::Bindings::NavigatorBinding; use dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::{Reflector, DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bluetooth::Bluetooth; @@ -17,10 +17,10 @@ use dom::window::Window; #[dom_struct] pub struct Navigator { reflector_: Reflector, - bluetooth: MutNullableHeap<JS<Bluetooth>>, - plugins: MutNullableHeap<JS<PluginArray>>, - mime_types: MutNullableHeap<JS<MimeTypeArray>>, - service_worker: MutNullableHeap<JS<ServiceWorkerContainer>>, + bluetooth: MutNullableJS<Bluetooth>, + plugins: MutNullableJS<PluginArray>, + mime_types: MutNullableJS<MimeTypeArray>, + service_worker: MutNullableJS<ServiceWorkerContainer>, } impl Navigator { diff --git a/components/script/dom/navigatorinfo.rs b/components/script/dom/navigatorinfo.rs index 54200e7be20..f0b331c49e6 100644 --- a/components/script/dom/navigatorinfo.rs +++ b/components/script/dom/navigatorinfo.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::str::DOMString; -use util::opts; +use servo_config::opts; pub fn Product() -> DOMString { DOMString::from("Gecko") diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 983f11f478c..d6bc301955d 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -21,7 +21,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::{Castable, CharacterDataTypeId, ElementTypeId}; use dom::bindings::inheritance::{EventTargetTypeId, HTMLElementTypeId, NodeTypeId}; use dom::bindings::inheritance::{SVGElementTypeId, SVGGraphicsElementTypeId}; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap}; +use dom::bindings::js::{JS, LayoutJS, MutNullableJS}; use dom::bindings::js::Root; use dom::bindings::js::RootedReference; use dom::bindings::reflector::{DomObject, reflect_dom_object}; @@ -57,7 +57,6 @@ use euclid::point::Point2D; use euclid::rect::Rect; use euclid::size::Size2D; use heapsize::{HeapSizeOf, heap_size_of}; -use html5ever::tree_builder::QuirksMode; use html5ever_atoms::{Prefix, Namespace, QualName}; use js::jsapi::{JSContext, JSObject, JSRuntime}; use libc::{self, c_void, uintptr_t}; @@ -78,6 +77,7 @@ use std::iter; use std::mem; use std::ops::Range; use std::sync::Arc; +use style::context::QuirksMode; use style::dom::OpaqueNode; use style::selector_parser::{SelectorImpl, SelectorParser}; use style::stylesheets::Stylesheet; @@ -95,25 +95,25 @@ pub struct Node { eventtarget: EventTarget, /// The parent of this node. - parent_node: MutNullableHeap<JS<Node>>, + parent_node: MutNullableJS<Node>, /// The first child of this node. - first_child: MutNullableHeap<JS<Node>>, + first_child: MutNullableJS<Node>, /// The last child of this node. - last_child: MutNullableHeap<JS<Node>>, + last_child: MutNullableJS<Node>, /// The next sibling of this node. - next_sibling: MutNullableHeap<JS<Node>>, + next_sibling: MutNullableJS<Node>, /// The previous sibling of this node. - prev_sibling: MutNullableHeap<JS<Node>>, + prev_sibling: MutNullableJS<Node>, /// The document that this node belongs to. - owner_doc: MutNullableHeap<JS<Document>>, + owner_doc: MutNullableJS<Document>, /// The live list of children return by .childNodes. - child_list: MutNullableHeap<JS<NodeList>>, + child_list: MutNullableJS<NodeList>, /// The live count of children of this node. children_count: Cell<u32>, @@ -426,10 +426,6 @@ impl Node { self.get_flag(HAS_DIRTY_DESCENDANTS) } - pub fn set_has_dirty_descendants(&self, state: bool) { - self.set_flag(HAS_DIRTY_DESCENDANTS, state) - } - pub fn rev_version(&self) { // The new version counter is 1 plus the max of the node's current version counter, // its descendants version, and the document's version. Normally, this will just be @@ -1370,7 +1366,7 @@ impl Node { last_child: Default::default(), next_sibling: Default::default(), prev_sibling: Default::default(), - owner_doc: MutNullableHeap::new(doc), + owner_doc: MutNullableJS::new(doc), child_list: Default::default(), children_count: Cell::new(0u32), flags: Cell::new(flags), @@ -1788,12 +1784,16 @@ impl Node { copy } + /// https://html.spec.whatwg.org/multipage/#child-text-content + pub fn child_text_content(&self) -> DOMString { + Node::collect_text_contents(self.children()) + } + pub fn collect_text_contents<T: Iterator<Item=Root<Node>>>(iterator: T) -> DOMString { let mut content = String::new(); for node in iterator { - match node.downcast::<Text>() { - Some(ref text) => content.push_str(&text.upcast::<CharacterData>().data()), - None => (), + if let Some(ref text) = node.downcast::<Text>() { + content.push_str(&text.upcast::<CharacterData>().data()); } } DOMString::from(content) diff --git a/components/script/dom/nodeiterator.rs b/components/script/dom/nodeiterator.rs index d9e46a5ea44..920d94d635c 100644 --- a/components/script/dom/nodeiterator.rs +++ b/components/script/dom/nodeiterator.rs @@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilterConstants; use dom::bindings::codegen::Bindings::NodeIteratorBinding; use dom::bindings::codegen::Bindings::NodeIteratorBinding::NodeIteratorMethods; use dom::bindings::error::Fallible; -use dom::bindings::js::{JS, MutHeap, Root}; +use dom::bindings::js::{JS, MutJS, Root}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::document::Document; use dom::node::Node; @@ -21,7 +21,7 @@ pub struct NodeIterator { reflector_: Reflector, root_node: JS<Node>, #[ignore_heap_size_of = "Defined in rust-mozjs"] - reference_node: MutHeap<JS<Node>>, + reference_node: MutJS<Node>, pointer_before_reference_node: Cell<bool>, what_to_show: u32, #[ignore_heap_size_of = "Can't measure due to #6870"] @@ -35,7 +35,7 @@ impl NodeIterator { NodeIterator { reflector_: Reflector::new(), root_node: JS::from_ref(root_node), - reference_node: MutHeap::new(root_node), + reference_node: MutJS::new(root_node), pointer_before_reference_node: Cell::new(true), what_to_show: what_to_show, filter: filter @@ -79,7 +79,6 @@ impl NodeIteratorMethods for NodeIterator { match self.filter { Filter::None => None, Filter::Callback(ref nf) => Some((*nf).clone()), - Filter::Native(_) => panic!("Cannot convert native node filter to DOM NodeFilter") } } @@ -200,7 +199,6 @@ impl NodeIterator { // Step 3-5. match self.filter { Filter::None => Ok(NodeFilterConstants::FILTER_ACCEPT), - Filter::Native(f) => Ok((f)(node)), Filter::Callback(ref callback) => callback.AcceptNode_(self, node, Rethrow) } } @@ -210,6 +208,5 @@ impl NodeIterator { #[derive(JSTraceable)] pub enum Filter { None, - Native(fn (node: &Node) -> u16), Callback(Rc<NodeFilter>) } diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index 391d21d5865..21e05fc7dcc 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::Bindings::NodeListBinding; use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{JS, MutNullableJS, Root, RootedReference}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::node::{ChildrenMutation, Node}; use dom::window::Window; @@ -111,7 +111,7 @@ impl NodeList { pub struct ChildrenList { node: JS<Node>, #[ignore_heap_size_of = "Defined in rust-mozjs"] - last_visited: MutNullableHeap<JS<Node>>, + last_visited: MutNullableJS<Node>, last_index: Cell<u32>, } @@ -120,7 +120,7 @@ impl ChildrenList { let last_visited = node.GetFirstChild(); ChildrenList { node: JS::from_ref(node), - last_visited: MutNullableHeap::new(last_visited.r()), + last_visited: MutNullableJS::new(last_visited.r()), last_index: Cell::new(0u32), } } diff --git a/components/script/dom/radionodelist.rs b/components/script/dom/radionodelist.rs index 5cf05cb872a..b8078aa6670 100644 --- a/components/script/dom/radionodelist.rs +++ b/components/script/dom/radionodelist.rs @@ -40,10 +40,6 @@ impl RadioNodeList { RadioNodeList::new(window, NodeListType::Simple(iter.map(|r| JS::from_ref(&*r)).collect())) } - pub fn empty(window: &Window) -> Root<RadioNodeList> { - RadioNodeList::new(window, NodeListType::Simple(vec![])) - } - // FIXME: This shouldn't need to be implemented here since NodeList (the parent of // RadioNodeList) implements Length // https://github.com/servo/servo/issues/5875 diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs index 723239ea3d3..e9e3a484d41 100644 --- a/components/script/dom/range.rs +++ b/components/script/dom/range.rs @@ -13,7 +13,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutHeap, Root, RootedReference}; +use dom::bindings::js::{JS, MutJS, Root, RootedReference}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::bindings::trace::JSTraceable; @@ -934,7 +934,7 @@ impl RangeMethods for Range { #[privatize] #[derive(HeapSizeOf)] pub struct BoundaryPoint { - node: MutHeap<JS<Node>>, + node: MutJS<Node>, offset: Cell<u32>, } @@ -943,7 +943,7 @@ impl BoundaryPoint { debug_assert!(!node.is_doctype()); debug_assert!(offset <= node.len()); BoundaryPoint { - node: MutHeap::new(node), + node: MutJS::new(node), offset: Cell::new(offset), } } diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs index cb338d65b29..8ca9104b945 100644 --- a/components/script/dom/request.rs +++ b/components/script/dom/request.rs @@ -17,7 +17,7 @@ use dom::bindings::codegen::Bindings::RequestBinding::RequestMode; use dom::bindings::codegen::Bindings::RequestBinding::RequestRedirect; use dom::bindings::codegen::Bindings::RequestBinding::RequestType; use dom::bindings::error::{Error, Fallible}; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::str::{ByteString, DOMString, USVString}; use dom::globalscope::GlobalScope; @@ -45,7 +45,7 @@ pub struct Request { reflector_: Reflector, request: DOMRefCell<NetTraitsRequest>, body_used: Cell<bool>, - headers: MutNullableHeap<JS<Headers>>, + headers: MutNullableJS<Headers>, mime_type: DOMRefCell<Vec<u8>>, #[ignore_heap_size_of = "Rc"] body_promise: DOMRefCell<Option<(Rc<Promise>, BodyType)>>, @@ -92,8 +92,7 @@ impl Request { let mut fallback_credentials: Option<NetTraitsRequestCredentials> = None; // Step 4 - // TODO: `entry settings object` is not implemented in Servo yet. - let base_url = global.get_url(); + let base_url = global.api_base_url(); match input { // Step 5 diff --git a/components/script/dom/response.rs b/components/script/dom/response.rs index 278ead3c36d..1d9d62c079a 100644 --- a/components/script/dom/response.rs +++ b/components/script/dom/response.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::ResponseBinding; use dom::bindings::codegen::Bindings::ResponseBinding::{ResponseMethods, ResponseType as DOMResponseType}; use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::BodyInit; use dom::bindings::error::{Error, Fallible}; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::str::{ByteString, USVString}; use dom::globalscope::GlobalScope; @@ -32,7 +32,7 @@ use url::Position; #[dom_struct] pub struct Response { reflector_: Reflector, - headers_reflector: MutNullableHeap<JS<Headers>>, + headers_reflector: MutNullableJS<Headers>, mime_type: DOMRefCell<Vec<u8>>, body_used: Cell<bool>, /// `None` can be considered a StatusCode of `0`. @@ -149,8 +149,7 @@ impl Response { // https://fetch.spec.whatwg.org/#dom-response-redirect pub fn Redirect(global: &GlobalScope, url: USVString, status: u16) -> Fallible<Root<Response>> { // Step 1 - // TODO: `entry settings object` is not implemented in Servo yet. - let base_url = global.get_url(); + let base_url = global.api_base_url(); let parsed_url = base_url.join(&url.0); // Step 2 diff --git a/components/script/dom/serviceworkercontainer.rs b/components/script/dom/serviceworkercontainer.rs index e5662f56dee..6757fc0179d 100644 --- a/components/script/dom/serviceworkercontainer.rs +++ b/components/script/dom/serviceworkercontainer.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::{ServiceWorkerContainerMethods, Wrap}; use dom::bindings::codegen::Bindings::ServiceWorkerContainerBinding::RegistrationOptions; use dom::bindings::error::Error; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::USVString; use dom::client::Client; @@ -22,7 +22,7 @@ use std::rc::Rc; #[dom_struct] pub struct ServiceWorkerContainer { eventtarget: EventTarget, - controller: MutNullableHeap<JS<ServiceWorker>>, + controller: MutNullableJS<ServiceWorker>, client: JS<Client> } diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs index 4daf07fff20..8dd3da01671 100644 --- a/components/script/dom/serviceworkerglobalscope.rs +++ b/components/script/dom/serviceworkerglobalscope.rs @@ -28,13 +28,12 @@ use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as Req use rand::random; use script_runtime::{CommonScriptMsg, StackRootTLS, get_reports, new_rt_and_cx, ScriptChan}; use script_traits::{TimerEvent, WorkerGlobalScopeInit, ScopeThings, ServiceWorkerMsg, WorkerScriptLoadOrigin}; +use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel}; use std::thread; use std::time::Duration; use style::thread_state::{self, IN_WORKER, SCRIPT}; -use util::prefs::PREFS; -use util::thread::spawn_named; /// Messages used to control service worker event loop pub enum ServiceWorkerScriptMsg { @@ -151,7 +150,7 @@ impl ServiceWorkerGlobalScope { .. } = scope_things; let serialized_worker_url = script_url.to_string(); - spawn_named(format!("ServiceWorker for {}", serialized_worker_url), move || { + thread::Builder::new().name(format!("ServiceWorker for {}", serialized_worker_url)).spawn(move || { thread_state::initialize(SCRIPT | IN_WORKER); let roots = RootCollection::new(); let _stack_roots_tls = StackRootTLS::new(&roots); @@ -202,11 +201,11 @@ impl ServiceWorkerGlobalScope { scope.execute_script(DOMString::from(source)); // Service workers are time limited - spawn_named("SWTimeoutThread".to_owned(), move || { + thread::Builder::new().name("SWTimeoutThread".to_owned()).spawn(move || { let sw_lifetime_timeout = PREFS.get("dom.serviceworker.timeout_seconds").as_u64().unwrap(); thread::sleep(Duration::new(sw_lifetime_timeout, 0)); let _ = timer_chan.send(()); - }); + }).expect("Thread spawning failed"); global.dispatch_activate(); let reporter_name = format!("service-worker-reporter-{}", random::<u64>()); @@ -217,7 +216,7 @@ impl ServiceWorkerGlobalScope { } } }, reporter_name, scope.script_chan(), CommonScriptMsg::CollectReports); - }); + }).expect("Thread spawning failed"); } fn handle_event(&self, event: MixedMessage) -> bool { diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs index ac6330c3ca2..28f8735891e 100644 --- a/components/script/dom/servoparser/html.rs +++ b/components/script/dom/servoparser/html.rs @@ -34,6 +34,7 @@ use js::jsapi::JSTracer; use servo_url::ServoUrl; use std::borrow::Cow; use std::io::{self, Write}; +use style::context::QuirksMode as ServoQuirksMode; #[derive(HeapSizeOf, JSTraceable)] #[must_root] @@ -187,6 +188,11 @@ impl<'a> TreeSink for Sink { } fn set_quirks_mode(&mut self, mode: QuirksMode) { + let mode = match mode { + QuirksMode::Quirks => ServoQuirksMode::Quirks, + QuirksMode::LimitedQuirks => ServoQuirksMode::LimitedQuirks, + QuirksMode::NoQuirks => ServoQuirksMode::NoQuirks, + }; self.document.set_quirks_mode(mode); } diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs index c6f4364925b..2f4f485be12 100644 --- a/components/script/dom/servoparser/mod.rs +++ b/components/script/dom/servoparser/mod.rs @@ -32,10 +32,10 @@ use network_listener::PreInvoke; use profile_traits::time::{TimerMetadata, TimerMetadataFrameType}; use profile_traits::time::{TimerMetadataReflowType, ProfilerCategory, profile}; use script_thread::ScriptThread; +use servo_config::resource_files::read_resource_file; use servo_url::ServoUrl; use std::cell::Cell; use std::mem; -use util::resource_files::read_resource_file; mod html; mod xml; diff --git a/components/script/dom/servoparser/xml.rs b/components/script/dom/servoparser/xml.rs index bcbfa6c4169..616263651c3 100644 --- a/components/script/dom/servoparser/xml.rs +++ b/components/script/dom/servoparser/xml.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, MutNullableJS, Root}; use dom::bindings::str::DOMString; use dom::bindings::trace::JSTraceable; use dom::comment::Comment; @@ -97,7 +97,7 @@ unsafe impl JSTraceable for XmlTokenizer<XmlTreeBuilder<JS<Node>, Sink>> { struct Sink { base_url: ServoUrl, document: JS<Document>, - script: MutNullableHeap<JS<HTMLScriptElement>>, + script: MutNullableJS<HTMLScriptElement>, } impl<'a> TreeSink for Sink { diff --git a/components/script/dom/storageevent.rs b/components/script/dom/storageevent.rs index 172a7be9ed8..9778976dc0f 100644 --- a/components/script/dom/storageevent.rs +++ b/components/script/dom/storageevent.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::StorageEventBinding; use dom::bindings::codegen::Bindings::StorageEventBinding::StorageEventMethods; use dom::bindings::error::Fallible; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; +use dom::bindings::js::{MutNullableJS, Root, RootedReference}; use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; use dom::event::{Event, EventBubbles, EventCancelable}; @@ -23,7 +23,7 @@ pub struct StorageEvent { old_value: Option<DOMString>, new_value: Option<DOMString>, url: DOMString, - storage_area: MutNullableHeap<JS<Storage>> + storage_area: MutNullableJS<Storage> } @@ -39,7 +39,7 @@ impl StorageEvent { old_value: old_value, new_value: new_value, url: url, - storage_area: MutNullableHeap::new(storage_area) + storage_area: MutNullableJS::new(storage_area) } } diff --git a/components/script/dom/svgelement.rs b/components/script/dom/svgelement.rs index c89bab166ee..3a18f965ecc 100644 --- a/components/script/dom/svgelement.rs +++ b/components/script/dom/svgelement.rs @@ -2,13 +2,10 @@ * 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::codegen::Bindings::SVGElementBinding; use dom::bindings::inheritance::Castable; -use dom::bindings::js::Root; use dom::bindings::str::DOMString; use dom::document::Document; use dom::element::Element; -use dom::node::Node; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; use style::element_state::ElementState; @@ -19,11 +16,6 @@ pub struct SVGElement { } impl SVGElement { - pub fn new_inherited(tag_name: LocalName, prefix: Option<DOMString>, - document: &Document) -> SVGElement { - SVGElement::new_inherited_with_state(ElementState::empty(), tag_name, prefix, document) - } - pub fn new_inherited_with_state(state: ElementState, tag_name: LocalName, prefix: Option<DOMString>, document: &Document) -> SVGElement { @@ -32,13 +24,6 @@ impl SVGElement { Element::new_inherited_with_state(state, tag_name, ns!(svg), prefix, document), } } - - #[allow(unrooted_must_root)] - pub fn new(local_name: LocalName, prefix: Option<DOMString>, document: &Document) -> Root<SVGElement> { - Node::reflect_node(box SVGElement::new_inherited(local_name, prefix, document), - document, - SVGElementBinding::Wrap) - } } impl VirtualMethods for SVGElement { diff --git a/components/script/dom/svggraphicselement.rs b/components/script/dom/svggraphicselement.rs index 9435cc6d6b7..b8e8aced371 100644 --- a/components/script/dom/svggraphicselement.rs +++ b/components/script/dom/svggraphicselement.rs @@ -2,12 +2,9 @@ * 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::codegen::Bindings::SVGGraphicsElementBinding; use dom::bindings::inheritance::Castable; -use dom::bindings::js::Root; use dom::bindings::str::DOMString; use dom::document::Document; -use dom::node::Node; use dom::svgelement::SVGElement; use dom::virtualmethods::VirtualMethods; use html5ever_atoms::LocalName; @@ -32,13 +29,6 @@ impl SVGGraphicsElement { SVGElement::new_inherited_with_state(state, tag_name, prefix, document), } } - - #[allow(unrooted_must_root)] - pub fn new(local_name: LocalName, prefix: Option<DOMString>, document: &Document) -> Root<SVGGraphicsElement> { - Node::reflect_node(box SVGGraphicsElement::new_inherited(local_name, prefix, document), - document, - SVGGraphicsElementBinding::Wrap) - } } impl VirtualMethods for SVGGraphicsElement { diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index 6b0c619749a..9f65d04bbfa 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -37,11 +37,11 @@ use js::jsapi::{HandleObject, HandleValue, JSContext, JSObject, JSAutoCompartmen use js::jsapi::{JS_NewPlainObject, JS_NewUint8ClampedArray}; use js::jsval::{JSVal, NullValue}; use script_traits::MsDuration; +use servo_config::prefs::PREFS; use std::borrow::ToOwned; use std::ptr; use std::rc::Rc; use timers::OneshotTimerCallback; -use util::prefs::PREFS; #[dom_struct] pub struct TestBinding { diff --git a/components/script/dom/touch.rs b/components/script/dom/touch.rs index 32eeb24b6e1..9b4e61788d3 100644 --- a/components/script/dom/touch.rs +++ b/components/script/dom/touch.rs @@ -4,7 +4,7 @@ use dom::bindings::codegen::Bindings::TouchBinding; use dom::bindings::codegen::Bindings::TouchBinding::TouchMethods; -use dom::bindings::js::{JS, MutHeap, Root}; +use dom::bindings::js::{MutJS, Root}; use dom::bindings::num::Finite; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::eventtarget::EventTarget; @@ -14,7 +14,7 @@ use dom::window::Window; pub struct Touch { reflector_: Reflector, identifier: i32, - target: MutHeap<JS<EventTarget>>, + target: MutJS<EventTarget>, screen_x: f64, screen_y: f64, client_x: f64, @@ -31,7 +31,7 @@ impl Touch { Touch { reflector_: Reflector::new(), identifier: identifier, - target: MutHeap::new(target), + target: MutJS::new(target), screen_x: *screen_x, screen_y: *screen_y, client_x: *client_x, diff --git a/components/script/dom/touchevent.rs b/components/script/dom/touchevent.rs index 9b4b3a250d5..f20dc4dc012 100644 --- a/components/script/dom/touchevent.rs +++ b/components/script/dom/touchevent.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::TouchEventBinding; use dom::bindings::codegen::Bindings::TouchEventBinding::TouchEventMethods; use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutHeap, Root}; +use dom::bindings::js::{MutJS, Root}; use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; use dom::event::{EventBubbles, EventCancelable}; @@ -18,9 +18,9 @@ use std::cell::Cell; #[dom_struct] pub struct TouchEvent { uievent: UIEvent, - touches: MutHeap<JS<TouchList>>, - target_touches: MutHeap<JS<TouchList>>, - changed_touches: MutHeap<JS<TouchList>>, + touches: MutJS<TouchList>, + target_touches: MutJS<TouchList>, + changed_touches: MutJS<TouchList>, alt_key: Cell<bool>, meta_key: Cell<bool>, ctrl_key: Cell<bool>, @@ -33,9 +33,9 @@ impl TouchEvent { target_touches: &TouchList) -> TouchEvent { TouchEvent { uievent: UIEvent::new_inherited(), - touches: MutHeap::new(touches), - target_touches: MutHeap::new(target_touches), - changed_touches: MutHeap::new(changed_touches), + touches: MutJS::new(touches), + target_touches: MutJS::new(target_touches), + changed_touches: MutJS::new(changed_touches), ctrl_key: Cell::new(false), shift_key: Cell::new(false), alt_key: Cell::new(false), diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs index 1dc3d22f1cf..2a3367b3393 100644 --- a/components/script/dom/treewalker.rs +++ b/components/script/dom/treewalker.rs @@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::NodeFilterBinding::NodeFilterConstants; use dom::bindings::codegen::Bindings::TreeWalkerBinding; use dom::bindings::codegen::Bindings::TreeWalkerBinding::TreeWalkerMethods; use dom::bindings::error::Fallible; -use dom::bindings::js::{JS, MutHeap}; +use dom::bindings::js::{JS, MutJS}; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::document::Document; @@ -21,7 +21,7 @@ use std::rc::Rc; pub struct TreeWalker { reflector_: Reflector, root_node: JS<Node>, - current_node: MutHeap<JS<Node>>, + current_node: MutJS<Node>, what_to_show: u32, #[ignore_heap_size_of = "function pointers and Rc<T> are hard"] filter: Filter @@ -34,7 +34,7 @@ impl TreeWalker { TreeWalker { reflector_: Reflector::new(), root_node: JS::from_ref(root_node), - current_node: MutHeap::new(root_node), + current_node: MutJS::new(root_node), what_to_show: what_to_show, filter: filter } @@ -251,9 +251,6 @@ impl TreeWalkerMethods for TreeWalker { } } -type NodeAdvancer<'a> = Fn(&Node) -> Option<Root<Node>> + 'a; - - impl TreeWalker { // https://dom.spec.whatwg.org/#concept-traverse-children fn traverse_children<F, G>(&self, diff --git a/components/script/dom/uievent.rs b/components/script/dom/uievent.rs index 289088b2977..b8c09a48994 100644 --- a/components/script/dom/uievent.rs +++ b/components/script/dom/uievent.rs @@ -7,8 +7,7 @@ use dom::bindings::codegen::Bindings::UIEventBinding; use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods; use dom::bindings::error::Fallible; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, RootedReference}; -use dom::bindings::js::Root; +use dom::bindings::js::{MutNullableJS, Root, RootedReference}; use dom::bindings::reflector::reflect_dom_object; use dom::bindings::str::DOMString; use dom::event::{Event, EventBubbles, EventCancelable}; @@ -21,7 +20,7 @@ use std::default::Default; #[dom_struct] pub struct UIEvent { event: Event, - view: MutNullableHeap<JS<Window>>, + view: MutNullableJS<Window>, detail: Cell<i32> } diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs index 2f3e3c3f923..cea4c898119 100644 --- a/components/script/dom/url.rs +++ b/components/script/dom/url.rs @@ -6,7 +6,7 @@ use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; use dom::bindings::codegen::Bindings::URLBinding::{self, URLMethods}; use dom::bindings::error::{Error, ErrorResult, Fallible}; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::str::{DOMString, USVString}; use dom::blob::Blob; @@ -30,7 +30,7 @@ pub struct URL { url: DOMRefCell<ServoUrl>, // https://url.spec.whatwg.org/#dom-url-searchparams - search_params: MutNullableHeap<JS<URLSearchParams>>, + search_params: MutNullableJS<URLSearchParams>, } impl URL { diff --git a/components/script/dom/userscripts.rs b/components/script/dom/userscripts.rs index a4051f44581..66758afaa98 100644 --- a/components/script/dom/userscripts.rs +++ b/components/script/dom/userscripts.rs @@ -9,11 +9,11 @@ use dom::bindings::js::RootedReference; use dom::bindings::str::DOMString; use dom::htmlheadelement::HTMLHeadElement; use dom::node::Node; +use servo_config::opts; +use servo_config::resource_files::resources_dir_path; use std::borrow::ToOwned; use std::fs::read_dir; use std::path::PathBuf; -use util::opts; -use util::resource_files::resources_dir_path; pub fn load_script(head: &HTMLHeadElement) { diff --git a/components/script/dom/validitystate.rs b/components/script/dom/validitystate.rs index 10801120871..f5b6501a82d 100755 --- a/components/script/dom/validitystate.rs +++ b/components/script/dom/validitystate.rs @@ -10,8 +10,8 @@ use dom::element::Element; use dom::window::Window; // https://html.spec.whatwg.org/multipage/#validity-states -#[derive(JSTraceable)] -#[derive(HeapSizeOf)] +#[derive(JSTraceable, HeapSizeOf)] +#[allow(dead_code)] pub enum ValidityStatus { ValueMissing, TypeMismatch, diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 02a767958e2..2f18362122d 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -7,7 +7,7 @@ use canvas_traits::CanvasMsg; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::WebGLFramebufferBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; -use dom::bindings::js::{HeapGCValue, JS, Root}; +use dom::bindings::js::{JS, Root}; use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use dom::webglrenderbuffer::WebGLRenderbuffer; @@ -25,8 +25,6 @@ enum WebGLFramebufferAttachment { Texture { texture: JS<WebGLTexture>, level: i32 }, } -impl HeapGCValue for WebGLFramebufferAttachment {} - #[dom_struct] pub struct WebGLFramebuffer { webgl_object: WebGLObject, diff --git a/components/script/dom/webglobject.rs b/components/script/dom/webglobject.rs index 9c7382ce5b5..3ebbf8fb017 100644 --- a/components/script/dom/webglobject.rs +++ b/components/script/dom/webglobject.rs @@ -3,10 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use dom::bindings::codegen::Bindings::WebGLObjectBinding; -use dom::bindings::js::Root; -use dom::bindings::reflector::{Reflector, reflect_dom_object}; -use dom::window::Window; +use dom::bindings::reflector::Reflector; #[dom_struct] pub struct WebGLObject { @@ -19,8 +16,4 @@ impl WebGLObject { reflector_: Reflector::new(), } } - - pub fn new(window: &Window) -> Root<WebGLObject> { - reflect_dom_object(box WebGLObject::new_inherited(), window, WebGLObjectBinding::Wrap) - } } diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 3f18c0e313b..ad33fc2f22f 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -6,7 +6,7 @@ use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::WebGLProgramBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::webglactiveinfo::WebGLActiveInfo; @@ -27,8 +27,8 @@ pub struct WebGLProgram { is_deleted: Cell<bool>, link_called: Cell<bool>, linked: Cell<bool>, - fragment_shader: MutNullableHeap<JS<WebGLShader>>, - vertex_shader: MutNullableHeap<JS<WebGLShader>>, + fragment_shader: MutNullableJS<WebGLShader>, + vertex_shader: MutNullableJS<WebGLShader>, #[ignore_heap_size_of = "Defined in ipc-channel"] renderer: IpcSender<CanvasMsg>, } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 98b160095d5..81dfe804278 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -13,7 +13,7 @@ use dom::bindings::conversions::{array_buffer_to_vec, array_buffer_view_data, ar use dom::bindings::conversions::{array_buffer_view_to_vec, array_buffer_view_to_vec_checked}; use dom::bindings::error::{Error, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, LayoutJS, MutNullableJS, Root}; use dom::bindings::reflector::{DomObject, Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; use dom::event::{Event, EventBubbles, EventCancelable}; @@ -124,13 +124,13 @@ pub struct WebGLRenderingContext { #[ignore_heap_size_of = "Defined in webrender_traits"] last_error: Cell<Option<WebGLError>>, texture_unpacking_settings: Cell<TextureUnpacking>, - bound_framebuffer: MutNullableHeap<JS<WebGLFramebuffer>>, - bound_renderbuffer: MutNullableHeap<JS<WebGLRenderbuffer>>, - bound_texture_2d: MutNullableHeap<JS<WebGLTexture>>, - bound_texture_cube_map: MutNullableHeap<JS<WebGLTexture>>, - bound_buffer_array: MutNullableHeap<JS<WebGLBuffer>>, - bound_buffer_element_array: MutNullableHeap<JS<WebGLBuffer>>, - current_program: MutNullableHeap<JS<WebGLProgram>>, + bound_framebuffer: MutNullableJS<WebGLFramebuffer>, + bound_renderbuffer: MutNullableJS<WebGLRenderbuffer>, + bound_texture_2d: MutNullableJS<WebGLTexture>, + bound_texture_cube_map: MutNullableJS<WebGLTexture>, + bound_buffer_array: MutNullableJS<WebGLBuffer>, + bound_buffer_element_array: MutNullableJS<WebGLBuffer>, + current_program: MutNullableJS<WebGLProgram>, #[ignore_heap_size_of = "Because it's small"] current_vertex_attrib_0: Cell<(f32, f32, f32, f32)>, #[ignore_heap_size_of = "Because it's small"] @@ -159,13 +159,13 @@ impl WebGLRenderingContext { canvas: JS::from_ref(canvas), last_error: Cell::new(None), texture_unpacking_settings: Cell::new(CONVERT_COLORSPACE), - bound_framebuffer: MutNullableHeap::new(None), - bound_texture_2d: MutNullableHeap::new(None), - bound_texture_cube_map: MutNullableHeap::new(None), - bound_buffer_array: MutNullableHeap::new(None), - bound_buffer_element_array: MutNullableHeap::new(None), - bound_renderbuffer: MutNullableHeap::new(None), - current_program: MutNullableHeap::new(None), + bound_framebuffer: MutNullableJS::new(None), + bound_texture_2d: MutNullableJS::new(None), + bound_texture_cube_map: MutNullableJS::new(None), + bound_buffer_array: MutNullableJS::new(None), + bound_buffer_element_array: MutNullableJS::new(None), + bound_renderbuffer: MutNullableJS::new(None), + current_program: MutNullableJS::new(None), current_vertex_attrib_0: Cell::new((0f32, 0f32, 0f32, 1f32)), current_scissor: Cell::new((0, 0, size.width, size.height)), current_clear_color: Cell::new((0.0, 0.0, 0.0, 0.0)) @@ -2829,39 +2829,4 @@ impl UniformSetterType { UniformSetterType::FloatMat4 => 16, } } - - pub fn is_compatible_with(&self, gl_type: u32) -> bool { - gl_type == self.as_gl_constant() || match *self { - // Sampler uniform variables have an index value (the index of the - // texture), and as such they have to be set as ints - UniformSetterType::Int => gl_type == constants::SAMPLER_2D || - gl_type == constants::SAMPLER_CUBE, - // Don't ask me why, but it seems we must allow setting bool - // uniforms with uniform1f. - // - // See the WebGL conformance test - // conformance/uniforms/gl-uniform-bool.html - UniformSetterType::Float => gl_type == constants::BOOL, - UniformSetterType::FloatVec2 => gl_type == constants::BOOL_VEC2, - UniformSetterType::FloatVec3 => gl_type == constants::BOOL_VEC3, - UniformSetterType::FloatVec4 => gl_type == constants::BOOL_VEC4, - _ => false, - } - } - - fn as_gl_constant(&self) -> u32 { - match *self { - UniformSetterType::Int => constants::INT, - UniformSetterType::IntVec2 => constants::INT_VEC2, - UniformSetterType::IntVec3 => constants::INT_VEC3, - UniformSetterType::IntVec4 => constants::INT_VEC4, - UniformSetterType::Float => constants::FLOAT, - UniformSetterType::FloatVec2 => constants::FLOAT_VEC2, - UniformSetterType::FloatVec3 => constants::FLOAT_VEC3, - UniformSetterType::FloatVec4 => constants::FLOAT_VEC4, - UniformSetterType::FloatMat2 => constants::FLOAT_MAT2, - UniformSetterType::FloatMat3 => constants::FLOAT_MAT3, - UniformSetterType::FloatMat4 => constants::FLOAT_MAT4, - } - } } diff --git a/components/script/dom/webglshaderprecisionformat.rs b/components/script/dom/webglshaderprecisionformat.rs index c0f954c8d4d..87ab7490e3a 100644 --- a/components/script/dom/webglshaderprecisionformat.rs +++ b/components/script/dom/webglshaderprecisionformat.rs @@ -2,6 +2,8 @@ * 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/. */ +#![allow(dead_code)] + // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl use dom::bindings::codegen::Bindings::WebGLShaderPrecisionFormatBinding; use dom::bindings::codegen::Bindings::WebGLShaderPrecisionFormatBinding::WebGLShaderPrecisionFormatMethods; diff --git a/components/script/dom/webidls/BluetoothAdvertisingData.webidl b/components/script/dom/webidls/BluetoothAdvertisingEvent.webidl index 27583a95e4e..2bb88b6f9de 100644 --- a/components/script/dom/webidls/BluetoothAdvertisingData.webidl +++ b/components/script/dom/webidls/BluetoothAdvertisingEvent.webidl @@ -2,21 +2,32 @@ * 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/. */ -//https://webbluetoothcg.github.io/web-bluetooth/#bluetoothadvertisingdata +// https://webbluetoothcg.github.io/web-bluetooth/#advertising-events /*interface BluetoothManufacturerDataMap { readonly maplike<unsigned short, DataView>; }; - interface BluetoothServiceDataMap { readonly maplike<UUID, DataView>; };*/ - -[Pref="dom.bluetooth.enabled"] -interface BluetoothAdvertisingData { +[Pref="dom.bluetooth.enabled", Constructor(DOMString type, BluetoothAdvertisingEventInit init)] +interface BluetoothAdvertisingEvent : Event { + readonly attribute BluetoothDevice device; + // readonly attribute FrozenArray<UUID> uuids; + readonly attribute DOMString? name; readonly attribute unsigned short? appearance; readonly attribute byte? txPower; readonly attribute byte? rssi; // readonly attribute BluetoothManufacturerDataMap manufacturerData; // readonly attribute BluetoothServiceDataMap serviceData; }; +dictionary BluetoothAdvertisingEventInit : EventInit { + required BluetoothDevice device; + // sequence<(DOMString or unsigned long)> uuids; + DOMString name; + unsigned short appearance; + byte txPower; + byte rssi; + // Map manufacturerData; + // Map serviceData; +}; diff --git a/components/script/dom/webidls/BluetoothDevice.webidl b/components/script/dom/webidls/BluetoothDevice.webidl index 0e7843db109..a68049dd08b 100644 --- a/components/script/dom/webidls/BluetoothDevice.webidl +++ b/components/script/dom/webidls/BluetoothDevice.webidl @@ -8,13 +8,11 @@ interface BluetoothDevice : EventTarget { readonly attribute DOMString id; readonly attribute DOMString? name; - // TODO: remove this after BluetoothAdvertisingEvent implemented. - readonly attribute BluetoothAdvertisingData adData; readonly attribute BluetoothRemoteGATTServer gatt; - // Promise<void> watchAdvertisements(); - // void unwatchAdvertisements(); - // readonly attribute boolean watchingAdvertisements; + Promise<void> watchAdvertisements(); + void unwatchAdvertisements(); + readonly attribute boolean watchingAdvertisements; }; [NoInterfaceObject] diff --git a/components/script/dom/webidls/CSSGroupingRule.webidl b/components/script/dom/webidls/CSSGroupingRule.webidl index 9f8347a17d5..41ac5e8dd57 100644 --- a/components/script/dom/webidls/CSSGroupingRule.webidl +++ b/components/script/dom/webidls/CSSGroupingRule.webidl @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://drafts.csswg.org/cssom/#the-cssgroupingrule-interface -[Exposed=Window] +[Abstract, Exposed=Window] interface CSSGroupingRule : CSSRule { [SameObject] readonly attribute CSSRuleList cssRules; [Throws] unsigned long insertRule(DOMString rule, unsigned long index); diff --git a/components/script/dom/webidls/CSSImportRule.webidl b/components/script/dom/webidls/CSSImportRule.webidl new file mode 100644 index 00000000000..b8131a7bb87 --- /dev/null +++ b/components/script/dom/webidls/CSSImportRule.webidl @@ -0,0 +1,11 @@ +/* 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/. */ + +// https://drafts.csswg.org/cssom/#cssimportrule +[Exposed=Window] +interface CSSImportRule : CSSRule { + // readonly attribute DOMString href; + // [SameObject, PutForwards=mediaText] readonly attribute MediaList media; + // [SameObject] readonly attribute CSSStyleSheet styleSheet; +}; diff --git a/components/script/dom/webidls/CSSKeyframesRule.webidl b/components/script/dom/webidls/CSSKeyframesRule.webidl index 34d45e1a357..fc31fc62406 100644 --- a/components/script/dom/webidls/CSSKeyframesRule.webidl +++ b/components/script/dom/webidls/CSSKeyframesRule.webidl @@ -5,7 +5,8 @@ // https://drafts.csswg.org/css-animations/#interface-csskeyframesrule [Exposed=Window] interface CSSKeyframesRule : CSSRule { - // attribute DOMString name; + [SetterThrows] + attribute DOMString name; readonly attribute CSSRuleList cssRules; void appendRule(DOMString rule); diff --git a/components/script/dom/webidls/CSSRule.webidl b/components/script/dom/webidls/CSSRule.webidl index 462943430e6..cda06ab1254 100644 --- a/components/script/dom/webidls/CSSRule.webidl +++ b/components/script/dom/webidls/CSSRule.webidl @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://drafts.csswg.org/cssom/#the-cssrule-interface -[Exposed=Window] +[Abstract, Exposed=Window] interface CSSRule { const unsigned short STYLE_RULE = 1; const unsigned short CHARSET_RULE = 2; // historical diff --git a/components/script/dom/webidls/CSSStyleDeclaration.webidl b/components/script/dom/webidls/CSSStyleDeclaration.webidl index 4314eca74f9..c32e9afddfc 100644 --- a/components/script/dom/webidls/CSSStyleDeclaration.webidl +++ b/components/script/dom/webidls/CSSStyleDeclaration.webidl @@ -38,6 +38,10 @@ partial interface CSSStyleDeclaration { [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-color; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundPosition; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-position; + [SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundPositionX; + [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-position-x; + [SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundPositionY; + [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-position-y; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundRepeat; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString background-repeat; [SetterThrows, TreatNullAs=EmptyString] attribute DOMString backgroundImage; diff --git a/components/script/dom/webidls/CSSStyleRule.webidl b/components/script/dom/webidls/CSSStyleRule.webidl index faee525e7ff..145650a916c 100644 --- a/components/script/dom/webidls/CSSStyleRule.webidl +++ b/components/script/dom/webidls/CSSStyleRule.webidl @@ -6,5 +6,5 @@ [Exposed=Window] interface CSSStyleRule : CSSRule { // attribute DOMString selectorText; - // [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style; + [SameObject, PutForwards=cssText] readonly attribute CSSStyleDeclaration style; }; diff --git a/components/script/dom/webidls/MediaQueryListEvent.webidl b/components/script/dom/webidls/MediaQueryListEvent.webidl new file mode 100644 index 00000000000..877ca17b60b --- /dev/null +++ b/components/script/dom/webidls/MediaQueryListEvent.webidl @@ -0,0 +1,15 @@ +/* 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/. */ + +// https://drafts.csswg.org/cssom-view/#dom-mediaquerylistevent-mediaquerylistevent +[Constructor(DOMString type, optional MediaQueryListEventInit eventInitDict), Exposed=(Window)] +interface MediaQueryListEvent : Event { + readonly attribute DOMString media; + readonly attribute boolean matches; +}; + +dictionary MediaQueryListEventInit : EventInit { + DOMString media = ""; + boolean matches = false; +}; diff --git a/components/script/dom/webidls/SVGElement.webidl b/components/script/dom/webidls/SVGElement.webidl index 02f673a420e..529e9e67f06 100644 --- a/components/script/dom/webidls/SVGElement.webidl +++ b/components/script/dom/webidls/SVGElement.webidl @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://svgwg.org/svg2-draft/types.html#InterfaceSVGElement -[Pref="dom.svg.enabled"] +[Abstract, Pref="dom.svg.enabled"] interface SVGElement : Element { //[SameObject] readonly attribute SVGAnimatedString className; diff --git a/components/script/dom/webidls/SVGGraphicsElement.webidl b/components/script/dom/webidls/SVGGraphicsElement.webidl index d8f90e639ea..cf6c315d917 100644 --- a/components/script/dom/webidls/SVGGraphicsElement.webidl +++ b/components/script/dom/webidls/SVGGraphicsElement.webidl @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://svgwg.org/svg2-draft/types.html#InterfaceSVGGraphicsElement -[Pref="dom.svg.enabled"] //dictionary SVGBoundingBoxOptions { // boolean fill = true; // boolean stroke = false; @@ -11,6 +10,7 @@ // boolean clipped = false; //}; +[Abstract, Pref="dom.svg.enabled"] interface SVGGraphicsElement : SVGElement { //[SameObject] readonly attribute SVGAnimatedTransformList transform; diff --git a/components/script/dom/webidls/WebGLObject.webidl b/components/script/dom/webidls/WebGLObject.webidl index 3ac7514830a..3e8f1f54cca 100644 --- a/components/script/dom/webidls/WebGLObject.webidl +++ b/components/script/dom/webidls/WebGLObject.webidl @@ -6,6 +6,6 @@ // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.3 // -[Exposed=Window] +[Abstract, Exposed=Window] interface WebGLObject { }; diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index 0953f7898a2..b2057e7effe 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -22,6 +22,8 @@ use dom::eventtarget::EventTarget; use dom::globalscope::GlobalScope; use dom::messageevent::MessageEvent; use dom::urlhelper::UrlHelper; +use hyper; +use hyper_serde::Serde; use ipc_channel::ipc::{self, IpcReceiver, IpcSender}; use js::jsapi::{JS_GetArrayBufferData, JS_NewArrayBuffer}; use js::jsapi::JSAutoCompartment; @@ -496,13 +498,10 @@ impl Runnable for ConnectionEstablishedTask { }; // Step 5: Cookies. - if let Some(cookies) = self.headers.get_raw("set-cookie") { - for cookie in cookies.iter() { - if let Ok(cookie_value) = String::from_utf8(cookie.clone()) { - let _ = ws.global().core_resource_thread().send( - SetCookiesForUrl(ws.url.clone(), cookie_value, HTTP)); - } - } + if let Some(cookies) = self.headers.get::<hyper::header::SetCookie>() { + let cookies = cookies.iter().map(|c| Serde(c.clone())).collect(); + let _ = ws.global().core_resource_thread().send( + SetCookiesForUrl(ws.url.clone(), cookies, HTTP)); } // Step 6. diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 282979dc7bf..7dd8d71e9c8 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -19,7 +19,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::{ScrollBehavior, ScrollToOp use dom::bindings::codegen::UnionTypes::RequestOrUSVString; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{JS, MutNullableJS, Root}; use dom::bindings::num::Finite; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::DomObject; @@ -28,7 +28,7 @@ use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::utils::{GlobalStaticData, WindowProxyHandler}; use dom::browsingcontext::BrowsingContext; use dom::crypto::Crypto; -use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration}; +use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration, CSSStyleOwner}; use dom::document::{AnimationFrameCallback, Document}; use dom::element::Element; use dom::event::Event; @@ -77,6 +77,9 @@ use script_traits::{DocumentState, TimerEvent, TimerEventId}; use script_traits::{ScriptMsg as ConstellationMsg, TimerEventRequest, WindowSizeData, WindowSizeType}; use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use servo_atoms::Atom; +use servo_config::opts; +use servo_config::prefs::PREFS; +use servo_geometry::{f32_rect_to_au_rect, max_rect}; use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -92,6 +95,7 @@ use std::sync::mpsc::TryRecvError::{Disconnected, Empty}; use style::context::ReflowGoal; use style::error_reporting::ParseErrorReporter; use style::media_queries; +use style::properties::PropertyId; use style::properties::longhands::overflow_x; use style::selector_parser::PseudoElement; use style::str::HTML_SPACE_CHARACTERS; @@ -105,9 +109,6 @@ use timers::{IsInterval, TimerCallback}; #[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))] use tinyfiledialogs::{self, MessageBoxIcon}; use url::Position; -use util::geometry::{self, max_rect}; -use util::opts; -use util::prefs::PREFS; use webdriver_handlers::jsval_to_webdriver; /// Current state of the window object @@ -141,8 +142,6 @@ pub enum ReflowReason { ElementStateChanged, } -pub type ScrollPoint = Point2D<Au>; - #[dom_struct] pub struct Window { globalscope: GlobalScope, @@ -158,19 +157,19 @@ pub struct Window { history_traversal_task_source: HistoryTraversalTaskSource, #[ignore_heap_size_of = "task sources are hard"] file_reading_task_source: FileReadingTaskSource, - navigator: MutNullableHeap<JS<Navigator>>, + navigator: MutNullableJS<Navigator>, #[ignore_heap_size_of = "channels are hard"] image_cache_thread: ImageCacheThread, #[ignore_heap_size_of = "channels are hard"] image_cache_chan: ImageCacheChan, - browsing_context: MutNullableHeap<JS<BrowsingContext>>, - history: MutNullableHeap<JS<History>>, - performance: MutNullableHeap<JS<Performance>>, + browsing_context: MutNullableJS<BrowsingContext>, + history: MutNullableJS<History>, + performance: MutNullableJS<Performance>, navigation_start: u64, navigation_start_precise: f64, - screen: MutNullableHeap<JS<Screen>>, - session_storage: MutNullableHeap<JS<Storage>>, - local_storage: MutNullableHeap<JS<Storage>>, + screen: MutNullableJS<Screen>, + session_storage: MutNullableJS<Storage>, + local_storage: MutNullableJS<Storage>, status: DOMRefCell<DOMString>, /// For sending timeline markers. Will be ignored if @@ -240,7 +239,7 @@ pub struct Window { /// All the MediaQueryLists we need to update media_query_lists: WeakMediaQueryListVec, - test_runner: MutNullableHeap<JS<TestRunner>>, + test_runner: MutNullableJS<TestRunner>, } impl Window { @@ -700,7 +699,10 @@ impl WindowMethods for Window { }; // Step 5. - CSSStyleDeclaration::new(self, element, pseudo, CSSModificationAccess::Readonly) + CSSStyleDeclaration::new(self, + CSSStyleOwner::Element(JS::from_ref(element)), + pseudo, + CSSModificationAccess::Readonly) } // https://drafts.csswg.org/cssom-view/#dom-window-innerheight @@ -1295,16 +1297,16 @@ impl Window { } pub fn resolved_style_query(&self, - element: TrustedNodeAddress, - pseudo: Option<PseudoElement>, - property: &Atom) -> Option<DOMString> { + element: TrustedNodeAddress, + pseudo: Option<PseudoElement>, + property: PropertyId) -> DOMString { if !self.reflow(ReflowGoal::ForScriptQuery, - ReflowQueryType::ResolvedStyleQuery(element, pseudo, property.clone()), + ReflowQueryType::ResolvedStyleQuery(element, pseudo, property), ReflowReason::Query) { - return None; + return DOMString::new(); } let ResolvedStyleResponse(resolved) = self.layout_rpc.resolved_style(); - resolved.map(DOMString::from) + DOMString::from(resolved) } pub fn offset_parent_query(&self, node: TrustedNodeAddress) -> (Option<Root<Element>>, Rect<Au>) { @@ -1412,13 +1414,13 @@ impl Window { } pub fn set_page_clip_rect_with_new_viewport(&self, viewport: Rect<f32>) -> bool { - let rect = geometry::f32_rect_to_au_rect(viewport.clone()); + let rect = f32_rect_to_au_rect(viewport.clone()); self.current_viewport.set(rect); // We use a clipping rectangle that is five times the size of the of the viewport, // so that we don't collect display list items for areas too far outside the viewport, // but also don't trigger reflows every time the viewport changes. static VIEWPORT_EXPANSION: f32 = 2.0; // 2 lengths on each side plus original length is 5 total. - let proposed_clip_rect = geometry::f32_rect_to_au_rect( + let proposed_clip_rect = f32_rect_to_au_rect( viewport.inflate(viewport.size.width * VIEWPORT_EXPANSION, viewport.size.height * VIEWPORT_EXPANSION)); let clip_rect = self.page_clip_rect.get(); diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 430757bce53..221d60c1570 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScop use dom::bindings::codegen::UnionTypes::RequestOrUSVString; use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::js::{MutNullableJS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::DomObject; use dom::bindings::str::DOMString; @@ -73,8 +73,8 @@ pub struct WorkerGlobalScope { closing: Option<Arc<AtomicBool>>, #[ignore_heap_size_of = "Defined in js"] runtime: Runtime, - location: MutNullableHeap<JS<WorkerLocation>>, - navigator: MutNullableHeap<JS<WorkerNavigator>>, + location: MutNullableJS<WorkerLocation>, + navigator: MutNullableJS<WorkerNavigator>, #[ignore_heap_size_of = "Defined in ipc-channel"] /// Optional `IpcSender` for sending the `DevtoolScriptControlMsg` diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 2e1fcd465e8..f676eac3b64 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -14,7 +14,7 @@ use dom::bindings::codegen::Bindings::XMLHttpRequestBinding::XMLHttpRequestRespo use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutHeapJSVal, MutNullableHeap, Root}; +use dom::bindings::js::{JS, MutHeapJSVal, MutNullableJS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::{DomObject, reflect_dom_object}; use dom::bindings::str::{ByteString, DOMString, USVString, is_token}; @@ -53,6 +53,7 @@ use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode use net_traits::trim_http_whitespace; use network_listener::{NetworkListener, PreInvoke}; use servo_atoms::Atom; +use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -64,7 +65,6 @@ use task_source::networking::NetworkingTaskSource; use time; use timers::{OneshotTimerCallback, OneshotTimerHandle}; use url::Position; -use util::prefs::PREFS; #[derive(JSTraceable, PartialEq, Copy, Clone, HeapSizeOf)] enum XMLHttpRequestState { @@ -122,8 +122,8 @@ pub struct XMLHttpRequest { status_text: DOMRefCell<ByteString>, response: DOMRefCell<ByteString>, response_type: Cell<XMLHttpRequestResponseType>, - response_xml: MutNullableHeap<JS<Document>>, - response_blob: MutNullableHeap<JS<Blob>>, + response_xml: MutNullableJS<Document>, + response_blob: MutNullableJS<Blob>, #[ignore_heap_size_of = "Defined in rust-mozjs"] response_json: MutHeapJSVal, #[ignore_heap_size_of = "Defined in hyper"] diff --git a/components/script/layout_wrapper.rs b/components/script/layout_wrapper.rs index 290ebeb2312..e6c38aa1fb3 100644 --- a/components/script/layout_wrapper.rs +++ b/components/script/layout_wrapper.rs @@ -61,7 +61,7 @@ use std::sync::atomic::Ordering; use style::atomic_refcell::AtomicRefCell; use style::attr::AttrValue; use style::computed_values::display; -use style::context::SharedStyleContext; +use style::context::{QuirksMode, SharedStyleContext}; use style::data::ElementData; use style::dom::{LayoutIterator, NodeInfo, OpaqueNode, PresentationalHintsSynthetizer, TElement, TNode}; use style::dom::UnsafeNode; @@ -86,7 +86,11 @@ impl<'ln> Debug for ServoLayoutNode<'ln> { if let Some(el) = self.as_element() { el.fmt(f) } else { - write!(f, "{:?} ({:#x})", self.type_id(), self.opaque().0) + if self.is_text_node() { + write!(f, "<text node> ({:#x})", self.opaque().0) + } else { + write!(f, "<non-text node> ({:#x})", self.opaque().0) + } } } } @@ -156,15 +160,6 @@ impl<'ln> TNode for ServoLayoutNode<'ln> { transmute(node) } - fn dump(self) { - self.dump_indent(0); - } - - fn dump_style(self) { - println!("\nDOM with computed styles:"); - self.dump_style_indent(0); - } - fn children(self) -> LayoutIterator<ServoChildrenIterator<'ln>> { LayoutIterator(ServoChildrenIterator { current: self.first_child(), @@ -290,54 +285,6 @@ impl<'le> GetLayoutData for ServoThreadSafeLayoutElement<'le> { } impl<'ln> ServoLayoutNode<'ln> { - fn dump_indent(self, indent: u32) { - let mut s = String::new(); - for _ in 0..indent { - s.push_str(" "); - } - - s.push_str(&self.debug_str()); - println!("{}", s); - - for kid in self.children() { - kid.dump_indent(indent + 1); - } - } - - fn dump_style_indent(self, indent: u32) { - if self.is_element() { - let mut s = String::new(); - for _ in 0..indent { - s.push_str(" "); - } - s.push_str(&self.debug_style_str()); - println!("{}", s); - } - - for kid in self.children() { - kid.dump_style_indent(indent + 1); - } - } - - fn debug_str(self) -> String { - format!("{:?}: dirty_descendants={}", - self.script_type_id(), - self.as_element().map_or(false, |el| el.has_dirty_descendants())) - } - - fn debug_style_str(self) -> String { - let maybe_element = self.as_element(); - let maybe_data = match maybe_element { - Some(ref el) => el.borrow_data(), - None => None, - }; - if let Some(data) = maybe_data { - format!("{:?}: {:?}", self.script_type_id(), &*data) - } else { - format!("{:?}: style_data=None", self.script_type_id()) - } - } - /// Returns the interior of this node as a `LayoutJS`. This is highly unsafe for layout to /// call and as such is marked `unsafe`. pub unsafe fn get_jsmanaged(&self) -> &LayoutJS<Node> { @@ -374,6 +321,10 @@ impl<'ld> ServoLayoutDocument<'ld> { unsafe { self.document.will_paint(); } } + pub fn quirks_mode(&self) -> QuirksMode { + unsafe { self.document.quirks_mode() } + } + pub fn from_layout_js(doc: LayoutJS<Document>) -> ServoLayoutDocument<'ld> { ServoLayoutDocument { document: doc, @@ -816,7 +767,7 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> { debug_assert!(self.is_text_node()); let parent = self.node.parent_node().unwrap().as_element().unwrap(); let parent_data = parent.get_data().unwrap().borrow(); - parent_data.current_styles().primary.values.clone() + parent_data.styles().primary.values.clone() } fn debug_id(self) -> usize { diff --git a/components/script/lib.rs b/components/script/lib.rs index e80e9553956..52c0cd6f358 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -83,6 +83,8 @@ extern crate script_traits; extern crate selectors; extern crate serde; #[macro_use] extern crate servo_atoms; +#[macro_use] extern crate servo_config; +extern crate servo_geometry; extern crate servo_url; extern crate smallvec; #[macro_use] @@ -93,7 +95,6 @@ extern crate time; extern crate tinyfiledialogs; extern crate url; #[macro_use] -extern crate util; extern crate uuid; extern crate webrender_traits; extern crate websocket; @@ -104,7 +105,7 @@ pub mod clipboard_provider; mod devtools; pub mod document_loader; #[macro_use] -pub mod dom; +mod dom; pub mod fetch; pub mod layout_wrapper; mod mem; @@ -115,7 +116,9 @@ pub mod script_runtime; pub mod script_thread; mod serviceworker_manager; mod serviceworkerjob; +mod stylesheet_loader; mod task_source; +pub mod test; pub mod textinput; mod timers; mod unpremultiplytable; diff --git a/components/script/network_listener.rs b/components/script/network_listener.rs index 5a96317fb18..fc7b4635756 100644 --- a/components/script/network_listener.rs +++ b/components/script/network_listener.rs @@ -2,7 +2,6 @@ * 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 bluetooth_traits::{BluetoothResponseListener, BluetoothResponseResult}; use net_traits::{Action, FetchResponseListener, FetchResponseMsg}; use script_thread::{Runnable, RunnableWrapper}; use std::sync::{Arc, Mutex}; @@ -41,13 +40,6 @@ impl<Listener: FetchResponseListener + PreInvoke + Send + 'static> NetworkListen } } -// helps type inference -impl<Listener: BluetoothResponseListener + PreInvoke + Send + 'static> NetworkListener<Listener> { - pub fn notify_response(&self, action: BluetoothResponseResult) { - self.notify(action); - } -} - /// A gating mechanism that runs before invoking the runnable on the target thread. /// If the `should_invoke` method returns false, the runnable is discarded without /// being invoked. diff --git a/components/script/script_runtime.rs b/components/script/script_runtime.rs index 00e7d3a198e..a21f96c5890 100644 --- a/components/script/script_runtime.rs +++ b/components/script/script_runtime.rs @@ -25,6 +25,8 @@ use js::rust::Runtime; use msg::constellation_msg::PipelineId; use profile_traits::mem::{Report, ReportKind, ReportsChan}; use script_thread::{Runnable, STACK_ROOTS, trace_thread}; +use servo_config::opts; +use servo_config::prefs::PREFS; use std::cell::Cell; use std::io::{Write, stdout}; use std::marker::PhantomData; @@ -35,8 +37,6 @@ use std::ptr; use std::rc::Rc; use style::thread_state; use time::{Tm, now}; -use util::opts; -use util::prefs::PREFS; /// Common messages used to control the event loops in both the script and the worker pub enum CommonScriptMsg { diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index f55d9279138..447b6775bdc 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -32,7 +32,7 @@ use dom::bindings::codegen::Bindings::TransitionEventBinding::TransitionEventIni use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::conversions::{ConversionResult, FromJSValConvertible, StringificationBehavior}; use dom::bindings::inheritance::Castable; -use dom::bindings::js::{JS, MutNullableHeap, Root, RootCollection}; +use dom::bindings::js::{JS, MutNullableJS, Root, RootCollection}; use dom::bindings::js::{RootCollectionPtr, RootedReference}; use dom::bindings::num::Finite; use dom::bindings::refcounted::Trusted; @@ -91,6 +91,7 @@ use script_traits::CompositorEvent::{KeyEvent, MouseButtonEvent, MouseMoveEvent, use script_traits::CompositorEvent::{TouchEvent, TouchpadPressureEvent}; use script_traits::webdriver_msg::WebDriverScriptCommand; use serviceworkerjob::{Job, JobQueue, AsyncJobHandler, FinishJobHandler, InvokeType, SettleType}; +use servo_config::opts; use servo_url::ServoUrl; use std::cell::Cell; use std::collections::{hash_map, HashMap, HashSet}; @@ -101,6 +102,7 @@ use std::result::Result; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::{Receiver, Select, Sender, channel}; +use std::thread; use style::context::ReflowGoal; use style::dom::{TNode, UnsafeNode}; use style::thread_state; @@ -112,8 +114,6 @@ use task_source::networking::NetworkingTaskSource; use task_source::user_interaction::{UserInteractionTask, UserInteractionTaskSource}; use time::Tm; use url::Position; -use util::opts; -use util::thread; use webdriver_handlers; thread_local!(pub static STACK_ROOTS: Cell<Option<RootCollectionPtr>> = Cell::new(None)); @@ -461,7 +461,7 @@ pub struct ScriptThread { js_runtime: Rc<Runtime>, /// The topmost element over the mouse. - topmost_mouse_over_target: MutNullableHeap<JS<Element>>, + topmost_mouse_over_target: MutNullableJS<Element>, /// List of pipelines that have been owned and closed by this script thread. closed_pipelines: DOMRefCell<HashSet<PipelineId>>, @@ -498,13 +498,10 @@ impl<'a> ScriptMemoryFailsafe<'a> { impl<'a> Drop for ScriptMemoryFailsafe<'a> { #[allow(unrooted_must_root)] fn drop(&mut self) { - match self.owner { - Some(owner) => { - for (_, document) in owner.documents.borrow().iter() { - document.window().clear_js_runtime_for_script_deallocation(); - } + if let Some(owner) = self.owner { + for (_, document) in owner.documents.borrow().iter() { + document.window().clear_js_runtime_for_script_deallocation(); } - None => (), } } } @@ -519,8 +516,7 @@ impl ScriptThreadFactory for ScriptThread { let (sender, receiver) = channel(); let layout_chan = sender.clone(); - thread::spawn_named(format!("ScriptThread {:?}", state.id), - move || { + thread::Builder::new().name(format!("ScriptThread {:?}", state.id)).spawn(move || { thread_state::initialize(thread_state::SCRIPT); PipelineNamespace::install(state.pipeline_namespace_id); FrameId::install(state.top_level_frame_id); @@ -553,7 +549,7 @@ impl ScriptThreadFactory for ScriptThread { // This must always be the very last operation performed before the thread completes failsafe.neuter(); - }); + }).expect("Thread spawning failed"); (sender, receiver) } @@ -686,7 +682,7 @@ impl ScriptThread { devtools_sender: ipc_devtools_sender, js_runtime: Rc::new(runtime), - topmost_mouse_over_target: MutNullableHeap::new(Default::default()), + topmost_mouse_over_target: MutNullableJS::new(Default::default()), closed_pipelines: DOMRefCell::new(HashSet::new()), scheduler_chan: state.scheduler_chan, @@ -726,10 +722,8 @@ impl ScriptThread { for (id, document) in self.documents.borrow().iter() { // Only process a resize if layout is idle. - let resize_event = document.window().steal_resize_event(); - match resize_event { - Some((size, size_type)) => resizes.push((id, size, size_type)), - None => () + if let Some((size, size_type)) = document.window().steal_resize_event() { + resizes.push((id, size, size_type)); } } @@ -1050,8 +1044,11 @@ impl ScriptThread { TimerSource::FromWorker => panic!("Worker timeouts must not be sent to script thread"), }; - let window = self.documents.borrow().find_window(pipeline_id) - .expect("ScriptThread: received fire timer msg for a pipeline not in this script thread. This is a bug."); + let window = self.documents.borrow().find_window(pipeline_id); + let window = match window { + Some(w) => w, + None => return warn!("Received fire timer msg for a closed pipeline {}.", pipeline_id), + }; window.handle_fire_timer(id); } @@ -1143,7 +1140,8 @@ impl ScriptThread { } fn handle_resize(&self, id: PipelineId, size: WindowSizeData, size_type: WindowSizeType) { - if let Some(ref window) = self.documents.borrow().find_window(id) { + let window = self.documents.borrow().find_window(id); + if let Some(ref window) = window { window.set_resize_event(size, size_type); return; } @@ -1156,7 +1154,8 @@ impl ScriptThread { } fn handle_viewport(&self, id: PipelineId, rect: Rect<f32>) { - if let Some(document) = self.documents.borrow().find_document(id) { + let document = self.documents.borrow().find_document(id); + if let Some(document) = document { if document.window().set_page_clip_rect_with_new_viewport(rect) { self.rebuild_and_force_reflow(&document, ReflowReason::Viewport); } @@ -1173,7 +1172,7 @@ impl ScriptThread { fn handle_set_scroll_state(&self, id: PipelineId, scroll_states: &[(UntrustedNodeAddress, Point2D<f32>)]) { - let window = match self.documents.borrow().find_window(id) { + let window = match { self.documents.borrow().find_window(id) } { Some(window) => window, None => return warn!("Set scroll state message sent to nonexistent pipeline: {:?}", id), }; @@ -1241,7 +1240,7 @@ impl ScriptThread { } fn handle_loads_complete(&self, pipeline: PipelineId) { - let doc = match self.documents.borrow().find_document(pipeline) { + let doc = match { self.documents.borrow().find_document(pipeline) } { Some(doc) => doc, None => return warn!("Message sent to closed pipeline {}.", pipeline), }; @@ -1296,7 +1295,8 @@ impl ScriptThread { /// To slow/speed up timers and manage any other script thread resource based on visibility. /// Returns true if successful. fn alter_resource_utilization(&self, id: PipelineId, visible: bool) -> bool { - if let Some(window) = self.documents.borrow().find_window(id) { + let window = self.documents.borrow().find_window(id); + if let Some(window) = window { if visible { window.upcast::<GlobalScope>().speed_up_timers(); } else { @@ -1309,7 +1309,8 @@ impl ScriptThread { /// Updates iframe element after a change in visibility fn handle_visibility_change_complete_msg(&self, parent_pipeline_id: PipelineId, id: FrameId, visible: bool) { - if let Some(iframe) = self.documents.borrow().find_iframe(parent_pipeline_id, id) { + let iframe = self.documents.borrow().find_iframe(parent_pipeline_id, id); + if let Some(iframe) = iframe { iframe.change_visibility_status(visible); } } @@ -1337,7 +1338,8 @@ impl ScriptThread { /// Handles freeze message fn handle_freeze_msg(&self, id: PipelineId) { - if let Some(window) = self.documents.borrow().find_window(id) { + let window = self.documents.borrow().find_window(id); + if let Some(window) = window { window.upcast::<GlobalScope>().suspend(); return; } @@ -1351,7 +1353,8 @@ impl ScriptThread { /// Handles thaw message fn handle_thaw_msg(&self, id: PipelineId) { - if let Some(document) = self.documents.borrow().find_document(id) { + let document = self.documents.borrow().find_document(id); + if let Some(document) = document { if let Some(context) = document.browsing_context() { let needed_reflow = context.set_reflow_status(false); if needed_reflow { @@ -1402,14 +1405,16 @@ impl ScriptThread { parent_pipeline_id: PipelineId, frame_id: Option<FrameId>, event: MozBrowserEvent) { - match self.documents.borrow().find_document(parent_pipeline_id) { - None => warn!("Mozbrowser event after pipeline {:?} closed.", parent_pipeline_id), - Some(doc) => match frame_id { - None => doc.window().dispatch_mozbrowser_event(event), - Some(frame_id) => match doc.find_iframe(frame_id) { - None => warn!("Mozbrowser event after iframe {:?}/{:?} closed.", parent_pipeline_id, frame_id), - Some(frame_element) => frame_element.dispatch_mozbrowser_event(event), - }, + let doc = match { self.documents.borrow().find_document(parent_pipeline_id) } { + None => return warn!("Mozbrowser event after pipeline {:?} closed.", parent_pipeline_id), + Some(doc) => doc, + }; + + match frame_id { + None => doc.window().dispatch_mozbrowser_event(event), + Some(frame_id) => match doc.find_iframe(frame_id) { + None => warn!("Mozbrowser event after iframe {:?}/{:?} closed.", parent_pipeline_id, frame_id), + Some(frame_element) => frame_element.dispatch_mozbrowser_event(event), }, } } @@ -1418,7 +1423,8 @@ impl ScriptThread { parent_pipeline_id: PipelineId, frame_id: FrameId, new_pipeline_id: PipelineId) { - if let Some(frame_element) = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id) { + let frame_element = self.documents.borrow().find_iframe(parent_pipeline_id, frame_id); + if let Some(frame_element) = frame_element { frame_element.update_pipeline_id(new_pipeline_id); } } @@ -1487,13 +1493,14 @@ impl ScriptThread { Some(r) => r, None => return }; - if let Some(window) = self.documents.borrow().find_window(pipeline_id) { - let script_url = maybe_registration.get_installed().get_script_url(); - let scope_things = ServiceWorkerRegistration::create_scope_things(window.upcast(), script_url); - let _ = self.constellation_chan.send(ConstellationMsg::RegisterServiceWorker(scope_things, scope.clone())); - } else { - warn!("Registration failed for {}", scope); - } + let window = match { self.documents.borrow().find_window(pipeline_id) } { + Some(window) => window, + None => return warn!("Registration failed for {}", scope), + }; + + let script_url = maybe_registration.get_installed().get_script_url(); + let scope_things = ServiceWorkerRegistration::create_scope_things(window.upcast(), script_url); + let _ = self.constellation_chan.send(ConstellationMsg::RegisterServiceWorker(scope_things, scope.clone())); } pub fn dispatch_job_queue(&self, job_handler: Box<AsyncJobHandler>) { @@ -1544,7 +1551,7 @@ impl ScriptThread { /// Handles a request for the window title. fn handle_get_title_msg(&self, pipeline_id: PipelineId) { - let document = match self.documents.borrow().find_document(pipeline_id) { + let document = match { self.documents.borrow().find_document(pipeline_id) } { Some(document) => document, None => return warn!("Message sent to closed pipeline {}.", pipeline_id), }; @@ -1601,7 +1608,7 @@ impl ScriptThread { /// Handles when layout thread finishes all animation in one tick fn handle_tick_all_animations(&self, id: PipelineId) { - let document = match self.documents.borrow().find_document(id) { + let document = match { self.documents.borrow().find_document(id) } { Some(document) => document, None => return warn!("Message sent to closed pipeline {}.", id), }; @@ -1642,7 +1649,8 @@ impl ScriptThread { /// Handles a Web font being loaded. Does nothing if the page no longer exists. fn handle_web_font_loaded(&self, pipeline_id: PipelineId) { - if let Some(document) = self.documents.borrow().find_document(pipeline_id) { + let document = self.documents.borrow().find_document(pipeline_id); + if let Some(document) = document { self.rebuild_and_force_reflow(&document, ReflowReason::WebFontLoaded); } } @@ -1650,12 +1658,14 @@ impl ScriptThread { /// Notify a window of a storage event fn handle_storage_event(&self, pipeline_id: PipelineId, storage_type: StorageType, url: ServoUrl, key: Option<String>, old_value: Option<String>, new_value: Option<String>) { - let storage = match self.documents.borrow().find_window(pipeline_id) { + let window = match { self.documents.borrow().find_window(pipeline_id) } { None => return warn!("Storage event sent to closed pipeline {}.", pipeline_id), - Some(window) => match storage_type { - StorageType::Local => window.LocalStorage(), - StorageType::Session => window.SessionStorage(), - }, + Some(window) => window, + }; + + let storage = match storage_type { + StorageType::Local => window.LocalStorage(), + StorageType::Session => window.SessionStorage(), }; storage.queue_storage_event(url, key, old_value, new_value); @@ -1908,7 +1918,7 @@ impl ScriptThread { } MouseMoveEvent(point) => { - let document = match self.documents.borrow().find_document(pipeline_id) { + let document = match { self.documents.borrow().find_document(pipeline_id) } { Some(document) => document, None => return warn!("Message sent to closed pipeline {}.", pipeline_id), }; @@ -1980,17 +1990,19 @@ impl ScriptThread { } TouchpadPressureEvent(point, pressure, phase) => { - match self.documents.borrow().find_document(pipeline_id) { - Some(doc) => doc.handle_touchpad_pressure_event(self.js_runtime.rt(), point, pressure, phase), - None => warn!("Message sent to closed pipeline {}.", pipeline_id), - } + let doc = match { self.documents.borrow().find_document(pipeline_id) } { + Some(doc) => doc, + None => return warn!("Message sent to closed pipeline {}.", pipeline_id), + }; + doc.handle_touchpad_pressure_event(self.js_runtime.rt(), point, pressure, phase); } KeyEvent(ch, key, state, modifiers) => { - match self.documents.borrow().find_document(pipeline_id) { - Some(document) => document.dispatch_key_event(ch, key, state, modifiers, &self.constellation_chan), - None => warn!("Message sent to closed pipeline {}.", pipeline_id), - } + let document = match { self.documents.borrow().find_document(pipeline_id) } { + Some(document) => document, + None => return warn!("Message sent to closed pipeline {}.", pipeline_id), + }; + document.dispatch_key_event(ch, key, state, modifiers, &self.constellation_chan); } } } @@ -2000,10 +2012,11 @@ impl ScriptThread { mouse_event_type: MouseEventType, button: MouseButton, point: Point2D<f32>) { - match self.documents.borrow().find_document(pipeline_id) { - Some(document) => document.handle_mouse_event(self.js_runtime.rt(), button, point, mouse_event_type), - None => warn!("Message sent to closed pipeline {}.", pipeline_id), - } + let document = match { self.documents.borrow().find_document(pipeline_id) } { + Some(document) => document, + None => return warn!("Message sent to closed pipeline {}.", pipeline_id), + }; + document.handle_mouse_event(self.js_runtime.rt(), button, point, mouse_event_type); } fn handle_touch_event(&self, @@ -2012,13 +2025,14 @@ impl ScriptThread { identifier: TouchId, point: Point2D<f32>) -> TouchEventResult { - match self.documents.borrow().find_document(pipeline_id) { - Some(document) => document.handle_touch_event(self.js_runtime.rt(), event_type, identifier, point), + let document = match { self.documents.borrow().find_document(pipeline_id) } { + Some(document) => document, None => { warn!("Message sent to closed pipeline {}.", pipeline_id); - TouchEventResult::Processed(true) + return TouchEventResult::Processed(true); }, - } + }; + document.handle_touch_event(self.js_runtime.rt(), event_type, identifier, point) } /// https://html.spec.whatwg.org/multipage/#navigating-across-documents @@ -2044,7 +2058,7 @@ impl ScriptThread { } fn handle_resize_event(&self, pipeline_id: PipelineId, new_size: WindowSizeData, size_type: WindowSizeType) { - let document = match self.documents.borrow().find_document(pipeline_id) { + let document = match { self.documents.borrow().find_document(pipeline_id) } { Some(document) => document, None => return warn!("Message sent to closed pipeline {}.", pipeline_id), }; @@ -2127,7 +2141,7 @@ impl ScriptThread { } fn handle_parsing_complete(&self, id: PipelineId) { - let document = match self.documents.borrow().find_document(id) { + let document = match { self.documents.borrow().find_document(id) } { Some(document) => document, None => return, }; @@ -2175,7 +2189,8 @@ impl ScriptThread { } fn handle_reload(&self, pipeline_id: PipelineId) { - if let Some(window) = self.documents.borrow().find_window(pipeline_id) { + let window = self.documents.borrow().find_window(pipeline_id); + if let Some(window) = window { window.Location().Reload(); } } diff --git a/components/script/serviceworker_manager.rs b/components/script/serviceworker_manager.rs index ac3c2ab4109..793d7ccf370 100644 --- a/components/script/serviceworker_manager.rs +++ b/components/script/serviceworker_manager.rs @@ -16,11 +16,11 @@ use ipc_channel::ipc::{self, IpcSender}; use ipc_channel::router::ROUTER; use net_traits::{CustomResponseMediator, CoreResourceMsg}; use script_traits::{ServiceWorkerMsg, ScopeThings, SWManagerMsg, SWManagerSenders, DOMMessage}; +use servo_config::prefs::PREFS; use servo_url::ServoUrl; use std::collections::HashMap; use std::sync::mpsc::{channel, Sender, Receiver, RecvError}; -use util::prefs::PREFS; -use util::thread::spawn_named; +use std::thread; enum Message { FromResource(CustomResponseMediator), @@ -60,11 +60,11 @@ impl ServiceWorkerManager { let resource_port = ROUTER.route_ipc_receiver_to_new_mpsc_receiver(resource_port); let _ = sw_senders.resource_sender.send(CoreResourceMsg::NetworkMediator(resource_chan)); let _ = sw_senders.swmanager_sender.send(SWManagerMsg::OwnSender(own_sender.clone())); - spawn_named("ServiceWorkerManager".to_owned(), move || { + thread::Builder::new().name("ServiceWorkerManager".to_owned()).spawn(move || { ServiceWorkerManager::new(own_sender, from_constellation, resource_port).handle_message(); - }); + }).expect("Thread spawning failed"); } pub fn get_matching_scope(&self, load_url: &ServoUrl) -> Option<ServoUrl> { diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs new file mode 100644 index 00000000000..427593c8500 --- /dev/null +++ b/components/script/stylesheet_loader.rs @@ -0,0 +1,245 @@ +/* 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 document_loader::LoadType; +use dom::bindings::inheritance::Castable; +use dom::bindings::refcounted::Trusted; +use dom::bindings::reflector::DomObject; +use dom::element::Element; +use dom::eventtarget::EventTarget; +use dom::htmlelement::HTMLElement; +use dom::htmllinkelement::HTMLLinkElement; +use dom::node::{document_from_node, window_from_node}; +use encoding::EncodingRef; +use encoding::all::UTF_8; +use hyper::header::ContentType; +use hyper::mime::{Mime, TopLevel, SubLevel}; +use hyper_serde::Serde; +use ipc_channel::ipc; +use ipc_channel::router::ROUTER; +use net_traits::{FetchResponseListener, FetchMetadata, Metadata, NetworkError, ReferrerPolicy}; +use net_traits::request::{CredentialsMode, Destination, RequestInit, Type as RequestType}; +use network_listener::{NetworkListener, PreInvoke}; +use parking_lot::RwLock; +use script_layout_interface::message::Msg; +use servo_url::ServoUrl; +use std::mem; +use std::sync::{Arc, Mutex}; +use style::media_queries::MediaList; +use style::parser::ParserContextExtraData; +use style::stylesheets::{ImportRule, Stylesheet, Origin}; +use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; + +pub trait StylesheetOwner { + /// Returns whether this element was inserted by the parser (i.e., it should + /// trigger a document-load-blocking load). + fn parser_inserted(&self) -> bool; + + /// Which referrer policy should loads triggered by this owner follow, or + /// `None` for the default. + fn referrer_policy(&self) -> Option<ReferrerPolicy>; + + /// Notes that a new load is pending to finish. + fn increment_pending_loads_count(&self); + + /// Returns None if there are still pending loads, or whether any load has + /// failed since the loads started. + fn load_finished(&self, successful: bool) -> Option<bool>; +} + +pub enum StylesheetContextSource { + // NB: `media` is just an option so we avoid cloning it. + LinkElement { media: Option<MediaList>, url: ServoUrl }, + Import(Arc<RwLock<ImportRule>>), +} + +impl StylesheetContextSource { + fn url(&self) -> ServoUrl { + match *self { + StylesheetContextSource::LinkElement { ref url, .. } => url.clone(), + StylesheetContextSource::Import(ref import) => { + let import = import.read(); + // Look at the parser in style::stylesheets, where we don't + // trigger a load if the url is invalid. + import.url.url() + .expect("Invalid urls shouldn't enter the loader") + .clone() + } + } + } +} + +/// The context required for asynchronously loading an external stylesheet. +pub struct StylesheetContext { + /// The element that initiated the request. + elem: Trusted<HTMLElement>, + source: StylesheetContextSource, + metadata: Option<Metadata>, + /// The response body received to date. + data: Vec<u8>, +} + +impl PreInvoke for StylesheetContext {} + +impl FetchResponseListener for StylesheetContext { + fn process_request_body(&mut self) {} + + fn process_request_eof(&mut self) {} + + fn process_response(&mut self, + metadata: Result<FetchMetadata, NetworkError>) { + self.metadata = metadata.ok().map(|m| { + match m { + FetchMetadata::Unfiltered(m) => m, + FetchMetadata::Filtered { unsafe_, .. } => unsafe_ + } + }); + } + + fn process_response_chunk(&mut self, mut payload: Vec<u8>) { + self.data.append(&mut payload); + } + + fn process_response_eof(&mut self, status: Result<(), NetworkError>) { + let elem = self.elem.root(); + let document = document_from_node(&*elem); + let mut successful = false; + + if status.is_ok() { + let metadata = match self.metadata.take() { + Some(meta) => meta, + None => return, + }; + let is_css = metadata.content_type.map_or(false, |Serde(ContentType(Mime(top, sub, _)))| + top == TopLevel::Text && sub == SubLevel::Css); + + let data = if is_css { mem::replace(&mut self.data, vec![]) } else { vec![] }; + + // TODO: Get the actual value. http://dev.w3.org/csswg/css-syntax/#environment-encoding + let environment_encoding = UTF_8 as EncodingRef; + let protocol_encoding_label = metadata.charset.as_ref().map(|s| &**s); + let final_url = metadata.final_url; + + let win = window_from_node(&*elem); + + let loader = StylesheetLoader::for_element(&elem); + match self.source { + StylesheetContextSource::LinkElement { ref mut media, .. } => { + let sheet = + Arc::new(Stylesheet::from_bytes(&data, final_url, + protocol_encoding_label, + Some(environment_encoding), + Origin::Author, + media.take().unwrap(), + Some(&loader), + win.css_error_reporter(), + ParserContextExtraData::default())); + elem.downcast::<HTMLLinkElement>() + .unwrap() + .set_stylesheet(sheet.clone()); + + let win = window_from_node(&*elem); + win.layout_chan().send(Msg::AddStylesheet(sheet)).unwrap(); + } + StylesheetContextSource::Import(ref import) => { + let import = import.read(); + Stylesheet::update_from_bytes(&import.stylesheet, + &data, + protocol_encoding_label, + Some(environment_encoding), + Some(&loader), + win.css_error_reporter(), + ParserContextExtraData::default()); + } + } + + document.invalidate_stylesheets(); + + // FIXME: Revisit once consensus is reached at: + // https://github.com/whatwg/html/issues/1142 + successful = metadata.status.map_or(false, |(code, _)| code == 200); + } + + let owner = elem.upcast::<Element>().as_stylesheet_owner() + .expect("Stylesheet not loaded by <style> or <link> element!"); + if owner.parser_inserted() { + document.decrement_script_blocking_stylesheet_count(); + } + + let url = self.source.url(); + document.finish_load(LoadType::Stylesheet(url)); + + if let Some(any_failed) = owner.load_finished(successful) { + let event = if any_failed { atom!("error") } else { atom!("load") }; + elem.upcast::<EventTarget>().fire_event(event); + } + } +} + +pub struct StylesheetLoader<'a> { + elem: &'a HTMLElement, +} + +impl<'a> StylesheetLoader<'a> { + pub fn for_element(element: &'a HTMLElement) -> Self { + StylesheetLoader { + elem: element, + } + } +} + +impl<'a> StylesheetLoader<'a> { + pub fn load(&self, source: StylesheetContextSource) { + let url = source.url(); + let context = Arc::new(Mutex::new(StylesheetContext { + elem: Trusted::new(&*self.elem), + source: source, + metadata: None, + data: vec![], + })); + + let document = document_from_node(self.elem); + + let (action_sender, action_receiver) = ipc::channel().unwrap(); + let listener = NetworkListener { + context: context, + task_source: document.window().networking_task_source(), + wrapper: Some(document.window().get_runnable_wrapper()) + }; + ROUTER.add_route(action_receiver.to_opaque(), box move |message| { + listener.notify_fetch(message.to().unwrap()); + }); + + + let owner = self.elem.upcast::<Element>().as_stylesheet_owner() + .expect("Stylesheet not loaded by <style> or <link> element!"); + let referrer_policy = owner.referrer_policy() + .or_else(|| document.get_referrer_policy()); + owner.increment_pending_loads_count(); + if owner.parser_inserted() { + document.increment_script_blocking_stylesheet_count(); + } + + let request = RequestInit { + url: url.clone(), + type_: RequestType::Style, + destination: Destination::Style, + credentials_mode: CredentialsMode::Include, + use_url_credentials: true, + origin: document.url(), + pipeline_id: Some(self.elem.global().pipeline_id()), + referrer_url: Some(document.url()), + referrer_policy: referrer_policy, + .. RequestInit::default() + }; + + document.fetch_async(LoadType::Stylesheet(url), request, action_sender); + } +} + +impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> { + fn request_stylesheet(&self, import: &Arc<RwLock<ImportRule>>) { + self.load(StylesheetContextSource::Import(import.clone())) + } +} diff --git a/components/script/test.rs b/components/script/test.rs new file mode 100644 index 00000000000..31353b5ffa3 --- /dev/null +++ b/components/script/test.rs @@ -0,0 +1,68 @@ +/* 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/. */ + +pub use dom::bindings::str::{ByteString, DOMString}; +pub use dom::headers::normalize_value; + +// For compile-fail tests only. +pub use dom::bindings::cell::DOMRefCell; +pub use dom::bindings::js::JS; +pub use dom::node::Node; + +pub mod size_of { + use dom::characterdata::CharacterData; + use dom::element::Element; + use dom::eventtarget::EventTarget; + use dom::htmldivelement::HTMLDivElement; + use dom::htmlelement::HTMLElement; + use dom::htmlspanelement::HTMLSpanElement; + use dom::node::Node; + use dom::text::Text; + use layout_wrapper::{ServoLayoutElement, ServoLayoutNode, ServoThreadSafeLayoutNode}; + use std::mem::size_of; + + pub fn CharacterData() -> usize { + size_of::<CharacterData>() + } + + pub fn Element() -> usize { + size_of::<Element>() + } + + pub fn EventTarget() -> usize { + size_of::<EventTarget>() + } + + pub fn HTMLDivElement() -> usize { + size_of::<HTMLDivElement>() + } + + pub fn HTMLElement() -> usize { + size_of::<HTMLElement>() + } + + pub fn HTMLSpanElement() -> usize { + size_of::<HTMLSpanElement>() + } + + pub fn Node() -> usize { + size_of::<Node>() + } + + pub fn SendElement() -> usize { + size_of::<::style::dom::SendElement<ServoLayoutElement>>() + } + + pub fn SendNode() -> usize { + size_of::<::style::dom::SendNode<ServoLayoutNode>>() + } + + pub fn ServoThreadSafeLayoutNode() -> usize { + size_of::<ServoThreadSafeLayoutNode>() + } + + pub fn Text() -> usize { + size_of::<Text>() + } +} diff --git a/components/script/timers.rs b/components/script/timers.rs index db0adfa9557..14c4eb89c13 100644 --- a/components/script/timers.rs +++ b/components/script/timers.rs @@ -18,12 +18,12 @@ use js::jsapi::{HandleValue, Heap}; use js::jsval::{JSVal, UndefinedValue}; use script_traits::{MsDuration, precise_time_ms}; use script_traits::{TimerEvent, TimerEventId, TimerEventRequest, TimerSource}; +use servo_config::prefs::PREFS; use std::cell::Cell; use std::cmp::{self, Ord, Ordering}; use std::collections::HashMap; use std::default::Default; use std::rc::Rc; -use util::prefs::PREFS; #[derive(JSTraceable, PartialEq, Eq, Copy, Clone, HeapSizeOf, Hash, PartialOrd, Ord, Debug)] pub struct OneshotTimerHandle(i32); diff --git a/components/script/webdriver_handlers.rs b/components/script/webdriver_handlers.rs index e0818347c56..e1599d7caef 100644 --- a/components/script/webdriver_handlers.rs +++ b/components/script/webdriver_handlers.rs @@ -31,7 +31,7 @@ use js::jsapi::{HandleValue, JSContext}; use js::jsval::UndefinedValue; use msg::constellation_msg::PipelineId; use net_traits::CookieSource::{HTTP, NonHTTP}; -use net_traits::CoreResourceMsg::{GetCookiesDataForUrl, SetCookiesForUrlWithData}; +use net_traits::CoreResourceMsg::{GetCookiesDataForUrl, SetCookieForUrl}; use net_traits::IpcSend; use script_thread::Documents; use script_traits::webdriver_msg::{WebDriverFrameId, WebDriverJSError, WebDriverJSResult, WebDriverJSValue}; @@ -243,14 +243,14 @@ pub fn handle_add_cookie(documents: &Documents, (true, _) => Err(WebDriverCookieError::InvalidDomain), (false, Some(ref domain)) if url.host_str().map(|x| { x == &**domain }).unwrap_or(false) => { let _ = document.window().upcast::<GlobalScope>().resource_threads().send( - SetCookiesForUrlWithData(url, cookie, method) - ); + SetCookieForUrl(url, cookie, method) + ); Ok(()) }, (false, None) => { let _ = document.window().upcast::<GlobalScope>().resource_threads().send( - SetCookiesForUrlWithData(url, cookie, method) - ); + SetCookieForUrl(url, cookie, method) + ); Ok(()) }, (_, _) => { |