aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/htmlscriptelement.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/htmlscriptelement.rs')
-rw-r--r--components/script/dom/htmlscriptelement.rs200
1 files changed, 115 insertions, 85 deletions
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index 9558d9c4b41..52935e32dcf 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -4,7 +4,6 @@
use document_loader::LoadType;
use dom::attr::Attr;
-use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding;
@@ -62,8 +61,8 @@ pub struct HTMLScriptElement {
/// Document of the parser that created this element
parser_document: JS<Document>,
- /// The source this script was loaded from
- load: DOMRefCell<Option<Result<ScriptOrigin, NetworkError>>>,
+ /// Track line line_number
+ line_number: u64,
}
impl HTMLScriptElement {
@@ -73,11 +72,11 @@ impl HTMLScriptElement {
htmlelement:
HTMLElement::new_inherited(local_name, prefix, document),
already_started: Cell::new(false),
- parser_inserted: Cell::new(creator == ElementCreator::ParserCreated),
- non_blocking: Cell::new(creator != ElementCreator::ParserCreated),
+ parser_inserted: Cell::new(creator.is_parser_created()),
+ non_blocking: Cell::new(!creator.is_parser_created()),
ready_to_be_parser_executed: Cell::new(false),
parser_document: JS::from_ref(document),
- load: DOMRefCell::new(None),
+ line_number: creator.return_line_number(),
}
}
@@ -113,23 +112,23 @@ static SCRIPT_JS_MIMES: StaticStringVec = &[
];
#[derive(HeapSizeOf, JSTraceable)]
-pub struct ScriptOrigin {
+pub struct ClassicScript {
text: DOMString,
url: ServoUrl,
external: bool,
}
-impl ScriptOrigin {
- fn internal(text: DOMString, url: ServoUrl) -> ScriptOrigin {
- ScriptOrigin {
+impl ClassicScript {
+ fn internal(text: DOMString, url: ServoUrl) -> ClassicScript {
+ ClassicScript {
text: text,
url: url,
external: false,
}
}
- fn external(text: DOMString, url: ServoUrl) -> ScriptOrigin {
- ScriptOrigin {
+ fn external(text: DOMString, url: ServoUrl) -> ClassicScript {
+ ClassicScript {
text: text,
url: url,
external: true,
@@ -137,10 +136,14 @@ impl ScriptOrigin {
}
}
+pub type ScriptResult = Result<ClassicScript, NetworkError>;
+
/// The context required for asynchronously loading an external script source.
struct ScriptContext {
/// The element that initiated the request.
elem: Trusted<HTMLScriptElement>,
+ /// The kind of external script.
+ kind: ExternalScriptKind,
/// The (fallback) character encoding argument to the "fetch a classic
/// script" algorithm.
character_encoding: EncodingRef,
@@ -200,17 +203,23 @@ impl FetchResponseListener for ScriptContext {
// Step 7.
let source_text = encoding.decode(&self.data, DecoderTrap::Replace).unwrap();
- ScriptOrigin::external(DOMString::from(source_text), metadata.final_url)
+ ClassicScript::external(DOMString::from(source_text), metadata.final_url)
});
// Step 9.
// https://html.spec.whatwg.org/multipage/#prepare-a-script
// Step 18.6 (When the chosen algorithm asynchronously completes).
let elem = self.elem.root();
- *elem.load.borrow_mut() = Some(load);
elem.ready_to_be_parser_executed.set(true);
-
let document = document_from_node(&*elem);
+
+ match self.kind {
+ ExternalScriptKind::Asap => document.asap_script_loaded(&elem, load),
+ ExternalScriptKind::AsapInOrder => document.asap_in_order_script_loaded(&elem, load),
+ ExternalScriptKind::Deferred => document.deferred_script_loaded(&elem, load),
+ ExternalScriptKind::ParsingBlocking => document.pending_parsing_blocking_script_loaded(&elem, load),
+ }
+
document.finish_load(LoadType::Script(self.url.clone()));
}
}
@@ -219,8 +228,10 @@ impl PreInvoke for ScriptContext {}
/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
fn fetch_a_classic_script(script: &HTMLScriptElement,
+ kind: ExternalScriptKind,
url: ServoUrl,
cors_setting: Option<CorsSettings>,
+ integrity_metadata: String,
character_encoding: EncodingRef) {
let doc = document_from_node(script);
@@ -245,6 +256,7 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
pipeline_id: Some(script.global().pipeline_id()),
referrer_url: Some(doc.url()),
referrer_policy: doc.get_referrer_policy(),
+ integrity_metadata: integrity_metadata,
.. RequestInit::default()
};
@@ -252,6 +264,7 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
let context = Arc::new(Mutex::new(ScriptContext {
elem: Trusted::new(script),
+ kind: kind,
character_encoding: character_encoding,
data: vec!(),
metadata: None,
@@ -363,83 +376,88 @@ impl HTMLScriptElement {
_ => unreachable!()
};
- // TODO: Step 15: Nonce.
+ // TODO: Step 15: Module script credentials mode.
+
+ // TODO: Step 16: Nonce.
+
+ // Step 17: Integrity metadata.
+ let im_attribute = element.get_attribute(&ns!(), &local_name!("integrity"));
+ let integrity_val = im_attribute.r().map(|a| a.value());
+ let integrity_metadata = match integrity_val {
+ Some(ref value) => &***value,
+ None => "",
+ };
- // TODO: Step 16: Parser state.
+ // TODO: Step 18: parser state.
- // TODO: Step 17: environment settings object.
+ // TODO: Step 19: environment settings object.
let base_url = doc.base_url();
- let is_external = match element.get_attribute(&ns!(), &local_name!("src")) {
- // Step 18.
- Some(ref src) => {
- // Step 18.1.
- let src = src.value();
-
- // Step 18.2.
- if src.is_empty() {
- self.queue_error_event();
- return;
- }
+ if let Some(src) = element.get_attribute(&ns!(), &local_name!("src")) {
+ // Step 20.
- // Step 18.4-18.5.
- let url = match base_url.join(&src) {
- Err(_) => {
- warn!("error parsing URL for script {}", &**src);
- self.queue_error_event();
- return;
- }
- Ok(url) => url,
- };
+ // Step 20.1.
+ let src = src.value();
- // Step 18.6.
- fetch_a_classic_script(self, url, cors_setting, encoding);
+ // Step 20.2.
+ if src.is_empty() {
+ self.queue_error_event();
+ return;
+ }
- true
- },
- // TODO: Step 19.
- None => false,
- };
+ // Step 20.3: The "from an external file"" flag is stored in ClassicScript.
- // Step 20.
- let deferred = element.has_attribute(&local_name!("defer"));
- // Step 20.a: classic, has src, has defer, was parser-inserted, is not async.
- if is_external &&
- deferred &&
- was_parser_inserted &&
- !async {
- doc.add_deferred_script(self);
- // Second part implemented in Document::process_deferred_scripts.
- // Step 20.b: classic, has src, was parser-inserted, is not async.
- } else if is_external &&
- was_parser_inserted &&
- !async {
- doc.set_pending_parsing_blocking_script(Some(self));
- // Second part implemented in the load result handler.
- // Step 20.c: classic, has src, isn't async, isn't non-blocking.
- } else if is_external &&
- !async &&
- !self.non_blocking.get() {
- doc.push_asap_in_order_script(self);
- // Second part implemented in Document::process_asap_scripts.
- // Step 20.d: classic, has src.
- } else if is_external {
- doc.add_asap_script(self);
- // Second part implemented in Document::process_asap_scripts.
- // Step 20.e: doesn't have src, was parser-inserted, is blocked on stylesheet.
- } else if !is_external &&
- was_parser_inserted &&
- doc.get_current_parser().map_or(false, |parser| parser.script_nesting_level() <= 1) &&
- doc.get_script_blocking_stylesheets_count() > 0 {
- doc.set_pending_parsing_blocking_script(Some(self));
- *self.load.borrow_mut() = Some(Ok(ScriptOrigin::internal(text, base_url)));
- self.ready_to_be_parser_executed.set(true);
- // Step 20.f: otherwise.
+ // Step 20.4-20.5.
+ let url = match base_url.join(&src) {
+ Ok(url) => url,
+ Err(_) => {
+ warn!("error parsing URL for script {}", &**src);
+ self.queue_error_event();
+ return;
+ },
+ };
+
+ // Preparation for step 22.
+ let kind = if element.has_attribute(&local_name!("defer")) && was_parser_inserted && !async {
+ // Step 22.a: classic, has src, has defer, was parser-inserted, is not async.
+ ExternalScriptKind::Deferred
+ } else if was_parser_inserted && !async {
+ // Step 22.b: classic, has src, was parser-inserted, is not async.
+ ExternalScriptKind::ParsingBlocking
+ } else if !async && !self.non_blocking.get() {
+ // Step 22.c: classic, has src, is not async, is not non-blocking.
+ ExternalScriptKind::AsapInOrder
+ } else {
+ // Step 22.d: classic, has src.
+ ExternalScriptKind::Asap
+ };
+
+ // Step 20.6.
+ fetch_a_classic_script(self, kind, url, cors_setting, integrity_metadata.to_owned(), encoding);
+
+ // Step 22.
+ match kind {
+ ExternalScriptKind::Deferred => doc.add_deferred_script(self),
+ ExternalScriptKind::ParsingBlocking => doc.set_pending_parsing_blocking_script(self, None),
+ ExternalScriptKind::AsapInOrder => doc.push_asap_in_order_script(self),
+ ExternalScriptKind::Asap => doc.add_asap_script(self),
+ }
} else {
+ // Step 21.
assert!(!text.is_empty());
+ let result = Ok(ClassicScript::internal(text, base_url));
self.ready_to_be_parser_executed.set(true);
- *self.load.borrow_mut() = Some(Ok(ScriptOrigin::internal(text, base_url)));
- self.execute();
+
+ // Step 22.
+ if was_parser_inserted &&
+ doc.get_current_parser().map_or(false, |parser| parser.script_nesting_level() <= 1) &&
+ doc.get_script_blocking_stylesheets_count() > 0 {
+ // Step 22.e: classic, has no src, was parser-inserted, is blocked on stylesheet.
+ doc.set_pending_parsing_blocking_script(self, Some(result));
+ } else {
+ // Step 22.f: otherwise.
+ self.execute(result);
+ }
}
}
@@ -448,7 +466,7 @@ impl HTMLScriptElement {
}
/// https://html.spec.whatwg.org/multipage/#execute-the-script-block
- pub fn execute(&self) {
+ pub fn execute(&self, result: Result<ClassicScript, NetworkError>) {
assert!(self.ready_to_be_parser_executed.get());
// Step 1.
@@ -457,8 +475,7 @@ impl HTMLScriptElement {
return;
}
- let load = self.load.borrow_mut().take().unwrap();
- let script = match load {
+ let script = match result {
// Step 2.
Err(e) => {
warn!("error loading script {:?}", e);
@@ -495,7 +512,7 @@ impl HTMLScriptElement {
let window = window_from_node(self);
rooted!(in(window.get_cx()) let mut rval = UndefinedValue());
window.upcast::<GlobalScope>().evaluate_script_on_global_with_result(
- &script.text, script.url.as_str(), rval.handle_mut());
+ &script.text, script.url.as_str(), rval.handle_mut(), self.line_number as u32);
// Step 6.
document.set_current_script(old_script.r());
@@ -675,6 +692,11 @@ impl HTMLScriptElementMethods for HTMLScriptElement {
// https://html.spec.whatwg.org/multipage/#dom-script-defer
make_bool_setter!(SetDefer, "defer");
+ // https://html.spec.whatwg.org/multipage/#dom-script-integrity
+ make_getter!(Integrity, "integrity");
+ // https://html.spec.whatwg.org/multipage/#dom-script-integrity
+ make_setter!(SetIntegrity, "integrity");
+
// https://html.spec.whatwg.org/multipage/#dom-script-event
make_getter!(Event, "event");
// https://html.spec.whatwg.org/multipage/#dom-script-event
@@ -721,3 +743,11 @@ impl HTMLScriptElementMethods for HTMLScriptElement {
self.upcast::<Node>().SetTextContent(Some(value))
}
}
+
+#[derive(Clone, Copy)]
+enum ExternalScriptKind {
+ Deferred,
+ ParsingBlocking,
+ AsapInOrder,
+ Asap,
+}