зеркало из https://github.com/mozilla/gecko-dev.git
Bug 792137. [TreatNonCallableAsNull] lives on the callback type now. r=peterv
This commit is contained in:
Родитель
cdb3cc0401
Коммит
7f28e933c6
|
@ -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;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче