Bug 868715 part 6. Add the ability to trace sequence arguments. r=peterv

This commit is contained in:
Boris Zbarsky 2013-05-16 12:36:55 -04:00
parent 69d3b09e1e
commit ac6b11ed0d
6 changed files with 326 additions and 42 deletions

View File

@ -1578,6 +1578,9 @@ public:
}
};
template<typename T>
void DoTraceSequence(JSTracer* trc, FallibleTArray<T>& seq);
// Class for simple sequence arguments, only used internally by codegen.
template<typename T>
class AutoSequence : public AutoFallibleTArray<T, 16>
@ -1592,6 +1595,148 @@ public:
}
};
// Class used to trace sequences, with specializations for various
// sequence types.
template<typename T, bool isDictionary=IsBaseOf<DictionaryBase, T>::value>
class SequenceTracer
{
explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
};
// sequence<object> or sequence<object?>
template<>
class SequenceTracer<JSObject*, false>
{
explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
public:
static void TraceSequence(JSTracer* trc, JSObject** objp, JSObject** end) {
for ( ; objp != end; ++objp) {
JS_CallObjectTracer(trc, objp, "sequence<object>");
}
}
};
// sequence<any>
template<>
class SequenceTracer<JS::Value, false>
{
explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
public:
static void TraceSequence(JSTracer* trc, JS::Value* valp, JS::Value* end) {
for ( ; valp != end; ++valp) {
JS_CallValueTracer(trc, valp, "sequence<any>");
}
}
};
// sequence<sequence<T>>
template<typename T>
class SequenceTracer<Sequence<T>, false>
{
explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
public:
static void TraceSequence(JSTracer* trc, Sequence<T>* seqp, Sequence<T>* end) {
for ( ; seqp != end; ++seqp) {
DoTraceSequence(trc, *seqp);
}
}
};
// sequence<someDictionary>
template<typename T>
class SequenceTracer<T, true>
{
explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
public:
static void TraceSequence(JSTracer* trc, T* dictp, T* end) {
for ( ; dictp != end; ++dictp) {
dictp->TraceDictionary(trc);
}
}
};
// sequence<sequence<T>?>
template<typename T>
class SequenceTracer<Nullable<Sequence<T> >, false>
{
explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
public:
static void TraceSequence(JSTracer* trc, Nullable<Sequence<T> >* seqp,
Nullable<Sequence<T> >* end) {
for ( ; seqp != end; ++seqp) {
if (!seqp->IsNull()) {
DoTraceSequence(trc, seqp->Value());
}
}
}
};
template<typename T>
void DoTraceSequence(JSTracer* trc, FallibleTArray<T>& seq)
{
SequenceTracer<T>::TraceSequence(trc, seq.Elements(),
seq.Elements() + seq.Length());
}
template<typename T>
void DoTraceSequence(JSTracer* trc, InfallibleTArray<T>& seq)
{
SequenceTracer<T>::TraceSequence(trc, seq.Elements(),
seq.Elements() + seq.Length());
}
// Rooter class for sequences; this is what we mostly use in the codegen
template<typename T>
class MOZ_STACK_CLASS SequenceRooter : private JS::CustomAutoRooter
{
public:
explicit SequenceRooter(JSContext *cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: JS::CustomAutoRooter(cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
mSequenceType(eNone)
{
}
void SetSequence(FallibleTArray<T>* aSequence)
{
mFallibleArray = aSequence;
mSequenceType = eFallibleArray;
}
void SetSequence(InfallibleTArray<T>* aSequence)
{
mInfallibleArray = aSequence;
mSequenceType = eInfallibleArray;
}
private:
enum SequenceType {
eNone,
eInfallibleArray,
eFallibleArray
};
virtual void trace(JSTracer *trc) MOZ_OVERRIDE
{
if (mSequenceType == eFallibleArray) {
DoTraceSequence(trc, *mFallibleArray);
} else if (mSequenceType == eInfallibleArray) {
DoTraceSequence(trc, *mInfallibleArray);
}
}
union {
InfallibleTArray<T>* mInfallibleArray;
FallibleTArray<T>* mFallibleArray;
};
SequenceType mSequenceType;
};
inline bool
IdEquals(jsid id, const char* string)
{

View File

@ -2618,40 +2618,43 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
# A helper function for converting things that look like a JSObject*.
def handleJSObjectType(type, isMember, failureCode):
if not isMember:
declType = CGGeneric("JS::Rooted<JSObject*>")
templateBody = "${declName} = &${valHandle}.toObject();"
setToNullCode = "${declName} = nullptr;"
template = wrapObjectTemplate(templateBody, type, setToNullCode,
failureCode)
return JSToNativeConversionInfo(template, declType=declType,
dealWithOptional=isOptional,
declArgs="cx")
if type.nullable():
declType = CGGeneric("LazyRootedObject")
else:
declType = CGGeneric("NonNullLazyRootedObject")
# If cx is null then LazyRootedObject will not be
# constructed and behave as nullptr.
templateBody = "${declName}.construct(cx, &${val}.toObject());"
# Cast of nullptr to (JSObject*) is required for template deduction.
setToNullCode = "${declName}.construct(cx, static_cast<JSObject*>(nullptr));"
if isMember == "Dictionary":
if type.nullable():
declType = CGGeneric("LazyRootedObject")
else:
declType = CGGeneric("NonNullLazyRootedObject")
# If cx is null then LazyRootedObject will not be
# constructed and behave as nullptr.
templateBody = "${declName}.construct(cx, &${val}.toObject());"
# Cast of nullptr to (JSObject*) is required for template deduction.
setToNullCode = "${declName}.construct(cx, static_cast<JSObject*>(nullptr));"
# If cx is null then LazyRootedObject will not be
# constructed and behave as nullptr.
templateBody = CGIfWrapper(CGGeneric(templateBody), "cx").define()
setToNullCode = CGIfWrapper(CGGeneric(setToNullCode), "cx").define()
template = wrapObjectTemplate(templateBody, type, setToNullCode,
failureCode)
return JSToNativeConversionInfo(template, declType=declType,
dealWithOptional=isOptional)
if not isMember:
declType = CGGeneric("JS::Rooted<JSObject*>")
else:
assert isMember == "Sequence" or isMember == "Variadic"
# We'll get traced by the sequence tracer
declType = CGGeneric("JSObject*")
templateBody = "${declName} = &${valHandle}.toObject();"
setToNullCode = "${declName} = nullptr;"
template = wrapObjectTemplate(templateBody, type, setToNullCode,
failureCode)
return JSToNativeConversionInfo(template, declType=declType,
dealWithOptional=isOptional)
dealWithOptional=isOptional,
declArgs="cx")
assert not (isEnforceRange and isClamp) # These are mutually exclusive
@ -2757,8 +2760,21 @@ for (uint32_t i = 0; i < length; ++i) {
templateBody += "\n}"
templateBody = wrapObjectTemplate(templateBody, type,
"${declName}.SetNull()")
# Sequence arguments that might contain traceable things need
# to get traced
if not isMember and typeNeedsCx(elementType, descriptorProvider):
holderType = CGTemplatedType("SequenceRooter", elementInfo.declType)
templateBody = (("${holderName}.SetSequence(&%s);\n" % arrayRef) +
templateBody)
holderArgs = "cx"
else:
holderType = None
holderArgs = None
return JSToNativeConversionInfo(templateBody, declType=typeName,
dealWithOptional=isOptional)
holderType=holderType,
dealWithOptional=isOptional,
holderArgs=holderArgs)
if type.isUnion():
if isMember:
@ -3333,12 +3349,9 @@ for (uint32_t i = 0; i < length; ++i) {
declType = "LazyRootedValue"
templateBody = "${declName}.construct(cx, ${val});"
nullHandling = "${declName}.construct(cx, JS::NullValue());"
elif isMember == "Sequence":
raise TypeError("Can't handle sequence member 'any'; need to sort "
"out rooting issues")
else:
if isMember == "Variadic":
# Variadic arguments are rooted by being in argv
if isMember == "Variadic" or isMember == "Sequence":
# Rooting is handled by the sequence tracer.
declType = "JS::Value"
else:
assert not isMember
@ -3700,11 +3713,18 @@ class CGArgumentConverter(CGThing):
replacer = dict(self.argcAndIndex, **self.replacementVariables)
replacer["seqType"] = CGTemplatedType("AutoSequence",
typeConversion.declType).define()
if typeNeedsCx(self.argument.type, self.descriptorProvider):
rooterDecl = ("SequenceRooter<%s> ${holderName}(cx);\n"
"${holderName}.SetSequence(&${declName});\n" %
typeConversion.declType.define())
else:
rooterDecl = ""
replacer["elemType"] = typeConversion.declType.define()
# NOTE: Keep this in sync with sequence conversions as needed
variadicConversion = string.Template("""${seqType} ${declName};
if (${argc} > ${index}) {
variadicConversion = string.Template("${seqType} ${declName};\n" +
rooterDecl +
"""if (${argc} > ${index}) {
if (!${declName}.SetCapacity(${argc} - ${index})) {
JS_ReportOutOfMemory(cx);
return false;
@ -4076,9 +4096,9 @@ def typeNeedsCx(type, descriptorProvider, retVal=False):
if type is None:
return False
if type.nullable():
type = type.inner
return typeNeedsCx(type.inner, descriptorProvider, retVal)
if type.isSequence() or type.isArray():
type = type.inner
return typeNeedsCx(type.inner, descriptorProvider, retVal)
if type.isUnion():
return any(typeNeedsCx(t, descriptorProvider) for t in
type.unroll().flatMemberTypes)
@ -7475,6 +7495,7 @@ class CGDictionary(CGThing):
" bool Init(JSContext* cx, JS::Handle<JS::Value> val);\n" +
(" bool Init(const nsAString& aJSON);\n" if not self.workers else "") +
" bool ToObject(JSContext* cx, JS::Handle<JSObject*> parentObject, JS::Value *vp) const;\n"
" void TraceDictionary(JSTracer* trc);\n"
"\n" +
"\n".join(memberDecls) + "\n"
"private:\n"
@ -7592,6 +7613,12 @@ class CGDictionary(CGThing):
"${defineMembers}\n"
"\n"
" return true;\n"
"}\n"
"\n"
"void\n"
"${selfName}::TraceDictionary(JSTracer* trc)\n"
"{\n"
" // XXXbz Need an implementation\n"
"}").substitute({
"selfName": self.makeClassName(d),
"initParent": CGIndenter(CGGeneric(initParent)).define(),

View File

@ -365,7 +365,11 @@ public:
void PassStringSequence(const Sequence<nsString>&);
void ReceiveAnySequence(JSContext*, nsTArray<JS::Value>&);
void ReceiveNullableAnySequence(JSContext*, Nullable<nsTArray<JS::Value> >);
void ReceiveNullableAnySequence(JSContext*, Nullable<nsTArray<JS::Value> >&);
void ReceiveAnySequenceSequence(JSContext*, nsTArray<nsTArray<JS::Value> >&);
void ReceiveObjectSequence(JSContext*, nsTArray<JSObject*>&);
void ReceiveNullableObjectSequence(JSContext*, nsTArray<JSObject*>&);
void PassSequenceOfSequences(const Sequence< Sequence<int32_t> >&);
void ReceiveSequenceOfSequences(nsTArray< nsTArray<int32_t> >&);
@ -429,16 +433,32 @@ public:
// Any types
void PassAny(JSContext*, JS::Handle<JS::Value>);
void PassVariadicAny(JSContext*, const Sequence<JS::Value>&);
void PassOptionalAny(JSContext*, const Optional<JS::Rooted<JS::Value> >&);
void PassAnyDefaultNull(JSContext*, JS::Handle<JS::Value>);
void PassSequenceOfAny(JSContext*, const Sequence<JS::Value>&);
void PassNullableSequenceOfAny(JSContext*, const Nullable<Sequence<JS::Value> >&);
void PassOptionalSequenceOfAny(JSContext*, const Optional<Sequence<JS::Value> >&);
void PassOptionalNullableSequenceOfAny(JSContext*, const Optional<Nullable<Sequence<JS::Value> > >&);
void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, const Nullable<Sequence<JS::Value> >&);
void PassSequenceOfSequenceOfAny(JSContext*, const Sequence<Sequence<JS::Value> >&);
void PassSequenceOfNullableSequenceOfAny(JSContext*, const Sequence<Nullable<Sequence<JS::Value> > >&);
void PassNullableSequenceOfNullableSequenceOfAny(JSContext*, const Nullable<Sequence<Nullable<Sequence<JS::Value> > > >&);
void PassOptionalNullableSequenceOfNullableSequenceOfAny(JSContext*, const Optional<Nullable<Sequence<Nullable<Sequence<JS::Value> > > > >&);
JS::Value ReceiveAny(JSContext*);
// object types
void PassObject(JSContext*, JS::Handle<JSObject*>);
void PassVariadicObject(JSContext*, const Sequence<JSObject*>&);
void PassNullableObject(JSContext*, JS::Handle<JSObject*>);
void PassVariadicNullableObject(JSContext*, const Sequence<JSObject*>&);
void PassOptionalObject(JSContext*, const Optional<JS::Rooted<JSObject*> >&);
void PassOptionalNullableObject(JSContext*, const Optional<JS::Rooted<JSObject*> >&);
void PassOptionalNullableObjectWithDefaultValue(JSContext*, JS::Handle<JSObject*>);
void PassSequenceOfObject(JSContext*, const Sequence<JSObject*>&);
void PassSequenceOfNullableObject(JSContext*, const Sequence<JSObject*>&);
void PassOptionalNullableSequenceOfNullableSequenceOfObject(JSContext*, const Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&);
void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject(JSContext*, const Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&);
JSObject* ReceiveObject(JSContext*);
JSObject* ReceiveNullableObject(JSContext*);
@ -495,8 +515,8 @@ public:
void PassDictionaryOrLong(JSContext*, const Dict&);
void PassDictionaryOrLong(int32_t);
void PassDictContainingDict(JSContext*, const DictContainingDict&);
void PassDictContainingSequence(const DictContainingSequence&);
void ReceiveDictContainingSequence(DictContainingSequence&);
void PassDictContainingSequence(JSContext*, const DictContainingSequence&);
void ReceiveDictContainingSequence(JSContext*, DictContainingSequence&);
// Typedefs
void ExerciseTypedefInterfaces1(TestInterface&);
@ -675,6 +695,19 @@ private:
void PassSequence(Sequence<int32_t> &) MOZ_DELETE;
void PassNullableSequence(Nullable< Sequence<int32_t> >&) MOZ_DELETE;
void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence<int32_t> >&) MOZ_DELETE;
void PassSequenceOfAny(JSContext*, Sequence<JS::Value>&) MOZ_DELETE;
void PassNullableSequenceOfAny(JSContext*, Nullable<Sequence<JS::Value> >&) MOZ_DELETE;
void PassOptionalSequenceOfAny(JSContext*, Optional<Sequence<JS::Value> >&) MOZ_DELETE;
void PassOptionalNullableSequenceOfAny(JSContext*, Optional<Nullable<Sequence<JS::Value> > >&) MOZ_DELETE;
void PassOptionalSequenceOfAnyWithDefaultValue(JSContext*, Nullable<Sequence<JS::Value> >&) MOZ_DELETE;
void PassSequenceOfSequenceOfAny(JSContext*, Sequence<Sequence<JS::Value> >&) MOZ_DELETE;
void PassSequenceOfNullableSequenceOfAny(JSContext*, Sequence<Nullable<Sequence<JS::Value> > >&) MOZ_DELETE;
void PassNullableSequenceOfNullableSequenceOfAny(JSContext*, Nullable<Sequence<Nullable<Sequence<JS::Value> > > >&) MOZ_DELETE;
void PassOptionalNullableSequenceOfNullableSequenceOfAny(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JS::Value> > > > >&) MOZ_DELETE;
void PassSequenceOfObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
void PassSequenceOfNullableObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
void PassOptionalNullableSequenceOfNullableSequenceOfObject(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&) MOZ_DELETE;
void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject(JSContext*, Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&) MOZ_DELETE;
// Enforce that only const things are passed for optional
void PassOptionalByte(Optional<int8_t>&) MOZ_DELETE;
@ -737,6 +770,11 @@ private:
void PassOptionalNullableDateWithDefaultValue(Nullable<Date>&) MOZ_DELETE;
void PassDateSequence(Sequence<Date>&) MOZ_DELETE;
void PassNullableDateSequence(Sequence<Nullable<Date> >&) MOZ_DELETE;
// Make sure variadics are const as needed
void PassVariadicAny(JSContext*, Sequence<JS::Value>&) MOZ_DELETE;
void PassVariadicObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
void PassVariadicNullableObject(JSContext*, Sequence<JSObject*>&) MOZ_DELETE;
};
class TestIndexedGetterInterface : public nsISupports,

View File

@ -336,6 +336,10 @@ interface TestInterface {
sequence<any> receiveAnySequence();
sequence<any>? receiveNullableAnySequence();
sequence<sequence<any>> receiveAnySequenceSequence();
sequence<object> receiveObjectSequence();
sequence<object?> receiveNullableObjectSequence();
void passSequenceOfSequences(sequence<sequence<long>> arg);
sequence<sequence<long>> receiveSequenceOfSequences();
@ -396,16 +400,32 @@ interface TestInterface {
// Any types
void passAny(any arg);
void passVariadicAny(any... arg);
void passOptionalAny(optional any arg);
void passAnyDefaultNull(optional any arg = null);
void passSequenceOfAny(sequence<any> arg);
void passNullableSequenceOfAny(sequence<any>? arg);
void passOptionalSequenceOfAny(optional sequence<any> arg);
void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
void passNullableSequenceOfNullableSequenceOfAny(sequence<sequence<any>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence<sequence<any>?>? arg);
any receiveAny();
// object types
void passObject(object arg);
void passVariadicObject(object... arg);
void passNullableObject(object? arg);
void passVariadicNullableObject(object... arg);
void passOptionalObject(optional object arg);
void passOptionalNullableObject(optional object? arg);
void passOptionalNullableObjectWithDefaultValue(optional object? arg = null);
void passSequenceOfObject(sequence<object> arg);
void passSequenceOfNullableObject(sequence<object?> arg);
void passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence<sequence<object>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence<sequence<object?>?>? arg);
object receiveObject();
object? receiveNullableObject();
@ -449,6 +469,8 @@ interface TestInterface {
Dict receiveDictionary();
void passOtherDictionary(optional GrandparentDict x);
void passSequenceOfDictionaries(sequence<Dict> x);
// No support for nullable dictionaries inside a sequence (nor should there be)
// void passSequenceOfNullableDictionaries(sequence<Dict?> x);
void passDictionaryOrLong(optional Dict x);
void passDictionaryOrLong(long x);
@ -657,6 +679,11 @@ dictionary DictContainingDict {
dictionary DictContainingSequence {
sequence<long> ourSequence;
sequence<TestInterface> ourSequence2;
sequence<any> ourSequence3;
// XXXbz we can't make up our minds about how to represent 'object';
// will be fixed once we trace dictionaries.
//sequence<object> ourSequence4;
sequence<object?> ourSequence5;
};
dictionary DictForConstructor {
@ -665,7 +692,9 @@ dictionary DictForConstructor {
sequence<Dict> seq1;
sequence<sequence<Dict>>? seq2;
sequence<sequence<Dict>?> seq3;
// No support for sequences of "any" or "object" as return values yet.
sequence<any> seq4;
sequence<any> seq5;
sequence<DictContainingSequence> seq6;
object obj1;
object? obj2;
any any1 = null;

View File

@ -234,6 +234,11 @@ interface TestExampleInterface {
sequence<any> receiveAnySequence();
sequence<any>? receiveNullableAnySequence();
//XXXbz No support for sequence of sequence return values yet.
//sequence<sequence<any>> receiveAnySequenceSequence();
sequence<object> receiveObjectSequence();
sequence<object?> receiveNullableObjectSequence();
void passSequenceOfSequences(sequence<sequence<long>> arg);
//XXXbz No support for sequence of sequence return values yet.
@ -293,16 +298,32 @@ interface TestExampleInterface {
// Any types
void passAny(any arg);
void passVariadicAny(any... arg);
void passOptionalAny(optional any arg);
void passAnyDefaultNull(optional any arg = null);
void passSequenceOfAny(sequence<any> arg);
void passNullableSequenceOfAny(sequence<any>? arg);
void passOptionalSequenceOfAny(optional sequence<any> arg);
void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
void passNullableSequenceOfNullableSequenceOfAny(sequence<sequence<any>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence<sequence<any>?>? arg);
any receiveAny();
// object types
void passObject(object arg);
void passVariadicObject(object... arg);
void passNullableObject(object? arg);
void passVariadicNullableObject(object... arg);
void passOptionalObject(optional object arg);
void passOptionalNullableObject(optional object? arg);
void passOptionalNullableObjectWithDefaultValue(optional object? arg = null);
void passSequenceOfObject(sequence<object> arg);
void passSequenceOfNullableObject(sequence<object?> arg);
void passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence<sequence<object>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence<sequence<object?>?>? arg);
object receiveObject();
object? receiveNullableObject();
@ -346,6 +367,8 @@ interface TestExampleInterface {
//UNSUPPORTED Dict receiveDictionary();
void passOtherDictionary(optional GrandparentDict x);
void passSequenceOfDictionaries(sequence<Dict> x);
// No support for nullable dictionaries inside a sequence (nor should there be)
// void passSequenceOfNullableDictionaries(sequence<Dict?> x);
void passDictionaryOrLong(optional Dict x);
void passDictionaryOrLong(long x);

View File

@ -252,9 +252,13 @@ interface TestJSImplInterface {
sequence<DOMString> receiveStringSequence();
// Callback interface problem. See bug 843261.
//void passStringSequence(sequence<DOMString> arg);
// "Can't handle sequence member 'any'; need to sort out rooting issues"
//sequence<any> receiveAnySequence();
//sequence<any>? receiveNullableAnySequence();
sequence<any> receiveAnySequence();
sequence<any>? receiveNullableAnySequence();
//XXXbz No support for sequence of sequence return values yet.
//sequence<sequence<any>> receiveAnySequenceSequence();
sequence<object> receiveObjectSequence();
sequence<object?> receiveNullableObjectSequence();
void passSequenceOfSequences(sequence<sequence<long>> arg);
//sequence<sequence<long>> receiveSequenceOfSequences();
@ -318,15 +322,31 @@ interface TestJSImplInterface {
// Any types
void passAny(any arg);
void passVariadicAny(any... arg);
void passOptionalAny(optional any arg);
void passAnyDefaultNull(optional any arg = null);
void passSequenceOfAny(sequence<any> arg);
void passNullableSequenceOfAny(sequence<any>? arg);
void passOptionalSequenceOfAny(optional sequence<any> arg);
void passOptionalNullableSequenceOfAny(optional sequence<any>? arg);
void passOptionalSequenceOfAnyWithDefaultValue(optional sequence<any>? arg = null);
void passSequenceOfSequenceOfAny(sequence<sequence<any>> arg);
void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
void passNullableSequenceOfNullableSequenceOfAny(sequence<sequence<any>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence<sequence<any>?>? arg);
any receiveAny();
void passObject(object arg);
void passVariadicObject(object... arg);
void passNullableObject(object? arg);
void passVariadicNullableObject(object... arg);
void passOptionalObject(optional object arg);
void passOptionalNullableObject(optional object? arg);
void passOptionalNullableObjectWithDefaultValue(optional object? arg = null);
void passSequenceOfObject(sequence<object> arg);
void passSequenceOfNullableObject(sequence<object?> arg);
void passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence<sequence<object>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence<sequence<object?>?>? arg);
object receiveObject();
object? receiveNullableObject();
@ -373,6 +393,8 @@ interface TestJSImplInterface {
// Dict receiveDictionary();
void passOtherDictionary(optional GrandparentDict x);
void passSequenceOfDictionaries(sequence<Dict> x);
// No support for nullable dictionaries inside a sequence (nor should there be)
// void passSequenceOfNullableDictionaries(sequence<Dict?> x);
void passDictionaryOrLong(optional Dict x);
void passDictionaryOrLong(long x);