mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Propagate CanGc
from Document::new()
(#33386)
* Add canGc as a parameter to autogenerated trait methods Signed-off-by: Andriy Sultanov <sultanovandriy@gmail.com> * Propagate CanGc from Document::new() Signed-off-by: Andriy Sultanov <sultanovandriy@gmail.com> --------- Signed-off-by: Andriy Sultanov <sultanovandriy@gmail.com>
This commit is contained in:
parent
10e5bb72d9
commit
e5150dbda1
41 changed files with 704 additions and 393 deletions
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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>()
|
||||
|
|
|
@ -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'],
|
||||
},
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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(())
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
},
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
//}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(©_contents_doc),
|
||||
CloneChildrenFlag::CloneChildren,
|
||||
CanGc::note(),
|
||||
);
|
||||
copy_contents.AppendChild(©_child).unwrap();
|
||||
}
|
||||
|
|
|
@ -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());
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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(),
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -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 => {},
|
||||
|
|
|
@ -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, ©, 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,
|
||||
))
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -159,6 +159,7 @@ impl Worker {
|
|||
global.wgpu_id_hub(),
|
||||
control_receiver,
|
||||
context_sender,
|
||||
CanGc::note(),
|
||||
);
|
||||
|
||||
let context = context_receiver
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue