mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Use fetch infrastructure to load external scripts
This commit is contained in:
parent
d4816762fa
commit
4dcf693a75
2 changed files with 57 additions and 20 deletions
|
@ -9,9 +9,9 @@ use dom::bindings::js::JS;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use ipc_channel::ipc::IpcSender;
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use net_traits::request::RequestInit;
|
|
||||||
use net_traits::{AsyncResponseTarget, PendingAsyncLoad, LoadContext};
|
use net_traits::{AsyncResponseTarget, PendingAsyncLoad, LoadContext};
|
||||||
use net_traits::{FetchResponseMsg, ResourceThreads, IpcSend};
|
use net_traits::{FetchResponseMsg, ResourceThreads, IpcSend};
|
||||||
|
use net_traits::request::RequestInit;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{JS, Root};
|
use dom::bindings::js::{JS, Root};
|
||||||
use dom::bindings::js::RootedReference;
|
use dom::bindings::js::RootedReference;
|
||||||
use dom::bindings::refcounted::Trusted;
|
use dom::bindings::refcounted::Trusted;
|
||||||
|
use dom::bindings::reflector::Reflectable;
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::element::{AttributeMutation, Element, ElementCreator};
|
use dom::element::{AttributeMutation, Element, ElementCreator};
|
||||||
|
@ -30,8 +31,8 @@ use html5ever::tree_builder::NextParserState;
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use js::jsval::UndefinedValue;
|
use js::jsval::UndefinedValue;
|
||||||
use net_traits::{AsyncResponseListener, AsyncResponseTarget, Metadata, NetworkError};
|
use net_traits::{FetchResponseListener, Metadata, NetworkError};
|
||||||
use net_traits::request::CORSSettings;
|
use net_traits::request::{CORSSettings, CredentialsMode, Destination, RequestInit, RequestMode, Type as RequestType};
|
||||||
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;
|
||||||
|
@ -153,8 +154,12 @@ struct ScriptContext {
|
||||||
status: Result<(), NetworkError>
|
status: Result<(), NetworkError>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsyncResponseListener for ScriptContext {
|
impl FetchResponseListener for ScriptContext {
|
||||||
fn headers_available(&mut self, metadata: Result<Metadata, NetworkError>) {
|
fn process_request_body(&mut self) {} // TODO(KiChjang): Perhaps add custom steps to perform fetch here?
|
||||||
|
|
||||||
|
fn process_request_eof(&mut self) {} // TODO(KiChjang): Perhaps add custom steps to perform fetch here?
|
||||||
|
|
||||||
|
fn process_response(&mut self, metadata: Result<Metadata, NetworkError>) {
|
||||||
self.metadata = metadata.ok();
|
self.metadata = metadata.ok();
|
||||||
|
|
||||||
let status_code = self.metadata.as_ref().and_then(|m| {
|
let status_code = self.metadata.as_ref().and_then(|m| {
|
||||||
|
@ -171,18 +176,17 @@ impl AsyncResponseListener for ScriptContext {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn data_available(&mut self, payload: Vec<u8>) {
|
fn process_response_chunk(&mut self, mut chunk: Vec<u8>) {
|
||||||
if self.status.is_ok() {
|
if self.status.is_ok() {
|
||||||
let mut payload = payload;
|
self.data.append(&mut chunk);
|
||||||
self.data.append(&mut payload);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
|
/// https://html.spec.whatwg.org/multipage/#fetch-a-classic-script
|
||||||
/// step 4-9
|
/// step 4-9
|
||||||
fn response_complete(&mut self, status: Result<(), NetworkError>) {
|
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
||||||
// Step 5.
|
// Step 5.
|
||||||
let load = status.and(self.status.clone()).map(|_| {
|
let load = response.and(self.status.clone()).map(|_| {
|
||||||
let metadata = self.metadata.take().unwrap();
|
let metadata = self.metadata.take().unwrap();
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
|
@ -212,8 +216,38 @@ 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,
|
fn fetch_a_classic_script(script: &HTMLScriptElement,
|
||||||
url: Url,
|
url: Url,
|
||||||
|
cors_setting: Option<CORSSettings>,
|
||||||
character_encoding: EncodingRef) {
|
character_encoding: EncodingRef) {
|
||||||
// TODO(#9186): use the fetch infrastructure.
|
let doc = document_from_node(script);
|
||||||
|
|
||||||
|
// Step 1, 2.
|
||||||
|
let request = RequestInit {
|
||||||
|
url: url.clone(),
|
||||||
|
type_: RequestType::Script,
|
||||||
|
destination: Destination::Script,
|
||||||
|
// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
|
||||||
|
// Step 1
|
||||||
|
mode: match cors_setting {
|
||||||
|
Some(_) => RequestMode::CORSMode,
|
||||||
|
None => RequestMode::NoCORS,
|
||||||
|
},
|
||||||
|
// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
|
||||||
|
// Step 3-4
|
||||||
|
credentials_mode: match cors_setting {
|
||||||
|
Some(CORSSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin,
|
||||||
|
_ => CredentialsMode::Include,
|
||||||
|
},
|
||||||
|
origin: doc.url().clone(),
|
||||||
|
pipeline_id: Some(script.global().r().pipeline_id()),
|
||||||
|
// FIXME: Set to true for now, discussion in https://github.com/whatwg/fetch/issues/381
|
||||||
|
same_origin_data: true,
|
||||||
|
referrer_url: Some(doc.url().clone()),
|
||||||
|
referrer_policy: doc.get_referrer_policy(),
|
||||||
|
.. RequestInit::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO: Step 3, Add custom steps to perform fetch
|
||||||
|
|
||||||
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,
|
character_encoding: character_encoding,
|
||||||
|
@ -231,14 +265,11 @@ fn fetch_a_classic_script(script: &HTMLScriptElement,
|
||||||
script_chan: doc.window().networking_task_source(),
|
script_chan: doc.window().networking_task_source(),
|
||||||
wrapper: Some(doc.window().get_runnable_wrapper()),
|
wrapper: Some(doc.window().get_runnable_wrapper()),
|
||||||
};
|
};
|
||||||
let response_target = AsyncResponseTarget {
|
|
||||||
sender: action_sender,
|
|
||||||
};
|
|
||||||
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
|
||||||
listener.notify_action(message.to().unwrap());
|
|
||||||
});
|
|
||||||
|
|
||||||
doc.load_async(LoadType::Script(url), response_target, None);
|
ROUTER.add_route(action_receiver.to_opaque(), box move |message| {
|
||||||
|
listener.notify_fetch(message.to().unwrap());
|
||||||
|
});
|
||||||
|
doc.fetch_async(LoadType::Script(url), request, action_sender, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLScriptElement {
|
impl HTMLScriptElement {
|
||||||
|
@ -324,7 +355,13 @@ impl HTMLScriptElement {
|
||||||
.and_then(|charset| encoding_from_whatwg_label(&charset.value()))
|
.and_then(|charset| encoding_from_whatwg_label(&charset.value()))
|
||||||
.unwrap_or_else(|| doc.encoding());
|
.unwrap_or_else(|| doc.encoding());
|
||||||
|
|
||||||
// TODO: Step 14: CORS.
|
// Step 14.
|
||||||
|
let cors_setting = match self.GetCrossOrigin() {
|
||||||
|
Some(ref s) if *s == "anonymous" => Some(CORSSettings::Anonymous),
|
||||||
|
Some(ref s) if *s == "use-credentials" => Some(CORSSettings::UseCredentials),
|
||||||
|
None => None,
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: Step 15: Nonce.
|
// TODO: Step 15: Nonce.
|
||||||
|
|
||||||
|
@ -356,7 +393,7 @@ impl HTMLScriptElement {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 18.6.
|
// Step 18.6.
|
||||||
fetch_a_classic_script(self, url, encoding);
|
fetch_a_classic_script(self, url, cors_setting, encoding);
|
||||||
|
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue