bug 1542932 Add code generation for callback constructors r=bzbarsky

TreatNonObjectAsNull is rejected in the parser because / so that there is no
need to implement the equivalent of CallCallback.getCallGuard().

Differential Revision: https://phabricator.services.mozilla.com/D26865

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Karl Tomlinson 2019-04-11 20:54:17 +00:00
Родитель eb7c3dbdf6
Коммит 26e9ce40c3
5 изменённых файлов: 115 добавлений и 5 удалений

Просмотреть файл

@ -16276,9 +16276,12 @@ class CGCallback(CGClass):
class CGCallbackFunction(CGCallback):
def __init__(self, callback, descriptorProvider):
self.callback = callback
if callback.isConstructor():
methods=[ConstructCallback(callback, descriptorProvider)]
else:
methods=[CallCallback(callback, descriptorProvider)]
CGCallback.__init__(self, callback, descriptorProvider,
"CallbackFunction",
methods=[CallCallback(callback, descriptorProvider)])
"CallbackFunction", methods)
def getConstructors(self):
return CGCallback.getConstructors(self) + [
@ -16483,7 +16486,7 @@ class CallbackMember(CGNativeMember):
return setupCall + declRval + argvDecl + convertArgs + doCall + returnResult
def getResultConversion(self):
def getResultConversion(self, isDefinitelyObject=False):
replacements = {
"val": "rval",
"holderName": "rvalHolder",
@ -16503,6 +16506,7 @@ class CallbackMember(CGNativeMember):
convertType = instantiateJSToNativeConversion(
getJSToNativeConversionInfo(self.retvalType,
self.descriptorProvider,
isDefinitelyObject=isDefinitelyObject,
exceptionCode=self.exceptionCode,
isCallbackReturnValue=isCallbackReturnValue,
# Allow returning a callback type that
@ -16672,6 +16676,45 @@ class CallbackMember(CGNativeMember):
idlObject.location))
class ConstructCallback(CallbackMember):
def __init__(self, callback, descriptorProvider):
self.callback = callback
CallbackMember.__init__(self, callback.signatures()[0], "Construct",
descriptorProvider, needThisHandling=False,
canRunScript=True)
def getRvalDecl(self):
# Box constructedObj for getJSToNativeConversionInfo().
return "JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());\n"
def getCall(self):
if self.argCount > 0:
args = "JS::HandleValueArray::subarray(argv, 0, argc)"
else:
args = "JS::HandleValueArray::empty()"
return fill(
"""
JS::Rooted<JS::Value> constructor(cx, JS::ObjectValue(*mCallback));
JS::Rooted<JSObject*> constructedObj(cx);
if (!JS::Construct(cx, constructor,
${args}, &constructedObj)) {
aRv.NoteJSContextException(cx);
return${errorReturn};
}
rval.setObject(*constructedObj);
""",
args=args,
errorReturn=self.getDefaultRetval())
def getResultConversion(self):
return CallbackMember.getResultConversion(self,
isDefinitelyObject=True);
def getPrettyName(self):
return self.callback.identifier.name
class CallbackMethod(CallbackMember):
def __init__(self, sig, name, descriptorProvider, needThisHandling,
rethrowContentException=False,

Просмотреть файл

@ -4705,8 +4705,15 @@ class IDLCallback(IDLObjectWithScope):
if attr.identifier() == "TreatNonCallableAsNull":
self._treatNonCallableAsNull = True
elif attr.identifier() == "TreatNonObjectAsNull":
if self._isConstructor:
raise WebIDLError("[TreatNonObjectAsNull] is not supported "
"on constructors", [self.location])
self._treatNonObjectAsNull = True
elif attr.identifier() == "MOZ_CAN_RUN_SCRIPT_BOUNDARY":
if self._isConstructor:
raise WebIDLError("[MOZ_CAN_RUN_SCRIPT_BOUNDARY] is not "
"permitted on constructors",
[self.location])
self._isRunScriptBoundary = True
else:
unhandledAttrs.append(attr)

Просмотреть файл

@ -35,3 +35,29 @@ def WebIDLTest(parser, harness):
callback = results[1]
harness.ok(callback.isConstructor(), "Callback is constructor")
parser.reset()
threw = False
try:
parser.parse("""
[TreatNonObjectAsNull]
callback constructor CallbackConstructorType = object ();
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should throw on TreatNonObjectAsNull callback constructors")
parser.reset()
threw = False
try:
parser.parse("""
[MOZ_CAN_RUN_SCRIPT_BOUNDARY]
callback constructor CallbackConstructorType = object ();
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should not permit MOZ_CAN_RUN_SCRIPT_BOUNDARY callback constructors")

Просмотреть файл

@ -617,7 +617,12 @@ class TestInterface : public nsISupports, public nsWrapperCache {
TestNullableTypedArrayReturn&, TestSequenceReturn&,
TestNullableSequenceReturn&, TestIntegerArguments&,
TestInterfaceArguments&, TestStringEnumArguments&, TestObjectArguments&,
TestOptionalArguments&);
TestOptionalArguments&, TestVoidConstruction&, TestIntegerConstruction&,
TestBooleanConstruction&, TestFloatConstruction&, TestStringConstruction&,
TestEnumConstruction&, TestInterfaceConstruction&,
TestExternalInterfaceConstruction&, TestCallbackInterfaceConstruction&,
TestCallbackConstruction&, TestObjectConstruction&,
TestTypedArrayConstruction&, TestSequenceConstruction&);
// Any types
void PassAny(JSContext*, JS::Handle<JS::Value>);

Просмотреть файл

@ -117,6 +117,22 @@ callback TestOptionalArguments = void(optional DOMString aString,
optional TestInterface? anInterface,
optional TestInterface anotherInterface,
optional long aLong);
// Callback constructor return value tests
callback constructor TestVoidConstruction = void(TestDictionaryTypedef arg);
callback constructor TestIntegerConstruction = unsigned long();
callback constructor TestBooleanConstruction = boolean(any arg1,
optional any arg2);
callback constructor TestFloatConstruction = unrestricted float(optional object arg1,
optional TestDictionaryTypedef arg2);
callback constructor TestStringConstruction = DOMString(long? arg);
callback constructor TestEnumConstruction = TestEnum(any... arg);
callback constructor TestInterfaceConstruction = TestInterface();
callback constructor TestExternalInterfaceConstruction = TestExternalInterface();
callback constructor TestCallbackInterfaceConstruction = TestCallbackInterface();
callback constructor TestCallbackConstruction = TestCallback();
callback constructor TestObjectConstruction = object();
callback constructor TestTypedArrayConstruction = ArrayBuffer();
callback constructor TestSequenceConstruction = sequence<boolean>();
// If you add a new test callback, add it to the forceCallbackGeneration
// method on TestInterface so it actually gets tested.
@ -546,7 +562,20 @@ interface TestInterface {
TestInterfaceArguments arg22,
TestStringEnumArguments arg23,
TestObjectArguments arg24,
TestOptionalArguments arg25);
TestOptionalArguments arg25,
TestVoidConstruction arg26,
TestIntegerConstruction arg27,
TestBooleanConstruction arg28,
TestFloatConstruction arg29,
TestStringConstruction arg30,
TestEnumConstruction arg31,
TestInterfaceConstruction arg32,
TestExternalInterfaceConstruction arg33,
TestCallbackInterfaceConstruction arg34,
TestCallbackConstruction arg35,
TestObjectConstruction arg36,
TestTypedArrayConstruction arg37,
TestSequenceConstruction arg38);
// Any types
void passAny(any arg);