Bug 938544 - Add support for a Chrome-only constructor in WebIDL. r=bz.

--HG--
extra : rebase_source : e36fef0090d57947ceae6c2fc11bea8b115423e4
This commit is contained in:
Peter Van der Beken 2013-08-12 16:45:33 +02:00
parent fe4b3c69aa
commit fb3f5ea859
3 changed files with 57 additions and 11 deletions

View File

@ -1141,6 +1141,11 @@ class CGClassConstructor(CGAbstractStaticMethod):
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
JS::Rooted<JSObject*> obj(cx, &args.callee());
"""
if isChromeOnly(self._ctor):
preamble += """ if (!%s) {
return ThrowingConstructor(cx, argc, vp);
}
""" % GetAccessCheck(self.descriptor, "cx", "obj")
name = self._ctor.identifier.name
nativeName = MakeNativeName(self.descriptor.binaryNames.get(name, name))
callGenerator = CGMethodCall(nativeName, True, self.descriptor,
@ -1957,7 +1962,7 @@ if (!unforgeableHolder) {
else:
properties = "nullptr"
if self.properties.hasChromeOnly():
accessCheck = GetAccessCheck(self.descriptor, "aGlobal")
accessCheck = GetAccessCheck(self.descriptor, "aCx", "aGlobal")
chromeProperties = accessCheck + " ? &sChromeOnlyNativeProperties : nullptr"
else:
chromeProperties = "nullptr"
@ -2143,7 +2148,7 @@ class CGConstructorEnabledChromeOnly(CGAbstractMethod):
Argument("JS::Handle<JSObject*>", "aObj")])
def definition_body(self):
return " return %s;" % GetAccessCheck(self.descriptor, "aObj")
return " return %s;" % GetAccessCheck(self.descriptor, "aCx", "aObj")
class CGConstructorEnabledViaFunc(CGAbstractMethod):
"""
@ -2211,13 +2216,14 @@ def CreateBindingJSObject(descriptor, properties, parent):
"""
return create % parent
def GetAccessCheck(descriptor, object):
def GetAccessCheck(descriptor, context, object):
"""
context is the name of a JSContext*
object is the name of a JSObject*
returns a string
"""
return "ThreadsafeCheckIsChrome(aCx, %s)" % object
return "ThreadsafeCheckIsChrome(%s, %s)" % (context, object)
def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturnValue=""):
"""
@ -2241,7 +2247,7 @@ def InitUnforgeablePropertiesOnObject(descriptor, obj, properties, failureReturn
unforgeables.append(
CGIfWrapper(CGGeneric(defineUnforgeables %
unforgeableAttrs.variableName(True)),
GetAccessCheck(descriptor, obj)))
GetAccessCheck(descriptor, "aCx", obj)))
return CGList(unforgeables, "\n")
def InitUnforgeableProperties(descriptor, properties):

View File

@ -868,7 +868,7 @@ class IDLInterface(IDLObjectWithScope):
[self.location])
self._noInterfaceObject = True
elif identifier == "Constructor" or identifier == "NamedConstructor":
elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor":
if identifier == "Constructor" and not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
@ -877,11 +877,15 @@ class IDLInterface(IDLObjectWithScope):
raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
[attr.location])
if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
args = attr.args() if attr.hasArgs() else []
retType = IDLWrapperType(self.location, self)
if identifier == "Constructor":
if identifier == "Constructor" or identifier == "ChromeConstructor":
name = "constructor"
allowForbidden = True
else:
@ -900,9 +904,11 @@ class IDLInterface(IDLObjectWithScope):
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("NewObject",)),
IDLExtendedAttribute(self.location, ("Throws",))])
if identifier == "ChromeConstructor":
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("ChromeOnly",))])
if identifier == "Constructor":
if identifier == "Constructor" or identifier == "ChromeConstructor":
method.resolve(self)
else:
# We need to detect conflicts for NamedConstructors across

View File

@ -12,7 +12,8 @@ def WebIDLTest(parser, harness):
def checkMethod(method, QName, name, signatures,
static=True, getter=False, setter=False, creator=False,
deleter=False, legacycaller=False, stringifier=False):
deleter=False, legacycaller=False, stringifier=False,
chromeOnly=False):
harness.ok(isinstance(method, WebIDL.IDLMethod),
"Should be an IDLMethod")
harness.ok(method.isMethod(), "Method is a method")
@ -27,6 +28,7 @@ def WebIDLTest(parser, harness):
harness.check(method.isDeleter(), deleter, "Method has the correct deleter value")
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly")
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
sigpairs = zip(method.signatures(), signatures)
@ -55,11 +57,13 @@ def WebIDLTest(parser, harness):
};
""")
results = parser.finish()
harness.check(len(results), 3, "Should be two productions")
harness.check(len(results), 3, "Should be three productions")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.ok(isinstance(results[1], WebIDL.IDLInterface),
"Should be an IDLInterface")
harness.ok(isinstance(results[2], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestConstructorNoArgs::constructor",
"constructor", [("TestConstructorNoArgs (Wrapper)", [])])
@ -73,3 +77,33 @@ def WebIDLTest(parser, harness):
[("::TestConstructorOverloads::constructor::foo", "foo", "Object", False, False)]),
("TestConstructorOverloads (Wrapper)",
[("::TestConstructorOverloads::constructor::bar", "bar", "Boolean", False, False)])])
parser = parser.reset()
parser.parse("""
[ChromeConstructor()]
interface TestChromeConstructor {
};
""")
results = parser.finish()
harness.check(len(results), 1, "Should be one production")
harness.ok(isinstance(results[0], WebIDL.IDLInterface),
"Should be an IDLInterface")
checkMethod(results[0].ctor(), "::TestChromeConstructor::constructor",
"constructor", [("TestChromeConstructor (Wrapper)", [])],
chromeOnly=True)
parser = parser.reset()
threw = False
try:
parser.parse("""
[Constructor(),
ChromeConstructor(DOMString a)]
interface TestChromeConstructor {
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor")