aboutsummaryrefslogtreecommitdiffstats
path: root/components/script
diff options
context:
space:
mode:
Diffstat (limited to 'components/script')
-rw-r--r--components/script/document_loader.rs7
-rw-r--r--components/script/dom/abstractworkerglobalscope.rs5
-rw-r--r--components/script/dom/bindings/codegen/Bindings.conf38
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py30
-rw-r--r--components/script/dom/bindings/codegen/Configuration.py1
-rw-r--r--components/script/dom/bindings/htmlconstructor.rs6
-rw-r--r--components/script/dom/bindings/settings_stack.rs3
-rw-r--r--components/script/dom/create.rs11
-rw-r--r--components/script/dom/customelementregistry.rs28
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs7
-rw-r--r--components/script/dom/document.rs49
-rw-r--r--components/script/dom/domimplementation.rs7
-rw-r--r--components/script/dom/domparser.rs7
-rw-r--r--components/script/dom/element.rs38
-rw-r--r--components/script/dom/globalscope.rs6
-rw-r--r--components/script/dom/htmlaudioelement.rs3
-rw-r--r--components/script/dom/htmliframeelement.rs38
-rw-r--r--components/script/dom/htmlimageelement.rs135
-rw-r--r--components/script/dom/htmlmediaelement.rs115
-rw-r--r--components/script/dom/htmloptionelement.rs3
-rw-r--r--components/script/dom/htmlscriptelement.rs15
-rw-r--r--components/script/dom/htmlsourceelement.rs21
-rw-r--r--components/script/dom/htmltemplateelement.rs15
-rw-r--r--components/script/dom/htmlvideoelement.rs14
-rw-r--r--components/script/dom/mediaelementaudiosourcenode.rs7
-rw-r--r--components/script/dom/mediasession.rs7
-rw-r--r--components/script/dom/node.rs9
-rw-r--r--components/script/dom/range.rs66
-rw-r--r--components/script/dom/selection.rs40
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs5
-rw-r--r--components/script/dom/servoparser/async_html.rs38
-rw-r--r--components/script/dom/servoparser/html.rs3
-rw-r--r--components/script/dom/servoparser/mod.rs126
-rw-r--r--components/script/dom/window.rs6
-rw-r--r--components/script/dom/worker.rs1
-rw-r--r--components/script/dom/xmlhttprequest.rs42
-rw-r--r--components/script/microtask.rs11
-rw-r--r--components/script/script_module.rs4
-rw-r--r--components/script/script_thread.rs101
-rw-r--r--components/script/serviceworker_manager.rs26
-rw-r--r--components/script/stylesheet_loader.rs3
41 files changed, 704 insertions, 393 deletions
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs
index 2d369697303..0b2a0ab8139 100644
--- a/components/script/document_loader.rs
+++ b/components/script/document_loader.rs
@@ -14,6 +14,7 @@ use servo_url::ServoUrl;
use crate::dom::bindings::root::Dom;
use crate::dom::document::Document;
use crate::fetch::FetchCanceller;
+use crate::script_runtime::CanGc;
#[derive(Clone, Debug, JSTraceable, MallocSizeOf, PartialEq)]
pub enum LoadType {
@@ -48,9 +49,9 @@ impl LoadBlocker {
}
/// Remove this load from the associated document's list of blocking loads.
- pub fn terminate(blocker: &mut Option<LoadBlocker>) {
+ pub fn terminate(blocker: &mut Option<LoadBlocker>, can_gc: CanGc) {
if let Some(this) = blocker.as_mut() {
- this.doc.finish_load(this.load.take().unwrap());
+ this.doc.finish_load(this.load.take().unwrap(), can_gc);
}
*blocker = None;
}
@@ -59,7 +60,7 @@ impl LoadBlocker {
impl Drop for LoadBlocker {
fn drop(&mut self) {
if let Some(load) = self.load.take() {
- self.doc.finish_load(load);
+ self.doc.finish_load(load, CanGc::note());
}
}
}
diff --git a/components/script/dom/abstractworkerglobalscope.rs b/components/script/dom/abstractworkerglobalscope.rs
index b5af70a3647..1f2fe94ffcc 100644
--- a/components/script/dom/abstractworkerglobalscope.rs
+++ b/components/script/dom/abstractworkerglobalscope.rs
@@ -13,7 +13,7 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::worker::TrustedWorkerAddress;
use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::realms::enter_realm;
-use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptPort};
+use crate::script_runtime::{CanGc, CommonScriptMsg, ScriptChan, ScriptPort};
use crate::task_queue::{QueuedTaskConversion, TaskQueue};
/// A ScriptChan that can be cloned freely and will silently send a TrustedWorkerAddress with
@@ -101,6 +101,7 @@ pub trait WorkerEventLoopMethods {
pub fn run_worker_event_loop<T, WorkerMsg, Event>(
worker_scope: &T,
worker: Option<&TrustedWorkerAddress>,
+ _can_gc: CanGc,
) where
WorkerMsg: QueuedTaskConversion + Send,
T: WorkerEventLoopMethods<WorkerMsg = WorkerMsg, Event = Event>
@@ -155,7 +156,7 @@ pub fn run_worker_event_loop<T, WorkerMsg, Event>(
};
worker_scope
.upcast::<GlobalScope>()
- .perform_a_microtask_checkpoint();
+ .perform_a_microtask_checkpoint(CanGc::note());
}
worker_scope
.upcast::<GlobalScope>()
diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf
index 94137dcc6a7..50d9bb6e7c7 100644
--- a/components/script/dom/bindings/codegen/Bindings.conf
+++ b/components/script/dom/bindings/codegen/Bindings.conf
@@ -40,6 +40,7 @@ DOMInterfaces = {
'Range': {
'weakReferenceable': True,
+ 'canGc': ['CreateContextualFragment', 'ExtractContents', 'CloneContents', 'CloneRange', 'SurroundContents'],
},
'EventSource': {
@@ -70,6 +71,7 @@ DOMInterfaces = {
'Window': {
'inRealms': ['Fetch', 'GetOpener'],
+ 'canGc': ['Stop'],
},
'WorkerGlobalScope': {
@@ -90,6 +92,7 @@ DOMInterfaces = {
'HTMLMediaElement': {
'inRealms': ['Play'],
+ 'canGc': ['Play', 'Pause', 'Load', 'SetSrcObject'],
},
'BluetoothRemoteGATTDescriptor': {
@@ -180,6 +183,39 @@ DOMInterfaces = {
'GamepadHapticActuator': {
'inRealms': ['PlayEffect', 'Reset']
-}
+},
+
+'DOMParser': {
+ 'canGc': ['ParseFromString'],
+},
+
+'XMLHttpRequest': {
+ 'canGc': ['Response', 'GetResponseXML'],
+},
+
+'DOMImplementation': {
+ 'canGc': ['CreateHTMLDocument', 'CreateDocument'],
+},
+
+'HTMLTemplateElement': {
+ 'canGc': ['Content'],
+},
+
+'Element': {
+ 'canGc': ['SetInnerHTML', 'SetOuterHTML', 'InsertAdjacentHTML'],
+},
+
+'Selection': {
+ 'canGc': ['Extend', 'SetBaseAndExtent', 'SelectAllChildren', 'Collapse', 'SetPosition',
+ 'CollapseToStart', 'CollapseToEnd'],
+},
+
+'Document': {
+ 'canGc': ['Write', 'Writeln', 'Close', 'SetTitle', 'CreateElementNS', 'CreateElement', 'ImportNode'],
+},
+
+'Node': {
+ 'canGc': ['CloneNode'],
+},
}
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 46d603955ab..cf8e70441c5 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -3700,6 +3700,8 @@ class CGCallGenerator(CGThing):
args.prepend(CGGeneric("cx"))
if nativeMethodName in descriptor.inRealmMethods:
args.append(CGGeneric("InRealm::already(&AlreadyInRealm::assert_for_cx(cx))"))
+ if nativeMethodName in descriptor.canGcMethods:
+ args.append(CGGeneric("CanGc::note()"))
# Build up our actual call
self.cgRoot = CGList([], "\n")
@@ -3723,7 +3725,7 @@ class CGCallGenerator(CGThing):
]))
if hasCEReactions:
- self.cgRoot.append(CGGeneric("pop_current_element_queue();\n"))
+ self.cgRoot.append(CGGeneric("pop_current_element_queue(CanGc::note());\n"))
if isFallible:
if static:
@@ -6263,7 +6265,7 @@ class CGInterfaceTrait(CGThing):
def __init__(self, descriptor):
CGThing.__init__(self)
- def attribute_arguments(needCx, argument=None, inRealm=False):
+ def attribute_arguments(needCx, argument=None, inRealm=False, canGc=False):
if needCx:
yield "cx", "SafeJSContext"
@@ -6273,6 +6275,9 @@ class CGInterfaceTrait(CGThing):
if inRealm:
yield "_comp", "InRealm"
+ if canGc:
+ yield "_can_gc", "CanGc"
+
def members():
for m in descriptor.interface.members:
if (m.isMethod() and not m.isStatic()
@@ -6283,7 +6288,8 @@ class CGInterfaceTrait(CGThing):
infallible = 'infallible' in descriptor.getExtendedAttributes(m)
for idx, (rettype, arguments) in enumerate(m.signatures()):
arguments = method_arguments(descriptor, rettype, arguments,
- inRealm=name in descriptor.inRealmMethods)
+ inRealm=name in descriptor.inRealmMethods,
+ canGc=name in descriptor.canGcMethods)
rettype = return_type(descriptor, rettype, infallible)
yield f"{name}{'_' * idx}", arguments, rettype
elif m.isAttr() and not m.isStatic():
@@ -6292,7 +6298,8 @@ class CGInterfaceTrait(CGThing):
yield (name,
attribute_arguments(
typeNeedsCx(m.type, True),
- inRealm=name in descriptor.inRealmMethods
+ inRealm=name in descriptor.inRealmMethods,
+ canGc=name in descriptor.canGcMethods
),
return_type(descriptor, m.type, infallible))
@@ -6307,7 +6314,8 @@ class CGInterfaceTrait(CGThing):
attribute_arguments(
typeNeedsCx(m.type, False),
m.type,
- inRealm=name in descriptor.inRealmMethods
+ inRealm=name in descriptor.inRealmMethods,
+ canGc=name in descriptor.canGcMethods
),
rettype)
@@ -6324,7 +6332,8 @@ class CGInterfaceTrait(CGThing):
if not rettype.nullable():
rettype = IDLNullableType(rettype.location, rettype)
arguments = method_arguments(descriptor, rettype, arguments,
- inRealm=name in descriptor.inRealmMethods)
+ inRealm=name in descriptor.inRealmMethods,
+ canGc=name in descriptor.canGcMethods)
# If this interface 'supports named properties', then we
# should be able to access 'supported property names'
@@ -6335,7 +6344,8 @@ class CGInterfaceTrait(CGThing):
yield "SupportedPropertyNames", [], "Vec<DOMString>"
else:
arguments = method_arguments(descriptor, rettype, arguments,
- inRealm=name in descriptor.inRealmMethods)
+ inRealm=name in descriptor.inRealmMethods,
+ canGc=name in descriptor.canGcMethods)
rettype = return_type(descriptor, rettype, infallible)
yield name, arguments, rettype
@@ -7123,7 +7133,8 @@ def argument_type(descriptorProvider, ty, optional=False, defaultValue=None, var
return declType.define()
-def method_arguments(descriptorProvider, returnType, arguments, passJSBits=True, trailing=None, inRealm=False):
+def method_arguments(descriptorProvider, returnType, arguments, passJSBits=True, trailing=None,
+ inRealm=False, canGc=False):
if needCx(returnType, arguments, passJSBits):
yield "cx", "SafeJSContext"
@@ -7138,6 +7149,9 @@ def method_arguments(descriptorProvider, returnType, arguments, passJSBits=True,
if inRealm:
yield "_comp", "InRealm"
+ if canGc:
+ yield "_can_gc", "CanGc"
+
def return_type(descriptorProvider, rettype, infallible):
result = getRetvalDeclarationForType(rettype, descriptorProvider)
diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py
index 81ebe68d8bb..2f067c39256 100644
--- a/components/script/dom/bindings/codegen/Configuration.py
+++ b/components/script/dom/bindings/codegen/Configuration.py
@@ -232,6 +232,7 @@ class Descriptor(DescriptorProvider):
self.register = desc.get('register', True)
self.path = desc.get('path', pathDefault)
self.inRealmMethods = [name for name in desc.get('inRealms', [])]
+ self.canGcMethods = [name for name in desc.get('canGc', [])]
self.bindingPath = f"{getModuleFromObject(self.interface)}::{ifaceName}_Binding"
self.outerObjectHook = desc.get('outerObjectHook', 'None')
self.proxy = False
diff --git a/components/script/dom/bindings/htmlconstructor.rs b/components/script/dom/bindings/htmlconstructor.rs
index 111f78751d7..56aedc04840 100644
--- a/components/script/dom/bindings/htmlconstructor.rs
+++ b/components/script/dom/bindings/htmlconstructor.rs
@@ -51,7 +51,7 @@ use crate::dom::element::{Element, ElementCreator};
use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::window::Window;
-use crate::script_runtime::{JSContext, JSContext as SafeJSContext};
+use crate::script_runtime::{CanGc, JSContext, JSContext as SafeJSContext};
use crate::script_thread::ScriptThread;
// https://html.spec.whatwg.org/multipage/#htmlconstructor
@@ -369,8 +369,8 @@ pub fn get_constructor_object_from_local_name(
}
}
-pub fn pop_current_element_queue() {
- ScriptThread::pop_current_element_queue();
+pub fn pop_current_element_queue(can_gc: CanGc) {
+ ScriptThread::pop_current_element_queue(can_gc);
}
pub fn push_new_element_queue() {
diff --git a/components/script/dom/bindings/settings_stack.rs b/components/script/dom/bindings/settings_stack.rs
index 113c9c3d404..0e913eb3de6 100644
--- a/components/script/dom/bindings/settings_stack.rs
+++ b/components/script/dom/bindings/settings_stack.rs
@@ -11,6 +11,7 @@ use js::rust::Runtime;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::trace::JSTraceable;
use crate::dom::globalscope::GlobalScope;
+use crate::script_runtime::CanGc;
thread_local!(static STACK: RefCell<Vec<StackEntry>> = const { RefCell::new(Vec::new()) });
@@ -76,7 +77,7 @@ impl Drop for AutoEntryScript {
// Step 5
if !thread::panicking() && incumbent_global().is_none() {
- self.global.perform_a_microtask_checkpoint();
+ self.global.perform_a_microtask_checkpoint(CanGc::note());
}
}
}
diff --git a/components/script/dom/create.rs b/components/script/dom/create.rs
index 771f19189f2..e1b6bb5dd3d 100644
--- a/components/script/dom/create.rs
+++ b/components/script/dom/create.rs
@@ -86,6 +86,7 @@ use crate::dom::htmlvideoelement::HTMLVideoElement;
use crate::dom::svgelement::SVGElement;
use crate::dom::svgsvgelement::SVGSVGElement;
use crate::realms::{enter_realm, InRealm};
+use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread;
fn create_svg_element(
@@ -127,6 +128,7 @@ fn create_html_element(
creator: ElementCreator,
mode: CustomElementCreationMode,
proto: Option<HandleObject>,
+ can_gc: CanGc,
) -> DomRoot<Element> {
assert_eq!(name.ns, ns!(html));
@@ -150,7 +152,7 @@ fn create_html_element(
CustomElementCreationMode::Synchronous => {
let local_name = name.local.clone();
//TODO(jdm) Pass proto to create_element?
- return match definition.create_element(document, prefix.clone()) {
+ return match definition.create_element(document, prefix.clone(), can_gc) {
Ok(element) => {
element.set_custom_element_definition(definition.clone());
element
@@ -185,7 +187,9 @@ fn create_html_element(
element.set_custom_element_state(CustomElementState::Undefined);
match mode {
// Step 5.3
- CustomElementCreationMode::Synchronous => upgrade_element(definition, &element),
+ CustomElementCreationMode::Synchronous => {
+ upgrade_element(definition, &element, can_gc)
+ },
// Step 5.4
CustomElementCreationMode::Asynchronous => {
ScriptThread::enqueue_upgrade_reaction(&element, definition)
@@ -395,10 +399,11 @@ pub fn create_element(
creator: ElementCreator,
mode: CustomElementCreationMode,
proto: Option<HandleObject>,
+ can_gc: CanGc,
) -> DomRoot<Element> {
let prefix = name.prefix.clone();
match name.ns {
- ns!(html) => create_html_element(name, prefix, is, document, creator, mode, proto),
+ ns!(html) => create_html_element(name, prefix, is, document, creator, mode, proto, can_gc),
ns!(svg) => create_svg_element(name, prefix, document, proto),
_ => Element::new(name.local, name.ns, prefix, document, proto),
}
diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs
index d1dfa4754fe..a0dabd1300a 100644
--- a/components/script/dom/customelementregistry.rs
+++ b/components/script/dom/customelementregistry.rs
@@ -48,7 +48,7 @@ use crate::dom::promise::Promise;
use crate::dom::window::Window;
use crate::microtask::Microtask;
use crate::realms::{enter_realm, InRealm};
-use crate::script_runtime::JSContext;
+use crate::script_runtime::{CanGc, JSContext};
use crate::script_thread::ScriptThread;
/// <https://dom.spec.whatwg.org/#concept-element-custom-element-state>
@@ -718,6 +718,7 @@ impl CustomElementDefinition {
&self,
document: &Document,
prefix: Option<Prefix>,
+ can_gc: CanGc,
) -> Fallible<DomRoot<Element>> {
let window = document.window();
let cx = GlobalScope::get_cx();
@@ -738,7 +739,7 @@ impl CustomElementDefinition {
if is_execution_stack_empty() {
window
.upcast::<GlobalScope>()
- .perform_a_microtask_checkpoint();
+ .perform_a_microtask_checkpoint(can_gc);
}
rooted!(in(*cx) let element_val = ObjectValue(element.get()));
@@ -783,7 +784,7 @@ impl CustomElementDefinition {
/// <https://html.spec.whatwg.org/multipage/#concept-upgrade-an-element>
#[allow(unsafe_code)]
-pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Element) {
+pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Element, can_gc: CanGc) {
// Step 1
let state = element.get_custom_element_state();
if state != CustomElementState::Undefined && state != CustomElementState::Uncustomized {
@@ -824,7 +825,7 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
.push(ConstructionStackEntry::Element(DomRoot::from_ref(element)));
// Steps 7-8, successful case
- let result = run_upgrade_constructor(&definition.constructor, element);
+ let result = run_upgrade_constructor(&definition.constructor, element, can_gc);
// "regardless of whether the above steps threw an exception" step
definition.construction_stack.borrow_mut().pop();
@@ -897,6 +898,7 @@ pub fn upgrade_element(definition: Rc<CustomElementDefinition>, element: &Elemen
fn run_upgrade_constructor(
constructor: &Rc<CustomElementConstructor>,
element: &Element,
+ can_gc: CanGc,
) -> ErrorResult {
let window = window_from_node(element);
let cx = GlobalScope::get_cx();
@@ -929,7 +931,7 @@ fn run_upgrade_constructor(
if is_execution_stack_empty() {
window
.upcast::<GlobalScope>()
- .perform_a_microtask_checkpoint();
+ .perform_a_microtask_checkpoint(can_gc);
}
// Step 8.3
@@ -982,11 +984,11 @@ pub enum CustomElementReaction {
impl CustomElementReaction {
/// <https://html.spec.whatwg.org/multipage/#invoke-custom-element-reactions>
#[allow(unsafe_code)]
- pub fn invoke(&self, element: &Element) {
+ pub fn invoke(&self, element: &Element, can_gc: CanGc) {
// Step 2.1
match *self {
CustomElementReaction::Upgrade(ref definition) => {
- upgrade_element(definition.clone(), element)
+ upgrade_element(definition.clone(), element, can_gc)
},
CustomElementReaction::Callback(ref callback, ref arguments) => {
// We're rooted, so it's safe to hand out a handle to objects in Heap
@@ -1039,12 +1041,12 @@ impl CustomElementReactionStack {
self.stack.borrow_mut().push(ElementQueue::new());
}
- pub fn pop_current_element_queue(&self) {
+ pub fn pop_current_element_queue(&self, can_gc: CanGc) {
rooted_vec!(let mut stack);
mem::swap(&mut *stack, &mut *self.stack.borrow_mut());
if let Some(current_queue) = stack.last() {
- current_queue.invoke_reactions();
+ current_queue.invoke_reactions(can_gc);
}
stack.pop();
@@ -1054,9 +1056,9 @@ impl CustomElementReactionStack {
/// <https://html.spec.whatwg.org/multipage/#enqueue-an-element-on-the-appropriate-element-queue>
/// Step 4
- pub fn invoke_backup_element_queue(&self) {
+ pub fn invoke_backup_element_queue(&self, can_gc: CanGc) {
// Step 4.1
- self.backup_queue.invoke_reactions();
+ self.backup_queue.invoke_reactions(can_gc);
// Step 4.2
self.processing_backup_element_queue
@@ -1237,10 +1239,10 @@ impl ElementQueue {
}
/// <https://html.spec.whatwg.org/multipage/#invoke-custom-element-reactions>
- fn invoke_reactions(&self) {
+ fn invoke_reactions(&self, _can_gc: CanGc) {
// Steps 1-2
while let Some(element) = self.next_element() {
- element.invoke_reactions()
+ element.invoke_reactions(CanGc::note())
}
self.queue.borrow_mut().clear();
}
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index 62c156b55de..ab833d3000b 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -55,8 +55,8 @@ use crate::fetch::load_whole_resource;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::ScriptThreadEventCategory::WorkerEvent;
use crate::script_runtime::{
- new_child_runtime, CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext,
- Runtime, ScriptChan, ScriptPort,
+ new_child_runtime, CanGc, CommonScriptMsg, ContextForRequestInterrupt,
+ JSContext as SafeJSContext, Runtime, ScriptChan, ScriptPort,
};
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
use crate::task_source::networking::NetworkingTaskSource;
@@ -333,6 +333,7 @@ impl DedicatedWorkerGlobalScope {
gpu_id_hub: Arc<Identities>,
control_receiver: Receiver<DedicatedWorkerControlMsg>,
context_sender: Sender<ContextForRequestInterrupt>,
+ _can_gc: CanGc,
) -> JoinHandle<()> {
let serialized_worker_url = worker_url.to_string();
let top_level_browsing_context_id = TopLevelBrowsingContextId::installed();
@@ -478,7 +479,7 @@ impl DedicatedWorkerGlobalScope {
// until the event loop is destroyed,
// which happens after the closing flag is set to true.
while !scope.is_closing() {
- run_worker_event_loop(&*global, Some(&worker));
+ run_worker_event_loop(&*global, Some(&worker), CanGc::note());
}
},
reporter_name,
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index 800e4dc8824..b09d7ec19e9 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -2117,7 +2117,7 @@ impl Document {
// https://html.spec.whatwg.org/multipage/#the-end
// https://html.spec.whatwg.org/multipage/#delay-the-load-event
- pub fn finish_load(&self, load: LoadType) {
+ pub fn finish_load(&self, load: LoadType, can_gc: CanGc) {
// This does not delay the load event anymore.
debug!("Document got finish_load: {:?}", load);
self.loader.borrow_mut().finish_load(&load);
@@ -2126,7 +2126,7 @@ impl Document {
LoadType::Stylesheet(_) => {
// A stylesheet finishing to load may unblock any pending
// parsing-blocking script or deferred script.
- self.process_pending_parsing_blocking_script();
+ self.process_pending_parsing_blocking_script(can_gc);
// Step 3.
self.process_deferred_scripts();
@@ -2489,6 +2489,7 @@ impl Document {
&self,
element: &HTMLScriptElement,
result: ScriptResult,
+ can_gc: CanGc,
) {
{
let mut blocking_script = self.pending_parsing_blocking_script.borrow_mut();
@@ -2496,10 +2497,10 @@ impl Document {
assert!(&*entry.element == element);
entry.loaded(result);
}
- self.process_pending_parsing_blocking_script();
+ self.process_pending_parsing_blocking_script(can_gc);
}
- fn process_pending_parsing_blocking_script(&self) {
+ fn process_pending_parsing_blocking_script(&self, can_gc: CanGc) {
if self.script_blocking_stylesheets_count.get() > 0 {
return;
}
@@ -2512,7 +2513,7 @@ impl Document {
*self.pending_parsing_blocking_script.borrow_mut() = None;
self.get_current_parser()
.unwrap()
- .resume_with_pending_parsing_blocking_script(&element, result);
+ .resume_with_pending_parsing_blocking_script(&element, result, can_gc);
}
}
@@ -2629,7 +2630,7 @@ impl Document {
}
// https://html.spec.whatwg.org/multipage/#abort-a-document
- pub fn abort(&self) {
+ pub fn abort(&self, can_gc: CanGc) {
// We need to inhibit the loader before anything else.
self.loader.borrow_mut().inhibit_events();
@@ -2637,7 +2638,7 @@ impl Document {
for iframe in self.iter_iframes() {
if let Some(document) = iframe.GetContentDocument() {
// TODO: abort the active documents of every child browsing context.
- document.abort();
+ document.abort(CanGc::note());
// TODO: salvageable flag.
}
}
@@ -2666,7 +2667,7 @@ impl Document {
// Step 3.
if let Some(parser) = self.get_current_parser() {
self.active_parser_was_aborted.set(true);
- parser.abort();
+ parser.abort(can_gc);
self.salvageable.set(false);
}
}
@@ -3457,6 +3458,7 @@ impl Document {
referrer_policy: Option<ReferrerPolicy>,
status_code: Option<u16>,
canceller: FetchCanceller,
+ can_gc: CanGc,
) -> DomRoot<Document> {
Self::new_with_proto(
window,
@@ -3474,7 +3476,7 @@ impl Document {
referrer_policy,
status_code,
canceller,
- CanGc::note(),
+ can_gc,
)
}
@@ -3613,7 +3615,7 @@ impl Document {
}
/// <https://html.spec.whatwg.org/multipage/#appropriate-template-contents-owner-document>
- pub fn appropriate_template_contents_owner_document(&self) -> DomRoot<Document> {
+ pub fn appropriate_template_contents_owner_document(&self, can_gc: CanGc) -> DomRoot<Document> {
self.appropriate_template_contents_owner_document
.or_init(|| {
let doctype = if self.is_html_document {
@@ -3637,6 +3639,7 @@ impl Document {
None,
None,
Default::default(),
+ can_gc,
);
new_doc
.appropriate_template_contents_owner_document
@@ -4351,6 +4354,7 @@ impl DocumentMethods for Document {
&self,
mut local_name: DOMString,
options: StringOrElementCreationOptions,
+ can_gc: CanGc,
) -> Fallible<DomRoot<Element>> {
if xml_name_type(&local_name) == Invalid {
debug!("Not a valid element name");
@@ -4384,6 +4388,7 @@ impl DocumentMethods for Document {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
None,
+ can_gc,
))
}
@@ -4393,6 +4398,7 @@ impl DocumentMethods for Document {
namespace: Option<DOMString>,
qualified_name: DOMString,
options: StringOrElementCreationOptions,
+ can_gc: CanGc,
) -> Fallible<DomRoot<Element>> {
let (namespace, prefix, local_name) = validate_and_extract(namespace, &qualified_name)?;
let name = QualName::new(prefix, namespace, local_name);
@@ -4409,6 +4415,7 @@ impl DocumentMethods for Document {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
None,
+ can_gc,
))
}
@@ -4507,7 +4514,7 @@ impl DocumentMethods for Document {
}
// https://dom.spec.whatwg.org/#dom-document-importnode
- fn ImportNode(&self, node: &Node, deep: bool) -> Fallible<DomRoot<Node>> {
+ fn ImportNode(&self, node: &Node, deep: bool, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
// Step 1.
if node.is::<Document>() || node.is::<ShadowRoot>() {
return Err(Error::NotSupported);
@@ -4520,7 +4527,7 @@ impl DocumentMethods for Document {
CloneChildrenFlag::DoNotCloneChildren
};
- Ok(Node::clone(node, Some(self), clone_children))
+ Ok(Node::clone(node, Some(self), clone_children, can_gc))
}
// https://dom.spec.whatwg.org/#dom-document-adoptnode
@@ -4656,7 +4663,7 @@ impl DocumentMethods for Document {
}
// https://html.spec.whatwg.org/multipage/#document.title
- fn SetTitle(&self, title: DOMString) {
+ fn SetTitle(&self, title: DOMString, can_gc: CanGc) {
let root = match self.GetDocumentElement() {
Some(root) => root,
None => return,
@@ -4677,6 +4684,7 @@ impl DocumentMethods for Document {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
None,
+ can_gc,
);
let parent = root.upcast::<Node>();
let child = elem.upcast::<Node>();
@@ -4702,6 +4710,7 @@ impl DocumentMethods for Document {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
None,
+ can_gc,
);
head.upcast::<Node>().AppendChild(elem.upcast()).unwrap()
},
@@ -5222,7 +5231,7 @@ impl DocumentMethods for Document {
if self.has_browsing_context() {
// spec says "stop document loading",
// which is a process that does more than just abort
- self.abort();
+ self.abort(CanGc::note());
}
// Step 9
@@ -5296,7 +5305,7 @@ impl DocumentMethods for Document {
}
// https://html.spec.whatwg.org/multipage/#dom-document-write
- fn Write(&self, text: Vec<DOMString>) -> ErrorResult {
+ fn Write(&self, text: Vec<DOMString>, can_gc: CanGc) -> ErrorResult {
if !self.is_html_document() {
// Step 1.
return Err(Error::InvalidState);
@@ -5334,20 +5343,20 @@ impl DocumentMethods for Document {
// TODO: handle reload override buffer.
// Steps 6-8.
- parser.write(text);
+ parser.write(text, can_gc);
// Step 9.
Ok(())
}
// https://html.spec.whatwg.org/multipage/#dom-document-writeln
- fn Writeln(&self, mut text: Vec<DOMString>) -> ErrorResult {
+ fn Writeln(&self, mut text: Vec<DOMString>, can_gc: CanGc) -> ErrorResult {
text.push("\n".into());
- self.Write(text)
+ self.Write(text, can_gc)
}
// https://html.spec.whatwg.org/multipage/#dom-document-close
- fn Close(&self) -> ErrorResult {
+ fn Close(&self, can_gc: CanGc) -> ErrorResult {
if !self.is_html_document() {
// Step 1.
return Err(Error::InvalidState);
@@ -5367,7 +5376,7 @@ impl DocumentMethods for Document {
};
// Step 4-6.
- parser.close();
+ parser.close(can_gc);
Ok(())
}
diff --git a/components/script/dom/domimplementation.rs b/components/script/dom/domimplementation.rs
index 00224056009..9266445ef17 100644
--- a/components/script/dom/domimplementation.rs
+++ b/components/script/dom/domimplementation.rs
@@ -28,6 +28,7 @@ use crate::dom::htmltitleelement::HTMLTitleElement;
use crate::dom::node::Node;
use crate::dom::text::Text;
use crate::dom::xmldocument::XMLDocument;
+use crate::script_runtime::CanGc;
// https://dom.spec.whatwg.org/#domimplementation
#[dom_struct]
@@ -74,6 +75,7 @@ impl DOMImplementationMethods for DOMImplementation {
maybe_namespace: Option<DOMString>,
qname: DOMString,
maybe_doctype: Option<&DocumentType>,
+ can_gc: CanGc,
) -> Fallible<DomRoot<XMLDocument>> {
let win = self.document.window();
let loader = DocumentLoader::new(&self.document.loader());
@@ -108,7 +110,7 @@ impl DOMImplementationMethods for DOMImplementation {
});
match doc
.upcast::<Document>()
- .CreateElementNS(maybe_namespace, qname, options)
+ .CreateElementNS(maybe_namespace, qname, options, can_gc)
{
Err(error) => return Err(error),
Ok(elem) => Some(elem),
@@ -137,7 +139,7 @@ impl DOMImplementationMethods for DOMImplementation {
}
// https://dom.spec.whatwg.org/#dom-domimplementation-createhtmldocument
- fn CreateHTMLDocument(&self, title: Option<DOMString>) -> DomRoot<Document> {
+ fn CreateHTMLDocument(&self, title: Option<DOMString>, can_gc: CanGc) -> DomRoot<Document> {
let win = self.document.window();
let loader = DocumentLoader::new(&self.document.loader());
@@ -157,6 +159,7 @@ impl DOMImplementationMethods for DOMImplementation {
None,
None,
Default::default(),
+ can_gc,
);
{
diff --git a/components/script/dom/domparser.rs b/components/script/dom/domparser.rs
index 53325508360..0487761261f 100644
--- a/components/script/dom/domparser.rs
+++ b/components/script/dom/domparser.rs
@@ -62,6 +62,7 @@ impl DOMParserMethods for DOMParser {
&self,
s: DOMString,
ty: DOMParserBinding::SupportedType,
+ can_gc: CanGc,
) -> Fallible<DomRoot<Document>> {
let url = self.window.get_url();
let content_type = ty
@@ -87,8 +88,9 @@ impl DOMParserMethods for DOMParser {
None,
None,
Default::default(),
+ can_gc,
);
- ServoParser::parse_html_document(&document, Some(s), url);
+ ServoParser::parse_html_document(&document, Some(s), url, CanGc::note());
document.set_ready_state(DocumentReadyState::Complete);
Ok(document)
},
@@ -108,8 +110,9 @@ impl DOMParserMethods for DOMParser {
None,
None,
Default::default(),
+ can_gc,
);
- ServoParser::parse_xml_document(&document, Some(s), url);
+ ServoParser::parse_xml_document(&document, Some(s), url, CanGc::note());
document.set_ready_state(DocumentReadyState::Complete);
Ok(document)
},
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 73390e4133f..e6ea30db2c9 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -148,6 +148,7 @@ use crate::dom::validation::Validatable;
use crate::dom::validitystate::ValidationFlags;
use crate::dom::virtualmethods::{vtable_for, VirtualMethods};
use crate::dom::window::ReflowReason;
+use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread;
use crate::stylesheet_loader::StylesheetOwner;
use crate::task::TaskOnce;
@@ -262,8 +263,9 @@ impl Element {
creator: ElementCreator,
mode: CustomElementCreationMode,
proto: Option<HandleObject>,
+ can_gc: CanGc,
) -> DomRoot<Element> {
- create_element(name, is, document, creator, mode, proto)
+ create_element(name, is, document, creator, mode, proto, can_gc)
}
pub fn new_inherited(
@@ -397,7 +399,7 @@ impl Element {
}
}
- pub fn invoke_reactions(&self) {
+ pub fn invoke_reactions(&self, _can_gc: CanGc) {
loop {
rooted_vec!(let mut reactions);
match *self.rare_data_mut() {
@@ -412,7 +414,7 @@ impl Element {
}
for reaction in reactions.iter() {
- reaction.invoke(self);
+ reaction.invoke(self, CanGc::note());
}
reactions.clear();
@@ -1872,15 +1874,19 @@ impl Element {
}
// https://w3c.github.io/DOM-Parsing/#parsing
- pub fn parse_fragment(&self, markup: DOMString) -> Fallible<DomRoot<DocumentFragment>> {
+ pub fn parse_fragment(
+ &self,
+ markup: DOMString,
+ can_gc: CanGc,
+ ) -> Fallible<DomRoot<DocumentFragment>> {
// Steps 1-2.
// TODO(#11995): XML case.
- let new_children = ServoParser::parse_html_fragment(self, markup);
+ let new_children = ServoParser::parse_html_fragment(self, markup, can_gc);
// Step 3.
// See https://github.com/w3c/DOM-Parsing/issues/61.
let context_document = {
if let Some(template) = self.downcast::<HTMLTemplateElement>() {
- template.Content().upcast::<Node>().owner_doc()
+ template.Content(CanGc::note()).upcast::<Node>().owner_doc()
} else {
document_from_node(self)
}
@@ -2633,11 +2639,11 @@ impl ElementMethods for Element {
}
/// <https://w3c.github.io/DOM-Parsing/#widl-Element-innerHTML>
- fn SetInnerHTML(&self, value: DOMString) -> ErrorResult {
+ fn SetInnerHTML(&self, value: DOMString, can_gc: CanGc) -> ErrorResult {
// Step 2.
// https://github.com/w3c/DOM-Parsing/issues/1
let target = if let Some(template) = self.downcast::<HTMLTemplateElement>() {
- DomRoot::upcast(template.Content())
+ DomRoot::upcast(template.Content(can_gc))
} else {
DomRoot::from_ref(self.upcast())
};
@@ -2656,7 +2662,7 @@ impl ElementMethods for Element {
}
// Step 1.
- let frag = self.parse_fragment(value)?;
+ let frag = self.parse_fragment(value, CanGc::note())?;
Node::replace_all(Some(frag.upcast()), &target);
Ok(())
@@ -2672,7 +2678,7 @@ impl ElementMethods for Element {
}
// https://w3c.github.io/DOM-Parsing/#dom-element-outerhtml
- fn SetOuterHTML(&self, value: DOMString) -> ErrorResult {
+ fn SetOuterHTML(&self, value: DOMString, can_gc: CanGc) -> ErrorResult {
let context_document = document_from_node(self);
let context_node = self.upcast::<Node>();
// Step 1.
@@ -2697,6 +2703,7 @@ impl ElementMethods for Element {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
None,
+ can_gc,
);
DomRoot::upcast(body_elem)
},
@@ -2704,7 +2711,7 @@ impl ElementMethods for Element {
};
// Step 5.
- let frag = parent.parse_fragment(value)?;
+ let frag = parent.parse_fragment(value, CanGc::note())?;
// Step 6.
context_parent.ReplaceChild(frag.upcast(), context_node)?;
Ok(())
@@ -2862,7 +2869,12 @@ impl ElementMethods for Element {
}
// https://w3c.github.io/DOM-Parsing/#dom-element-insertadjacenthtml
- fn InsertAdjacentHTML(&self, position: DOMString, text: DOMString) -> ErrorResult {
+ fn InsertAdjacentHTML(
+ &self,
+ position: DOMString,
+ text: DOMString,
+ can_gc: CanGc,
+ ) -> ErrorResult {
// Step 1.
let position = position.parse::<AdjacentPosition>()?;
@@ -2886,7 +2898,7 @@ impl ElementMethods for Element {
Element::fragment_parsing_context(&context.owner_doc(), context.downcast::<Element>());
// Step 3.
- let fragment = context.parse_fragment(text)?;
+ let fragment = context.parse_fragment(text, can_gc)?;
// Step 4.
self.insert_adjacent(position, fragment.upcast())
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index a14a750015c..680f9e652b2 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -120,7 +120,8 @@ use crate::microtask::{Microtask, MicrotaskQueue, UserMicrotask};
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_module::{DynamicModuleList, ModuleScript, ModuleTree, ScriptFetchOptions};
use crate::script_runtime::{
- CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext, ScriptChan, ScriptPort,
+ CanGc, CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext, ScriptChan,
+ ScriptPort,
};
use crate::script_thread::{MainThreadScriptChan, ScriptThread};
use crate::security_manager::CSPViolationReporter;
@@ -2952,13 +2953,14 @@ impl GlobalScope {
}
/// Perform a microtask checkpoint.
- pub fn perform_a_microtask_checkpoint(&self) {
+ pub fn perform_a_microtask_checkpoint(&self, can_gc: CanGc) {
// Only perform the checkpoint if we're not shutting down.
if self.can_continue_running() {
self.microtask_queue.checkpoint(
GlobalScope::get_cx(),
|_| Some(DomRoot::from_ref(self)),
vec![DomRoot::from_ref(self)],
+ can_gc,
);
}
}
diff --git a/components/script/dom/htmlaudioelement.rs b/components/script/dom/htmlaudioelement.rs
index 12ed22b0839..28161f13829 100644
--- a/components/script/dom/htmlaudioelement.rs
+++ b/components/script/dom/htmlaudioelement.rs
@@ -56,7 +56,7 @@ impl HTMLAudioElement {
pub fn Audio(
window: &Window,
proto: Option<HandleObject>,
- _can_gc: CanGc,
+ can_gc: CanGc,
src: Option<DOMString>,
) -> Fallible<DomRoot<HTMLAudioElement>> {
let element = Element::create(
@@ -66,6 +66,7 @@ impl HTMLAudioElement {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
proto,
+ can_gc,
);
let audio = DomRoot::downcast::<HTMLAudioElement>(element).unwrap();
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index 73edda35b33..17c0bb9896a 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -40,6 +40,7 @@ use crate::dom::node::{
};
use crate::dom::virtualmethods::VirtualMethods;
use crate::dom::windowproxy::WindowProxy;
+use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread;
#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
@@ -114,8 +115,9 @@ impl HTMLIFrameElement {
&self,
load_data: LoadData,
replace: HistoryEntryReplacement,
+ can_gc: CanGc,
) {
- self.start_new_pipeline(load_data, PipelineType::Navigation, replace);
+ self.start_new_pipeline(load_data, PipelineType::Navigation, replace, can_gc);
}
fn start_new_pipeline(
@@ -123,6 +125,7 @@ impl HTMLIFrameElement {
mut load_data: LoadData,
pipeline_type: PipelineType,
replace: HistoryEntryReplacement,
+ can_gc: CanGc,
) {
let sandboxed = if self.is_sandboxed() {
IFrameSandboxed
@@ -146,7 +149,7 @@ impl HTMLIFrameElement {
let mut load_blocker = self.load_blocker.borrow_mut();
// Any oustanding load is finished from the point of view of the blocked
// document; the new navigation will continue blocking it.
- LoadBlocker::terminate(&mut load_blocker);
+ LoadBlocker::terminate(&mut load_blocker, can_gc);
}
if load_data.url.scheme() == "javascript" {
@@ -241,7 +244,7 @@ impl HTMLIFrameElement {
}
/// <https://html.spec.whatwg.org/multipage/#process-the-iframe-attributes>
- fn process_the_iframe_attributes(&self, mode: ProcessingMode) {
+ fn process_the_iframe_attributes(&self, mode: ProcessingMode, can_gc: CanGc) {
// > 1. If `element`'s `srcdoc` attribute is specified, then:
if self
.upcast::<Element>()
@@ -264,6 +267,7 @@ impl HTMLIFrameElement {
self.navigate_or_reload_child_browsing_context(
load_data,
HistoryEntryReplacement::Disabled,
+ can_gc,
);
return;
}
@@ -347,10 +351,10 @@ impl HTMLIFrameElement {
} else {
HistoryEntryReplacement::Disabled
};
- self.navigate_or_reload_child_browsing_context(load_data, replace);
+ self.navigate_or_reload_child_browsing_context(load_data, replace, CanGc::note());
}
- fn create_nested_browsing_context(&self) {
+ fn create_nested_browsing_context(&self, can_gc: CanGc) {
// Synchronously create a new browsing context, which will present
// `about:blank`. (This is not a navigation.)
//
@@ -389,6 +393,7 @@ impl HTMLIFrameElement {
load_data,
PipelineType::InitialAboutBlank,
HistoryEntryReplacement::Disabled,
+ can_gc,
);
}
@@ -400,7 +405,12 @@ impl HTMLIFrameElement {
self.browsing_context_id.set(None);
}
- pub fn update_pipeline_id(&self, new_pipeline_id: PipelineId, reason: UpdatePipelineIdReason) {
+ pub fn update_pipeline_id(
+ &self,
+ new_pipeline_id: PipelineId,
+ reason: UpdatePipelineIdReason,
+ can_gc: CanGc,
+ ) {
if self.pending_pipeline_id.get() != Some(new_pipeline_id) &&
reason == UpdatePipelineIdReason::Navigation
{
@@ -413,7 +423,7 @@ impl HTMLIFrameElement {
// The load blocker will be terminated for a navigation in iframe_load_event_steps.
if reason == UpdatePipelineIdReason::Traversal {
let mut blocker = self.load_blocker.borrow_mut();
- LoadBlocker::terminate(&mut blocker);
+ LoadBlocker::terminate(&mut blocker, can_gc);
}
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
@@ -478,7 +488,7 @@ impl HTMLIFrameElement {
}
/// <https://html.spec.whatwg.org/multipage/#iframe-load-event-steps> steps 1-4
- pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId) {
+ pub fn iframe_load_event_steps(&self, loaded_pipeline: PipelineId, can_gc: CanGc) {
// TODO(#9592): assert that the load blocker is present at all times when we
// can guarantee that it's created for the case of iframe.reload().
if Some(loaded_pipeline) != self.pending_pipeline_id.get() {
@@ -495,7 +505,7 @@ impl HTMLIFrameElement {
self.upcast::<EventTarget>().fire_event(atom!("load"));
let mut blocker = self.load_blocker.borrow_mut();
- LoadBlocker::terminate(&mut blocker);
+ LoadBlocker::terminate(&mut blocker, can_gc);
// TODO Step 5 - unset child document `mut iframe load` flag
}
@@ -667,7 +677,7 @@ impl VirtualMethods for HTMLIFrameElement {
// trigger the processing of iframe attributes whenever "srcdoc" attribute is set, changed or removed
if self.upcast::<Node>().is_connected_with_browsing_context() {
debug!("iframe srcdoc modified while in browsing context.");
- self.process_the_iframe_attributes(ProcessingMode::NotFirstTime);
+ self.process_the_iframe_attributes(ProcessingMode::NotFirstTime, CanGc::note());
}
},
local_name!("src") => {
@@ -681,7 +691,7 @@ impl VirtualMethods for HTMLIFrameElement {
// the child browsing context to be created.
if self.upcast::<Node>().is_connected_with_browsing_context() {
debug!("iframe src set while in browsing context.");
- self.process_the_iframe_attributes(ProcessingMode::NotFirstTime);
+ self.process_the_iframe_attributes(ProcessingMode::NotFirstTime, CanGc::note());
}
},
_ => {},
@@ -718,8 +728,8 @@ impl VirtualMethods for HTMLIFrameElement {
if this.upcast::<Node>().is_connected_with_browsing_context() {
debug!("iframe bound to browsing context.");
debug_assert!(tree_connected, "is_connected_with_bc, but not tree_connected");
- this.create_nested_browsing_context();
- this.process_the_iframe_attributes(ProcessingMode::FirstTime);
+ this.create_nested_browsing_context(CanGc::note());
+ this.process_the_iframe_attributes(ProcessingMode::FirstTime, CanGc::note());
}
}));
}
@@ -728,7 +738,7 @@ impl VirtualMethods for HTMLIFrameElement {
self.super_type().unwrap().unbind_from_tree(context);
let mut blocker = self.load_blocker.borrow_mut();
- LoadBlocker::terminate(&mut blocker);
+ LoadBlocker::terminate(&mut blocker, CanGc::note());
// https://html.spec.whatwg.org/multipage/#a-browsing-context-is-discarded
let window = window_from_node(self);
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 1a485ac8ddb..77b4f6344b1 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -332,7 +332,7 @@ pub(crate) fn image_fetch_request(
#[allow(non_snake_case)]
impl HTMLImageElement {
/// Update the current image with a valid URL.
- fn fetch_image(&self, img_url: &ServoUrl) {
+ fn fetch_image(&self, img_url: &ServoUrl, can_gc: CanGc) {
let window = window_from_node(self);
let image_cache = window.image_cache();
let sender = generate_cache_listener_for_element(self);
@@ -351,17 +351,20 @@ impl HTMLImageElement {
is_placeholder,
}) => {
if is_placeholder {
- self.process_image_response(ImageResponse::PlaceholderLoaded(image, url))
+ self.process_image_response(
+ ImageResponse::PlaceholderLoaded(image, url),
+ can_gc,
+ )
} else {
- self.process_image_response(ImageResponse::Loaded(image, url))
+ self.process_image_response(ImageResponse::Loaded(image, url), can_gc)
}
},
ImageCacheResult::Available(ImageOrMetadataAvailable::MetadataAvailable(m)) => {
- self.process_image_response(ImageResponse::MetadataLoaded(m))
+ self.process_image_response(ImageResponse::MetadataLoaded(m), can_gc)
},
ImageCacheResult::Pending(_) => (),
ImageCacheResult::ReadyForRequest(id) => self.fetch_request(img_url, id),
- ImageCacheResult::LoadError => self.process_image_response(ImageResponse::None),
+ ImageCacheResult::LoadError => self.process_image_response(ImageResponse::None, can_gc),
};
}
@@ -418,7 +421,7 @@ impl HTMLImageElement {
}
// Steps common to when an image has been loaded.
- fn handle_loaded_image(&self, image: Arc<Image>, url: ServoUrl) {
+ fn handle_loaded_image(&self, image: Arc<Image>, url: ServoUrl, can_gc: CanGc) {
self.current_request.borrow_mut().metadata = Some(ImageMetadata {
height: image.height,
width: image.width,
@@ -426,34 +429,34 @@ impl HTMLImageElement {
self.current_request.borrow_mut().final_url = Some(url);
self.current_request.borrow_mut().image = Some(image);
self.current_request.borrow_mut().state = State::CompletelyAvailable;
- LoadBlocker::terminate(&mut self.current_request.borrow_mut().blocker);
+ LoadBlocker::terminate(&mut self.current_request.borrow_mut().blocker, can_gc);
// Mark the node dirty
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
self.resolve_image_decode_promises();
}
/// Step 24 of <https://html.spec.whatwg.org/multipage/#update-the-image-data>
- fn process_image_response(&self, image: ImageResponse) {
+ fn process_image_response(&self, image: ImageResponse, can_gc: CanGc) {
// TODO: Handle multipart/x-mixed-replace
let (trigger_image_load, trigger_image_error) = match (image, self.image_request.get()) {
(ImageResponse::Loaded(image, url), ImageRequestPhase::Current) => {
- self.handle_loaded_image(image, url);
+ self.handle_loaded_image(image, url, can_gc);
(true, false)
},
(ImageResponse::PlaceholderLoaded(image, url), ImageRequestPhase::Current) => {
- self.handle_loaded_image(image, url);
+ self.handle_loaded_image(image, url, can_gc);
(false, true)
},
(ImageResponse::Loaded(image, url), ImageRequestPhase::Pending) => {
- self.abort_request(State::Unavailable, ImageRequestPhase::Pending);
+ self.abort_request(State::Unavailable, ImageRequestPhase::Pending, can_gc);
self.image_request.set(ImageRequestPhase::Current);
- self.handle_loaded_image(image, url);
+ self.handle_loaded_image(image, url, CanGc::note());
(true, false)
},
(ImageResponse::PlaceholderLoaded(image, url), ImageRequestPhase::Pending) => {
- self.abort_request(State::Unavailable, ImageRequestPhase::Pending);
+ self.abort_request(State::Unavailable, ImageRequestPhase::Pending, can_gc);
self.image_request.set(ImageRequestPhase::Current);
- self.handle_loaded_image(image, url);
+ self.handle_loaded_image(image, url, CanGc::note());
(false, true)
},
(ImageResponse::MetadataLoaded(meta), ImageRequestPhase::Current) => {
@@ -466,12 +469,12 @@ impl HTMLImageElement {
(false, false)
},
(ImageResponse::None, ImageRequestPhase::Current) => {
- self.abort_request(State::Broken, ImageRequestPhase::Current);
+ self.abort_request(State::Broken, ImageRequestPhase::Current, can_gc);
(false, true)
},
(ImageResponse::None, ImageRequestPhase::Pending) => {
- self.abort_request(State::Broken, ImageRequestPhase::Current);
- self.abort_request(State::Broken, ImageRequestPhase::Pending);
+ self.abort_request(State::Broken, ImageRequestPhase::Current, can_gc);
+ self.abort_request(State::Broken, ImageRequestPhase::Pending, CanGc::note());
self.image_request.set(ImageRequestPhase::Current);
(false, true)
},
@@ -501,6 +504,7 @@ impl HTMLImageElement {
src: USVString,
generation: u32,
selected_pixel_density: f64,
+ can_gc: CanGc,
) {
match image {
ImageResponse::Loaded(image, url) | ImageResponse::PlaceholderLoaded(image, url) => {
@@ -510,24 +514,29 @@ impl HTMLImageElement {
});
self.pending_request.borrow_mut().final_url = Some(url);
self.pending_request.borrow_mut().image = Some(image);
- self.finish_reacting_to_environment_change(src, generation, selected_pixel_density);
+ self.finish_reacting_to_environment_change(
+ src,
+ generation,
+ selected_pixel_density,
+ can_gc,
+ );
},
ImageResponse::MetadataLoaded(meta) => {
self.pending_request.borrow_mut().metadata = Some(meta);
},
ImageResponse::None => {
- self.abort_request(State::Unavailable, ImageRequestPhase::Pending);
+ self.abort_request(State::Unavailable, ImageRequestPhase::Pending, can_gc);
},
};
}
/// <https://html.spec.whatwg.org/multipage/#abort-the-image-request>
- fn abort_request(&self, state: State, request: ImageRequestPhase) {
+ fn abort_request(&self, state: State, request: ImageRequestPhase, can_gc: CanGc) {
let mut request = match request {
ImageRequestPhase::Current => self.current_request.borrow_mut(),
ImageRequestPhase::Pending => self.pending_request.borrow_mut(),
};
- LoadBlocker::terminate(&mut request.blocker);
+ LoadBlocker::terminate(&mut request.blocker, can_gc);
request.state = state;
request.image = None;
request.metadata = None;
@@ -804,18 +813,25 @@ impl HTMLImageElement {
request: &mut RefMut<ImageRequest>,
url: &ServoUrl,
src: &USVString,
+ can_gc: CanGc,
) {
request.parsed_url = Some(url.clone());
request.source_url = Some(src.clone());
request.image = None;
request.metadata = None;
let document = document_from_node(self);
- LoadBlocker::terminate(&mut request.blocker);
+ LoadBlocker::terminate(&mut request.blocker, can_gc);
request.blocker = Some(LoadBlocker::new(&document, LoadType::Image(url.clone())));
}
/// Step 13-17 of html.spec.whatwg.org/multipage/#update-the-image-data
- fn prepare_image_request(&self, url: &ServoUrl, src: &USVString, selected_pixel_density: f64) {
+ fn prepare_image_request(
+ &self,
+ url: &ServoUrl,
+ src: &USVString,
+ selected_pixel_density: f64,
+ can_gc: CanGc,
+ ) {
match self.image_request.get() {
ImageRequestPhase::Pending => {
if let Some(pending_url) = self.pending_request.borrow().parsed_url.clone() {
@@ -836,33 +852,33 @@ impl HTMLImageElement {
// Step 15 abort pending request
pending_request.image = None;
pending_request.parsed_url = None;
- LoadBlocker::terminate(&mut pending_request.blocker);
+ LoadBlocker::terminate(&mut pending_request.blocker, can_gc);
// TODO: queue a task to restart animation, if restart-animation is set
return;
}
pending_request.current_pixel_density = Some(selected_pixel_density);
self.image_request.set(ImageRequestPhase::Pending);
- self.init_image_request(&mut pending_request, url, src);
+ self.init_image_request(&mut pending_request, url, src, can_gc);
},
(_, State::Broken) | (_, State::Unavailable) => {
// Step 17
current_request.current_pixel_density = Some(selected_pixel_density);
- self.init_image_request(&mut current_request, url, src);
+ self.init_image_request(&mut current_request, url, src, can_gc);
},
(_, _) => {
// step 17
pending_request.current_pixel_density = Some(selected_pixel_density);
self.image_request.set(ImageRequestPhase::Pending);
- self.init_image_request(&mut pending_request, url, src);
+ self.init_image_request(&mut pending_request, url, src, can_gc);
},
}
},
}
- self.fetch_image(url);
+ self.fetch_image(url, CanGc::note());
}
/// Step 8-12 of html.spec.whatwg.org/multipage/#update-the-image-data
- fn update_the_image_data_sync_steps(&self) {
+ fn update_the_image_data_sync_steps(&self, can_gc: CanGc) {
let document = document_from_node(self);
let window = document.window();
let task_source = window.task_manager().dom_manipulation_task_source();
@@ -871,8 +887,8 @@ impl HTMLImageElement {
// Step 8
Some(data) => data,
None => {
- self.abort_request(State::Broken, ImageRequestPhase::Current);
- self.abort_request(State::Broken, ImageRequestPhase::Pending);
+ self.abort_request(State::Broken, ImageRequestPhase::Current, can_gc);
+ self.abort_request(State::Broken, ImageRequestPhase::Pending, CanGc::note());
// Step 9.
// FIXME(nox): Why are errors silenced here?
let _ = task_source.queue(
@@ -903,11 +919,11 @@ impl HTMLImageElement {
match parsed_url {
Ok(url) => {
// Step 13-17
- self.prepare_image_request(&url, &src, pixel_density);
+ self.prepare_image_request(&url, &src, pixel_density, can_gc);
},
Err(_) => {
- self.abort_request(State::Broken, ImageRequestPhase::Current);
- self.abort_request(State::Broken, ImageRequestPhase::Pending);
+ self.abort_request(State::Broken, ImageRequestPhase::Current, can_gc);
+ self.abort_request(State::Broken, ImageRequestPhase::Pending, CanGc::note());
// Step 12.1-12.5.
let src = src.0;
// FIXME(nox): Why are errors silenced here?
@@ -929,7 +945,7 @@ impl HTMLImageElement {
}
/// <https://html.spec.whatwg.org/multipage/#update-the-image-data>
- pub fn update_the_image_data(&self) {
+ pub fn update_the_image_data(&self, can_gc: CanGc) {
let document = document_from_node(self);
let window = document.window();
let elem = self.upcast::<Element>();
@@ -990,8 +1006,16 @@ impl HTMLImageElement {
width: image.width,
};
// Step 6.3.2 abort requests
- self.abort_request(State::CompletelyAvailable, ImageRequestPhase::Current);
- self.abort_request(State::Unavailable, ImageRequestPhase::Pending);
+ self.abort_request(
+ State::CompletelyAvailable,
+ ImageRequestPhase::Current,
+ can_gc,
+ );
+ self.abort_request(
+ State::Unavailable,
+ ImageRequestPhase::Pending,
+ CanGc::note(),
+ );
let mut current_request = self.current_request.borrow_mut();
current_request.final_url = Some(img_url.clone());
current_request.image = Some(image.clone());
@@ -1038,13 +1062,14 @@ impl HTMLImageElement {
}
/// Step 2-12 of <https://html.spec.whatwg.org/multipage/#img-environment-changes>
- fn react_to_environment_changes_sync_steps(&self, generation: u32) {
+ fn react_to_environment_changes_sync_steps(&self, generation: u32, can_gc: CanGc) {
// TODO reduce duplicacy of this code
fn generate_cache_listener_for_element(
elem: &HTMLImageElement,
selected_source: String,
selected_pixel_density: f64,
+ _can_gc: CanGc,
) -> IpcSender<PendingImageResponse> {
let trusted_node = Trusted::new(elem);
let (responder_sender, responder_receiver) = ipc::channel().unwrap();
@@ -1069,7 +1094,8 @@ impl HTMLImageElement {
// Ignore any image response for a previous request that has been discarded.
if generation == element.generation.get() {
element.process_image_response_for_environment_change(image,
- USVString::from(selected_source_clone), generation, selected_pixel_density);
+ USVString::from(selected_source_clone), generation,
+ selected_pixel_density, CanGc::note());
}
}),
&canceller,
@@ -1124,6 +1150,7 @@ impl HTMLImageElement {
&mut self.pending_request.borrow_mut(),
&img_url,
&selected_source,
+ CanGc::note(),
);
let window = window_from_node(self);
@@ -1134,6 +1161,7 @@ impl HTMLImageElement {
self,
selected_source.0.clone(),
selected_pixel_density,
+ CanGc::note(),
);
let cache_result = image_cache.track_image(
img_url.clone(),
@@ -1150,6 +1178,7 @@ impl HTMLImageElement {
selected_source,
generation,
selected_pixel_density,
+ can_gc,
)
},
ImageCacheResult::Available(ImageOrMetadataAvailable::MetadataAvailable(m)) => {
@@ -1158,6 +1187,7 @@ impl HTMLImageElement {
selected_source,
generation,
selected_pixel_density,
+ can_gc,
);
},
ImageCacheResult::LoadError => {
@@ -1166,6 +1196,7 @@ impl HTMLImageElement {
selected_source,
generation,
selected_pixel_density,
+ can_gc,
);
},
ImageCacheResult::ReadyForRequest(id) => self.fetch_request(&img_url, id),
@@ -1221,6 +1252,7 @@ impl HTMLImageElement {
src: USVString,
generation: u32,
selected_pixel_density: f64,
+ can_gc: CanGc,
) {
let this = Trusted::new(self);
let window = window_from_node(self);
@@ -1231,7 +1263,7 @@ impl HTMLImageElement {
let relevant_mutation = this.generation.get() != generation;
// Step 15.1
if relevant_mutation {
- this.abort_request(State::Unavailable, ImageRequestPhase::Pending);
+ this.abort_request(State::Unavailable, ImageRequestPhase::Pending, can_gc);
return;
}
// Step 15.2
@@ -1249,7 +1281,7 @@ impl HTMLImageElement {
// Step 15.5
mem::swap(&mut this.current_request.borrow_mut(), &mut pending_request);
- this.abort_request(State::Unavailable, ImageRequestPhase::Pending);
+ this.abort_request(State::Unavailable, ImageRequestPhase::Pending, can_gc);
}
// Step 15.6
@@ -1326,7 +1358,7 @@ impl HTMLImageElement {
pub fn Image(
window: &Window,
proto: Option<HandleObject>,
- _can_gc: CanGc,
+ can_gc: CanGc,
width: Option<u32>,
height: Option<u32>,
) -> Fallible<DomRoot<HTMLImageElement>> {
@@ -1337,6 +1369,7 @@ impl HTMLImageElement {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
proto,
+ can_gc,
);
let image = DomRoot::downcast::<HTMLImageElement>(element).unwrap();
@@ -1349,7 +1382,7 @@ impl HTMLImageElement {
// run update_the_image_data when the element is created.
// https://html.spec.whatwg.org/multipage/#when-to-obtain-images
- image.update_the_image_data();
+ image.update_the_image_data(CanGc::note());
Ok(image)
}
@@ -1415,7 +1448,7 @@ pub enum ImageElementMicrotask {
}
impl MicrotaskRunnable for ImageElementMicrotask {
- fn handler(&self) {
+ fn handler(&self, can_gc: CanGc) {
match *self {
ImageElementMicrotask::StableStateUpdateImageDataTask {
ref elem,
@@ -1424,14 +1457,14 @@ impl MicrotaskRunnable for ImageElementMicrotask {
// Step 7 of https://html.spec.whatwg.org/multipage/#update-the-image-data,
// stop here if other instances of this algorithm have been scheduled
if elem.generation.get() == *generation {
- elem.update_the_image_data_sync_steps();
+ elem.update_the_image_data_sync_steps(can_gc);
}
},
ImageElementMicrotask::EnvironmentChangesTask {
ref elem,
ref generation,
} => {
- elem.react_to_environment_changes_sync_steps(*generation);
+ elem.react_to_environment_changes_sync_steps(*generation, can_gc);
},
ImageElementMicrotask::DecodeTask {
ref elem,
@@ -1739,7 +1772,7 @@ impl VirtualMethods for HTMLImageElement {
fn adopting_steps(&self, old_doc: &Document) {
self.super_type().unwrap().adopting_steps(old_doc);
- self.update_the_image_data();
+ self.update_the_image_data(CanGc::note());
}
fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
@@ -1750,7 +1783,7 @@ impl VirtualMethods for HTMLImageElement {
&local_name!("width") |
&local_name!("crossorigin") |
&local_name!("sizes") |
- &local_name!("referrerpolicy") => self.update_the_image_data(),
+ &local_name!("referrerpolicy") => self.update_the_image_data(CanGc::note()),
_ => {},
}
}
@@ -1819,7 +1852,7 @@ impl VirtualMethods for HTMLImageElement {
// https://html.spec.whatwg.org/multipage/#relevant-mutations
if let Some(parent) = self.upcast::<Node>().GetParentElement() {
if parent.is::<HTMLPictureElement>() {
- self.update_the_image_data();
+ self.update_the_image_data(CanGc::note());
}
}
}
@@ -1832,7 +1865,7 @@ impl VirtualMethods for HTMLImageElement {
// The element is removed from a picture parent element
// https://html.spec.whatwg.org/multipage/#relevant-mutations
if context.parent.is::<HTMLPictureElement>() {
- self.update_the_image_data();
+ self.update_the_image_data(CanGc::note());
}
}
}
@@ -1861,7 +1894,7 @@ impl ImageCacheListener for HTMLImageElement {
}
fn process_image_response(&self, response: ImageResponse) {
- self.process_image_response(response);
+ self.process_image_response(response, CanGc::note());
}
}
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index 8a5889cae8f..e9c0b1e8a35 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -101,6 +101,7 @@ use crate::fetch::{create_a_potential_cors_request, FetchCanceller};
use crate::microtask::{Microtask, MicrotaskRunnable};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::realms::{enter_realm, InRealm};
+use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread;
use crate::task_source::TaskSource;
@@ -496,12 +497,12 @@ impl HTMLMediaElement {
/// we pass true to that method again.
///
/// <https://html.spec.whatwg.org/multipage/#delaying-the-load-event-flag>
- pub fn delay_load_event(&self, delay: bool) {
+ pub fn delay_load_event(&self, delay: bool, can_gc: CanGc) {
let mut blocker = self.delaying_the_load_event_flag.borrow_mut();
if delay && blocker.is_none() {
*blocker = Some(LoadBlocker::new(&document_from_node(self), LoadType::Media));
} else if !delay && blocker.is_some() {
- LoadBlocker::terminate(&mut blocker);
+ LoadBlocker::terminate(&mut blocker, can_gc);
}
}
@@ -607,7 +608,7 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#ready-states
- fn change_ready_state(&self, ready_state: ReadyState) {
+ fn change_ready_state(&self, ready_state: ReadyState, can_gc: CanGc) {
let old_ready_state = self.ready_state.get();
self.ready_state.set(ready_state);
@@ -638,7 +639,7 @@ impl HTMLMediaElement {
task!(media_reached_current_data: move || {
let this = this.root();
this.upcast::<EventTarget>().fire_event(atom!("loadeddata"));
- this.delay_load_event(false);
+ this.delay_load_event(false, can_gc);
}),
window.upcast(),
);
@@ -697,7 +698,7 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#concept-media-load-algorithm
- fn invoke_resource_selection_algorithm(&self) {
+ fn invoke_resource_selection_algorithm(&self, can_gc: CanGc) {
// Step 1.
self.network_state.set(NetworkState::NoSource);
@@ -705,7 +706,7 @@ impl HTMLMediaElement {
self.set_show_poster(true);
// Step 3.
- self.delay_load_event(true);
+ self.delay_load_event(true, can_gc);
// Step 4.
// If the resource selection mode in the synchronous section is
@@ -728,7 +729,7 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#concept-media-load-algorithm
- fn resource_selection_algorithm_sync(&self, base_url: ServoUrl) {
+ fn resource_selection_algorithm_sync(&self, base_url: ServoUrl, can_gc: CanGc) {
// Step 5.
// FIXME(ferjm): Implement blocked_on_parser logic
// https://html.spec.whatwg.org/multipage/#blocked-on-parser
@@ -765,7 +766,7 @@ impl HTMLMediaElement {
} else {
self.network_state.set(NetworkState::Empty);
// https://github.com/whatwg/html/issues/3065
- self.delay_load_event(false);
+ self.delay_load_event(false, can_gc);
return;
};
@@ -792,12 +793,12 @@ impl HTMLMediaElement {
// Step 9.obj.3.
// Note that the resource fetch algorithm itself takes care
// of the cleanup in case of failure itself.
- self.resource_fetch_algorithm(Resource::Object);
+ self.resource_fetch_algorithm(Resource::Object, can_gc);
},
Mode::Attribute(src) => {
// Step 9.attr.1.
if src.is_empty() {
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(can_gc);
return;
}
@@ -805,7 +806,7 @@ impl HTMLMediaElement {
let url_record = match base_url.join(&src) {
Ok(url) => url,
Err(_) => {
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(can_gc);
return;
},
};
@@ -816,7 +817,7 @@ impl HTMLMediaElement {
// Step 9.attr.4.
// Note that the resource fetch algorithm itself takes care
// of the cleanup in case of failure itself.
- self.resource_fetch_algorithm(Resource::Url(url_record));
+ self.resource_fetch_algorithm(Resource::Url(url_record), can_gc);
},
// Step 9.children.
Mode::Children(source) => {
@@ -826,7 +827,7 @@ impl HTMLMediaElement {
// Step 9.attr.2.
if src.is_empty() {
source.upcast::<EventTarget>().fire_event(atom!("error"));
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(can_gc);
return;
}
// Step 9.attr.3.
@@ -834,20 +835,20 @@ impl HTMLMediaElement {
Ok(url) => url,
Err(_) => {
source.upcast::<EventTarget>().fire_event(atom!("error"));
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(can_gc);
return;
},
};
// Step 9.attr.8.
- self.resource_fetch_algorithm(Resource::Url(url_record));
+ self.resource_fetch_algorithm(Resource::Url(url_record), can_gc);
},
}
}
- fn fetch_request(&self, offset: Option<u64>, seek_lock: Option<SeekLock>) {
+ fn fetch_request(&self, offset: Option<u64>, seek_lock: Option<SeekLock>, can_gc: CanGc) {
if self.resource_url.borrow().is_none() && self.blob_url.borrow().is_none() {
eprintln!("Missing request url");
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(can_gc);
return;
}
@@ -919,10 +920,10 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource
- fn resource_fetch_algorithm(&self, resource: Resource) {
- if let Err(e) = self.setup_media_player(&resource) {
+ fn resource_fetch_algorithm(&self, resource: Resource, can_gc: CanGc) {
+ if let Err(e) = self.setup_media_player(&resource, CanGc::note()) {
eprintln!("Setup media player error {:?}", e);
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(CanGc::note());
return;
}
@@ -955,7 +956,7 @@ impl HTMLMediaElement {
.media_element_task_source()
.queue(
task!(set_media_delay_load_event_flag_to_false: move || {
- this.root().delay_load_event(false);
+ this.root().delay_load_event(false, can_gc);
}),
window.upcast(),
)
@@ -974,7 +975,7 @@ impl HTMLMediaElement {
// Step 4.remote.2.
*self.resource_url.borrow_mut() = Some(url);
- self.fetch_request(None, None);
+ self.fetch_request(None, None, can_gc);
},
Resource::Object => {
if let Some(ref src_object) = *self.src_object.borrow() {
@@ -983,7 +984,7 @@ impl HTMLMediaElement {
let blob_url = URL::CreateObjectURL(&self.global(), blob);
*self.blob_url.borrow_mut() =
Some(ServoUrl::parse(&blob_url).expect("infallible"));
- self.fetch_request(None, None);
+ self.fetch_request(None, None, can_gc);
},
SrcObject::MediaStream(ref stream) => {
let tracks = &*stream.get_tracks();
@@ -998,7 +999,7 @@ impl HTMLMediaElement {
.set_stream(&track.id(), pos == tracks.len() - 1)
.is_err()
{
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(CanGc::note());
}
}
},
@@ -1011,7 +1012,7 @@ impl HTMLMediaElement {
/// Queues a task to run the [dedicated media source failure steps][steps].
///
/// [steps]: https://html.spec.whatwg.org/multipage/#dedicated-media-source-failure-steps
- fn queue_dedicated_media_source_failure_steps(&self) {
+ fn queue_dedicated_media_source_failure_steps(&self, can_gc: CanGc) {
let window = window_from_node(self);
let this = Trusted::new(self);
let generation_id = self.generation_id.get();
@@ -1056,7 +1057,7 @@ impl HTMLMediaElement {
});
// Step 7.
- this.delay_load_event(false);
+ this.delay_load_event(false, can_gc);
}),
window.upcast(),
);
@@ -1104,7 +1105,7 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#media-element-load-algorithm
- fn media_element_load_algorithm(&self) {
+ fn media_element_load_algorithm(&self, can_gc: CanGc) {
// Reset the flag that signals whether loadeddata was ever fired for
// this invokation of the load algorithm.
self.fired_loadeddata_event.set(false);
@@ -1145,7 +1146,7 @@ impl HTMLMediaElement {
// Step 6.5.
if self.ready_state.get() != ReadyState::HaveNothing {
- self.change_ready_state(ReadyState::HaveNothing);
+ self.change_ready_state(ReadyState::HaveNothing, can_gc);
}
// Step 6.6.
@@ -1185,7 +1186,7 @@ impl HTMLMediaElement {
self.autoplaying.set(true);
// Step 9.
- self.invoke_resource_selection_algorithm();
+ self.invoke_resource_selection_algorithm(CanGc::note());
// Step 10.
// FIXME(nox): Stop playback of any previously running media resource.
@@ -1245,14 +1246,14 @@ impl HTMLMediaElement {
/// Handles insertion of `source` children.
///
/// <https://html.spec.whatwg.org/multipage/#the-source-element:nodes-are-inserted>
- pub fn handle_source_child_insertion(&self) {
+ pub fn handle_source_child_insertion(&self, can_gc: CanGc) {
if self.upcast::<Element>().has_attribute(&local_name!("src")) {
return;
}
if self.network_state.get() != NetworkState::Empty {
return;
}
- self.media_element_load_algorithm();
+ self.media_element_load_algorithm(can_gc);
}
// https://html.spec.whatwg.org/multipage/#dom-media-seek
@@ -1351,7 +1352,7 @@ impl HTMLMediaElement {
}
}
- fn setup_media_player(&self, resource: &Resource) -> Result<(), ()> {
+ fn setup_media_player(&self, resource: &Resource, _can_gc: CanGc) -> Result<(), ()> {
let stream_type = match *resource {
Resource::Object => {
if let Some(ref src_object) = *self.src_object.borrow() {
@@ -1402,7 +1403,7 @@ impl HTMLMediaElement {
let this = trusted_node.clone();
if let Err(err) = task_source.queue_with_canceller(
task!(handle_player_event: move || {
- this.root().handle_player_event(&event);
+ this.root().handle_player_event(&event, CanGc::note());
}),
&canceller,
) {
@@ -1495,14 +1496,14 @@ impl HTMLMediaElement {
}
}
- fn handle_player_event(&self, event: &PlayerEvent) {
+ fn handle_player_event(&self, event: &PlayerEvent, can_gc: CanGc) {
match *event {
PlayerEvent::EndOfStream => {
// https://html.spec.whatwg.org/multipage/#media-data-processing-steps-list
// => "If the media data can be fetched but is found by inspection to be in
// an unsupported format, or can otherwise not be rendered at all"
if self.ready_state.get() < ReadyState::HaveMetadata {
- self.queue_dedicated_media_source_failure_steps();
+ self.queue_dedicated_media_source_failure_steps(can_gc);
} else {
// https://html.spec.whatwg.org/multipage/#reaches-the-end
match self.direction_of_playback() {
@@ -1548,7 +1549,7 @@ impl HTMLMediaElement {
);
// https://html.spec.whatwg.org/multipage/#dom-media-have_current_data
- self.change_ready_state(ReadyState::HaveCurrentData);
+ self.change_ready_state(ReadyState::HaveCurrentData, can_gc);
}
},
@@ -1592,7 +1593,7 @@ impl HTMLMediaElement {
self.network_state.set(NetworkState::Idle);
// 4. Set the element's delaying-the-load-event flag to false. This stops delaying the load event.
- self.delay_load_event(false);
+ self.delay_load_event(false, can_gc);
// 5. Fire an event named error at the media element.
self.upcast::<EventTarget>().fire_event(atom!("error"));
@@ -1752,7 +1753,7 @@ impl HTMLMediaElement {
}
// Step 6.
- self.change_ready_state(ReadyState::HaveMetadata);
+ self.change_ready_state(ReadyState::HaveMetadata, can_gc);
// Step 7.
let mut jumped = false;
@@ -1822,7 +1823,7 @@ impl HTMLMediaElement {
}
},
PlayerEvent::EnoughData => {
- self.change_ready_state(ReadyState::HaveEnoughData);
+ self.change_ready_state(ReadyState::HaveEnoughData, can_gc);
// The player has enough data and it is asking us to stop pushing
// bytes, so we cancel the ongoing fetch request iff we are able
@@ -1855,7 +1856,7 @@ impl HTMLMediaElement {
));
},
PlayerEvent::SeekData(p, ref seek_lock) => {
- self.fetch_request(Some(p), Some(seek_lock.clone()));
+ self.fetch_request(Some(p), Some(seek_lock.clone()), can_gc);
},
PlayerEvent::SeekDone(_) => {
// Continuation of
@@ -1874,7 +1875,7 @@ impl HTMLMediaElement {
PlaybackState::Paused => {
media_session_playback_state = MediaSessionPlaybackState::Paused;
if self.ready_state.get() == ReadyState::HaveMetadata {
- self.change_ready_state(ReadyState::HaveEnoughData);
+ self.change_ready_state(ReadyState::HaveEnoughData, can_gc);
}
},
PlaybackState::Playing => {
@@ -1984,13 +1985,13 @@ impl HTMLMediaElement {
/// selected by the servo-media Player instance. However, in some cases, like
/// the WebAudio MediaElementAudioSourceNode, we need to set a custom audio
/// renderer.
- pub fn set_audio_renderer(&self, audio_renderer: Arc<Mutex<dyn AudioRenderer>>) {
+ pub fn set_audio_renderer(&self, audio_renderer: Arc<Mutex<dyn AudioRenderer>>, can_gc: CanGc) {
*self.audio_renderer.borrow_mut() = Some(audio_renderer);
if let Some(ref player) = *self.player.borrow() {
if let Err(e) = player.lock().unwrap().stop() {
eprintln!("Could not stop player {:?}", e);
}
- self.media_element_load_algorithm();
+ self.media_element_load_algorithm(can_gc);
}
}
@@ -2141,9 +2142,9 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#dom-media-srcobject
- fn SetSrcObject(&self, value: Option<MediaStreamOrBlob>) {
+ fn SetSrcObject(&self, value: Option<MediaStreamOrBlob>, can_gc: CanGc) {
*self.src_object.borrow_mut() = value.map(|value| value.into());
- self.media_element_load_algorithm();
+ self.media_element_load_algorithm(can_gc);
}
// https://html.spec.whatwg.org/multipage/#attr-media-preload
@@ -2158,8 +2159,8 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#dom-media-load
- fn Load(&self) {
- self.media_element_load_algorithm();
+ fn Load(&self, can_gc: CanGc) {
+ self.media_element_load_algorithm(can_gc);
}
// https://html.spec.whatwg.org/multipage/#dom-navigator-canplaytype
@@ -2177,7 +2178,7 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#dom-media-play
- fn Play(&self, comp: InRealm) -> Rc<Promise> {
+ fn Play(&self, comp: InRealm, can_gc: CanGc) -> Rc<Promise> {
let promise = Promise::new_in_current_realm(comp);
// Step 1.
// FIXME(nox): Reject promise if not allowed to play.
@@ -2197,7 +2198,7 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
// Step 4.
if self.network_state.get() == NetworkState::Empty {
- self.invoke_resource_selection_algorithm();
+ self.invoke_resource_selection_algorithm(can_gc);
}
// Step 5.
@@ -2267,10 +2268,10 @@ impl HTMLMediaElementMethods for HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#dom-media-pause
- fn Pause(&self) {
+ fn Pause(&self, can_gc: CanGc) {
// Step 1
if self.network_state.get() == NetworkState::Empty {
- self.invoke_resource_selection_algorithm();
+ self.invoke_resource_selection_algorithm(can_gc);
}
// Step 2
@@ -2489,7 +2490,7 @@ impl VirtualMethods for HTMLMediaElement {
if mutation.new_value(attr).is_none() {
return;
}
- self.media_element_load_algorithm();
+ self.media_element_load_algorithm(CanGc::note());
},
local_name!("controls") => {
if mutation.new_value(attr).is_some() {
@@ -2552,7 +2553,7 @@ pub enum MediaElementMicrotask {
}
impl MicrotaskRunnable for MediaElementMicrotask {
- fn handler(&self) {
+ fn handler(&self, can_gc: CanGc) {
match self {
&MediaElementMicrotask::ResourceSelectionTask {
ref elem,
@@ -2560,7 +2561,7 @@ impl MicrotaskRunnable for MediaElementMicrotask {
ref base_url,
} => {
if generation_id == elem.generation_id.get() {
- elem.resource_selection_algorithm_sync(base_url.clone());
+ elem.resource_selection_algorithm_sync(base_url.clone(), can_gc);
}
},
MediaElementMicrotask::PauseIfNotInDocumentTask { elem } => {
@@ -2752,7 +2753,7 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
if let Some(ref mut current_fetch_context) = *elem.current_fetch_context.borrow_mut() {
current_fetch_context.cancel(CancelReason::Error);
}
- elem.queue_dedicated_media_source_failure_steps();
+ elem.queue_dedicated_media_source_failure_steps(CanGc::note());
}
}
@@ -2878,13 +2879,13 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
elem.network_state.set(NetworkState::Idle);
// Step 4.
- elem.delay_load_event(false);
+ elem.delay_load_event(false, CanGc::note());
// Step 5
elem.upcast::<EventTarget>().fire_event(atom!("error"));
} else {
// => "If the media data cannot be fetched at all..."
- elem.queue_dedicated_media_source_failure_steps();
+ elem.queue_dedicated_media_source_failure_steps(CanGc::note());
}
}
diff --git a/components/script/dom/htmloptionelement.rs b/components/script/dom/htmloptionelement.rs
index e4916093fcb..29bf795a0f9 100644
--- a/components/script/dom/htmloptionelement.rs
+++ b/components/script/dom/htmloptionelement.rs
@@ -87,7 +87,7 @@ impl HTMLOptionElement {
pub fn Option(
window: &Window,
proto: Option<HandleObject>,
- _can_gc: CanGc,
+ can_gc: CanGc,
text: DOMString,
value: Option<DOMString>,
default_selected: bool,
@@ -100,6 +100,7 @@ impl HTMLOptionElement {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Synchronous,
proto,
+ can_gc,
);
let option = DomRoot::downcast::<HTMLOptionElement>(element).unwrap();
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index ff5ca63c0eb..f814ef47fa9 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -66,6 +66,7 @@ use crate::realms::enter_realm;
use crate::script_module::{
fetch_external_module_script, fetch_inline_module_script, ModuleOwner, ScriptFetchOptions,
};
+use crate::script_runtime::CanGc;
use crate::task::TaskCanceller;
use crate::task_source::dom_manipulation::DOMManipulationTaskSource;
use crate::task_source::{TaskSource, TaskSourceName};
@@ -304,6 +305,7 @@ fn finish_fetching_a_classic_script(
script_kind: ExternalScriptKind,
url: ServoUrl,
load: ScriptResult,
+ can_gc: CanGc,
) {
// Step 11, Asynchronously complete this algorithm with script,
// which refers to step 26.6 "When the chosen algorithm asynchronously completes",
@@ -315,11 +317,11 @@ fn finish_fetching_a_classic_script(
ExternalScriptKind::AsapInOrder => document.asap_in_order_script_loaded(elem, load),
ExternalScriptKind::Deferred => document.deferred_script_loaded(elem, load),
ExternalScriptKind::ParsingBlocking => {
- document.pending_parsing_blocking_script_loaded(elem, load)
+ document.pending_parsing_blocking_script_loaded(elem, load, can_gc)
},
}
- document.finish_load(LoadType::Script(url));
+ document.finish_load(LoadType::Script(url), CanGc::note());
}
pub type ScriptResult = Result<ScriptOrigin, NoTrace<NetworkError>>;
@@ -397,6 +399,7 @@ impl FetchResponseListener for ClassicContext {
self.kind,
self.url.clone(),
Err(NoTrace(err.clone())),
+ CanGc::note(),
);
return;
},
@@ -457,7 +460,13 @@ impl FetchResponseListener for ClassicContext {
self.fetch_options.clone(),
ScriptType::Classic,
);
- finish_fetching_a_classic_script(&elem, self.kind, self.url.clone(), Ok(load));
+ finish_fetching_a_classic_script(
+ &elem,
+ self.kind,
+ self.url.clone(),
+ Ok(load),
+ CanGc::note(),
+ );
//}
}
diff --git a/components/script/dom/htmlsourceelement.rs b/components/script/dom/htmlsourceelement.rs
index 0ef9d96df2d..e50ad5c131a 100644
--- a/components/script/dom/htmlsourceelement.rs
+++ b/components/script/dom/htmlsourceelement.rs
@@ -19,6 +19,7 @@ use crate::dom::htmlimageelement::HTMLImageElement;
use crate::dom::htmlmediaelement::HTMLMediaElement;
use crate::dom::node::{BindContext, Node, UnbindContext};
use crate::dom::virtualmethods::VirtualMethods;
+use crate::script_runtime::CanGc;
#[dom_struct]
pub struct HTMLSourceElement {
@@ -54,10 +55,11 @@ impl HTMLSourceElement {
fn iterate_next_html_image_element_siblings(
next_siblings_iterator: impl Iterator<Item = Root<Dom<Node>>>,
+ _can_gc: CanGc,
) {
for next_sibling in next_siblings_iterator {
if let Some(html_image_element_sibling) = next_sibling.downcast::<HTMLImageElement>() {
- html_image_element_sibling.update_the_image_data();
+ html_image_element_sibling.update_the_image_data(CanGc::note());
}
}
}
@@ -76,7 +78,10 @@ impl VirtualMethods for HTMLSourceElement {
&local_name!("media") |
&local_name!("type") => {
let next_sibling_iterator = self.upcast::<Node>().following_siblings();
- HTMLSourceElement::iterate_next_html_image_element_siblings(next_sibling_iterator);
+ HTMLSourceElement::iterate_next_html_image_element_siblings(
+ next_sibling_iterator,
+ CanGc::note(),
+ );
},
_ => {},
}
@@ -87,17 +92,23 @@ impl VirtualMethods for HTMLSourceElement {
self.super_type().unwrap().bind_to_tree(context);
let parent = self.upcast::<Node>().GetParentNode().unwrap();
if let Some(media) = parent.downcast::<HTMLMediaElement>() {
- media.handle_source_child_insertion();
+ media.handle_source_child_insertion(CanGc::note());
}
let next_sibling_iterator = self.upcast::<Node>().following_siblings();
- HTMLSourceElement::iterate_next_html_image_element_siblings(next_sibling_iterator);
+ HTMLSourceElement::iterate_next_html_image_element_siblings(
+ next_sibling_iterator,
+ CanGc::note(),
+ );
}
fn unbind_from_tree(&self, context: &UnbindContext) {
self.super_type().unwrap().unbind_from_tree(context);
if let Some(next_sibling) = context.next_sibling {
let next_sibling_iterator = next_sibling.inclusively_following_siblings();
- HTMLSourceElement::iterate_next_html_image_element_siblings(next_sibling_iterator);
+ HTMLSourceElement::iterate_next_html_image_element_siblings(
+ next_sibling_iterator,
+ CanGc::note(),
+ );
}
}
}
diff --git a/components/script/dom/htmltemplateelement.rs b/components/script/dom/htmltemplateelement.rs
index fcfd06ad74d..02b8358fd0b 100644
--- a/components/script/dom/htmltemplateelement.rs
+++ b/components/script/dom/htmltemplateelement.rs
@@ -16,6 +16,7 @@ use crate::dom::documentfragment::DocumentFragment;
use crate::dom::htmlelement::HTMLElement;
use crate::dom::node::{document_from_node, CloneChildrenFlag, Node};
use crate::dom::virtualmethods::VirtualMethods;
+use crate::script_runtime::CanGc;
#[dom_struct]
pub struct HTMLTemplateElement {
@@ -59,10 +60,10 @@ impl HTMLTemplateElement {
impl HTMLTemplateElementMethods for HTMLTemplateElement {
/// <https://html.spec.whatwg.org/multipage/#dom-template-content>
- fn Content(&self) -> DomRoot<DocumentFragment> {
+ fn Content(&self, can_gc: CanGc) -> DomRoot<DocumentFragment> {
self.contents.or_init(|| {
let doc = document_from_node(self);
- doc.appropriate_template_contents_owner_document()
+ doc.appropriate_template_contents_owner_document(can_gc)
.CreateDocumentFragment()
})
}
@@ -77,9 +78,10 @@ impl VirtualMethods for HTMLTemplateElement {
fn adopting_steps(&self, old_doc: &Document) {
self.super_type().unwrap().adopting_steps(old_doc);
// Step 1.
- let doc = document_from_node(self).appropriate_template_contents_owner_document();
+ let doc =
+ document_from_node(self).appropriate_template_contents_owner_document(CanGc::note());
// Step 2.
- Node::adopt(self.Content().upcast(), &doc);
+ Node::adopt(self.Content(CanGc::note()).upcast(), &doc);
}
/// <https://html.spec.whatwg.org/multipage/#the-template-element:concept-node-clone-ext>
@@ -98,13 +100,14 @@ impl VirtualMethods for HTMLTemplateElement {
}
let copy = copy.downcast::<HTMLTemplateElement>().unwrap();
// Steps 2-3.
- let copy_contents = DomRoot::upcast::<Node>(copy.Content());
+ let copy_contents = DomRoot::upcast::<Node>(copy.Content(CanGc::note()));
let copy_contents_doc = copy_contents.owner_doc();
- for child in self.Content().upcast::<Node>().children() {
+ for child in self.Content(CanGc::note()).upcast::<Node>().children() {
let copy_child = Node::clone(
&child,
Some(&copy_contents_doc),
CloneChildrenFlag::CloneChildren,
+ CanGc::note(),
);
copy_contents.AppendChild(&copy_child).unwrap();
}
diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs
index b09503627c5..61ee1a75e2e 100644
--- a/components/script/dom/htmlvideoelement.rs
+++ b/components/script/dom/htmlvideoelement.rs
@@ -42,6 +42,7 @@ use crate::dom::virtualmethods::VirtualMethods;
use crate::fetch::FetchCanceller;
use crate::image_listener::{generate_cache_listener_for_element, ImageCacheListener};
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
+use crate::script_runtime::CanGc;
const DEFAULT_WIDTH: u32 = 300;
const DEFAULT_HEIGHT: u32 = 150;
@@ -137,7 +138,7 @@ impl HTMLVideoElement {
}
/// <https://html.spec.whatwg.org/multipage/#poster-frame>
- fn fetch_poster_frame(&self, poster_url: &str) {
+ fn fetch_poster_frame(&self, poster_url: &str, can_gc: CanGc) {
// Step 1.
let cancel_receiver = self.poster_frame_canceller.borrow_mut().initialize();
self.generation_id.set(self.generation_id.get() + 1);
@@ -176,7 +177,7 @@ impl HTMLVideoElement {
self.process_image_response(ImageResponse::Loaded(image, url));
},
ImageCacheResult::ReadyForRequest(id) => {
- self.do_fetch_poster_frame(poster_url, id, cancel_receiver)
+ self.do_fetch_poster_frame(poster_url, id, cancel_receiver, can_gc)
},
_ => (),
}
@@ -188,6 +189,7 @@ impl HTMLVideoElement {
poster_url: ServoUrl,
id: PendingImageId,
cancel_receiver: ipc::IpcReceiver<()>,
+ can_gc: CanGc,
) {
// Continuation of step 4.
let document = document_from_node(self);
@@ -205,7 +207,7 @@ impl HTMLVideoElement {
// (which triggers no media load algorithm unless a explicit call to .load() is done)
// will block the document's load event forever.
let mut blocker = self.load_blocker.borrow_mut();
- LoadBlocker::terminate(&mut blocker);
+ LoadBlocker::terminate(&mut blocker, can_gc);
*blocker = Some(LoadBlocker::new(
&document_from_node(self),
LoadType::Image(poster_url.clone()),
@@ -280,7 +282,7 @@ impl VirtualMethods for HTMLVideoElement {
if let Some(new_value) = mutation.new_value(attr) {
if attr.local_name() == &local_name!("poster") {
- self.fetch_poster_frame(&new_value);
+ self.fetch_poster_frame(&new_value, CanGc::note());
}
}
}
@@ -296,13 +298,13 @@ impl ImageCacheListener for HTMLVideoElement {
ImageResponse::Loaded(image, url) => {
debug!("Loaded poster image for video element: {:?}", url);
self.htmlmediaelement.process_poster_image_loaded(image);
- LoadBlocker::terminate(&mut self.load_blocker.borrow_mut());
+ LoadBlocker::terminate(&mut self.load_blocker.borrow_mut(), CanGc::note());
},
ImageResponse::MetadataLoaded(..) => {},
// The image cache may have loaded a placeholder for an invalid poster url
ImageResponse::PlaceholderLoaded(..) | ImageResponse::None => {
// A failed load should unblock the document load.
- LoadBlocker::terminate(&mut self.load_blocker.borrow_mut());
+ LoadBlocker::terminate(&mut self.load_blocker.borrow_mut(), CanGc::note());
},
}
}
diff --git a/components/script/dom/mediaelementaudiosourcenode.rs b/components/script/dom/mediaelementaudiosourcenode.rs
index 7eb4486e8a4..c1938479e3f 100644
--- a/components/script/dom/mediaelementaudiosourcenode.rs
+++ b/components/script/dom/mediaelementaudiosourcenode.rs
@@ -32,6 +32,7 @@ impl MediaElementAudioSourceNode {
fn new_inherited(
context: &AudioContext,
media_element: &HTMLMediaElement,
+ can_gc: CanGc,
) -> Fallible<MediaElementAudioSourceNode> {
let node = AudioNode::new_inherited(
AudioNodeInit::MediaElementSourceNode,
@@ -45,7 +46,7 @@ impl MediaElementAudioSourceNode {
MediaElementSourceNodeMessage::GetAudioRenderer(sender),
));
let audio_renderer = receiver.recv().unwrap();
- media_element.set_audio_renderer(audio_renderer);
+ media_element.set_audio_renderer(audio_renderer, can_gc);
let media_element = Dom::from_ref(media_element);
Ok(MediaElementAudioSourceNode {
node,
@@ -69,12 +70,12 @@ impl MediaElementAudioSourceNode {
media_element: &HTMLMediaElement,
can_gc: CanGc,
) -> Fallible<DomRoot<MediaElementAudioSourceNode>> {
- let node = MediaElementAudioSourceNode::new_inherited(context, media_element)?;
+ let node = MediaElementAudioSourceNode::new_inherited(context, media_element, can_gc)?;
Ok(reflect_dom_object_with_proto(
Box::new(node),
window,
proto,
- can_gc,
+ CanGc::note(),
))
}
diff --git a/components/script/dom/mediasession.rs b/components/script/dom/mediasession.rs
index 1f0e3392436..6fc045ca3eb 100644
--- a/components/script/dom/mediasession.rs
+++ b/components/script/dom/mediasession.rs
@@ -28,6 +28,7 @@ use crate::dom::htmlmediaelement::HTMLMediaElement;
use crate::dom::mediametadata::MediaMetadata;
use crate::dom::window::Window;
use crate::realms::{enter_realm, InRealm};
+use crate::script_runtime::CanGc;
#[dom_struct]
pub struct MediaSession {
@@ -67,7 +68,7 @@ impl MediaSession {
self.media_instance.set(Some(media_instance));
}
- pub fn handle_action(&self, action: MediaSessionActionType) {
+ pub fn handle_action(&self, action: MediaSessionActionType, can_gc: CanGc) {
debug!("Handle media session action {:?}", action);
if let Some(handler) = self.action_handlers.borrow().get(&action) {
@@ -82,10 +83,10 @@ impl MediaSession {
match action {
MediaSessionActionType::Play => {
let realm = enter_realm(self);
- media.Play(InRealm::Entered(&realm));
+ media.Play(InRealm::Entered(&realm), can_gc);
},
MediaSessionActionType::Pause => {
- media.Pause();
+ media.Pause(can_gc);
},
MediaSessionActionType::SeekBackward => {},
MediaSessionActionType::SeekForward => {},
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index f167b75a81d..6122db3221a 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -2240,6 +2240,7 @@ impl Node {
node: &Node,
maybe_doc: Option<&Document>,
clone_children: CloneChildrenFlag,
+ can_gc: CanGc,
) -> DomRoot<Node> {
// Step 1.
let document = match maybe_doc {
@@ -2306,6 +2307,7 @@ impl Node {
None,
document.status_code(),
Default::default(),
+ CanGc::note(),
);
DomRoot::upcast::<Node>(document)
},
@@ -2323,6 +2325,7 @@ impl Node {
ElementCreator::ScriptCreated,
CustomElementCreationMode::Asynchronous,
None,
+ can_gc,
);
DomRoot::upcast::<Node>(element)
},
@@ -2366,7 +2369,8 @@ impl Node {
// Step 6.
if clone_children == CloneChildrenFlag::CloneChildren {
for child in node.children() {
- let child_copy = Node::clone(&child, Some(&document), clone_children);
+ let child_copy =
+ Node::clone(&child, Some(&document), clone_children, CanGc::note());
let _inserted_node = Node::pre_insert(&child_copy, &copy, None);
}
}
@@ -2816,7 +2820,7 @@ impl NodeMethods for Node {
}
/// <https://dom.spec.whatwg.org/#dom-node-clonenode>
- fn CloneNode(&self, deep: bool) -> Fallible<DomRoot<Node>> {
+ fn CloneNode(&self, deep: bool, can_gc: CanGc) -> Fallible<DomRoot<Node>> {
if deep && self.is::<ShadowRoot>() {
return Err(Error::NotSupported);
}
@@ -2828,6 +2832,7 @@ impl NodeMethods for Node {
} else {
CloneChildrenFlag::DoNotCloneChildren
},
+ can_gc,
))
}
diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs
index f2b828927cb..d686da407aa 100644
--- a/components/script/dom/range.rs
+++ b/components/script/dom/range.rs
@@ -87,6 +87,7 @@ impl Range {
start_offset: u32,
end_container: &Node,
end_offset: u32,
+ can_gc: CanGc,
) -> DomRoot<Range> {
Self::new_with_proto(
document,
@@ -95,7 +96,7 @@ impl Range {
start_offset,
end_container,
end_offset,
- CanGc::note(),
+ can_gc,
)
}
@@ -482,7 +483,7 @@ impl RangeMethods for Range {
}
/// <https://dom.spec.whatwg.org/#dom-range-clonerange>
- fn CloneRange(&self) -> DomRoot<Range> {
+ fn CloneRange(&self, can_gc: CanGc) -> DomRoot<Range> {
let start_node = self.start_container();
let owner_doc = start_node.owner_doc();
Range::new(
@@ -491,6 +492,7 @@ impl RangeMethods for Range {
self.start_offset(),
&self.end_container(),
self.end_offset(),
+ can_gc,
)
}
@@ -552,7 +554,7 @@ impl RangeMethods for Range {
/// <https://dom.spec.whatwg.org/#dom-range-clonecontents>
/// <https://dom.spec.whatwg.org/#concept-range-clone>
- fn CloneContents(&self) -> Fallible<DomRoot<DocumentFragment>> {
+ fn CloneContents(&self, can_gc: CanGc) -> Fallible<DomRoot<DocumentFragment>> {
// Step 3.
let start_node = self.start_container();
let start_offset = self.start_offset();
@@ -598,7 +600,7 @@ impl RangeMethods for Range {
fragment.upcast::<Node>().AppendChild(&clone)?;
} else {
// Step 14.1.
- let clone = child.CloneNode(/* deep */ false)?;
+ let clone = child.CloneNode(/* deep */ false, CanGc::note())?;
// Step 14.2.
fragment.upcast::<Node>().AppendChild(&clone)?;
// Step 14.3.
@@ -608,9 +610,10 @@ impl RangeMethods for Range {
start_offset,
&child,
child.len(),
+ can_gc,
);
// Step 14.4.
- let subfragment = subrange.CloneContents()?;
+ let subfragment = subrange.CloneContents(CanGc::note())?;
// Step 14.5.
clone.AppendChild(subfragment.upcast())?;
}
@@ -619,7 +622,7 @@ impl RangeMethods for Range {
// Step 15.
for child in contained_children {
// Step 15.1.
- let clone = child.CloneNode(/* deep */ true)?;
+ let clone = child.CloneNode(/* deep */ true, CanGc::note())?;
// Step 15.2.
fragment.upcast::<Node>().AppendChild(&clone)?;
}
@@ -635,13 +638,20 @@ impl RangeMethods for Range {
fragment.upcast::<Node>().AppendChild(&clone)?;
} else {
// Step 17.1.
- let clone = child.CloneNode(/* deep */ false)?;
+ let clone = child.CloneNode(/* deep */ false, CanGc::note())?;
// Step 17.2.
fragment.upcast::<Node>().AppendChild(&clone)?;
// Step 17.3.
- let subrange = Range::new(&clone.owner_doc(), &child, 0, &end_node, end_offset);
+ let subrange = Range::new(
+ &clone.owner_doc(),
+ &child,
+ 0,
+ &end_node,
+ end_offset,
+ CanGc::note(),
+ );
// Step 17.4.
- let subfragment = subrange.CloneContents()?;
+ let subfragment = subrange.CloneContents(CanGc::note())?;
// Step 17.5.
clone.AppendChild(subfragment.upcast())?;
}
@@ -653,7 +663,7 @@ impl RangeMethods for Range {
/// <https://dom.spec.whatwg.org/#dom-range-extractcontents>
/// <https://dom.spec.whatwg.org/#concept-range-extract>
- fn ExtractContents(&self) -> Fallible<DomRoot<DocumentFragment>> {
+ fn ExtractContents(&self, can_gc: CanGc) -> Fallible<DomRoot<DocumentFragment>> {
// Step 3.
let start_node = self.start_container();
let start_offset = self.start_offset();
@@ -671,7 +681,7 @@ impl RangeMethods for Range {
if end_node == start_node {
if let Some(end_data) = end_node.downcast::<CharacterData>() {
// Step 4.1.
- let clone = end_node.CloneNode(/* deep */ true)?;
+ let clone = end_node.CloneNode(/* deep */ true, CanGc::note())?;
// Step 4.2.
let text = end_data.SubstringData(start_offset, end_offset - start_offset);
clone
@@ -712,7 +722,7 @@ impl RangeMethods for Range {
if let Some(start_data) = child.downcast::<CharacterData>() {
assert!(child == start_node);
// Step 15.1.
- let clone = start_node.CloneNode(/* deep */ true)?;
+ let clone = start_node.CloneNode(/* deep */ true, CanGc::note())?;
// Step 15.2.
let text = start_data.SubstringData(start_offset, start_node.len() - start_offset);
clone
@@ -729,7 +739,7 @@ impl RangeMethods for Range {
)?;
} else {
// Step 16.1.
- let clone = child.CloneNode(/* deep */ false)?;
+ let clone = child.CloneNode(/* deep */ false, CanGc::note())?;
// Step 16.2.
fragment.upcast::<Node>().AppendChild(&clone)?;
// Step 16.3.
@@ -739,9 +749,10 @@ impl RangeMethods for Range {
start_offset,
&child,
child.len(),
+ can_gc,
);
// Step 16.4.
- let subfragment = subrange.ExtractContents()?;
+ let subfragment = subrange.ExtractContents(CanGc::note())?;
// Step 16.5.
clone.AppendChild(subfragment.upcast())?;
}
@@ -756,7 +767,7 @@ impl RangeMethods for Range {
if let Some(end_data) = child.downcast::<CharacterData>() {
assert!(child == end_node);
// Step 18.1.
- let clone = end_node.CloneNode(/* deep */ true)?;
+ let clone = end_node.CloneNode(/* deep */ true, CanGc::note())?;
// Step 18.2.
let text = end_data.SubstringData(0, end_offset);
clone
@@ -769,13 +780,20 @@ impl RangeMethods for Range {
end_data.ReplaceData(0, end_offset, DOMString::new())?;
} else {
// Step 19.1.
- let clone = child.CloneNode(/* deep */ false)?;
+ let clone = child.CloneNode(/* deep */ false, CanGc::note())?;
// Step 19.2.
fragment.upcast::<Node>().AppendChild(&clone)?;
// Step 19.3.
- let subrange = Range::new(&clone.owner_doc(), &child, 0, &end_node, end_offset);
+ let subrange = Range::new(
+ &clone.owner_doc(),
+ &child,
+ 0,
+ &end_node,
+ end_offset,
+ CanGc::note(),
+ );
// Step 19.4.
- let subfragment = subrange.ExtractContents()?;
+ let subfragment = subrange.ExtractContents(CanGc::note())?;
// Step 19.5.
clone.AppendChild(subfragment.upcast())?;
}
@@ -964,7 +982,7 @@ impl RangeMethods for Range {
}
/// <https://dom.spec.whatwg.org/#dom-range-surroundcontents>
- fn SurroundContents(&self, new_parent: &Node) -> ErrorResult {
+ fn SurroundContents(&self, new_parent: &Node, can_gc: CanGc) -> ErrorResult {
// Step 1.
let start = self.start_container();
let end = self.end_container();
@@ -989,7 +1007,7 @@ impl RangeMethods for Range {
}
// Step 3.
- let fragment = self.ExtractContents()?;
+ let fragment = self.ExtractContents(can_gc)?;
// Step 4.
Node::replace_all(None, new_parent);
@@ -1056,7 +1074,11 @@ impl RangeMethods for Range {
}
/// <https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#extensions-to-the-range-interface>
- fn CreateContextualFragment(&self, fragment: DOMString) -> Fallible<DomRoot<DocumentFragment>> {
+ fn CreateContextualFragment(
+ &self,
+ fragment: DOMString,
+ can_gc: CanGc,
+ ) -> Fallible<DomRoot<DocumentFragment>> {
// Step 1.
let node = self.start_container();
let owner_doc = node.owner_doc();
@@ -1074,7 +1096,7 @@ impl RangeMethods for Range {
let element = Element::fragment_parsing_context(&owner_doc, element.as_deref());
// Step 3.
- let fragment_node = element.parse_fragment(fragment)?;
+ let fragment_node = element.parse_fragment(fragment, can_gc)?;
// Step 4.
for node in fragment_node
diff --git a/components/script/dom/selection.rs b/components/script/dom/selection.rs
index 7d62cb04db2..63ec919a4b3 100644
--- a/components/script/dom/selection.rs
+++ b/components/script/dom/selection.rs
@@ -19,6 +19,7 @@ use crate::dom::document::Document;
use crate::dom::eventtarget::EventTarget;
use crate::dom::node::{window_from_node, Node};
use crate::dom::range::Range;
+use crate::script_runtime::CanGc;
use crate::task_source::TaskSource;
#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
@@ -241,7 +242,7 @@ impl SelectionMethods for Selection {
}
// https://w3c.github.io/selection-api/#dom-selection-collapse
- fn Collapse(&self, node: Option<&Node>, offset: u32) -> ErrorResult {
+ fn Collapse(&self, node: Option<&Node>, offset: u32, can_gc: CanGc) -> ErrorResult {
if let Some(node) = node {
if node.is_doctype() {
// w3c/selection-api#118
@@ -258,7 +259,7 @@ impl SelectionMethods for Selection {
}
// Steps 4-5
- let range = Range::new(&self.document, node, offset, node, offset);
+ let range = Range::new(&self.document, node, offset, node, offset, can_gc);
// Step 6
self.set_range(&range);
@@ -276,23 +277,27 @@ impl SelectionMethods for Selection {
// TODO: When implementing actual selection UI, this may be the correct
// method to call as the start-of-selection action, after a
// selectstart event has fired and not been cancelled.
- fn SetPosition(&self, node: Option<&Node>, offset: u32) -> ErrorResult {
- self.Collapse(node, offset)
+ fn SetPosition(&self, node: Option<&Node>, offset: u32, can_gc: CanGc) -> ErrorResult {
+ self.Collapse(node, offset, can_gc)
}
// https://w3c.github.io/selection-api/#dom-selection-collapsetostart
- fn CollapseToStart(&self) -> ErrorResult {
+ fn CollapseToStart(&self, can_gc: CanGc) -> ErrorResult {
if let Some(range) = self.range.get() {
- self.Collapse(Some(&*range.start_container()), range.start_offset())
+ self.Collapse(
+ Some(&*range.start_container()),
+ range.start_offset(),
+ can_gc,
+ )
} else {
Err(Error::InvalidState)
}
}
// https://w3c.github.io/selection-api/#dom-selection-collapsetoend
- fn CollapseToEnd(&self) -> ErrorResult {
+ fn CollapseToEnd(&self, can_gc: CanGc) -> ErrorResult {
if let Some(range) = self.range.get() {
- self.Collapse(Some(&*range.end_container()), range.end_offset())
+ self.Collapse(Some(&*range.end_container()), range.end_offset(), can_gc)
} else {
Err(Error::InvalidState)
}
@@ -301,7 +306,7 @@ impl SelectionMethods for Selection {
// https://w3c.github.io/selection-api/#dom-selection-extend
// TODO: When implementing actual selection UI, this may be the correct
// method to call as the continue-selection action
- fn Extend(&self, node: &Node, offset: u32) -> ErrorResult {
+ fn Extend(&self, node: &Node, offset: u32, can_gc: CanGc) -> ErrorResult {
if !self.is_same_root(node) {
// Step 1
return Ok(());
@@ -321,7 +326,14 @@ impl SelectionMethods for Selection {
// Step 4
if !self.is_same_root(&range.start_container()) {
// Step 5, and its following 8 and 9
- self.set_range(&Range::new(&self.document, node, offset, node, offset));
+ self.set_range(&Range::new(
+ &self.document,
+ node,
+ offset,
+ node,
+ offset,
+ can_gc,
+ ));
self.direction.set(Direction::Forwards);
} else {
let old_anchor_node = &*self.GetAnchorNode().unwrap(); // has range, therefore has anchor node
@@ -341,6 +353,7 @@ impl SelectionMethods for Selection {
old_anchor_offset,
node,
offset,
+ can_gc,
));
self.direction.set(Direction::Forwards);
} else {
@@ -351,6 +364,7 @@ impl SelectionMethods for Selection {
offset,
old_anchor_node,
old_anchor_offset,
+ can_gc,
));
self.direction.set(Direction::Backwards);
}
@@ -369,6 +383,7 @@ impl SelectionMethods for Selection {
anchor_offset: u32,
focus_node: &Node,
focus_offset: u32,
+ can_gc: CanGc,
) -> ErrorResult {
// Step 1
if anchor_node.is_doctype() || focus_node.is_doctype() {
@@ -400,6 +415,7 @@ impl SelectionMethods for Selection {
focus_offset,
anchor_node,
anchor_offset,
+ can_gc,
));
self.direction.set(Direction::Backwards);
} else {
@@ -409,6 +425,7 @@ impl SelectionMethods for Selection {
anchor_offset,
focus_node,
focus_offset,
+ can_gc,
));
self.direction.set(Direction::Forwards);
}
@@ -416,7 +433,7 @@ impl SelectionMethods for Selection {
}
// https://w3c.github.io/selection-api/#dom-selection-selectallchildren
- fn SelectAllChildren(&self, node: &Node) -> ErrorResult {
+ fn SelectAllChildren(&self, node: &Node, can_gc: CanGc) -> ErrorResult {
if node.is_doctype() {
// w3c/selection-api#118
return Err(Error::InvalidNodeType);
@@ -434,6 +451,7 @@ impl SelectionMethods for Selection {
0,
node,
node.children_count(),
+ can_gc,
));
self.direction.set(Direction::Forwards);
diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs
index 5e0794b86a3..1b6c768a186 100644
--- a/components/script/dom/serviceworkerglobalscope.rs
+++ b/components/script/dom/serviceworkerglobalscope.rs
@@ -45,7 +45,7 @@ use crate::dom::workerglobalscope::WorkerGlobalScope;
use crate::fetch::load_whole_resource;
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
use crate::script_runtime::{
- new_rt_and_cx, CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext,
+ new_rt_and_cx, CanGc, CommonScriptMsg, ContextForRequestInterrupt, JSContext as SafeJSContext,
Runtime, ScriptChan,
};
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
@@ -295,6 +295,7 @@ impl ServiceWorkerGlobalScope {
control_receiver: Receiver<ServiceWorkerControlMsg>,
context_sender: Sender<ContextForRequestInterrupt>,
closing: Arc<AtomicBool>,
+ _can_gc: CanGc,
) -> JoinHandle<()> {
let ScopeThings {
script_url,
@@ -398,7 +399,7 @@ impl ServiceWorkerGlobalScope {
// which happens after the closing flag is set to true,
// or until the worker has run beyond its allocated time.
while !scope.is_closing() && !global.has_timed_out() {
- run_worker_event_loop(&*global, None);
+ run_worker_event_loop(&*global, None, CanGc::note());
}
},
reporter_name,
diff --git a/components/script/dom/servoparser/async_html.rs b/components/script/dom/servoparser/async_html.rs
index 551692af1f8..be8adb01e09 100644
--- a/components/script/dom/servoparser/async_html.rs
+++ b/components/script/dom/servoparser/async_html.rs
@@ -41,6 +41,7 @@ use crate::dom::node::Node;
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::servoparser::{create_element_for_token, ElementAttribute, ParsingAlgorithm};
use crate::dom::virtualmethods::vtable_for;
+use crate::script_runtime::CanGc;
type ParseNodeId = usize;
@@ -283,7 +284,11 @@ impl Tokenizer {
tokenizer
}
- pub fn feed(&self, input: &BufferQueue) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
+ pub fn feed(
+ &self,
+ input: &BufferQueue,
+ _can_gc: CanGc,
+ ) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
let mut send_tendrils = VecDeque::new();
while let Some(str) = input.pop_front() {
send_tendrils.push_back(SendTendril::from(str));
@@ -303,7 +308,9 @@ impl Tokenizer {
.recv()
.expect("Unexpected channel panic in main thread.")
{
- ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
+ ToTokenizerMsg::ProcessOperation(parse_op) => {
+ self.process_operation(parse_op, CanGc::note())
+ },
ToTokenizerMsg::TokenizerResultDone { updated_input } => {
let buffer_queue = create_buffer_queue(updated_input);
input.replace_with(buffer_queue);
@@ -323,7 +330,7 @@ impl Tokenizer {
}
}
- pub fn end(&self) {
+ pub fn end(&self, _can_gc: CanGc) {
self.html_tokenizer_sender
.send(ToHtmlTokenizerMsg::End)
.unwrap();
@@ -333,7 +340,9 @@ impl Tokenizer {
.recv()
.expect("Unexpected channel panic in main thread.")
{
- ToTokenizerMsg::ProcessOperation(parse_op) => self.process_operation(parse_op),
+ ToTokenizerMsg::ProcessOperation(parse_op) => {
+ self.process_operation(parse_op, CanGc::note())
+ },
ToTokenizerMsg::TokenizerResultDone { updated_input: _ } |
ToTokenizerMsg::TokenizerResultScript {
script: _,
@@ -364,7 +373,7 @@ impl Tokenizer {
})
}
- fn append_before_sibling(&self, sibling: ParseNodeId, node: NodeOrText) {
+ fn append_before_sibling(&self, sibling: ParseNodeId, node: NodeOrText, can_gc: CanGc) {
let node = match node {
NodeOrText::Node(n) => {
HtmlNodeOrText::AppendNode(Dom::from_ref(&**self.get_node(&n.id)))
@@ -376,10 +385,10 @@ impl Tokenizer {
.GetParentNode()
.expect("append_before_sibling called on node without parent");
- super::insert(parent, Some(sibling), node, self.parsing_algorithm);
+ super::insert(parent, Some(sibling), node, self.parsing_algorithm, can_gc);
}
- fn append(&self, parent: ParseNodeId, node: NodeOrText) {
+ fn append(&self, parent: ParseNodeId, node: NodeOrText, can_gc: CanGc) {
let node = match node {
NodeOrText::Node(n) => {
HtmlNodeOrText::AppendNode(Dom::from_ref(&**self.get_node(&n.id)))
@@ -388,7 +397,7 @@ impl Tokenizer {
};
let parent = &**self.get_node(&parent);
- super::insert(parent, None, node, self.parsing_algorithm);
+ super::insert(parent, None, node, self.parsing_algorithm, can_gc);
}
fn has_parent_node(&self, node: ParseNodeId) -> bool {
@@ -404,7 +413,7 @@ impl Tokenizer {
x.is_in_same_home_subtree(y)
}
- fn process_operation(&self, op: ParseOperation) {
+ fn process_operation(&self, op: ParseOperation, can_gc: CanGc) {
let document = DomRoot::from_ref(&**self.get_node(&0));
let document = document
.downcast::<Document>()
@@ -415,7 +424,7 @@ impl Tokenizer {
let template = target
.downcast::<HTMLTemplateElement>()
.expect("Tried to extract contents from non-template element while parsing");
- self.insert_node(contents, Dom::from_ref(template.Content().upcast()));
+ self.insert_node(contents, Dom::from_ref(template.Content(can_gc).upcast()));
},
ParseOperation::CreateElement {
node,
@@ -433,6 +442,7 @@ impl Tokenizer {
&self.document,
ElementCreator::ParserCreated(current_line),
ParsingAlgorithm::Normal,
+ can_gc,
);
self.insert_node(node, Dom::from_ref(element.upcast()));
},
@@ -441,10 +451,10 @@ impl Tokenizer {
self.insert_node(node, Dom::from_ref(comment.upcast()));
},
ParseOperation::AppendBeforeSibling { sibling, node } => {
- self.append_before_sibling(sibling, node);
+ self.append_before_sibling(sibling, node, can_gc);
},
ParseOperation::Append { parent, node } => {
- self.append(parent, node);
+ self.append(parent, node, can_gc);
},
ParseOperation::AppendBasedOnParentNode {
element,
@@ -452,9 +462,9 @@ impl Tokenizer {
node,
} => {
if self.has_parent_node(element) {
- self.append_before_sibling(element, node);
+ self.append_before_sibling(element, node, can_gc);
} else {
- self.append(prev_element, node);
+ self.append(prev_element, node, can_gc);
}
},
ParseOperation::AppendDoctypeToDocument {
diff --git a/components/script/dom/servoparser/html.rs b/components/script/dom/servoparser/html.rs
index b3184923609..a2ef2a323fd 100644
--- a/components/script/dom/servoparser/html.rs
+++ b/components/script/dom/servoparser/html.rs
@@ -30,6 +30,7 @@ use crate::dom::htmltemplateelement::HTMLTemplateElement;
use crate::dom::node::Node;
use crate::dom::processinginstruction::ProcessingInstruction;
use crate::dom::servoparser::{ParsingAlgorithm, Sink};
+use crate::script_runtime::CanGc;
#[derive(JSTraceable, MallocSizeOf)]
#[crown::unrooted_must_root_lint::must_root]
@@ -163,7 +164,7 @@ fn rev_children_iter(n: &Node) -> impl Iterator<Item = DomRoot<Node>> {
}
match n.downcast::<HTMLTemplateElement>() {
- Some(t) => t.Content().upcast::<Node>().rev_children(),
+ Some(t) => t.Content(CanGc::note()).upcast::<Node>().rev_children(),
None => n.rev_children(),
}
}
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index f6c7af85838..958b2bbf3db 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -67,6 +67,7 @@ use crate::dom::text::Text;
use crate::dom::virtualmethods::vtable_for;
use crate::network_listener::PreInvoke;
use crate::realms::enter_realm;
+use crate::script_runtime::CanGc;
use crate::script_thread::ScriptThread;
mod async_html;
@@ -150,7 +151,12 @@ impl ServoParser {
self.can_write()
}
- pub fn parse_html_document(document: &Document, input: Option<DOMString>, url: ServoUrl) {
+ pub fn parse_html_document(
+ document: &Document,
+ input: Option<DOMString>,
+ url: ServoUrl,
+ can_gc: CanGc,
+ ) {
let parser = if pref!(dom.servoparser.async_html_tokenizer.enabled) {
ServoParser::new(
document,
@@ -172,7 +178,7 @@ impl ServoParser {
// Set as the document's current parser and initialize with `input`, if given.
if let Some(input) = input {
- parser.parse_complete_string_chunk(String::from(input));
+ parser.parse_complete_string_chunk(String::from(input), can_gc);
} else {
parser.document.set_current_parser(Some(&parser));
}
@@ -182,6 +188,7 @@ impl ServoParser {
pub fn parse_html_fragment(
context: &Element,
input: DOMString,
+ can_gc: CanGc,
) -> impl Iterator<Item = DomRoot<Node>> {
let context_node = context.upcast::<Node>();
let context_document = context_node.owner_doc();
@@ -208,6 +215,7 @@ impl ServoParser {
None,
None,
Default::default(),
+ can_gc,
);
// Step 2.
@@ -233,7 +241,7 @@ impl ServoParser {
)),
ParserKind::Normal,
);
- parser.parse_complete_string_chunk(String::from(input));
+ parser.parse_complete_string_chunk(String::from(input), CanGc::note());
// Step 14.
let root_element = document.GetDocumentElement().expect("no document element");
@@ -257,7 +265,12 @@ impl ServoParser {
document.set_current_parser(Some(&parser));
}
- pub fn parse_xml_document(document: &Document, input: Option<DOMString>, url: ServoUrl) {
+ pub fn parse_xml_document(
+ document: &Document,
+ input: Option<DOMString>,
+ url: ServoUrl,
+ can_gc: CanGc,
+ ) {
let parser = ServoParser::new(
document,
Tokenizer::Xml(self::xml::Tokenizer::new(document, url)),
@@ -266,7 +279,7 @@ impl ServoParser {
// Set as the document's current parser and initialize with `input`, if given.
if let Some(input) = input {
- parser.parse_complete_string_chunk(String::from(input));
+ parser.parse_complete_string_chunk(String::from(input), can_gc);
} else {
parser.document.set_current_parser(Some(&parser));
}
@@ -298,6 +311,7 @@ impl ServoParser {
&self,
script: &HTMLScriptElement,
result: ScriptResult,
+ can_gc: CanGc,
) {
assert!(self.suspended.get());
self.suspended.set(false);
@@ -315,7 +329,7 @@ impl ServoParser {
self.script_nesting_level.set(script_nesting_level);
if !self.suspended.get() && !self.aborted.get() {
- self.parse_sync();
+ self.parse_sync(can_gc);
}
}
@@ -324,7 +338,7 @@ impl ServoParser {
}
/// Steps 6-8 of <https://html.spec.whatwg.org/multipage/#document.write()>
- pub fn write(&self, text: Vec<DOMString>) {
+ pub fn write(&self, text: Vec<DOMString>, _can_gc: CanGc) {
assert!(self.can_write());
if self.document.has_pending_parsing_blocking_script() {
@@ -347,7 +361,7 @@ impl ServoParser {
input.push_back(String::from(chunk).into());
}
- self.tokenize(|tokenizer| tokenizer.feed(&input));
+ self.tokenize(|tokenizer| tokenizer.feed(&input, CanGc::note()));
if self.suspended.get() {
// Parser got suspended, insert remaining input at end of
@@ -363,7 +377,7 @@ impl ServoParser {
}
// Steps 4-6 of https://html.spec.whatwg.org/multipage/#dom-document-close
- pub fn close(&self) {
+ pub fn close(&self, can_gc: CanGc) {
assert!(self.script_created_parser);
// Step 4.
@@ -375,11 +389,11 @@ impl ServoParser {
}
// Step 6.
- self.parse_sync();
+ self.parse_sync(can_gc);
}
// https://html.spec.whatwg.org/multipage/#abort-a-parser
- pub fn abort(&self) {
+ pub fn abort(&self, can_gc: CanGc) {
assert!(!self.aborted.get());
self.aborted.set(true);
@@ -392,7 +406,7 @@ impl ServoParser {
.set_ready_state(DocumentReadyState::Interactive);
// Step 3.
- self.tokenizer.end();
+ self.tokenizer.end(can_gc);
self.document.set_current_parser(None);
// Step 4.
@@ -499,7 +513,7 @@ impl ServoParser {
self.push_tendril_input_chunk(chunk);
}
- fn parse_sync(&self) {
+ fn parse_sync(&self, can_gc: CanGc) {
let metadata = TimerMetadata {
url: self.document.url().as_str().into(),
iframe: TimerMetadataFrameType::RootWindow,
@@ -514,11 +528,11 @@ impl ServoParser {
.upcast::<GlobalScope>()
.time_profiler_chan()
.clone(),
- || self.do_parse_sync(),
+ || self.do_parse_sync(can_gc),
)
}
- fn do_parse_sync(&self) {
+ fn do_parse_sync(&self, _can_gc: CanGc) {
assert!(self.script_input.is_empty());
// This parser will continue to parse while there is either pending input or
@@ -532,7 +546,7 @@ impl ServoParser {
}
}
}
- self.tokenize(|tokenizer| tokenizer.feed(&self.network_input));
+ self.tokenize(|tokenizer| tokenizer.feed(&self.network_input, CanGc::note()));
if self.suspended.get() {
return;
@@ -541,24 +555,24 @@ impl ServoParser {
assert!(self.network_input.is_empty());
if self.last_chunk_received.get() {
- self.finish();
+ self.finish(CanGc::note());
}
}
- fn parse_complete_string_chunk(&self, input: String) {
+ fn parse_complete_string_chunk(&self, input: String, can_gc: CanGc) {
self.document.set_current_parser(Some(self));
self.push_string_input_chunk(input);
self.last_chunk_received.set(true);
if !self.suspended.get() {
- self.parse_sync();
+ self.parse_sync(can_gc);
}
}
- fn parse_bytes_chunk(&self, input: Vec<u8>) {
+ fn parse_bytes_chunk(&self, input: Vec<u8>, can_gc: CanGc) {
self.document.set_current_parser(Some(self));
self.push_bytes_input_chunk(input);
if !self.suspended.get() {
- self.parse_sync();
+ self.parse_sync(can_gc);
}
}
@@ -586,7 +600,7 @@ impl ServoParser {
self.document
.window()
.upcast::<GlobalScope>()
- .perform_a_microtask_checkpoint();
+ .perform_a_microtask_checkpoint(CanGc::note());
}
let script_nesting_level = self.script_nesting_level.get();
@@ -606,7 +620,7 @@ impl ServoParser {
}
// https://html.spec.whatwg.org/multipage/#the-end
- fn finish(&self) {
+ fn finish(&self, can_gc: CanGc) {
assert!(!self.suspended.get());
assert!(self.last_chunk_received.get());
assert!(self.script_input.is_empty());
@@ -618,12 +632,13 @@ impl ServoParser {
.set_ready_state(DocumentReadyState::Interactive);
// Step 2.
- self.tokenizer.end();
+ self.tokenizer.end(can_gc);
self.document.set_current_parser(None);
// Steps 3-12 are in another castle, namely finish_load.
let url = self.tokenizer.url().clone();
- self.document.finish_load(LoadType::PageSource(url));
+ self.document
+ .finish_load(LoadType::PageSource(url), CanGc::note());
}
}
@@ -666,18 +681,22 @@ enum Tokenizer {
}
impl Tokenizer {
- fn feed(&self, input: &BufferQueue) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
+ fn feed(
+ &self,
+ input: &BufferQueue,
+ can_gc: CanGc,
+ ) -> TokenizerResult<DomRoot<HTMLScriptElement>> {
match *self {
Tokenizer::Html(ref tokenizer) => tokenizer.feed(input),
- Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.feed(input),
+ Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.feed(input, can_gc),
Tokenizer::Xml(ref tokenizer) => tokenizer.feed(input),
}
}
- fn end(&self) {
+ fn end(&self, can_gc: CanGc) {
match *self {
Tokenizer::Html(ref tokenizer) => tokenizer.end(),
- Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.end(),
+ Tokenizer::AsyncHtml(ref tokenizer) => tokenizer.end(can_gc),
Tokenizer::Xml(ref tokenizer) => tokenizer.end(),
}
}
@@ -797,7 +816,7 @@ impl FetchResponseListener for ParserContext {
Some(csp_list)
});
- let parser = match ScriptThread::page_headers_available(&self.id, metadata) {
+ let parser = match ScriptThread::page_headers_available(&self.id, metadata, CanGc::note()) {
Some(parser) => parser,
None => return,
};
@@ -829,7 +848,7 @@ impl FetchResponseListener for ParserContext {
self.is_synthesized_document = true;
let page = "<html><body></body></html>".into();
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
let doc = &parser.document;
let doc_body = DomRoot::upcast::<Node>(doc.GetBody().unwrap());
@@ -843,7 +862,7 @@ impl FetchResponseListener for ParserContext {
// https://html.spec.whatwg.org/multipage/#read-text
let page = "<pre>\n".into();
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
parser.tokenizer.set_plaintext_state();
},
(mime::TEXT, mime::HTML, _) => match error {
@@ -856,21 +875,21 @@ impl FetchResponseListener for ParserContext {
let page =
page.replace("${secret}", &net_traits::PRIVILEGED_SECRET.to_string());
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
Some(NetworkError::Internal(reason)) => {
self.is_synthesized_document = true;
let page = resources::read_string(Resource::NetErrorHTML);
let page = page.replace("${reason}", &reason);
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
Some(NetworkError::Crash(details)) => {
self.is_synthesized_document = true;
let page = resources::read_string(Resource::CrashHTML);
let page = page.replace("${details}", &details);
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
Some(_) => {},
None => {},
@@ -888,7 +907,7 @@ impl FetchResponseListener for ParserContext {
);
self.is_synthesized_document = true;
parser.push_string_input_chunk(page);
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
},
}
}
@@ -905,7 +924,7 @@ impl FetchResponseListener for ParserContext {
return;
}
let _realm = enter_realm(&*parser);
- parser.parse_bytes_chunk(payload);
+ parser.parse_bytes_chunk(payload, CanGc::note());
}
// This method is called via script_thread::handle_fetch_eof, so we must call
@@ -935,7 +954,7 @@ impl FetchResponseListener for ParserContext {
parser.last_chunk_received.set(true);
if !parser.suspended.get() {
- parser.parse_sync();
+ parser.parse_sync(CanGc::note());
}
// TODO: Only update if this is the current document resource.
@@ -1000,6 +1019,7 @@ fn insert(
reference_child: Option<&Node>,
child: NodeOrText<Dom<Node>>,
parsing_algorithm: ParsingAlgorithm,
+ can_gc: CanGc,
) {
match child {
NodeOrText::AppendNode(n) => {
@@ -1013,7 +1033,7 @@ fn insert(
}
parent.InsertBefore(&n, reference_child).unwrap();
if element_in_non_fragment {
- ScriptThread::pop_current_element_queue();
+ ScriptThread::pop_current_element_queue(can_gc);
}
},
NodeOrText::AppendText(t) => {
@@ -1076,7 +1096,7 @@ impl TreeSink for Sink {
let template = target
.downcast::<HTMLTemplateElement>()
.expect("tried to get template contents of non-HTMLTemplateElement in HTML parsing");
- Dom::from_ref(template.Content().upcast())
+ Dom::from_ref(template.Content(CanGc::note()).upcast())
}
fn same_node(&self, x: &Dom<Node>, y: &Dom<Node>) -> bool {
@@ -1110,6 +1130,7 @@ impl TreeSink for Sink {
&self.document,
ElementCreator::ParserCreated(self.current_line.get()),
self.parsing_algorithm,
+ CanGc::note(),
);
Dom::from_ref(element.upcast())
}
@@ -1167,7 +1188,13 @@ impl TreeSink for Sink {
.GetParentNode()
.expect("append_before_sibling called on node without parent");
- insert(&parent, Some(sibling), new_node, self.parsing_algorithm);
+ insert(
+ &parent,
+ Some(sibling),
+ new_node,
+ self.parsing_algorithm,
+ CanGc::note(),
+ );
}
fn parse_error(&self, msg: Cow<'static, str>) {
@@ -1185,7 +1212,7 @@ impl TreeSink for Sink {
#[allow(crown::unrooted_must_root)]
fn append(&self, parent: &Dom<Node>, child: NodeOrText<Dom<Node>>) {
- insert(parent, None, child, self.parsing_algorithm);
+ insert(parent, None, child, self.parsing_algorithm, CanGc::note());
}
#[allow(crown::unrooted_must_root)]
@@ -1289,6 +1316,7 @@ fn create_element_for_token(
document: &Document,
creator: ElementCreator,
parsing_algorithm: ParsingAlgorithm,
+ can_gc: CanGc,
) -> DomRoot<Element> {
// Step 3.
let is = attrs
@@ -1312,7 +1340,7 @@ fn create_element_for_token(
document
.window()
.upcast::<GlobalScope>()
- .perform_a_microtask_checkpoint();
+ .perform_a_microtask_checkpoint(can_gc);
}
// Step 6.3
ScriptThread::push_new_element_queue()
@@ -1325,7 +1353,15 @@ fn create_element_for_token(
CustomElementCreationMode::Asynchronous
};
- let element = Element::create(name, is, document, creator, creation_mode, None);
+ let element = Element::create(
+ name,
+ is,
+ document,
+ creator,
+ creation_mode,
+ None,
+ CanGc::note(),
+ );
// https://html.spec.whatwg.org/multipage#the-input-element:value-sanitization-algorithm-3
// says to invoke sanitization "when an input element is first created";
@@ -1353,7 +1389,7 @@ fn create_element_for_token(
// Step 9.
if will_execute_script {
// Steps 9.1 - 9.2.
- ScriptThread::pop_current_element_queue();
+ ScriptThread::pop_current_element_queue(CanGc::note());
// Step 9.3.
document.decrement_throw_on_dynamic_markup_insertion_counter();
}
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 0540cabeab5..611fccbf974 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -144,7 +144,7 @@ use crate::layout_image::fetch_image_for_layout;
use crate::microtask::MicrotaskQueue;
use crate::realms::InRealm;
use crate::script_runtime::{
- CommonScriptMsg, JSContext, Runtime, ScriptChan, ScriptPort, ScriptThreadEventCategory,
+ CanGc, CommonScriptMsg, JSContext, Runtime, ScriptChan, ScriptPort, ScriptThreadEventCategory,
};
use crate::script_thread::{
ImageCacheMsg, MainThreadScriptChan, MainThreadScriptMsg, ScriptThread,
@@ -676,10 +676,10 @@ impl WindowMethods for Window {
}
// https://html.spec.whatwg.org/multipage/#dom-window-stop
- fn Stop(&self) {
+ fn Stop(&self, can_gc: CanGc) {
// TODO: Cancel ongoing navigation.
let doc = self.Document();
- doc.abort();
+ doc.abort(can_gc);
}
// https://html.spec.whatwg.org/multipage/#dom-open
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index 0f7ea7f035b..fa04bd8cbe2 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -159,6 +159,7 @@ impl Worker {
global.wgpu_id_hub(),
control_receiver,
context_sender,
+ CanGc::note(),
);
let context = context_receiver
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 05f14a9b380..e8c41c08cb3 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -950,7 +950,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
#[allow(unsafe_code)]
/// <https://xhr.spec.whatwg.org/#the-response-attribute>
- fn Response(&self, cx: JSContext) -> JSVal {
+ fn Response(&self, cx: JSContext, can_gc: CanGc) -> JSVal {
rooted!(in(*cx) let mut rval = UndefinedValue());
match self.response_type.get() {
XMLHttpRequestResponseType::_empty | XMLHttpRequestResponseType::Text => unsafe {
@@ -971,7 +971,8 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
},
// Step 2
XMLHttpRequestResponseType::Document => unsafe {
- self.document_response().to_jsval(*cx, rval.handle_mut());
+ self.document_response(can_gc)
+ .to_jsval(*cx, rval.handle_mut());
},
XMLHttpRequestResponseType::Json => unsafe {
self.json_response(cx).to_jsval(*cx, rval.handle_mut());
@@ -1006,12 +1007,12 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
}
/// <https://xhr.spec.whatwg.org/#the-responsexml-attribute>
- fn GetResponseXML(&self) -> Fallible<Option<DomRoot<Document>>> {
+ fn GetResponseXML(&self, can_gc: CanGc) -> Fallible<Option<DomRoot<Document>>> {
match self.response_type.get() {
XMLHttpRequestResponseType::_empty | XMLHttpRequestResponseType::Document => {
// Step 3
if let XMLHttpRequestState::Done = self.ready_state.get() {
- Ok(self.document_response())
+ Ok(self.document_response(can_gc))
} else {
// Step 2
Ok(None)
@@ -1367,7 +1368,7 @@ impl XMLHttpRequest {
}
/// <https://xhr.spec.whatwg.org/#document-response>
- fn document_response(&self) -> Option<DomRoot<Document>> {
+ fn document_response(&self, can_gc: CanGc) -> Option<DomRoot<Document>> {
// Caching: if we have existing response xml, redirect it directly
let response = self.response_xml.get();
if response.is_some() {
@@ -1392,12 +1393,12 @@ impl XMLHttpRequest {
} else {
// TODO Step 5.2 "If charset is null, prescan the first 1024 bytes of xhr’s received bytes"
// Step 5
- temp_doc = self.document_text_html();
+ temp_doc = self.document_text_html(can_gc);
}
},
// Step 7
None => {
- temp_doc = self.handle_xml();
+ temp_doc = self.handle_xml(can_gc);
// Not sure it the parser should throw an error for this case
// The specification does not indicates this test,
// but for now we check the document has no child nodes
@@ -1411,7 +1412,7 @@ impl XMLHttpRequest {
(mime.type_() == mime::APPLICATION && mime.subtype() == mime::XML) ||
mime.suffix() == Some(mime::XML) =>
{
- temp_doc = self.handle_xml();
+ temp_doc = self.handle_xml(can_gc);
// Not sure it the parser should throw an error for this case
// The specification does not indicates this test,
// but for now we check the document has no child nodes
@@ -1488,29 +1489,39 @@ impl XMLHttpRequest {
self.response_json.get()
}
- fn document_text_html(&self) -> DomRoot<Document> {
+ fn document_text_html(&self, can_gc: CanGc) -> DomRoot<Document> {
let charset = self.final_charset().unwrap_or(UTF_8);
let wr = self.global();
let response = self.response.borrow();
let (decoded, _, _) = charset.decode(&response);
- let document = self.new_doc(IsHTMLDocument::HTMLDocument);
+ let document = self.new_doc(IsHTMLDocument::HTMLDocument, can_gc);
// TODO: Disable scripting while parsing
- ServoParser::parse_html_document(&document, Some(DOMString::from(decoded)), wr.get_url());
+ ServoParser::parse_html_document(
+ &document,
+ Some(DOMString::from(decoded)),
+ wr.get_url(),
+ CanGc::note(),
+ );
document
}
- fn handle_xml(&self) -> DomRoot<Document> {
+ fn handle_xml(&self, can_gc: CanGc) -> DomRoot<Document> {
let charset = self.final_charset().unwrap_or(UTF_8);
let wr = self.global();
let response = self.response.borrow();
let (decoded, _, _) = charset.decode(&response);
- let document = self.new_doc(IsHTMLDocument::NonHTMLDocument);
+ let document = self.new_doc(IsHTMLDocument::NonHTMLDocument, can_gc);
// TODO: Disable scripting while parsing
- ServoParser::parse_xml_document(&document, Some(DOMString::from(decoded)), wr.get_url());
+ ServoParser::parse_xml_document(
+ &document,
+ Some(DOMString::from(decoded)),
+ wr.get_url(),
+ CanGc::note(),
+ );
document
}
- fn new_doc(&self, is_html_document: IsHTMLDocument) -> DomRoot<Document> {
+ fn new_doc(&self, is_html_document: IsHTMLDocument, can_gc: CanGc) -> DomRoot<Document> {
let wr = self.global();
let win = wr.as_window();
let doc = win.Document();
@@ -1536,6 +1547,7 @@ impl XMLHttpRequest {
None,
None,
Default::default(),
+ can_gc,
)
}
diff --git a/components/script/microtask.rs b/components/script/microtask.rs
index 820afcc5f97..086fa99cd50 100644
--- a/components/script/microtask.rs
+++ b/components/script/microtask.rs
@@ -23,7 +23,7 @@ use crate::dom::htmlimageelement::ImageElementMicrotask;
use crate::dom::htmlmediaelement::MediaElementMicrotask;
use crate::dom::mutationobserver::MutationObserver;
use crate::realms::enter_realm;
-use crate::script_runtime::{notify_about_rejected_promises, JSContext};
+use crate::script_runtime::{notify_about_rejected_promises, CanGc, JSContext};
use crate::script_thread::ScriptThread;
/// A collection of microtasks in FIFO order.
@@ -46,7 +46,7 @@ pub enum Microtask {
}
pub trait MicrotaskRunnable {
- fn handler(&self) {}
+ fn handler(&self, _can_gc: CanGc) {}
fn enter_realm(&self) -> JSAutoRealm;
}
@@ -87,6 +87,7 @@ impl MicrotaskQueue {
cx: JSContext,
target_provider: F,
globalscopes: Vec<DomRoot<GlobalScope>>,
+ _can_gc: CanGc,
) where
F: Fn(PipelineId) -> Option<DomRoot<GlobalScope>>,
{
@@ -127,14 +128,14 @@ impl MicrotaskQueue {
},
Microtask::MediaElement(ref task) => {
let _realm = task.enter_realm();
- task.handler();
+ task.handler(CanGc::note());
},
Microtask::ImageElement(ref task) => {
let _realm = task.enter_realm();
- task.handler();
+ task.handler(CanGc::note());
},
Microtask::CustomElementReaction => {
- ScriptThread::invoke_backup_element_queue();
+ ScriptThread::invoke_backup_element_queue(CanGc::note());
},
Microtask::NotifyMutationObservers => {
MutationObserver::notify_mutation_observers();
diff --git a/components/script/script_module.rs b/components/script/script_module.rs
index db155fa4f00..6dfb0a64ac0 100644
--- a/components/script/script_module.rs
+++ b/components/script/script_module.rs
@@ -72,7 +72,7 @@ use crate::dom::window::Window;
use crate::dom::worker::TrustedWorkerAddress;
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
use crate::realms::{enter_realm, AlreadyInRealm, InRealm};
-use crate::script_runtime::JSContext as SafeJSContext;
+use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
use crate::task::TaskBox;
use crate::task_source::TaskSourceName;
@@ -1091,7 +1091,7 @@ impl FetchResponseListener for ModuleContext {
if let Some(window) = global.downcast::<Window>() {
window
.Document()
- .finish_load(LoadType::Script(self.url.clone()));
+ .finish_load(LoadType::Script(self.url.clone()), CanGc::note());
}
// Step 9-1 & 9-2.
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 9677c371ff3..34744d73bb1 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -145,8 +145,8 @@ use crate::microtask::{Microtask, MicrotaskQueue};
use crate::realms::enter_realm;
use crate::script_module::ScriptFetchOptions;
use crate::script_runtime::{
- get_reports, new_rt_and_cx, CommonScriptMsg, ContextForRequestInterrupt, JSContext, Runtime,
- ScriptChan, ScriptPort, ScriptThreadEventCategory,
+ get_reports, new_rt_and_cx, CanGc, CommonScriptMsg, ContextForRequestInterrupt, JSContext,
+ Runtime, ScriptChan, ScriptPort, ScriptThreadEventCategory,
};
use crate::task_manager::TaskManager;
use crate::task_queue::{QueuedTask, QueuedTaskConversion, TaskQueue};
@@ -840,7 +840,7 @@ impl ScriptThreadFactory for ScriptThread {
let reporter_name = format!("script-reporter-{:?}", id);
mem_profiler_chan.run_with_memory_reporting(
|| {
- script_thread.start();
+ script_thread.start(CanGc::note());
let _ = script_thread.content_process_shutdown_chan.send(());
},
reporter_name,
@@ -935,10 +935,11 @@ impl ScriptThread {
pub fn page_headers_available(
id: &PipelineId,
metadata: Option<Metadata>,
+ can_gc: CanGc,
) -> Option<DomRoot<ServoParser>> {
SCRIPT_THREAD_ROOT.with(|root| {
let script_thread = unsafe { &*root.get().unwrap() };
- script_thread.handle_page_headers_available(id, metadata)
+ script_thread.handle_page_headers_available(id, metadata, can_gc)
})
}
@@ -1208,13 +1209,13 @@ impl ScriptThread {
})
}
- pub fn pop_current_element_queue() {
+ pub fn pop_current_element_queue(can_gc: CanGc) {
SCRIPT_THREAD_ROOT.with(|root| {
if let Some(script_thread) = root.get() {
let script_thread = unsafe { &*script_thread };
script_thread
.custom_element_reaction_stack
- .pop_current_element_queue();
+ .pop_current_element_queue(can_gc);
}
})
}
@@ -1245,13 +1246,13 @@ impl ScriptThread {
})
}
- pub fn invoke_backup_element_queue() {
+ pub fn invoke_backup_element_queue(can_gc: CanGc) {
SCRIPT_THREAD_ROOT.with(|root| {
if let Some(script_thread) = root.get() {
let script_thread = unsafe { &*script_thread };
script_thread
.custom_element_reaction_stack
- .invoke_backup_element_queue();
+ .invoke_backup_element_queue(can_gc);
}
})
}
@@ -1447,9 +1448,9 @@ impl ScriptThread {
/// Starts the script thread. After calling this method, the script thread will loop receiving
/// messages on its port.
- pub fn start(&self) {
+ pub fn start(&self, _can_gc: CanGc) {
debug!("Starting script thread.");
- while self.handle_msgs() {
+ while self.handle_msgs(CanGc::note()) {
// Go on...
debug!("Running script thread.");
}
@@ -1781,7 +1782,7 @@ impl ScriptThread {
}
/// Handle incoming messages from other tasks and the task queue.
- fn handle_msgs(&self) -> bool {
+ fn handle_msgs(&self, _can_gc: CanGc) -> bool {
use self::MixedMessage::{
FromConstellation, FromDevtools, FromImageCache, FromScript, FromWebGPUServer,
};
@@ -1893,7 +1894,7 @@ impl ScriptThread {
// Run the "update the rendering" task.
task.run_box();
// Always perform a microtrask checkpoint after running a task.
- self.perform_a_microtask_checkpoint();
+ self.perform_a_microtask_checkpoint(CanGc::note());
},
FromScript(MainThreadScriptMsg::Inactive) => {
// An event came-in from a document that is not fully-active, it has been stored by the task-queue.
@@ -1948,14 +1949,18 @@ impl ScriptThread {
// If we've received the closed signal from the BHM, only handle exit messages.
match msg {
FromConstellation(ConstellationControlMsg::ExitScriptThread) => {
- self.handle_exit_script_thread_msg();
+ self.handle_exit_script_thread_msg(CanGc::note());
return false;
},
FromConstellation(ConstellationControlMsg::ExitPipeline(
pipeline_id,
discard_browsing_context,
)) => {
- self.handle_exit_pipeline_msg(pipeline_id, discard_browsing_context);
+ self.handle_exit_pipeline_msg(
+ pipeline_id,
+ discard_browsing_context,
+ CanGc::note(),
+ );
},
_ => {},
}
@@ -1965,10 +1970,12 @@ impl ScriptThread {
let result = self.profile_event(category, pipeline_id, move || {
match msg {
FromConstellation(ConstellationControlMsg::ExitScriptThread) => {
- self.handle_exit_script_thread_msg();
+ self.handle_exit_script_thread_msg(CanGc::note());
return Some(false);
},
- FromConstellation(inner_msg) => self.handle_msg_from_constellation(inner_msg),
+ FromConstellation(inner_msg) => {
+ self.handle_msg_from_constellation(inner_msg, CanGc::note())
+ },
FromScript(inner_msg) => self.handle_msg_from_script(inner_msg),
FromDevtools(inner_msg) => self.handle_msg_from_devtools(inner_msg),
FromImageCache(inner_msg) => self.handle_msg_from_image_cache(inner_msg),
@@ -1984,7 +1991,7 @@ impl ScriptThread {
// https://html.spec.whatwg.org/multipage/#event-loop-processing-model step 6
// TODO(#32003): A microtask checkpoint is only supposed to be performed after running a task.
- self.perform_a_microtask_checkpoint();
+ self.perform_a_microtask_checkpoint(CanGc::note());
}
{
@@ -2246,7 +2253,7 @@ impl ScriptThread {
value
}
- fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg) {
+ fn handle_msg_from_constellation(&self, msg: ConstellationControlMsg, can_gc: CanGc) {
match msg {
ConstellationControlMsg::StopDelayingLoadEventsMode(pipeline_id) => {
self.handle_stop_delaying_load_events_mode(pipeline_id)
@@ -2273,6 +2280,7 @@ impl ScriptThread {
browsing_context_id,
load_data,
replace,
+ can_gc,
),
ConstellationControlMsg::UnloadDocument(pipeline_id) => {
self.handle_unload_document(pipeline_id)
@@ -2325,6 +2333,7 @@ impl ScriptThread {
top_level_browsing_context_id,
new_pipeline_id,
reason,
+ can_gc,
),
ConstellationControlMsg::UpdateHistoryState(pipeline_id, history_state_id, url) => {
self.handle_update_history_state_msg(pipeline_id, history_state_id, url)
@@ -2345,7 +2354,7 @@ impl ScriptThread {
target: browsing_context_id,
parent: parent_id,
child: child_id,
- } => self.handle_iframe_load_event(parent_id, browsing_context_id, child_id),
+ } => self.handle_iframe_load_event(parent_id, browsing_context_id, child_id, can_gc),
ConstellationControlMsg::DispatchStorageEvent(
pipeline_id,
storage,
@@ -2359,13 +2368,13 @@ impl ScriptThread {
},
ConstellationControlMsg::Reload(pipeline_id) => self.handle_reload(pipeline_id),
ConstellationControlMsg::ExitPipeline(pipeline_id, discard_browsing_context) => {
- self.handle_exit_pipeline_msg(pipeline_id, discard_browsing_context)
+ self.handle_exit_pipeline_msg(pipeline_id, discard_browsing_context, can_gc)
},
ConstellationControlMsg::PaintMetric(pipeline_id, metric_type, metric_value) => {
self.handle_paint_metric(pipeline_id, metric_type, metric_value)
},
ConstellationControlMsg::MediaSessionAction(pipeline_id, action) => {
- self.handle_media_session_action(pipeline_id, action)
+ self.handle_media_session_action(pipeline_id, action, can_gc)
},
ConstellationControlMsg::SetWebGPUPort(port) => {
if self.webgpu_port.borrow().is_some() {
@@ -3050,13 +3059,14 @@ impl ScriptThread {
top_level_browsing_context_id: TopLevelBrowsingContextId,
new_pipeline_id: PipelineId,
reason: UpdatePipelineIdReason,
+ can_gc: CanGc,
) {
let frame_element = self
.documents
.borrow()
.find_iframe(parent_pipeline_id, browsing_context_id);
if let Some(frame_element) = frame_element {
- frame_element.update_pipeline_id(new_pipeline_id, reason);
+ frame_element.update_pipeline_id(new_pipeline_id, reason, can_gc);
}
if let Some(window) = self.documents.borrow().find_window(new_pipeline_id) {
@@ -3123,6 +3133,7 @@ impl ScriptThread {
&self,
id: &PipelineId,
metadata: Option<Metadata>,
+ _can_gc: CanGc,
) -> Option<DomRoot<ServoParser>> {
let idx = self
.incomplete_loads
@@ -3161,7 +3172,7 @@ impl ScriptThread {
};
let load = self.incomplete_loads.borrow_mut().remove(idx);
- metadata.map(|meta| self.load(meta, load))
+ metadata.map(|meta| self.load(meta, load, CanGc::note()))
},
None => {
assert!(self.closed_pipelines.borrow().contains(id));
@@ -3244,7 +3255,12 @@ impl ScriptThread {
}
/// Handles a request to exit a pipeline and shut down layout.
- fn handle_exit_pipeline_msg(&self, id: PipelineId, discard_bc: DiscardBrowsingContext) {
+ fn handle_exit_pipeline_msg(
+ &self,
+ id: PipelineId,
+ discard_bc: DiscardBrowsingContext,
+ can_gc: CanGc,
+ ) {
debug!("{id}: Starting pipeline exit.");
self.closed_pipelines.borrow_mut().insert(id);
@@ -3261,7 +3277,7 @@ impl ScriptThread {
.any(|load| load.pipeline_id == id));
if let Some(parser) = document.get_current_parser() {
- parser.abort();
+ parser.abort(can_gc);
}
debug!("{id}: Shutting down layout");
@@ -3298,7 +3314,7 @@ impl ScriptThread {
}
/// Handles a request to exit the script thread and shut down layout.
- fn handle_exit_script_thread_msg(&self) {
+ fn handle_exit_script_thread_msg(&self, _can_gc: CanGc) {
debug!("Exiting script thread.");
let mut pipeline_ids = Vec::new();
@@ -3318,7 +3334,7 @@ impl ScriptThread {
);
for pipeline_id in pipeline_ids {
- self.handle_exit_pipeline_msg(pipeline_id, DiscardBrowsingContext::Yes);
+ self.handle_exit_pipeline_msg(pipeline_id, DiscardBrowsingContext::Yes, CanGc::note());
}
self.background_hang_monitor.unregister();
@@ -3399,13 +3415,14 @@ impl ScriptThread {
parent_id: PipelineId,
browsing_context_id: BrowsingContextId,
child_id: PipelineId,
+ can_gc: CanGc,
) {
let iframe = self
.documents
.borrow()
.find_iframe(parent_id, browsing_context_id);
match iframe {
- Some(iframe) => iframe.iframe_load_event_steps(child_id),
+ Some(iframe) => iframe.iframe_load_event_steps(child_id, can_gc),
None => warn!("Message sent to closed pipeline {}.", parent_id),
}
}
@@ -3547,7 +3564,12 @@ impl ScriptThread {
/// The entry point to document loading. Defines bindings, sets up the window and document
/// objects, parses HTML and CSS, and kicks off initial layout.
- fn load(&self, metadata: Metadata, incomplete: InProgressLoad) -> DomRoot<ServoParser> {
+ fn load(
+ &self,
+ metadata: Metadata,
+ incomplete: InProgressLoad,
+ can_gc: CanGc,
+ ) -> DomRoot<ServoParser> {
let final_url = metadata.final_url.clone();
{
self.script_sender
@@ -3736,6 +3758,7 @@ impl ScriptThread {
referrer_policy,
Some(status_code),
incomplete.canceller,
+ CanGc::note(),
);
document.set_ready_state(DocumentReadyState::Loading);
@@ -3758,6 +3781,7 @@ impl ScriptThread {
window_proxy.top_level_browsing_context_id(),
incomplete.pipeline_id,
UpdatePipelineIdReason::Navigation,
+ can_gc,
);
}
@@ -3776,9 +3800,9 @@ impl ScriptThread {
document.set_navigation_start(incomplete.navigation_start);
if is_html_document == IsHTMLDocument::NonHTMLDocument {
- ServoParser::parse_xml_document(&document, None, final_url);
+ ServoParser::parse_xml_document(&document, None, final_url, CanGc::note());
} else {
- ServoParser::parse_html_document(&document, None, final_url);
+ ServoParser::parse_html_document(&document, None, final_url, CanGc::note());
}
if incomplete.activity == DocumentActivity::FullyActive {
@@ -3901,13 +3925,14 @@ impl ScriptThread {
browsing_context_id: BrowsingContextId,
load_data: LoadData,
replace: HistoryEntryReplacement,
+ can_gc: CanGc,
) {
let iframe = self
.documents
.borrow()
.find_iframe(parent_pipeline_id, browsing_context_id);
if let Some(iframe) = iframe {
- iframe.navigate_or_reload_child_browsing_context(load_data, replace);
+ iframe.navigate_or_reload_child_browsing_context(load_data, replace, can_gc);
}
}
@@ -4179,10 +4204,15 @@ impl ScriptThread {
}
}
- fn handle_media_session_action(&self, pipeline_id: PipelineId, action: MediaSessionActionType) {
+ fn handle_media_session_action(
+ &self,
+ pipeline_id: PipelineId,
+ action: MediaSessionActionType,
+ can_gc: CanGc,
+ ) {
if let Some(window) = self.documents.borrow().find_window(pipeline_id) {
let media_session = window.Navigator().MediaSession();
- media_session.handle_action(action);
+ media_session.handle_action(action, can_gc);
} else {
warn!("No MediaSession for this pipeline ID");
};
@@ -4197,7 +4227,7 @@ impl ScriptThread {
});
}
- fn perform_a_microtask_checkpoint(&self) {
+ fn perform_a_microtask_checkpoint(&self, can_gc: CanGc) {
// Only perform the checkpoint if we're not shutting down.
if self.can_continue_running_inner() {
let globals = self
@@ -4211,6 +4241,7 @@ impl ScriptThread {
self.get_cx(),
|id| self.documents.borrow().find_global(id),
globals,
+ can_gc,
)
}
}
diff --git a/components/script/serviceworker_manager.rs b/components/script/serviceworker_manager.rs
index 8059e4ee41b..1c377bfc8a1 100644
--- a/components/script/serviceworker_manager.rs
+++ b/components/script/serviceworker_manager.rs
@@ -29,7 +29,7 @@ use crate::dom::serviceworkerglobalscope::{
ServiceWorkerControlMsg, ServiceWorkerGlobalScope, ServiceWorkerScriptMsg,
};
use crate::dom::serviceworkerregistration::longest_prefix_match;
-use crate::script_runtime::ContextForRequestInterrupt;
+use crate::script_runtime::{CanGc, ContextForRequestInterrupt};
enum Message {
FromResource(CustomResponseMediator),
@@ -250,10 +250,12 @@ impl ServiceWorkerManager {
None
}
- fn handle_message(&mut self) {
+ fn handle_message(&mut self, _can_gc: CanGc) {
while let Ok(message) = self.receive_message() {
let should_continue = match message {
- Message::FromConstellation(msg) => self.handle_message_from_constellation(msg),
+ Message::FromConstellation(msg) => {
+ self.handle_message_from_constellation(msg, CanGc::note())
+ },
Message::FromResource(msg) => self.handle_message_from_resource(msg),
};
if !should_continue {
@@ -288,7 +290,7 @@ impl ServiceWorkerManager {
}
}
- fn handle_message_from_constellation(&mut self, msg: ServiceWorkerMsg) -> bool {
+ fn handle_message_from_constellation(&mut self, msg: ServiceWorkerMsg, can_gc: CanGc) -> bool {
match msg {
ServiceWorkerMsg::Timeout(_scope) => {
// TODO: https://w3c.github.io/ServiceWorker/#terminate-service-worker
@@ -305,7 +307,7 @@ impl ServiceWorkerManager {
self.handle_register_job(job);
},
JobType::Update => {
- self.handle_update_job(job);
+ self.handle_update_job(job, can_gc);
},
JobType::Unregister => {
// TODO: https://w3c.github.io/ServiceWorker/#unregister-algorithm
@@ -380,7 +382,7 @@ impl ServiceWorkerManager {
}
/// <https://w3c.github.io/ServiceWorker/#update>
- fn handle_update_job(&mut self, job: Job) {
+ fn handle_update_job(&mut self, job: Job, can_gc: CanGc) {
// Step 1: Get registation
if let Some(registration) = self.registrations.get_mut(&job.scope_url) {
// Step 3.
@@ -403,8 +405,12 @@ impl ServiceWorkerManager {
// Very roughly steps 5 to 18.
// TODO: implement all steps precisely.
- let (new_worker, join_handle, control_sender, context, closing) =
- update_serviceworker(self.own_sender.clone(), job.scope_url.clone(), scope_things);
+ let (new_worker, join_handle, control_sender, context, closing) = update_serviceworker(
+ self.own_sender.clone(),
+ job.scope_url.clone(),
+ scope_things,
+ can_gc,
+ );
// Since we've just started the worker thread, ensure we can shut it down later.
registration.note_worker_thread(join_handle, control_sender, context, closing);
@@ -443,6 +449,7 @@ fn update_serviceworker(
own_sender: IpcSender<ServiceWorkerMsg>,
scope_url: ServoUrl,
scope_things: ScopeThings,
+ can_gc: CanGc,
) -> (
ServiceWorker,
JoinHandle<()>,
@@ -468,6 +475,7 @@ fn update_serviceworker(
control_receiver,
context_sender,
closing.clone(),
+ can_gc,
);
let context = context_receiver
@@ -504,7 +512,7 @@ impl ServiceWorkerManagerFactory for ServiceWorkerManager {
resource_port,
constellation_sender,
)
- .handle_message()
+ .handle_message(CanGc::note())
};
if thread::Builder::new()
.name("SvcWorkerManager".to_owned())
diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs
index 90aeb8754f1..079566d1971 100644
--- a/components/script/stylesheet_loader.rs
+++ b/components/script/stylesheet_loader.rs
@@ -44,6 +44,7 @@ use crate::dom::performanceresourcetiming::InitiatorType;
use crate::dom::shadowroot::ShadowRoot;
use crate::fetch::create_a_potential_cors_request;
use crate::network_listener::{self, NetworkListener, PreInvoke, ResourceTimingListener};
+use crate::script_runtime::CanGc;
pub trait StylesheetOwner {
/// Returns whether this element was inserted by the parser (i.e., it should
@@ -213,7 +214,7 @@ impl FetchResponseListener for StylesheetContext {
document.decrement_script_blocking_stylesheet_count();
}
- document.finish_load(LoadType::Stylesheet(self.url.clone()));
+ document.finish_load(LoadType::Stylesheet(self.url.clone()), CanGc::note());
if let Some(any_failed) = owner.load_finished(successful) {
let event = if any_failed {