diff options
Diffstat (limited to 'components/script/dom/servoparser/prefetch.rs')
-rw-r--r-- | components/script/dom/servoparser/prefetch.rs | 170 |
1 files changed, 92 insertions, 78 deletions
diff --git a/components/script/dom/servoparser/prefetch.rs b/components/script/dom/servoparser/prefetch.rs index 314cb3b97a1..b249c695ab2 100644 --- a/components/script/dom/servoparser/prefetch.rs +++ b/components/script/dom/servoparser/prefetch.rs @@ -9,6 +9,7 @@ use crate::dom::htmlimageelement::image_fetch_request; use crate::dom::htmlscriptelement::script_fetch_request; use crate::stylesheet_loader::stylesheet_fetch_request; use html5ever::buffer_queue::BufferQueue; +use html5ever::tokenizer::states::RawKind; use html5ever::tokenizer::Tag; use html5ever::tokenizer::TagKind; use html5ever::tokenizer::Token; @@ -63,8 +64,8 @@ impl Tokenizer { Tokenizer { inner } } - pub fn feed(&mut self, input: &mut BufferQueue) -> TokenizerResult<()> { - self.inner.feed(input) + pub fn feed(&mut self, input: &mut BufferQueue) { + while let TokenizerResult::Script(PrefetchHandle) = self.inner.feed(input) {} } } @@ -79,86 +80,99 @@ struct PrefetchSink { prefetching: bool, } +/// The prefetch tokenizer produces trivial results +struct PrefetchHandle; + impl TokenSink for PrefetchSink { - type Handle = (); - fn process_token(&mut self, token: Token, _line_number: u64) -> TokenSinkResult<()> { - if let Token::TagToken(ref tag) = token { - match (tag.kind, &tag.name) { - (TagKind::StartTag, local_name!("script")) if self.prefetching => { - if let Some(url) = self.get_url(tag, local_name!("src")) { - debug!("Prefetch script {}", url); - let cors_setting = self.get_cors_settings(tag, local_name!("crossorigin")); - let integrity_metadata = self - .get_attr(tag, local_name!("integrity")) - .map(|attr| String::from(&attr.value)) - .unwrap_or_default(); - let request = script_fetch_request( - url, - cors_setting, - self.origin.clone(), - self.pipeline_id, - self.referrer.clone(), - self.referrer_policy, - integrity_metadata, - ); - let _ = self - .resource_threads - .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); - } - // Don't prefetch inside script - self.prefetching = false; - }, - (TagKind::StartTag, local_name!("img")) if self.prefetching => { - if let Some(url) = self.get_url(tag, local_name!("src")) { - debug!("Prefetch {} {}", tag.name, url); - let request = - image_fetch_request(url, self.origin.clone(), self.pipeline_id); - let _ = self - .resource_threads - .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); - } - }, - (TagKind::StartTag, local_name!("link")) if self.prefetching => { - if let Some(rel) = self.get_attr(tag, local_name!("rel")) { - if rel.value.eq_ignore_ascii_case("stylesheet") { - if let Some(url) = self.get_url(tag, local_name!("href")) { - debug!("Prefetch {} {}", tag.name, url); - let cors_setting = - self.get_cors_settings(tag, local_name!("crossorigin")); - let integrity_metadata = self - .get_attr(tag, local_name!("integrity")) - .map(|attr| String::from(&attr.value)) - .unwrap_or_default(); - let request = stylesheet_fetch_request( - url, - cors_setting, - self.origin.clone(), - self.pipeline_id, - self.referrer.clone(), - self.referrer_policy, - integrity_metadata, - ); - let _ = self - .resource_threads - .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); - } + type Handle = PrefetchHandle; + fn process_token( + &mut self, + token: Token, + _line_number: u64, + ) -> TokenSinkResult<PrefetchHandle> { + let tag = match token { + Token::TagToken(ref tag) => tag, + _ => return TokenSinkResult::Continue, + }; + match (tag.kind, &tag.name) { + (TagKind::StartTag, local_name!("script")) if self.prefetching => { + if let Some(url) = self.get_url(tag, local_name!("src")) { + debug!("Prefetch script {}", url); + let cors_setting = self.get_cors_settings(tag, local_name!("crossorigin")); + let integrity_metadata = self + .get_attr(tag, local_name!("integrity")) + .map(|attr| String::from(&attr.value)) + .unwrap_or_default(); + let request = script_fetch_request( + url, + cors_setting, + self.origin.clone(), + self.pipeline_id, + self.referrer.clone(), + self.referrer_policy, + integrity_metadata, + ); + let _ = self + .resource_threads + .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); + } + TokenSinkResult::RawData(RawKind::ScriptData) + }, + (TagKind::StartTag, local_name!("img")) if self.prefetching => { + if let Some(url) = self.get_url(tag, local_name!("src")) { + debug!("Prefetch {} {}", tag.name, url); + let request = image_fetch_request(url, self.origin.clone(), self.pipeline_id); + let _ = self + .resource_threads + .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); + } + TokenSinkResult::Continue + }, + (TagKind::StartTag, local_name!("link")) if self.prefetching => { + if let Some(rel) = self.get_attr(tag, local_name!("rel")) { + if rel.value.eq_ignore_ascii_case("stylesheet") { + if let Some(url) = self.get_url(tag, local_name!("href")) { + debug!("Prefetch {} {}", tag.name, url); + let cors_setting = + self.get_cors_settings(tag, local_name!("crossorigin")); + let integrity_metadata = self + .get_attr(tag, local_name!("integrity")) + .map(|attr| String::from(&attr.value)) + .unwrap_or_default(); + let request = stylesheet_fetch_request( + url, + cors_setting, + self.origin.clone(), + self.pipeline_id, + self.referrer.clone(), + self.referrer_policy, + integrity_metadata, + ); + let _ = self + .resource_threads + .send(CoreResourceMsg::Fetch(request, FetchChannels::Prefetch)); } } - }, - (TagKind::EndTag, local_name!("script")) => { - // After the first script tag, the main parser is blocked, so it's worth prefetching. - self.prefetching = true; - }, - (TagKind::StartTag, local_name!("base")) => { - if let Some(url) = self.get_url(tag, local_name!("href")) { - debug!("Setting base {}", url); - self.base = url; - } - }, - _ => {}, - } + } + TokenSinkResult::Continue + }, + (TagKind::StartTag, local_name!("script")) => { + TokenSinkResult::RawData(RawKind::ScriptData) + }, + (TagKind::EndTag, local_name!("script")) => { + // After the first script tag, the main parser is blocked, so it's worth prefetching. + self.prefetching = true; + TokenSinkResult::Script(PrefetchHandle) + }, + (TagKind::StartTag, local_name!("base")) => { + if let Some(url) = self.get_url(tag, local_name!("href")) { + debug!("Setting base {}", url); + self.base = url; + } + TokenSinkResult::Continue + }, + _ => TokenSinkResult::Continue, } - TokenSinkResult::Continue } } |