mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
Auto merge of #9603 - Ms2ger:document-bc, r=jdm
Store a pointer to the browsing context in the Document. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9603) <!-- Reviewable:end -->
This commit is contained in:
commit
ee158cc65f
10 changed files with 53 additions and 23 deletions
|
@ -2,6 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* 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::conversions::{ToJSValConvertible, root_from_handleobject};
|
||||||
use dom::bindings::js::{JS, Root, RootedReference};
|
use dom::bindings::js::{JS, Root, RootedReference};
|
||||||
use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor};
|
use dom::bindings::proxyhandler::{fill_property_descriptor, get_property_descriptor};
|
||||||
|
@ -25,26 +26,24 @@ use js::jsval::{ObjectValue, UndefinedValue, PrivateValue};
|
||||||
#[dom_struct]
|
#[dom_struct]
|
||||||
pub struct BrowsingContext {
|
pub struct BrowsingContext {
|
||||||
reflector: Reflector,
|
reflector: Reflector,
|
||||||
history: Vec<SessionHistoryEntry>,
|
history: DOMRefCell<Vec<SessionHistoryEntry>>,
|
||||||
active_index: usize,
|
active_index: usize,
|
||||||
frame_element: Option<JS<Element>>,
|
frame_element: Option<JS<Element>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BrowsingContext {
|
impl BrowsingContext {
|
||||||
pub fn new_inherited(document: &Document, frame_element: Option<&Element>) -> BrowsingContext {
|
pub fn new_inherited(frame_element: Option<&Element>) -> BrowsingContext {
|
||||||
BrowsingContext {
|
BrowsingContext {
|
||||||
reflector: Reflector::new(),
|
reflector: Reflector::new(),
|
||||||
history: vec![SessionHistoryEntry::new(document)],
|
history: DOMRefCell::new(vec![]),
|
||||||
active_index: 0,
|
active_index: 0,
|
||||||
frame_element: frame_element.map(JS::from_ref),
|
frame_element: frame_element.map(JS::from_ref),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
pub fn new(document: &Document, frame_element: Option<&Element>) -> Root<BrowsingContext> {
|
pub fn new(window: &Window, frame_element: Option<&Element>) -> Root<BrowsingContext> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let window = document.window();
|
|
||||||
|
|
||||||
let WindowProxyHandler(handler) = window.windowproxy_handler();
|
let WindowProxyHandler(handler) = window.windowproxy_handler();
|
||||||
assert!(!handler.is_null());
|
assert!(!handler.is_null());
|
||||||
|
|
||||||
|
@ -58,7 +57,7 @@ impl BrowsingContext {
|
||||||
NewWindowProxy(cx, parent, handler));
|
NewWindowProxy(cx, parent, handler));
|
||||||
assert!(!window_proxy.ptr.is_null());
|
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);
|
let raw = Box::into_raw(object);
|
||||||
SetProxyExtra(window_proxy.ptr, 0, PrivateValue(raw as *const _));
|
SetProxyExtra(window_proxy.ptr, 0, PrivateValue(raw as *const _));
|
||||||
|
@ -69,12 +68,18 @@ impl BrowsingContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn active_document(&self) -> &Document {
|
pub fn init(&self, document: &Document) {
|
||||||
&*self.history[self.active_index].document
|
assert!(self.history.borrow().is_empty());
|
||||||
|
assert_eq!(self.active_index, 0);
|
||||||
|
self.history.borrow_mut().push(SessionHistoryEntry::new(document));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn active_window(&self) -> &Window {
|
pub fn active_document(&self) -> Root<Document> {
|
||||||
self.active_document().window()
|
Root::from_ref(&*self.history.borrow()[self.active_index].document)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn active_window(&self) -> Root<Window> {
|
||||||
|
Root::from_ref(self.active_document().window())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn frame_element(&self) -> Option<&Element> {
|
pub fn frame_element(&self) -> Option<&Element> {
|
||||||
|
|
|
@ -30,6 +30,7 @@ use dom::bindings::reflector::{Reflectable, reflect_dom_object};
|
||||||
use dom::bindings::trace::RootedVec;
|
use dom::bindings::trace::RootedVec;
|
||||||
use dom::bindings::xmlname::XMLName::InvalidXMLName;
|
use dom::bindings::xmlname::XMLName::InvalidXMLName;
|
||||||
use dom::bindings::xmlname::{validate_and_extract, namespace_from_domstring, xml_name_type};
|
use dom::bindings::xmlname::{validate_and_extract, namespace_from_domstring, xml_name_type};
|
||||||
|
use dom::browsingcontext::BrowsingContext;
|
||||||
use dom::comment::Comment;
|
use dom::comment::Comment;
|
||||||
use dom::customevent::CustomEvent;
|
use dom::customevent::CustomEvent;
|
||||||
use dom::documentfragment::DocumentFragment;
|
use dom::documentfragment::DocumentFragment;
|
||||||
|
@ -129,6 +130,8 @@ enum ParserBlockedByScript {
|
||||||
pub struct Document {
|
pub struct Document {
|
||||||
node: Node,
|
node: Node,
|
||||||
window: JS<Window>,
|
window: JS<Window>,
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#concept-document-bc
|
||||||
|
browsing_context: Option<JS<BrowsingContext>>,
|
||||||
implementation: MutNullableHeap<JS<DOMImplementation>>,
|
implementation: MutNullableHeap<JS<DOMImplementation>>,
|
||||||
location: MutNullableHeap<JS<Location>>,
|
location: MutNullableHeap<JS<Location>>,
|
||||||
content_type: DOMString,
|
content_type: DOMString,
|
||||||
|
@ -279,6 +282,12 @@ impl Document {
|
||||||
self.loader.borrow_mut()
|
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]
|
#[inline]
|
||||||
pub fn window(&self) -> &Window {
|
pub fn window(&self) -> &Window {
|
||||||
&*self.window
|
&*self.window
|
||||||
|
@ -309,7 +318,7 @@ impl Document {
|
||||||
let browsing_context = browsing_context.as_ref().unwrap();
|
let browsing_context = browsing_context.as_ref().unwrap();
|
||||||
let active_document = browsing_context.active_document();
|
let active_document = browsing_context.active_document();
|
||||||
|
|
||||||
if self != active_document {
|
if self != &*active_document {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// FIXME: It should also check whether the browser context is top-level or not
|
// FIXME: It should also check whether the browser context is top-level or not
|
||||||
|
@ -1507,6 +1516,7 @@ impl LayoutDocumentHelpers for LayoutJS<Document> {
|
||||||
|
|
||||||
impl Document {
|
impl Document {
|
||||||
pub fn new_inherited(window: &Window,
|
pub fn new_inherited(window: &Window,
|
||||||
|
browsing_context: Option<&BrowsingContext>,
|
||||||
url: Option<Url>,
|
url: Option<Url>,
|
||||||
is_html_document: IsHTMLDocument,
|
is_html_document: IsHTMLDocument,
|
||||||
content_type: Option<DOMString>,
|
content_type: Option<DOMString>,
|
||||||
|
@ -1525,6 +1535,7 @@ impl Document {
|
||||||
Document {
|
Document {
|
||||||
node: Node::new_document_node(),
|
node: Node::new_document_node(),
|
||||||
window: JS::from_ref(window),
|
window: JS::from_ref(window),
|
||||||
|
browsing_context: browsing_context.map(JS::from_ref),
|
||||||
implementation: Default::default(),
|
implementation: Default::default(),
|
||||||
location: Default::default(),
|
location: Default::default(),
|
||||||
content_type: match content_type {
|
content_type: match content_type {
|
||||||
|
@ -1593,6 +1604,7 @@ impl Document {
|
||||||
let doc = doc.r();
|
let doc = doc.r();
|
||||||
let docloader = DocumentLoader::new(&*doc.loader());
|
let docloader = DocumentLoader::new(&*doc.loader());
|
||||||
Ok(Document::new(win,
|
Ok(Document::new(win,
|
||||||
|
None,
|
||||||
None,
|
None,
|
||||||
IsHTMLDocument::NonHTMLDocument,
|
IsHTMLDocument::NonHTMLDocument,
|
||||||
None,
|
None,
|
||||||
|
@ -1602,6 +1614,7 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(window: &Window,
|
pub fn new(window: &Window,
|
||||||
|
browsing_context: Option<&BrowsingContext>,
|
||||||
url: Option<Url>,
|
url: Option<Url>,
|
||||||
doctype: IsHTMLDocument,
|
doctype: IsHTMLDocument,
|
||||||
content_type: Option<DOMString>,
|
content_type: Option<DOMString>,
|
||||||
|
@ -1610,6 +1623,7 @@ impl Document {
|
||||||
doc_loader: DocumentLoader)
|
doc_loader: DocumentLoader)
|
||||||
-> Root<Document> {
|
-> Root<Document> {
|
||||||
let document = reflect_dom_object(box Document::new_inherited(window,
|
let document = reflect_dom_object(box Document::new_inherited(window,
|
||||||
|
browsing_context,
|
||||||
url,
|
url,
|
||||||
doctype,
|
doctype,
|
||||||
content_type,
|
content_type,
|
||||||
|
@ -1672,6 +1686,7 @@ impl Document {
|
||||||
IsHTMLDocument::NonHTMLDocument
|
IsHTMLDocument::NonHTMLDocument
|
||||||
};
|
};
|
||||||
let new_doc = Document::new(self.window(),
|
let new_doc = Document::new(self.window(),
|
||||||
|
None,
|
||||||
None,
|
None,
|
||||||
doctype,
|
doctype,
|
||||||
None,
|
None,
|
||||||
|
@ -1761,7 +1776,7 @@ impl DocumentMethods for Document {
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let candidate = browsing_context.active_document();
|
let candidate = browsing_context.active_document();
|
||||||
// Step 3.
|
// Step 3.
|
||||||
if candidate == target {
|
if &*candidate == target {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false //TODO Step 4.
|
false //TODO Step 4.
|
||||||
|
|
|
@ -115,6 +115,7 @@ impl DOMImplementationMethods for DOMImplementation {
|
||||||
|
|
||||||
// Step 1-2.
|
// Step 1-2.
|
||||||
let doc = Document::new(win,
|
let doc = Document::new(win,
|
||||||
|
None,
|
||||||
None,
|
None,
|
||||||
IsHTMLDocument::HTMLDocument,
|
IsHTMLDocument::HTMLDocument,
|
||||||
None,
|
None,
|
||||||
|
|
|
@ -59,6 +59,7 @@ impl DOMParserMethods for DOMParser {
|
||||||
match ty {
|
match ty {
|
||||||
Text_html => {
|
Text_html => {
|
||||||
let document = Document::new(&self.window,
|
let document = Document::new(&self.window,
|
||||||
|
None,
|
||||||
Some(url.clone()),
|
Some(url.clone()),
|
||||||
IsHTMLDocument::HTMLDocument,
|
IsHTMLDocument::HTMLDocument,
|
||||||
Some(content_type),
|
Some(content_type),
|
||||||
|
@ -72,6 +73,7 @@ impl DOMParserMethods for DOMParser {
|
||||||
Text_xml => {
|
Text_xml => {
|
||||||
// FIXME: this should probably be FromParser when we actually parse the string (#3756).
|
// FIXME: this should probably be FromParser when we actually parse the string (#3756).
|
||||||
let document = Document::new(&self.window,
|
let document = Document::new(&self.window,
|
||||||
|
None,
|
||||||
Some(url.clone()),
|
Some(url.clone()),
|
||||||
IsHTMLDocument::NonHTMLDocument,
|
IsHTMLDocument::NonHTMLDocument,
|
||||||
Some(content_type),
|
Some(content_type),
|
||||||
|
|
|
@ -1605,7 +1605,8 @@ impl Node {
|
||||||
};
|
};
|
||||||
let window = document.window();
|
let window = document.window();
|
||||||
let loader = DocumentLoader::new(&*document.loader());
|
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,
|
is_html_doc, None,
|
||||||
None, DocumentSource::NotFromParser, loader);
|
None, DocumentSource::NotFromParser, loader);
|
||||||
Root::upcast::<Node>(document)
|
Root::upcast::<Node>(document)
|
||||||
|
|
|
@ -426,7 +426,7 @@ impl WindowMethods for Window {
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-document-2
|
// https://html.spec.whatwg.org/multipage/#dom-document-2
|
||||||
fn Document(&self) -> Root<Document> {
|
fn Document(&self) -> Root<Document> {
|
||||||
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
|
// https://html.spec.whatwg.org/multipage/#dom-location
|
||||||
|
@ -1095,8 +1095,9 @@ impl Window {
|
||||||
(element, response.rect)
|
(element, response.rect)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_browsing_context(&self, doc: &Document, frame_element: Option<&Element>) {
|
pub fn init_browsing_context(&self, browsing_context: &BrowsingContext) {
|
||||||
self.browsing_context.set(Some(&BrowsingContext::new(doc, frame_element)));
|
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.
|
/// Commence a new URL load which will either replace this window or scroll to a fragment.
|
||||||
|
@ -1283,7 +1284,7 @@ impl Window {
|
||||||
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);
|
||||||
let context = window.browsing_context();
|
let context = window.browsing_context();
|
||||||
Root::from_ref(context.unwrap().active_window())
|
context.unwrap().active_window()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@ impl XMLDocument {
|
||||||
doc_loader: DocumentLoader) -> XMLDocument {
|
doc_loader: DocumentLoader) -> XMLDocument {
|
||||||
XMLDocument {
|
XMLDocument {
|
||||||
document: Document::new_inherited(window,
|
document: Document::new_inherited(window,
|
||||||
|
None,
|
||||||
url,
|
url,
|
||||||
is_html_document,
|
is_html_document,
|
||||||
content_type,
|
content_type,
|
||||||
|
|
|
@ -1230,6 +1230,7 @@ impl XMLHttpRequest {
|
||||||
DOMString::from(format!("{}", mime))
|
DOMString::from(format!("{}", mime))
|
||||||
});
|
});
|
||||||
Document::new(win,
|
Document::new(win,
|
||||||
|
None,
|
||||||
parsed_url,
|
parsed_url,
|
||||||
is_html_document,
|
is_html_document,
|
||||||
content_type,
|
content_type,
|
||||||
|
|
|
@ -275,7 +275,7 @@ pub fn parse_html_fragment(context_node: &Node,
|
||||||
|
|
||||||
// Step 1.
|
// Step 1.
|
||||||
let loader = DocumentLoader::new(&*context_document.loader());
|
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,
|
IsHTMLDocument::HTMLDocument,
|
||||||
None, None,
|
None, None,
|
||||||
DocumentSource::FromParser,
|
DocumentSource::FromParser,
|
||||||
|
|
|
@ -32,6 +32,7 @@ use dom::bindings::js::{RootCollectionPtr, RootedReference};
|
||||||
use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference, trace_refcounted_objects};
|
use dom::bindings::refcounted::{LiveDOMReferences, Trusted, TrustedReference, trace_refcounted_objects};
|
||||||
use dom::bindings::trace::{JSTraceable, RootedVec, trace_traceables};
|
use dom::bindings::trace::{JSTraceable, RootedVec, trace_traceables};
|
||||||
use dom::bindings::utils::{DOM_CALLBACKS, WRAP_CALLBACKS};
|
use dom::bindings::utils::{DOM_CALLBACKS, WRAP_CALLBACKS};
|
||||||
|
use dom::browsingcontext::BrowsingContext;
|
||||||
use dom::document::{Document, DocumentProgressHandler, DocumentSource, FocusType, IsHTMLDocument};
|
use dom::document::{Document, DocumentProgressHandler, DocumentSource, FocusType, IsHTMLDocument};
|
||||||
use dom::element::Element;
|
use dom::element::Element;
|
||||||
use dom::event::{Event, EventBubbles, EventCancelable};
|
use dom::event::{Event, EventBubbles, EventCancelable};
|
||||||
|
@ -1795,6 +1796,10 @@ impl ScriptThread {
|
||||||
incomplete.parent_info,
|
incomplete.parent_info,
|
||||||
incomplete.window_size);
|
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| {
|
let last_modified = metadata.headers.as_ref().and_then(|headers| {
|
||||||
headers.get().map(|&LastModified(HttpDate(ref tm))| dom_last_modified(tm))
|
headers.get().map(|&LastModified(HttpDate(ref tm))| dom_last_modified(tm))
|
||||||
});
|
});
|
||||||
|
@ -1822,16 +1827,14 @@ impl ScriptThread {
|
||||||
};
|
};
|
||||||
|
|
||||||
let document = Document::new(window.r(),
|
let document = Document::new(window.r(),
|
||||||
|
Some(&browsing_context),
|
||||||
Some(final_url.clone()),
|
Some(final_url.clone()),
|
||||||
is_html_document,
|
is_html_document,
|
||||||
content_type,
|
content_type,
|
||||||
last_modified,
|
last_modified,
|
||||||
DocumentSource::FromParser,
|
DocumentSource::FromParser,
|
||||||
loader);
|
loader);
|
||||||
|
browsing_context.init(&document);
|
||||||
let frame_element = frame_element.r().map(Castable::upcast);
|
|
||||||
window.init_browsing_context(document.r(), frame_element);
|
|
||||||
|
|
||||||
document.set_ready_state(DocumentReadyState::Loading);
|
document.set_ready_state(DocumentReadyState::Loading);
|
||||||
|
|
||||||
// Create the root frame
|
// Create the root frame
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue