diff --git a/components/script/dom/bindings/codegen/Bindings.conf b/components/script/dom/bindings/codegen/Bindings.conf index 48d9392465f..a1f3de7e46a 100644 --- a/components/script/dom/bindings/codegen/Bindings.conf +++ b/components/script/dom/bindings/codegen/Bindings.conf @@ -527,3 +527,49 @@ DOMInterfaces = { }, } + +Dictionaries = { +'GPUCanvasConfiguration': { + 'derives': ['Clone'] +}, + +'GPUExtent3DDict': { + 'derives': ["MallocSizeOf"], +}, + +'GPUObjectDescriptorBase': { + 'derives': ['MallocSizeOf'] +}, + +'GPUTextureDescriptor': { + 'derives': ["MallocSizeOf"], +}, + +'HeadersInit': { + 'derives': ["Clone"], +}, +} + +Enums = { +'GPUFeatureName': { + 'derives': ['Hash', 'Eq'] +} +} + +Unions = { +'ByteStringSequenceSequenceOrByteStringByteStringRecord': { + 'derives': ['Clone'] +}, + +'HTMLCanvasElementOrOffscreenCanvas': { + 'derives': ['Clone', 'MallocSizeOf'] +}, + +'RangeEnforcedUnsignedLongSequenceOrGPUExtent3DDict': { + 'derives': ['MallocSizeOf'] +}, + +'StringOrUnsignedLong': { + 'derives': ['Clone'], +}, +} \ No newline at end of file diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index 6ac9ae1d5d9..83f183283ec 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -2649,7 +2649,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config): if name not in unionStructs: provider = descriptor or config.getDescriptorProvider() unionStructs[name] = CGList([ - CGUnionStruct(t, provider), + CGUnionStruct(t, provider, config), CGUnionConversionStruct(t, provider) ]) @@ -4865,14 +4865,18 @@ def getEnumValueName(value): class CGEnum(CGThing): - def __init__(self, enum): + def __init__(self, enum, config): CGThing.__init__(self) ident = enum.identifier.name enums = ",\n ".join(map(getEnumValueName, list(enum.values()))) + derives = ["Copy", "Clone", "Debug", "JSTraceable", "MallocSizeOf", "PartialEq"] + enum_config = config.getEnumConfig(ident) + extra_derives = enum_config.get('derives', []) + derives = ', '.join(derives + extra_derives) decl = f""" #[repr(usize)] -#[derive(Copy, Clone, Debug, JSTraceable, MallocSizeOf, PartialEq)] +#[derive({derives})] pub enum {ident} {{ {enums} }} @@ -4907,6 +4911,18 @@ impl Default for super::{ident} {{ }} }} +impl std::str::FromStr for super::{ident} {{ + type Err = (); + + fn from_str(s: &str) -> Result {{ + pairs + .iter() + .find(|&&(key, _)| s == key) + .map(|&(_, ev)| ev) + .ok_or(()) + }} +}} + impl ToJSValConvertible for super::{ident} {{ unsafe fn to_jsval(&self, cx: *mut JSContext, rval: MutableHandleValue) {{ pairs[*self as usize].0.to_jsval(cx, rval); @@ -5037,12 +5053,13 @@ def getUnionTypeTemplateVars(type, descriptorProvider): class CGUnionStruct(CGThing): - def __init__(self, type, descriptorProvider): + def __init__(self, type, descriptorProvider, config): assert not type.nullable() assert not type.hasNullableType CGThing.__init__(self) self.type = type + self.derives = config.getUnionConfig(str(type)).get('derives', []) self.descriptorProvider = descriptorProvider def membersNeedTracing(self): @@ -5071,8 +5088,9 @@ class CGUnionStruct(CGThing): ] joinedEnumValues = "\n".join(enumValues) joinedEnumConversions = "\n".join(enumConversions) + derives = ["JSTraceable"] + self.derives return f""" -#[derive(JSTraceable)] +#[derive({", ".join(derives)})] pub enum {self.type} {{ {joinedEnumValues} }} @@ -6879,9 +6897,10 @@ class CGNonNamespacedEnum(CGThing): class CGDictionary(CGThing): - def __init__(self, dictionary, descriptorProvider): + def __init__(self, dictionary, descriptorProvider, config): self.dictionary = dictionary - if all(CGDictionary(d, descriptorProvider).generatable for + self.derives = config.getDictConfig(dictionary.identifier.name).get('derives', []) + if all(CGDictionary(d, descriptorProvider, config).generatable for d in CGDictionary.getDictionaryDependencies(dictionary)): self.generatable = True else: @@ -6915,12 +6934,40 @@ class CGDictionary(CGThing): memberDecls = [f" pub {self.makeMemberName(m[0].identifier.name)}: {self.getMemberType(m)}," for m in self.memberInfo] - derive = ["JSTraceable"] + derive = ["JSTraceable"] + self.derives + default = "" mustRoot = "" if self.membersNeedTracing(): mustRoot = "#[crown::unrooted_must_root_lint::must_root]\n" - if not self.hasRequiredFields(self.dictionary): - derive += ["Default"] + + # We can't unconditionally derive Default here, because union types can have unique + # default values provided for each usage. Instead, whenever possible we re-use the empty() + # method that is generated. + if not self.hasRequiredFields(self.dictionary): + if d.parent: + inheritanceDefault = " parent: Default::default(),\n" + else: + inheritanceDefault = "" + if not self.membersNeedTracing(): + impl = " Self::empty()\n" + else: + memberDefaults = [f" {self.makeMemberName(m[0].identifier.name)}: Default::default()," + for m in self.memberInfo] + joinedDefaults = '\n'.join(memberDefaults) + impl = ( + " Self {\n" + f" {inheritanceDefault}{joinedDefaults}" + " }\n" + ) + + default = ( + f"impl Default for {self.makeClassName(d)} {{\n" + " fn default() -> Self {\n" + f"{impl}" + " }\n" + "}\n" + ) + joinedMemberDecls = '\n'.join(memberDecls) return ( f"#[derive({', '.join(derive)})]\n" @@ -6928,7 +6975,8 @@ class CGDictionary(CGThing): f"pub struct {self.makeClassName(d)} {{\n" f"{inheritance}" f"{joinedMemberDecls}\n" - "}" + "}\n" + f"{default}" ) def impl(self): @@ -7227,7 +7275,7 @@ class CGBindingRoot(CGThing): return # Do codegen for all the enums. - cgthings = [CGEnum(e) for e in enums] + cgthings = [CGEnum(e, config) for e in enums] # Do codegen for all the typedefs for t in typedefs: @@ -7244,7 +7292,7 @@ class CGBindingRoot(CGThing): cgthings.append(CGGeneric(typeDefinition)) # Do codegen for all the dictionaries. - cgthings.extend([CGDictionary(d, config.getDescriptorProvider()) + cgthings.extend([CGDictionary(d, config.getDescriptorProvider(), config) for d in dictionaries]) # Do codegen for all the callbacks. @@ -8145,7 +8193,10 @@ class GlobalGenRoots(): descriptors = (set(toBindingModuleFile(d.name) for d in descriptors if d.maybeGetSuperModule() is None) | set(leafModule(d) for d in config.callbacks) | set(leafModule(d) for d in config.getDictionaries())) - curr = CGList([CGGeneric(f"pub mod {name};\n") for name in sorted(descriptors)]) + curr = CGList([CGGeneric( + "#[allow(clippy::derivable_impls)]\n" + f"pub mod {name};\n" + ) for name in sorted(descriptors)]) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) return curr diff --git a/components/script/dom/bindings/codegen/Configuration.py b/components/script/dom/bindings/codegen/Configuration.py index 2f067c39256..b887fe91931 100644 --- a/components/script/dom/bindings/codegen/Configuration.py +++ b/components/script/dom/bindings/codegen/Configuration.py @@ -18,6 +18,9 @@ class Configuration: glbl = {} exec(compile(open(filename).read(), filename, 'exec'), glbl) config = glbl['DOMInterfaces'] + self.enumConfig = glbl['Enums'] + self.dictConfig = glbl['Dictionaries'] + self.unionConfig = glbl['Unions'] # Build descriptors for all the interfaces we have in the parse data. # This allows callers to specify a subset of interfaces by filtering @@ -110,6 +113,9 @@ class Configuration: def getEnums(self, webIDLFile): return [e for e in self.enums if e.filename == webIDLFile] + def getEnumConfig(self, name): + return self.enumConfig.get(name, {}) + def getTypedefs(self, webIDLFile): return [e for e in self.typedefs if e.filename == webIDLFile] @@ -121,9 +127,15 @@ class Configuration: return [x for x in items if x.filename == webIDLFile] + def getUnionConfig(self, name): + return self.unionConfig.get(name, {}) + def getDictionaries(self, webIDLFile=""): return self._filterForFile(self.dictionaries, webIDLFile=webIDLFile) + def getDictConfig(self, name): + return self.dictConfig.get(name, {}) + def getCallbacks(self, webIDLFile=""): return self._filterForFile(self.callbacks, webIDLFile=webIDLFile) diff --git a/components/script/dom/bluetoothuuid.rs b/components/script/dom/bluetoothuuid.rs index 9c2d053f8d7..e39937d3b3d 100644 --- a/components/script/dom/bluetoothuuid.rs +++ b/components/script/dom/bluetoothuuid.rs @@ -624,15 +624,6 @@ impl BluetoothUUID { } } -impl Clone for StringOrUnsignedLong { - fn clone(&self) -> StringOrUnsignedLong { - match self { - StringOrUnsignedLong::String(s) => StringOrUnsignedLong::String(s.clone()), - &StringOrUnsignedLong::UnsignedLong(ul) => StringOrUnsignedLong::UnsignedLong(ul), - } - } -} - fn canonical_uuid(alias: u32) -> UUID { UUID::from(format!("{:08x}", &alias) + BASE_UUID) } diff --git a/components/script/dom/event.rs b/components/script/dom/event.rs index a591656a694..52b8b838787 100644 --- a/components/script/dom/event.rs +++ b/components/script/dom/event.rs @@ -753,9 +753,3 @@ fn inner_invoke( // Step 3. found } - -impl Default for EventBinding::EventInit { - fn default() -> Self { - Self::empty() - } -} diff --git a/components/script/dom/extendableevent.rs b/components/script/dom/extendableevent.rs index c5e0bac0baa..1bec9c8cf25 100644 --- a/components/script/dom/extendableevent.rs +++ b/components/script/dom/extendableevent.rs @@ -102,9 +102,3 @@ impl ExtendableEventMethods for ExtendableEvent { self.event.IsTrusted() } } - -impl Default for ExtendableEventInit { - fn default() -> Self { - Self::empty() - } -} diff --git a/components/script/dom/gpucanvascontext.rs b/components/script/dom/gpucanvascontext.rs index c20f1d1d877..2f443c2d7ea 100644 --- a/components/script/dom/gpucanvascontext.rs +++ b/components/script/dom/gpucanvascontext.rs @@ -39,60 +39,6 @@ use crate::dom::globalscope::GlobalScope; use crate::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutCanvasRenderingContextHelpers}; use crate::dom::node::{document_from_node, Node, NodeDamage}; -// TODO: make all this derivables available via new Bindings.conf option -impl Clone for GPUCanvasConfiguration { - fn clone(&self) -> Self { - Self { - alphaMode: self.alphaMode, - device: self.device.clone(), - format: self.format, - usage: self.usage, - viewFormats: self.viewFormats.clone(), - } - } -} - -impl Clone for HTMLCanvasElementOrOffscreenCanvas { - fn clone(&self) -> Self { - match self { - Self::HTMLCanvasElement(arg0) => Self::HTMLCanvasElement(arg0.clone()), - Self::OffscreenCanvas(arg0) => Self::OffscreenCanvas(arg0.clone()), - } - } -} - -impl malloc_size_of::MallocSizeOf for GPUTextureDescriptor { - fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize { - let Self { - parent, - dimension, - format, - mipLevelCount, - sampleCount, - size, - usage, - viewFormats, - } = self; - parent.size_of(ops) + - dimension.size_of(ops) + - format.size_of(ops) + - mipLevelCount.size_of(ops) + - sampleCount.size_of(ops) + - size.size_of(ops) + - usage.size_of(ops) + - viewFormats.size_of(ops) - } -} - -impl malloc_size_of::MallocSizeOf for HTMLCanvasElementOrOffscreenCanvas { - fn size_of(&self, ops: &mut malloc_size_of::MallocSizeOfOps) -> usize { - match self { - HTMLCanvasElementOrOffscreenCanvas::HTMLCanvasElement(canvas) => canvas.size_of(ops), - HTMLCanvasElementOrOffscreenCanvas::OffscreenCanvas(canvas) => canvas.size_of(ops), - } - } -} - impl HTMLCanvasElementOrOffscreenCanvas { fn size(&self) -> Size2D { match self { diff --git a/components/script/dom/gpusupportedfeatures.rs b/components/script/dom/gpusupportedfeatures.rs index 797b2635925..07242113f9e 100644 --- a/components/script/dom/gpusupportedfeatures.rs +++ b/components/script/dom/gpusupportedfeatures.rs @@ -4,8 +4,6 @@ // check-tidy: no specs after this line -use std::str::FromStr; - use dom_struct::dom_struct; use indexmap::IndexSet; use js::rust::HandleObject; @@ -13,7 +11,6 @@ use webgpu::wgt::Features; use super::bindings::like::Setlike; use crate::dom::bindings::cell::DomRefCell; -use crate::dom::bindings::codegen::Bindings::WebGPUBinding::GPUFeatureNameValues::pairs; use crate::dom::bindings::codegen::Bindings::WebGPUBinding::{ GPUFeatureName, GPUSupportedFeaturesMethods, }; @@ -24,16 +21,6 @@ use crate::dom::bindings::str::DOMString; use crate::dom::globalscope::GlobalScope; use crate::script_runtime::CanGc; -// manual hash derived -// TODO: allow derivables in bindings.conf -impl std::hash::Hash for GPUFeatureName { - fn hash(&self, state: &mut H) { - core::mem::discriminant(self).hash(state); - } -} - -impl Eq for GPUFeatureName {} - #[dom_struct] pub struct GPUSupportedFeatures { reflector: Reflector, @@ -152,19 +139,6 @@ pub fn gpu_to_wgt_feature(feature: GPUFeatureName) -> Option { } } -// this should be autogenerate by bindings -impl FromStr for GPUFeatureName { - type Err = (); - - fn from_str(s: &str) -> Result { - pairs - .iter() - .find(|&&(key, _)| s == key) - .map(|&(_, ev)| ev) - .ok_or(()) - } -} - // this error is wrong because if we inline Self::Key and Self::Value all errors are gone #[allow(crown::unrooted_must_root)] impl Setlike for GPUSupportedFeatures { diff --git a/components/script/dom/request.rs b/components/script/dom/request.rs index 39d32c135cb..31886e41a0c 100644 --- a/components/script/dom/request.rs +++ b/components/script/dom/request.rs @@ -857,16 +857,3 @@ impl From for RequestRedirect { } } } - -impl Clone for HeadersInit { - fn clone(&self) -> HeadersInit { - match self { - HeadersInit::ByteStringSequenceSequence(b) => { - HeadersInit::ByteStringSequenceSequence(b.clone()) - }, - HeadersInit::ByteStringByteStringRecord(m) => { - HeadersInit::ByteStringByteStringRecord(m.clone()) - }, - } - } -} diff --git a/support/crown/src/unrooted_must_root.rs b/support/crown/src/unrooted_must_root.rs index 4d6cf5a283b..fe99def5c52 100644 --- a/support/crown/src/unrooted_must_root.rs +++ b/support/crown/src/unrooted_must_root.rs @@ -290,7 +290,7 @@ impl<'tcx> LateLintPass<'tcx> for UnrootedPass { ) { let in_new_function = match kind { visit::FnKind::ItemFn(n, _, _) | visit::FnKind::Method(n, _) => { - n.as_str() == "new" || n.as_str().starts_with("new_") + n.as_str() == "new" || n.as_str().starts_with("new_") || n.as_str() == "default" }, visit::FnKind::Closure => return, };