Bug 851178 - Add support for JS-implemented WebIDL constructors with arguments. r=bz

This commit is contained in:
Andrew McCreight 2013-05-02 18:00:50 -07:00
Родитель 953592544f
Коммит f9834a5efc
3 изменённых файлов: 77 добавлений и 17 удалений

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

@ -8653,11 +8653,34 @@ class CGJSImplMethod(CGNativeMember):
if self.name != 'Constructor':
raise TypeError("Named constructors are not supported for JS implemented WebIDL. See bug 851287.")
if len(self.signature[1]) != 0:
raise TypeError("Constructors with arguments are unsupported. See bug 851178.")
return genConstructorBody(self.descriptor)
args = self.getArgs(self.signature[0], self.signature[1])
# The first two arguments to the constructor implementation are not
# arguments to the WebIDL constructor, so don't pass them to __Init()
assert args[0].argType == 'const GlobalObject&'
assert args[1].argType == 'JSContext*'
args = args[2:]
constructorArgs = [arg.name for arg in args]
initCall = """
// Wrap the object before calling __Init so that __DOM_IMPL__ is available.
nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(window);
JS::Rooted<JSObject*> scopeObj(cx, globalHolder->GetGlobalJSObject());
JS::Rooted<JS::Value> wrappedVal(cx);
if (!WrapNewBindingObject(cx, scopeObj, impl, wrappedVal.address())) {
MOZ_ASSERT(JS_IsExceptionPending(cx));
aRv.Throw(NS_ERROR_UNEXPECTED);
return nullptr;
}
// Initialize the object with the constructor arguments.
impl->mImpl->__Init(%s);
if (aRv.Failed()) {
return nullptr;
}""" % (", ".join(constructorArgs))
else:
initCall = ""
return genConstructorBody(self.descriptor, initCall)
def genConstructorBody(descriptor):
return string.Template(
def genConstructorBody(descriptor, initCall=""):
return string.Template(
""" // Get the window to use as a parent and for initialization.
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global.Get());
if (!window) {
@ -8705,9 +8728,10 @@ def genConstructorBody(descriptor):
}
}
// Build the C++ implementation.
nsRefPtr<${implClass}> impl = new ${implClass}(jsImplObj, window);
nsRefPtr<${implClass}> impl = new ${implClass}(jsImplObj, window);${initCall}
return impl.forget();""").substitute({"implClass" : descriptor.name,
"contractId" : descriptor.interface.getJSImplementation()
"contractId" : descriptor.interface.getJSImplementation(),
"initCall" : initCall
})
# We're always fallible
@ -8984,6 +9008,11 @@ class CGCallbackInterface(CGCallback):
if m.isMethod() and not m.isStatic()]
methods = [CallbackOperation(m, sig, descriptor) for m in methods
for sig in m.signatures()]
if iface.isJSImplemented() and iface.ctor():
sigs = descriptor.interface.ctor().signatures()
if len(sigs) != 1:
raise TypeError("We only handle one constructor. See bug 869268.")
methods.append(CGJSImplInitOperation(sigs[0], descriptor))
CGCallback.__init__(self, iface, descriptor, "CallbackInterface",
methods, getters=getters, setters=setters)
@ -9256,15 +9285,14 @@ class CallCallback(CallbackMethod):
def getCallableDecl(self):
return "JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));\n"
class CallbackOperation(CallbackMethod):
def __init__(self, method, signature, descriptor):
self.singleOperation = descriptor.interface.isSingleOperationInterface()
self.ensureASCIIName(method)
self.methodName = method.identifier.name
CallbackMethod.__init__(self, signature,
MakeNativeName(self.methodName),
descriptor,
self.singleOperation)
class CallbackOperationBase(CallbackMethod):
"""
Common class for implementing various callback operations.
"""
def __init__(self, signature, jsName, nativeName, descriptor, singleOperation):
self.singleOperation = singleOperation
self.methodName = jsName
CallbackMethod.__init__(self, signature, nativeName, descriptor, singleOperation)
def getThisObj(self):
if not self.singleOperation:
@ -9295,6 +9323,17 @@ class CallbackOperation(CallbackMethod):
'%s'
'}\n' % CGIndenter(CGGeneric(getCallableFromProp)).define())
class CallbackOperation(CallbackOperationBase):
"""
Codegen actual WebIDL operations on callback interfaces.
"""
def __init__(self, method, signature, descriptor):
self.ensureASCIIName(method)
jsName = method.identifier.name
CallbackOperationBase.__init__(self, signature,
jsName, MakeNativeName(jsName),
descriptor, descriptor.interface.isSingleOperationInterface())
class CallbackGetter(CallbackMember):
def __init__(self, attr, descriptor):
self.ensureASCIIName(attr)
@ -9350,6 +9389,15 @@ class CallbackSetter(CallbackMember):
def getArgcDecl(self):
return None
class CGJSImplInitOperation(CallbackOperationBase):
"""
Codegen the __Init() method used to pass along constructor arguments for JS-implemented WebIDL.
"""
def __init__(self, sig, descriptor):
assert sig in descriptor.interface.ctor().signatures()
CallbackOperationBase.__init__(self, (BuiltinTypes[IDLBuiltinType.Types.void], sig[1]),
"__init", "__Init", descriptor, False)
class GlobalGenRoots():
"""
Roots for global codegen.

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

@ -10,7 +10,10 @@
Constructor(long arg1, IndirectlyImplementedInterface iface),
// Constructor(long arg1, long arg2, (TestInterface or OnlyForUseInConstructor) arg3),
NamedConstructor=Example,
NamedConstructor=Example(DOMString str)
NamedConstructor=Example(DOMString str),
NamedConstructor=Example2(DictForConstructor dict, any any1, object obj1,
object? obj2, sequence<Dict> seq, optional any any2,
optional object obj3, optional object? obj4)
]
interface TestExampleInterface {
// Integer types

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

@ -17,7 +17,16 @@ enum MyTestEnum {
"b"
};
[Constructor, JSImplementation="@mozilla.org/test-js-impl-interface;1"]
// We don't support multiple constructors (bug 869268) or named constructors
// for JS-implemented WebIDL.
[Constructor(DOMString str, unsigned long num, boolean? boolArg,
TestInterface? iface, long arg1,
DictForConstructor dict, any any1,
/* (BUG 856911) object obj1,*/
object? obj2, sequence<Dict> seq, optional any any2,
/* (BUG 856911) optional object obj3, */
optional object? obj4),
JSImplementation="@mozilla.org/test-js-impl-interface;1"]
interface TestJSImplInterface {
// Integer types
// XXXbz add tests for throwing versions of all the integer stuff