diff options
Diffstat (limited to 'components/script')
72 files changed, 1084 insertions, 470 deletions
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml index ffde81f1a91..fb90edec267 100644 --- a/components/script/Cargo.toml +++ b/components/script/Cargo.toml @@ -46,11 +46,8 @@ path = "../canvas_traits" [dependencies.js] git = "https://github.com/servo/rust-mozjs" -[dependencies.offscreen_gl_context] -git = "https://github.com/ecoal95/rust-offscreen-rendering-context" - [dependencies.angle] -git = "https://github.com/ecoal95/angle" +git = "https://github.com/emilio/angle" branch = "servo" [dependencies.ipc-channel] @@ -63,6 +60,9 @@ features = ["unstable"] [dependencies.gfx_traits] path = "../gfx_traits" +[dependencies.webrender_traits] +git = "https://github.com/servo/webrender_traits" + [dependencies] app_units = {version = "0.2.3", features = ["plugins"]} bitflags = "0.3" @@ -79,9 +79,11 @@ image = "0.7" libc = "0.2" log = "0.3.5" num = "0.1.24" +offscreen_gl_context = "0.1.2" rand = "0.3" phf = "0.7.13" phf_macros = "0.7.13" +range = { path = "../range" } ref_filter_map = "1.0" ref_slice = "0.1.0" regex = "0.1.43" @@ -94,4 +96,4 @@ time = "0.1.12" unicase = "1.0" url = {version = "0.5.7", features = ["heap_size"]} uuid = "0.1.16" -websocket = "0.15.2" +websocket = "0.16.1" diff --git a/components/script/cors.rs b/components/script/cors.rs index b5ad670a38c..8be1ec9d6d2 100644 --- a/components/script/cors.rs +++ b/components/script/cors.rs @@ -394,9 +394,8 @@ impl CORSCache { header_name: &str) -> Option<&'a mut CORSCacheEntry> { self.cleanup(); - let CORSCache(ref mut buf) = *self; // Credentials are not yet implemented here - buf.iter_mut().find(|e| { + self.0.iter_mut().find(|e| { e.origin.scheme == request.origin.scheme && e.origin.host() == request.origin.host() && e.origin.port() == request.origin.port() && e.url == request.destination && e.header_or_method.match_header(header_name) @@ -421,9 +420,8 @@ impl CORSCache { -> Option<&'a mut CORSCacheEntry> { // we can take the method from CORSRequest itself self.cleanup(); - let CORSCache(ref mut buf) = *self; // Credentials are not yet implemented here - buf.iter_mut().find(|e| { + self.0.iter_mut().find(|e| { e.origin.scheme == request.origin.scheme && e.origin.host() == request.origin.host() && e.origin.port() == request.origin.port() && e.url == request.destination && e.header_or_method.match_method(method) @@ -445,8 +443,7 @@ impl CORSCache { fn insert(&mut self, entry: CORSCacheEntry) { self.cleanup(); - let CORSCache(ref mut buf) = *self; - buf.push(entry); + self.0.push(entry); } } diff --git a/components/script/devtools.rs b/components/script/devtools.rs index f0ec814cdc2..a1f5f21573c 100644 --- a/components/script/devtools.rs +++ b/components/script/devtools.rs @@ -167,7 +167,7 @@ pub fn handle_get_cached_messages(_pipeline_id: PipelineId, // TODO: make script error reporter pass all reported errors // to devtools and cache them for returning here. let msg = PageError { - _type: "PageError".to_owned(), + type_: "PageError".to_owned(), errorMessage: "page error test".to_owned(), sourceName: String::new(), lineText: String::new(), @@ -186,7 +186,7 @@ pub fn handle_get_cached_messages(_pipeline_id: PipelineId, if message_types.contains(CONSOLE_API) { // TODO: do for real let msg = ConsoleAPI { - _type: "ConsoleAPI".to_owned(), + type_: "ConsoleAPI".to_owned(), level: "error".to_owned(), filename: "http://localhost/~mihai/mozilla/test.html".to_owned(), lineNumber: 0, diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 4468bb13b6b..51c29764125 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1893,15 +1893,16 @@ class CGInterfaceObjectJSClass(CGThing): constructor = CONSTRUCT_HOOK_NAME else: constructor = "throwing_constructor" + name = self.descriptor.interface.identifier.name args = { "constructor": constructor, - "name": self.descriptor.interface.identifier.name, - "id": self.descriptor.interface.identifier.name, + "id": name, + "representation": str_to_const_array("function %s() {\\n [native code]\\n}" % name), "depth": self.descriptor.prototypeDepth } return """\ static InterfaceObjectClass: NonCallbackInterfaceObjectClass = - NonCallbackInterfaceObjectClass::new(%(constructor)s, fun_to_string, + NonCallbackInterfaceObjectClass::new(%(constructor)s, %(representation)s, PrototypeList::ID::%(id)s, %(depth)s); """ % args @@ -4824,21 +4825,6 @@ let args = CallArgs::from_vp(vp, argc); return CGList([preamble, callGenerator]) -class CGClassFunToStringHook(CGAbstractExternMethod): - """ - A hook to convert functions to strings. - """ - def __init__(self, descriptor): - args = [Argument('*mut JSContext', 'cx'), Argument('HandleObject', '_obj'), - Argument('u32', '_indent')] - CGAbstractExternMethod.__init__(self, descriptor, "fun_to_string", '*mut JSString', args) - - def definition_body(self): - name = self.descriptor.interface.identifier.name - string = str_to_const_array("function %s() {\\n [native code]\\n}" % name) - return CGGeneric("JS_NewStringCopyZ(cx, %s as *const _ as *const libc::c_char)" % string) - - class CGClassFinalizeHook(CGAbstractClassHook): """ A hook for finalize, used to release our native object. @@ -5007,7 +4993,6 @@ class CGDescriptor(CGThing): cgThings.append(CGClassConstructHook(descriptor, ctor)) if not descriptor.interface.isCallback(): cgThings.append(CGInterfaceObjectJSClass(descriptor)) - cgThings.append(CGClassFunToStringHook(descriptor)) if not descriptor.interface.isCallback(): cgThings.append(CGPrototypeJSClass(descriptor)) @@ -5201,6 +5186,14 @@ class CGDictionary(CGThing): " }\n" "}\n" "\n" + "impl FromJSValConvertible for ${selfName} {\n" + " type Config = ();\n" + " unsafe fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ())\n" + " -> Result<${selfName}, ()> {\n" + " ${selfName}::new(cx, value)\n" + " }\n" + "}\n" + "\n" "impl ToJSValConvertible for ${selfName} {\n" " unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {\n" " let obj = RootedObject::new(cx, JS_NewObject(cx, ptr::null()));\n" @@ -5349,8 +5342,8 @@ class CGBindingRoot(CGThing): # Do codegen for all the typdefs for t in typedefs: if t.innerType.isUnion(): - cgthings.extend([CGGeneric("\npub type %s = %s;\n\n" % (t.identifier.name, - "UnionTypes::" + str(t.innerType)))]) + cgthings.extend([CGGeneric("\npub use dom::bindings::codegen::UnionTypes::%s as %s;\n\n" % + (t.innerType, t.identifier.name))]) else: assert not typeNeedsRooting(t.innerType, config.getDescriptorProvider) cgthings.extend([CGGeneric("\npub type %s = " % (t.identifier.name)), diff --git a/components/script/dom/bindings/interface.rs b/components/script/dom/bindings/interface.rs index a5bc3ec513c..7db3c6e17c4 100644 --- a/components/script/dom/bindings/interface.rs +++ b/components/script/dom/bindings/interface.rs @@ -13,8 +13,9 @@ use js::jsapi::{HandleObject, HandleValue, JSClass, JSContext, JSFunctionSpec}; use js::jsapi::{JSPropertySpec, JSString, JS_DefineProperty1, JS_DefineProperty2}; use js::jsapi::{JS_DefineProperty4, JS_GetClass, JS_GetFunctionObject, JS_GetPrototype}; use js::jsapi::{JS_InternString, JS_LinkConstructorAndPrototype, JS_NewFunction, JS_NewObject}; -use js::jsapi::{JS_NewObjectWithUniqueType, JS_DefineProperty, MutableHandleObject}; -use js::jsapi::{MutableHandleValue, ObjectOps, RootedObject, RootedString, RootedValue, Value}; +use js::jsapi::{JS_NewObjectWithUniqueType, JS_NewStringCopyZ, JS_DefineProperty}; +use js::jsapi::{MutableHandleObject, MutableHandleValue, ObjectOps, RootedObject, RootedString}; +use js::jsapi::{RootedValue, Value}; use js::jsval::{BooleanValue, DoubleValue, Int32Value, JSVal, NullValue, UInt32Value}; use js::rust::{define_methods, define_properties}; use js::{JSPROP_ENUMERATE, JSFUN_CONSTRUCTOR, JSPROP_PERMANENT, JSPROP_READONLY}; @@ -79,17 +80,23 @@ pub fn define_constants(cx: *mut JSContext, obj: HandleObject, constants: &'stat } } +unsafe extern "C" fn fun_to_string_hook(cx: *mut JSContext, + obj: HandleObject, + _indent: u32) + -> *mut JSString { + let js_class = JS_GetClass(obj.get()); + assert!(!js_class.is_null()); + let object_class = &*(js_class as *const NonCallbackInterfaceObjectClass); + assert!(object_class.representation.last() == Some(&0)); + let ret = JS_NewStringCopyZ(cx, object_class.representation.as_ptr() as *const libc::c_char); + assert!(!ret.is_null()); + ret +} + /// A constructor class hook. pub type ConstructorClassHook = unsafe extern "C" fn(cx: *mut JSContext, argc: u32, vp: *mut Value) -> bool; -/// A fun_to_string class hook. -pub type FunToStringHook = - unsafe extern "C" fn(cx: *mut JSContext, - obj: HandleObject, - indent: u32) - -> *mut JSString; - /// The class of a non-callback interface object. #[derive(Copy, Clone)] pub struct NonCallbackInterfaceObjectClass { @@ -99,6 +106,8 @@ pub struct NonCallbackInterfaceObjectClass { pub proto_id: PrototypeList::ID, /// The prototype depth of that interface, used in the hasInstance hook. pub proto_depth: u16, + /// The string representation of the object (ends with '\0'). + pub representation: &'static [u8], } unsafe impl Sync for NonCallbackInterfaceObjectClass {} @@ -107,7 +116,7 @@ impl NonCallbackInterfaceObjectClass { /// Create a new `NonCallbackInterfaceObjectClass` structure. pub const fn new( constructor: ConstructorClassHook, - fun_to_string: FunToStringHook, + string_rep: &'static [u8], proto_id: PrototypeList::ID, proto_depth: u16) -> NonCallbackInterfaceObjectClass { @@ -157,11 +166,12 @@ impl NonCallbackInterfaceObjectClass { getElements: None, enumerate: None, thisObject: None, - funToString: Some(fun_to_string), + funToString: Some(fun_to_string_hook), } }, proto_id: proto_id, proto_depth: proto_depth, + representation: string_rep, } } diff --git a/components/script/dom/bindings/proxyhandler.rs b/components/script/dom/bindings/proxyhandler.rs index 3d5a841edb3..31b5f3db2d0 100644 --- a/components/script/dom/bindings/proxyhandler.rs +++ b/components/script/dom/bindings/proxyhandler.rs @@ -57,9 +57,10 @@ pub unsafe extern "C" fn define_property(cx: *mut JSContext, desc: Handle<JSPropertyDescriptor>, result: *mut ObjectOpResult) -> bool { - // FIXME: Workaround for https://github.com/mozilla/rust/issues/13385 + // FIXME: Workaround for https://github.com/rust-lang/rfcs/issues/718 let setter: *const libc::c_void = mem::transmute(desc.get().setter); - let setter_stub: *const libc::c_void = mem::transmute(JS_StrictPropertyStub); + let setter_stub: unsafe extern fn(_, _, _, _, _) -> _ = JS_StrictPropertyStub; + let setter_stub: *const libc::c_void = mem::transmute(setter_stub); if (desc.get().attrs & JSPROP_GETTER) != 0 && setter == setter_stub { (*result).code_ = JSErrNum::JSMSG_GETTER_ONLY as ::libc::uintptr_t; return true; diff --git a/components/script/dom/bindings/str.rs b/components/script/dom/bindings/str.rs index 6276c2c19bd..f1de6297ceb 100644 --- a/components/script/dom/bindings/str.rs +++ b/components/script/dom/bindings/str.rs @@ -58,8 +58,7 @@ impl Into<Vec<u8>> for ByteString { impl Hash for ByteString { fn hash<H: Hasher>(&self, state: &mut H) { - let ByteString(ref vec) = *self; - vec.hash(state); + self.0.hash(state); } } diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 7bfb6978ee6..2491058750c 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -29,7 +29,6 @@ //! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to //! a datatype. -use canvas_traits::WebGLError; use canvas_traits::{CanvasGradientStop, LinearGradientStyle, RadialGradientStyle}; use canvas_traits::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle}; use cssparser::RGBA; @@ -91,7 +90,7 @@ use style::values::specified::Length; use url::Url; use util::str::{DOMString, LengthOrPercentageOrAuto}; use uuid::Uuid; - +use webrender_traits::WebGLError; /// A trait to allow tracing (only) DOM objects. pub trait JSTraceable { diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs index dc24cbb01fc..9c23b8f6da0 100644 --- a/components/script/dom/blob.rs +++ b/components/script/dom/blob.rs @@ -4,11 +4,14 @@ use dom::bindings::codegen::Bindings::BlobBinding; use dom::bindings::codegen::Bindings::BlobBinding::BlobMethods; +use dom::bindings::codegen::UnionTypes::BlobOrString; use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; use dom::bindings::reflector::{Reflectable, Reflector, reflect_dom_object}; use dom::bindings::trace::JSTraceable; +use encoding::all::UTF_8; +use encoding::types::{EncoderTrap, Encoding}; use num::ToPrimitive; use std::ascii::AsciiExt; use std::borrow::ToOwned; @@ -120,16 +123,29 @@ impl Blob { // https://w3c.github.io/FileAPI/#constructorBlob pub fn Constructor_(global: GlobalRef, - blobParts: DOMString, + blobParts: Vec<BlobOrString>, blobPropertyBag: &BlobBinding::BlobPropertyBag) -> Fallible<Root<Blob>> { - // TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView or Blob + + // TODO: accept other blobParts types - ArrayBuffer or ArrayBufferView + let bytes: Vec<u8> = blobParts.iter() + .flat_map(|bPart| { + match bPart { + &BlobOrString::String(ref s) => { + UTF_8.encode(s, EncoderTrap::Replace).unwrap() + }, + &BlobOrString::Blob(ref b) => { + b.get_data().get_bytes().to_vec() + }, + } + }) + .collect(); let typeString = if is_ascii_printable(&blobPropertyBag.type_) { &*blobPropertyBag.type_ } else { "" }; - Ok(Blob::new(global, blobParts.into(), &typeString.to_ascii_lowercase())) + Ok(Blob::new(global, bytes, &typeString.to_ascii_lowercase())) } pub fn get_data(&self) -> &DataSlice { diff --git a/components/script/dom/canvasrenderingcontext2d.rs b/components/script/dom/canvasrenderingcontext2d.rs index 97574187038..aa5c7d9f72b 100644 --- a/components/script/dom/canvasrenderingcontext2d.rs +++ b/components/script/dom/canvasrenderingcontext2d.rs @@ -62,7 +62,6 @@ enum CanvasFillOrStrokeStyle { #[dom_struct] pub struct CanvasRenderingContext2D { reflector_: Reflector, - renderer_id: usize, #[ignore_heap_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender<CanvasMsg>, canvas: JS<HTMLCanvasElement>, @@ -125,10 +124,9 @@ impl CanvasRenderingContext2D { let (sender, receiver) = ipc::channel().unwrap(); let constellation_chan = global.constellation_chan(); constellation_chan.0.send(ConstellationMsg::CreateCanvasPaintThread(size, sender)).unwrap(); - let (ipc_renderer, renderer_id) = receiver.recv().unwrap(); + let ipc_renderer = receiver.recv().unwrap(); CanvasRenderingContext2D { reflector_: Reflector::new(), - renderer_id: renderer_id, ipc_renderer: ipc_renderer, canvas: JS::from_ref(canvas), state: DOMRefCell::new(CanvasContextState::new()), @@ -501,9 +499,6 @@ impl CanvasRenderingContext2D { } } - pub fn get_renderer_id(&self) -> usize { - self.renderer_id - } pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> { self.ipc_renderer.clone() } @@ -519,17 +514,11 @@ impl CanvasRenderingContext2D { pub trait LayoutCanvasRenderingContext2DHelpers { #[allow(unsafe_code)] - unsafe fn get_renderer_id(&self) -> usize; - #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg>; } impl LayoutCanvasRenderingContext2DHelpers for LayoutJS<CanvasRenderingContext2D> { #[allow(unsafe_code)] - unsafe fn get_renderer_id(&self) -> usize { - (*self.unsafe_get()).renderer_id - } - #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> { (*self.unsafe_get()).ipc_renderer.clone() } diff --git a/components/script/dom/closeevent.rs b/components/script/dom/closeevent.rs index edf0c6199df..b7181baa2ea 100644 --- a/components/script/dom/closeevent.rs +++ b/components/script/dom/closeevent.rs @@ -46,8 +46,8 @@ impl CloseEvent { { let event = ev.upcast::<Event>(); event.init_event(type_, - bubbles == EventBubbles::Bubbles, - cancelable == EventCancelable::Cancelable); + bool::from(bubbles), + bool::from(cancelable)); } ev } @@ -56,16 +56,8 @@ impl CloseEvent { type_: DOMString, init: &CloseEventBinding::CloseEventInit) -> Fallible<Root<CloseEvent>> { - let bubbles = if init.parent.bubbles { - EventBubbles::Bubbles - } else { - EventBubbles::DoesNotBubble - }; - let cancelable = if init.parent.cancelable { - EventCancelable::Cancelable - } else { - EventCancelable::NotCancelable - }; + let bubbles = EventBubbles::from(init.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.cancelable); Ok(CloseEvent::new(global, Atom::from(type_), bubbles, diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs index c63b657cd19..e560f788278 100644 --- a/components/script/dom/dedicatedworkerglobalscope.rs +++ b/components/script/dom/dedicatedworkerglobalscope.rs @@ -32,7 +32,6 @@ use script_thread::ScriptThreadEventCategory::WorkerEvent; use script_thread::{ScriptThread, ScriptChan, ScriptPort, StackRootTLS, CommonScriptMsg}; use script_traits::{TimerEvent, TimerSource}; use std::mem::replace; -use std::rc::Rc; use std::sync::mpsc::{Receiver, RecvError, Select, Sender, channel}; use url::Url; use util::str::DOMString; @@ -158,7 +157,7 @@ impl DedicatedWorkerGlobalScope { worker_url: Url, id: PipelineId, from_devtools_receiver: Receiver<DevtoolScriptControlMsg>, - runtime: Rc<Runtime>, + runtime: Runtime, parent_sender: Box<ScriptChan + Send>, own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>, receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>, @@ -185,24 +184,25 @@ impl DedicatedWorkerGlobalScope { worker_url: Url, id: PipelineId, from_devtools_receiver: Receiver<DevtoolScriptControlMsg>, - runtime: Rc<Runtime>, + runtime: Runtime, parent_sender: Box<ScriptChan + Send>, own_sender: Sender<(TrustedWorkerAddress, WorkerScriptMsg)>, receiver: Receiver<(TrustedWorkerAddress, WorkerScriptMsg)>, timer_event_chan: IpcSender<TimerEvent>, timer_event_port: Receiver<(TrustedWorkerAddress, TimerEvent)>) -> Root<DedicatedWorkerGlobalScope> { + let cx = runtime.cx(); let scope = box DedicatedWorkerGlobalScope::new_inherited(init, worker_url, id, from_devtools_receiver, - runtime.clone(), + runtime, parent_sender, own_sender, receiver, timer_event_chan, timer_event_port); - DedicatedWorkerGlobalScopeBinding::Wrap(runtime.cx(), scope) + DedicatedWorkerGlobalScopeBinding::Wrap(cx, scope) } pub fn run_worker_scope(init: WorkerGlobalScopeInit, @@ -235,7 +235,7 @@ impl DedicatedWorkerGlobalScope { } }; - let runtime = Rc::new(ScriptThread::new_rt_and_cx()); + let runtime = ScriptThread::new_rt_and_cx(); let (devtools_mpsc_chan, devtools_mpsc_port) = channel(); ROUTER.route_ipc_receiver_to_mpsc_sender(from_devtools_receiver, devtools_mpsc_chan); @@ -249,7 +249,7 @@ impl DedicatedWorkerGlobalScope { }); let global = DedicatedWorkerGlobalScope::new( - init, url, id, devtools_mpsc_port, runtime.clone(), + init, url, id, devtools_mpsc_port, runtime, parent_sender.clone(), own_sender, receiver, timer_ipc_chan, timer_rx); // FIXME(njn): workers currently don't have a unique ID suitable for using in reporter diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 0a148f0cb69..a24580d0f95 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -77,6 +77,8 @@ use dom::touchlist::TouchList; use dom::treewalker::TreeWalker; use dom::uievent::UIEvent; use dom::window::{ReflowReason, Window}; +use encoding::EncodingRef; +use encoding::all::UTF_8; use euclid::point::Point2D; use html5ever::tree_builder::{LimitedQuirks, NoQuirks, Quirks, QuirksMode}; use ipc_channel::ipc::{self, IpcSender}; @@ -139,7 +141,7 @@ pub struct Document { location: MutNullableHeap<JS<Location>>, content_type: DOMString, last_modified: Option<String>, - encoding_name: DOMRefCell<DOMString>, + encoding: Cell<EncodingRef>, is_html_document: bool, url: Url, quirks_mode: Cell<QuirksMode>, @@ -156,7 +158,7 @@ pub struct Document { anchors: MutNullableHeap<JS<HTMLCollection>>, applets: MutNullableHeap<JS<HTMLCollection>>, /// List of stylesheets associated with nodes in this document. |None| if the list needs to be refreshed. - stylesheets: DOMRefCell<Option<Vec<Arc<Stylesheet>>>>, + stylesheets: DOMRefCell<Option<Vec<(JS<Node>, Arc<Stylesheet>)>>>, /// Whether the list of stylesheets has changed since the last reflow was triggered. stylesheets_changed_since_reflow: Cell<bool>, ready_state: Cell<DocumentReadyState>, @@ -297,11 +299,6 @@ impl Document { } #[inline] - pub fn encoding_name(&self) -> Ref<DOMString> { - self.encoding_name.borrow() - } - - #[inline] pub fn is_html_document(&self) -> bool { self.is_html_document } @@ -394,36 +391,12 @@ impl Document { } } - pub fn set_encoding_name(&self, name: DOMString) { - *self.encoding_name.borrow_mut() = DOMString::from( - match name.as_ref() { - "utf-8" => "UTF-8", - "ibm866" => "IBM866", - "iso-8859-2" => "ISO-8859-2", - "iso-8859-3" => "ISO-8859-3", - "iso-8859-4" => "ISO-8859-4", - "iso-8859-5" => "ISO-8859-5", - "iso-8859-6" => "ISO-8859-6", - "iso-8859-7" => "ISO-8859-7", - "iso-8859-8" => "ISO-8859-8", - "iso-8859-8-i" => "ISO-8859-8-I", - "iso-8859-10" => "ISO-8859-10", - "iso-8859-13" => "ISO-8859-13", - "iso-8859-14" => "ISO-8859-14", - "iso-8859-15" => "ISO-8859-15", - "iso-8859-16" => "ISO-8859-16", - "koi8-r" => "KOI8-R", - "koi8-u" => "KOI8-U", - "gbk" => "GBK", - "big5" => "Big5", - "euc-jp" => "EUC-JP", - "iso-2022-jp" => "ISO-2022-JP", - "shift_jis" => "Shift_JIS", - "euc-kr" => "EUC-KR", - "utf-16be" => "UTF-16BE", - "utf-16le" => "UTF-16LE", - _ => &*name - }); + pub fn encoding(&self) -> EncodingRef { + self.encoding.get() + } + + pub fn set_encoding(&self, encoding: EncodingRef) { + self.encoding.set(encoding); } pub fn content_changed(&self, node: &Node, damage: NodeDamage) { @@ -1562,7 +1535,7 @@ impl Document { // https://dom.spec.whatwg.org/#concept-document-quirks quirks_mode: Cell::new(NoQuirks), // https://dom.spec.whatwg.org/#concept-document-encoding - encoding_name: DOMRefCell::new(DOMString::from("UTF-8")), + encoding: Cell::new(UTF_8), is_html_document: is_html_document == IsHTMLDocument::HTMLDocument, id_map: DOMRefCell::new(HashMap::new()), tag_map: DOMRefCell::new(HashMap::new()), @@ -1663,11 +1636,11 @@ impl Document { } /// Returns the list of stylesheets associated with nodes in the document. - pub fn stylesheets(&self) -> Ref<Vec<Arc<Stylesheet>>> { + pub fn stylesheets(&self) -> Vec<Arc<Stylesheet>> { { let mut stylesheets = self.stylesheets.borrow_mut(); if stylesheets.is_none() { - let new_stylesheets: Vec<Arc<Stylesheet>> = self.upcast::<Node>() + *stylesheets = Some(self.upcast::<Node>() .traverse_preorder() .filter_map(|node| { if let Some(node) = node.downcast::<HTMLStyleElement>() { @@ -1678,13 +1651,14 @@ impl Document { node.get_stylesheet() } else { None - } + }.map(|stylesheet| (JS::from_rooted(&node), stylesheet)) }) - .collect(); - *stylesheets = Some(new_stylesheets); + .collect()); }; } - Ref::map(self.stylesheets.borrow(), |t| t.as_ref().unwrap()) + self.stylesheets.borrow().as_ref().unwrap().iter() + .map(|&(_, ref stylesheet)| stylesheet.clone()) + .collect() } /// https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document @@ -1800,12 +1774,6 @@ impl DocumentMethods for Document { fn Domain(&self) -> DOMString { // TODO: This should use the effective script origin when it exists let origin = self.window.get_url(); - - if let Some(&Host::Ipv6(ipv6)) = origin.host() { - // Omit square brackets for IPv6 addresses. - return DOMString::from(ipv6.to_string()); - } - DOMString::from(origin.serialize_host().unwrap_or_else(|| "".to_owned())) } @@ -1824,7 +1792,34 @@ impl DocumentMethods for Document { // https://dom.spec.whatwg.org/#dom-document-characterset fn CharacterSet(&self) -> DOMString { - self.encoding_name.borrow().clone() + DOMString::from(match self.encoding.get().name() { + "utf-8" => "UTF-8", + "ibm866" => "IBM866", + "iso-8859-2" => "ISO-8859-2", + "iso-8859-3" => "ISO-8859-3", + "iso-8859-4" => "ISO-8859-4", + "iso-8859-5" => "ISO-8859-5", + "iso-8859-6" => "ISO-8859-6", + "iso-8859-7" => "ISO-8859-7", + "iso-8859-8" => "ISO-8859-8", + "iso-8859-8-i" => "ISO-8859-8-I", + "iso-8859-10" => "ISO-8859-10", + "iso-8859-13" => "ISO-8859-13", + "iso-8859-14" => "ISO-8859-14", + "iso-8859-15" => "ISO-8859-15", + "iso-8859-16" => "ISO-8859-16", + "koi8-r" => "KOI8-R", + "koi8-u" => "KOI8-U", + "gbk" => "GBK", + "big5" => "Big5", + "euc-jp" => "EUC-JP", + "iso-2022-jp" => "ISO-2022-JP", + "shift_jis" => "Shift_JIS", + "euc-kr" => "EUC-KR", + "utf-16be" => "UTF-16BE", + "utf-16le" => "UTF-16LE", + name => name + }) } // https://dom.spec.whatwg.org/#dom-document-charset diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index f74887d0899..3968b2084cb 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -139,6 +139,32 @@ impl DOMTokenListMethods for DOMTokenList { self.element.set_tokenlist_attribute(&self.local_name, value); } + // https://dom.spec.whatwg.org/#dom-domtokenlist-replace + fn Replace(&self, token: DOMString, new_token: DOMString) -> ErrorResult { + if token.is_empty() || new_token.is_empty() { + // Step 1. + return Err(Error::Syntax); + } + if token.contains(HTML_SPACE_CHARACTERS) || new_token.contains(HTML_SPACE_CHARACTERS) { + // Step 2. + return Err(Error::InvalidCharacter); + } + // Steps 3-4. + let token = Atom::from(token); + let new_token = Atom::from(new_token); + let mut atoms = self.element.get_tokenlist_attribute(&self.local_name); + if let Some(pos) = atoms.iter().position(|atom| *atom == token) { + if !atoms.contains(&new_token) { + atoms[pos] = new_token; + } else { + atoms.remove(pos); + } + } + // Step 5. + self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms); + Ok(()) + } + // https://dom.spec.whatwg.org/#concept-dtl-serialize fn Stringifier(&self) -> DOMString { self.element.get_string_attribute(&self.local_name) diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 25d9f0d45b8..677f9acda0e 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -47,7 +47,9 @@ use dom::htmlimageelement::{HTMLImageElement, LayoutHTMLImageElementHelpers}; use dom::htmlinputelement::{HTMLInputElement, LayoutHTMLInputElementHelpers}; use dom::htmllabelelement::HTMLLabelElement; use dom::htmllegendelement::HTMLLegendElement; +use dom::htmlobjectelement::HTMLObjectElement; use dom::htmloptgroupelement::HTMLOptGroupElement; +use dom::htmlselectelement::HTMLSelectElement; use dom::htmltablecellelement::{HTMLTableCellElement, HTMLTableCellElementLayoutHelpers}; use dom::htmltableelement::{HTMLTableElement, HTMLTableElementLayoutHelpers}; use dom::htmltablerowelement::{HTMLTableRowElement, HTMLTableRowElementLayoutHelpers}; @@ -60,6 +62,7 @@ use dom::node::{NodeDamage, SEQUENTIALLY_FOCUSABLE, UnbindContext}; use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; use dom::text::Text; +use dom::validation::Validatable; use dom::virtualmethods::{VirtualMethods, vtable_for}; use html5ever::serialize; use html5ever::serialize::SerializeOpts; @@ -1075,7 +1078,7 @@ impl Element { } let url = self.get_string_attribute(local_name); let doc = document_from_node(self); - let base = doc.url(); + let base = doc.base_url(); // https://html.spec.whatwg.org/multipage/#reflect // XXXManishearth this doesn't handle `javascript:` urls properly match base.join(&url) { @@ -1165,6 +1168,35 @@ impl Element { let node = self.upcast::<Node>(); node.owner_doc().element_attr_will_change(self); } + + // https://dom.spec.whatwg.org/#insert-adjacent + pub fn insert_adjacent(&self, where_: DOMString, node: &Node) + -> Fallible<Option<Root<Node>>> { + let self_node = self.upcast::<Node>(); + match &*where_ { + "beforebegin" => { + if let Some(parent) = self_node.GetParentNode() { + Node::pre_insert(node, &parent, Some(self_node)).map(Some) + } else { + Ok(None) + } + } + "afterbegin" => { + Node::pre_insert(node, &self_node, self_node.GetFirstChild().r()).map(Some) + } + "beforeend" => { + Node::pre_insert(node, &self_node, None).map(Some) + } + "afterend" => { + if let Some(parent) = self_node.GetParentNode() { + Node::pre_insert(node, &parent, self_node.GetNextSibling().r()).map(Some) + } else { + Ok(None) + } + } + _ => Err(Error::Syntax) + } + } } impl ElementMethods for Element { @@ -1617,6 +1649,23 @@ impl ElementMethods for Element { } } } + + // https://dom.spec.whatwg.org/#dom-element-insertadjacentelement + fn InsertAdjacentElement(&self, where_: DOMString, element: &Element) + -> Fallible<Option<Root<Element>>> { + let inserted_node = try!(self.insert_adjacent(where_, element.upcast())); + Ok(inserted_node.map(|node| Root::downcast(node).unwrap())) + } + + // https://dom.spec.whatwg.org/#dom-element-insertadjacenttext + fn InsertAdjacentText(&self, where_: DOMString, data: DOMString) + -> ErrorResult { + // Step 1. + let text = Text::new(data, &document_from_node(self)); + + // Step 2. + self.insert_adjacent(where_, text.upcast()).map(|_| ()) + } } pub fn fragment_affecting_attributes() -> [Atom; 3] { @@ -1913,6 +1962,36 @@ impl Element { }) } + // https://html.spec.whatwg.org/multipage/#category-submit + pub fn as_maybe_validatable(&self) -> Option<&Validatable> { + let element = match self.upcast::<Node>().type_id() { + NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) => { + let element = self.downcast::<HTMLInputElement>().unwrap(); + Some(element as &Validatable) + }, + NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) => { + let element = self.downcast::<HTMLButtonElement>().unwrap(); + Some(element as &Validatable) + }, + NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLObjectElement)) => { + let element = self.downcast::<HTMLObjectElement>().unwrap(); + Some(element as &Validatable) + }, + NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) => { + let element = self.downcast::<HTMLSelectElement>().unwrap(); + Some(element as &Validatable) + }, + NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) => { + let element = self.downcast::<HTMLTextAreaElement>().unwrap(); + Some(element as &Validatable) + }, + _ => { + None + } + }; + element + } + pub fn click_in_progress(&self) -> bool { self.upcast::<Node>().get_flag(CLICK_IN_PROGRESS) } diff --git a/components/script/dom/errorevent.rs b/components/script/dom/errorevent.rs index c9d5a79b0fd..763fa823d17 100644 --- a/components/script/dom/errorevent.rs +++ b/components/script/dom/errorevent.rs @@ -60,8 +60,8 @@ impl ErrorEvent { let ev = ErrorEvent::new_uninitialized(global); { let event = ev.upcast::<Event>(); - event.init_event(type_, bubbles == EventBubbles::Bubbles, - cancelable == EventCancelable::Cancelable); + event.init_event(type_, bool::from(bubbles), + bool::from(cancelable)); *ev.message.borrow_mut() = message; *ev.filename.borrow_mut() = filename; ev.lineno.set(lineno); @@ -88,13 +88,9 @@ impl ErrorEvent { let col_num = init.colno.unwrap_or(0); - let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble }; + let bubbles = EventBubbles::from(init.parent.bubbles); - let cancelable = if init.parent.cancelable { - EventCancelable::Cancelable - } else { - EventCancelable::NotCancelable - }; + let cancelable = EventCancelable::from(init.parent.cancelable); // Dictionaries need to be rooted // https://github.com/servo/servo/issues/6381 diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index 5aa97872647..97fc065d2b1 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -32,12 +32,48 @@ pub enum EventBubbles { DoesNotBubble } +impl From<EventBubbles> for bool { + fn from(bubbles: EventBubbles) -> Self { + match bubbles { + EventBubbles::Bubbles => true, + EventBubbles::DoesNotBubble => false + } + } +} + +impl From<bool> for EventBubbles { + fn from(boolean: bool) -> Self { + match boolean { + true => EventBubbles::Bubbles, + false => EventBubbles::DoesNotBubble + } + } +} + #[derive(PartialEq, HeapSizeOf)] pub enum EventCancelable { Cancelable, NotCancelable } +impl From<EventCancelable> for bool { + fn from(bubbles: EventCancelable) -> Self { + match bubbles { + EventCancelable::Cancelable => true, + EventCancelable::NotCancelable => false + } + } +} + +impl From<bool> for EventCancelable { + fn from(boolean: bool) -> Self { + match boolean { + true => EventCancelable::Cancelable, + false => EventCancelable::NotCancelable + } + } +} + #[dom_struct] pub struct Event { reflector_: Reflector, @@ -87,15 +123,15 @@ impl Event { bubbles: EventBubbles, cancelable: EventCancelable) -> Root<Event> { let event = Event::new_uninitialized(global); - event.init_event(type_, bubbles == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable); + event.init_event(type_, bool::from(bubbles), bool::from(cancelable)); event } pub fn Constructor(global: GlobalRef, type_: DOMString, init: &EventBinding::EventInit) -> Fallible<Root<Event>> { - let bubbles = if init.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble }; - let cancelable = if init.cancelable { EventCancelable::Cancelable } else { EventCancelable::NotCancelable }; + let bubbles = EventBubbles::from(init.bubbles); + let cancelable = EventCancelable::from(init.cancelable); Ok(Event::new(global, Atom::from(type_), bubbles, cancelable)) } diff --git a/components/script/dom/focusevent.rs b/components/script/dom/focusevent.rs index 5ad61305637..84259749295 100644 --- a/components/script/dom/focusevent.rs +++ b/components/script/dom/focusevent.rs @@ -41,8 +41,8 @@ impl FocusEvent { let event = box FocusEvent::new_inherited(); let ev = reflect_dom_object(event, GlobalRef::Window(window), FocusEventBinding::Wrap); ev.upcast::<UIEvent>().InitUIEvent(type_, - can_bubble == EventBubbles::Bubbles, - cancelable == EventCancelable::Cancelable, + bool::from(can_bubble), + bool::from(cancelable), view, detail); ev.related_target.set(related_target); ev @@ -51,16 +51,8 @@ impl FocusEvent { pub fn Constructor(global: GlobalRef, type_: DOMString, init: &FocusEventBinding::FocusEventInit) -> Fallible<Root<FocusEvent>> { - let bubbles = if init.parent.parent.bubbles { - EventBubbles::Bubbles - } else { - EventBubbles::DoesNotBubble - }; - let cancelable = if init.parent.parent.cancelable { - EventCancelable::Cancelable - } else { - EventCancelable::NotCancelable - }; + let bubbles = EventBubbles::from(init.parent.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.parent.cancelable); let event = FocusEvent::new(global.as_window(), type_, bubbles, cancelable, diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs index 0a1e15ef193..16f47315b76 100644 --- a/components/script/dom/htmlanchorelement.rs +++ b/components/script/dom/htmlanchorelement.rs @@ -5,6 +5,7 @@ use dom::activation::Activatable; use dom::attr::AttrValue; +use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding; use dom::bindings::codegen::Bindings::HTMLAnchorElementBinding::HTMLAnchorElementMethods; @@ -12,6 +13,7 @@ use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, MutNullableHeap, Root}; +use dom::bindings::str::USVString; use dom::document::Document; use dom::domtokenlist::DOMTokenList; use dom::element::Element; @@ -21,16 +23,19 @@ use dom::htmlelement::HTMLElement; use dom::htmlimageelement::HTMLImageElement; use dom::mouseevent::MouseEvent; use dom::node::{Node, document_from_node, window_from_node}; +use dom::urlhelper::UrlHelper; use dom::virtualmethods::VirtualMethods; use num::ToPrimitive; use std::default::Default; use string_cache::Atom; +use url::{Url, UrlParser}; use util::str::DOMString; #[dom_struct] pub struct HTMLAnchorElement { htmlelement: HTMLElement, rel_list: MutNullableHeap<JS<DOMTokenList>>, + url: DOMRefCell<Option<Url>>, } impl HTMLAnchorElement { @@ -41,6 +46,7 @@ impl HTMLAnchorElement { htmlelement: HTMLElement::new_inherited(localName, prefix, document), rel_list: Default::default(), + url: DOMRefCell::new(None), } } @@ -51,6 +57,37 @@ impl HTMLAnchorElement { let element = HTMLAnchorElement::new_inherited(localName, prefix, document); Node::reflect_node(box element, document, HTMLAnchorElementBinding::Wrap) } + + // https://html.spec.whatwg.org/multipage/#concept-hyperlink-url-set + fn set_url(&self) { + let attribute = self.upcast::<Element>().get_attribute(&ns!(), &atom!("href")); + *self.url.borrow_mut() = attribute.and_then(|attribute| { + let document = document_from_node(self); + let mut parser = UrlParser::new(); + parser.base_url(document.url()); + parser.parse(&attribute.value()).ok() + }); + } + + // https://html.spec.whatwg.org/multipage/#reinitialise-url + fn reinitialize_url(&self) { + // Step 1. + match *self.url.borrow() { + None => return, + Some(ref url) if url.scheme == "blob" && + url.non_relative_scheme_data().is_some() => return, + _ => (), + } + + // Step 2. + self.set_url(); + } + + // https://html.spec.whatwg.org/multipage/#update-href + fn update_href(&self) { + self.upcast::<Element>().set_string_attribute(&atom!("href"), + self.url.borrow().as_ref().unwrap().serialize().into()); + } } impl VirtualMethods for HTMLAnchorElement { @@ -107,6 +144,312 @@ impl HTMLAnchorElementMethods for HTMLAnchorElement { // https://html.spec.whatwg.org/multipage/#dom-a-shape make_setter!(SetShape, "shape"); + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-hash + fn Hash(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 3. + None => USVString(String::new()), + Some(ref url) => { + // Steps 3-4. + UrlHelper::Hash(url) + } + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-hash + fn SetHash(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + if url.scheme == "javascript" { return; } + // Steps 4-5. + UrlHelper::SetHash(url, value); + // Step 6. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-host + fn Host(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 3. + None => USVString(String::new()), + Some(ref url) => { + if url.host().is_none() { + USVString(String::new()) + } else { + // Steps 4-5. + UrlHelper::Host(url) + } + } + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-host + fn SetHost(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + if url.non_relative_scheme_data().is_some() { + return; + } + // Step 4. + UrlHelper::SetHost(url, value); + // Step 5. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-hostname + fn Hostname(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 3. + None => USVString(String::new()), + Some(ref url) => { + // Step 4. + UrlHelper::Hostname(url) + } + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-hostname + fn SetHostname(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + if url.non_relative_scheme_data().is_some() { + return; + } + // Step 4. + UrlHelper::SetHostname(url, value); + // Step 5. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-href + fn Href(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + USVString(match *self.url.borrow() { + None => { + match self.upcast::<Element>().get_attribute(&ns!(), &atom!("href")) { + // Step 3. + None => String::new(), + // Step 4. + Some(attribute) => (**attribute.value()).to_owned(), + } + }, + // Step 5. + Some(ref url) => url.serialize(), + }) + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-href + fn SetHref(&self, value: USVString) { + self.upcast::<Element>().set_string_attribute(&atom!("href"), + DOMString::from_string(value.0)); + self.set_url(); + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-password + fn Password(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 3. + None => USVString(String::new()), + // Steps 3-4. + Some(ref url) => UrlHelper::Password(url) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-password + fn SetPassword(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + if url.host().is_none() || url.non_relative_scheme_data().is_some() { + return; + } + // Step 4. + UrlHelper::SetPassword(url, value); + // Step 5. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-pathname + fn Pathname(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 3. + None => USVString(String::new()), + // Steps 4-5. + Some(ref url) => UrlHelper::Pathname(url) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-pathname + fn SetPathname(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + if url.non_relative_scheme_data().is_some() { return; } + // Step 5. + UrlHelper::SetPathname(url, value); + // Step 6. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-port + fn Port(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 3. + None => USVString(String::new()), + // Step 4. + Some(ref url) => UrlHelper::Port(url) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-port + fn SetPort(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + if url.host().is_none() || + url.non_relative_scheme_data().is_some() || + url.scheme == "file" { + return; + } + // Step 4. + UrlHelper::SetPort(url, value); + // Step 5. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-protocol + fn Protocol(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 2. + None => USVString(":".to_owned()), + // Step 3. + Some(ref url) => UrlHelper::Protocol(url) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-protocol + fn SetProtocol(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 2. + if let Some(url) = self.url.borrow_mut().as_mut() { + // Step 3. + UrlHelper::SetProtocol(url, value); + // Step 4. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-search + fn Search(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 2. + None => USVString(String::new()), + // Step 3. + Some(ref url) => UrlHelper::Search(url) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-search + fn SetSearch(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + // Steps 4-5. + // TODO add this element's node document character encoding as + // encoding override (as described in the spec) + UrlHelper::SetSearch(url, value); + // Step 6. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-username + fn Username(&self) -> USVString { + // Step 1. + self.reinitialize_url(); + + match *self.url.borrow() { + // Step 2. + None => USVString(String::new()), + // Step 3. + Some(ref url) => UrlHelper::Username(url) + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-username + fn SetUsername(&self, value: USVString) { + // Step 1. + self.reinitialize_url(); + + // Step 3. + if let Some(url) = self.url.borrow_mut().as_mut() { + if url.host().is_none() || url.non_relative_scheme_data().is_some() { + return; + } + + // Step 4. + UrlHelper::SetUsername(url, value); + // Step 5. + self.update_href(); + } + } + + // https://html.spec.whatwg.org/multipage/#dom-hyperlink-href + fn Stringifier(&self) -> DOMString { + DOMString::from(self.Href().0) + } } impl Activatable for HTMLAnchorElement { diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs index 661fb3d6f68..342d4173343 100644 --- a/components/script/dom/htmlbuttonelement.rs +++ b/components/script/dom/htmlbuttonelement.rs @@ -18,6 +18,7 @@ use dom::htmlformelement::{FormControl, FormSubmitter, ResetFrom}; use dom::htmlformelement::{SubmittedFrom, HTMLFormElement}; use dom::node::{Node, UnbindContext, document_from_node, window_from_node}; use dom::nodelist::NodeList; +use dom::validation::Validatable; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use std::ascii::AsciiExt; @@ -66,7 +67,7 @@ impl HTMLButtonElementMethods for HTMLButtonElement { // https://html.spec.whatwg.org/multipage/#dom-cva-validity fn Validity(&self) -> Root<ValidityState> { let window = window_from_node(self); - ValidityState::new(window.r()) + ValidityState::new(window.r(), self.upcast()) } // https://html.spec.whatwg.org/multipage/#dom-fe-disabled @@ -203,6 +204,8 @@ impl VirtualMethods for HTMLButtonElement { impl FormControl for HTMLButtonElement {} +impl Validatable for HTMLButtonElement {} + impl Activatable for HTMLButtonElement { fn as_element(&self) -> &Element { self.upcast() diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 0288efc206a..622824f88d9 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -94,7 +94,6 @@ impl HTMLCanvasElement { } pub struct HTMLCanvasData { - pub renderer_id: Option<usize>, pub ipc_renderer: Option<IpcSender<CanvasMsg>>, pub width: u32, pub height: u32, @@ -109,22 +108,20 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { 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), - }; + let ipc_renderer = canvas.context.borrow_for_layout().as_ref().map(|context| { + match *context { + CanvasContext::Context2d(ref context) => { + context.to_layout().get_ipc_renderer() + }, + CanvasContext::WebGL(ref context) => { + context.to_layout().get_ipc_renderer() + }, + } + }); let width_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(), &atom!("width")); let height_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(), &atom!("height")); HTMLCanvasData { - renderer_id: renderer_id, ipc_renderer: ipc_renderer, width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()), height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()), @@ -209,7 +206,7 @@ impl HTMLCanvasElement { CanvasData::Pixels(pixel_data) => pixel_data.image_data.to_vec(), CanvasData::WebGL(_) - // TODO(ecoal95): Not sure if WebGL canvas is required for 2d spec, + // TODO(emilio): Not sure if WebGL canvas is required for 2d spec, // but I think it's not. => return None, } diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs index d36fb177e7b..25e17586f9b 100644 --- a/components/script/dom/htmlcollection.rs +++ b/components/script/dom/htmlcollection.rs @@ -11,7 +11,7 @@ use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::trace::JSTraceable; use dom::bindings::xmlname::namespace_from_domstring; use dom::element::Element; -use dom::node::{Node, FollowingNodeIterator, PrecedingNodeIterator}; +use dom::node::Node; use dom::window::Window; use std::ascii::AsciiExt; use std::cell::Cell; @@ -208,7 +208,7 @@ impl HTMLCollection { pub fn elements_iter_after(&self, after: &Node) -> HTMLCollectionElementsIter { // Iterate forwards from a node. HTMLCollectionElementsIter { - node_iter: after.following_nodes(&self.root), + node_iter: box after.following_nodes(&self.root), root: Root::from_ref(&self.root), filter: &self.filter, } @@ -219,10 +219,10 @@ impl HTMLCollection { self.elements_iter_after(&*self.root) } - pub fn elements_iter_before(&self, before: &Node) -> HTMLCollectionElementsRevIter { + pub fn elements_iter_before(&self, before: &Node) -> HTMLCollectionElementsIter { // Iterate backwards from a node. - HTMLCollectionElementsRevIter { - node_iter: before.preceding_nodes(&self.root), + HTMLCollectionElementsIter { + node_iter: box before.preceding_nodes(&self.root), root: Root::from_ref(&self.root), filter: &self.filter, } @@ -232,7 +232,7 @@ impl HTMLCollection { // TODO: Make this generic, and avoid code duplication pub struct HTMLCollectionElementsIter<'a> { - node_iter: FollowingNodeIterator, + node_iter: Box<Iterator<Item = Root<Node>>>, root: Root<Node>, filter: &'a Box<CollectionFilter>, } @@ -250,25 +250,6 @@ impl<'a> Iterator for HTMLCollectionElementsIter<'a> { } } -pub struct HTMLCollectionElementsRevIter<'a> { - node_iter: PrecedingNodeIterator, - root: Root<Node>, - filter: &'a Box<CollectionFilter>, -} - -impl<'a> Iterator for HTMLCollectionElementsRevIter<'a> { - type Item = Root<Element>; - - fn next(&mut self) -> Option<Self::Item> { - let filter = &self.filter; - let root = &self.root; - self.node_iter.by_ref() - .filter_map(Root::downcast) - .filter(|element| filter.filter(&element, root)) - .next() - } -} - impl HTMLCollectionMethods for HTMLCollection { // https://dom.spec.whatwg.org/#dom-htmlcollection-length fn Length(&self) -> u32 { diff --git a/components/script/dom/htmlfieldsetelement.rs b/components/script/dom/htmlfieldsetelement.rs index 0390d9aa599..b9800dcd1f1 100644 --- a/components/script/dom/htmlfieldsetelement.rs +++ b/components/script/dom/htmlfieldsetelement.rs @@ -64,7 +64,7 @@ impl HTMLFieldSetElementMethods for HTMLFieldSetElement { // https://html.spec.whatwg.org/multipage/#dom-cva-validity fn Validity(&self) -> Root<ValidityState> { let window = window_from_node(self); - ValidityState::new(window.r()) + ValidityState::new(window.r(), self.upcast()) } // https://html.spec.whatwg.org/multipage/#dom-fieldset-disabled diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs index 4cf2c3f467e..4e7e6108785 100644 --- a/components/script/dom/htmliframeelement.rs +++ b/components/script/dom/htmliframeelement.rs @@ -6,6 +6,7 @@ use document_loader::{LoadType, LoadBlocker}; use dom::attr::{Attr, AttrValue}; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementIconChangeEventDetail; +use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementLocationChangeEventDetail; use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserElementSecurityChangeDetail; use dom::bindings::codegen::Bindings::BrowserElementBinding::BrowserShowModalPromptEventDetail; use dom::bindings::codegen::Bindings::HTMLIFrameElementBinding; @@ -27,6 +28,7 @@ use dom::node::{Node, UnbindContext, window_from_node, document_from_node}; use dom::urlhelper::UrlHelper; use dom::virtualmethods::VirtualMethods; use dom::window::{ReflowReason, Window}; +use ipc_channel::ipc; use js::jsapi::{JSAutoCompartment, JSAutoRequest, RootedValue, JSContext, MutableHandleValue}; use js::jsval::{UndefinedValue, NullValue}; use layout_interface::ReflowQueryType; @@ -323,9 +325,16 @@ impl MozBrowserEventDetailBuilder for HTMLIFrameElement { mixedState: None, }.to_jsval(cx, rval); } - MozBrowserEvent::LocationChange(ref string) | MozBrowserEvent::TitleChange(ref string) => { + MozBrowserEvent::TitleChange(ref string) => { string.to_jsval(cx, rval); } + MozBrowserEvent::LocationChange(uri, can_go_back, can_go_forward) => { + BrowserElementLocationChangeEventDetail { + uri: Some(DOMString::from(uri)), + canGoBack: Some(can_go_back), + canGoForward: Some(can_go_forward), + }.to_jsval(cx, rval); + } MozBrowserEvent::IconChange(rel, href, sizes) => { BrowserElementIconChangeEventDetail { rel: Some(DOMString::from(rel)), @@ -551,9 +560,30 @@ impl VirtualMethods for HTMLIFrameElement { let window = window_from_node(self); let window = window.r(); + // The only reason we're waiting for the iframe to be totally + // removed is to ensure the script thread can't add iframes faster + // than the compositor can remove them. + // + // Since most of this cleanup doesn't happen on same-origin + // iframes, and since that would cause a deadlock, don't do it. let ConstellationChan(ref chan) = window.constellation_chan(); - let msg = ConstellationMsg::RemoveIFrame(pipeline_id); + let same_origin = if let Some(self_url) = self.get_url() { + let win_url = window_from_node(self).get_url(); + UrlHelper::SameOrigin(&self_url, &win_url) + } else { + false + }; + let (sender, receiver) = if same_origin { + (None, None) + } else { + let (sender, receiver) = ipc::channel().unwrap(); + (Some(sender), Some(receiver)) + }; + let msg = ConstellationMsg::RemoveIFrame(pipeline_id, sender); chan.send(msg).unwrap(); + if let Some(receiver) = receiver { + receiver.recv().unwrap() + } // Resetting the subpage id to None is required here so that // if this iframe is subsequently re-added to the document diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index 03c3bf83d0c..e14a91ae9d7 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -28,8 +28,10 @@ use dom::keyboardevent::KeyboardEvent; use dom::node::{Node, NodeDamage, UnbindContext}; use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; +use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; +use range::Range; use script_thread::ScriptThreadEventCategory::InputEvent; use script_thread::{CommonScriptMsg, Runnable}; use script_traits::ScriptMsg as ConstellationMsg; @@ -208,7 +210,7 @@ pub trait LayoutHTMLInputElementHelpers { #[allow(unsafe_code)] unsafe fn get_size_for_layout(self) -> u32; #[allow(unsafe_code)] - unsafe fn get_insertion_point_index_for_layout(self) -> Option<isize>; + unsafe fn get_selection_for_layout(self) -> Option<Range<isize>>; #[allow(unsafe_code)] unsafe fn get_checked_state_for_layout(self) -> bool; #[allow(unsafe_code)] @@ -241,7 +243,7 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { InputType::InputPassword => { let text = get_raw_textinput_value(self); if !text.is_empty() { - // The implementation of get_insertion_point_index_for_layout expects a 1:1 mapping of chars. + // The implementation of get_selection_for_layout expects a 1:1 mapping of chars. text.chars().map(|_| '●').collect() } else { String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone()) @@ -250,7 +252,7 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { _ => { let text = get_raw_textinput_value(self); if !text.is_empty() { - // The implementation of get_insertion_point_index_for_layout expects a 1:1 mapping of chars. + // The implementation of get_selection_for_layout expects a 1:1 mapping of chars. String::from(text) } else { String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone()) @@ -267,25 +269,24 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { #[allow(unrooted_must_root)] #[allow(unsafe_code)] - unsafe fn get_insertion_point_index_for_layout(self) -> Option<isize> { + unsafe fn get_selection_for_layout(self) -> Option<Range<isize>> { if !(*self.unsafe_get()).upcast::<Element>().get_focus_state() { return None; } - match (*self.unsafe_get()).input_type.get() { - InputType::InputText => { - let raw = self.get_value_for_layout(); - Some(search_index((*self.unsafe_get()).textinput.borrow_for_layout().edit_point.index, - raw.char_indices())) - } - InputType::InputPassword => { - // Use the raw textinput to get the index as long as we use a 1:1 char mapping - // in get_input_value_for_layout. - let raw = get_raw_textinput_value(self); - Some(search_index((*self.unsafe_get()).textinput.borrow_for_layout().edit_point.index, - raw.char_indices())) - } - _ => None - } + + // Use the raw textinput to get the index as long as we use a 1:1 char mapping + // in get_value_for_layout. + let raw = match (*self.unsafe_get()).input_type.get() { + InputType::InputText | + InputType::InputPassword => get_raw_textinput_value(self), + _ => return None + }; + let textinput = (*self.unsafe_get()).textinput.borrow_for_layout(); + let selection = textinput.get_absolute_selection_range(); + let begin_byte = selection.begin(); + let begin = search_index(begin_byte, raw.char_indices()); + let length = search_index(selection.length(), raw[begin_byte..].char_indices()); + Some(Range::new(begin, length)) } #[allow(unrooted_must_root)] @@ -861,10 +862,6 @@ impl VirtualMethods for HTMLInputElement { } if event.type_() == atom!("click") && !event.DefaultPrevented() { - if let InputType::InputRadio = self.input_type.get() { - self.update_checked_state(true, true); - } - // TODO: Dispatch events for non activatable inputs // https://html.spec.whatwg.org/multipage/#common-input-element-events @@ -908,6 +905,8 @@ impl VirtualMethods for HTMLInputElement { impl FormControl for HTMLInputElement {} +impl Validatable for HTMLInputElement {} + impl Activatable for HTMLInputElement { fn as_element(&self) -> &Element { self.upcast() diff --git a/components/script/dom/htmllabelelement.rs b/components/script/dom/htmllabelelement.rs index 7042b98f0d7..90d4a16b86e 100644 --- a/components/script/dom/htmllabelelement.rs +++ b/components/script/dom/htmllabelelement.rs @@ -63,12 +63,15 @@ impl Activatable for HTMLLabelElement { // https://html.spec.whatwg.org/multipage/#run-post-click-activation-steps fn activation_behavior(&self, _event: &Event, _target: &EventTarget) { - synthetic_click_activation(self.upcast::<Element>(), - false, - false, - false, - false, - ActivationSource::NotFromClick); + if let Some(e) = self.GetControl() { + let elem = e.upcast::<Element>(); + synthetic_click_activation(elem, + false, + false, + false, + false, + ActivationSource::NotFromClick); + } } // https://html.spec.whatwg.org/multipage/#implicit-submission diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index 779c5c79e07..73cc5c73aa0 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -73,6 +73,9 @@ impl HTMLMetaElement { rules: vec![CSSRule::Viewport(translated_rule)], origin: Origin::Author, media: None, + // Viewport constraints are always recomputed on resize; they don't need to + // force all styles to be recomputed. + dirty_on_viewport_size_change: false, })); let doc = document_from_node(self); doc.invalidate_stylesheets(); diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs index c60c4dd1d13..4d2b1cde778 100644 --- a/components/script/dom/htmlobjectelement.rs +++ b/components/script/dom/htmlobjectelement.rs @@ -13,6 +13,7 @@ use dom::element::{AttributeMutation, Element}; use dom::htmlelement::HTMLElement; use dom::htmlformelement::{FormControl, HTMLFormElement}; use dom::node::{Node, window_from_node}; +use dom::validation::Validatable; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use net_traits::image::base::Image; @@ -76,7 +77,7 @@ impl HTMLObjectElementMethods for HTMLObjectElement { // https://html.spec.whatwg.org/multipage/#dom-cva-validity fn Validity(&self) -> Root<ValidityState> { let window = window_from_node(self); - ValidityState::new(window.r()) + ValidityState::new(window.r(), self.upcast()) } // https://html.spec.whatwg.org/multipage/#dom-object-type @@ -91,6 +92,8 @@ impl HTMLObjectElementMethods for HTMLObjectElement { } } +impl Validatable for HTMLObjectElement {} + impl VirtualMethods for HTMLObjectElement { fn super_type(&self) -> Option<&VirtualMethods> { Some(self.upcast::<HTMLElement>() as &VirtualMethods) diff --git a/components/script/dom/htmloutputelement.rs b/components/script/dom/htmloutputelement.rs index 0a018f4217d..b614684b863 100644 --- a/components/script/dom/htmloutputelement.rs +++ b/components/script/dom/htmloutputelement.rs @@ -43,7 +43,7 @@ impl HTMLOutputElementMethods for HTMLOutputElement { // https://html.spec.whatwg.org/multipage/#dom-cva-validity fn Validity(&self) -> Root<ValidityState> { let window = window_from_node(self); - ValidityState::new(window.r()) + ValidityState::new(window.r(), self.upcast()) } // https://html.spec.whatwg.org/multipage/#dom-fae-form diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index bbd1884dc4f..eb63d524c9c 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -25,7 +25,6 @@ use dom::node::{ChildrenMutation, CloneChildrenFlag, Node}; use dom::node::{document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use dom::window::ScriptHelpers; -use encoding::all::UTF_8; use encoding::label::encoding_from_whatwg_label; use encoding::types::{DecoderTrap, Encoding, EncodingRef}; use html5ever::tree_builder::NextParserState; @@ -71,7 +70,7 @@ pub struct HTMLScriptElement { #[ignore_heap_size_of = "Defined in rust-encoding"] /// https://html.spec.whatwg.org/multipage/#concept-script-encoding - block_character_encoding: DOMRefCell<EncodingRef>, + block_character_encoding: Cell<Option<EncodingRef>>, } impl HTMLScriptElement { @@ -86,7 +85,7 @@ impl HTMLScriptElement { ready_to_be_parser_executed: Cell::new(false), parser_document: JS::from_ref(document), load: DOMRefCell::new(None), - block_character_encoding: DOMRefCell::new(UTF_8 as EncodingRef), + block_character_encoding: Cell::new(None), } } @@ -248,7 +247,7 @@ impl HTMLScriptElement { // Step 13. if let Some(ref charset) = element.get_attribute(&ns!(), &atom!("charset")) { if let Some(encodingRef) = encoding_from_whatwg_label(&charset.Value()) { - *self.block_character_encoding.borrow_mut() = encodingRef; + self.block_character_encoding.set(Some(encodingRef)); } } @@ -391,10 +390,16 @@ impl HTMLScriptElement { // Step 2.b.1.a. ScriptOrigin::External(Ok((metadata, bytes))) => { - // TODO(#9185): implement encoding determination. - (DOMString::from(UTF_8.decode(&*bytes, DecoderTrap::Replace).unwrap()), - true, - metadata.final_url) + debug!("loading external script, url = {}", metadata.final_url); + + let encoding = metadata.charset + .and_then(|encoding| encoding_from_whatwg_label(&encoding)) + .or_else(|| self.block_character_encoding.get()) + .unwrap_or_else(|| self.parser_document.encoding()); + + (DOMString::from(encoding.decode(&*bytes, DecoderTrap::Replace).unwrap()), + true, + metadata.final_url) }, // Step 2.b.1.c. diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs index 1b5ddb22183..d42ba617a75 100644 --- a/components/script/dom/htmlselectelement.rs +++ b/components/script/dom/htmlselectelement.rs @@ -18,6 +18,7 @@ use dom::htmlformelement::{FormControl, FormDatum, HTMLFormElement}; use dom::htmloptionelement::HTMLOptionElement; use dom::node::{Node, UnbindContext, window_from_node}; use dom::nodelist::NodeList; +use dom::validation::Validatable; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use string_cache::Atom; @@ -130,7 +131,7 @@ impl HTMLSelectElementMethods for HTMLSelectElement { // https://html.spec.whatwg.org/multipage/#dom-cva-validity fn Validity(&self) -> Root<ValidityState> { let window = window_from_node(self); - ValidityState::new(window.r()) + ValidityState::new(window.r(), self.upcast()) } // Note: this function currently only exists for union.html. @@ -234,3 +235,5 @@ impl VirtualMethods for HTMLSelectElement { } impl FormControl for HTMLSelectElement {} + +impl Validatable for HTMLSelectElement {} diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index dfcfdc77f73..0f82919124f 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -23,8 +23,10 @@ use dom::keyboardevent::KeyboardEvent; use dom::node::{ChildrenMutation, Node, NodeDamage, UnbindContext}; use dom::node::{document_from_node}; use dom::nodelist::NodeList; +use dom::validation::Validatable; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; +use range::Range; use script_traits::ScriptMsg as ConstellationMsg; use std::cell::Cell; use string_cache::Atom; @@ -45,7 +47,7 @@ pub trait LayoutHTMLTextAreaElementHelpers { #[allow(unsafe_code)] unsafe fn get_value_for_layout(self) -> String; #[allow(unsafe_code)] - unsafe fn get_absolute_insertion_point_for_layout(self) -> Option<usize>; + unsafe fn get_absolute_selection_for_layout(self) -> Option<Range<usize>>; #[allow(unsafe_code)] fn get_cols(self) -> u32; #[allow(unsafe_code)] @@ -61,10 +63,10 @@ impl LayoutHTMLTextAreaElementHelpers for LayoutJS<HTMLTextAreaElement> { #[allow(unrooted_must_root)] #[allow(unsafe_code)] - unsafe fn get_absolute_insertion_point_for_layout(self) -> Option<usize> { + unsafe fn get_absolute_selection_for_layout(self) -> Option<Range<usize>> { if (*self.unsafe_get()).upcast::<Element>().get_focus_state() { Some((*self.unsafe_get()).textinput.borrow_for_layout() - .get_absolute_insertion_point()) + .get_absolute_selection_range()) } else { None } @@ -334,3 +336,5 @@ impl VirtualMethods for HTMLTextAreaElement { } impl FormControl for HTMLTextAreaElement {} + +impl Validatable for HTMLTextAreaElement {} diff --git a/components/script/dom/keyboardevent.rs b/components/script/dom/keyboardevent.rs index 9feb08b7674..91d69e7cfd8 100644 --- a/components/script/dom/keyboardevent.rs +++ b/components/script/dom/keyboardevent.rs @@ -148,7 +148,7 @@ impl KeyboardEvent { } -// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3Events-key.html +// https://w3c.github.io/uievents-key/#key-value-tables pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str { let shift = mods.contains(constellation_msg::SHIFT); match key { @@ -319,6 +319,8 @@ pub fn key_value(key: Key, mods: KeyModifiers) -> &'static str { Key::RightAlt => "Alt", Key::RightSuper => "Super", Key::Menu => "ContextMenu", + Key::NavigateForward => "BrowserForward", + Key::NavigateBackward => "BrowserBack", } } @@ -489,11 +491,13 @@ fn key_from_string(key_string: &str, location: u32) -> Option<Key> { "Alt" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightAlt), "Super" if location == KeyboardEventConstants::DOM_KEY_LOCATION_RIGHT => Some(Key::RightSuper), "ContextMenu" => Some(Key::Menu), + "BrowserForward" => Some(Key::NavigateForward), + "BrowserBack" => Some(Key::NavigateBackward), _ => None } } -// https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3Events-code.html +// https://w3c.github.io/uievents-code/#code-value-tables fn code_value(key: Key) -> &'static str { match key { Key::Space => "Space", @@ -613,7 +617,10 @@ fn code_value(key: Key) -> &'static str { Key::LeftControl | Key::RightControl => "Control", Key::LeftAlt | Key::RightAlt => "Alt", Key::LeftSuper | Key::RightSuper => "Super", - Key::Menu => "Menu", + Key::Menu => "ContextMenu", + + Key::NavigateForward => "BrowserForward", + Key::NavigateBackward => "BrowserBackward", } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index e75c717b154..662f41dc7a9 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -375,6 +375,7 @@ pub mod url; pub mod urlhelper; pub mod urlsearchparams; pub mod userscripts; +pub mod validation; pub mod validitystate; pub mod values; pub mod virtualmethods; diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs index 5bd6cb7ca06..3acebff3f46 100644 --- a/components/script/dom/mouseevent.rs +++ b/components/script/dom/mouseevent.rs @@ -74,7 +74,7 @@ impl MouseEvent { button: i16, relatedTarget: Option<&EventTarget>) -> Root<MouseEvent> { let ev = MouseEvent::new_uninitialized(window); - ev.InitMouseEvent(type_, canBubble == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable, + ev.InitMouseEvent(type_, bool::from(canBubble), bool::from(cancelable), view, detail, screenX, screenY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, @@ -85,16 +85,8 @@ impl MouseEvent { pub fn Constructor(global: GlobalRef, type_: DOMString, init: &MouseEventBinding::MouseEventInit) -> Fallible<Root<MouseEvent>> { - let bubbles = if init.parent.parent.parent.bubbles { - EventBubbles::Bubbles - } else { - EventBubbles::DoesNotBubble - }; - let cancelable = if init.parent.parent.parent.cancelable { - EventCancelable::Cancelable - } else { - EventCancelable::NotCancelable - }; + let bubbles = EventBubbles::from(init.parent.parent.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.parent.parent.cancelable); let event = MouseEvent::new(global.as_window(), type_, bubbles, cancelable, diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index fed47bb7b24..730f69f24cd 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -1696,7 +1696,7 @@ impl Node { NodeTypeId::Document(_) => { let node_doc = node.downcast::<Document>().unwrap(); let copy_doc = copy.downcast::<Document>().unwrap(); - copy_doc.set_encoding_name(node_doc.encoding_name().clone()); + copy_doc.set_encoding(node_doc.encoding()); copy_doc.set_quirks_mode(node_doc.quirks_mode()); }, NodeTypeId::Element(..) => { diff --git a/components/script/dom/progressevent.rs b/components/script/dom/progressevent.rs index e7b0b1510ef..215bcdd3db4 100644 --- a/components/script/dom/progressevent.rs +++ b/components/script/dom/progressevent.rs @@ -39,7 +39,7 @@ impl ProgressEvent { ProgressEventBinding::Wrap); { let event = ev.upcast::<Event>(); - event.init_event(type_, can_bubble == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable); + event.init_event(type_, bool::from(can_bubble), bool::from(cancelable)); } ev } @@ -47,9 +47,8 @@ impl ProgressEvent { type_: DOMString, init: &ProgressEventBinding::ProgressEventInit) -> Fallible<Root<ProgressEvent>> { - let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble }; - let cancelable = if init.parent.cancelable { EventCancelable::Cancelable } - else { EventCancelable::NotCancelable }; + let bubbles = EventBubbles::from(init.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.cancelable); let ev = ProgressEvent::new(global, Atom::from(type_), bubbles, cancelable, init.lengthComputable, init.loaded, init.total); Ok(ev) diff --git a/components/script/dom/storageevent.rs b/components/script/dom/storageevent.rs index 4c7200f5fc1..7d1f7520c4a 100644 --- a/components/script/dom/storageevent.rs +++ b/components/script/dom/storageevent.rs @@ -57,7 +57,7 @@ impl StorageEvent { StorageEventBinding::Wrap); { let event = ev.upcast::<Event>(); - event.init_event(type_, bubbles == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable); + event.init_event(type_, bool::from(bubbles), bool::from(cancelable)); } ev } @@ -70,12 +70,8 @@ impl StorageEvent { let newValue = init.newValue.clone(); let url = init.url.clone(); let storageArea = init.storageArea.r(); - let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble }; - let cancelable = if init.parent.cancelable { - EventCancelable::Cancelable - } else { - EventCancelable::NotCancelable - }; + let bubbles = EventBubbles::from(init.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.cancelable); let event = StorageEvent::new(global, Atom::from(type_), bubbles, cancelable, key, oldValue, newValue, diff --git a/components/script/dom/testbinding.rs b/components/script/dom/testbinding.rs index ae63c1f6e20..41a1ff188b2 100644 --- a/components/script/dom/testbinding.rs +++ b/components/script/dom/testbinding.rs @@ -27,6 +27,7 @@ use js::jsval::{JSVal, NullValue}; use std::borrow::ToOwned; use std::ptr; use std::rc::Rc; +use util::prefs::{get_pref}; use util::str::DOMString; #[dom_struct] @@ -486,6 +487,9 @@ impl TestBindingMethods for TestBinding { fn PassVariadicUnion6(&self, _: Vec<UnsignedLongOrBoolean>) {} fn PassVariadicAny(&self, _: *mut JSContext, _: Vec<HandleValue>) {} fn PassVariadicObject(&self, _: *mut JSContext, _: Vec<*mut JSObject>) {} + fn BooleanMozPreference(&self, pref_name: DOMString) -> bool { + get_pref(pref_name.as_ref()).as_boolean().unwrap_or(false) + } } impl TestBinding { diff --git a/components/script/dom/touchevent.rs b/components/script/dom/touchevent.rs index 5d6b85a550a..86f53968fe3 100644 --- a/components/script/dom/touchevent.rs +++ b/components/script/dom/touchevent.rs @@ -68,8 +68,8 @@ impl TouchEvent { metaKey: bool) -> Root<TouchEvent> { let ev = TouchEvent::new_uninitialized(window, touches, changed_touches, target_touches); ev.upcast::<UIEvent>().InitUIEvent(type_, - canBubble == EventBubbles::Bubbles, - cancelable == EventCancelable::Cancelable, + bool::from(canBubble), + bool::from(cancelable), view, detail); ev.ctrl_key.set(ctrlKey); ev.alt_key.set(altKey); diff --git a/components/script/dom/uievent.rs b/components/script/dom/uievent.rs index bc340638255..e962c10c8aa 100644 --- a/components/script/dom/uievent.rs +++ b/components/script/dom/uievent.rs @@ -48,20 +48,15 @@ impl UIEvent { view: Option<&Window>, detail: i32) -> Root<UIEvent> { let ev = UIEvent::new_uninitialized(window); - ev.InitUIEvent(type_, can_bubble == EventBubbles::Bubbles, - cancelable == EventCancelable::Cancelable, view, detail); + ev.InitUIEvent(type_, bool::from(can_bubble), bool::from(cancelable), view, detail); ev } pub fn Constructor(global: GlobalRef, type_: DOMString, init: &UIEventBinding::UIEventInit) -> Fallible<Root<UIEvent>> { - let bubbles = if init.parent.bubbles { EventBubbles::Bubbles } else { EventBubbles::DoesNotBubble }; - let cancelable = if init.parent.cancelable { - EventCancelable::Cancelable - } else { - EventCancelable::NotCancelable - }; + let bubbles = EventBubbles::from(init.parent.bubbles); + let cancelable = EventCancelable::from(init.parent.cancelable); let event = UIEvent::new(global.as_window(), type_, bubbles, cancelable, init.view.r(), init.detail); diff --git a/components/script/dom/urlhelper.rs b/components/script/dom/urlhelper.rs index 580c541502d..ab0a0c5f8c0 100644 --- a/components/script/dom/urlhelper.rs +++ b/components/script/dom/urlhelper.rs @@ -21,6 +21,7 @@ impl UrlHelper { } pub fn SetHash(url: &mut Url, value: USVString) { + url.fragment = Some(String::new()); let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_fragment(&value.0); } @@ -101,6 +102,9 @@ impl UrlHelper { } pub fn SetPathname(url: &mut Url, value: USVString) { + if let Some(path) = url.path_mut() { + path.clear(); + } let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_path(&value.0); } @@ -149,6 +153,7 @@ impl UrlHelper { } pub fn SetSearch(url: &mut Url, value: USVString) { + url.query = Some(String::new()); let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_query(&value.0); } diff --git a/components/script/dom/validation.rs b/components/script/dom/validation.rs new file mode 100644 index 00000000000..e9a6a156848 --- /dev/null +++ b/components/script/dom/validation.rs @@ -0,0 +1,5 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +pub trait Validatable {} diff --git a/components/script/dom/validitystate.rs b/components/script/dom/validitystate.rs index ae48a1624b0..bd2cbb21aa7 100644 --- a/components/script/dom/validitystate.rs +++ b/components/script/dom/validitystate.rs @@ -3,29 +3,109 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::bindings::codegen::Bindings::ValidityStateBinding; +use dom::bindings::codegen::Bindings::ValidityStateBinding::ValidityStateMethods; use dom::bindings::global::GlobalRef; -use dom::bindings::js::Root; +use dom::bindings::js::{JS, Root}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; +use dom::element::Element; use dom::window::Window; +// https://html.spec.whatwg.org/multipage/#validity-states +#[derive_JSTraceable] +#[derive_HeapSizeOf] +pub enum ValidityStatus { + ValueMissing, + TypeMismatch, + PatternMismatch, + TooLong, + TooShort, + RangeUnderflow, + RangeOverflow, + StepMismatch, + BadInput, + CustomError, + Valid +} + // https://html.spec.whatwg.org/multipage/#validitystate #[dom_struct] pub struct ValidityState { reflector_: Reflector, - state: u8, + element: JS<Element>, + state: ValidityStatus } + impl ValidityState { - fn new_inherited() -> ValidityState { + fn new_inherited(element: &Element) -> ValidityState { ValidityState { reflector_: Reflector::new(), - state: 0, + element: JS::from_ref(element), + state: ValidityStatus::Valid } } - pub fn new(window: &Window) -> Root<ValidityState> { - reflect_dom_object(box ValidityState::new_inherited(), + pub fn new(window: &Window, element: &Element) -> Root<ValidityState> { + reflect_dom_object(box ValidityState::new_inherited(element), GlobalRef::Window(window), ValidityStateBinding::Wrap) } } + +impl ValidityStateMethods for ValidityState { + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-valuemissing + fn ValueMissing(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-typemismatch + fn TypeMismatch(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-patternmismatch + fn PatternMismatch(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-toolong + fn TooLong(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-tooshort + fn TooShort(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeunderflow + fn RangeUnderflow(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-rangeoverflow + fn RangeOverflow(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-stepmismatch + fn StepMismatch(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-badinput + fn BadInput(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-customerror + fn CustomError(&self) -> bool { + false + } + + // https://html.spec.whatwg.org/multipage/#dom-validitystate-valid + fn Valid(&self) -> bool { + false + } +} diff --git a/components/script/dom/webglbuffer.rs b/components/script/dom/webglbuffer.rs index cfb9cdc4810..0fedc762f4c 100644 --- a/components/script/dom/webglbuffer.rs +++ b/components/script/dom/webglbuffer.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult}; +use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::WebGLBufferBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; @@ -11,6 +11,7 @@ use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; +use webrender_traits::{WebGLCommand, WebGLError, WebGLResult}; #[dom_struct] pub struct WebGLBuffer { @@ -39,7 +40,7 @@ impl WebGLBuffer { pub fn maybe_new(global: GlobalRef, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLBuffer>> { let (sender, receiver) = ipc::channel().unwrap(); - renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateBuffer(sender))).unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateBuffer(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|buffer_id| WebGLBuffer::new(global, renderer, *buffer_id)) @@ -65,7 +66,7 @@ impl WebGLBuffer { } else { self.target.set(Some(target)); } - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BindBuffer(target, self.id))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::BindBuffer(target, self.id))).unwrap(); Ok(()) } @@ -78,7 +79,7 @@ impl WebGLBuffer { } self.capacity.set(data.len()); self.renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BufferData(target, data.to_vec(), usage))) + .send(CanvasMsg::WebGL(WebGLCommand::BufferData(target, data.to_vec(), usage))) .unwrap(); Ok(()) @@ -91,7 +92,7 @@ impl WebGLBuffer { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteBuffer(self.id))); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteBuffer(self.id))); } } } diff --git a/components/script/dom/webglcontextevent.rs b/components/script/dom/webglcontextevent.rs index 195848273fe..ac93727eb7c 100644 --- a/components/script/dom/webglcontextevent.rs +++ b/components/script/dom/webglcontextevent.rs @@ -53,7 +53,7 @@ impl WebGLContextEvent { { let parent = event.upcast::<Event>(); - parent.init_event(type_, bubbles == EventBubbles::Bubbles, cancelable == EventCancelable::Cancelable); + parent.init_event(type_, bool::from(bubbles), bool::from(cancelable)); } event @@ -67,17 +67,9 @@ impl WebGLContextEvent { None => DOMString::new(), }; - let bubbles = if init.parent.bubbles { - EventBubbles::Bubbles - } else { - EventBubbles::DoesNotBubble - }; + let bubbles = EventBubbles::from(init.parent.bubbles); - let cancelable = if init.parent.cancelable { - EventCancelable::Cancelable - } else { - EventCancelable::NotCancelable - }; + let cancelable = EventCancelable::from(init.parent.cancelable); Ok(WebGLContextEvent::new(global, Atom::from(type_), bubbles, diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs index 86ed0e61b30..9dc4d7c16be 100644 --- a/components/script/dom/webglframebuffer.rs +++ b/components/script/dom/webglframebuffer.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLFramebufferBindingRequest}; +use canvas_traits::{CanvasMsg}; use dom::bindings::codegen::Bindings::WebGLFramebufferBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; @@ -11,6 +11,7 @@ use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; +use webrender_traits::{WebGLCommand, WebGLFramebufferBindingRequest}; #[dom_struct] pub struct WebGLFramebuffer { @@ -34,7 +35,7 @@ impl WebGLFramebuffer { pub fn maybe_new(global: GlobalRef, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLFramebuffer>> { let (sender, receiver) = ipc::channel().unwrap(); - renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateFramebuffer(sender))).unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateFramebuffer(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|fb_id| WebGLFramebuffer::new(global, renderer, *fb_id)) @@ -53,14 +54,14 @@ impl WebGLFramebuffer { } pub fn bind(&self, target: u32) { - let cmd = CanvasWebGLMsg::BindFramebuffer(target, WebGLFramebufferBindingRequest::Explicit(self.id)); + let cmd = WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Explicit(self.id)); self.renderer.send(CanvasMsg::WebGL(cmd)).unwrap(); } pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteFramebuffer(self.id))); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteFramebuffer(self.id))); } } } diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs index 42eb0a23581..338a1e8d46b 100644 --- a/components/script/dom/webglprogram.rs +++ b/components/script/dom/webglprogram.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult, WebGLParameter}; +use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::WebGLProgramBinding; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::global::GlobalRef; @@ -15,6 +15,7 @@ use dom::webglshader::WebGLShader; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; use util::str::DOMString; +use webrender_traits::{WebGLCommand, WebGLError, WebGLParameter, WebGLResult}; #[dom_struct] pub struct WebGLProgram { @@ -42,7 +43,7 @@ impl WebGLProgram { pub fn maybe_new(global: GlobalRef, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLProgram>> { let (sender, receiver) = ipc::channel().unwrap(); - renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateProgram(sender))).unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateProgram(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|program_id| WebGLProgram::new(global, renderer, *program_id)) @@ -63,13 +64,13 @@ impl WebGLProgram { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteProgram(self.id))); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteProgram(self.id))); } } /// glLinkProgram pub fn link(&self) { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::LinkProgram(self.id))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::LinkProgram(self.id))).unwrap(); } /// glUseProgram @@ -84,7 +85,7 @@ impl WebGLProgram { _ => return Err(WebGLError::InvalidOperation), } - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::UseProgram(self.id))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::UseProgram(self.id))).unwrap(); Ok(()) } @@ -96,7 +97,7 @@ impl WebGLProgram { _ => return Err(WebGLError::InvalidOperation), }; - // TODO(ecoal95): Differentiate between same shader already assigned and other previous + // TODO(emilio): Differentiate between same shader already assigned and other previous // shader. if shader_slot.get().is_some() { return Err(WebGLError::InvalidOperation); @@ -104,7 +105,7 @@ impl WebGLProgram { shader_slot.set(Some(shader)); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::AttachShader(self.id, shader.id()))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::AttachShader(self.id, shader.id()))).unwrap(); Ok(()) } @@ -121,7 +122,7 @@ impl WebGLProgram { } self.renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BindAttribLocation(self.id, index, String::from(name)))) + .send(CanvasMsg::WebGL(WebGLCommand::BindAttribLocation(self.id, index, String::from(name)))) .unwrap(); Ok(()) } @@ -139,7 +140,7 @@ impl WebGLProgram { let (sender, receiver) = ipc::channel().unwrap(); self.renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::GetAttribLocation(self.id, String::from(name), sender))) + .send(CanvasMsg::WebGL(WebGLCommand::GetAttribLocation(self.id, String::from(name), sender))) .unwrap(); Ok(receiver.recv().unwrap()) } @@ -157,7 +158,7 @@ impl WebGLProgram { let (sender, receiver) = ipc::channel().unwrap(); self.renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::GetUniformLocation(self.id, String::from(name), sender))) + .send(CanvasMsg::WebGL(WebGLCommand::GetUniformLocation(self.id, String::from(name), sender))) .unwrap(); Ok(receiver.recv().unwrap()) } @@ -165,7 +166,7 @@ impl WebGLProgram { /// glGetProgramParameter pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> { let (sender, receiver) = ipc::channel().unwrap(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetProgramParameter(self.id, param_id, sender))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetProgramParameter(self.id, param_id, sender))).unwrap(); receiver.recv().unwrap() } } diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs index 5257c4782a9..a63bd1c975a 100644 --- a/components/script/dom/webglrenderbuffer.rs +++ b/components/script/dom/webglrenderbuffer.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::{CanvasMsg, CanvasWebGLMsg}; +use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::WebGLRenderbufferBinding; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; @@ -11,6 +11,7 @@ use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; +use webrender_traits::WebGLCommand; #[dom_struct] pub struct WebGLRenderbuffer { @@ -34,7 +35,7 @@ impl WebGLRenderbuffer { pub fn maybe_new(global: GlobalRef, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLRenderbuffer>> { let (sender, receiver) = ipc::channel().unwrap(); - renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateRenderbuffer(sender))).unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateRenderbuffer(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|renderbuffer_id| WebGLRenderbuffer::new(global, renderer, *renderbuffer_id)) @@ -53,13 +54,13 @@ impl WebGLRenderbuffer { } pub fn bind(&self, target: u32) { - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BindRenderbuffer(target, self.id))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, self.id))).unwrap(); } pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteRenderbuffer(self.id))); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteRenderbuffer(self.id))); } } } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index aba9e32b45f..e614b7afc6f 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -2,9 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -use canvas_traits::WebGLError::*; -use canvas_traits::{CanvasCommonMsg, CanvasMsg, CanvasWebGLMsg, WebGLError}; -use canvas_traits::{WebGLFramebufferBindingRequest, WebGLParameter}; +use canvas_traits::{CanvasCommonMsg, CanvasMsg}; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{WebGLRenderingContextMethods}; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::{self, WebGLContextAttributes}; @@ -37,6 +35,8 @@ use script_traits::ScriptMsg as ConstellationMsg; use std::cell::Cell; use util::str::DOMString; use util::vec::byte_swap; +use webrender_traits::WebGLError::*; +use webrender_traits::{WebGLCommand, WebGLError, WebGLFramebufferBindingRequest, WebGLParameter}; pub const MAX_UNIFORM_AND_ATTRIBUTE_LEN: usize = 256; @@ -68,7 +68,6 @@ bitflags! { #[dom_struct] pub struct WebGLRenderingContext { reflector_: Reflector, - renderer_id: usize, #[ignore_heap_size_of = "Defined in ipc-channel"] ipc_renderer: IpcSender<CanvasMsg>, canvas: JS<HTMLCanvasElement>, @@ -95,10 +94,9 @@ impl WebGLRenderingContext { .unwrap(); let result = receiver.recv().unwrap(); - result.map(|(ipc_renderer, renderer_id)| { + result.map(|ipc_renderer| { WebGLRenderingContext { reflector_: Reflector::new(), - renderer_id: renderer_id, ipc_renderer: ipc_renderer, canvas: JS::from_ref(canvas), last_error: Cell::new(None), @@ -166,7 +164,7 @@ impl WebGLRenderingContext { fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::VertexAttrib(indx, x, y, z, w))) + .send(CanvasMsg::WebGL(WebGLCommand::VertexAttrib(indx, x, y, z, w))) .unwrap(); } } @@ -187,7 +185,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn DrawingBufferWidth(&self) -> i32 { let (sender, receiver) = ipc::channel().unwrap(); self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::DrawingBufferWidth(sender))) + .send(CanvasMsg::WebGL(WebGLCommand::DrawingBufferWidth(sender))) .unwrap(); receiver.recv().unwrap() } @@ -196,7 +194,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn DrawingBufferHeight(&self) -> i32 { let (sender, receiver) = ipc::channel().unwrap(); self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::DrawingBufferHeight(sender))) + .send(CanvasMsg::WebGL(WebGLCommand::DrawingBufferHeight(sender))) .unwrap(); receiver.recv().unwrap() } @@ -206,7 +204,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn GetBufferParameter(&self, _cx: *mut JSContext, target: u32, parameter: u32) -> JSVal { let (sender, receiver) = ipc::channel().unwrap(); self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::GetBufferParameter(target, parameter, sender))) + .send(CanvasMsg::WebGL(WebGLCommand::GetBufferParameter(target, parameter, sender))) .unwrap(); match handle_potential_webgl_error!(self, receiver.recv().unwrap(), WebGLParameter::Invalid) { WebGLParameter::Int(val) => Int32Value(val), @@ -222,7 +220,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { fn GetParameter(&self, cx: *mut JSContext, parameter: u32) -> JSVal { let (sender, receiver) = ipc::channel().unwrap(); self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::GetParameter(parameter, sender))) + .send(CanvasMsg::WebGL(WebGLCommand::GetParameter(parameter, sender))) .unwrap(); match handle_potential_webgl_error!(self, receiver.recv().unwrap(), WebGLParameter::Invalid) { WebGLParameter::Int(val) => Int32Value(val), @@ -262,7 +260,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // If the send does not succeed, assume context lost if let Err(_) = self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::GetContextAttributes(sender))) { + .send(CanvasMsg::WebGL(WebGLCommand::GetContextAttributes(sender))) { return None; } let attrs = receiver.recv().unwrap(); @@ -291,37 +289,37 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ActiveTexture(&self, texture: u32) { - self.ipc_renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::ActiveTexture(texture))).unwrap(); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::ActiveTexture(texture))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn BlendColor(&self, r: f32, g: f32, b: f32, a: f32) { - self.ipc_renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BlendColor(r, g, b, a))).unwrap(); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::BlendColor(r, g, b, a))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn BlendEquation(&self, mode: u32) { - self.ipc_renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BlendEquation(mode))).unwrap(); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::BlendEquation(mode))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn BlendEquationSeparate(&self, mode_rgb: u32, mode_alpha: u32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BlendEquationSeparate(mode_rgb, mode_alpha))) + .send(CanvasMsg::WebGL(WebGLCommand::BlendEquationSeparate(mode_rgb, mode_alpha))) .unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn BlendFunc(&self, src_factor: u32, dest_factor: u32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BlendFunc(src_factor, dest_factor))) + .send(CanvasMsg::WebGL(WebGLCommand::BlendFunc(src_factor, dest_factor))) .unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn BlendFuncSeparate(&self, src_rgb: u32, dest_rgb: u32, src_alpha: u32, dest_alpha: u32) { self.ipc_renderer.send( - CanvasMsg::WebGL(CanvasWebGLMsg::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha))).unwrap(); + CanvasMsg::WebGL(WebGLCommand::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha))).unwrap(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.9 @@ -358,7 +356,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } else { // Unbind the current buffer self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BindBuffer(target, 0))) + .send(CanvasMsg::WebGL(WebGLCommand::BindBuffer(target, 0))) .unwrap() } } @@ -373,7 +371,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { framebuffer.bind(target) } else { // Bind the default framebuffer - let cmd = CanvasWebGLMsg::BindFramebuffer(target, WebGLFramebufferBindingRequest::Default); + let cmd = WebGLCommand::BindFramebuffer(target, WebGLFramebufferBindingRequest::Default); self.ipc_renderer.send(CanvasMsg::WebGL(cmd)).unwrap(); } } @@ -389,7 +387,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } else { // Unbind the currently bound renderbuffer self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BindRenderbuffer(target, 0))) + .send(CanvasMsg::WebGL(WebGLCommand::BindRenderbuffer(target, 0))) .unwrap() } } @@ -411,7 +409,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } else { // Unbind the currently bound texture self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BindTexture(target, 0))) + .send(CanvasMsg::WebGL(WebGLCommand::BindTexture(target, 0))) .unwrap() } } @@ -472,7 +470,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { return self.webgl_error(InvalidValue); } self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::BufferSubData(target, offset as isize, data_vec))) + .send(CanvasMsg::WebGL(WebGLCommand::BufferSubData(target, offset as isize, data_vec))) .unwrap() } else { self.webgl_error(InvalidValue); @@ -498,35 +496,35 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.11 fn Clear(&self, mask: u32) { - self.ipc_renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::Clear(mask))).unwrap(); + self.ipc_renderer.send(CanvasMsg::WebGL(WebGLCommand::Clear(mask))).unwrap(); self.mark_as_dirty(); } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ClearColor(&self, red: f32, green: f32, blue: f32, alpha: f32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::ClearColor(red, green, blue, alpha))) + .send(CanvasMsg::WebGL(WebGLCommand::ClearColor(red, green, blue, alpha))) .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ClearDepth(&self, depth: f32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::ClearDepth(depth as f64))) + .send(CanvasMsg::WebGL(WebGLCommand::ClearDepth(depth as f64))) .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ClearStencil(&self, stencil: i32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::ClearStencil(stencil))) + .send(CanvasMsg::WebGL(WebGLCommand::ClearStencil(stencil))) .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn ColorMask(&self, r: bool, g: bool, b: bool, a: bool) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::ColorMask(r, g, b, a))) + .send(CanvasMsg::WebGL(WebGLCommand::ColorMask(r, g, b, a))) .unwrap() } @@ -535,7 +533,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { match mode { constants::FRONT | constants::BACK | constants::FRONT_AND_BACK => self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::CullFace(mode))) + .send(CanvasMsg::WebGL(WebGLCommand::CullFace(mode))) .unwrap(), _ => self.webgl_error(InvalidEnum), } @@ -546,7 +544,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { match mode { constants::CW | constants::CCW => self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::FrontFace(mode))) + .send(CanvasMsg::WebGL(WebGLCommand::FrontFace(mode))) .unwrap(), _ => self.webgl_error(InvalidEnum), } @@ -559,7 +557,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { constants::GREATER | constants::NOTEQUAL | constants::GEQUAL | constants::ALWAYS => self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::DepthFunc(func))) + .send(CanvasMsg::WebGL(WebGLCommand::DepthFunc(func))) .unwrap(), _ => self.webgl_error(InvalidEnum), } @@ -568,14 +566,14 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn DepthMask(&self, flag: bool) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::DepthMask(flag))) + .send(CanvasMsg::WebGL(WebGLCommand::DepthMask(flag))) .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn DepthRange(&self, near: f32, far: f32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::DepthRange(near as f64, far as f64))) + .send(CanvasMsg::WebGL(WebGLCommand::DepthRange(near as f64, far as f64))) .unwrap() } @@ -586,7 +584,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { constants::POLYGON_OFFSET_FILL | constants::SAMPLE_ALPHA_TO_COVERAGE | constants::SAMPLE_COVERAGE | constants::SAMPLE_COVERAGE_INVERT | constants::SCISSOR_TEST => self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Enable(cap))) + .send(CanvasMsg::WebGL(WebGLCommand::Enable(cap))) .unwrap(), _ => self.webgl_error(InvalidEnum), } @@ -599,7 +597,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { constants::POLYGON_OFFSET_FILL | constants::SAMPLE_ALPHA_TO_COVERAGE | constants::SAMPLE_COVERAGE | constants::SAMPLE_COVERAGE_INVERT | constants::SCISSOR_TEST => self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Disable(cap))) + .send(CanvasMsg::WebGL(WebGLCommand::Disable(cap))) .unwrap(), _ => self.webgl_error(InvalidEnum), } @@ -612,7 +610,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } } - // TODO(ecoal95): Probably in the future we should keep track of the + // TODO(emilio): Probably in the future we should keep track of the // generated objects, either here or in the webgl thread // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.5 fn CreateBuffer(&self) -> Option<Root<WebGLBuffer>> { @@ -701,7 +699,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { self.webgl_error(InvalidValue); } else { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::DrawArrays(mode, first, count))) + .send(CanvasMsg::WebGL(WebGLCommand::DrawArrays(mode, first, count))) .unwrap(); self.mark_as_dirty(); } @@ -741,7 +739,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { constants::TRIANGLE_STRIP | constants::TRIANGLE_FAN | constants::TRIANGLES => { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::DrawElements(mode, count, type_, offset))) + .send(CanvasMsg::WebGL(WebGLCommand::DrawElements(mode, count, type_, offset))) .unwrap(); self.mark_as_dirty(); }, @@ -752,7 +750,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.10 fn EnableVertexAttribArray(&self, attrib_id: u32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::EnableVertexAttribArray(attrib_id))) + .send(CanvasMsg::WebGL(WebGLCommand::EnableVertexAttribArray(attrib_id))) .unwrap() } @@ -827,7 +825,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Hint(target, mode))) + .send(CanvasMsg::WebGL(WebGLCommand::Hint(target, mode))) .unwrap() } @@ -838,7 +836,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::LineWidth(width))) + .send(CanvasMsg::WebGL(WebGLCommand::LineWidth(width))) .unwrap() } @@ -891,21 +889,21 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { } self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::PixelStorei(param_name, param_value))) + .send(CanvasMsg::WebGL(WebGLCommand::PixelStorei(param_name, param_value))) .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.3 fn PolygonOffset(&self, factor: f32, units: f32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::PolygonOffset(factor, units))) + .send(CanvasMsg::WebGL(WebGLCommand::PolygonOffset(factor, units))) .unwrap() } // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4 fn Scissor(&self, x: i32, y: i32, width: i32, height: i32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Scissor(x, y, width, height))) + .send(CanvasMsg::WebGL(WebGLCommand::Scissor(x, y, width, height))) .unwrap() } @@ -947,7 +945,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { }; self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform1f(uniform.id(), val))) + .send(CanvasMsg::WebGL(WebGLCommand::Uniform1f(uniform.id(), val))) .unwrap() } @@ -977,7 +975,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { }; self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Uniform4f(uniform.id(), x, y, z, w))) + .send(CanvasMsg::WebGL(WebGLCommand::Uniform4f(uniform.id(), x, y, z, w))) .unwrap() } @@ -1088,7 +1086,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { normalized: bool, stride: i32, offset: i64) { if let constants::FLOAT = data_type { let msg = CanvasMsg::WebGL( - CanvasWebGLMsg::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset as u32)); + WebGLCommand::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset as u32)); self.ipc_renderer.send(msg).unwrap() } else { panic!("VertexAttribPointer: Data Type not supported") @@ -1098,7 +1096,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { // https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.4 fn Viewport(&self, x: i32, y: i32, width: i32, height: i32) { self.ipc_renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::Viewport(x, y, width, height))) + .send(CanvasMsg::WebGL(WebGLCommand::Viewport(x, y, width, height))) .unwrap() } @@ -1118,8 +1116,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { if texture.is_none() { return self.webgl_error(InvalidOperation); } - // TODO(ecoal95): Validate more parameters - + // TODO(emilio): Validate more parameters let source = match source { Some(s) => s, None => return, @@ -1146,7 +1143,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { }; let size = Size2D::new(img.width as i32, img.height as i32); - // TODO(ecoal95): Validate that the format argument is coherent with the image. + // TODO(emilio): Validate that the format argument is coherent with the image. // RGB8 should be easy to support too let mut data = match img.format { PixelFormat::RGBA8 => img.bytes.to_vec(), @@ -1157,7 +1154,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { (data, size) }, - // TODO(ecoal95): Getting canvas data is implemented in CanvasRenderingContext2D, but + // TODO(emilio): Getting canvas data is implemented in CanvasRenderingContext2D, but // we need to refactor it moving it to `HTMLCanvasElement` and supporting WebGLContext ImageDataOrHTMLImageElementOrHTMLCanvasElementOrHTMLVideoElement::HTMLCanvasElement(canvas) => { let canvas = canvas.r(); @@ -1172,8 +1169,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { => unimplemented!(), }; - // TODO(ecoal95): Invert axis, convert colorspace, premultiply alpha if requested - let msg = CanvasWebGLMsg::TexImage2D(target, level, internal_format as i32, + // TODO(emilio): Invert axis, convert colorspace, premultiply alpha if requested + let msg = WebGLCommand::TexImage2D(target, level, internal_format as i32, size.width, size.height, format, data_type, pixels); @@ -1195,17 +1192,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext { pub trait LayoutCanvasWebGLRenderingContextHelpers { #[allow(unsafe_code)] - unsafe fn get_renderer_id(&self) -> usize; - #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg>; } impl LayoutCanvasWebGLRenderingContextHelpers for LayoutJS<WebGLRenderingContext> { #[allow(unsafe_code)] - unsafe fn get_renderer_id(&self) -> usize { - (*self.unsafe_get()).renderer_id - } - #[allow(unsafe_code)] unsafe fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> { (*self.unsafe_get()).ipc_renderer.clone() } diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs index 9c4548f1675..03c39b698b0 100644 --- a/components/script/dom/webglshader.rs +++ b/components/script/dom/webglshader.rs @@ -4,7 +4,7 @@ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl use angle::hl::{BuiltInResources, Output, ShaderValidator}; -use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLResult, WebGLParameter}; +use canvas_traits::CanvasMsg; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::WebGLShaderBinding; use dom::bindings::global::GlobalRef; @@ -15,6 +15,7 @@ use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; use std::sync::{ONCE_INIT, Once}; use util::str::DOMString; +use webrender_traits::{WebGLCommand, WebGLParameter, WebGLResult}; #[derive(Clone, Copy, PartialEq, Debug, JSTraceable, HeapSizeOf)] pub enum ShaderCompilationStatus { @@ -63,7 +64,7 @@ impl WebGLShader { renderer: IpcSender<CanvasMsg>, shader_type: u32) -> Option<Root<WebGLShader>> { let (sender, receiver) = ipc::channel().unwrap(); - renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateShader(shader_type, sender))).unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateShader(shader_type, sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|shader_id| WebGLShader::new(global, renderer, *shader_id, shader_type)) @@ -103,7 +104,7 @@ impl WebGLShader { // NOTE: At this point we should be pretty sure that the compilation in the paint thread // will succeed. // It could be interesting to retrieve the info log from the paint thread though - let msg = CanvasWebGLMsg::CompileShader(self.id, translated_source); + let msg = WebGLCommand::CompileShader(self.id, translated_source); self.renderer.send(CanvasMsg::WebGL(msg)).unwrap(); self.compilation_status.set(ShaderCompilationStatus::Succeeded); }, @@ -122,7 +123,7 @@ impl WebGLShader { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteShader(self.id))); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteShader(self.id))); } } @@ -134,7 +135,7 @@ impl WebGLShader { /// glGetParameter pub fn parameter(&self, param_id: u32) -> WebGLResult<WebGLParameter> { let (sender, receiver) = ipc::channel().unwrap(); - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::GetShaderParameter(self.id, param_id, sender))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::GetShaderParameter(self.id, param_id, sender))).unwrap(); receiver.recv().unwrap() } diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs index e7f645ce235..e40938d84f1 100644 --- a/components/script/dom/webgltexture.rs +++ b/components/script/dom/webgltexture.rs @@ -3,7 +3,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://www.khronos.org/registry/webgl/specs/latest/1.0/webgl.idl -use canvas_traits::{CanvasMsg, CanvasWebGLMsg, WebGLError, WebGLResult}; +use canvas_traits::CanvasMsg; use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants; use dom::bindings::codegen::Bindings::WebGLTextureBinding; use dom::bindings::global::GlobalRef; @@ -12,6 +12,7 @@ use dom::bindings::reflector::reflect_dom_object; use dom::webglobject::WebGLObject; use ipc_channel::ipc::{self, IpcSender}; use std::cell::Cell; +use webrender_traits::{WebGLCommand, WebGLError, WebGLResult}; pub enum TexParameterValue { Float(f32), @@ -43,7 +44,7 @@ impl WebGLTexture { pub fn maybe_new(global: GlobalRef, renderer: IpcSender<CanvasMsg>) -> Option<Root<WebGLTexture>> { let (sender, receiver) = ipc::channel().unwrap(); - renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::CreateTexture(sender))).unwrap(); + renderer.send(CanvasMsg::WebGL(WebGLCommand::CreateTexture(sender))).unwrap(); let result = receiver.recv().unwrap(); result.map(|texture_id| WebGLTexture::new(global, renderer, *texture_id)) @@ -70,7 +71,7 @@ impl WebGLTexture { self.target.set(Some(target)); } - self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::BindTexture(target, self.id))).unwrap(); + self.renderer.send(CanvasMsg::WebGL(WebGLCommand::BindTexture(target, self.id))).unwrap(); Ok(()) } @@ -78,7 +79,7 @@ impl WebGLTexture { pub fn delete(&self) { if !self.is_deleted.get() { self.is_deleted.set(true); - let _ = self.renderer.send(CanvasMsg::WebGL(CanvasWebGLMsg::DeleteTexture(self.id))); + let _ = self.renderer.send(CanvasMsg::WebGL(WebGLCommand::DeleteTexture(self.id))); } } @@ -104,7 +105,7 @@ impl WebGLTexture { constants::NEAREST_MIPMAP_LINEAR | constants::LINEAR_MIPMAP_LINEAR => { self.renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::TexParameteri(target, name, int_value))) + .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value))) .unwrap(); Ok(()) }, @@ -117,7 +118,7 @@ impl WebGLTexture { constants::NEAREST | constants::LINEAR => { self.renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::TexParameteri(target, name, int_value))) + .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value))) .unwrap(); Ok(()) }, @@ -132,7 +133,7 @@ impl WebGLTexture { constants::MIRRORED_REPEAT | constants::REPEAT => { self.renderer - .send(CanvasMsg::WebGL(CanvasWebGLMsg::TexParameteri(target, name, int_value))) + .send(CanvasMsg::WebGL(WebGLCommand::TexParameteri(target, name, int_value))) .unwrap(); Ok(()) }, diff --git a/components/script/dom/webidls/Blob.webidl b/components/script/dom/webidls/Blob.webidl index 5f338a15239..bad890fafdc 100644 --- a/components/script/dom/webidls/Blob.webidl +++ b/components/script/dom/webidls/Blob.webidl @@ -4,11 +4,9 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // http://dev.w3.org/2006/webapi/FileAPI/#dfn-Blob -//[Exposed=Window,Worker][Constructor, -// Constructor(sequence<(ArrayBuffer or ArrayBufferView or Blob or DOMString)> blobParts, -// optional BlobPropertyBag options)] [Constructor, - Constructor(DOMString blobParts, optional BlobPropertyBag options), + Constructor(sequence<(/*ArrayBuffer or ArrayBufferView or */Blob or DOMString)> blobParts, + optional BlobPropertyBag options), Exposed=Window/*,Worker*/] interface Blob { diff --git a/components/script/dom/webidls/BrowserElement.webidl b/components/script/dom/webidls/BrowserElement.webidl index 33f1fa6fd5e..6e658a1b5b7 100644 --- a/components/script/dom/webidls/BrowserElement.webidl +++ b/components/script/dom/webidls/BrowserElement.webidl @@ -54,6 +54,12 @@ dictionary BrowserElementSecurityChangeDetail { boolean mixedContent; }; +dictionary BrowserElementLocationChangeEventDetail { + DOMString uri; + boolean canGoBack; + boolean canGoForward; +}; + dictionary BrowserElementIconChangeEventDetail { DOMString rel; DOMString href; diff --git a/components/script/dom/webidls/DOMTokenList.webidl b/components/script/dom/webidls/DOMTokenList.webidl index c9125285f74..21be3590c0a 100644 --- a/components/script/dom/webidls/DOMTokenList.webidl +++ b/components/script/dom/webidls/DOMTokenList.webidl @@ -18,6 +18,8 @@ interface DOMTokenList { void remove(DOMString... tokens); [Throws] boolean toggle(DOMString token, optional boolean force); + [Throws] + void replace(DOMString token, DOMString newToken); [Pure] attribute DOMString value; diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl index c5c395536ac..9bc5ff64597 100644 --- a/components/script/dom/webidls/Element.webidl +++ b/components/script/dom/webidls/Element.webidl @@ -70,6 +70,10 @@ interface Element : Node { HTMLCollection getElementsByTagName(DOMString localName); HTMLCollection getElementsByTagNameNS(DOMString? namespace, DOMString localName); HTMLCollection getElementsByClassName(DOMString classNames); + [Throws] + Element? insertAdjacentElement(DOMString where_, Element element); + [Throws] + void insertAdjacentText(DOMString where_, DOMString data); }; // http://dev.w3.org/csswg/cssom-view/#extensions-to-the-element-interface diff --git a/components/script/dom/webidls/HTMLAnchorElement.webidl b/components/script/dom/webidls/HTMLAnchorElement.webidl index 6585e1ccc56..bfca9b31b7d 100644 --- a/components/script/dom/webidls/HTMLAnchorElement.webidl +++ b/components/script/dom/webidls/HTMLAnchorElement.webidl @@ -26,7 +26,7 @@ interface HTMLAnchorElement : HTMLElement { // also has obsolete members }; -//HTMLAnchorElement implements HTMLHyperlinkElementUtils; +HTMLAnchorElement implements HTMLHyperlinkElementUtils; // https://html.spec.whatwg.org/multipage/#HTMLAnchorElement-partial partial interface HTMLAnchorElement { diff --git a/components/script/dom/webidls/HTMLHyperlinkElementUtils.webidl b/components/script/dom/webidls/HTMLHyperlinkElementUtils.webidl index c8d7a35493d..0efcea09710 100644 --- a/components/script/dom/webidls/HTMLHyperlinkElementUtils.webidl +++ b/components/script/dom/webidls/HTMLHyperlinkElementUtils.webidl @@ -4,17 +4,23 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ // https://html.spec.whatwg.org/multipage/#htmlhyperlinkelementutils -//[NoInterfaceObject/*, Exposed=Window*/] -//interface HTMLHyperlinkElementUtils { +[NoInterfaceObject/*, Exposed=Window*/] +interface HTMLHyperlinkElementUtils { // stringifier attribute USVString href; + attribute USVString href; // attribute USVString origin; -// attribute USVString protocol; -// attribute USVString username; -// attribute USVString password; -// attribute USVString host; -// attribute USVString hostname; -// attribute USVString port; -// attribute USVString pathname; -// attribute USVString search; -// attribute USVString hash; -//}; + attribute USVString protocol; + attribute USVString username; + attribute USVString password; + attribute USVString host; + attribute USVString hostname; + attribute USVString port; + attribute USVString pathname; + attribute USVString search; + attribute USVString hash; + + // Adding a separate stringifier method until + // https://github.com/servo/servo/issues/7590 adds attribute stringifier + // support. + stringifier; +}; diff --git a/components/script/dom/webidls/Navigator.webidl b/components/script/dom/webidls/Navigator.webidl index c23415aa094..50f695279ff 100644 --- a/components/script/dom/webidls/Navigator.webidl +++ b/components/script/dom/webidls/Navigator.webidl @@ -36,5 +36,6 @@ interface NavigatorBluetooth { [NoInterfaceObject/*, Exposed=Window,Worker*/] interface NavigatorLanguage { readonly attribute DOMString language; + // https://github.com/servo/servo/issues/10073 //readonly attribute DOMString[] languages; }; diff --git a/components/script/dom/webidls/TestBinding.webidl b/components/script/dom/webidls/TestBinding.webidl index 269114dbf80..9047833bfa8 100644 --- a/components/script/dom/webidls/TestBinding.webidl +++ b/components/script/dom/webidls/TestBinding.webidl @@ -29,6 +29,7 @@ dictionary TestDictionary { any anyValue; object objectValue; TestDictionaryDefaults dict; + sequence<TestDictionaryDefaults> seqDict; }; dictionary TestDictionaryDefaults { @@ -398,4 +399,5 @@ interface TestBinding { static attribute boolean booleanAttributeStatic; static void receiveVoidStatic(); + boolean BooleanMozPreference(DOMString pref_name); }; diff --git a/components/script/dom/webidls/ValidityState.webidl b/components/script/dom/webidls/ValidityState.webidl index c6f9c7ba0e2..7ed0167b010 100644 --- a/components/script/dom/webidls/ValidityState.webidl +++ b/components/script/dom/webidls/ValidityState.webidl @@ -5,15 +5,15 @@ // https://html.spec.whatwg.org/multipage/#validitystate interface ValidityState { - //readonly attribute boolean valueMissing; - //readonly attribute boolean typeMismatch; - //readonly attribute boolean patternMismatch; - //readonly attribute boolean tooLong; - //readonly attribute boolean tooShort; - //readonly attribute boolean rangeUnderflow; - //readonly attribute boolean rangeOverflow; - //readonly attribute boolean stepMismatch; - //readonly attribute boolean badInput; - //readonly attribute boolean customError; - //readonly attribute boolean valid; + readonly attribute boolean valueMissing; + readonly attribute boolean typeMismatch; + readonly attribute boolean patternMismatch; + readonly attribute boolean tooLong; + readonly attribute boolean tooShort; + readonly attribute boolean rangeUnderflow; + readonly attribute boolean rangeOverflow; + readonly attribute boolean stepMismatch; + readonly attribute boolean badInput; + readonly attribute boolean customError; + readonly attribute boolean valid; }; diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index df7d1f92de7..a8b55cf8c06 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -996,7 +996,7 @@ impl Window { page_clip_rect: self.page_clip_rect.get(), }, document: self.Document().upcast::<Node>().to_trusted_node_address(), - document_stylesheets: document.stylesheets().clone(), + document_stylesheets: document.stylesheets(), stylesheets_changed: stylesheets_changed, window_size: window_size, script_join_chan: join_chan, @@ -1021,7 +1021,11 @@ impl Window { debug!("script: layout joined"); - self.pending_reflow_count.set(0); + // Pending reflows require display, so only reset the pending reflow count if this reflow + // was to be displayed. + if goal == ReflowGoal::ForDisplay { + self.pending_reflow_count.set(0); + } if let Some(marker) = marker { self.emit_timeline_marker(marker.end()); @@ -1056,7 +1060,7 @@ impl Window { // When all these conditions are met, notify the constellation // that this pipeline is ready to write the image (from the script thread // perspective at least). - if opts::get().output_file.is_some() && for_display { + if (opts::get().output_file.is_some() || opts::get().exit_after_load) && for_display { let document = self.Document(); // Checks if the html element has reftest-wait attribute present. @@ -1104,7 +1108,7 @@ impl Window { pub fn hit_test_query(&self, hit_test_request: Point2D<f32>, update_cursor: bool) -> Option<UntrustedNodeAddress> { - self.reflow(ReflowGoal::ForDisplay, + self.reflow(ReflowGoal::ForScriptQuery, ReflowQueryType::HitTestQuery(hit_test_request, update_cursor), ReflowReason::Query); self.layout_rpc.hit_test().node_address diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs index 7ab29945961..fcc6bbdd151 100644 --- a/components/script/dom/workerglobalscope.rs +++ b/components/script/dom/workerglobalscope.rs @@ -55,8 +55,8 @@ pub struct WorkerGlobalScope { eventtarget: EventTarget, worker_id: WorkerId, worker_url: Url, - #[ignore_heap_size_of = "Defined in std"] - runtime: Rc<Runtime>, + #[ignore_heap_size_of = "Defined in js"] + runtime: Runtime, next_worker_id: Cell<WorkerId>, #[ignore_heap_size_of = "Defined in std"] resource_thread: ResourceThread, @@ -94,7 +94,7 @@ pub struct WorkerGlobalScope { impl WorkerGlobalScope { pub fn new_inherited(init: WorkerGlobalScopeInit, worker_url: Url, - runtime: Rc<Runtime>, + runtime: Runtime, from_devtools_receiver: Receiver<DevtoolScriptControlMsg>, timer_event_chan: IpcSender<TimerEvent>) -> WorkerGlobalScope { diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 7de3d956437..20a729c70c0 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -62,6 +62,7 @@ use time; use timers::{OneshotTimerCallback, OneshotTimerHandle}; use url::Url; use url::percent_encoding::{utf8_percent_encode, USERNAME_ENCODE_SET, PASSWORD_ENCODE_SET}; +use util::prefs; use util::str::DOMString; pub type SendParam = BlobOrStringOrURLSearchParams; @@ -118,7 +119,7 @@ pub struct XMLHttpRequest { timeout: Cell<u32>, with_credentials: Cell<bool>, upload: JS<XMLHttpRequestUpload>, - response_url: String, + response_url: DOMRefCell<String>, status: Cell<u16>, status_text: DOMRefCell<ByteString>, response: DOMRefCell<ByteString>, @@ -160,7 +161,7 @@ impl XMLHttpRequest { timeout: Cell::new(0u32), with_credentials: Cell::new(false), upload: JS::from_rooted(&XMLHttpRequestUpload::new(global)), - response_url: String::from(""), + response_url: DOMRefCell::new(String::from("")), status: Cell::new(0), status_text: DOMRefCell::new(ByteString::new(vec!())), response: DOMRefCell::new(ByteString::new(vec!())), @@ -691,7 +692,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { // https://xhr.spec.whatwg.org/#the-responseurl-attribute fn ResponseURL(&self) -> USVString { - USVString(self.response_url.clone()) + USVString(self.response_url.borrow().clone()) } // https://xhr.spec.whatwg.org/#the-status-attribute @@ -866,16 +867,37 @@ impl XMLHttpRequest { fn process_headers_available(&self, cors_request: Option<CORSRequest>, gen_id: GenerationId, metadata: Metadata) -> Result<(), Error> { - if let Some(ref req) = cors_request { - match metadata.headers { - Some(ref h) if allow_cross_origin_request(req, h) => {}, - _ => { - self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network)); - return Err(Error::Network); + let bypass_cross_origin_check = { + // We want to be able to do cross-origin requests in browser.html. + // If the XHR happens in a top level window and the mozbrowser + // preference is enabled, we allow bypassing the CORS check. + // This is a temporary measure until we figure out Servo privilege + // story. See https://github.com/servo/servo/issues/9582 + if let GlobalRoot::Window(win) = self.global() { + let is_root_pipeline = win.parent_info().is_none(); + let is_mozbrowser_enabled = prefs::get_pref("dom.mozbrowser.enabled").as_boolean().unwrap_or(false); + is_root_pipeline && is_mozbrowser_enabled + } else { + false + } + }; + + if !bypass_cross_origin_check { + if let Some(ref req) = cors_request { + match metadata.headers { + Some(ref h) if allow_cross_origin_request(req, h) => {}, + _ => { + self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network)); + return Err(Error::Network); + } } } + } else { + debug!("Bypassing cross origin check"); } + *self.response_url.borrow_mut() = metadata.final_url.serialize_no_fragment(); + // XXXManishearth Clear cache entries in case of a network error self.process_partial_response(XHRProgress::HeadersReceived(gen_id, metadata.headers, @@ -980,6 +1002,7 @@ impl XMLHttpRequest { // Subsubsteps 5-7 self.send_flag.set(false); + self.change_ready_state(XMLHttpRequestState::Done); return_if_fetch_was_terminated!(); // Subsubsteps 10-12 @@ -1150,7 +1173,7 @@ impl XMLHttpRequest { _ => { return None; } } // Step 9 - temp_doc.set_encoding_name(DOMString::from(charset.name())); + temp_doc.set_encoding(charset); // Step 13 self.response_xml.set(Some(temp_doc.r())); return self.response_xml.get(); diff --git a/components/script/lib.rs b/components/script/lib.rs index 99a3bb7ce9b..fa6dc8a385e 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -58,6 +58,7 @@ extern crate phf; #[macro_use] extern crate profile_traits; extern crate rand; +extern crate range; extern crate ref_filter_map; extern crate ref_slice; extern crate regex; @@ -75,6 +76,7 @@ extern crate url; #[macro_use] extern crate util; extern crate uuid; +extern crate webrender_traits; extern crate websocket; extern crate xml5ever; diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 9cfc2627786..c591cd955a3 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -321,13 +321,11 @@ pub struct SendableMainThreadScriptChan(pub Sender<CommonScriptMsg>); impl ScriptChan for SendableMainThreadScriptChan { fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let SendableMainThreadScriptChan(ref chan) = *self; - chan.send(msg).map_err(|_| ()) + self.0.send(msg).map_err(|_| ()) } fn clone(&self) -> Box<ScriptChan + Send> { - let SendableMainThreadScriptChan(ref chan) = *self; - box SendableMainThreadScriptChan((*chan).clone()) + box SendableMainThreadScriptChan((&self.0).clone()) } } @@ -345,13 +343,11 @@ pub struct MainThreadScriptChan(pub Sender<MainThreadScriptMsg>); impl ScriptChan for MainThreadScriptChan { fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let MainThreadScriptChan(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) } fn clone(&self) -> Box<ScriptChan + Send> { - let MainThreadScriptChan(ref chan) = *self; - box MainThreadScriptChan((*chan).clone()) + box MainThreadScriptChan((&self.0).clone()) } } @@ -552,6 +548,7 @@ impl ScriptThreadFactory for ScriptThread { let reporter_name = format!("script-reporter-{}", id); mem_profiler_chan.run_with_memory_reporting(|| { script_thread.start(); + let _ = script_thread.compositor.borrow_mut().send(ScriptToCompositorMsg::Exited); let _ = script_thread.content_process_shutdown_chan.send(()); }, reporter_name, channel_for_reporter, CommonScriptMsg::CollectReports); diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs index d60ce7de93d..9676ade6ded 100644 --- a/components/script/task_source/dom_manipulation.rs +++ b/components/script/task_source/dom_manipulation.rs @@ -16,13 +16,11 @@ pub struct DOMManipulationTaskSource(pub Sender<MainThreadScriptMsg>); impl TaskSource<DOMManipulationTask> for DOMManipulationTaskSource { fn queue(&self, msg: DOMManipulationTask) -> Result<(), ()> { - let DOMManipulationTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ()) + self.0.send(MainThreadScriptMsg::DOMManipulation(msg)).map_err(|_| ()) } fn clone(&self) -> Box<TaskSource<DOMManipulationTask> + Send> { - let DOMManipulationTaskSource(ref chan) = *self; - box DOMManipulationTaskSource((*chan).clone()) + box DOMManipulationTaskSource((&self.0).clone()) } } diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs index e4afad34b4b..30e9530a76d 100644 --- a/components/script/task_source/file_reading.rs +++ b/components/script/task_source/file_reading.rs @@ -10,12 +10,10 @@ pub struct FileReadingTaskSource(pub Sender<MainThreadScriptMsg>); impl ScriptChan for FileReadingTaskSource { fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let FileReadingTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) } fn clone(&self) -> Box<ScriptChan + Send> { - let FileReadingTaskSource(ref chan) = *self; - box FileReadingTaskSource((*chan).clone()) + box FileReadingTaskSource((&self.0).clone()) } } diff --git a/components/script/task_source/history_traversal.rs b/components/script/task_source/history_traversal.rs index 0916c121345..c2d276e6eec 100644 --- a/components/script/task_source/history_traversal.rs +++ b/components/script/task_source/history_traversal.rs @@ -10,12 +10,10 @@ pub struct HistoryTraversalTaskSource(pub Sender<MainThreadScriptMsg>); impl ScriptChan for HistoryTraversalTaskSource { fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let HistoryTraversalTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) } fn clone(&self) -> Box<ScriptChan + Send> { - let HistoryTraversalTaskSource(ref chan) = *self; - box HistoryTraversalTaskSource((*chan).clone()) + box HistoryTraversalTaskSource((&self.0).clone()) } } diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs index 8ebeecdb965..83160468395 100644 --- a/components/script/task_source/networking.rs +++ b/components/script/task_source/networking.rs @@ -10,12 +10,10 @@ pub struct NetworkingTaskSource(pub Sender<MainThreadScriptMsg>); impl ScriptChan for NetworkingTaskSource { fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let NetworkingTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) } fn clone(&self) -> Box<ScriptChan + Send> { - let NetworkingTaskSource(ref chan) = *self; - box NetworkingTaskSource((*chan).clone()) + box NetworkingTaskSource((&self.0).clone()) } } diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs index 7912eac720d..254b0d008d1 100644 --- a/components/script/task_source/user_interaction.rs +++ b/components/script/task_source/user_interaction.rs @@ -10,12 +10,10 @@ pub struct UserInteractionTaskSource(pub Sender<MainThreadScriptMsg>); impl ScriptChan for UserInteractionTaskSource { fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> { - let UserInteractionTaskSource(ref chan) = *self; - chan.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) + self.0.send(MainThreadScriptMsg::Common(msg)).map_err(|_| ()) } fn clone(&self) -> Box<ScriptChan + Send> { - let UserInteractionTaskSource(ref chan) = *self; - box UserInteractionTaskSource((*chan).clone()) + box UserInteractionTaskSource((&self.0).clone()) } } diff --git a/components/script/textinput.rs b/components/script/textinput.rs index 35b49ee57a4..cc5936d42b0 100644 --- a/components/script/textinput.rs +++ b/components/script/textinput.rs @@ -8,6 +8,7 @@ use clipboard_provider::ClipboardProvider; use dom::keyboardevent::{KeyboardEvent, key_value}; use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER}; use msg::constellation_msg::{Key, KeyModifiers}; +use range::Range; use std::borrow::ToOwned; use std::cmp::{max, min}; use std::default::Default; @@ -20,7 +21,7 @@ pub enum Selection { NotSelected } -#[derive(JSTraceable, Copy, Clone, HeapSizeOf)] +#[derive(JSTraceable, Copy, Clone, HeapSizeOf, PartialEq)] pub struct TextPoint { /// 0-based line number pub line: usize, @@ -123,7 +124,7 @@ impl<T: ClipboardProvider> TextInput<T> { /// Remove a character at the current editing point pub fn delete_char(&mut self, dir: Direction) { - if self.selection_begin.is_none() { + if self.selection_begin.is_none() || self.selection_begin == Some(self.edit_point) { self.adjust_horizontal_by_one(dir, Selection::Selected); } self.replace_selection(DOMString::new()); @@ -154,6 +155,15 @@ impl<T: ClipboardProvider> TextInput<T> { }) } + pub fn get_absolute_selection_range(&self) -> Range<usize> { + match self.get_sorted_selection() { + Some((begin, _end)) => + Range::new(self.get_absolute_point_for_text_point(&begin), self.selection_len()), + None => + Range::new(self.get_absolute_insertion_point(), 0) + } + } + pub fn get_selection_text(&self) -> Option<String> { self.get_sorted_selection().map(|(begin, end)| { if begin.line != end.line { |