Bug 822470 part 7. Use new callback codegen for conversion to and from JS. r=peterv

NodeFilter, EventListener, and DOMTransaction will be updated to use the new codegen once we've fixed the consumers.
This commit is contained in:
Boris Zbarsky 2013-01-28 08:34:31 -05:00
parent 1ddbf2e612
commit fd94476421
5 changed files with 133 additions and 50 deletions

View File

@ -1169,6 +1169,41 @@ WrapNewBindingObject(JSContext* cx, JSObject* scope, T& value,
return WrapNewBindingObjectHelper<T>::Wrap(cx, scope, value, vp);
}
template <class T>
inline JSObject*
GetCallbackFromCallbackObject(T* aObj)
{
return aObj->Callback();
}
// Helper for getting the callback JSObject* of a smart ptr around a
// CallbackObject or a reference to a CallbackObject or something like
// that.
template <class T, bool isSmartPtr=HasgetMember<T>::Value>
struct GetCallbackFromCallbackObjectHelper
{
static inline JSObject* Get(const T& aObj)
{
return GetCallbackFromCallbackObject(aObj.get());
}
};
template <class T>
struct GetCallbackFromCallbackObjectHelper<T, false>
{
static inline JSObject* Get(T& aObj)
{
return GetCallbackFromCallbackObject(&aObj);
}
};
template<class T>
inline JSObject*
GetCallbackFromCallbackObject(T& aObj)
{
return GetCallbackFromCallbackObjectHelper<T>::Get(aObj);
}
static inline bool
InternJSString(JSContext* cx, jsid& id, const char* chars)
{

View File

@ -273,6 +273,9 @@ DOMInterfaces = {
}],
'EventListener': [
{
'nativeType': 'nsIDOMEventListener'
},
{
'workers': True,
}],
@ -305,6 +308,7 @@ DOMInterfaces = {
'DOMTransaction': [
{
'nativeType': 'nsIUndoManagerTransaction',
'headerFile': 'nsIUndoManagerTransaction.h',
}],
'UndoManager': [
@ -535,6 +539,11 @@ DOMInterfaces = {
'attributes' ]
},
'NodeFilter': {
'nativeType': 'nsIDOMNodeFilter',
'headerFile': 'nsIDOMNodeFilter.h',
},
'NodeList': {
'nativeType': 'nsINodeList',
'resultNotAddRefed': [ 'item' ]
@ -1039,12 +1048,6 @@ DOMInterfaces = {
'wrapperCache': False
},
'TestCallbackInterface': {
'nativeType': 'mozilla::dom::TestCallbackInterfaceOld',
'headerFile': 'TestBindingHeader.h',
'register': False
},
'IndirectlyImplementedInterface': {
'headerFile': 'TestBindingHeader.h',
'register': False,

View File

@ -2519,6 +2519,34 @@ for (uint32_t i = 0; i < length; ++i) {
descriptor = descriptorProvider.getDescriptor(
type.unroll().inner.identifier.name)
if (descriptor.interface.isCallback() and
descriptor.interface.identifier.name != "NodeFilter" and
descriptor.interface.identifier.name != "EventListener" and
descriptor.interface.identifier.name != "DOMTransaction"):
if descriptor.workers:
if type.nullable():
declType = CGGeneric("JSObject*")
else:
declType = CGGeneric("NonNull<JSObject>")
conversion = " ${declName} = &${val}.toObject();\n"
else:
name = descriptor.interface.identifier.name
if type.nullable():
declType = CGGeneric("nsRefPtr<%s>" % name);
else:
declType = CGGeneric("OwningNonNull<%s>" % name)
conversion = (
" bool inited;\n"
" ${declName} = new %s(cx, ${obj}, &${val}.toObject(), &inited);\n"
" if (!inited) {\n"
"%s\n"
" }\n" % (name, CGIndenter(exceptionCodeIndented).define()))
template = wrapObjectTemplate(conversion, type,
"${declName} = nullptr",
failureCode)
return (template, declType, None, isOptional)
# This is an interface that we implement as a concrete class
# or an XPCOM interface.
@ -3333,7 +3361,11 @@ if (!returnArray) {
CGIndenter(exceptionCodeIndented, 4).define())) +
setValue("JS::ObjectValue(*returnArray)"), False)
if type.isGeckoInterface():
if (type.isGeckoInterface() and
(not type.isCallbackInterface() or
type.unroll().inner.identifier.name == "EventListener" or
type.unroll().inner.identifier.name == "NodeFilter" or
type.unroll().inner.identifier.name == "DOMTransaction")):
descriptor = descriptorProvider.getDescriptor(type.unroll().inner.identifier.name)
if type.nullable():
wrappingCode = ("if (!%s) {\n" % (result) +
@ -3400,22 +3432,24 @@ if (!%(resultStr)s) {
"exceptionCode" : exceptionCode } +
setValue("JS::StringValue(%s_str)" % result), False)
if type.isCallback():
assert not type.isInterface()
# XXXbz we're going to assume that callback types are always
# nullable and always have [TreatNonCallableAsNull] for now.
if type.isCallback() or type.isCallbackInterface():
# See comments in WrapNewBindingObject explaining why we need
# to wrap here.
# NB: setValue(..., True) calls JS_WrapValue(), so is fallible
if descriptorProvider.workers:
return (setValue("JS::ObjectOrNullValue(%s)" % result, True), False)
wrapCode = (("if (%(result)s) {\n" +
CGIndenter(CGGeneric(setValue(
"JS::ObjectValue(*%(result)s->Callable())", True))).define() + "\n"
"} else {\n" +
CGIndenter(CGGeneric(setValue("JS::NullValue()"))).define() + "\n"
"}") % { "result": result })
wrapCode = setValue(
"JS::ObjectValue(*GetCallbackFromCallbackObject(%(result)s))",
True)
if type.nullable():
wrapCode = (
"if (%(result)s) {\n" +
CGIndenter(CGGeneric(wrapCode)).define() + "\n"
"} else {\n" +
CGIndenter(CGGeneric(setValue("JS::NullValue()"))).define() + "\n"
"}")
wrapCode = wrapCode % { "result": result }
return wrapCode, False
if type.tag() == IDLType.Tags.any:
@ -7305,7 +7339,11 @@ class CGNativeMember(ClassMethod):
type = type.inner
return str(type), True, True
if type.isGeckoInterface():
if (type.isGeckoInterface() and
(not type.isCallbackInterface() or
type.unroll().inner.identifier.name == "NodeFilter" or
type.unroll().inner.identifier.name == "EventListener" or
type.unroll().inner.identifier.name == "DOMTransaction")):
iface = type.unroll().inner
argIsPointer = type.nullable() or iface.isExternal()
forceOwningType = iface.isCallback() or isMember
@ -7350,18 +7388,23 @@ class CGNativeMember(ClassMethod):
if type.isEnum():
return type.inner.identifier.name, False, True
if type.isCallback():
if type.isCallback() or type.isCallbackInterface():
forceOwningType = optional or isMember
if type.nullable():
if optional:
if forceOwningType:
declType = "nsRefPtr<%s>"
else:
declType = "%s*"
else:
if optional:
if forceOwningType:
declType = "OwningNonNull<%s>"
else:
declType = "%s&"
return declType % type.unroll().identifier.name, False, False
if type.isCallback():
name = type.unroll().identifier.name
else:
name = type.unroll().inner.identifier.name
return declType % name, False, False
if type.isAny():
return "JS::Value", False, False

View File

@ -3,6 +3,7 @@
# You can obtain one at http://mozilla.org/MPL/2.0/.
from WebIDL import IDLInterface, IDLExternalInterface
import os
autogenerated_comment = "/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
@ -155,11 +156,16 @@ class Descriptor(DescriptorProvider):
# Read the desc, and fill in the relevant defaults.
ifaceName = self.interface.identifier.name
if self.interface.isExternal() or self.interface.isCallback():
if self.interface.isExternal():
if self.workers:
nativeTypeDefault = "JSObject"
else:
nativeTypeDefault = "nsIDOM" + ifaceName
elif self.interface.isCallback():
if self.workers:
nativeTypeDefault = "JSObject"
else:
nativeTypeDefault = "mozilla::dom::" + ifaceName
else:
if self.workers:
nativeTypeDefault = "mozilla::dom::workers::" + ifaceName
@ -172,6 +178,13 @@ class Descriptor(DescriptorProvider):
# Do something sane for JSObject
if self.nativeType == "JSObject":
headerDefault = "jsapi.h"
elif self.interface.isCallback():
# A copy of CGHeaders.getDeclarationFilename; we can't
# import it here, sadly.
# Use our local version of the header, not the exported one, so that
# test bindings, which don't export, will work correctly.
basename = os.path.basename(self.interface.filename())
headerDefault = basename.replace('.webidl', 'Binding.h')
else:
if self.workers:
headerDefault = "mozilla/dom/workers/bindings/%s.h" % ifaceName

View File

@ -82,17 +82,6 @@ public:
NS_DECL_ISUPPORTS
};
// IID for the TestCallbackInterface
#define NS_TEST_CALLBACK_INTERFACE_IID \
{ 0xbf711ba4, 0xc8f6, 0x46cf, \
{ 0xba, 0x5b, 0xaa, 0xe2, 0x78, 0x18, 0xe6, 0x4a } }
class TestCallbackInterfaceOld : public nsISupports
{
public:
NS_DECLARE_STATIC_IID_ACCESSOR(NS_TEST_CALLBACK_INTERFACE_IID)
NS_DECL_ISUPPORTS
};
class TestNonWrapperCacheInterface : public nsISupports
{
public:
@ -302,20 +291,20 @@ public:
void PassOptionalNonNullExternal(const Optional<TestExternalInterface*>&);
void PassOptionalExternalWithDefault(TestExternalInterface*);
already_AddRefed<TestCallbackInterfaceOld> ReceiveCallbackInterface();
already_AddRefed<TestCallbackInterfaceOld> ReceiveNullableCallbackInterface();
TestCallbackInterfaceOld* ReceiveWeakCallbackInterface();
TestCallbackInterfaceOld* ReceiveWeakNullableCallbackInterface();
void PassCallbackInterface(TestCallbackInterfaceOld&);
void PassCallbackInterface2(OwningNonNull<TestCallbackInterfaceOld>);
void PassNullableCallbackInterface(TestCallbackInterfaceOld*);
already_AddRefed<TestCallbackInterfaceOld> NonNullCallbackInterface();
void SetNonNullCallbackInterface(TestCallbackInterfaceOld&);
already_AddRefed<TestCallbackInterfaceOld> GetNullableCallbackInterface();
void SetNullableCallbackInterface(TestCallbackInterfaceOld*);
void PassOptionalCallbackInterface(const Optional<nsRefPtr<TestCallbackInterfaceOld> >&);
void PassOptionalNonNullCallbackInterface(const Optional<OwningNonNull<TestCallbackInterfaceOld> >&);
void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterfaceOld*);
already_AddRefed<TestCallbackInterface> ReceiveCallbackInterface();
already_AddRefed<TestCallbackInterface> ReceiveNullableCallbackInterface();
TestCallbackInterface* ReceiveWeakCallbackInterface();
TestCallbackInterface* ReceiveWeakNullableCallbackInterface();
void PassCallbackInterface(TestCallbackInterface&);
void PassCallbackInterface2(OwningNonNull<TestCallbackInterface>);
void PassNullableCallbackInterface(TestCallbackInterface*);
already_AddRefed<TestCallbackInterface> NonNullCallbackInterface();
void SetNonNullCallbackInterface(TestCallbackInterface&);
already_AddRefed<TestCallbackInterface> GetNullableCallbackInterface();
void SetNullableCallbackInterface(TestCallbackInterface*);
void PassOptionalCallbackInterface(const Optional<nsRefPtr<TestCallbackInterface> >&);
void PassOptionalNonNullCallbackInterface(const Optional<OwningNonNull<TestCallbackInterface> >&);
void PassOptionalCallbackInterfaceWithDefault(TestCallbackInterface*);
already_AddRefed<IndirectlyImplementedInterface> ReceiveConsequentialInterface();
void PassConsequentialInterface(IndirectlyImplementedInterface&);
@ -331,9 +320,9 @@ public:
void PassOptionalSequenceOfNullableInts(const Optional<Sequence<Nullable<int32_t> > > &);
void PassOptionalNullableSequenceOfNullableInts(const Optional<Nullable<Sequence<Nullable<int32_t> > > > &);
void ReceiveCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &);
void ReceiveCallbackObjectSequence(nsTArray< nsRefPtr<TestCallbackInterfaceOld> > &);
void ReceiveCallbackObjectSequence(nsTArray< nsRefPtr<TestCallbackInterface> > &);
void ReceiveNullableCastableObjectSequence(nsTArray< nsRefPtr<TestInterface> > &);
void ReceiveNullableCallbackObjectSequence(nsTArray< nsRefPtr<TestCallbackInterfaceOld> > &);
void ReceiveNullableCallbackObjectSequence(nsTArray< nsRefPtr<TestCallbackInterface> > &);
void ReceiveCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&);
void ReceiveNullableCastableObjectNullableSequence(Nullable< nsTArray< nsRefPtr<TestInterface> > >&);
void ReceiveWeakCastableObjectSequence(nsTArray<TestInterface*> &);