summaryrefslogtreecommitdiffstats
path: root/dom/bindings/Codegen.py
diff options
context:
space:
mode:
Diffstat (limited to 'dom/bindings/Codegen.py')
-rw-r--r--dom/bindings/Codegen.py345
1 files changed, 175 insertions, 170 deletions
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 7a6a28bffc..a6a49f9b2f 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -926,11 +926,51 @@ def InterfaceObjectProtoGetter(descriptor, forXrays=False):
return (protoGetter, protoHandleGetter)
-class CGInterfaceObjectJSClass(CGThing):
- def __init__(self, descriptor, properties):
+class CGNamespaceObjectJSClass(CGThing):
+ def __init__(self, descriptor):
+ CGThing.__init__(self)
+ self.descriptor = descriptor
+
+ def declare(self):
+ # We're purely for internal consumption
+ return ""
+
+ def define(self):
+ (protoGetter, _) = InterfaceObjectProtoGetter(self.descriptor, forXrays=True)
+
+ classString = self.descriptor.interface.getExtendedAttribute("ClassString")
+ if classString is None:
+ classString = self.descriptor.interface.identifier.name
+ else:
+ classString = classString[0]
+ return fill(
+ """
+ static const DOMIfaceAndProtoJSClass sNamespaceObjectClass = {
+ {
+ "${classString}",
+ JSCLASS_IS_DOMIFACEANDPROTOJSCLASS,
+ JS_NULL_CLASS_OPS,
+ JS_NULL_CLASS_SPEC,
+ JS_NULL_CLASS_EXT,
+ JS_NULL_OBJECT_OPS
+ },
+ eNamespace,
+ prototypes::id::_ID_Count,
+ 0,
+ ${hooks},
+ ${protoGetter}
+ };
+ """,
+ classString=classString,
+ hooks=NativePropertyHooks(self.descriptor),
+ protoGetter=protoGetter,
+ )
+
+
+class CGInterfaceObjectInfo(CGThing):
+ def __init__(self, descriptor):
CGThing.__init__(self)
self.descriptor = descriptor
- self.properties = properties
def declare(self):
# We're purely for internal consumption
@@ -938,104 +978,31 @@ class CGInterfaceObjectJSClass(CGThing):
def define(self):
if self.descriptor.interface.ctor():
- assert not self.descriptor.interface.isNamespace()
ctorname = CONSTRUCT_HOOK_NAME
- elif self.descriptor.interface.isNamespace():
- ctorname = "nullptr"
else:
ctorname = "ThrowingConstructor"
wantsIsInstance = self.descriptor.interface.hasInterfacePrototypeObject()
prototypeID, depth = PrototypeIDAndDepth(self.descriptor)
- slotCount = "DOM_INTERFACE_SLOTS_BASE"
- if len(self.descriptor.interface.legacyFactoryFunctions) > 0:
- slotCount += " + %i /* slots for the legacy factory functions */" % len(
- self.descriptor.interface.legacyFactoryFunctions
- )
(protoGetter, _) = InterfaceObjectProtoGetter(self.descriptor, forXrays=True)
- if ctorname == "ThrowingConstructor":
- ret = ""
- classOpsPtr = "&sBoringInterfaceObjectClassClassOps"
- elif ctorname == "nullptr":
- ret = ""
- classOpsPtr = "JS_NULL_CLASS_OPS"
- else:
- ret = fill(
- """
- static const JSClassOps sInterfaceObjectClassOps = {
- nullptr, /* addProperty */
- nullptr, /* delProperty */
- nullptr, /* enumerate */
- nullptr, /* newEnumerate */
- nullptr, /* resolve */
- nullptr, /* mayResolve */
- nullptr, /* finalize */
- ${ctorname}, /* call */
- ${ctorname}, /* construct */
- nullptr, /* trace */
- };
-
- """,
- ctorname=ctorname,
- )
- classOpsPtr = "&sInterfaceObjectClassOps"
-
- if self.descriptor.interface.isNamespace():
- classString = self.descriptor.interface.getExtendedAttribute("ClassString")
- if classString is None:
- classString = self.descriptor.interface.identifier.name
- else:
- classString = classString[0]
- funToString = "nullptr"
- objectOps = "JS_NULL_OBJECT_OPS"
- else:
- classString = "Function"
- funToString = (
- '"function %s() {\\n [native code]\\n}"'
- % self.descriptor.interface.identifier.name
- )
- # We need non-default ObjectOps so we can actually make
- # use of our funToString.
- objectOps = "&sInterfaceObjectClassObjectOps"
-
- ret = ret + fill(
+ return fill(
"""
- static const DOMIfaceJSClass sInterfaceObjectClass = {
- {
- {
- "${classString}",
- JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(${slotCount}),
- ${classOpsPtr},
- JS_NULL_CLASS_SPEC,
- JS_NULL_CLASS_EXT,
- ${objectOps}
- },
- ${type},
- ${prototypeID},
- ${depth},
- ${hooks},
- ${protoGetter}
- },
+ static const DOMInterfaceInfo sInterfaceObjectInfo = {
+ { ${ctorname}, ${hooks} },
+ ${protoGetter},
+ ${prototypeID},
+ ${depth},
${wantsIsInstance},
- ${funToString}
};
""",
- classString=classString,
- slotCount=slotCount,
- classOpsPtr=classOpsPtr,
+ ctorname=ctorname,
hooks=NativePropertyHooks(self.descriptor),
- objectOps=objectOps,
- type="eNamespace"
- if self.descriptor.interface.isNamespace()
- else "eInterface",
+ protoGetter=protoGetter,
prototypeID=prototypeID,
depth=depth,
- protoGetter=protoGetter,
wantsIsInstance=toStringBool(wantsIsInstance),
- funToString=funToString,
)
- return ret
class CGList(CGThing):
@@ -2323,7 +2290,6 @@ class CGLegacyFactoryFunctions(CGThing):
static const LegacyFactoryFunction legacyFactoryFunctions[] = {
$*{legacyFactoryFunctions}
- { nullptr, { nullptr, nullptr }, 0 }
};
""",
name=self.descriptor.name,
@@ -3538,83 +3504,30 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
self.haveLegacyWindowAliases = haveLegacyWindowAliases
def definition_body(self):
- (protoGetter, protoHandleGetter) = InterfacePrototypeObjectProtoGetter(
- self.descriptor
- )
- if protoHandleGetter is None:
- parentProtoType = "Rooted"
- getParentProto = "aCx, " + protoGetter
- else:
- parentProtoType = "Handle"
- getParentProto = protoHandleGetter
- getParentProto = getParentProto + "(aCx)"
-
- (protoGetter, protoHandleGetter) = InterfaceObjectProtoGetter(self.descriptor)
- if protoHandleGetter is None:
- getConstructorProto = "aCx, " + protoGetter
- constructorProtoType = "Rooted"
- else:
- getConstructorProto = protoHandleGetter
- constructorProtoType = "Handle"
- getConstructorProto += "(aCx)"
-
needInterfaceObject = self.descriptor.interface.hasInterfaceObject()
- needInterfacePrototypeObject = (
- self.descriptor.interface.hasInterfacePrototypeObject()
- )
-
- # if we don't need to create anything, why are we generating this?
- assert needInterfaceObject or needInterfacePrototypeObject
-
- getParentProto = fill(
- """
- JS::${type}<JSObject*> parentProto(${getParentProto});
- if (!parentProto) {
- return;
- }
- """,
- type=parentProtoType,
- getParentProto=getParentProto,
- )
-
- getConstructorProto = fill(
- """
- JS::${type}<JSObject*> constructorProto(${getConstructorProto});
- if (!constructorProto) {
- return;
- }
- """,
- type=constructorProtoType,
- getConstructorProto=getConstructorProto,
- )
-
- if self.descriptor.interface.ctor():
- constructArgs = methodLength(self.descriptor.interface.ctor())
- isConstructorChromeOnly = isChromeOnly(self.descriptor.interface.ctor())
- else:
- constructArgs = 0
- isConstructorChromeOnly = False
- if len(self.descriptor.interface.legacyFactoryFunctions) > 0:
- legacyFactoryFunctions = "legacyFactoryFunctions"
- else:
- legacyFactoryFunctions = "nullptr"
+ if needInterfaceObject:
+ (protoGetter, protoHandleGetter) = InterfaceObjectProtoGetter(
+ self.descriptor
+ )
+ if protoHandleGetter is None:
+ getConstructorProto = "aCx, " + protoGetter
+ constructorProtoType = "Rooted"
+ else:
+ getConstructorProto = protoHandleGetter
+ constructorProtoType = "Handle"
- if needInterfacePrototypeObject:
- protoClass = "&sPrototypeClass"
- protoCache = (
- "&aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::%s)"
- % self.descriptor.name
+ getConstructorProto = fill(
+ """
+ JS::${type}<JSObject*> constructorProto(${getConstructorProto}(aCx));
+ if (!constructorProto) {
+ return;
+ }
+ """,
+ type=constructorProtoType,
+ getConstructorProto=getConstructorProto,
)
- parentProto = "parentProto"
- getParentProto = CGGeneric(getParentProto)
- else:
- protoClass = "nullptr"
- protoCache = "nullptr"
- parentProto = "nullptr"
- getParentProto = None
- if needInterfaceObject:
- interfaceClass = "&sInterfaceObjectClass"
+ interfaceInfo = "&sInterfaceObjectInfo"
interfaceCache = (
"&aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::%s)"
% self.descriptor.name
@@ -3624,12 +3537,11 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
else:
# We don't have slots to store the legacy factory functions.
assert len(self.descriptor.interface.legacyFactoryFunctions) == 0
- interfaceClass = "nullptr"
+ interfaceInfo = "nullptr"
interfaceCache = "nullptr"
getConstructorProto = None
constructorProto = "nullptr"
- isGlobal = self.descriptor.isGlobal() is not None
if self.properties.hasNonChromeOnly():
properties = "sNativeProperties.Upcast()"
else:
@@ -3648,31 +3560,117 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
name = self.descriptor.interface.getClassName()
assert not (needInterfaceObject and " " in name)
- call = fill(
+ if self.descriptor.interface.isNamespace():
+ # If we don't need to create anything, why are we generating this?
+ assert needInterfaceObject
+
+ call = fill(
+ """
+ JS::Heap<JSObject*>* interfaceCache = ${interfaceCache};
+ dom::CreateNamespaceObject(aCx, aGlobal, ${constructorProto},
+ sNamespaceObjectClass,
+ interfaceCache,
+ ${properties},
+ ${chromeProperties},
+ "${name}", aDefineOnGlobal);
+ """,
+ interfaceCache=interfaceCache,
+ constructorProto=constructorProto,
+ properties=properties,
+ chromeProperties=chromeProperties,
+ name=name,
+ )
+ return CGList(
+ [
+ getConstructorProto,
+ CGGeneric(call),
+ ],
+ "\n",
+ ).define()
+
+ needInterfacePrototypeObject = (
+ self.descriptor.interface.hasInterfacePrototypeObject()
+ )
+
+ # If we don't need to create anything, why are we generating this?
+ assert needInterfaceObject or needInterfacePrototypeObject
+
+ if needInterfacePrototypeObject:
+ (protoGetter, protoHandleGetter) = InterfacePrototypeObjectProtoGetter(
+ self.descriptor
+ )
+ if protoHandleGetter is None:
+ parentProtoType = "Rooted"
+ getParentProto = "aCx, " + protoGetter
+ else:
+ parentProtoType = "Handle"
+ getParentProto = protoHandleGetter
+
+ getParentProto = fill(
+ """
+ JS::${type}<JSObject*> parentProto(${getParentProto}(aCx));
+ if (!parentProto) {
+ return;
+ }
+ """,
+ type=parentProtoType,
+ getParentProto=getParentProto,
+ )
+
+ protoClass = "&sPrototypeClass"
+ protoCache = (
+ "&aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::%s)"
+ % self.descriptor.name
+ )
+ parentProto = "parentProto"
+ getParentProto = CGGeneric(getParentProto)
+ else:
+ protoClass = "nullptr"
+ protoCache = "nullptr"
+ parentProto = "nullptr"
+ getParentProto = None
+
+ if self.descriptor.interface.ctor():
+ constructArgs = methodLength(self.descriptor.interface.ctor())
+ isConstructorChromeOnly = isChromeOnly(self.descriptor.interface.ctor())
+ else:
+ constructArgs = 0
+ isConstructorChromeOnly = False
+ if len(self.descriptor.interface.legacyFactoryFunctions) > 0:
+ legacyFactoryFunctions = "Span(legacyFactoryFunctions)"
+ else:
+ legacyFactoryFunctions = "Span<const LegacyFactoryFunction, 0>{}"
+
+ isGlobal = self.descriptor.isGlobal() is not None
+
+ ensureCaches = fill(
"""
JS::Heap<JSObject*>* protoCache = ${protoCache};
JS::Heap<JSObject*>* interfaceCache = ${interfaceCache};
+ """,
+ protoCache=protoCache,
+ interfaceCache=interfaceCache,
+ )
+ call = fill(
+ """
dom::CreateInterfaceObjects(aCx, aGlobal, ${parentProto},
${protoClass}, protoCache,
- ${constructorProto}, ${interfaceClass}, ${constructArgs}, ${isConstructorChromeOnly}, ${legacyFactoryFunctions},
+ ${constructorProto}, ${interfaceInfo}, ${constructArgs}, ${isConstructorChromeOnly}, ${legacyFactoryFunctions},
interfaceCache,
${properties},
${chromeProperties},
"${name}", aDefineOnGlobal,
${unscopableNames},
${isGlobal},
- ${legacyWindowAliases},
- ${isNamespace});
+ ${legacyWindowAliases});
""",
protoClass=protoClass,
parentProto=parentProto,
- protoCache=protoCache,
constructorProto=constructorProto,
- interfaceClass=interfaceClass,
+ interfaceInfo=interfaceInfo,
constructArgs=constructArgs,
isConstructorChromeOnly=toStringBool(isConstructorChromeOnly),
legacyFactoryFunctions=legacyFactoryFunctions,
- interfaceCache=interfaceCache,
properties=properties,
chromeProperties=chromeProperties,
name=name,
@@ -3681,7 +3679,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
legacyWindowAliases="legacyWindowAliases"
if self.haveLegacyWindowAliases
else "nullptr",
- isNamespace=toStringBool(self.descriptor.interface.isNamespace()),
)
# If we fail after here, we must clear interface and prototype caches
@@ -3896,8 +3893,14 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
)
else:
defineProtoVar = None
+
+ # ensureCaches needs to come first as it crashes on failure (like OOM).
+ # We want to make sure that the caches do exist before we try to return
+ # to the caller, so it can rely on that (and detect other failures by
+ # checking for null in the caches).
return CGList(
[
+ CGGeneric(ensureCaches),
getParentProto,
getConstructorProto,
CGGeneric(call),
@@ -16955,9 +16958,11 @@ class CGDescriptor(CGThing):
# done, set up our NativePropertyHooks.
cgThings.append(CGNativePropertyHooks(descriptor, properties))
- if descriptor.interface.hasInterfaceObject():
+ if descriptor.interface.isNamespace():
+ cgThings.append(CGNamespaceObjectJSClass(descriptor))
+ elif descriptor.interface.hasInterfaceObject():
cgThings.append(CGClassConstructor(descriptor, descriptor.interface.ctor()))
- cgThings.append(CGInterfaceObjectJSClass(descriptor, properties))
+ cgThings.append(CGInterfaceObjectInfo(descriptor))
cgThings.append(CGLegacyFactoryFunctions(descriptor))
cgThings.append(CGLegacyCallHook(descriptor))