mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Make BrowsingContext JS-managed.
This commit is contained in:
parent
b6850853da
commit
f86502f80c
2 changed files with 52 additions and 46 deletions
|
@ -6,45 +6,70 @@ use dom::bindings::conversions::native_from_handleobject;
|
||||||
use dom::bindings::conversions::{ToJSValConvertible};
|
use dom::bindings::conversions::{ToJSValConvertible};
|
||||||
use dom::bindings::js::{JS, Root};
|
use dom::bindings::js::{JS, Root};
|
||||||
use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor};
|
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::WindowProxyHandler;
|
||||||
use dom::bindings::utils::get_array_index_from_id;
|
use dom::bindings::utils::get_array_index_from_id;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
use dom::window::Window;
|
use dom::window::Window;
|
||||||
|
use js::JSCLASS_IS_GLOBAL;
|
||||||
use js::glue::{CreateWrapperProxyHandler, ProxyTraps, WrapperNew};
|
use js::glue::{CreateWrapperProxyHandler, ProxyTraps, WrapperNew};
|
||||||
use js::glue::{GetProxyPrivate};
|
use js::glue::{GetProxyPrivate, SetProxyExtra};
|
||||||
use js::jsapi::{Handle, Heap, JS_ForwardSetPropertyTo, ObjectOpResult, RootedObject, RootedValue};
|
use js::jsapi::{Handle, JS_ForwardSetPropertyTo, ObjectOpResult, RootedObject, RootedValue};
|
||||||
use js::jsapi::{HandleId, HandleObject, MutableHandle, MutableHandleValue};
|
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::{JSContext, JSErrNum, JSObject, JSPropertyDescriptor};
|
||||||
use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo};
|
use js::jsapi::{JS_AlreadyHasOwnPropertyById, JS_ForwardGetPropertyTo};
|
||||||
use js::jsapi::{JS_DefinePropertyById6, JS_GetPropertyDescriptorById};
|
use js::jsapi::{JS_DefinePropertyById6, JS_GetPropertyDescriptorById};
|
||||||
use js::jsval::{ObjectValue, UndefinedValue};
|
use js::jsval::{ObjectValue, UndefinedValue, PrivateValue};
|
||||||
use std::default::Default;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
#[derive(JSTraceable, HeapSizeOf)]
|
#[dom_struct]
|
||||||
#[privatize]
|
|
||||||
#[allow(raw_pointer_derive)]
|
|
||||||
#[must_root]
|
|
||||||
pub struct BrowsingContext {
|
pub struct BrowsingContext {
|
||||||
|
reflector: Reflector,
|
||||||
history: Vec<SessionHistoryEntry>,
|
history: Vec<SessionHistoryEntry>,
|
||||||
active_index: usize,
|
active_index: usize,
|
||||||
window_proxy: Heap<*mut JSObject>,
|
|
||||||
frame_element: Option<JS<Element>>,
|
frame_element: Option<JS<Element>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BrowsingContext {
|
impl BrowsingContext {
|
||||||
pub fn new(document: &Document, frame_element: Option<&Element>) -> BrowsingContext {
|
pub fn new_inherited(document: &Document, frame_element: Option<&Element>) -> BrowsingContext {
|
||||||
BrowsingContext {
|
BrowsingContext {
|
||||||
|
reflector: Reflector::new(),
|
||||||
history: vec!(SessionHistoryEntry::new(document)),
|
history: vec!(SessionHistoryEntry::new(document)),
|
||||||
active_index: 0,
|
active_index: 0,
|
||||||
window_proxy: Heap::default(),
|
|
||||||
frame_element: frame_element.map(JS::from_ref),
|
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 {
|
pub fn active_document(&self) -> &Document {
|
||||||
&*self.history[self.active_index].document
|
&*self.history[self.active_index].document
|
||||||
}
|
}
|
||||||
|
@ -58,25 +83,9 @@ impl BrowsingContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn window_proxy(&self) -> *mut JSObject {
|
pub fn window_proxy(&self) -> *mut JSObject {
|
||||||
assert!(!self.window_proxy.get().is_null());
|
let window_proxy = self.reflector.get_jsobject();
|
||||||
self.window_proxy.get()
|
assert!(!window_proxy.get().is_null());
|
||||||
}
|
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +96,7 @@ impl BrowsingContext {
|
||||||
#[derive(JSTraceable, HeapSizeOf)]
|
#[derive(JSTraceable, HeapSizeOf)]
|
||||||
pub struct SessionHistoryEntry {
|
pub struct SessionHistoryEntry {
|
||||||
document: JS<Document>,
|
document: JS<Document>,
|
||||||
children: Vec<BrowsingContext>
|
children: Vec<JS<BrowsingContext>>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SessionHistoryEntry {
|
impl SessionHistoryEntry {
|
||||||
|
|
|
@ -59,7 +59,7 @@ use script_traits::{TimerEventChan, TimerEventId, TimerEventRequest, TimerSource
|
||||||
use selectors::parser::PseudoElement;
|
use selectors::parser::PseudoElement;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
use std::cell::{Cell, Ref};
|
use std::cell::Cell;
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
@ -119,7 +119,7 @@ pub struct Window {
|
||||||
image_cache_chan: ImageCacheChan,
|
image_cache_chan: ImageCacheChan,
|
||||||
#[ignore_heap_size_of = "TODO(#6911) newtypes containing unmeasurable types are hard"]
|
#[ignore_heap_size_of = "TODO(#6911) newtypes containing unmeasurable types are hard"]
|
||||||
compositor: IpcSender<ScriptToCompositorMsg>,
|
compositor: IpcSender<ScriptToCompositorMsg>,
|
||||||
browsing_context: DOMRefCell<Option<BrowsingContext>>,
|
browsing_context: MutNullableHeap<JS<BrowsingContext>>,
|
||||||
page: Rc<Page>,
|
page: Rc<Page>,
|
||||||
performance: MutNullableHeap<JS<Performance>>,
|
performance: MutNullableHeap<JS<Performance>>,
|
||||||
navigation_start: u64,
|
navigation_start: u64,
|
||||||
|
@ -217,7 +217,7 @@ impl Window {
|
||||||
pub fn clear_js_runtime_for_script_deallocation(&self) {
|
pub fn clear_js_runtime_for_script_deallocation(&self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
*self.js_runtime.borrow_for_script_deallocation() = None;
|
*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);
|
self.current_state.set(WindowState::Zombie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -271,8 +271,8 @@ impl Window {
|
||||||
&self.compositor
|
&self.compositor
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn browsing_context(&self) -> Ref<Option<BrowsingContext>> {
|
pub fn browsing_context(&self) -> Option<Root<BrowsingContext>> {
|
||||||
self.browsing_context.borrow()
|
self.browsing_context.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn page(&self) -> &Page {
|
pub fn page(&self) -> &Page {
|
||||||
|
@ -797,7 +797,7 @@ impl Window {
|
||||||
|
|
||||||
self.current_state.set(WindowState::Zombie);
|
self.current_state.set(WindowState::Zombie);
|
||||||
*self.js_runtime.borrow_mut() = None;
|
*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
|
/// https://drafts.csswg.org/cssom-view/#dom-window-scroll
|
||||||
|
@ -1009,9 +1009,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_browsing_context(&self, doc: &Document, frame_element: Option<&Element>) {
|
pub fn init_browsing_context(&self, doc: &Document, frame_element: Option<&Element>) {
|
||||||
let mut browsing_context = self.browsing_context.borrow_mut();
|
self.browsing_context.set(Some(&BrowsingContext::new(doc, frame_element)));
|
||||||
*browsing_context = Some(BrowsingContext::new(doc, frame_element));
|
|
||||||
(*browsing_context).as_mut().unwrap().create_window_proxy();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Commence a new URL load which will either replace this window or scroll to a fragment.
|
/// Commence a new URL load which will either replace this window or scroll to a fragment.
|
||||||
|
@ -1183,15 +1181,14 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parent(&self) -> Option<Root<Window>> {
|
pub fn parent(&self) -> Option<Root<Window>> {
|
||||||
let browsing_context = self.browsing_context();
|
let browsing_context = self.browsing_context().unwrap();
|
||||||
let browsing_context = browsing_context.as_ref().unwrap();
|
|
||||||
|
|
||||||
browsing_context.frame_element().map(|frame_element| {
|
browsing_context.frame_element().map(|frame_element| {
|
||||||
let window = window_from_node(frame_element);
|
let window = window_from_node(frame_element);
|
||||||
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
// FIXME(https://github.com/rust-lang/rust/issues/23338)
|
||||||
let r = window.r();
|
let r = window.r();
|
||||||
let context = r.browsing_context();
|
let context = r.browsing_context();
|
||||||
Root::from_ref(context.as_ref().unwrap().active_window())
|
Root::from_ref(context.unwrap().active_window())
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1234,7 +1231,7 @@ impl Window {
|
||||||
image_cache_task: image_cache_task,
|
image_cache_task: image_cache_task,
|
||||||
mem_profiler_chan: mem_profiler_chan,
|
mem_profiler_chan: mem_profiler_chan,
|
||||||
devtools_chan: devtools_chan,
|
devtools_chan: devtools_chan,
|
||||||
browsing_context: DOMRefCell::new(None),
|
browsing_context: Default::default(),
|
||||||
performance: Default::default(),
|
performance: Default::default(),
|
||||||
navigation_start: time::get_time().sec as u64,
|
navigation_start: time::get_time().sec as u64,
|
||||||
navigation_start_precise: time::precise_time_ns() as f64,
|
navigation_start_precise: time::precise_time_ns() as f64,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue