Various CanGc fixes (#33800)

* CanGc fix for pagetransitionevent

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for dom/node

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for gamepad

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for gpu

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for dom/element

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for xhr

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for dom/worker

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for rtcdatachannel

Signed-off-by: webbeef <me@webbeef.org>

* CanGc fix for rtcerror

Signed-off-by: webbeef <me@webbeef.org>

* Address review comments

Signed-off-by: webbeef <me@webbeef.org>

---------

Signed-off-by: webbeef <me@webbeef.org>
This commit is contained in:
webbeef 2024-10-10 20:53:39 -07:00 committed by GitHub
parent c00c6e728d
commit 2b71130a8a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
24 changed files with 168 additions and 119 deletions

View file

@ -693,7 +693,7 @@ impl Document {
self.activity.get() != DocumentActivity::Inactive self.activity.get() != DocumentActivity::Inactive
} }
pub fn set_activity(&self, activity: DocumentActivity) { pub fn set_activity(&self, activity: DocumentActivity, can_gc: CanGc) {
// This function should only be called on documents with a browsing context // This function should only be called on documents with a browsing context
assert!(self.has_browsing_context); assert!(self.has_browsing_context);
if activity == self.activity.get() { if activity == self.activity.get() {
@ -751,6 +751,7 @@ impl Document {
false, // bubbles false, // bubbles
false, // cancelable false, // cancelable
true, // persisted true, // persisted
can_gc,
); );
let event = event.upcast::<Event>(); let event = event.upcast::<Event>();
event.set_trusted(true); event.set_trusted(true);
@ -2256,7 +2257,7 @@ impl Document {
} }
// https://html.spec.whatwg.org/multipage/#unload-a-document // https://html.spec.whatwg.org/multipage/#unload-a-document
pub fn unload(&self, recursive_flag: bool) { pub fn unload(&self, recursive_flag: bool, can_gc: CanGc) {
// TODO: Step 1, increase the event loop's termination nesting level by 1. // TODO: Step 1, increase the event loop's termination nesting level by 1.
// Step 2 // Step 2
self.incr_ignore_opens_during_unload_counter(); self.incr_ignore_opens_during_unload_counter();
@ -2272,6 +2273,7 @@ impl Document {
false, // bubbles false, // bubbles
false, // cancelable false, // cancelable
self.salvageable.get(), // persisted self.salvageable.get(), // persisted
can_gc,
); );
let event = event.upcast::<Event>(); let event = event.upcast::<Event>();
event.set_trusted(true); event.set_trusted(true);
@ -2286,7 +2288,7 @@ impl Document {
atom!("unload"), atom!("unload"),
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::Cancelable, EventCancelable::Cancelable,
CanGc::note(), can_gc,
); );
event.set_trusted(true); event.set_trusted(true);
let event_target = self.window.upcast::<EventTarget>(); let event_target = self.window.upcast::<EventTarget>();
@ -2305,7 +2307,7 @@ impl Document {
for iframe in self.iter_iframes() { for iframe in self.iter_iframes() {
// TODO: handle the case of cross origin iframes. // TODO: handle the case of cross origin iframes.
let document = document_from_node(&*iframe); let document = document_from_node(&*iframe);
document.unload(true); document.unload(true, can_gc);
if !document.salvageable() { if !document.salvageable() {
self.salvageable.set(false); self.salvageable.set(false);
} }
@ -2422,6 +2424,7 @@ impl Document {
false, // bubbles false, // bubbles
false, // cancelable false, // cancelable
false, // persisted false, // persisted
can_gc,
); );
let event = event.upcast::<Event>(); let event = event.upcast::<Event>();
event.set_trusted(true); event.set_trusted(true);

View file

@ -1896,7 +1896,7 @@ impl Element {
// See https://github.com/w3c/DOM-Parsing/issues/61. // See https://github.com/w3c/DOM-Parsing/issues/61.
let context_document = { let context_document = {
if let Some(template) = self.downcast::<HTMLTemplateElement>() { if let Some(template) = self.downcast::<HTMLTemplateElement>() {
template.Content(CanGc::note()).upcast::<Node>().owner_doc() template.Content(can_gc).upcast::<Node>().owner_doc()
} else { } else {
document_from_node(self) document_from_node(self)
} }
@ -2674,7 +2674,7 @@ impl ElementMethods for Element {
} }
// Step 1. // Step 1.
let frag = self.parse_fragment(value, CanGc::note())?; let frag = self.parse_fragment(value, can_gc)?;
Node::replace_all(Some(frag.upcast()), &target); Node::replace_all(Some(frag.upcast()), &target);
Ok(()) Ok(())
@ -2723,7 +2723,7 @@ impl ElementMethods for Element {
}; };
// Step 5. // Step 5.
let frag = parent.parse_fragment(value, CanGc::note())?; let frag = parent.parse_fragment(value, can_gc)?;
// Step 6. // Step 6.
context_parent.ReplaceChild(frag.upcast(), context_node)?; context_parent.ReplaceChild(frag.upcast(), context_node)?;
Ok(()) Ok(())

View file

@ -98,6 +98,7 @@ impl Gamepad {
button_bounds: (f64, f64), button_bounds: (f64, f64),
supported_haptic_effects: GamepadSupportedHapticEffects, supported_haptic_effects: GamepadSupportedHapticEffects,
xr: bool, xr: bool,
can_gc: CanGc,
) -> DomRoot<Gamepad> { ) -> DomRoot<Gamepad> {
Self::new_with_proto( Self::new_with_proto(
global, global,
@ -108,6 +109,7 @@ impl Gamepad {
button_bounds, button_bounds,
supported_haptic_effects, supported_haptic_effects,
xr, xr,
can_gc,
) )
} }
@ -126,6 +128,7 @@ impl Gamepad {
button_bounds: (f64, f64), button_bounds: (f64, f64),
supported_haptic_effects: GamepadSupportedHapticEffects, supported_haptic_effects: GamepadSupportedHapticEffects,
xr: bool, xr: bool,
can_gc: CanGc,
) -> DomRoot<Gamepad> { ) -> DomRoot<Gamepad> {
let button_list = GamepadButtonList::init_buttons(global); let button_list = GamepadButtonList::init_buttons(global);
let vibration_actuator = let vibration_actuator =
@ -148,7 +151,7 @@ impl Gamepad {
)), )),
global, global,
None, None,
CanGc::note(), can_gc,
); );
gamepad.init_axes(); gamepad.init_axes();
gamepad gamepad

View file

@ -532,7 +532,7 @@ impl TimerListener {
}, },
}; };
// Step 7, substeps run in a task. // Step 7, substeps run in a task.
global.fire_timer(id); global.fire_timer(id, CanGc::note());
}), }),
&self.canceller, &self.canceller,
); );
@ -2893,8 +2893,8 @@ impl GlobalScope {
} }
} }
pub fn fire_timer(&self, handle: TimerEventId) { pub fn fire_timer(&self, handle: TimerEventId, can_gc: CanGc) {
self.timers.fire_timer(handle, self); self.timers.fire_timer(handle, self, can_gc);
} }
pub fn resume(&self) { pub fn resume(&self) {
@ -3208,7 +3208,7 @@ impl GlobalScope {
} }
} }
pub fn handle_gamepad_event(&self, gamepad_event: GamepadEvent) { pub fn handle_gamepad_event(&self, gamepad_event: GamepadEvent, can_gc: CanGc) {
match gamepad_event { match gamepad_event {
GamepadEvent::Connected(index, name, bounds, supported_haptic_effects) => { GamepadEvent::Connected(index, name, bounds, supported_haptic_effects) => {
self.handle_gamepad_connect( self.handle_gamepad_connect(
@ -3217,6 +3217,7 @@ impl GlobalScope {
bounds.axis_bounds, bounds.axis_bounds,
bounds.button_bounds, bounds.button_bounds,
supported_haptic_effects, supported_haptic_effects,
can_gc,
); );
}, },
GamepadEvent::Disconnected(index) => { GamepadEvent::Disconnected(index) => {
@ -3239,6 +3240,7 @@ impl GlobalScope {
axis_bounds: (f64, f64), axis_bounds: (f64, f64),
button_bounds: (f64, f64), button_bounds: (f64, f64),
supported_haptic_effects: GamepadSupportedHapticEffects, supported_haptic_effects: GamepadSupportedHapticEffects,
can_gc: CanGc,
) { ) {
// TODO: 2. If document is not null and is not allowed to use the "gamepad" permission, // TODO: 2. If document is not null and is not allowed to use the "gamepad" permission,
// then abort these steps. // then abort these steps.
@ -3259,7 +3261,8 @@ impl GlobalScope {
axis_bounds, axis_bounds,
button_bounds, button_bounds,
supported_haptic_effects, supported_haptic_effects,
false false,
can_gc,
); );
navigator.set_gamepad(selected_index as usize, &gamepad); navigator.set_gamepad(selected_index as usize, &gamepad);
} }

View file

@ -25,6 +25,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::gpuadapter::GPUAdapter; use crate::dom::gpuadapter::GPUAdapter;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
use crate::task_source::{TaskSource, TaskSourceName}; use crate::task_source::{TaskSource, TaskSourceName};
#[dom_struct] #[dom_struct]
@ -46,7 +47,7 @@ impl GPU {
} }
pub trait AsyncWGPUListener { pub trait AsyncWGPUListener {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>); fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, can_gc: CanGc);
} }
struct WGPUResponse<T: AsyncWGPUListener + DomObject> { struct WGPUResponse<T: AsyncWGPUListener + DomObject> {
@ -56,9 +57,11 @@ struct WGPUResponse<T: AsyncWGPUListener + DomObject> {
impl<T: AsyncWGPUListener + DomObject> WGPUResponse<T> { impl<T: AsyncWGPUListener + DomObject> WGPUResponse<T> {
#[allow(crown::unrooted_must_root)] #[allow(crown::unrooted_must_root)]
fn response(self, response: WebGPUResponse) { fn response(self, response: WebGPUResponse, can_gc: CanGc) {
let promise = self.trusted.root(); let promise = self.trusted.root();
self.receiver.root().handle_response(response, &promise); self.receiver
.root()
.handle_response(response, &promise, can_gc);
} }
} }
@ -89,7 +92,7 @@ pub fn response_async<T: AsyncWGPUListener + DomObject + 'static>(
}; };
let result = task_source.queue_with_canceller( let result = task_source.queue_with_canceller(
task!(process_webgpu_task: move|| { task!(process_webgpu_task: move|| {
context.response(message.to().unwrap()); context.response(message.to().unwrap(), CanGc::note());
}), }),
&canceller, &canceller,
); );
@ -140,7 +143,7 @@ impl GPUMethods for GPU {
} }
impl AsyncWGPUListener for GPU { impl AsyncWGPUListener for GPU {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, _can_gc: CanGc) {
match response { match response {
WebGPUResponse::Adapter(Ok(adapter)) => { WebGPUResponse::Adapter(Ok(adapter)) => {
let adapter = GPUAdapter::new( let adapter = GPUAdapter::new(

View file

@ -27,6 +27,7 @@ use crate::dom::gpudevice::GPUDevice;
use crate::dom::gpusupportedfeatures::gpu_to_wgt_feature; use crate::dom::gpusupportedfeatures::gpu_to_wgt_feature;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct GPUAdapter { pub struct GPUAdapter {
@ -194,7 +195,7 @@ impl GPUAdapterMethods for GPUAdapter {
} }
impl AsyncWGPUListener for GPUAdapter { impl AsyncWGPUListener for GPUAdapter {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, _can_gc: CanGc) {
match response { match response {
WebGPUResponse::Device((device_id, queue_id, Ok(descriptor))) => { WebGPUResponse::Device((device_id, queue_id, Ok(descriptor))) => {
let device = GPUDevice::new( let device = GPUDevice::new(

View file

@ -29,7 +29,7 @@ use crate::dom::gpu::{response_async, AsyncWGPUListener};
use crate::dom::gpudevice::GPUDevice; use crate::dom::gpudevice::GPUDevice;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::JSContext; use crate::script_runtime::{CanGc, JSContext};
#[derive(JSTraceable, MallocSizeOf)] #[derive(JSTraceable, MallocSizeOf)]
pub struct ActiveBufferMapping { pub struct ActiveBufferMapping {
@ -413,7 +413,7 @@ impl GPUBuffer {
impl AsyncWGPUListener for GPUBuffer { impl AsyncWGPUListener for GPUBuffer {
#[allow(unsafe_code)] #[allow(unsafe_code)]
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, _can_gc: CanGc) {
match response { match response {
WebGPUResponse::BufferMapAsync(Ok(mapping)) => self.map_success(promise, mapping), WebGPUResponse::BufferMapAsync(Ok(mapping)) => self.map_success(promise, mapping),
WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise), WebGPUResponse::BufferMapAsync(Err(_)) => self.map_failure(promise),

View file

@ -31,16 +31,19 @@ impl GPUCompilationInfo {
} }
#[allow(dead_code)] #[allow(dead_code)]
pub fn new(global: &GlobalScope, msg: Vec<DomRoot<GPUCompilationMessage>>) -> DomRoot<Self> { pub fn new(
reflect_dom_object_with_proto( global: &GlobalScope,
Box::new(Self::new_inherited(msg)), msg: Vec<DomRoot<GPUCompilationMessage>>,
global, can_gc: CanGc,
None, ) -> DomRoot<Self> {
CanGc::note(), reflect_dom_object_with_proto(Box::new(Self::new_inherited(msg)), global, None, can_gc)
)
} }
pub fn from(global: &GlobalScope, error: Option<ShaderCompilationInfo>) -> DomRoot<Self> { pub fn from(
global: &GlobalScope,
error: Option<ShaderCompilationInfo>,
can_gc: CanGc,
) -> DomRoot<Self> {
Self::new( Self::new(
global, global,
if let Some(error) = error { if let Some(error) = error {
@ -48,6 +51,7 @@ impl GPUCompilationInfo {
} else { } else {
Vec::new() Vec::new()
}, },
can_gc,
) )
} }
} }

View file

@ -561,13 +561,13 @@ impl GPUDeviceMethods for GPUDevice {
} }
impl AsyncWGPUListener for GPUDevice { impl AsyncWGPUListener for GPUDevice {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, can_gc: CanGc) {
match response { match response {
WebGPUResponse::PoppedErrorScope(result) => match result { WebGPUResponse::PoppedErrorScope(result) => match result {
Ok(None) | Err(PopError::Lost) => promise.resolve_native(&None::<Option<GPUError>>), Ok(None) | Err(PopError::Lost) => promise.resolve_native(&None::<Option<GPUError>>),
Err(PopError::Empty) => promise.reject_error(Error::Operation), Err(PopError::Empty) => promise.reject_error(Error::Operation),
Ok(Some(error)) => { Ok(Some(error)) => {
let error = GPUError::from_error(&self.global(), error, CanGc::note()); let error = GPUError::from_error(&self.global(), error, can_gc);
promise.resolve_native(&error); promise.resolve_native(&error);
}, },
}, },

View file

@ -24,6 +24,7 @@ use crate::dom::gpubuffer::GPUBuffer;
use crate::dom::gpucommandbuffer::GPUCommandBuffer; use crate::dom::gpucommandbuffer::GPUCommandBuffer;
use crate::dom::gpudevice::GPUDevice; use crate::dom::gpudevice::GPUDevice;
use crate::dom::promise::Promise; use crate::dom::promise::Promise;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct GPUQueue { pub struct GPUQueue {
@ -206,7 +207,12 @@ impl GPUQueueMethods for GPUQueue {
} }
impl AsyncWGPUListener for GPUQueue { impl AsyncWGPUListener for GPUQueue {
fn handle_response(&self, response: webgpu::WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(
&self,
response: webgpu::WebGPUResponse,
promise: &Rc<Promise>,
_can_gc: CanGc,
) {
match response { match response {
WebGPUResponse::SubmittedWorkDone => { WebGPUResponse::SubmittedWorkDone => {
promise.resolve_native(&()); promise.resolve_native(&());

View file

@ -22,6 +22,7 @@ use crate::dom::bindings::trace::RootedTraceableBox;
use crate::dom::globalscope::GlobalScope; use crate::dom::globalscope::GlobalScope;
use crate::dom::gpu::response_async; use crate::dom::gpu::response_async;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct GPUShaderModule { pub struct GPUShaderModule {
@ -125,10 +126,10 @@ impl GPUShaderModuleMethods for GPUShaderModule {
} }
impl AsyncWGPUListener for GPUShaderModule { impl AsyncWGPUListener for GPUShaderModule {
fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>) { fn handle_response(&self, response: WebGPUResponse, promise: &Rc<Promise>, can_gc: CanGc) {
match response { match response {
WebGPUResponse::CompilationInfo(info) => { WebGPUResponse::CompilationInfo(info) => {
let info = GPUCompilationInfo::from(&self.global(), info); let info = GPUCompilationInfo::from(&self.global(), info, can_gc);
promise.resolve_native(&info); promise.resolve_native(&info);
}, },
_ => unreachable!("Wrong response received on AsyncWGPUListener for GPUShaderModule"), _ => unreachable!("Wrong response received on AsyncWGPUListener for GPUShaderModule"),

View file

@ -2298,7 +2298,7 @@ impl Node {
None, None,
document.status_code(), document.status_code(),
Default::default(), Default::default(),
CanGc::note(), can_gc,
); );
DomRoot::upcast::<Node>(document) DomRoot::upcast::<Node>(document)
}, },
@ -2360,8 +2360,7 @@ impl Node {
// Step 6. // Step 6.
if clone_children == CloneChildrenFlag::CloneChildren { if clone_children == CloneChildrenFlag::CloneChildren {
for child in node.children() { for child in node.children() {
let child_copy = let child_copy = Node::clone(&child, Some(&document), clone_children, can_gc);
Node::clone(&child, Some(&document), clone_children, CanGc::note());
let _inserted_node = Node::pre_insert(&child_copy, &copy, None); let _inserted_node = Node::pre_insert(&child_copy, &copy, None);
} }
} }

View file

@ -54,16 +54,9 @@ impl PageTransitionEvent {
bubbles: bool, bubbles: bool,
cancelable: bool, cancelable: bool,
persisted: bool, persisted: bool,
can_gc: CanGc,
) -> DomRoot<PageTransitionEvent> { ) -> DomRoot<PageTransitionEvent> {
Self::new_with_proto( Self::new_with_proto(window, None, type_, bubbles, cancelable, persisted, can_gc)
window,
None,
type_,
bubbles,
cancelable,
persisted,
CanGc::note(),
)
} }
fn new_with_proto( fn new_with_proto(

View file

@ -111,24 +111,24 @@ impl RTCDataChannel {
rtc_data_channel rtc_data_channel
} }
pub fn on_open(&self) { pub fn on_open(&self, can_gc: CanGc) {
let event = Event::new( let event = Event::new(
&self.global(), &self.global(),
atom!("open"), atom!("open"),
EventBubbles::DoesNotBubble, EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable, EventCancelable::NotCancelable,
CanGc::note(), can_gc,
); );
event.upcast::<Event>().fire(self.upcast()); event.upcast::<Event>().fire(self.upcast());
} }
pub fn on_close(&self) { pub fn on_close(&self, can_gc: CanGc) {
let event = Event::new( let event = Event::new(
&self.global(), &self.global(),
atom!("close"), atom!("close"),
EventBubbles::DoesNotBubble, EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable, EventCancelable::NotCancelable,
CanGc::note(), can_gc,
); );
event.upcast::<Event>().fire(self.upcast()); event.upcast::<Event>().fire(self.upcast());
@ -151,7 +151,7 @@ impl RTCDataChannel {
let message = match error { let message = match error {
WebRtcError::Backend(message) => DOMString::from(message), WebRtcError::Backend(message) => DOMString::from(message),
}; };
let error = RTCError::new(&global, &init, message); let error = RTCError::new(&global, &init, message, can_gc);
let event = RTCErrorEvent::new(&global, atom!("error"), false, false, &error, can_gc); let event = RTCErrorEvent::new(&global, atom!("error"), false, false, &error, can_gc);
event.upcast::<Event>().fire(self.upcast()); event.upcast::<Event>().fire(self.upcast());
} }

View file

@ -43,8 +43,13 @@ impl RTCError {
} }
} }
pub fn new(global: &GlobalScope, init: &RTCErrorInit, message: DOMString) -> DomRoot<RTCError> { pub fn new(
Self::new_with_proto(global, None, init, message, CanGc::note()) global: &GlobalScope,
init: &RTCErrorInit,
message: DOMString,
can_gc: CanGc,
) -> DomRoot<RTCError> {
Self::new_with_proto(global, None, init, message, can_gc)
} }
fn new_with_proto( fn new_with_proto(

View file

@ -334,8 +334,8 @@ impl RTCPeerConnection {
}; };
match event { match event {
DataChannelEvent::Open => channel.on_open(), DataChannelEvent::Open => channel.on_open(can_gc),
DataChannelEvent::Close => channel.on_close(), DataChannelEvent::Close => channel.on_close(can_gc),
DataChannelEvent::Error(error) => channel.on_error(error, can_gc), DataChannelEvent::Error(error) => channel.on_error(error, can_gc),
DataChannelEvent::OnMessage(message) => channel.on_message(message, can_gc), DataChannelEvent::OnMessage(message) => channel.on_message(message, can_gc),
DataChannelEvent::StateChange(state) => channel.on_state_change(state, can_gc), DataChannelEvent::StateChange(state) => channel.on_state_change(state, can_gc),

View file

@ -56,8 +56,8 @@ use script_layout_interface::{
use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult}; use script_traits::webdriver_msg::{WebDriverJSError, WebDriverJSResult};
use script_traits::{ use script_traits::{
ConstellationControlMsg, DocumentState, HistoryEntryReplacement, LoadData, ScriptMsg, ConstellationControlMsg, DocumentState, HistoryEntryReplacement, LoadData, ScriptMsg,
ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerEventId, ScriptToConstellationChan, ScrollState, StructuredSerializedData, TimerSchedulerMsg,
TimerSchedulerMsg, WindowSizeData, WindowSizeType, WindowSizeData, WindowSizeType,
}; };
use selectors::attr::CaseSensitivity; use selectors::attr::CaseSensitivity;
use servo_arc::Arc as ServoArc; use servo_arc::Arc as ServoArc;
@ -783,7 +783,7 @@ impl WindowMethods for Window {
// but we pass false here, which suggests we are not doing that. Why? // but we pass false here, which suggests we are not doing that. Why?
if document.prompt_to_unload(false) { if document.prompt_to_unload(false) {
// Step 4, unload. // Step 4, unload.
document.unload(false); document.unload(false, CanGc::note());
// https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded // https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded
// which calls into https://html.spec.whatwg.org/multipage/#discard-a-document. // which calls into https://html.spec.whatwg.org/multipage/#discard-a-document.
@ -2310,10 +2310,6 @@ impl Window {
}; };
} }
pub fn handle_fire_timer(&self, timer_id: TimerEventId) {
self.upcast::<GlobalScope>().fire_timer(timer_id);
}
pub fn set_window_size(&self, size: WindowSizeData) { pub fn set_window_size(&self, size: WindowSizeData) {
self.window_size.set(size); self.window_size.set(size);
} }

View file

@ -220,7 +220,7 @@ impl WorkerMethods for Worker {
global.wgpu_id_hub(), global.wgpu_id_hub(),
control_receiver, control_receiver,
context_sender, context_sender,
CanGc::note(), can_gc,
); );
let context = context_receiver let context = context_receiver

View file

@ -254,24 +254,27 @@ impl XMLHttpRequest {
fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) { fn process_response(&mut self, metadata: Result<FetchMetadata, NetworkError>) {
let xhr = self.xhr.root(); let xhr = self.xhr.root();
let rv = xhr.process_headers_available(self.gen_id, metadata); let rv = xhr.process_headers_available(self.gen_id, metadata, CanGc::note());
if rv.is_err() { if rv.is_err() {
*self.sync_status.borrow_mut() = Some(rv); *self.sync_status.borrow_mut() = Some(rv);
} }
} }
fn process_response_chunk(&mut self, chunk: Vec<u8>) { fn process_response_chunk(&mut self, chunk: Vec<u8>) {
self.xhr.root().process_data_available(self.gen_id, chunk); self.xhr
.root()
.process_data_available(self.gen_id, chunk, CanGc::note());
} }
fn process_response_eof( fn process_response_eof(
&mut self, &mut self,
response: Result<ResourceFetchTiming, NetworkError>, response: Result<ResourceFetchTiming, NetworkError>,
) { ) {
let rv = self let rv = self.xhr.root().process_response_complete(
.xhr self.gen_id,
.root() response.map(|_| ()),
.process_response_complete(self.gen_id, response.map(|_| ())); CanGc::note(),
);
*self.sync_status.borrow_mut() = Some(rv); *self.sync_status.borrow_mut() = Some(rv);
} }
@ -445,7 +448,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
// Step 13 // Step 13
if self.ready_state.get() != XMLHttpRequestState::Opened { if self.ready_state.get() != XMLHttpRequestState::Opened {
self.change_ready_state(XMLHttpRequestState::Opened); self.change_ready_state(XMLHttpRequestState::Opened, CanGc::note());
} }
Ok(()) Ok(())
}, },
@ -810,7 +813,10 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
state == XMLHttpRequestState::Loading state == XMLHttpRequestState::Loading
{ {
let gen_id = self.generation_id.get(); let gen_id = self.generation_id.get();
self.process_partial_response(XHRProgress::Errored(gen_id, Error::Abort)); self.process_partial_response(
XHRProgress::Errored(gen_id, Error::Abort),
CanGc::note(),
);
// If open was called in one of the handlers invoked by the // If open was called in one of the handlers invoked by the
// above call then we should terminate the abort sequence // above call then we should terminate the abort sequence
if self.generation_id.get() != gen_id { if self.generation_id.get() != gen_id {
@ -819,7 +825,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
} }
// Step 3 // Step 3
if self.ready_state.get() == XMLHttpRequestState::Done { if self.ready_state.get() == XMLHttpRequestState::Done {
self.change_ready_state(XMLHttpRequestState::Unsent); self.change_ready_state(XMLHttpRequestState::Unsent, CanGc::note());
self.response_status.set(Err(())); self.response_status.set(Err(()));
self.response.borrow_mut().clear(); self.response.borrow_mut().clear();
self.response_headers.borrow_mut().clear(); self.response_headers.borrow_mut().clear();
@ -1021,7 +1027,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
pub type TrustedXHRAddress = Trusted<XMLHttpRequest>; pub type TrustedXHRAddress = Trusted<XMLHttpRequest>;
impl XMLHttpRequest { impl XMLHttpRequest {
fn change_ready_state(&self, rs: XMLHttpRequestState) { fn change_ready_state(&self, rs: XMLHttpRequestState, can_gc: CanGc) {
assert_ne!(self.ready_state.get(), rs); assert_ne!(self.ready_state.get(), rs);
self.ready_state.set(rs); self.ready_state.set(rs);
if rs != XMLHttpRequestState::Unsent { if rs != XMLHttpRequestState::Unsent {
@ -1030,7 +1036,7 @@ impl XMLHttpRequest {
atom!("readystatechange"), atom!("readystatechange"),
EventBubbles::DoesNotBubble, EventBubbles::DoesNotBubble,
EventCancelable::Cancelable, EventCancelable::Cancelable,
CanGc::note(), can_gc,
); );
event.fire(self.upcast()); event.fire(self.upcast());
} }
@ -1040,6 +1046,7 @@ impl XMLHttpRequest {
&self, &self,
gen_id: GenerationId, gen_id: GenerationId,
metadata: Result<FetchMetadata, NetworkError>, metadata: Result<FetchMetadata, NetworkError>,
can_gc: CanGc,
) -> Result<(), Error> { ) -> Result<(), Error> {
let metadata = match metadata { let metadata = match metadata {
Ok(meta) => match meta { Ok(meta) => match meta {
@ -1052,7 +1059,7 @@ impl XMLHttpRequest {
}, },
}, },
Err(_) => { Err(_) => {
self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network)); self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network), can_gc);
return Err(Error::Network); return Err(Error::Network);
}, },
}; };
@ -1060,36 +1067,40 @@ impl XMLHttpRequest {
metadata.final_url[..Position::AfterQuery].clone_into(&mut self.response_url.borrow_mut()); metadata.final_url[..Position::AfterQuery].clone_into(&mut self.response_url.borrow_mut());
// XXXManishearth Clear cache entries in case of a network error // XXXManishearth Clear cache entries in case of a network error
self.process_partial_response(XHRProgress::HeadersReceived( self.process_partial_response(
gen_id, XHRProgress::HeadersReceived(
metadata.headers.map(Serde::into_inner), gen_id,
metadata.status, metadata.headers.map(Serde::into_inner),
)); metadata.status,
),
can_gc,
);
Ok(()) Ok(())
} }
fn process_data_available(&self, gen_id: GenerationId, payload: Vec<u8>) { fn process_data_available(&self, gen_id: GenerationId, payload: Vec<u8>, can_gc: CanGc) {
self.process_partial_response(XHRProgress::Loading(gen_id, payload)); self.process_partial_response(XHRProgress::Loading(gen_id, payload), can_gc);
} }
fn process_response_complete( fn process_response_complete(
&self, &self,
gen_id: GenerationId, gen_id: GenerationId,
status: Result<(), NetworkError>, status: Result<(), NetworkError>,
can_gc: CanGc,
) -> ErrorResult { ) -> ErrorResult {
match status { match status {
Ok(()) => { Ok(()) => {
self.process_partial_response(XHRProgress::Done(gen_id)); self.process_partial_response(XHRProgress::Done(gen_id), can_gc);
Ok(()) Ok(())
}, },
Err(_) => { Err(_) => {
self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network)); self.process_partial_response(XHRProgress::Errored(gen_id, Error::Network), can_gc);
Err(Error::Network) Err(Error::Network)
}, },
} }
} }
fn process_partial_response(&self, progress: XHRProgress) { fn process_partial_response(&self, progress: XHRProgress, can_gc: CanGc) {
let msg_id = progress.generation_id(); let msg_id = progress.generation_id();
// Aborts processing if abort() or open() was called // Aborts processing if abort() or open() was called
@ -1156,7 +1167,7 @@ impl XMLHttpRequest {
} }
// Substep 3 // Substep 3
if !self.sync.get() { if !self.sync.get() {
self.change_ready_state(XMLHttpRequestState::HeadersReceived); self.change_ready_state(XMLHttpRequestState::HeadersReceived, can_gc);
} }
}, },
XHRProgress::Loading(_, mut partial_response) => { XHRProgress::Loading(_, mut partial_response) => {
@ -1174,7 +1185,7 @@ impl XMLHttpRequest {
atom!("readystatechange"), atom!("readystatechange"),
EventBubbles::DoesNotBubble, EventBubbles::DoesNotBubble,
EventCancelable::Cancelable, EventCancelable::Cancelable,
CanGc::note(), can_gc,
); );
event.fire(self.upcast()); event.fire(self.upcast());
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
@ -1197,7 +1208,7 @@ impl XMLHttpRequest {
// Subsubsteps 6-8 // Subsubsteps 6-8
self.send_flag.set(false); self.send_flag.set(false);
self.change_ready_state(XMLHttpRequestState::Done); self.change_ready_state(XMLHttpRequestState::Done, can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
// Subsubsteps 11-12 // Subsubsteps 11-12
self.dispatch_response_progress_event(atom!("load")); self.dispatch_response_progress_event(atom!("load"));
@ -1211,7 +1222,7 @@ impl XMLHttpRequest {
self.discard_subsequent_responses(); self.discard_subsequent_responses();
self.send_flag.set(false); self.send_flag.set(false);
// XXXManishearth set response to NetworkError // XXXManishearth set response to NetworkError
self.change_ready_state(XMLHttpRequestState::Done); self.change_ready_state(XMLHttpRequestState::Done, can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
let errormsg = match e { let errormsg = match e {
@ -1499,7 +1510,7 @@ impl XMLHttpRequest {
&document, &document,
Some(DOMString::from(decoded)), Some(DOMString::from(decoded)),
wr.get_url(), wr.get_url(),
CanGc::note(), can_gc,
); );
document document
} }
@ -1515,7 +1526,7 @@ impl XMLHttpRequest {
&document, &document,
Some(DOMString::from(decoded)), Some(DOMString::from(decoded)),
wr.get_url(), wr.get_url(),
CanGc::note(), can_gc,
); );
document document
} }
@ -1662,10 +1673,13 @@ pub struct XHRTimeoutCallback {
} }
impl XHRTimeoutCallback { impl XHRTimeoutCallback {
pub fn invoke(self) { pub fn invoke(self, can_gc: CanGc) {
let xhr = self.xhr.root(); let xhr = self.xhr.root();
if xhr.ready_state.get() != XMLHttpRequestState::Done { if xhr.ready_state.get() != XMLHttpRequestState::Done {
xhr.process_partial_response(XHRProgress::Errored(self.generation_id, Error::Timeout)); xhr.process_partial_response(
XHRProgress::Errored(self.generation_id, Error::Timeout),
can_gc,
);
} }
} }
} }

View file

@ -20,7 +20,7 @@ use crate::dom::xrhand::XRHand;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
use crate::dom::xrspace::XRSpace; use crate::dom::xrspace::XRSpace;
use crate::realms::enter_realm; use crate::realms::enter_realm;
use crate::script_runtime::JSContext; use crate::script_runtime::{CanGc, JSContext};
#[dom_struct] #[dom_struct]
pub struct XRInputSource { pub struct XRInputSource {
@ -42,6 +42,7 @@ impl XRInputSource {
global: &GlobalScope, global: &GlobalScope,
session: &XRSession, session: &XRSession,
info: InputSource, info: InputSource,
can_gc: CanGc,
) -> XRInputSource { ) -> XRInputSource {
// <https://www.w3.org/TR/webxr-gamepads-module-1/#gamepad-differences> // <https://www.w3.org/TR/webxr-gamepads-module-1/#gamepad-differences>
let gamepad = Gamepad::new( let gamepad = Gamepad::new(
@ -56,6 +57,7 @@ impl XRInputSource {
supports_trigger_rumble: false, supports_trigger_rumble: false,
}, },
true, true,
can_gc,
); );
XRInputSource { XRInputSource {
reflector: Reflector::new(), reflector: Reflector::new(),
@ -74,9 +76,10 @@ impl XRInputSource {
global: &GlobalScope, global: &GlobalScope,
session: &XRSession, session: &XRSession,
info: InputSource, info: InputSource,
can_gc: CanGc,
) -> DomRoot<XRInputSource> { ) -> DomRoot<XRInputSource> {
let source = reflect_dom_object( let source = reflect_dom_object(
Box::new(XRInputSource::new_inherited(global, session, info)), Box::new(XRInputSource::new_inherited(global, session, info, can_gc)),
global, global,
); );

View file

@ -15,6 +15,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::xrinputsource::XRInputSource; use crate::dom::xrinputsource::XRInputSource;
use crate::dom::xrinputsourceschangeevent::XRInputSourcesChangeEvent; use crate::dom::xrinputsourceschangeevent::XRInputSourcesChangeEvent;
use crate::dom::xrsession::XRSession; use crate::dom::xrsession::XRSession;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct XRInputSourceArray { pub struct XRInputSourceArray {
@ -34,7 +35,7 @@ impl XRInputSourceArray {
reflect_dom_object(Box::new(XRInputSourceArray::new_inherited()), global) reflect_dom_object(Box::new(XRInputSourceArray::new_inherited()), global)
} }
pub fn add_input_sources(&self, session: &XRSession, inputs: &[InputSource]) { pub fn add_input_sources(&self, session: &XRSession, inputs: &[InputSource], can_gc: CanGc) {
let mut input_sources = self.input_sources.borrow_mut(); let mut input_sources = self.input_sources.borrow_mut();
let global = self.global(); let global = self.global();
@ -46,7 +47,7 @@ impl XRInputSourceArray {
!input_sources.iter().any(|i| i.id() == info.id), !input_sources.iter().any(|i| i.id() == info.id),
"Should never add a duplicate input id!" "Should never add a duplicate input id!"
); );
let input = XRInputSource::new(&global, session, info.clone()); let input = XRInputSource::new(&global, session, info.clone(), can_gc);
input_sources.push(Dom::from_ref(&input)); input_sources.push(Dom::from_ref(&input));
added.push(input); added.push(input);
} }
@ -90,7 +91,13 @@ impl XRInputSourceArray {
event.upcast::<Event>().fire(session.upcast()); event.upcast::<Event>().fire(session.upcast());
} }
pub fn add_remove_input_source(&self, session: &XRSession, id: InputId, info: InputSource) { pub fn add_remove_input_source(
&self,
session: &XRSession,
id: InputId,
info: InputSource,
can_gc: CanGc,
) {
let mut input_sources = self.input_sources.borrow_mut(); let mut input_sources = self.input_sources.borrow_mut();
let global = self.global(); let global = self.global();
let root; let root;
@ -103,7 +110,7 @@ impl XRInputSourceArray {
&[] &[]
}; };
input_sources.retain(|i| i.id() != id); input_sources.retain(|i| i.id() != id);
let input = XRInputSource::new(&global, session, info); let input = XRInputSource::new(&global, session, info, can_gc);
input_sources.push(Dom::from_ref(&input)); input_sources.push(Dom::from_ref(&input));
let added = [input]; let added = [input];

View file

@ -68,6 +68,7 @@ use crate::dom::xrspace::XRSpace;
use crate::realms::InRealm; use crate::realms::InRealm;
use crate::script_runtime::JSContext; use crate::script_runtime::JSContext;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
use crate::script_runtime::CanGc;
#[dom_struct] #[dom_struct]
pub struct XRSession { pub struct XRSession {
@ -240,7 +241,7 @@ impl XRSession {
let this = this.clone(); let this = this.clone();
let _ = task_source.queue_with_canceller( let _ = task_source.queue_with_canceller(
task!(xr_event_callback: move || { task!(xr_event_callback: move || {
this.root().event_callback(message.to().unwrap()); this.root().event_callback(message.to().unwrap(), CanGc::note());
}), }),
&canceller, &canceller,
); );
@ -275,13 +276,13 @@ impl XRSession {
let _ = task_source.queue_with_canceller( let _ = task_source.queue_with_canceller(
task!(session_initial_inputs: move || { task!(session_initial_inputs: move || {
let this = this.root(); let this = this.root();
this.input_sources.add_input_sources(&this, &initial_inputs); this.input_sources.add_input_sources(&this, &initial_inputs, CanGc::note());
}), }),
&canceller, &canceller,
); );
} }
fn event_callback(&self, event: XREvent) { fn event_callback(&self, event: XREvent, can_gc: CanGc) {
match event { match event {
XREvent::SessionEnd => { XREvent::SessionEnd => {
// https://immersive-web.github.io/webxr/#shut-down-the-session // https://immersive-web.github.io/webxr/#shut-down-the-session
@ -366,13 +367,14 @@ impl XRSession {
self.dirty_layers(); self.dirty_layers();
}, },
XREvent::AddInput(info) => { XREvent::AddInput(info) => {
self.input_sources.add_input_sources(self, &[info]); self.input_sources.add_input_sources(self, &[info], can_gc);
}, },
XREvent::RemoveInput(id) => { XREvent::RemoveInput(id) => {
self.input_sources.remove_input_source(self, id); self.input_sources.remove_input_source(self, id);
}, },
XREvent::UpdateInput(id, source) => { XREvent::UpdateInput(id, source) => {
self.input_sources.add_remove_input_source(self, id, source); self.input_sources
.add_remove_input_source(self, id, source, can_gc);
}, },
XREvent::InputChanged(id, frame) => { XREvent::InputChanged(id, frame) => {
self.input_frames.borrow_mut().insert(id, frame); self.input_frames.borrow_mut().insert(id, frame);

View file

@ -1538,7 +1538,7 @@ impl ScriptThread {
} }
/// Process compositor events as part of a "update the rendering task". /// Process compositor events as part of a "update the rendering task".
fn process_pending_compositor_events(&self, pipeline_id: PipelineId) { fn process_pending_compositor_events(&self, pipeline_id: PipelineId, can_gc: CanGc) {
let Some(document) = self.documents.borrow().find_document(pipeline_id) else { let Some(document) = self.documents.borrow().find_document(pipeline_id) else {
warn!("Processing pending compositor events for closed pipeline {pipeline_id}."); warn!("Processing pending compositor events for closed pipeline {pipeline_id}.");
return; return;
@ -1630,7 +1630,7 @@ impl ScriptThread {
CompositorEvent::GamepadEvent(gamepad_event) => { CompositorEvent::GamepadEvent(gamepad_event) => {
let global = window.upcast::<GlobalScope>(); let global = window.upcast::<GlobalScope>();
global.handle_gamepad_event(gamepad_event); global.handle_gamepad_event(gamepad_event, can_gc);
}, },
} }
} }
@ -1638,7 +1638,7 @@ impl ScriptThread {
} }
/// <https://html.spec.whatwg.org/multipage/#update-the-rendering> /// <https://html.spec.whatwg.org/multipage/#update-the-rendering>
fn update_the_rendering(&self) { fn update_the_rendering(&self, can_gc: CanGc) {
self.update_the_rendering_task_queued_for_pipeline self.update_the_rendering_task_queued_for_pipeline
.borrow_mut() .borrow_mut()
.clear(); .clear();
@ -1687,7 +1687,7 @@ impl ScriptThread {
// TODO: Should this be broken and to match the specification more closely? For instance see // TODO: Should this be broken and to match the specification more closely? For instance see
// https://html.spec.whatwg.org/multipage/#flush-autofocus-candidates. // https://html.spec.whatwg.org/multipage/#flush-autofocus-candidates.
self.process_pending_compositor_events(pipeline_id); self.process_pending_compositor_events(pipeline_id, can_gc);
// TODO(#31665): Implement the "run the scroll steps" from // TODO(#31665): Implement the "run the scroll steps" from
// https://drafts.csswg.org/cssom-view/#document-run-the-scroll-steps. // https://drafts.csswg.org/cssom-view/#document-run-the-scroll-steps.
@ -1781,7 +1781,7 @@ impl ScriptThread {
SCRIPT_THREAD_ROOT.with(|root| { SCRIPT_THREAD_ROOT.with(|root| {
if let Some(script_thread) = root.get() { if let Some(script_thread) = root.get() {
let script_thread = unsafe {&*script_thread}; let script_thread = unsafe {&*script_thread};
script_thread.update_the_rendering(); script_thread.update_the_rendering(CanGc::note());
} }
}) })
}), }),
@ -2311,7 +2311,7 @@ impl ScriptThread {
can_gc, can_gc,
), ),
ConstellationControlMsg::UnloadDocument(pipeline_id) => { ConstellationControlMsg::UnloadDocument(pipeline_id) => {
self.handle_unload_document(pipeline_id) self.handle_unload_document(pipeline_id, can_gc)
}, },
ConstellationControlMsg::ResizeInactive(id, new_size) => { ConstellationControlMsg::ResizeInactive(id, new_size) => {
self.handle_resize_inactive_msg(id, new_size) self.handle_resize_inactive_msg(id, new_size)
@ -2320,7 +2320,7 @@ impl ScriptThread {
self.handle_get_title_msg(pipeline_id) self.handle_get_title_msg(pipeline_id)
}, },
ConstellationControlMsg::SetDocumentActivity(pipeline_id, activity) => { ConstellationControlMsg::SetDocumentActivity(pipeline_id, activity) => {
self.handle_set_document_activity_msg(pipeline_id, activity) self.handle_set_document_activity_msg(pipeline_id, activity, can_gc)
}, },
ConstellationControlMsg::SetThrottled(pipeline_id, throttled) => { ConstellationControlMsg::SetThrottled(pipeline_id, throttled) => {
self.handle_set_throttled_msg(pipeline_id, throttled) self.handle_set_throttled_msg(pipeline_id, throttled)
@ -2988,7 +2988,12 @@ impl ScriptThread {
} }
/// Handles activity change message /// Handles activity change message
fn handle_set_document_activity_msg(&self, id: PipelineId, activity: DocumentActivity) { fn handle_set_document_activity_msg(
&self,
id: PipelineId,
activity: DocumentActivity,
can_gc: CanGc,
) {
debug!( debug!(
"Setting activity of {} to be {:?} in {:?}.", "Setting activity of {} to be {:?} in {:?}.",
id, id,
@ -2997,7 +3002,7 @@ impl ScriptThread {
); );
let document = self.documents.borrow().find_document(id); let document = self.documents.borrow().find_document(id);
if let Some(document) = document { if let Some(document) = document {
document.set_activity(activity); document.set_activity(activity, can_gc);
return; return;
} }
let mut loads = self.incomplete_loads.borrow_mut(); let mut loads = self.incomplete_loads.borrow_mut();
@ -3073,10 +3078,10 @@ impl ScriptThread {
} }
} }
fn handle_unload_document(&self, pipeline_id: PipelineId) { fn handle_unload_document(&self, pipeline_id: PipelineId, can_gc: CanGc) {
let document = self.documents.borrow().find_document(pipeline_id); let document = self.documents.borrow().find_document(pipeline_id);
if let Some(document) = document { if let Some(document) = document {
document.unload(false); document.unload(false, can_gc);
} }
} }

View file

@ -29,6 +29,7 @@ use crate::dom::htmlmetaelement::RefreshRedirectDue;
use crate::dom::testbinding::TestBindingCallback; use crate::dom::testbinding::TestBindingCallback;
use crate::dom::xmlhttprequest::XHRTimeoutCallback; use crate::dom::xmlhttprequest::XHRTimeoutCallback;
use crate::script_module::ScriptFetchOptions; use crate::script_module::ScriptFetchOptions;
use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread; use crate::script_thread::ScriptThread;
#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, MallocSizeOf, Ord, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, MallocSizeOf, Ord, PartialEq, PartialOrd)]
@ -88,9 +89,9 @@ pub enum OneshotTimerCallback {
} }
impl OneshotTimerCallback { impl OneshotTimerCallback {
fn invoke<T: DomObject>(self, this: &T, js_timers: &JsTimers) { fn invoke<T: DomObject>(self, this: &T, js_timers: &JsTimers, can_gc: CanGc) {
match self { match self {
OneshotTimerCallback::XhrTimeout(callback) => callback.invoke(), OneshotTimerCallback::XhrTimeout(callback) => callback.invoke(can_gc),
OneshotTimerCallback::EventSourceTimeout(callback) => callback.invoke(), OneshotTimerCallback::EventSourceTimeout(callback) => callback.invoke(),
OneshotTimerCallback::JsTimer(task) => task.invoke(this, js_timers), OneshotTimerCallback::JsTimer(task) => task.invoke(this, js_timers),
OneshotTimerCallback::TestBindingCallback(callback) => callback.invoke(), OneshotTimerCallback::TestBindingCallback(callback) => callback.invoke(),
@ -190,7 +191,7 @@ impl OneshotTimers {
} }
} }
pub fn fire_timer(&self, id: TimerEventId, global: &GlobalScope) { pub fn fire_timer(&self, id: TimerEventId, global: &GlobalScope, can_gc: CanGc) {
let expected_id = self.expected_event_id.get(); let expected_id = self.expected_event_id.get();
if expected_id != id { if expected_id != id {
debug!( debug!(
@ -233,7 +234,7 @@ impl OneshotTimers {
return; return;
} }
let callback = timer.callback; let callback = timer.callback;
callback.invoke(global, &self.js_timers); callback.invoke(global, &self.js_timers, can_gc);
} }
self.schedule_timer_call(); self.schedule_timer_call();