diff options
author | Ms2ger <ms2ger@gmail.com> | 2015-02-22 22:17:49 +0100 |
---|---|---|
committer | Ms2ger <ms2ger@gmail.com> | 2015-02-23 10:28:49 +0100 |
commit | ada6a088d107ac48ff0e91df800f58c50fdb8512 (patch) | |
tree | 742683887bf3495dfee52d1670361c5ba0eb1133 /components/script/dom/htmlscriptelement.rs | |
parent | 2e1adb3fa670504fb0fedaa517f312ba233bf67b (diff) | |
download | servo-ada6a088d107ac48ff0e91df800f58c50fdb8512.tar.gz servo-ada6a088d107ac48ff0e91df800f58c50fdb8512.zip |
Split the 'Execute a script block' code out of prepare().
This also adds comments for missing steps.
The only change in behaviour should be the debug message when an external
script fails to load.
Diffstat (limited to 'components/script/dom/htmlscriptelement.rs')
-rw-r--r-- | components/script/dom/htmlscriptelement.rs | 172 |
1 files changed, 128 insertions, 44 deletions
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs index df1a2287462..8a0c3483650 100644 --- a/components/script/dom/htmlscriptelement.rs +++ b/components/script/dom/htmlscriptelement.rs @@ -29,12 +29,12 @@ use script_task::{ScriptMsg, Runnable}; use encoding::all::UTF_8; use encoding::types::{Encoding, DecoderTrap}; -use net::resource_task::load_whole_resource; +use net::resource_task::{load_whole_resource, Metadata}; use util::str::{DOMString, HTML_SPACE_CHARACTERS, StaticStringVec}; use std::borrow::ToOwned; use std::cell::Cell; use string_cache::Atom; -use url::UrlParser; +use url::{Url, UrlParser}; #[dom_struct] pub struct HTMLScriptElement { @@ -87,6 +87,10 @@ pub trait HTMLScriptElementHelpers { /// Prepare a script (<http://www.whatwg.org/html/#prepare-a-script>) fn prepare(self); + /// [Execute a script block] + /// (https://html.spec.whatwg.org/multipage/#execute-the-script-block) + fn execute(self, load: ScriptOrigin); + /// Prepare a script, steps 6 and 7. fn is_javascript(self) -> bool; @@ -124,9 +128,9 @@ static SCRIPT_JS_MIMES: StaticStringVec = &[ "text/x-javascript", ]; -enum ScriptOrigin { - Internal, - External, +pub enum ScriptOrigin { + Internal(String, Url), + External(Result<(Metadata, Vec<u8>), String>), } impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> { @@ -200,66 +204,146 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> { // character encoding for this script element be the result of getting an encoding from the // value of the `charset` attribute. - // Step 14 and 15. - // TODO: Add support for the `defer` and `async` attributes. (For now, we fetch all - // scripts synchronously and execute them immediately.) + // Step 14. let window = window_from_node(self).root(); let window = window.r(); let page = window.page(); let base_url = page.get_url(); - let (origin, source, url) = match element.get_attribute(ns!(""), &atom!("src")).root() { + let load = match element.get_attribute(ns!(""), &atom!("src")).root() { + // Step 14. Some(src) => { - if src.r().Value().is_empty() { + // Step 14.1 + let src = src.r().Value(); + + // Step 14.2 + if src.is_empty() { self.queue_error_event(); return; } - match UrlParser::new().base_url(&base_url).parse(src.r().Value().as_slice()) { + + // Step 14.3 + match UrlParser::new().base_url(&base_url).parse(&*src) { + Err(_) => { + // Step 14.4 + error!("error parsing URL for script {}", src); + self.queue_error_event(); + return; + } Ok(url) => { + // Step 14.5 // TODO: Do a potentially CORS-enabled fetch with the mode being the current // state of the element's `crossorigin` content attribute, the origin being // the origin of the script element's node document, and the default origin // behaviour set to taint. - match load_whole_resource(&page.resource_task, url) { - Ok((metadata, bytes)) => { - // TODO: use the charset from step 13. - let source = UTF_8.decode(bytes.as_slice(), DecoderTrap::Replace).unwrap(); - (ScriptOrigin::External, source, metadata.final_url) - } - Err(_) => { - error!("error loading script {}", src.r().Value()); - self.queue_error_event(); - return; - } - } - } - Err(_) => { - error!("error parsing URL for script {}", src.r().Value()); - self.queue_error_event(); - return; + ScriptOrigin::External(load_whole_resource(&page.resource_task, url)) } } - } - None => (ScriptOrigin::Internal, text, base_url) + }, + None => ScriptOrigin::Internal(text, base_url), }; - window.evaluate_script_on_global_with_result(source.as_slice(), url.serialize().as_slice()); + // Step 15. + // TODO: Add support for the `defer` and `async` attributes. (For now, we fetch all + // scripts synchronously and execute them immediately.) + self.execute(load); + } + + fn execute(self, load: ScriptOrigin) { + // Step 1. + // TODO: If the element is flagged as "parser-inserted", but the + // element's node document is not the Document of the parser that + // created the element, then abort these steps. - // https://html.spec.whatwg.org/multipage/scripting.html#execute-the-script-block - // step 2, substep 10 - match origin { - ScriptOrigin::External => { - self.dispatch_load_event(); + // Step 2. + let (source, external, url) = match load { + // Step 2.a. + ScriptOrigin::External(Err(e)) => { + error!("error loading script {}", e); + self.queue_error_event(); + return; } - ScriptOrigin::Internal => { - let chan = window.script_chan(); - let handler = Trusted::new(window.get_cx(), self, chan.clone()); - let dispatcher = Box::new(EventDispatcher { - element: handler, - is_error: false, - }); - chan.send(ScriptMsg::RunnableMsg(dispatcher)).unwrap(); + + // Step 2.b.1.a. + ScriptOrigin::External(Ok((metadata, bytes))) => { + // Step 1. + // TODO: If the resource's Content Type metadata, if any, + // specifies a character encoding, and the user agent supports + // that encoding, then let character encoding be that encoding, + // and jump to the bottom step in this series of steps. + + // Step 2. + // TODO: If the algorithm above set the script block's + // character encoding, then let character encoding be that + // encoding, and jump to the bottom step in this series of + // steps. + + // Step 3. + // TODO: Let character encoding be the script block's fallback + // character encoding. + + // Step 4. + // TODO: Otherwise, decode the file to Unicode, using character + // encoding as the fallback encoding. + + (UTF_8.decode(&*bytes, DecoderTrap::Replace).unwrap(), true, + metadata.final_url) + }, + + // Step 2.b.1.c. + ScriptOrigin::Internal(text, url) => { + (text, false, url) } + }; + + // Step 2.b.2. + // TODO: Fire a simple event named beforescriptexecute that bubbles and + // is cancelable at the script element. + // If the event is canceled, then abort these steps. + + // Step 2.b.3. + // TODO: If the script is from an external file, then increment the + // ignore-destructive-writes counter of the script element's node + // document. Let neutralised doc be that Document. + + // Step 2.b.4. + // TODO: Let old script element be the value to which the script + // element's node document's currentScript object was most recently + // initialised. + + // Step 2.b.5. + // TODO: Initialise the script element's node document's currentScript + // object to the script element. + + // Step 2.b.6. + // TODO: Create a script... + let window = window_from_node(self).root(); + window.r().evaluate_script_on_global_with_result(&*source, + &*url.serialize()); + + // Step 2.b.7. + // TODO: Initialise the script element's node document's currentScript + // object to old script element. + + // Step 2.b.8. + // TODO: Decrement the ignore-destructive-writes counter of neutralised + // doc, if it was incremented in the earlier step. + + // Step 2.b.9. + // TODO: Fire a simple event named afterscriptexecute that bubbles (but + // is not cancelable) at the script element. + + // Step 2.b.10. + if external { + self.dispatch_load_event(); + } else { + let chan = window.r().script_chan(); + let handler = Trusted::new(window.r().get_cx(), self, chan.clone()); + let dispatcher = Box::new(EventDispatcher { + element: handler, + is_error: false, + }); + chan.send(ScriptMsg::RunnableMsg(dispatcher)).unwrap(); } } |