script: Mark callback methods with CanGc. (#35753)

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2025-03-03 07:17:25 -05:00 committed by GitHub
parent 3d320fa96a
commit 5650fa2e79
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 133 additions and 67 deletions

View file

@ -547,7 +547,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
assert!(resolvers.contains_key(&uuid_));
let resolver = resolvers.remove(&uuid_).unwrap();
if let Some(callback) = resolver.success_callback {
let _ = callback.Call__(&buffer, ExceptionHandling::Report);
let _ = callback.Call__(&buffer, ExceptionHandling::Report, CanGc::note());
}
resolver.promise.resolve_native(&buffer, CanGc::note());
}));
@ -561,7 +561,7 @@ impl BaseAudioContextMethods<crate::DomTypeHolder> for BaseAudioContext {
if let Some(callback) = resolver.error_callback {
let _ = callback.Call__(
&DOMException::new(&this.global(), DOMErrorName::DataCloneError, CanGc::note()),
ExceptionHandling::Report);
ExceptionHandling::Report, CanGc::note());
}
let error = format!("Audio decode error {:?}", error);
resolver.promise.reject_error(Error::Type(error), CanGc::note());

View file

@ -44,7 +44,7 @@ pub(crate) mod base {
};
pub(crate) use crate::dom::globalscope::{GlobalScope, GlobalScopeHelpers};
pub(crate) use crate::dom::promise::PromiseHelpers;
pub(crate) use crate::script_runtime::JSContext as SafeJSContext;
pub(crate) use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
}
#[allow(unused_imports)]

View file

@ -1020,6 +1020,7 @@ impl CustomElementReaction {
arguments,
value.handle_mut(),
ExceptionHandling::Report,
can_gc,
);
},
}

View file

@ -126,7 +126,7 @@ impl DataTransferItemMethods<crate::DomTypeHolder> for DataTransferItem {
let maybe_index = this.root().pending_callbacks.borrow().iter().position(|val| val.id == id);
if let Some(index) = maybe_index {
let callback = this.root().pending_callbacks.borrow_mut().swap_remove(index).callback;
let _ = callback.Call__(DOMString::from(string), ExceptionHandling::Report);
let _ = callback.Call__(DOMString::from(string), ExceptionHandling::Report, CanGc::note());
}
}));
}

View file

@ -2380,7 +2380,7 @@ impl Document {
}
/// <https://html.spec.whatwg.org/multipage/#run-the-animation-frame-callbacks>
pub(crate) fn run_the_animation_frame_callbacks(&self) {
pub(crate) fn run_the_animation_frame_callbacks(&self, can_gc: CanGc) {
let _realm = enter_realm(self);
rooted_vec!(let mut animation_frame_list);
mem::swap(
@ -2398,7 +2398,7 @@ impl Document {
for (_, callback) in animation_frame_list.drain(..) {
if let Some(callback) = callback {
callback.call(self, *timing);
callback.call(self, *timing, can_gc);
}
}
@ -6106,7 +6106,7 @@ pub(crate) enum AnimationFrameCallback {
}
impl AnimationFrameCallback {
fn call(&self, document: &Document, now: f64) {
fn call(&self, document: &Document, now: f64, can_gc: CanGc) {
match *self {
AnimationFrameCallback::DevtoolsFramerateTick { ref actor_name } => {
let msg = ScriptToDevtoolsControlMsg::FramerateTick(actor_name.clone(), now);
@ -6116,7 +6116,7 @@ impl AnimationFrameCallback {
AnimationFrameCallback::FrameRequestCallback { ref callback } => {
// TODO(jdm): The spec says that any exceptions should be suppressed:
// https://github.com/servo/servo/issues/6928
let _ = callback.Call__(Finite::wrap(now), ExceptionHandling::Report);
let _ = callback.Call__(Finite::wrap(now), ExceptionHandling::Report, can_gc);
},
}
}

View file

@ -1154,6 +1154,7 @@ fn invoke(
phase,
invocation_target_in_shadow_tree,
timeline_window,
can_gc,
);
// Step 9. If found is false and events isTrusted attribute is true:
@ -1182,6 +1183,7 @@ fn invoke(
phase,
invocation_target_in_shadow_tree,
timeline_window,
can_gc,
);
// Step 9.4 Set events type attribute value to originalEventType.
@ -1196,6 +1198,7 @@ fn inner_invoke(
_phase: ListenerPhase,
invocation_target_in_shadow_tree: bool,
timeline_window: Option<&Window>,
can_gc: CanGc,
) -> bool {
// Step 1. Let found be false.
let mut found = false;
@ -1261,6 +1264,7 @@ fn inner_invoke(
.expect("event target was initialized as part of \"invoke\""),
event,
ExceptionHandling::Report,
can_gc,
);
if let Some(window) = timeline_window {
window.emit_timeline_marker(marker.end());

View file

@ -190,11 +190,12 @@ impl CompiledEventListener {
object: &EventTarget,
event: &Event,
exception_handle: ExceptionHandling,
can_gc: CanGc,
) {
// Step 3
match *self {
CompiledEventListener::Listener(ref listener) => {
let _ = listener.HandleEvent_(object, event, exception_handle);
let _ = listener.HandleEvent_(object, event, exception_handle, can_gc);
},
CompiledEventListener::Handler(ref handler) => {
match *handler {
@ -214,6 +215,7 @@ impl CompiledEventListener {
Some(error.handle()),
rooted_return_value.handle_mut(),
exception_handle,
can_gc,
);
// Step 4
if let Ok(()) = return_value {
@ -237,15 +239,19 @@ impl CompiledEventListener {
None,
rooted_return_value.handle_mut(),
exception_handle,
can_gc,
);
},
CommonEventHandler::BeforeUnloadEventHandler(ref handler) => {
if let Some(event) = event.downcast::<BeforeUnloadEvent>() {
// Step 5
if let Ok(value) =
handler.Call_(object, event.upcast::<Event>(), exception_handle)
{
if let Ok(value) = handler.Call_(
object,
event.upcast::<Event>(),
exception_handle,
can_gc,
) {
let rv = event.ReturnValue();
if let Some(v) = value {
if rv.is_empty() {
@ -256,8 +262,12 @@ impl CompiledEventListener {
}
} else {
// Step 5, "Otherwise" clause
let _ =
handler.Call_(object, event.upcast::<Event>(), exception_handle);
let _ = handler.Call_(
object,
event.upcast::<Event>(),
exception_handle,
can_gc,
);
}
},
@ -269,6 +279,7 @@ impl CompiledEventListener {
event,
rooted_return_value.handle_mut(),
exception_handle,
can_gc,
) {
let value = rooted_return_value.handle();

View file

@ -640,9 +640,9 @@ impl HTMLCanvasElementMethods<crate::DomTypeHolder> for HTMLCanvasElement {
// Set result to a new Blob object, created in the relevant realm of this canvas element
// Invoke callback with « result » and "report".
let blob = Blob::new(&this.global(), blob_impl, CanGc::note());
let _ = callback.Call__(Some(&blob), ExceptionHandling::Report);
let _ = callback.Call__(Some(&blob), ExceptionHandling::Report, CanGc::note());
} else {
let _ = callback.Call__(None, ExceptionHandling::Report);
let _ = callback.Call__(None, ExceptionHandling::Report, CanGc::note());
}
}));

View file

@ -75,7 +75,7 @@ impl MediaSession {
debug!("Handle media session action {:?}", action);
if let Some(handler) = self.action_handlers.borrow().get(&action) {
if handler.Call__(ExceptionHandling::Report).is_err() {
if handler.Call__(ExceptionHandling::Report, can_gc).is_err() {
warn!("Error calling MediaSessionActionHandler callback");
}
return;

View file

@ -134,7 +134,7 @@ impl MutationObserver {
if !queue.is_empty() {
let _ = mo
.callback
.Call_(&**mo, queue, mo, ExceptionHandling::Report);
.Call_(&**mo, queue, mo, ExceptionHandling::Report, can_gc);
}
}

View file

@ -103,7 +103,7 @@ impl NodeIteratorMethods<crate::DomTypeHolder> for NodeIterator {
}
// https://dom.spec.whatwg.org/#dom-nodeiterator-nextnode
fn NextNode(&self) -> Fallible<Option<DomRoot<Node>>> {
fn NextNode(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// https://dom.spec.whatwg.org/#concept-NodeIterator-traverse
// Step 1.
let node = self.reference_node.get();
@ -116,7 +116,7 @@ impl NodeIteratorMethods<crate::DomTypeHolder> for NodeIterator {
before_node = false;
// Step 3-2.
let result = self.accept_node(&node)?;
let result = self.accept_node(&node, can_gc)?;
// Step 3-3.
if result == NodeFilterConstants::FILTER_ACCEPT {
@ -131,7 +131,7 @@ impl NodeIteratorMethods<crate::DomTypeHolder> for NodeIterator {
// Step 3-1.
for following_node in node.following_nodes(&self.root_node) {
// Step 3-2.
let result = self.accept_node(&following_node)?;
let result = self.accept_node(&following_node, can_gc)?;
// Step 3-3.
if result == NodeFilterConstants::FILTER_ACCEPT {
@ -147,7 +147,7 @@ impl NodeIteratorMethods<crate::DomTypeHolder> for NodeIterator {
}
// https://dom.spec.whatwg.org/#dom-nodeiterator-previousnode
fn PreviousNode(&self) -> Fallible<Option<DomRoot<Node>>> {
fn PreviousNode(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// https://dom.spec.whatwg.org/#concept-NodeIterator-traverse
// Step 1.
let node = self.reference_node.get();
@ -160,7 +160,7 @@ impl NodeIteratorMethods<crate::DomTypeHolder> for NodeIterator {
before_node = true;
// Step 3-2.
let result = self.accept_node(&node)?;
let result = self.accept_node(&node, can_gc)?;
// Step 3-3.
if result == NodeFilterConstants::FILTER_ACCEPT {
@ -175,7 +175,7 @@ impl NodeIteratorMethods<crate::DomTypeHolder> for NodeIterator {
// Step 3-1.
for preceding_node in node.preceding_nodes(&self.root_node) {
// Step 3-2.
let result = self.accept_node(&preceding_node)?;
let result = self.accept_node(&preceding_node, can_gc)?;
// Step 3-3.
if result == NodeFilterConstants::FILTER_ACCEPT {
@ -198,7 +198,7 @@ impl NodeIteratorMethods<crate::DomTypeHolder> for NodeIterator {
impl NodeIterator {
// https://dom.spec.whatwg.org/#concept-node-filter
fn accept_node(&self, node: &Node) -> Fallible<u16> {
fn accept_node(&self, node: &Node, can_gc: CanGc) -> Fallible<u16> {
// Step 1.
if self.active.get() {
return Err(Error::InvalidState);
@ -217,7 +217,7 @@ impl NodeIterator {
// Step 5.
self.active.set(true);
// Step 6.
let result = callback.AcceptNode_(self, node, Rethrow);
let result = callback.AcceptNode_(self, node, Rethrow, can_gc);
// Step 7.
self.active.set(false);
// Step 8.

View file

@ -291,7 +291,7 @@ impl NotificationMethods<crate::DomTypeHolder> for Notification {
// Step 3.2.1: If deprecatedCallback is given,
// then invoke deprecatedCallback with « permissionState » and "report".
if let Some(callback) = global.remove_notification_permission_request_callback(uuid_) {
let _ = callback.Call__(notification_permission, ExceptionHandling::Report);
let _ = callback.Call__(notification_permission, ExceptionHandling::Report, CanGc::note());
}
// Step 3.2.2: Resolve promise with permissionState.

View file

@ -101,9 +101,13 @@ impl PerformanceObserver {
let observer_entry_list =
PerformanceObserverEntryList::new(&self.global(), entry_list, can_gc);
// using self both as thisArg and as the second formal argument
let _ = self
.callback
.Call_(self, &observer_entry_list, self, ExceptionHandling::Report);
let _ = self.callback.Call_(
self,
&observer_entry_list,
self,
ExceptionHandling::Report,
can_gc,
);
}
pub(crate) fn callback(&self) -> Rc<PerformanceObserverCallback> {

View file

@ -679,7 +679,7 @@ impl ReadableStreamDefaultController {
let size = if let Some(strategy_size) = strategy_size {
// Note: the Rethrow exception handling is necessary,
// otherwise returning JSFailed will panic because no exception is pending.
let result = strategy_size.Call__(chunk, ExceptionHandling::Rethrow);
let result = strategy_size.Call__(chunk, ExceptionHandling::Rethrow, can_gc);
match result {
// Let chunkSize be result.[[Value]].
Ok(size) => size,

View file

@ -148,7 +148,7 @@ impl ResizeObserver {
}
let _ = self
.callback
.Call_(self, entries, self, ExceptionHandling::Report);
.Call_(self, entries, self, ExceptionHandling::Report, can_gc);
}
/// <https://drafts.csswg.org/resize-observer/#has-skipped-observations-h>

View file

@ -1034,9 +1034,11 @@ impl TestBindingMethods<crate::DomTypeHolder> for TestBinding {
}
}
impl Callback for SimpleHandler {
fn callback(&self, cx: SafeJSContext, v: HandleValue, realm: InRealm, _can_gc: CanGc) {
fn callback(&self, cx: SafeJSContext, v: HandleValue, realm: InRealm, can_gc: CanGc) {
let global = GlobalScope::from_safe_context(cx, realm);
let _ = self.handler.Call_(&*global, v, ExceptionHandling::Report);
let _ = self
.handler
.Call_(&*global, v, ExceptionHandling::Report, can_gc);
}
}
}

View file

@ -100,7 +100,7 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
}
// https://dom.spec.whatwg.org/#dom-treewalker-parentnode
fn ParentNode(&self) -> Fallible<Option<DomRoot<Node>>> {
fn ParentNode(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// "1. Let node be the value of the currentNode attribute."
let mut node = self.current_node.get();
// "2. While node is not null and is not root, run these substeps:"
@ -111,7 +111,7 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
node = n;
// "2. If node is not null and filtering node returns FILTER_ACCEPT,
// then set the currentNode attribute to node, return node."
if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node)? {
if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node, can_gc)? {
self.current_node.set(&node);
return Ok(Some(node));
}
@ -124,31 +124,47 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
}
// https://dom.spec.whatwg.org/#dom-treewalker-firstchild
fn FirstChild(&self) -> Fallible<Option<DomRoot<Node>>> {
fn FirstChild(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// "The firstChild() method must traverse children of type first."
self.traverse_children(|node| node.GetFirstChild(), |node| node.GetNextSibling())
self.traverse_children(
|node| node.GetFirstChild(),
|node| node.GetNextSibling(),
can_gc,
)
}
// https://dom.spec.whatwg.org/#dom-treewalker-lastchild
fn LastChild(&self) -> Fallible<Option<DomRoot<Node>>> {
fn LastChild(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// "The lastChild() method must traverse children of type last."
self.traverse_children(|node| node.GetLastChild(), |node| node.GetPreviousSibling())
self.traverse_children(
|node| node.GetLastChild(),
|node| node.GetPreviousSibling(),
can_gc,
)
}
// https://dom.spec.whatwg.org/#dom-treewalker-previoussibling
fn PreviousSibling(&self) -> Fallible<Option<DomRoot<Node>>> {
fn PreviousSibling(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// "The nextSibling() method must traverse siblings of type next."
self.traverse_siblings(|node| node.GetLastChild(), |node| node.GetPreviousSibling())
self.traverse_siblings(
|node| node.GetLastChild(),
|node| node.GetPreviousSibling(),
can_gc,
)
}
// https://dom.spec.whatwg.org/#dom-treewalker-nextsibling
fn NextSibling(&self) -> Fallible<Option<DomRoot<Node>>> {
fn NextSibling(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// "The previousSibling() method must traverse siblings of type previous."
self.traverse_siblings(|node| node.GetFirstChild(), |node| node.GetNextSibling())
self.traverse_siblings(
|node| node.GetFirstChild(),
|node| node.GetNextSibling(),
can_gc,
)
}
// https://dom.spec.whatwg.org/#dom-treewalker-previousnode
fn PreviousNode(&self) -> Fallible<Option<DomRoot<Node>>> {
fn PreviousNode(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// "1. Let node be the value of the currentNode attribute."
let mut node = self.current_node.get();
// "2. While node is not root, run these substeps:"
@ -166,7 +182,7 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
// "4. If result is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
loop {
let result = self.accept_node(&node)?;
let result = self.accept_node(&node, can_gc)?;
match result {
NodeFilterConstants::FILTER_REJECT => break,
_ if node.GetFirstChild().is_some() => node = node.GetLastChild().unwrap(),
@ -196,7 +212,7 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
}
// "5. Filter node and if the return value is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node)? {
if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node, can_gc)? {
self.current_node.set(&node);
return Ok(Some(node));
}
@ -206,7 +222,7 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
}
// https://dom.spec.whatwg.org/#dom-treewalker-nextnode
fn NextNode(&self) -> Fallible<Option<DomRoot<Node>>> {
fn NextNode(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Node>>> {
// "1. Let node be the value of the currentNode attribute."
let mut node = self.current_node.get();
// "2. Let result be FILTER_ACCEPT."
@ -224,7 +240,7 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
// "1. Set node to its first child."
node = child;
// "2. Filter node and set result to the return value."
result = self.accept_node(&node)?;
result = self.accept_node(&node, can_gc)?;
// "3. If result is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
if NodeFilterConstants::FILTER_ACCEPT == result {
@ -242,7 +258,7 @@ impl TreeWalkerMethods<crate::DomTypeHolder> for TreeWalker {
Some(n) => {
node = n;
// "3. Filter node and set result to the return value."
result = self.accept_node(&node)?;
result = self.accept_node(&node, can_gc)?;
// "4. If result is FILTER_ACCEPT, then
// set the currentNode attribute to node and return node."
if NodeFilterConstants::FILTER_ACCEPT == result {
@ -262,6 +278,7 @@ impl TreeWalker {
&self,
next_child: F,
next_sibling: G,
can_gc: CanGc,
) -> Fallible<Option<DomRoot<Node>>>
where
F: Fn(&Node) -> Option<DomRoot<Node>>,
@ -281,7 +298,7 @@ impl TreeWalker {
// 4. Main: Repeat these substeps:
'main: loop {
// "1. Filter node and let result be the return value."
let result = self.accept_node(&node)?;
let result = self.accept_node(&node, can_gc)?;
match result {
// "2. If result is FILTER_ACCEPT, then set the currentNode
// attribute to node and return node."
@ -338,6 +355,7 @@ impl TreeWalker {
&self,
next_child: F,
next_sibling: G,
can_gc: CanGc,
) -> Fallible<Option<DomRoot<Node>>>
where
F: Fn(&Node) -> Option<DomRoot<Node>>,
@ -360,7 +378,7 @@ impl TreeWalker {
// "1. Set node to sibling."
node = sibling_op.unwrap();
// "2. Filter node and let result be the return value."
let result = self.accept_node(&node)?;
let result = self.accept_node(&node, can_gc)?;
// "3. If result is FILTER_ACCEPT, then set the currentNode
// attribute to node and return node."
if NodeFilterConstants::FILTER_ACCEPT == result {
@ -389,7 +407,7 @@ impl TreeWalker {
// "5. Filter node and if the return value is FILTER_ACCEPT, then return null."
Some(n) => {
node = n;
if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node)? {
if NodeFilterConstants::FILTER_ACCEPT == self.accept_node(&node, can_gc)? {
return Ok(None);
}
},
@ -421,7 +439,7 @@ impl TreeWalker {
}
// https://dom.spec.whatwg.org/#concept-node-filter
fn accept_node(&self, node: &Node) -> Fallible<u16> {
fn accept_node(&self, node: &Node, can_gc: CanGc) -> Fallible<u16> {
// Step 1.
if self.active.get() {
return Err(Error::InvalidState);
@ -439,7 +457,7 @@ impl TreeWalker {
// Step 5.
self.active.set(true);
// Step 6.
let result = callback.AcceptNode_(self, node, Rethrow);
let result = callback.AcceptNode_(self, node, Rethrow, can_gc);
// Step 7.
self.active.set(false);
// Step 8.
@ -461,7 +479,7 @@ impl Iterator for &TreeWalker {
type Item = DomRoot<Node>;
fn next(&mut self) -> Option<DomRoot<Node>> {
match self.NextNode() {
match self.NextNode(CanGc::note()) {
Ok(node) => node,
Err(_) =>
// The Err path happens only when a JavaScript

View file

@ -117,6 +117,7 @@ impl UnderlyingSourceContainer {
&SafeHandle::from_raw(this_obj.handle()),
Some(reason),
ExceptionHandling::Rethrow,
can_gc,
)
};
return Some(result);
@ -146,6 +147,7 @@ impl UnderlyingSourceContainer {
&SafeHandle::from_raw(this_obj.handle()),
controller,
ExceptionHandling::Rethrow,
can_gc,
)
};
return Some(result);
@ -186,6 +188,7 @@ impl UnderlyingSourceContainer {
controller,
result.handle_mut(),
ExceptionHandling::Rethrow,
can_gc,
) {
return Some(Err(error));
}

View file

@ -480,7 +480,7 @@ impl XRSession {
for i in 0..len {
let callback = self.current_raf_callback_list.borrow()[i].1.clone();
if let Some(callback) = callback {
let _ = callback.Call__(time, &frame, ExceptionHandling::Report);
let _ = callback.Call__(time, &frame, ExceptionHandling::Report, can_gc);
}
}
self.outside_raf.set(true);

View file

@ -180,10 +180,15 @@ impl XRTestMethods<crate::DomTypeHolder> for XRTest {
}
/// <https://github.com/immersive-web/webxr-test-api/blob/master/explainer.md>
fn SimulateUserActivation(&self, f: Rc<Function>) {
fn SimulateUserActivation(&self, f: Rc<Function>, can_gc: CanGc) {
ScriptThread::set_user_interacting(true);
rooted!(in(*GlobalScope::get_cx()) let mut value: JSVal);
let _ = f.Call__(vec![], value.handle_mut(), ExceptionHandling::Rethrow);
let _ = f.Call__(
vec![],
value.handle_mut(),
ExceptionHandling::Rethrow,
can_gc,
);
ScriptThread::set_user_interacting(false);
}

View file

@ -373,6 +373,7 @@ impl WritableStreamDefaultController {
self,
result.handle_mut(),
ExceptionHandling::Rethrow,
can_gc,
)?;
let is_promise = unsafe {
if result.is_object() {
@ -445,6 +446,7 @@ impl WritableStreamDefaultController {
&this_object.handle(),
Some(reason),
ExceptionHandling::Rethrow,
can_gc,
)
} else {
Ok(Promise::new_resolved(global, cx, (), can_gc))
@ -471,6 +473,7 @@ impl WritableStreamDefaultController {
chunk,
self,
ExceptionHandling::Rethrow,
can_gc,
)
} else {
Ok(Promise::new_resolved(global, cx, (), can_gc))
@ -492,7 +495,7 @@ impl WritableStreamDefaultController {
this_object.set(self.underlying_sink_obj.get());
let algo = self.close.borrow().clone();
let result = if let Some(algo) = algo {
algo.Call_(&this_object.handle(), ExceptionHandling::Rethrow)
algo.Call_(&this_object.handle(), ExceptionHandling::Rethrow, can_gc)
} else {
Ok(Promise::new_resolved(global, cx, (), can_gc))
};
@ -688,7 +691,7 @@ impl WritableStreamDefaultController {
// Let returnValue be the result of performing controller.[[strategySizeAlgorithm]],
// passing in chunk, and interpreting the result as a completion record.
let result = strategy_size.Call__(chunk, ExceptionHandling::Rethrow);
let result = strategy_size.Call__(chunk, ExceptionHandling::Rethrow, can_gc);
match result {
// Let chunkSize be result.[[Value]].

View file

@ -118,14 +118,18 @@ impl MicrotaskQueue {
let was_interacting = ScriptThread::is_user_interacting();
ScriptThread::set_user_interacting(job.is_user_interacting);
let _realm = enter_realm(&*target);
let _ = job.callback.Call_(&*target, ExceptionHandling::Report);
let _ = job
.callback
.Call_(&*target, ExceptionHandling::Report, can_gc);
ScriptThread::set_user_interacting(was_interacting);
}
},
Microtask::User(ref job) => {
if let Some(target) = target_provider(job.pipeline) {
let _realm = enter_realm(&*target);
let _ = job.callback.Call_(&*target, ExceptionHandling::Report);
let _ = job
.callback
.Call_(&*target, ExceptionHandling::Report, can_gc);
}
},
Microtask::MediaElement(ref task) => {

View file

@ -1238,7 +1238,7 @@ impl ScriptThread {
// > in the relative high resolution time given frameTimestamp and doc's
// > relevant global object as the timestamp.
if should_run_rafs {
document.run_the_animation_frame_callbacks();
document.run_the_animation_frame_callbacks(can_gc);
}
// Run the resize observer steps.

View file

@ -558,7 +558,7 @@ impl JsTimerTask {
InternalTimerCallback::FunctionTimerCallback(ref function, ref arguments) => {
let arguments = self.collect_heap_args(arguments);
rooted!(in(*GlobalScope::get_cx()) let mut value: JSVal);
let _ = function.Call_(this, arguments, value.handle_mut(), Report);
let _ = function.Call_(this, arguments, value.handle_mut(), Report, can_gc);
},
};
ScriptThread::set_user_interacting(was_user_interacting);

View file

@ -417,6 +417,10 @@ DOMInterfaces = {
'canGc': ['CloneNode', 'SetTextContent'],
},
'NodeIterator': {
'canGc': ['NextNode', 'PreviousNode'],
},
'Notification': {
'canGc': ['RequestPermission'],
},
@ -518,6 +522,10 @@ DOMInterfaces = {
'canGc': ['Encode']
},
'TreeWalker': {
'canGc': ['ParentNode', 'PreviousNode', 'NextNode', 'FirstChild', 'LastChild', 'PreviousSibling', 'NextSibling']
},
'URL': {
'weakReferenceable': True,
'canGc': ['Parse', 'SearchParams'],
@ -598,7 +606,7 @@ DOMInterfaces = {
},
'XRTest': {
'canGc': ['SimulateDeviceConnection', 'DisconnectAllDevices'],
'canGc': ['SimulateDeviceConnection', 'DisconnectAllDevices', 'SimulateUserActivation'],
},
'XRView': {

View file

@ -7931,7 +7931,7 @@ class CGCallback(CGClass):
args = args[2:]
# Record the names of all the arguments, so we can use them when we call
# the private method.
argnames = [arg.name for arg in args]
argnames = [arg.name for arg in args] + ["can_gc"]
argnamesWithThis = ["s.get_context()", "thisValue.handle()"] + argnames
argnamesWithoutThis = ["s.get_context()", "HandleValue::undefined()"] + argnames
# Now that we've recorded the argnames for our call to our private
@ -7940,6 +7940,9 @@ class CGCallback(CGClass):
args.append(Argument("ExceptionHandling", "aExceptionHandling",
"ReportExceptions"))
args.append(Argument("CanGc", "can_gc"))
method.args.append(Argument("CanGc", "can_gc"))
# And now insert our template argument.
argsWithoutThis = list(args)
args.insert(0, Argument("&T", "thisObj"))