Prevent moving CanGc values between threads/tasks (#33902)

* Make CanGc non-sendable, and add documentation.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

* Update CanGc usage to fix usages that were moved between threads/tasks.

Signed-off-by: Josh Matthews <josh@joshmatthews.net>

---------

Signed-off-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
Josh Matthews 2024-10-18 13:26:54 -04:00 committed by GitHub
parent a58da5aa83
commit b85093ad74
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 69 additions and 89 deletions

View file

@ -333,7 +333,6 @@ impl DedicatedWorkerGlobalScope {
gpu_id_hub: Arc<IdentityHub>,
control_receiver: Receiver<DedicatedWorkerControlMsg>,
context_sender: Sender<ThreadSafeJSContext>,
can_gc: CanGc,
) -> JoinHandle<()> {
let serialized_worker_url = worker_url.to_string();
let top_level_browsing_context_id = TopLevelBrowsingContextId::installed();
@ -479,7 +478,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), can_gc);
run_worker_event_loop(&*global, Some(&worker), CanGc::note());
}
},
reporter_name,

View file

@ -694,7 +694,7 @@ impl Document {
self.activity.get() != DocumentActivity::Inactive
}
pub fn set_activity(&self, activity: DocumentActivity, can_gc: CanGc) {
pub fn set_activity(&self, activity: DocumentActivity) {
// This function should only be called on documents with a browsing context
assert!(self.has_browsing_context);
if activity == self.activity.get() {
@ -752,7 +752,7 @@ impl Document {
false, // bubbles
false, // cancelable
true, // persisted
can_gc,
CanGc::note(),
);
let event = event.upcast::<Event>();
event.set_trusted(true);
@ -2379,7 +2379,7 @@ impl Document {
}
// https://html.spec.whatwg.org/multipage/#the-end
pub fn maybe_queue_document_completion(&self, can_gc: CanGc) {
pub fn maybe_queue_document_completion(&self) {
// https://html.spec.whatwg.org/multipage/#delaying-load-events-mode
let is_in_delaying_load_events_mode = match self.window.undiscarded_window_proxy() {
Some(window_proxy) => window_proxy.is_delaying_load_events_mode(),
@ -2429,7 +2429,7 @@ impl Document {
atom!("load"),
EventBubbles::DoesNotBubble,
EventCancelable::NotCancelable,
can_gc,
CanGc::note(),
);
event.set_trusted(true);
@ -2472,7 +2472,7 @@ impl Document {
false, // bubbles
false, // cancelable
false, // persisted
can_gc,
CanGc::note(),
);
let event = event.upcast::<Event>();
event.set_trusted(true);

View file

@ -3185,7 +3185,7 @@ impl GlobalScope {
}
}
pub fn handle_gamepad_event(&self, gamepad_event: GamepadEvent, can_gc: CanGc) {
pub fn handle_gamepad_event(&self, gamepad_event: GamepadEvent) {
match gamepad_event {
GamepadEvent::Connected(index, name, bounds, supported_haptic_effects) => {
self.handle_gamepad_connect(
@ -3194,7 +3194,6 @@ impl GlobalScope {
bounds.axis_bounds,
bounds.button_bounds,
supported_haptic_effects,
can_gc,
);
},
GamepadEvent::Disconnected(index) => {
@ -3207,7 +3206,7 @@ impl GlobalScope {
}
/// <https://www.w3.org/TR/gamepad/#dfn-gamepadconnected>
pub fn handle_gamepad_connect(
fn handle_gamepad_connect(
&self,
// As the spec actually defines how to set the gamepad index, the GilRs index
// is currently unused, though in practice it will almost always be the same.
@ -3217,7 +3216,6 @@ impl GlobalScope {
axis_bounds: (f64, f64),
button_bounds: (f64, f64),
supported_haptic_effects: GamepadSupportedHapticEffects,
can_gc: CanGc,
) {
// TODO: 2. If document is not null and is not allowed to use the "gamepad" permission,
// then abort these steps.
@ -3239,7 +3237,7 @@ impl GlobalScope {
button_bounds,
supported_haptic_effects,
false,
can_gc,
CanGc::note(),
);
navigator.set_gamepad(selected_index as usize, &gamepad);
}

View file

@ -516,12 +516,7 @@ 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,
can_gc,
);
self.finish_reacting_to_environment_change(src, generation, selected_pixel_density);
},
ImageResponse::MetadataLoaded(meta) => {
self.pending_request.borrow_mut().metadata = Some(meta);
@ -1067,7 +1062,6 @@ impl HTMLImageElement {
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();
@ -1094,7 +1088,7 @@ impl HTMLImageElement {
if generation == element.generation.get() {
element.process_image_response_for_environment_change(image.response,
USVString::from(selected_source_clone), generation,
selected_pixel_density, can_gc);
selected_pixel_density, CanGc::note());
}
}),
&canceller,
@ -1160,7 +1154,6 @@ impl HTMLImageElement {
self,
selected_source.0.clone(),
selected_pixel_density,
can_gc,
);
let cache_result = image_cache.track_image(
img_url.clone(),
@ -1177,7 +1170,6 @@ impl HTMLImageElement {
selected_source,
generation,
selected_pixel_density,
can_gc,
)
},
ImageCacheResult::Available(ImageOrMetadataAvailable::MetadataAvailable(m)) => {
@ -1251,7 +1243,6 @@ impl HTMLImageElement {
src: USVString,
generation: u32,
selected_pixel_density: f64,
can_gc: CanGc,
) {
let this = Trusted::new(self);
let window = window_from_node(self);
@ -1262,7 +1253,7 @@ impl HTMLImageElement {
let relevant_mutation = this.generation.get() != generation;
// Step 15.1
if relevant_mutation {
this.abort_request(State::Unavailable, ImageRequestPhase::Pending, can_gc);
this.abort_request(State::Unavailable, ImageRequestPhase::Pending, CanGc::note());
return;
}
// Step 15.2
@ -1280,7 +1271,7 @@ impl HTMLImageElement {
// Step 15.5
mem::swap(&mut this.current_request.borrow_mut(), &mut pending_request);
this.abort_request(State::Unavailable, ImageRequestPhase::Pending, can_gc);
this.abort_request(State::Unavailable, ImageRequestPhase::Pending, CanGc::note());
}
// Step 15.6

View file

@ -611,7 +611,7 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#ready-states
fn change_ready_state(&self, ready_state: ReadyState, can_gc: CanGc) {
fn change_ready_state(&self, ready_state: ReadyState) {
let old_ready_state = self.ready_state.get();
self.ready_state.set(ready_state);
@ -642,7 +642,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, can_gc);
this.delay_load_event(false, CanGc::note());
}),
window.upcast(),
);
@ -796,12 +796,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, can_gc);
self.resource_fetch_algorithm(Resource::Object);
},
Mode::Attribute(src) => {
// Step 9.attr.1.
if src.is_empty() {
self.queue_dedicated_media_source_failure_steps(can_gc);
self.queue_dedicated_media_source_failure_steps();
return;
}
@ -809,7 +809,7 @@ impl HTMLMediaElement {
let url_record = match base_url.join(&src) {
Ok(url) => url,
Err(_) => {
self.queue_dedicated_media_source_failure_steps(can_gc);
self.queue_dedicated_media_source_failure_steps();
return;
},
};
@ -820,7 +820,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), can_gc);
self.resource_fetch_algorithm(Resource::Url(url_record));
},
// Step 9.children.
Mode::Children(source) => {
@ -830,7 +830,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(can_gc);
self.queue_dedicated_media_source_failure_steps();
return;
}
// Step 9.attr.3.
@ -838,20 +838,20 @@ impl HTMLMediaElement {
Ok(url) => url,
Err(_) => {
source.upcast::<EventTarget>().fire_event(atom!("error"));
self.queue_dedicated_media_source_failure_steps(can_gc);
self.queue_dedicated_media_source_failure_steps();
return;
},
};
// Step 9.attr.8.
self.resource_fetch_algorithm(Resource::Url(url_record), can_gc);
self.resource_fetch_algorithm(Resource::Url(url_record));
},
}
}
fn fetch_request(&self, offset: Option<u64>, seek_lock: Option<SeekLock>, can_gc: CanGc) {
fn fetch_request(&self, offset: Option<u64>, seek_lock: Option<SeekLock>) {
if self.resource_url.borrow().is_none() && self.blob_url.borrow().is_none() {
eprintln!("Missing request url");
self.queue_dedicated_media_source_failure_steps(can_gc);
self.queue_dedicated_media_source_failure_steps();
return;
}
@ -899,10 +899,10 @@ impl HTMLMediaElement {
}
// https://html.spec.whatwg.org/multipage/#concept-media-load-resource
fn resource_fetch_algorithm(&self, resource: Resource, can_gc: CanGc) {
if let Err(e) = self.setup_media_player(&resource, can_gc) {
fn resource_fetch_algorithm(&self, resource: Resource) {
if let Err(e) = self.setup_media_player(&resource) {
eprintln!("Setup media player error {:?}", e);
self.queue_dedicated_media_source_failure_steps(can_gc);
self.queue_dedicated_media_source_failure_steps();
return;
}
@ -935,7 +935,7 @@ impl HTMLMediaElement {
.media_element_task_source()
.queue(
task!(set_media_delay_load_event_flag_to_false: move || {
this.root().delay_load_event(false, can_gc);
this.root().delay_load_event(false, CanGc::note());
}),
window.upcast(),
)
@ -954,7 +954,7 @@ impl HTMLMediaElement {
// Step 4.remote.2.
*self.resource_url.borrow_mut() = Some(url);
self.fetch_request(None, None, can_gc);
self.fetch_request(None, None);
},
Resource::Object => {
if let Some(ref src_object) = *self.src_object.borrow() {
@ -963,7 +963,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, can_gc);
self.fetch_request(None, None);
},
SrcObject::MediaStream(ref stream) => {
let tracks = &*stream.get_tracks();
@ -978,7 +978,7 @@ impl HTMLMediaElement {
.set_stream(&track.id(), pos == tracks.len() - 1)
.is_err()
{
self.queue_dedicated_media_source_failure_steps(can_gc);
self.queue_dedicated_media_source_failure_steps();
}
}
},
@ -991,7 +991,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, can_gc: CanGc) {
fn queue_dedicated_media_source_failure_steps(&self) {
let window = window_from_node(self);
let this = Trusted::new(self);
let generation_id = self.generation_id.get();
@ -1036,7 +1036,7 @@ impl HTMLMediaElement {
});
// Step 7.
this.delay_load_event(false, can_gc);
this.delay_load_event(false, CanGc::note());
}),
window.upcast(),
);
@ -1123,7 +1123,7 @@ impl HTMLMediaElement {
// Step 6.5.
if self.ready_state.get() != ReadyState::HaveNothing {
self.change_ready_state(ReadyState::HaveNothing, can_gc);
self.change_ready_state(ReadyState::HaveNothing);
}
// Step 6.6.
@ -1329,7 +1329,7 @@ impl HTMLMediaElement {
}
}
fn setup_media_player(&self, resource: &Resource, can_gc: CanGc) -> Result<(), ()> {
fn setup_media_player(&self, resource: &Resource) -> Result<(), ()> {
let stream_type = match *resource {
Resource::Object => {
if let Some(ref src_object) = *self.src_object.borrow() {
@ -1380,7 +1380,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, can_gc);
this.root().handle_player_event(&event, CanGc::note());
}),
&canceller,
) {
@ -1480,7 +1480,7 @@ impl HTMLMediaElement {
// => "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(can_gc);
self.queue_dedicated_media_source_failure_steps();
} else {
// https://html.spec.whatwg.org/multipage/#reaches-the-end
match self.direction_of_playback() {
@ -1526,7 +1526,7 @@ impl HTMLMediaElement {
);
// https://html.spec.whatwg.org/multipage/#dom-media-have_current_data
self.change_ready_state(ReadyState::HaveCurrentData, can_gc);
self.change_ready_state(ReadyState::HaveCurrentData);
}
},
@ -1730,7 +1730,7 @@ impl HTMLMediaElement {
}
// Step 6.
self.change_ready_state(ReadyState::HaveMetadata, can_gc);
self.change_ready_state(ReadyState::HaveMetadata);
// Step 7.
let mut jumped = false;
@ -1800,7 +1800,7 @@ impl HTMLMediaElement {
}
},
PlayerEvent::EnoughData => {
self.change_ready_state(ReadyState::HaveEnoughData, can_gc);
self.change_ready_state(ReadyState::HaveEnoughData);
// 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
@ -1833,7 +1833,7 @@ impl HTMLMediaElement {
));
},
PlayerEvent::SeekData(p, ref seek_lock) => {
self.fetch_request(Some(p), Some(seek_lock.clone()), can_gc);
self.fetch_request(Some(p), Some(seek_lock.clone()));
},
PlayerEvent::SeekDone(_) => {
// Continuation of
@ -1852,7 +1852,7 @@ impl HTMLMediaElement {
PlaybackState::Paused => {
media_session_playback_state = MediaSessionPlaybackState::Paused;
if self.ready_state.get() == ReadyState::HaveMetadata {
self.change_ready_state(ReadyState::HaveEnoughData, can_gc);
self.change_ready_state(ReadyState::HaveEnoughData);
}
},
PlaybackState::Playing => {
@ -2731,7 +2731,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(CanGc::note());
elem.queue_dedicated_media_source_failure_steps();
}
}
@ -2867,7 +2867,7 @@ impl FetchResponseListener for HTMLMediaElementFetchListener {
elem.upcast::<EventTarget>().fire_event(atom!("error"));
} else {
// => "If the media data cannot be fetched at all..."
elem.queue_dedicated_media_source_failure_steps(CanGc::note());
elem.queue_dedicated_media_source_failure_steps();
}
}

View file

@ -294,7 +294,6 @@ impl ServiceWorkerGlobalScope {
control_receiver: Receiver<ServiceWorkerControlMsg>,
context_sender: Sender<ThreadSafeJSContext>,
closing: Arc<AtomicBool>,
can_gc: CanGc,
) -> JoinHandle<()> {
let ScopeThings {
script_url,
@ -384,7 +383,7 @@ impl ServiceWorkerGlobalScope {
scope.execute_script(DOMString::from(source));
}
global.dispatch_activate(can_gc);
global.dispatch_activate(CanGc::note());
let reporter_name = format!("service-worker-reporter-{}", random::<u64>());
scope
.upcast::<GlobalScope>()
@ -398,7 +397,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, can_gc);
run_worker_event_loop(&*global, None, CanGc::note());
}
},
reporter_name,

View file

@ -232,7 +232,6 @@ impl WorkerMethods for Worker {
global.wgpu_id_hub(),
control_receiver,
context_sender,
can_gc,
);
let context = context_receiver