aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/script_task.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/script_task.rs')
-rw-r--r--components/script/script_task.rs65
1 files changed, 61 insertions, 4 deletions
diff --git a/components/script/script_task.rs b/components/script/script_task.rs
index d463d1d8107..fcf29605b80 100644
--- a/components/script/script_task.rs
+++ b/components/script/script_task.rs
@@ -95,6 +95,7 @@ use std::option::Option;
use std::ptr;
use std::rc::Rc;
use std::result::Result;
+use std::sync::atomic::{Ordering, AtomicBool};
use std::sync::mpsc::{Receiver, Select, Sender, channel};
use std::sync::{Arc, Mutex};
use string_cache::Atom;
@@ -158,7 +159,38 @@ impl InProgressLoad {
}
}
+/// Encapsulated state required to create cancellable runnables from non-script threads.
+pub struct RunnableWrapper {
+ pub cancelled: Arc<AtomicBool>,
+}
+
+impl RunnableWrapper {
+ pub fn wrap_runnable<T: Runnable + Send + 'static>(&self, runnable: T) -> Box<Runnable + Send> {
+ box CancellableRunnable {
+ cancelled: self.cancelled.clone(),
+ inner: box runnable,
+ }
+ }
+}
+
+/// A runnable that can be discarded by toggling a shared flag.
+pub struct CancellableRunnable<T: Runnable + Send> {
+ cancelled: Arc<AtomicBool>,
+ inner: Box<T>,
+}
+
+impl<T: Runnable + Send> Runnable for CancellableRunnable<T> {
+ fn is_cancelled(&self) -> bool {
+ self.cancelled.load(Ordering::Relaxed)
+ }
+
+ fn handler(self: Box<CancellableRunnable<T>>) {
+ self.inner.handler()
+ }
+}
+
pub trait Runnable {
+ fn is_cancelled(&self) -> bool { false }
fn handler(self: Box<Self>);
}
@@ -990,10 +1022,13 @@ impl ScriptTask {
runnable.handler(self),
MainThreadScriptMsg::DocumentLoadsComplete(id) =>
self.handle_loads_complete(id),
- MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) =>
+ MainThreadScriptMsg::Common(CommonScriptMsg::RunnableMsg(_, runnable)) => {
// The category of the runnable is ignored by the pattern, however
// it is still respected by profiling (see categorize_msg).
- runnable.handler(),
+ if !runnable.is_cancelled() {
+ runnable.handler()
+ }
+ }
MainThreadScriptMsg::Common(CommonScriptMsg::RefcountCleanup(addr)) =>
LiveDOMReferences::cleanup(addr),
MainThreadScriptMsg::Common(CommonScriptMsg::CollectReports(reports_chan)) =>
@@ -1636,10 +1671,32 @@ impl ScriptTask {
let is_javascript = incomplete.url.scheme == "javascript";
let parse_input = if is_javascript {
+ use url::percent_encoding::percent_decode_to;
+
+ // Turn javascript: URL into JS code to eval, according to the steps in
+ // https://html.spec.whatwg.org/multipage/#javascript-protocol
let _ar = JSAutoRequest::new(self.get_cx());
- let evalstr = incomplete.url.non_relative_scheme_data().unwrap();
+ let mut script_source_bytes = Vec::new();
+ // Start with the scheme data of the parsed URL (5.), while percent-decoding (8.)
+ percent_decode_to(incomplete.url.non_relative_scheme_data().unwrap().as_bytes(),
+ &mut script_source_bytes);
+ // Append question mark and query component, if any (6.), while percent-decoding (8.)
+ if let Some(ref query) = incomplete.url.query {
+ script_source_bytes.push(b'?');
+ percent_decode_to(query.as_bytes(), &mut script_source_bytes);
+ }
+ // Append number sign and fragment component if any (7.), while percent-decoding (8.)
+ if let Some(ref fragment) = incomplete.url.fragment {
+ script_source_bytes.push(b'#');
+ percent_decode_to(fragment.as_bytes(), &mut script_source_bytes);
+ }
+
+ // UTF-8 decode (9.)
+ let script_source = String::from_utf8_lossy(&script_source_bytes);
+
+ // Script source is ready to be evaluated (11.)
let mut jsval = RootedValue::new(self.get_cx(), UndefinedValue());
- window.evaluate_js_on_global_with_result(evalstr, jsval.handle_mut());
+ window.evaluate_js_on_global_with_result(&script_source, jsval.handle_mut());
let strval = DOMString::from_jsval(self.get_cx(), jsval.handle(),
StringificationBehavior::Empty);
strval.unwrap_or(DOMString::new())