aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom
diff options
context:
space:
mode:
authorrohan.prinja <rohan.prinja@samsung.com>2015-10-27 17:58:34 +0900
committerrohan.prinja <rohan.prinja@samsung.com>2015-10-30 20:26:29 +0900
commit45224028dbc1d75e6dfc8add19ff8e997c7ebb99 (patch)
treef5a113706605564ec491dbf9710842d79e5b2e5c /components/script/dom
parentbb2536cd014676263f5bfd5d98cf0fc69d2abee0 (diff)
downloadservo-45224028dbc1d75e6dfc8add19ff8e997c7ebb99.tar.gz
servo-45224028dbc1d75e6dfc8add19ff8e997c7ebb99.zip
more refactoring
Diffstat (limited to 'components/script/dom')
-rw-r--r--components/script/dom/attr.rs2
-rw-r--r--components/script/dom/bindings/callback.rs2
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py7
-rw-r--r--components/script/dom/bindings/conversions.rs4
-rw-r--r--components/script/dom/bindings/global.rs3
-rw-r--r--components/script/dom/bindings/inheritance.rs4
-rw-r--r--components/script/dom/bindings/js.rs3
-rw-r--r--components/script/dom/bindings/mod.rs3
-rw-r--r--components/script/dom/bindings/refcounted.rs3
-rw-r--r--components/script/dom/bindings/reflector.rs79
-rw-r--r--components/script/dom/bindings/trace.rs3
-rw-r--r--components/script/dom/bindings/utils.rs239
-rw-r--r--components/script/dom/bindings/xmlname.rs176
-rw-r--r--components/script/dom/blob.rs2
-rw-r--r--components/script/dom/browsercontext.rs3
-rw-r--r--components/script/dom/canvasgradient.rs2
-rw-r--r--components/script/dom/canvaspattern.rs2
-rw-r--r--components/script/dom/canvasrenderingcontext2d.rs2
-rw-r--r--components/script/dom/closeevent.rs2
-rw-r--r--components/script/dom/console.rs2
-rw-r--r--components/script/dom/crypto.rs2
-rw-r--r--components/script/dom/css.rs2
-rw-r--r--components/script/dom/cssstyledeclaration.rs2
-rw-r--r--components/script/dom/customevent.rs2
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs2
-rw-r--r--components/script/dom/document.rs7
-rw-r--r--components/script/dom/domexception.rs2
-rw-r--r--components/script/dom/domimplementation.rs4
-rw-r--r--components/script/dom/domparser.rs2
-rw-r--r--components/script/dom/dompoint.rs2
-rw-r--r--components/script/dom/dompointreadonly.rs2
-rw-r--r--components/script/dom/domrect.rs2
-rw-r--r--components/script/dom/domrectlist.rs2
-rw-r--r--components/script/dom/domrectreadonly.rs2
-rw-r--r--components/script/dom/domstringmap.rs2
-rw-r--r--components/script/dom/domtokenlist.rs2
-rw-r--r--components/script/dom/element.rs4
-rw-r--r--components/script/dom/errorevent.rs2
-rw-r--r--components/script/dom/event.rs2
-rw-r--r--components/script/dom/eventtarget.rs3
-rw-r--r--components/script/dom/file.rs2
-rw-r--r--components/script/dom/filelist.rs2
-rw-r--r--components/script/dom/filereader.rs3
-rw-r--r--components/script/dom/formdata.rs2
-rw-r--r--components/script/dom/htmlareaelement.rs2
-rw-r--r--components/script/dom/htmlbodyelement.rs2
-rw-r--r--components/script/dom/htmlcanvaselement.rs2
-rw-r--r--components/script/dom/htmlcanvaselement.rs.BACKUP.20128.rs355
-rw-r--r--components/script/dom/htmlcanvaselement.rs.BACKUP.20237.rs355
-rw-r--r--components/script/dom/htmlcanvaselement.rs.BASE.20128.rs307
-rw-r--r--components/script/dom/htmlcanvaselement.rs.BASE.20237.rs307
-rw-r--r--components/script/dom/htmlcanvaselement.rs.LOCAL.20128.rs351
-rw-r--r--components/script/dom/htmlcanvaselement.rs.LOCAL.20237.rs351
-rw-r--r--components/script/dom/htmlcanvaselement.rs.REMOTE.20128.rs307
-rw-r--r--components/script/dom/htmlcanvaselement.rs.REMOTE.20237.rs307
-rw-r--r--components/script/dom/htmlcanvaselement.rs.orig355
-rw-r--r--components/script/dom/htmlcollection.rs3
-rw-r--r--components/script/dom/htmlelement.rs2
-rw-r--r--components/script/dom/htmlformelement.rs4
-rw-r--r--components/script/dom/htmliframeelement.rs2
-rw-r--r--components/script/dom/imagedata.rs2
-rw-r--r--components/script/dom/keyboardevent.rs3
-rw-r--r--components/script/dom/location.rs2
-rw-r--r--components/script/dom/messageevent.rs2
-rw-r--r--components/script/dom/mouseevent.rs2
-rw-r--r--components/script/dom/namednodemap.rs3
-rw-r--r--components/script/dom/navigator.rs2
-rw-r--r--components/script/dom/node.rs3
-rw-r--r--components/script/dom/nodeiterator.rs2
-rw-r--r--components/script/dom/nodelist.rs2
-rw-r--r--components/script/dom/performance.rs2
-rw-r--r--components/script/dom/performancetiming.rs2
-rw-r--r--components/script/dom/progressevent.rs2
-rw-r--r--components/script/dom/range.rs2
-rw-r--r--components/script/dom/screen.rs2
-rw-r--r--components/script/dom/servohtmlparser.rs2
-rw-r--r--components/script/dom/storage.rs2
-rw-r--r--components/script/dom/storageevent.rs2
-rw-r--r--components/script/dom/testbinding.rs2
-rw-r--r--components/script/dom/testbindingproxy.rs2
-rw-r--r--components/script/dom/textdecoder.rs2
-rw-r--r--components/script/dom/textencoder.rs2
-rw-r--r--components/script/dom/touch.rs2
-rw-r--r--components/script/dom/touchevent.rs2
-rw-r--r--components/script/dom/touchlist.rs2
-rw-r--r--components/script/dom/treewalker.rs2
-rw-r--r--components/script/dom/uievent.rs2
-rw-r--r--components/script/dom/url.rs2
-rw-r--r--components/script/dom/urlsearchparams.rs2
-rw-r--r--components/script/dom/validitystate.rs2
-rw-r--r--components/script/dom/webglactiveinfo.rs2
-rw-r--r--components/script/dom/webglbuffer.rs2
-rw-r--r--components/script/dom/webglcontextevent.rs2
-rw-r--r--components/script/dom/webglframebuffer.rs2
-rw-r--r--components/script/dom/webglobject.rs2
-rw-r--r--components/script/dom/webglprogram.rs2
-rw-r--r--components/script/dom/webglrenderbuffer.rs2
-rw-r--r--components/script/dom/webglrenderingcontext.rs4
-rw-r--r--components/script/dom/webglshader.rs2
-rw-r--r--components/script/dom/webglshaderprecisionformat.rs2
-rw-r--r--components/script/dom/webgltexture.rs2
-rw-r--r--components/script/dom/webgluniformlocation.rs2
-rw-r--r--components/script/dom/websocket.rs3
-rw-r--r--components/script/dom/window.rs3
-rw-r--r--components/script/dom/worker.rs3
-rw-r--r--components/script/dom/workerglobalscope.rs2
-rw-r--r--components/script/dom/workerlocation.rs2
-rw-r--r--components/script/dom/workernavigator.rs2
-rw-r--r--components/script/dom/xmlhttprequest.rs3
-rw-r--r--components/script/dom/xmlhttprequestupload.rs2
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]