зеркало из https://github.com/mozilla/gecko-dev.git
Bug 851178 - Add support for JS-implemented WebIDL constructors with arguments. r=bz
This commit is contained in:
Родитель
953592544f
Коммит
f9834a5efc
|
@ -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
|
||||
|
|
Загрузка…
Ссылка в новой задаче