diff --git a/components/script/dom/browsingcontext.rs b/components/script/dom/browsingcontext.rs index d9b75153a1f7..02d4baf7f506 100644 --- a/components/script/dom/browsingcontext.rs +++ b/components/script/dom/browsingcontext.rs @@ -2,6 +2,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use dom::bindings::cell::DOMRefCell; use dom::bindings::conversions::{ToJSValConvertible, root_from_handleobject}; use dom::bindings::js::{JS, Root}; use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor}; @@ -26,26 +27,24 @@ use std::ptr; #[dom_struct] pub struct BrowsingContext { reflector: Reflector, - history: Vec, + history: DOMRefCell>, active_index: usize, frame_element: Option>, } impl BrowsingContext { - pub fn new_inherited(document: &Document, frame_element: Option<&Element>) -> BrowsingContext { + pub fn new_inherited(frame_element: Option<&Element>) -> BrowsingContext { BrowsingContext { reflector: Reflector::new(), - history: vec![SessionHistoryEntry::new(document)], + history: DOMRefCell::new(vec![]), active_index: 0, frame_element: frame_element.map(JS::from_ref), } } #[allow(unsafe_code)] - pub fn new(document: &Document, frame_element: Option<&Element>) -> Root { + pub fn new(window: &Window, frame_element: Option<&Element>) -> Root { unsafe { - let window = document.window(); - let WindowProxyHandler(handler) = window.windowproxy_handler(); assert!(!handler.is_null()); @@ -59,7 +58,7 @@ impl BrowsingContext { NewWindowProxy(cx, parent, handler)); assert!(!window_proxy.ptr.is_null()); - let object = box BrowsingContext::new_inherited(document, frame_element); + let object = box BrowsingContext::new_inherited(frame_element); let raw = Box::into_raw(object); SetProxyExtra(window_proxy.ptr, 0, PrivateValue(raw as *const _)); @@ -70,12 +69,18 @@ impl BrowsingContext { } } - pub fn active_document(&self) -> &Document { - &*self.history[self.active_index].document + pub fn init(&self, document: &Document) { + assert!(self.history.borrow().is_empty()); + assert_eq!(self.active_index, 0); + self.history.borrow_mut().push(SessionHistoryEntry::new(document)); + } + + pub fn active_document(&self) -> Root { + Root::from_ref(&*self.history.borrow()[self.active_index].document) } - pub fn active_window(&self) -> &Window { - self.active_document().window() + pub fn active_window(&self) -> Root { + Root::from_ref(self.active_document().window()) } pub fn frame_element(&self) -> Option<&Element> { diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 99a61d2f981a..e81800529d64 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -30,6 +30,7 @@ use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::trace::RootedVec; use dom::bindings::xmlname::XMLName::InvalidXMLName; use dom::bindings::xmlname::{validate_and_extract, namespace_from_domstring, xml_name_type}; +use dom::browsingcontext::BrowsingContext; use dom::comment::Comment; use dom::customevent::CustomEvent; use dom::documentfragment::DocumentFragment; @@ -127,6 +128,8 @@ enum ParserBlockedByScript { pub struct Document { node: Node, window: JS, + /// https://html.spec.whatwg.org/multipage/#concept-document-bc + browsing_context: Option>, implementation: MutNullableHeap>, location: MutNullableHeap>, content_type: DOMString, @@ -277,6 +280,12 @@ impl Document { self.loader.borrow_mut() } + /// https://html.spec.whatwg.org/multipage/#concept-document-bc + #[inline] + pub fn browsing_context(&self) -> Option<&BrowsingContext> { + self.browsing_context.as_ref().map(|browsing_context| &**browsing_context) + } + #[inline] pub fn window(&self) -> &Window { &*self.window @@ -307,7 +316,7 @@ impl Document { let browsing_context = browsing_context.as_ref().unwrap(); let active_document = browsing_context.active_document(); - if self != active_document { + if self != &*active_document { return false; } // FIXME: It should also check whether the browser context is top-level or not @@ -1462,6 +1471,7 @@ impl LayoutDocumentHelpers for LayoutJS { impl Document { pub fn new_inherited(window: &Window, + browsing_context: Option<&BrowsingContext>, url: Option, is_html_document: IsHTMLDocument, content_type: Option, @@ -1480,6 +1490,7 @@ impl Document { Document { node: Node::new_document_node(), window: JS::from_ref(window), + browsing_context: browsing_context.map(JS::from_ref), implementation: Default::default(), location: Default::default(), content_type: match content_type { @@ -1548,6 +1559,7 @@ impl Document { let doc = doc.r(); let docloader = DocumentLoader::new(&*doc.loader()); Ok(Document::new(win, + None, None, IsHTMLDocument::NonHTMLDocument, None, @@ -1557,6 +1569,7 @@ impl Document { } pub fn new(window: &Window, + browsing_context: Option<&BrowsingContext>, url: Option, doctype: IsHTMLDocument, content_type: Option, @@ -1565,6 +1578,7 @@ impl Document { doc_loader: DocumentLoader) -> Root { let document = reflect_dom_object(box Document::new_inherited(window, + browsing_context, url, doctype, content_type, @@ -1627,6 +1641,7 @@ impl Document { IsHTMLDocument::NonHTMLDocument }; let new_doc = Document::new(self.window(), + None, None, doctype, None, @@ -1716,7 +1731,7 @@ impl DocumentMethods for Document { // Step 2. let candidate = browsing_context.active_document(); // Step 3. - if candidate == target { + if &*candidate == target { true } else { false //TODO Step 4. diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs index d994b111b698..01cd8acb7df9 100644 --- a/components/script/dom/domimplementation.rs +++ b/components/script/dom/domimplementation.rs @@ -115,6 +115,7 @@ impl DOMImplementationMethods for DOMImplementation { // Step 1-2. let doc = Document::new(win, + None, None, IsHTMLDocument::HTMLDocument, None, diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs index 21b0fcf0730c..1a3fb7f37930 100644 --- a/components/script/dom/domparser.rs +++ b/components/script/dom/domparser.rs @@ -59,6 +59,7 @@ impl DOMParserMethods for DOMParser { match ty { Text_html => { let document = Document::new(&self.window, + None, Some(url.clone()), IsHTMLDocument::HTMLDocument, Some(content_type), @@ -72,6 +73,7 @@ impl DOMParserMethods for DOMParser { Text_xml => { // FIXME: this should probably be FromParser when we actually parse the string (#3756). let document = Document::new(&self.window, + None, Some(url.clone()), IsHTMLDocument::NonHTMLDocument, Some(content_type), diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index aef4192dc6e7..f6b8abf49f30 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -1602,7 +1602,8 @@ impl Node { }; let window = document.window(); let loader = DocumentLoader::new(&*document.loader()); - let document = Document::new(window, Some((*document.url()).clone()), + let document = Document::new(window, None, + Some((*document.url()).clone()), is_html_doc, None, None, DocumentSource::NotFromParser, loader); Root::upcast::(document) diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs index c8ea1d9f0f88..7648aec8977d 100644 --- a/components/script/dom/window.rs +++ b/components/script/dom/window.rs @@ -425,7 +425,7 @@ impl WindowMethods for Window { // https://html.spec.whatwg.org/multipage/#dom-document-2 fn Document(&self) -> Root { - Root::from_ref(self.browsing_context().as_ref().unwrap().active_document()) + self.browsing_context().as_ref().unwrap().active_document() } // https://html.spec.whatwg.org/multipage/#dom-location @@ -1094,8 +1094,9 @@ impl Window { (element, response.rect) } - pub fn init_browsing_context(&self, doc: &Document, frame_element: Option<&Element>) { - self.browsing_context.set(Some(&BrowsingContext::new(doc, frame_element))); + pub fn init_browsing_context(&self, browsing_context: &BrowsingContext) { + assert!(self.browsing_context.get().is_none()); + self.browsing_context.set(Some(&browsing_context)); } /// Commence a new URL load which will either replace this window or scroll to a fragment. @@ -1282,7 +1283,7 @@ impl Window { browsing_context.frame_element().map(|frame_element| { let window = window_from_node(frame_element); let context = window.browsing_context(); - Root::from_ref(context.unwrap().active_window()) + context.unwrap().active_window() }) } } diff --git a/components/script/dom/xmldocument.rs b/components/script/dom/xmldocument.rs index 6f73ecbf8ea4..200480d4fc0c 100644 --- a/components/script/dom/xmldocument.rs +++ b/components/script/dom/xmldocument.rs @@ -35,6 +35,7 @@ impl XMLDocument { doc_loader: DocumentLoader) -> XMLDocument { XMLDocument { document: Document::new_inherited(window, + None, url, is_html_document, content_type, diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs index d81bfe4ab7c4..b5f86e6a8684 100644 --- a/components/script/dom/xmlhttprequest.rs +++ b/components/script/dom/xmlhttprequest.rs @@ -1110,6 +1110,7 @@ impl XMLHttpRequest { DOMString::from(format!("{}", mime)) }); Document::new(win, + None, parsed_url, is_html_document, content_type, diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs index d4ea3cf20934..2d7f71eed156 100644 --- a/components/script/parse/html.rs +++ b/components/script/parse/html.rs @@ -275,7 +275,7 @@ pub fn parse_html_fragment(context_node: &Node, // Step 1. let loader = DocumentLoader::new(&*context_document.loader()); - let document = Document::new(window.r(), Some(url.clone()), + let document = Document::new(window.r(), None, Some(url.clone()), IsHTMLDocument::HTMLDocument, None, None, DocumentSource::FromParser, diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs index 83e60a505495..5907490dd051 100644 --- a/components/script/script_thread.rs +++ b/components/script/script_thread.rs @@ -32,6 +32,7 @@ use dom::bindings::js::{RootCollectionPtr, RootedReference}; use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference, trace_refcounted_objects}; use dom::bindings::trace::{JSTraceable, RootedVec, trace_traceables}; use dom::bindings::utils::{DOM_CALLBACKS, WRAP_CALLBACKS}; +use dom::browsingcontext::BrowsingContext; use dom::document::{Document, DocumentProgressHandler, DocumentSource, FocusType, IsHTMLDocument}; use dom::element::Element; use dom::event::{Event, EventBubbles, EventCancelable}; @@ -1792,6 +1793,10 @@ impl ScriptThread { incomplete.parent_info, incomplete.window_size); + let frame_element = frame_element.r().map(Castable::upcast); + let browsing_context = BrowsingContext::new(&window, frame_element); + window.init_browsing_context(&browsing_context); + let last_modified = metadata.headers.as_ref().and_then(|headers| { headers.get().map(|&LastModified(HttpDate(ref tm))| dom_last_modified(tm)) }); @@ -1819,16 +1824,14 @@ impl ScriptThread { }; let document = Document::new(window.r(), + Some(&browsing_context), Some(final_url.clone()), is_html_document, content_type, last_modified, DocumentSource::FromParser, loader); - - let frame_element = frame_element.r().map(Castable::upcast); - window.init_browsing_context(document.r(), frame_element); - + browsing_context.init(&document); document.set_ready_state(DocumentReadyState::Loading); // Create the root frame