mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Auto merge of #12472 - KiChjang:use-fetch-in-script, r=jdm
Use fetch infrastructure to load external scripts Fixes #9186. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12472) <!-- Reviewable:end -->
This commit is contained in:
commit
f357afc94a
15 changed files with 364 additions and 353 deletions
|
@ -22,7 +22,7 @@ use hyper::status::StatusCode;
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
use mime_guess::guess_mime_type;
|
use mime_guess::guess_mime_type;
|
||||||
use msg::constellation_msg::ReferrerPolicy;
|
use msg::constellation_msg::ReferrerPolicy;
|
||||||
use net_traits::FetchTaskTarget;
|
use net_traits::{FetchTaskTarget, FetchMetadata};
|
||||||
use net_traits::request::{CacheMode, CredentialsMode, Destination};
|
use net_traits::request::{CacheMode, CredentialsMode, Destination};
|
||||||
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode, ResponseTainting};
|
use net_traits::request::{RedirectMode, Referrer, Request, RequestMode, ResponseTainting};
|
||||||
use net_traits::request::{Type, Origin, Window};
|
use net_traits::request::{Type, Origin, Window};
|
||||||
|
@ -361,13 +361,14 @@ fn main_fetch(request: Rc<Request>, cache: &mut CORSCache, cors_flag: bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if let Some(ref mut target) = *target {
|
} else if let Some(ref mut target) = *target {
|
||||||
if let ResponseBody::Done(ref vec) = *response.body.lock().unwrap() {
|
let body = response.body.lock().unwrap();
|
||||||
|
if let ResponseBody::Done(ref vec) = *body {
|
||||||
// in case there was no channel to wait for, the body was
|
// in case there was no channel to wait for, the body was
|
||||||
// obtained synchronously via basic_fetch for data/file/about/etc
|
// obtained synchronously via basic_fetch for data/file/about/etc
|
||||||
// We should still send the body across as a chunk
|
// We should still send the body across as a chunk
|
||||||
target.process_response_chunk(vec.clone());
|
target.process_response_chunk(vec.clone());
|
||||||
} else {
|
} else {
|
||||||
assert!(*response.body.lock().unwrap() == ResponseBody::Empty)
|
assert!(*body == ResponseBody::Empty)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,7 +982,10 @@ fn http_network_fetch(request: Rc<Request>,
|
||||||
|
|
||||||
// We're about to spawn a thread to be waited on here
|
// We're about to spawn a thread to be waited on here
|
||||||
*done_chan = Some(channel());
|
*done_chan = Some(channel());
|
||||||
let meta = response.metadata().expect("Response metadata should exist at this stage");
|
let meta = match response.metadata().expect("Response metadata should exist at this stage") {
|
||||||
|
FetchMetadata::Unfiltered(m) => m,
|
||||||
|
FetchMetadata::Filtered { unsafe_, .. } => unsafe_
|
||||||
|
};
|
||||||
let done_sender = done_chan.as_ref().map(|ch| ch.0.clone());
|
let done_sender = done_chan.as_ref().map(|ch| ch.0.clone());
|
||||||
let devtools_sender = devtools_chan.clone();
|
let devtools_sender = devtools_chan.clone();
|
||||||
let meta_status = meta.status.clone();
|
let meta_status = meta.status.clone();
|
||||||
|
|
|
@ -170,7 +170,7 @@ pub enum FetchResponseMsg {
|
||||||
ProcessRequestBody,
|
ProcessRequestBody,
|
||||||
ProcessRequestEOF,
|
ProcessRequestEOF,
|
||||||
// todo: send more info about the response (or perhaps the entire Response)
|
// todo: send more info about the response (or perhaps the entire Response)
|
||||||
ProcessResponse(Result<Metadata, NetworkError>),
|
ProcessResponse(Result<FetchMetadata, NetworkError>),
|
||||||
ProcessResponseChunk(Vec<u8>),
|
ProcessResponseChunk(Vec<u8>),
|
||||||
ProcessResponseEOF(Result<(), NetworkError>),
|
ProcessResponseEOF(Result<(), NetworkError>),
|
||||||
}
|
}
|
||||||
|
@ -200,10 +200,25 @@ pub trait FetchTaskTarget {
|
||||||
fn process_response_eof(&mut self, response: &Response);
|
fn process_response_eof(&mut self, response: &Response);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub enum FilteredMetadata {
|
||||||
|
Opaque,
|
||||||
|
Transparent(Metadata)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub enum FetchMetadata {
|
||||||
|
Unfiltered(Metadata),
|
||||||
|
Filtered {
|
||||||
|
filtered: FilteredMetadata,
|
||||||
|
unsafe_: Metadata
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub trait FetchResponseListener {
|
pub trait FetchResponseListener {
|
||||||
fn process_request_body(&mut self);
|
fn process_request_body(&mut self);
|
||||||
fn process_request_eof(&mut self);
|
fn process_request_eof(&mut self);
|
||||||
fn process_response(&mut self, metadata: Result<Metadata, NetworkError>);
|
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>);
|
||||||
fn process_response_chunk(&mut self, chunk: Vec<u8>);
|
fn process_response_chunk(&mut self, chunk: Vec<u8>);
|
||||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>);
|
fn process_response_eof(&mut self, response: Result<(), NetworkError>);
|
||||||
}
|
}
|
||||||
|
@ -520,6 +535,13 @@ impl PendingAsyncLoad {
|
||||||
let consumer = LoadConsumer::Listener(listener);
|
let consumer = LoadConsumer::Listener(listener);
|
||||||
self.core_resource_thread.send(CoreResourceMsg::Load(load_data, consumer, None)).unwrap();
|
self.core_resource_thread.send(CoreResourceMsg::Load(load_data, consumer, None)).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initiate the fetch associated with this pending load.
|
||||||
|
pub fn fetch_async(mut self, request: RequestInit, fetch_target: IpcSender<FetchResponseMsg>) {
|
||||||
|
self.guard.neuter();
|
||||||
|
|
||||||
|
self.core_resource_thread.send(CoreResourceMsg::Fetch(request, fetch_target)).unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Message sent in response to `Load`. Contains metadata, and a port
|
/// Message sent in response to `Load`. Contains metadata, and a port
|
||||||
|
|
|
@ -6,6 +6,7 @@ use hyper::header::Headers;
|
||||||
use hyper::method::Method;
|
use hyper::method::Method;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
|
use std::default::Default;
|
||||||
use std::mem::swap;
|
use std::mem::swap;
|
||||||
use url::{Origin as UrlOrigin, Url};
|
use url::{Origin as UrlOrigin, Url};
|
||||||
|
|
||||||
|
@ -20,7 +21,7 @@ pub enum Initiator {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A request [type](https://fetch.spec.whatwg.org/#concept-request-type)
|
/// A request [type](https://fetch.spec.whatwg.org/#concept-request-type)
|
||||||
#[derive(Copy, Clone, PartialEq, HeapSizeOf)]
|
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize, HeapSizeOf)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
None, Audio, Font, Image,
|
None, Audio, Font, Image,
|
||||||
Script, Style, Track, Video
|
Script, Style, Track, Video
|
||||||
|
@ -103,7 +104,7 @@ pub enum Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [CORS settings attribute](https://html.spec.whatwg.org/multipage/#attr-crossorigin-anonymous)
|
/// [CORS settings attribute](https://html.spec.whatwg.org/multipage/#attr-crossorigin-anonymous)
|
||||||
#[derive(Copy, Clone, PartialEq)]
|
#[derive(Copy, Clone, PartialEq, Serialize, Deserialize)]
|
||||||
pub enum CORSSettings {
|
pub enum CORSSettings {
|
||||||
Anonymous,
|
Anonymous,
|
||||||
UseCredentials
|
UseCredentials
|
||||||
|
@ -122,6 +123,7 @@ pub struct RequestInit {
|
||||||
pub same_origin_data: bool,
|
pub same_origin_data: bool,
|
||||||
pub body: Option<Vec<u8>>,
|
pub body: Option<Vec<u8>>,
|
||||||
// TODO: client object
|
// TODO: client object
|
||||||
|
pub type_: Type,
|
||||||
pub destination: Destination,
|
pub destination: Destination,
|
||||||
pub synchronous: bool,
|
pub synchronous: bool,
|
||||||
pub mode: RequestMode,
|
pub mode: RequestMode,
|
||||||
|
@ -137,6 +139,30 @@ pub struct RequestInit {
|
||||||
pub pipeline_id: Option<PipelineId>,
|
pub pipeline_id: Option<PipelineId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for RequestInit {
|
||||||
|
fn default() -> RequestInit {
|
||||||
|
RequestInit {
|
||||||
|
method: Method::Get,
|
||||||
|
url: Url::parse("about:blank").unwrap(),
|
||||||
|
headers: Headers::new(),
|
||||||
|
unsafe_request: false,
|
||||||
|
same_origin_data: false,
|
||||||
|
body: None,
|
||||||
|
type_: Type::None,
|
||||||
|
destination: Destination::None,
|
||||||
|
synchronous: false,
|
||||||
|
mode: RequestMode::NoCORS,
|
||||||
|
use_cors_preflight: false,
|
||||||
|
credentials_mode: CredentialsMode::Omit,
|
||||||
|
use_url_credentials: false,
|
||||||
|
origin: Url::parse("about:blank").unwrap(),
|
||||||
|
referrer_url: None,
|
||||||
|
referrer_policy: None,
|
||||||
|
pipeline_id: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A [Request](https://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
|
/// A [Request](https://fetch.spec.whatwg.org/#requests) as defined by the Fetch spec
|
||||||
#[derive(Clone, HeapSizeOf)]
|
#[derive(Clone, HeapSizeOf)]
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
|
@ -232,6 +258,7 @@ impl Request {
|
||||||
req.unsafe_request = init.unsafe_request;
|
req.unsafe_request = init.unsafe_request;
|
||||||
req.same_origin_data.set(init.same_origin_data);
|
req.same_origin_data.set(init.same_origin_data);
|
||||||
*req.body.borrow_mut() = init.body;
|
*req.body.borrow_mut() = init.body;
|
||||||
|
req.type_ = init.type_;
|
||||||
req.destination = init.destination;
|
req.destination = init.destination;
|
||||||
req.synchronous = init.synchronous;
|
req.synchronous = init.synchronous;
|
||||||
req.mode = init.mode;
|
req.mode = init.mode;
|
||||||
|
@ -248,56 +275,6 @@ impl Request {
|
||||||
req
|
req
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#create-a-potential-cors-request
|
|
||||||
pub fn potential_cors_request(url: Url,
|
|
||||||
cors_attribute_state: Option<CORSSettings>,
|
|
||||||
is_service_worker_global_scope: bool,
|
|
||||||
same_origin_fallback: bool,
|
|
||||||
pipeline_id: Option<PipelineId>) -> Request {
|
|
||||||
Request {
|
|
||||||
method: RefCell::new(Method::Get),
|
|
||||||
local_urls_only: false,
|
|
||||||
sandboxed_storage_area_urls: false,
|
|
||||||
headers: RefCell::new(Headers::new()),
|
|
||||||
unsafe_request: false,
|
|
||||||
body: RefCell::new(None),
|
|
||||||
is_service_worker_global_scope: is_service_worker_global_scope,
|
|
||||||
window: Cell::new(Window::Client),
|
|
||||||
keep_alive: Cell::new(false),
|
|
||||||
skip_service_worker: Cell::new(false),
|
|
||||||
initiator: Initiator::None,
|
|
||||||
type_: Type::None,
|
|
||||||
destination: Destination::None,
|
|
||||||
origin: RefCell::new(Origin::Client),
|
|
||||||
omit_origin_header: Cell::new(false),
|
|
||||||
same_origin_data: Cell::new(false),
|
|
||||||
referrer: RefCell::new(Referrer::Client),
|
|
||||||
referrer_policy: Cell::new(None),
|
|
||||||
synchronous: false,
|
|
||||||
// Step 1-2
|
|
||||||
mode: match cors_attribute_state {
|
|
||||||
Some(_) => RequestMode::CORSMode,
|
|
||||||
None if same_origin_fallback => RequestMode::SameOrigin,
|
|
||||||
None => RequestMode::NoCORS
|
|
||||||
},
|
|
||||||
use_cors_preflight: false,
|
|
||||||
// Step 3-4
|
|
||||||
credentials_mode: match cors_attribute_state {
|
|
||||||
Some(CORSSettings::Anonymous) => CredentialsMode::CredentialsSameOrigin,
|
|
||||||
_ => CredentialsMode::Include,
|
|
||||||
},
|
|
||||||
use_url_credentials: true,
|
|
||||||
cache_mode: Cell::new(CacheMode::Default),
|
|
||||||
redirect_mode: Cell::new(RedirectMode::Follow),
|
|
||||||
integrity_metadata: RefCell::new(String::new()),
|
|
||||||
url_list: RefCell::new(vec![url]),
|
|
||||||
redirect_count: Cell::new(0),
|
|
||||||
response_tainting: Cell::new(ResponseTainting::Basic),
|
|
||||||
pipeline_id: Cell::new(pipeline_id),
|
|
||||||
done: Cell::new(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn url(&self) -> Url {
|
pub fn url(&self) -> Url {
|
||||||
self.url_list.borrow().first().unwrap().clone()
|
self.url_list.borrow().first().unwrap().clone()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
//! The [Response](https://fetch.spec.whatwg.org/#responses) object
|
||||||
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
//! resulting from a [fetch operation](https://fetch.spec.whatwg.org/#concept-fetch)
|
||||||
use {Metadata, NetworkError};
|
use {FetchMetadata, FilteredMetadata, Metadata, NetworkError};
|
||||||
use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
|
use hyper::header::{AccessControlExposeHeaders, ContentType, Headers};
|
||||||
use hyper::status::StatusCode;
|
use hyper::status::StatusCode;
|
||||||
use hyper_serde::Serde;
|
use hyper_serde::Serde;
|
||||||
|
@ -225,24 +225,42 @@ impl Response {
|
||||||
response
|
response
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metadata(&self) -> Result<Metadata, NetworkError> {
|
pub fn metadata(&self) -> Result<FetchMetadata, NetworkError> {
|
||||||
let mut metadata = if let Some(ref url) = self.url {
|
fn init_metadata(response: &Response, url: &Url) -> Metadata {
|
||||||
Metadata::default(url.clone())
|
let mut metadata = Metadata::default(url.clone());
|
||||||
} else {
|
metadata.set_content_type(match response.headers.get() {
|
||||||
return Err(NetworkError::Internal("No url found in response".to_string()));
|
Some(&ContentType(ref mime)) => Some(mime),
|
||||||
|
None => None
|
||||||
|
});
|
||||||
|
metadata.headers = Some(Serde(response.headers.clone()));
|
||||||
|
metadata.status = response.raw_status.clone();
|
||||||
|
metadata.https_state = response.https_state;
|
||||||
|
metadata
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.is_network_error() {
|
if self.is_network_error() {
|
||||||
return Err(NetworkError::Internal("Cannot extract metadata from network error".to_string()));
|
return Err(NetworkError::Internal("Cannot extract metadata from network error".to_owned()));
|
||||||
}
|
}
|
||||||
|
|
||||||
metadata.set_content_type(match self.headers.get() {
|
let metadata = self.url.as_ref().map(|url| init_metadata(self, url));
|
||||||
Some(&ContentType(ref mime)) => Some(mime),
|
|
||||||
None => None
|
if let Some(ref response) = self.internal_response {
|
||||||
});
|
match response.url {
|
||||||
metadata.headers = Some(Serde(self.headers.clone()));
|
Some(ref url) => {
|
||||||
metadata.status = self.raw_status.clone();
|
let unsafe_metadata = init_metadata(response, url);
|
||||||
metadata.https_state = self.https_state;
|
|
||||||
return Ok(metadata);
|
Ok(FetchMetadata::Filtered {
|
||||||
|
filtered: match metadata {
|
||||||
|
Some(m) => FilteredMetadata::Transparent(m),
|
||||||
|
None => FilteredMetadata::Opaque
|
||||||
|
},
|
||||||
|
unsafe_: unsafe_metadata
|
||||||
|
})
|
||||||
|
}
|
||||||
|
None => Err(NetworkError::Internal("No url found in unsafe response".to_owned()))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(FetchMetadata::Unfiltered(metadata.unwrap()))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
|
|
||||||
use dom::bindings::js::JS;
|
use dom::bindings::js::JS;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
|
use ipc_channel::ipc::IpcSender;
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use net_traits::{PendingAsyncLoad, AsyncResponseTarget, LoadContext};
|
use net_traits::{AsyncResponseTarget, PendingAsyncLoad, LoadContext};
|
||||||
use net_traits::{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;
|
||||||
|
|
||||||
|
@ -148,6 +150,17 @@ impl DocumentLoader {
|
||||||
pending.load_async(listener)
|
pending.load_async(listener)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Initiate a new fetch.
|
||||||
|
pub fn fetch_async(&mut self,
|
||||||
|
load: LoadType,
|
||||||
|
request: RequestInit,
|
||||||
|
fetch_target: IpcSender<FetchResponseMsg>,
|
||||||
|
referrer: &Document,
|
||||||
|
referrer_policy: Option<ReferrerPolicy>) {
|
||||||
|
let pending = self.prepare_async_load(load, referrer, referrer_policy);
|
||||||
|
pending.fetch_async(request, fetch_target);
|
||||||
|
}
|
||||||
|
|
||||||
/// Mark an in-progress network request complete.
|
/// Mark an in-progress network request complete.
|
||||||
pub fn finish_load(&mut self, load: &LoadType) {
|
pub fn finish_load(&mut self, load: &LoadType) {
|
||||||
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
|
let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
|
||||||
|
|
|
@ -95,9 +95,10 @@ use js::jsapi::JS_GetRuntime;
|
||||||
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
|
use msg::constellation_msg::{ALT, CONTROL, SHIFT, SUPER};
|
||||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
use msg::constellation_msg::{Key, KeyModifiers, KeyState};
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use net_traits::{AsyncResponseTarget, IpcSend, PendingAsyncLoad};
|
use net_traits::{AsyncResponseTarget, FetchResponseMsg, IpcSend, PendingAsyncLoad};
|
||||||
use net_traits::CookieSource::NonHTTP;
|
use net_traits::CookieSource::NonHTTP;
|
||||||
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
|
use net_traits::CoreResourceMsg::{GetCookiesForUrl, SetCookiesForUrl};
|
||||||
|
use net_traits::request::RequestInit;
|
||||||
use net_traits::response::HttpsState;
|
use net_traits::response::HttpsState;
|
||||||
use num_traits::ToPrimitive;
|
use num_traits::ToPrimitive;
|
||||||
use origin::Origin;
|
use origin::Origin;
|
||||||
|
@ -1433,6 +1434,14 @@ impl Document {
|
||||||
loader.load_async(load, listener, self, referrer_policy);
|
loader.load_async(load, listener, self, referrer_policy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn fetch_async(&self, load: LoadType,
|
||||||
|
request: RequestInit,
|
||||||
|
fetch_target: IpcSender<FetchResponseMsg>,
|
||||||
|
referrer_policy: Option<ReferrerPolicy>) {
|
||||||
|
let mut loader = self.loader.borrow_mut();
|
||||||
|
loader.fetch_async(load, request, fetch_target, self, referrer_policy);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn finish_load(&self, load: LoadType) {
|
pub fn finish_load(&self, load: LoadType) {
|
||||||
debug!("Document got finish_load: {:?}", load);
|
debug!("Document got finish_load: {:?}", load);
|
||||||
// The parser might need the loader, so restrict the lifetime of the borrow.
|
// The parser might need the loader, so restrict the lifetime of the borrow.
|
||||||
|
@ -1520,7 +1529,7 @@ impl Document {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// https://html.spec.whatwg.org/multipage/#the-end step 5 and the latter parts of
|
/// https://html.spec.whatwg.org/multipage/#the-end step 5 and the latter parts of
|
||||||
/// https://html.spec.whatwg.org/multipage/#prepare-a-script 15.d and 15.e.
|
/// https://html.spec.whatwg.org/multipage/#prepare-a-script 20.d and 20.e.
|
||||||
pub fn process_asap_scripts(&self) {
|
pub fn process_asap_scripts(&self) {
|
||||||
// Execute the first in-order asap-executed script if it's ready, repeat as required.
|
// Execute the first in-order asap-executed script if it's ready, repeat as required.
|
||||||
// Re-borrowing the list for each step because it can also be borrowed under execute.
|
// Re-borrowing the list for each step because it can also be borrowed under execute.
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
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;
|
||||||
|
@ -14,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};
|
||||||
|
@ -29,7 +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::{FetchMetadata, FetchResponseListener, Metadata, NetworkError};
|
||||||
|
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;
|
||||||
|
@ -151,9 +154,17 @@ 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?
|
||||||
self.metadata = metadata.ok();
|
|
||||||
|
fn process_request_eof(&mut self) {} // TODO(KiChjang): Perhaps add custom steps to perform fetch here?
|
||||||
|
|
||||||
|
fn process_response(&mut self,
|
||||||
|
metadata: Result<FetchMetadata, NetworkError>) {
|
||||||
|
self.metadata = metadata.ok().map(|meta| match meta {
|
||||||
|
FetchMetadata::Unfiltered(m) => m,
|
||||||
|
FetchMetadata::Filtered { unsafe_, .. } => unsafe_
|
||||||
|
});
|
||||||
|
|
||||||
let status_code = self.metadata.as_ref().and_then(|m| {
|
let status_code = self.metadata.as_ref().and_then(|m| {
|
||||||
match m.status {
|
match m.status {
|
||||||
|
@ -169,18 +180,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.
|
||||||
|
@ -210,8 +220,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,
|
||||||
|
@ -229,14 +269,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 {
|
||||||
|
@ -322,7 +359,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.
|
||||||
|
|
||||||
|
@ -354,10 +397,11 @@ 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
|
||||||
},
|
},
|
||||||
|
// TODO: Step 19.
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -652,6 +696,32 @@ impl HTMLScriptElementMethods for HTMLScriptElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-script-htmlfor
|
// https://html.spec.whatwg.org/multipage/#dom-script-htmlfor
|
||||||
make_setter!(SetHtmlFor, "for");
|
make_setter!(SetHtmlFor, "for");
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-script-crossorigin
|
||||||
|
fn GetCrossOrigin(&self) -> Option<DOMString> {
|
||||||
|
let element = self.upcast::<Element>();
|
||||||
|
let attr = element.get_attribute(&ns!(), &atom!("crossorigin"));
|
||||||
|
|
||||||
|
if let Some(mut val) = attr.map(|v| v.Value()) {
|
||||||
|
val.make_ascii_lowercase();
|
||||||
|
if val == "anonymous" || val == "use-credentials" {
|
||||||
|
return Some(val);
|
||||||
|
}
|
||||||
|
return Some(DOMString::from("anonymous"));
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://html.spec.whatwg.org/multipage/#dom-script-crossorigin
|
||||||
|
fn SetCrossOrigin(&self, value: Option<DOMString>) {
|
||||||
|
let element = self.upcast::<Element>();
|
||||||
|
match value {
|
||||||
|
Some(val) => element.set_string_attribute(&atom!("crossorigin"), val),
|
||||||
|
None => {
|
||||||
|
element.remove_attribute(&ns!(), &atom!("crossorigin"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-script-text
|
// https://html.spec.whatwg.org/multipage/#dom-script-text
|
||||||
fn Text(&self) -> DOMString {
|
fn Text(&self) -> DOMString {
|
||||||
Node::collect_text_contents(self.upcast::<Node>().children())
|
Node::collect_text_contents(self.upcast::<Node>().children())
|
||||||
|
|
|
@ -10,7 +10,7 @@ interface HTMLScriptElement : HTMLElement {
|
||||||
attribute DOMString charset;
|
attribute DOMString charset;
|
||||||
// attribute boolean async;
|
// attribute boolean async;
|
||||||
attribute boolean defer;
|
attribute boolean defer;
|
||||||
// attribute DOMString crossOrigin;
|
attribute DOMString? crossOrigin;
|
||||||
[Pure]
|
[Pure]
|
||||||
attribute DOMString text;
|
attribute DOMString text;
|
||||||
|
|
||||||
|
|
|
@ -45,8 +45,8 @@ use js::jsapi::{JSContext, JS_ParseJSON};
|
||||||
use js::jsapi::JS_ClearPendingException;
|
use js::jsapi::JS_ClearPendingException;
|
||||||
use js::jsval::{JSVal, NullValue, UndefinedValue};
|
use js::jsval::{JSVal, NullValue, UndefinedValue};
|
||||||
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
use msg::constellation_msg::{PipelineId, ReferrerPolicy};
|
||||||
use net_traits::{CoreResourceThread, LoadOrigin};
|
use net_traits::{CoreResourceThread, FetchMetadata, FilteredMetadata};
|
||||||
use net_traits::{FetchResponseListener, Metadata, NetworkError};
|
use net_traits::{FetchResponseListener, LoadOrigin, NetworkError};
|
||||||
use net_traits::CoreResourceMsg::Fetch;
|
use net_traits::CoreResourceMsg::Fetch;
|
||||||
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
|
use net_traits::request::{CredentialsMode, Destination, RequestInit, RequestMode};
|
||||||
use net_traits::trim_http_whitespace;
|
use net_traits::trim_http_whitespace;
|
||||||
|
@ -219,35 +219,39 @@ impl XMLHttpRequest {
|
||||||
core_resource_thread: CoreResourceThread,
|
core_resource_thread: CoreResourceThread,
|
||||||
init: RequestInit) {
|
init: RequestInit) {
|
||||||
impl FetchResponseListener for XHRContext {
|
impl FetchResponseListener for XHRContext {
|
||||||
fn process_request_body(&mut self) {
|
fn process_request_body(&mut self) {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
fn process_request_eof(&mut self) {
|
|
||||||
// todo
|
fn process_request_eof(&mut self) {
|
||||||
}
|
// todo
|
||||||
fn process_response(&mut self, metadata: Result<Metadata, NetworkError>) {
|
}
|
||||||
let xhr = self.xhr.root();
|
|
||||||
let rv = xhr.process_headers_available(self.gen_id,
|
fn process_response(&mut self,
|
||||||
metadata);
|
metadata: Result<FetchMetadata, NetworkError>) {
|
||||||
if rv.is_err() {
|
let xhr = self.xhr.root();
|
||||||
*self.sync_status.borrow_mut() = Some(rv);
|
let rv = xhr.process_headers_available(self.gen_id, metadata);
|
||||||
}
|
if rv.is_err() {
|
||||||
}
|
|
||||||
fn process_response_chunk(&mut self, mut chunk: Vec<u8>) {
|
|
||||||
self.buf.borrow_mut().append(&mut chunk);
|
|
||||||
self.xhr.root().process_data_available(self.gen_id, self.buf.borrow().clone());
|
|
||||||
}
|
|
||||||
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
|
||||||
let rv = match response {
|
|
||||||
Ok(()) => {
|
|
||||||
self.xhr.root().process_response_complete(self.gen_id, Ok(()))
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
self.xhr.root().process_response_complete(self.gen_id, Err(e))
|
|
||||||
}
|
|
||||||
};
|
|
||||||
*self.sync_status.borrow_mut() = Some(rv);
|
*self.sync_status.borrow_mut() = Some(rv);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_response_chunk(&mut self, mut chunk: Vec<u8>) {
|
||||||
|
self.buf.borrow_mut().append(&mut chunk);
|
||||||
|
self.xhr.root().process_data_available(self.gen_id, self.buf.borrow().clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_response_eof(&mut self, response: Result<(), NetworkError>) {
|
||||||
|
let rv = match response {
|
||||||
|
Ok(()) => {
|
||||||
|
self.xhr.root().process_response_complete(self.gen_id, Ok(()))
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
self.xhr.root().process_response_complete(self.gen_id, Err(e))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*self.sync_status.borrow_mut() = Some(rv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PreInvoke for XHRContext {
|
impl PreInvoke for XHRContext {
|
||||||
|
@ -273,9 +277,11 @@ impl LoadOrigin for XMLHttpRequest {
|
||||||
fn referrer_url(&self) -> Option<Url> {
|
fn referrer_url(&self) -> Option<Url> {
|
||||||
return self.referrer_url.clone();
|
return self.referrer_url.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
fn referrer_policy(&self) -> Option<ReferrerPolicy> {
|
||||||
return self.referrer_policy;
|
return self.referrer_policy;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pipeline_id(&self) -> Option<PipelineId> {
|
fn pipeline_id(&self) -> Option<PipelineId> {
|
||||||
let global = self.global();
|
let global = self.global();
|
||||||
Some(global.r().pipeline_id())
|
Some(global.r().pipeline_id())
|
||||||
|
@ -596,6 +602,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
|
||||||
referrer_url: self.referrer_url.clone(),
|
referrer_url: self.referrer_url.clone(),
|
||||||
referrer_policy: self.referrer_policy.clone(),
|
referrer_policy: self.referrer_policy.clone(),
|
||||||
pipeline_id: self.pipeline_id(),
|
pipeline_id: self.pipeline_id(),
|
||||||
|
.. RequestInit::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
if bypass_cross_origin_check {
|
if bypass_cross_origin_check {
|
||||||
|
@ -862,10 +869,16 @@ impl XMLHttpRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_headers_available(&self,
|
fn process_headers_available(&self,
|
||||||
gen_id: GenerationId, metadata: Result<Metadata, NetworkError>)
|
gen_id: GenerationId, metadata: Result<FetchMetadata, NetworkError>)
|
||||||
-> Result<(), Error> {
|
-> Result<(), Error> {
|
||||||
let metadata = match metadata {
|
let metadata = match metadata {
|
||||||
Ok(meta) => meta,
|
Ok(meta) => match meta {
|
||||||
|
FetchMetadata::Unfiltered(m) => m,
|
||||||
|
FetchMetadata::Filtered { filtered, .. } => match filtered {
|
||||||
|
FilteredMetadata::Opaque => return Err(Error::Network),
|
||||||
|
FilteredMetadata::Transparent(m) => m
|
||||||
|
}
|
||||||
|
},
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network));
|
self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network));
|
||||||
return Err(Error::Network);
|
return Err(Error::Network);
|
||||||
|
|
|
@ -37505,6 +37505,18 @@
|
||||||
"path": "html/semantics/forms/the-input-element/minlength.html",
|
"path": "html/semantics/forms/the-input-element/minlength.html",
|
||||||
"url": "/html/semantics/forms/the-input-element/minlength.html"
|
"url": "/html/semantics/forms/the-input-element/minlength.html"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"html/semantics/scripting-1/the-script-element/script-crossorigin-network.html": [
|
||||||
|
{
|
||||||
|
"path": "html/semantics/scripting-1/the-script-element/script-crossorigin-network.html",
|
||||||
|
"url": "/html/semantics/scripting-1/the-script-element/script-crossorigin-network.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"html/semantics/scripting-1/the-script-element/script-crossorigin.html": [
|
||||||
|
{
|
||||||
|
"path": "html/semantics/scripting-1/the-script-element/script-crossorigin.html",
|
||||||
|
"url": "/html/semantics/scripting-1/the-script-element/script-crossorigin.html"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -4359,15 +4359,9 @@
|
||||||
[HTMLScriptElement interface: attribute async]
|
[HTMLScriptElement interface: attribute async]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLScriptElement interface: attribute crossOrigin]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLScriptElement interface: document.createElement("script") must inherit property "async" with the proper type (3)]
|
[HTMLScriptElement interface: document.createElement("script") must inherit property "async" with the proper type (3)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[HTMLScriptElement interface: document.createElement("script") must inherit property "crossOrigin" with the proper type (5)]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[HTMLCanvasElement interface: operation probablySupportsContext(DOMString,any)]
|
[HTMLCanvasElement interface: operation probablySupportsContext(DOMString,any)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1317,222 +1317,6 @@
|
||||||
[script.tabIndex: IDL set to -2147483648 followed by getAttribute()]
|
[script.tabIndex: IDL set to -2147483648 followed by getAttribute()]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[script.crossOrigin: typeof IDL attribute]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL get with DOM attribute unset]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to undefined followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to 7 followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to 1.5 followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to true followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to false followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to object "[object Object\]" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to NaN followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to Infinity followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to -Infinity followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "\\0" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to null followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to object "test-toString" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to object "test-valueOf" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "anonymous" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "xanonymous" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "anonymous\\0" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "nonymous" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "ANONYMOUS" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "use-credentials" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "xuse-credentials" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "use-credentials\\0" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "se-credentials" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: setAttribute() to "USE-CREDENTIALS" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to " \\0\\x01\\x02\\x03\\x04\\x05\\x06\\x07 \\b\\t\\n\\v\\f\\r\\x0e\\x0f \\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17 \\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f foo " followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to undefined followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to undefined followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to 7 followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to 7 followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to 1.5 followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to 1.5 followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to true followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to true followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to false followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to false followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to object "[object Object\]" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to object "[object Object\]" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to NaN followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to NaN followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to Infinity followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to Infinity followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to -Infinity followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to -Infinity followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "\\0" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "\\0" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to object "test-toString" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to object "test-toString" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to object "test-valueOf" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to object "test-valueOf" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "anonymous" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "xanonymous" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "xanonymous" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "anonymous\\0" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "anonymous\\0" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "nonymous" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "nonymous" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "ANONYMOUS" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "ANONYMOUS" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "use-credentials" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "xuse-credentials" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "xuse-credentials" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "use-credentials\\0" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "use-credentials\\0" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "se-credentials" followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "se-credentials" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to "USE-CREDENTIALS" followed by IDL get]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[script.itemScope: typeof IDL attribute]
|
[script.itemScope: typeof IDL attribute]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -12447,6 +12231,3 @@
|
||||||
[dialog.itemId: IDL set to object "test-valueOf" followed by IDL get]
|
[dialog.itemId: IDL set to object "test-valueOf" followed by IDL get]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[script.crossOrigin: IDL set to null followed by getAttribute()]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
def main(request, response):
|
||||||
|
headers = [("Content-Type", "text/javascript")]
|
||||||
|
milk = request.cookies.first("milk", None)
|
||||||
|
|
||||||
|
if milk is None:
|
||||||
|
return headers, "var included = false;"
|
||||||
|
elif milk.value == "yes":
|
||||||
|
return headers, "var included = true;"
|
||||||
|
|
||||||
|
return headers, "var included = false;"
|
|
@ -0,0 +1,49 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>HTMLScriptElement: crossorigin attribute network test</title>
|
||||||
|
<link rel="author" title="KiChjang" href="mailto:kungfukeith11@gmail.com">
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
var test1 = async_test(document.title + "1");
|
||||||
|
var test2 = async_test(document.title + "2");
|
||||||
|
var test3 = async_test(document.title + "3");
|
||||||
|
|
||||||
|
var script1 = document.createElement("script");
|
||||||
|
script1.src = "resources/cross-origin.py";
|
||||||
|
script1.crossOrigin = "use-credentials";
|
||||||
|
var script2 = document.createElement("script");
|
||||||
|
script2.src = "resources/cross-origin.py";
|
||||||
|
script2.crossOrigin = "gibberish";
|
||||||
|
var script3 = document.createElement("script");
|
||||||
|
script3.src = "resources/cross-origin.py";
|
||||||
|
|
||||||
|
document.cookie = "milk=yes";
|
||||||
|
document.body.appendChild(script1);
|
||||||
|
script1.onload = function() {
|
||||||
|
test1.step(function() {
|
||||||
|
assert_true(included, "credentials should be included in script request");
|
||||||
|
test1.done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
document.body.appendChild(script2);
|
||||||
|
script2.onload = function() {
|
||||||
|
test2.step(function() {
|
||||||
|
assert_true(included, "invalid values should default to include credentials due to response tainting");
|
||||||
|
test2.done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
document.body.appendChild(script3);
|
||||||
|
script3.onload = function() {
|
||||||
|
test3.step(function() {
|
||||||
|
assert_true(included, "missing value should default to include credentials");
|
||||||
|
test3.done();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
</body>
|
|
@ -0,0 +1,39 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>HTMLScriptElement: crossOrigin IDL attribute</title>
|
||||||
|
<link rel="author" title="KiChjang" href="mailto:kungfukeith11@gmail.com">
|
||||||
|
<link rel="help" href="https://html.spec.whatwg.org/multipage/#cors-settings-attribute">
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<script id="script1"></script>
|
||||||
|
<script id="script2" crossorigin=""></script>
|
||||||
|
<script id="script3" crossorigin="foo"></script>
|
||||||
|
<script id="script4" crossorigin="anonymous"></script>
|
||||||
|
<script id="script5" crossorigin="use-credentials"></script>
|
||||||
|
<script>
|
||||||
|
test(function() {
|
||||||
|
var script1 = document.getElementById("script1");
|
||||||
|
var script2 = document.getElementById("script2");
|
||||||
|
var script3 = document.getElementById("script3");
|
||||||
|
var script4 = document.getElementById("script4");
|
||||||
|
var script5 = document.getElementById("script5");
|
||||||
|
|
||||||
|
assert_equals(script1.crossOrigin, null, "Missing value default should be null");
|
||||||
|
assert_equals(script2.crossOrigin, "anonymous", "Empty string should map to anonymous");
|
||||||
|
assert_equals(script3.crossOrigin, "anonymous", "Invalid value default should be anonymous");
|
||||||
|
assert_equals(script4.crossOrigin, "anonymous", "anonymous should be parsed correctly");
|
||||||
|
assert_equals(script5.crossOrigin, "use-credentials", "use-credentials should be parsed correctly");
|
||||||
|
|
||||||
|
script1.crossOrigin = "bar";
|
||||||
|
assert_equals(script1.crossOrigin, "anonymous", "Setting to invalid value would default to anonymous");
|
||||||
|
|
||||||
|
script2.crossOrigin = null;
|
||||||
|
assert_equals(script2.crossOrigin, null, "Resetting to null should work");
|
||||||
|
|
||||||
|
script4.crossOrigin = "use-credentials";
|
||||||
|
assert_equals(script4.crossOrigin, "use-credentials", "Switching from anonymous to use-credentials should work");
|
||||||
|
|
||||||
|
script5.crossOrigin = "anonymous";
|
||||||
|
assert_equals(script5.crossOrigin, "anonymous", "Switching from use-credentials to anonymous should work");
|
||||||
|
}, document.title);
|
||||||
|
</script>
|
Loading…
Add table
Add a link
Reference in a new issue