diff options
Diffstat (limited to 'components/script/dom')
58 files changed, 1045 insertions, 900 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 1d054d03f14..c71e0f354dc 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -5907,8 +5907,8 @@ pub trait %(derivedTrait)s: Sized { impl %(name)sCast { #[inline] - /// Downcast an instance of a base class of `${name}` to an instance of - /// `${name}`, if it internally is an instance of `${name}` + /// Downcast an instance of a base class of `%(name)s` to an instance of + /// `%(name)s`, if it internally is an instance of `%(name)s` pub fn to_ref<T: %(derivedTrait)s + Reflectable>(base: &T) -> Option<&%(name)s> { match base.%(methodName)s() { true => Some(unsafe { mem::transmute(base) }), diff --git a/components/script/dom/bindings/conversions.rs b/components/script/dom/bindings/conversions.rs index 3805a0e76d3..eb9c1c81305 100644 --- a/components/script/dom/bindings/conversions.rs +++ b/components/script/dom/bindings/conversions.rs @@ -177,6 +177,7 @@ fn clamp_to<D>(d: f64) -> D } } +//http://heycam.github.io/webidl/#es-void impl ToJSValConvertible for () { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(UndefinedValue()); @@ -217,12 +218,14 @@ fn convert_int_from_jsval<T, M>(cx: *mut JSContext, value: HandleValue, } } +//http://heycam.github.io/webidl/#es-boolean impl ToJSValConvertible for bool { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(BooleanValue(*self)); } } +//http://heycam.github.io/webidl/#es-boolean impl FromJSValConvertible for bool { type Config = (); fn from_jsval(_cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<bool, ()> { @@ -230,12 +233,14 @@ impl FromJSValConvertible for bool { } } +//http://heycam.github.io/webidl/#es-byte impl ToJSValConvertible for i8 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(Int32Value(*self as i32)); } } +//http://heycam.github.io/webidl/#es-byte impl FromJSValConvertible for i8 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<i8, ()> { @@ -243,12 +248,14 @@ impl FromJSValConvertible for i8 { } } +//http://heycam.github.io/webidl/#es-octet impl ToJSValConvertible for u8 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(Int32Value(*self as i32)); } } +//http://heycam.github.io/webidl/#es-octet impl FromJSValConvertible for u8 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<u8, ()> { @@ -256,12 +263,14 @@ impl FromJSValConvertible for u8 { } } +//http://heycam.github.io/webidl/#es-short impl ToJSValConvertible for i16 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(Int32Value(*self as i32)); } } +//http://heycam.github.io/webidl/#es-short impl FromJSValConvertible for i16 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<i16, ()> { @@ -269,12 +278,14 @@ impl FromJSValConvertible for i16 { } } +//http://heycam.github.io/webidl/#es-unsigned-short impl ToJSValConvertible for u16 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(Int32Value(*self as i32)); } } +//http://heycam.github.io/webidl/#es-unsigned-short impl FromJSValConvertible for u16 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<u16, ()> { @@ -282,12 +293,14 @@ impl FromJSValConvertible for u16 { } } +//http://heycam.github.io/webidl/#es-long impl ToJSValConvertible for i32 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(Int32Value(*self)); } } +//http://heycam.github.io/webidl/#es-long impl FromJSValConvertible for i32 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<i32, ()> { @@ -295,12 +308,14 @@ impl FromJSValConvertible for i32 { } } +//http://heycam.github.io/webidl/#es-unsigned-long impl ToJSValConvertible for u32 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { rval.set(UInt32Value(*self)); } } +//http://heycam.github.io/webidl/#es-unsigned-long impl FromJSValConvertible for u32 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<u32, ()> { @@ -308,6 +323,7 @@ impl FromJSValConvertible for u32 { } } +//http://heycam.github.io/webidl/#es-long-long impl ToJSValConvertible for i64 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { unsafe { @@ -316,6 +332,7 @@ impl ToJSValConvertible for i64 { } } +//http://heycam.github.io/webidl/#es-long-long impl FromJSValConvertible for i64 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<i64, ()> { @@ -323,6 +340,7 @@ impl FromJSValConvertible for i64 { } } +//http://heycam.github.io/webidl/#es-unsigned-long-long impl ToJSValConvertible for u64 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { unsafe { @@ -331,6 +349,7 @@ impl ToJSValConvertible for u64 { } } +//http://heycam.github.io/webidl/#es-unsigned-long-long impl FromJSValConvertible for u64 { type Config = ConversionBehavior; fn from_jsval(cx: *mut JSContext, val: HandleValue, option: ConversionBehavior) -> Result<u64, ()> { @@ -338,6 +357,7 @@ impl FromJSValConvertible for u64 { } } +//http://heycam.github.io/webidl/#es-float impl ToJSValConvertible for f32 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { unsafe { @@ -346,6 +366,7 @@ impl ToJSValConvertible for f32 { } } +//http://heycam.github.io/webidl/#es-float impl FromJSValConvertible for f32 { type Config = (); fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<f32, ()> { @@ -354,6 +375,7 @@ impl FromJSValConvertible for f32 { } } +//http://heycam.github.io/webidl/#es-double impl ToJSValConvertible for f64 { fn to_jsval(&self, _cx: *mut JSContext, rval: MutableHandleValue) { unsafe { @@ -362,6 +384,7 @@ impl ToJSValConvertible for f64 { } } +//http://heycam.github.io/webidl/#es-double impl FromJSValConvertible for f64 { type Config = (); fn from_jsval(cx: *mut JSContext, val: HandleValue, _option: ()) -> Result<f64, ()> { @@ -407,6 +430,7 @@ impl ToJSValConvertible for str { } } +//http://heycam.github.io/webidl/#es-DOMString impl ToJSValConvertible for DOMString { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) { (**self).to_jsval(cx, rval); @@ -484,6 +508,7 @@ pub fn jsid_to_str(cx: *mut JSContext, id: HandleId) -> DOMString { } } +//http://heycam.github.io/webidl/#es-DOMString impl FromJSValConvertible for DOMString { type Config = StringificationBehavior; fn from_jsval(cx: *mut JSContext, value: HandleValue, @@ -504,12 +529,14 @@ impl FromJSValConvertible for DOMString { } } +//http://heycam.github.io/webidl/#es-USVString impl ToJSValConvertible for USVString { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) { self.0.to_jsval(cx, rval); } } +//http://heycam.github.io/webidl/#es-USVString impl FromJSValConvertible for USVString { type Config = (); fn from_jsval(cx: *mut JSContext, value: HandleValue, _: ()) @@ -533,6 +560,7 @@ impl FromJSValConvertible for USVString { } } +//http://heycam.github.io/webidl/#es-ByteString impl ToJSValConvertible for ByteString { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) { unsafe { @@ -546,6 +574,7 @@ impl ToJSValConvertible for ByteString { } } +//http://heycam.github.io/webidl/#es-ByteString impl FromJSValConvertible for ByteString { type Config = (); fn from_jsval(cx: *mut JSContext, value: HandleValue, _option: ()) -> Result<ByteString, ()> { @@ -586,6 +615,7 @@ impl FromJSValConvertible for ByteString { } } + impl ToJSValConvertible for Reflector { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) { let obj = self.get_jsobject().get(); @@ -770,6 +800,7 @@ impl<T: FromJSValConvertible> FromJSValConvertible for Option<T> { } } +//http://heycam.github.io/webidl/#es-object impl ToJSValConvertible for *mut JSObject { fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) { rval.set(ObjectOrNullValue(*self)); diff --git a/components/script/dom/bindings/js.rs b/components/script/dom/bindings/js.rs index aea80d88431..1ef1d93a86d 100644 --- a/components/script/dom/bindings/js.rs +++ b/components/script/dom/bindings/js.rs @@ -96,6 +96,16 @@ impl<T: Reflectable> JS<T> { } } +impl<T: Reflectable> Deref for JS<T> { + type Target = T; + + fn deref(&self) -> &T { + // We can only have &JS<T> from a rooted thing, so it's safe to deref + // it to &T. + unsafe { &**self.ptr } + } +} + impl<T: Reflectable> JSTraceable for JS<T> { fn trace(&self, trc: *mut JSTracer) { trace_reflector(trc, "", unsafe { (**self.ptr).reflector() }); diff --git a/components/script/dom/bindings/utils.rs b/components/script/dom/bindings/utils.rs index 7b430f1340e..af028ebfcbc 100644 --- a/components/script/dom/bindings/utils.rs +++ b/components/script/dom/bindings/utils.rs @@ -222,20 +222,21 @@ pub fn do_create_interface_objects(cx: *mut JSContext, dom_class: Option<&'static DOMClass>, members: &'static NativeProperties, rval: MutableHandleObject) { + assert!(rval.get().is_null()); if let Some(proto_class) = proto_class { create_interface_prototype_object(cx, proto_proto, proto_class, members, rval); - } - if !rval.get().is_null() { - let dom_class_ptr = match dom_class { - Some(dom_class) => dom_class as *const DOMClass as *const libc::c_void, - None => ptr::null() as *const libc::c_void, - }; + if !rval.get().is_null() { + let dom_class_ptr = match dom_class { + Some(dom_class) => dom_class as *const DOMClass as *const libc::c_void, + None => ptr::null() as *const libc::c_void, + }; - unsafe { - JS_SetReservedSlot(rval.get(), DOM_PROTO_INSTANCE_CLASS_SLOT, - PrivateValue(dom_class_ptr)); + unsafe { + JS_SetReservedSlot(rval.get(), DOM_PROTO_INSTANCE_CLASS_SLOT, + PrivateValue(dom_class_ptr)); + } } } diff --git a/components/script/dom/browsercontext.rs b/components/script/dom/browsercontext.rs index af2bfbdc81e..60dbdc5523e 100644 --- a/components/script/dom/browsercontext.rs +++ b/components/script/dom/browsercontext.rs @@ -44,17 +44,16 @@ impl BrowsingContext { } } - pub fn active_document(&self) -> Root<Document> { - self.history[self.active_index].document.root() + pub fn active_document(&self) -> &Document { + &*self.history[self.active_index].document } - pub fn active_window(&self) -> Root<Window> { - let doc = self.active_document(); - doc.r().window() + pub fn active_window(&self) -> &Window { + self.active_document().window() } - pub fn frame_element(&self) -> Option<Root<Element>> { - self.frame_element.as_ref().map(JS::root) + pub fn frame_element(&self) -> Option<&Element> { + self.frame_element.as_ref().map(|element| &**element) } pub fn window_proxy(&self) -> *mut JSObject { @@ -64,8 +63,8 @@ impl BrowsingContext { #[allow(unsafe_code)] pub fn create_window_proxy(&mut self) { - let win = self.active_window(); - let win = win.r(); + // We inline self.active_window() because we can't borrow *self here. + let win = self.history[self.active_index].document.window(); let WindowProxyHandler(handler) = win.windowproxy_handler(); assert!(!handler.is_null()); diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 175cc68ea9d..8fe2fee79c5 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -232,8 +232,8 @@ impl Document { } #[inline] - pub fn window(&self) -> Root<Window> { - self.window.root() + pub fn window(&self) -> &Window { + &*self.window } #[inline] @@ -248,13 +248,11 @@ impl Document { // https://html.spec.whatwg.org/multipage/#fully-active pub fn is_fully_active(&self) -> bool { - let window = self.window.root(); - let window = window.r(); - let browsing_context = window.browsing_context(); + let browsing_context = self.window.browsing_context(); let browsing_context = browsing_context.as_ref().unwrap(); let active_document = browsing_context.active_document(); - if self != active_document.r() { + if self != active_document { return false; } // FIXME: It should also check whether the browser context is top-level or not @@ -308,9 +306,7 @@ impl Document { self.quirks_mode.set(mode); if mode == Quirks { - let window = self.window.root(); - let window = window.r(); - let LayoutChan(ref layout_chan) = window.layout_chan(); + let LayoutChan(ref layout_chan) = self.window.layout_chan(); layout_chan.send(Msg::SetQuirksMode).unwrap(); } } @@ -336,10 +332,9 @@ impl Document { } self.reflow_timeout.set(None); - let window = self.window.root(); - window.r().reflow(ReflowGoal::ForDisplay, - ReflowQueryType::NoQuery, - ReflowReason::RefreshTick); + self.window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::RefreshTick); } } @@ -449,8 +444,7 @@ impl Document { None => return None, }; let root = NodeCast::from_ref(root); - let win = self.window.root(); - let address = match win.r().layout().hit_test(root.to_trusted_node_address(), *point) { + let address = match self.window.layout().hit_test(root.to_trusted_node_address(), *point) { Ok(HitTestResponse(node_address)) => Some(node_address), Err(()) => { debug!("layout query error"); @@ -467,8 +461,7 @@ impl Document { None => return vec!(), }; let root = NodeCast::from_ref(root); - let win = self.window.root(); - match win.r().layout().mouse_over(root.to_trusted_node_address(), *point) { + match self.window.layout().mouse_over(root.to_trusted_node_address(), *point) { Ok(MouseOverResponse(node_address)) => node_address, Err(()) => vec!(), } @@ -478,8 +471,7 @@ impl Document { pub fn set_ready_state(&self, state: DocumentReadyState) { self.ready_state.set(state); - let window = self.window.root(); - let event = Event::new(GlobalRef::Window(window.r()), "readystatechange".to_owned(), + let event = Event::new(GlobalRef::Window(&self.window), "readystatechange".to_owned(), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable); let target = EventTargetCast::from_ref(self); @@ -516,22 +508,19 @@ impl Document { //TODO: dispatch blur, focus, focusout, and focusin events if let Some(ref elem) = self.focused.get_rooted() { - let node = NodeCast::from_ref(elem.r()); - node.set_focus_state(false); + elem.set_focus_state(false); } self.focused.set(self.possibly_focused.get().r()); if let Some(ref elem) = self.focused.get_rooted() { - let node = NodeCast::from_ref(elem.r()); - node.set_focus_state(true); + elem.set_focus_state(true); // Update the focus state for all elements in the focus chain. // https://html.spec.whatwg.org/multipage/#focus-chain if focus_type == FocusType::Element { - let window = self.window.root(); - let ConstellationChan(ref chan) = window.r().constellation_chan(); - let event = ConstellationMsg::Focus(window.r().pipeline()); + let ConstellationChan(ref chan) = self.window.constellation_chan(); + let event = ConstellationMsg::Focus(self.window.pipeline()); chan.send(event).unwrap(); } } @@ -548,8 +537,6 @@ impl Document { /// Sends this document's title to the compositor. pub fn send_title_to_compositor(&self) { let window = self.window(); - // FIXME(https://github.com/rust-lang/rust/issues/23338) - let window = window.r(); let compositor = window.compositor(); compositor.send(ScriptToCompositorMsg::SetTitle(window.pipeline(), Some(self.Title()))).unwrap(); } @@ -593,24 +580,22 @@ impl Document { debug!("{} on {:?}", mouse_event_type_string, node.debug_str()); // Prevent click event if form control element is disabled. if let MouseEventType::Click = mouse_event_type { - if node.click_event_filter_by_disabled_state() { + if el.click_event_filter_by_disabled_state() { return; } self.begin_focus_transaction(); } - let window = self.window.root(); - // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#event-type-click let x = point.x as i32; let y = point.y as i32; let clickCount = 1; - let event = MouseEvent::new(window.r(), + let event = MouseEvent::new(&self.window, mouse_event_type_string, EventBubbles::Bubbles, EventCancelable::Cancelable, - Some(window.r()), + Some(&self.window), clickCount, x, y, x, y, false, false, false, false, @@ -632,7 +617,9 @@ impl Document { if let MouseEventType::Click = mouse_event_type { self.commit_focus_transaction(FocusType::Element); } - window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::MouseEvent); + self.window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::MouseEvent); } pub fn fire_mouse_event(&self, @@ -642,13 +629,11 @@ impl Document { let x = point.x.to_i32().unwrap_or(0); let y = point.y.to_i32().unwrap_or(0); - let window = self.window.root(); - - let mouse_event = MouseEvent::new(window.r(), + let mouse_event = MouseEvent::new(&self.window, event_name, EventBubbles::Bubbles, EventCancelable::Cancelable, - Some(window.r()), + Some(&self.window), 0i32, x, y, x, y, false, false, false, false, @@ -661,15 +646,16 @@ impl Document { pub fn handle_mouse_move_event(&self, js_runtime: *mut JSRuntime, point: Point2D<f32>, - prev_mouse_over_targets: &mut RootedVec<JS<Node>>) { + prev_mouse_over_targets: &mut RootedVec<JS<Element>>) { // Build a list of elements that are currently under the mouse. let mouse_over_addresses = self.get_nodes_under_mouse(&point); - let mut mouse_over_targets: RootedVec<JS<Node>> = RootedVec::new(); + let mut mouse_over_targets: RootedVec<JS<Element>> = RootedVec::new(); for node_address in &mouse_over_addresses { let node = node::from_untrusted_node_address(js_runtime, *node_address); mouse_over_targets.push(node.r().inclusive_ancestors() .find(|node| node.r().is_element()) - .map(|node| JS::from_rooted(&node)).unwrap()); + .map(|node| JS::from_ref(ElementCast::to_ref(node.r()).unwrap())) + .unwrap()); }; // Remove hover from any elements in the previous list that are no longer @@ -715,10 +701,9 @@ impl Document { prev_mouse_over_targets.clear(); prev_mouse_over_targets.append(&mut *mouse_over_targets); - let window = self.window.root(); - window.r().reflow(ReflowGoal::ForDisplay, - ReflowQueryType::NoQuery, - ReflowReason::MouseEvent); + self.window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::MouseEvent); } /// The entry point for all key processing for web content @@ -727,14 +712,13 @@ impl Document { state: KeyState, modifiers: KeyModifiers, compositor: &mut IpcSender<ScriptToCompositorMsg>) { - let window = self.window.root(); let focused = self.get_focused_element(); let body = self.GetBody(); let target = match (&focused, &body) { (&Some(ref focused), _) => EventTargetCast::from_ref(focused.r()), (&None, &Some(ref body)) => EventTargetCast::from_ref(body.r()), - (&None, &None) => EventTargetCast::from_ref(window.r()), + (&None, &None) => EventTargetCast::from_ref(&*self.window), }; let ctrl = modifiers.contains(CONTROL); @@ -751,8 +735,8 @@ impl Document { let props = KeyboardEvent::key_properties(key, modifiers); - let keyevent = KeyboardEvent::new(window.r(), ev_type, true, true, - Some(window.r()), 0, Some(key), + let keyevent = KeyboardEvent::new(&self.window, ev_type, true, true, + Some(&self.window), 0, Some(key), props.key_string.to_owned(), props.code.to_owned(), props.location, is_repeating, is_composing, ctrl, alt, shift, meta, @@ -764,8 +748,8 @@ impl Document { // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keys-cancelable-keys if state != KeyState::Released && props.is_printable() && !prevented { // https://dvcs.w3.org/hg/dom3events/raw-file/tip/html/DOM3-Events.html#keypress-event-order - let event = KeyboardEvent::new(window.r(), "keypress".to_owned(), - true, true, Some(window.r()), 0, Some(key), + let event = KeyboardEvent::new(&self.window, "keypress".to_owned(), + true, true, Some(&self.window), 0, Some(key), props.key_string.to_owned(), props.code.to_owned(), props.location, is_repeating, is_composing, ctrl, alt, shift, meta, @@ -805,7 +789,9 @@ impl Document { _ => () } - window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::KeyEvent); + self.window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::KeyEvent); } pub fn node_from_nodes_and_strings(&self, nodes: Vec<NodeOrString>) @@ -857,10 +843,8 @@ impl Document { pub fn trigger_mozbrowser_event(&self, event: MozBrowserEvent) { if htmliframeelement::mozbrowser_enabled() { - let window = self.window.root(); - - if let Some((containing_pipeline_id, subpage_id)) = window.r().parent_info() { - let ConstellationChan(ref chan) = window.r().constellation_chan(); + if let Some((containing_pipeline_id, subpage_id)) = self.window.parent_info() { + let ConstellationChan(ref chan) = self.window.constellation_chan(); let event = ConstellationMsg::MozBrowserEvent(containing_pipeline_id, subpage_id, event); @@ -871,16 +855,14 @@ impl Document { /// https://html.spec.whatwg.org/multipage/#dom-window-requestanimationframe pub fn request_animation_frame(&self, callback: Box<FnBox(f64)>) -> u32 { - let window = self.window.root(); - let window = window.r(); let ident = self.animation_frame_ident.get() + 1; self.animation_frame_ident.set(ident); self.animation_frame_list.borrow_mut().insert(ident, callback); // TODO: Should tick animation only when document is visible - let ConstellationChan(ref chan) = window.constellation_chan(); - let event = ConstellationMsg::ChangeRunningAnimationsState(window.pipeline(), + let ConstellationChan(ref chan) = self.window.constellation_chan(); + let event = ConstellationMsg::ChangeRunningAnimationsState(self.window.pipeline(), AnimationState::AnimationCallbacksPresent); chan.send(event).unwrap(); @@ -891,10 +873,8 @@ impl Document { pub fn cancel_animation_frame(&self, ident: u32) { self.animation_frame_list.borrow_mut().remove(&ident); if self.animation_frame_list.borrow().is_empty() { - let window = self.window.root(); - let window = window.r(); - let ConstellationChan(ref chan) = window.constellation_chan(); - let event = ConstellationMsg::ChangeRunningAnimationsState(window.pipeline(), + let ConstellationChan(ref chan) = self.window.constellation_chan(); + let event = ConstellationMsg::ChangeRunningAnimationsState(self.window.pipeline(), AnimationState::NoAnimationCallbacksPresent); chan.send(event).unwrap(); } @@ -907,16 +887,12 @@ impl Document { let mut list = self.animation_frame_list.borrow_mut(); animation_frame_list = Vec::from_iter(list.drain()); - let window = self.window.root(); - let window = window.r(); - let ConstellationChan(ref chan) = window.constellation_chan(); - let event = ConstellationMsg::ChangeRunningAnimationsState(window.pipeline(), + let ConstellationChan(ref chan) = self.window.constellation_chan(); + let event = ConstellationMsg::ChangeRunningAnimationsState(self.window.pipeline(), AnimationState::NoAnimationCallbacksPresent); chan.send(event).unwrap(); } - let window = self.window.root(); - let window = window.r(); - let performance = window.Performance(); + let performance = self.window.Performance(); let performance = performance.r(); let timing = performance.Now(); @@ -924,9 +900,9 @@ impl Document { callback(*timing); } - window.reflow(ReflowGoal::ForDisplay, - ReflowQueryType::NoQuery, - ReflowReason::RequestAnimationFrame); + self.window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::RequestAnimationFrame); } pub fn prepare_async_load(&self, load: LoadType) -> PendingAsyncLoad { @@ -950,9 +926,8 @@ impl Document { } pub fn notify_constellation_load(&self) { - let window = self.window.root(); - let pipeline_id = window.r().pipeline(); - let ConstellationChan(ref chan) = window.r().constellation_chan(); + let pipeline_id = self.window.pipeline(); + let ConstellationChan(ref chan) = self.window.constellation_chan(); let event = ConstellationMsg::DOMLoad(pipeline_id); chan.send(event).unwrap(); @@ -1093,12 +1068,11 @@ impl Document { } fn create_node_list<F: Fn(&Node) -> bool>(&self, callback: F) -> Root<NodeList> { - let window = self.window.root(); let doc = self.GetDocumentElement(); let maybe_node = doc.r().map(NodeCast::from_ref); let iter = maybe_node.iter().flat_map(|node| node.traverse_preorder()) .filter(|node| callback(node.r())); - NodeList::new_simple_list(window.r(), iter) + NodeList::new_simple_list(&self.window, iter) } fn get_html_element(&self) -> Option<Root<HTMLHtmlElement>> { @@ -1117,7 +1091,7 @@ impl Document { IsHTMLDocument::NonHTMLDocument }; let new_doc = Document::new( - &*self.window(), None, doctype, None, None, + self.window(), None, doctype, None, None, DocumentSource::NotFromParser, DocumentLoader::new(&self.loader())); new_doc.appropriate_template_contents_owner_document.set(Some(&new_doc)); new_doc @@ -1126,9 +1100,10 @@ impl Document { } -impl Node { +impl Element { fn click_event_filter_by_disabled_state(&self) -> bool { - match self.type_id() { + let node = NodeCast::from_ref(self); + match node.type_id() { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLButtonElement)) | NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLInputElement)) | // NodeTypeId::Element(ElementTypeId::HTMLKeygenElement) | @@ -1168,9 +1143,7 @@ impl DocumentMethods for Document { // https://html.spec.whatwg.org/multipage/#dom-document-hasfocus fn HasFocus(&self) -> bool { let target = self; // Step 1. - let window = self.window.root(); - let window = window.r(); - let browsing_context = window.browsing_context(); + let browsing_context = self.window.browsing_context(); let browsing_context = browsing_context.as_ref(); match browsing_context { @@ -1230,22 +1203,18 @@ impl DocumentMethods for Document { // https://dom.spec.whatwg.org/#dom-document-getelementsbytagname fn GetElementsByTagName(&self, tag_name: DOMString) -> Root<HTMLCollection> { - let window = self.window.root(); - HTMLCollection::by_tag_name(window.r(), NodeCast::from_ref(self), tag_name) + HTMLCollection::by_tag_name(&self.window, NodeCast::from_ref(self), tag_name) } // https://dom.spec.whatwg.org/#dom-document-getelementsbytagnamens fn GetElementsByTagNameNS(&self, maybe_ns: Option<DOMString>, tag_name: DOMString) -> Root<HTMLCollection> { - let window = self.window.root(); - HTMLCollection::by_tag_name_ns(window.r(), NodeCast::from_ref(self), tag_name, maybe_ns) + HTMLCollection::by_tag_name_ns(&self.window, NodeCast::from_ref(self), tag_name, maybe_ns) } // https://dom.spec.whatwg.org/#dom-document-getelementsbyclassname fn GetElementsByClassName(&self, classes: DOMString) -> Root<HTMLCollection> { - let window = self.window.root(); - - HTMLCollection::by_class_name(window.r(), NodeCast::from_ref(self), classes) + HTMLCollection::by_class_name(&self.window, NodeCast::from_ref(self), classes) } // https://dom.spec.whatwg.org/#dom-nonelementparentnode-getelementbyid @@ -1284,13 +1253,12 @@ impl DocumentMethods for Document { return Err(Error::InvalidCharacter); } - let window = self.window.root(); let name = Atom::from_slice(&local_name); // repetition used because string_cache::atom::Atom is non-copyable let l_name = Atom::from_slice(&local_name); let value = AttrValue::String("".to_owned()); - Ok(Attr::new(window.r(), name, value, l_name, ns!(""), None, None)) + Ok(Attr::new(&self.window, name, value, l_name, ns!(""), None, None)) } // https://dom.spec.whatwg.org/#dom-document-createattributens @@ -1298,10 +1266,9 @@ impl DocumentMethods for Document { -> Fallible<Root<Attr>> { let (namespace, prefix, local_name) = try!(validate_and_extract(namespace, &qualified_name)); - let window = self.window.root(); let value = AttrValue::String("".to_owned()); let qualified_name = Atom::from_slice(&qualified_name); - Ok(Attr::new(window.r(), local_name, value, qualified_name, + Ok(Attr::new(&self.window, local_name, value, qualified_name, namespace, prefix, None)) } @@ -1369,22 +1336,20 @@ impl DocumentMethods for Document { // https://dom.spec.whatwg.org/#dom-document-createevent fn CreateEvent(&self, mut interface: DOMString) -> Fallible<Root<Event>> { - let window = self.window.root(); - interface.make_ascii_lowercase(); match &*interface { "uievents" | "uievent" => Ok(EventCast::from_root( - UIEvent::new_uninitialized(window.r()))), + UIEvent::new_uninitialized(&self.window))), "mouseevents" | "mouseevent" => Ok(EventCast::from_root( - MouseEvent::new_uninitialized(window.r()))), + MouseEvent::new_uninitialized(&self.window))), "customevent" => Ok(EventCast::from_root( - CustomEvent::new_uninitialized(GlobalRef::Window(window.r())))), + CustomEvent::new_uninitialized(GlobalRef::Window(&self.window)))), "htmlevents" | "events" | "event" => Ok(Event::new_uninitialized( - GlobalRef::Window(window.r()))), + GlobalRef::Window(&self.window))), "keyboardevent" | "keyevents" => Ok(EventCast::from_root( - KeyboardEvent::new_uninitialized(window.r()))), + KeyboardEvent::new_uninitialized(&self.window))), "messageevent" => Ok(EventCast::from_root( - MessageEvent::new_uninitialized(GlobalRef::Window(window.r())))), + MessageEvent::new_uninitialized(GlobalRef::Window(&self.window)))), _ => Err(Error::NotSupported) } } @@ -1585,20 +1550,18 @@ impl DocumentMethods for Document { // https://html.spec.whatwg.org/multipage/#dom-document-images fn Images(&self) -> Root<HTMLCollection> { self.images.or_init(|| { - let window = self.window.root(); let root = NodeCast::from_ref(self); let filter = box ImagesFilter; - HTMLCollection::create(window.r(), root, filter) + HTMLCollection::create(&self.window, root, filter) }) } // https://html.spec.whatwg.org/multipage/#dom-document-embeds fn Embeds(&self) -> Root<HTMLCollection> { self.embeds.or_init(|| { - let window = self.window.root(); let root = NodeCast::from_ref(self); let filter = box EmbedsFilter; - HTMLCollection::create(window.r(), root, filter) + HTMLCollection::create(&self.window, root, filter) }) } @@ -1610,40 +1573,36 @@ impl DocumentMethods for Document { // https://html.spec.whatwg.org/multipage/#dom-document-links fn Links(&self) -> Root<HTMLCollection> { self.links.or_init(|| { - let window = self.window.root(); let root = NodeCast::from_ref(self); let filter = box LinksFilter; - HTMLCollection::create(window.r(), root, filter) + HTMLCollection::create(&self.window, root, filter) }) } // https://html.spec.whatwg.org/multipage/#dom-document-forms fn Forms(&self) -> Root<HTMLCollection> { self.forms.or_init(|| { - let window = self.window.root(); let root = NodeCast::from_ref(self); let filter = box FormsFilter; - HTMLCollection::create(window.r(), root, filter) + HTMLCollection::create(&self.window, root, filter) }) } // https://html.spec.whatwg.org/multipage/#dom-document-scripts fn Scripts(&self) -> Root<HTMLCollection> { self.scripts.or_init(|| { - let window = self.window.root(); let root = NodeCast::from_ref(self); let filter = box ScriptsFilter; - HTMLCollection::create(window.r(), root, filter) + HTMLCollection::create(&self.window, root, filter) }) } // https://html.spec.whatwg.org/multipage/#dom-document-anchors fn Anchors(&self) -> Root<HTMLCollection> { self.anchors.or_init(|| { - let window = self.window.root(); let root = NodeCast::from_ref(self); let filter = box AnchorsFilter; - HTMLCollection::create(window.r(), root, filter) + HTMLCollection::create(&self.window, root, filter) }) } @@ -1651,24 +1610,20 @@ impl DocumentMethods for Document { fn Applets(&self) -> Root<HTMLCollection> { // FIXME: This should be return OBJECT elements containing applets. self.applets.or_init(|| { - let window = self.window.root(); let root = NodeCast::from_ref(self); let filter = box AppletsFilter; - HTMLCollection::create(window.r(), root, filter) + HTMLCollection::create(&self.window, root, filter) }) } // https://html.spec.whatwg.org/multipage/#dom-document-location fn Location(&self) -> Root<Location> { - let window = self.window.root(); - let window = window.r(); - self.location.or_init(|| Location::new(window)) + self.location.or_init(|| Location::new(&self.window)) } // https://dom.spec.whatwg.org/#dom-parentnode-children fn Children(&self) -> Root<HTMLCollection> { - let window = self.window.root(); - HTMLCollection::children(window.r(), NodeCast::from_ref(self)) + HTMLCollection::children(&self.window, NodeCast::from_ref(self)) } // https://dom.spec.whatwg.org/#dom-parentnode-firstelementchild @@ -1725,9 +1680,8 @@ impl DocumentMethods for Document { if !is_scheme_host_port_tuple(&url) { return Err(Error::Security); } - let window = self.window.root(); let (tx, rx) = ipc::channel().unwrap(); - let _ = window.r().resource_task().send(GetCookiesForUrl((*url).clone(), tx, NonHTTP)); + let _ = self.window.resource_task().send(GetCookiesForUrl((*url).clone(), tx, NonHTTP)); let cookies = rx.recv().unwrap(); Ok(cookies.unwrap_or("".to_owned())) } @@ -1739,8 +1693,7 @@ impl DocumentMethods for Document { if !is_scheme_host_port_tuple(url) { return Err(Error::Security); } - let window = self.window.root(); - let _ = window.r().resource_task().send(SetCookiesForUrl((*url).clone(), cookie, NonHTTP)); + let _ = self.window.resource_task().send(SetCookiesForUrl((*url).clone(), cookie, NonHTTP)); Ok(()) } @@ -1834,9 +1787,8 @@ impl DocumentMethods for Document { } // Step 4. *found = true; - let window = self.window(); let filter = NamedElementFilter { name: name }; - let collection = HTMLCollection::create(window.r(), root, box filter); + let collection = HTMLCollection::create(self.window(), root, box filter); collection.r().reflector().get_jsobject().get() } @@ -1894,13 +1846,15 @@ impl DocumentProgressHandler { fn dispatch_dom_content_loaded(&self) { let document = self.addr.root(); let window = document.r().window(); - let event = Event::new(GlobalRef::Window(window.r()), "DOMContentLoaded".to_owned(), + let event = Event::new(GlobalRef::Window(window), "DOMContentLoaded".to_owned(), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable); let doctarget = EventTargetCast::from_ref(document.r()); let _ = doctarget.DispatchEvent(event.r()); - window.r().reflow(ReflowGoal::ForDisplay, ReflowQueryType::NoQuery, ReflowReason::DOMContentLoaded); + window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::DOMContentLoaded); } fn set_ready_state_complete(&self) { @@ -1911,35 +1865,34 @@ impl DocumentProgressHandler { fn dispatch_load(&self) { let document = self.addr.root(); let window = document.r().window(); - let event = Event::new(GlobalRef::Window(window.r()), "load".to_owned(), + let event = Event::new(GlobalRef::Window(window), "load".to_owned(), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable); - let wintarget = EventTargetCast::from_ref(window.r()); + let wintarget = EventTargetCast::from_ref(window); let doctarget = EventTargetCast::from_ref(document.r()); event.r().set_trusted(true); let _ = wintarget.dispatch_event_with_target(doctarget, event.r()); - let window_ref = window.r(); - let browsing_context = window_ref.browsing_context(); + let browsing_context = window.browsing_context(); let browsing_context = browsing_context.as_ref().unwrap(); - browsing_context.frame_element().map(|frame_element| { - let frame_window = window_from_node(frame_element.r()); + if let Some(frame_element) = browsing_context.frame_element() { + let frame_window = window_from_node(frame_element); let event = Event::new(GlobalRef::Window(frame_window.r()), "load".to_owned(), EventBubbles::DoesNotBubble, EventCancelable::NotCancelable); - let target = EventTargetCast::from_ref(frame_element.r()); + let target = EventTargetCast::from_ref(frame_element); event.r().fire(target); - }); + }; document.r().notify_constellation_load(); // https://developer.mozilla.org/en-US/docs/Web/Events/mozbrowserloadend document.r().trigger_mozbrowser_event(MozBrowserEvent::LoadEnd); - window_ref.reflow(ReflowGoal::ForDisplay, - ReflowQueryType::NoQuery, - ReflowReason::DocumentLoaded); + window.reflow(ReflowGoal::ForDisplay, + ReflowQueryType::NoQuery, + ReflowReason::DocumentLoaded); } } @@ -1947,7 +1900,7 @@ impl Runnable for DocumentProgressHandler { fn handler(self: Box<DocumentProgressHandler>) { let document = self.addr.root(); let window = document.r().window(); - if window.r().is_alive() { + if window.is_alive() { match self.task { DocumentProgressTask::DOMContentLoaded => { self.dispatch_dom_content_loaded(); diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index d66cba67bc0..93eb8cf8e0a 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -42,7 +42,7 @@ impl DOMImplementation { pub fn new(document: &Document) -> Root<DOMImplementation> { let window = document.window(); reflect_dom_object(box DOMImplementation::new_inherited(document), - GlobalRef::Window(window.r()), + GlobalRef::Window(window), DOMImplementationBinding::Wrap) } } @@ -53,20 +53,17 @@ impl DOMImplementationMethods for DOMImplementation { fn CreateDocumentType(&self, qualified_name: DOMString, pubid: DOMString, sysid: DOMString) -> Fallible<Root<DocumentType>> { try!(validate_qualified_name(&qualified_name)); - let document = self.document.root(); - Ok(DocumentType::new(qualified_name, Some(pubid), Some(sysid), document.r())) + Ok(DocumentType::new(qualified_name, Some(pubid), Some(sysid), &self.document)) } // https://dom.spec.whatwg.org/#dom-domimplementation-createdocument fn CreateDocument(&self, namespace: Option<DOMString>, qname: DOMString, maybe_doctype: Option<&DocumentType>) -> Fallible<Root<Document>> { - let doc = self.document.root(); - let doc = doc.r(); - let win = doc.window(); - let loader = DocumentLoader::new(&*doc.loader()); + let win = self.document.window(); + let loader = DocumentLoader::new(&self.document.loader()); // Step 1. - let doc = Document::new(win.r(), None, IsHTMLDocument::NonHTMLDocument, + let doc = Document::new(win, None, IsHTMLDocument::NonHTMLDocument, None, None, DocumentSource::NotFromParser, loader); // Step 2-3. let maybe_elem = if qname.is_empty() { @@ -108,13 +105,11 @@ impl DOMImplementationMethods for DOMImplementation { // https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument fn CreateHTMLDocument(&self, title: Option<DOMString>) -> Root<Document> { - let document = self.document.root(); - let document = document.r(); - let win = document.window(); - let loader = DocumentLoader::new(&*document.loader()); + let win = self.document.window(); + let loader = DocumentLoader::new(&self.document.loader()); // Step 1-2. - let doc = Document::new(win.r(), None, IsHTMLDocument::HTMLDocument, None, None, + let doc = Document::new(win, None, IsHTMLDocument::HTMLDocument, None, None, DocumentSource::NotFromParser, loader); { diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs index 8ad9bfa507b..a66b8ea3962 100644 --- a/components/script/dom/domparser.rs +++ b/components/script/dom/domparser.rs @@ -49,15 +49,14 @@ impl DOMParserMethods for DOMParser { s: DOMString, ty: DOMParserBinding::SupportedType) -> Fallible<Root<Document>> { - let window = self.window.root(); - let url = window.r().get_url(); + let url = self.window.get_url(); let content_type = DOMParserBinding::SupportedTypeValues::strings[ty as usize].to_owned(); - let doc = window.r().Document(); + let doc = self.window.Document(); let doc = doc.r(); let loader = DocumentLoader::new(&*doc.loader()); match ty { Text_html => { - let document = Document::new(window.r(), Some(url.clone()), + let document = Document::new(&self.window, Some(url.clone()), IsHTMLDocument::HTMLDocument, Some(content_type), None, @@ -69,7 +68,7 @@ impl DOMParserMethods for DOMParser { } Text_xml => { //FIXME: this should probably be FromParser when we actually parse the string (#3756). - Ok(Document::new(window.r(), Some(url.clone()), + Ok(Document::new(&self.window, Some(url.clone()), IsHTMLDocument::NonHTMLDocument, Some(content_type), None, diff --git a/components/script/dom/domrect.rs b/components/script/dom/domrect.rs index 6706642b5c5..fa1dcc1b165 100644 --- a/components/script/dom/domrect.rs +++ b/components/script/dom/domrect.rs @@ -2,74 +2,75 @@ * 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 app_units::Au; use dom::bindings::codegen::Bindings::DOMRectBinding; use dom::bindings::codegen::Bindings::DOMRectBinding::DOMRectMethods; +use dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::DOMRectReadOnlyMethods; +use dom::bindings::error::Fallible; use dom::bindings::global::GlobalRef; use dom::bindings::js::Root; -use dom::bindings::num::Finite; -use dom::bindings::utils::{Reflector, reflect_dom_object}; -use dom::window::Window; +use dom::bindings::utils::reflect_dom_object; +use dom::domrectreadonly::DOMRectReadOnly; #[dom_struct] pub struct DOMRect { - reflector_: Reflector, - top: f32, - bottom: f32, - left: f32, - right: f32, + rect: DOMRectReadOnly, } impl DOMRect { - fn new_inherited(top: Au, bottom: Au, - left: Au, right: Au) -> DOMRect { + fn new_inherited(x: f64, y: f64, width: f64, height: f64) -> DOMRect { DOMRect { - top: top.to_nearest_px() as f32, - bottom: bottom.to_nearest_px() as f32, - left: left.to_nearest_px() as f32, - right: right.to_nearest_px() as f32, - reflector_: Reflector::new(), + rect: DOMRectReadOnly::new_inherited(x, y, width, height), } } - pub fn new(window: &Window, - top: Au, bottom: Au, - left: Au, right: Au) -> Root<DOMRect> { - reflect_dom_object(box DOMRect::new_inherited(top, bottom, left, right), - GlobalRef::Window(window), DOMRectBinding::Wrap) + pub fn new(global: GlobalRef, x: f64, y: f64, width: f64, height: f64) -> Root<DOMRect> { + reflect_dom_object(box DOMRect::new_inherited(x, y, width, height), global, DOMRectBinding::Wrap) + } + + pub fn Constructor(global: GlobalRef, + x: f64, y: f64, width: f64, height: f64) -> Fallible<Root<DOMRect>> { + Ok(DOMRect::new(global, x, y, width, height)) } } impl DOMRectMethods for DOMRect { - // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-top - fn Top(&self) -> Finite<f32> { - Finite::wrap(self.top) + // https://drafts.fxtf.org/geometry/#dom-domrect-x + fn X(&self) -> f64 { + self.rect.X() + } + + // https://drafts.fxtf.org/geometry/#dom-domrect-x + fn SetX(&self, value: f64) { + self.rect.set_x(value); + } + + // https://drafts.fxtf.org/geometry/#dom-domrect-y + fn Y(&self) -> f64 { + self.rect.Y() } - // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-bottom - fn Bottom(&self) -> Finite<f32> { - Finite::wrap(self.bottom) + // https://drafts.fxtf.org/geometry/#dom-domrect-y + fn SetY(&self, value: f64) { + self.rect.set_y(value); } - // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left - fn Left(&self) -> Finite<f32> { - Finite::wrap(self.left) + // https://drafts.fxtf.org/geometry/#dom-domrect-width + fn Width(&self) -> f64 { + self.rect.Width() } - // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-right - fn Right(&self) -> Finite<f32> { - Finite::wrap(self.right) + // https://drafts.fxtf.org/geometry/#dom-domrect-width + fn SetWidth(&self, value: f64) { + self.rect.set_width(value); } - // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-width - fn Width(&self) -> Finite<f32> { - let result = (self.right - self.left).abs(); - Finite::wrap(result) + // https://drafts.fxtf.org/geometry/#dom-domrect-height + fn Height(&self) -> f64 { + self.rect.Height() } - // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-height - fn Height(&self) -> Finite<f32> { - let result = (self.bottom - self.top).abs(); - Finite::wrap(result) + // https://drafts.fxtf.org/geometry/#dom-domrect-height + fn SetHeight(&self, value: f64) { + self.rect.set_height(value); } } diff --git a/components/script/dom/domrectreadonly.rs b/components/script/dom/domrectreadonly.rs new file mode 100644 index 00000000000..a6ba99ead2a --- /dev/null +++ b/components/script/dom/domrectreadonly.rs @@ -0,0 +1,102 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use dom::bindings::codegen::Bindings::DOMRectReadOnlyBinding::{DOMRectReadOnlyMethods, Wrap}; +use dom::bindings::error::Fallible; +use dom::bindings::global::GlobalRef; +use dom::bindings::js::Root; +use dom::bindings::utils::{Reflector, reflect_dom_object}; +use std::cell::Cell; + +#[dom_struct] +pub struct DOMRectReadOnly { + reflector_: Reflector, + x: Cell<f64>, + y: Cell<f64>, + width: Cell<f64>, + height: Cell<f64>, +} + +impl DOMRectReadOnly { + pub fn new_inherited(x: f64, y: f64, width: f64, height: f64) -> DOMRectReadOnly { + DOMRectReadOnly { + x: Cell::new(x), + y: Cell::new(y), + width: Cell::new(width), + height: Cell::new(height), + reflector_: Reflector::new(), + } + } + + pub fn new(global: GlobalRef, x: f64, y: f64, width: f64, height: f64) -> Root<DOMRectReadOnly> { + reflect_dom_object(box DOMRectReadOnly::new_inherited(x, y, width, height), global, Wrap) + } + + pub fn Constructor(global: GlobalRef, + x: f64, y: f64, width: f64, height: f64) -> Fallible<Root<DOMRectReadOnly>> { + Ok(DOMRectReadOnly::new(global, x, y, width, height)) + } + + pub fn set_x(&self, value: f64) { + self.x.set(value); + } + + pub fn set_y(&self, value: f64) { + self.y.set(value); + } + + pub fn set_width(&self, value: f64) { + self.width.set(value); + } + + pub fn set_height(&self, value: f64) { + self.height.set(value); + } +} + +impl DOMRectReadOnlyMethods for DOMRectReadOnly { + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-x + fn X(&self) -> f64 { + self.x.get() + } + + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-y + fn Y(&self) -> f64 { + self.y.get() + } + + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-width + fn Width(&self) -> f64 { + self.width.get() + } + + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-height + fn Height(&self) -> f64 { + self.height.get() + } + + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-top + fn Top(&self) -> f64 { + let height = self.height.get(); + if height >= 0f64 { self.y.get() } else { self.y.get() + height } + } + + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-right + fn Right(&self) -> f64 { + let width = self.width.get(); + if width < 0f64 { self.x.get() } else { self.x.get() + width } + } + + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-bottom + fn Bottom(&self) -> f64 { + let height = self.height.get(); + if height < 0f64 { self.y.get() } else { self.y.get() + height } + } + + // https://drafts.fxtf.org/geometry/#dom-domrectreadonly-left + fn Left(&self) -> f64 { + let width = self.width.get(); + if width >= 0f64 { self.x.get() } else { self.x.get() + width } + } +} diff --git a/components/script/dom/domstringmap.rs b/components/script/dom/domstringmap.rs index cfa5a8e0a1c..95f727c93cb 100644 --- a/components/script/dom/domstringmap.rs +++ b/components/script/dom/domstringmap.rs @@ -37,20 +37,17 @@ impl DOMStringMap { impl DOMStringMapMethods for DOMStringMap { // https://html.spec.whatwg.org/multipage/#dom-domstringmap-removeitem fn NamedDeleter(&self, name: DOMString) { - let element = self.element.root(); - element.r().delete_custom_attr(name) + self.element.delete_custom_attr(name) } // https://html.spec.whatwg.org/multipage/#dom-domstringmap-setitem fn NamedSetter(&self, name: DOMString, value: DOMString) -> ErrorResult { - let element = self.element.root(); - element.r().set_custom_attr(name, value) + self.element.set_custom_attr(name, value) } // https://html.spec.whatwg.org/multipage/#dom-domstringmap-nameditem fn NamedGetter(&self, name: DOMString, found: &mut bool) -> DOMString { - let element = self.element.root(); - match element.r().get_custom_attr(name) { + match self.element.get_custom_attr(name) { Some(value) => { *found = true; value.clone() diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs index e13c1448d70..c3944b7627c 100644 --- a/components/script/dom/domtokenlist.rs +++ b/components/script/dom/domtokenlist.rs @@ -39,8 +39,7 @@ impl DOMTokenList { } fn attribute(&self) -> Option<Root<Attr>> { - let element = self.element.root(); - element.r().get_attribute(&ns!(""), &self.local_name) + self.element.get_attribute(&ns!(""), &self.local_name) } fn check_token_exceptions(&self, token: &str) -> Fallible<Atom> { @@ -87,43 +86,40 @@ impl DOMTokenListMethods for DOMTokenList { // https://dom.spec.whatwg.org/#dom-domtokenlist-add fn Add(&self, tokens: Vec<DOMString>) -> ErrorResult { - let element = self.element.root(); - let mut atoms = element.r().get_tokenlist_attribute(&self.local_name); + let mut atoms = self.element.get_tokenlist_attribute(&self.local_name); for token in &tokens { let token = try!(self.check_token_exceptions(&token)); if !atoms.iter().any(|atom| *atom == token) { atoms.push(token); } } - element.r().set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms); Ok(()) } // https://dom.spec.whatwg.org/#dom-domtokenlist-remove fn Remove(&self, tokens: Vec<DOMString>) -> ErrorResult { - let element = self.element.root(); - let mut atoms = element.r().get_tokenlist_attribute(&self.local_name); + let mut atoms = self.element.get_tokenlist_attribute(&self.local_name); for token in &tokens { let token = try!(self.check_token_exceptions(&token)); atoms.iter().position(|atom| *atom == token).map(|index| { atoms.remove(index) }); } - element.r().set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms); Ok(()) } // https://dom.spec.whatwg.org/#dom-domtokenlist-toggle fn Toggle(&self, token: DOMString, force: Option<bool>) -> Fallible<bool> { - let element = self.element.root(); - let mut atoms = element.r().get_tokenlist_attribute(&self.local_name); + let mut atoms = self.element.get_tokenlist_attribute(&self.local_name); let token = try!(self.check_token_exceptions(&token)); match atoms.iter().position(|atom| *atom == token) { Some(index) => match force { Some(true) => Ok(true), _ => { atoms.remove(index); - element.r().set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms); Ok(false) } }, @@ -131,7 +127,7 @@ impl DOMTokenListMethods for DOMTokenList { Some(false) => Ok(false), _ => { atoms.push(token); - element.r().set_atomic_tokenlist_attribute(&self.local_name, atoms); + self.element.set_atomic_tokenlist_attribute(&self.local_name, atoms); Ok(true) } } @@ -140,7 +136,7 @@ impl DOMTokenListMethods for DOMTokenList { // https://dom.spec.whatwg.org/#stringification-behavior fn Stringifier(&self) -> DOMString { - let tokenlist = self.element.root().r().get_tokenlist_attribute(&self.local_name); + let tokenlist = self.element.get_tokenlist_attribute(&self.local_name); str_join(&tokenlist, "\x20") } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index 651142df713..a2970ffff1f 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -22,14 +22,16 @@ use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, DocumentDerived, ElementCast}; use dom::bindings::codegen::InheritTypes::{ElementDerived, ElementTypeId, EventTargetCast}; use dom::bindings::codegen::InheritTypes::{HTMLAnchorElementCast, HTMLBodyElementCast}; -use dom::bindings::codegen::InheritTypes::{HTMLElementTypeId, HTMLFontElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLElementTypeId, HTMLFieldSetElementDerived, HTMLFontElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLIFrameElementCast, HTMLInputElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLLegendElementDerived, HTMLOptGroupElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLTableCellElementCast, HTMLTableElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLTableRowElementCast, HTMLTableSectionElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLTemplateElementCast, HTMLTextAreaElementCast}; use dom::bindings::codegen::InheritTypes::{NodeCast, NodeTypeId, TextCast}; use dom::bindings::codegen::UnionTypes::NodeOrString; use dom::bindings::error::{Error, ErrorResult, Fallible}; +use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap}; use dom::bindings::js::{Root, RootedReference}; use dom::bindings::utils::XMLName::InvalidXMLName; @@ -47,7 +49,7 @@ use dom::htmltableelement::HTMLTableElement; use dom::htmltextareaelement::RawLayoutHTMLTextAreaElementHelpers; use dom::namednodemap::NamedNodeMap; use dom::node::{CLICK_IN_PROGRESS, LayoutNodeHelpers, Node}; -use dom::node::{NodeDamage, NodeFlags, SEQUENTIALLY_FOCUSABLE}; +use dom::node::{NodeDamage, SEQUENTIALLY_FOCUSABLE}; use dom::node::{document_from_node, window_from_node}; use dom::nodelist::NodeList; use dom::virtualmethods::{VirtualMethods, vtable_for}; @@ -62,7 +64,7 @@ use selectors::parser::{AttrSelector, NamespaceConstraint}; use smallvec::VecLike; use std::ascii::AsciiExt; use std::borrow::{Cow, ToOwned}; -use std::cell::Ref; +use std::cell::{Cell, Ref}; use std::default::Default; use std::mem; use std::sync::Arc; @@ -76,6 +78,25 @@ use style::values::specified::{self, CSSColor, CSSRGBA}; use url::UrlParser; use util::str::{DOMString, LengthOrPercentageOrAuto}; +bitflags! { + #[doc = "Element Event States."] + #[derive(JSTraceable, HeapSizeOf)] + flags EventState: u8 { + #[doc = "The mouse is down on this element. \ + (https://html.spec.whatwg.org/multipage/#selector-active). \ + FIXME(#7333): set/unset this when appropriate"] + const IN_ACTIVE_STATE = 0x01, + #[doc = "This element has focus."] + const IN_FOCUS_STATE = 0x02, + #[doc = "The mouse is hovering over this element."] + const IN_HOVER_STATE = 0x04, + #[doc = "Content is enabled (and can be disabled)."] + const IN_ENABLED_STATE = 0x08, + #[doc = "Content is disabled."] + const IN_DISABLED_STATE = 0x10, + } +} + #[dom_struct] pub struct Element { node: Node, @@ -87,6 +108,7 @@ pub struct Element { style_attribute: DOMRefCell<Option<PropertyDeclarationBlock>>, attr_list: MutNullableHeap<JS<NamedNodeMap>>, class_list: MutNullableHeap<JS<DOMTokenList>>, + event_state: Cell<EventState>, } impl PartialEq for Element { @@ -115,16 +137,16 @@ impl Element { pub fn new_inherited(local_name: DOMString, namespace: Namespace, prefix: Option<DOMString>, document: &Document) -> Element { - Element::new_inherited_with_flags(NodeFlags::new(), local_name, + Element::new_inherited_with_state(EventState::empty(), local_name, namespace, prefix, document) } - pub fn new_inherited_with_flags(flags: NodeFlags, local_name: DOMString, + pub fn new_inherited_with_state(state: EventState, local_name: DOMString, namespace: Namespace, prefix: Option<DOMString>, document: &Document) -> Element { Element { - node: Node::new_inherited_with_flags(flags, document), + node: Node::new_inherited(document), local_name: Atom::from_slice(&local_name), namespace: namespace, prefix: prefix, @@ -133,6 +155,7 @@ impl Element { class_list: Default::default(), id_attribute: DOMRefCell::new(None), style_attribute: DOMRefCell::new(None), + event_state: Cell::new(state), } } @@ -224,6 +247,8 @@ pub trait LayoutElementHelpers { fn namespace(&self) -> &Namespace; fn get_checked_state_for_layout(&self) -> bool; fn get_indeterminate_state_for_layout(&self) -> bool; + + fn get_event_state_for_layout(&self) -> EventState; } impl LayoutElementHelpers for LayoutJS<Element> { @@ -574,6 +599,14 @@ impl LayoutElementHelpers for LayoutJS<Element> { None => false, } } + + #[inline] + #[allow(unsafe_code)] + fn get_event_state_for_layout(&self) -> EventState { + unsafe { + (*self.unsafe_get()).event_state.get() + } + } } #[derive(PartialEq, Eq, Copy, Clone, HeapSizeOf)] @@ -827,7 +860,7 @@ impl Element { NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLSelectElement)) | NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLTextAreaElement)) | NodeTypeId::Element(ElementTypeId::HTMLElement(HTMLElementTypeId::HTMLOptionElement)) => { - node.get_disabled_state() + self.get_disabled_state() } // TODO: // an optgroup element that has a disabled attribute @@ -1143,13 +1176,13 @@ impl ElementMethods for Element { node.owner_doc() }; let window = doc.r().window(); - NamedNodeMap::new(window.r(), self) + NamedNodeMap::new(window, self) }) } // https://dom.spec.whatwg.org/#dom-element-getattribute fn GetAttribute(&self, name: DOMString) -> Option<DOMString> { - self.get_attribute_by_name(name) + self.GetAttributeNode(name) .map(|s| s.r().Value()) } @@ -1157,9 +1190,21 @@ impl ElementMethods for Element { fn GetAttributeNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<DOMString> { + self.GetAttributeNodeNS(namespace, local_name) + .map(|attr| attr.r().Value()) + } + + // https://dom.spec.whatwg.org/#dom-element-getattributenode + fn GetAttributeNode(&self, name: DOMString) -> Option<Root<Attr>> { + self.get_attribute_by_name(name) + } + + // https://dom.spec.whatwg.org/#dom-element-getattributenodens + fn GetAttributeNodeNS(&self, + namespace: Option<DOMString>, + local_name: DOMString) -> Option<Root<Attr>> { let namespace = &namespace_from_domstring(namespace); self.get_attribute(namespace, &Atom::from_slice(&local_name)) - .map(|attr| attr.r().Value()) } // https://dom.spec.whatwg.org/#dom-element-setattribute @@ -1249,9 +1294,11 @@ impl ElementMethods for Element { let node = NodeCast::from_ref(self); let raw_rects = node.get_content_boxes(); let rects = raw_rects.iter().map(|rect| { - DOMRect::new(win.r(), - rect.origin.y, rect.origin.y + rect.size.height, - rect.origin.x, rect.origin.x + rect.size.width) + DOMRect::new(GlobalRef::Window(win.r()), + rect.origin.x.to_f64_px(), + rect.origin.y.to_f64_px(), + rect.size.width.to_f64_px(), + rect.size.height.to_f64_px()) }); DOMRectList::new(win.r(), rects) } @@ -1261,12 +1308,11 @@ impl ElementMethods for Element { let win = window_from_node(self); let node = NodeCast::from_ref(self); let rect = node.get_bounding_content_box(); - DOMRect::new( - win.r(), - rect.origin.y, - rect.origin.y + rect.size.height, - rect.origin.x, - rect.origin.x + rect.size.width) + DOMRect::new(GlobalRef::Window(win.r()), + rect.origin.x.to_f64_px(), + rect.origin.y.to_f64_px(), + rect.size.width.to_f64_px(), + rect.size.height.to_f64_px()) } // https://drafts.csswg.org/cssom-view/#dom-element-clienttop @@ -1624,31 +1670,30 @@ impl<'a> ::selectors::Element for Root<Element> { fn get_namespace<'b>(&'b self) -> &'b Namespace { self.namespace() } + fn get_hover_state(&self) -> bool { - let node = NodeCast::from_ref(&**self); - node.get_hover_state() + Element::get_hover_state(self) } + fn get_active_state(&self) -> bool { - let node = NodeCast::from_ref(&**self); - node.get_active_state() + Element::get_active_state(self) } + fn get_focus_state(&self) -> bool { // TODO: Also check whether the top-level browsing context has the system focus, // and whether this element is a browsing context container. // https://html.spec.whatwg.org/multipage/#selector-focus - let node = NodeCast::from_ref(&**self); - node.get_focus_state() + Element::get_focus_state(self) } + fn get_id(&self) -> Option<Atom> { self.id_attribute.borrow().clone() } fn get_disabled_state(&self) -> bool { - let node = NodeCast::from_ref(&**self); - node.get_disabled_state() + Element::get_disabled_state(self) } fn get_enabled_state(&self) -> bool { - let node = NodeCast::from_ref(&**self); - node.get_enabled_state() + Element::get_enabled_state(self) } fn get_checked_state(&self) -> bool { let input_element: Option<&HTMLInputElement> = HTMLInputElementCast::to_ref(&**self); @@ -1816,6 +1861,105 @@ impl Element { // Step 7 self.set_click_in_progress(false); } + + fn set_state(&self, which: EventState, value: bool) { + let mut state = self.event_state.get(); + match value { + true => state.insert(which), + false => state.remove(which), + }; + self.event_state.set(state); + + let node = NodeCast::from_ref(self); + node.dirty(NodeDamage::NodeStyleDamaged); + } + + pub fn get_active_state(&self) -> bool { + self.event_state.get().contains(IN_ACTIVE_STATE) + } + + pub fn set_active_state(&self, value: bool) { + self.set_state(IN_ACTIVE_STATE, value) + } + + pub fn get_focus_state(&self) -> bool { + self.event_state.get().contains(IN_FOCUS_STATE) + } + + pub fn set_focus_state(&self, value: bool) { + self.set_state(IN_FOCUS_STATE, value) + } + + pub fn get_hover_state(&self) -> bool { + self.event_state.get().contains(IN_HOVER_STATE) + } + + pub fn set_hover_state(&self, value: bool) { + self.set_state(IN_HOVER_STATE, value) + } + + pub fn get_enabled_state(&self) -> bool { + self.event_state.get().contains(IN_ENABLED_STATE) + } + + pub fn set_enabled_state(&self, value: bool) { + self.set_state(IN_ENABLED_STATE, value) + } + + pub fn get_disabled_state(&self) -> bool { + self.event_state.get().contains(IN_DISABLED_STATE) + } + + pub fn set_disabled_state(&self, value: bool) { + self.set_state(IN_DISABLED_STATE, value) + } +} + +impl Element { + pub fn check_ancestors_disabled_state_for_form_control(&self) { + let node = NodeCast::from_ref(self); + if self.get_disabled_state() { return; } + for ancestor in node.ancestors() { + let ancestor = ancestor; + let ancestor = ancestor.r(); + if !ancestor.is_htmlfieldsetelement() { continue; } + if !ElementCast::to_ref(ancestor).unwrap().get_disabled_state() { continue; } + if ancestor.is_parent_of(node) { + self.set_disabled_state(true); + self.set_enabled_state(false); + return; + } + match ancestor.children() + .find(|child| child.r().is_htmllegendelement()) + { + Some(ref legend) => { + // XXXabinader: should we save previous ancestor to avoid this iteration? + if node.ancestors().any(|ancestor| ancestor == *legend) { continue; } + }, + None => () + } + self.set_disabled_state(true); + self.set_enabled_state(false); + return; + } + } + + pub fn check_parent_disabled_state_for_option(&self) { + if self.get_disabled_state() { return; } + let node = NodeCast::from_ref(self); + if let Some(ref parent) = node.GetParentNode() { + if parent.r().is_htmloptgroupelement() && ElementCast::to_ref(parent.r()).unwrap().get_disabled_state() { + self.set_disabled_state(true); + self.set_enabled_state(false); + } + } + } + + pub fn check_disabled_attribute(&self) { + let has_disabled_attrib = self.has_attribute(&atom!("disabled")); + self.set_disabled_state(has_disabled_attrib); + self.set_enabled_state(!has_disabled_attrib); + } } #[derive(Clone, Copy, PartialEq)] diff --git a/components/script/dom/htmlbodyelement.rs b/components/script/dom/htmlbodyelement.rs index 806086a6b03..438aa79ec74 100644 --- a/components/script/dom/htmlbodyelement.rs +++ b/components/script/dom/htmlbodyelement.rs @@ -83,6 +83,18 @@ impl HTMLBodyElementMethods for HTMLBodyElement { let win = window_from_node(self); win.r().SetOnunload(listener) } + + // https://html.spec.whatwg.org/multipage/#the-body-element + fn GetOnstorage(&self) -> Option<Rc<EventHandlerNonNull>> { + let win = window_from_node(self); + win.r().GetOnstorage() + } + + // https://html.spec.whatwg.org/multipage/#the-body-element + fn SetOnstorage(&self, listener: Option<Rc<EventHandlerNonNull>>) { + let win = window_from_node(self); + win.r().SetOnstorage(listener) + } } diff --git a/components/script/dom/htmlbuttonelement.rs b/components/script/dom/htmlbuttonelement.rs index 104619aecbb..93f7f9b292a 100644 --- a/components/script/dom/htmlbuttonelement.rs +++ b/components/script/dom/htmlbuttonelement.rs @@ -10,14 +10,13 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLButtonElementCast, H use dom::bindings::codegen::InheritTypes::{HTMLFieldSetElementDerived, NodeCast}; use dom::bindings::js::Root; use dom::document::Document; -use dom::element::{AttributeMutation, Element}; +use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE}; use dom::event::Event; use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::htmlformelement::{FormControl, FormSubmitter}; use dom::htmlformelement::{SubmittedFrom, HTMLFormElement}; -use dom::node::{IN_ENABLED_STATE, Node, NodeFlags}; -use dom::node::{document_from_node, window_from_node}; +use dom::node::{Node, document_from_node, window_from_node}; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use std::ascii::AsciiExt; @@ -47,7 +46,7 @@ impl HTMLButtonElement { document: &Document) -> HTMLButtonElement { HTMLButtonElement { htmlelement: - HTMLElement::new_inherited_with_flags(NodeFlags::new() | IN_ENABLED_STATE, + HTMLElement::new_inherited_with_state(IN_ENABLED_STATE, localName, prefix, document), //TODO: implement button_type in attribute_mutated button_type: Cell::new(ButtonType::ButtonSubmit) @@ -144,17 +143,17 @@ impl VirtualMethods for HTMLButtonElement { self.super_type().unwrap().attribute_mutated(attr, mutation); match attr.local_name() { &atom!(disabled) => { - let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); match mutation { AttributeMutation::Set(Some(_)) => {} AttributeMutation::Set(None) => { - node.set_disabled_state(true); - node.set_enabled_state(false); + el.set_disabled_state(true); + el.set_enabled_state(false); }, AttributeMutation::Removed => { - node.set_disabled_state(false); - node.set_enabled_state(true); - node.check_ancestors_disabled_state_for_form_control(); + el.set_disabled_state(false); + el.set_enabled_state(true); + el.check_ancestors_disabled_state_for_form_control(); } } }, @@ -167,8 +166,8 @@ impl VirtualMethods for HTMLButtonElement { s.bind_to_tree(tree_in_doc); } - let node = NodeCast::from_ref(self); - node.check_ancestors_disabled_state_for_form_control(); + let el = ElementCast::from_ref(self); + el.check_ancestors_disabled_state_for_form_control(); } fn unbind_from_tree(&self, tree_in_doc: bool) { @@ -177,10 +176,11 @@ impl VirtualMethods for HTMLButtonElement { } let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) { - node.check_ancestors_disabled_state_for_form_control(); + el.check_ancestors_disabled_state_for_form_control(); } else { - node.check_disabled_attribute(); + el.check_disabled_attribute(); } } } @@ -194,8 +194,8 @@ impl<'a> Activatable for &'a HTMLButtonElement { fn is_instance_activatable(&self) -> bool { //https://html.spec.whatwg.org/multipage/#the-button-element - let node = NodeCast::from_ref(*self); - !(node.get_disabled_state()) + let el = ElementCast::from_ref(*self); + !(el.get_disabled_state()) } // https://html.spec.whatwg.org/multipage/#run-pre-click-activation-steps @@ -232,13 +232,9 @@ impl<'a> Activatable for &'a HTMLButtonElement { if owner.is_none() || elem.click_in_progress() { return; } - // This is safe because we are stopping after finding the first element - // and only then performing actions which may modify the DOM tree - unsafe { - node.query_selector_iter("button[type=submit]".to_owned()).unwrap() - .filter_map(HTMLButtonElementCast::to_root) - .find(|r| r.r().form_owner() == owner) - .map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey)); - } + node.query_selector_iter("button[type=submit]".to_owned()).unwrap() + .filter_map(HTMLButtonElementCast::to_root) + .find(|r| r.r().form_owner() == owner) + .map(|s| s.r().synthetic_click_activation(ctrlKey, shiftKey, altKey, metaKey)); } } diff --git a/components/script/dom/htmlelement.rs b/components/script/dom/htmlelement.rs index 48154d25042..ae25eb3dc17 100644 --- a/components/script/dom/htmlelement.rs +++ b/components/script/dom/htmlelement.rs @@ -20,9 +20,9 @@ use dom::bindings::utils::Reflectable; use dom::cssstyledeclaration::{CSSModificationAccess, CSSStyleDeclaration}; use dom::document::Document; use dom::domstringmap::DOMStringMap; -use dom::element::{AttributeMutation, Element}; +use dom::element::{AttributeMutation, Element, EventState}; use dom::htmlinputelement::HTMLInputElement; -use dom::node::{Node, NodeFlags, SEQUENTIALLY_FOCUSABLE}; +use dom::node::{Node, SEQUENTIALLY_FOCUSABLE}; use dom::node::{document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::FocusType; @@ -49,15 +49,15 @@ impl PartialEq for HTMLElement { impl HTMLElement { pub fn new_inherited(tag_name: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLElement { - HTMLElement::new_inherited_with_flags(NodeFlags::new(), tag_name, prefix, document) + HTMLElement::new_inherited_with_state(EventState::empty(), tag_name, prefix, document) } - pub fn new_inherited_with_flags(flags: NodeFlags, tag_name: DOMString, + pub fn new_inherited_with_state(state: EventState, tag_name: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLElement { HTMLElement { element: - Element::new_inherited_with_flags(flags, tag_name, ns!(HTML), prefix, document), + Element::new_inherited_with_state(state, tag_name, ns!(HTML), prefix, document), style_decl: Default::default(), dataset: Default::default(), } @@ -194,8 +194,8 @@ impl HTMLElementMethods for HTMLElement { // https://html.spec.whatwg.org/multipage/#dom-blur fn Blur(&self) { // TODO: Run the unfocusing steps. - let node = NodeCast::from_ref(self); - if !node.get_focus_state() { + let el = ElementCast::from_ref(self); + if !el.get_focus_state() { return; } // https://html.spec.whatwg.org/multipage/#unfocusing-steps diff --git a/components/script/dom/htmlfieldsetelement.rs b/components/script/dom/htmlfieldsetelement.rs index c50f3bf6756..2eb696affb8 100644 --- a/components/script/dom/htmlfieldsetelement.rs +++ b/components/script/dom/htmlfieldsetelement.rs @@ -5,16 +5,16 @@ use dom::attr::Attr; use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding; use dom::bindings::codegen::Bindings::HTMLFieldSetElementBinding::HTMLFieldSetElementMethods; -use dom::bindings::codegen::InheritTypes::{ElementTypeId, HTMLElementCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, ElementTypeId, HTMLElementCast}; use dom::bindings::codegen::InheritTypes::{HTMLElementTypeId, HTMLLegendElementDerived}; use dom::bindings::codegen::InheritTypes::{NodeCast, NodeTypeId}; use dom::bindings::js::{Root, RootedReference}; use dom::document::Document; -use dom::element::{AttributeMutation, Element}; +use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE}; use dom::htmlcollection::{CollectionFilter, HTMLCollection}; use dom::htmlelement::HTMLElement; use dom::htmlformelement::{FormControl, HTMLFormElement}; -use dom::node::{IN_ENABLED_STATE, Node, NodeFlags, window_from_node}; +use dom::node::{Node, window_from_node}; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use util::str::{DOMString, StaticStringVec}; @@ -30,7 +30,7 @@ impl HTMLFieldSetElement { document: &Document) -> HTMLFieldSetElement { HTMLFieldSetElement { htmlelement: - HTMLElement::new_inherited_with_flags(NodeFlags::new() | IN_ENABLED_STATE, + HTMLElement::new_inherited_with_state(IN_ENABLED_STATE, localName, prefix, document) } } @@ -99,8 +99,9 @@ impl VirtualMethods for HTMLFieldSetElement { AttributeMutation::Removed => false, }; let node = NodeCast::from_ref(self); - node.set_disabled_state(disabled_state); - node.set_enabled_state(!disabled_state); + let el = ElementCast::from_ref(self); + el.set_disabled_state(disabled_state); + el.set_enabled_state(!disabled_state); let mut found_legend = false; let children = node.children().filter(|node| { if found_legend { @@ -135,13 +136,15 @@ impl VirtualMethods for HTMLFieldSetElement { }); if disabled_state { for field in fields { - field.set_disabled_state(true); - field.set_enabled_state(false); + let el = ElementCast::to_ref(field.r()).unwrap(); + el.set_disabled_state(true); + el.set_enabled_state(false); } } else { for field in fields { - field.check_disabled_attribute(); - field.check_ancestors_disabled_state_for_form_control(); + let el = ElementCast::to_ref(field.r()).unwrap(); + el.check_disabled_attribute(); + el.check_ancestors_disabled_state_for_form_control(); } } }, diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs index 46caced7d45..8fa12c02c6c 100644 --- a/components/script/dom/htmlformelement.rs +++ b/components/script/dom/htmlformelement.rs @@ -223,9 +223,11 @@ impl HTMLFormElement { // TODO: This is an incorrect way of getting controls owned // by the form, but good enough until html5ever lands node.traverse_preorder().filter_map(|child| { - if child.r().get_disabled_state() { - return None; + match ElementCast::to_ref(child.r()) { + Some(el) if !el.get_disabled_state() => (), + _ => return None, } + if child.r().ancestors() .any(|a| HTMLDataListElementCast::to_root(a).is_some()) { return None; diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index c07022306d6..9e58d68a4e2 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -100,7 +100,6 @@ impl HTMLImageElement { let node = NodeCast::from_ref(self); let document = node.owner_doc(); let window = document.r().window(); - let window = window.r(); let image_cache = window.image_cache_task(); match value { None => { diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index cdfe8716775..78ca2e3e726 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -17,14 +17,14 @@ use dom::bindings::codegen::InheritTypes::{KeyboardEventCast, NodeCast}; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, LayoutJS, Root, RootedReference}; use dom::document::Document; -use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; +use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE, RawLayoutElementHelpers}; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::eventtarget::EventTarget; use dom::htmlelement::HTMLElement; use dom::htmlformelement::{FormControl, FormDatum, FormSubmitter, HTMLFormElement}; use dom::htmlformelement::{ResetFrom, SubmittedFrom}; use dom::keyboardevent::KeyboardEvent; -use dom::node::{IN_ENABLED_STATE, Node, NodeDamage, NodeFlags}; +use dom::node::{Node, NodeDamage}; use dom::node::{document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; @@ -106,10 +106,10 @@ static DEFAULT_INPUT_SIZE: u32 = 20; impl HTMLInputElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLInputElement { - let chan = document.window().r().constellation_chan(); + let chan = document.window().constellation_chan(); HTMLInputElement { htmlelement: - HTMLElement::new_inherited_with_flags(NodeFlags::new() | IN_ENABLED_STATE, + HTMLElement::new_inherited_with_state(IN_ENABLED_STATE, localName, prefix, document), input_type: Cell::new(InputType::InputText), checked: Cell::new(false), @@ -359,12 +359,9 @@ fn broadcast_radio_checked(broadcaster: &HTMLInputElement, group: Option<&Atom>) // This function is a workaround for lifetime constraint difficulties. fn do_broadcast(doc_node: &Node, broadcaster: &HTMLInputElement, owner: Option<&HTMLFormElement>, group: Option<&Atom>) { - // There is no DOM tree manipulation here, so this is safe - let iter = unsafe { - doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap() - .filter_map(HTMLInputElementCast::to_root) - .filter(|r| in_same_group(r.r(), owner, group) && broadcaster != r.r()) - }; + let iter = doc_node.query_selector_iter("input[type=radio]".to_owned()) + .unwrap().filter_map(HTMLInputElementCast::to_root) + .filter(|r| in_same_group(r.r(), owner, group) && broadcaster != r.r()); for ref r in iter { if r.r().Checked() { r.r().SetChecked(false); @@ -472,8 +469,8 @@ impl HTMLInputElement { fn mutable(&self) -> bool { // https://html.spec.whatwg.org/multipage/#the-input-element:concept-fe-mutable // https://html.spec.whatwg.org/multipage/#the-readonly-attribute:concept-fe-mutable - let node = NodeCast::from_ref(self); - !(node.get_disabled_state() || self.ReadOnly()) + let el = ElementCast::from_ref(self); + !(el.get_disabled_state() || self.ReadOnly()) } // https://html.spec.whatwg.org/multipage/#the-input-element:concept-form-reset-control @@ -511,10 +508,10 @@ impl VirtualMethods for HTMLInputElement { }, AttributeMutation::Removed => false, }; - let node = NodeCast::from_ref(self); - node.set_disabled_state(disabled_state); - node.set_enabled_state(!disabled_state); - node.check_ancestors_disabled_state_for_form_control(); + let el = ElementCast::from_ref(self); + el.set_disabled_state(disabled_state); + el.set_enabled_state(!disabled_state); + el.check_ancestors_disabled_state_for_form_control(); }, &atom!(checked) if !self.checked_changed.get() => { let checked_state = match mutation { @@ -596,8 +593,8 @@ impl VirtualMethods for HTMLInputElement { s.bind_to_tree(tree_in_doc); } - let node = NodeCast::from_ref(self); - node.check_ancestors_disabled_state_for_form_control(); + let el = ElementCast::from_ref(self); + el.check_ancestors_disabled_state_for_form_control(); } fn unbind_from_tree(&self, tree_in_doc: bool) { @@ -606,10 +603,11 @@ impl VirtualMethods for HTMLInputElement { } let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) { - node.check_ancestors_disabled_state_for_form_control(); + el.check_ancestors_disabled_state_for_form_control(); } else { - node.check_disabled_attribute(); + el.check_disabled_attribute(); } } @@ -713,15 +711,12 @@ impl Activatable for HTMLInputElement { let doc_node = NodeCast::from_ref(doc.r()); let group = self.get_radio_group_name();; - // Safe since we only manipulate the DOM tree after finding an element - let checked_member = unsafe { - doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap() - .filter_map(HTMLInputElementCast::to_root) - .find(|r| { - in_same_group(r.r(), owner.r(), group.as_ref()) && - r.r().Checked() - }) - }; + let checked_member = doc_node.query_selector_iter("input[type=radio]".to_owned()).unwrap() + .filter_map(HTMLInputElementCast::to_root) + .find(|r| { + in_same_group(r.r(), owner.r(), group.as_ref()) && + r.r().Checked() + }); cache.checked_radio = checked_member.r().map(JS::from_ref); cache.checked_changed = self.checked_changed.get(); self.SetChecked(true); @@ -758,17 +753,16 @@ impl Activatable for HTMLInputElement { InputType::InputRadio => { // We want to restore state only if the element had been changed in the first place if cache.was_mutable { - let old_checked = cache.checked_radio.as_ref().map(|t| t.root()); let name = self.get_radio_group_name(); - match old_checked { - Some(ref o) => { + match cache.checked_radio.as_ref().map(|t| &*t) { + Some(o) => { // Avoiding iterating through the whole tree here, instead // we can check if the conditions for radio group siblings apply - if name == o.r().get_radio_group_name() && // TODO should be compatibility caseless - self.form_owner() == o.r().form_owner() && + if name == o.get_radio_group_name() && // TODO should be compatibility caseless + self.form_owner() == o.form_owner() && // TODO Both a and b are in the same home subtree - o.r().input_type.get() == InputType::InputRadio { - o.r().SetChecked(true); + o.input_type.get() == InputType::InputRadio { + o.SetChecked(true); } else { self.SetChecked(false); } @@ -849,14 +843,10 @@ impl Activatable for HTMLInputElement { if elem.click_in_progress() { return; } - // This is safe because we are stopping after finding the first element - // and only then performing actions which may modify the DOM tree let submit_button; - unsafe { - submit_button = node.query_selector_iter("input[type=submit]".to_owned()).unwrap() - .filter_map(HTMLInputElementCast::to_root) - .find(|r| r.r().form_owner() == owner); - } + submit_button = node.query_selector_iter("input[type=submit]".to_owned()).unwrap() + .filter_map(HTMLInputElementCast::to_root) + .find(|r| r.r().form_owner() == owner); match submit_button { Some(ref button) => { if button.r().is_instance_activatable() { @@ -864,28 +854,23 @@ impl Activatable for HTMLInputElement { } } None => { - unsafe { - // Safe because we don't perform any DOM modification - // until we're done with the iterator. - let inputs = node.query_selector_iter("input".to_owned()).unwrap() - .filter_map(HTMLInputElementCast::to_root) - .filter(|input| { - input.r().form_owner() == owner && match &*input.r().Type() { - "text" | "search" | "url" | "tel" | - "email" | "password" | "datetime" | - "date" | "month" | "week" | "time" | - "datetime-local" | "number" - => true, - _ => false - } - }); + let inputs = node.query_selector_iter("input".to_owned()).unwrap() + .filter_map(HTMLInputElementCast::to_root) + .filter(|input| { + input.r().form_owner() == owner && match &*input.r().Type() { + "text" | "search" | "url" | "tel" | + "email" | "password" | "datetime" | + "date" | "month" | "week" | "time" | + "datetime-local" | "number" + => true, + _ => false + } + }); - if inputs.skip(1).next().is_some() { - // lazily test for > 1 submission-blocking inputs - return; - } + if inputs.skip(1).next().is_some() { + // lazily test for > 1 submission-blocking inputs + return; } - form.r().submit(SubmittedFrom::NotFromFormSubmitMethod, FormSubmitter::FormElement(form.r())); } diff --git a/components/script/dom/htmloptgroupelement.rs b/components/script/dom/htmloptgroupelement.rs index b90eacff87f..cabb19936ab 100644 --- a/components/script/dom/htmloptgroupelement.rs +++ b/components/script/dom/htmloptgroupelement.rs @@ -5,12 +5,13 @@ use dom::attr::Attr; use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding; use dom::bindings::codegen::Bindings::HTMLOptGroupElementBinding::HTMLOptGroupElementMethods; -use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLOptionElementDerived, NodeCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLOptionElementCast}; +use dom::bindings::codegen::InheritTypes::{HTMLOptionElementDerived, NodeCast}; use dom::bindings::js::Root; use dom::document::Document; -use dom::element::AttributeMutation; +use dom::element::{AttributeMutation, IN_ENABLED_STATE}; use dom::htmlelement::HTMLElement; -use dom::node::{IN_ENABLED_STATE, Node, NodeFlags}; +use dom::node::{Node}; use dom::virtualmethods::VirtualMethods; use util::str::DOMString; @@ -25,7 +26,7 @@ impl HTMLOptGroupElement { document: &Document) -> HTMLOptGroupElement { HTMLOptGroupElement { htmlelement: - HTMLElement::new_inherited_with_flags(NodeFlags::new() | IN_ENABLED_STATE, + HTMLElement::new_inherited_with_state(IN_ENABLED_STATE, localName, prefix, document) } } @@ -66,19 +67,22 @@ impl VirtualMethods for HTMLOptGroupElement { AttributeMutation::Removed => false, }; let node = NodeCast::from_ref(self); - node.set_disabled_state(disabled_state); - node.set_enabled_state(!disabled_state); + let el = ElementCast::from_ref(self); + el.set_disabled_state(disabled_state); + el.set_enabled_state(!disabled_state); let options = node.children().filter(|child| { child.is_htmloptionelement() - }); + }).map(|child| Root::from_ref(HTMLOptionElementCast::to_ref(child.r()).unwrap())); if disabled_state { for option in options { - option.set_disabled_state(true); - option.set_enabled_state(false); + let el = ElementCast::from_ref(option.r()); + el.set_disabled_state(true); + el.set_enabled_state(false); } } else { for option in options { - option.check_disabled_attribute(); + let el = ElementCast::from_ref(option.r()); + el.check_disabled_attribute(); } } }, diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs index 74454c14355..b84fc43af34 100644 --- a/components/script/dom/htmloptionelement.rs +++ b/components/script/dom/htmloptionelement.rs @@ -12,9 +12,9 @@ use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLScriptElementDer use dom::bindings::codegen::InheritTypes::{NodeCast, TextDerived}; use dom::bindings::js::Root; use dom::document::Document; -use dom::element::{AttributeMutation, Element}; +use dom::element::{AttributeMutation, Element, IN_ENABLED_STATE}; use dom::htmlelement::HTMLElement; -use dom::node::{IN_ENABLED_STATE, Node, NodeFlags}; +use dom::node::{Node}; use dom::virtualmethods::VirtualMethods; use std::cell::Cell; use util::str::{DOMString, split_html_space_chars, str_join}; @@ -36,7 +36,7 @@ impl HTMLOptionElement { document: &Document) -> HTMLOptionElement { HTMLOptionElement { htmlelement: - HTMLElement::new_inherited_with_flags(NodeFlags::new() | IN_ENABLED_STATE, + HTMLElement::new_inherited_with_state(IN_ENABLED_STATE, localName, prefix, document), selectedness: Cell::new(false), dirtiness: Cell::new(false), @@ -151,16 +151,16 @@ impl VirtualMethods for HTMLOptionElement { self.super_type().unwrap().attribute_mutated(attr, mutation); match attr.local_name() { &atom!(disabled) => { - let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); match mutation { AttributeMutation::Set(_) => { - node.set_disabled_state(true); - node.set_enabled_state(false); + el.set_disabled_state(true); + el.set_enabled_state(false); }, AttributeMutation::Removed => { - node.set_disabled_state(false); - node.set_enabled_state(true); - node.check_parent_disabled_state_for_option(); + el.set_disabled_state(false); + el.set_enabled_state(true); + el.check_parent_disabled_state_for_option(); } } }, @@ -189,8 +189,8 @@ impl VirtualMethods for HTMLOptionElement { s.bind_to_tree(tree_in_doc); } - let node = NodeCast::from_ref(self); - node.check_parent_disabled_state_for_option(); + let el = ElementCast::from_ref(self); + el.check_parent_disabled_state_for_option(); } fn unbind_from_tree(&self, tree_in_doc: bool) { @@ -199,10 +199,11 @@ impl VirtualMethods for HTMLOptionElement { } let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); if node.GetParentNode().is_some() { - node.check_parent_disabled_state_for_option(); + el.check_parent_disabled_state_for_option(); } else { - node.check_disabled_attribute(); + el.check_disabled_attribute(); } } } diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index b6f9e97e712..579fe0c7c1b 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -209,7 +209,7 @@ impl HTMLScriptElement { // Step 10. let document_from_node_ref = document_from_node(self); let document_from_node_ref = document_from_node_ref.r(); - if self.parser_inserted.get() && self.parser_document.root().r() != document_from_node_ref { + if self.parser_inserted.get() && &*self.parser_document != document_from_node_ref { return NextParserState::Continue; } diff --git a/components/script/dom/htmlselectelement.rs b/components/script/dom/htmlselectelement.rs index 33a46acace1..878bfe2538c 100644 --- a/components/script/dom/htmlselectelement.rs +++ b/components/script/dom/htmlselectelement.rs @@ -5,15 +5,15 @@ use dom::attr::{Attr, AttrValue}; use dom::bindings::codegen::Bindings::HTMLSelectElementBinding; use dom::bindings::codegen::Bindings::HTMLSelectElementBinding::HTMLSelectElementMethods; -use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLFieldSetElementDerived, NodeCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, HTMLFieldSetElementDerived, NodeCast}; use dom::bindings::codegen::UnionTypes::HTMLElementOrLong; use dom::bindings::codegen::UnionTypes::HTMLOptionElementOrHTMLOptGroupElement; use dom::bindings::js::Root; use dom::document::Document; -use dom::element::AttributeMutation; +use dom::element::{AttributeMutation, IN_ENABLED_STATE}; use dom::htmlelement::HTMLElement; use dom::htmlformelement::{FormControl, HTMLFormElement}; -use dom::node::{IN_ENABLED_STATE, Node, NodeFlags, window_from_node}; +use dom::node::{Node, window_from_node}; use dom::validitystate::ValidityState; use dom::virtualmethods::VirtualMethods; use std::borrow::ToOwned; @@ -33,7 +33,7 @@ impl HTMLSelectElement { document: &Document) -> HTMLSelectElement { HTMLSelectElement { htmlelement: - HTMLElement::new_inherited_with_flags(NodeFlags::new() | IN_ENABLED_STATE, + HTMLElement::new_inherited_with_state(IN_ENABLED_STATE, localName, prefix, document) } } @@ -107,16 +107,16 @@ impl VirtualMethods for HTMLSelectElement { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { self.super_type().unwrap().attribute_mutated(attr, mutation); if attr.local_name() == &atom!(disabled) { - let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); match mutation { AttributeMutation::Set(_) => { - node.set_disabled_state(true); - node.set_enabled_state(false); + el.set_disabled_state(true); + el.set_enabled_state(false); }, AttributeMutation::Removed => { - node.set_disabled_state(false); - node.set_enabled_state(true); - node.check_ancestors_disabled_state_for_form_control(); + el.set_disabled_state(false); + el.set_enabled_state(true); + el.check_ancestors_disabled_state_for_form_control(); } } } @@ -127,8 +127,8 @@ impl VirtualMethods for HTMLSelectElement { s.bind_to_tree(tree_in_doc); } - let node = NodeCast::from_ref(self); - node.check_ancestors_disabled_state_for_form_control(); + let el = ElementCast::from_ref(self); + el.check_ancestors_disabled_state_for_form_control(); } fn unbind_from_tree(&self, tree_in_doc: bool) { @@ -137,10 +137,11 @@ impl VirtualMethods for HTMLSelectElement { } let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) { - node.check_ancestors_disabled_state_for_form_control(); + el.check_ancestors_disabled_state_for_form_control(); } else { - node.check_disabled_attribute(); + el.check_disabled_attribute(); } } diff --git a/components/script/dom/htmltablerowelement.rs b/components/script/dom/htmltablerowelement.rs index a485048b240..a35d5d79d66 100644 --- a/components/script/dom/htmltablerowelement.rs +++ b/components/script/dom/htmltablerowelement.rs @@ -8,11 +8,13 @@ use dom::bindings::codegen::Bindings::HTMLTableRowElementBinding::{self, HTMLTab use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTableDataCellElementDerived}; use dom::bindings::codegen::InheritTypes::{HTMLTableHeaderCellElementDerived, NodeCast}; +use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::js::{JS, MutNullableHeap, Root, RootedReference}; use dom::document::Document; use dom::element::{AttributeMutation, Element}; use dom::htmlcollection::{CollectionFilter, HTMLCollection}; use dom::htmlelement::HTMLElement; +use dom::htmltabledatacellelement::HTMLTableDataCellElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use std::cell::Cell; @@ -73,6 +75,24 @@ impl HTMLTableRowElementMethods for HTMLTableRowElement { HTMLCollection::create(window.r(), NodeCast::from_ref(self), filter) }) } + + // https://html.spec.whatwg.org/multipage/#dom-tr-insertcell + fn InsertCell(&self, index: i32) -> Fallible<Root<HTMLElement>> { + let node = NodeCast::from_ref(self); + node.insert_cell_or_row( + index, + || self.Cells(), + || HTMLTableDataCellElement::new("td".to_owned(), None, node.owner_doc().r())) + } + + // https://html.spec.whatwg.org/multipage/#dom-tr-deletecell + fn DeleteCell(&self, index: i32) -> ErrorResult { + let node = NodeCast::from_ref(self); + node.delete_cell_or_row( + index, + || self.Cells(), + |n| n.is_htmltabledatacellelement()) + } } impl VirtualMethods for HTMLTableRowElement { diff --git a/components/script/dom/htmltablesectionelement.rs b/components/script/dom/htmltablesectionelement.rs index a384afcaae7..dfc2ceb5900 100644 --- a/components/script/dom/htmltablesectionelement.rs +++ b/components/script/dom/htmltablesectionelement.rs @@ -4,12 +4,9 @@ use cssparser::RGBA; use dom::attr::Attr; -use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods; use dom::bindings::codegen::Bindings::HTMLTableSectionElementBinding::{self, HTMLTableSectionElementMethods}; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; -use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast}; -use dom::bindings::codegen::InheritTypes::{HTMLTableRowElementDerived, NodeCast}; -use dom::bindings::error::Error; +use dom::bindings::codegen::InheritTypes::{HTMLElementCast, HTMLTableRowElementDerived, NodeCast}; use dom::bindings::error::{ErrorResult, Fallible}; use dom::bindings::js::{Root, RootedReference}; use dom::document::Document; @@ -20,7 +17,6 @@ use dom::htmltablerowelement::HTMLTableRowElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; use std::cell::Cell; -use std::iter; use util::str::{self, DOMString}; #[dom_struct] @@ -67,57 +63,20 @@ impl HTMLTableSectionElementMethods for HTMLTableSectionElement { // https://html.spec.whatwg.org/multipage/#dom-tbody-insertrow fn InsertRow(&self, index: i32) -> Fallible<Root<HTMLElement>> { - if index < -1 { - return Err(Error::IndexSize); - } - let node = NodeCast::from_ref(self); - let tr = HTMLTableRowElement::new("tr".to_owned(), None, node.owner_doc().r()); - - let after_node = if index == -1 { - None - } else { - match self.Rows() - .elements_iter() - .map(NodeCast::from_root) - .map(Some) - .chain(iter::once(None)) - .nth(index as usize) { - None => return Err(Error::IndexSize), - Some(node) => node, - } - }; - - { - let tr_node = NodeCast::from_ref(tr.r()); - try!(node.InsertBefore(tr_node, after_node.r())); - } - - Ok(HTMLElementCast::from_root(tr)) + node.insert_cell_or_row( + index, + || self.Rows(), + || HTMLTableRowElement::new("tr".to_owned(), None, node.owner_doc().r())) } // https://html.spec.whatwg.org/multipage/#dom-tbody-deleterow fn DeleteRow(&self, index: i32) -> ErrorResult { - let element = match index { - index if index < -1 => return Err(Error::IndexSize), - -1 => { - let last_child = NodeCast::from_ref(self).GetLastChild(); - match last_child.and_then(|node| node.inclusively_preceding_siblings() - .filter_map(ElementCast::to_root) - .filter(|n| n.is_htmltablerowelement()) - .next()) { - Some(element) => element, - None => return Ok(()), - } - }, - index => match self.Rows().Item(index as u32) { - Some(element) => element, - None => return Err(Error::IndexSize), - }, - }; - - NodeCast::from_ref(element.r()).remove_self(); - Ok(()) + let node = NodeCast::from_ref(self); + node.delete_cell_or_row( + index, + || self.Rows(), + |n| n.is_htmltablerowelement()) } } diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs index 19cd81e6519..ba46c064762 100644 --- a/components/script/dom/htmltextareaelement.rs +++ b/components/script/dom/htmltextareaelement.rs @@ -15,13 +15,13 @@ use dom::bindings::global::GlobalRef; use dom::bindings::js::{LayoutJS, Root}; use dom::bindings::refcounted::Trusted; use dom::document::Document; -use dom::element::AttributeMutation; +use dom::element::{AttributeMutation, IN_ENABLED_STATE}; use dom::event::{Event, EventBubbles, EventCancelable}; use dom::htmlelement::HTMLElement; use dom::htmlformelement::{FormControl, HTMLFormElement}; use dom::keyboardevent::KeyboardEvent; -use dom::node::{ChildrenMutation, IN_ENABLED_STATE, Node, NodeDamage}; -use dom::node::{NodeFlags, document_from_node, window_from_node}; +use dom::node::{ChildrenMutation, Node, NodeDamage}; +use dom::node::{document_from_node, window_from_node}; use dom::virtualmethods::VirtualMethods; use msg::constellation_msg::ConstellationChan; use script_task::ScriptTaskEventCategory::InputEvent; @@ -84,10 +84,10 @@ impl HTMLTextAreaElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: &Document) -> HTMLTextAreaElement { - let chan = document.window().r().constellation_chan(); + let chan = document.window().constellation_chan(); HTMLTextAreaElement { htmlelement: - HTMLElement::new_inherited_with_flags(NodeFlags::new() | IN_ENABLED_STATE, + HTMLElement::new_inherited_with_state(IN_ENABLED_STATE, localName, prefix, document), textinput: DOMRefCell::new(TextInput::new(Lines::Multiple, "".to_owned(), chan)), cols: Cell::new(DEFAULT_COLS), @@ -245,16 +245,16 @@ impl VirtualMethods for HTMLTextAreaElement { self.super_type().unwrap().attribute_mutated(attr, mutation); match attr.local_name() { &atom!(disabled) => { - let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); match mutation { AttributeMutation::Set(_) => { - node.set_disabled_state(true); - node.set_enabled_state(false); + el.set_disabled_state(true); + el.set_enabled_state(false); }, AttributeMutation::Removed => { - node.set_disabled_state(false); - node.set_enabled_state(true); - node.check_ancestors_disabled_state_for_form_control(); + el.set_disabled_state(false); + el.set_enabled_state(true); + el.check_ancestors_disabled_state_for_form_control(); } } }, @@ -279,8 +279,8 @@ impl VirtualMethods for HTMLTextAreaElement { s.bind_to_tree(tree_in_doc); } - let node = NodeCast::from_ref(self); - node.check_ancestors_disabled_state_for_form_control(); + let el = ElementCast::from_ref(self); + el.check_ancestors_disabled_state_for_form_control(); } fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { @@ -297,10 +297,11 @@ impl VirtualMethods for HTMLTextAreaElement { } let node = NodeCast::from_ref(self); + let el = ElementCast::from_ref(self); if node.ancestors().any(|ancestor| ancestor.r().is_htmlfieldsetelement()) { - node.check_ancestors_disabled_state_for_form_control(); + el.check_ancestors_disabled_state_for_form_control(); } else { - node.check_disabled_attribute(); + el.check_disabled_attribute(); } } diff --git a/components/script/dom/location.rs b/components/script/dom/location.rs index c366139649b..a9e788a7b04 100644 --- a/components/script/dom/location.rs +++ b/components/script/dom/location.rs @@ -4,7 +4,6 @@ use dom::bindings::codegen::Bindings::LocationBinding; use dom::bindings::codegen::Bindings::LocationBinding::LocationMethods; -use dom::bindings::error::ErrorResult; use dom::bindings::global::GlobalRef; use dom::bindings::js::{JS, Root}; use dom::bindings::str::USVString; @@ -35,141 +34,117 @@ impl Location { } fn get_url(&self) -> Url { - self.window.root().get_url() + self.window.get_url() } fn set_url_component(&self, value: USVString, setter: fn(&mut Url, USVString)) { - let window = self.window.root(); - let mut url = window.get_url(); + let mut url = self.window.get_url(); setter(&mut url, value); - window.load_url(url); + self.window.load_url(url); } } impl LocationMethods for Location { // https://html.spec.whatwg.org/multipage/#dom-location-assign - fn Assign(&self, url: DOMString) { - let window = self.window.root(); + fn Assign(&self, url: USVString) { // TODO: per spec, we should use the _API base URL_ specified by the // _entry settings object_. - let base_url = window.get_url(); - if let Ok(url) = UrlParser::new().base_url(&base_url).parse(&url) { - window.load_url(url); + let base_url = self.window.get_url(); + if let Ok(url) = UrlParser::new().base_url(&base_url).parse(&url.0) { + self.window.load_url(url); } } // https://html.spec.whatwg.org/multipage/#dom-location-reload fn Reload(&self) { - self.window.root().load_url(self.get_url()); + self.window.load_url(self.get_url()); } - // https://url.spec.whatwg.org/#dom-urlutils-hash + // https://html.spec.whatwg.org/multipage/#dom-location-hash fn Hash(&self) -> USVString { UrlHelper::Hash(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-hash + // https://html.spec.whatwg.org/multipage/#dom-location-hash fn SetHash(&self, value: USVString) { self.set_url_component(value, UrlHelper::SetHash); } - // https://url.spec.whatwg.org/#dom-urlutils-host + // https://html.spec.whatwg.org/multipage/#dom-location-host fn Host(&self) -> USVString { UrlHelper::Host(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-host + // https://html.spec.whatwg.org/multipage/#dom-location-host fn SetHost(&self, value: USVString) { self.set_url_component(value, UrlHelper::SetHost); } - // https://url.spec.whatwg.org/#dom-urlutils-hostname + // https://html.spec.whatwg.org/multipage/#dom-location-hostname fn Hostname(&self) -> USVString { UrlHelper::Hostname(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-hostname + // https://html.spec.whatwg.org/multipage/#dom-location-hostname fn SetHostname(&self, value: USVString) { self.set_url_component(value, UrlHelper::SetHostname); } - // https://url.spec.whatwg.org/#dom-urlutils-href + // https://html.spec.whatwg.org/multipage/#dom-location-href fn Href(&self) -> USVString { UrlHelper::Href(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-href - fn SetHref(&self, value: USVString) -> ErrorResult { - let window = self.window.root(); - if let Ok(url) = UrlParser::new().base_url(&window.get_url()).parse(&value.0) { - window.load_url(url); - }; - Ok(()) - } - - // https://url.spec.whatwg.org/#dom-urlutils-password - fn Password(&self) -> USVString { - UrlHelper::Password(&self.get_url()) - } - - // https://url.spec.whatwg.org/#dom-urlutils-password - fn SetPassword(&self, value: USVString) { - self.set_url_component(value, UrlHelper::SetPassword); + // https://html.spec.whatwg.org/multipage/#dom-location-href + fn SetHref(&self, value: USVString) { + if let Ok(url) = UrlParser::new().base_url(&self.window.get_url()).parse(&value.0) { + self.window.load_url(url); + } } - // https://url.spec.whatwg.org/#dom-urlutils-pathname + // https://html.spec.whatwg.org/multipage/#dom-location-pathname fn Pathname(&self) -> USVString { UrlHelper::Pathname(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-pathname + // https://html.spec.whatwg.org/multipage/#dom-location-pathname fn SetPathname(&self, value: USVString) { self.set_url_component(value, UrlHelper::SetPathname); } - // https://url.spec.whatwg.org/#dom-urlutils-port + // https://html.spec.whatwg.org/multipage/#dom-location-port fn Port(&self) -> USVString { UrlHelper::Port(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-port + // https://html.spec.whatwg.org/multipage/#dom-location-port fn SetPort(&self, value: USVString) { self.set_url_component(value, UrlHelper::SetPort); } - // https://url.spec.whatwg.org/#dom-urlutils-protocol + // https://html.spec.whatwg.org/multipage/#dom-location-protocol fn Protocol(&self) -> USVString { UrlHelper::Protocol(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-protocol + // https://html.spec.whatwg.org/multipage/#dom-location-protocol fn SetProtocol(&self, value: USVString) { self.set_url_component(value, UrlHelper::SetProtocol); } - // https://url.spec.whatwg.org/#URLUtils-stringification-behavior + // https://html.spec.whatwg.org/multipage/#dom-location-href fn Stringifier(&self) -> DOMString { self.Href().0 } - // https://url.spec.whatwg.org/#dom-urlutils-search + // https://html.spec.whatwg.org/multipage/#dom-location-search fn Search(&self) -> USVString { UrlHelper::Search(&self.get_url()) } - // https://url.spec.whatwg.org/#dom-urlutils-search + // https://html.spec.whatwg.org/multipage/#dom-location-search fn SetSearch(&self, value: USVString) { self.set_url_component(value, UrlHelper::SetSearch); } - - // https://url.spec.whatwg.org/#dom-urlutils-username - fn Username(&self) -> USVString { - UrlHelper::Username(&self.get_url()) - } - - // https://url.spec.whatwg.org/#dom-urlutils-username - fn SetUsername(&self, value: USVString) { - self.set_url_component(value, UrlHelper::SetUsername); - } } diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 05d89c232df..c8179c3f0e3 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -220,6 +220,7 @@ pub mod dompoint; pub mod dompointreadonly; pub mod domrect; pub mod domrectlist; +pub mod domrectreadonly; pub mod domstringmap; pub mod domtokenlist; pub mod element; diff --git a/components/script/dom/namednodemap.rs b/components/script/dom/namednodemap.rs index 078ddcc0d84..6070c0bb0c2 100644 --- a/components/script/dom/namednodemap.rs +++ b/components/script/dom/namednodemap.rs @@ -37,57 +37,38 @@ impl NamedNodeMap { impl NamedNodeMapMethods for NamedNodeMap { // https://dom.spec.whatwg.org/#dom-namednodemap-length fn Length(&self) -> u32 { - let owner = self.owner.root(); - // FIXME(https://github.com/rust-lang/rust/issues/23338) - let owner = owner.r(); - let attrs = owner.attrs(); - attrs.len() as u32 + self.owner.attrs().len() as u32 } // https://dom.spec.whatwg.org/#dom-namednodemap-item fn Item(&self, index: u32) -> Option<Root<Attr>> { - let owner = self.owner.root(); - // FIXME(https://github.com/rust-lang/rust/issues/23338) - let owner = owner.r(); - let attrs = owner.attrs(); - attrs.get(index as usize).map(|t| t.root()) + self.owner.attrs().get(index as usize).map(JS::root) } // https://dom.spec.whatwg.org/#dom-namednodemap-getnameditem fn GetNamedItem(&self, name: DOMString) -> Option<Root<Attr>> { - let owner = self.owner.root(); - // FIXME(https://github.com/rust-lang/rust/issues/23338) - let owner = owner.r(); - owner.get_attribute_by_name(name) + self.owner.get_attribute_by_name(name) } // https://dom.spec.whatwg.org/#dom-namednodemap-getnameditemns fn GetNamedItemNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Option<Root<Attr>> { - let owner = self.owner.root(); - // FIXME(https://github.com/rust-lang/rust/issues/23338) - let owner = owner.r(); let ns = namespace_from_domstring(namespace); - owner.get_attribute(&ns, &Atom::from_slice(&local_name)) + self.owner.get_attribute(&ns, &Atom::from_slice(&local_name)) } // https://dom.spec.whatwg.org/#dom-namednodemap-removenameditem fn RemoveNamedItem(&self, name: DOMString) -> Fallible<Root<Attr>> { - let owner = self.owner.root(); - // FIXME(https://github.com/rust-lang/rust/issues/23338) - let owner = owner.r(); - let name = owner.parsed_name(name); - owner.remove_attribute_by_name(&name).ok_or(Error::NotFound) + let name = self.owner.parsed_name(name); + self.owner.remove_attribute_by_name(&name).ok_or(Error::NotFound) } // https://dom.spec.whatwg.org/#dom-namednodemap-removenameditemns fn RemoveNamedItemNS(&self, namespace: Option<DOMString>, local_name: DOMString) -> Fallible<Root<Attr>> { - let owner = self.owner.root(); - // FIXME(https://github.com/rust-lang/rust/issues/23338) - let owner = owner.r(); let ns = namespace_from_domstring(namespace); - owner.remove_attribute(&ns, &Atom::from_slice(&local_name)).ok_or(Error::NotFound) + self.owner.remove_attribute(&ns, &Atom::from_slice(&local_name)) + .ok_or(Error::NotFound) } // https://dom.spec.whatwg.org/#dom-namednodemap-item diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index daacdd09fa0..b50d71ccd10 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -14,16 +14,18 @@ use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::CharacterDataBinding::CharacterDataMethods; use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods; use dom::bindings::codegen::Bindings::ElementBinding::ElementMethods; +use dom::bindings::codegen::Bindings::HTMLCollectionBinding::HTMLCollectionMethods; use dom::bindings::codegen::Bindings::NamedNodeMapBinding::NamedNodeMapMethods; use dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods}; use dom::bindings::codegen::Bindings::NodeListBinding::NodeListMethods; use dom::bindings::codegen::Bindings::ProcessingInstructionBinding::ProcessingInstructionMethods; +use dom::bindings::codegen::InheritTypes::HTMLElementBase; +use dom::bindings::codegen::InheritTypes::HTMLElementCast; use dom::bindings::codegen::InheritTypes::{CharacterDataCast, CharacterDataTypeId}; use dom::bindings::codegen::InheritTypes::{DocumentCast, DocumentDerived, DocumentTypeCast}; use dom::bindings::codegen::InheritTypes::{ElementCast, ElementDerived, ElementTypeId}; use dom::bindings::codegen::InheritTypes::{EventTargetCast, EventTargetTypeId}; -use dom::bindings::codegen::InheritTypes::{HTMLElementTypeId, HTMLFieldSetElementDerived}; -use dom::bindings::codegen::InheritTypes::{HTMLLegendElementDerived, HTMLOptGroupElementDerived}; +use dom::bindings::codegen::InheritTypes::{HTMLElementTypeId}; use dom::bindings::codegen::InheritTypes::{NodeBase, NodeCast, NodeTypeId}; use dom::bindings::codegen::InheritTypes::{ProcessingInstructionCast, TextCast, TextDerived}; use dom::bindings::codegen::UnionTypes::NodeOrString; @@ -43,6 +45,8 @@ use dom::documentfragment::DocumentFragment; use dom::documenttype::DocumentType; use dom::element::{Element, ElementCreator}; use dom::eventtarget::EventTarget; +use dom::htmlcollection::HTMLCollection; +use dom::htmlelement::HTMLElement; use dom::nodelist::NodeList; use dom::processinginstruction::ProcessingInstruction; use dom::text::Text; @@ -60,7 +64,7 @@ use selectors::parser::parse_author_origin_selector_list_from_str; use std::borrow::ToOwned; use std::cell::{Cell, Ref, RefCell, RefMut}; use std::default::Default; -use std::iter::{FilterMap, Peekable}; +use std::iter::{self, FilterMap, Peekable}; use std::mem; use std::slice::ref_slice; use std::sync::Arc; @@ -125,40 +129,28 @@ impl PartialEq for Node { bitflags! { #[doc = "Flags for node items."] #[derive(JSTraceable, HeapSizeOf)] - flags NodeFlags: u16 { + flags NodeFlags: u8 { #[doc = "Specifies whether this node is in a document."] const IS_IN_DOC = 0x01, - #[doc = "Specifies whether this node is in hover state."] - const IN_HOVER_STATE = 0x02, - #[doc = "Specifies whether this node is in disabled state."] - const IN_DISABLED_STATE = 0x04, - #[doc = "Specifies whether this node is in enabled state."] - const IN_ENABLED_STATE = 0x08, #[doc = "Specifies whether this node _must_ be reflowed regardless of style differences."] - const HAS_CHANGED = 0x10, + const HAS_CHANGED = 0x02, #[doc = "Specifies whether this node needs style recalc on next reflow."] - const IS_DIRTY = 0x20, + const IS_DIRTY = 0x04, #[doc = "Specifies whether this node has siblings (inclusive of itself) which \ changed since the last reflow."] - const HAS_DIRTY_SIBLINGS = 0x40, + const HAS_DIRTY_SIBLINGS = 0x08, #[doc = "Specifies whether this node has descendants (inclusive of itself) which \ have changed since the last reflow."] - const HAS_DIRTY_DESCENDANTS = 0x80, + const HAS_DIRTY_DESCENDANTS = 0x10, // TODO: find a better place to keep this (#4105) // https://critic.hoppipolla.co.uk/showcomment?chain=8873 // Perhaps using a Set in Document? #[doc = "Specifies whether or not there is an authentic click in progress on \ this element."] - const CLICK_IN_PROGRESS = 0x100, - #[doc = "Specifies whether this node has the focus."] - const IN_FOCUS_STATE = 0x200, + const CLICK_IN_PROGRESS = 0x20, #[doc = "Specifies whether this node is focusable and whether it is supposed \ to be reachable with using sequential focus navigation."] - const SEQUENTIALLY_FOCUSABLE = 0x400, - #[doc = "Specifies whether this node is [being activated]\ - (https://html.spec.whatwg.org/multipage/#selector-active). \ - FIXME(#7333): set/unset this when appropriate"] - const IN_ACTIVE_STATE = 0x800, + const SEQUENTIALLY_FOCUSABLE = 0x40, } } @@ -353,8 +345,7 @@ pub struct QuerySelectorIterator { } impl<'a> QuerySelectorIterator { - #[allow(unsafe_code)] - unsafe fn new(iter: TreeIterator, selectors: Vec<Selector>) + fn new(iter: TreeIterator, selectors: Vec<Selector>) -> QuerySelectorIterator { QuerySelectorIterator { selectors: selectors, @@ -474,49 +465,6 @@ impl Node { self.flags.set(flags); } - pub fn get_hover_state(&self) -> bool { - self.get_flag(IN_HOVER_STATE) - } - - pub fn set_hover_state(&self, state: bool) { - self.set_flag(IN_HOVER_STATE, state); - self.dirty(NodeDamage::NodeStyleDamaged); - } - - pub fn get_focus_state(&self) -> bool { - self.get_flag(IN_FOCUS_STATE) - } - - pub fn set_focus_state(&self, state: bool) { - self.set_flag(IN_FOCUS_STATE, state); - self.dirty(NodeDamage::NodeStyleDamaged); - } - - pub fn get_active_state(&self) -> bool { - self.get_flag(IN_ACTIVE_STATE) - } - - pub fn set_active_state(&self, state: bool) { - self.set_flag(IN_ACTIVE_STATE, state); - self.dirty(NodeDamage::NodeStyleDamaged); - } - - pub fn get_disabled_state(&self) -> bool { - self.get_flag(IN_DISABLED_STATE) - } - - pub fn set_disabled_state(&self, state: bool) { - self.set_flag(IN_DISABLED_STATE, state) - } - - pub fn get_enabled_state(&self) -> bool { - self.get_flag(IN_ENABLED_STATE) - } - - pub fn set_enabled_state(&self, state: bool) { - self.set_flag(IN_ENABLED_STATE, state) - } - pub fn get_has_changed(&self) -> bool { self.get_flag(HAS_CHANGED) } @@ -788,8 +736,7 @@ impl Node { /// Get an iterator over all nodes which match a set of selectors /// Be careful not to do anything which may manipulate the DOM tree /// whilst iterating, otherwise the iterator may be invalidated. - #[allow(unsafe_code)] - pub unsafe fn query_selector_iter(&self, selectors: DOMString) + pub fn query_selector_iter(&self, selectors: DOMString) -> Fallible<QuerySelectorIterator> { // Step 1. match parse_author_origin_selector_list_from_str(&selectors) { @@ -806,7 +753,7 @@ impl Node { #[allow(unsafe_code)] pub fn query_selector_all(&self, selectors: DOMString) -> Fallible<Root<NodeList>> { let window = window_from_node(self); - let iter = try!(unsafe { self.query_selector_iter(selectors) }); + let iter = try!(self.query_selector_iter(selectors)); Ok(NodeList::new_simple_list(window.r(), iter)) } @@ -918,6 +865,66 @@ impl Node { } Ok(fragment) } + + /// Used by `HTMLTableSectionElement::InsertRow` and `HTMLTableRowElement::InsertCell` + pub fn insert_cell_or_row<F, G, I>(&self, index: i32, get_items: F, new_child: G) -> Fallible<Root<HTMLElement>> + where F: Fn() -> Root<HTMLCollection>, + G: Fn() -> Root<I>, + I: NodeBase + HTMLElementBase + Reflectable, + { + if index < -1 { + return Err(Error::IndexSize); + } + + let tr = new_child(); + + let after_node = if index == -1 { + None + } else { + match get_items().elements_iter() + .map(NodeCast::from_root) + .map(Some) + .chain(iter::once(None)) + .nth(index as usize) { + None => return Err(Error::IndexSize), + Some(node) => node, + } + }; + + { + let tr_node = NodeCast::from_ref(tr.r()); + try!(self.InsertBefore(tr_node, after_node.r())); + } + + Ok(HTMLElementCast::from_root(tr)) + } + + /// Used by `HTMLTableSectionElement::DeleteRow` and `HTMLTableRowElement::DeleteCell` + pub fn delete_cell_or_row<F, G>(&self, index: i32, get_items: F, is_delete_type: G) -> ErrorResult + where F: Fn() -> Root<HTMLCollection>, + G: Fn(&Element) -> bool + { + let element = match index { + index if index < -1 => return Err(Error::IndexSize), + -1 => { + let last_child = NodeCast::from_ref(self).GetLastChild(); + match last_child.and_then(|node| node.inclusively_preceding_siblings() + .filter_map(ElementCast::to_root) + .filter(|elem| is_delete_type(elem)) + .next()) { + Some(element) => element, + None => return Ok(()), + } + }, + index => match get_items().Item(index as u32) { + Some(element) => element, + None => return Err(Error::IndexSize), + }, + }; + + NodeCast::from_ref(element.r()).remove_self(); + Ok(()) + } } @@ -975,12 +982,6 @@ pub trait LayoutNodeHelpers { unsafe fn layout_data(&self) -> Ref<Option<LayoutData>>; unsafe fn layout_data_mut(&self) -> RefMut<Option<LayoutData>>; unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData>; - - fn get_hover_state_for_layout(&self) -> bool; - fn get_focus_state_for_layout(&self) -> bool; - fn get_active_state_for_layout(&self) -> bool; - fn get_disabled_state_for_layout(&self) -> bool; - fn get_enabled_state_for_layout(&self) -> bool; } impl LayoutNodeHelpers for LayoutJS<Node> { @@ -1076,42 +1077,6 @@ impl LayoutNodeHelpers for LayoutJS<Node> { unsafe fn layout_data_unchecked(&self) -> *const Option<LayoutData> { (*self.unsafe_get()).layout_data.borrow_unchecked() } - - #[inline] - #[allow(unsafe_code)] - fn get_hover_state_for_layout(&self) -> bool { - unsafe { - self.get_flag(IN_HOVER_STATE) - } - } - #[inline] - #[allow(unsafe_code)] - fn get_focus_state_for_layout(&self) -> bool { - unsafe { - self.get_flag(IN_FOCUS_STATE) - } - } - #[inline] - #[allow(unsafe_code)] - fn get_active_state_for_layout(&self) -> bool { - unsafe { - self.get_flag(IN_ACTIVE_STATE) - } - } - #[inline] - #[allow(unsafe_code)] - fn get_disabled_state_for_layout(&self) -> bool { - unsafe { - self.get_flag(IN_DISABLED_STATE) - } - } - #[inline] - #[allow(unsafe_code)] - fn get_enabled_state_for_layout(&self) -> bool { - unsafe { - self.get_flag(IN_ENABLED_STATE) - } - } } @@ -1341,15 +1306,11 @@ impl Node { wrap_fn: extern "Rust" fn(*mut JSContext, GlobalRef, Box<N>) -> Root<N>) -> Root<N> { let window = document.window(); - reflect_dom_object(node, GlobalRef::Window(window.r()), wrap_fn) + reflect_dom_object(node, GlobalRef::Window(window), wrap_fn) } pub fn new_inherited(doc: &Document) -> Node { - Node::new_inherited_with_flags(NodeFlags::new(), doc) - } - - pub fn new_inherited_with_flags(flags: NodeFlags, doc: &Document) -> Node { - Node::new_(flags, Some(doc)) + Node::new_(NodeFlags::new(), Some(doc)) } #[allow(unrooted_must_root)] @@ -1688,7 +1649,7 @@ impl Node { }; let window = document.window(); let loader = DocumentLoader::new(&*document.loader()); - let document = Document::new(window.r(), Some((*document.url()).clone()), + let document = Document::new(window, Some((*document.url()).clone()), is_html_doc, None, None, DocumentSource::NotFromParser, loader); NodeCast::from_root(document) @@ -1929,7 +1890,7 @@ impl NodeMethods for Node { self.child_list.or_init(|| { let doc = self.owner_doc(); let window = doc.r().window(); - NodeList::new_child_list(window.r(), self) + NodeList::new_child_list(window, self) }) } @@ -2428,7 +2389,7 @@ pub fn document_from_node<T: NodeBase + Reflectable>(derived: &T) -> Root<Docume pub fn window_from_node<T: NodeBase + Reflectable>(derived: &T) -> Root<Window> { let document = document_from_node(derived); - document.r().window() + Root::from_ref(document.r().window()) } impl VirtualMethods for Node { @@ -2462,53 +2423,6 @@ impl VirtualMethods for Node { } } - -impl Node { - pub fn check_ancestors_disabled_state_for_form_control(&self) { - if self.get_disabled_state() { return; } - for ancestor in self.ancestors() { - let ancestor = ancestor; - let ancestor = ancestor.r(); - if !ancestor.is_htmlfieldsetelement() { continue; } - if !ancestor.get_disabled_state() { continue; } - if ancestor.is_parent_of(self) { - self.set_disabled_state(true); - self.set_enabled_state(false); - return; - } - match ancestor.children() - .find(|child| child.r().is_htmllegendelement()) - { - Some(ref legend) => { - // XXXabinader: should we save previous ancestor to avoid this iteration? - if self.ancestors().any(|ancestor| ancestor == *legend) { continue; } - }, - None => () - } - self.set_disabled_state(true); - self.set_enabled_state(false); - return; - } - } - - pub fn check_parent_disabled_state_for_option(&self) { - if self.get_disabled_state() { return; } - if let Some(ref parent) = self.GetParentNode() { - if parent.r().is_htmloptgroupelement() && parent.r().get_disabled_state() { - self.set_disabled_state(true); - self.set_enabled_state(false); - } - } - } - - pub fn check_disabled_attribute(&self) { - let elem = ElementCast::to_ref(self).unwrap(); - let has_disabled_attrib = elem.has_attribute(&atom!("disabled")); - self.set_disabled_state(has_disabled_attrib); - self.set_enabled_state(!has_disabled_attrib); - } -} - /// A summary of the changes that happened to a node. #[derive(Copy, Clone, PartialEq, HeapSizeOf)] pub enum NodeDamage { diff --git a/components/script/dom/nodeiterator.rs b/components/script/dom/nodeiterator.rs index c7152231776..27a99ec3b55 100644 --- a/components/script/dom/nodeiterator.rs +++ b/components/script/dom/nodeiterator.rs @@ -47,9 +47,8 @@ impl NodeIterator { root_node: &Node, what_to_show: u32, filter: Filter) -> Root<NodeIterator> { - let window = document.window(); reflect_dom_object(box NodeIterator::new_inherited(root_node, what_to_show, filter), - GlobalRef::Window(window.r()), + GlobalRef::Window(document.window()), NodeIteratorBinding::Wrap) } @@ -122,7 +121,7 @@ impl NodeIteratorMethods for NodeIterator { } // Step 3-1. - for following_node in node.r().following_nodes(self.root_node.root().r()) { + for following_node in node.r().following_nodes(&self.root_node) { // Step 3-2. let result = try!(self.accept_node(following_node.r())); @@ -166,7 +165,7 @@ impl NodeIteratorMethods for NodeIterator { } // Step 3-1. - for preceding_node in node.r().preceding_nodes(self.root_node.root().r()) { + for preceding_node in node.r().preceding_nodes(&self.root_node) { // Step 3-2. let result = try!(self.accept_node(preceding_node.r())); diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs index b5db05945ca..2ed127dd2dc 100644 --- a/components/script/dom/nodelist.rs +++ b/components/script/dom/nodelist.rs @@ -109,7 +109,7 @@ impl ChildrenList { } pub fn len(&self) -> u32 { - self.node.root().children_count() + self.node.children_count() } pub fn item(&self, index: u32) -> Option<Root<Node>> { @@ -121,7 +121,7 @@ impl ChildrenList { } if index == 0u32 { // Item is first child if any, not worth updating last visited. - return self.node.root().GetFirstChild(); + return self.node.GetFirstChild(); } let last_index = self.last_index.get(); if index == last_index { @@ -137,7 +137,7 @@ impl ChildrenList { } else if index > last_index { if index == len - 1u32 { // Item is parent's last child, not worth updating last visited. - return Some(self.node.root().GetLastChild().unwrap()); + return Some(self.node.GetLastChild().unwrap()); } if index <= last_index + (len - last_index) / 2u32 { // Item is closer to the last visited child and follows it. @@ -147,7 +147,7 @@ impl ChildrenList { } else { // Item is closer to parent's last child and obviously // precedes it. - self.node.root().GetLastChild().unwrap() + self.node.GetLastChild().unwrap() .inclusively_preceding_siblings() .nth((len - index - 1u32) as usize).unwrap() } @@ -159,7 +159,7 @@ impl ChildrenList { } else { // Item is closer to parent's first child and obviously follows it. debug_assert!(index < last_index / 2u32); - self.node.root().GetFirstChild().unwrap() + self.node.GetFirstChild().unwrap() .inclusively_following_siblings() .nth(index as usize) .unwrap() @@ -263,7 +263,7 @@ impl ChildrenList { } fn reset(&self) { - self.last_visited.set(self.node.root().GetFirstChild().as_ref().map(Root::r)); + self.last_visited.set(self.node.GetFirstChild().r()); self.last_index.set(0u32); } } diff --git a/components/script/dom/performance.rs b/components/script/dom/performance.rs index 2d0a5990cdc..b8b6c17ef09 100644 --- a/components/script/dom/performance.rs +++ b/components/script/dom/performance.rs @@ -51,7 +51,7 @@ impl PerformanceMethods for Performance { // https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/HighResolutionTime/Overview.html#dom-performance-now fn Now(&self) -> DOMHighResTimeStamp { - let navStart = self.timing.root().r().NavigationStartPrecise(); + let navStart = self.timing.NavigationStartPrecise(); let now = (time::precise_time_ns() as f64 - navStart) / 1000000 as f64; Finite::wrap(now) } diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs index 0b9a5cc0dbf..52ab9d24d66 100644 --- a/components/script/dom/range.rs +++ b/components/script/dom/range.rs @@ -49,10 +49,9 @@ impl Range { start_container: &Node, start_offset: u32, end_container: &Node, end_offset: u32) -> Root<Range> { - let window = document.window(); reflect_dom_object(box Range::new_inherited(start_container, start_offset, end_container, end_offset), - GlobalRef::Window(window.r()), + GlobalRef::Window(document.window()), RangeBinding::Wrap) } diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index 9b319e66a9a..2cf4bac0a4c 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -15,7 +15,7 @@ use dom::bindings::refcounted::Trusted; use dom::bindings::trace::JSTraceable; use dom::bindings::utils::{Reflector, reflect_dom_object}; use dom::document::Document; -use dom::node::{Node, window_from_node}; +use dom::node::Node; use dom::text::Text; use dom::window::Window; use encoding::all::UTF_8; @@ -48,8 +48,7 @@ impl Sink { match child { NodeOrText::AppendNode(n) => n.root(), NodeOrText::AppendText(t) => { - let doc = self.document.root(); - let text = Text::new(t.into(), &doc); + let text = Text::new(t.into(), &self.document); NodeCast::from_root(text) } } @@ -109,7 +108,7 @@ impl AsyncResponseListener for ParserContext { let parser = parser.r(); let win = parser.window(); - self.parser = Some(Trusted::new(win.r().get_cx(), parser, self.script_chan.clone())); + self.parser = Some(Trusted::new(win.get_cx(), parser, self.script_chan.clone())); match content_type { Some(ContentType(Mime(TopLevel::Image, _, _))) => { @@ -153,8 +152,7 @@ impl AsyncResponseListener for ParserContext { Some(parser) => parser.root(), None => return, }; - let doc = parser.r().document.root(); - doc.r().finish_load(LoadType::PageSource(self.url.clone())); + parser.document.finish_load(LoadType::PageSource(self.url.clone())); if let Err(err) = status { debug!("Failed to load page URL {}, error: {}", self.url.serialize(), err); @@ -189,7 +187,7 @@ pub struct ServoHTMLParser { impl<'a> Parser for &'a ServoHTMLParser { fn parse_chunk(self, input: String) { - self.document.root().r().set_current_parser(Some(self)); + self.document.set_current_parser(Some(self)); self.pending_input.borrow_mut().push(input); self.parse_sync(); } @@ -201,8 +199,7 @@ impl<'a> Parser for &'a ServoHTMLParser { self.tokenizer().borrow_mut().end(); debug!("finished parsing"); - let document = self.document.root(); - document.r().set_current_parser(None); + self.document.set_current_parser(None); if let Some(pipeline) = self.pipeline { ScriptTask::parsing_complete(pipeline); @@ -214,7 +211,6 @@ impl ServoHTMLParser { #[allow(unrooted_must_root)] pub fn new(base_url: Option<Url>, document: &Document, pipeline: Option<PipelineId>) -> Root<ServoHTMLParser> { - let window = document.window(); let sink = Sink { base_url: base_url, document: JS::from_ref(document), @@ -237,14 +233,13 @@ impl ServoHTMLParser { pipeline: pipeline, }; - reflect_dom_object(box parser, GlobalRef::Window(window.r()), + reflect_dom_object(box parser, GlobalRef::Window(document.window()), ServoHTMLParserBinding::Wrap) } #[allow(unrooted_must_root)] pub fn new_for_fragment(base_url: Option<Url>, document: &Document, fragment_context: FragmentContext) -> Root<ServoHTMLParser> { - let window = document.window(); let sink = Sink { base_url: base_url, document: JS::from_ref(document), @@ -275,7 +270,7 @@ impl ServoHTMLParser { pipeline: None, }; - reflect_dom_object(box parser, GlobalRef::Window(window.r()), + reflect_dom_object(box parser, GlobalRef::Window(document.window()), ServoHTMLParserBinding::Wrap) } @@ -301,8 +296,7 @@ impl ServoHTMLParser { break; } - let document = self.document.root(); - document.r().reflow_if_reflow_timer_expired(); + self.document.reflow_if_reflow_timer_expired(); let mut pending_input = self.pending_input.borrow_mut(); if !pending_input.is_empty() { @@ -320,9 +314,8 @@ impl ServoHTMLParser { } } - fn window(&self) -> Root<Window> { - let doc = self.document.root(); - window_from_node(doc.r()) + fn window(&self) -> &Window { + self.document.window() } } diff --git a/components/script/dom/treewalker.rs b/components/script/dom/treewalker.rs index 7f4646a1618..f19e8383ddf 100644 --- a/components/script/dom/treewalker.rs +++ b/components/script/dom/treewalker.rs @@ -45,9 +45,8 @@ impl TreeWalker { root_node: &Node, what_to_show: u32, filter: Filter) -> Root<TreeWalker> { - let window = document.window(); reflect_dom_object(box TreeWalker::new_inherited(root_node, what_to_show, filter), - GlobalRef::Window(window.r()), + GlobalRef::Window(document.window()), TreeWalkerBinding::Wrap) } diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs index 4a3bb19a776..9ff22b53597 100644 --- a/components/script/dom/url.rs +++ b/components/script/dom/url.rs @@ -88,42 +88,42 @@ impl URL { } impl URLMethods for URL { - // https://url.spec.whatwg.org/#dom-urlutils-hash + // https://url.spec.whatwg.org/#dom-url-hash fn Hash(&self) -> USVString { UrlHelper::Hash(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-hash + // https://url.spec.whatwg.org/#dom-url-hash fn SetHash(&self, value: USVString) { UrlHelper::SetHash(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#dom-urlutils-host + // https://url.spec.whatwg.org/#dom-url-host fn Host(&self) -> USVString { UrlHelper::Host(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-host + // https://url.spec.whatwg.org/#dom-url-host fn SetHost(&self, value: USVString) { UrlHelper::SetHost(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#dom-urlutils-hostname + // https://url.spec.whatwg.org/#dom-url-hostname fn Hostname(&self) -> USVString { UrlHelper::Hostname(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-hostname + // https://url.spec.whatwg.org/#dom-url-hostname fn SetHostname(&self, value: USVString) { UrlHelper::SetHostname(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#dom-urlutils-href + // https://url.spec.whatwg.org/#dom-url-href fn Href(&self) -> USVString { UrlHelper::Href(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-href + // https://url.spec.whatwg.org/#dom-url-href fn SetHref(&self, value: USVString) -> ErrorResult { match parse_with_base(value, self.base.as_ref()) { Ok(url) => { @@ -136,67 +136,67 @@ impl URLMethods for URL { } } - // https://url.spec.whatwg.org/#dom-urlutils-password + // https://url.spec.whatwg.org/#dom-url-password fn Password(&self) -> USVString { UrlHelper::Password(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-password + // https://url.spec.whatwg.org/#dom-url-password fn SetPassword(&self, value: USVString) { UrlHelper::SetPassword(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#dom-urlutils-pathname + // https://url.spec.whatwg.org/#dom-url-pathname fn Pathname(&self) -> USVString { UrlHelper::Pathname(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-pathname + // https://url.spec.whatwg.org/#dom-url-pathname fn SetPathname(&self, value: USVString) { UrlHelper::SetPathname(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#dom-urlutils-port + // https://url.spec.whatwg.org/#dom-url-port fn Port(&self) -> USVString { UrlHelper::Port(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-port + // https://url.spec.whatwg.org/#dom-url-port fn SetPort(&self, value: USVString) { UrlHelper::SetPort(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#dom-urlutils-protocol + // https://url.spec.whatwg.org/#dom-url-protocol fn Protocol(&self) -> USVString { UrlHelper::Protocol(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-protocol + // https://url.spec.whatwg.org/#dom-url-protocol fn SetProtocol(&self, value: USVString) { UrlHelper::SetProtocol(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#dom-urlutils-search + // https://url.spec.whatwg.org/#dom-url-search fn Search(&self) -> USVString { UrlHelper::Search(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-search + // https://url.spec.whatwg.org/#dom-url-search fn SetSearch(&self, value: USVString) { UrlHelper::SetSearch(&mut self.url.borrow_mut(), value); } - // https://url.spec.whatwg.org/#URLUtils-stringification-behavior + // https://url.spec.whatwg.org/#dom-url-href fn Stringifier(&self) -> DOMString { self.Href().0 } - // https://url.spec.whatwg.org/#dom-urlutils-username + // https://url.spec.whatwg.org/#dom-url-username fn Username(&self) -> USVString { UrlHelper::Username(&self.url.borrow()) } - // https://url.spec.whatwg.org/#dom-urlutils-username + // https://url.spec.whatwg.org/#dom-url-username fn SetUsername(&self, value: USVString) { UrlHelper::SetUsername(&mut self.url.borrow_mut(), value); } diff --git a/components/script/dom/urlhelper.rs b/components/script/dom/urlhelper.rs index 8d6916c0551..d9e26e84263 100644 --- a/components/script/dom/urlhelper.rs +++ b/components/script/dom/urlhelper.rs @@ -12,7 +12,6 @@ use url::{SchemeData, Url, UrlParser}; pub struct UrlHelper; impl UrlHelper { - // https://url.spec.whatwg.org/#dom-urlutils-hash pub fn Hash(url: &Url) -> USVString { USVString(match url.fragment { None => "".to_owned(), @@ -21,13 +20,11 @@ impl UrlHelper { }) } - // https://url.spec.whatwg.org/#dom-urlutils-hash pub fn SetHash(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_fragment(&value.0); } - // https://url.spec.whatwg.org/#dom-urlutils-host pub fn Host(url: &Url) -> USVString { USVString(match url.scheme_data { SchemeData::NonRelative(..) => "".to_owned(), @@ -41,40 +38,33 @@ impl UrlHelper { }) } - // https://url.spec.whatwg.org/#dom-urlutils-host pub fn SetHost(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_host(&value.0); } - // https://url.spec.whatwg.org/#dom-urlutils-hostname pub fn Hostname(url: &Url) -> USVString { USVString(url.serialize_host().unwrap_or_else(|| "".to_owned())) } - // https://url.spec.whatwg.org/#dom-urlutils-hostname pub fn SetHostname(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_host_and_port(&value.0); } - // https://url.spec.whatwg.org/#dom-urlutils-href pub fn Href(url: &Url) -> USVString { USVString(url.serialize()) } - // https://url.spec.whatwg.org/#dom-urlutils-password pub fn Password(url: &Url) -> USVString { USVString(url.password().unwrap_or("").to_owned()) } - // https://url.spec.whatwg.org/#dom-urlutils-password pub fn SetPassword(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_password(&value.0); } - // https://url.spec.whatwg.org/#dom-urlutils-pathname pub fn Pathname(url: &Url) -> USVString { USVString(match url.scheme_data { SchemeData::NonRelative(ref scheme_data) => scheme_data.clone(), @@ -82,13 +72,11 @@ impl UrlHelper { }) } - // https://url.spec.whatwg.org/#dom-urlutils-pathname pub fn SetPathname(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_path(&value.0); } - // https://url.spec.whatwg.org/#dom-urlutils-port pub fn Port(url: &Url) -> USVString { USVString(match url.port() { None => "".to_owned(), @@ -96,18 +84,15 @@ impl UrlHelper { }) } - // https://url.spec.whatwg.org/#dom-urlutils-port pub fn SetPort(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_port(&value.0); } - // https://url.spec.whatwg.org/#dom-urlutils-protocol pub fn Protocol(url: &Url) -> USVString { USVString(format!("{}:", url.scheme.clone())) } - // https://url.spec.whatwg.org/#dom-urlutils-protocol pub fn SetProtocol(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_scheme(&value.0); @@ -127,7 +112,6 @@ impl UrlHelper { true } - // https://url.spec.whatwg.org/#dom-urlutils-search pub fn Search(url: &Url) -> USVString { USVString(match url.query { None => "".to_owned(), @@ -136,18 +120,15 @@ impl UrlHelper { }) } - // https://url.spec.whatwg.org/#dom-urlutils-search pub fn SetSearch(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_query(&value.0); } - // https://url.spec.whatwg.org/#dom-urlutils-username pub fn Username(url: &Url) -> USVString { USVString(url.username().unwrap_or("").to_owned()) } - // https://url.spec.whatwg.org/#dom-urlutils-username pub fn SetUsername(url: &mut Url, value: USVString) { let mut wrapper = UrlUtilsWrapper { url: url, parser: &UrlParser::new() }; let _ = wrapper.set_username(&value.0); diff --git a/components/script/dom/webidls/DOMRect.webidl b/components/script/dom/webidls/DOMRect.webidl index 6e0fe24b57d..9ea5933c3f9 100644 --- a/components/script/dom/webidls/DOMRect.webidl +++ b/components/script/dom/webidls/DOMRect.webidl @@ -3,12 +3,13 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -// http://dev.w3.org/fxtf/geometry/#DOMRect -interface DOMRect { - readonly attribute float top; - readonly attribute float right; - readonly attribute float bottom; - readonly attribute float left; - readonly attribute float width; - readonly attribute float height; +[Constructor(optional unrestricted double x = 0, optional unrestricted double y = 0, + optional unrestricted double width = 0, optional unrestricted double height = 0), + /*Exposed=(Window,Worker)*/] +// https://drafts.fxtf.org/geometry/#domrect +interface DOMRect : DOMRectReadOnly { + inherit attribute unrestricted double x; + inherit attribute unrestricted double y; + inherit attribute unrestricted double width; + inherit attribute unrestricted double height; }; diff --git a/components/script/dom/webidls/DOMRectReadOnly.webidl b/components/script/dom/webidls/DOMRectReadOnly.webidl new file mode 100644 index 00000000000..937ed4eb478 --- /dev/null +++ b/components/script/dom/webidls/DOMRectReadOnly.webidl @@ -0,0 +1,29 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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/. */ + +[Constructor(optional unrestricted double x = 0, optional unrestricted double y = 0, + optional unrestricted double width = 0, optional unrestricted double height = 0), + /*Exposed=(Window,Worker)*/] +// https://drafts.fxtf.org/geometry/#domrect +interface DOMRectReadOnly { + // [NewObject] static DOMRectReadOnly fromRect(optional DOMRectInit other); + + readonly attribute unrestricted double x; + readonly attribute unrestricted double y; + readonly attribute unrestricted double width; + readonly attribute unrestricted double height; + readonly attribute unrestricted double top; + readonly attribute unrestricted double right; + readonly attribute unrestricted double bottom; + readonly attribute unrestricted double left; +}; + +// https://drafts.fxtf.org/geometry/#dictdef-domrectinit +dictionary DOMRectInit { + unrestricted double x = 0; + unrestricted double y = 0; + unrestricted double width = 0; + unrestricted double height = 0; +}; diff --git a/components/script/dom/webidls/Element.webidl b/components/script/dom/webidls/Element.webidl index dde5b978890..b5b35f8e802 100644 --- a/components/script/dom/webidls/Element.webidl +++ b/components/script/dom/webidls/Element.webidl @@ -37,6 +37,10 @@ interface Element : Node { DOMString? getAttribute(DOMString name); [Pure] DOMString? getAttributeNS(DOMString? namespace, DOMString localName); + [Pure] + Attr? getAttributeNode(DOMString name); + [Pure] + Attr? getAttributeNodeNS(DOMString? namespace, DOMString localName); [Throws] void setAttribute(DOMString name, DOMString value); [Throws] diff --git a/components/script/dom/webidls/EventHandler.webidl b/components/script/dom/webidls/EventHandler.webidl index 8848c3aafbb..7ff237f2ceb 100644 --- a/components/script/dom/webidls/EventHandler.webidl +++ b/components/script/dom/webidls/EventHandler.webidl @@ -36,6 +36,7 @@ interface GlobalEventHandlers { [NoInterfaceObject] interface WindowEventHandlers { attribute EventHandler onunload; + attribute EventHandler onstorage; }; // The spec has |attribute OnErrorEventHandler onerror;| on diff --git a/components/script/dom/webidls/HTMLAnchorElement.webidl b/components/script/dom/webidls/HTMLAnchorElement.webidl index f21e3dc6af7..6585e1ccc56 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 URLUtils; +//HTMLAnchorElement implements HTMLHyperlinkElementUtils; // https://html.spec.whatwg.org/multipage/#HTMLAnchorElement-partial partial interface HTMLAnchorElement { diff --git a/components/script/dom/webidls/HTMLAreaElement.webidl b/components/script/dom/webidls/HTMLAreaElement.webidl index 860e9af008a..a6568bd0b6b 100644 --- a/components/script/dom/webidls/HTMLAreaElement.webidl +++ b/components/script/dom/webidls/HTMLAreaElement.webidl @@ -13,12 +13,9 @@ interface HTMLAreaElement : HTMLElement { //[PutForwards=value] attribute DOMSettableTokenList ping; // attribute DOMString rel; readonly attribute DOMTokenList relList; - // attribute DOMString hreflang; - // attribute DOMString type; - - // also has obsolete members + // hreflang and type are not reflected }; -//HTMLAreaElement implements URLUtils; +//HTMLAreaElement implements HTMLHyperlinkElementUtils; // https://html.spec.whatwg.org/multipage/#HTMLAreaElement-partial partial interface HTMLAreaElement { diff --git a/components/script/dom/webidls/HTMLHyperlinkElementUtils.webidl b/components/script/dom/webidls/HTMLHyperlinkElementUtils.webidl new file mode 100644 index 00000000000..c8d7a35493d --- /dev/null +++ b/components/script/dom/webidls/HTMLHyperlinkElementUtils.webidl @@ -0,0 +1,20 @@ +/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +// https://html.spec.whatwg.org/multipage/#htmlhyperlinkelementutils +//[NoInterfaceObject/*, Exposed=Window*/] +//interface HTMLHyperlinkElementUtils { +// stringifier 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; +//}; diff --git a/components/script/dom/webidls/HTMLTableRowElement.webidl b/components/script/dom/webidls/HTMLTableRowElement.webidl index 9ddf710653f..66538630c9d 100644 --- a/components/script/dom/webidls/HTMLTableRowElement.webidl +++ b/components/script/dom/webidls/HTMLTableRowElement.webidl @@ -8,8 +8,10 @@ interface HTMLTableRowElement : HTMLElement { //readonly attribute long rowIndex; //readonly attribute long sectionRowIndex; readonly attribute HTMLCollection cells; - //HTMLElement insertCell(optional long index = -1); - //void deleteCell(long index); + [Throws] + HTMLElement insertCell(optional long index = -1); + [Throws] + void deleteCell(long index); // also has obsolete members }; diff --git a/components/script/dom/webidls/Location.webidl b/components/script/dom/webidls/Location.webidl index 70b496b00ec..f82031ac74b 100644 --- a/components/script/dom/webidls/Location.webidl +++ b/components/script/dom/webidls/Location.webidl @@ -5,8 +5,24 @@ // https://html.spec.whatwg.org/multipage/#location /*[Unforgeable]*/ interface Location { - void assign(DOMString url); - //void replace(DOMString url); + /*stringifier*/ attribute USVString href; + // attribute USVString origin; + attribute USVString protocol; + attribute USVString host; + attribute USVString hostname; + attribute USVString port; + attribute USVString pathname; + attribute USVString search; + attribute USVString hash; + + void assign(USVString url); + //void replace(USVString url); void reload(); + + //[SameObject] readonly attribute USVString[] ancestorOrigins; + + // This is only doing as well as gecko right now. + // https://github.com/servo/servo/issues/7590 is on file for + // adding attribute stringifier support. + stringifier; }; -Location implements URLUtils; diff --git a/components/script/dom/webidls/URL.webidl b/components/script/dom/webidls/URL.webidl index 2e03ea9b858..57ae34a3eba 100644 --- a/components/script/dom/webidls/URL.webidl +++ b/components/script/dom/webidls/URL.webidl @@ -8,5 +8,23 @@ interface URL { static USVString domainToASCII(USVString domain); // static USVString domainToUnicode(USVString domain); + + [SetterThrows] + /*stringifier*/ attribute USVString href; + // readonly 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; + // readonly attribute URLSearchParams searchParams; + attribute USVString hash; + + // This is only doing as well as gecko right now. + // https://github.com/servo/servo/issues/7590 is on file for + // adding attribute stringifier support. + stringifier; }; -URL implements URLUtils; diff --git a/components/script/dom/webidls/URLSearchParams.webidl b/components/script/dom/webidls/URLSearchParams.webidl index 1afdc30a352..4ab1cd43019 100644 --- a/components/script/dom/webidls/URLSearchParams.webidl +++ b/components/script/dom/webidls/URLSearchParams.webidl @@ -7,7 +7,7 @@ * https://url.spec.whatwg.org/#interface-urlsearchparams */ -[Constructor(optional (DOMString or URLSearchParams) init)] +[Constructor(optional (DOMString or URLSearchParams) init/* = ""*/)] interface URLSearchParams { void append(DOMString name, DOMString value); void delete(DOMString name); @@ -15,5 +15,7 @@ interface URLSearchParams { // sequence<DOMString> getAll(DOMString name); boolean has(DOMString name); void set(DOMString name, DOMString value); + // iterable<USVString, USVString>; stringifier; }; + diff --git a/components/script/dom/webidls/URLUtils.webidl b/components/script/dom/webidls/URLUtils.webidl deleted file mode 100644 index bb32fb82e5e..00000000000 --- a/components/script/dom/webidls/URLUtils.webidl +++ /dev/null @@ -1,28 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// https://url.spec.whatwg.org/#urlutils -[NoInterfaceObject] -interface URLUtils { - //stringifier attribute USVString href; - [SetterThrows] - attribute USVString href; - //readonly 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 URLSearchParams searchParams; - attribute USVString hash; - - // This is only doing as well as gecko right now. - // https://github.com/servo/servo/issues/7590 is on file for - // adding attribute stringifier support. - stringifier; -}; diff --git a/components/script/dom/webidls/URLUtilsReadOnly.webidl b/components/script/dom/webidls/URLUtilsReadOnly.webidl deleted file mode 100644 index a919986bbbe..00000000000 --- a/components/script/dom/webidls/URLUtilsReadOnly.webidl +++ /dev/null @@ -1,26 +0,0 @@ -/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -// https://url.spec.whatwg.org/#urlutilsreadonly -[NoInterfaceObject/*, - Exposed=(Window,Worker)*/] -interface URLUtilsReadOnly { - //stringifier readonly attribute USVString href; - readonly attribute USVString href; - //readonly attribute USVString origin; - - readonly attribute USVString protocol; - readonly attribute USVString host; - readonly attribute USVString hostname; - readonly attribute USVString port; - readonly attribute USVString pathname; - readonly attribute USVString search; - readonly attribute USVString hash; - - // This is only doing as well as gecko right now. - // https://github.com/servo/servo/issues/7590 is on file for - // adding attribute stringifier support. - stringifier; -}; diff --git a/components/script/dom/webidls/WebSocket.webidl b/components/script/dom/webidls/WebSocket.webidl index e2652a3716f..bf19ff6e78f 100644 --- a/components/script/dom/webidls/WebSocket.webidl +++ b/components/script/dom/webidls/WebSocket.webidl @@ -15,7 +15,7 @@ interface WebSocket : EventTarget { const unsigned short CLOSING = 2; const unsigned short CLOSED = 3; readonly attribute unsigned short readyState; - //readonly attribute unsigned long bufferedAmount; + readonly attribute unsigned long bufferedAmount; //networking attribute EventHandler onopen; diff --git a/components/script/dom/webidls/WorkerLocation.webidl b/components/script/dom/webidls/WorkerLocation.webidl index 7d624118271..598e210de44 100644 --- a/components/script/dom/webidls/WorkerLocation.webidl +++ b/components/script/dom/webidls/WorkerLocation.webidl @@ -5,5 +5,19 @@ // https://html.spec.whatwg.org/multipage/#worker-locations //[Exposed=Worker] -interface WorkerLocation { }; -WorkerLocation implements URLUtilsReadOnly; +interface WorkerLocation { + /*stringifier*/ readonly attribute USVString href; + // readonly attribute USVString origin; + readonly attribute USVString protocol; + readonly attribute USVString host; + readonly attribute USVString hostname; + readonly attribute USVString port; + readonly attribute USVString pathname; + readonly attribute USVString search; + readonly attribute USVString hash; + + // This is only doing as well as gecko right now. + // https://github.com/servo/servo/issues/7590 is on file for + // adding attribute stringifier support. + stringifier; +}; diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs index c348efc88d0..4b2797248fa 100644 --- a/components/script/dom/websocket.rs +++ b/components/script/dom/websocket.rs @@ -132,6 +132,8 @@ pub struct WebSocket { url: Url, global: GlobalField, ready_state: Cell<WebSocketRequestState>, + buffered_amount: Cell<u32>, + clearing_buffer: Cell<bool>, //Flag to tell if there is a running task to clear buffered_amount #[ignore_heap_size_of = "Defined in std"] sender: RefCell<Option<Arc<Mutex<Sender<WebSocketStream>>>>>, failed: Cell<bool>, //Flag to tell if websocket was closed due to failure @@ -172,6 +174,8 @@ impl WebSocket { url: url, global: GlobalField::from_rooted(&global), ready_state: Cell::new(WebSocketRequestState::Connecting), + buffered_amount: Cell::new(0), + clearing_buffer: Cell::new(false), failed: Cell::new(false), sender: RefCell::new(None), full: Cell::new(false), @@ -314,6 +318,11 @@ impl WebSocketMethods for WebSocket { self.ready_state.get() as u16 } + // https://html.spec.whatwg.org/multipage/#dom-websocket-bufferedamount + fn BufferedAmount(&self) -> u32 { + self.buffered_amount.get() + } + // https://html.spec.whatwg.org/multipage/#dom-websocket-binarytype fn BinaryType(&self) -> BinaryType { self.binary_type.get() @@ -340,14 +349,28 @@ impl WebSocketMethods for WebSocket { /*TODO: This is not up to spec see http://html.spec.whatwg.org/multipage/comms.html search for "If argument is a string" TODO: Need to buffer data - TODO: bufferedAmount attribute returns the size of the buffer in bytes - - this is a required attribute defined in the websocket.webidl file TODO: The send function needs to flag when full by using the following self.full.set(true). This needs to be done when the buffer is full */ let mut other_sender = self.sender.borrow_mut(); let my_sender = other_sender.as_mut().unwrap(); + + self.buffered_amount.set(self.buffered_amount.get() + (data.0.as_bytes().len() as u32)); + let _ = my_sender.lock().unwrap().send_message(Message::Text(data.0)); + + if !self.clearing_buffer.get() && self.ready_state.get() == WebSocketRequestState::Open { + self.clearing_buffer.set(true); + + let global = self.global.root(); + let task = box BufferedAmountTask { + addr: Trusted::new(global.r().get_cx(), self, global.r().script_chan()), + }; + let chan = global.r().script_chan(); + + chan.send(CommonScriptMsg::RunnableMsg(WebSocketEvent, task)).unwrap(); + } + Ok(()) } @@ -437,6 +460,24 @@ impl Runnable for ConnectionEstablishedTask { } } +struct BufferedAmountTask { + addr: Trusted<WebSocket>, +} + +impl Runnable for BufferedAmountTask { + // See https://html.spec.whatwg.org/multipage/#dom-websocket-bufferedamount + // + // To be compliant with standards, we need to reset bufferedAmount only when the event loop + // reaches step 1. In our implementation, the bytes will already have been sent on a background + // thread. + fn handler(self: Box<Self>) { + let ws = self.addr.root(); + + ws.buffered_amount.set(0); + ws.clearing_buffer.set(false); + } +} + struct CloseTask { addr: Trusted<WebSocket>, } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index 4ada66c36cc..b3968a9205d 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -381,7 +381,7 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#dom-document-0 fn Document(&self) -> Root<Document> { - self.browsing_context().as_ref().unwrap().active_document() + Root::from_ref(self.browsing_context().as_ref().unwrap().active_document()) } // https://html.spec.whatwg.org/multipage/#dom-location @@ -411,7 +411,7 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#dom-frameelement fn GetFrameElement(&self) -> Option<Root<Element>> { - self.browsing_context().as_ref().unwrap().frame_element() + self.browsing_context().as_ref().unwrap().frame_element().map(Root::from_ref) } // https://html.spec.whatwg.org/multipage/#dom-navigator @@ -513,6 +513,9 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#handler-window-onunload event_handler!(unload, GetOnunload, SetOnunload); + // https://html.spec.whatwg.org/multipage/#handler-window-onstorage + event_handler!(storage, GetOnstorage, SetOnstorage); + // https://html.spec.whatwg.org/multipage/#handler-onerror error_event_handler!(error, GetOnerror, SetOnerror); @@ -1245,11 +1248,11 @@ impl Window { let browsing_context = browsing_context.as_ref().unwrap(); browsing_context.frame_element().map(|frame_element| { - let window = window_from_node(frame_element.r()); + let window = window_from_node(frame_element); // FIXME(https://github.com/rust-lang/rust/issues/23338) let r = window.r(); let context = r.browsing_context(); - context.as_ref().unwrap().active_window() + Root::from_ref(context.as_ref().unwrap().active_window()) }) } } diff --git a/components/script/dom/workerlocation.rs b/components/script/dom/workerlocation.rs index 467d2fef7ee..477c329cf75 100644 --- a/components/script/dom/workerlocation.rs +++ b/components/script/dom/workerlocation.rs @@ -36,47 +36,47 @@ impl WorkerLocation { } impl WorkerLocationMethods for WorkerLocation { - // https://url.spec.whatwg.org/#dom-urlutils-hash + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-hash fn Hash(&self) -> USVString { UrlHelper::Hash(&self.url) } - // https://url.spec.whatwg.org/#dom-urlutils-host + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-host fn Host(&self) -> USVString { UrlHelper::Host(&self.url) } - // https://url.spec.whatwg.org/#dom-urlutils-hostname + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-hostname fn Hostname(&self) -> USVString { UrlHelper::Hostname(&self.url) } - // https://url.spec.whatwg.org/#dom-urlutils-href + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-href fn Href(&self) -> USVString { UrlHelper::Href(&self.url) } - // https://url.spec.whatwg.org/#dom-urlutils-pathname + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-pathname fn Pathname(&self) -> USVString { UrlHelper::Pathname(&self.url) } - // https://url.spec.whatwg.org/#dom-urlutils-port + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-port fn Port(&self) -> USVString { UrlHelper::Port(&self.url) } - // https://url.spec.whatwg.org/#dom-urlutils-protocol + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-protocol fn Protocol(&self) -> USVString { UrlHelper::Protocol(&self.url) } - // https://url.spec.whatwg.org/#dom-urlutils-search + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-search fn Search(&self) -> USVString { UrlHelper::Search(&self.url) } - // https://url.spec.whatwg.org/#URLUtils-stringification-behavior + // https://html.spec.whatwg.org/multipage/#dom-workerlocation-href fn Stringifier(&self) -> DOMString { self.Href().0 } diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index 3373865fa5f..400b06ca95f 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -493,8 +493,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest { if !self.sync.get() { // Step 8 - let upload_target = self.upload.root(); - let event_target = EventTargetCast::from_ref(upload_target.r()); + let event_target = EventTargetCast::from_ref(&*self.upload); if event_target.has_handlers() { self.upload_events.set(true); } @@ -917,13 +916,12 @@ impl XMLHttpRequest { fn dispatch_progress_event(&self, upload: bool, type_: DOMString, loaded: u64, total: Option<u64>) { let global = self.global.root(); - let upload_target = self.upload.root(); let progressevent = ProgressEvent::new(global.r(), type_, EventBubbles::DoesNotBubble, EventCancelable::NotCancelable, total.is_some(), loaded, total.unwrap_or(0)); let target = if upload { - EventTargetCast::from_ref(upload_target.r()) + EventTargetCast::from_ref(&*self.upload) } else { EventTargetCast::from_ref(self) }; |