diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:29 +0000 |
commit | 59203c63bb777a3bacec32fb8830fba33540e809 (patch) | |
tree | 58298e711c0ff0575818c30485b44a2f21bf28a0 /xpcom/idl-parser/xpidl | |
parent | Adding upstream version 126.0.1. (diff) | |
download | firefox-59203c63bb777a3bacec32fb8830fba33540e809.tar.xz firefox-59203c63bb777a3bacec32fb8830fba33540e809.zip |
Adding upstream version 127.0.upstream/127.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xpcom/idl-parser/xpidl')
-rw-r--r-- | xpcom/idl-parser/xpidl/fixtures/xpctest.d.json | 2 | ||||
-rwxr-xr-x | xpcom/idl-parser/xpidl/xpidl.py | 97 |
2 files changed, 93 insertions, 6 deletions
diff --git a/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json index 087a323dd4..b81760c0f5 100644 --- a/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json +++ b/xpcom/idl-parser/xpidl/fixtures/xpctest.d.json @@ -1313,7 +1313,7 @@ "callable": false, "consts": [], "enums": [], - "id": "nsIXPCTestNoScriptMembers", + "id": "nsIXPCTestTypeScript", "members": [ { "name": "exposedProp", diff --git a/xpcom/idl-parser/xpidl/xpidl.py b/xpcom/idl-parser/xpidl/xpidl.py index 11b5d05e58..59e4e355de 100755 --- a/xpcom/idl-parser/xpidl/xpidl.py +++ b/xpcom/idl-parser/xpidl/xpidl.py @@ -524,6 +524,8 @@ class Typedef(object): return "%s%s" % ("*mut " if "out" in calltype else "", self.name) def tsType(self): + # Make sure that underlying type is supported: doesn't throw TSNoncompat. + self.realtype.tsType() return self.name def __str__(self): @@ -1214,19 +1216,24 @@ def ensureInfallibleIsSound(methodOrAttribute): if methodOrAttribute.notxpcom: raise IDLError( - "[infallible] does not make sense for a [notxpcom] " "method or attribute", + "[infallible] does not make sense for a [notxpcom] method or attribute", methodOrAttribute.location, ) # An interface cannot be implemented by JS if it has a notxpcom or nostdcall -# method or attribute, so it must be marked as builtinclass. +# method or attribute, or uses a by-value native type, so it must be marked as +# builtinclass. def ensureBuiltinClassIfNeeded(methodOrAttribute): iface = methodOrAttribute.iface if not iface.attributes.scriptable or iface.attributes.builtinclass: return if iface.name == "nsISupports": return + + # notxpcom and nostdcall types change calling conventions, which breaks + # xptcall wrappers. We cannot allow XPCWrappedJS to be created for + # interfaces with these methods. if methodOrAttribute.notxpcom: raise IDLError( ( @@ -1246,6 +1253,84 @@ def ensureBuiltinClassIfNeeded(methodOrAttribute): methodOrAttribute.location, ) + # Methods with custom native parameters passed without indirection cannot be + # safely handled by xptcall (as it cannot know the calling stack/register + # layout), so require the interface to be builtinclass. + # + # Only "in" parameters and writable attributes are checked, as other + # parameters are always passed indirectly, so do not impact calling + # conventions. + def typeNeedsBuiltinclass(type): + inner = type + while inner.kind == "typedef": + inner = inner.realtype + return ( + inner.kind == "native" + and inner.specialtype is None + and inner.modifier is None + ) + + if methodOrAttribute.kind == "method": + for p in methodOrAttribute.params: + if p.paramtype == "in" and typeNeedsBuiltinclass(p.realtype): + raise IDLError( + ( + "scriptable interface '%s' must be marked [builtinclass] " + "because it contains method '%s' with a by-value custom native " + "parameter '%s'" + ) + % (iface.name, methodOrAttribute.name, p.name), + methodOrAttribute.location, + ) + elif methodOrAttribute.kind == "attribute" and not methodOrAttribute.readonly: + if typeNeedsBuiltinclass(methodOrAttribute.realtype): + raise IDLError( + ( + "scriptable interface '%s' must be marked [builtinclass] because it " + "contains writable attribute '%s' with a by-value custom native type" + ) + % (iface.name, methodOrAttribute.name), + methodOrAttribute.location, + ) + + +def ensureNoscriptIfNeeded(methodOrAttribute): + if not methodOrAttribute.isScriptable(): + return + + # NOTE: We can't check forward-declared interfaces to see if they're + # scriptable, as the information about whether they're scriptable is not + # known here. + def typeNeedsNoscript(type): + if type.kind in ["array", "legacyarray"]: + return typeNeedsNoscript(type.type) + if type.kind == "typedef": + return typeNeedsNoscript(type.realtype) + if type.kind == "native": + return type.specialtype is None + if type.kind == "interface": + return not type.attributes.scriptable + return False + + if typeNeedsNoscript(methodOrAttribute.realtype): + raise IDLError( + "%s '%s' must be marked [noscript] because it has a non-scriptable type" + % (methodOrAttribute.kind, methodOrAttribute.name), + methodOrAttribute.location, + ) + if methodOrAttribute.kind == "method": + for p in methodOrAttribute.params: + # iid_is arguments have their type ignored, so shouldn't be checked. + if not p.iid_is and typeNeedsNoscript(p.realtype): + raise IDLError( + ( + "method '%s' must be marked [noscript] because it has a " + "non-scriptable parameter '%s'" + ) + % (methodOrAttribute.name, p.name), + methodOrAttribute.location, + ) + class Attribute(object): kind = "attribute" @@ -1334,6 +1419,7 @@ class Attribute(object): ensureInfallibleIsSound(self) ensureBuiltinClassIfNeeded(self) + ensureNoscriptIfNeeded(self) def toIDL(self): attribs = attlistToIDL(self.attlist) @@ -1420,9 +1506,6 @@ class Method(object): self.iface = iface self.realtype = self.iface.idl.getName(self.type, self.location) - ensureInfallibleIsSound(self) - ensureBuiltinClassIfNeeded(self) - for p in self.params: p.resolve(self) for p in self.params: @@ -1462,6 +1545,10 @@ class Method(object): self.location, ) + ensureInfallibleIsSound(self) + ensureBuiltinClassIfNeeded(self) + ensureNoscriptIfNeeded(self) + def isScriptable(self): if not self.iface.attributes.scriptable: return False |