diff options
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/document_loader.rs | 10 | ||||
-rw-r--r-- | components/script/dom/browsercontext.rs | 75 | ||||
-rw-r--r-- | components/script/dom/htmlcanvaselement.rs | 65 | ||||
-rw-r--r-- | components/script/dom/window.rs | 26 |
4 files changed, 77 insertions, 99 deletions
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs index 2cfa9096d9c..c9241956bb5 100644 --- a/components/script/document_loader.rs +++ b/components/script/document_loader.rs @@ -7,7 +7,7 @@ use msg::constellation_msg::{PipelineId}; use net_traits::AsyncResponseTarget; -use net_traits::{Metadata, PendingAsyncLoad, ResourceTask, load_whole_resource}; +use net_traits::{PendingAsyncLoad, ResourceTask}; use std::sync::Arc; use url::Url; @@ -78,14 +78,6 @@ impl DocumentLoader { pending.load_async(listener) } - /// Create, initiate, and await the response for a new network request. - pub fn load_sync(&mut self, load: LoadType) -> Result<(Metadata, Vec<u8>), String> { - self.blocking_loads.push(load.clone()); - let result = load_whole_resource(&self.resource_task, load.url().clone()); - self.finish_load(load); - result - } - /// Mark an in-progress network request complete. pub fn finish_load(&mut self, load: LoadType) { let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == load); diff --git a/components/script/dom/browsercontext.rs b/components/script/dom/browsercontext.rs index 049ff432538..72d48d51d45 100644 --- a/components/script/dom/browsercontext.rs +++ b/components/script/dom/browsercontext.rs @@ -6,45 +6,70 @@ use dom::bindings::conversions::native_from_handleobject; use dom::bindings::conversions::{ToJSValConvertible}; use dom::bindings::js::{JS, Root}; use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor}; -use dom::bindings::reflector::Reflectable; +use dom::bindings::reflector::{Reflectable, Reflector}; use dom::bindings::utils::WindowProxyHandler; use dom::bindings::utils::get_array_index_from_id; use dom::document::Document; use dom::element::Element; use dom::window::Window; +use js::JSCLASS_IS_GLOBAL; use js::glue::{CreateWrapperProxyHandler, ProxyTraps, WrapperNew}; -use js::glue::{GetProxyPrivate}; -use js::jsapi::{Handle, Heap, JS_ForwardSetPropertyTo, ObjectOpResult, RootedObject, RootedValue}; +use js::glue::{GetProxyPrivate, SetProxyExtra}; +use js::jsapi::{Handle, JS_ForwardSetPropertyTo, ObjectOpResult, RootedObject, RootedValue}; use js::jsapi::{HandleId, HandleObject, MutableHandle, MutableHandleValue}; -use js::jsapi::{JSAutoCompartment, JSAutoRequest}; +use js::jsapi::{JSAutoCompartment, JSAutoRequest, JS_GetClass}; use js::jsapi::{JSContext, JSErrNum, JSObject, JSPropertyDescriptor}; use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo}; use js::jsapi::{JS_DefinePropertyById6, JS_GetPropertyDescriptorById}; -use js::jsval::{ObjectValue, UndefinedValue}; -use std::default::Default; +use js::jsval::{ObjectValue, UndefinedValue, PrivateValue}; use std::ptr; -#[derive(JSTraceable, HeapSizeOf)] -#[privatize] -#[allow(raw_pointer_derive)] -#[must_root] +#[dom_struct] pub struct BrowsingContext { + reflector: Reflector, history: Vec<SessionHistoryEntry>, active_index: usize, - window_proxy: Heap<*mut JSObject>, frame_element: Option<JS<Element>>, } impl BrowsingContext { - pub fn new(document: &Document, frame_element: Option<&Element>) -> BrowsingContext { + pub fn new_inherited(document: &Document, frame_element: Option<&Element>) -> BrowsingContext { BrowsingContext { + reflector: Reflector::new(), history: vec!(SessionHistoryEntry::new(document)), active_index: 0, - window_proxy: Heap::default(), frame_element: frame_element.map(JS::from_ref), } } + #[allow(unsafe_code)] + pub fn new(document: &Document, frame_element: Option<&Element>) -> Root<BrowsingContext> { + unsafe { + let window = document.window(); + + let WindowProxyHandler(handler) = window.windowproxy_handler(); + assert!(!handler.is_null()); + + let cx = window.get_cx(); + let _ar = JSAutoRequest::new(cx); + let parent = window.reflector().get_jsobject(); + assert!(!parent.get().is_null()); + assert!(((*JS_GetClass(parent.get())).flags & JSCLASS_IS_GLOBAL) != 0); + let _ac = JSAutoCompartment::new(cx, parent.get()); + let window_proxy = RootedObject::new(cx, WrapperNew(cx, parent, handler, ptr::null(), true)); + assert!(!window_proxy.ptr.is_null()); + + let object = box BrowsingContext::new_inherited(document, frame_element); + + let raw = Box::into_raw(object); + SetProxyExtra(window_proxy.ptr, 0, PrivateValue(raw as *const _)); + + (*raw).init_reflector(window_proxy.ptr); + + Root::from_ref(&*raw) + } + } + pub fn active_document(&self) -> &Document { &*self.history[self.active_index].document } @@ -58,25 +83,9 @@ impl BrowsingContext { } pub fn window_proxy(&self) -> *mut JSObject { - assert!(!self.window_proxy.get().is_null()); - self.window_proxy.get() - } - - #[allow(unsafe_code)] - pub fn create_window_proxy(&mut self) { - // 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()); - - let cx = win.get_cx(); - let _ar = JSAutoRequest::new(cx); - let parent = win.reflector().get_jsobject(); - let _ac = JSAutoCompartment::new(cx, parent.get()); - let wrapper = unsafe { WrapperNew(cx, parent, handler, ptr::null(), false) }; - assert!(!wrapper.is_null()); - self.window_proxy.set(wrapper); + let window_proxy = self.reflector.get_jsobject(); + assert!(!window_proxy.get().is_null()); + window_proxy.get() } } @@ -87,7 +96,7 @@ impl BrowsingContext { #[derive(JSTraceable, HeapSizeOf)] pub struct SessionHistoryEntry { document: JS<Document>, - children: Vec<BrowsingContext> + children: Vec<JS<BrowsingContext>> } impl SessionHistoryEntry { diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 95e3476f757..9ada3036f1d 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -4,6 +4,7 @@ use canvas_traits::{CanvasMsg, FromLayoutMsg}; use dom::attr::Attr; +use dom::attr::AttrValue; use dom::bindings::cell::DOMRefCell; use dom::bindings::codegen::Bindings::CanvasRenderingContext2DBinding::CanvasRenderingContext2DMethods; use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding; @@ -18,7 +19,7 @@ use dom::bindings::num::Finite; use dom::bindings::reflector::Reflectable; use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers}; use dom::document::Document; -use dom::element::{AttributeMutation, Element}; +use dom::element::{AttributeMutation, Element, RawLayoutElementHelpers}; use dom::htmlelement::HTMLElement; use dom::node::{Node, window_from_node}; use dom::virtualmethods::VirtualMethods; @@ -30,9 +31,9 @@ use ipc_channel::ipc::{self, IpcSender}; use js::jsapi::{HandleValue, JSContext}; use offscreen_gl_context::GLContextAttributes; use rustc_serialize::base64::{STANDARD, ToBase64}; -use std::cell::Cell; use std::iter::repeat; -use util::str::{DOMString, parse_unsigned_integer}; +use string_cache::Atom; +use util::str::DOMString; const DEFAULT_WIDTH: u32 = 300; const DEFAULT_HEIGHT: u32 = 150; @@ -50,8 +51,6 @@ impl HeapGCValue for CanvasContext {} pub struct HTMLCanvasElement { htmlelement: HTMLElement, context: DOMRefCell<Option<CanvasContext>>, - width: Cell<u32>, - height: Cell<u32>, } impl PartialEq for HTMLCanvasElement { @@ -67,8 +66,6 @@ impl HTMLCanvasElement { HTMLCanvasElement { htmlelement: HTMLElement::new_inherited(localName, prefix, document), context: DOMRefCell::new(None), - width: Cell::new(DEFAULT_WIDTH), - height: Cell::new(DEFAULT_HEIGHT), } } @@ -91,7 +88,7 @@ impl HTMLCanvasElement { } pub fn get_size(&self) -> Size2D<i32> { - Size2D::new(self.width.get() as i32, self.height.get() as i32) + Size2D::new(self.Width() as i32, self.Height() as i32) } } @@ -123,11 +120,13 @@ impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> { None => (None, None), }; + let width_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(""), &atom!(width)); + let height_attr = canvas.upcast::<Element>().get_attr_for_layout(&ns!(""), &atom!(height)); HTMLCanvasData { renderer_id: renderer_id, ipc_renderer: ipc_renderer, - width: canvas.width.get(), - height: canvas.height.get(), + width: width_attr.map_or(DEFAULT_WIDTH, |val| val.as_uint()), + height: height_attr.map_or(DEFAULT_HEIGHT, |val| val.as_uint()), } } } @@ -189,7 +188,7 @@ impl HTMLCanvasElement { } pub fn is_valid(&self) -> bool { - self.height.get() != 0 && self.width.get() != 0 + self.Height() != 0 && self.Width() != 0 } pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> { @@ -215,24 +214,16 @@ impl HTMLCanvasElement { impl HTMLCanvasElementMethods for HTMLCanvasElement { // https://html.spec.whatwg.org/multipage/#dom-canvas-width - fn Width(&self) -> u32 { - self.width.get() - } + make_uint_getter!(Width, "width", DEFAULT_WIDTH); // https://html.spec.whatwg.org/multipage/#dom-canvas-width - fn SetWidth(&self, width: u32) { - self.upcast::<Element>().set_uint_attribute(&atom!("width"), width) - } + make_uint_setter!(SetWidth, "width", DEFAULT_WIDTH); // https://html.spec.whatwg.org/multipage/#dom-canvas-height - fn Height(&self) -> u32 { - self.height.get() - } + make_uint_getter!(Height, "height", DEFAULT_HEIGHT); // https://html.spec.whatwg.org/multipage/#dom-canvas-height - fn SetHeight(&self, height: u32) { - self.upcast::<Element>().set_uint_attribute(&atom!("height"), height) - } + make_uint_setter!(SetHeight, "height", DEFAULT_HEIGHT); // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext fn GetContext(&self, @@ -299,25 +290,17 @@ impl VirtualMethods for HTMLCanvasElement { fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) { self.super_type().unwrap().attribute_mutated(attr, mutation); - let recreate = match attr.local_name() { - &atom!(width) => { - let width = mutation.new_value(attr).and_then(|value| { - parse_unsigned_integer(value.chars()) - }); - self.width.set(width.unwrap_or(DEFAULT_WIDTH)); - true - }, - &atom!(height) => { - let height = mutation.new_value(attr).and_then(|value| { - parse_unsigned_integer(value.chars()) - }); - self.height.set(height.unwrap_or(DEFAULT_HEIGHT)); - true - }, - _ => false, + match attr.local_name() { + &atom!(width) | &atom!(height) => self.recreate_contexts(), + _ => (), }; - if recreate { - self.recreate_contexts(); + } + + fn parse_plain_attribute(&self, name: &Atom, value: DOMString) -> AttrValue { + match name { + &atom!("width") => AttrValue::from_u32(value, DEFAULT_WIDTH), + &atom!("height") => AttrValue::from_u32(value, DEFAULT_HEIGHT), + _ => self.super_type().unwrap().parse_plain_attribute(name, value), } } } diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index a5b9fa4d0e1..9682b89cba6 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -59,7 +59,7 @@ use script_traits::{TimerEventChan, TimerEventId, TimerEventRequest, TimerSource use selectors::parser::PseudoElement; use std::ascii::AsciiExt; use std::borrow::ToOwned; -use std::cell::{Cell, Ref}; +use std::cell::Cell; use std::collections::HashSet; use std::default::Default; use std::ffi::CString; @@ -119,7 +119,7 @@ pub struct Window { image_cache_chan: ImageCacheChan, #[ignore_heap_size_of = "TODO(#6911) newtypes containing unmeasurable types are hard"] compositor: IpcSender<ScriptToCompositorMsg>, - browsing_context: DOMRefCell<Option<BrowsingContext>>, + browsing_context: MutNullableHeap<JS<BrowsingContext>>, page: Rc<Page>, performance: MutNullableHeap<JS<Performance>>, navigation_start: u64, @@ -217,7 +217,7 @@ impl Window { pub fn clear_js_runtime_for_script_deallocation(&self) { unsafe { *self.js_runtime.borrow_for_script_deallocation() = None; - *self.browsing_context.borrow_for_script_deallocation() = None; + self.browsing_context.set(None); self.current_state.set(WindowState::Zombie); } } @@ -271,8 +271,8 @@ impl Window { &self.compositor } - pub fn browsing_context(&self) -> Ref<Option<BrowsingContext>> { - self.browsing_context.borrow() + pub fn browsing_context(&self) -> Option<Root<BrowsingContext>> { + self.browsing_context.get() } pub fn page(&self) -> &Page { @@ -797,7 +797,7 @@ impl Window { self.current_state.set(WindowState::Zombie); *self.js_runtime.borrow_mut() = None; - *self.browsing_context.borrow_mut() = None; + self.browsing_context.set(None); } /// https://drafts.csswg.org/cssom-view/#dom-window-scroll @@ -919,9 +919,6 @@ impl Window { debug!("script: layout forked"); - // FIXME(cgaebel): this is racey. What if the compositor triggers a - // reflow between the "join complete" message and returning from this - // function? match join_port.try_recv() { Err(Empty) => { info!("script: waiting on layout"); @@ -1009,9 +1006,7 @@ impl Window { } pub fn init_browsing_context(&self, doc: &Document, frame_element: Option<&Element>) { - let mut browsing_context = self.browsing_context.borrow_mut(); - *browsing_context = Some(BrowsingContext::new(doc, frame_element)); - (*browsing_context).as_mut().unwrap().create_window_proxy(); + self.browsing_context.set(Some(&BrowsingContext::new(doc, frame_element))); } /// Commence a new URL load which will either replace this window or scroll to a fragment. @@ -1183,15 +1178,14 @@ impl Window { } pub fn parent(&self) -> Option<Root<Window>> { - let browsing_context = self.browsing_context(); - let browsing_context = browsing_context.as_ref().unwrap(); + let browsing_context = self.browsing_context().unwrap(); browsing_context.frame_element().map(|frame_element| { 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(); - Root::from_ref(context.as_ref().unwrap().active_window()) + Root::from_ref(context.unwrap().active_window()) }) } } @@ -1234,7 +1228,7 @@ impl Window { image_cache_task: image_cache_task, mem_profiler_chan: mem_profiler_chan, devtools_chan: devtools_chan, - browsing_context: DOMRefCell::new(None), + browsing_context: Default::default(), performance: Default::default(), navigation_start: time::get_time().sec as u64, navigation_start_precise: time::precise_time_ns() as f64, |