mirror of
https://github.com/servo/servo
synced 2026-04-26 01:25:32 +02:00
Reviewable per commits: As noted in https://github.com/servo/servo/pull/42180#discussion_r2749861902 transmuting `&Reflector<AssociatedMemory>` to `&Reflector<()>` will ignore AssociatedMemory information and thus it will not remove extra associated memory. By returning `&Reflector<Self::ReflectorType>` from `DomObject::reflector()` we will preserve this information and thus correctly handle cases with associated memory. We also do not need `overrideMemoryUsage` in bindings.conf anymore. 🎉 Instead of removing associated memory in drop code we should do it as part of finalizers, otherwise we have problems in nested (inherited) structs, where drop is run for both parent and child, but we only added associated memory for child (on init_reflector) which already included size of parent. The only exception here is promise, because it is RCed and not finalized. Testing: Tested locally that it fixes speedometer. Fixes #42269 --------- Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
64 lines
2.2 KiB
Rust
64 lines
2.2 KiB
Rust
/* 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/. */
|
|
|
|
#![recursion_limit = "128"]
|
|
|
|
use proc_macro::TokenStream;
|
|
use quote::quote;
|
|
use syn::*;
|
|
mod domobject;
|
|
use crate::domobject::expand_dom_object;
|
|
|
|
#[proc_macro_attribute]
|
|
pub fn dom_struct(args: TokenStream, input: TokenStream) -> TokenStream {
|
|
let associated_memory = args.to_string().contains("associated_memory");
|
|
if !associated_memory && !args.is_empty() {
|
|
panic!("#[dom_struct] only takes 'associated_memory' as an argument");
|
|
}
|
|
let attributes = quote! {
|
|
#[derive(deny_public_fields::DenyPublicFields, JSTraceable, MallocSizeOf)]
|
|
#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
|
|
#[repr(C)]
|
|
};
|
|
|
|
// Work around https://github.com/rust-lang/rust/issues/46489
|
|
let attributes: TokenStream = attributes.to_string().parse().unwrap();
|
|
|
|
let output: TokenStream = attributes.into_iter().chain(input).collect();
|
|
|
|
let item: Item = syn::parse(output).unwrap();
|
|
|
|
if let Item::Struct(s) = item {
|
|
let expanded_dom_object = expand_dom_object(s.clone(), associated_memory);
|
|
let s2 = quote! { #s #expanded_dom_object };
|
|
if !s.generics.params.is_empty() {
|
|
return s2.into();
|
|
}
|
|
if let Fields::Named(ref f) = s.fields {
|
|
let f = f.named.first().expect("Must have at least one field");
|
|
let ident = f.ident.as_ref().expect("Must have named fields");
|
|
let name = &s.ident;
|
|
let ty = &f.ty;
|
|
|
|
quote! (
|
|
#s2
|
|
|
|
impl crate::HasParent for #name {
|
|
type Parent = #ty;
|
|
/// This is used in a type assertion to ensure that
|
|
/// the source and webidls agree as to what the parent type is
|
|
fn as_parent(&self) -> &#ty {
|
|
&self.#ident
|
|
}
|
|
}
|
|
)
|
|
.into()
|
|
} else {
|
|
panic!("#[dom_struct] only applies to structs with named fields");
|
|
}
|
|
} else {
|
|
panic!("#[dom_struct] only applies to structs");
|
|
}
|
|
}
|