Auto merge of #29798 - jdm:per-interface-codegen, r=jdm

Extract bodies of generated binding helpers into common code

This is part of fixing #29770, by extracting common behaviour that [will be called](https://searchfox.org/mozilla-central/rev/2d678a843ceab81e43f7ffb83212197dc10e944a/dom/bindings/BindingUtils.cpp#3744) from new code in interface.rs.

---
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] There are tests for these changes
This commit is contained in:
bors-servo 2023-05-26 08:18:51 +02:00 committed by GitHub
commit 43ebf6c82c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 30 deletions

View file

@ -3490,24 +3490,12 @@ class CGGetPerInterfaceObject(CGAbstractMethod):
CGAbstractMethod.__init__(self, descriptor, name,
'void', args, pub=pub)
self.id = idPrefix + "::" + MakeNativeName(self.descriptor.name)
self.variant = self.id.split('::')[-2]
def definition_body(self):
return CGGeneric("""
unsafe {
assert!(((*get_object_class(global.get())).flags & JSCLASS_DOM_GLOBAL) != 0);
/* Check to see whether the interface objects are already installed */
let proto_or_iface_array = get_proto_or_iface_array(global.get());
rval.set((*proto_or_iface_array)[%(id)s as usize]);
if !rval.get().is_null() {
return;
}
CreateInterfaceObjects(cx, global, proto_or_iface_array);
rval.set((*proto_or_iface_array)[%(id)s as usize]);
assert!(!rval.get().is_null());
}
""" % {"id": self.id})
get_per_interface_object_handle(cx, global, ProtoOrIfaceIndex::%s(%s), CreateInterfaceObjects, rval)
""" % (self.variant, self.id))
class CGGetProtoObjectMethod(CGGetPerInterfaceObject):
@ -3655,25 +3643,20 @@ class CGDefineDOMInterfaceMethod(CGAbstractMethod):
]
CGAbstractMethod.__init__(self, descriptor, 'DefineDOMInterface',
'void', args, pub=True)
if self.descriptor.interface.isCallback() or self.descriptor.interface.isNamespace():
idPrefix = "PrototypeList::Constructor"
else:
idPrefix = "PrototypeList::ID"
self.id = idPrefix + "::" + MakeNativeName(self.descriptor.name)
self.variant = self.id.split('::')[-2]
def define(self):
return CGAbstractMethod.define(self)
def definition_body(self):
if self.descriptor.interface.isCallback() or self.descriptor.interface.isNamespace():
function = "GetConstructorObject"
else:
function = "GetProtoObject"
return CGGeneric("""\
assert!(!global.get().is_null());
if !ConstructorEnabled(cx, global) {
return;
}
rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
%s(cx, global, proto.handle_mut());
assert!(!proto.is_null());""" % (function,))
return CGGeneric("""
define_dom_interface(cx, global, ProtoOrIfaceIndex::%s(%s), CreateInterfaceObjects, ConstructorEnabled)
""" % (self.variant, self.id))
def needCx(returnType, arguments, considerTypes):
@ -6444,15 +6427,18 @@ def generate_imports(config, cgthings, descriptors, callbacks=None, dictionaries
'crate::dom::bindings::interface::ConstructorClassHook',
'crate::dom::bindings::interface::InterfaceConstructorBehavior',
'crate::dom::bindings::interface::NonCallbackInterfaceObjectClass',
'crate::dom::bindings::interface::ProtoOrIfaceIndex',
'crate::dom::bindings::interface::create_global_object',
'crate::dom::bindings::interface::create_callback_interface_object',
'crate::dom::bindings::interface::create_interface_prototype_object',
'crate::dom::bindings::interface::create_named_constructors',
'crate::dom::bindings::interface::create_noncallback_interface_object',
'crate::dom::bindings::interface::define_dom_interface',
'crate::dom::bindings::interface::define_guarded_constants',
'crate::dom::bindings::interface::define_guarded_methods',
'crate::dom::bindings::interface::define_guarded_properties',
'crate::dom::bindings::interface::is_exposed_in',
'crate::dom::bindings::interface::get_per_interface_object_handle',
'crate::dom::bindings::htmlconstructor::pop_current_element_queue',
'crate::dom::bindings::htmlconstructor::push_new_element_queue',
'crate::dom::bindings::iterable::Iterable',

View file

@ -10,7 +10,9 @@ use crate::dom::bindings::constant::{define_constants, ConstantSpec};
use crate::dom::bindings::conversions::{get_dom_class, DOM_OBJECT_SLOT};
use crate::dom::bindings::guard::Guard;
use crate::dom::bindings::principals::ServoJSPrincipals;
use crate::dom::bindings::utils::{ProtoOrIfaceArray, DOM_PROTOTYPE_SLOT};
use crate::dom::bindings::utils::{
get_proto_or_iface_array, ProtoOrIfaceArray, DOM_PROTOTYPE_SLOT, JSCLASS_DOM_GLOBAL,
};
use crate::script_runtime::JSContext as SafeJSContext;
use js::error::throw_type_error;
use js::glue::UncheckedUnwrapObject;
@ -534,3 +536,59 @@ unsafe extern "C" fn non_new_constructor(
throw_type_error(cx, "This constructor needs to be called with `new`.");
false
}
pub enum ProtoOrIfaceIndex {
ID(PrototypeList::ID),
Constructor(PrototypeList::Constructor),
}
impl Into<usize> for ProtoOrIfaceIndex {
fn into(self) -> usize {
match self {
ProtoOrIfaceIndex::ID(id) => id as usize,
ProtoOrIfaceIndex::Constructor(constructor) => constructor as usize,
}
}
}
pub fn get_per_interface_object_handle(
cx: SafeJSContext,
global: HandleObject,
id: ProtoOrIfaceIndex,
creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
mut rval: MutableHandleObject,
) {
unsafe {
assert!(((*get_object_class(global.get())).flags & JSCLASS_DOM_GLOBAL) != 0);
/* Check to see whether the interface objects are already installed */
let proto_or_iface_array = get_proto_or_iface_array(global.get());
let index: usize = id.into();
rval.set((*proto_or_iface_array)[index]);
if !rval.get().is_null() {
return;
}
creator(cx, global, proto_or_iface_array);
rval.set((*proto_or_iface_array)[index]);
assert!(!rval.get().is_null());
}
}
pub fn define_dom_interface(
cx: SafeJSContext,
global: HandleObject,
id: ProtoOrIfaceIndex,
creator: unsafe fn(SafeJSContext, HandleObject, *mut ProtoOrIfaceArray),
enabled: fn(SafeJSContext, HandleObject) -> bool,
) {
assert!(!global.get().is_null());
if !enabled(cx, global) {
return;
}
rooted!(in(*cx) let mut proto = ptr::null_mut::<JSObject>());
get_per_interface_object_handle(cx, global, id, creator, proto.handle_mut());
assert!(!proto.is_null());
}