Bug 792137. [TreatNonCallableAsNull] lives on the callback type now. r=peterv

This commit is contained in:
Boris Zbarsky 2012-10-10 15:53:02 -04:00
Родитель cdb3cc0401
Коммит 7f28e933c6
12 изменённых файлов: 108 добавлений и 54 удалений

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

@ -1770,6 +1770,10 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
return CGWrapper(CGGeneric(
failureCode or
'return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "%s");' % typeName), post="\n")
def onFailureNotCallable(failureCode):
return CGWrapper(CGGeneric(
failureCode or
'return ThrowErrorMessage(cx, MSG_NOT_CALLABLE);'), post="\n")
# A helper function for handling default values. Takes a template
# body and the C++ code to set the default value and wraps the
@ -2393,23 +2397,41 @@ for (uint32_t i = 0; i < length; ++i) {
if type.isCallback():
assert not isEnforceRange and not isClamp
assert not type.treatNonCallableAsNull() or type.nullable()
if isMember:
raise TypeError("Can't handle member callbacks; need to sort out "
"rooting issues")
# XXXbz we're going to assume that callback types are always
# nullable and always have [TreatNonCallableAsNull] for now.
haveCallable = "${val}.isObject() && JS_ObjectIsCallable(cx, &${val}.toObject())"
if type.nullable():
declType = CGGeneric("JSObject*")
else:
declType = CGGeneric("NonNull<JSObject>")
if type.treatNonCallableAsNull():
haveCallable = "JS_ObjectIsCallable(cx, &${val}.toObject())"
if not isDefinitelyObject:
haveCallable = "${val}.isObject() && " + haveCallable
if defaultValue is not None:
assert(isinstance(defaultValue, IDLNullValue))
haveCallable = "${haveValue} && " + haveCallable
return (
template = (
"if (%s) {\n"
" ${declName} = &${val}.toObject();\n"
"} else {\n"
" ${declName} = NULL;\n"
"}" % haveCallable,
CGGeneric("JSObject*"), None, isOptional)
" ${declName} = nullptr;\n"
"}" % haveCallable)
else:
template = wrapObjectTemplate(
"if (JS_ObjectIsCallable(cx, &${val}.toObject())) {\n"
" ${declName} = &${val}.toObject();\n"
"} else {\n"
"%s"
"}" % CGIndenter(onFailureNotCallable(failureCode)).define(),
isDefinitelyObject, type,
"${declName} = nullptr",
failureCode)
return (template, declType, None, isOptional)
if type.isAny():
assert not isEnforceRange and not isClamp
@ -3849,7 +3871,9 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
return CGGeneric(type.inner.identifier.name)
if type.isCallback():
if type.nullable():
return CGGeneric("JSObject*")
return CGGeneric("JSObject&")
if type.isAny():
return CGGeneric("JS::Value")

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

@ -22,6 +22,7 @@
MSG_DEF(MSG_INVALID_ENUM_VALUE, 2, "Value '{0}' is not a valid value for enumeration {1}.")
MSG_DEF(MSG_MISSING_ARGUMENTS, 1, "Not enough arguments to {0}.")
MSG_DEF(MSG_NOT_OBJECT, 0, "Value not an object.")
MSG_DEF(MSG_NOT_CALLABLE, 0, "Value is not callable.")
MSG_DEF(MSG_DOES_NOT_IMPLEMENT_INTERFACE, 1, "Value does not implement interface {0}.")
MSG_DEF(MSG_NOT_IN_UNION, 1, "Value could not be converted to any of: {0}.")
MSG_DEF(MSG_ILLEGAL_CONSTRUCTOR, 0, "Illegal constructor.")

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

@ -963,15 +963,8 @@ class IDLType(IDLObject):
assert False # Override me!
def treatNonCallableAsNull(self):
if not (self.nullable() and self.tag() == IDLType.Tags.callback):
raise WebIDLError("Type %s cannot be TreatNonCallableAsNull" % self,
[self.location])
return hasattr(self, "_treatNonCallableAsNull")
def markTreatNonCallableAsNull(self):
assert not self.treatNonCallableAsNull()
self._treatNonCallableAsNull = True
assert self.tag() == IDLType.Tags.callback
return self.nullable() and self.inner._treatNonCallableAsNull
def addExtendedAttributes(self, attrs):
assert len(attrs) == 0
@ -1999,7 +1992,8 @@ class IDLAttribute(IDLInterfaceMember):
def handleExtendedAttribute(self, attr):
identifier = attr.identifier()
if identifier == "TreatNonCallableAsNull":
self.type.markTreatNonCallableAsNull();
raise WebIDLError("TreatNonCallableAsNull cannot be specified on attributes",
[attr.location, self.location])
elif identifier == "SetterInfallible" and self.readonly:
raise WebIDLError("Readonly attributes must not be flagged as "
"[SetterInfallible]",
@ -2114,6 +2108,8 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
for argument in arguments:
argument.resolve(self)
self._treatNonCallableAsNull = False
def isCallback(self):
return True
@ -2153,6 +2149,16 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isNonCallbackInterface() or other.isDate())
def addExtendedAttributes(self, attrs):
unhandledAttrs = []
for attr in attrs:
if attr.identifier() == "TreatNonCallableAsNull":
self._treatNonCallableAsNull = True
else:
unhandledAttrs.append(attr)
if len(unhandledAttrs) != 0:
IDLType.addExtendedAttributes(self, unhandledAttrs)
class IDLMethodOverload:
"""
A class that represents a single overload of a WebIDL method. This is not

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

@ -12,7 +12,7 @@ def WebIDLTest(parser, harness):
results = parser.finish()
harness.ok(True, "TestCallback interface parsed without error.")
harness.check(len(results), 2, "Should be one production.")
harness.check(len(results), 2, "Should be two productions.")
iface = results[0]
harness.ok(isinstance(iface, WebIDL.IDLInterface),
"Should be an IDLInterface")

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

@ -2,11 +2,11 @@ import WebIDL
def WebIDLTest(parser, harness):
parser.parse("""
callback Function = any(any... arguments);
[TreatNonCallableAsNull] callback Function = any(any... arguments);
interface TestTreatNonCallableAsNull1 {
[TreatNonCallableAsNull] attribute Function? onfoo;
attribute Function? onbar;
attribute Function? onfoo;
attribute Function onbar;
};
""")

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

@ -334,13 +334,16 @@ public:
void SetEnumAttribute(TestEnum);
// Callback types
void PassCallback(JSContext*, JSObject*);
void PassCallback(JSContext*, JSObject&);
void PassNullableCallback(JSContext*, JSObject*);
void PassOptionalCallback(JSContext*, const Optional<JSObject*>&);
void PassOptionalCallback(JSContext*, const Optional<NonNull<JSObject> >&);
void PassOptionalNullableCallback(JSContext*, const Optional<JSObject*>&);
void PassOptionalNullableCallbackWithDefaultValue(JSContext*, JSObject*);
JSObject* ReceiveCallback(JSContext*);
JSObject* ReceiveNullableCallback(JSContext*);
void PassNullableTreatAsNullCallback(JSContext*, JSObject*);
void PassOptionalNullableTreatAsNullCallback(JSContext*, const Optional<JSObject*>&);
void PassOptionalNullableTreatAsNullCallbackWithDefaultValue(JSContext*, JSObject*);
// Any types
void PassAny(JSContext*, JS::Value);

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

@ -24,6 +24,7 @@ enum TestEnum {
};
callback TestCallback = void();
[TreatNonCallableAsNull] callback TestTreatAsNullCallback = void();
TestInterface implements ImplementedInterface;
@ -265,6 +266,9 @@ interface TestInterface {
void passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null);
TestCallback receiveCallback();
TestCallback? receiveNullableCallback();
void passNullableTreatAsNullCallback(TestTreatAsNullCallback? arg);
void passOptionalNullableTreatAsNullCallback(optional TestTreatAsNullCallback? arg);
void passOptionalNullableTreatAsNullCallbackWithDefaultValue(optional TestTreatAsNullCallback? arg = null);
// Any types
void passAny(any arg);

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

@ -0,0 +1,15 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://www.whatwg.org/specs/web-apps/current-work/#eventhandler
*
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
* Opera Software ASA. You are granted a license to use, reproduce
* and create derivative works of this document.
*/
[TreatNonCallableAsNull]
callback EventHandlerNonNull = any (Event event);
typedef EventHandlerNonNull? EventHandler;

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

@ -22,6 +22,7 @@ webidl_files = \
DOMTokenList.webidl \
DOMSettableTokenList.webidl \
Function.webidl \
EventHandler.webidl \
EventListener.webidl \
EventTarget.webidl \
FileList.webidl \

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

@ -32,14 +32,14 @@ interface WebSocket : EventTarget {
// networking
[TreatNonCallableAsNull, SetterThrows]
attribute Function? onopen;
[SetterThrows]
attribute EventHandler onopen;
[TreatNonCallableAsNull, SetterThrows]
attribute Function? onerror;
[SetterThrows]
attribute EventHandler onerror;
[TreatNonCallableAsNull, SetterThrows]
attribute Function? onclose;
[SetterThrows]
attribute EventHandler onclose;
readonly attribute DOMString extensions;
@ -50,8 +50,8 @@ interface WebSocket : EventTarget {
// messaging
[TreatNonCallableAsNull, SetterThrows]
attribute Function? onmessage;
[SetterThrows]
attribute EventHandler onmessage;
attribute BinaryType binaryType;

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

@ -59,8 +59,8 @@ dictionary MozXMLHttpRequestParameters
Constructor(DOMString ignored)]
interface XMLHttpRequest : XMLHttpRequestEventTarget {
// event handler
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? onreadystatechange;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler onreadystatechange;
// states
const unsigned short UNSENT = 0;

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

@ -13,24 +13,24 @@
[NoInterfaceObject]
interface XMLHttpRequestEventTarget : EventTarget {
// event handlers
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? onloadstart;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler onloadstart;
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? onprogress;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler onprogress;
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? onabort;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler onabort;
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? onerror;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler onerror;
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? onload;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler onload;
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? ontimeout;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler ontimeout;
[TreatNonCallableAsNull, SetterThrows, GetterThrows=Workers]
attribute Function? onloadend;
[SetterThrows, GetterThrows=Workers]
attribute EventHandler onloadend;
};