Bug 820665 part 3. WebIDL spec updates to changes in how callback interfaces work. r=khuey

Specifically, any object that's not a Date or RegExp can implement a callback interface.
This commit is contained in:
Boris Zbarsky 2013-01-03 14:03:11 -05:00
parent e957e7f52d
commit c709838653
5 changed files with 42 additions and 23 deletions

View File

@ -233,6 +233,12 @@ IsConvertibleToDictionary(JSContext* cx, JS::Value val)
(val.isObject() && IsConvertibleToDictionary(cx, &val.toObject())); (val.isObject() && IsConvertibleToDictionary(cx, &val.toObject()));
} }
MOZ_ALWAYS_INLINE bool
IsConvertibleToCallbackInterface(JSContext* cx, JSObject* obj)
{
return IsNotDateOrRegExp(cx, obj);
}
inline bool inline bool
IsPlatformObject(JSContext* cx, JSObject* obj) IsPlatformObject(JSContext* cx, JSObject* obj)
{ {

View File

@ -1936,12 +1936,16 @@ class CallbackObjectUnwrapper:
"codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure)).define() } "codeOnFailure" : CGIndenter(CGGeneric(codeOnFailure)).define() }
def __str__(self): def __str__(self):
checkObjectType = CGIfWrapper(
CGGeneric(self.substitution["codeOnFailure"]),
"!IsConvertibleToCallbackInterface(cx, %(source)s)" %
self.substitution).define() + "\n\n"
if self.descriptor.workers: if self.descriptor.workers:
return string.Template( return checkObjectType + string.Template(
"${target} = ${source};" "${target} = ${source};"
).substitute(self.substitution) ).substitute(self.substitution)
return string.Template( return checkObjectType + string.Template(
"""nsresult rv; """nsresult rv;
XPCCallContext ccx(JS_CALLER, cx); XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) { if (!ccx.IsValid()) {
@ -2348,11 +2352,6 @@ for (uint32_t i = 0; i < length; ++i) {
else: else:
callbackObject = None callbackObject = None
if callbackObject and callbackMemberTypes[0].isCallbackInterface():
callbackObject = CGWrapper(CGIndenter(callbackObject),
pre="if (!IsPlatformObject(cx, &argObj)) {\n",
post="\n}")
dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes) dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
if len(dictionaryMemberTypes) > 0: if len(dictionaryMemberTypes) > 0:
raise TypeError("No support for unwrapping dictionaries as member " raise TypeError("No support for unwrapping dictionaries as member "
@ -4032,16 +4031,13 @@ class CGMethodCall(CGThing):
# 3) A RegExp object being passed to a RegExp or "object" arg. # 3) A RegExp object being passed to a RegExp or "object" arg.
# 4) A callable object being passed to a callback or "object" arg. # 4) A callable object being passed to a callback or "object" arg.
# 5) Any non-Date and non-RegExp object being passed to a # 5) Any non-Date and non-RegExp object being passed to a
# dictionary or array or sequence or "object" arg. # array or sequence or callback interface dictionary or
# 6) Some other kind of object being passed to a callback # "object" arg.
# interface or "object" arg.
# #
# Unfortunately, we cannot push the "some other kind of object" # We can can coalesce these five cases together, as long as we make
# check down into case 6, because callbacks interfaces _can_ normally be # sure to check whether our object works as an interface argument
# initialized from platform objects. But we can coalesce the other # before checking whether it works as an arraylike or dictionary or
# five cases together, as long as we make sure to check whether our # callback function or callback interface.
# object works as an interface argument before checking whether it
# works as an arraylike or dictionary or callback function.
# First grab all the overloads that have a non-callback interface # First grab all the overloads that have a non-callback interface
# (which includes typed arrays and arraybuffers) at the # (which includes typed arrays and arraybuffers) at the
@ -4062,11 +4058,12 @@ class CGMethodCall(CGThing):
if distinguishingType(s).isCallback()) if distinguishingType(s).isCallback())
# Now append all the overloads that take an array or sequence or # Now append all the overloads that take an array or sequence or
# dictionary: # dictionary or callback interface:
objectSigs.extend(s for s in possibleSignatures objectSigs.extend(s for s in possibleSignatures
if (distinguishingType(s).isArray() or if (distinguishingType(s).isArray() or
distinguishingType(s).isSequence() or distinguishingType(s).isSequence() or
distinguishingType(s).isDictionary())) distinguishingType(s).isDictionary() or
distinguishingType(s).isCallbackInterface()))
# There might be more than one thing in objectSigs; we need to check # There might be more than one thing in objectSigs; we need to check
# which ones we unwrap to. # which ones we unwrap to.
@ -4092,11 +4089,6 @@ class CGMethodCall(CGThing):
caseBody.append(CGGeneric("}")) caseBody.append(CGGeneric("}"))
# Check for vanilla JS objects
pickFirstSignature("%s.isObject() && !IsPlatformObject(cx, &%s.toObject())" %
(distinguishingArg, distinguishingArg),
lambda s: distinguishingType(s).isCallbackInterface())
# The remaining cases are mutually exclusive. The # The remaining cases are mutually exclusive. The
# pickFirstSignature calls are what change caseBody # pickFirstSignature calls are what change caseBody
# Check for strings or enums # Check for strings or enums

View File

@ -482,8 +482,15 @@ public:
// Overload resolution tests // Overload resolution tests
bool Overload1(TestInterface&); bool Overload1(TestInterface&);
TestInterface* Overload1(const nsAString&, TestInterface&); TestInterface* Overload1(const nsAString&, TestInterface&);
void Overload2(TestInterface&);
void Overload2(const Dict&); void Overload2(const Dict&);
void Overload2(const nsAString&); void Overload2(const nsAString&);
void Overload3(TestInterface&);
void Overload3(const TestCallback&);
void Overload3(const nsAString&);
void Overload4(TestInterface&);
void Overload4(TestCallbackInterface&);
void Overload4(const nsAString&);
// Variadic handling // Variadic handling
void PassVariadicThirdArg(const nsAString&, int32_t, void PassVariadicThirdArg(const nsAString&, int32_t,

View File

@ -432,8 +432,15 @@ interface TestInterface {
//void overload1(DOMString... strs); //void overload1(DOMString... strs);
boolean overload1(TestInterface arg); boolean overload1(TestInterface arg);
TestInterface overload1(DOMString strs, TestInterface arg); TestInterface overload1(DOMString strs, TestInterface arg);
void overload2(TestInterface arg);
void overload2(optional Dict arg); void overload2(optional Dict arg);
void overload2(DOMString arg); void overload2(DOMString arg);
void overload3(TestInterface arg);
void overload3(TestCallback arg);
void overload3(DOMString arg);
void overload4(TestInterface arg);
void overload4(TestCallbackInterface arg);
void overload4(DOMString arg);
// Variadic handling // Variadic handling
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3); void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);

View File

@ -351,8 +351,15 @@ interface TestExampleInterface {
//void overload1(DOMString... strs); //void overload1(DOMString... strs);
boolean overload1(TestInterface arg); boolean overload1(TestInterface arg);
TestInterface overload1(DOMString strs, TestInterface arg); TestInterface overload1(DOMString strs, TestInterface arg);
void overload2(TestInterface arg);
void overload2(optional Dict arg); void overload2(optional Dict arg);
void overload2(DOMString arg); void overload2(DOMString arg);
void overload3(TestInterface arg);
void overload3(TestCallback arg);
void overload3(DOMString arg);
void overload4(TestInterface arg);
void overload4(TestCallbackInterface arg);
void overload4(DOMString arg);
// Variadic handling // Variadic handling
void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3); void passVariadicThirdArg(DOMString arg1, long arg2, TestInterface... arg3);