Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make script load event asynchronous for internal scripts #4540

Merged
merged 3 commits into from Jan 16, 2015
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

@@ -15,6 +15,7 @@ use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast, NodeCas
use dom::bindings::codegen::InheritTypes::EventTargetCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JSRef, Temporary, OptionalRootable};
use dom::bindings::refcounted::Trusted;
use dom::document::Document;
use dom::element::{Element, AttributeHandlers, ElementCreator};
use dom::eventtarget::{EventTarget, EventTargetTypeId, EventTargetHelpers};
@@ -24,6 +25,7 @@ use dom::htmlelement::{HTMLElement, HTMLElementTypeId};
use dom::node::{Node, NodeHelpers, NodeTypeId, window_from_node, CloneChildrenFlag};
use dom::virtualmethods::VirtualMethods;
use dom::window::ScriptHelpers;
use script_task::{ScriptMsg, Runnable};

use encoding::all::UTF_8;
use encoding::types::{Encoding, DecoderTrap};
@@ -89,6 +91,9 @@ pub trait HTMLScriptElementHelpers {

/// Set the "already started" flag (<https://whatwg.org/html/#already-started>)
fn mark_already_started(self);

/// Dispatch load event.
fn dispatch_load_event(self);
}

/// Supported script types as defined by
@@ -112,6 +117,11 @@ static SCRIPT_JS_MIMES: StaticStringVec = &[
"text/x-javascript",
];

enum ScriptOrigin {
Internal,
External,
}

impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
fn prepare(self) {
// https://html.spec.whatwg.org/multipage/scripting.html#prepare-a-script
@@ -175,7 +185,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
let page = window.page();
let base_url = page.get_url();

let (source, url) = match element.get_attribute(ns!(""), &atom!("src")).root() {
let (origin, source, url) = match element.get_attribute(ns!(""), &atom!("src")).root() {
Some(src) => {
if src.r().Value().is_empty() {
// TODO: queue a task to fire a simple event named `error` at the element
@@ -191,7 +201,7 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
Ok((metadata, bytes)) => {
// TODO: use the charset from step 13.
let source = UTF_8.decode(bytes.as_slice(), DecoderTrap::Replace).unwrap();
(source, metadata.final_url)
(ScriptOrigin::External, source, metadata.final_url)
}
Err(_) => {
error!("error loading script {}", src.r().Value());
@@ -206,11 +216,28 @@ impl<'a> HTMLScriptElementHelpers for JSRef<'a, HTMLScriptElement> {
}
}
}
None => (text, base_url)
None => (ScriptOrigin::Internal, text, base_url)
};

window.evaluate_script_on_global_with_result(source.as_slice(), url.serialize().as_slice());

// https://html.spec.whatwg.org/multipage/scripting.html#execute-the-script-block
// step 2, substep 10
match origin {
ScriptOrigin::External => {
self.dispatch_load_event();
}
ScriptOrigin::Internal => {
let chan = window.script_chan();
let handler = Trusted::new(window.get_cx(), self, chan.clone());
chan.send(ScriptMsg::RunnableMsg(box handler));
}
}
}

fn dispatch_load_event(self) {
let window = window_from_node(self).root();
let window = window.r();
let event = Event::new(GlobalRef::Window(window),
"load".into_string(),
EventBubbles::DoesNotBubble,
@@ -331,3 +358,9 @@ impl<'a> HTMLScriptElementMethods for JSRef<'a, HTMLScriptElement> {
}
}

impl Runnable for Trusted<HTMLScriptElement> {
fn handler(self: Box<Trusted<HTMLScriptElement>>) {
let target = self.to_temporary().root();
target.r().dispatch_load_event();
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.