diff options
author | rohan.prinja <rohan.prinja@samsung.com> | 2015-10-27 17:58:34 +0900 |
---|---|---|
committer | rohan.prinja <rohan.prinja@samsung.com> | 2015-10-30 20:26:29 +0900 |
commit | 45224028dbc1d75e6dfc8add19ff8e997c7ebb99 (patch) | |
tree | f5a113706605564ec491dbf9710842d79e5b2e5c /components/script/dom | |
parent | bb2536cd014676263f5bfd5d98cf0fc69d2abee0 (diff) | |
download | servo-45224028dbc1d75e6dfc8add19ff8e997c7ebb99.tar.gz servo-45224028dbc1d75e6dfc8add19ff8e997c7ebb99.zip |
more refactoring
Diffstat (limited to 'components/script/dom')
110 files changed, 3378 insertions, 345 deletions
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs index f9d85314169..747d5f74013 100644 --- a/components/script/dom/attr.rs +++ b/components/script/dom/attr.rs @@ -10,7 +10,7 @@ use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, MutNullableHeap}; use dom::bindings::js::{LayoutJS, Root, RootedReference}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::element::{AttributeMutation, Element}; use dom::values::UNSIGNED_LONG_MAX; use dom::virtualmethods::vtable_for; diff --git a/components/script/dom/bindings/callback.rs b/components/script/dom/bindings/callback.rs index a879e469e27..1b067c5c596 100644 --- a/components/script/dom/bindings/callback.rs +++ b/components/script/dom/bindings/callback.rs @@ -6,7 +6,7 @@ use dom::bindings::error::{Error, Fallible}; use dom::bindings::global::global_object_for_js_object; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use js::jsapi::GetGlobalForObjectCrossCompartment; use js::jsapi::{Heap, MutableHandleObject, RootedObject, RootedValue}; use js::jsapi::{IsCallable, JSContext, JSObject, JS_WrapObject}; diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 51a4653279f..bd81592d43c 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -5197,6 +5197,7 @@ class CGBindingRoot(CGThing): 'dom::bindings::global::global_object_for_js_object', 'dom::bindings::js::{JS, Root, RootedReference}', 'dom::bindings::js::{OptionalRootedReference}', + 'dom::bindings::reflector::{Reflectable}', 'dom::bindings::utils::{create_dom_global, do_create_interface_objects}', 'dom::bindings::utils::ConstantSpec', 'dom::bindings::utils::{DOMClass}', @@ -5206,7 +5207,6 @@ class CGBindingRoot(CGThing): 'dom::bindings::utils::{finalize_global, trace_global}', 'dom::bindings::utils::has_property_on_prototype', 'dom::bindings::utils::is_platform_object', - 'dom::bindings::utils::{Reflectable}', 'dom::bindings::utils::throwing_constructor', 'dom::bindings::utils::get_dictionary_property', 'dom::bindings::utils::set_dictionary_property', @@ -5915,10 +5915,11 @@ class GlobalGenRoots(): descriptors = config.getDescriptors(register=True, isCallback=False) imports = [CGGeneric("use dom::types::*;\n"), - CGGeneric("use dom::bindings::conversions::{Castable, DerivedFrom, get_dom_class};\n"), + CGGeneric("use dom::bindings::conversions::{DerivedFrom, get_dom_class};\n"), + CGGeneric("use dom::bindings::inheritance::Castable;\n"), CGGeneric("use dom::bindings::js::{JS, LayoutJS, Root};\n"), CGGeneric("use dom::bindings::trace::JSTraceable;\n"), - CGGeneric("use dom::bindings::utils::Reflectable;\n"), + CGGeneric("use dom::bindings::reflector::Reflectable;\n"), CGGeneric("use js::jsapi::JSTracer;\n\n"), CGGeneric("use std::mem;\n\n")] allprotos = [] diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index c8f3b986623..1da266efe4c 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -38,7 +38,8 @@ use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; use dom::bindings::num::Finite; use dom::bindings::str::{ByteString, USVString}; -use dom::bindings::utils::{DOMClass, Reflectable, Reflector}; +use dom::bindings::reflector::{Reflectable, Reflector}; +use dom::bindings::utils::DOMClass; use js; use js::glue::{GetProxyPrivate, IsWrapper, RUST_JS_NumberValue}; use js::glue::{RUST_JSID_IS_STRING, RUST_JSID_TO_STRING, UnwrapObject}; @@ -56,7 +57,6 @@ use libc; use num::Float; use num::traits::{Bounded, Zero}; use std::borrow::ToOwned; -use std::mem; use std::rc::Rc; use std::{char, ptr, slice}; use util::str::DOMString; diff --git a/components/script/dom/bindings/global.rs b/components/script/dom/bindings/global.rs index a1a1c68c8c0..d0b38196608 100644 --- a/components/script/dom/bindings/global.rs +++ b/components/script/dom/bindings/global.rs @@ -11,7 +11,8 @@ use devtools_traits::ScriptToDevtoolsControlMsg; use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::conversions::native_from_reflector_jsmanaged; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::Reflectable; use dom::window::{self, ScriptHelpers}; use dom::workerglobalscope::WorkerGlobalScope; use ipc_channel::ipc::IpcSender; diff --git a/components/script/dom/bindings/inheritance.rs b/components/script/dom/bindings/inheritance.rs index 5878c44c5f3..6ee06999563 100644 --- a/components/script/dom/bindings/inheritance.rs +++ b/components/script/dom/bindings/inheritance.rs @@ -2,9 +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/. */ +//! The `Castable` trait. + use dom::bindings::conversions::get_dom_class; use dom::bindings::conversions::{DerivedFrom, IDLInterface}; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use std::mem; /// A trait to hold the cast functions of IDL interfaces that either derive diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index 388a8ba81ef..d347b00bb4f 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -28,7 +28,8 @@ use dom::bindings::conversions::DerivedFrom; use dom::bindings::inheritance::Castable; use dom::bindings::trace::JSTraceable; use dom::bindings::trace::trace_reflector; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::Reflectable; use dom::node::Node; use js::jsapi::{Heap, JSObject, JSTracer}; use js::jsval::JSVal; diff --git a/components/script/dom/bindings/mod.rs b/components/script/dom/bindings/mod.rs index 394c7b722bf..f4b795f8c58 100644 --- a/components/script/dom/bindings/mod.rs +++ b/components/script/dom/bindings/mod.rs @@ -137,14 +137,17 @@ pub mod cell; pub mod conversions; pub mod error; pub mod global; +pub mod inheritance; pub mod js; pub mod num; pub mod proxyhandler; pub mod refcounted; +pub mod reflector; pub mod str; pub mod structuredclone; pub mod trace; pub mod utils; +pub mod xmlname; /// Generated JS-Rust bindings. #[allow(missing_docs, non_snake_case)] diff --git a/components/script/dom/bindings/refcounted.rs b/components/script/dom/bindings/refcounted.rs index ee8647be3ce..e101d2bbd83 100644 --- a/components/script/dom/bindings/refcounted.rs +++ b/components/script/dom/bindings/refcounted.rs @@ -25,7 +25,8 @@ use core::nonzero::NonZero; use dom::bindings::js::Root; use dom::bindings::trace::trace_reflector; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::Reflectable; use js::jsapi::{JSContext, JSTracer}; use libc; use script_task::{CommonScriptMsg, ScriptChan}; diff --git a/components/script/dom/bindings/reflector.rs b/components/script/dom/bindings/reflector.rs new file mode 100644 index 00000000000..3279f4de55e --- /dev/null +++ b/components/script/dom/bindings/reflector.rs @@ -0,0 +1,79 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +//! The `Reflector` struct. + +use dom::bindings::global::GlobalRef; +use dom::bindings::js::Root; +use js::jsapi::{HandleObject, JSContext, JSObject}; +use std::cell::UnsafeCell; +use std::ptr; + +/// Create the reflector for a new DOM object and yield ownership to the +/// reflector. +pub fn reflect_dom_object<T: Reflectable> + (obj: Box<T>, + global: GlobalRef, + wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>) + -> Root<T> { + wrap_fn(global.get_cx(), global, obj) +} + +/// A struct to store a reference to the reflector of a DOM object. +#[allow(raw_pointer_derive, unrooted_must_root)] +#[must_root] +#[servo_lang = "reflector"] +#[derive(HeapSizeOf)] +// If you're renaming or moving this field, update the path in plugins::reflector as well +pub struct Reflector { + #[ignore_heap_size_of = "defined and measured in rust-mozjs"] + object: UnsafeCell<*mut JSObject>, +} + +#[allow(unrooted_must_root)] +impl PartialEq for Reflector { + fn eq(&self, other: &Reflector) -> bool { + unsafe { *self.object.get() == *other.object.get() } + } +} + +impl Reflector { + /// Get the reflector. + #[inline] + pub fn get_jsobject(&self) -> HandleObject { + unsafe { HandleObject::from_marked_location(self.object.get()) } + } + + /// Initialize the reflector. (May be called only once.) + pub fn set_jsobject(&mut self, object: *mut JSObject) { + unsafe { + let obj = self.object.get(); + assert!((*obj).is_null()); + assert!(!object.is_null()); + *obj = object; + } + } + + /// Return a pointer to the memory location at which the JS reflector + /// object is stored. Used to root the reflector, as + /// required by the JSAPI rooting APIs. + pub fn rootable(&self) -> *mut *mut JSObject { + self.object.get() + } + + /// Create an uninitialized `Reflector`. + pub fn new() -> Reflector { + Reflector { + object: UnsafeCell::new(ptr::null_mut()) + } + } +} + +/// A trait to provide access to the `Reflector` for a DOM object. +pub trait Reflectable { + /// Returns the receiver's reflector. + fn reflector(&self) -> &Reflector; + /// Initializes the Reflector + fn init_reflector(&mut self, obj: *mut JSObject); +}
\ No newline at end of file diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index c78429f8368..6ed7e45c45a 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -35,7 +35,8 @@ use canvas_traits::{CompositionOrBlending, LineCapStyle, LineJoinStyle, Repetiti use cssparser::RGBA; use dom::bindings::js::{JS, Root}; use dom::bindings::refcounted::Trusted; -use dom::bindings::utils::{Reflectable, Reflector, WindowProxyHandler}; +use dom::bindings::reflector::{Reflectable, Reflector}; +use dom::bindings::utils::WindowProxyHandler; use encoding::types::EncodingRef; use euclid::length::Length as EuclidLength; use euclid::matrix2d::Matrix2D; diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 6fae276271c..72c0745d3b1 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -49,14 +49,10 @@ use js::rust::{GCMethods, ToString, define_methods, define_properties}; use js::{JSFUN_CONSTRUCTOR, JSPROP_ENUMERATE, JS_CALLEE}; use js::{JSPROP_PERMANENT, JSPROP_READONLY}; use libc::{self, c_uint}; -use std::cell::UnsafeCell; -use std::cmp::PartialEq; use std::default::Default; use std::ffi::CString; use std::ptr; -use string_cache::{Atom, Namespace}; use util::mem::HeapSizeOf; -use util::str::DOMString; /// Proxy handler for a WindowProxy. #[allow(raw_pointer_derive)] @@ -391,74 +387,6 @@ pub fn initialize_global(global: *mut JSObject) { } } -/// A trait to provide access to the `Reflector` for a DOM object. -pub trait Reflectable { - /// Returns the receiver's reflector. - fn reflector(&self) -> &Reflector; - /// Initializes the Reflector - fn init_reflector(&mut self, obj: *mut JSObject); -} - -/// Create the reflector for a new DOM object and yield ownership to the -/// reflector. -pub fn reflect_dom_object<T: Reflectable> - (obj: Box<T>, - global: GlobalRef, - wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<T>) -> Root<T>) - -> Root<T> { - wrap_fn(global.get_cx(), global, obj) -} - -/// A struct to store a reference to the reflector of a DOM object. -#[allow(raw_pointer_derive, unrooted_must_root)] -#[must_root] -#[servo_lang = "reflector"] -#[derive(HeapSizeOf)] -// If you're renaming or moving this field, update the path in plugins::reflector as well -pub struct Reflector { - #[ignore_heap_size_of = "defined and measured in rust-mozjs"] - object: UnsafeCell<*mut JSObject>, -} - -#[allow(unrooted_must_root)] -impl PartialEq for Reflector { - fn eq(&self, other: &Reflector) -> bool { - unsafe { *self.object.get() == *other.object.get() } - } -} - -impl Reflector { - /// Get the reflector. - #[inline] - pub fn get_jsobject(&self) -> HandleObject { - unsafe { HandleObject::from_marked_location(self.object.get()) } - } - - /// Initialize the reflector. (May be called only once.) - pub fn set_jsobject(&mut self, object: *mut JSObject) { - unsafe { - let obj = self.object.get(); - assert!((*obj).is_null()); - assert!(!object.is_null()); - *obj = object; - } - } - - /// Return a pointer to the memory location at which the JS reflector - /// object is stored. Used to root the reflector, as - /// required by the JSAPI rooting APIs. - pub fn rootable(&self) -> *mut *mut JSObject { - self.object.get() - } - - /// Create an uninitialized `Reflector`. - pub fn new() -> Reflector { - Reflector { - object: UnsafeCell::new(ptr::null_mut()) - } - } -} - /// Gets the property `id` on `proxy`'s prototype. If it exists, `*found` is /// set to true and `*vp` to the value, otherwise `*found` is set to false. /// @@ -800,21 +728,6 @@ pub unsafe extern fn generic_lenient_setter(cx: *mut JSContext, generic_call(cx, argc, vp, true, call_setter) } -/// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. -pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult { - match xml_name_type(qualified_name) { - XMLName::InvalidXMLName => { - // Step 1. - Err(Error::InvalidCharacter) - }, - XMLName::Name => { - // Step 2. - Err(Error::Namespace) - }, - XMLName::QName => Ok(()) - } -} - unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi::Class, proto_id: u32, depth: u32) -> bool { @@ -827,155 +740,3 @@ unsafe extern "C" fn instance_class_has_proto_at_depth(clasp: *const js::jsapi:: pub const DOM_CALLBACKS: DOMCallbacks = DOMCallbacks { instanceClassMatchesProto: Some(instance_class_has_proto_at_depth), }; - -/// Validate a namespace and qualified name and extract their parts. -/// See https://dom.spec.whatwg.org/#validate-and-extract for details. -pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str) - -> Fallible<(Namespace, Option<Atom>, Atom)> { - // Step 1. - let namespace = namespace_from_domstring(namespace); - - // Step 2. - try!(validate_qualified_name(qualified_name)); - - let colon = ':'; - - // Step 5. - let mut parts = qualified_name.splitn(2, colon); - - let (maybe_prefix, local_name) = { - let maybe_prefix = parts.next(); - let maybe_local_name = parts.next(); - - debug_assert!(parts.next().is_none()); - - if let Some(local_name) = maybe_local_name { - debug_assert!(!maybe_prefix.unwrap().is_empty()); - - (maybe_prefix, local_name) - } else { - (None, maybe_prefix.unwrap()) - } - }; - - debug_assert!(!local_name.contains(colon)); - - match (namespace, maybe_prefix) { - (ns!(""), Some(_)) => { - // Step 6. - Err(Error::Namespace) - }, - (ref ns, Some("xml")) if ns != &ns!(XML) => { - // Step 7. - Err(Error::Namespace) - }, - (ref ns, p) if ns != &ns!(XMLNS) && - (qualified_name == "xmlns" || p == Some("xmlns")) => { - // Step 8. - Err(Error::Namespace) - }, - (ns!(XMLNS), p) if qualified_name != "xmlns" && p != Some("xmlns") => { - // Step 9. - Err(Error::Namespace) - }, - (ns, p) => { - // Step 10. - Ok((ns, p.map(Atom::from_slice), Atom::from_slice(local_name))) - } - } -} - -/// Results of `xml_name_type`. -#[derive(PartialEq)] -#[allow(missing_docs)] -pub enum XMLName { - QName, - Name, - InvalidXMLName -} - -/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name -/// for details. -pub fn xml_name_type(name: &str) -> XMLName { - fn is_valid_start(c: char) -> bool { - match c { - ':' | - 'A' ... 'Z' | - '_' | - 'a' ... 'z' | - '\u{C0}' ... '\u{D6}' | - '\u{D8}' ... '\u{F6}' | - '\u{F8}' ... '\u{2FF}' | - '\u{370}' ... '\u{37D}' | - '\u{37F}' ... '\u{1FFF}' | - '\u{200C}' ... '\u{200D}' | - '\u{2070}' ... '\u{218F}' | - '\u{2C00}' ... '\u{2FEF}' | - '\u{3001}' ... '\u{D7FF}' | - '\u{F900}' ... '\u{FDCF}' | - '\u{FDF0}' ... '\u{FFFD}' | - '\u{10000}' ... '\u{EFFFF}' => true, - _ => false, - } - } - - fn is_valid_continuation(c: char) -> bool { - is_valid_start(c) || match c { - '-' | - '.' | - '0' ... '9' | - '\u{B7}' | - '\u{300}' ... '\u{36F}' | - '\u{203F}' ... '\u{2040}' => true, - _ => false, - } - } - - let mut iter = name.chars(); - let mut non_qname_colons = false; - let mut seen_colon = false; - let mut last = match iter.next() { - None => return XMLName::InvalidXMLName, - Some(c) => { - if !is_valid_start(c) { - return XMLName::InvalidXMLName; - } - if c == ':' { - non_qname_colons = true; - } - c - } - }; - - for c in iter { - if !is_valid_continuation(c) { - return XMLName::InvalidXMLName; - } - if c == ':' { - match seen_colon { - true => non_qname_colons = true, - false => seen_colon = true - } - } - last = c - } - - if last == ':' { - non_qname_colons = true - } - - match non_qname_colons { - false => XMLName::QName, - true => XMLName::Name - } -} - -/// Convert a possibly-null URL to a namespace. -/// -/// If the URL is None, returns the empty namespace. -pub fn namespace_from_domstring(url: Option<DOMString>) -> Namespace { - match url { - None => ns!(""), - Some(ref s) => Namespace(Atom::from_slice(s)), - } -} diff --git a/components/script/dom/bindings/xmlname.rs b/components/script/dom/bindings/xmlname.rs new file mode 100644 index 00000000000..e8a53707420 --- /dev/null +++ b/components/script/dom/bindings/xmlname.rs @@ -0,0 +1,176 @@ +/* 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/. */ + +//! Functions for validating and extracting qualified XML names. + +use dom::bindings::error::{Error, ErrorResult, Fallible}; +use string_cache::{Atom, Namespace}; +use util::str::DOMString; + +/// Validate a qualified name. See https://dom.spec.whatwg.org/#validate for details. +pub fn validate_qualified_name(qualified_name: &str) -> ErrorResult { + match xml_name_type(qualified_name) { + XMLName::InvalidXMLName => { + // Step 1. + Err(Error::InvalidCharacter) + }, + XMLName::Name => { + // Step 2. + Err(Error::Namespace) + }, + XMLName::QName => Ok(()) + } +} + +/// Validate a namespace and qualified name and extract their parts. +/// See https://dom.spec.whatwg.org/#validate-and-extract for details. +pub fn validate_and_extract(namespace: Option<DOMString>, qualified_name: &str) + -> Fallible<(Namespace, Option<Atom>, Atom)> { + // Step 1. + let namespace = namespace_from_domstring(namespace); + + // Step 2. + try!(validate_qualified_name(qualified_name)); + + let colon = ':'; + + // Step 5. + let mut parts = qualified_name.splitn(2, colon); + + let (maybe_prefix, local_name) = { + let maybe_prefix = parts.next(); + let maybe_local_name = parts.next(); + + debug_assert!(parts.next().is_none()); + + if let Some(local_name) = maybe_local_name { + debug_assert!(!maybe_prefix.unwrap().is_empty()); + + (maybe_prefix, local_name) + } else { + (None, maybe_prefix.unwrap()) + } + }; + + debug_assert!(!local_name.contains(colon)); + + match (namespace, maybe_prefix) { + (ns!(""), Some(_)) => { + // Step 6. + Err(Error::Namespace) + }, + (ref ns, Some("xml")) if ns != &ns!(XML) => { + // Step 7. + Err(Error::Namespace) + }, + (ref ns, p) if ns != &ns!(XMLNS) && + (qualified_name == "xmlns" || p == Some("xmlns")) => { + // Step 8. + Err(Error::Namespace) + }, + (ns!(XMLNS), p) if qualified_name != "xmlns" && p != Some("xmlns") => { + // Step 9. + Err(Error::Namespace) + }, + (ns, p) => { + // Step 10. + Ok((ns, p.map(Atom::from_slice), Atom::from_slice(local_name))) + } + } +} + +/// Results of `xml_name_type`. +#[derive(PartialEq)] +#[allow(missing_docs)] +pub enum XMLName { + QName, + Name, + InvalidXMLName +} + +/// Check if an element name is valid. See http://www.w3.org/TR/xml/#NT-Name +/// for details. +pub fn xml_name_type(name: &str) -> XMLName { + fn is_valid_start(c: char) -> bool { + match c { + ':' | + 'A' ... 'Z' | + '_' | + 'a' ... 'z' | + '\u{C0}' ... '\u{D6}' | + '\u{D8}' ... '\u{F6}' | + '\u{F8}' ... '\u{2FF}' | + '\u{370}' ... '\u{37D}' | + '\u{37F}' ... '\u{1FFF}' | + '\u{200C}' ... '\u{200D}' | + '\u{2070}' ... '\u{218F}' | + '\u{2C00}' ... '\u{2FEF}' | + '\u{3001}' ... '\u{D7FF}' | + '\u{F900}' ... '\u{FDCF}' | + '\u{FDF0}' ... '\u{FFFD}' | + '\u{10000}' ... '\u{EFFFF}' => true, + _ => false, + } + } + + fn is_valid_continuation(c: char) -> bool { + is_valid_start(c) || match c { + '-' | + '.' | + '0' ... '9' | + '\u{B7}' | + '\u{300}' ... '\u{36F}' | + '\u{203F}' ... '\u{2040}' => true, + _ => false, + } + } + + let mut iter = name.chars(); + let mut non_qname_colons = false; + let mut seen_colon = false; + let mut last = match iter.next() { + None => return XMLName::InvalidXMLName, + Some(c) => { + if !is_valid_start(c) { + return XMLName::InvalidXMLName; + } + if c == ':' { + non_qname_colons = true; + } + c + } + }; + + for c in iter { + if !is_valid_continuation(c) { + return XMLName::InvalidXMLName; + } + if c == ':' { + match seen_colon { + true => non_qname_colons = true, + false => seen_colon = true + } + } + last = c + } + + if last == ':' { + non_qname_colons = true + } + + match non_qname_colons { + false => XMLName::QName, + true => XMLName::Name + } +} + +/// Convert a possibly-null URL to a namespace. +/// +/// If the URL is None, returns the empty namespace. +pub fn namespace_from_domstring(url: Option<DOMString>) -> Namespace { + match url { + None => ns!(""), + Some(ref s) => Namespace(Atom::from_slice(s)), + } +} diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index efbf1abbc15..0645a146c0f 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; use dom::bindings::error::Fallible; use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use num::ToPrimitive; use std::ascii::AsciiExt; use std::borrow::ToOwned; diff --git a/components/script/dom/browsercontext.rs b/components/script/dom/browsercontext.rs index 60dbdc5523e..a20b576cc1b 100644 --- a/components/script/dom/browsercontext.rs +++ b/components/script/dom/browsercontext.rs @@ -7,7 +7,8 @@ use dom::bindings::conversions::{ToJSValConvertible}; use dom::bindings::js::{JS, Root}; use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor}; use dom::bindings::utils::get_array_index_from_id; -use dom::bindings::utils::{Reflectable, WindowProxyHandler}; +use dom::bindings::reflector::Reflectable; +use dom::bindings::utils::WindowProxyHandler; use dom::document::Document; use dom::element::Element; use dom::window::Window; diff --git a/components/script/dom/canvasgradient.rs b/components/script/dom/canvasgradient.rs index 8f8ad3cc99f..a9cf8a2d878 100644 --- a/components/script/dom/canvasgradient.rs +++ b/components/script/dom/canvasgradient.rs @@ -10,7 +10,7 @@ use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::num::Finite; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::canvasrenderingcontext2d::parse_color; // https://html.spec.whatwg.org/multipage/#canvasgradient diff --git a/components/script/dom/canvaspattern.rs b/components/script/dom/canvaspattern.rs index 7457c06a30d..2f385be82bf 100644 --- a/components/script/dom/canvaspattern.rs +++ b/components/script/dom/canvaspattern.rs @@ -6,7 +6,7 @@ use canvas_traits::{FillOrStrokeStyle, RepetitionStyle, SurfaceStyle}; use dom::bindings::codegen::Bindings::CanvasPatternBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::canvasgradient::ToFillOrStrokeStyle; use euclid::size::Size2D; diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index d60e02f921a..131dca45df8 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -19,7 +19,7 @@ use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, LayoutJS, Root}; use dom::bindings::num::Finite; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::canvasgradient::{CanvasGradient, CanvasGradientStyle, ToFillOrStrokeStyle}; use dom::canvaspattern::CanvasPattern; use dom::htmlcanvaselement::HTMLCanvasElement; diff --git a/components/script/dom/closeevent.rs b/components/script/dom/closeevent.rs index c903a68262f..45362ea5741 100644 --- a/components/script/dom/closeevent.rs +++ b/components/script/dom/closeevent.rs @@ -9,7 +9,7 @@ use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{Event, EventBubbles, EventCancelable}; use script_task::ScriptChan; use util::str::DOMString; diff --git a/components/script/dom/console.rs b/components/script/dom/console.rs index 8845ecd5b22..9303a433e36 100644 --- a/components/script/dom/console.rs +++ b/components/script/dom/console.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::ConsoleBinding; use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods; use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use util::str::DOMString; // https://developer.mozilla.org/en-US/docs/Web/API/Console diff --git a/components/script/dom/crypto.rs b/components/script/dom/crypto.rs index cd5338a1868..5caa678017a 100644 --- a/components/script/dom/crypto.rs +++ b/components/script/dom/crypto.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::CryptoBinding::CryptoMethods; use dom::bindings::error::{Error, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use js::jsapi::{JSContext, JSObject}; use js::jsapi::{JS_GetArrayBufferViewType, JS_GetObjectAsArrayBufferView, Type}; use rand::{OsRng, Rng}; diff --git a/components/script/dom/css.rs b/components/script/dom/css.rs index 527b08315e9..a4cd3a132ec 100644 --- a/components/script/dom/css.rs +++ b/components/script/dom/css.rs @@ -5,7 +5,7 @@ use cssparser::serialize_identifier; use dom::bindings::error::{Error, Fallible}; use dom::bindings::global::GlobalRef; -use dom::bindings::utils::Reflector; +use dom::bindings::reflector::Reflector; use util::str::DOMString; #[dom_struct] diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs index 763cc43059c..da8dc78878e 100644 --- a/components/script/dom/cssstyledeclaration.rs +++ b/components/script/dom/cssstyledeclaration.rs @@ -7,7 +7,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::element::{Element, StylePriority}; use dom::node::{Node, NodeDamage, document_from_node, window_from_node}; use dom::window::Window; diff --git a/components/script/dom/customevent.rs b/components/script/dom/customevent.rs index 89edb89e202..6f7b04cc8e4 100644 --- a/components/script/dom/customevent.rs +++ b/components/script/dom/customevent.rs @@ -9,7 +9,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{MutHeapJSVal, Root}; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::Event; use js::jsapi::{HandleValue, JSContext}; use js::jsval::JSVal; diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index 596ac6b33de..5216ff13664 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -14,7 +14,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::js::{Root, RootCollection}; use dom::bindings::refcounted::LiveDOMReferences; use dom::bindings::structuredclone::StructuredCloneData; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use dom::messageevent::MessageEvent; use dom::worker::{SimpleWorkerErrorHandler, TrustedWorkerAddress, WorkerMessageHandler}; use dom::workerglobalscope::WorkerGlobalScope; diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 8aa8ab08447..ad9e51a9c08 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -24,9 +24,10 @@ use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; use dom::bindings::num::Finite; use dom::bindings::refcounted::Trusted; use dom::bindings::trace::RootedVec; -use dom::bindings::utils::XMLName::InvalidXMLName; -use dom::bindings::utils::{Reflectable, reflect_dom_object}; -use dom::bindings::utils::{validate_and_extract, xml_name_type}; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::reflector::Reflectable; +use dom::bindings::xmlname::{validate_and_extract, xml_name_type}; +use dom::bindings::xmlname::XMLName::InvalidXMLName; use dom::comment::Comment; use dom::customevent::CustomEvent; use dom::documentfragment::DocumentFragment; diff --git a/components/script/dom/domexception.rs b/components/script/dom/domexception.rs index e63cbedafbc..8bc3497f5c9 100644 --- a/components/script/dom/domexception.rs +++ b/components/script/dom/domexception.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionConstants use dom::bindings::codegen::Bindings::DOMExceptionBinding::DOMExceptionMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use std::borrow::ToOwned; use util::str::DOMString; diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index 62db553454e..caf53a0d749 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -11,8 +11,8 @@ use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::validate_qualified_name; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::xmlname::validate_qualified_name; use dom::document::DocumentSource; use dom::document::{Document, IsHTMLDocument}; use dom::documenttype::DocumentType; diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs index a66b8ea3962..10ecd077a31 100644 --- a/components/script/dom/domparser.rs +++ b/components/script/dom/domparser.rs @@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::document::DocumentSource; use dom::document::{Document, IsHTMLDocument}; use dom::window::Window; diff --git a/components/script/dom/dompoint.rs b/components/script/dom/dompoint.rs index 1f8e85f50ad..3d797598ba0 100644 --- a/components/script/dom/dompoint.rs +++ b/components/script/dom/dompoint.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::DOMPointReadOnlyM use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::dompointreadonly::{DOMPointReadOnly, DOMPointWriteMethods}; // http://dev.w3.org/fxtf/geometry/Overview.html#dompoint diff --git a/components/script/dom/dompointreadonly.rs b/components/script/dom/dompointreadonly.rs index fd4965402cf..db56e70113d 100644 --- a/components/script/dom/dompointreadonly.rs +++ b/components/script/dom/dompointreadonly.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::DOMPointReadOnlyBinding::{DOMPointReadOnly use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use std::cell::Cell; // http://dev.w3.org/fxtf/geometry/Overview.html#dompointreadonly diff --git a/components/script/dom/domrect.rs b/components/script/dom/domrect.rs index fa1dcc1b165..aa4758d2b89 100644 --- a/components/script/dom/domrect.rs +++ b/components/script/dom/domrect.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::DOMRectReadOnlyMet use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::domrectreadonly::DOMRectReadOnly; #[dom_struct] diff --git a/components/script/dom/domrectlist.rs b/components/script/dom/domrectlist.rs index cd67dbc28c7..1c9c92ca3e3 100644 --- a/components/script/dom/domrectlist.rs +++ b/components/script/dom/domrectlist.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::DOMRectListBinding; use dom::bindings::codegen::Bindings::DOMRectListBinding::DOMRectListMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::domrect::DOMRect; use dom::window::Window; diff --git a/components/script/dom/domrectreadonly.rs b/components/script/dom/domrectreadonly.rs index a6ba99ead2a..f0bb23a20fe 100644 --- a/components/script/dom/domrectreadonly.rs +++ b/components/script/dom/domrectreadonly.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::{DOMRectReadOnlyMe use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use std::cell::Cell; #[dom_struct] diff --git a/components/script/dom/domstringmap.rs b/components/script/dom/domstringmap.rs index 95f727c93cb..49b7d0f6cf8 100644 --- a/components/script/dom/domstringmap.rs +++ b/components/script/dom/domstringmap.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::DOMStringMapBinding::DOMStringMapMethods; use dom::bindings::error::ErrorResult; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::htmlelement::HTMLElement; use dom::node::window_from_node; use util::str::DOMString; diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index c3944b7627c..fca96e5df16 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::DOMTokenListBinding::DOMTokenListMethods; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::element::Element; use dom::node::window_from_node; use std::borrow::ToOwned; diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index a26a292b7e6..8cdb4910d0d 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -26,8 +26,8 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap}; use dom::bindings::js::{Root, RootedReference}; -use dom::bindings::utils::XMLName::InvalidXMLName; -use dom::bindings::utils::{namespace_from_domstring, validate_and_extract, xml_name_type}; +use dom::bindings::xmlname::{namespace_from_domstring, validate_and_extract, xml_name_type}; +use dom::bindings::xmlname::XMLName::InvalidXMLName; use dom::characterdata::CharacterData; use dom::create::create_element; use dom::document::{Document, LayoutDocumentHelpers}; diff --git a/components/script/dom/errorevent.rs b/components/script/dom/errorevent.rs index ada456c84c6..edc422e0dd7 100644 --- a/components/script/dom/errorevent.rs +++ b/components/script/dom/errorevent.rs @@ -11,7 +11,7 @@ use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{MutHeapJSVal, Root}; use dom::bindings::trace::JSTraceable; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{Event, EventBubbles, EventCancelable}; use js::jsapi::{RootedValue, HandleValue, JSContext}; use js::jsval::JSVal; diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 6b63b3a58ee..34db84f561c 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::EventBinding::{EventConstants, EventMethod use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutNullableHeap, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::eventtarget::EventTarget; use std::borrow::ToOwned; use std::cell::Cell; diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs index 179e82917aa..31f603ee105 100644 --- a/components/script/dom/eventtarget.rs +++ b/components/script/dom/eventtarget.rs @@ -9,7 +9,8 @@ use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener; use dom::bindings::codegen::Bindings::EventTargetBinding::EventTargetMethods; use dom::bindings::codegen::InheritTypes::EventTargetTypeId; use dom::bindings::error::{Error, Fallible, report_pending_exception}; -use dom::bindings::utils::{Reflectable, Reflector}; +use dom::bindings::reflector::Reflector; +use dom::bindings::reflector::Reflectable; use dom::event::Event; use dom::eventdispatcher::dispatch_event; use dom::virtualmethods::VirtualMethods; diff --git a/components/script/dom/file.rs b/components/script/dom/file.rs index b9ccd721a47..5dfffd62541 100644 --- a/components/script/dom/file.rs +++ b/components/script/dom/file.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::FileBinding; use dom::bindings::codegen::Bindings::FileBinding::FileMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::blob::Blob; use util::str::DOMString; diff --git a/components/script/dom/filelist.rs b/components/script/dom/filelist.rs index d695ac8f43a..bed3d451b94 100644 --- a/components/script/dom/filelist.rs +++ b/components/script/dom/filelist.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::FileListBinding; use dom::bindings::codegen::Bindings::FileListBinding::FileListMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::file::File; use dom::window::Window; diff --git a/components/script/dom/filereader.rs b/components/script/dom/filereader.rs index fa71b76e83a..ad519c0efc8 100644 --- a/components/script/dom/filereader.rs +++ b/components/script/dom/filereader.rs @@ -10,7 +10,8 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::refcounted::Trusted; -use dom::bindings::utils::{Reflectable, reflect_dom_object}; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::reflector::Reflectable; use dom::blob::Blob; use dom::domexception::{DOMErrorName, DOMException}; use dom::event::{Event, EventBubbles, EventCancelable}; diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs index 14b497fca15..8c02f132a88 100644 --- a/components/script/dom/formdata.rs +++ b/components/script/dom/formdata.rs @@ -11,7 +11,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::{Fallible}; use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::blob::Blob; use dom::file::File; use dom::htmlformelement::HTMLFormElement; diff --git a/components/script/dom/htmlareaelement.rs b/components/script/dom/htmlareaelement.rs index 871def58e54..cd01baf4930 100644 --- a/components/script/dom/htmlareaelement.rs +++ b/components/script/dom/htmlareaelement.rs @@ -7,7 +7,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::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use dom::document::Document; use dom::domtokenlist::DOMTokenList; use dom::htmlelement::HTMLElement; diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs index 64719bae903..4ecb3d00225 100644 --- a/components/script/dom/htmlbodyelement.rs +++ b/components/script/dom/htmlbodyelement.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::Bindings::HTMLBodyElementBinding::{self, HTMLBodyEle use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods; use dom::bindings::inheritance::Castable; use dom::bindings::js::Root; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use dom::document::Document; use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; use dom::eventtarget::EventTarget; diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 3829f036e2d..f7bbb1753af 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -14,7 +14,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::global::GlobalRef; use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; use dom::bindings::num::Finite; -use dom::bindings::utils::{Reflectable}; +use dom::bindings::reflector::Reflectable; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; use dom::document::Document; use dom::element::{AttributeMutation, Element}; diff --git a/components/script/dom/htmlcanvaselement.rs.BACKUP.20128.rs b/components/script/dom/htmlcanvaselement.rs.BACKUP.20128.rs new file mode 100644 index 00000000000..7b6fda591da --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.BACKUP.20128.rs @@ -0,0 +1,355 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +<<<<<<< HEAD +use dom::bindings::conversions::Castable; +use dom::bindings::error::{Error, Fallible}; +======= +use dom::bindings::inheritance::Castable; +>>>>>>> move Castable into dom::bindings::inheritance +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::num::Finite; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use image::ColorType; +use image::png::PNGEncoder; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use rustc_serialize::base64::{STANDARD, ToBase64}; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl + fn ToDataURL(&self, + _context: *mut JSContext, + _mime_type: Option<DOMString>, + _arguments: Vec<HandleValue>) -> Fallible<DOMString> { + + // Step 1: Check the origin-clean flag (should be set in fillText/strokeText + // and currently unimplemented) + + // Step 2. + if self.Width() == 0 || self.Height() == 0 { + return Ok("data:,".to_owned()); + } + + // Step 3. + if let Some(CanvasContext::Context2d(ref context)) = *self.context.borrow() { + let window = window_from_node(self); + let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64), + Finite::wrap(self.Width() as f64), + Finite::wrap(self.Height() as f64))); + let raw_data = image_data.get_data_array(&GlobalRef::Window(window.r())); + + // Only handle image/png for now. + let mime_type = "image/png"; + + let mut encoded = Vec::new(); + { + let encoder: PNGEncoder<&mut Vec<u8>> = PNGEncoder::new(&mut encoded); + encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap(); + } + + let encoded = encoded.to_base64(STANDARD); + Ok(format!("data:{};base64,{}", mime_type, encoded)) + } else { + Err(Error::NotSupported) + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.BACKUP.20237.rs b/components/script/dom/htmlcanvaselement.rs.BACKUP.20237.rs new file mode 100644 index 00000000000..7b6fda591da --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.BACKUP.20237.rs @@ -0,0 +1,355 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +<<<<<<< HEAD +use dom::bindings::conversions::Castable; +use dom::bindings::error::{Error, Fallible}; +======= +use dom::bindings::inheritance::Castable; +>>>>>>> move Castable into dom::bindings::inheritance +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::num::Finite; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use image::ColorType; +use image::png::PNGEncoder; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use rustc_serialize::base64::{STANDARD, ToBase64}; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl + fn ToDataURL(&self, + _context: *mut JSContext, + _mime_type: Option<DOMString>, + _arguments: Vec<HandleValue>) -> Fallible<DOMString> { + + // Step 1: Check the origin-clean flag (should be set in fillText/strokeText + // and currently unimplemented) + + // Step 2. + if self.Width() == 0 || self.Height() == 0 { + return Ok("data:,".to_owned()); + } + + // Step 3. + if let Some(CanvasContext::Context2d(ref context)) = *self.context.borrow() { + let window = window_from_node(self); + let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64), + Finite::wrap(self.Width() as f64), + Finite::wrap(self.Height() as f64))); + let raw_data = image_data.get_data_array(&GlobalRef::Window(window.r())); + + // Only handle image/png for now. + let mime_type = "image/png"; + + let mut encoded = Vec::new(); + { + let encoder: PNGEncoder<&mut Vec<u8>> = PNGEncoder::new(&mut encoded); + encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap(); + } + + let encoded = encoded.to_base64(STANDARD); + Ok(format!("data:{};base64,{}", mime_type, encoded)) + } else { + Err(Error::NotSupported) + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.BASE.20128.rs b/components/script/dom/htmlcanvaselement.rs.BASE.20128.rs new file mode 100644 index 00000000000..2fdb8a129e6 --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.BASE.20128.rs @@ -0,0 +1,307 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +use dom::bindings::conversions::Castable; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.BASE.20237.rs b/components/script/dom/htmlcanvaselement.rs.BASE.20237.rs new file mode 100644 index 00000000000..2fdb8a129e6 --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.BASE.20237.rs @@ -0,0 +1,307 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +use dom::bindings::conversions::Castable; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.LOCAL.20128.rs b/components/script/dom/htmlcanvaselement.rs.LOCAL.20128.rs new file mode 100644 index 00000000000..47126ed3dd0 --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.LOCAL.20128.rs @@ -0,0 +1,351 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +use dom::bindings::conversions::Castable; +use dom::bindings::error::{Error, Fallible}; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::num::Finite; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use image::ColorType; +use image::png::PNGEncoder; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use rustc_serialize::base64::{STANDARD, ToBase64}; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl + fn ToDataURL(&self, + _context: *mut JSContext, + _mime_type: Option<DOMString>, + _arguments: Vec<HandleValue>) -> Fallible<DOMString> { + + // Step 1: Check the origin-clean flag (should be set in fillText/strokeText + // and currently unimplemented) + + // Step 2. + if self.Width() == 0 || self.Height() == 0 { + return Ok("data:,".to_owned()); + } + + // Step 3. + if let Some(CanvasContext::Context2d(ref context)) = *self.context.borrow() { + let window = window_from_node(self); + let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64), + Finite::wrap(self.Width() as f64), + Finite::wrap(self.Height() as f64))); + let raw_data = image_data.get_data_array(&GlobalRef::Window(window.r())); + + // Only handle image/png for now. + let mime_type = "image/png"; + + let mut encoded = Vec::new(); + { + let encoder: PNGEncoder<&mut Vec<u8>> = PNGEncoder::new(&mut encoded); + encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap(); + } + + let encoded = encoded.to_base64(STANDARD); + Ok(format!("data:{};base64,{}", mime_type, encoded)) + } else { + Err(Error::NotSupported) + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.LOCAL.20237.rs b/components/script/dom/htmlcanvaselement.rs.LOCAL.20237.rs new file mode 100644 index 00000000000..47126ed3dd0 --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.LOCAL.20237.rs @@ -0,0 +1,351 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +use dom::bindings::conversions::Castable; +use dom::bindings::error::{Error, Fallible}; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::num::Finite; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use image::ColorType; +use image::png::PNGEncoder; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use rustc_serialize::base64::{STANDARD, ToBase64}; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl + fn ToDataURL(&self, + _context: *mut JSContext, + _mime_type: Option<DOMString>, + _arguments: Vec<HandleValue>) -> Fallible<DOMString> { + + // Step 1: Check the origin-clean flag (should be set in fillText/strokeText + // and currently unimplemented) + + // Step 2. + if self.Width() == 0 || self.Height() == 0 { + return Ok("data:,".to_owned()); + } + + // Step 3. + if let Some(CanvasContext::Context2d(ref context)) = *self.context.borrow() { + let window = window_from_node(self); + let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64), + Finite::wrap(self.Width() as f64), + Finite::wrap(self.Height() as f64))); + let raw_data = image_data.get_data_array(&GlobalRef::Window(window.r())); + + // Only handle image/png for now. + let mime_type = "image/png"; + + let mut encoded = Vec::new(); + { + let encoder: PNGEncoder<&mut Vec<u8>> = PNGEncoder::new(&mut encoded); + encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap(); + } + + let encoded = encoded.to_base64(STANDARD); + Ok(format!("data:{};base64,{}", mime_type, encoded)) + } else { + Err(Error::NotSupported) + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.REMOTE.20128.rs b/components/script/dom/htmlcanvaselement.rs.REMOTE.20128.rs new file mode 100644 index 00000000000..d15c7096f90 --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.REMOTE.20128.rs @@ -0,0 +1,307 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +use dom::bindings::inheritance::Castable; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.REMOTE.20237.rs b/components/script/dom/htmlcanvaselement.rs.REMOTE.20237.rs new file mode 100644 index 00000000000..d15c7096f90 --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.REMOTE.20237.rs @@ -0,0 +1,307 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +use dom::bindings::inheritance::Castable; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcanvaselement.rs.orig b/components/script/dom/htmlcanvaselement.rs.orig new file mode 100644 index 00000000000..7b6fda591da --- /dev/null +++ b/components/script/dom/htmlcanvaselement.rs.orig @@ -0,0 +1,355 @@ +/* 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 canvas_traits::{CanvasMsg, FromLayoutMsg}; +use dom::attr::Attr; +use dom::bindings::cell::DOMRefCell; +use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; +use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods; +use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes; +use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext; +<<<<<<< HEAD +use dom::bindings::conversions::Castable; +use dom::bindings::error::{Error, Fallible}; +======= +use dom::bindings::inheritance::Castable; +>>>>>>> move Castable into dom::bindings::inheritance +use dom::bindings::global::GlobalRef; +use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root}; +use dom::bindings::num::Finite; +use dom::bindings::utils::{Reflectable}; +use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; +use dom::document::Document; +use dom::element::{AttributeMutation, Element}; +use dom::htmlelement::HTMLElement; +use dom::node::{Node, window_from_node}; +use dom::virtualmethods::VirtualMethods; +use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext}; +use euclid::size::Size2D; +use image::ColorType; +use image::png::PNGEncoder; +use ipc_channel::ipc::{self, IpcSender}; +use js::jsapi::{HandleValue, JSContext}; +use offscreen_gl_context::GLContextAttributes; +use rustc_serialize::base64::{STANDARD, ToBase64}; +use std::cell::Cell; +use std::iter::repeat; +use util::str::{DOMString, parse_unsigned_integer}; + +const DEFAULT_WIDTH: u32 = 300; +const DEFAULT_HEIGHT: u32 = 150; + +#[must_root] +#[derive(JSTraceable, Clone, HeapSizeOf)] +pub enum CanvasContext { + Context2d(JS<CanvasRenderingContext2D>), + WebGL(JS<WebGLRenderingContext>), +} + +impl HeapGCValue for CanvasContext {} + +#[dom_struct] +pub struct HTMLCanvasElement { + htmlelement: HTMLElement, + context: DOMRefCell<Option<CanvasContext>>, + width: Cell<u32>, + height: Cell<u32>, +} + +impl PartialEq for HTMLCanvasElement { + fn eq(&self, other: &HTMLCanvasElement) -> bool { + self as *const HTMLCanvasElement == &*other + } +} + +impl HTMLCanvasElement { + fn new_inherited(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> HTMLCanvasElement { + HTMLCanvasElement { + htmlelement: HTMLElement::new_inherited(localName, prefix, document), + context: DOMRefCell::new(None), + width: Cell::new(DEFAULT_WIDTH), + height: Cell::new(DEFAULT_HEIGHT), + } + } + + #[allow(unrooted_must_root)] + pub fn new(localName: DOMString, + prefix: Option<DOMString>, + document: &Document) -> Root<HTMLCanvasElement> { + let element = HTMLCanvasElement::new_inherited(localName, prefix, document); + Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap) + } + + fn recreate_contexts(&self) { + let size = self.get_size(); + if let Some(ref context) = *self.context.borrow() { + match *context { + CanvasContext::Context2d(ref context) => context.recreate(size), + CanvasContext::WebGL(ref context) => context.recreate(size), + } + } + } + + pub fn get_size(&self) -> Size2D<i32> { + Size2D::new(self.width.get() as i32, self.height.get() as i32) + } +} + +pub struct HTMLCanvasData { + pub renderer_id: Option<usize>, + pub ipc_renderer: Option<IpcSender<CanvasMsg>>, + pub width: u32, + pub height: u32, +} + +pub trait LayoutHTMLCanvasElementHelpers { + fn data(&self) -> HTMLCanvasData; +} + +impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { + #[allow(unsafe_code)] + fn data(&self) -> HTMLCanvasData { + unsafe { + let canvas = &*self.unsafe_get(); + let (renderer_id, ipc_renderer) = match canvas.context.borrow_for_layout().as_ref() { + Some(&CanvasContext::Context2d(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + Some(&CanvasContext::WebGL(ref context)) => { + let context = context.to_layout(); + (Some(context.get_renderer_id()), Some(context.get_ipc_renderer())) + }, + None => (None, None), + }; + + HTMLCanvasData { + renderer_id: renderer_id, + ipc_renderer: ipc_renderer, + width: canvas.width.get(), + height: canvas.height.get(), + } + } + } +} + + +impl HTMLCanvasElement { + pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> { + self.context.borrow().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => context.ipc_renderer(), + CanvasContext::WebGL(ref context) => context.ipc_renderer(), + } + }) + } + + pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size); + *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context))); + } + + match *self.context.borrow().as_ref().unwrap() { + CanvasContext::Context2d(ref context) => Some(context.root()), + _ => None, + } + } + + pub fn get_or_init_webgl_context(&self, + cx: *mut JSContext, + attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> { + if self.context.borrow().is_none() { + let window = window_from_node(self); + let size = self.get_size(); + + let attrs = if let Some(webgl_attributes) = attrs { + if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) { + From::from(attrs) + } else { + debug!("Unexpected error on conversion of WebGLContextAttributes"); + return None; + } + } else { + GLContextAttributes::default() + }; + + let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs); + + *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))); + } + + if let Some(CanvasContext::WebGL(ref context)) = *self.context.borrow() { + Some(context.root()) + } else { + None + } + } + + pub fn is_valid(&self) -> bool { + self.height.get() != 0 && self.width.get() != 0 + } + + pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { + let size = self.get_size(); + + if size.width == 0 || size.height == 0 { + return None + } + + let data = if let Some(renderer) = self.ipc_renderer() { + let (sender, receiver) = ipc::channel().unwrap(); + let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender)); + renderer.send(msg).unwrap(); + + receiver.recv().unwrap().to_vec() + } else { + repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect() + }; + + Some((data, size)) + } +} + +impl HTMLCanvasElementMethods for HTMLCanvasElement { + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn Width(&self) -> u32 { + self.width.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-width + fn SetWidth(&self, width: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn Height(&self) -> u32 { + self.height.get() + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-height + fn SetHeight(&self, height: u32) { + self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext + fn GetContext(&self, + cx: *mut JSContext, + id: DOMString, + attributes: Vec<HandleValue>) + -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> { + match &*id { + "2d" => { + self.get_or_init_2d_context() + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D) + } + "webgl" | "experimental-webgl" => { + self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p)) + .map(CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext) + } + _ => None + } + } + + // https://html.spec.whatwg.org/multipage/#dom-canvas-todataurl + fn ToDataURL(&self, + _context: *mut JSContext, + _mime_type: Option<DOMString>, + _arguments: Vec<HandleValue>) -> Fallible<DOMString> { + + // Step 1: Check the origin-clean flag (should be set in fillText/strokeText + // and currently unimplemented) + + // Step 2. + if self.Width() == 0 || self.Height() == 0 { + return Ok("data:,".to_owned()); + } + + // Step 3. + if let Some(CanvasContext::Context2d(ref context)) = *self.context.borrow() { + let window = window_from_node(self); + let image_data = try!(context.GetImageData(Finite::wrap(0f64), Finite::wrap(0f64), + Finite::wrap(self.Width() as f64), + Finite::wrap(self.Height() as f64))); + let raw_data = image_data.get_data_array(&GlobalRef::Window(window.r())); + + // Only handle image/png for now. + let mime_type = "image/png"; + + let mut encoded = Vec::new(); + { + let encoder: PNGEncoder<&mut Vec<u8>> = PNGEncoder::new(&mut encoded); + encoder.encode(&raw_data, self.Width(), self.Height(), ColorType::RGBA(8)).unwrap(); + } + + let encoded = encoded.to_base64(STANDARD); + Ok(format!("data:{};base64,{}", mime_type, encoded)) + } else { + Err(Error::NotSupported) + } + } +} + +impl VirtualMethods for HTMLCanvasElement { + fn super_type(&self) -> Option<&VirtualMethods> { + Some(self.upcast::<HTMLElement>() as &VirtualMethods) + } + + fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { + self.super_type().unwrap().attribute_mutated(attr, mutation); + let recreate = match attr.local_name() { + &atom!(width) => { + let width = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.width.set(width.unwrap_or(DEFAULT_WIDTH)); + true + }, + &atom!(height) => { + let height = mutation.new_value(attr).and_then(|value| { + parse_unsigned_integer(value.chars()) + }); + self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); + true + }, + _ => false, + }; + if recreate { + self.recreate_contexts(); + } + } +} + +impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes { + fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes { + GLContextAttributes { + alpha: attrs.alpha, + depth: attrs.depth, + stencil: attrs.stencil, + antialias: attrs.antialias, + premultiplied_alpha: attrs.premultipliedAlpha, + preserve_drawing_buffer: attrs.preserveDrawingBuffer, + } + } +} + +pub mod utils { + use dom::window::Window; + use ipc_channel::ipc; + use net_traits::image_cache_task::{ImageCacheChan, ImageResponse}; + use url::Url; + + pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse { + let image_cache = window.image_cache_task(); + let (response_chan, response_port) = ipc::channel().unwrap(); + image_cache.request_image(url, ImageCacheChan(response_chan), None); + let result = response_port.recv().unwrap(); + result.image_response + } +} diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs index 4cc54c43e73..27c2a88093d 100644 --- a/components/script/dom/htmlcollection.rs +++ b/components/script/dom/htmlcollection.rs @@ -8,7 +8,8 @@ use dom::bindings::inheritance::Castable; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; use dom::bindings::trace::JSTraceable; -use dom::bindings::utils::{Reflector, namespace_from_domstring, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::xmlname::namespace_from_domstring; use dom::element::Element; use dom::node::{Node, TreeIterator}; use dom::window::Window; diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 115b4d88439..16f46bc68c1 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -13,7 +13,7 @@ use dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId, Nod use dom::bindings::inheritance::Castable; use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::js::{JS, MutNullableHeap, Root}; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration}; use dom::document::Document; use dom::domstringmap::DOMStringMap; diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 58e82932df0..b73385bf705 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -10,11 +10,11 @@ use dom::bindings::codegen::Bindings::HTMLFormElementBinding; use dom::bindings::codegen::Bindings::HTMLFormElementBinding::HTMLFormElementMethods; use dom::bindings::codegen::Bindings::HTMLInputElementBinding::HTMLInputElementMethods; use dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementTypeId, NodeTypeId}; -use dom::bindings::conversions::{DerivedFrom}; +use dom::bindings::conversions::DerivedFrom; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{Root}; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use dom::document::Document; use dom::element::Element; use dom::event::{Event, EventBubbles, EventCancelable}; diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 6e4a32e603e..95fb9bbf2f3 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -11,7 +11,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::inheritance::Castable; use dom::bindings::js::{Root, LayoutJS}; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use dom::customevent::CustomEvent; use dom::document::Document; use dom::element::{self, AttributeMutation, Element}; diff --git a/components/script/dom/imagedata.rs b/components/script/dom/imagedata.rs index 7f2b561e85f..ffbe0a4b225 100644 --- a/components/script/dom/imagedata.rs +++ b/components/script/dom/imagedata.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::ImageDataBinding; use dom::bindings::codegen::Bindings::ImageDataBinding::ImageDataMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use euclid::size::Size2D; use js::jsapi::{Heap, JSContext, JSObject}; use js::jsapi::{JS_GetUint8ClampedArrayData, JS_NewUint8ClampedArray}; diff --git a/components/script/dom/keyboardevent.rs b/components/script/dom/keyboardevent.rs index db94b451318..d09701b9dda 100644 --- a/components/script/dom/keyboardevent.rs +++ b/components/script/dom/keyboardevent.rs @@ -9,7 +9,8 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{Root, RootedReference}; -use dom::bindings::utils::{Reflectable, reflect_dom_object}; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::reflector::Reflectable; use dom::event::Event; use dom::uievent::UIEvent; use dom::window::Window; diff --git a/components/script/dom/location.rs b/components/script/dom/location.rs index a9e788a7b04..1bab27b9c48 100644 --- a/components/script/dom/location.rs +++ b/components/script/dom/location.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; use dom::bindings::str::USVString; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::urlhelper::UrlHelper; use dom::window::Window; use url::{Url, UrlParser}; diff --git a/components/script/dom/messageevent.rs b/components/script/dom/messageevent.rs index b767c738f8a..8904cdce139 100644 --- a/components/script/dom/messageevent.rs +++ b/components/script/dom/messageevent.rs @@ -9,7 +9,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::Event; use dom::eventtarget::EventTarget; use js::jsapi::{RootedValue, HandleValue, Heap, JSContext}; diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs index 904b9fddb80..b027f8af8d2 100644 --- a/components/script/dom/mouseevent.rs +++ b/components/script/dom/mouseevent.rs @@ -9,7 +9,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; use dom::uievent::UIEvent; diff --git a/components/script/dom/namednodemap.rs b/components/script/dom/namednodemap.rs index 6070c0bb0c2..e3115223931 100644 --- a/components/script/dom/namednodemap.rs +++ b/components/script/dom/namednodemap.rs @@ -8,7 +8,8 @@ use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods; use dom::bindings::error::{Error, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, namespace_from_domstring, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::bindings::xmlname::namespace_from_domstring; use dom::element::Element; use dom::window::Window; use string_cache::Atom; diff --git a/components/script/dom/navigator.rs b/components/script/dom/navigator.rs index 4f3f3d2c2da..5fa0465d361 100644 --- a/components/script/dom/navigator.rs +++ b/components/script/dom/navigator.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::NavigatorBinding; use dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::navigatorinfo; use dom::window::Window; use util::str::DOMString; diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 43f7d0e9449..72168536912 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -31,7 +31,8 @@ use dom::bindings::js::RootedReference; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap}; use dom::bindings::trace::JSTraceable; use dom::bindings::trace::RootedVec; -use dom::bindings::utils::{Reflectable, namespace_from_domstring, reflect_dom_object}; +use dom::bindings::reflector::{Reflectable, reflect_dom_object}; +use dom::bindings::xmlname::namespace_from_domstring; use dom::characterdata::CharacterData; use dom::comment::Comment; use dom::document::{Document, DocumentSource, IsHTMLDocument}; diff --git a/components/script/dom/nodeiterator.rs b/components/script/dom/nodeiterator.rs index 27a99ec3b55..379ce5a3743 100644 --- a/components/script/dom/nodeiterator.rs +++ b/components/script/dom/nodeiterator.rs @@ -11,7 +11,7 @@ use dom::bindings::codegen::Bindings::NodeIteratorBinding::NodeIteratorMethods; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::document::Document; use dom::node::Node; use std::cell::Cell; diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index 490df73bd56..cf5da3b0a3f 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::NodeListBinding; use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::node::{ChildrenMutation, Node}; use dom::window::Window; use std::cell::Cell; diff --git a/components/script/dom/performance.rs b/components/script/dom/performance.rs index b8b6c17ef09..ffcdc7a170e 100644 --- a/components/script/dom/performance.rs +++ b/components/script/dom/performance.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::PerformanceBinding::PerformanceMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; use dom::bindings::num::Finite; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::performancetiming::PerformanceTiming; use dom::window::Window; use time; diff --git a/components/script/dom/performancetiming.rs b/components/script/dom/performancetiming.rs index 9992f87f3c8..1799d6a7f91 100644 --- a/components/script/dom/performancetiming.rs +++ b/components/script/dom/performancetiming.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::PerformanceTimingBinding; use dom::bindings::codegen::Bindings::PerformanceTimingBinding::PerformanceTimingMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::window::Window; #[dom_struct] diff --git a/components/script/dom/progressevent.rs b/components/script/dom/progressevent.rs index 1d03015ffad..4fefde82c47 100644 --- a/components/script/dom/progressevent.rs +++ b/components/script/dom/progressevent.rs @@ -9,7 +9,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{Event, EventBubbles, EventCancelable}; use util::str::DOMString; diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs index 86f8ae8a8bd..3a6c823eb2b 100644 --- a/components/script/dom/range.rs +++ b/components/script/dom/range.rs @@ -15,7 +15,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root, RootedReference}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::characterdata::CharacterData; use dom::document::Document; use dom::documentfragment::DocumentFragment; diff --git a/components/script/dom/screen.rs b/components/script/dom/screen.rs index e38dc676afe..158615e84dc 100644 --- a/components/script/dom/screen.rs +++ b/components/script/dom/screen.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::ScreenBinding; use dom::bindings::codegen::Bindings::ScreenBinding::ScreenMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::window::Window; #[dom_struct] diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index 3a4a59ba3af..c7e4cd45b35 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -12,7 +12,7 @@ use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; use dom::bindings::refcounted::Trusted; use dom::bindings::trace::JSTraceable; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::document::Document; use dom::node::Node; use dom::text::Text; diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs index 9a21c98e607..17003692e15 100644 --- a/components/script/dom/storage.rs +++ b/components/script/dom/storage.rs @@ -9,7 +9,7 @@ use dom::bindings::error::{Error, ErrorResult}; use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::js::{Root, RootedReference}; use dom::bindings::refcounted::Trusted; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::storageevent::StorageEvent; use dom::urlhelper::UrlHelper; diff --git a/components/script/dom/storageevent.rs b/components/script/dom/storageevent.rs index 92a0fb197b5..55f2d04d6cc 100644 --- a/components/script/dom/storageevent.rs +++ b/components/script/dom/storageevent.rs @@ -9,7 +9,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; -use dom::bindings::utils::{reflect_dom_object}; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::storage::Storage; use util::str::DOMString; diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index 7c2038eab3b..9e2da895852 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -18,7 +18,7 @@ use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::js::Root; use dom::bindings::num::Finite; use dom::bindings::str::{ByteString, USVString}; -use dom::bindings::utils::Reflector; +use dom::bindings::reflector::Reflector; use dom::blob::Blob; use js::jsapi::{HandleValue, JSContext, JSObject}; use js::jsval::{JSVal, NullValue}; diff --git a/components/script/dom/testbindingproxy.rs b/components/script/dom/testbindingproxy.rs index 079e7656f68..0c323a3f4c3 100644 --- a/components/script/dom/testbindingproxy.rs +++ b/components/script/dom/testbindingproxy.rs @@ -5,7 +5,7 @@ // check-tidy: no specs after this line use dom::bindings::codegen::Bindings::TestBindingProxyBinding::TestBindingProxyMethods; -use dom::bindings::utils::Reflector; +use dom::bindings::reflector::Reflector; use util::str::DOMString; diff --git a/components/script/dom/textdecoder.rs b/components/script/dom/textdecoder.rs index c09fcd25614..ad2f28c9ff5 100644 --- a/components/script/dom/textdecoder.rs +++ b/components/script/dom/textdecoder.rs @@ -9,7 +9,7 @@ use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::str::USVString; use dom::bindings::trace::JSTraceable; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use encoding::Encoding; use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, EncodingRef}; diff --git a/components/script/dom/textencoder.rs b/components/script/dom/textencoder.rs index 913b7c4fe86..1025df5d3d3 100644 --- a/components/script/dom/textencoder.rs +++ b/components/script/dom/textencoder.rs @@ -8,7 +8,7 @@ use dom::bindings::error::{Error, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::str::USVString; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use encoding::label::encoding_from_whatwg_label; use encoding::types::EncodingRef; use encoding::{EncoderTrap, Encoding}; diff --git a/components/script/dom/touch.rs b/components/script/dom/touch.rs index 9e25dacf422..29bfac34152 100644 --- a/components/script/dom/touch.rs +++ b/components/script/dom/touch.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::TouchBinding::TouchMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; use dom::bindings::num::Finite; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::eventtarget::EventTarget; use dom::window::Window; diff --git a/components/script/dom/touchevent.rs b/components/script/dom/touchevent.rs index e87f47c4747..d84d4788eda 100644 --- a/components/script/dom/touchevent.rs +++ b/components/script/dom/touchevent.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::UIEventBinding::UIEventMethods; use dom::bindings::inheritance::Castable; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutHeap, Root}; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{EventBubbles, EventCancelable}; use dom::touchlist::TouchList; use dom::uievent::UIEvent; diff --git a/components/script/dom/touchlist.rs b/components/script/dom/touchlist.rs index 5806f945008..ed40a5ee2ed 100644 --- a/components/script/dom/touchlist.rs +++ b/components/script/dom/touchlist.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::TouchListBinding; use dom::bindings::codegen::Bindings::TouchListBinding::TouchListMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::touch::Touch; use dom::window::Window; diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs index f19e8383ddf..35a7291122d 100644 --- a/components/script/dom/treewalker.rs +++ b/components/script/dom/treewalker.rs @@ -12,7 +12,7 @@ use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::js::{JS, MutHeap}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::document::Document; use dom::node::Node; use std::rc::Rc; diff --git a/components/script/dom/uievent.rs b/components/script/dom/uievent.rs index 41eb6097005..079dbb3a814 100644 --- a/components/script/dom/uievent.rs +++ b/components/script/dom/uievent.rs @@ -10,7 +10,7 @@ use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::js::{JS, MutNullableHeap, RootedReference}; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::window::Window; use std::cell::Cell; diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs index 9ff22b53597..95fc38122f1 100644 --- a/components/script/dom/url.rs +++ b/components/script/dom/url.rs @@ -7,7 +7,7 @@ use dom::bindings::error::{Error, ErrorResult, Fallible}; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::str::USVString; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::urlhelper::UrlHelper; use std::borrow::ToOwned; use std::cell::RefCell; diff --git a/components/script/dom/urlsearchparams.rs b/components/script/dom/urlsearchparams.rs index 6ddfe4f5278..88a576814ac 100644 --- a/components/script/dom/urlsearchparams.rs +++ b/components/script/dom/urlsearchparams.rs @@ -10,7 +10,7 @@ use dom::bindings::codegen::UnionTypes::StringOrURLSearchParams::{eString, eURLS use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use encoding::types::EncodingRef; use url::form_urlencoded::{parse, serialize_with_encoding}; use util::str::DOMString; diff --git a/components/script/dom/validitystate.rs b/components/script/dom/validitystate.rs index 547e7363b82..ae48a1624b0 100644 --- a/components/script/dom/validitystate.rs +++ b/components/script/dom/validitystate.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::Bindings::ValidityStateBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::window::Window; // https://html.spec.whatwg.org/multipage/#validitystate diff --git a/components/script/dom/webglactiveinfo.rs b/components/script/dom/webglactiveinfo.rs index efac59725b5..3b069407f36 100644 --- a/components/script/dom/webglactiveinfo.rs +++ b/components/script/dom/webglactiveinfo.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::WebGLActiveInfoBinding; use dom::bindings::codegen::Bindings::WebGLActiveInfoBinding::WebGLActiveInfoMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use util::str::DOMString; #[dom_struct] diff --git a/components/script/dom/webglbuffer.rs b/components/script/dom/webglbuffer.rs index 05f8d7263bb..e577c06aa19 100644 --- a/components/script/dom/webglbuffer.rs +++ b/components/script/dom/webglbuffer.rs @@ -7,7 +7,7 @@ use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult}; use dom::bindings::codegen::Bindings::WebGLBufferBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; diff --git a/components/script/dom/webglcontextevent.rs b/components/script/dom/webglcontextevent.rs index 8f4eda6a535..905deaaddf2 100644 --- a/components/script/dom/webglcontextevent.rs +++ b/components/script/dom/webglcontextevent.rs @@ -10,7 +10,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::event::{Event, EventBubbles, EventCancelable}; use util::str::DOMString; diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index a3a9781fbfb..60f550d63c7 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -7,7 +7,7 @@ use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLFramebufferBindingRequest}; use dom::bindings::codegen::Bindings::WebGLFramebufferBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; diff --git a/components/script/dom/webglobject.rs b/components/script/dom/webglobject.rs index c950768e329..c6bc733de62 100644 --- a/components/script/dom/webglobject.rs +++ b/components/script/dom/webglobject.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::WebGLObjectBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; #[dom_struct] pub struct WebGLObject { diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 997f48c96b4..88052215254 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::WebGLProgramBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutNullableHeap, Root}; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use dom::webglrenderingcontext::MAX_UNIFORM_AND_ATTRIBUTE_LEN; use dom::webglshader::WebGLShader; diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs index b01bcce896a..9bca4b5972c 100644 --- a/components/script/dom/webglrenderbuffer.rs +++ b/components/script/dom/webglrenderbuffer.rs @@ -7,7 +7,7 @@ use canvas_traits::{CanvasMsg, CanvasWebGLMsg}; use dom::bindings::codegen::Bindings::WebGLRenderbufferBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 03762f887d5..3e9cc0b60b7 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -9,11 +9,11 @@ use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderi use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{WebGLRenderingContextMethods}; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes}; use dom::bindings::codegen::UnionTypes::ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement; -use dom::bindings::conversions::{ToJSValConvertible}; +use dom::bindings::conversions::ToJSValConvertible; use dom::bindings::global::{GlobalField, GlobalRef}; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap, Root}; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::htmlcanvaselement::HTMLCanvasElement; use dom::htmlcanvaselement::utils as canvas_utils; diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs index e33b27d3839..e272706a95e 100644 --- a/components/script/dom/webglshader.rs +++ b/components/script/dom/webglshader.rs @@ -9,7 +9,7 @@ use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderi use dom::bindings::codegen::Bindings::WebGLShaderBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::{Cell, RefCell}; diff --git a/components/script/dom/webglshaderprecisionformat.rs b/components/script/dom/webglshaderprecisionformat.rs index e3b8f473bc5..6cd78b8d51a 100644 --- a/components/script/dom/webglshaderprecisionformat.rs +++ b/components/script/dom/webglshaderprecisionformat.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::WebGLShaderPrecisionFormatBinding; use dom::bindings::codegen::Bindings::WebGLShaderPrecisionFormatBinding::WebGLShaderPrecisionFormatMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; #[dom_struct] pub struct WebGLShaderPrecisionFormat { diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index fb8ee4033fd..f6a7acc786b 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -8,7 +8,7 @@ use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderi use dom::bindings::codegen::Bindings::WebGLTextureBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; diff --git a/components/script/dom/webgluniformlocation.rs b/components/script/dom/webgluniformlocation.rs index ea30afc8b51..7367f9f1d7d 100644 --- a/components/script/dom/webgluniformlocation.rs +++ b/components/script/dom/webgluniformlocation.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::WebGLUniformLocationBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; #[dom_struct] pub struct WebGLUniformLocation { diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index 595ee147cdf..46471b0761c 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -14,7 +14,8 @@ use dom::bindings::js::Root; use dom::bindings::refcounted::Trusted; use dom::bindings::str::USVString; use dom::bindings::trace::JSTraceable; -use dom::bindings::utils::{Reflectable, reflect_dom_object}; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::reflector::Reflectable; use dom::blob::Blob; use dom::closeevent::CloseEvent; use dom::event::{Event, EventBubbles, EventCancelable}; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index f922a7a5ae3..44c138bb1e5 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -18,7 +18,8 @@ use dom::bindings::global::global_object_for_js_object; use dom::bindings::js::RootedReference; use dom::bindings::js::{JS, MutNullableHeap, Root}; use dom::bindings::num::Finite; -use dom::bindings::utils::{GlobalStaticData, Reflectable, WindowProxyHandler}; +use dom::bindings::reflector::Reflectable; +use dom::bindings::utils::{GlobalStaticData, WindowProxyHandler}; use dom::browsercontext::BrowsingContext; use dom::console::Console; use dom::crypto::Crypto; diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs index 7745319c19d..a16452b5b4f 100644 --- a/components/script/dom/worker.rs +++ b/components/script/dom/worker.rs @@ -13,7 +13,8 @@ use dom::bindings::js::Root; use dom::bindings::refcounted::Trusted; use dom::bindings::structuredclone::StructuredCloneData; use dom::bindings::trace::JSTraceable; -use dom::bindings::utils::{Reflectable, reflect_dom_object}; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::reflector::Reflectable; use dom::dedicatedworkerglobalscope::{DedicatedWorkerGlobalScope, WorkerScriptMsg}; use dom::errorevent::ErrorEvent; use dom::event::{Event, EventBubbles, EventCancelable}; diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 693b4116756..fb263bbea27 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -9,7 +9,7 @@ use dom::bindings::inheritance::Castable; use dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, MutNullableHeap, Root}; -use dom::bindings::utils::Reflectable; +use dom::bindings::reflector::Reflectable; use dom::console::Console; use dom::crypto::Crypto; use dom::dedicatedworkerglobalscope::DedicatedWorkerGlobalScope; diff --git a/components/script/dom/workerlocation.rs b/components/script/dom/workerlocation.rs index 477c329cf75..23f9e18f4b0 100644 --- a/components/script/dom/workerlocation.rs +++ b/components/script/dom/workerlocation.rs @@ -7,7 +7,7 @@ use dom::bindings::codegen::Bindings::WorkerLocationBinding::WorkerLocationMetho use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::str::USVString; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::urlhelper::UrlHelper; use dom::workerglobalscope::WorkerGlobalScope; use url::Url; diff --git a/components/script/dom/workernavigator.rs b/components/script/dom/workernavigator.rs index 6bef4bdb048..146c098d7d1 100644 --- a/components/script/dom/workernavigator.rs +++ b/components/script/dom/workernavigator.rs @@ -6,7 +6,7 @@ use dom::bindings::codegen::Bindings::WorkerNavigatorBinding; use dom::bindings::codegen::Bindings::WorkerNavigatorBinding::WorkerNavigatorMethods; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::{Reflector, reflect_dom_object}; +use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::navigatorinfo; use dom::workerglobalscope::WorkerGlobalScope; use util::str::DOMString; diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 5afd4cb7777..8e0b3c30d0a 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -20,7 +20,8 @@ use dom::bindings::js::Root; use dom::bindings::js::{JS, MutNullableHeap}; use dom::bindings::refcounted::Trusted; use dom::bindings::str::ByteString; -use dom::bindings::utils::{Reflectable, reflect_dom_object}; +use dom::bindings::reflector::reflect_dom_object; +use dom::bindings::reflector::Reflectable; use dom::document::Document; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; diff --git a/components/script/dom/xmlhttprequestupload.rs b/components/script/dom/xmlhttprequestupload.rs index e426c63c30c..900548f2e05 100644 --- a/components/script/dom/xmlhttprequestupload.rs +++ b/components/script/dom/xmlhttprequestupload.rs @@ -5,7 +5,7 @@ use dom::bindings::codegen::Bindings::XMLHttpRequestUploadBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::utils::reflect_dom_object; +use dom::bindings::reflector::reflect_dom_object; use dom::xmlhttprequesteventtarget::XMLHttpRequestEventTarget; #[dom_struct] |