mirror of
https://github.com/servo/servo.git
synced 2025-08-27 08:08:19 +01:00
Implement trusted types for setTimeout/setInterval (#38736)
I had a difficult time figuring out where the relevant steps had to be added. Therefore, I aggressively commented the spec steps so eventually I discovered where I should add them. Part of #36258 --------- Signed-off-by: Tim van der Lippe <tvanderlippe@gmail.com> Signed-off-by: Tim van der Lippe <TimvdLippe@users.noreply.github.com> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
a31235e52b
commit
4de9a9d100
16 changed files with 149 additions and 120 deletions
|
@ -2894,7 +2894,8 @@ impl GlobalScope {
|
|||
arguments: Vec<HandleValue>,
|
||||
timeout: Duration,
|
||||
is_interval: IsInterval,
|
||||
) -> i32 {
|
||||
can_gc: CanGc,
|
||||
) -> Fallible<i32> {
|
||||
self.timers().set_timeout_or_interval(
|
||||
self,
|
||||
callback,
|
||||
|
@ -2902,6 +2903,7 @@ impl GlobalScope {
|
|||
timeout,
|
||||
is_interval,
|
||||
self.timer_source(),
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -110,7 +110,9 @@ use crate::dom::bindings::codegen::Bindings::WindowBinding::{
|
|||
self, FrameRequestCallback, ScrollBehavior, ScrollToOptions, WindowMethods,
|
||||
WindowPostMessageOptions,
|
||||
};
|
||||
use crate::dom::bindings::codegen::UnionTypes::{RequestOrUSVString, StringOrFunction};
|
||||
use crate::dom::bindings::codegen::UnionTypes::{
|
||||
RequestOrUSVString, TrustedScriptOrString, TrustedScriptOrStringOrFunction,
|
||||
};
|
||||
use crate::dom::bindings::error::{Error, ErrorResult, Fallible};
|
||||
use crate::dom::bindings::inheritance::{Castable, ElementTypeId, HTMLElementTypeId, NodeTypeId};
|
||||
use crate::dom::bindings::num::Finite;
|
||||
|
@ -1098,23 +1100,30 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
.or_init(|| Navigator::new(self, CanGc::note()))
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/#dom-windowtimers-settimeout
|
||||
// https://html.spec.whatwg.org/multipage/#dom-settimeout
|
||||
fn SetTimeout(
|
||||
&self,
|
||||
_cx: JSContext,
|
||||
callback: StringOrFunction,
|
||||
callback: TrustedScriptOrStringOrFunction,
|
||||
timeout: i32,
|
||||
args: Vec<HandleValue>,
|
||||
) -> i32 {
|
||||
can_gc: CanGc,
|
||||
) -> Fallible<i32> {
|
||||
let callback = match callback {
|
||||
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
|
||||
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
TrustedScriptOrStringOrFunction::String(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::String(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::TrustedScript(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::TrustedScript(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
};
|
||||
self.as_global_scope().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::NonInterval,
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1127,19 +1136,26 @@ impl WindowMethods<crate::DomTypeHolder> for Window {
|
|||
fn SetInterval(
|
||||
&self,
|
||||
_cx: JSContext,
|
||||
callback: StringOrFunction,
|
||||
callback: TrustedScriptOrStringOrFunction,
|
||||
timeout: i32,
|
||||
args: Vec<HandleValue>,
|
||||
) -> i32 {
|
||||
can_gc: CanGc,
|
||||
) -> Fallible<i32> {
|
||||
let callback = match callback {
|
||||
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
|
||||
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
TrustedScriptOrStringOrFunction::String(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::String(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::TrustedScript(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::TrustedScript(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
};
|
||||
self.as_global_scope().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::Interval,
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,8 @@ use crate::dom::bindings::codegen::Bindings::VoidFunctionBinding::VoidFunction;
|
|||
use crate::dom::bindings::codegen::Bindings::WorkerBinding::WorkerType;
|
||||
use crate::dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
||||
use crate::dom::bindings::codegen::UnionTypes::{
|
||||
RequestOrUSVString, StringOrFunction, TrustedScriptURLOrUSVString,
|
||||
RequestOrUSVString, TrustedScriptOrString, TrustedScriptOrStringOrFunction,
|
||||
TrustedScriptURLOrUSVString,
|
||||
};
|
||||
use crate::dom::bindings::error::{Error, ErrorResult, Fallible, report_pending_exception};
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
|
@ -485,19 +486,26 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
|
|||
fn SetTimeout(
|
||||
&self,
|
||||
_cx: JSContext,
|
||||
callback: StringOrFunction,
|
||||
callback: TrustedScriptOrStringOrFunction,
|
||||
timeout: i32,
|
||||
args: Vec<HandleValue>,
|
||||
) -> i32 {
|
||||
can_gc: CanGc,
|
||||
) -> Fallible<i32> {
|
||||
let callback = match callback {
|
||||
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
|
||||
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
TrustedScriptOrStringOrFunction::String(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::String(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::TrustedScript(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::TrustedScript(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
};
|
||||
self.upcast::<GlobalScope>().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::NonInterval,
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -511,19 +519,26 @@ impl WorkerGlobalScopeMethods<crate::DomTypeHolder> for WorkerGlobalScope {
|
|||
fn SetInterval(
|
||||
&self,
|
||||
_cx: JSContext,
|
||||
callback: StringOrFunction,
|
||||
callback: TrustedScriptOrStringOrFunction,
|
||||
timeout: i32,
|
||||
args: Vec<HandleValue>,
|
||||
) -> i32 {
|
||||
can_gc: CanGc,
|
||||
) -> Fallible<i32> {
|
||||
let callback = match callback {
|
||||
StringOrFunction::String(i) => TimerCallback::StringTimerCallback(i),
|
||||
StringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
TrustedScriptOrStringOrFunction::String(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::String(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::TrustedScript(i) => {
|
||||
TimerCallback::StringTimerCallback(TrustedScriptOrString::TrustedScript(i))
|
||||
},
|
||||
TrustedScriptOrStringOrFunction::Function(i) => TimerCallback::FunctionTimerCallback(i),
|
||||
};
|
||||
self.upcast::<GlobalScope>().set_timeout_or_interval(
|
||||
callback,
|
||||
args,
|
||||
Duration::from_millis(timeout.max(0) as u64),
|
||||
IsInterval::Interval,
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@ use timers::{BoxedTimerCallback, TimerEventRequest};
|
|||
use crate::dom::bindings::callback::ExceptionHandling::Report;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||
use crate::dom::bindings::codegen::UnionTypes::TrustedScriptOrString;
|
||||
use crate::dom::bindings::error::Fallible;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::refcounted::Trusted;
|
||||
use crate::dom::bindings::reflector::{DomGlobal, DomObject};
|
||||
|
@ -32,6 +34,7 @@ use crate::dom::eventsource::EventSourceTimeoutCallback;
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
#[cfg(feature = "testbinding")]
|
||||
use crate::dom::testbinding::TestBindingCallback;
|
||||
use crate::dom::trustedscript::TrustedScript;
|
||||
use crate::dom::types::{Window, WorkerGlobalScope};
|
||||
use crate::dom::xmlhttprequest::XHRTimeoutCallback;
|
||||
use crate::script_module::ScriptFetchOptions;
|
||||
|
@ -185,7 +188,9 @@ impl OneshotTimers {
|
|||
}
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps>
|
||||
pub(crate) fn fire_timer(&self, id: TimerEventId, global: &GlobalScope, can_gc: CanGc) {
|
||||
// Step 9.2. If id does not exist in global's map of setTimeout and setInterval IDs, then abort these steps.
|
||||
let expected_id = self.expected_event_id.get();
|
||||
if expected_id != id {
|
||||
debug!(
|
||||
|
@ -278,6 +283,7 @@ impl OneshotTimers {
|
|||
self.schedule_timer_call();
|
||||
}
|
||||
|
||||
/// <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps>
|
||||
fn schedule_timer_call(&self) {
|
||||
if self.suspended_since.get().is_some() {
|
||||
// The timer will be scheduled when the pipeline is fully activated.
|
||||
|
@ -290,6 +296,8 @@ impl OneshotTimers {
|
|||
};
|
||||
|
||||
let expected_event_id = self.invalidate_expected_event_id();
|
||||
// Step 12. Let completionStep be an algorithm step which queues a global
|
||||
// task on the timer task source given global to run task.
|
||||
let callback = TimerListener {
|
||||
context: Trusted::new(&*self.global_scope),
|
||||
task_source: self
|
||||
|
@ -321,6 +329,7 @@ impl OneshotTimers {
|
|||
next_id
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn set_timeout_or_interval(
|
||||
&self,
|
||||
global: &GlobalScope,
|
||||
|
@ -329,7 +338,8 @@ impl OneshotTimers {
|
|||
timeout: Duration,
|
||||
is_interval: IsInterval,
|
||||
source: TimerSource,
|
||||
) -> i32 {
|
||||
can_gc: CanGc,
|
||||
) -> Fallible<i32> {
|
||||
self.js_timers.set_timeout_or_interval(
|
||||
global,
|
||||
callback,
|
||||
|
@ -337,6 +347,7 @@ impl OneshotTimers {
|
|||
timeout,
|
||||
is_interval,
|
||||
source,
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -388,9 +399,8 @@ pub(crate) enum IsInterval {
|
|||
NonInterval,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) enum TimerCallback {
|
||||
StringTimerCallback(DOMString),
|
||||
StringTimerCallback(TrustedScriptOrString),
|
||||
FunctionTimerCallback(Rc<Function>),
|
||||
}
|
||||
|
||||
|
@ -416,7 +426,8 @@ impl Default for JsTimers {
|
|||
}
|
||||
|
||||
impl JsTimers {
|
||||
// see https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
/// <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps>
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
||||
pub(crate) fn set_timeout_or_interval(
|
||||
&self,
|
||||
|
@ -426,16 +437,42 @@ impl JsTimers {
|
|||
timeout: Duration,
|
||||
is_interval: IsInterval,
|
||||
source: TimerSource,
|
||||
) -> i32 {
|
||||
can_gc: CanGc,
|
||||
) -> Fallible<i32> {
|
||||
let callback = match callback {
|
||||
TimerCallback::StringTimerCallback(code_str) => {
|
||||
TimerCallback::StringTimerCallback(trusted_script_or_string) => {
|
||||
// Step 9.6.1.1. Let globalName be "Window" if global is a Window object; "WorkerGlobalScope" otherwise.
|
||||
let global_name = if global.is::<Window>() {
|
||||
"Window"
|
||||
} else {
|
||||
"WorkerGlobalScope"
|
||||
};
|
||||
// Step 9.6.1.2. Let methodName be "setInterval" if repeat is true; "setTimeout" otherwise.
|
||||
let method_name = if is_interval == IsInterval::Interval {
|
||||
"setInterval"
|
||||
} else {
|
||||
"setTimeout"
|
||||
};
|
||||
// Step 9.6.1.3. Let sink be a concatenation of globalName, U+0020 SPACE, and methodName.
|
||||
let sink = format!("{} {}", global_name, method_name);
|
||||
// Step 9.6.1.4. Set handler to the result of invoking the
|
||||
// Get Trusted Type compliant string algorithm with TrustedScript, global, handler, sink, and "script".
|
||||
let code_str = TrustedScript::get_trusted_script_compliant_string(
|
||||
global,
|
||||
trusted_script_or_string,
|
||||
&sink,
|
||||
can_gc,
|
||||
)?;
|
||||
// Step 9.6.3. Perform EnsureCSPDoesNotBlockStringCompilation(realm, « », handler, handler, timer, « », handler).
|
||||
// If this throws an exception, catch it, report it for global, and abort these steps.
|
||||
if global
|
||||
.get_csp_list()
|
||||
.is_js_evaluation_allowed(global, code_str.as_ref())
|
||||
{
|
||||
// Step 9.6.2. Assert: handler is a string.
|
||||
InternalTimerCallback::StringTimerCallback(code_str)
|
||||
} else {
|
||||
return 0;
|
||||
return Ok(0);
|
||||
}
|
||||
},
|
||||
TimerCallback::FunctionTimerCallback(function) => {
|
||||
|
@ -448,6 +485,8 @@ impl JsTimers {
|
|||
for (i, item) in arguments.iter().enumerate() {
|
||||
args.get_mut(i).unwrap().set(item.get());
|
||||
}
|
||||
// Step 9.5. If handler is a Function, then invoke handler given arguments and "report",
|
||||
// and with callback this value set to thisArg.
|
||||
InternalTimerCallback::FunctionTimerCallback(
|
||||
function,
|
||||
Rc::new(args.into_boxed_slice()),
|
||||
|
@ -455,13 +494,15 @@ impl JsTimers {
|
|||
},
|
||||
};
|
||||
|
||||
// step 2
|
||||
// Step 2. If previousId was given, let id be previousId; otherwise,
|
||||
// let id be an implementation-defined integer that is greater than zero
|
||||
// and does not already exist in global's map of setTimeout and setInterval IDs.
|
||||
let JsTimerHandle(new_handle) = self.next_timer_handle.get();
|
||||
self.next_timer_handle.set(JsTimerHandle(new_handle + 1));
|
||||
|
||||
// step 3 as part of initialize_and_schedule below
|
||||
|
||||
// step 4
|
||||
// Step 3. If the surrounding agent's event loop's currently running task
|
||||
// is a task that was created by this algorithm, then let nesting level
|
||||
// be the task's timer nesting level. Otherwise, let nesting level be 0.
|
||||
let mut task = JsTimerTask {
|
||||
handle: JsTimerHandle(new_handle),
|
||||
source,
|
||||
|
@ -472,14 +513,13 @@ impl JsTimers {
|
|||
duration: Duration::ZERO,
|
||||
};
|
||||
|
||||
// step 5
|
||||
// Step 4. If timeout is less than 0, then set timeout to 0.
|
||||
task.duration = timeout.max(Duration::ZERO);
|
||||
|
||||
// step 3, 6-9, 11-14
|
||||
self.initialize_and_schedule(global, task);
|
||||
|
||||
// step 10
|
||||
new_handle
|
||||
// Step 15. Return id.
|
||||
Ok(new_handle)
|
||||
}
|
||||
|
||||
pub(crate) fn clear_timeout_or_interval(&self, global: &GlobalScope, handle: i32) {
|
||||
|
@ -506,24 +546,27 @@ impl JsTimers {
|
|||
}
|
||||
}
|
||||
|
||||
// see https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
/// <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps>
|
||||
fn initialize_and_schedule(&self, global: &GlobalScope, mut task: JsTimerTask) {
|
||||
let handle = task.handle;
|
||||
let mut active_timers = self.active_timers.borrow_mut();
|
||||
|
||||
// step 6
|
||||
// Step 3. If the surrounding agent's event loop's currently running task
|
||||
// is a task that was created by this algorithm, then let nesting level be
|
||||
// the task's timer nesting level. Otherwise, let nesting level be 0.
|
||||
let nesting_level = self.nesting_level.get();
|
||||
|
||||
// step 7, 13
|
||||
let duration = self.user_agent_pad(clamp_duration(nesting_level, task.duration));
|
||||
// step 8, 9
|
||||
// Step 10. Increment nesting level by one.
|
||||
// Step 11. Set task's timer nesting level to nesting level.
|
||||
task.nesting_level = nesting_level + 1;
|
||||
|
||||
// essentially step 11, 12, and 14
|
||||
// Step 13. Set uniqueHandle to the result of running steps after a timeout given global,
|
||||
// "setTimeout/setInterval", timeout, and completionStep.
|
||||
let callback = OneshotTimerCallback::JsTimer(task);
|
||||
let oneshot_handle = global.schedule_callback(callback, duration);
|
||||
|
||||
// step 3
|
||||
// Step 14. Set global's map of setTimeout and setInterval IDs[id] to uniqueHandle.
|
||||
let entry = active_timers
|
||||
.entry(handle)
|
||||
.or_insert(JsTimerEntry { oneshot_handle });
|
||||
|
@ -531,8 +574,9 @@ impl JsTimers {
|
|||
}
|
||||
}
|
||||
|
||||
// see step 7 of https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
/// Step 5 of <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps>
|
||||
fn clamp_duration(nesting_level: u32, unclamped: Duration) -> Duration {
|
||||
// Step 5. If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.
|
||||
let lower_bound_ms = if nesting_level > 5 { 4 } else { 0 };
|
||||
let lower_bound = Duration::from_millis(lower_bound_ms);
|
||||
lower_bound.max(unclamped)
|
||||
|
@ -541,30 +585,47 @@ fn clamp_duration(nesting_level: u32, unclamped: Duration) -> Duration {
|
|||
impl JsTimerTask {
|
||||
// see https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
pub(crate) fn invoke<T: DomObject>(self, this: &T, timers: &JsTimers, can_gc: CanGc) {
|
||||
// step 4.1 can be ignored, because we proactively prevent execution
|
||||
// step 9.2 can be ignored, because we proactively prevent execution
|
||||
// of this task when its scheduled execution is canceled.
|
||||
|
||||
// prep for step 6 in nested set_timeout_or_interval calls
|
||||
// prep for step ? in nested set_timeout_or_interval calls
|
||||
timers.nesting_level.set(self.nesting_level);
|
||||
|
||||
// step 4.2
|
||||
let was_user_interacting = ScriptThread::is_user_interacting();
|
||||
ScriptThread::set_user_interacting(self.is_user_interacting);
|
||||
match self.callback {
|
||||
InternalTimerCallback::StringTimerCallback(ref code_str) => {
|
||||
// Step 6.4. Let settings object be global's relevant settings object.
|
||||
// Step 6. Let realm be global's relevant realm.
|
||||
let global = this.global();
|
||||
// Step 7. Let initiating script be the active script.
|
||||
let cx = GlobalScope::get_cx();
|
||||
// Step 9.6.7. If initiating script is not null, then:
|
||||
rooted!(in(*cx) let mut rval = UndefinedValue());
|
||||
// Step 9.6.7.1. Set fetch options to a script fetch options whose cryptographic nonce
|
||||
// is initiating script's fetch options's cryptographic nonce,
|
||||
// integrity metadata is the empty string, parser metadata is "not-parser-inserted",
|
||||
// credentials mode is initiating script's fetch options's credentials mode,
|
||||
// referrer policy is initiating script's fetch options's referrer policy,
|
||||
// and fetch priority is "auto".
|
||||
// Step 9.6.8. Let script be the result of creating a classic script given handler,
|
||||
// settings object, base URL, and fetch options.
|
||||
// Step 9.6.9. Run the classic script script.
|
||||
//
|
||||
// FIXME(cybai): Use base url properly by saving private reference for timers (#27260)
|
||||
_ = global.evaluate_js_on_global_with_result(
|
||||
code_str,
|
||||
rval.handle_mut(),
|
||||
ScriptFetchOptions::default_classic_script(&global),
|
||||
// Step 9.6. Let base URL be settings object's API base URL.
|
||||
// Step 9.7.2. Set base URL to initiating script's base URL.
|
||||
global.api_base_url(),
|
||||
can_gc,
|
||||
Some(IntroductionType::DOM_TIMER),
|
||||
);
|
||||
},
|
||||
// Step 9.5. If handler is a Function, then invoke handler given arguments and
|
||||
// "report", and with callback this value set to thisArg.
|
||||
InternalTimerCallback::FunctionTimerCallback(ref function, ref arguments) => {
|
||||
let arguments = self.collect_heap_args(arguments);
|
||||
rooted!(in(*GlobalScope::get_cx()) let mut value: JSVal);
|
||||
|
@ -576,7 +637,9 @@ impl JsTimerTask {
|
|||
// reset nesting level (see above)
|
||||
timers.nesting_level.set(0);
|
||||
|
||||
// step 4.3
|
||||
// Step 9.9. If repeat is true, then perform the timer initialization steps again,
|
||||
// given global, handler, timeout, arguments, true, and id.
|
||||
//
|
||||
// Since we choose proactively prevent execution (see 4.1 above), we must only
|
||||
// reschedule repeating timers when they were not canceled as part of step 4.2.
|
||||
if self.is_interval == IsInterval::Interval &&
|
||||
|
@ -622,10 +685,10 @@ struct TimerListener {
|
|||
impl TimerListener {
|
||||
/// Handle a timer-event coming from the [`timers::TimerScheduler`]
|
||||
/// by queuing the appropriate task on the relevant event-loop.
|
||||
/// <https://html.spec.whatwg.org/multipage/#timer-initialisation-steps>
|
||||
fn handle(&self, event: TimerEvent) {
|
||||
let context = self.context.clone();
|
||||
// Step 18, queue a task,
|
||||
// https://html.spec.whatwg.org/multipage/#timer-initialisation-steps
|
||||
// Step 9. Let task be a task that runs the following substeps:
|
||||
self.task_source.queue(task!(timer_event: move || {
|
||||
let global = context.root();
|
||||
let TimerEvent(source, id) = event;
|
||||
|
@ -638,7 +701,6 @@ impl TimerListener {
|
|||
global.downcast::<Window>().expect("Worker timer delivered to window");
|
||||
},
|
||||
};
|
||||
// Step 7, substeps run in a task.
|
||||
global.fire_timer(id, CanGc::note());
|
||||
})
|
||||
);
|
||||
|
|
|
@ -651,7 +651,7 @@ DOMInterfaces = {
|
|||
},
|
||||
|
||||
'Window': {
|
||||
'canGc': ['Stop', 'Fetch', 'Stop', 'Fetch', 'Open', 'CreateImageBitmap', 'CreateImageBitmap_', 'TrustedTypes', 'WebdriverCallback', 'WebdriverException'],
|
||||
'canGc': ['Stop', 'Fetch', 'Stop', 'Fetch', 'Open', 'CreateImageBitmap', 'CreateImageBitmap_', 'SetInterval', 'SetTimeout', 'TrustedTypes', 'WebdriverCallback', 'WebdriverException'],
|
||||
'inRealms': ['Fetch', 'GetOpener', 'WebdriverCallback', 'WebdriverException'],
|
||||
'additionalTraits': ['crate::interfaces::WindowHelpers'],
|
||||
},
|
||||
|
@ -663,7 +663,7 @@ DOMInterfaces = {
|
|||
|
||||
'WorkerGlobalScope': {
|
||||
'inRealms': ['Fetch'],
|
||||
'canGc': ['Fetch', 'CreateImageBitmap', 'CreateImageBitmap_', 'ImportScripts', 'TrustedTypes'],
|
||||
'canGc': ['Fetch', 'CreateImageBitmap', 'CreateImageBitmap_', 'ImportScripts', 'SetInterval', 'SetTimeout', 'TrustedTypes'],
|
||||
},
|
||||
|
||||
'Worklet': {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
// https://html.spec.whatwg.org/multipage/#windoworworkerglobalscope
|
||||
|
||||
typedef (DOMString or Function) TimerHandler;
|
||||
typedef (TrustedScript or DOMString or Function) TimerHandler;
|
||||
|
||||
[Exposed=(Window,Worker)]
|
||||
interface mixin WindowOrWorkerGlobalScope {
|
||||
|
@ -15,9 +15,9 @@ interface mixin WindowOrWorkerGlobalScope {
|
|||
[Throws] DOMString atob(DOMString data);
|
||||
|
||||
// timers
|
||||
long setTimeout(TimerHandler handler, optional long timeout = 0, any... arguments);
|
||||
[Throws] long setTimeout(TimerHandler handler, optional long timeout = 0, any... arguments);
|
||||
undefined clearTimeout(optional long handle = 0);
|
||||
long setInterval(TimerHandler handler, optional long timeout = 0, any... arguments);
|
||||
[Throws] long setInterval(TimerHandler handler, optional long timeout = 0, any... arguments);
|
||||
undefined clearInterval(optional long handle = 0);
|
||||
|
||||
// microtask queuing
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
[DedicatedWorker-setTimeout-setInterval.html]
|
||||
expected: TIMEOUT
|
||||
[DedicatedWorkerGlobalScope.setTimeout assigned via default policy (successful Script transformation).]
|
||||
expected: TIMEOUT
|
||||
|
||||
[DedicatedWorkerGlobalScope.setInterval assigned via default policy (successful Script transformation).]
|
||||
expected: TIMEOUT
|
|
@ -1,7 +0,0 @@
|
|||
[Window-setTimeout-setInterval.html]
|
||||
expected: TIMEOUT
|
||||
[Window.setTimeout assigned via default policy (successful Script transformation).]
|
||||
expected: TIMEOUT
|
||||
|
||||
[Window.setInterval assigned via default policy (successful Script transformation).]
|
||||
expected: TIMEOUT
|
|
@ -1,12 +0,0 @@
|
|||
[block-string-assignment-to-DedicatedWorker-setTimeout-setInterval.html]
|
||||
[`DedicatedWorkerGlobalScope.setTimeout(string)` throws.]
|
||||
expected: FAIL
|
||||
|
||||
[`DedicatedWorkerGlobalScope.setTimeout(null)` throws.]
|
||||
expected: FAIL
|
||||
|
||||
[`DedicatedWorkerGlobalScope.setInterval(string)` throws.]
|
||||
expected: FAIL
|
||||
|
||||
[`DedicatedWorkerGlobalScope.setInterval(null)` throws.]
|
||||
expected: FAIL
|
|
@ -1,13 +0,0 @@
|
|||
[block-string-assignment-to-Window-setTimeout-setInterval.html]
|
||||
expected: ERROR
|
||||
[`Window.setTimeout(string)` throws.]
|
||||
expected: FAIL
|
||||
|
||||
[`Window.setTimeout(null)` throws.]
|
||||
expected: FAIL
|
||||
|
||||
[`Window.setInterval(string)` throws.]
|
||||
expected: FAIL
|
||||
|
||||
[`Window.setInterval(null)` throws.]
|
||||
expected: FAIL
|
|
@ -1,6 +0,0 @@
|
|||
[should-sink-type-mismatch-violation-be-blocked-by-csp-002-worker.html]
|
||||
[Checking reported violations for setTimeout(';;;;;') from DedicatedWorker]
|
||||
expected: FAIL
|
||||
|
||||
[Location of required-trusted-types-for violations.]
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[should-sink-type-mismatch-violation-be-blocked-by-csp-003.html]
|
||||
[Location of required-trusted-types-for violations.]
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[trusted-types-reporting-check-report-DedicatedWorker-sink-mismatch.html]
|
||||
[Test number of sent reports.]
|
||||
expected: FAIL
|
|
@ -1,3 +0,0 @@
|
|||
[trusted-types-reporting-check-report-Window-sink-mismatch.html]
|
||||
[Test number of sent reports.]
|
||||
expected: FAIL
|
|
@ -1,6 +0,0 @@
|
|||
[trusted-types-reporting-for-DedicatedWorker-setTimeout-setInterval.html]
|
||||
[Violation report for setTimeout with plain string.]
|
||||
expected: FAIL
|
||||
|
||||
[Violation report for setInterval with plain string.]
|
||||
expected: FAIL
|
|
@ -1,6 +0,0 @@
|
|||
[trusted-types-reporting-for-Window-setTimeout-setInterval.html]
|
||||
[Violation report for setTimeout with plain string.]
|
||||
expected: FAIL
|
||||
|
||||
[Violation report for setInterval with plain string.]
|
||||
expected: FAIL
|
Loading…
Add table
Add a link
Reference in a new issue