aboutsummaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
Diffstat (limited to 'components')
-rw-r--r--components/jstraceable_derive/lib.rs156
-rw-r--r--components/script/Cargo.toml3
-rw-r--r--components/script/animations.rs20
-rw-r--r--components/script/body.rs4
-rw-r--r--components/script/canvas_state.rs17
-rw-r--r--components/script/document_loader.rs11
-rw-r--r--components/script/dom/abstractworkerglobalscope.rs2
-rw-r--r--components/script/dom/analysernode.rs1
-rw-r--r--components/script/dom/animationevent.rs1
-rw-r--r--components/script/dom/attr.rs2
-rw-r--r--components/script/dom/audiobuffer.rs1
-rw-r--r--components/script/dom/audionode.rs1
-rw-r--r--components/script/dom/audioparam.rs2
-rw-r--r--components/script/dom/baseaudiocontext.rs1
-rw-r--r--components/script/dom/bindings/trace.rs628
-rw-r--r--components/script/dom/blob.rs1
-rw-r--r--components/script/dom/broadcastchannel.rs1
-rw-r--r--components/script/dom/canvasgradient.rs5
-rw-r--r--components/script/dom/canvaspattern.rs1
-rw-r--r--components/script/dom/client.rs2
-rw-r--r--components/script/dom/cssfontfacerule.rs1
-rw-r--r--components/script/dom/cssgroupingrule.rs1
-rw-r--r--components/script/dom/cssimportrule.rs1
-rw-r--r--components/script/dom/csskeyframerule.rs1
-rw-r--r--components/script/dom/csskeyframesrule.rs1
-rw-r--r--components/script/dom/cssmediarule.rs1
-rw-r--r--components/script/dom/cssnamespacerule.rs1
-rw-r--r--components/script/dom/cssstyledeclaration.rs5
-rw-r--r--components/script/dom/cssstylerule.rs1
-rw-r--r--components/script/dom/cssstylesheet.rs1
-rw-r--r--components/script/dom/csssupportsrule.rs1
-rw-r--r--components/script/dom/customelementregistry.rs18
-rw-r--r--components/script/dom/dedicatedworkerglobalscope.rs4
-rw-r--r--components/script/dom/document.rs62
-rw-r--r--components/script/dom/documentfragment.rs9
-rw-r--r--components/script/dom/documentorshadowroot.rs8
-rw-r--r--components/script/dom/dommatrixreadonly.rs1
-rw-r--r--components/script/dom/domtokenlist.rs2
-rw-r--r--components/script/dom/dynamicmoduleowner.rs2
-rw-r--r--components/script/dom/element.rs9
-rw-r--r--components/script/dom/event.rs1
-rw-r--r--components/script/dom/eventsource.rs3
-rw-r--r--components/script/dom/eventtarget.rs6
-rw-r--r--components/script/dom/fakexrdevice.rs2
-rw-r--r--components/script/dom/fakexrinputcontroller.rs2
-rw-r--r--components/script/dom/formdata.rs32
-rw-r--r--components/script/dom/globalscope.rs84
-rw-r--r--components/script/dom/gpuadapter.rs2
-rw-r--r--components/script/dom/gpubindgroup.rs2
-rw-r--r--components/script/dom/gpubindgrouplayout.rs1
-rw-r--r--components/script/dom/gpubuffer.rs2
-rw-r--r--components/script/dom/gpucanvascontext.rs3
-rw-r--r--components/script/dom/gpucommandbuffer.rs2
-rw-r--r--components/script/dom/gpucommandencoder.rs2
-rw-r--r--components/script/dom/gpucomputepassencoder.rs2
-rw-r--r--components/script/dom/gpucomputepipeline.rs2
-rw-r--r--components/script/dom/gpudevice.rs2
-rw-r--r--components/script/dom/gpupipelinelayout.rs2
-rw-r--r--components/script/dom/gpuqueue.rs2
-rw-r--r--components/script/dom/gpurenderbundle.rs3
-rw-r--r--components/script/dom/gpurenderbundleencoder.rs2
-rw-r--r--components/script/dom/gpurenderpassencoder.rs2
-rw-r--r--components/script/dom/gpurenderpipeline.rs2
-rw-r--r--components/script/dom/gpusampler.rs2
-rw-r--r--components/script/dom/gpushadermodule.rs1
-rw-r--r--components/script/dom/gpuswapchain.rs1
-rw-r--r--components/script/dom/gputexture.rs2
-rw-r--r--components/script/dom/gputextureview.rs1
-rw-r--r--components/script/dom/headers.rs1
-rw-r--r--components/script/dom/history.rs1
-rw-r--r--components/script/dom/htmlanchorelement.rs1
-rw-r--r--components/script/dom/htmlcollection.rs4
-rw-r--r--components/script/dom/htmlformelement.rs13
-rw-r--r--components/script/dom/htmliframeelement.rs5
-rw-r--r--components/script/dom/htmlimageelement.rs4
-rwxr-xr-xcomponents/script/dom/htmlinputelement.rs1
-rw-r--r--components/script/dom/htmllinkelement.rs1
-rw-r--r--components/script/dom/htmlmediaelement.rs8
-rwxr-xr-xcomponents/script/dom/htmlobjectelement.rs1
-rw-r--r--components/script/dom/htmlscriptelement.rs12
-rw-r--r--components/script/dom/htmlstyleelement.rs1
-rwxr-xr-xcomponents/script/dom/htmltextareaelement.rs1
-rw-r--r--components/script/dom/htmlvideoelement.rs1
-rw-r--r--components/script/dom/medialist.rs1
-rw-r--r--components/script/dom/mediaquerylist.rs1
-rw-r--r--components/script/dom/mediasession.rs9
-rw-r--r--components/script/dom/mediastreamtrack.rs2
-rw-r--r--components/script/dom/messageport.rs2
-rw-r--r--components/script/dom/mouseevent.rs1
-rw-r--r--components/script/dom/node.rs1
-rw-r--r--components/script/dom/nodelist.rs1
-rw-r--r--components/script/dom/paintrenderingcontext2d.rs1
-rw-r--r--components/script/dom/paintworkletglobalscope.rs13
-rw-r--r--components/script/dom/pannernode.rs2
-rw-r--r--components/script/dom/raredata.rs2
-rw-r--r--components/script/dom/request.rs1
-rw-r--r--components/script/dom/response.rs3
-rw-r--r--components/script/dom/rtcpeerconnection.rs1
-rw-r--r--components/script/dom/serviceworker.rs2
-rw-r--r--components/script/dom/serviceworkerglobalscope.rs9
-rw-r--r--components/script/dom/serviceworkerregistration.rs2
-rw-r--r--components/script/dom/servoparser/async_html.rs7
-rw-r--r--components/script/dom/servoparser/mod.rs5
-rw-r--r--components/script/dom/servoparser/prefetch.rs7
-rw-r--r--components/script/dom/storage.rs1
-rw-r--r--components/script/dom/stylepropertymapreadonly.rs8
-rw-r--r--components/script/dom/textdecoder.rs2
-rw-r--r--components/script/dom/transitionevent.rs1
-rw-r--r--components/script/dom/url.rs1
-rw-r--r--components/script/dom/vertexarrayobject.rs1
-rw-r--r--components/script/dom/webgl_extensions/extensions.rs6
-rw-r--r--components/script/dom/webglbuffer.rs1
-rw-r--r--components/script/dom/webglframebuffer.rs2
-rw-r--r--components/script/dom/webglprogram.rs4
-rw-r--r--components/script/dom/webglquery.rs1
-rw-r--r--components/script/dom/webglrenderbuffer.rs1
-rw-r--r--components/script/dom/webglrenderingcontext.rs11
-rw-r--r--components/script/dom/webglsampler.rs1
-rw-r--r--components/script/dom/webglshader.rs1
-rw-r--r--components/script/dom/webglsync.rs1
-rw-r--r--components/script/dom/webgltexture.rs4
-rw-r--r--components/script/dom/webgluniformlocation.rs2
-rw-r--r--components/script/dom/websocket.rs2
-rw-r--r--components/script/dom/window.rs44
-rw-r--r--components/script/dom/windowproxy.rs7
-rw-r--r--components/script/dom/worker.rs1
-rw-r--r--components/script/dom/workerglobalscope.rs4
-rw-r--r--components/script/dom/workerlocation.rs1
-rw-r--r--components/script/dom/worklet.rs9
-rw-r--r--components/script/dom/workletglobalscope.rs2
-rw-r--r--components/script/dom/xmlhttprequest.rs8
-rw-r--r--components/script/dom/xrframe.rs1
-rw-r--r--components/script/dom/xrhittestresult.rs1
-rw-r--r--components/script/dom/xrhittestsource.rs1
-rw-r--r--components/script/dom/xrinputsource.rs1
-rw-r--r--components/script/dom/xrjointspace.rs2
-rw-r--r--components/script/dom/xrlayer.rs1
-rw-r--r--components/script/dom/xrray.rs1
-rw-r--r--components/script/dom/xrrigidtransform.rs1
-rw-r--r--components/script/dom/xrsession.rs10
-rw-r--r--components/script/dom/xrsystem.rs1
-rw-r--r--components/script/dom/xrview.rs1
-rw-r--r--components/script/dom/xrviewport.rs1
-rw-r--r--components/script/dom/xrwebglsubimage.rs1
-rw-r--r--components/script/fetch.rs1
-rw-r--r--components/script/lib.rs9
-rw-r--r--components/script/microtask.rs2
-rw-r--r--components/script/script_module.rs15
-rw-r--r--components/script/script_thread.rs52
-rw-r--r--components/script/task_source/dom_manipulation.rs2
-rw-r--r--components/script/task_source/file_reading.rs5
-rw-r--r--components/script/task_source/history_traversal.rs5
-rw-r--r--components/script/task_source/media_element.rs5
-rw-r--r--components/script/task_source/networking.rs5
-rw-r--r--components/script/task_source/performance_timeline.rs5
-rw-r--r--components/script/task_source/port_message.rs5
-rw-r--r--components/script/task_source/remote_event.rs5
-rw-r--r--components/script/task_source/timer.rs5
-rw-r--r--components/script/task_source/user_interaction.rs5
-rw-r--r--components/script/task_source/websocket.rs5
-rw-r--r--components/script/timers.rs10
-rw-r--r--components/script_plugins/Cargo.toml4
-rw-r--r--components/script_plugins/lib.rs646
-rw-r--r--components/script_plugins/trace_in_no_trace.rs204
-rw-r--r--components/script_plugins/unrooted_must_root.rs378
165 files changed, 1799 insertions, 1012 deletions
diff --git a/components/jstraceable_derive/lib.rs b/components/jstraceable_derive/lib.rs
index 1a3e3faa966..669a71842d3 100644
--- a/components/jstraceable_derive/lib.rs
+++ b/components/jstraceable_derive/lib.rs
@@ -7,10 +7,160 @@ extern crate syn;
#[macro_use]
extern crate synstructure;
-decl_derive!([JSTraceable] => js_traceable_derive);
+decl_derive!([JSTraceable, attributes(no_trace)] =>
+/// Implements `JSTraceable` on structs and enums
+///
+/// Example:
+/// ```rust
+/// #[derive(JSTraceable)]
+/// struct S {
+/// js_managed: JSManagedType,
+/// #[no_trace]
+/// non_js: NonJSManagedType,
+/// }
+/// ```
+///
+/// creates:
+///
+/// ```rust
+/// unsafe impl JSTraceable for S {
+/// #[inline]
+/// unsafe fn trace(&self, tracer: *mut js::jsapi::JSTracer) {
+/// match *self {
+/// S {
+/// js_managed: ref __binding_0,
+/// non_js: ref __binding_1,
+/// } => {
+/// {
+/// __binding_0.trace(tracer);
+/// }
+/// {
+/// // __binding_1 is not traceable so we do not need to trace it
+/// }
+/// },
+/// }
+/// }
+/// }
+/// ```
+///
+/// In cases where there is a need to make type (empty) traceable (`HashMap<NoTraceable, Traceable>`),
+/// NoTrace wrapper can be used, because it implements empty traceble:
+/// ```rust
+/// unsafe impl<T> JSTraceable for NoTrace<T> {
+/// unsafe fn trace(&self, _: *mut ::js::jsapi::JSTracer) { /* nop */}
+/// }
+/// ```
+///
+/// ## SAFETY
+/// Puting `#[no_trace]` on fields is safe if there are no types that are JS managed in that field.
+/// `#[no_trace]` should NOT be put on field that does implement (non-empty) `JSTraceable` (is JS managed).
+/// There are safeguards in place to prevent such mistakes. Example error:
+///
+/// ```console
+/// error[E0282]: type annotations needed
+/// |
+/// | #[derive(JSTraceable, MallocSizeOf)]
+/// | ^^^^^^^^^^^ cannot infer type of the type parameter `Self` declared on the trait `NoTraceOnJSTraceable`
+/// |
+/// = note: this error originates in the derive macro `JSTraceable`
+/// ```
+///
+/// If you can assure that type has empty JSTraceable impl, you can bypass guards, providing your reasoning:
+/// ```rust
+/// #[derive(JSTraceable)]
+/// struct S {
+/// #[no_trace = "Safe because both u32 and u64 are empty traceable"]
+/// field: HashMap<u32, u64>,
+/// }
+/// ```
+js_traceable_derive);
+
+// based off https://docs.rs/static_assertions/latest/src/static_assertions/assert_impl.rs.html#263
+fn assert_not_impl_traceable(ty: &syn::Type) -> proc_macro2::TokenStream {
+ quote!(
+ const _: fn() = || {
+ // Generic trait with a blanket impl over `()` for all types.
+ // becomes ambiguous if impl
+ trait NoTraceOnJSTraceable<A> {
+ // Required for actually being able to reference the trait.
+ fn some_item() {}
+ }
+
+ impl<T: ?Sized> NoTraceOnJSTraceable<()> for T {}
+
+ // Used for the specialized impl when JSTraceable is implemented.
+ #[allow(dead_code)]
+ struct Invalid0;
+ // forbids JSTraceable
+ impl<T> NoTraceOnJSTraceable<Invalid0> for T where T: ?Sized + crate::dom::bindings::trace::JSTraceable {}
+
+ #[allow(dead_code)]
+ struct Invalid2;
+ // forbids HashMap<JSTraceble, _>
+ impl<K, V, S> NoTraceOnJSTraceable<Invalid2> for std::collections::HashMap<K, V, S>
+ where
+ K: crate::dom::bindings::trace::JSTraceable + std::cmp::Eq + std::hash::Hash,
+ S: std::hash::BuildHasher,
+ {
+ }
+
+ #[allow(dead_code)]
+ struct Invalid3;
+ // forbids HashMap<_, JSTraceble>
+ impl<K, V, S> NoTraceOnJSTraceable<Invalid3> for std::collections::HashMap<K, V, S>
+ where
+ K: std::cmp::Eq + std::hash::Hash,
+ V: crate::dom::bindings::trace::JSTraceable,
+ S: std::hash::BuildHasher,
+ {
+ }
+
+ #[allow(dead_code)]
+ struct Invalid4;
+ // forbids BTreeMap<_, JSTraceble>
+ impl<K, V> NoTraceOnJSTraceable<Invalid4> for std::collections::BTreeMap<K, V> where
+ K: crate::dom::bindings::trace::JSTraceable + std::cmp::Eq + std::hash::Hash
+ {
+ }
+
+ #[allow(dead_code)]
+ struct Invalid5;
+ // forbids BTreeMap<_, JSTraceble>
+ impl<K, V> NoTraceOnJSTraceable<Invalid5> for std::collections::BTreeMap<K, V>
+ where
+ K: std::cmp::Eq + std::hash::Hash,
+ V: crate::dom::bindings::trace::JSTraceable,
+ {
+ }
+
+ // If there is only one specialized trait impl, type inference with
+ // `_` can be resolved and this can compile. Fails to compile if
+ // ty implements `NoTraceOnJSTraceable<InvalidX>`.
+ let _ = <#ty as NoTraceOnJSTraceable<_>>::some_item;
+ };
+ )
+}
fn js_traceable_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
- let match_body = s.each(|binding| Some(quote!(#binding.trace(tracer);)));
+ let mut asserts = quote!();
+ let match_body = s.each(|binding| {
+ for attr in binding.ast().attrs.iter() {
+ match attr.parse_meta().unwrap() {
+ syn::Meta::Path(ref path) | syn::Meta::List(syn::MetaList { ref path, .. }) => {
+ if path.is_ident("no_trace") {
+ asserts.extend(assert_not_impl_traceable(&binding.ast().ty));
+ return None;
+ }
+ },
+ syn::Meta::NameValue(syn::MetaNameValue { ref path, .. }) => {
+ if path.is_ident("no_trace") {
+ return None;
+ }
+ },
+ }
+ }
+ Some(quote!(#binding.trace(tracer);))
+ });
let ast = s.ast();
let name = &ast.ident;
@@ -24,6 +174,8 @@ fn js_traceable_derive(s: synstructure::Structure) -> proc_macro2::TokenStream {
}
let tokens = quote! {
+ #asserts
+
#[allow(unsafe_code)]
unsafe impl #impl_generics crate::dom::bindings::trace::JSTraceable for #name #ty_generics #where_clause {
#[inline]
diff --git a/components/script/Cargo.toml b/components/script/Cargo.toml
index 839b7be0169..0a8b713ce9d 100644
--- a/components/script/Cargo.toml
+++ b/components/script/Cargo.toml
@@ -17,7 +17,8 @@ debugmozjs = ['js/debugmozjs']
jitspew = ['js/jitspew']
profilemozjs = ['js/profilemozjs']
unrooted_must_root_lint = ["script_plugins/unrooted_must_root_lint"]
-default = ["unrooted_must_root_lint"]
+trace_in_no_trace_lint = ["script_plugins/trace_in_no_trace_lint"]
+default = ["unrooted_must_root_lint", "trace_in_no_trace_lint"]
webgl_backtrace = ["canvas_traits/webgl_backtrace"]
js_backtrace = []
refcell_backtrace = ["accountable-refcell"]
diff --git a/components/script/animations.rs b/components/script/animations.rs
index 49dfe77e1b4..531d941d6f9 100644
--- a/components/script/animations.rs
+++ b/components/script/animations.rs
@@ -13,6 +13,7 @@ use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::num::Finite;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::DOMString;
+use crate::dom::bindings::trace::NoTrace;
use crate::dom::event::Event;
use crate::dom::node::{from_untrusted_node_address, window_from_node, Node, NodeDamage};
use crate::dom::transitionevent::TransitionEvent;
@@ -35,13 +36,14 @@ use style::selector_parser::PseudoElement;
#[unrooted_must_root_lint::must_root]
pub(crate) struct Animations {
/// The map of nodes to their animation states.
+ #[no_trace]
pub sets: DocumentAnimationSet,
/// Whether or not we have animations that are running.
has_running_animations: Cell<bool>,
/// A list of nodes with in-progress CSS transitions or pending events.
- rooted_nodes: DomRefCell<FxHashMap<OpaqueNode, Dom<Node>>>,
+ rooted_nodes: DomRefCell<FxHashMap<NoTrace<OpaqueNode>, Dom<Node>>>,
/// A list of pending animation-related events.
pending_events: DomRefCell<Vec<TransitionOrAnimationEvent>>,
@@ -81,7 +83,10 @@ impl Animations {
let sets = self.sets.sets.read();
let rooted_nodes = self.rooted_nodes.borrow();
- for node in sets.keys().filter_map(|key| rooted_nodes.get(&key.node)) {
+ for node in sets
+ .keys()
+ .filter_map(|key| rooted_nodes.get(&NoTrace(key.node)))
+ {
node.dirty(NodeDamage::NodeStyleDamaged);
}
@@ -332,7 +337,7 @@ impl Animations {
let mut rooted_nodes = self.rooted_nodes.borrow_mut();
for (key, set) in sets.iter() {
let opaque_node = key.node;
- if rooted_nodes.contains_key(&opaque_node) {
+ if rooted_nodes.contains_key(&NoTrace(opaque_node)) {
continue;
}
@@ -342,7 +347,7 @@ impl Animations {
let address = UntrustedNodeAddress(opaque_node.0 as *const c_void);
unsafe {
rooted_nodes.insert(
- opaque_node,
+ NoTrace(opaque_node),
Dom::from_ref(&*from_untrusted_node_address(address)),
)
};
@@ -355,7 +360,7 @@ impl Animations {
let pending_events = self.pending_events.borrow();
let nodes: FxHashSet<OpaqueNode> = sets.keys().map(|key| key.node).collect();
self.rooted_nodes.borrow_mut().retain(|node, _| {
- nodes.contains(&node) || pending_events.iter().any(|event| event.node == *node)
+ nodes.contains(&node.0) || pending_events.iter().any(|event| event.node == node.0)
});
}
@@ -459,7 +464,7 @@ impl Animations {
for event in events.into_iter() {
// We root the node here to ensure that sending this event doesn't
// unroot it as a side-effect.
- let node = match self.rooted_nodes.borrow().get(&event.node) {
+ let node = match self.rooted_nodes.borrow().get(&NoTrace(event.node)) {
Some(node) => DomRoot::from_ref(&**node),
None => {
warn!("Tried to send an event for an unrooted node");
@@ -569,12 +574,15 @@ impl TransitionOrAnimationEventType {
/// A transition or animation event.
pub struct TransitionOrAnimationEvent {
/// The pipeline id of the layout task that sent this message.
+ #[no_trace]
pub pipeline_id: PipelineId,
/// The type of transition event this should trigger.
pub event_type: TransitionOrAnimationEventType,
/// The address of the node which owns this transition.
+ #[no_trace]
pub node: OpaqueNode,
/// The pseudo element for this transition or animation, if applicable.
+ #[no_trace]
pub pseudo_element: Option<PseudoElement>,
/// The name of the property that is transitioning (in the case of a transition)
/// or the name of the animation (in the case of an animation).
diff --git a/components/script/body.rs b/components/script/body.rs
index 8ac94d09a1e..baa4011062e 100644
--- a/components/script/body.rs
+++ b/components/script/body.rs
@@ -281,9 +281,11 @@ impl TransmitBodyConnectHandler {
#[derive(Clone, JSTraceable, MallocSizeOf)]
struct TransmitBodyPromiseHandler {
#[ignore_malloc_size_of = "Channels are hard"]
+ #[no_trace]
bytes_sender: IpcSender<BodyChunkResponse>,
stream: DomRoot<ReadableStream>,
#[ignore_malloc_size_of = "Channels are hard"]
+ #[no_trace]
control_sender: IpcSender<BodyChunkRequest>,
}
@@ -328,9 +330,11 @@ impl Callback for TransmitBodyPromiseHandler {
#[derive(Clone, JSTraceable, MallocSizeOf)]
struct TransmitBodyPromiseRejectionHandler {
#[ignore_malloc_size_of = "Channels are hard"]
+ #[no_trace]
bytes_sender: IpcSender<BodyChunkResponse>,
stream: DomRoot<ReadableStream>,
#[ignore_malloc_size_of = "Channels are hard"]
+ #[no_trace]
control_sender: IpcSender<BodyChunkRequest>,
}
diff --git a/components/script/canvas_state.rs b/components/script/canvas_state.rs
index 3dacd34ec48..fc1eff7df8b 100644
--- a/components/script/canvas_state.rs
+++ b/components/script/canvas_state.rs
@@ -61,7 +61,7 @@ use style_traits::values::ToCss;
#[derive(Clone, JSTraceable, MallocSizeOf)]
#[allow(dead_code)]
pub(crate) enum CanvasFillOrStrokeStyle {
- Color(RGBA),
+ Color(#[no_trace] RGBA),
Gradient(Dom<CanvasGradient>),
Pattern(Dom<CanvasPattern>),
}
@@ -80,22 +80,31 @@ impl CanvasFillOrStrokeStyle {
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub(crate) struct CanvasContextState {
global_alpha: f64,
+ #[no_trace]
global_composition: CompositionOrBlending,
image_smoothing_enabled: bool,
fill_style: CanvasFillOrStrokeStyle,
stroke_style: CanvasFillOrStrokeStyle,
line_width: f64,
+ #[no_trace]
line_cap: LineCapStyle,
+ #[no_trace]
line_join: LineJoinStyle,
miter_limit: f64,
+ #[no_trace]
transform: Transform2D<f32>,
shadow_offset_x: f64,
shadow_offset_y: f64,
shadow_blur: f64,
+ #[no_trace]
shadow_color: RGBA,
+ #[no_trace]
font_style: Option<Font>,
+ #[no_trace]
text_align: TextAlign,
+ #[no_trace]
text_baseline: TextBaseline,
+ #[no_trace]
direction: Direction,
}
@@ -131,17 +140,23 @@ impl CanvasContextState {
#[derive(JSTraceable, MallocSizeOf)]
pub(crate) struct CanvasState {
#[ignore_malloc_size_of = "Defined in ipc-channel"]
+ #[no_trace]
ipc_renderer: IpcSender<CanvasMsg>,
+ #[no_trace]
canvas_id: CanvasId,
state: DomRefCell<CanvasContextState>,
origin_clean: Cell<bool>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
image_cache: Arc<dyn ImageCache>,
/// The base URL for resolving CSS image URL values.
/// Needed because of https://github.com/servo/servo/issues/17625
+ #[no_trace]
base_url: ServoUrl,
+ #[no_trace]
origin: ImmutableOrigin,
/// Any missing image URLs.
+ #[no_trace]
missing_image_urls: DomRefCell<Vec<ServoUrl>>,
saved_states: DomRefCell<Vec<CanvasContextState>>,
}
diff --git a/components/script/document_loader.rs b/components/script/document_loader.rs
index 9e103b91380..7dc2d6201fb 100644
--- a/components/script/document_loader.rs
+++ b/components/script/document_loader.rs
@@ -17,11 +17,11 @@ use servo_url::ServoUrl;
#[derive(Clone, Debug, JSTraceable, MallocSizeOf, PartialEq)]
pub enum LoadType {
- Image(ServoUrl),
- Script(ServoUrl),
- Subframe(ServoUrl),
- Stylesheet(ServoUrl),
- PageSource(ServoUrl),
+ Image(#[no_trace] ServoUrl),
+ Script(#[no_trace] ServoUrl),
+ Subframe(#[no_trace] ServoUrl),
+ Stylesheet(#[no_trace] ServoUrl),
+ PageSource(#[no_trace] ServoUrl),
Media,
}
@@ -66,6 +66,7 @@ impl Drop for LoadBlocker {
#[derive(JSTraceable, MallocSizeOf)]
pub struct DocumentLoader {
+ #[no_trace]
resource_threads: ResourceThreads,
blocking_loads: Vec<LoadType>,
events_inhibited: bool,
diff --git a/components/script/dom/abstractworkerglobalscope.rs b/components/script/dom/abstractworkerglobalscope.rs
index a1cab9aca2d..0bf298e1a4e 100644
--- a/components/script/dom/abstractworkerglobalscope.rs
+++ b/components/script/dom/abstractworkerglobalscope.rs
@@ -20,6 +20,7 @@ use devtools_traits::DevtoolScriptControlMsg;
/// Worker object will remain alive.
#[derive(Clone, JSTraceable)]
pub struct SendableWorkerScriptChan {
+ #[no_trace]
pub sender: Sender<DedicatedWorkerScriptMsg>,
pub worker: TrustedWorkerAddress,
}
@@ -46,6 +47,7 @@ impl ScriptChan for SendableWorkerScriptChan {
/// Worker object will remain alive.
#[derive(Clone, JSTraceable)]
pub struct WorkerThreadWorkerChan {
+ #[no_trace]
pub sender: Sender<DedicatedWorkerScriptMsg>,
pub worker: TrustedWorkerAddress,
}
diff --git a/components/script/dom/analysernode.rs b/components/script/dom/analysernode.rs
index 568d2b120e8..7a83ca0052e 100644
--- a/components/script/dom/analysernode.rs
+++ b/components/script/dom/analysernode.rs
@@ -31,6 +31,7 @@ use servo_media::audio::node::AudioNodeInit;
pub struct AnalyserNode {
node: AudioNode,
#[ignore_malloc_size_of = "Defined in servo-media"]
+ #[no_trace]
engine: DomRefCell<AnalysisEngine>,
}
diff --git a/components/script/dom/animationevent.rs b/components/script/dom/animationevent.rs
index cde3d466da3..053801631c5 100644
--- a/components/script/dom/animationevent.rs
+++ b/components/script/dom/animationevent.rs
@@ -20,6 +20,7 @@ use servo_atoms::Atom;
#[dom_struct]
pub struct AnimationEvent {
event: Event,
+ #[no_trace]
animation_name: Atom,
elapsed_time: Finite<f32>,
pseudo_element: DOMString,
diff --git a/components/script/dom/attr.rs b/components/script/dom/attr.rs
index 9c4b221f6f3..2ad3d60bbbd 100644
--- a/components/script/dom/attr.rs
+++ b/components/script/dom/attr.rs
@@ -27,7 +27,9 @@ use style::values::GenericAtomIdent;
#[dom_struct]
pub struct Attr {
node_: Node,
+ #[no_trace]
identifier: AttrIdentifier,
+ #[no_trace]
value: DomRefCell<AttrValue>,
/// the element that owns this attribute.
diff --git a/components/script/dom/audiobuffer.rs b/components/script/dom/audiobuffer.rs
index bad4bf87141..29623fee6a2 100644
--- a/components/script/dom/audiobuffer.rs
+++ b/components/script/dom/audiobuffer.rs
@@ -50,6 +50,7 @@ pub struct AudioBuffer {
/// Aggregates the data from js_channels.
/// This is Some<T> iff the buffers in js_channels are detached.
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
shared_channels: DomRefCell<Option<ServoMediaAudioBuffer>>,
/// https://webaudio.github.io/web-audio-api/#dom-audiobuffer-samplerate
sample_rate: f32,
diff --git a/components/script/dom/audionode.rs b/components/script/dom/audionode.rs
index 841b99d2d8f..5df6d7a76b1 100644
--- a/components/script/dom/audionode.rs
+++ b/components/script/dom/audionode.rs
@@ -33,6 +33,7 @@ pub const MAX_CHANNEL_COUNT: u32 = 32;
pub struct AudioNode {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
node_id: NodeId,
context: Dom<BaseAudioContext>,
number_of_inputs: u32,
diff --git a/components/script/dom/audioparam.rs b/components/script/dom/audioparam.rs
index dd0e72f7bcf..99f64d765f6 100644
--- a/components/script/dom/audioparam.rs
+++ b/components/script/dom/audioparam.rs
@@ -23,8 +23,10 @@ pub struct AudioParam {
reflector_: Reflector,
context: Dom<BaseAudioContext>,
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
node: NodeId,
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
param: ParamType,
automation_rate: Cell<AutomationRate>,
default_value: f32,
diff --git a/components/script/dom/baseaudiocontext.rs b/components/script/dom/baseaudiocontext.rs
index 0b193b25e29..20180d8a939 100644
--- a/components/script/dom/baseaudiocontext.rs
+++ b/components/script/dom/baseaudiocontext.rs
@@ -82,6 +82,7 @@ struct DecodeResolver {
pub struct BaseAudioContext {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
audio_context_impl: Arc<Mutex<AudioContext>>,
/// https://webaudio.github.io/web-audio-api/#dom-baseaudiocontext-destination
destination: MutNullableDom<AudioDestinationNode>,
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index 8efa7b09ecf..2eaad330108 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -40,43 +40,11 @@ use crate::dom::gpubuffer::GPUBufferState;
use crate::dom::gpucanvascontext::WebGPUContextId;
use crate::dom::gpucommandencoder::GPUCommandEncoderState;
use crate::dom::htmlimageelement::SourceSet;
-use crate::dom::htmlmediaelement::{HTMLMediaElementFetchContext, MediaFrameRenderer};
-use crate::dom::identityhub::Identities;
+use crate::dom::htmlmediaelement::HTMLMediaElementFetchContext;
use crate::script_runtime::{ContextForRequestInterrupt, StreamConsumer};
use crate::script_thread::IncompleteParserContexts;
use crate::task::TaskBox;
-use app_units::Au;
-use canvas_traits::canvas::{
- CanvasGradientStop, CanvasId, LinearGradientStyle, RadialGradientStyle,
-};
-use canvas_traits::canvas::{
- CompositionOrBlending, Direction, LineCapStyle, LineJoinStyle, RepetitionStyle, TextAlign,
- TextBaseline,
-};
-use canvas_traits::webgl::WebGLVertexArrayId;
-use canvas_traits::webgl::{
- ActiveAttribInfo, ActiveUniformBlockInfo, ActiveUniformInfo, GlType, TexDataType, TexFormat,
-};
-use canvas_traits::webgl::{GLLimits, WebGLQueryId, WebGLSamplerId};
-use canvas_traits::webgl::{WebGLBufferId, WebGLChan, WebGLContextId, WebGLError};
-use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsgSender, WebGLPipeline, WebGLProgramId};
-use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender};
-use canvas_traits::webgl::{WebGLShaderId, WebGLSyncId, WebGLTextureId, WebGLVersion};
-use content_security_policy::CspList;
-use crossbeam_channel::{Receiver, Sender};
-use cssparser::RGBA;
-use devtools_traits::{CSSError, TimelineMarkerType, WorkerId};
-use embedder_traits::{EventLoopWaker, MediaMetadata};
-use encoding_rs::{Decoder, Encoding};
-use euclid::default::{Point2D, Rect, Rotation3D, Transform2D};
-use euclid::Length as EuclidLength;
-use html5ever::buffer_queue::BufferQueue;
-use html5ever::{LocalName, Namespace, Prefix, QualName};
-use http::header::HeaderMap;
-use http::Method;
-use http::StatusCode;
use indexmap::IndexMap;
-use ipc_channel::ipc::{IpcReceiver, IpcSender};
use js::glue::{CallObjectTracer, CallScriptTracer, CallStringTracer, CallValueTracer};
use js::jsapi::{
GCTraceKindToAscii, Heap, JSObject, JSScript, JSString, JSTracer, JobQueue, TraceKind,
@@ -86,56 +54,14 @@ use js::rust::{GCMethods, Handle, Runtime, Stencil};
use js::typedarray::TypedArray;
use js::typedarray::TypedArrayElement;
use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
-use media::WindowGLContext;
-use metrics::{InteractiveMetrics, InteractiveWindow};
-use mime::Mime;
-use msg::constellation_msg::{
- BlobId, BroadcastChannelRouterId, BrowsingContextId, HistoryStateId, MessagePortId,
- MessagePortRouterId, PipelineId, TopLevelBrowsingContextId,
-};
-use msg::constellation_msg::{ServiceWorkerId, ServiceWorkerRegistrationId};
-use net_traits::filemanager_thread::RelativePos;
-use net_traits::image::base::{Image, ImageMetadata};
-use net_traits::image_cache::{ImageCache, PendingImageId};
-use net_traits::request::{CredentialsMode, ParserMetadata, Referrer, Request, RequestBuilder};
-use net_traits::response::HttpsState;
-use net_traits::response::{Response, ResponseBody};
-use net_traits::storage_thread::StorageType;
-use net_traits::{Metadata, NetworkError, ReferrerPolicy, ResourceFetchTiming, ResourceThreads};
-use parking_lot::{Mutex as ParkMutex, RwLock};
-use profile_traits::mem::ProfilerChan as MemProfilerChan;
-use profile_traits::time::ProfilerChan as TimeProfilerChan;
-use script_layout_interface::message::PendingRestyle;
-use script_layout_interface::rpc::LayoutRPC;
-use script_layout_interface::StyleAndOpaqueLayoutData;
-use script_traits::serializable::BlobImpl;
-use script_traits::transferable::MessagePortImpl;
-use script_traits::{
- DocumentActivity, DrawAPaintImageResult, MediaSessionActionType, ScriptToConstellationChan,
- TimerEventId, TimerSource, UntrustedNodeAddress, WebrenderIpcSender, WindowSizeData,
- WindowSizeType,
-};
-use selectors::matching::ElementSelectorFlags;
-use serde::{Deserialize, Serialize};
+use parking_lot::RwLock;
use servo_arc::Arc as ServoArc;
-use servo_atoms::Atom;
-use servo_media::audio::analyser_node::AnalysisEngine;
-use servo_media::audio::buffer_source_node::AudioBuffer;
-use servo_media::audio::context::AudioContext;
-use servo_media::audio::graph::NodeId;
-use servo_media::audio::panner_node::{DistanceModel, PanningModel};
-use servo_media::audio::param::ParamType;
-use servo_media::player::audio::AudioRenderer;
-use servo_media::player::video::VideoFrame;
-use servo_media::player::Player;
-use servo_media::streams::registry::MediaStreamId;
-use servo_media::streams::MediaStreamType;
-use servo_media::webrtc::WebRtcController;
-use servo_url::{ImmutableOrigin, MutableOrigin, ServoUrl};
use smallvec::SmallVec;
use std::borrow::Cow;
use std::cell::{Cell, RefCell, UnsafeCell};
+use std::collections::hash_map::RandomState;
use std::collections::{BTreeMap, HashMap, HashSet, VecDeque};
+use std::fmt::Display;
use std::hash::{BuildHasher, Hash};
use std::mem;
use std::num::NonZeroU64;
@@ -143,42 +69,16 @@ use std::ops::{Deref, DerefMut, Range};
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::atomic::{AtomicBool, AtomicUsize};
-use std::sync::{Arc, Mutex};
+use std::sync::Arc;
use std::thread::JoinHandle;
use std::time::{Instant, SystemTime};
-use style::animation::DocumentAnimationSet;
-use style::attr::{AttrIdentifier, AttrValue, LengthOrPercentageOrAuto};
use style::author_styles::AuthorStyles;
-use style::context::QuirksMode;
-use style::dom::OpaqueNode;
-use style::element_state::*;
-use style::media_queries::MediaList;
-use style::properties::style_structs::Font;
-use style::properties::PropertyDeclarationBlock;
-use style::selector_parser::{PseudoElement, Snapshot};
-use style::shared_lock::{Locked as StyleLocked, SharedRwLock as StyleSharedRwLock};
use style::stylesheet_set::{AuthorStylesheetSet, DocumentStylesheetSet};
-use style::stylesheets::keyframes_rule::Keyframe;
-use style::stylesheets::{CssRules, FontFaceRule, KeyframesRule, MediaRule, Stylesheet};
-use style::stylesheets::{ImportRule, NamespaceRule, StyleRule, SupportsRule};
-use style::stylist::CascadeData;
-use style::values::specified::Length;
use tendril::fmt::UTF8;
use tendril::stream::LossyDecoder;
-use tendril::{StrTendril, TendrilSink};
-use time::{Duration, Timespec, Tm};
-use uuid::Uuid;
-use webgpu::{
- wgpu::command::{ComputePass, RenderBundleEncoder, RenderPass},
- WebGPU, WebGPUAdapter, WebGPUBindGroup, WebGPUBindGroupLayout, WebGPUBuffer,
- WebGPUCommandBuffer, WebGPUCommandEncoder, WebGPUComputePipeline, WebGPUDevice,
- WebGPUPipelineLayout, WebGPUQueue, WebGPURenderBundle, WebGPURenderPipeline, WebGPUSampler,
- WebGPUShaderModule, WebGPUTexture, WebGPUTextureView,
-};
-use webrender_api::{DocumentId, ExternalImageId, ImageKey};
-use webxr_api::{Finger, Hand, Ray, View};
+use tendril::TendrilSink;
+use webxr_api::{Finger, Hand};
-unsafe_no_jsmanaged_fields!(Tm);
unsafe_no_jsmanaged_fields!(JoinHandle<()>);
/// A trait to allow tracing (only) DOM objects.
@@ -187,40 +87,159 @@ pub unsafe trait JSTraceable {
unsafe fn trace(&self, trc: *mut JSTracer);
}
-unsafe_no_jsmanaged_fields!(Box<dyn TaskBox>, Box<dyn EventLoopWaker>);
+/// Wrapper type for nop traceble
+///
+/// SAFETY: Inner type must not impl JSTraceable
+#[derive(Clone, Copy, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
+#[trace_in_no_trace_lint::must_not_have_traceable]
+pub struct NoTrace<T>(pub T);
-unsafe_no_jsmanaged_fields!(IncompleteParserContexts);
+impl<T: Display> Display for NoTrace<T> {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.0.fmt(f)
+ }
+}
-unsafe_no_jsmanaged_fields!(MessagePortImpl);
-unsafe_no_jsmanaged_fields!(MessagePortId);
-unsafe_no_jsmanaged_fields!(MessagePortRouterId);
+impl<T> From<T> for NoTrace<T> {
+ fn from(item: T) -> Self {
+ Self(item)
+ }
+}
-unsafe_no_jsmanaged_fields!(ServiceWorkerId);
-unsafe_no_jsmanaged_fields!(ServiceWorkerRegistrationId);
+#[allow(unsafe_code)]
+unsafe impl<T> JSTraceable for NoTrace<T> {
+ #[inline]
+ unsafe fn trace(&self, _: *mut ::js::jsapi::JSTracer) {}
+}
-unsafe_no_jsmanaged_fields!(BroadcastChannelRouterId);
+impl<T: MallocSizeOf> MallocSizeOf for NoTrace<T> {
+ fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
+ self.0.size_of(ops)
+ }
+}
-unsafe_no_jsmanaged_fields!(BlobId);
-unsafe_no_jsmanaged_fields!(BlobImpl);
+/// HashMap wrapper, that has non-jsmanaged keys
+///
+/// Not all methods are reexposed, but you can access inner type via .0
+#[trace_in_no_trace_lint::must_not_have_traceable(0)]
+#[derive(Clone, Debug)]
+pub struct HashMapTracedValues<K, V, S = RandomState>(pub HashMap<K, V, S>);
-unsafe_no_jsmanaged_fields!(CSSError);
+impl<K, V, S: Default> Default for HashMapTracedValues<K, V, S> {
+ fn default() -> Self {
+ Self(Default::default())
+ }
+}
+
+impl<K, V> HashMapTracedValues<K, V, RandomState> {
+ /// Wrapper for HashMap::new()
+ #[inline]
+ #[must_use]
+ pub fn new() -> HashMapTracedValues<K, V, RandomState> {
+ Self(HashMap::new())
+ }
+}
-unsafe_no_jsmanaged_fields!(&'static Encoding);
+impl<K, V, S> HashMapTracedValues<K, V, S> {
+ #[inline]
+ pub fn iter(&self) -> std::collections::hash_map::Iter<'_, K, V> {
+ self.0.iter()
+ }
-unsafe_no_jsmanaged_fields!(Decoder);
+ #[inline]
+ pub fn drain(&mut self) -> std::collections::hash_map::Drain<'_, K, V> {
+ self.0.drain()
+ }
-unsafe_no_jsmanaged_fields!(Reflector);
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.0.is_empty()
+ }
+}
-unsafe_no_jsmanaged_fields!(Duration);
+impl<K, V, S> HashMapTracedValues<K, V, S>
+where
+ K: Eq + Hash,
+ S: BuildHasher,
+{
+ #[inline]
+ pub fn insert(&mut self, k: K, v: V) -> Option<V> {
+ self.0.insert(k, v)
+ }
-unsafe_no_jsmanaged_fields!(TexDataType, TexFormat);
+ #[inline]
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
+ where
+ K: std::borrow::Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ self.0.get(k)
+ }
+
+ #[inline]
+ pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
+ where
+ K: std::borrow::Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ self.0.get_mut(k)
+ }
+
+ #[inline]
+ pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
+ where
+ K: std::borrow::Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ self.0.contains_key(k)
+ }
+
+ #[inline]
+ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
+ where
+ K: std::borrow::Borrow<Q>,
+ Q: Hash + Eq,
+ {
+ self.0.remove(k)
+ }
+
+ #[inline]
+ pub fn entry(&mut self, key: K) -> std::collections::hash_map::Entry<'_, K, V> {
+ self.0.entry(key)
+ }
+}
+
+impl<K, V, S> MallocSizeOf for HashMapTracedValues<K, V, S>
+where
+ K: Eq + Hash + MallocSizeOf,
+ V: MallocSizeOf,
+ S: BuildHasher,
+{
+ fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
+ self.0.size_of(ops)
+ }
+}
+
+#[allow(unsafe_code)]
+unsafe impl<K, V: JSTraceable, S> JSTraceable for HashMapTracedValues<K, V, S> {
+ #[inline]
+ unsafe fn trace(&self, trc: *mut ::js::jsapi::JSTracer) {
+ for v in self.0.values() {
+ v.trace(trc);
+ }
+ }
+}
+
+unsafe_no_jsmanaged_fields!(Box<dyn TaskBox>);
+
+unsafe_no_jsmanaged_fields!(IncompleteParserContexts);
+
+unsafe_no_jsmanaged_fields!(Reflector);
unsafe_no_jsmanaged_fields!(*mut JobQueue);
unsafe_no_jsmanaged_fields!(Cow<'static, str>);
-unsafe_no_jsmanaged_fields!(CspList);
-
/// Trace a `JSScript`.
pub fn trace_script(tracer: *mut JSTracer, description: &str, script: &Heap<*mut JSScript>) {
unsafe {
@@ -519,164 +538,28 @@ unsafe impl<A: JSTraceable, B: JSTraceable, C: JSTraceable> JSTraceable for (A,
}
}
-unsafe_no_jsmanaged_fields!(ActiveAttribInfo);
-unsafe_no_jsmanaged_fields!(ActiveUniformInfo);
-unsafe_no_jsmanaged_fields!(ActiveUniformBlockInfo);
-unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, Uuid, char);
+unsafe_no_jsmanaged_fields!(bool, f32, f64, String, AtomicBool, AtomicUsize, char);
unsafe_no_jsmanaged_fields!(usize, u8, u16, u32, u64);
unsafe_no_jsmanaged_fields!(isize, i8, i16, i32, i64);
unsafe_no_jsmanaged_fields!(NonZeroU64);
unsafe_no_jsmanaged_fields!(Error);
-unsafe_no_jsmanaged_fields!(ServoUrl, ImmutableOrigin, MutableOrigin);
-unsafe_no_jsmanaged_fields!(Image, ImageMetadata, dyn ImageCache, PendingImageId);
-unsafe_no_jsmanaged_fields!(Metadata);
-unsafe_no_jsmanaged_fields!(NetworkError);
-unsafe_no_jsmanaged_fields!(Atom, Prefix, LocalName, Namespace, QualName);
unsafe_no_jsmanaged_fields!(TrustedPromise);
-unsafe_no_jsmanaged_fields!(PropertyDeclarationBlock);
-unsafe_no_jsmanaged_fields!(Font);
-// These three are interdependent, if you plan to put jsmanaged data
-// in one of these make sure it is propagated properly to containing structs
-unsafe_no_jsmanaged_fields!(DocumentActivity, WindowSizeData, WindowSizeType);
-unsafe_no_jsmanaged_fields!(
- BrowsingContextId,
- HistoryStateId,
- PipelineId,
- TopLevelBrowsingContextId
-);
-unsafe_no_jsmanaged_fields!(TimerEventId, TimerSource);
-unsafe_no_jsmanaged_fields!(TimelineMarkerType);
-unsafe_no_jsmanaged_fields!(WorkerId);
-unsafe_no_jsmanaged_fields!(BufferQueue, QuirksMode, StrTendril);
+
unsafe_no_jsmanaged_fields!(Runtime);
unsafe_no_jsmanaged_fields!(ContextForRequestInterrupt);
-unsafe_no_jsmanaged_fields!(HeaderMap, Method);
unsafe_no_jsmanaged_fields!(WindowProxyHandler);
-unsafe_no_jsmanaged_fields!(UntrustedNodeAddress, OpaqueNode);
-unsafe_no_jsmanaged_fields!(LengthOrPercentageOrAuto);
-unsafe_no_jsmanaged_fields!(RGBA);
-unsafe_no_jsmanaged_fields!(StorageType);
-unsafe_no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
-unsafe_no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
-unsafe_no_jsmanaged_fields!(TextAlign, TextBaseline, Direction);
-unsafe_no_jsmanaged_fields!(RepetitionStyle);
-unsafe_no_jsmanaged_fields!(WebGLError, GLLimits, GlType);
-unsafe_no_jsmanaged_fields!(TimeProfilerChan);
-unsafe_no_jsmanaged_fields!(MemProfilerChan);
-unsafe_no_jsmanaged_fields!(PseudoElement);
-unsafe_no_jsmanaged_fields!(Length);
-unsafe_no_jsmanaged_fields!(ElementSelectorFlags);
-unsafe_no_jsmanaged_fields!(ElementState);
unsafe_no_jsmanaged_fields!(DOMString);
-unsafe_no_jsmanaged_fields!(Mime);
-unsafe_no_jsmanaged_fields!(AttrIdentifier);
-unsafe_no_jsmanaged_fields!(AttrValue);
-unsafe_no_jsmanaged_fields!(Snapshot);
-unsafe_no_jsmanaged_fields!(PendingRestyle);
-unsafe_no_jsmanaged_fields!(Stylesheet);
-unsafe_no_jsmanaged_fields!(HttpsState);
-unsafe_no_jsmanaged_fields!(Request);
-unsafe_no_jsmanaged_fields!(RequestBuilder);
-unsafe_no_jsmanaged_fields!(StyleSharedRwLock);
unsafe_no_jsmanaged_fields!(USVString);
-unsafe_no_jsmanaged_fields!(Referrer);
-unsafe_no_jsmanaged_fields!(ReferrerPolicy);
-unsafe_no_jsmanaged_fields!(CredentialsMode);
-unsafe_no_jsmanaged_fields!(ParserMetadata);
-unsafe_no_jsmanaged_fields!(Response);
-unsafe_no_jsmanaged_fields!(ResponseBody);
-unsafe_no_jsmanaged_fields!(ResourceThreads);
-unsafe_no_jsmanaged_fields!(StatusCode);
unsafe_no_jsmanaged_fields!(SystemTime);
unsafe_no_jsmanaged_fields!(Instant);
-unsafe_no_jsmanaged_fields!(RelativePos);
-unsafe_no_jsmanaged_fields!(StyleAndOpaqueLayoutData);
unsafe_no_jsmanaged_fields!(PathBuf);
-unsafe_no_jsmanaged_fields!(DrawAPaintImageResult);
-unsafe_no_jsmanaged_fields!(DocumentId);
-unsafe_no_jsmanaged_fields!(ImageKey);
-unsafe_no_jsmanaged_fields!(ExternalImageId);
-unsafe_no_jsmanaged_fields!(WebGLBufferId);
-unsafe_no_jsmanaged_fields!(WebGLChan);
-unsafe_no_jsmanaged_fields!(WebGLFramebufferId);
-unsafe_no_jsmanaged_fields!(WebGLMsgSender);
-unsafe_no_jsmanaged_fields!(WebGLPipeline);
-unsafe_no_jsmanaged_fields!(WebGLProgramId);
-unsafe_no_jsmanaged_fields!(WebGLQueryId);
-unsafe_no_jsmanaged_fields!(WebGLRenderbufferId);
-unsafe_no_jsmanaged_fields!(WebGLSamplerId);
-unsafe_no_jsmanaged_fields!(WebGLShaderId);
-unsafe_no_jsmanaged_fields!(WebGLSyncId);
-unsafe_no_jsmanaged_fields!(WebGLTextureId);
-unsafe_no_jsmanaged_fields!(WebGLVertexArrayId);
-unsafe_no_jsmanaged_fields!(WebGLVersion);
-unsafe_no_jsmanaged_fields!(WebGLSLVersion);
-unsafe_no_jsmanaged_fields!(Arc<ParkMutex<Identities>>);
-unsafe_no_jsmanaged_fields!(WebGPU);
-unsafe_no_jsmanaged_fields!(WebGPUAdapter);
-unsafe_no_jsmanaged_fields!(WebGPUBuffer);
-unsafe_no_jsmanaged_fields!(WebGPUBindGroup);
-unsafe_no_jsmanaged_fields!(WebGPUBindGroupLayout);
-unsafe_no_jsmanaged_fields!(WebGPUComputePipeline);
-unsafe_no_jsmanaged_fields!(WebGPURenderPipeline);
-unsafe_no_jsmanaged_fields!(WebGPURenderBundle);
-unsafe_no_jsmanaged_fields!(WebGPUPipelineLayout);
-unsafe_no_jsmanaged_fields!(WebGPUQueue);
-unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
-unsafe_no_jsmanaged_fields!(WebGPUSampler);
-unsafe_no_jsmanaged_fields!(WebGPUTexture);
-unsafe_no_jsmanaged_fields!(WebGPUTextureView);
unsafe_no_jsmanaged_fields!(WebGPUContextId);
-unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
-unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
-unsafe_no_jsmanaged_fields!(WebGPUDevice);
-unsafe_no_jsmanaged_fields!(Option<RenderPass>);
-unsafe_no_jsmanaged_fields!(Option<RenderBundleEncoder>);
-unsafe_no_jsmanaged_fields!(Option<ComputePass>);
unsafe_no_jsmanaged_fields!(GPUBufferState);
unsafe_no_jsmanaged_fields!(GPUCommandEncoderState);
unsafe_no_jsmanaged_fields!(Range<u64>);
-unsafe_no_jsmanaged_fields!(MediaList);
-unsafe_no_jsmanaged_fields!(
- webxr_api::Registry,
- webxr_api::Session,
- webxr_api::Frame,
- webxr_api::LayerId,
- webxr_api::InputSource,
- webxr_api::InputId,
- webxr_api::Joint,
- webxr_api::HitTestId,
- webxr_api::HitTestResult
-);
-unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
-unsafe_no_jsmanaged_fields!(InteractiveMetrics);
-unsafe_no_jsmanaged_fields!(InteractiveWindow);
-unsafe_no_jsmanaged_fields!(CanvasId);
unsafe_no_jsmanaged_fields!(SourceSet);
-unsafe_no_jsmanaged_fields!(AudioBuffer);
-unsafe_no_jsmanaged_fields!(Arc<Mutex<AudioContext>>);
-unsafe_no_jsmanaged_fields!(NodeId);
-unsafe_no_jsmanaged_fields!(AnalysisEngine, DistanceModel, PanningModel, ParamType);
-unsafe_no_jsmanaged_fields!(Arc<Mutex<dyn Player>>);
-unsafe_no_jsmanaged_fields!(WebRtcController);
-unsafe_no_jsmanaged_fields!(MediaStreamId, MediaStreamType);
-unsafe_no_jsmanaged_fields!(Mutex<MediaFrameRenderer>);
-unsafe_no_jsmanaged_fields!(ResourceFetchTiming);
-unsafe_no_jsmanaged_fields!(Timespec);
unsafe_no_jsmanaged_fields!(HTMLMediaElementFetchContext);
-unsafe_no_jsmanaged_fields!(Rotation3D<f64>, Transform2D<f32>);
-unsafe_no_jsmanaged_fields!(Point2D<f32>, Rect<Au>);
-unsafe_no_jsmanaged_fields!(Rect<f32>);
-unsafe_no_jsmanaged_fields!(CascadeData);
-unsafe_no_jsmanaged_fields!(WindowGLContext);
-unsafe_no_jsmanaged_fields!(VideoFrame);
-unsafe_no_jsmanaged_fields!(WebGLContextId);
-unsafe_no_jsmanaged_fields!(Arc<Mutex<dyn AudioRenderer>>);
-unsafe_no_jsmanaged_fields!(MediaSessionActionType);
-unsafe_no_jsmanaged_fields!(MediaMetadata);
-unsafe_no_jsmanaged_fields!(WebrenderIpcSender);
unsafe_no_jsmanaged_fields!(StreamConsumer);
-unsafe_no_jsmanaged_fields!(DocumentAnimationSet);
unsafe_no_jsmanaged_fields!(Stencil);
unsafe impl<'a> JSTraceable for &'a str {
@@ -693,24 +576,6 @@ unsafe impl<A, B> JSTraceable for fn(A) -> B {
}
}
-unsafe impl<T> JSTraceable for IpcSender<T>
-where
- T: for<'de> Deserialize<'de> + Serialize,
-{
- #[inline]
- unsafe fn trace(&self, _: *mut JSTracer) {
- // Do nothing
- }
-}
-
-// Safe thanks to the Send bound.
-unsafe impl JSTraceable for Box<dyn LayoutRPC + Send + 'static> {
- #[inline]
- unsafe fn trace(&self, _: *mut JSTracer) {
- // Do nothing
- }
-}
-
unsafe impl JSTraceable for () {
#[inline]
unsafe fn trace(&self, _: *mut JSTracer) {
@@ -718,16 +583,6 @@ unsafe impl JSTraceable for () {
}
}
-unsafe impl<T> JSTraceable for IpcReceiver<T>
-where
- T: for<'de> Deserialize<'de> + Serialize,
-{
- #[inline]
- unsafe fn trace(&self, _: *mut JSTracer) {
- // Do nothing
- }
-}
-
unsafe impl<T: DomObject> JSTraceable for Trusted<T> {
#[inline]
unsafe fn trace(&self, _: *mut JSTracer) {
@@ -735,197 +590,6 @@ unsafe impl<T: DomObject> JSTraceable for Trusted<T> {
}
}
-unsafe impl<T: Send> JSTraceable for Receiver<T> {
- #[inline]
- unsafe fn trace(&self, _: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T: Send> JSTraceable for Sender<T> {
- #[inline]
- unsafe fn trace(&self, _: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T: Send> JSTraceable for WebGLReceiver<T>
-where
- T: for<'de> Deserialize<'de> + Serialize,
-{
- #[inline]
- unsafe fn trace(&self, _: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T: Send> JSTraceable for WebGLSender<T>
-where
- T: for<'de> Deserialize<'de> + Serialize,
-{
- #[inline]
- unsafe fn trace(&self, _: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<U> JSTraceable for euclid::Vector2D<f32, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T, U> JSTraceable for euclid::Scale<f32, T, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T, U> JSTraceable for euclid::RigidTransform3D<f32, T, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T, U> JSTraceable for euclid::RigidTransform3D<f64, T, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T, U> JSTraceable for euclid::Transform3D<f32, T, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T, U> JSTraceable for euclid::Transform3D<f64, T, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<T> JSTraceable for EuclidLength<u64, T> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<U> JSTraceable for euclid::Size2D<i32, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<U> JSTraceable for euclid::Size2D<f32, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<U> JSTraceable for euclid::Size2D<u32, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<U> JSTraceable for euclid::Rect<i32, U> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<Space> JSTraceable for Ray<Space> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl<Eye> JSTraceable for View<Eye> {
- #[inline]
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<FontFaceRule> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<CssRules> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<Keyframe> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<KeyframesRule> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<ImportRule> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<SupportsRule> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<MediaRule> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<NamespaceRule> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<StyleRule> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<PropertyDeclarationBlock> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
-unsafe impl JSTraceable for StyleLocked<MediaList> {
- unsafe fn trace(&self, _trc: *mut JSTracer) {
- // Do nothing.
- }
-}
-
unsafe impl<T> JSTraceable for TypedArray<T, Box<Heap<*mut JSObject>>>
where
T: TypedArrayElement,
diff --git a/components/script/dom/blob.rs b/components/script/dom/blob.rs
index b2127f071a0..a6599d3ac99 100644
--- a/components/script/dom/blob.rs
+++ b/components/script/dom/blob.rs
@@ -34,6 +34,7 @@ use uuid::Uuid;
#[dom_struct]
pub struct Blob {
reflector_: Reflector,
+ #[no_trace]
blob_id: BlobId,
}
diff --git a/components/script/dom/broadcastchannel.rs b/components/script/dom/broadcastchannel.rs
index 458ed299e85..dd5149c1203 100644
--- a/components/script/dom/broadcastchannel.rs
+++ b/components/script/dom/broadcastchannel.rs
@@ -22,6 +22,7 @@ pub struct BroadcastChannel {
eventtarget: EventTarget,
name: DOMString,
closed: Cell<bool>,
+ #[no_trace]
id: Uuid,
}
diff --git a/components/script/dom/canvasgradient.rs b/components/script/dom/canvasgradient.rs
index 3671df678af..e404998b004 100644
--- a/components/script/dom/canvasgradient.rs
+++ b/components/script/dom/canvasgradient.rs
@@ -22,13 +22,14 @@ use dom_struct::dom_struct;
pub struct CanvasGradient {
reflector_: Reflector,
style: CanvasGradientStyle,
+ #[no_trace]
stops: DomRefCell<Vec<CanvasGradientStop>>,
}
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub enum CanvasGradientStyle {
- Linear(LinearGradientStyle),
- Radial(RadialGradientStyle),
+ Linear(#[no_trace] LinearGradientStyle),
+ Radial(#[no_trace] RadialGradientStyle),
}
impl CanvasGradient {
diff --git a/components/script/dom/canvaspattern.rs b/components/script/dom/canvaspattern.rs
index 3557f646ab9..5472598ea28 100644
--- a/components/script/dom/canvaspattern.rs
+++ b/components/script/dom/canvaspattern.rs
@@ -15,6 +15,7 @@ use euclid::default::Size2D;
pub struct CanvasPattern {
reflector_: Reflector,
surface_data: Vec<u8>,
+ #[no_trace]
surface_size: Size2D<u32>,
repeat_x: bool,
repeat_y: bool,
diff --git a/components/script/dom/client.rs b/components/script/dom/client.rs
index 2768ee7c9ba..178f6bfba8c 100644
--- a/components/script/dom/client.rs
+++ b/components/script/dom/client.rs
@@ -18,9 +18,11 @@ use uuid::Uuid;
pub struct Client {
reflector_: Reflector,
active_worker: MutNullableDom<ServiceWorker>,
+ #[no_trace]
url: ServoUrl,
frame_type: FrameType,
#[ignore_malloc_size_of = "Defined in uuid"]
+ #[no_trace]
id: Uuid,
}
diff --git a/components/script/dom/cssfontfacerule.rs b/components/script/dom/cssfontfacerule.rs
index 8e2349a0429..679ec525383 100644
--- a/components/script/dom/cssfontfacerule.rs
+++ b/components/script/dom/cssfontfacerule.rs
@@ -17,6 +17,7 @@ use style::stylesheets::FontFaceRule;
pub struct CSSFontFaceRule {
cssrule: CSSRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
fontfacerule: Arc<Locked<FontFaceRule>>,
}
diff --git a/components/script/dom/cssgroupingrule.rs b/components/script/dom/cssgroupingrule.rs
index af0b969058c..f89f58126de 100644
--- a/components/script/dom/cssgroupingrule.rs
+++ b/components/script/dom/cssgroupingrule.rs
@@ -20,6 +20,7 @@ use style::stylesheets::CssRules as StyleCssRules;
pub struct CSSGroupingRule {
cssrule: CSSRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
rules: Arc<Locked<StyleCssRules>>,
rulelist: MutNullableDom<CSSRuleList>,
}
diff --git a/components/script/dom/cssimportrule.rs b/components/script/dom/cssimportrule.rs
index 52fbe62c2bd..e2da2a04378 100644
--- a/components/script/dom/cssimportrule.rs
+++ b/components/script/dom/cssimportrule.rs
@@ -17,6 +17,7 @@ use style::stylesheets::ImportRule;
pub struct CSSImportRule {
cssrule: CSSRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
import_rule: Arc<Locked<ImportRule>>,
}
diff --git a/components/script/dom/csskeyframerule.rs b/components/script/dom/csskeyframerule.rs
index 281fc4b8e5e..9ab465e79a4 100644
--- a/components/script/dom/csskeyframerule.rs
+++ b/components/script/dom/csskeyframerule.rs
@@ -20,6 +20,7 @@ use style::stylesheets::keyframes_rule::Keyframe;
pub struct CSSKeyframeRule {
cssrule: CSSRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
keyframerule: Arc<Locked<Keyframe>>,
style_decl: MutNullableDom<CSSStyleDeclaration>,
}
diff --git a/components/script/dom/csskeyframesrule.rs b/components/script/dom/csskeyframesrule.rs
index aa2be337022..52a25a52dd0 100644
--- a/components/script/dom/csskeyframesrule.rs
+++ b/components/script/dom/csskeyframesrule.rs
@@ -24,6 +24,7 @@ use style::values::KeyframesName;
pub struct CSSKeyframesRule {
cssrule: CSSRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
keyframesrule: Arc<Locked<KeyframesRule>>,
rulelist: MutNullableDom<CSSRuleList>,
}
diff --git a/components/script/dom/cssmediarule.rs b/components/script/dom/cssmediarule.rs
index ca2bdd4d447..cc18fc46797 100644
--- a/components/script/dom/cssmediarule.rs
+++ b/components/script/dom/cssmediarule.rs
@@ -25,6 +25,7 @@ use style_traits::{ParsingMode, ToCss};
pub struct CSSMediaRule {
cssconditionrule: CSSConditionRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
mediarule: Arc<Locked<MediaRule>>,
medialist: MutNullableDom<MediaList>,
}
diff --git a/components/script/dom/cssnamespacerule.rs b/components/script/dom/cssnamespacerule.rs
index 3a15c7d5ffd..d03da04b116 100644
--- a/components/script/dom/cssnamespacerule.rs
+++ b/components/script/dom/cssnamespacerule.rs
@@ -18,6 +18,7 @@ use style::stylesheets::NamespaceRule;
pub struct CSSNamespaceRule {
cssrule: CSSRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
namespacerule: Arc<Locked<NamespaceRule>>,
}
diff --git a/components/script/dom/cssstyledeclaration.rs b/components/script/dom/cssstyledeclaration.rs
index 41101afd625..a2cc459d94c 100644
--- a/components/script/dom/cssstyledeclaration.rs
+++ b/components/script/dom/cssstyledeclaration.rs
@@ -34,6 +34,7 @@ pub struct CSSStyleDeclaration {
reflector_: Reflector,
owner: CSSStyleOwner,
readonly: bool,
+ #[no_trace]
pseudo: Option<PseudoElement>,
}
@@ -43,7 +44,9 @@ pub enum CSSStyleOwner {
Element(Dom<Element>),
CSSRule(
Dom<CSSRule>,
- #[ignore_malloc_size_of = "Arc"] Arc<Locked<PropertyDeclarationBlock>>,
+ #[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
+ Arc<Locked<PropertyDeclarationBlock>>,
),
}
diff --git a/components/script/dom/cssstylerule.rs b/components/script/dom/cssstylerule.rs
index f81f30ab258..007a98a7592 100644
--- a/components/script/dom/cssstylerule.rs
+++ b/components/script/dom/cssstylerule.rs
@@ -26,6 +26,7 @@ use style::stylesheets::{Origin, StyleRule};
pub struct CSSStyleRule {
cssrule: CSSRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
stylerule: Arc<Locked<StyleRule>>,
style_decl: MutNullableDom<CSSStyleDeclaration>,
}
diff --git a/components/script/dom/cssstylesheet.rs b/components/script/dom/cssstylesheet.rs
index dda321be153..e8de2ef3add 100644
--- a/components/script/dom/cssstylesheet.rs
+++ b/components/script/dom/cssstylesheet.rs
@@ -26,6 +26,7 @@ pub struct CSSStyleSheet {
owner: MutNullableDom<Element>,
rulelist: MutNullableDom<CSSRuleList>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
style_stylesheet: Arc<StyleStyleSheet>,
origin_clean: Cell<bool>,
}
diff --git a/components/script/dom/csssupportsrule.rs b/components/script/dom/csssupportsrule.rs
index 8a028e9efb2..0eaa1f9d53a 100644
--- a/components/script/dom/csssupportsrule.rs
+++ b/components/script/dom/csssupportsrule.rs
@@ -23,6 +23,7 @@ use style_traits::{ParsingMode, ToCss};
pub struct CSSSupportsRule {
cssconditionrule: CSSConditionRule,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
supportsrule: Arc<Locked<SupportsRule>>,
}
diff --git a/components/script/dom/customelementregistry.rs b/components/script/dom/customelementregistry.rs
index 153b1d206fc..df458ec90c3 100644
--- a/components/script/dom/customelementregistry.rs
+++ b/components/script/dom/customelementregistry.rs
@@ -43,12 +43,14 @@ use js::jsval::{JSVal, NullValue, ObjectValue, UndefinedValue};
use js::rust::wrappers::{Construct1, JS_GetProperty, SameValue};
use js::rust::{HandleObject, HandleValue, MutableHandleValue};
use std::cell::Cell;
-use std::collections::{HashMap, VecDeque};
+use std::collections::VecDeque;
use std::mem;
use std::ops::Deref;
use std::ptr;
use std::rc::Rc;
+use super::bindings::trace::HashMapTracedValues;
+
/// <https://dom.spec.whatwg.org/#concept-element-custom-element-state>
#[derive(Clone, Copy, Eq, JSTraceable, MallocSizeOf, PartialEq)]
pub enum CustomElementState {
@@ -72,12 +74,12 @@ pub struct CustomElementRegistry {
window: Dom<Window>,
#[ignore_malloc_size_of = "Rc"]
- when_defined: DomRefCell<HashMap<LocalName, Rc<Promise>>>,
+ when_defined: DomRefCell<HashMapTracedValues<LocalName, Rc<Promise>>>,
element_definition_is_running: Cell<bool>,
#[ignore_malloc_size_of = "Rc"]
- definitions: DomRefCell<HashMap<LocalName, Rc<CustomElementDefinition>>>,
+ definitions: DomRefCell<HashMapTracedValues<LocalName, Rc<CustomElementDefinition>>>,
}
impl CustomElementRegistry {
@@ -85,9 +87,9 @@ impl CustomElementRegistry {
CustomElementRegistry {
reflector_: Reflector::new(),
window: Dom::from_ref(window),
- when_defined: DomRefCell::new(HashMap::new()),
+ when_defined: DomRefCell::new(HashMapTracedValues::new()),
element_definition_is_running: Cell::new(false),
- definitions: DomRefCell::new(HashMap::new()),
+ definitions: DomRefCell::new(HashMapTracedValues::new()),
}
}
@@ -101,7 +103,7 @@ impl CustomElementRegistry {
/// Cleans up any active promises
/// <https://github.com/servo/servo/issues/15318>
pub fn teardown(&self) {
- self.when_defined.borrow_mut().clear()
+ self.when_defined.borrow_mut().0.clear()
}
/// <https://html.spec.whatwg.org/multipage/#look-up-a-custom-element-definition>
@@ -112,6 +114,7 @@ impl CustomElementRegistry {
) -> Option<Rc<CustomElementDefinition>> {
self.definitions
.borrow()
+ .0
.values()
.find(|definition| {
// Step 4-5
@@ -127,6 +130,7 @@ impl CustomElementRegistry {
) -> Option<Rc<CustomElementDefinition>> {
self.definitions
.borrow()
+ .0
.values()
.find(|definition| definition.constructor.callback() == constructor.get())
.cloned()
@@ -497,8 +501,10 @@ pub enum ConstructionStackEntry {
/// <https://html.spec.whatwg.org/multipage/#custom-element-definition>
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub struct CustomElementDefinition {
+ #[no_trace]
pub name: LocalName,
+ #[no_trace]
pub local_name: LocalName,
#[ignore_malloc_size_of = "Rc"]
diff --git a/components/script/dom/dedicatedworkerglobalscope.rs b/components/script/dom/dedicatedworkerglobalscope.rs
index acd2942b1a8..956634856ce 100644
--- a/components/script/dom/dedicatedworkerglobalscope.rs
+++ b/components/script/dom/dedicatedworkerglobalscope.rs
@@ -182,6 +182,7 @@ pub struct DedicatedWorkerGlobalScope {
#[ignore_malloc_size_of = "Defined in std"]
task_queue: TaskQueue<DedicatedWorkerScriptMsg>,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
own_sender: Sender<DedicatedWorkerScriptMsg>,
#[ignore_malloc_size_of = "Trusted<T> has unclear ownership like Dom<T>"]
worker: DomRefCell<Option<TrustedWorkerAddress>>,
@@ -189,11 +190,14 @@ pub struct DedicatedWorkerGlobalScope {
/// Sender to the parent thread.
parent_sender: Box<dyn ScriptChan + Send>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
image_cache: Arc<dyn ImageCache>,
+ #[no_trace]
browsing_context: Option<BrowsingContextId>,
/// A receiver of control messages,
/// currently only used to signal shutdown.
#[ignore_malloc_size_of = "Channels are hard"]
+ #[no_trace]
control_receiver: Receiver<DedicatedWorkerControlMsg>,
}
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index d816428684b..aa7a2057503 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -176,6 +176,8 @@ use url::Host;
use uuid::Uuid;
use webrender_api::units::DeviceIntRect;
+use super::bindings::trace::{HashMapTracedValues, NoTrace};
+
/// The number of times we are allowed to see spurious `requestAnimationFrame()` calls before
/// falling back to fake ones.
///
@@ -235,21 +237,26 @@ pub struct Document {
window: Dom<Window>,
implementation: MutNullableDom<DOMImplementation>,
#[ignore_malloc_size_of = "type from external crate"]
+ #[no_trace]
content_type: Mime,
last_modified: Option<String>,
+ #[no_trace]
encoding: Cell<&'static Encoding>,
has_browsing_context: bool,
is_html_document: bool,
+ #[no_trace]
activity: Cell<DocumentActivity>,
+ #[no_trace]
url: DomRefCell<ServoUrl>,
#[ignore_malloc_size_of = "defined in selectors"]
+ #[no_trace]
quirks_mode: Cell<QuirksMode>,
/// Caches for the getElement methods
- id_map: DomRefCell<HashMap<Atom, Vec<Dom<Element>>>>,
- name_map: DomRefCell<HashMap<Atom, Vec<Dom<Element>>>>,
- tag_map: DomRefCell<HashMap<LocalName, Dom<HTMLCollection>>>,
- tagns_map: DomRefCell<HashMap<QualName, Dom<HTMLCollection>>>,
- classes_map: DomRefCell<HashMap<Vec<Atom>, Dom<HTMLCollection>>>,
+ id_map: DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>>,
+ name_map: DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>>,
+ tag_map: DomRefCell<HashMapTracedValues<LocalName, Dom<HTMLCollection>>>,
+ tagns_map: DomRefCell<HashMapTracedValues<QualName, Dom<HTMLCollection>>>,
+ classes_map: DomRefCell<HashMapTracedValues<Vec<Atom>, Dom<HTMLCollection>>>,
images: MutNullableDom<HTMLCollection>,
embeds: MutNullableDom<HTMLCollection>,
links: MutNullableDom<HTMLCollection>,
@@ -259,6 +266,7 @@ pub struct Document {
applets: MutNullableDom<HTMLCollection>,
/// Lock use for style attributes and author-origin stylesheet objects in this document.
/// Can be acquired once for accessing many objects.
+ #[no_trace]
style_shared_lock: StyleSharedRwLock,
/// List of stylesheets associated with nodes in this document. |None| if the list needs to be refreshed.
stylesheets: DomRefCell<DocumentStylesheetSet<StyleSheetInDocument>>,
@@ -309,7 +317,7 @@ pub struct Document {
appropriate_template_contents_owner_document: MutNullableDom<Document>,
/// Information on elements needing restyle to ship over to the layout thread when the
/// time comes.
- pending_restyles: DomRefCell<HashMap<Dom<Element>, PendingRestyle>>,
+ pending_restyles: DomRefCell<HashMap<Dom<Element>, NoTrace<PendingRestyle>>>,
/// This flag will be true if layout suppressed a reflow attempt that was
/// needed in order for the page to be painted.
needs_paint: Cell<bool>,
@@ -328,10 +336,13 @@ pub struct Document {
unload_event_start: Cell<u64>,
unload_event_end: Cell<u64>,
/// <https://html.spec.whatwg.org/multipage/#concept-document-https-state>
+ #[no_trace]
https_state: Cell<HttpsState>,
/// The document's origin.
+ #[no_trace]
origin: MutableOrigin,
/// https://w3c.github.io/webappsec-referrer-policy/#referrer-policy-states
+ #[no_trace]
referrer_policy: Cell<Option<ReferrerPolicy>>,
/// <https://html.spec.whatwg.org/multipage/#dom-document-referrer>
referrer: Option<String>,
@@ -339,6 +350,7 @@ pub struct Document {
target_element: MutNullableDom<Element>,
/// <https://w3c.github.io/uievents/#event-type-dblclick>
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
last_click_info: DomRefCell<Option<(Instant, Point2D<f32>)>>,
/// <https://html.spec.whatwg.org/multipage/#ignore-destructive-writes-counter>
ignore_destructive_writes_counter: Cell<u32>,
@@ -362,8 +374,10 @@ pub struct Document {
/// whenever any element with the same ID as the form attribute
/// is inserted or removed from the document.
/// See https://html.spec.whatwg.org/multipage/#form-owner
- form_id_listener_map: DomRefCell<HashMap<Atom, HashSet<Dom<Element>>>>,
+ form_id_listener_map: DomRefCell<HashMapTracedValues<Atom, HashSet<Dom<Element>>>>,
+ #[no_trace]
interactive_time: DomRefCell<InteractiveMetrics>,
+ #[no_trace]
tti_window: DomRefCell<InteractiveWindow>,
/// RAII canceller for Fetch
canceller: FetchCanceller,
@@ -399,11 +413,13 @@ pub struct Document {
/// hosting the media controls UI.
media_controls: DomRefCell<HashMap<String, Dom<ShadowRoot>>>,
/// List of all WebGL context IDs that need flushing.
- dirty_webgl_contexts: DomRefCell<HashMap<WebGLContextId, Dom<WebGLRenderingContext>>>,
+ dirty_webgl_contexts:
+ DomRefCell<HashMapTracedValues<WebGLContextId, Dom<WebGLRenderingContext>>>,
/// List of all WebGPU context IDs that need flushing.
dirty_webgpu_contexts: DomRefCell<HashMap<WebGPUContextId, Dom<GPUCanvasContext>>>,
/// https://html.spec.whatwg.org/multipage/#concept-document-csp-list
#[ignore_malloc_size_of = "Defined in rust-content-security-policy"]
+ #[no_trace]
csp_list: DomRefCell<Option<CspList>>,
/// https://w3c.github.io/slection-api/#dfn-selection
selection: MutNullableDom<Selection>,
@@ -2865,11 +2881,11 @@ impl Document {
.for_each(|(_, context)| context.send_swap_chain_present());
}
- pub fn id_map(&self) -> Ref<HashMap<Atom, Vec<Dom<Element>>>> {
+ pub fn id_map(&self) -> Ref<HashMapTracedValues<Atom, Vec<Dom<Element>>>> {
self.id_map.borrow()
}
- pub fn name_map(&self) -> Ref<HashMap<Atom, Vec<Dom<Element>>>> {
+ pub fn name_map(&self) -> Ref<HashMapTracedValues<Atom, Vec<Dom<Element>>>> {
self.name_map.borrow()
}
}
@@ -3071,15 +3087,15 @@ impl Document {
url: DomRefCell::new(url),
// https://dom.spec.whatwg.org/#concept-document-quirks
quirks_mode: Cell::new(QuirksMode::NoQuirks),
- id_map: DomRefCell::new(HashMap::new()),
- name_map: DomRefCell::new(HashMap::new()),
+ id_map: DomRefCell::new(HashMapTracedValues::new()),
+ name_map: DomRefCell::new(HashMapTracedValues::new()),
// https://dom.spec.whatwg.org/#concept-document-encoding
encoding: Cell::new(encoding),
is_html_document: is_html_document == IsHTMLDocument::HTMLDocument,
activity: Cell::new(activity),
- tag_map: DomRefCell::new(HashMap::new()),
- tagns_map: DomRefCell::new(HashMap::new()),
- classes_map: DomRefCell::new(HashMap::new()),
+ tag_map: DomRefCell::new(HashMapTracedValues::new()),
+ tagns_map: DomRefCell::new(HashMapTracedValues::new()),
+ classes_map: DomRefCell::new(HashMapTracedValues::new()),
images: Default::default(),
embeds: Default::default(),
links: Default::default(),
@@ -3164,7 +3180,7 @@ impl Document {
shadow_roots: DomRefCell::new(HashSet::new()),
shadow_roots_styles_changed: Cell::new(false),
media_controls: DomRefCell::new(HashMap::new()),
- dirty_webgl_contexts: DomRefCell::new(HashMap::new()),
+ dirty_webgl_contexts: DomRefCell::new(HashMapTracedValues::new()),
dirty_webgpu_contexts: DomRefCell::new(HashMap::new()),
csp_list: DomRefCell::new(None),
selection: MutNullableDom::new(None),
@@ -3494,8 +3510,10 @@ impl Document {
pub fn ensure_pending_restyle(&self, el: &Element) -> RefMut<PendingRestyle> {
let map = self.pending_restyles.borrow_mut();
RefMut::map(map, |m| {
- m.entry(Dom::from_ref(el))
- .or_insert_with(PendingRestyle::new)
+ &mut m
+ .entry(Dom::from_ref(el))
+ .or_insert_with(|| NoTrace(PendingRestyle::new()))
+ .0
})
}
@@ -3864,7 +3882,7 @@ impl Document {
return None;
}
node.note_dirty_descendants();
- Some((node.to_trusted_node_address(), restyle))
+ Some((node.to_trusted_node_address(), restyle.0))
})
.collect()
}
@@ -4838,6 +4856,7 @@ impl DocumentMethods for Document {
// Step 4.
#[derive(JSTraceable, MallocSizeOf)]
struct DocumentNamedGetter {
+ #[no_trace]
name: Atom,
}
impl CollectionFilter for DocumentNamedGetter {
@@ -4878,7 +4897,7 @@ impl DocumentMethods for Document {
let mut names_with_first_named_element_map: HashMap<&Atom, &Element> = HashMap::new();
let name_map = self.name_map.borrow();
- for (name, elements) in &*name_map {
+ for (name, elements) in &(*name_map).0 {
if name.is_empty() {
continue;
}
@@ -4890,7 +4909,7 @@ impl DocumentMethods for Document {
}
}
let id_map = self.id_map.borrow();
- for (id, elements) in &*id_map {
+ for (id, elements) in &(*id_map).0 {
if id.is_empty() {
continue;
}
@@ -5367,6 +5386,7 @@ impl PendingInOrderScriptVec {
#[unrooted_must_root_lint::must_root]
struct PendingScript {
element: Dom<HTMLScriptElement>,
+ // TODO(sagudev): could this be all no_trace?
load: Option<ScriptResult>,
}
diff --git a/components/script/dom/documentfragment.rs b/components/script/dom/documentfragment.rs
index 8f35a0d8781..f2455f61130 100644
--- a/components/script/dom/documentfragment.rs
+++ b/components/script/dom/documentfragment.rs
@@ -19,14 +19,15 @@ use crate::dom::window::Window;
use dom_struct::dom_struct;
use js::rust::HandleObject;
use servo_atoms::Atom;
-use std::collections::HashMap;
+
+use super::bindings::trace::HashMapTracedValues;
// https://dom.spec.whatwg.org/#documentfragment
#[dom_struct]
pub struct DocumentFragment {
node: Node,
/// Caches for the getElement methods
- id_map: DomRefCell<HashMap<Atom, Vec<Dom<Element>>>>,
+ id_map: DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>>,
}
impl DocumentFragment {
@@ -34,7 +35,7 @@ impl DocumentFragment {
pub fn new_inherited(document: &Document) -> DocumentFragment {
DocumentFragment {
node: Node::new_inherited(document),
- id_map: DomRefCell::new(HashMap::new()),
+ id_map: DomRefCell::new(HashMapTracedValues::new()),
}
}
@@ -63,7 +64,7 @@ impl DocumentFragment {
Ok(DocumentFragment::new_with_proto(&document, proto))
}
- pub fn id_map(&self) -> &DomRefCell<HashMap<Atom, Vec<Dom<Element>>>> {
+ pub fn id_map(&self) -> &DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>> {
&self.id_map
}
}
diff --git a/components/script/dom/documentorshadowroot.rs b/components/script/dom/documentorshadowroot.rs
index 5ed1e19f0ab..14e4774c55b 100644
--- a/components/script/dom/documentorshadowroot.rs
+++ b/components/script/dom/documentorshadowroot.rs
@@ -17,17 +17,19 @@ use script_layout_interface::message::{NodesFromPointQueryType, QueryMsg};
use script_traits::UntrustedNodeAddress;
use servo_arc::Arc;
use servo_atoms::Atom;
-use std::collections::HashMap;
use std::fmt;
use style::invalidation::media_queries::{MediaListKey, ToMediaListKey};
use style::media_queries::MediaList;
use style::shared_lock::{SharedRwLock as StyleSharedRwLock, SharedRwLockReadGuard};
use style::stylesheets::{Stylesheet, StylesheetContents};
+use super::bindings::trace::HashMapTracedValues;
+
#[derive(Clone, JSTraceable, MallocSizeOf)]
#[unrooted_must_root_lint::must_root]
pub struct StyleSheetInDocument {
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
pub sheet: Arc<Stylesheet>,
pub owner: Dom<Element>,
}
@@ -247,7 +249,7 @@ impl DocumentOrShadowRoot {
/// Remove any existing association between the provided id/name and any elements in this document.
pub fn unregister_named_element(
&self,
- id_map: &DomRefCell<HashMap<Atom, Vec<Dom<Element>>>>,
+ id_map: &DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>>,
to_unregister: &Element,
id: &Atom,
) {
@@ -275,7 +277,7 @@ impl DocumentOrShadowRoot {
/// Associate an element present in this document with the provided id/name.
pub fn register_named_element(
&self,
- id_map: &DomRefCell<HashMap<Atom, Vec<Dom<Element>>>>,
+ id_map: &DomRefCell<HashMapTracedValues<Atom, Vec<Dom<Element>>>>,
element: &Element,
id: &Atom,
root: DomRoot<Node>,
diff --git a/components/script/dom/dommatrixreadonly.rs b/components/script/dom/dommatrixreadonly.rs
index cd0cdb058a1..f6cc458b618 100644
--- a/components/script/dom/dommatrixreadonly.rs
+++ b/components/script/dom/dommatrixreadonly.rs
@@ -34,6 +34,7 @@ use style::parser::ParserContext;
#[allow(non_snake_case)]
pub struct DOMMatrixReadOnly {
reflector_: Reflector,
+ #[no_trace]
matrix: DomRefCell<Transform3D<f64>>,
is2D: Cell<bool>,
}
diff --git a/components/script/dom/domtokenlist.rs b/components/script/dom/domtokenlist.rs
index 70b306d223b..1e01cea8070 100644
--- a/components/script/dom/domtokenlist.rs
+++ b/components/script/dom/domtokenlist.rs
@@ -19,7 +19,9 @@ use style::str::HTML_SPACE_CHARACTERS;
pub struct DOMTokenList {
reflector_: Reflector,
element: Dom<Element>,
+ #[no_trace]
local_name: LocalName,
+ #[no_trace]
supported_tokens: Option<Vec<Atom>>,
}
diff --git a/components/script/dom/dynamicmoduleowner.rs b/components/script/dom/dynamicmoduleowner.rs
index 50fc71fbd79..67f83442d8f 100644
--- a/components/script/dom/dynamicmoduleowner.rs
+++ b/components/script/dom/dynamicmoduleowner.rs
@@ -13,7 +13,7 @@ use uuid::Uuid;
/// An unique id for dynamic module
#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)]
-pub struct DynamicModuleId(pub Uuid);
+pub struct DynamicModuleId(#[no_trace] pub Uuid);
#[dom_struct]
pub struct DynamicModuleOwner {
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 7408147893f..3304e23cb64 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -149,23 +149,31 @@ use xml5ever::serialize::TraversalScope::IncludeNode as XmlIncludeNode;
#[dom_struct]
pub struct Element {
node: Node,
+ #[no_trace]
local_name: LocalName,
tag_name: TagName,
+ #[no_trace]
namespace: Namespace,
+ #[no_trace]
prefix: DomRefCell<Option<Prefix>>,
attrs: DomRefCell<Vec<Dom<Attr>>>,
+ #[no_trace]
id_attribute: DomRefCell<Option<Atom>>,
+ #[no_trace]
is: DomRefCell<Option<LocalName>>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
style_attribute: DomRefCell<Option<Arc<Locked<PropertyDeclarationBlock>>>>,
attr_list: MutNullableDom<NamedNodeMap>,
class_list: MutNullableDom<DOMTokenList>,
+ #[no_trace]
state: Cell<ElementState>,
/// These flags are set by the style system to indicate the that certain
/// operations may require restyling this element or its descendants. The
/// flags are not atomic, so the style system takes care of only set them
/// when it has exclusive access to the element.
#[ignore_malloc_size_of = "bitflags defined in rust-selectors"]
+ #[no_trace]
selector_flags: Cell<ElementSelectorFlags>,
rare_data: DomRefCell<Option<Box<ElementRareData>>>,
}
@@ -3673,6 +3681,7 @@ impl<'a> AttributeMutation<'a> {
/// owner changes.
#[derive(JSTraceable, MallocSizeOf)]
struct TagName {
+ #[no_trace]
ptr: DomRefCell<Option<LocalName>>,
}
diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs
index c5a5835521f..78a409ce507 100644
--- a/components/script/dom/event.rs
+++ b/components/script/dom/event.rs
@@ -39,6 +39,7 @@ pub struct Event {
reflector_: Reflector,
current_target: MutNullableDom<EventTarget>,
target: MutNullableDom<EventTarget>,
+ #[no_trace]
type_: DomRefCell<Atom>,
phase: Cell<EventPhase>,
canceled: Cell<EventDefault>,
diff --git a/components/script/dom/eventsource.rs b/components/script/dom/eventsource.rs
index f451545f491..57d8a84df8b 100644
--- a/components/script/dom/eventsource.rs
+++ b/components/script/dom/eventsource.rs
@@ -60,7 +60,9 @@ enum ReadyState {
#[dom_struct]
pub struct EventSource {
eventtarget: EventTarget,
+ #[no_trace]
url: ServoUrl,
+ #[no_trace]
request: DomRefCell<Option<RequestBuilder>>,
last_event_id: DomRefCell<DOMString>,
reconnection_time: Cell<u64>,
@@ -647,6 +649,7 @@ pub struct EventSourceTimeoutCallback {
#[ignore_malloc_size_of = "Because it is non-owning"]
event_source: Trusted<EventSource>,
#[ignore_malloc_size_of = "Because it is non-owning"]
+ #[no_trace]
action_sender: ipc::IpcSender<FetchResponseMsg>,
}
diff --git a/components/script/dom/eventtarget.rs b/components/script/dom/eventtarget.rs
index 919cf43b4fc..dde317955cc 100644
--- a/components/script/dom/eventtarget.rs
+++ b/components/script/dom/eventtarget.rs
@@ -44,7 +44,6 @@ use libc::c_char;
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::collections::HashMap;
use std::default::Default;
use std::ffi::CString;
use std::hash::BuildHasherDefault;
@@ -52,6 +51,8 @@ use std::mem;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
+use super::bindings::trace::HashMapTracedValues;
+
#[derive(Clone, JSTraceable, MallocSizeOf, PartialEq)]
pub enum CommonEventHandler {
EventHandler(#[ignore_malloc_size_of = "Rc"] Rc<EventHandlerNonNull>),
@@ -81,6 +82,7 @@ pub enum ListenerPhase {
#[derive(Clone, JSTraceable, MallocSizeOf, PartialEq)]
struct InternalRawUncompiledHandler {
source: DOMString,
+ #[no_trace]
url: ServoUrl,
line: usize,
}
@@ -344,7 +346,7 @@ impl EventListeners {
#[dom_struct]
pub struct EventTarget {
reflector_: Reflector,
- handlers: DomRefCell<HashMap<Atom, EventListeners, BuildHasherDefault<FnvHasher>>>,
+ handlers: DomRefCell<HashMapTracedValues<Atom, EventListeners, BuildHasherDefault<FnvHasher>>>,
}
impl EventTarget {
diff --git a/components/script/dom/fakexrdevice.rs b/components/script/dom/fakexrdevice.rs
index 811a7e01b42..a1905965bc3 100644
--- a/components/script/dom/fakexrdevice.rs
+++ b/components/script/dom/fakexrdevice.rs
@@ -38,8 +38,10 @@ use webxr_api::{
pub struct FakeXRDevice {
reflector: Reflector,
#[ignore_malloc_size_of = "defined in ipc-channel"]
+ #[no_trace]
sender: IpcSender<MockDeviceMsg>,
#[ignore_malloc_size_of = "defined in webxr-api"]
+ #[no_trace]
next_input_id: Cell<InputId>,
}
diff --git a/components/script/dom/fakexrinputcontroller.rs b/components/script/dom/fakexrinputcontroller.rs
index 5699fa5d747..047729b96f6 100644
--- a/components/script/dom/fakexrinputcontroller.rs
+++ b/components/script/dom/fakexrinputcontroller.rs
@@ -23,8 +23,10 @@ use webxr_api::{
pub struct FakeXRInputController {
reflector: Reflector,
#[ignore_malloc_size_of = "defined in ipc-channel"]
+ #[no_trace]
sender: IpcSender<MockDeviceMsg>,
#[ignore_malloc_size_of = "defined in webxr-api"]
+ #[no_trace]
id: InputId,
}
diff --git a/components/script/dom/formdata.rs b/components/script/dom/formdata.rs
index af810e2d888..aa889522f5e 100644
--- a/components/script/dom/formdata.rs
+++ b/components/script/dom/formdata.rs
@@ -20,10 +20,12 @@ use html5ever::LocalName;
use js::rust::HandleObject;
use script_traits::serializable::BlobImpl;
+use super::bindings::trace::NoTrace;
+
#[dom_struct]
pub struct FormData {
reflector_: Reflector,
- data: DomRefCell<Vec<(LocalName, FormDatum)>>,
+ data: DomRefCell<Vec<(NoTrace<LocalName>, FormDatum)>>,
}
impl FormData {
@@ -31,8 +33,8 @@ impl FormData {
let data = match form_datums {
Some(data) => data
.iter()
- .map(|datum| (LocalName::from(datum.name.as_ref()), datum.clone()))
- .collect::<Vec<(LocalName, FormDatum)>>(),
+ .map(|datum| (NoTrace(LocalName::from(datum.name.as_ref())), datum.clone()))
+ .collect::<Vec<(NoTrace<LocalName>, FormDatum)>>(),
None => Vec::new(),
};
@@ -87,7 +89,7 @@ impl FormDataMethods for FormData {
self.data
.borrow_mut()
- .push((LocalName::from(name.0), datum));
+ .push((NoTrace(LocalName::from(name.0)), datum));
}
#[allow(unrooted_must_root)]
@@ -101,14 +103,14 @@ impl FormDataMethods for FormData {
self.data
.borrow_mut()
- .push((LocalName::from(name.0), datum));
+ .push((NoTrace(LocalName::from(name.0)), datum));
}
// https://xhr.spec.whatwg.org/#dom-formdata-delete
fn Delete(&self, name: USVString) {
self.data
.borrow_mut()
- .retain(|(datum_name, _)| datum_name != &LocalName::from(name.0.clone()));
+ .retain(|(datum_name, _)| datum_name.0 != LocalName::from(name.0.clone()));
}
// https://xhr.spec.whatwg.org/#dom-formdata-get
@@ -116,7 +118,7 @@ impl FormDataMethods for FormData {
self.data
.borrow()
.iter()
- .filter(|(datum_name, _)| datum_name == &LocalName::from(name.0.clone()))
+ .filter(|(datum_name, _)| datum_name.0 == LocalName::from(name.0.clone()))
.next()
.map(|(_, datum)| match &datum.value {
FormDatumValue::String(ref s) => {
@@ -131,12 +133,12 @@ impl FormDataMethods for FormData {
self.data
.borrow()
.iter()
- .filter_map(|datum| {
- if datum.0 != LocalName::from(name.0.clone()) {
+ .filter_map(|(datum_name, datum)| {
+ if datum_name.0 != LocalName::from(name.0.clone()) {
return None;
}
- Some(match &datum.1.value {
+ Some(match &datum.value {
FormDatumValue::String(ref s) => {
FileOrUSVString::USVString(USVString(s.to_string()))
},
@@ -151,7 +153,7 @@ impl FormDataMethods for FormData {
self.data
.borrow()
.iter()
- .any(|(datum_name, _0)| datum_name == &LocalName::from(name.0.clone()))
+ .any(|(datum_name, _0)| datum_name.0 == LocalName::from(name.0.clone()))
}
// https://xhr.spec.whatwg.org/#dom-formdata-set
@@ -159,10 +161,10 @@ impl FormDataMethods for FormData {
let mut data = self.data.borrow_mut();
let local_name = LocalName::from(name.0.clone());
- data.retain(|(datum_name, _)| datum_name != &local_name);
+ data.retain(|(datum_name, _)| datum_name.0 != local_name);
data.push((
- local_name,
+ NoTrace(local_name),
FormDatum {
ty: DOMString::from("string"),
name: DOMString::from(name.0),
@@ -177,10 +179,10 @@ impl FormDataMethods for FormData {
let mut data = self.data.borrow_mut();
let local_name = LocalName::from(name.0.clone());
- data.retain(|(datum_name, _)| datum_name != &local_name);
+ data.retain(|(datum_name, _)| datum_name.0 != local_name);
data.push((
- LocalName::from(name.0.clone()),
+ NoTrace(LocalName::from(name.0.clone())),
FormDatum {
ty: DOMString::from("file"),
name: DOMString::from(name.0),
diff --git a/components/script/dom/globalscope.rs b/components/script/dom/globalscope.rs
index b03915997e5..ed082c0f4b9 100644
--- a/components/script/dom/globalscope.rs
+++ b/components/script/dom/globalscope.rs
@@ -129,6 +129,8 @@ use time::{get_time, Timespec};
use uuid::Uuid;
use webgpu::{identity::WebGPUOpResult, ErrorScopeId, WebGPUDevice};
+use super::bindings::trace::HashMapTracedValues;
+
#[derive(JSTraceable)]
pub struct AutoCloseWorker {
/// https://html.spec.whatwg.org/multipage/#dom-workerglobalscope-closing
@@ -137,6 +139,7 @@ pub struct AutoCloseWorker {
join_handle: Option<JoinHandle<()>>,
/// A sender of control messages,
/// currently only used to signal shutdown.
+ #[no_trace]
control_sender: Sender<DedicatedWorkerControlMsg>,
/// The context to request an interrupt on the worker thread.
context: ContextForRequestInterrupt,
@@ -187,13 +190,15 @@ pub struct GlobalScope {
blob_state: DomRefCell<BlobState>,
/// <https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-registration-object-map>
- registration_map:
- DomRefCell<HashMap<ServiceWorkerRegistrationId, Dom<ServiceWorkerRegistration>>>,
+ registration_map: DomRefCell<
+ HashMapTracedValues<ServiceWorkerRegistrationId, Dom<ServiceWorkerRegistration>>,
+ >,
/// <https://w3c.github.io/ServiceWorker/#environment-settings-object-service-worker-object-map>
- worker_map: DomRefCell<HashMap<ServiceWorkerId, Dom<ServiceWorker>>>,
+ worker_map: DomRefCell<HashMapTracedValues<ServiceWorkerId, Dom<ServiceWorker>>>,
/// Pipeline id associated with this global.
+ #[no_trace]
pipeline_id: PipelineId,
/// A flag to indicate whether the developer tools has requested
@@ -206,28 +211,33 @@ pub struct GlobalScope {
/// module map is used when importing JavaScript modules
/// https://html.spec.whatwg.org/multipage/#concept-settings-object-module-map
#[ignore_malloc_size_of = "mozjs"]
- module_map: DomRefCell<HashMap<ServoUrl, Rc<ModuleTree>>>,
+ module_map: DomRefCell<HashMapTracedValues<ServoUrl, Rc<ModuleTree>>>,
#[ignore_malloc_size_of = "mozjs"]
inline_module_map: DomRefCell<HashMap<ScriptId, Rc<ModuleTree>>>,
/// For providing instructions to an optional devtools server.
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
/// For sending messages to the memory profiler.
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
mem_profiler_chan: profile_mem::ProfilerChan,
/// For sending messages to the time profiler.
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
time_profiler_chan: profile_time::ProfilerChan,
/// A handle for communicating messages to the constellation thread.
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
script_to_constellation_chan: ScriptToConstellationChan,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
scheduler_chan: IpcSender<TimerSchedulerMsg>,
/// <https://html.spec.whatwg.org/multipage/#in-error-reporting-mode>
@@ -235,6 +245,7 @@ pub struct GlobalScope {
/// Associated resource threads for use by DOM objects like XMLHttpRequest,
/// including resource_thread, filemanager_thread and storage_thread
+ #[no_trace]
resource_threads: ResourceThreads,
/// The mechanism by which time-outs and intervals are scheduled.
@@ -245,9 +256,11 @@ pub struct GlobalScope {
init_timers: Cell<bool>,
/// The origin of the globalscope
+ #[no_trace]
origin: MutableOrigin,
/// https://html.spec.whatwg.org/multipage/#concept-environment-creation-url
+ #[no_trace]
creation_url: Option<ServoUrl>,
/// A map for storing the previous permission state read results.
@@ -296,16 +309,18 @@ pub struct GlobalScope {
/// Identity Manager for WebGPU resources
#[ignore_malloc_size_of = "defined in wgpu"]
+ #[no_trace]
gpu_id_hub: Arc<Mutex<Identities>>,
/// WebGPU devices
- gpu_devices: DomRefCell<HashMap<WebGPUDevice, Dom<GPUDevice>>>,
+ gpu_devices: DomRefCell<HashMapTracedValues<WebGPUDevice, Dom<GPUDevice>>>,
// https://w3c.github.io/performance-timeline/#supportedentrytypes-attribute
#[ignore_malloc_size_of = "mozjs"]
frozen_supported_performance_entry_types: DomRefCell<Option<Heap<JSVal>>>,
/// currect https state (from previous request)
+ #[no_trace]
https_state: Cell<HttpsState>,
/// The stack of active group labels for the Console APIs.
@@ -379,6 +394,7 @@ pub struct BlobInfo {
/// The weak ref to the corresponding DOM object.
tracker: BlobTracker,
/// The data and logic backing the DOM object.
+ #[no_trace]
blob_impl: BlobImpl,
/// Whether this blob has an outstanding URL,
/// <https://w3c.github.io/FileAPI/#url>.
@@ -389,7 +405,7 @@ pub struct BlobInfo {
#[derive(JSTraceable, MallocSizeOf)]
pub enum BlobState {
/// A map of managed blobs.
- Managed(HashMap<BlobId, BlobInfo>),
+ Managed(HashMapTracedValues<BlobId, BlobInfo>),
/// This global is not managing any blobs at this time.
UnManaged,
}
@@ -412,6 +428,7 @@ pub struct ManagedMessagePort {
/// The option is needed to take out the port-impl
/// as part of its transferring steps,
/// without having to worry about rooting the dom-port.
+ #[no_trace]
port_impl: Option<MessagePortImpl>,
/// We keep ports pending when they are first transfer-received,
/// and only add them, and ask the constellation to complete the transfer,
@@ -430,7 +447,7 @@ pub enum BroadcastChannelState {
/// of https://html.spec.whatwg.org/multipage/#dom-broadcastchannel-postmessage
/// requires keeping track of creation order, hence the queue.
Managed(
- BroadcastChannelRouterId,
+ #[no_trace] BroadcastChannelRouterId,
/// The map of channel-name to queue of channels, in order of creation.
HashMap<DOMString, VecDeque<Dom<BroadcastChannel>>>,
),
@@ -444,8 +461,8 @@ pub enum BroadcastChannelState {
pub enum MessagePortState {
/// The message-port router id for this global, and a map of managed ports.
Managed(
- MessagePortRouterId,
- HashMap<MessagePortId, ManagedMessagePort>,
+ #[no_trace] MessagePortRouterId,
+ HashMapTracedValues<MessagePortId, ManagedMessagePort>,
),
/// This global is not managing any ports at this time.
UnManaged,
@@ -739,8 +756,8 @@ impl GlobalScope {
blob_state: DomRefCell::new(BlobState::UnManaged),
eventtarget: EventTarget::new_inherited(),
crypto: Default::default(),
- registration_map: DomRefCell::new(HashMap::new()),
- worker_map: DomRefCell::new(HashMap::new()),
+ registration_map: DomRefCell::new(HashMapTracedValues::new()),
+ worker_map: DomRefCell::new(HashMapTracedValues::new()),
pipeline_id,
devtools_wants_updates: Default::default(),
console_timers: DomRefCell::new(Default::default()),
@@ -766,7 +783,7 @@ impl GlobalScope {
is_headless,
user_agent,
gpu_id_hub,
- gpu_devices: DomRefCell::new(HashMap::new()),
+ gpu_devices: DomRefCell::new(HashMapTracedValues::new()),
frozen_supported_performance_entry_types: DomRefCell::new(Default::default()),
https_state: Cell::new(HttpsState::None),
console_group_stack: DomRefCell::new(Vec::new()),
@@ -789,7 +806,7 @@ impl GlobalScope {
if let MessagePortState::Managed(_router_id, message_ports) =
&*self.message_port_state.borrow()
{
- return message_ports.contains_key(port_id);
+ return message_ports.contains_key(&*port_id);
}
false
}
@@ -976,7 +993,7 @@ impl GlobalScope {
&mut *self.message_port_state.borrow_mut()
{
for (port_id, entangled_id) in &[(port1, port2), (port2, port1)] {
- match message_ports.get_mut(&port_id) {
+ match message_ports.get_mut(&*port_id) {
None => {
return warn!("entangled_ports called on a global not managing the port.");
},
@@ -1017,7 +1034,7 @@ impl GlobalScope {
&mut *self.message_port_state.borrow_mut()
{
let mut port_impl = message_ports
- .remove(&port_id)
+ .remove(&*port_id)
.map(|ref mut managed_port| {
managed_port
.port_impl
@@ -1040,7 +1057,7 @@ impl GlobalScope {
if let MessagePortState::Managed(_id, message_ports) =
&mut *self.message_port_state.borrow_mut()
{
- let message_buffer = match message_ports.get_mut(&port_id) {
+ let message_buffer = match message_ports.get_mut(&*port_id) {
None => panic!("start_message_port called on a unknown port."),
Some(managed_port) => {
if let Some(port_impl) = managed_port.port_impl.as_mut() {
@@ -1073,7 +1090,7 @@ impl GlobalScope {
if let MessagePortState::Managed(_id, message_ports) =
&mut *self.message_port_state.borrow_mut()
{
- match message_ports.get_mut(&port_id) {
+ match message_ports.get_mut(&*port_id) {
None => panic!("close_message_port called on an unknown port."),
Some(managed_port) => {
if let Some(port_impl) = managed_port.port_impl.as_mut() {
@@ -1306,7 +1323,7 @@ impl GlobalScope {
.collect();
for id in to_be_added.iter() {
let managed_port = message_ports
- .get_mut(&id)
+ .get_mut(&*id)
.expect("Collected port-id to match an entry");
if !managed_port.pending {
panic!("Only pending ports should be found in to_be_added")
@@ -1472,7 +1489,8 @@ impl GlobalScope {
}),
);
let router_id = MessagePortRouterId::new();
- *current_state = MessagePortState::Managed(router_id.clone(), HashMap::new());
+ *current_state =
+ MessagePortState::Managed(router_id.clone(), HashMapTracedValues::new());
let _ = self
.script_to_constellation_chan()
.send(ScriptMsg::NewMessagePortRouter(
@@ -1551,7 +1569,7 @@ impl GlobalScope {
match &mut *blob_state {
BlobState::UnManaged => {
- let mut blobs_map = HashMap::new();
+ let mut blobs_map = HashMapTracedValues::new();
blobs_map.insert(blob_id, blob_info);
*blob_state = BlobState::Managed(blobs_map);
},
@@ -1593,7 +1611,7 @@ impl GlobalScope {
fn perform_a_blob_garbage_collection_checkpoint(&self) {
let mut blob_state = self.blob_state.borrow_mut();
if let BlobState::Managed(blobs_map) = &mut *blob_state {
- blobs_map.retain(|_id, blob_info| {
+ blobs_map.0.retain(|_id, blob_info| {
let garbage_collected = match &blob_info.tracker {
BlobTracker::File(weak) => weak.root().is_none(),
BlobTracker::Blob(weak) => weak.root().is_none(),
@@ -1644,7 +1662,7 @@ impl GlobalScope {
let blob_state = self.blob_state.borrow();
if let BlobState::Managed(blobs_map) = &*blob_state {
let blob_info = blobs_map
- .get(blob_id)
+ .get(&blob_id)
.expect("get_blob_bytes for an unknown blob.");
match blob_info.blob_impl.blob_data() {
BlobData::Sliced(ref parent, ref rel_pos) => {
@@ -1671,7 +1689,7 @@ impl GlobalScope {
let blob_state = self.blob_state.borrow();
if let BlobState::Managed(blobs_map) = &*blob_state {
let blob_info = blobs_map
- .get(blob_id)
+ .get(&blob_id)
.expect("get_blob_bytes_non_sliced called for a unknown blob.");
match blob_info.blob_impl.blob_data() {
BlobData::File(ref f) => {
@@ -1709,7 +1727,7 @@ impl GlobalScope {
let blob_state = self.blob_state.borrow();
if let BlobState::Managed(blobs_map) = &*blob_state {
let blob_info = blobs_map
- .get(blob_id)
+ .get(&blob_id)
.expect("get_blob_bytes_or_file_id for an unknown blob.");
match blob_info.blob_impl.blob_data() {
BlobData::Sliced(ref parent, ref rel_pos) => {
@@ -1745,7 +1763,7 @@ impl GlobalScope {
let blob_state = self.blob_state.borrow();
if let BlobState::Managed(blobs_map) = &*blob_state {
let blob_info = blobs_map
- .get(blob_id)
+ .get(&blob_id)
.expect("get_blob_bytes_non_sliced_or_file_id called for a unknown blob.");
match blob_info.blob_impl.blob_data() {
BlobData::File(ref f) => match f.get_cache() {
@@ -1767,7 +1785,7 @@ impl GlobalScope {
let blob_state = self.blob_state.borrow();
if let BlobState::Managed(blobs_map) = &*blob_state {
let blob_info = blobs_map
- .get(blob_id)
+ .get(&blob_id)
.expect("get_blob_type_string called for a unknown blob.");
blob_info.blob_impl.type_string()
} else {
@@ -1781,7 +1799,7 @@ impl GlobalScope {
if let BlobState::Managed(blobs_map) = &*blob_state {
let parent = {
let blob_info = blobs_map
- .get(blob_id)
+ .get(&blob_id)
.expect("get_blob_size called for a unknown blob.");
match blob_info.blob_impl.blob_data() {
BlobData::Sliced(ref parent, ref rel_pos) => {
@@ -1803,7 +1821,9 @@ impl GlobalScope {
rel_pos.to_abs_range(parent_size as usize).len() as u64
},
None => {
- let blob_info = blobs_map.get(blob_id).expect("Blob whose size is unknown.");
+ let blob_info = blobs_map
+ .get(&blob_id)
+ .expect("Blob whose size is unknown.");
match blob_info.blob_impl.blob_data() {
BlobData::File(ref f) => f.get_size(),
BlobData::Memory(ref v) => v.len() as u64,
@@ -1823,7 +1843,7 @@ impl GlobalScope {
if let BlobState::Managed(blobs_map) = &mut *blob_state {
let parent = {
let blob_info = blobs_map
- .get_mut(blob_id)
+ .get_mut(&blob_id)
.expect("get_blob_url_id called for a unknown blob.");
// Keep track of blobs with outstanding URLs.
@@ -1849,13 +1869,13 @@ impl GlobalScope {
};
let parent_size = rel_pos.to_abs_range(parent_size as usize).len() as u64;
let blob_info = blobs_map
- .get_mut(blob_id)
+ .get_mut(&blob_id)
.expect("Blob whose url is requested is unknown.");
self.create_sliced_url_id(blob_info, &parent_file_id, &rel_pos, parent_size)
},
None => {
let blob_info = blobs_map
- .get_mut(blob_id)
+ .get_mut(&blob_id)
.expect("Blob whose url is requested is unknown.");
self.promote(blob_info, /* set_valid is */ true)
},
@@ -2206,7 +2226,7 @@ impl GlobalScope {
self.module_map.borrow_mut().insert(url, Rc::new(module));
}
- pub fn get_module_map(&self) -> &DomRefCell<HashMap<ServoUrl, Rc<ModuleTree>>> {
+ pub fn get_module_map(&self) -> &DomRefCell<HashMapTracedValues<ServoUrl, Rc<ModuleTree>>> {
&self.module_map
}
diff --git a/components/script/dom/gpuadapter.rs b/components/script/dom/gpuadapter.rs
index ce82e4ec4a3..e87f0589c51 100644
--- a/components/script/dom/gpuadapter.rs
+++ b/components/script/dom/gpuadapter.rs
@@ -26,10 +26,12 @@ use webgpu::{wgt, WebGPU, WebGPUAdapter, WebGPURequest, WebGPUResponse, WebGPURe
pub struct GPUAdapter {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
channel: WebGPU,
name: DOMString,
#[ignore_malloc_size_of = "mozjs"]
extensions: Heap<*mut JSObject>,
+ #[no_trace]
adapter: WebGPUAdapter,
}
diff --git a/components/script/dom/gpubindgroup.rs b/components/script/dom/gpubindgroup.rs
index 394cf41e915..d25cf7fa5bd 100644
--- a/components/script/dom/gpubindgroup.rs
+++ b/components/script/dom/gpubindgroup.rs
@@ -16,7 +16,9 @@ use webgpu::{WebGPUBindGroup, WebGPUDevice};
pub struct GPUBindGroup {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
bind_group: WebGPUBindGroup,
+ #[no_trace]
device: WebGPUDevice,
layout: Dom<GPUBindGroupLayout>,
}
diff --git a/components/script/dom/gpubindgrouplayout.rs b/components/script/dom/gpubindgrouplayout.rs
index ce794269359..87442c1d744 100644
--- a/components/script/dom/gpubindgrouplayout.rs
+++ b/components/script/dom/gpubindgrouplayout.rs
@@ -15,6 +15,7 @@ use webgpu::WebGPUBindGroupLayout;
pub struct GPUBindGroupLayout {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
bind_group_layout: WebGPUBindGroupLayout,
}
diff --git a/components/script/dom/gpubuffer.rs b/components/script/dom/gpubuffer.rs
index 83dd27b47d9..0d528812a96 100644
--- a/components/script/dom/gpubuffer.rs
+++ b/components/script/dom/gpubuffer.rs
@@ -59,9 +59,11 @@ pub struct GPUBufferMapInfo {
pub struct GPUBuffer {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
+ #[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
state: Cell<GPUBufferState>,
+ #[no_trace]
buffer: WebGPUBuffer,
device: Dom<GPUDevice>,
size: GPUSize64,
diff --git a/components/script/dom/gpucanvascontext.rs b/components/script/dom/gpucanvascontext.rs
index 9679479394e..e1fac360758 100644
--- a/components/script/dom/gpucanvascontext.rs
+++ b/components/script/dom/gpucanvascontext.rs
@@ -37,11 +37,14 @@ pub struct WebGPUContextId(pub u64);
pub struct GPUCanvasContext {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
channel: WebGPU,
canvas: Dom<HTMLCanvasElement>,
+ #[no_trace]
size: Cell<Size2D<u32>>,
swap_chain: DomRefCell<Option<Dom<GPUSwapChain>>>,
#[ignore_malloc_size_of = "Defined in webrender"]
+ #[no_trace]
webrender_image: Cell<Option<webrender_api::ImageKey>>,
context_id: WebGPUContextId,
}
diff --git a/components/script/dom/gpucommandbuffer.rs b/components/script/dom/gpucommandbuffer.rs
index eb6ede84c26..633dcb9cc6a 100644
--- a/components/script/dom/gpucommandbuffer.rs
+++ b/components/script/dom/gpucommandbuffer.rs
@@ -26,8 +26,10 @@ impl Hash for DomRoot<GPUBuffer> {
pub struct GPUCommandBuffer {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
+ #[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
command_buffer: WebGPUCommandBuffer,
buffers: DomRefCell<HashSet<Dom<GPUBuffer>>>,
}
diff --git a/components/script/dom/gpucommandencoder.rs b/components/script/dom/gpucommandencoder.rs
index 60eabbf1973..30eb4c91ba9 100644
--- a/components/script/dom/gpucommandencoder.rs
+++ b/components/script/dom/gpucommandencoder.rs
@@ -44,8 +44,10 @@ pub enum GPUCommandEncoderState {
pub struct GPUCommandEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
+ #[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
encoder: webgpu::WebGPUCommandEncoder,
buffers: DomRefCell<HashSet<DomRoot<GPUBuffer>>>,
state: DomRefCell<GPUCommandEncoderState>,
diff --git a/components/script/dom/gpucomputepassencoder.rs b/components/script/dom/gpucomputepassencoder.rs
index f0f4325ae6d..c9b807ae6ac 100644
--- a/components/script/dom/gpucomputepassencoder.rs
+++ b/components/script/dom/gpucomputepassencoder.rs
@@ -22,9 +22,11 @@ use webgpu::{
pub struct GPUComputePassEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
+ #[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
+ #[no_trace]
compute_pass: DomRefCell<Option<ComputePass>>,
command_encoder: Dom<GPUCommandEncoder>,
}
diff --git a/components/script/dom/gpucomputepipeline.rs b/components/script/dom/gpucomputepipeline.rs
index 604af2373e0..cf325837663 100644
--- a/components/script/dom/gpucomputepipeline.rs
+++ b/components/script/dom/gpucomputepipeline.rs
@@ -19,7 +19,9 @@ use webgpu::{WebGPUBindGroupLayout, WebGPUComputePipeline};
pub struct GPUComputePipeline {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
compute_pipeline: WebGPUComputePipeline,
+ #[no_trace]
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
device: Dom<GPUDevice>,
}
diff --git a/components/script/dom/gpudevice.rs b/components/script/dom/gpudevice.rs
index 5ea21eac5de..054a0ecb8e7 100644
--- a/components/script/dom/gpudevice.rs
+++ b/components/script/dom/gpudevice.rs
@@ -108,6 +108,7 @@ struct ScopeContext {
pub struct GPUDevice {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
channel: WebGPU,
adapter: Dom<GPUAdapter>,
#[ignore_malloc_size_of = "mozjs"]
@@ -115,6 +116,7 @@ pub struct GPUDevice {
#[ignore_malloc_size_of = "Because it is non-owning"]
limits: GPULimits,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
device: webgpu::WebGPUDevice,
default_queue: Dom<GPUQueue>,
scope_context: DomRefCell<ScopeContext>,
diff --git a/components/script/dom/gpupipelinelayout.rs b/components/script/dom/gpupipelinelayout.rs
index 563d0ca9220..4a28fcf4a6c 100644
--- a/components/script/dom/gpupipelinelayout.rs
+++ b/components/script/dom/gpupipelinelayout.rs
@@ -15,7 +15,9 @@ use webgpu::{WebGPUBindGroupLayout, WebGPUPipelineLayout};
pub struct GPUPipelineLayout {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
pipeline_layout: WebGPUPipelineLayout,
+ #[no_trace]
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
}
diff --git a/components/script/dom/gpuqueue.rs b/components/script/dom/gpuqueue.rs
index ca571371c8c..e2a9e99b90b 100644
--- a/components/script/dom/gpuqueue.rs
+++ b/components/script/dom/gpuqueue.rs
@@ -27,9 +27,11 @@ use webgpu::{identity::WebGPUOpResult, wgt, WebGPU, WebGPUQueue, WebGPURequest};
pub struct GPUQueue {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
+ #[no_trace]
channel: WebGPU,
device: DomRefCell<Option<Dom<GPUDevice>>>,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
queue: WebGPUQueue,
}
diff --git a/components/script/dom/gpurenderbundle.rs b/components/script/dom/gpurenderbundle.rs
index 5c020f8f697..c39559ed62c 100644
--- a/components/script/dom/gpurenderbundle.rs
+++ b/components/script/dom/gpurenderbundle.rs
@@ -15,8 +15,11 @@ use webgpu::{WebGPU, WebGPUDevice, WebGPURenderBundle};
pub struct GPURenderBundle {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
channel: WebGPU,
+ #[no_trace]
device: WebGPUDevice,
+ #[no_trace]
render_bundle: WebGPURenderBundle,
label: DomRefCell<Option<USVString>>,
}
diff --git a/components/script/dom/gpurenderbundleencoder.rs b/components/script/dom/gpurenderbundleencoder.rs
index 722afdebc0e..b261af6d857 100644
--- a/components/script/dom/gpurenderbundleencoder.rs
+++ b/components/script/dom/gpurenderbundleencoder.rs
@@ -24,9 +24,11 @@ use webgpu::{
pub struct GPURenderBundleEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
channel: WebGPU,
device: Dom<GPUDevice>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
+ #[no_trace]
render_bundle_encoder: DomRefCell<Option<RenderBundleEncoder>>,
label: DomRefCell<Option<USVString>>,
}
diff --git a/components/script/dom/gpurenderpassencoder.rs b/components/script/dom/gpurenderpassencoder.rs
index ac7424b1999..0bcbda00b23 100644
--- a/components/script/dom/gpurenderpassencoder.rs
+++ b/components/script/dom/gpurenderpassencoder.rs
@@ -25,9 +25,11 @@ use webgpu::{
pub struct GPURenderPassEncoder {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webgpu"]
+ #[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
#[ignore_malloc_size_of = "defined in wgpu-core"]
+ #[no_trace]
render_pass: DomRefCell<Option<RenderPass>>,
command_encoder: Dom<GPUCommandEncoder>,
}
diff --git a/components/script/dom/gpurenderpipeline.rs b/components/script/dom/gpurenderpipeline.rs
index 9914b1d3114..76bbd76330e 100644
--- a/components/script/dom/gpurenderpipeline.rs
+++ b/components/script/dom/gpurenderpipeline.rs
@@ -19,7 +19,9 @@ use webgpu::{WebGPUBindGroupLayout, WebGPURenderPipeline};
pub struct GPURenderPipeline {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
render_pipeline: WebGPURenderPipeline,
+ #[no_trace]
bind_group_layouts: Vec<WebGPUBindGroupLayout>,
device: Dom<GPUDevice>,
}
diff --git a/components/script/dom/gpusampler.rs b/components/script/dom/gpusampler.rs
index 23395ee058c..473ac28c3b7 100644
--- a/components/script/dom/gpusampler.rs
+++ b/components/script/dom/gpusampler.rs
@@ -15,8 +15,10 @@ use webgpu::{WebGPUDevice, WebGPUSampler};
pub struct GPUSampler {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
device: WebGPUDevice,
compare_enable: bool,
+ #[no_trace]
sampler: WebGPUSampler,
}
diff --git a/components/script/dom/gpushadermodule.rs b/components/script/dom/gpushadermodule.rs
index c4f20124ea8..5eff0c9cbb3 100644
--- a/components/script/dom/gpushadermodule.rs
+++ b/components/script/dom/gpushadermodule.rs
@@ -15,6 +15,7 @@ use webgpu::WebGPUShaderModule;
pub struct GPUShaderModule {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
shader_module: WebGPUShaderModule,
}
diff --git a/components/script/dom/gpuswapchain.rs b/components/script/dom/gpuswapchain.rs
index 9b8e9aab588..18a5fe29696 100644
--- a/components/script/dom/gpuswapchain.rs
+++ b/components/script/dom/gpuswapchain.rs
@@ -18,6 +18,7 @@ use webrender_api::ImageKey;
pub struct GPUSwapChain {
reflector_: Reflector,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
channel: WebGPU,
label: DomRefCell<Option<USVString>>,
context: Dom<GPUCanvasContext>,
diff --git a/components/script/dom/gputexture.rs b/components/script/dom/gputexture.rs
index b473e52eaae..6f27f4cbc6d 100644
--- a/components/script/dom/gputexture.rs
+++ b/components/script/dom/gputexture.rs
@@ -29,10 +29,12 @@ use webgpu::{
#[dom_struct]
pub struct GPUTexture {
reflector_: Reflector,
+ #[no_trace]
texture: WebGPUTexture,
label: DomRefCell<Option<USVString>>,
device: Dom<GPUDevice>,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
channel: WebGPU,
#[ignore_malloc_size_of = "defined in webgpu"]
texture_size: GPUExtent3DDict,
diff --git a/components/script/dom/gputextureview.rs b/components/script/dom/gputextureview.rs
index af346d92250..1300079422f 100644
--- a/components/script/dom/gputextureview.rs
+++ b/components/script/dom/gputextureview.rs
@@ -16,6 +16,7 @@ use webgpu::WebGPUTextureView;
pub struct GPUTextureView {
reflector_: Reflector,
label: DomRefCell<Option<USVString>>,
+ #[no_trace]
texture_view: WebGPUTextureView,
texture: Dom<GPUTexture>,
}
diff --git a/components/script/dom/headers.rs b/components/script/dom/headers.rs
index a2e2d4acdac..32d0ed36d40 100644
--- a/components/script/dom/headers.rs
+++ b/components/script/dom/headers.rs
@@ -25,6 +25,7 @@ pub struct Headers {
reflector_: Reflector,
guard: Cell<Guard>,
#[ignore_malloc_size_of = "Defined in hyper"]
+ #[no_trace]
header_list: DomRefCell<HyperHeaders>,
}
diff --git a/components/script/dom/history.rs b/components/script/dom/history.rs
index 663499da38f..f527d38a915 100644
--- a/components/script/dom/history.rs
+++ b/components/script/dom/history.rs
@@ -42,6 +42,7 @@ pub struct History {
window: Dom<Window>,
#[ignore_malloc_size_of = "mozjs"]
state: Heap<JSVal>,
+ #[no_trace]
state_id: Cell<Option<HistoryStateId>>,
}
diff --git a/components/script/dom/htmlanchorelement.rs b/components/script/dom/htmlanchorelement.rs
index aca8e99b95a..d52ab647509 100644
--- a/components/script/dom/htmlanchorelement.rs
+++ b/components/script/dom/htmlanchorelement.rs
@@ -42,6 +42,7 @@ use style::attr::AttrValue;
pub struct HTMLAnchorElement {
htmlelement: HTMLElement,
rel_list: MutNullableDom<DOMTokenList>,
+ #[no_trace]
url: DomRefCell<Option<ServoUrl>>,
}
diff --git a/components/script/dom/htmlcollection.rs b/components/script/dom/htmlcollection.rs
index f1eb1fdd706..02a225fb9b6 100644
--- a/components/script/dom/htmlcollection.rs
+++ b/components/script/dom/htmlcollection.rs
@@ -164,7 +164,9 @@ impl HTMLCollection {
#[derive(JSTraceable, MallocSizeOf)]
struct HtmlDocumentFilter {
+ #[no_trace]
qualified_name: LocalName,
+ #[no_trace]
ascii_lower_qualified_name: LocalName,
}
impl CollectionFilter for HtmlDocumentFilter {
@@ -216,6 +218,7 @@ impl HTMLCollection {
) -> DomRoot<HTMLCollection> {
#[derive(JSTraceable, MallocSizeOf)]
struct TagNameNSFilter {
+ #[no_trace]
qname: QualName,
}
impl CollectionFilter for TagNameNSFilter {
@@ -245,6 +248,7 @@ impl HTMLCollection {
) -> DomRoot<HTMLCollection> {
#[derive(JSTraceable, MallocSizeOf)]
struct ClassNameFilter {
+ #[no_trace]
classes: Vec<Atom>,
}
impl CollectionFilter for ClassNameFilter {
diff --git a/components/script/dom/htmlformelement.rs b/components/script/dom/htmlformelement.rs
index 7594026046c..9a1cdc40555 100644
--- a/components/script/dom/htmlformelement.rs
+++ b/components/script/dom/htmlformelement.rs
@@ -76,11 +76,12 @@ use style::element_state::ElementState;
use style::str::split_html_space_chars;
use crate::dom::bindings::codegen::UnionTypes::RadioNodeListOrElement;
-use std::collections::HashMap;
use time::{now, Duration, Tm};
use crate::dom::bindings::codegen::Bindings::NodeBinding::{NodeConstants, NodeMethods};
+use super::bindings::trace::{HashMapTracedValues, NoTrace};
+
#[derive(Clone, Copy, JSTraceable, MallocSizeOf, PartialEq)]
pub struct GenerationId(u32);
@@ -93,7 +94,7 @@ pub struct HTMLFormElement {
elements: DomOnceCell<HTMLFormControlsCollection>,
generation_id: Cell<GenerationId>,
controls: DomRefCell<Vec<Dom<Element>>>,
- past_names_map: DomRefCell<HashMap<Atom, (Dom<Element>, Tm)>>,
+ past_names_map: DomRefCell<HashMapTracedValues<Atom, (Dom<Element>, NoTrace<Tm>)>>,
firing_submission_events: Cell<bool>,
rel_list: MutNullableDom<DOMTokenList>,
}
@@ -116,7 +117,7 @@ impl HTMLFormElement {
elements: Default::default(),
generation_id: Cell::new(GenerationId(0)),
controls: DomRefCell::new(Vec::new()),
- past_names_map: DomRefCell::new(HashMap::new()),
+ past_names_map: DomRefCell::new(HashMapTracedValues::new()),
firing_submission_events: Cell::new(false),
rel_list: Default::default(),
}
@@ -441,7 +442,7 @@ impl HTMLFormElementMethods for HTMLFormElement {
name,
(
Dom::from_ref(&*element_node.downcast::<Element>().unwrap()),
- now(),
+ NoTrace(now()),
),
);
@@ -555,7 +556,7 @@ impl HTMLFormElementMethods for HTMLFormElement {
let entry = SourcedName {
name: key.clone(),
element: DomRoot::from_ref(&*val.0),
- source: SourcedNameSource::Past(now() - val.1), // calculate difference now()-val.1 to find age
+ source: SourcedNameSource::Past(now() - val.1 .0), // calculate difference now()-val.1 to find age
};
sourced_names_vec.push(entry);
}
@@ -1336,7 +1337,7 @@ impl HTMLFormElement {
// changes form owner, then its entries must be removed
// from that map."
let mut past_names_map = self.past_names_map.borrow_mut();
- past_names_map.retain(|_k, v| v.0 != control);
+ past_names_map.0.retain(|_k, v| v.0 != control);
}
self.update_validity();
}
diff --git a/components/script/dom/htmliframeelement.rs b/components/script/dom/htmliframeelement.rs
index e0fe53317ce..55c515d8c1d 100644
--- a/components/script/dom/htmliframeelement.rs
+++ b/components/script/dom/htmliframeelement.rs
@@ -71,10 +71,15 @@ enum ProcessingMode {
#[dom_struct]
pub struct HTMLIFrameElement {
htmlelement: HTMLElement,
+ #[no_trace]
top_level_browsing_context_id: Cell<Option<TopLevelBrowsingContextId>>,
+ #[no_trace]
browsing_context_id: Cell<Option<BrowsingContextId>>,
+ #[no_trace]
pipeline_id: Cell<Option<PipelineId>>,
+ #[no_trace]
pending_pipeline_id: Cell<Option<PipelineId>>,
+ #[no_trace]
about_blank_pipeline_id: Cell<Option<PipelineId>>,
sandbox: MutNullableDom<DOMTokenList>,
sandbox_allowance: Cell<Option<SandboxAllowance>>,
diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index 1598dbd7e2d..cd6e27537e5 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -142,12 +142,16 @@ enum ImageRequestPhase {
#[unrooted_must_root_lint::must_root]
struct ImageRequest {
state: State,
+ #[no_trace]
parsed_url: Option<ServoUrl>,
source_url: Option<USVString>,
blocker: Option<LoadBlocker>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
image: Option<Arc<Image>>,
+ #[no_trace]
metadata: Option<ImageMetadata>,
+ #[no_trace]
final_url: Option<ServoUrl>,
current_pixel_density: Option<f64>,
}
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs
index f0e16612c90..16bbbac21e4 100755
--- a/components/script/dom/htmlinputelement.rs
+++ b/components/script/dom/htmlinputelement.rs
@@ -255,6 +255,7 @@ pub struct HTMLInputElement {
maxlength: Cell<i32>,
minlength: Cell<i32>,
#[ignore_malloc_size_of = "#7193"]
+ #[no_trace]
textinput: DomRefCell<TextInput<ScriptToConstellationChan>>,
// https://html.spec.whatwg.org/multipage/#concept-input-value-dirty-flag
value_dirty: Cell<bool>,
diff --git a/components/script/dom/htmllinkelement.rs b/components/script/dom/htmllinkelement.rs
index 5b8ed9e2250..6b833d6473a 100644
--- a/components/script/dom/htmllinkelement.rs
+++ b/components/script/dom/htmllinkelement.rs
@@ -57,6 +57,7 @@ pub struct HTMLLinkElement {
htmlelement: HTMLElement,
rel_list: MutNullableDom<DOMTokenList>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
stylesheet: DomRefCell<Option<Arc<Stylesheet>>>,
cssom_stylesheet: MutNullableDom<CSSStyleSheet>,
diff --git a/components/script/dom/htmlmediaelement.rs b/components/script/dom/htmlmediaelement.rs
index 2d404cf2d49..5fae503be08 100644
--- a/components/script/dom/htmlmediaelement.rs
+++ b/components/script/dom/htmlmediaelement.rs
@@ -333,10 +333,13 @@ pub struct HTMLMediaElement {
#[ignore_malloc_size_of = "promises are hard"]
in_flight_play_promises_queue: DomRefCell<VecDeque<(Box<[Rc<Promise>]>, ErrorResult)>>,
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
player: DomRefCell<Option<Arc<Mutex<dyn Player>>>>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
video_renderer: Arc<Mutex<MediaFrameRenderer>>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
audio_renderer: DomRefCell<Option<Arc<Mutex<dyn AudioRenderer>>>>,
/// https://html.spec.whatwg.org/multipage/#show-poster-flag
show_poster: Cell<bool>,
@@ -353,9 +356,11 @@ pub struct HTMLMediaElement {
/// https://html.spec.whatwg.org/multipage/#dom-media-muted
muted: Cell<bool>,
/// URL of the media resource, if any.
+ #[no_trace]
resource_url: DomRefCell<Option<ServoUrl>>,
/// URL of the media resource, if the resource is set through the src_object attribute and it
/// is a blob.
+ #[no_trace]
blob_url: DomRefCell<Option<ServoUrl>>,
/// https://html.spec.whatwg.org/multipage/#dom-media-played
#[ignore_malloc_size_of = "Rc"]
@@ -368,6 +373,7 @@ pub struct HTMLMediaElement {
text_tracks_list: MutNullableDom<TextTrackList>,
/// Time of last timeupdate notification.
#[ignore_malloc_size_of = "Defined in time"]
+ #[no_trace]
next_timeupdate_event: Cell<Timespec>,
/// Latest fetch request context.
current_fetch_context: DomRefCell<Option<HTMLMediaElementFetchContext>>,
@@ -379,6 +385,7 @@ pub struct HTMLMediaElement {
/// keeping a whitelist of media controls identifiers.
media_controls_id: DomRefCell<Option<String>>,
#[ignore_malloc_size_of = "Defined in other crates"]
+ #[no_trace]
player_context: WindowGLContext,
}
@@ -2471,6 +2478,7 @@ pub enum MediaElementMicrotask {
ResourceSelectionTask {
elem: DomRoot<HTMLMediaElement>,
generation_id: u32,
+ #[no_trace]
base_url: ServoUrl,
},
PauseIfNotInDocumentTask {
diff --git a/components/script/dom/htmlobjectelement.rs b/components/script/dom/htmlobjectelement.rs
index a6f78b6ec70..348e52d9ee2 100755
--- a/components/script/dom/htmlobjectelement.rs
+++ b/components/script/dom/htmlobjectelement.rs
@@ -27,6 +27,7 @@ use std::default::Default;
pub struct HTMLObjectElement {
htmlelement: HTMLElement,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
image: DomRefCell<Option<Arc<Image>>>,
form_owner: MutNullableDom<HTMLFormElement>,
validity_state: MutNullableDom<ValidityState>,
diff --git a/components/script/dom/htmlscriptelement.rs b/components/script/dom/htmlscriptelement.rs
index e7e520e56bd..8889f6ad696 100644
--- a/components/script/dom/htmlscriptelement.rs
+++ b/components/script/dom/htmlscriptelement.rs
@@ -13,6 +13,7 @@ use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::settings_stack::AutoEntryScript;
use crate::dom::bindings::str::{DOMString, USVString};
+use crate::dom::bindings::trace::NoTrace;
use crate::dom::document::Document;
use crate::dom::element::{
cors_setting_for_element, referrer_policy_for_element, reflect_cross_origin_attribute,
@@ -117,9 +118,9 @@ unsafe extern "C" fn off_thread_compilation_callback(
let compiled_script = FinishOffThreadStencil(*cx, token.0, ptr::null_mut());
let load = if compiled_script.is_null() {
- Err(NetworkError::Internal(
+ Err(NoTrace(NetworkError::Internal(
"Off-thread compilation failed.".into(),
- ))
+ )))
} else {
let script_text = DOMString::from(script);
let code = SourceCode::Compiled(CompiledSourceCode {
@@ -144,7 +145,7 @@ unsafe extern "C" fn off_thread_compilation_callback(
/// An unique id for script element.
#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)]
-pub struct ScriptId(Uuid);
+pub struct ScriptId(#[no_trace] Uuid);
#[dom_struct]
pub struct HTMLScriptElement {
@@ -257,6 +258,7 @@ pub enum SourceCode {
pub struct ScriptOrigin {
#[ignore_malloc_size_of = "Rc is hard"]
code: SourceCode,
+ #[no_trace]
url: ServoUrl,
external: bool,
fetch_options: ScriptFetchOptions,
@@ -326,7 +328,7 @@ fn finish_fetching_a_classic_script(
document.finish_load(LoadType::Script(url));
}
-pub type ScriptResult = Result<ScriptOrigin, NetworkError>;
+pub type ScriptResult = Result<ScriptOrigin, NoTrace<NetworkError>>;
/// The context required for asynchronously loading an external script source.
struct ClassicContext {
@@ -400,7 +402,7 @@ impl FetchResponseListener for ClassicContext {
&*self.elem.root(),
self.kind.clone(),
self.url.clone(),
- Err(err.clone()),
+ Err(NoTrace(err.clone())),
);
return;
},
diff --git a/components/script/dom/htmlstyleelement.rs b/components/script/dom/htmlstyleelement.rs
index 6dd0ee24ab4..e2ffb441f73 100644
--- a/components/script/dom/htmlstyleelement.rs
+++ b/components/script/dom/htmlstyleelement.rs
@@ -34,6 +34,7 @@ use style_traits::ParsingMode;
pub struct HTMLStyleElement {
htmlelement: HTMLElement,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
stylesheet: DomRefCell<Option<Arc<Stylesheet>>>,
cssom_stylesheet: MutNullableDom<CSSStyleSheet>,
/// <https://html.spec.whatwg.org/multipage/#a-style-sheet-that-is-blocking-scripts>
diff --git a/components/script/dom/htmltextareaelement.rs b/components/script/dom/htmltextareaelement.rs
index db21db49b18..6ff51963348 100755
--- a/components/script/dom/htmltextareaelement.rs
+++ b/components/script/dom/htmltextareaelement.rs
@@ -49,6 +49,7 @@ use style::element_state::ElementState;
pub struct HTMLTextAreaElement {
htmlelement: HTMLElement,
#[ignore_malloc_size_of = "#7193"]
+ #[no_trace]
textinput: DomRefCell<TextInput<ScriptToConstellationChan>>,
placeholder: DomRefCell<DOMString>,
// https://html.spec.whatwg.org/multipage/#concept-textarea-dirty
diff --git a/components/script/dom/htmlvideoelement.rs b/components/script/dom/htmlvideoelement.rs
index 4a288607be7..45e843d0efc 100644
--- a/components/script/dom/htmlvideoelement.rs
+++ b/components/script/dom/htmlvideoelement.rs
@@ -60,6 +60,7 @@ pub struct HTMLVideoElement {
load_blocker: DomRefCell<Option<LoadBlocker>>,
/// A copy of the last frame
#[ignore_malloc_size_of = "VideoFrame"]
+ #[no_trace]
last_frame: DomRefCell<Option<VideoFrame>>,
}
diff --git a/components/script/dom/medialist.rs b/components/script/dom/medialist.rs
index 772c508fc04..87a318ddbe2 100644
--- a/components/script/dom/medialist.rs
+++ b/components/script/dom/medialist.rs
@@ -24,6 +24,7 @@ pub struct MediaList {
reflector_: Reflector,
parent_stylesheet: Dom<CSSStyleSheet>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
media_queries: Arc<Locked<StyleMediaList>>,
}
diff --git a/components/script/dom/mediaquerylist.rs b/components/script/dom/mediaquerylist.rs
index 48080f95adf..57140c8cb6f 100644
--- a/components/script/dom/mediaquerylist.rs
+++ b/components/script/dom/mediaquerylist.rs
@@ -27,6 +27,7 @@ pub enum MediaQueryListMatchState {
pub struct MediaQueryList {
eventtarget: EventTarget,
document: Dom<Document>,
+ #[no_trace]
media_query_list: MediaList,
last_match_state: Cell<Option<bool>>,
}
diff --git a/components/script/dom/mediasession.rs b/components/script/dom/mediasession.rs
index 49112ba921b..edd73158acc 100644
--- a/components/script/dom/mediasession.rs
+++ b/components/script/dom/mediasession.rs
@@ -26,20 +26,23 @@ use embedder_traits::MediaMetadata as EmbedderMediaMetadata;
use embedder_traits::MediaSessionEvent;
use script_traits::MediaSessionActionType;
use script_traits::ScriptMsg;
-use std::collections::HashMap;
use std::rc::Rc;
+use super::bindings::trace::HashMapTracedValues;
+
#[dom_struct]
pub struct MediaSession {
reflector_: Reflector,
/// https://w3c.github.io/mediasession/#dom-mediasession-metadata
#[ignore_malloc_size_of = "defined in embedder_traits"]
+ #[no_trace]
metadata: DomRefCell<Option<EmbedderMediaMetadata>>,
/// https://w3c.github.io/mediasession/#dom-mediasession-playbackstate
playback_state: DomRefCell<MediaSessionPlaybackState>,
/// https://w3c.github.io/mediasession/#supported-media-session-actions
#[ignore_malloc_size_of = "Rc"]
- action_handlers: DomRefCell<HashMap<MediaSessionActionType, Rc<MediaSessionActionHandler>>>,
+ action_handlers:
+ DomRefCell<HashMapTracedValues<MediaSessionActionType, Rc<MediaSessionActionHandler>>>,
/// The media instance controlled by this media session.
/// For now only HTMLMediaElements are controlled by media sessions.
media_instance: MutNullableDom<HTMLMediaElement>,
@@ -52,7 +55,7 @@ impl MediaSession {
reflector_: Reflector::new(),
metadata: DomRefCell::new(None),
playback_state: DomRefCell::new(MediaSessionPlaybackState::None),
- action_handlers: DomRefCell::new(HashMap::new()),
+ action_handlers: DomRefCell::new(HashMapTracedValues::new()),
media_instance: Default::default(),
};
media_session
diff --git a/components/script/dom/mediastreamtrack.rs b/components/script/dom/mediastreamtrack.rs
index c5178b3682b..729dbfc5cce 100644
--- a/components/script/dom/mediastreamtrack.rs
+++ b/components/script/dom/mediastreamtrack.rs
@@ -16,8 +16,10 @@ use servo_media::streams::MediaStreamType;
pub struct MediaStreamTrack {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "defined in servo-media"]
+ #[no_trace]
id: MediaStreamId,
#[ignore_malloc_size_of = "defined in servo-media"]
+ #[no_trace]
ty: MediaStreamType,
}
diff --git a/components/script/dom/messageport.rs b/components/script/dom/messageport.rs
index fee7c75a9eb..3035cc5bcd4 100644
--- a/components/script/dom/messageport.rs
+++ b/components/script/dom/messageport.rs
@@ -33,7 +33,9 @@ use std::rc::Rc;
/// The MessagePort used in the DOM.
pub struct MessagePort {
eventtarget: EventTarget,
+ #[no_trace]
message_port_id: MessagePortId,
+ #[no_trace]
entangled_port: RefCell<Option<MessagePortId>>,
detached: Cell<bool>,
}
diff --git a/components/script/dom/mouseevent.rs b/components/script/dom/mouseevent.rs
index 137ccbc7673..670b058b0ba 100644
--- a/components/script/dom/mouseevent.rs
+++ b/components/script/dom/mouseevent.rs
@@ -43,6 +43,7 @@ pub struct MouseEvent {
button: Cell<i16>,
buttons: Cell<u16>,
related_target: MutNullableDom<EventTarget>,
+ #[no_trace]
point_in_target: Cell<Option<Point2D<f32>>>,
}
diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs
index 943a0eaaa1a..a4913faa683 100644
--- a/components/script/dom/node.rs
+++ b/components/script/dom/node.rs
@@ -151,6 +151,7 @@ pub struct Node {
/// Style+Layout information.
#[ignore_malloc_size_of = "trait object"]
+ #[no_trace]
style_and_layout_data: DomRefCell<Option<Box<StyleAndOpaqueLayoutData>>>,
}
diff --git a/components/script/dom/nodelist.rs b/components/script/dom/nodelist.rs
index d7ec1808323..b8286e5f0ea 100644
--- a/components/script/dom/nodelist.rs
+++ b/components/script/dom/nodelist.rs
@@ -392,6 +392,7 @@ pub enum RadioListMode {
pub struct RadioList {
form: Dom<HTMLFormElement>,
mode: RadioListMode,
+ #[no_trace]
name: Atom,
}
diff --git a/components/script/dom/paintrenderingcontext2d.rs b/components/script/dom/paintrenderingcontext2d.rs
index af9f5cd01b3..bdda5fc934e 100644
--- a/components/script/dom/paintrenderingcontext2d.rs
+++ b/components/script/dom/paintrenderingcontext2d.rs
@@ -35,6 +35,7 @@ use style_traits::DevicePixel;
#[dom_struct]
pub struct PaintRenderingContext2D {
context: CanvasRenderingContext2D,
+ #[no_trace]
device_pixel_ratio: Cell<Scale<f32, CSSPixel, DevicePixel>>,
}
diff --git a/components/script/dom/paintworkletglobalscope.rs b/components/script/dom/paintworkletglobalscope.rs
index 25bdeeb5ca3..ab16d75a672 100644
--- a/components/script/dom/paintworkletglobalscope.rs
+++ b/components/script/dom/paintworkletglobalscope.rs
@@ -55,7 +55,6 @@ use servo_config::pref;
use servo_url::ServoUrl;
use std::cell::Cell;
use std::collections::hash_map::Entry;
-use std::collections::HashMap;
use std::ptr::null_mut;
use std::rc::Rc;
use std::sync::Arc;
@@ -66,6 +65,8 @@ use style_traits::CSSPixel;
use style_traits::DevicePixel;
use style_traits::SpeculativePainter;
+use super::bindings::trace::HashMapTracedValues;
+
/// <https://drafts.css-houdini.org/css-paint-api/#paintworkletglobalscope>
#[dom_struct]
pub struct PaintWorkletGlobalScope {
@@ -73,23 +74,29 @@ pub struct PaintWorkletGlobalScope {
worklet_global: WorkletGlobalScope,
/// The image cache
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
image_cache: Arc<dyn ImageCache>,
/// <https://drafts.css-houdini.org/css-paint-api/#paint-definitions>
- paint_definitions: DomRefCell<HashMap<Atom, Box<PaintDefinition>>>,
+ paint_definitions: DomRefCell<HashMapTracedValues<Atom, Box<PaintDefinition>>>,
/// <https://drafts.css-houdini.org/css-paint-api/#paint-class-instances>
#[ignore_malloc_size_of = "mozjs"]
- paint_class_instances: DomRefCell<HashMap<Atom, Box<Heap<JSVal>>>>,
+ paint_class_instances: DomRefCell<HashMapTracedValues<Atom, Box<Heap<JSVal>>>>,
/// The most recent name the worklet was called with
+ #[no_trace]
cached_name: DomRefCell<Atom>,
/// The most recent size the worklet was drawn at
+ #[no_trace]
cached_size: Cell<Size2D<f32, CSSPixel>>,
/// The most recent device pixel ratio the worklet was drawn at
+ #[no_trace]
cached_device_pixel_ratio: Cell<Scale<f32, CSSPixel, DevicePixel>>,
/// The most recent properties the worklet was drawn at
+ #[no_trace]
cached_properties: DomRefCell<Vec<(Atom, String)>>,
/// The most recent arguments the worklet was drawn at
cached_arguments: DomRefCell<Vec<String>>,
/// The most recent result
+ #[no_trace]
cached_result: DomRefCell<DrawAPaintImageResult>,
}
diff --git a/components/script/dom/pannernode.rs b/components/script/dom/pannernode.rs
index 3d1b4d6d112..48b572da260 100644
--- a/components/script/dom/pannernode.rs
+++ b/components/script/dom/pannernode.rs
@@ -42,8 +42,10 @@ pub struct PannerNode {
orientation_y: Dom<AudioParam>,
orientation_z: Dom<AudioParam>,
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
panning_model: Cell<PanningModel>,
#[ignore_malloc_size_of = "servo_media"]
+ #[no_trace]
distance_model: Cell<DistanceModel>,
ref_distance: Cell<f64>,
max_distance: Cell<f64>,
diff --git a/components/script/dom/raredata.rs b/components/script/dom/raredata.rs
index 9d4a82d63d6..1a4916f1694 100644
--- a/components/script/dom/raredata.rs
+++ b/components/script/dom/raredata.rs
@@ -47,7 +47,9 @@ pub struct ElementRareData {
pub custom_element_state: CustomElementState,
/// The "name" content attribute; not used as frequently as id, but used
/// in named getter loops so it's worth looking up quickly when present
+ #[no_trace]
pub name_attribute: Option<Atom>,
/// The client rect reported by layout.
+ #[no_trace]
pub client_rect: Option<LayoutValue<Rect<i32>>>,
}
diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs
index da9b57aab13..26234e7ab68 100644
--- a/components/script/dom/request.rs
+++ b/components/script/dom/request.rs
@@ -48,6 +48,7 @@ use std::str::FromStr;
#[dom_struct]
pub struct Request {
reflector_: Reflector,
+ #[no_trace]
request: DomRefCell<NetTraitsRequest>,
body_stream: MutNullableDom<ReadableStream>,
headers: MutNullableDom<Headers>,
diff --git a/components/script/dom/response.rs b/components/script/dom/response.rs
index dbfd1653fd6..bf4d858c9c3 100644
--- a/components/script/dom/response.rs
+++ b/components/script/dom/response.rs
@@ -40,10 +40,13 @@ pub struct Response {
headers_reflector: MutNullableDom<Headers>,
/// `None` can be considered a StatusCode of `0`.
#[ignore_malloc_size_of = "Defined in hyper"]
+ #[no_trace]
status: DomRefCell<Option<StatusCode>>,
raw_status: DomRefCell<Option<(u16, Vec<u8>)>>,
response_type: DomRefCell<DOMResponseType>,
+ #[no_trace]
url: DomRefCell<Option<ServoUrl>>,
+ #[no_trace]
url_list: DomRefCell<Vec<ServoUrl>>,
/// The stream of https://fetch.spec.whatwg.org/#body.
body_stream: MutNullableDom<ReadableStream>,
diff --git a/components/script/dom/rtcpeerconnection.rs b/components/script/dom/rtcpeerconnection.rs
index df954136867..93600b4f209 100644
--- a/components/script/dom/rtcpeerconnection.rs
+++ b/components/script/dom/rtcpeerconnection.rs
@@ -59,6 +59,7 @@ use std::rc::Rc;
pub struct RTCPeerConnection {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "defined in servo-media"]
+ #[no_trace]
controller: DomRefCell<Option<WebRtcController>>,
closed: Cell<bool>,
// Helps track state changes between the time createOffer/createAnswer
diff --git a/components/script/dom/serviceworker.rs b/components/script/dom/serviceworker.rs
index bcbdd158a40..b01fc2a1d97 100644
--- a/components/script/dom/serviceworker.rs
+++ b/components/script/dom/serviceworker.rs
@@ -34,8 +34,10 @@ pub type TrustedServiceWorkerAddress = Trusted<ServiceWorker>;
pub struct ServiceWorker {
eventtarget: EventTarget,
script_url: DomRefCell<String>,
+ #[no_trace]
scope_url: ServoUrl,
state: Cell<ServiceWorkerState>,
+ #[no_trace]
worker_id: ServiceWorkerId,
}
diff --git a/components/script/dom/serviceworkerglobalscope.rs b/components/script/dom/serviceworkerglobalscope.rs
index cbd38c0fc42..fff0f9b9ddc 100644
--- a/components/script/dom/serviceworkerglobalscope.rs
+++ b/components/script/dom/serviceworkerglobalscope.rs
@@ -131,6 +131,7 @@ pub enum MixedMessage {
#[derive(Clone, JSTraceable)]
pub struct ServiceWorkerChan {
+ #[no_trace]
pub sender: Sender<ServiceWorkerScriptMsg>,
}
@@ -150,16 +151,16 @@ impl ScriptChan for ServiceWorkerChan {
}
}
-unsafe_no_jsmanaged_fields!(TaskQueue<ServiceWorkerScriptMsg>);
-
#[dom_struct]
pub struct ServiceWorkerGlobalScope {
workerglobalscope: WorkerGlobalScope,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
task_queue: TaskQueue<ServiceWorkerScriptMsg>,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
own_sender: Sender<ServiceWorkerScriptMsg>,
/// A port on which a single "time-out" message can be received,
@@ -167,16 +168,20 @@ pub struct ServiceWorkerGlobalScope {
/// while still draining the task-queue
// and running all enqueued, and not cancelled, tasks.
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
time_out_port: Receiver<Instant>,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
swmanager_sender: IpcSender<ServiceWorkerMsg>,
+ #[no_trace]
scope_url: ServoUrl,
/// A receiver of control messages,
/// currently only used to signal shutdown.
#[ignore_malloc_size_of = "Channels are hard"]
+ #[no_trace]
control_receiver: Receiver<ServiceWorkerControlMsg>,
}
diff --git a/components/script/dom/serviceworkerregistration.rs b/components/script/dom/serviceworkerregistration.rs
index 0c1734b41cc..d9438880f7b 100644
--- a/components/script/dom/serviceworkerregistration.rs
+++ b/components/script/dom/serviceworkerregistration.rs
@@ -28,11 +28,13 @@ pub struct ServiceWorkerRegistration {
installing: DomRefCell<Option<Dom<ServiceWorker>>>,
waiting: DomRefCell<Option<Dom<ServiceWorker>>>,
navigation_preload: MutNullableDom<NavigationPreloadManager>,
+ #[no_trace]
scope: ServoUrl,
navigation_preload_enabled: Cell<bool>,
navigation_preload_header_value: DomRefCell<Option<ByteString>>,
update_via_cache: ServiceWorkerUpdateViaCache,
uninstalling: Cell<bool>,
+ #[no_trace]
registration_id: ServiceWorkerRegistrationId,
}
diff --git a/components/script/dom/servoparser/async_html.rs b/components/script/dom/servoparser/async_html.rs
index 9a76278b178..6a87458d9f1 100644
--- a/components/script/dom/servoparser/async_html.rs
+++ b/components/script/dom/servoparser/async_html.rs
@@ -43,6 +43,7 @@ type ParseNodeId = usize;
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub struct ParseNode {
id: ParseNodeId,
+ #[no_trace]
qual_name: Option<QualName>,
}
@@ -54,6 +55,7 @@ enum NodeOrText {
#[derive(JSTraceable, MallocSizeOf)]
struct Attribute {
+ #[no_trace]
name: QualName,
value: String,
}
@@ -67,6 +69,7 @@ enum ParseOperation {
CreateElement {
node: ParseNodeId,
+ #[no_trace]
name: QualName,
attrs: Vec<Attribute>,
current_line: u64,
@@ -130,6 +133,7 @@ enum ParseOperation {
SetQuirksMode {
#[ignore_malloc_size_of = "Defined in style"]
+ #[no_trace]
mode: ServoQuirksMode,
},
}
@@ -200,11 +204,14 @@ fn create_buffer_queue(mut buffers: VecDeque<SendTendril<UTF8>>) -> BufferQueue
pub struct Tokenizer {
document: Dom<Document>,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
receiver: Receiver<ToTokenizerMsg>,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
html_tokenizer_sender: Sender<ToHtmlTokenizerMsg>,
#[ignore_malloc_size_of = "Defined in std"]
nodes: HashMap<ParseNodeId, Dom<Node>>,
+ #[no_trace]
url: ServoUrl,
parsing_algorithm: ParsingAlgorithm,
}
diff --git a/components/script/dom/servoparser/mod.rs b/components/script/dom/servoparser/mod.rs
index ba114366aa2..44d0c3de1df 100644
--- a/components/script/dom/servoparser/mod.rs
+++ b/components/script/dom/servoparser/mod.rs
@@ -95,9 +95,11 @@ pub struct ServoParser {
network_decoder: DomRefCell<Option<NetworkDecoder>>,
/// Input received from network.
#[ignore_malloc_size_of = "Defined in html5ever"]
+ #[no_trace]
network_input: DomRefCell<BufferQueue>,
/// Input received from script. Used only to support document.write().
#[ignore_malloc_size_of = "Defined in html5ever"]
+ #[no_trace]
script_input: DomRefCell<BufferQueue>,
/// The tokenizer of this parser.
tokenizer: DomRefCell<Tokenizer>,
@@ -116,6 +118,7 @@ pub struct ServoParser {
// building the DOM. https://github.com/servo/servo/pull/19203
prefetch_tokenizer: DomRefCell<prefetch::Tokenizer>,
#[ignore_malloc_size_of = "Defined in html5ever"]
+ #[no_trace]
prefetch_input: DomRefCell<BufferQueue>,
}
@@ -1046,6 +1049,7 @@ fn insert(
#[derive(JSTraceable, MallocSizeOf)]
#[unrooted_must_root_lint::must_root]
pub struct Sink {
+ #[no_trace]
base_url: ServoUrl,
document: Dom<Document>,
current_line: u64,
@@ -1401,6 +1405,7 @@ impl NetworkDecoder {
#[derive(Default, JSTraceable)]
struct NetworkSink {
+ #[no_trace]
output: StrTendril,
}
diff --git a/components/script/dom/servoparser/prefetch.rs b/components/script/dom/servoparser/prefetch.rs
index 4de7e765b0c..f328b417bd0 100644
--- a/components/script/dom/servoparser/prefetch.rs
+++ b/components/script/dom/servoparser/prefetch.rs
@@ -75,12 +75,19 @@ impl Tokenizer {
#[derive(JSTraceable)]
struct PrefetchSink {
+ #[no_trace]
origin: ImmutableOrigin,
+ #[no_trace]
pipeline_id: PipelineId,
+ #[no_trace]
document_url: ServoUrl,
+ #[no_trace]
base_url: Option<ServoUrl>,
+ #[no_trace]
referrer: Referrer,
+ #[no_trace]
referrer_policy: Option<ReferrerPolicy>,
+ #[no_trace]
resource_threads: ResourceThreads,
prefetching: bool,
}
diff --git a/components/script/dom/storage.rs b/components/script/dom/storage.rs
index 8d8ad0dc7ba..10746abe10b 100644
--- a/components/script/dom/storage.rs
+++ b/components/script/dom/storage.rs
@@ -24,6 +24,7 @@ use servo_url::ServoUrl;
#[dom_struct]
pub struct Storage {
reflector_: Reflector,
+ #[no_trace]
storage_type: StorageType,
}
diff --git a/components/script/dom/stylepropertymapreadonly.rs b/components/script/dom/stylepropertymapreadonly.rs
index 3881bfcdd87..f64c9cfc54a 100644
--- a/components/script/dom/stylepropertymapreadonly.rs
+++ b/components/script/dom/stylepropertymapreadonly.rs
@@ -12,14 +12,15 @@ use crate::dom::globalscope::GlobalScope;
use dom_struct::dom_struct;
use servo_atoms::Atom;
use std::cmp::Ordering;
-use std::collections::HashMap;
use std::iter::Iterator;
use style::custom_properties;
+use super::bindings::trace::HashMapTracedValues;
+
#[dom_struct]
pub struct StylePropertyMapReadOnly {
reflector: Reflector,
- entries: HashMap<Atom, Dom<CSSStyleValue>>,
+ entries: HashMapTracedValues<Atom, Dom<CSSStyleValue>>,
}
impl StylePropertyMapReadOnly {
@@ -29,7 +30,7 @@ impl StylePropertyMapReadOnly {
{
StylePropertyMapReadOnly {
reflector: Reflector::new(),
- entries: entries.into_iter().collect(),
+ entries: HashMapTracedValues(entries.into_iter().collect()),
}
}
@@ -78,6 +79,7 @@ impl StylePropertyMapReadOnlyMethods for StylePropertyMapReadOnly {
fn GetProperties(&self) -> Vec<DOMString> {
let mut result: Vec<DOMString> = self
.entries
+ .0
.keys()
.map(|key| DOMString::from(&**key))
.collect();
diff --git a/components/script/dom/textdecoder.rs b/components/script/dom/textdecoder.rs
index 67d9d8790ea..dad1568a293 100644
--- a/components/script/dom/textdecoder.rs
+++ b/components/script/dom/textdecoder.rs
@@ -22,10 +22,12 @@ use std::cell::{Cell, RefCell};
#[allow(non_snake_case)]
pub struct TextDecoder {
reflector_: Reflector,
+ #[no_trace]
encoding: &'static Encoding,
fatal: bool,
ignoreBOM: bool,
#[ignore_malloc_size_of = "defined in encoding_rs"]
+ #[no_trace]
decoder: RefCell<Decoder>,
in_stream: RefCell<Vec<u8>>,
do_not_flush: Cell<bool>,
diff --git a/components/script/dom/transitionevent.rs b/components/script/dom/transitionevent.rs
index ab32fefc1c3..cba2856b57e 100644
--- a/components/script/dom/transitionevent.rs
+++ b/components/script/dom/transitionevent.rs
@@ -21,6 +21,7 @@ use servo_atoms::Atom;
#[dom_struct]
pub struct TransitionEvent {
event: Event,
+ #[no_trace]
property_name: Atom,
elapsed_time: Finite<f32>,
pseudo_element: DOMString,
diff --git a/components/script/dom/url.rs b/components/script/dom/url.rs
index fe3631e93fb..9868ba0655b 100644
--- a/components/script/dom/url.rs
+++ b/components/script/dom/url.rs
@@ -28,6 +28,7 @@ pub struct URL {
reflector_: Reflector,
// https://url.spec.whatwg.org/#concept-url-url
+ #[no_trace]
url: DomRefCell<ServoUrl>,
// https://url.spec.whatwg.org/#dom-url-searchparams
diff --git a/components/script/dom/vertexarrayobject.rs b/components/script/dom/vertexarrayobject.rs
index fcf6461e2a8..eef71e32a86 100644
--- a/components/script/dom/vertexarrayobject.rs
+++ b/components/script/dom/vertexarrayobject.rs
@@ -17,6 +17,7 @@ use std::cell::Cell;
#[unrooted_must_root_lint::must_root]
pub struct VertexArrayObject {
context: Dom<WebGLRenderingContext>,
+ #[no_trace]
id: Option<WebGLVertexArrayId>,
ever_bound: Cell<bool>,
is_deleted: Cell<bool>,
diff --git a/components/script/dom/webgl_extensions/extensions.rs b/components/script/dom/webgl_extensions/extensions.rs
index 97e5900960f..4873b3638e8 100644
--- a/components/script/dom/webgl_extensions/extensions.rs
+++ b/components/script/dom/webgl_extensions/extensions.rs
@@ -82,6 +82,7 @@ struct WebGLExtensionFeatures {
gl_extensions: FnvHashSet<String>,
disabled_tex_types: FnvHashSet<GLenum>,
not_filterable_tex_types: FnvHashSet<GLenum>,
+ #[no_trace]
effective_tex_internal_formats: FnvHashMap<TexFormatType, TexFormat>,
/// WebGL Hint() targets enabled by extensions.
hint_targets: FnvHashSet<GLenum>,
@@ -166,8 +167,11 @@ impl WebGLExtensionFeatures {
pub struct WebGLExtensions {
extensions: DomRefCell<HashMap<String, Box<dyn WebGLExtensionWrapper>>>,
features: DomRefCell<WebGLExtensionFeatures>,
+ #[no_trace]
webgl_version: WebGLVersion,
+ #[no_trace]
api_type: GlType,
+ #[no_trace]
glsl_version: WebGLSLVersion,
}
@@ -466,5 +470,5 @@ impl WebGLExtensions {
}
// Helper structs
-#[derive(Eq, Hash, JSTraceable, MallocSizeOf, PartialEq)]
+#[derive(Eq, Hash, MallocSizeOf, PartialEq)]
struct TexFormatType(TexFormat, u32);
diff --git a/components/script/dom/webglbuffer.rs b/components/script/dom/webglbuffer.rs
index f81270d8240..7deb030e6c6 100644
--- a/components/script/dom/webglbuffer.rs
+++ b/components/script/dom/webglbuffer.rs
@@ -24,6 +24,7 @@ fn target_is_copy_buffer(target: u32) -> bool {
#[dom_struct]
pub struct WebGLBuffer {
webgl_object: WebGLObject,
+ #[no_trace]
id: WebGLBufferId,
/// The target to which this buffer was bound the first time
target: Cell<Option<u32>>,
diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs
index 8172b1b6c4e..021ebb0fd0c 100644
--- a/components/script/dom/webglframebuffer.rs
+++ b/components/script/dom/webglframebuffer.rs
@@ -87,7 +87,9 @@ pub enum WebGLFramebufferAttachmentRoot {
#[dom_struct]
pub struct WebGLFramebuffer {
webgl_object: WebGLObject,
+ #[no_trace]
webgl_version: WebGLVersion,
+ #[no_trace]
id: WebGLFramebufferId,
target: Cell<Option<u32>>,
is_deleted: Cell<bool>,
diff --git a/components/script/dom/webglprogram.rs b/components/script/dom/webglprogram.rs
index 88cecf0296f..3ea2e6afef4 100644
--- a/components/script/dom/webglprogram.rs
+++ b/components/script/dom/webglprogram.rs
@@ -26,6 +26,7 @@ use std::cell::Cell;
#[dom_struct]
pub struct WebGLProgram {
webgl_object: WebGLObject,
+ #[no_trace]
id: WebGLProgramId,
is_in_use: Cell<bool>,
marked_for_deletion: Cell<bool>,
@@ -34,8 +35,11 @@ pub struct WebGLProgram {
link_generation: Cell<u64>,
fragment_shader: MutNullableDom<WebGLShader>,
vertex_shader: MutNullableDom<WebGLShader>,
+ #[no_trace]
active_attribs: DomRefCell<Box<[ActiveAttribInfo]>>,
+ #[no_trace]
active_uniforms: DomRefCell<Box<[ActiveUniformInfo]>>,
+ #[no_trace]
active_uniform_blocks: DomRefCell<Box<[ActiveUniformBlockInfo]>>,
transform_feedback_varyings_length: Cell<i32>,
transform_feedback_mode: Cell<i32>,
diff --git a/components/script/dom/webglquery.rs b/components/script/dom/webglquery.rs
index 454fe72954e..c971d8442ff 100644
--- a/components/script/dom/webglquery.rs
+++ b/components/script/dom/webglquery.rs
@@ -18,6 +18,7 @@ use std::cell::Cell;
#[dom_struct]
pub struct WebGLQuery {
webgl_object: WebGLObject,
+ #[no_trace]
gl_id: WebGLQueryId,
gl_target: Cell<Option<u32>>,
marked_for_deletion: Cell<bool>,
diff --git a/components/script/dom/webglrenderbuffer.rs b/components/script/dom/webglrenderbuffer.rs
index 204fe9ab46e..6fe3d06d7fd 100644
--- a/components/script/dom/webglrenderbuffer.rs
+++ b/components/script/dom/webglrenderbuffer.rs
@@ -22,6 +22,7 @@ use std::cell::Cell;
#[dom_struct]
pub struct WebGLRenderbuffer {
webgl_object: WebGLObject,
+ #[no_trace]
id: WebGLRenderbufferId,
ever_bound: Cell<bool>,
is_deleted: Cell<bool>,
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index 9a2b561adae..cedbbd5cc7e 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -166,13 +166,18 @@ pub struct WebGLRenderingContext {
#[ignore_malloc_size_of = "Channels are hard"]
webgl_sender: WebGLMessageSender,
#[ignore_malloc_size_of = "Defined in webrender"]
+ #[no_trace]
webrender_image: ImageKey,
+ #[no_trace]
webgl_version: WebGLVersion,
+ #[no_trace]
glsl_version: WebGLSLVersion,
#[ignore_malloc_size_of = "Defined in surfman"]
+ #[no_trace]
limits: GLLimits,
canvas: Dom<HTMLCanvasElement>,
#[ignore_malloc_size_of = "Defined in canvas_traits"]
+ #[no_trace]
last_error: Cell<Option<WebGLError>>,
texture_packing_alignment: Cell<u8>,
texture_unpacking_settings: Cell<TextureUnpacking>,
@@ -190,6 +195,7 @@ pub struct WebGLRenderingContext {
current_scissor: Cell<(i32, i32, u32, u32)>,
#[ignore_malloc_size_of = "Because it's small"]
current_clear_color: Cell<(f32, f32, f32, f32)>,
+ #[no_trace]
size: Cell<Size2D<u32>>,
extension_manager: WebGLExtensions,
capabilities: Capabilities,
@@ -198,6 +204,7 @@ pub struct WebGLRenderingContext {
default_vao_webgl2: DomOnceCell<WebGLVertexArrayObject>,
current_vao_webgl2: MutNullableDom<WebGLVertexArrayObject>,
textures: Textures,
+ #[no_trace]
api_type: GlType,
}
@@ -4886,7 +4893,9 @@ pub enum TexSource {
#[derive(JSTraceable)]
pub struct WebGLCommandSender {
+ #[no_trace]
sender: WebGLChan,
+ #[no_trace]
waker: Option<Box<dyn EventLoopWaker>>,
}
@@ -4906,8 +4915,10 @@ impl WebGLCommandSender {
#[derive(JSTraceable, MallocSizeOf)]
pub(crate) struct WebGLMessageSender {
+ #[no_trace]
sender: WebGLMsgSender,
#[ignore_malloc_size_of = "traits are cumbersome"]
+ #[no_trace]
waker: Option<Box<dyn EventLoopWaker>>,
}
diff --git a/components/script/dom/webglsampler.rs b/components/script/dom/webglsampler.rs
index 063decffe8f..ec68328fab9 100644
--- a/components/script/dom/webglsampler.rs
+++ b/components/script/dom/webglsampler.rs
@@ -16,6 +16,7 @@ use std::cell::Cell;
#[dom_struct]
pub struct WebGLSampler {
webgl_object: WebGLObject,
+ #[no_trace]
gl_id: WebGLSamplerId,
marked_for_deletion: Cell<bool>,
}
diff --git a/components/script/dom/webglshader.rs b/components/script/dom/webglshader.rs
index 3f5f6c1cf43..ad61db47a5a 100644
--- a/components/script/dom/webglshader.rs
+++ b/components/script/dom/webglshader.rs
@@ -33,6 +33,7 @@ pub enum ShaderCompilationStatus {
#[dom_struct]
pub struct WebGLShader {
webgl_object: WebGLObject,
+ #[no_trace]
id: WebGLShaderId,
gl_type: u32,
source: DomRefCell<DOMString>,
diff --git a/components/script/dom/webglsync.rs b/components/script/dom/webglsync.rs
index a6288f69c1e..c26eb839eed 100644
--- a/components/script/dom/webglsync.rs
+++ b/components/script/dom/webglsync.rs
@@ -17,6 +17,7 @@ use std::cell::Cell;
#[dom_struct]
pub struct WebGLSync {
webgl_object: WebGLObject,
+ #[no_trace]
sync_id: WebGLSyncId,
marked_for_deletion: Cell<bool>,
client_wait_status: Cell<Option<u32>>,
diff --git a/components/script/dom/webgltexture.rs b/components/script/dom/webgltexture.rs
index ccb005cc393..b4562e36e76 100644
--- a/components/script/dom/webgltexture.rs
+++ b/components/script/dom/webgltexture.rs
@@ -48,6 +48,7 @@ jsmanaged_array!(MAX_LEVEL_COUNT * MAX_FACE_COUNT);
#[dom_struct]
pub struct WebGLTexture {
webgl_object: WebGLObject,
+ #[no_trace]
id: WebGLTextureId,
/// The target to which this texture was bound the first time
target: Cell<Option<u32>>,
@@ -532,7 +533,9 @@ pub struct ImageInfo {
width: u32,
height: u32,
depth: u32,
+ #[no_trace]
internal_format: TexFormat,
+ #[no_trace]
data_type: Option<TexDataType>,
}
@@ -581,6 +584,7 @@ pub enum TexCompressionValidation {
#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf)]
pub struct TexCompression {
+ #[no_trace]
pub format: TexFormat,
pub bytes_per_block: u8,
pub block_width: u8,
diff --git a/components/script/dom/webgluniformlocation.rs b/components/script/dom/webgluniformlocation.rs
index 153b2e651ba..a579743399b 100644
--- a/components/script/dom/webgluniformlocation.rs
+++ b/components/script/dom/webgluniformlocation.rs
@@ -14,7 +14,9 @@ use dom_struct::dom_struct;
pub struct WebGLUniformLocation {
reflector_: Reflector,
id: i32,
+ #[no_trace]
context_id: WebGLContextId,
+ #[no_trace]
program_id: WebGLProgramId,
link_generation: u64,
size: Option<i32>,
diff --git a/components/script/dom/websocket.rs b/components/script/dom/websocket.rs
index 5b5815f90c3..75b30001d21 100644
--- a/components/script/dom/websocket.rs
+++ b/components/script/dom/websocket.rs
@@ -101,11 +101,13 @@ fn fail_the_websocket_connection(
#[dom_struct]
pub struct WebSocket {
eventtarget: EventTarget,
+ #[no_trace]
url: ServoUrl,
ready_state: Cell<WebSocketRequestState>,
buffered_amount: Cell<u64>,
clearing_buffer: Cell<bool>, //Flag to tell if there is a running thread to clear buffered_amount
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
sender: IpcSender<WebSocketDomAction>,
binary_type: Cell<BinaryType>,
protocol: DomRefCell<String>, //Subprotocol selected by server
diff --git a/components/script/dom/window.rs b/components/script/dom/window.rs
index 705d976c97e..65dc4118583 100644
--- a/components/script/dom/window.rs
+++ b/components/script/dom/window.rs
@@ -157,6 +157,8 @@ use url::Position;
use webrender_api::units::{DeviceIntPoint, DeviceIntSize, LayoutPixel};
use webrender_api::{DocumentId, ExternalScrollId};
+use super::bindings::trace::HashMapTracedValues;
+
/// Current state of the window object
#[derive(Clone, Copy, Debug, JSTraceable, MallocSizeOf, PartialEq)]
enum WindowState {
@@ -199,8 +201,10 @@ pub struct Window {
task_manager: TaskManager,
navigator: MutNullableDom<Navigator>,
#[ignore_malloc_size_of = "Arc"]
+ #[no_trace]
image_cache: Arc<dyn ImageCache>,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
image_cache_chan: Sender<ImageCacheMsg>,
window_proxy: MutNullableDom<WindowProxy>,
document: MutNullableDom<Document>,
@@ -217,14 +221,18 @@ pub struct Window {
/// For sending timeline markers. Will be ignored if
/// no devtools server
+ #[no_trace]
devtools_markers: DomRefCell<HashSet<TimelineMarkerType>>,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
devtools_marker_sender: DomRefCell<Option<IpcSender<Option<TimelineMarker>>>>,
/// Pending resize event, if any.
+ #[no_trace]
resize_event: Cell<Option<(WindowSizeData, WindowSizeType)>>,
/// Parent id associated with this page, if any.
+ #[no_trace]
parent_info: Option<PipelineId>,
/// Global static data related to the DOM.
@@ -239,23 +247,28 @@ pub struct Window {
/// This channel shouldn't be accessed directly, but through `Window::layout_chan()`,
/// which returns `None` if there's no layout thread anymore.
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
layout_chan: Sender<Msg>,
/// A handle to perform RPC calls into the layout, quickly.
#[ignore_malloc_size_of = "trait objects are hard"]
+ #[no_trace]
layout_rpc: Box<dyn LayoutRPC + Send + 'static>,
/// The current size of the window, in pixels.
+ #[no_trace]
window_size: Cell<WindowSizeData>,
/// A handle for communicating messages to the bluetooth thread.
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
bluetooth_thread: IpcSender<BluetoothRequest>,
bluetooth_extra_permission_data: BluetoothExtraPermissionData,
/// An enlarged rectangle around the page contents visible in the viewport, used
/// to prevent creating display list items for content that is far away from the viewport.
+ #[no_trace]
page_clip_rect: Cell<UntypedRect<Au>>,
/// Flag to suppress reflows. The first reflow will come either with
@@ -268,16 +281,19 @@ pub struct Window {
/// A channel for communicating results of async scripts back to the webdriver server
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
webdriver_script_chan: DomRefCell<Option<IpcSender<WebDriverJSResult>>>,
/// The current state of the window object
current_state: Cell<WindowState>,
+ #[no_trace]
current_viewport: Cell<UntypedRect<Au>>,
error_reporter: CSSErrorReporter,
/// A list of scroll offsets for each scrollable element.
+ #[no_trace]
scroll_offsets: DomRefCell<HashMap<OpaqueNode, Vector2D<f32, LayoutPixel>>>,
/// All the MediaQueryLists we need to update
@@ -287,16 +303,18 @@ pub struct Window {
/// A handle for communicating messages to the WebGL thread, if available.
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
webgl_chan: Option<WebGLChan>,
#[ignore_malloc_size_of = "defined in webxr"]
+ #[no_trace]
webxr_registry: webxr_api::Registry,
/// All of the elements that have an outstanding image request that was
/// initiated by layout during a reflow. They are stored in the script thread
/// to ensure that the element can be marked dirty when the image data becomes
/// available at some point in the future.
- pending_layout_images: DomRefCell<HashMap<PendingImageId, Vec<Dom<Node>>>>,
+ pending_layout_images: DomRefCell<HashMapTracedValues<PendingImageId, Vec<Dom<Node>>>>,
/// Directory to store unminified scripts for this window if unminify-js
/// opt is enabled.
@@ -311,6 +329,7 @@ pub struct Window {
paint_worklet: MutNullableDom<Worklet>,
/// The Webrender Document id associated with this window.
#[ignore_malloc_size_of = "defined in webrender_api"]
+ #[no_trace]
webrender_document: DocumentId,
/// Flag to identify whether mutation observers are present(true)/absent(false)
@@ -318,6 +337,7 @@ pub struct Window {
/// Webrender API Sender
#[ignore_malloc_size_of = "Wraps an IpcSender"]
+ #[no_trace]
webrender_api_sender: WebrenderIpcSender,
/// Indicate whether a SetDocumentStatus message has been sent after a reflow is complete.
@@ -348,10 +368,12 @@ pub struct Window {
/// Window's GL context from application
#[ignore_malloc_size_of = "defined in script_thread"]
+ #[no_trace]
player_context: WindowGLContext,
/// A mechanism to force the compositor to process events.
#[ignore_malloc_size_of = "traits are cumbersome"]
+ #[no_trace]
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
visible: Cell<bool>,
@@ -1469,6 +1491,7 @@ impl WindowMethods for Window {
// Step 4.
#[derive(JSTraceable, MallocSizeOf)]
struct WindowNamedGetter {
+ #[no_trace]
name: Atom,
}
impl CollectionFilter for WindowNamedGetter {
@@ -1509,7 +1532,7 @@ impl WindowMethods for Window {
let document = self.Document();
let name_map = document.name_map();
- for (name, elements) in &*name_map {
+ for (name, elements) in &(*name_map).0 {
if name.is_empty() {
continue;
}
@@ -1521,7 +1544,7 @@ impl WindowMethods for Window {
}
}
let id_map = document.id_map();
- for (id, elements) in &*id_map {
+ for (id, elements) in &(*id_map).0 {
if id.is_empty() {
continue;
}
@@ -2666,7 +2689,7 @@ impl Window {
/// Create a new cached instance of the given value.
pub fn cache_layout_value<T>(&self, value: T) -> LayoutValue<T>
where
- T: Copy + JSTraceable + MallocSizeOf,
+ T: Copy + MallocSizeOf,
{
LayoutValue::new(self.layout_marker.borrow().clone(), value)
}
@@ -2676,14 +2699,21 @@ impl Window {
/// value can only be read as long as the associated layout marker that is considered
/// valid. It will automatically become unavailable when the next layout operation is
/// performed.
-#[derive(JSTraceable, MallocSizeOf)]
-pub struct LayoutValue<T: JSTraceable + MallocSizeOf> {
+#[derive(MallocSizeOf)]
+pub struct LayoutValue<T: MallocSizeOf> {
#[ignore_malloc_size_of = "Rc is hard"]
is_valid: Rc<Cell<bool>>,
value: T,
}
-impl<T: Copy + JSTraceable + MallocSizeOf> LayoutValue<T> {
+#[allow(unsafe_code)]
+unsafe impl<T: JSTraceable + MallocSizeOf> JSTraceable for LayoutValue<T> {
+ unsafe fn trace(&self, trc: *mut js::jsapi::JSTracer) {
+ self.value.trace(trc)
+ }
+}
+
+impl<T: Copy + MallocSizeOf> LayoutValue<T> {
fn new(marker: Rc<Cell<bool>>, value: T) -> Self {
LayoutValue {
is_valid: marker,
diff --git a/components/script/dom/windowproxy.rs b/components/script/dom/windowproxy.rs
index 9ae85a30fc6..a2b1cbfe7f4 100644
--- a/components/script/dom/windowproxy.rs
+++ b/components/script/dom/windowproxy.rs
@@ -72,13 +72,16 @@ pub struct WindowProxy {
/// The id of the browsing context.
/// In the case that this is a nested browsing context, this is the id
/// of the container.
+ #[no_trace]
browsing_context_id: BrowsingContextId,
// https://html.spec.whatwg.org/multipage/#opener-browsing-context
+ #[no_trace]
opener: Option<BrowsingContextId>,
/// The frame id of the top-level ancestor browsing context.
/// In the case that this is a top-level window, this is our id.
+ #[no_trace]
top_level_browsing_context_id: TopLevelBrowsingContextId,
/// The name of the browsing context (sometimes, but not always,
@@ -89,6 +92,7 @@ pub struct WindowProxy {
/// We do not try to keep the pipeline id for documents in other threads,
/// as this would require the constellation notifying many script threads about
/// the change, which could be expensive.
+ #[no_trace]
currently_active: Cell<Option<PipelineId>>,
/// Has the browsing context been discarded?
@@ -110,12 +114,15 @@ pub struct WindowProxy {
delaying_load_events_mode: Cell<bool>,
/// The creator browsing context's base url.
+ #[no_trace]
creator_base_url: Option<ServoUrl>,
/// The creator browsing context's url.
+ #[no_trace]
creator_url: Option<ServoUrl>,
/// The creator browsing context's origin.
+ #[no_trace]
creator_origin: Option<ImmutableOrigin>,
}
diff --git a/components/script/dom/worker.rs b/components/script/dom/worker.rs
index fbc0c0cd138..321474f31ee 100644
--- a/components/script/dom/worker.rs
+++ b/components/script/dom/worker.rs
@@ -46,6 +46,7 @@ pub type TrustedWorkerAddress = Trusted<Worker>;
pub struct Worker {
eventtarget: EventTarget,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
/// Sender to the Receiver associated with the DedicatedWorkerGlobalScope
/// this Worker created.
sender: Sender<DedicatedWorkerScriptMsg>,
diff --git a/components/script/dom/workerglobalscope.rs b/components/script/dom/workerglobalscope.rs
index 3aaeca56d3b..a41946926db 100644
--- a/components/script/dom/workerglobalscope.rs
+++ b/components/script/dom/workerglobalscope.rs
@@ -97,7 +97,9 @@ pub struct WorkerGlobalScope {
worker_name: DOMString,
worker_type: WorkerType,
+ #[no_trace]
worker_id: WorkerId,
+ #[no_trace]
worker_url: DomRefCell<ServoUrl>,
#[ignore_malloc_size_of = "Arc"]
closing: Arc<AtomicBool>,
@@ -107,11 +109,13 @@ pub struct WorkerGlobalScope {
navigator: MutNullableDom<WorkerNavigator>,
#[ignore_malloc_size_of = "Defined in ipc-channel"]
+ #[no_trace]
/// Optional `IpcSender` for sending the `DevtoolScriptControlMsg`
/// to the server from within the worker
from_devtools_sender: Option<IpcSender<DevtoolScriptControlMsg>>,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
/// This `Receiver` will be ignored later if the corresponding
/// `IpcSender` doesn't exist
from_devtools_receiver: Receiver<DevtoolScriptControlMsg>,
diff --git a/components/script/dom/workerlocation.rs b/components/script/dom/workerlocation.rs
index c3974e3e1ce..cbe7996899c 100644
--- a/components/script/dom/workerlocation.rs
+++ b/components/script/dom/workerlocation.rs
@@ -15,6 +15,7 @@ use servo_url::{ImmutableOrigin, ServoUrl};
#[dom_struct]
pub struct WorkerLocation {
reflector_: Reflector,
+ #[no_trace]
url: ServoUrl,
}
diff --git a/components/script/dom/worklet.rs b/components/script/dom/worklet.rs
index 7455e2a5775..b1f9fc83ebe 100644
--- a/components/script/dom/worklet.rs
+++ b/components/script/dom/worklet.rs
@@ -169,7 +169,7 @@ impl WorkletMethods for Worklet {
/// A guid for worklets.
#[derive(Clone, Copy, Debug, Eq, Hash, JSTraceable, PartialEq)]
-pub struct WorkletId(Uuid);
+pub struct WorkletId(#[no_trace] Uuid);
malloc_size_of_is_0!(WorkletId);
@@ -251,12 +251,18 @@ impl PendingTasksStruct {
#[derive(Clone, JSTraceable)]
pub struct WorkletThreadPool {
// Channels to send data messages to the three roles.
+ #[no_trace]
primary_sender: Sender<WorkletData>,
+ #[no_trace]
hot_backup_sender: Sender<WorkletData>,
+ #[no_trace]
cold_backup_sender: Sender<WorkletData>,
// Channels to send control messages to the three threads.
+ #[no_trace]
control_sender_0: Sender<WorkletControl>,
+ #[no_trace]
control_sender_1: Sender<WorkletControl>,
+ #[no_trace]
control_sender_2: Sender<WorkletControl>,
}
@@ -746,6 +752,7 @@ impl WorkletThread {
pub struct WorkletExecutor {
worklet_id: WorkletId,
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
primary_sender: Sender<WorkletData>,
}
diff --git a/components/script/dom/workletglobalscope.rs b/components/script/dom/workletglobalscope.rs
index 96270b8fab8..888a2058bc3 100644
--- a/components/script/dom/workletglobalscope.rs
+++ b/components/script/dom/workletglobalscope.rs
@@ -41,9 +41,11 @@ pub struct WorkletGlobalScope {
/// The global for this worklet.
globalscope: GlobalScope,
/// The base URL for this worklet.
+ #[no_trace]
base_url: ServoUrl,
/// Sender back to the script thread
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
to_script_thread_sender: Sender<MainThreadScriptMsg>,
/// Worklet task executor
executor: WorkletExecutor,
diff --git a/components/script/dom/xmlhttprequest.rs b/components/script/dom/xmlhttprequest.rs
index 4f901a13b3b..669edfb1c71 100644
--- a/components/script/dom/xmlhttprequest.rs
+++ b/components/script/dom/xmlhttprequest.rs
@@ -141,16 +141,22 @@ pub struct XMLHttpRequest {
#[ignore_malloc_size_of = "Defined in rust-mozjs"]
response_json: Heap<JSVal>,
#[ignore_malloc_size_of = "Defined in hyper"]
+ #[no_trace]
response_headers: DomRefCell<HeaderMap>,
#[ignore_malloc_size_of = "Defined in hyper"]
+ #[no_trace]
override_mime_type: DomRefCell<Option<Mime>>,
+ #[no_trace]
override_charset: DomRefCell<Option<&'static Encoding>>,
// Associated concepts
#[ignore_malloc_size_of = "Defined in hyper"]
+ #[no_trace]
request_method: DomRefCell<Method>,
+ #[no_trace]
request_url: DomRefCell<Option<ServoUrl>>,
#[ignore_malloc_size_of = "Defined in hyper"]
+ #[no_trace]
request_headers: DomRefCell<HeaderMap>,
request_body_len: Cell<usize>,
sync: Cell<bool>,
@@ -162,7 +168,9 @@ pub struct XMLHttpRequest {
fetch_time: Cell<i64>,
generation_id: Cell<GenerationId>,
response_status: Cell<Result<(), ()>>,
+ #[no_trace]
referrer: Referrer,
+ #[no_trace]
referrer_policy: Option<ReferrerPolicy>,
canceller: DomRefCell<FetchCanceller>,
}
diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs
index 5086626e256..6274ca78387 100644
--- a/components/script/dom/xrframe.rs
+++ b/components/script/dom/xrframe.rs
@@ -28,6 +28,7 @@ pub struct XRFrame {
reflector_: Reflector,
session: Dom<XRSession>,
#[ignore_malloc_size_of = "defined in webxr_api"]
+ #[no_trace]
data: Frame,
active: Cell<bool>,
animation_frame: Cell<bool>,
diff --git a/components/script/dom/xrhittestresult.rs b/components/script/dom/xrhittestresult.rs
index 9c7c36a24ef..dd35043e187 100644
--- a/components/script/dom/xrhittestresult.rs
+++ b/components/script/dom/xrhittestresult.rs
@@ -16,6 +16,7 @@ use webxr_api::HitTestResult;
pub struct XRHitTestResult {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webxr"]
+ #[no_trace]
result: HitTestResult,
frame: Dom<XRFrame>,
}
diff --git a/components/script/dom/xrhittestsource.rs b/components/script/dom/xrhittestsource.rs
index a665a9f1b71..913193cfae3 100644
--- a/components/script/dom/xrhittestsource.rs
+++ b/components/script/dom/xrhittestsource.rs
@@ -14,6 +14,7 @@ use webxr_api::HitTestId;
pub struct XRHitTestSource {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webxr"]
+ #[no_trace]
id: HitTestId,
session: Dom<XRSession>,
}
diff --git a/components/script/dom/xrinputsource.rs b/components/script/dom/xrinputsource.rs
index 592ced2f10d..8b3f3f793e4 100644
--- a/components/script/dom/xrinputsource.rs
+++ b/components/script/dom/xrinputsource.rs
@@ -24,6 +24,7 @@ pub struct XRInputSource {
reflector: Reflector,
session: Dom<XRSession>,
#[ignore_malloc_size_of = "Defined in rust-webxr"]
+ #[no_trace]
info: InputSource,
target_ray_space: MutNullableDom<XRSpace>,
grip_space: MutNullableDom<XRSpace>,
diff --git a/components/script/dom/xrjointspace.rs b/components/script/dom/xrjointspace.rs
index 4b31b0bc6a2..57b0b88f761 100644
--- a/components/script/dom/xrjointspace.rs
+++ b/components/script/dom/xrjointspace.rs
@@ -15,8 +15,10 @@ use webxr_api::{BaseSpace, Frame, InputId, Joint, JointFrame, Space};
pub struct XRJointSpace {
xrspace: XRSpace,
#[ignore_malloc_size_of = "defined in rust-webxr"]
+ #[no_trace]
input: InputId,
#[ignore_malloc_size_of = "defined in rust-webxr"]
+ #[no_trace]
joint: Joint,
}
diff --git a/components/script/dom/xrlayer.rs b/components/script/dom/xrlayer.rs
index 7328609d89f..7319eb482dd 100644
--- a/components/script/dom/xrlayer.rs
+++ b/components/script/dom/xrlayer.rs
@@ -21,6 +21,7 @@ pub struct XRLayer {
/// If none, the session is inline (the composition disabled flag is true)
/// and this is a XRWebGLLayer.
#[ignore_malloc_size_of = "Layer ids don't heap-allocate"]
+ #[no_trace]
layer_id: Option<LayerId>,
}
diff --git a/components/script/dom/xrray.rs b/components/script/dom/xrray.rs
index f39813a4ddc..1847e985362 100644
--- a/components/script/dom/xrray.rs
+++ b/components/script/dom/xrray.rs
@@ -24,6 +24,7 @@ use webxr_api::{ApiSpace, Ray};
pub struct XRRay {
reflector_: Reflector,
#[ignore_malloc_size_of = "defined in webxr"]
+ #[no_trace]
ray: Ray<ApiSpace>,
#[ignore_malloc_size_of = "defined in mozjs"]
matrix: Heap<*mut JSObject>,
diff --git a/components/script/dom/xrrigidtransform.rs b/components/script/dom/xrrigidtransform.rs
index 74f5e348137..1ee7f4304ea 100644
--- a/components/script/dom/xrrigidtransform.rs
+++ b/components/script/dom/xrrigidtransform.rs
@@ -27,6 +27,7 @@ pub struct XRRigidTransform {
position: MutNullableDom<DOMPointReadOnly>,
orientation: MutNullableDom<DOMPointReadOnly>,
#[ignore_malloc_size_of = "defined in euclid"]
+ #[no_trace]
transform: ApiRigidTransform,
inverse: MutNullableDom<XRRigidTransform>,
#[ignore_malloc_size_of = "defined in mozjs"]
diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs
index 73f2bc4ce88..0afa821211f 100644
--- a/components/script/dom/xrsession.rs
+++ b/components/script/dom/xrsession.rs
@@ -43,7 +43,6 @@ use ipc_channel::router::ROUTER;
use metrics::ToMs;
use profile_traits::ipc;
use std::cell::Cell;
-use std::collections::HashMap;
use std::f64::consts::{FRAC_PI_2, PI};
use std::mem;
use std::rc::Rc;
@@ -54,6 +53,8 @@ use webxr_api::{
View, Viewer, Visibility,
};
+use super::bindings::trace::HashMapTracedValues;
+
#[dom_struct]
pub struct XRSession {
eventtarget: EventTarget,
@@ -62,11 +63,13 @@ pub struct XRSession {
visibility_state: Cell<XRVisibilityState>,
viewer_space: MutNullableDom<XRSpace>,
#[ignore_malloc_size_of = "defined in webxr"]
+ #[no_trace]
session: DomRefCell<Session>,
frame_requested: Cell<bool>,
pending_render_state: MutNullableDom<XRRenderState>,
active_render_state: MutDom<XRRenderState>,
/// Cached projection matrix for inline sessions
+ #[no_trace]
inline_projection_matrix: DomRefCell<Transform3D<f32, Viewer, Display>>,
next_raf_id: Cell<i32>,
@@ -81,9 +84,10 @@ pub struct XRSession {
/// https://immersive-web.github.io/webxr/#ended
ended: Cell<bool>,
#[ignore_malloc_size_of = "defined in webxr"]
+ #[no_trace]
next_hit_test_id: Cell<HitTestId>,
#[ignore_malloc_size_of = "defined in webxr"]
- pending_hit_test_promises: DomRefCell<HashMap<HitTestId, Rc<Promise>>>,
+ pending_hit_test_promises: DomRefCell<HashMapTracedValues<HitTestId, Rc<Promise>>>,
/// Opaque framebuffers need to know the session is "outside of a requestAnimationFrame"
/// https://immersive-web.github.io/webxr/#opaque-framebuffer
outside_raf: Cell<bool>,
@@ -115,7 +119,7 @@ impl XRSession {
end_promises: DomRefCell::new(vec![]),
ended: Cell::new(false),
next_hit_test_id: Cell::new(HitTestId(0)),
- pending_hit_test_promises: DomRefCell::new(HashMap::new()),
+ pending_hit_test_promises: DomRefCell::new(HashMapTracedValues::new()),
outside_raf: Cell::new(true),
}
}
diff --git a/components/script/dom/xrsystem.rs b/components/script/dom/xrsystem.rs
index 15e4f9e65f4..907aa2935d1 100644
--- a/components/script/dom/xrsystem.rs
+++ b/components/script/dom/xrsystem.rs
@@ -40,6 +40,7 @@ pub struct XRSystem {
active_immersive_session: MutNullableDom<XRSession>,
active_inline_sessions: DomRefCell<Vec<Dom<XRSession>>>,
test: MutNullableDom<XRTest>,
+ #[no_trace]
pipeline: PipelineId,
}
diff --git a/components/script/dom/xrview.rs b/components/script/dom/xrview.rs
index b849b1d03ba..ec3edde82e0 100644
--- a/components/script/dom/xrview.rs
+++ b/components/script/dom/xrview.rs
@@ -25,6 +25,7 @@ pub struct XRView {
#[ignore_malloc_size_of = "mozjs"]
proj: Heap<*mut JSObject>,
#[ignore_malloc_size_of = "defined in rust-webxr"]
+ #[no_trace]
view: View<ApiSpace>,
transform: Dom<XRRigidTransform>,
}
diff --git a/components/script/dom/xrviewport.rs b/components/script/dom/xrviewport.rs
index 30872bae0c4..968cb573264 100644
--- a/components/script/dom/xrviewport.rs
+++ b/components/script/dom/xrviewport.rs
@@ -13,6 +13,7 @@ use webxr_api::Viewport;
#[dom_struct]
pub struct XRViewport {
reflector_: Reflector,
+ #[no_trace]
viewport: Rect<i32, Viewport>,
}
diff --git a/components/script/dom/xrwebglsubimage.rs b/components/script/dom/xrwebglsubimage.rs
index 0813bd85d9e..d9d5420dfe3 100644
--- a/components/script/dom/xrwebglsubimage.rs
+++ b/components/script/dom/xrwebglsubimage.rs
@@ -17,6 +17,7 @@ pub struct XRWebGLSubImage {
color_texture: Dom<WebGLTexture>,
depth_stencil_texture: Option<Dom<WebGLTexture>>,
image_index: Option<u32>,
+ #[no_trace]
size: Size2D<u32, Viewport>,
}
diff --git a/components/script/fetch.rs b/components/script/fetch.rs
index 9de88ba0277..5e88d46dffb 100644
--- a/components/script/fetch.rs
+++ b/components/script/fetch.rs
@@ -52,6 +52,7 @@ struct FetchContext {
#[derive(Default, JSTraceable, MallocSizeOf)]
pub struct FetchCanceller {
#[ignore_malloc_size_of = "channels are hard"]
+ #[no_trace]
cancel_chan: Option<ipc::IpcSender<()>>,
}
diff --git a/components/script/lib.rs b/components/script/lib.rs
index 66c878dbbde..3d46f4f797c 100644
--- a/components/script/lib.rs
+++ b/components/script/lib.rs
@@ -8,10 +8,17 @@
#![feature(register_tool)]
#![deny(unsafe_code)]
#![doc = "The script crate contains all matters DOM."]
-#![cfg_attr(not(feature = "unrooted_must_root_lint"), allow(unknown_lints))]
+#![cfg_attr(
+ not(any(
+ feature = "unrooted_must_root_lint",
+ feature = "trace_in_no_trace_lint"
+ )),
+ allow(unknown_lints)
+)]
#![allow(deprecated)] // FIXME: Can we make `allow` only apply to the `plugin` crate attribute?
#![plugin(script_plugins)]
#![register_tool(unrooted_must_root_lint)]
+#![register_tool(trace_in_no_trace_lint)]
#[macro_use]
extern crate bitflags;
diff --git a/components/script/microtask.rs b/components/script/microtask.rs
index 10322bb2fef..4a810fd0cfd 100644
--- a/components/script/microtask.rs
+++ b/components/script/microtask.rs
@@ -53,6 +53,7 @@ pub trait MicrotaskRunnable {
pub struct EnqueuedPromiseCallback {
#[ignore_malloc_size_of = "Rc has unclear ownership"]
pub callback: Rc<PromiseJobCallback>,
+ #[no_trace]
pub pipeline: PipelineId,
pub is_user_interacting: bool,
}
@@ -63,6 +64,7 @@ pub struct EnqueuedPromiseCallback {
pub struct UserMicrotask {
#[ignore_malloc_size_of = "Rc has unclear ownership"]
pub callback: Rc<VoidFunction>,
+ #[no_trace]
pub pipeline: PipelineId,
}
diff --git a/components/script/script_module.rs b/components/script/script_module.rs
index 9ba8dd523a0..01fe01e3472 100644
--- a/components/script/script_module.rs
+++ b/components/script/script_module.rs
@@ -145,7 +145,7 @@ impl ModuleScript {
#[derive(Clone, Debug, Eq, Hash, JSTraceable, PartialEq)]
pub enum ModuleIdentity {
ScriptId(ScriptId),
- ModuleUrl(ServoUrl),
+ ModuleUrl(#[no_trace] ServoUrl),
}
impl ModuleIdentity {
@@ -165,6 +165,7 @@ impl ModuleIdentity {
#[derive(JSTraceable)]
pub struct ModuleTree {
+ #[no_trace]
url: ServoUrl,
text: DomRefCell<Rc<DOMString>>,
record: DomRefCell<Option<ModuleObject>>,
@@ -178,11 +179,15 @@ pub struct ModuleTree {
// (https://infra.spec.whatwg.org/#ordered-map), however we can usually get away with using
// stdlib maps and sets because we rarely iterate over them.
parent_identities: DomRefCell<IndexSet<ModuleIdentity>>,
+ #[no_trace]
descendant_urls: DomRefCell<IndexSet<ServoUrl>>,
// A set to memoize which descendants are under fetching
+ #[no_trace]
incomplete_fetch_urls: DomRefCell<IndexSet<ServoUrl>>,
+ #[no_trace]
visited_urls: DomRefCell<HashSet<ServoUrl>>,
rethrow_error: DomRefCell<Option<RethrowError>>,
+ #[no_trace]
network_error: DomRefCell<Option<NetworkError>>,
// A promise for owners to execute when the module tree
// is finished
@@ -324,7 +329,7 @@ impl ModuleTree {
let module_map = global.get_module_map().borrow();
let mut discovered_urls = HashSet::new();
- return ModuleTree::recursive_check_descendants(&self, &module_map, &mut discovered_urls);
+ return ModuleTree::recursive_check_descendants(&self, &module_map.0, &mut discovered_urls);
}
// We just leverage the power of Promise to run the task for `finish` the owner.
@@ -926,7 +931,7 @@ impl ModuleOwner {
let network_error = module_tree.get_network_error().borrow();
match network_error.as_ref() {
- Some(network_error) => Err(network_error.clone()),
+ Some(network_error) => Err(network_error.clone().into()),
None => match module_identity {
ModuleIdentity::ModuleUrl(script_src) => Ok(ScriptOrigin::external(
Rc::clone(&module_tree.get_text().borrow()),
@@ -1296,11 +1301,15 @@ pub unsafe extern "C" fn host_import_module_dynamically(
#[derive(Clone, JSTraceable, MallocSizeOf)]
/// <https://html.spec.whatwg.org/multipage/#script-fetch-options>
pub struct ScriptFetchOptions {
+ #[no_trace]
pub referrer: Referrer,
pub integrity_metadata: String,
+ #[no_trace]
pub credentials_mode: CredentialsMode,
pub cryptographic_nonce: String,
+ #[no_trace]
pub parser_metadata: ParserMetadata,
+ #[no_trace]
pub referrer_policy: Option<ReferrerPolicy>,
}
diff --git a/components/script/script_thread.rs b/components/script/script_thread.rs
index 96ea03881d4..e3051a0f8c2 100644
--- a/components/script/script_thread.rs
+++ b/components/script/script_thread.rs
@@ -34,7 +34,7 @@ use crate::dom::bindings::reflector::DomObject;
use crate::dom::bindings::root::ThreadLocalStackRoots;
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom, RootCollection};
use crate::dom::bindings::str::DOMString;
-use crate::dom::bindings::trace::JSTraceable;
+use crate::dom::bindings::trace::{HashMapTracedValues, JSTraceable};
use crate::dom::customelementregistry::{
CallbackReaction, CustomElementDefinition, CustomElementReactionStack,
};
@@ -185,26 +185,36 @@ pub unsafe fn trace_thread(tr: *mut JSTracer) {
#[derive(JSTraceable)]
struct InProgressLoad {
/// The pipeline which requested this load.
+ #[no_trace]
pipeline_id: PipelineId,
/// The browsing context being loaded into.
+ #[no_trace]
browsing_context_id: BrowsingContextId,
/// The top level ancestor browsing context.
+ #[no_trace]
top_level_browsing_context_id: TopLevelBrowsingContextId,
/// The parent pipeline and frame type associated with this load, if any.
+ #[no_trace]
parent_info: Option<PipelineId>,
/// The opener, if this is an auxiliary.
+ #[no_trace]
opener: Option<BrowsingContextId>,
/// The current window size associated with this pipeline.
+ #[no_trace]
window_size: WindowSizeData,
/// Channel to the layout thread associated with this pipeline.
+ #[no_trace]
layout_chan: Sender<message::Msg>,
/// The activity level of the document (inactive, active or fully active).
+ #[no_trace]
activity: DocumentActivity,
/// Window is visible.
is_visible: bool,
/// The requested URL of the load.
+ #[no_trace]
url: ServoUrl,
/// The origin for the document
+ #[no_trace]
origin: MutableOrigin,
/// Timestamp reporting the time when the browser started this load.
navigation_start: u64,
@@ -398,7 +408,7 @@ impl ScriptPort for Receiver<(TrustedServiceWorkerAddress, CommonScriptMsg)> {
/// Encapsulates internal communication of shared messages within the script thread.
#[derive(JSTraceable)]
-pub struct SendableMainThreadScriptChan(pub Sender<CommonScriptMsg>);
+pub struct SendableMainThreadScriptChan(#[no_trace] pub Sender<CommonScriptMsg>);
impl ScriptChan for SendableMainThreadScriptChan {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
@@ -412,7 +422,7 @@ impl ScriptChan for SendableMainThreadScriptChan {
/// Encapsulates internal communication of main thread messages within the script thread.
#[derive(JSTraceable)]
-pub struct MainThreadScriptChan(pub Sender<MainThreadScriptMsg>);
+pub struct MainThreadScriptChan(#[no_trace] pub Sender<MainThreadScriptMsg>);
impl ScriptChan for MainThreadScriptChan {
fn send(&self, msg: CommonScriptMsg) -> Result<(), ()> {
@@ -436,13 +446,13 @@ impl OpaqueSender<CommonScriptMsg> for Sender<MainThreadScriptMsg> {
#[derive(JSTraceable)]
#[unrooted_must_root_lint::must_root]
pub struct Documents {
- map: HashMap<PipelineId, Dom<Document>>,
+ map: HashMapTracedValues<PipelineId, Dom<Document>>,
}
impl Documents {
pub fn new() -> Documents {
Documents {
- map: HashMap::new(),
+ map: HashMapTracedValues::new(),
}
}
@@ -522,17 +532,20 @@ pub struct ScriptThread {
documents: DomRefCell<Documents>,
/// The window proxies known by this thread
/// TODO: this map grows, but never shrinks. Issue #15258.
- window_proxies: DomRefCell<HashMap<BrowsingContextId, Dom<WindowProxy>>>,
+ window_proxies: DomRefCell<HashMapTracedValues<BrowsingContextId, Dom<WindowProxy>>>,
/// A list of data pertaining to loads that have not yet received a network response
incomplete_loads: DomRefCell<Vec<InProgressLoad>>,
/// A vector containing parser contexts which have not yet been fully processed
incomplete_parser_contexts: IncompleteParserContexts,
/// Image cache for this script thread.
+ #[no_trace]
image_cache: Arc<dyn ImageCache>,
/// A handle to the resource thread. This is an `Arc` to avoid running out of file descriptors if
/// there are many iframes.
+ #[no_trace]
resource_threads: ResourceThreads,
/// A handle to the bluetooth thread.
+ #[no_trace]
bluetooth_thread: IpcSender<BluetoothRequest>,
/// A queue of tasks to be executed in this script-thread.
@@ -551,12 +564,15 @@ pub struct ScriptThread {
dom_manipulation_task_sender: Box<dyn ScriptChan>,
+ #[no_trace]
media_element_task_sender: Sender<MainThreadScriptMsg>,
+ #[no_trace]
user_interaction_task_sender: Sender<MainThreadScriptMsg>,
networking_task_sender: Box<dyn ScriptChan>,
+ #[no_trace]
history_traversal_task_sender: Sender<MainThreadScriptMsg>,
file_reading_task_sender: Box<dyn ScriptChan>,
@@ -570,34 +586,45 @@ pub struct ScriptThread {
remote_event_task_sender: Box<dyn ScriptChan>,
/// A channel to hand out to threads that need to respond to a message from the script thread.
+ #[no_trace]
control_chan: IpcSender<ConstellationControlMsg>,
/// The port on which the constellation and layout threads can communicate with the
/// script thread.
+ #[no_trace]
control_port: Receiver<ConstellationControlMsg>,
/// For communicating load url messages to the constellation
+ #[no_trace]
script_sender: IpcSender<(PipelineId, ScriptMsg)>,
/// A sender for new layout threads to communicate to the constellation.
+ #[no_trace]
layout_to_constellation_chan: IpcSender<LayoutMsg>,
/// The port on which we receive messages from the image cache
+ #[no_trace]
image_cache_port: Receiver<ImageCacheMsg>,
/// The channel on which the image cache can send messages to ourself.
+ #[no_trace]
image_cache_channel: Sender<ImageCacheMsg>,
/// For providing contact with the time profiler.
+ #[no_trace]
time_profiler_chan: profile_time::ProfilerChan,
/// For providing contact with the memory profiler.
+ #[no_trace]
mem_profiler_chan: profile_mem::ProfilerChan,
/// For providing instructions to an optional devtools server.
+ #[no_trace]
devtools_chan: Option<IpcSender<ScriptToDevtoolsControlMsg>>,
/// For receiving commands from an optional devtools server. Will be ignored if
/// no such server exists.
+ #[no_trace]
devtools_port: Receiver<DevtoolScriptControlMsg>,
+ #[no_trace]
devtools_sender: IpcSender<DevtoolScriptControlMsg>,
/// The JavaScript runtime.
@@ -607,10 +634,13 @@ pub struct ScriptThread {
topmost_mouse_over_target: MutNullableDom<Element>,
/// List of pipelines that have been owned and closed by this script thread.
+ #[no_trace]
closed_pipelines: DomRefCell<HashSet<PipelineId>>,
+ #[no_trace]
scheduler_chan: IpcSender<TimerSchedulerMsg>,
+ #[no_trace]
content_process_shutdown_chan: Sender<()>,
/// <https://html.spec.whatwg.org/multipage/#microtask-queue>
@@ -623,9 +653,11 @@ pub struct ScriptThread {
mutation_observers: DomRefCell<Vec<Dom<MutationObserver>>>,
/// A handle to the WebGL thread
+ #[no_trace]
webgl_chan: Option<WebGLPipeline>,
/// The WebXR device registry
+ #[no_trace]
webxr_registry: webxr_api::Registry,
/// The worklet thread pool
@@ -639,9 +671,11 @@ pub struct ScriptThread {
custom_element_reaction_stack: CustomElementReactionStack,
/// The Webrender Document ID associated with this thread.
+ #[no_trace]
webrender_document: DocumentId,
/// Webrender API sender.
+ #[no_trace]
webrender_api_sender: WebrenderIpcSender,
/// Periodically print out on which events script threads spend their processing time.
@@ -678,9 +712,11 @@ pub struct ScriptThread {
user_agent: Cow<'static, str>,
/// Application window's GL Context for Media player
+ #[no_trace]
player_context: WindowGLContext,
/// A mechanism to force the compositor's event loop to process events.
+ #[no_trace]
event_loop_waker: Option<Box<dyn EventLoopWaker>>,
/// A set of all nodes ever created in this script thread
@@ -690,9 +726,11 @@ pub struct ScriptThread {
is_user_interacting: Cell<bool>,
/// Identity manager for WebGPU resources
+ #[no_trace]
gpu_id_hub: Arc<Mutex<Identities>>,
/// Receiver to receive commands from optional WebGPU server.
+ #[no_trace]
webgpu_port: RefCell<Option<Receiver<WebGPUMsg>>>,
// Secure context
@@ -1297,7 +1335,7 @@ impl ScriptThread {
ScriptThread {
documents: DomRefCell::new(Documents::new()),
- window_proxies: DomRefCell::new(HashMap::new()),
+ window_proxies: DomRefCell::new(HashMapTracedValues::new()),
incomplete_loads: DomRefCell::new(vec![]),
incomplete_parser_contexts: IncompleteParserContexts(RefCell::new(vec![])),
diff --git a/components/script/task_source/dom_manipulation.rs b/components/script/task_source/dom_manipulation.rs
index d9dcdfb2472..68316b79fe3 100644
--- a/components/script/task_source/dom_manipulation.rs
+++ b/components/script/task_source/dom_manipulation.rs
@@ -16,7 +16,7 @@ use std::fmt;
use std::result::Result;
#[derive(JSTraceable)]
-pub struct DOMManipulationTaskSource(pub Box<dyn ScriptChan + Send>, pub PipelineId);
+pub struct DOMManipulationTaskSource(pub Box<dyn ScriptChan + Send>, #[no_trace] pub PipelineId);
impl Clone for DOMManipulationTaskSource {
fn clone(&self) -> DOMManipulationTaskSource {
diff --git a/components/script/task_source/file_reading.rs b/components/script/task_source/file_reading.rs
index 20b49a239b4..646778ffea5 100644
--- a/components/script/task_source/file_reading.rs
+++ b/components/script/task_source/file_reading.rs
@@ -10,7 +10,10 @@ use crate::task_source::{TaskSource, TaskSourceName};
use msg::constellation_msg::PipelineId;
#[derive(JSTraceable)]
-pub struct FileReadingTaskSource(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
+pub struct FileReadingTaskSource(
+ pub Box<dyn ScriptChan + Send + 'static>,
+ #[no_trace] pub PipelineId,
+);
impl Clone for FileReadingTaskSource {
fn clone(&self) -> FileReadingTaskSource {
diff --git a/components/script/task_source/history_traversal.rs b/components/script/task_source/history_traversal.rs
index 0fdb428b845..ecabbddfa55 100644
--- a/components/script/task_source/history_traversal.rs
+++ b/components/script/task_source/history_traversal.rs
@@ -10,7 +10,10 @@ use crossbeam_channel::Sender;
use msg::constellation_msg::PipelineId;
#[derive(Clone, JSTraceable)]
-pub struct HistoryTraversalTaskSource(pub Sender<MainThreadScriptMsg>, pub PipelineId);
+pub struct HistoryTraversalTaskSource(
+ #[no_trace] pub Sender<MainThreadScriptMsg>,
+ #[no_trace] pub PipelineId,
+);
impl TaskSource for HistoryTraversalTaskSource {
const NAME: TaskSourceName = TaskSourceName::HistoryTraversal;
diff --git a/components/script/task_source/media_element.rs b/components/script/task_source/media_element.rs
index c0a902b373b..16922a0ec87 100644
--- a/components/script/task_source/media_element.rs
+++ b/components/script/task_source/media_element.rs
@@ -18,7 +18,10 @@ use std::fmt;
use std::result::Result;
#[derive(Clone, JSTraceable)]
-pub struct MediaElementTaskSource(pub Sender<MainThreadScriptMsg>, pub PipelineId);
+pub struct MediaElementTaskSource(
+ #[no_trace] pub Sender<MainThreadScriptMsg>,
+ #[no_trace] pub PipelineId,
+);
impl fmt::Debug for MediaElementTaskSource {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/components/script/task_source/networking.rs b/components/script/task_source/networking.rs
index 92d04b29220..0193cb22839 100644
--- a/components/script/task_source/networking.rs
+++ b/components/script/task_source/networking.rs
@@ -8,7 +8,10 @@ use crate::task_source::{TaskSource, TaskSourceName};
use msg::constellation_msg::PipelineId;
#[derive(JSTraceable)]
-pub struct NetworkingTaskSource(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
+pub struct NetworkingTaskSource(
+ pub Box<dyn ScriptChan + Send + 'static>,
+ #[no_trace] pub PipelineId,
+);
impl Clone for NetworkingTaskSource {
fn clone(&self) -> NetworkingTaskSource {
diff --git a/components/script/task_source/performance_timeline.rs b/components/script/task_source/performance_timeline.rs
index 1669ac6e689..58e2660e6fd 100644
--- a/components/script/task_source/performance_timeline.rs
+++ b/components/script/task_source/performance_timeline.rs
@@ -16,7 +16,10 @@ use std::fmt;
use std::result::Result;
#[derive(JSTraceable)]
-pub struct PerformanceTimelineTaskSource(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
+pub struct PerformanceTimelineTaskSource(
+ pub Box<dyn ScriptChan + Send + 'static>,
+ #[no_trace] pub PipelineId,
+);
impl Clone for PerformanceTimelineTaskSource {
fn clone(&self) -> PerformanceTimelineTaskSource {
diff --git a/components/script/task_source/port_message.rs b/components/script/task_source/port_message.rs
index e9d1766f521..e21230f8099 100644
--- a/components/script/task_source/port_message.rs
+++ b/components/script/task_source/port_message.rs
@@ -9,7 +9,10 @@ use msg::constellation_msg::PipelineId;
use std::fmt;
#[derive(JSTraceable)]
-pub struct PortMessageQueue(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
+pub struct PortMessageQueue(
+ pub Box<dyn ScriptChan + Send + 'static>,
+ #[no_trace] pub PipelineId,
+);
impl Clone for PortMessageQueue {
fn clone(&self) -> PortMessageQueue {
diff --git a/components/script/task_source/remote_event.rs b/components/script/task_source/remote_event.rs
index a1d54604996..91e132ed719 100644
--- a/components/script/task_source/remote_event.rs
+++ b/components/script/task_source/remote_event.rs
@@ -8,7 +8,10 @@ use crate::task_source::{TaskSource, TaskSourceName};
use msg::constellation_msg::PipelineId;
#[derive(JSTraceable)]
-pub struct RemoteEventTaskSource(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
+pub struct RemoteEventTaskSource(
+ pub Box<dyn ScriptChan + Send + 'static>,
+ #[no_trace] pub PipelineId,
+);
impl Clone for RemoteEventTaskSource {
fn clone(&self) -> RemoteEventTaskSource {
diff --git a/components/script/task_source/timer.rs b/components/script/task_source/timer.rs
index cd134fb12a2..9c4d03bdda5 100644
--- a/components/script/task_source/timer.rs
+++ b/components/script/task_source/timer.rs
@@ -10,7 +10,10 @@ use std::fmt;
#[derive(JSTraceable)]
/// https://html.spec.whatwg.org/multipage/#timer-task-source
-pub struct TimerTaskSource(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
+pub struct TimerTaskSource(
+ pub Box<dyn ScriptChan + Send + 'static>,
+ #[no_trace] pub PipelineId,
+);
impl Clone for TimerTaskSource {
fn clone(&self) -> TimerTaskSource {
diff --git a/components/script/task_source/user_interaction.rs b/components/script/task_source/user_interaction.rs
index bb434ab7026..1f543d88cfd 100644
--- a/components/script/task_source/user_interaction.rs
+++ b/components/script/task_source/user_interaction.rs
@@ -18,7 +18,10 @@ use std::fmt;
use std::result::Result;
#[derive(Clone, JSTraceable)]
-pub struct UserInteractionTaskSource(pub Sender<MainThreadScriptMsg>, pub PipelineId);
+pub struct UserInteractionTaskSource(
+ #[no_trace] pub Sender<MainThreadScriptMsg>,
+ #[no_trace] pub PipelineId,
+);
impl fmt::Debug for UserInteractionTaskSource {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
diff --git a/components/script/task_source/websocket.rs b/components/script/task_source/websocket.rs
index f4e153328b9..843a9632a8a 100644
--- a/components/script/task_source/websocket.rs
+++ b/components/script/task_source/websocket.rs
@@ -8,7 +8,10 @@ use crate::task_source::{TaskSource, TaskSourceName};
use msg::constellation_msg::PipelineId;
#[derive(JSTraceable)]
-pub struct WebsocketTaskSource(pub Box<dyn ScriptChan + Send + 'static>, pub PipelineId);
+pub struct WebsocketTaskSource(
+ pub Box<dyn ScriptChan + Send + 'static>,
+ #[no_trace] pub PipelineId,
+);
impl Clone for WebsocketTaskSource {
fn clone(&self) -> WebsocketTaskSource {
diff --git a/components/script/timers.rs b/components/script/timers.rs
index 5078bc1e788..d337f197061 100644
--- a/components/script/timers.rs
+++ b/components/script/timers.rs
@@ -36,20 +36,24 @@ pub struct OneshotTimerHandle(i32);
pub struct OneshotTimers {
js_timers: JsTimers,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
/// The sender, to be cloned for each timer,
/// on which the timer scheduler in the constellation can send an event
/// when the timer is due.
timer_event_chan: DomRefCell<Option<IpcSender<TimerEvent>>>,
#[ignore_malloc_size_of = "Defined in std"]
+ #[no_trace]
/// The sender to the timer scheduler in the constellation.
scheduler_chan: IpcSender<TimerSchedulerMsg>,
next_timer_handle: Cell<OneshotTimerHandle>,
timers: DomRefCell<Vec<OneshotTimer>>,
+ #[no_trace]
suspended_since: Cell<Option<MsDuration>>,
/// Initially 0, increased whenever the associated document is reactivated
/// by the amount of ms the document was inactive. The current time can be
/// offset back by this amount for a coherent time across document
/// activations.
+ #[no_trace]
suspension_offset: Cell<MsDuration>,
/// Calls to `fire_timer` with a different argument than this get ignored.
/// They were previously scheduled and got invalidated when
@@ -57,14 +61,17 @@ pub struct OneshotTimers {
/// - the timer it was scheduled for got canceled or
/// - a timer was added with an earlier callback time. In this case the
/// original timer is rescheduled when it is the next one to get called.
+ #[no_trace]
expected_event_id: Cell<TimerEventId>,
}
#[derive(DenyPublicFields, JSTraceable, MallocSizeOf)]
struct OneshotTimer {
handle: OneshotTimerHandle,
+ #[no_trace]
source: TimerSource,
callback: OneshotTimerCallback,
+ #[no_trace]
scheduled_for: MsDuration,
}
@@ -355,6 +362,7 @@ pub struct JsTimers {
/// The nesting level of the currently executing timer task or 0.
nesting_level: Cell<u32>,
/// Used to introduce a minimum delay in event intervals
+ #[no_trace]
min_duration: Cell<Option<MsDuration>>,
}
@@ -371,10 +379,12 @@ struct JsTimerEntry {
pub struct JsTimerTask {
#[ignore_malloc_size_of = "Because it is non-owning"]
handle: JsTimerHandle,
+ #[no_trace]
source: TimerSource,
callback: InternalTimerCallback,
is_interval: IsInterval,
nesting_level: u32,
+ #[no_trace]
duration: MsDuration,
is_user_interacting: bool,
}
diff --git a/components/script_plugins/Cargo.toml b/components/script_plugins/Cargo.toml
index 8bf9ce325ee..505317eb900 100644
--- a/components/script_plugins/Cargo.toml
+++ b/components/script_plugins/Cargo.toml
@@ -12,3 +12,7 @@ plugin = true
[features]
unrooted_must_root_lint = []
+trace_in_no_trace_lint = []
+
+[package.metadata.rust-analyzer]
+rustc_private=true
diff --git a/components/script_plugins/lib.rs b/components/script_plugins/lib.rs
index a2717dc1e44..8e3de2cecab 100644
--- a/components/script_plugins/lib.rs
+++ b/components/script_plugins/lib.rs
@@ -10,372 +10,50 @@
#![deny(unsafe_code)]
#![feature(plugin)]
#![feature(rustc_private)]
-#![cfg(feature = "unrooted_must_root_lint")]
extern crate rustc_ast;
extern crate rustc_driver;
+extern crate rustc_error_messages;
extern crate rustc_hir;
+extern crate rustc_infer;
extern crate rustc_lint;
extern crate rustc_middle;
extern crate rustc_session;
extern crate rustc_span;
+extern crate rustc_trait_selection;
+extern crate rustc_type_ir;
-use rustc_ast::ast::{AttrKind, Attribute};
+use rustc_ast::Mutability;
use rustc_driver::plugin::Registry;
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit as visit;
-use rustc_hir::{self as hir, ExprKind};
-use rustc_lint::{LateContext, LateLintPass, LintContext, LintPass};
-use rustc_middle::ty;
-use rustc_session::declare_lint;
-use rustc_span::def_id::LocalDefId;
-use rustc_span::source_map;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
+use rustc_hir::PrimTy;
+use rustc_hir::{ImplItemRef, ItemKind, Node, OwnerId, TraitItemRef};
+use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
+use rustc_infer::infer::TyCtxtInferExt;
+use rustc_lint::LateContext;
+use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{self, GenericArg, ParamEnv, Ty, TypeVisitable};
use rustc_span::source_map::{ExpnKind, MacroKind, Span};
-use rustc_span::symbol::sym;
+use rustc_span::symbol::Ident;
use rustc_span::symbol::Symbol;
+use rustc_span::DUMMY_SP;
+use rustc_trait_selection::infer::InferCtxtExt;
+use rustc_type_ir::{FloatTy, IntTy, UintTy};
+
+#[cfg(feature = "unrooted_must_root_lint")]
+mod unrooted_must_root;
+
+#[cfg(feature = "trace_in_no_trace_lint")]
+mod trace_in_no_trace;
#[allow(unsafe_code)] // #[no_mangle] is unsafe
#[no_mangle]
fn __rustc_plugin_registrar(reg: &mut Registry) {
- registrar(reg)
-}
-
-fn registrar(reg: &mut Registry) {
- let symbols = Symbols::new();
- reg.lint_store.register_lints(&[&UNROOTED_MUST_ROOT]);
- reg.lint_store
- .register_late_pass(move |_| Box::new(UnrootedPass::new(symbols.clone())));
-}
-
-declare_lint!(
- UNROOTED_MUST_ROOT,
- Deny,
- "Warn and report usage of unrooted jsmanaged objects"
-);
-
-/// Lint for ensuring safe usage of unrooted pointers
-///
-/// This lint (disable with `-A unrooted-must-root`/`#[allow(unrooted_must_root)]`) ensures that
-/// `#[unrooted_must_root_lint::must_root]` values are used correctly.
-///
-/// "Incorrect" usage includes:
-///
-/// - Not being used in a struct/enum field which is not `#[unrooted_must_root_lint::must_root]` itself
-/// - Not being used as an argument to a function (Except onces named `new` and `new_inherited`)
-/// - Not being bound locally in a `let` statement, assignment, `for` loop, or `match` statement.
-///
-/// This helps catch most situations where pointers like `JS<T>` are used in a way that they can be invalidated by a
-/// GC pass.
-///
-/// Structs which have their own mechanism of rooting their unrooted contents (e.g. `ScriptThread`)
-/// can be marked as `#[allow(unrooted_must_root)]`. Smart pointers which root their interior type
-/// can be marked as `#[unrooted_must_root_lint::allow_unrooted_interior]`
-pub(crate) struct UnrootedPass {
- symbols: Symbols,
-}
-
-impl UnrootedPass {
- pub fn new(symbols: Symbols) -> UnrootedPass {
- UnrootedPass { symbols }
- }
-}
-
-fn has_lint_attr(sym: &Symbols, attrs: &[Attribute], name: Symbol) -> bool {
- attrs.iter().any(|attr| {
- matches!(
- &attr.kind,
- AttrKind::Normal(normal)
- if normal.item.path.segments.len() == 2 &&
- normal.item.path.segments[0].ident.name == sym.unrooted_must_root_lint &&
- normal.item.path.segments[1].ident.name == name
- )
- })
-}
-
-/// Checks if a type is unrooted or contains any owned unrooted types
-fn is_unrooted_ty<'tcx>(
- sym: &'_ Symbols,
- cx: &LateContext<'tcx>,
- ty: ty::Ty<'tcx>,
- in_new_function: bool,
-) -> bool {
- let mut ret = false;
- let mut walker = ty.walk();
- while let Some(generic_arg) = walker.next() {
- let t = match generic_arg.unpack() {
- rustc_middle::ty::subst::GenericArgKind::Type(t) => t,
- _ => {
- walker.skip_current_subtree();
- continue;
- },
- };
- let recur_into_subtree = match t.kind() {
- ty::Adt(did, substs) => {
- let has_attr =
- |did, name| has_lint_attr(sym, &cx.tcx.get_attrs_unchecked(did), name);
- if has_attr(did.did(), sym.must_root) {
- ret = true;
- false
- } else if has_attr(did.did(), sym.allow_unrooted_interior) {
- false
- } else if match_def_path(cx, did.did(), &[sym.alloc, sym.rc, sym.Rc]) {
- // Rc<Promise> is okay
- let inner = substs.type_at(0);
- if let ty::Adt(did, _) = inner.kind() {
- if has_attr(did.did(), sym.allow_unrooted_in_rc) {
- false
- } else {
- true
- }
- } else {
- true
- }
- } else if match_def_path(cx, did.did(), &[sym::core, sym.cell, sym.Ref]) ||
- match_def_path(cx, did.did(), &[sym::core, sym.cell, sym.RefMut]) ||
- match_def_path(cx, did.did(), &[sym::core, sym::slice, sym::iter, sym.Iter]) ||
- match_def_path(
- cx,
- did.did(),
- &[sym::core, sym::slice, sym::iter, sym.IterMut],
- ) ||
- match_def_path(cx, did.did(), &[sym.accountable_refcell, sym.Ref]) ||
- match_def_path(cx, did.did(), &[sym.accountable_refcell, sym.RefMut]) ||
- match_def_path(
- cx,
- did.did(),
- &[sym::std, sym.collections, sym.hash, sym.map, sym.Entry],
- ) ||
- match_def_path(
- cx,
- did.did(),
- &[
- sym::std,
- sym.collections,
- sym.hash,
- sym.map,
- sym.OccupiedEntry,
- ],
- ) ||
- match_def_path(
- cx,
- did.did(),
- &[
- sym::std,
- sym.collections,
- sym.hash,
- sym.map,
- sym.VacantEntry,
- ],
- ) ||
- match_def_path(
- cx,
- did.did(),
- &[sym::std, sym.collections, sym.hash, sym.map, sym.Iter],
- ) ||
- match_def_path(
- cx,
- did.did(),
- &[sym::std, sym.collections, sym.hash, sym.set, sym.Iter],
- )
- {
- // Structures which are semantically similar to an &ptr.
- false
- } else if did.is_box() && in_new_function {
- // box in new() is okay
- false
- } else {
- true
- }
- },
- ty::Ref(..) => false, // don't recurse down &ptrs
- ty::RawPtr(..) => false, // don't recurse down *ptrs
- ty::FnDef(..) | ty::FnPtr(_) => false,
-
- _ => true,
- };
- if !recur_into_subtree {
- walker.skip_current_subtree();
- }
- }
- ret
-}
-
-impl LintPass for UnrootedPass {
- fn name(&self) -> &'static str {
- "ServoUnrootedPass"
- }
-}
-
-impl<'tcx> LateLintPass<'tcx> for UnrootedPass {
- /// All structs containing #[unrooted_must_root_lint::must_root] types
- /// must be #[unrooted_must_root_lint::must_root] themselves
- fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item) {
- let attrs = cx.tcx.hir().attrs(item.hir_id());
- if has_lint_attr(&self.symbols, &attrs, self.symbols.must_root) {
- return;
- }
- if let hir::ItemKind::Struct(def, ..) = &item.kind {
- for ref field in def.fields() {
- let field_type = cx.tcx.type_of(field.def_id);
- if is_unrooted_ty(&self.symbols, cx, field_type, false) {
- cx.lint(
- UNROOTED_MUST_ROOT,
- "Type must be rooted, use #[unrooted_must_root_lint::must_root] \
- on the struct definition to propagate",
- |lint| lint.set_span(field.span),
- )
- }
- }
- }
- }
-
- /// All enums containing #[unrooted_must_root_lint::must_root] types
- /// must be #[unrooted_must_root_lint::must_root] themselves
- fn check_variant(&mut self, cx: &LateContext, var: &hir::Variant) {
- let ref map = cx.tcx.hir();
- let parent_item = map.expect_item(map.get_parent_item(var.hir_id).def_id);
- let attrs = cx.tcx.hir().attrs(parent_item.hir_id());
- if !has_lint_attr(&self.symbols, &attrs, self.symbols.must_root) {
- match var.data {
- hir::VariantData::Tuple(fields, ..) => {
- for field in fields {
- let field_type = cx.tcx.type_of(field.def_id);
- if is_unrooted_ty(&self.symbols, cx, field_type, false) {
- cx.lint(
- UNROOTED_MUST_ROOT,
- "Type must be rooted, \
- use #[unrooted_must_root_lint::must_root] \
- on the enum definition to propagate",
- |lint| lint.set_span(field.ty.span),
- )
- }
- }
- },
- _ => (), // Struct variants already caught by check_struct_def
- }
- }
- }
- /// Function arguments that are #[unrooted_must_root_lint::must_root] types are not allowed
- fn check_fn(
- &mut self,
- cx: &LateContext<'tcx>,
- kind: visit::FnKind<'tcx>,
- decl: &'tcx hir::FnDecl,
- body: &'tcx hir::Body,
- span: source_map::Span,
- def_id: LocalDefId,
- ) {
- let in_new_function = match kind {
- visit::FnKind::ItemFn(n, _, _) | visit::FnKind::Method(n, _) => {
- &*n.as_str() == "new" || n.as_str().starts_with("new_")
- },
- visit::FnKind::Closure => return,
- };
-
- if !in_derive_expn(span) {
- let sig = cx.tcx.type_of(def_id).fn_sig(cx.tcx);
-
- for (arg, ty) in decl.inputs.iter().zip(sig.inputs().skip_binder().iter()) {
- if is_unrooted_ty(&self.symbols, cx, *ty, false) {
- cx.lint(UNROOTED_MUST_ROOT, "Type must be rooted", |lint| {
- lint.set_span(arg.span)
- })
- }
- }
-
- if !in_new_function &&
- is_unrooted_ty(&self.symbols, cx, sig.output().skip_binder(), false)
- {
- cx.lint(UNROOTED_MUST_ROOT, "Type must be rooted", |lint| {
- lint.set_span(decl.output.span())
- })
- }
- }
-
- let mut visitor = FnDefVisitor {
- symbols: &self.symbols,
- cx,
- in_new_function,
- };
- visit::walk_expr(&mut visitor, &body.value);
- }
-}
-
-struct FnDefVisitor<'a, 'tcx: 'a> {
- symbols: &'a Symbols,
- cx: &'a LateContext<'tcx>,
- in_new_function: bool,
-}
-
-impl<'a, 'tcx> visit::Visitor<'tcx> for FnDefVisitor<'a, 'tcx> {
- type Map = rustc_middle::hir::map::Map<'tcx>;
-
- fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
- let cx = self.cx;
-
- let require_rooted = |cx: &LateContext, in_new_function: bool, subexpr: &hir::Expr| {
- let ty = cx.typeck_results().expr_ty(&subexpr);
- if is_unrooted_ty(&self.symbols, cx, ty, in_new_function) {
- cx.lint(
- UNROOTED_MUST_ROOT,
- format!("Expression of type {:?} must be rooted", ty),
- |lint| lint.set_span(subexpr.span),
- )
- }
- };
-
- match expr.kind {
- // Trait casts from #[unrooted_must_root_lint::must_root] types are not allowed
- ExprKind::Cast(subexpr, _) => require_rooted(cx, self.in_new_function, &subexpr),
- // This catches assignments... the main point of this would be to catch mutable
- // references to `JS<T>`.
- // FIXME: Enable this? Triggers on certain kinds of uses of DomRefCell.
- // hir::ExprAssign(_, ref rhs) => require_rooted(cx, self.in_new_function, &*rhs),
- // This catches calls; basically, this enforces the constraint that only constructors
- // can call other constructors.
- // FIXME: Enable this? Currently triggers with constructs involving DomRefCell, and
- // constructs like Vec<JS<T>> and RootedVec<JS<T>>.
- // hir::ExprCall(..) if !self.in_new_function => {
- // require_rooted(cx, self.in_new_function, expr);
- // }
- _ => {
- // TODO(pcwalton): Check generics with a whitelist of allowed generics.
- },
- }
-
- visit::walk_expr(self, expr);
- }
-
- fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
- let cx = self.cx;
-
- // We want to detect pattern bindings that move a value onto the stack.
- // When "default binding modes" https://github.com/rust-lang/rust/issues/42640
- // are implemented, the `Unannotated` case could cause false-positives.
- // These should be fixable by adding an explicit `ref`.
- match pat.kind {
- hir::PatKind::Binding(hir::BindingAnnotation::NONE, ..) |
- hir::PatKind::Binding(hir::BindingAnnotation::MUT, ..) => {
- let ty = cx.typeck_results().pat_ty(pat);
- if is_unrooted_ty(self.symbols, cx, ty, self.in_new_function) {
- cx.lint(
- UNROOTED_MUST_ROOT,
- format!("Expression of type {:?} must be rooted", ty),
- |lint| lint.set_span(pat.span),
- )
- }
- },
- _ => {},
- }
-
- visit::walk_pat(self, pat);
- }
-
- fn visit_ty(&mut self, _: &'tcx hir::Ty) {}
-
- fn nested_visit_map(&mut self) -> Self::Map {
- self.cx.tcx.hir()
- }
+ #[cfg(feature = "unrooted_must_root_lint")]
+ unrooted_must_root::register(reg);
+ #[cfg(feature = "trace_in_no_trace_lint")]
+ trace_in_no_trace::register(reg);
}
/// check if a DefId's path matches the given absolute type path
@@ -408,11 +86,12 @@ fn in_derive_expn(span: Span) -> bool {
)
}
+#[macro_export]
macro_rules! symbols {
($($s: ident)+) => {
#[derive(Clone)]
#[allow(non_snake_case)]
- struct Symbols {
+ pub(crate) struct Symbols {
$( $s: Symbol, )+
}
@@ -426,25 +105,248 @@ macro_rules! symbols {
}
}
-symbols! {
- unrooted_must_root_lint
- allow_unrooted_interior
- allow_unrooted_in_rc
- must_root
- alloc
- rc
- Rc
- cell
- accountable_refcell
- Ref
- RefMut
- Iter
- IterMut
- collections
- hash
- map
- set
- Entry
- OccupiedEntry
- VacantEntry
+/*
+Stuff copied from clippy:
+*/
+
+fn find_primitive_impls<'tcx>(tcx: TyCtxt<'tcx>, name: &str) -> impl Iterator<Item = DefId> + 'tcx {
+ use rustc_middle::ty::fast_reject::SimplifiedType::*;
+ let ty = match name {
+ "bool" => BoolSimplifiedType,
+ "char" => CharSimplifiedType,
+ "str" => StrSimplifiedType,
+ "array" => ArraySimplifiedType,
+ "slice" => SliceSimplifiedType,
+ // FIXME: rustdoc documents these two using just `pointer`.
+ //
+ // Maybe this is something we should do here too.
+ "const_ptr" => PtrSimplifiedType(Mutability::Not),
+ "mut_ptr" => PtrSimplifiedType(Mutability::Mut),
+ "isize" => IntSimplifiedType(IntTy::Isize),
+ "i8" => IntSimplifiedType(IntTy::I8),
+ "i16" => IntSimplifiedType(IntTy::I16),
+ "i32" => IntSimplifiedType(IntTy::I32),
+ "i64" => IntSimplifiedType(IntTy::I64),
+ "i128" => IntSimplifiedType(IntTy::I128),
+ "usize" => UintSimplifiedType(UintTy::Usize),
+ "u8" => UintSimplifiedType(UintTy::U8),
+ "u16" => UintSimplifiedType(UintTy::U16),
+ "u32" => UintSimplifiedType(UintTy::U32),
+ "u64" => UintSimplifiedType(UintTy::U64),
+ "u128" => UintSimplifiedType(UintTy::U128),
+ "f32" => FloatSimplifiedType(FloatTy::F32),
+ "f64" => FloatSimplifiedType(FloatTy::F64),
+ _ => return [].iter().copied(),
+ };
+
+ tcx.incoherent_impls(ty).iter().copied()
+}
+
+fn non_local_item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
+ match tcx.def_kind(def_id) {
+ DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
+ .module_children(def_id)
+ .iter()
+ .filter(|item| item.ident.name == name)
+ .map(|child| child.res.expect_non_local())
+ .collect(),
+ DefKind::Impl { .. } => tcx
+ .associated_item_def_ids(def_id)
+ .iter()
+ .copied()
+ .filter(|assoc_def_id| tcx.item_name(*assoc_def_id) == name)
+ .map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id))
+ .collect(),
+ _ => Vec::new(),
+ }
+}
+
+fn local_item_children_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, name: Symbol) -> Vec<Res> {
+ let hir = tcx.hir();
+
+ let root_mod;
+ let item_kind = match hir.find_by_def_id(local_id) {
+ Some(Node::Crate(r#mod)) => {
+ root_mod = ItemKind::Mod(r#mod);
+ &root_mod
+ },
+ Some(Node::Item(item)) => &item.kind,
+ _ => return Vec::new(),
+ };
+
+ let res = |ident: Ident, owner_id: OwnerId| {
+ if ident.name == name {
+ let def_id = owner_id.to_def_id();
+ Some(Res::Def(tcx.def_kind(def_id), def_id))
+ } else {
+ None
+ }
+ };
+
+ match item_kind {
+ ItemKind::Mod(r#mod) => r#mod
+ .item_ids
+ .iter()
+ .filter_map(|&item_id| res(hir.item(item_id).ident, item_id.owner_id))
+ .collect(),
+ ItemKind::Impl(r#impl) => r#impl
+ .items
+ .iter()
+ .filter_map(|&ImplItemRef { ident, id, .. }| res(ident, id.owner_id))
+ .collect(),
+ ItemKind::Trait(.., trait_item_refs) => trait_item_refs
+ .iter()
+ .filter_map(|&TraitItemRef { ident, id, .. }| res(ident, id.owner_id))
+ .collect(),
+ _ => Vec::new(),
+ }
+}
+
+fn item_children_by_name(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Vec<Res> {
+ if let Some(local_id) = def_id.as_local() {
+ local_item_children_by_name(tcx, local_id, name)
+ } else {
+ non_local_item_children_by_name(tcx, def_id, name)
+ }
+}
+
+/// Resolves a def path like `std::vec::Vec`.
+///
+/// Can return multiple resolutions when there are multiple versions of the same crate, e.g.
+/// `memchr::memchr` could return the functions from both memchr 1.0 and memchr 2.0.
+///
+/// Also returns multiple results when there are multiple paths under the same name e.g. `std::vec`
+/// would have both a [`DefKind::Mod`] and [`DefKind::Macro`].
+///
+/// This function is expensive and should be used sparingly.
+pub fn def_path_res(cx: &LateContext<'_>, path: &[&str]) -> Vec<Res> {
+ fn find_crates(tcx: TyCtxt<'_>, name: Symbol) -> impl Iterator<Item = DefId> + '_ {
+ tcx.crates(())
+ .iter()
+ .copied()
+ .filter(move |&num| tcx.crate_name(num) == name)
+ .map(CrateNum::as_def_id)
+ }
+
+ let tcx = cx.tcx;
+
+ let (base, mut path) = match *path {
+ [primitive] => {
+ return vec![PrimTy::from_name(Symbol::intern(primitive)).map_or(Res::Err, Res::PrimTy)];
+ },
+ [base, ref path @ ..] => (base, path),
+ _ => return Vec::new(),
+ };
+
+ let base_sym = Symbol::intern(base);
+
+ let local_crate = if tcx.crate_name(LOCAL_CRATE) == base_sym {
+ Some(LOCAL_CRATE.as_def_id())
+ } else {
+ None
+ };
+
+ let starts = find_primitive_impls(tcx, base)
+ .chain(find_crates(tcx, base_sym))
+ .chain(local_crate)
+ .map(|id| Res::Def(tcx.def_kind(id), id));
+
+ let mut resolutions: Vec<Res> = starts.collect();
+
+ while let [segment, rest @ ..] = path {
+ path = rest;
+ let segment = Symbol::intern(segment);
+
+ resolutions = resolutions
+ .into_iter()
+ .filter_map(|res| res.opt_def_id())
+ .flat_map(|def_id| {
+ // When the current def_id is e.g. `struct S`, check the impl items in
+ // `impl S { ... }`
+ let inherent_impl_children = tcx
+ .inherent_impls(def_id)
+ .iter()
+ .flat_map(|&impl_def_id| item_children_by_name(tcx, impl_def_id, segment));
+
+ let direct_children = item_children_by_name(tcx, def_id, segment);
+
+ inherent_impl_children.chain(direct_children)
+ })
+ .collect();
+ }
+
+ resolutions
+}
+
+/// Resolves a def path like `std::vec::Vec` to its [`DefId`]s, see [`def_path_res`].
+pub fn def_path_def_ids(cx: &LateContext<'_>, path: &[&str]) -> impl Iterator<Item = DefId> {
+ def_path_res(cx, path)
+ .into_iter()
+ .filter_map(|res| res.opt_def_id())
+}
+
+pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
+ def_path_res(cx, path)
+ .into_iter()
+ .find_map(|res| match res {
+ Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
+ _ => None,
+ })
+}
+
+/// Checks whether a type implements a trait.
+/// The function returns false in case the type contains an inference variable.
+///
+/// See:
+/// * [`get_trait_def_id`](super::get_trait_def_id) to get a trait [`DefId`].
+/// * [Common tools for writing lints] for an example how to use this function and other options.
+///
+/// [Common tools for writing lints]: https://github.com/rust-lang/rust-clippy/blob/master/book/src/development/common_tools_writing_lints.md#checking-if-a-type-implements-a-specific-trait
+pub fn implements_trait<'tcx>(
+ cx: &LateContext<'tcx>,
+ ty: Ty<'tcx>,
+ trait_id: DefId,
+ ty_params: &[GenericArg<'tcx>],
+) -> bool {
+ implements_trait_with_env(
+ cx.tcx,
+ cx.param_env,
+ ty,
+ trait_id,
+ ty_params.iter().map(|&arg| Some(arg)),
+ )
+}
+
+/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
+pub fn implements_trait_with_env<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ty: ty::Ty<'tcx>,
+ trait_id: DefId,
+ ty_params: impl IntoIterator<Item = Option<GenericArg<'tcx>>>,
+) -> bool {
+ let ty = tcx.erase_regions(ty);
+ if ty.has_escaping_bound_vars() {
+ return false;
+ }
+ let infcx = tcx.infer_ctxt().build();
+ let orig = TypeVariableOrigin {
+ kind: TypeVariableOriginKind::MiscVariable,
+ span: DUMMY_SP,
+ };
+ // in new nightlies: mk_substs -> mk_substs_from_iter
+ let ty_params = tcx.mk_substs(
+ ty_params
+ .into_iter()
+ .map(|arg| arg.unwrap_or_else(|| infcx.next_ty_var(orig).into())),
+ );
+ infcx
+ .type_implements_trait(
+ trait_id,
+ // for some unknown reason we need to have vec here
+ // clippy has array
+ vec![ty.into()].into_iter().chain(ty_params),
+ param_env,
+ )
+ .must_apply_modulo_regions()
}
diff --git a/components/script_plugins/trace_in_no_trace.rs b/components/script_plugins/trace_in_no_trace.rs
new file mode 100644
index 00000000000..f713364458c
--- /dev/null
+++ b/components/script_plugins/trace_in_no_trace.rs
@@ -0,0 +1,204 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::{get_trait_def_id, implements_trait, symbols};
+
+use rustc_ast::ast::{AttrKind, Attribute};
+use rustc_ast::token::TokenKind;
+use rustc_ast::tokenstream::TokenTree;
+use rustc_ast::AttrArgs;
+use rustc_driver::plugin::Registry;
+use rustc_error_messages::MultiSpan;
+use rustc_hir::{self as hir};
+use rustc_lint::{LateContext, LateLintPass, LintContext, LintPass};
+use rustc_middle::ty;
+use rustc_session::declare_lint;
+use rustc_span::symbol::Symbol;
+
+declare_lint!(
+ TRACE_IN_NO_TRACE,
+ Deny,
+ "Warn and report incorrect usage of Traceable (jsmanaged) objects in must_not_have_traceable marked wrappers"
+);
+
+declare_lint!(
+ EMPTY_TRACE_IN_NO_TRACE,
+ Warn,
+ "Warn about usage of empty Traceable objects in must_not_have_traceable marked wrappers"
+);
+const EMPTY_TRACE_IN_NO_TRACE_MSG: &str =
+ "must_not_have_traceable marked wrapper is not needed for types that implements \
+empty Traceable (like primitive types). Consider removing the wrapper.";
+
+pub fn register(reg: &mut Registry) {
+ let symbols = Symbols::new();
+ reg.lint_store
+ .register_lints(&[&TRACE_IN_NO_TRACE, &EMPTY_TRACE_IN_NO_TRACE]);
+ reg.lint_store
+ .register_late_pass(move |_| Box::new(NotracePass::new(symbols.clone())));
+}
+
+/// Lint for ensuring safe usage of NoTrace wrappers
+///
+/// This lint (disable with `-A trace-in-no-trace`/`#[allow(trace_in_no_trace)]`) ensures that
+/// wrappers marked with must_not_have_traceable(i: usize) only stores
+/// non-jsmanaged (DOES NOT implement JSTraceble) type in i-th generic
+///
+/// For example usage look at the tests
+pub(crate) struct NotracePass {
+ symbols: Symbols,
+}
+
+impl NotracePass {
+ pub(crate) fn new(symbols: Symbols) -> Self {
+ Self { symbols }
+ }
+}
+
+impl LintPass for NotracePass {
+ fn name(&self) -> &'static str {
+ "ServoNotracePass"
+ }
+}
+
+fn get_must_not_have_traceable(sym: &Symbols, attrs: &[Attribute]) -> Option<usize> {
+ attrs
+ .iter()
+ .find(|attr| {
+ matches!(
+ &attr.kind,
+ AttrKind::Normal(normal)
+ if normal.item.path.segments.len() == 2 &&
+ normal.item.path.segments[0].ident.name == sym.trace_in_no_trace_lint &&
+ normal.item.path.segments[1].ident.name == sym.must_not_have_traceable
+ )
+ })
+ .map(|x| match &x.get_normal_item().args {
+ AttrArgs::Empty => 0,
+ AttrArgs::Delimited(a) => match a
+ .tokens
+ .trees()
+ .next()
+ .expect("Arguments not found for must_not_have_traceable")
+ {
+ TokenTree::Token(tok, _) => match tok.kind {
+ TokenKind::Literal(lit) => lit.symbol.as_str().parse().unwrap(),
+ _ => panic!("must_not_have_traceable expected integer literal here"),
+ },
+ TokenTree::Delimited(_, _, _) => {
+ todo!("must_not_have_traceable does not support multiple notraceable positions")
+ },
+ },
+ _ => {
+ panic!("must_not_have_traceable does not support key-value arguments")
+ },
+ })
+}
+
+fn is_jstraceable<'tcx>(cx: &LateContext<'tcx>, ty: ty::Ty<'tcx>) -> bool {
+ // TODO(sagudev): get_trait_def_id is expensive, use lazy and cache it for whole pass
+ if let Some(trait_id) =
+ get_trait_def_id(cx, &["script", "dom", "bindings", "trace", "JSTraceable"])
+ {
+ return implements_trait(cx, ty, trait_id, &[]);
+ }
+ // when running tests
+ if let Some(trait_id) = get_trait_def_id(
+ cx,
+ &[
+ "script_plugins_tests",
+ "trace_in_no_trace_lint",
+ "JSTraceable",
+ ],
+ ) {
+ return implements_trait(cx, ty, trait_id, &[]);
+ }
+ panic!("JSTraceable not found");
+}
+
+/// Gives warrning or errors for incorect usage of NoTrace like `NoTrace<impl Traceable>`.
+fn incorrect_no_trace<'tcx, I: Into<MultiSpan> + Copy>(
+ sym: &'_ Symbols,
+ cx: &LateContext<'tcx>,
+ ty: ty::Ty<'tcx>,
+ span: I,
+) {
+ let mut walker = ty.walk();
+ while let Some(generic_arg) = walker.next() {
+ let t = match generic_arg.unpack() {
+ rustc_middle::ty::subst::GenericArgKind::Type(t) => t,
+ _ => {
+ walker.skip_current_subtree();
+ continue;
+ },
+ };
+ let recur_into_subtree = match t.kind() {
+ ty::Adt(did, substs) => {
+ if let Some(pos) =
+ get_must_not_have_traceable(sym, &cx.tcx.get_attrs_unchecked(did.did()))
+ {
+ let inner = substs.type_at(pos);
+ if inner.is_primitive_ty() {
+ cx.lint(
+ EMPTY_TRACE_IN_NO_TRACE,
+ EMPTY_TRACE_IN_NO_TRACE_MSG,
+ |lint| lint.set_span(span),
+ )
+ } else if is_jstraceable(cx, inner) {
+ cx.lint(
+ TRACE_IN_NO_TRACE,
+ format!(
+ "must_not_have_traceable marked wrapper must not have \
+jsmanaged inside on {pos}-th position. Consider removing the wrapper."
+ ),
+ |lint| lint.set_span(span),
+ )
+ }
+ false
+ } else {
+ true
+ }
+ },
+ _ => !t.is_primitive_ty(),
+ };
+ if !recur_into_subtree {
+ walker.skip_current_subtree();
+ }
+ }
+}
+
+// NoTrace correct usage of NoTrace must only be checked on Struct (item) and Enums (variants)
+// as these are the only ones that are actually traced
+impl<'tcx> LateLintPass<'tcx> for NotracePass {
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item) {
+ // TODO: better performance if we limit with lint attr???
+ /*let attrs = cx.tcx.hir().attrs(item.hir_id());
+ if has_lint_attr(&self.symbols, &attrs, self.symbols.must_root) {
+ return;
+ }*/
+ if let hir::ItemKind::Struct(def, ..) = &item.kind {
+ for ref field in def.fields() {
+ let field_type = cx.tcx.type_of(field.def_id);
+ incorrect_no_trace(&self.symbols, cx, field_type, field.span);
+ }
+ }
+ }
+
+ fn check_variant(&mut self, cx: &LateContext, var: &hir::Variant) {
+ match var.data {
+ hir::VariantData::Tuple(fields, ..) => {
+ for field in fields {
+ let field_type = cx.tcx.type_of(field.def_id);
+ incorrect_no_trace(&self.symbols, cx, field_type, field.ty.span);
+ }
+ },
+ _ => (), // Struct variants already caught by check_struct_def
+ }
+ }
+}
+
+symbols! {
+ trace_in_no_trace_lint
+ must_not_have_traceable
+}
diff --git a/components/script_plugins/unrooted_must_root.rs b/components/script_plugins/unrooted_must_root.rs
new file mode 100644
index 00000000000..4e7b57c26a1
--- /dev/null
+++ b/components/script_plugins/unrooted_must_root.rs
@@ -0,0 +1,378 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+use crate::{in_derive_expn, match_def_path, symbols};
+
+use rustc_ast::ast::{AttrKind, Attribute};
+use rustc_driver::plugin::Registry;
+use rustc_hir::intravisit as visit;
+use rustc_hir::{self as hir, ExprKind};
+use rustc_lint::{LateContext, LateLintPass, LintContext, LintPass};
+use rustc_middle::ty;
+use rustc_session::declare_lint;
+use rustc_span::def_id::LocalDefId;
+use rustc_span::source_map;
+use rustc_span::symbol::sym;
+use rustc_span::symbol::Symbol;
+
+declare_lint!(
+ UNROOTED_MUST_ROOT,
+ Deny,
+ "Warn and report usage of unrooted jsmanaged objects"
+);
+
+pub fn register(reg: &mut Registry) {
+ let symbols = Symbols::new();
+ reg.lint_store.register_lints(&[&UNROOTED_MUST_ROOT]);
+ reg.lint_store
+ .register_late_pass(move |_| Box::new(UnrootedPass::new(symbols.clone())));
+}
+
+/// Lint for ensuring safe usage of unrooted pointers
+///
+/// This lint (disable with `-A unrooted-must-root`/`#[allow(unrooted_must_root)]`) ensures that
+/// `#[unrooted_must_root_lint::must_root]` values are used correctly.
+///
+/// "Incorrect" usage includes:
+///
+/// - Not being used in a struct/enum field which is not `#[unrooted_must_root_lint::must_root]` itself
+/// - Not being used as an argument to a function (Except onces named `new` and `new_inherited`)
+/// - Not being bound locally in a `let` statement, assignment, `for` loop, or `match` statement.
+///
+/// This helps catch most situations where pointers like `JS<T>` are used in a way that they can be invalidated by a
+/// GC pass.
+///
+/// Structs which have their own mechanism of rooting their unrooted contents (e.g. `ScriptThread`)
+/// can be marked as `#[allow(unrooted_must_root)]`. Smart pointers which root their interior type
+/// can be marked as `#[unrooted_must_root_lint::allow_unrooted_interior]`
+pub(crate) struct UnrootedPass {
+ symbols: Symbols,
+}
+
+impl UnrootedPass {
+ pub(crate) fn new(symbols: Symbols) -> UnrootedPass {
+ UnrootedPass { symbols }
+ }
+}
+
+fn has_lint_attr(sym: &Symbols, attrs: &[Attribute], name: Symbol) -> bool {
+ attrs.iter().any(|attr| {
+ matches!(
+ &attr.kind,
+ AttrKind::Normal(normal)
+ if normal.item.path.segments.len() == 2 &&
+ normal.item.path.segments[0].ident.name == sym.unrooted_must_root_lint &&
+ normal.item.path.segments[1].ident.name == name
+ )
+ })
+}
+
+/// Checks if a type is unrooted or contains any owned unrooted types
+fn is_unrooted_ty<'tcx>(
+ sym: &'_ Symbols,
+ cx: &LateContext<'tcx>,
+ ty: ty::Ty<'tcx>,
+ in_new_function: bool,
+) -> bool {
+ let mut ret = false;
+ let mut walker = ty.walk();
+ while let Some(generic_arg) = walker.next() {
+ let t = match generic_arg.unpack() {
+ rustc_middle::ty::subst::GenericArgKind::Type(t) => t,
+ _ => {
+ walker.skip_current_subtree();
+ continue;
+ },
+ };
+ let recur_into_subtree = match t.kind() {
+ ty::Adt(did, substs) => {
+ let has_attr =
+ |did, name| has_lint_attr(sym, &cx.tcx.get_attrs_unchecked(did), name);
+ if has_attr(did.did(), sym.must_root) {
+ ret = true;
+ false
+ } else if has_attr(did.did(), sym.allow_unrooted_interior) {
+ false
+ } else if match_def_path(cx, did.did(), &[sym.alloc, sym.rc, sym.Rc]) {
+ // Rc<Promise> is okay
+ let inner = substs.type_at(0);
+ if let ty::Adt(did, _) = inner.kind() {
+ if has_attr(did.did(), sym.allow_unrooted_in_rc) {
+ false
+ } else {
+ true
+ }
+ } else {
+ true
+ }
+ } else if match_def_path(cx, did.did(), &[sym::core, sym.cell, sym.Ref]) ||
+ match_def_path(cx, did.did(), &[sym::core, sym.cell, sym.RefMut]) ||
+ match_def_path(cx, did.did(), &[sym::core, sym::slice, sym::iter, sym.Iter]) ||
+ match_def_path(
+ cx,
+ did.did(),
+ &[sym::core, sym::slice, sym::iter, sym.IterMut],
+ ) ||
+ match_def_path(cx, did.did(), &[sym.accountable_refcell, sym.Ref]) ||
+ match_def_path(cx, did.did(), &[sym.accountable_refcell, sym.RefMut]) ||
+ match_def_path(
+ cx,
+ did.did(),
+ &[sym::std, sym.collections, sym.hash, sym.map, sym.Entry],
+ ) ||
+ match_def_path(
+ cx,
+ did.did(),
+ &[
+ sym::std,
+ sym.collections,
+ sym.hash,
+ sym.map,
+ sym.OccupiedEntry,
+ ],
+ ) ||
+ match_def_path(
+ cx,
+ did.did(),
+ &[
+ sym::std,
+ sym.collections,
+ sym.hash,
+ sym.map,
+ sym.VacantEntry,
+ ],
+ ) ||
+ match_def_path(
+ cx,
+ did.did(),
+ &[sym::std, sym.collections, sym.hash, sym.map, sym.Iter],
+ ) ||
+ match_def_path(
+ cx,
+ did.did(),
+ &[sym::std, sym.collections, sym.hash, sym.set, sym.Iter],
+ )
+ {
+ // Structures which are semantically similar to an &ptr.
+ false
+ } else if did.is_box() && in_new_function {
+ // box in new() is okay
+ false
+ } else {
+ true
+ }
+ },
+ ty::Ref(..) => false, // don't recurse down &ptrs
+ ty::RawPtr(..) => false, // don't recurse down *ptrs
+ ty::FnDef(..) | ty::FnPtr(_) => false,
+
+ _ => true,
+ };
+ if !recur_into_subtree {
+ walker.skip_current_subtree();
+ }
+ }
+ ret
+}
+
+impl LintPass for UnrootedPass {
+ fn name(&self) -> &'static str {
+ "ServoUnrootedPass"
+ }
+}
+
+impl<'tcx> LateLintPass<'tcx> for UnrootedPass {
+ /// All structs containing #[unrooted_must_root_lint::must_root] types
+ /// must be #[unrooted_must_root_lint::must_root] themselves
+ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item) {
+ let attrs = cx.tcx.hir().attrs(item.hir_id());
+ if has_lint_attr(&self.symbols, &attrs, self.symbols.must_root) {
+ return;
+ }
+ if let hir::ItemKind::Struct(def, ..) = &item.kind {
+ for ref field in def.fields() {
+ let field_type = cx.tcx.type_of(field.def_id);
+ if is_unrooted_ty(&self.symbols, cx, field_type, false) {
+ cx.lint(
+ UNROOTED_MUST_ROOT,
+ "Type must be rooted, use #[unrooted_must_root_lint::must_root] \
+ on the struct definition to propagate",
+ |lint| lint.set_span(field.span),
+ )
+ }
+ }
+ }
+ }
+
+ /// All enums containing #[unrooted_must_root_lint::must_root] types
+ /// must be #[unrooted_must_root_lint::must_root] themselves
+ fn check_variant(&mut self, cx: &LateContext, var: &hir::Variant) {
+ let ref map = cx.tcx.hir();
+ let parent_item = map.expect_item(map.get_parent_item(var.hir_id).def_id);
+ let attrs = cx.tcx.hir().attrs(parent_item.hir_id());
+ if !has_lint_attr(&self.symbols, &attrs, self.symbols.must_root) {
+ match var.data {
+ hir::VariantData::Tuple(fields, ..) => {
+ for field in fields {
+ let field_type = cx.tcx.type_of(field.def_id);
+ if is_unrooted_ty(&self.symbols, cx, field_type, false) {
+ cx.lint(
+ UNROOTED_MUST_ROOT,
+ "Type must be rooted, \
+ use #[unrooted_must_root_lint::must_root] \
+ on the enum definition to propagate",
+ |lint| lint.set_span(field.ty.span),
+ )
+ }
+ }
+ },
+ _ => (), // Struct variants already caught by check_struct_def
+ }
+ }
+ }
+ /// Function arguments that are #[unrooted_must_root_lint::must_root] types are not allowed
+ fn check_fn(
+ &mut self,
+ cx: &LateContext<'tcx>,
+ kind: visit::FnKind<'tcx>,
+ decl: &'tcx hir::FnDecl,
+ body: &'tcx hir::Body,
+ span: source_map::Span,
+ def_id: LocalDefId,
+ ) {
+ let in_new_function = match kind {
+ visit::FnKind::ItemFn(n, _, _) | visit::FnKind::Method(n, _) => {
+ &*n.as_str() == "new" || n.as_str().starts_with("new_")
+ },
+ visit::FnKind::Closure => return,
+ };
+
+ if !in_derive_expn(span) {
+ let sig = cx.tcx.type_of(def_id).fn_sig(cx.tcx);
+
+ for (arg, ty) in decl.inputs.iter().zip(sig.inputs().skip_binder().iter()) {
+ if is_unrooted_ty(&self.symbols, cx, *ty, false) {
+ cx.lint(UNROOTED_MUST_ROOT, "Type must be rooted", |lint| {
+ lint.set_span(arg.span)
+ })
+ }
+ }
+
+ if !in_new_function &&
+ is_unrooted_ty(&self.symbols, cx, sig.output().skip_binder(), false)
+ {
+ cx.lint(UNROOTED_MUST_ROOT, "Type must be rooted", |lint| {
+ lint.set_span(decl.output.span())
+ })
+ }
+ }
+
+ let mut visitor = FnDefVisitor {
+ symbols: &self.symbols,
+ cx,
+ in_new_function,
+ };
+ visit::walk_expr(&mut visitor, &body.value);
+ }
+}
+
+struct FnDefVisitor<'a, 'tcx: 'a> {
+ symbols: &'a Symbols,
+ cx: &'a LateContext<'tcx>,
+ in_new_function: bool,
+}
+
+impl<'a, 'tcx> visit::Visitor<'tcx> for FnDefVisitor<'a, 'tcx> {
+ type Map = rustc_middle::hir::map::Map<'tcx>;
+
+ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
+ let cx = self.cx;
+
+ let require_rooted = |cx: &LateContext, in_new_function: bool, subexpr: &hir::Expr| {
+ let ty = cx.typeck_results().expr_ty(&subexpr);
+ if is_unrooted_ty(&self.symbols, cx, ty, in_new_function) {
+ cx.lint(
+ UNROOTED_MUST_ROOT,
+ format!("Expression of type {:?} must be rooted", ty),
+ |lint| lint.set_span(subexpr.span),
+ )
+ }
+ };
+
+ match expr.kind {
+ // Trait casts from #[unrooted_must_root_lint::must_root] types are not allowed
+ ExprKind::Cast(subexpr, _) => require_rooted(cx, self.in_new_function, &subexpr),
+ // This catches assignments... the main point of this would be to catch mutable
+ // references to `JS<T>`.
+ // FIXME: Enable this? Triggers on certain kinds of uses of DomRefCell.
+ // hir::ExprAssign(_, ref rhs) => require_rooted(cx, self.in_new_function, &*rhs),
+ // This catches calls; basically, this enforces the constraint that only constructors
+ // can call other constructors.
+ // FIXME: Enable this? Currently triggers with constructs involving DomRefCell, and
+ // constructs like Vec<JS<T>> and RootedVec<JS<T>>.
+ // hir::ExprCall(..) if !self.in_new_function => {
+ // require_rooted(cx, self.in_new_function, expr);
+ // }
+ _ => {
+ // TODO(pcwalton): Check generics with a whitelist of allowed generics.
+ },
+ }
+
+ visit::walk_expr(self, expr);
+ }
+
+ fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
+ let cx = self.cx;
+
+ // We want to detect pattern bindings that move a value onto the stack.
+ // When "default binding modes" https://github.com/rust-lang/rust/issues/42640
+ // are implemented, the `Unannotated` case could cause false-positives.
+ // These should be fixable by adding an explicit `ref`.
+ match pat.kind {
+ hir::PatKind::Binding(hir::BindingAnnotation::NONE, ..) |
+ hir::PatKind::Binding(hir::BindingAnnotation::MUT, ..) => {
+ let ty = cx.typeck_results().pat_ty(pat);
+ if is_unrooted_ty(self.symbols, cx, ty, self.in_new_function) {
+ cx.lint(
+ UNROOTED_MUST_ROOT,
+ format!("Expression of type {:?} must be rooted", ty),
+ |lint| lint.set_span(pat.span),
+ )
+ }
+ },
+ _ => {},
+ }
+
+ visit::walk_pat(self, pat);
+ }
+
+ fn visit_ty(&mut self, _: &'tcx hir::Ty) {}
+
+ fn nested_visit_map(&mut self) -> Self::Map {
+ self.cx.tcx.hir()
+ }
+}
+
+symbols! {
+ unrooted_must_root_lint
+ allow_unrooted_interior
+ allow_unrooted_in_rc
+ must_root
+ alloc
+ rc
+ Rc
+ cell
+ accountable_refcell
+ Ref
+ RefMut
+ Iter
+ IterMut
+ collections
+ hash
+ map
+ set
+ Entry
+ OccupiedEntry
+ VacantEntry
+}