CanGc fixes in several files (#33958)

* few cangc fixes

Signed-off-by: L Ashwin B <lashwinib@gmail.com>

* few cangc fixes

Signed-off-by: L Ashwin B <lashwinib@gmail.com>

---------

Signed-off-by: L Ashwin B <lashwinib@gmail.com>
This commit is contained in:
chickenleaf 2024-10-22 03:02:22 +05:30 committed by GitHub
parent 1bf68567b8
commit ebfea9b352
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 170 additions and 129 deletions

View file

@ -121,6 +121,10 @@ DOMInterfaces = {
'weakReferenceable': True, 'weakReferenceable': True,
}, },
'FileReader': {
'canGc': ['Abort'],
},
'GPU': { 'GPU': {
'inRealms': ['RequestAdapter'], 'inRealms': ['RequestAdapter'],
}, },
@ -164,11 +168,11 @@ DOMInterfaces = {
}, },
'HTMLFormElement': { 'HTMLFormElement': {
'canGc': ['RequestSubmit', 'ReportValidity'], 'canGc': ['RequestSubmit', 'ReportValidity', 'Submit'],
}, },
'HTMLInputElement': { 'HTMLInputElement': {
'canGc': ['ReportValidity'], 'canGc': ['ReportValidity', 'SelectFiles'],
}, },
'HTMLMediaElement': { 'HTMLMediaElement': {
@ -276,7 +280,7 @@ DOMInterfaces = {
}, },
'Response': { 'Response': {
'canGc': ['Error', 'Redirect', 'Clone', 'Text', 'Blob', 'FormData', 'Json', 'ArrayBuffer'], 'canGc': ['Error', 'Redirect', 'Clone', 'Text', 'Blob', 'FormData', 'Json', 'ArrayBuffer', 'Headers'],
}, },
'Request': { 'Request': {
@ -342,7 +346,7 @@ DOMInterfaces = {
}, },
'XMLHttpRequest': { 'XMLHttpRequest': {
'canGc': ['Abort', 'GetResponseXML', 'Response'], 'canGc': ['Abort', 'GetResponseXML', 'Response', 'Send'],
}, },
'XRBoundedReferenceSpace': { 'XRBoundedReferenceSpace': {

View file

@ -46,8 +46,9 @@ impl File {
blob_impl: BlobImpl, blob_impl: BlobImpl,
name: DOMString, name: DOMString,
modified: Option<SystemTime>, modified: Option<SystemTime>,
can_gc: CanGc,
) -> DomRoot<File> { ) -> DomRoot<File> {
Self::new_with_proto(global, None, blob_impl, name, modified, CanGc::note()) Self::new_with_proto(global, None, blob_impl, name, modified, can_gc)
} }
#[allow(crown::unrooted_must_root)] #[allow(crown::unrooted_must_root)]
@ -70,7 +71,11 @@ impl File {
} }
// Construct from selected file message from file manager thread // Construct from selected file message from file manager thread
pub fn new_from_selected(window: &Window, selected: SelectedFile) -> DomRoot<File> { pub fn new_from_selected(
window: &Window,
selected: SelectedFile,
can_gc: CanGc,
) -> DomRoot<File> {
let name = DOMString::from( let name = DOMString::from(
selected selected
.filename .filename
@ -88,6 +93,7 @@ impl File {
), ),
name, name,
Some(selected.modified), Some(selected.modified),
can_gc,
) )
} }

View file

@ -166,6 +166,7 @@ impl FileReader {
filereader: TrustedFileReader, filereader: TrustedFileReader,
gen_id: GenerationId, gen_id: GenerationId,
error: DOMErrorName, error: DOMErrorName,
can_gc: CanGc,
) { ) {
let fr = filereader.root(); let fr = filereader.root();
@ -185,17 +186,17 @@ impl FileReader {
let exception = DOMException::new(&fr.global(), error); let exception = DOMException::new(&fr.global(), error);
fr.error.set(Some(&exception)); fr.error.set(Some(&exception));
fr.dispatch_progress_event(atom!("error"), 0, None); fr.dispatch_progress_event(atom!("error"), 0, None, can_gc);
return_on_abort!(); return_on_abort!();
// Step 3 // Step 3
fr.dispatch_progress_event(atom!("loadend"), 0, None); fr.dispatch_progress_event(atom!("loadend"), 0, None, can_gc);
return_on_abort!(); return_on_abort!();
// Step 4 // Step 4
fr.terminate_ongoing_reading(); fr.terminate_ongoing_reading();
} }
// https://w3c.github.io/FileAPI/#dfn-readAsText // https://w3c.github.io/FileAPI/#dfn-readAsText
pub fn process_read_data(filereader: TrustedFileReader, gen_id: GenerationId) { pub fn process_read_data(filereader: TrustedFileReader, gen_id: GenerationId, can_gc: CanGc) {
let fr = filereader.root(); let fr = filereader.root();
macro_rules! return_on_abort( macro_rules! return_on_abort(
@ -207,11 +208,11 @@ impl FileReader {
); );
return_on_abort!(); return_on_abort!();
//FIXME Step 7 send current progress //FIXME Step 7 send current progress
fr.dispatch_progress_event(atom!("progress"), 0, None); fr.dispatch_progress_event(atom!("progress"), 0, None, can_gc);
} }
// https://w3c.github.io/FileAPI/#dfn-readAsText // https://w3c.github.io/FileAPI/#dfn-readAsText
pub fn process_read(filereader: TrustedFileReader, gen_id: GenerationId) { pub fn process_read(filereader: TrustedFileReader, gen_id: GenerationId, can_gc: CanGc) {
let fr = filereader.root(); let fr = filereader.root();
macro_rules! return_on_abort( macro_rules! return_on_abort(
@ -223,7 +224,7 @@ impl FileReader {
); );
return_on_abort!(); return_on_abort!();
// Step 6 // Step 6
fr.dispatch_progress_event(atom!("loadstart"), 0, None); fr.dispatch_progress_event(atom!("loadstart"), 0, None, can_gc);
} }
// https://w3c.github.io/FileAPI/#dfn-readAsText // https://w3c.github.io/FileAPI/#dfn-readAsText
@ -232,6 +233,7 @@ impl FileReader {
gen_id: GenerationId, gen_id: GenerationId,
data: ReadMetaData, data: ReadMetaData,
blob_contents: Vec<u8>, blob_contents: Vec<u8>,
can_gc: CanGc,
) { ) {
let fr = filereader.root(); let fr = filereader.root();
@ -267,11 +269,11 @@ impl FileReader {
}; };
// Step 8.3 // Step 8.3
fr.dispatch_progress_event(atom!("load"), 0, None); fr.dispatch_progress_event(atom!("load"), 0, None, can_gc);
return_on_abort!(); return_on_abort!();
// Step 8.4 // Step 8.4
if fr.ready_state.get() != FileReaderReadyState::Loading { if fr.ready_state.get() != FileReaderReadyState::Loading {
fr.dispatch_progress_event(atom!("loadend"), 0, None); fr.dispatch_progress_event(atom!("loadend"), 0, None, can_gc);
} }
return_on_abort!(); return_on_abort!();
} }
@ -368,7 +370,7 @@ impl FileReaderMethods for FileReader {
} }
// https://w3c.github.io/FileAPI/#dfn-abort // https://w3c.github.io/FileAPI/#dfn-abort
fn Abort(&self) { fn Abort(&self, can_gc: CanGc) {
// Step 2 // Step 2
if self.ready_state.get() == FileReaderReadyState::Loading { if self.ready_state.get() == FileReaderReadyState::Loading {
self.change_ready_state(FileReaderReadyState::Done); self.change_ready_state(FileReaderReadyState::Done);
@ -381,8 +383,8 @@ impl FileReaderMethods for FileReader {
self.terminate_ongoing_reading(); self.terminate_ongoing_reading();
// Steps 5 & 6 // Steps 5 & 6
self.dispatch_progress_event(atom!("abort"), 0, None); self.dispatch_progress_event(atom!("abort"), 0, None, can_gc);
self.dispatch_progress_event(atom!("loadend"), 0, None); self.dispatch_progress_event(atom!("loadend"), 0, None, can_gc);
} }
// https://w3c.github.io/FileAPI/#dfn-error // https://w3c.github.io/FileAPI/#dfn-error
@ -412,7 +414,7 @@ impl FileReaderMethods for FileReader {
} }
impl FileReader { impl FileReader {
fn dispatch_progress_event(&self, type_: Atom, loaded: u64, total: Option<u64>) { fn dispatch_progress_event(&self, type_: Atom, loaded: u64, total: Option<u64>, can_gc: CanGc) {
let progressevent = ProgressEvent::new( let progressevent = ProgressEvent::new(
&self.global(), &self.global(),
type_, type_,
@ -421,6 +423,7 @@ impl FileReader {
total.is_some(), total.is_some(),
loaded, loaded,
total.unwrap_or(0), total.unwrap_or(0),
can_gc,
); );
progressevent.upcast::<Event>().fire(self.upcast()); progressevent.upcast::<Event>().fire(self.upcast());
} }

View file

@ -110,7 +110,11 @@ impl FormDataMethods for FormData {
let datum = FormDatum { let datum = FormDatum {
ty: DOMString::from("file"), ty: DOMString::from("file"),
name: DOMString::from(name.0.clone()), name: DOMString::from(name.0.clone()),
value: FormDatumValue::File(DomRoot::from_ref(&*self.create_an_entry(blob, filename))), value: FormDatumValue::File(DomRoot::from_ref(&*self.create_an_entry(
blob,
filename,
CanGc::note(),
))),
}; };
self.data self.data
@ -187,7 +191,7 @@ impl FormDataMethods for FormData {
#[allow(crown::unrooted_must_root)] #[allow(crown::unrooted_must_root)]
// https://xhr.spec.whatwg.org/#dom-formdata-set // https://xhr.spec.whatwg.org/#dom-formdata-set
fn Set_(&self, name: USVString, blob: &Blob, filename: Option<USVString>) { fn Set_(&self, name: USVString, blob: &Blob, filename: Option<USVString>) {
let file = self.create_an_entry(blob, filename); let file = self.create_an_entry(blob, filename, CanGc::note());
let mut data = self.data.borrow_mut(); let mut data = self.data.borrow_mut();
let local_name = LocalName::from(name.0.clone()); let local_name = LocalName::from(name.0.clone());
@ -207,7 +211,12 @@ impl FormDataMethods for FormData {
impl FormData { impl FormData {
// https://xhr.spec.whatwg.org/#create-an-entry // https://xhr.spec.whatwg.org/#create-an-entry
fn create_an_entry(&self, blob: &Blob, opt_filename: Option<USVString>) -> DomRoot<File> { fn create_an_entry(
&self,
blob: &Blob,
opt_filename: Option<USVString>,
can_gc: CanGc,
) -> DomRoot<File> {
// Steps 3-4 // Steps 3-4
let name = match opt_filename { let name = match opt_filename {
Some(filename) => DOMString::from(filename.0), Some(filename) => DOMString::from(filename.0),
@ -229,6 +238,7 @@ impl FormData {
BlobImpl::new_from_bytes(bytes, blob.type_string()), BlobImpl::new_from_bytes(bytes, blob.type_string()),
name, name,
None, None,
can_gc,
) )
} }

View file

@ -216,7 +216,7 @@ impl Gamepad {
self.gamepad_id self.gamepad_id
} }
pub fn update_connected(&self, connected: bool, has_gesture: bool) { pub fn update_connected(&self, connected: bool, has_gesture: bool, can_gc: CanGc) {
if self.connected.get() == connected { if self.connected.get() == connected {
return; return;
} }
@ -229,7 +229,7 @@ impl Gamepad {
}; };
if has_gesture { if has_gesture {
self.notify_event(event_type); self.notify_event(event_type, can_gc);
} }
} }
@ -245,8 +245,8 @@ impl Gamepad {
self.timestamp.set(timestamp); self.timestamp.set(timestamp);
} }
pub fn notify_event(&self, event_type: GamepadEventType) { pub fn notify_event(&self, event_type: GamepadEventType, can_gc: CanGc) {
let event = GamepadEvent::new_with_type(&self.global(), event_type, self, CanGc::note()); let event = GamepadEvent::new_with_type(&self.global(), event_type, self, can_gc);
event event
.upcast::<Event>() .upcast::<Event>()
.fire(self.global().as_window().upcast::<EventTarget>()); .fire(self.global().as_window().upcast::<EventTarget>());

View file

@ -3239,7 +3239,7 @@ impl GlobalScope {
false, false,
CanGc::note(), CanGc::note(),
); );
navigator.set_gamepad(selected_index as usize, &gamepad); navigator.set_gamepad(selected_index as usize, &gamepad, CanGc::note());
} }
}), }),
&self.task_canceller(TaskSourceName::Gamepad), &self.task_canceller(TaskSourceName::Gamepad),
@ -3258,7 +3258,7 @@ impl GlobalScope {
let navigator = window.Navigator(); let navigator = window.Navigator();
if let Some(gamepad) = navigator.get_gamepad(index) { if let Some(gamepad) = navigator.get_gamepad(index) {
if window.Document().is_fully_active() { if window.Document().is_fully_active() {
gamepad.update_connected(false, gamepad.exposed()); gamepad.update_connected(false, gamepad.exposed(), CanGc::note());
navigator.remove_gamepad(index); navigator.remove_gamepad(index);
} }
} }
@ -3304,7 +3304,7 @@ impl GlobalScope {
window.task_manager().gamepad_task_source().queue_with_canceller( window.task_manager().gamepad_task_source().queue_with_canceller(
task!(update_gamepad_connect: move || { task!(update_gamepad_connect: move || {
let gamepad = new_gamepad.root(); let gamepad = new_gamepad.root();
gamepad.notify_event(GamepadEventType::Connected); gamepad.notify_event(GamepadEventType::Connected, CanGc::note());
}), }),
&window.upcast::<GlobalScope>() &window.upcast::<GlobalScope>()
.task_canceller(TaskSourceName::Gamepad), .task_canceller(TaskSourceName::Gamepad),

View file

@ -269,11 +269,11 @@ impl HTMLFormElementMethods for HTMLFormElement {
make_getter!(Rel, "rel"); make_getter!(Rel, "rel");
// https://html.spec.whatwg.org/multipage/#the-form-element:concept-form-submit // https://html.spec.whatwg.org/multipage/#the-form-element:concept-form-submit
fn Submit(&self) { fn Submit(&self, can_gc: CanGc) {
self.submit( self.submit(
SubmittedFrom::FromForm, SubmittedFrom::FromForm,
FormSubmitterElement::Form(self), FormSubmitterElement::Form(self),
CanGc::note(), can_gc,
); );
} }

View file

@ -1559,9 +1559,9 @@ impl HTMLInputElementMethods for HTMLInputElement {
// enabled by dom.htmlinputelement.select_files.enabled, // enabled by dom.htmlinputelement.select_files.enabled,
// used for test purpose. // used for test purpose.
// check-tidy: no specs after this line // check-tidy: no specs after this line
fn SelectFiles(&self, paths: Vec<DOMString>) { fn SelectFiles(&self, paths: Vec<DOMString>, can_gc: CanGc) {
if self.input_type() == InputType::File { if self.input_type() == InputType::File {
self.select_files(Some(paths)); self.select_files(Some(paths), can_gc);
} }
} }
@ -1826,7 +1826,7 @@ impl HTMLInputElement {
// https://html.spec.whatwg.org/multipage/#file-upload-state-(type=file) // https://html.spec.whatwg.org/multipage/#file-upload-state-(type=file)
// Select files by invoking UI or by passed in argument // Select files by invoking UI or by passed in argument
fn select_files(&self, opt_test_paths: Option<Vec<DOMString>>) { fn select_files(&self, opt_test_paths: Option<Vec<DOMString>>, can_gc: CanGc) {
let window = window_from_node(self); let window = window_from_node(self);
let origin = get_blob_origin(&window.get_url()); let origin = get_blob_origin(&window.get_url());
let resource_threads = window.upcast::<GlobalScope>().resource_threads(); let resource_threads = window.upcast::<GlobalScope>().resource_threads();
@ -1851,7 +1851,7 @@ impl HTMLInputElement {
match recv.recv().expect("IpcSender side error") { match recv.recv().expect("IpcSender side error") {
Ok(selected_files) => { Ok(selected_files) => {
for selected in selected_files { for selected in selected_files {
files.push(File::new_from_selected(&window, selected)); files.push(File::new_from_selected(&window, selected, can_gc));
} }
}, },
Err(err) => error = Some(err), Err(err) => error = Some(err),
@ -1877,7 +1877,7 @@ impl HTMLInputElement {
match recv.recv().expect("IpcSender side error") { match recv.recv().expect("IpcSender side error") {
Ok(selected) => { Ok(selected) => {
files.push(File::new_from_selected(&window, selected)); files.push(File::new_from_selected(&window, selected, can_gc));
}, },
Err(err) => error = Some(err), Err(err) => error = Some(err),
}; };
@ -2839,7 +2839,7 @@ impl Activatable for HTMLInputElement {
target.fire_bubbling_event(atom!("input")); target.fire_bubbling_event(atom!("input"));
target.fire_bubbling_event(atom!("change")); target.fire_bubbling_event(atom!("change"));
}, },
InputType::File => self.select_files(None), InputType::File => self.select_files(None, CanGc::note()),
_ => (), _ => (),
} }
} }

View file

@ -1632,6 +1632,7 @@ impl HTMLMediaElement {
false, false,
false, false,
&Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(audio_track)), &Some(VideoTrackOrAudioTrackOrTextTrack::AudioTrack(audio_track)),
can_gc,
); );
event.upcast::<Event>().fire(self.upcast::<EventTarget>()); event.upcast::<Event>().fire(self.upcast::<EventTarget>());
@ -1686,6 +1687,7 @@ impl HTMLMediaElement {
false, false,
false, false,
&Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(video_track)), &Some(VideoTrackOrAudioTrackOrTextTrack::VideoTrack(video_track)),
can_gc,
); );
event.upcast::<Event>().fire(self.upcast::<EventTarget>()); event.upcast::<Event>().fire(self.upcast::<EventTarget>());

View file

@ -29,7 +29,7 @@ use crate::dom::pluginarray::PluginArray;
use crate::dom::serviceworkercontainer::ServiceWorkerContainer; use crate::dom::serviceworkercontainer::ServiceWorkerContainer;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::dom::xrsystem::XRSystem; use crate::dom::xrsystem::XRSystem;
use crate::script_runtime::JSContext; use crate::script_runtime::{CanGc, JSContext};
pub(super) fn hardware_concurrency() -> u64 { pub(super) fn hardware_concurrency() -> u64 {
static CPUS: LazyLock<u64> = LazyLock::new(|| num_cpus::get().try_into().unwrap_or(1)); static CPUS: LazyLock<u64> = LazyLock::new(|| num_cpus::get().try_into().unwrap_or(1));
@ -85,14 +85,14 @@ impl Navigator {
self.gamepads.borrow().get(index).and_then(|g| g.get()) self.gamepads.borrow().get(index).and_then(|g| g.get())
} }
pub fn set_gamepad(&self, index: usize, gamepad: &Gamepad) { pub fn set_gamepad(&self, index: usize, gamepad: &Gamepad, can_gc: CanGc) {
if let Some(gamepad_to_set) = self.gamepads.borrow().get(index) { if let Some(gamepad_to_set) = self.gamepads.borrow().get(index) {
gamepad_to_set.set(Some(gamepad)); gamepad_to_set.set(Some(gamepad));
} }
if self.has_gamepad_gesture.get() { if self.has_gamepad_gesture.get() {
gamepad.set_exposed(true); gamepad.set_exposed(true);
if self.global().as_window().Document().is_fully_active() { if self.global().as_window().Document().is_fully_active() {
gamepad.notify_event(GamepadEventType::Connected); gamepad.notify_event(GamepadEventType::Connected, can_gc);
} }
} }
} }

View file

@ -36,6 +36,7 @@ impl ProgressEvent {
} }
} }
#[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
global: &GlobalScope, global: &GlobalScope,
type_: Atom, type_: Atom,
@ -44,6 +45,7 @@ impl ProgressEvent {
length_computable: bool, length_computable: bool,
loaded: u64, loaded: u64,
total: u64, total: u64,
can_gc: CanGc,
) -> DomRoot<ProgressEvent> { ) -> DomRoot<ProgressEvent> {
Self::new_with_proto( Self::new_with_proto(
global, global,
@ -54,7 +56,7 @@ impl ProgressEvent {
length_computable, length_computable,
loaded, loaded,
total, total,
CanGc::note(), can_gc,
) )
} }

View file

@ -113,8 +113,8 @@ impl BodyMixin for Response {
self.body_stream.get() self.body_stream.get()
} }
fn get_mime_type(&self, _can_gc: CanGc) -> Vec<u8> { fn get_mime_type(&self, can_gc: CanGc) -> Vec<u8> {
let headers = self.Headers(); let headers = self.Headers(can_gc);
headers.extract_mime_type() headers.extract_mime_type()
} }
} }
@ -172,7 +172,7 @@ impl ResponseMethods for Response {
// Step 5 // Step 5
if let Some(ref headers_member) = init.headers { if let Some(ref headers_member) = init.headers {
r.Headers().fill(Some(headers_member.clone()))?; r.Headers(can_gc).fill(Some(headers_member.clone()))?;
} }
// Step 6 // Step 6
@ -197,11 +197,11 @@ impl ResponseMethods for Response {
// Step 6.3 // Step 6.3
if let Some(content_type_contents) = content_type { if let Some(content_type_contents) = content_type {
if !r if !r
.Headers() .Headers(can_gc)
.Has(ByteString::new(b"Content-Type".to_vec())) .Has(ByteString::new(b"Content-Type".to_vec()))
.unwrap() .unwrap()
{ {
r.Headers().Append( r.Headers(can_gc).Append(
ByteString::new(b"Content-Type".to_vec()), ByteString::new(b"Content-Type".to_vec()),
ByteString::new(content_type_contents.as_bytes().to_vec()), ByteString::new(content_type_contents.as_bytes().to_vec()),
)?; )?;
@ -221,7 +221,7 @@ impl ResponseMethods for Response {
fn Error(global: &GlobalScope, can_gc: CanGc) -> DomRoot<Response> { fn Error(global: &GlobalScope, can_gc: CanGc) -> DomRoot<Response> {
let r = Response::new(global, can_gc); let r = Response::new(global, can_gc);
*r.response_type.borrow_mut() = DOMResponseType::Error; *r.response_type.borrow_mut() = DOMResponseType::Error;
r.Headers().set_guard(Guard::Immutable); r.Headers(can_gc).set_guard(Guard::Immutable);
*r.status.borrow_mut() = HttpStatus::new_error(); *r.status.borrow_mut() = HttpStatus::new_error();
r r
} }
@ -258,12 +258,12 @@ impl ResponseMethods for Response {
// Step 6 // Step 6
let url_bytestring = let url_bytestring =
ByteString::from_str(url.as_str()).unwrap_or(ByteString::new(b"".to_vec())); ByteString::from_str(url.as_str()).unwrap_or(ByteString::new(b"".to_vec()));
r.Headers() r.Headers(can_gc)
.Set(ByteString::new(b"Location".to_vec()), url_bytestring)?; .Set(ByteString::new(b"Location".to_vec()), url_bytestring)?;
// Step 4 continued // Step 4 continued
// Headers Guard is set to Immutable here to prevent error in Step 6 // Headers Guard is set to Immutable here to prevent error in Step 6
r.Headers().set_guard(Guard::Immutable); r.Headers(can_gc).set_guard(Guard::Immutable);
// Step 7 // Step 7
Ok(r) Ok(r)
@ -305,9 +305,9 @@ impl ResponseMethods for Response {
} }
// https://fetch.spec.whatwg.org/#dom-response-headers // https://fetch.spec.whatwg.org/#dom-response-headers
fn Headers(&self) -> DomRoot<Headers> { fn Headers(&self, can_gc: CanGc) -> DomRoot<Headers> {
self.headers_reflector self.headers_reflector
.or_init(|| Headers::for_response(&self.global(), CanGc::note())) .or_init(|| Headers::for_response(&self.global(), can_gc))
} }
// https://fetch.spec.whatwg.org/#dom-response-clone // https://fetch.spec.whatwg.org/#dom-response-clone
@ -319,8 +319,12 @@ impl ResponseMethods for Response {
// Step 2 // Step 2
let new_response = Response::new(&self.global(), can_gc); let new_response = Response::new(&self.global(), can_gc);
new_response.Headers().copy_from_headers(self.Headers())?; new_response
new_response.Headers().set_guard(self.Headers().get_guard()); .Headers(can_gc)
.copy_from_headers(self.Headers(can_gc))?;
new_response
.Headers(can_gc)
.set_guard(self.Headers(can_gc).get_guard());
// https://fetch.spec.whatwg.org/#concept-response-clone // https://fetch.spec.whatwg.org/#concept-response-clone
// Instead of storing a net_traits::Response internally, we // Instead of storing a net_traits::Response internally, we
@ -388,13 +392,14 @@ fn serialize_without_fragment(url: &ServoUrl) -> &str {
} }
impl Response { impl Response {
pub fn set_type(&self, new_response_type: DOMResponseType) { pub fn set_type(&self, new_response_type: DOMResponseType, can_gc: CanGc) {
*self.response_type.borrow_mut() = new_response_type; *self.response_type.borrow_mut() = new_response_type;
self.set_response_members_by_type(new_response_type); self.set_response_members_by_type(new_response_type, can_gc);
} }
pub fn set_headers(&self, option_hyper_headers: Option<Serde<HyperHeaders>>) { pub fn set_headers(&self, option_hyper_headers: Option<Serde<HyperHeaders>>, can_gc: CanGc) {
self.Headers().set_headers(match option_hyper_headers { self.Headers(can_gc)
.set_headers(match option_hyper_headers {
Some(hyper_headers) => hyper_headers.into_inner(), Some(hyper_headers) => hyper_headers.into_inner(),
None => HyperHeaders::new(), None => HyperHeaders::new(),
}); });
@ -412,21 +417,21 @@ impl Response {
*self.redirected.borrow_mut() = is_redirected; *self.redirected.borrow_mut() = is_redirected;
} }
fn set_response_members_by_type(&self, response_type: DOMResponseType) { fn set_response_members_by_type(&self, response_type: DOMResponseType, can_gc: CanGc) {
match response_type { match response_type {
DOMResponseType::Error => { DOMResponseType::Error => {
*self.status.borrow_mut() = HttpStatus::new_error(); *self.status.borrow_mut() = HttpStatus::new_error();
self.set_headers(None); self.set_headers(None, can_gc);
}, },
DOMResponseType::Opaque => { DOMResponseType::Opaque => {
*self.url_list.borrow_mut() = vec![]; *self.url_list.borrow_mut() = vec![];
*self.status.borrow_mut() = HttpStatus::new_error(); *self.status.borrow_mut() = HttpStatus::new_error();
self.set_headers(None); self.set_headers(None, can_gc);
self.body_stream.set(None); self.body_stream.set(None);
}, },
DOMResponseType::Opaqueredirect => { DOMResponseType::Opaqueredirect => {
*self.status.borrow_mut() = HttpStatus::new_error(); *self.status.borrow_mut() = HttpStatus::new_error();
self.set_headers(None); self.set_headers(None, can_gc);
self.body_stream.set(None); self.body_stream.set(None);
}, },
DOMResponseType::Default => {}, DOMResponseType::Default => {},

View file

@ -93,16 +93,9 @@ impl SecurityPolicyViolationEvent {
bubbles: EventBubbles, bubbles: EventBubbles,
cancelable: EventCancelable, cancelable: EventCancelable,
init: &SecurityPolicyViolationEventInit, init: &SecurityPolicyViolationEventInit,
can_gc: CanGc,
) -> DomRoot<Self> { ) -> DomRoot<Self> {
Self::new_with_proto( Self::new_with_proto(global, None, type_, bubbles, cancelable, init, can_gc)
global,
None,
type_,
bubbles,
cancelable,
init,
CanGc::note(),
)
} }
} }

View file

@ -158,22 +158,22 @@ struct SerializationIterator {
stack: Vec<SerializationCommand>, stack: Vec<SerializationCommand>,
} }
fn rev_children_iter(n: &Node) -> impl Iterator<Item = DomRoot<Node>> { fn rev_children_iter(n: &Node, can_gc: CanGc) -> impl Iterator<Item = DomRoot<Node>> {
if n.downcast::<Element>().is_some_and(|e| e.is_void()) { if n.downcast::<Element>().is_some_and(|e| e.is_void()) {
return Node::new_document_node().rev_children(); return Node::new_document_node().rev_children();
} }
match n.downcast::<HTMLTemplateElement>() { match n.downcast::<HTMLTemplateElement>() {
Some(t) => t.Content(CanGc::note()).upcast::<Node>().rev_children(), Some(t) => t.Content(can_gc).upcast::<Node>().rev_children(),
None => n.rev_children(), None => n.rev_children(),
} }
} }
impl SerializationIterator { impl SerializationIterator {
fn new(node: &Node, skip_first: bool) -> SerializationIterator { fn new(node: &Node, skip_first: bool, can_gc: CanGc) -> SerializationIterator {
let mut ret = SerializationIterator { stack: vec![] }; let mut ret = SerializationIterator { stack: vec![] };
if skip_first || node.is::<DocumentFragment>() || node.is::<Document>() { if skip_first || node.is::<DocumentFragment>() || node.is::<Document>() {
for c in rev_children_iter(node) { for c in rev_children_iter(node, can_gc) {
ret.push_node(&c); ret.push_node(&c);
} }
} else { } else {
@ -203,7 +203,7 @@ impl Iterator for SerializationIterator {
if let Some(SerializationCommand::OpenElement(ref e)) = res { if let Some(SerializationCommand::OpenElement(ref e)) = res {
self.stack self.stack
.push(SerializationCommand::CloseElement(e.clone())); .push(SerializationCommand::CloseElement(e.clone()));
for c in rev_children_iter(e.upcast::<Node>()) { for c in rev_children_iter(e.upcast::<Node>(), CanGc::note()) {
self.push_node(&c); self.push_node(&c);
} }
} }
@ -220,7 +220,7 @@ impl<'a> Serialize for &'a Node {
) -> io::Result<()> { ) -> io::Result<()> {
let node = *self; let node = *self;
let iter = SerializationIterator::new(node, traversal_scope != IncludeNode); let iter = SerializationIterator::new(node, traversal_scope != IncludeNode, CanGc::note());
for cmd in iter { for cmd in iter {
match cmd { match cmd {

View file

@ -17,6 +17,7 @@ use crate::dom::eventtarget::EventTarget;
use crate::dom::texttrack::TextTrack; use crate::dom::texttrack::TextTrack;
use crate::dom::trackevent::TrackEvent; use crate::dom::trackevent::TrackEvent;
use crate::dom::window::Window; use crate::dom::window::Window;
use crate::script_runtime::CanGc;
use crate::task_source::TaskSource; use crate::task_source::TaskSource;
#[dom_struct] #[dom_struct]
@ -83,6 +84,7 @@ impl TextTrackList {
&Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack( &Some(VideoTrackOrAudioTrackOrTextTrack::TextTrack(
DomRoot::from_ref(&track) DomRoot::from_ref(&track)
)), )),
CanGc::note()
); );
event.upcast::<Event>().fire(this.upcast::<EventTarget>()); event.upcast::<Event>().fire(this.upcast::<EventTarget>());

View file

@ -65,16 +65,9 @@ impl TrackEvent {
bubbles: bool, bubbles: bool,
cancelable: bool, cancelable: bool,
track: &Option<VideoTrackOrAudioTrackOrTextTrack>, track: &Option<VideoTrackOrAudioTrackOrTextTrack>,
can_gc: CanGc,
) -> DomRoot<TrackEvent> { ) -> DomRoot<TrackEvent> {
Self::new_with_proto( Self::new_with_proto(global, None, type_, bubbles, cancelable, track, can_gc)
global,
None,
type_,
bubbles,
cancelable,
track,
CanGc::note(),
)
} }
fn new_with_proto( fn new_with_proto(

View file

@ -554,7 +554,7 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
} }
/// <https://xhr.spec.whatwg.org/#the-send()-method> /// <https://xhr.spec.whatwg.org/#the-send()-method>
fn Send(&self, data: Option<DocumentOrXMLHttpRequestBodyInit>) -> ErrorResult { fn Send(&self, data: Option<DocumentOrXMLHttpRequestBodyInit>, can_gc: CanGc) -> ErrorResult {
// Step 1, 2 // Step 1, 2
if self.ready_state.get() != XMLHttpRequestState::Opened || self.send_flag.get() { if self.ready_state.get() != XMLHttpRequestState::Opened || self.send_flag.get() {
return Err(Error::InvalidState); return Err(Error::InvalidState);
@ -661,13 +661,13 @@ impl XMLHttpRequestMethods for XMLHttpRequest {
// abort or open we will need the current generation id to detect it. // abort or open we will need the current generation id to detect it.
// Substep 1 // Substep 1
let gen_id = self.generation_id.get(); let gen_id = self.generation_id.get();
self.dispatch_response_progress_event(atom!("loadstart")); self.dispatch_response_progress_event(atom!("loadstart"), can_gc);
if self.generation_id.get() != gen_id { if self.generation_id.get() != gen_id {
return Ok(()); return Ok(());
} }
// Substep 2 // Substep 2
if !self.upload_complete.get() && self.upload_listener.get() { if !self.upload_complete.get() && self.upload_listener.get() {
self.dispatch_upload_progress_event(atom!("loadstart"), Ok(Some(0))); self.dispatch_upload_progress_event(atom!("loadstart"), Ok(Some(0)), can_gc);
if self.generation_id.get() != gen_id { if self.generation_id.get() != gen_id {
return Ok(()); return Ok(());
} }
@ -1114,11 +1114,11 @@ impl XMLHttpRequest {
self.upload_complete.set(true); self.upload_complete.set(true);
// Substeps 2-4 // Substeps 2-4
if !self.sync.get() && self.upload_listener.get() { if !self.sync.get() && self.upload_listener.get() {
self.dispatch_upload_progress_event(atom!("progress"), Ok(None)); self.dispatch_upload_progress_event(atom!("progress"), Ok(None), can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
self.dispatch_upload_progress_event(atom!("load"), Ok(None)); self.dispatch_upload_progress_event(atom!("load"), Ok(None), can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
self.dispatch_upload_progress_event(atom!("loadend"), Ok(None)); self.dispatch_upload_progress_event(atom!("loadend"), Ok(None), can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
} }
// Part of step 13, send() (processing response) // Part of step 13, send() (processing response)
@ -1171,7 +1171,7 @@ impl XMLHttpRequest {
); );
event.fire(self.upcast()); event.fire(self.upcast());
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
self.dispatch_response_progress_event(atom!("progress")); self.dispatch_response_progress_event(atom!("progress"), can_gc);
} }
}, },
XHRProgress::Done(_) => { XHRProgress::Done(_) => {
@ -1193,9 +1193,9 @@ impl XMLHttpRequest {
self.change_ready_state(XMLHttpRequestState::Done, can_gc); self.change_ready_state(XMLHttpRequestState::Done, can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
// Subsubsteps 11-12 // Subsubsteps 11-12
self.dispatch_response_progress_event(atom!("load")); self.dispatch_response_progress_event(atom!("load"), can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
self.dispatch_response_progress_event(atom!("loadend")); self.dispatch_response_progress_event(atom!("loadend"), can_gc);
}, },
XHRProgress::Errored(_, e) => { XHRProgress::Errored(_, e) => {
self.cancel_timeout(); self.cancel_timeout();
@ -1217,15 +1217,15 @@ impl XMLHttpRequest {
if !upload_complete.get() { if !upload_complete.get() {
upload_complete.set(true); upload_complete.set(true);
if self.upload_listener.get() { if self.upload_listener.get() {
self.dispatch_upload_progress_event(Atom::from(errormsg), Err(())); self.dispatch_upload_progress_event(Atom::from(errormsg), Err(()), can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
self.dispatch_upload_progress_event(atom!("loadend"), Err(())); self.dispatch_upload_progress_event(atom!("loadend"), Err(()), can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
} }
} }
self.dispatch_response_progress_event(Atom::from(errormsg)); self.dispatch_response_progress_event(Atom::from(errormsg), can_gc);
return_if_fetch_was_terminated!(); return_if_fetch_was_terminated!();
self.dispatch_response_progress_event(atom!("loadend")); self.dispatch_response_progress_event(atom!("loadend"), can_gc);
}, },
} }
} }
@ -1237,7 +1237,14 @@ impl XMLHttpRequest {
self.response_status.set(Ok(())); self.response_status.set(Ok(()));
} }
fn dispatch_progress_event(&self, upload: bool, type_: Atom, loaded: u64, total: Option<u64>) { fn dispatch_progress_event(
&self,
upload: bool,
type_: Atom,
loaded: u64,
total: Option<u64>,
can_gc: CanGc,
) {
let (total_length, length_computable) = if self let (total_length, length_computable) = if self
.response_headers .response_headers
.borrow() .borrow()
@ -1255,6 +1262,7 @@ impl XMLHttpRequest {
length_computable, length_computable,
loaded, loaded,
total_length, total_length,
can_gc,
); );
let target = if upload { let target = if upload {
self.upload.upcast() self.upload.upcast()
@ -1264,7 +1272,12 @@ impl XMLHttpRequest {
progressevent.upcast::<Event>().fire(target); progressevent.upcast::<Event>().fire(target);
} }
fn dispatch_upload_progress_event(&self, type_: Atom, partial_load: Result<Option<u64>, ()>) { fn dispatch_upload_progress_event(
&self,
type_: Atom,
partial_load: Result<Option<u64>, ()>,
can_gc: CanGc,
) {
// If partial_load is Ok(None), loading has completed and we can just use the value from the request body // If partial_load is Ok(None), loading has completed and we can just use the value from the request body
// If an error occured, we pass 0 for both loaded and total // If an error occured, we pass 0 for both loaded and total
@ -1276,17 +1289,17 @@ impl XMLHttpRequest {
}, },
Err(()) => (0, None), Err(()) => (0, None),
}; };
self.dispatch_progress_event(true, type_, loaded, total); self.dispatch_progress_event(true, type_, loaded, total, can_gc);
} }
fn dispatch_response_progress_event(&self, type_: Atom) { fn dispatch_response_progress_event(&self, type_: Atom, can_gc: CanGc) {
let len = self.response.borrow().len() as u64; let len = self.response.borrow().len() as u64;
let total = self let total = self
.response_headers .response_headers
.borrow() .borrow()
.typed_get::<ContentLength>() .typed_get::<ContentLength>()
.map(|v| v.0); .map(|v| v.0);
self.dispatch_progress_event(false, type_, len, total); self.dispatch_progress_event(false, type_, len, total, can_gc);
} }
fn set_timeout(&self, duration: Duration) { fn set_timeout(&self, duration: Duration) {

View file

@ -71,7 +71,7 @@ impl XRInputSourceArray {
pub fn remove_input_source(&self, session: &XRSession, id: InputId, can_gc: CanGc) { pub fn remove_input_source(&self, session: &XRSession, id: InputId, can_gc: CanGc) {
let global = self.global(); let global = self.global();
let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) { let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
i.gamepad().update_connected(false, false); i.gamepad().update_connected(false, false, can_gc);
[DomRoot::from_ref(&**i)] [DomRoot::from_ref(&**i)]
} else { } else {
return; return;
@ -101,7 +101,7 @@ impl XRInputSourceArray {
let global = self.global(); let global = self.global();
let root; let root;
let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) { let removed = if let Some(i) = self.input_sources.borrow().iter().find(|i| i.id() == id) {
i.gamepad().update_connected(false, false); i.gamepad().update_connected(false, false, can_gc);
root = [DomRoot::from_ref(&**i)]; root = [DomRoot::from_ref(&**i)];
&root as &[_] &root as &[_]
} else { } else {

View file

@ -149,7 +149,7 @@ pub fn Fetch(
// Step 7. Let responseObject be null. // Step 7. Let responseObject be null.
// NOTE: We do initialize the object earlier earlier so we can use it to track errors // NOTE: We do initialize the object earlier earlier so we can use it to track errors
let response = Response::new(global, can_gc); let response = Response::new(global, can_gc);
response.Headers().set_guard(Guard::Immutable); response.Headers(can_gc).set_guard(Guard::Immutable);
// Step 2. Let requestObject be the result of invoking the initial value of Request as constructor // Step 2. Let requestObject be the result of invoking the initial value of Request as constructor
// with input and init as arguments. If this throws an exception, reject p with it and return p. // with input and init as arguments. If this throws an exception, reject p with it and return p.
@ -231,35 +231,39 @@ impl FetchResponseListener for FetchContext {
promise.reject_error(Error::Type("Network error occurred".to_string())); promise.reject_error(Error::Type("Network error occurred".to_string()));
self.fetch_promise = Some(TrustedPromise::new(promise)); self.fetch_promise = Some(TrustedPromise::new(promise));
let response = self.response_object.root(); let response = self.response_object.root();
response.set_type(DOMResponseType::Error); response.set_type(DOMResponseType::Error, CanGc::note());
response.error_stream(Error::Type("Network error occurred".to_string())); response.error_stream(Error::Type("Network error occurred".to_string()));
return; return;
}, },
// Step 4.2 // Step 4.2
Ok(metadata) => match metadata { Ok(metadata) => match metadata {
FetchMetadata::Unfiltered(m) => { FetchMetadata::Unfiltered(m) => {
fill_headers_with_metadata(self.response_object.root(), m); fill_headers_with_metadata(self.response_object.root(), m, CanGc::note());
self.response_object self.response_object
.root() .root()
.set_type(DOMResponseType::Default); .set_type(DOMResponseType::Default, CanGc::note());
}, },
FetchMetadata::Filtered { filtered, .. } => match filtered { FetchMetadata::Filtered { filtered, .. } => match filtered {
FilteredMetadata::Basic(m) => { FilteredMetadata::Basic(m) => {
fill_headers_with_metadata(self.response_object.root(), m); fill_headers_with_metadata(self.response_object.root(), m, CanGc::note());
self.response_object.root().set_type(DOMResponseType::Basic); self.response_object
.root()
.set_type(DOMResponseType::Basic, CanGc::note());
}, },
FilteredMetadata::Cors(m) => { FilteredMetadata::Cors(m) => {
fill_headers_with_metadata(self.response_object.root(), m); fill_headers_with_metadata(self.response_object.root(), m, CanGc::note());
self.response_object.root().set_type(DOMResponseType::Cors); self.response_object
.root()
.set_type(DOMResponseType::Cors, CanGc::note());
}, },
FilteredMetadata::Opaque => { FilteredMetadata::Opaque => {
self.response_object self.response_object
.root() .root()
.set_type(DOMResponseType::Opaque); .set_type(DOMResponseType::Opaque, CanGc::note());
}, },
FilteredMetadata::OpaqueRedirect(url) => { FilteredMetadata::OpaqueRedirect(url) => {
let r = self.response_object.root(); let r = self.response_object.root();
r.set_type(DOMResponseType::Opaqueredirect); r.set_type(DOMResponseType::Opaqueredirect, CanGc::note());
r.set_final_url(url); r.set_final_url(url);
}, },
}, },
@ -317,8 +321,8 @@ impl ResourceTimingListener for FetchContext {
} }
} }
fn fill_headers_with_metadata(r: DomRoot<Response>, m: Metadata) { fn fill_headers_with_metadata(r: DomRoot<Response>, m: Metadata, can_gc: CanGc) {
r.set_headers(m.headers); r.set_headers(m.headers, can_gc);
r.set_status(&m.status); r.set_status(&m.status);
r.set_final_url(m.final_url); r.set_final_url(m.final_url);
r.set_redirected(m.redirected); r.set_redirected(m.redirected);

View file

@ -1025,7 +1025,7 @@ unsafe extern "C" fn consume_stream(
root_from_handleobject::<Response>(RustHandleObject::from_raw(obj), *cx) root_from_handleobject::<Response>(RustHandleObject::from_raw(obj), *cx)
{ {
//Step 2.2 Let mimeType be the result of extracting a MIME type from responses header list. //Step 2.2 Let mimeType be the result of extracting a MIME type from responses header list.
let mimetype = unwrapped_source.Headers().extract_mime_type(); let mimetype = unwrapped_source.Headers(CanGc::note()).extract_mime_type();
//Step 2.3 If mimeType is not `application/wasm`, return with a TypeError and abort these substeps. //Step 2.3 If mimeType is not `application/wasm`, return with a TypeError and abort these substeps.
if !&mimetype[..].eq_ignore_ascii_case(b"application/wasm") { if !&mimetype[..].eq_ignore_ascii_case(b"application/wasm") {

View file

@ -19,6 +19,7 @@ use crate::dom::event::{Event, EventBubbles, EventCancelable};
use crate::dom::eventtarget::EventTarget; use crate::dom::eventtarget::EventTarget;
use crate::dom::securitypolicyviolationevent::SecurityPolicyViolationEvent; use crate::dom::securitypolicyviolationevent::SecurityPolicyViolationEvent;
use crate::dom::types::GlobalScope; use crate::dom::types::GlobalScope;
use crate::script_runtime::CanGc;
use crate::task::TaskOnce; use crate::task::TaskOnce;
pub struct CSPViolationReporter { pub struct CSPViolationReporter {
@ -100,7 +101,7 @@ impl CSPViolationReporter {
} }
} }
fn fire_violation_event(&self) { fn fire_violation_event(&self, can_gc: CanGc) {
let target = self.target.root(); let target = self.target.root();
let global = &target.global(); let global = &target.global();
let report = self.get_report(global); let report = self.get_report(global);
@ -111,6 +112,7 @@ impl CSPViolationReporter {
EventBubbles::Bubbles, EventBubbles::Bubbles,
EventCancelable::Cancelable, EventCancelable::Cancelable,
&report.into(), &report.into(),
can_gc,
); );
event.upcast::<Event>().fire(&target); event.upcast::<Event>().fire(&target);
@ -142,7 +144,7 @@ impl TaskOnce for CSPViolationReporter {
// > If target implements EventTarget, fire an event named securitypolicyviolation // > If target implements EventTarget, fire an event named securitypolicyviolation
// > that uses the SecurityPolicyViolationEvent interface // > that uses the SecurityPolicyViolationEvent interface
// > at target with its attributes initialized as follows: // > at target with its attributes initialized as follows:
self.fire_violation_event(); self.fire_violation_event(CanGc::note());
// TODO: Support `report-to` directive that corresponds to 5.5.3.5. // TODO: Support `report-to` directive that corresponds to 5.5.3.5.
} }
} }

View file

@ -6,7 +6,7 @@ use base::id::PipelineId;
use crate::dom::domexception::DOMErrorName; use crate::dom::domexception::DOMErrorName;
use crate::dom::filereader::{FileReader, GenerationId, ReadMetaData, TrustedFileReader}; use crate::dom::filereader::{FileReader, GenerationId, ReadMetaData, TrustedFileReader};
use crate::script_runtime::{CommonScriptMsg, ScriptChan, ScriptThreadEventCategory}; use crate::script_runtime::{CanGc, CommonScriptMsg, ScriptChan, ScriptThreadEventCategory};
use crate::task::{TaskCanceller, TaskOnce}; use crate::task::{TaskCanceller, TaskOnce};
use crate::task_source::{TaskSource, TaskSourceName}; use crate::task_source::{TaskSource, TaskSourceName};
@ -40,7 +40,7 @@ impl TaskSource for FileReadingTaskSource {
impl TaskOnce for FileReadingTask { impl TaskOnce for FileReadingTask {
fn run_once(self) { fn run_once(self) {
self.handle_task(); self.handle_task(CanGc::note());
} }
} }
@ -53,17 +53,19 @@ pub enum FileReadingTask {
} }
impl FileReadingTask { impl FileReadingTask {
pub fn handle_task(self) { pub fn handle_task(self, can_gc: CanGc) {
use self::FileReadingTask::*; use self::FileReadingTask::*;
match self { match self {
ProcessRead(reader, gen_id) => FileReader::process_read(reader, gen_id), ProcessRead(reader, gen_id) => FileReader::process_read(reader, gen_id, can_gc),
ProcessReadData(reader, gen_id) => FileReader::process_read_data(reader, gen_id), ProcessReadData(reader, gen_id) => {
FileReader::process_read_data(reader, gen_id, can_gc)
},
ProcessReadError(reader, gen_id, error) => { ProcessReadError(reader, gen_id, error) => {
FileReader::process_read_error(reader, gen_id, error) FileReader::process_read_error(reader, gen_id, error, can_gc)
}, },
ProcessReadEOF(reader, gen_id, metadata, blob_contents) => { ProcessReadEOF(reader, gen_id, metadata, blob_contents) => {
FileReader::process_read_eof(reader, gen_id, metadata, blob_contents) FileReader::process_read_eof(reader, gen_id, metadata, blob_contents, can_gc)
}, },
} }
} }