diff options
author | Matt Brubeck <mbrubeck@limpet.net> | 2014-10-17 09:48:31 -0700 |
---|---|---|
committer | Matt Brubeck <mbrubeck@limpet.net> | 2014-10-29 14:31:47 -0700 |
commit | fe123ad07ce048c11c2820481c9fd54ce296202d (patch) | |
tree | 920d2a5cf4ca502aa1e6a2b761528c4080af9b84 /components/script | |
parent | 65a0d1fe9a14e09b675cc24cb59c9aebf1615020 (diff) | |
download | servo-fe123ad07ce048c11c2820481c9fd54ce296202d.tar.gz servo-fe123ad07ce048c11c2820481c9fd54ce296202d.zip |
Switch to synchronous script loading
This removes the old code for asyncronously loading scripts during HTML
parsing and then executing them afterward.
Fixes #3356.
Diffstat (limited to 'components/script')
-rw-r--r-- | components/script/dom/document.rs | 7 | ||||
-rw-r--r-- | components/script/dom/htmlscriptelement.rs | 63 | ||||
-rw-r--r-- | components/script/dom/node.rs | 4 | ||||
-rw-r--r-- | components/script/dom/servohtmlparser.rs | 6 | ||||
-rw-r--r-- | components/script/dom/virtualmethods.rs | 7 | ||||
-rw-r--r-- | components/script/parse/html.rs | 133 | ||||
-rw-r--r-- | components/script/script_task.rs | 49 |
7 files changed, 95 insertions, 174 deletions
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 90c0ae5a5c4..76505df7148 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -55,7 +55,7 @@ use dom::range::Range; use dom::treewalker::TreeWalker; use dom::uievent::UIEvent; use dom::window::{Window, WindowHelpers}; -use parse::html::build_element_from_tag; +use parse::html::{build_element_from_tag, ScriptCreated}; use servo_util::namespace; use servo_util::str::{DOMString, split_html_space_chars}; @@ -529,7 +529,7 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { } let local_name = local_name.as_slice().to_ascii_lower(); let name = QualName::new(ns!(HTML), Atom::from_slice(local_name.as_slice())); - Ok(build_element_from_tag(name, None, self)) + Ok(build_element_from_tag(name, None, self, ScriptCreated)) } // http://dom.spec.whatwg.org/#dom-document-createelementns @@ -574,7 +574,8 @@ impl<'a> DocumentMethods for JSRef<'a, Document> { if ns == ns!(HTML) { let name = QualName::new(ns!(HTML), Atom::from_slice(local_name_from_qname)); - Ok(build_element_from_tag(name, prefix_from_qname.map(|s| s.to_string()), self)) + Ok(build_element_from_tag(name, prefix_from_qname.map(|s| s.to_string()), self, + ScriptCreated)) } else { Ok(Element::new(local_name_from_qname.to_string(), ns, prefix_from_qname.map(|s| s.to_string()), self)) diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index 9c20435f67a..19731e3932f 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -2,12 +2,14 @@ * 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::attr::Attr; +use dom::attr::AttrHelpers; use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::HTMLScriptElementBinding; use dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElementMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::InheritTypes::HTMLScriptElementDerived; -use dom::bindings::codegen::InheritTypes::{ElementCast, NodeCast}; +use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCast}; use dom::bindings::js::{JSRef, Temporary, OptionalRootable}; use dom::bindings::utils::{Reflectable, Reflector}; use dom::document::Document; @@ -15,10 +17,12 @@ use dom::element::{HTMLScriptElementTypeId, Element, AttributeHandlers}; use dom::eventtarget::{EventTarget, NodeTargetTypeId}; use dom::htmlelement::HTMLElement; use dom::node::{Node, NodeHelpers, ElementNodeTypeId, window_from_node}; +use dom::virtualmethods::VirtualMethods; use dom::window::WindowHelpers; use encoding::all::UTF_8; use encoding::types::{Encoding, DecodeReplace}; +use parse::html::{ElementCreator, ParserCreated}; use servo_net::resource_task::load_whole_resource; use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec}; use std::cell::Cell; @@ -53,20 +57,20 @@ impl HTMLScriptElementDerived for EventTarget { impl HTMLScriptElement { fn new_inherited(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>, - parser_inserted: bool) -> HTMLScriptElement { + creator: ElementCreator) -> HTMLScriptElement { HTMLScriptElement { htmlelement: HTMLElement::new_inherited(HTMLScriptElementTypeId, localName, prefix, document), already_started: Cell::new(false), - parser_inserted: Cell::new(parser_inserted), - non_blocking: Cell::new(!parser_inserted), + parser_inserted: Cell::new(creator == ParserCreated), + non_blocking: Cell::new(creator != ParserCreated), ready_to_be_parser_executed: Cell::new(false), } } #[allow(unrooted_must_root)] pub fn new(localName: DOMString, prefix: Option<DOMString>, document: JSRef<Document>, - parser_inserted: bool) -> Temporary<HTMLScriptElement> { - let element = HTMLScriptElement::new_inherited(localName, prefix, document, parser_inserted); + creator: ElementCreator) -> Temporary<HTMLScriptElement> { + let element = HTMLScriptElement::new_inherited(localName, prefix, document, creator); Node::reflect_node(box element, document, HTMLScriptElementBinding::Wrap) } } @@ -77,6 +81,9 @@ pub trait HTMLScriptElementHelpers { /// Prepare a script, steps 6 and 7. fn is_javascript(self) -> bool; + + /// Set the "already started" flag (<https://whatwg.org/html/#already-started>) + fn mark_already_started(self); } /// Supported script types as defined by @@ -232,6 +239,50 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> { } } } + + fn mark_already_started(self) { + self.already_started.set(true); + } +} + +impl<'a> VirtualMethods for JSRef<'a, HTMLScriptElement> { + fn super_type<'a>(&'a self) -> Option<&'a VirtualMethods> { + let htmlelement: &JSRef<HTMLElement> = HTMLElementCast::from_borrowed_ref(self); + Some(htmlelement as &VirtualMethods) + } + + fn after_set_attr(&self, attr: JSRef<Attr>) { + match self.super_type() { + Some(ref s) => s.after_set_attr(attr), + _ => (), + } + let node: JSRef<Node> = NodeCast::from_ref(*self); + if attr.local_name() == &atom!("src") && !self.parser_inserted.get() && node.is_in_doc() { + self.prepare(); + } + } + + fn child_inserted(&self, child: JSRef<Node>) { + match self.super_type() { + Some(ref s) => s.child_inserted(child), + _ => (), + } + let node: JSRef<Node> = NodeCast::from_ref(*self); + if !self.parser_inserted.get() && node.is_in_doc() { + self.prepare(); + } + } + + fn bind_to_tree(&self, tree_in_doc: bool) { + match self.super_type() { + Some(ref s) => s.bind_to_tree(tree_in_doc), + _ => () + } + + if tree_in_doc && !self.parser_inserted.get() { + self.prepare(); + } + } } impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> { diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 7748ee13ccc..38884630e3b 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -45,7 +45,7 @@ use dom::text::Text; use dom::virtualmethods::{VirtualMethods, vtable_for}; use dom::window::Window; use geom::rect::Rect; -use parse::html::build_element_from_tag; +use parse::html::{build_element_from_tag, ScriptCreated}; use layout_interface::{ContentBoxResponse, ContentBoxesResponse, LayoutRPC, LayoutChan, ReapLayoutDataMsg}; use devtools_traits::NodeInfo; @@ -1521,7 +1521,7 @@ impl Node { local: element.local_name().clone() }; let element = build_element_from_tag(name, - Some(element.prefix().as_slice().to_string()), *document); + Some(element.prefix().as_slice().to_string()), *document, ScriptCreated); NodeCast::from_temporary(element) }, TextNodeTypeId => { diff --git a/components/script/dom/servohtmlparser.rs b/components/script/dom/servohtmlparser.rs index f88c0777437..b16b02cfdcc 100644 --- a/components/script/dom/servohtmlparser.rs +++ b/components/script/dom/servohtmlparser.rs @@ -13,7 +13,6 @@ use dom::bindings::js::{JS, JSRef, Temporary}; use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object}; use dom::node::TrustedNodeAddress; use dom::document::{Document, DocumentHelpers}; -use parse::html::JSMessage; use parse::Parser; use servo_util::task_state; @@ -28,7 +27,6 @@ use html5ever::tree_builder::{TreeBuilder, TreeBuilderOpts}; #[must_root] #[jstraceable] pub struct Sink { - pub js_chan: Sender<JSMessage>, pub base_url: Option<Url>, pub document: JS<Document>, } @@ -55,11 +53,9 @@ impl Parser for ServoHTMLParser{ impl ServoHTMLParser { #[allow(unrooted_must_root)] - pub fn new(js_chan: Sender<JSMessage>, base_url: Option<Url>, document: JSRef<Document>) - -> Temporary<ServoHTMLParser> { + pub fn new(base_url: Option<Url>, document: JSRef<Document>) -> Temporary<ServoHTMLParser> { let window = document.window().root(); let sink = Sink { - js_chan: js_chan, base_url: base_url, document: JS::from_rooted(document), }; diff --git a/components/script/dom/virtualmethods.rs b/components/script/dom/virtualmethods.rs index edde69f8f10..e5f20f99f06 100644 --- a/components/script/dom/virtualmethods.rs +++ b/components/script/dom/virtualmethods.rs @@ -18,6 +18,7 @@ use dom::bindings::codegen::InheritTypes::HTMLLinkElementCast; use dom::bindings::codegen::InheritTypes::HTMLObjectElementCast; use dom::bindings::codegen::InheritTypes::HTMLOptGroupElementCast; use dom::bindings::codegen::InheritTypes::HTMLOptionElementCast; +use dom::bindings::codegen::InheritTypes::HTMLScriptElementCast; use dom::bindings::codegen::InheritTypes::HTMLSelectElementCast; use dom::bindings::codegen::InheritTypes::HTMLStyleElementCast; use dom::bindings::codegen::InheritTypes::HTMLTableCellElementCast; @@ -37,6 +38,7 @@ use dom::element::HTMLLinkElementTypeId; use dom::element::HTMLObjectElementTypeId; use dom::element::HTMLOptGroupElementTypeId; use dom::element::HTMLOptionElementTypeId; +use dom::element::HTMLScriptElementTypeId; use dom::element::HTMLSelectElementTypeId; use dom::element::HTMLStyleElementTypeId; use dom::element::HTMLTableDataCellElementTypeId; @@ -56,6 +58,7 @@ use dom::htmllinkelement::HTMLLinkElement; use dom::htmlobjectelement::HTMLObjectElement; use dom::htmloptgroupelement::HTMLOptGroupElement; use dom::htmloptionelement::HTMLOptionElement; +use dom::htmlscriptelement::HTMLScriptElement; use dom::htmlselectelement::HTMLSelectElement; use dom::htmlstyleelement::HTMLStyleElement; use dom::htmltablecellelement::HTMLTableCellElement; @@ -189,6 +192,10 @@ pub fn vtable_for<'a>(node: &'a JSRef<'a, Node>) -> &'a VirtualMethods + 'a { let element: &'a JSRef<'a, HTMLOptionElement> = HTMLOptionElementCast::to_borrowed_ref(node).unwrap(); element as &'a VirtualMethods + 'a } + ElementNodeTypeId(HTMLScriptElementTypeId) => { + let element: &'a JSRef<'a, HTMLScriptElement> = HTMLScriptElementCast::to_borrowed_ref(node).unwrap(); + element as &'a VirtualMethods + 'a + } ElementNodeTypeId(HTMLSelectElementTypeId) => { let element: &'a JSRef<'a, HTMLSelectElement> = HTMLSelectElementCast::to_borrowed_ref(node).unwrap(); element as &'a VirtualMethods + 'a diff --git a/components/script/parse/html.rs b/components/script/parse/html.rs index 39001fe8f7f..c802e6de9aa 100644 --- a/components/script/parse/html.rs +++ b/components/script/parse/html.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use dom::attr::AttrHelpers; -use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods; use dom::bindings::codegen::Bindings::NodeBinding::NodeMethods; use dom::bindings::codegen::InheritTypes::{NodeCast, ElementCast, HTMLScriptElementCast}; use dom::bindings::js::{JS, JSRef, Temporary, OptionalRootable, Root}; @@ -23,82 +22,26 @@ use parse::Parser; use encoding::all::UTF_8; use encoding::types::{Encoding, DecodeReplace}; -use servo_net::resource_task::{Load, LoadData, Payload, Done, ResourceTask, load_whole_resource}; +use servo_net::resource_task::{Load, LoadData, Payload, Done, ResourceTask}; use servo_msg::constellation_msg::LoadData as MsgLoadData; -use servo_util::task::spawn_named; use servo_util::task_state; use servo_util::task_state::InHTMLParser; use servo_util::str::DOMString; use std::ascii::StrAsciiExt; -use std::comm::{channel, Sender, Receiver}; +use std::comm::channel; use std::str::MaybeOwned; -use url::{Url, UrlParser}; +use url::Url; use http::headers::HeaderEnum; use time; use html5ever::Attribute; use html5ever::tree_builder::{TreeSink, QuirksMode, NodeOrText, AppendNode, AppendText}; use string_cache::QualName; -pub struct JSFile { - pub data: String, - pub url: Option<Url>, -} - -pub type JSResult = Vec<JSFile>; - pub enum HTMLInput { InputString(String), InputUrl(Url), } -pub enum JSMessage { - JSTaskNewFile(Url), - JSTaskNewInlineScript(String, Option<Url>), - JSTaskExit -} - -/// Messages generated by the HTML parser upon discovery of additional resources -pub enum HtmlDiscoveryMessage { - HtmlDiscoveredScript(JSResult) -} - -pub struct HtmlParserResult { - pub discovery_port: Receiver<HtmlDiscoveryMessage>, -} - -fn js_script_listener(to_parent: Sender<HtmlDiscoveryMessage>, - from_parent: Receiver<JSMessage>, - resource_task: ResourceTask) { - let mut result_vec = vec!(); - - loop { - match from_parent.recv_opt() { - Ok(JSTaskNewFile(url)) => { - match load_whole_resource(&resource_task, url.clone()) { - Err(_) => { - error!("error loading script {:s}", url.serialize()); - } - Ok((metadata, bytes)) => { - let decoded = UTF_8.decode(bytes.as_slice(), DecodeReplace).unwrap(); - result_vec.push(JSFile { - data: decoded.to_string(), - url: Some(metadata.final_url), - }); - } - } - } - Ok(JSTaskNewInlineScript(data, url)) => { - result_vec.push(JSFile { data: data, url: url }); - } - Ok(JSTaskExit) | Err(()) => { - break; - } - } - } - - assert!(to_parent.send_opt(HtmlDiscoveredScript(result_vec)).is_ok()); -} - // Parses an RFC 2616 compliant date/time string, and returns a localized // date/time string in a format suitable for document.lastModified. fn parse_last_modified(timestamp: &str) -> String { @@ -123,9 +66,16 @@ fn parse_last_modified(timestamp: &str) -> String { } } +#[deriving(PartialEq)] +pub enum ElementCreator { + ParserCreated, + ScriptCreated, +} + pub fn build_element_from_tag(name: QualName, prefix: Option<DOMString>, - document: JSRef<Document>) -> Temporary<Element> { + document: JSRef<Document>, + creator: ElementCreator) -> Temporary<Element> { if name.ns != ns!(HTML) { return Element::new(name.local.as_slice().to_string(), name.ns, None, document); } @@ -233,7 +183,7 @@ pub fn build_element_from_tag(name: QualName, atom!("ruby") => make!(HTMLElement), atom!("s") => make!(HTMLElement), atom!("samp") => make!(HTMLElement), - atom!("script") => make!(HTMLScriptElement, true), + atom!("script") => make!(HTMLScriptElement, creator), atom!("section") => make!(HTMLElement), atom!("select") => make!(HTMLSelectElement), atom!("small") => make!(HTMLElement), @@ -307,7 +257,7 @@ impl<'a> TreeSink<TrustedNodeAddress> for servohtmlparser::Sink { fn create_element(&mut self, name: QualName, attrs: Vec<Attribute>) -> TrustedNodeAddress { let doc = self.document.root(); - let elem = build_element_from_tag(name, None, *doc).root(); + let elem = build_element_from_tag(name, None, *doc, ParserCreated).root(); for attr in attrs.into_iter() { elem.set_attribute_from_parser(attr.name, attr.value, None); @@ -378,42 +328,16 @@ impl<'a> TreeSink<TrustedNodeAddress> for servohtmlparser::Sink { error!("remove_from_parent not implemented!"); } - fn mark_script_already_started(&mut self, _node: TrustedNodeAddress) { - error!("mark_script_already_started not implemented!"); + fn mark_script_already_started(&mut self, node: TrustedNodeAddress) { + let node: Root<Node> = unsafe { JS::from_trusted_node_address(node).root() }; + let script: Option<JSRef<HTMLScriptElement>> = HTMLScriptElementCast::to_ref(*node); + script.map(|script| script.mark_already_started()); } fn complete_script(&mut self, node: TrustedNodeAddress) { let node: Root<Node> = unsafe { JS::from_trusted_node_address(node).root() }; - let script: Option<JSRef<HTMLScriptElement>> = - HTMLScriptElementCast::to_ref(*node); - let script = match script { - Some(script) if script.is_javascript() => script, - _ => return, - }; - - let script_element: JSRef<Element> = ElementCast::from_ref(script); - match script_element.get_attribute(ns!(""), &atom!("src")).root() { - Some(src) => { - debug!("found script: {:s}", src.deref().Value()); - let mut url_parser = UrlParser::new(); - match self.base_url { - None => (), - Some(ref base_url) => { - url_parser.base_url(base_url); - } - }; - match url_parser.parse(src.deref().value().as_slice()) { - Ok(new_url) => self.js_chan.send(JSTaskNewFile(new_url)), - Err(e) => debug!("Parsing url {:s} failed: {:?}", src.deref().Value(), e) - }; - } - None => { - let scriptnode: JSRef<Node> = NodeCast::from_ref(script); - let data = Node::collect_text_contents(scriptnode.children()); - debug!("script data = {:?}", data); - self.js_chan.send(JSTaskNewInlineScript(data, self.base_url.clone())); - } - } + let script: Option<JSRef<HTMLScriptElement>> = HTMLScriptElementCast::to_ref(*node); + script.map(|script| script.prepare()); } } @@ -422,17 +346,7 @@ pub fn parse_html(page: &Page, document: JSRef<Document>, input: HTMLInput, resource_task: ResourceTask, - msg_load_data: Option<MsgLoadData>) - -> HtmlParserResult { - // Spawn a JS parser to receive JavaScript. - let (discovery_chan, discovery_port) = channel(); - let resource_task2 = resource_task.clone(); - let js_result_chan = discovery_chan.clone(); - let (js_chan, js_msg_port) = channel(); - spawn_named("parse_html:js", proc() { - js_script_listener(js_result_chan, js_msg_port, resource_task2.clone()); - }); - + msg_load_data: Option<MsgLoadData>) { let (base_url, load_response) = match input { InputUrl(ref url) => { // Wait for the LoadResponse so that the parser knows the final URL. @@ -480,7 +394,7 @@ pub fn parse_html(page: &Page, }, }; - let parser = ServoHTMLParser::new(js_chan.clone(), base_url.clone(), document).root(); + let parser = ServoHTMLParser::new(base_url.clone(), document).root(); let parser: JSRef<ServoHTMLParser> = *parser; task_state::enter(InHTMLParser); @@ -520,9 +434,4 @@ pub fn parse_html(page: &Page, task_state::exit(InHTMLParser); debug!("finished parsing"); - js_chan.send(JSTaskExit); - - HtmlParserResult { - discovery_port: discovery_port, - } } diff --git a/components/script/script_task.rs b/components/script/script_task.rs index cbcdfea03ac..deb6aaded80 100644 --- a/components/script/script_task.rs +++ b/components/script/script_task.rs @@ -16,7 +16,6 @@ use dom::bindings::conversions::{FromJSValConvertible, Empty}; use dom::bindings::global; use dom::bindings::js::{JS, JSRef, RootCollection, Temporary, OptionalRootable}; use dom::bindings::trace::JSTraceable; -use dom::bindings::utils::Reflectable; use dom::bindings::utils::{wrap_for_same_compartment, pre_wrap}; use dom::document::{Document, HTMLDocument, DocumentHelpers, FromParser}; use dom::element::{Element, HTMLButtonElementTypeId, HTMLInputElementTypeId}; @@ -29,7 +28,7 @@ use dom::node::{ElementNodeTypeId, Node, NodeHelpers}; use dom::window::{Window, WindowHelpers}; use dom::worker::{Worker, TrustedWorkerAddress}; use dom::xmlhttprequest::{TrustedXHRAddress, XMLHttpRequest, XHRProgress}; -use parse::html::{InputString, InputUrl, HtmlParserResult, HtmlDiscoveredScript, parse_html}; +use parse::html::{InputString, InputUrl, parse_html}; use layout_interface::{ScriptLayoutChan, LayoutChan, ReflowForDisplay}; use layout_interface; use page::{Page, IterablePage, Frame}; @@ -62,7 +61,6 @@ use js::jsapi::{JSContext, JSRuntime, JSTracer}; use js::jsapi::{JS_SetGCParameter, JSGC_MAX_BYTES}; use js::jsapi::{JS_SetGCCallback, JSGCStatus, JSGC_BEGIN, JSGC_END}; use js::rust::{Cx, RtUtils}; -use js::rust::with_compartment; use js; use url::Url; @@ -797,13 +795,6 @@ impl ScriptTask { InputString(strval.unwrap_or("".to_string())) }; - // Parse HTML. - // - // Note: We can parse the next document in parallel with any previous documents. - let HtmlParserResult { discovery_port } - = parse_html(&*page, *document, parser_input, self.resource_task.clone(), - Some(load_data)); - { // Create the root frame. let mut frame = page.mut_frame(); @@ -813,18 +804,9 @@ impl ScriptTask { }); } - document.set_ready_state(DocumentReadyStateValues::Interactive); + parse_html(&*page, *document, parser_input, self.resource_task.clone(), Some(load_data)); - let mut js_scripts = None; - loop { - match discovery_port.recv_opt() { - Ok(HtmlDiscoveredScript(scripts)) => { - assert!(js_scripts.is_none()); - js_scripts = Some(scripts); - } - Err(()) => break - } - } + document.set_ready_state(DocumentReadyStateValues::Interactive); // Kick off the initial reflow of the page. debug!("kicking off initial reflow of {}", url); @@ -841,31 +823,6 @@ impl ScriptTask { *page_url = Some((url.clone(), false)); } - // Receive the JavaScript scripts. - assert!(js_scripts.is_some()); - let js_scripts = js_scripts.take().unwrap(); - debug!("js_scripts: {:?}", js_scripts); - - with_compartment((**cx).ptr, window.reflector().get_jsobject(), || { - // Evaluate every script in the document. - for file in js_scripts.iter() { - let global_obj = window.reflector().get_jsobject(); - let filename = match file.url { - None => String::new(), - Some(ref url) => url.serialize(), - }; - - //FIXME: this should have some kind of error handling, or explicitly - // drop an exception on the floor. - match cx.evaluate_script(global_obj, file.data.clone(), filename, 1) { - Ok(_) => (), - Err(_) => println!("evaluate_script failed") - } - - window.flush_layout(ReflowForDisplay); - } - }); - // https://html.spec.whatwg.org/multipage/#the-end step 4 let event = Event::new(&global::Window(*window), "DOMContentLoaded".to_string(), DoesNotBubble, NotCancelable).root(); |