зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
eb7c3dbdf6
Коммит
26e9ce40c3
|
@ -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);
|
||||
|
|
Загрузка…
Ссылка в новой задаче