mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Handle script encoding more in line with the specification.
This commit is contained in:
parent
20a8c97cf0
commit
7489f82a9b
1 changed files with 31 additions and 28 deletions
|
@ -5,7 +5,6 @@
|
||||||
use document_loader::LoadType;
|
use document_loader::LoadType;
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
|
|
||||||
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
use dom::bindings::codegen::Bindings::DocumentBinding::DocumentMethods;
|
||||||
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLScriptElementBinding::HTMLScriptElementMethods;
|
||||||
|
@ -35,7 +34,6 @@ use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkEr
|
||||||
use network_listener::{NetworkListener, PreInvoke};
|
use network_listener::{NetworkListener, PreInvoke};
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::mem;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use string_cache::Atom;
|
use string_cache::Atom;
|
||||||
use style::str::{HTML_SPACE_CHARACTERS, StaticStringVec};
|
use style::str::{HTML_SPACE_CHARACTERS, StaticStringVec};
|
||||||
|
@ -64,10 +62,6 @@ pub struct HTMLScriptElement {
|
||||||
|
|
||||||
/// The source this script was loaded from
|
/// The source this script was loaded from
|
||||||
load: DOMRefCell<Option<ScriptOrigin>>,
|
load: DOMRefCell<Option<ScriptOrigin>>,
|
||||||
|
|
||||||
#[ignore_heap_size_of = "Defined in rust-encoding"]
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#concept-script-encoding
|
|
||||||
block_character_encoding: Cell<Option<EncodingRef>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLScriptElement {
|
impl HTMLScriptElement {
|
||||||
|
@ -82,7 +76,6 @@ impl HTMLScriptElement {
|
||||||
ready_to_be_parser_executed: Cell::new(false),
|
ready_to_be_parser_executed: Cell::new(false),
|
||||||
parser_document: JS::from_ref(document),
|
parser_document: JS::from_ref(document),
|
||||||
load: DOMRefCell::new(None),
|
load: DOMRefCell::new(None),
|
||||||
block_character_encoding: Cell::new(None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +113,16 @@ static SCRIPT_JS_MIMES: StaticStringVec = &[
|
||||||
#[derive(HeapSizeOf, JSTraceable)]
|
#[derive(HeapSizeOf, JSTraceable)]
|
||||||
pub enum ScriptOrigin {
|
pub enum ScriptOrigin {
|
||||||
Internal(DOMString, Url),
|
Internal(DOMString, Url),
|
||||||
External(Result<(Metadata, Vec<u8>), NetworkError>),
|
External(Result<(String, Url), NetworkError>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The context required for asynchronously loading an external script source.
|
/// The context required for asynchronously loading an external script source.
|
||||||
struct ScriptContext {
|
struct ScriptContext {
|
||||||
/// The element that initiated the request.
|
/// The element that initiated the request.
|
||||||
elem: Trusted<HTMLScriptElement>,
|
elem: Trusted<HTMLScriptElement>,
|
||||||
|
/// The (fallback) character encoding argument to the "fetch a classic
|
||||||
|
/// script" algorithm.
|
||||||
|
character_encoding: EncodingRef,
|
||||||
/// The response body received to date.
|
/// The response body received to date.
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
/// The response metadata received to date.
|
/// The response metadata received to date.
|
||||||
|
@ -162,12 +158,26 @@ impl AsyncResponseListener for ScriptContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
|
||||||
|
/// step 4-9
|
||||||
fn response_complete(&mut self, status: Result<(), NetworkError>) {
|
fn response_complete(&mut self, status: Result<(), NetworkError>) {
|
||||||
|
// Step 5.
|
||||||
let load = status.and(self.status.clone()).map(|_| {
|
let load = status.and(self.status.clone()).map(|_| {
|
||||||
let data = mem::replace(&mut self.data, vec!());
|
|
||||||
let metadata = self.metadata.take().unwrap();
|
let metadata = self.metadata.take().unwrap();
|
||||||
(metadata, data)
|
|
||||||
|
// Step 6.
|
||||||
|
let encoding = metadata.charset
|
||||||
|
.and_then(|encoding| encoding_from_whatwg_label(&encoding))
|
||||||
|
.unwrap_or(self.character_encoding);
|
||||||
|
|
||||||
|
// Step 7.
|
||||||
|
let source_text = encoding.decode(&self.data, DecoderTrap::Replace).unwrap();
|
||||||
|
(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();
|
let elem = self.elem.root();
|
||||||
// TODO: maybe set this to None again after script execution to save memory.
|
// TODO: maybe set this to None again after script execution to save memory.
|
||||||
*elem.load.borrow_mut() = Some(ScriptOrigin::External(load));
|
*elem.load.borrow_mut() = Some(ScriptOrigin::External(load));
|
||||||
|
@ -181,10 +191,13 @@ impl AsyncResponseListener for ScriptContext {
|
||||||
impl PreInvoke for ScriptContext {}
|
impl PreInvoke for ScriptContext {}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
|
/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
|
||||||
fn fetch_a_classic_script(script: &HTMLScriptElement, url: Url) {
|
fn fetch_a_classic_script(script: &HTMLScriptElement,
|
||||||
|
url: Url,
|
||||||
|
character_encoding: EncodingRef) {
|
||||||
// TODO(#9186): use the fetch infrastructure.
|
// TODO(#9186): use the fetch infrastructure.
|
||||||
let context = Arc::new(Mutex::new(ScriptContext {
|
let context = Arc::new(Mutex::new(ScriptContext {
|
||||||
elem: Trusted::new(script),
|
elem: Trusted::new(script),
|
||||||
|
character_encoding: character_encoding,
|
||||||
data: vec!(),
|
data: vec!(),
|
||||||
metadata: None,
|
metadata: None,
|
||||||
url: url.clone(),
|
url: url.clone(),
|
||||||
|
@ -288,11 +301,9 @@ impl HTMLScriptElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 13.
|
// Step 13.
|
||||||
if let Some(ref charset) = element.get_attribute(&ns!(), &atom!("charset")) {
|
let encoding = element.get_attribute(&ns!(), &atom!("charset"))
|
||||||
if let Some(encodingRef) = encoding_from_whatwg_label(&charset.Value()) {
|
.and_then(|charset| encoding_from_whatwg_label(&charset.value()))
|
||||||
self.block_character_encoding.set(Some(encodingRef));
|
.unwrap_or_else(|| doc.encoding());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Step 14: CORS.
|
// TODO: Step 14: CORS.
|
||||||
|
|
||||||
|
@ -326,7 +337,7 @@ impl HTMLScriptElement {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 18.6.
|
// Step 18.6.
|
||||||
fetch_a_classic_script(self, url);
|
fetch_a_classic_script(self, url, encoding);
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
None => false,
|
None => false,
|
||||||
|
@ -410,17 +421,9 @@ impl HTMLScriptElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 2.b.1.a.
|
// Step 2.b.1.a.
|
||||||
ScriptOrigin::External(Ok((metadata, bytes))) => {
|
ScriptOrigin::External(Ok((text, url))) => {
|
||||||
debug!("loading external script, url = {}", metadata.final_url);
|
debug!("loading external script, url = {}", url);
|
||||||
|
(DOMString::from(text), true, url)
|
||||||
let encoding = metadata.charset
|
|
||||||
.and_then(|encoding| encoding_from_whatwg_label(&encoding))
|
|
||||||
.or_else(|| self.block_character_encoding.get())
|
|
||||||
.unwrap_or_else(|| self.parser_document.encoding());
|
|
||||||
|
|
||||||
(DOMString::from(encoding.decode(&*bytes, DecoderTrap::Replace).unwrap()),
|
|
||||||
true,
|
|
||||||
metadata.final_url)
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// Step 2.b.1.c.
|
// Step 2.b.1.c.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue