Bug 743906 part 2. Use Optional<> for optional arguments that don't have default values. r=peterv

This commit is contained in:
Boris Zbarsky 2012-05-29 23:45:18 -04:00
Родитель d27336d5d7
Коммит 702a4a496f
8 изменённых файлов: 530 добавлений и 70 удалений

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

@ -1767,13 +1767,21 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
// No optional arguments were passed in. Default async to true.
async = true;
}
return Open(method, url, async, user, password);
Optional<nsAString> realUser;
if (optional_argc > 1) {
realUser = &user;
}
Optional<nsAString> realPassword;
if (optional_argc > 2) {
realPassword = &password;
}
return Open(method, url, async, realUser, realPassword);
}
nsresult
nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
bool async, const nsAString& user,
const nsAString& password)
bool async, const Optional<nsAString>& user,
const Optional<nsAString>& password)
{
NS_ENSURE_ARG(!method.IsEmpty());
@ -1870,12 +1878,14 @@ nsXMLHttpRequest::Open(const nsACString& method, const nsACString& url,
return NS_ERROR_CONTENT_BLOCKED;
}
if (!user.IsEmpty()) {
// XXXbz this is wrong: we should only be looking at whether
// user/password were passed, not at the values! See bug 759624.
if (user.WasPassed() && !user.Value().IsEmpty()) {
nsCAutoString userpass;
CopyUTF16toUTF8(user, userpass);
if (!password.IsEmpty()) {
CopyUTF16toUTF8(user.Value(), userpass);
if (password.WasPassed() && !password.Value().IsEmpty()) {
userpass.Append(':');
AppendUTF16toUTF8(password, userpass);
AppendUTF16toUTF8(password.Value(), userpass);
}
uri->SetUserPass(userpass);
}

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

@ -252,7 +252,9 @@ public:
// request
void Open(const nsAString& aMethod, const nsAString& aUrl, bool aAsync,
const nsAString& aUser, const nsAString& aPassword, ErrorResult& aRv)
const mozilla::dom::Optional<nsAString>& aUser,
const mozilla::dom::Optional<nsAString>& aPassword,
ErrorResult& aRv)
{
aRv = Open(NS_ConvertUTF16toUTF8(aMethod), NS_ConvertUTF16toUTF8(aUrl),
aAsync, aUser, aPassword);
@ -536,7 +538,8 @@ protected:
void OnRedirectVerifyCallback(nsresult result);
nsresult Open(const nsACString& method, const nsACString& url, bool async,
const nsAString& user, const nsAString& password);
const mozilla::dom::Optional<nsAString>& user,
const mozilla::dom::Optional<nsAString>& password);
nsCOMPtr<nsISupports> mContext;
nsCOMPtr<nsIPrincipal> mPrincipal;

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

@ -631,6 +631,12 @@ public:
return *ptr;
}
operator const T&() const {
MOZ_ASSERT(inited);
MOZ_ASSERT(ptr, "NonNull<T> was set to null");
return *ptr;
}
void operator=(T* t) {
ptr = t;
MOZ_ASSERT(ptr);
@ -745,6 +751,71 @@ ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval,
return true;
}
// Class for representing optional arguments.
template<typename T>
class Optional {
public:
Optional() {}
bool WasPassed() const {
return !mImpl.empty();
}
void Construct() {
mImpl.construct();
}
template <class T1, class T2>
void Construct(const T1 &t1, const T2 &t2) {
mImpl.construct(t1, t2);
}
const T& Value() const {
return mImpl.ref();
}
T& Value() {
return mImpl.ref();
}
private:
// Forbid copy-construction and assignment
Optional(const Optional& other) MOZ_DELETE;
const Optional &operator=(const Optional &other) MOZ_DELETE;
Maybe<T> mImpl;
};
// Specialization for strings.
template<>
class Optional<nsAString> {
public:
Optional() : mPassed(false) {}
bool WasPassed() const {
return mPassed;
}
void operator=(const nsAString* str) {
MOZ_ASSERT(str);
mStr = str;
mPassed = true;
}
const nsAString& Value() const {
MOZ_ASSERT(WasPassed());
return *mStr;
}
private:
// Forbid copy-construction and assignment
Optional(const Optional& other) MOZ_DELETE;
const Optional &operator=(const Optional &other) MOZ_DELETE;
bool mPassed;
const nsAString* mStr;
};
// Class for representing sequences in arguments. We use an auto array that can
// hold 16 elements, to avoid having to allocate in common cases. This needs to
// be fallible because web content controls the length of the array, and can
@ -752,6 +823,8 @@ ConvertJSValueToString(JSContext* cx, const JS::Value& v, JS::Value* pval,
template<typename T>
class Sequence : public AutoFallibleTArray<T, 16>
{
public:
Sequence() : AutoFallibleTArray<T, 16>() {}
};
} // namespace dom

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

@ -1301,7 +1301,8 @@ ${target} = tmp.forget();""").substitute(self.substitution)
def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
isDefinitelyObject=False,
isSequenceMember=False):
isSequenceMember=False,
isOptional=False):
"""
Get a template for converting a JS value to a native object based on the
given type and descriptor. If failureCode is given, then we're actually
@ -1315,7 +1316,12 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
If isDefinitelyObject is True, that means we know the value
isObject() and we have no need to recheck that.
The return value from this function is a tuple consisting of three things:
if isSequenceMember is True, we're being converted as part of a sequence.
If isOptional is true, then we are doing conversion of an optional
argument with no default value.
The return value from this function is a tuple consisting of four things:
1) A string representing the conversion code. This will have template
substitution performed on it as follows:
@ -1331,6 +1337,11 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
3) A CGThing representing the type of a "holder" (holderType) which will
hold a possible reference to the C++ thing whose type we returned in #1,
or None if no such holder is needed.
4) A boolean indicating whether the caller has to do optional-argument handling.
This will only be true if isOptional is true and if the returned template
expects both declType and holderType to be wrapped in Optional<>, with
${declName} and ${holderName} adjusted to point to the Value() of the
Optional, and Construct() calls to be made on the Optional<>s as needed.
${declName} must be in scope before the generated code is entered.
@ -1383,17 +1394,24 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
# We don't know anything about the object-ness of the things
# we wrap, so don't pass through isDefinitelyObject
(elementTemplate, elementDeclType,
elementHolderType) = getJSToNativeConversionTemplate(
elementHolderType, dealWithOptional) = getJSToNativeConversionTemplate(
elementType, descriptorProvider, isSequenceMember=True)
if dealWithOptional:
raise TypeError("Shouldn't have optional things in sequences")
if elementHolderType is not None:
raise TypeError("Shouldn't need holders for sequences")
typeName = CGWrapper(elementDeclType, pre="Sequence< ", post=" >")
if nullable:
typeName = CGWrapper(typeName, pre="Nullable< ", post=" >")
arrayRef = "${holderName}.Value()"
arrayRef = "${declName}.Value()"
else:
arrayRef = "${holderName}"
arrayRef = "${declName}"
# If we're optional, the const will come from the Optional
mutableTypeName = typeName
if not isOptional:
typeName = CGWrapper(typeName, pre="const ")
templateBody = ("""JSObject* seq = &${val}.toObject();\n
if (!IsArrayLike(cx, seq)) {
return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);
@ -1403,7 +1421,7 @@ uint32_t length;
if (!JS_GetArrayLength(cx, seq, &length)) {
return false;
}
Sequence< %s > &arr = %s;
Sequence< %s > &arr = const_cast< Sequence< %s >& >(%s);
if (!arr.SetCapacity(length)) {
return Throw<%s>(cx, NS_ERROR_OUT_OF_MEMORY);
}
@ -1413,6 +1431,7 @@ for (uint32_t i = 0; i < length; ++i) {
return false;
}
""" % (toStringBool(descriptorProvider.workers),
elementDeclType.define(),
elementDeclType.define(),
arrayRef,
toStringBool(descriptorProvider.workers)))
@ -1427,15 +1446,10 @@ for (uint32_t i = 0; i < length; ++i) {
templateBody += "\n}"
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
type, "${holderName}.SetNull()",
type,
"const_cast< %s & >(${declName}).SetNull()" % mutableTypeName.define(),
descriptorProvider.workers)
# And now at the very end (so we make sure it happens in the
# null case too, set our declName.
templateBody += ("\n" + "${declName} = &${holderName};")
# This is a bit of a hack: we're using NonNull with a const type inside
# to effectively produce a const ref from a non-const object.
return (templateBody, CGWrapper(typeName, pre="NonNull<const ", post=" >"),
typeName)
return (templateBody, typeName, None, isOptional)
if type.isGeckoInterface():
descriptor = descriptorProvider.getDescriptor(
@ -1535,7 +1549,7 @@ for (uint32_t i = 0; i < length; ++i) {
declType = CGGeneric(declType)
if holderType is not None:
holderType = CGGeneric(holderType)
return (templateBody, declType, holderType)
return (templateBody, declType, holderType, isOptional)
if type.isSpiderMonkeyInterface():
if isSequenceMember:
@ -1550,27 +1564,53 @@ for (uint32_t i = 0; i < length; ++i) {
else:
jsname = type.name
# By default, we use a Maybe<> to hold our typed array. And in the optional
# non-nullable case we want to pass Optional<TypedArray> to consumers, not
# Optional<NonNull<TypedArray> >, so jump though some hoops to do that.
holderType = "Maybe<%s>" % name
constructLoc = "${holderName}"
constructMethod = "construct"
if type.nullable():
declType = name + "*"
if isOptional:
declType = "const Optional<" + name + "*>"
else:
declType = name + "*"
else:
declType = "NonNull<" + name + ">"
if isOptional:
declType = "const Optional<" + name + ">"
# We don't need a holder in this case
holderType = None
constructLoc = "(const_cast<Optional<" + name + ">& >(${declName}))"
constructMethod = "Construct"
else:
declType = "NonNull<" + name + ">"
template = (
"if (!JS_Is%s(&${val}.toObject(), cx)) {\n"
" %s" # No newline here because onFailure() handles that
"}\n"
"${holderName}.construct(cx, &${val}.toObject());\n" %
(jsname, onFailure(failureCode, descriptorProvider.workers).define()))
if type.nullable:
"%s.%s(cx, &${val}.toObject());\n" %
(jsname, onFailure(failureCode, descriptorProvider.workers).define(),
constructLoc, constructMethod))
nullableTarget = ""
if type.nullable():
if isOptional:
mutableDecl = "(const_cast<Optional<" + name + "*>& >(${declName}))"
template += "%s.Construct();\n" % mutableDecl
nullableTarget = "%s.Value()" % mutableDecl
else:
nullableTarget = "${declName}"
template += "%s = ${holderName}.addr();" % nullableTarget
elif not isOptional:
template += "${declName} = ${holderName}.addr();"
else:
template += "${declName} = ${holderName}.ref();"
template = wrapObjectTemplate(template, isDefinitelyObject, type,
"${declName} = NULL",
"%s = NULL" % nullableTarget,
descriptorProvider.workers,
failureCode)
return (template, CGGeneric(declType), CGGeneric(holderType))
if holderType is not None:
holderType = CGGeneric(holderType)
# We handle all the optional stuff ourselves; no need for caller to do it.
return (template, CGGeneric(declType), holderType, False)
if type.isString():
if isSequenceMember:
@ -1587,12 +1627,19 @@ for (uint32_t i = 0; i < length; ++i) {
nullBehavior = "eStringify"
undefinedBehavior = "eStringify"
if isOptional:
declType = "Optional<nsAString>"
else:
declType = "NonNull<nsAString>"
return (
"if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, ${holderName})) {\n"
" return false;\n"
"}\n"
"${declName} = &${holderName};" % (nullBehavior, undefinedBehavior),
CGGeneric("NonNull<const nsAString>"), CGGeneric("nsDependentString"))
"const_cast<%s&>(${declName}) = &${holderName};" %
(nullBehavior, undefinedBehavior, declType),
CGGeneric("const " + declType), CGGeneric("nsDependentString"),
# No need to deal with Optional here; we have handled it already
False)
if type.isEnum():
if type.nullable():
@ -1608,7 +1655,7 @@ for (uint32_t i = 0; i < length; ++i) {
" }\n"
"}" % { "enumtype" : enum,
"values" : enum + "Values::strings" },
CGGeneric(enum), None)
CGGeneric(enum), None, isOptional)
if type.isCallback():
if isSequenceMember:
@ -1620,12 +1667,12 @@ for (uint32_t i = 0; i < length; ++i) {
" ${declName} = &${val}.toObject();\n"
"} else {\n"
" ${declName} = NULL;\n"
"}", CGGeneric("JSObject*"), None)
"}", CGGeneric("JSObject*"), None, isOptional)
if type.isAny():
if isSequenceMember:
raise TypeError("Can't handle sequences of 'any'")
return ("${declName} = ${val};", CGGeneric("JS::Value"), None)
return ("${declName} = ${val};", CGGeneric("JS::Value"), None, isOptional)
if type.isObject():
if isSequenceMember:
@ -1638,7 +1685,7 @@ for (uint32_t i = 0; i < length; ++i) {
declType = CGGeneric("JSObject*")
else:
declType = CGGeneric("NonNull<JSObject>")
return (template, declType, None)
return (template, declType, None, isOptional)
if not type.isPrimitive():
raise TypeError("Need conversion for argument type '%s'" % type)
@ -1650,33 +1697,91 @@ for (uint32_t i = 0; i < length; ++i) {
" ${declName}.SetNull();\n"
"} else if (!ValueToPrimitive<" + typeName + ">(cx, ${val}, &${declName}.SetValue())) {\n"
" return false;\n"
"}", CGGeneric("Nullable<" + typeName + ">"), None)
"}", CGGeneric("Nullable<" + typeName + ">"), None, isOptional)
else:
return ("if (!ValueToPrimitive<" + typeName + ">(cx, ${val}, &${declName})) {\n"
" return false;\n"
"}", CGGeneric(typeName), None)
"}", CGGeneric(typeName), None, isOptional)
def instantiateJSToNativeConversionTemplate(templateTuple, replacements):
def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
argcAndIndex=None):
"""
Take a tuple as returned by getJSToNativeConversionTemplate and a set of
replacements as required by the strings in such a tuple, and generate code
to convert into stack C++ types.
If argcAndIndex is not None it must be a dict that can be used to
replace ${argc} and ${index}, where ${index} is the index of this
argument (0-based) and ${argc} is the total number of arguments.
"""
(templateBody, declType, holderType) = templateTuple
(templateBody, declType, holderType, dealWithOptional) = templateTuple
if dealWithOptional and argcAndIndex is None:
raise TypeError("Have to deal with optional things, but don't know how")
if argcAndIndex is not None and declType is None:
raise TypeError("Need to predeclare optional things, so they will be "
"outside the check for big enough arg count!");
result = CGList([], "\n")
# Make a copy of "replacements" since we may be about to start modifying it
replacements = dict(replacements)
originalHolderName = replacements["holderName"]
if holderType is not None:
if dealWithOptional:
replacements["holderName"] = (
"const_cast< %s & >(%s.Value())" %
(holderType.define(), originalHolderName))
mutableHolderType = CGWrapper(holderType, pre="Optional< ", post=" >")
holderType = CGWrapper(mutableHolderType, pre="const ")
result.append(
CGList([holderType, CGGeneric(" "),
CGGeneric(replacements["holderName"]),
CGGeneric(originalHolderName),
CGGeneric(";")]))
originalDeclName = replacements["declName"]
if declType is not None:
if dealWithOptional:
replacements["declName"] = (
"const_cast< %s & >(%s.Value())" %
(declType.define(), originalDeclName))
mutableDeclType = CGWrapper(declType, pre="Optional< ", post=" >")
declType = CGWrapper(mutableDeclType, pre="const ")
result.append(
CGList([declType, CGGeneric(" "),
CGGeneric(replacements["declName"]),
CGGeneric(originalDeclName),
CGGeneric(";")]))
result.append(CGGeneric(
conversion = CGGeneric(
string.Template(templateBody).substitute(replacements)
))
)
if argcAndIndex is not None:
if dealWithOptional:
declConstruct = CGIndenter(
CGGeneric("const_cast< %s &>(%s).Construct();" %
(mutableDeclType.define(), originalDeclName)))
if holderType is not None:
holderConstruct = CGIndenter(
CGGeneric("const_cast< %s &>(%s).Construct();" %
(mutableHolderType.define(), originalHolderName)))
else:
holderConstruct = None
else:
declConstruct = None
holderConstruct = None
conversion = CGList(
[CGGeneric(
string.Template("if (${index} < ${argc}) {").substitute(
argcAndIndex
)),
declConstruct,
holderConstruct,
CGIndenter(conversion),
CGGeneric("}")],
"\n")
result.append(conversion)
# Add an empty CGGeneric to get an extra newline after the argument
# conversion.
result.append(CGGeneric(""))
@ -1702,7 +1807,8 @@ def convertConstIDLValueToJSVal(value):
def convertIDLDefaultValueToJSVal(value):
if value.type:
tag = value.type.tag()
if tag == IDLType.Tags.domstring:
if (tag == IDLType.Tags.domstring and
(not value.type.nullable() or not isinstance(value, IDLNullValue))):
assert False # Not implemented!
return convertConstIDLValueToJSVal(value)
@ -1743,12 +1849,18 @@ class CGArgumentConverter(CGThing):
self.replacementVariables["valPtr"] = (
"&" + self.replacementVariables["val"])
self.descriptorProvider = descriptorProvider
if self.argument.optional and not self.argument.defaultValue:
self.argcAndIndex = replacer
else:
self.argcAndIndex = None
def define(self):
return instantiateJSToNativeConversionTemplate(
getJSToNativeConversionTemplate(self.argument.type,
self.descriptorProvider),
self.replacementVariables).define()
self.descriptorProvider,
isOptional=(self.argcAndIndex is not None)),
self.replacementVariables,
self.argcAndIndex).define()
def getWrapTemplateForType(type, descriptorProvider, result, successCode):
"""
@ -2036,7 +2148,7 @@ class CGCallGenerator(CGThing):
for (i, a) in enumerate(arguments):
arg = "arg" + str(i)
# This is a workaround for a bug in Apple's clang.
if a.type.isObject() and not a.type.nullable():
if a.type.isObject() and not a.type.nullable() and not a.optional:
arg = "(JSObject&)" + arg
args.append(CGGeneric(arg))
resultOutParam = (returnType is not None and
@ -2387,7 +2499,10 @@ class CGMethodCall(CGThing):
for sig in interfacesSigs:
caseBody.append(CGIndenter(CGGeneric("do {")));
type = sig[1][distinguishingIndex].type
# The argument at index distinguishingIndex can't possibly
# be unset here, because we've already checked that argc is
# large enough that we can examine this argument.
testCode = instantiateJSToNativeConversionTemplate(
getJSToNativeConversionTemplate(type, descriptor,
failureCode="break;",

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

@ -10,7 +10,10 @@
#include "nsWrapperCache.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/TypedArray.h"
#include "nsCOMPtr.h"
// We don't export TestCodeGenBinding.h, but it's right in our parent dir.
#include "../TestCodeGenBinding.h"
namespace mozilla {
namespace dom {
@ -52,54 +55,75 @@ public:
virtual nsISupports* GetParentObject();
// And now our actual WebIDL API
// Integer types
int8_t GetReadonlyByte(ErrorResult&);
int8_t GetWritableByte(ErrorResult&);
void SetWritableByte(int8_t, ErrorResult&);
void PassByte(int8_t, ErrorResult&);
int8_t ReceiveByte(ErrorResult&);
void PassOptionalByte(const Optional<int8_t>&, ErrorResult&);
void PassOptionalByteWithDefault(int8_t, ErrorResult&);
void PassNullableByte(Nullable<int8_t>&, ErrorResult&);
void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&,
ErrorResult&);
int16_t GetReadonlyShort(ErrorResult&);
int16_t GetWritableShort(ErrorResult&);
void SetWritableShort(int16_t, ErrorResult&);
void PassShort(int16_t, ErrorResult&);
int16_t ReceiveShort(ErrorResult&);
void PassOptionalShort(const Optional<int16_t>&, ErrorResult&);
void PassOptionalShortWithDefault(int16_t, ErrorResult&);
int32_t GetReadonlyLong(ErrorResult&);
int32_t GetWritableLong(ErrorResult&);
void SetWritableLong(int32_t, ErrorResult&);
void PassLong(int32_t, ErrorResult&);
int16_t ReceiveLong(ErrorResult&);
void PassOptionalLong(const Optional<int32_t>&, ErrorResult&);
void PassOptionalLongWithDefault(int32_t, ErrorResult&);
int64_t GetReadonlyLongLong(ErrorResult&);
int64_t GetWritableLongLong(ErrorResult&);
void SetWritableLongLong(int64_t, ErrorResult&);
void PassLongLong(int64_t, ErrorResult&);
int64_t ReceiveLongLong(ErrorResult&);
void PassOptionalLongLong(const Optional<int64_t>&, ErrorResult&);
void PassOptionalLongLongWithDefault(int64_t, ErrorResult&);
uint8_t GetReadonlyOctet(ErrorResult&);
uint8_t GetWritableOctet(ErrorResult&);
void SetWritableOctet(uint8_t, ErrorResult&);
void PassOctet(uint8_t, ErrorResult&);
uint8_t ReceiveOctet(ErrorResult&);
void PassOptionalOctet(const Optional<uint8_t>&, ErrorResult&);
void PassOptionalOctetWithDefault(uint8_t, ErrorResult&);
uint16_t GetReadonlyUnsignedShort(ErrorResult&);
uint16_t GetWritableUnsignedShort(ErrorResult&);
void SetWritableUnsignedShort(uint16_t, ErrorResult&);
void PassUnsignedShort(uint16_t, ErrorResult&);
uint16_t ReceiveUnsignedShort(ErrorResult&);
void PassOptionalUnsignedShort(const Optional<uint16_t>&, ErrorResult&);
void PassOptionalUnsignedShortWithDefault(uint16_t, ErrorResult&);
uint32_t GetReadonlyUnsignedLong(ErrorResult&);
uint32_t GetWritableUnsignedLong(ErrorResult&);
void SetWritableUnsignedLong(uint32_t, ErrorResult&);
void PassUnsignedLong(uint32_t, ErrorResult&);
uint32_t ReceiveUnsignedLong(ErrorResult&);
void PassOptionalUnsignedLong(const Optional<uint32_t>&, ErrorResult&);
void PassOptionalUnsignedLongWithDefault(uint32_t, ErrorResult&);
uint64_t GetReadonlyUnsignedLongLong(ErrorResult&);
uint64_t GetWritableUnsignedLongLong(ErrorResult&);
void SetWritableUnsignedLongLong(uint64_t, ErrorResult&);
void PassUnsignedLongLong(uint64_t, ErrorResult&);
uint64_t ReceiveUnsignedLongLong(ErrorResult&);
void PassOptionalUnsignedLongLong(const Optional<uint64_t>&, ErrorResult&);
void PassOptionalUnsignedLongLongWithDefault(uint64_t, ErrorResult&);
// Interface types
already_AddRefed<TestInterface> ReceiveSelf(ErrorResult&);
already_AddRefed<TestInterface> ReceiveNullableSelf(ErrorResult&);
TestInterface* ReceiveWeakSelf(ErrorResult&);
@ -111,6 +135,9 @@ public:
void SetNonNullSelf(TestInterface&, ErrorResult&);
already_AddRefed<TestInterface> GetNullableSelf(ErrorResult&);
void SetNullableSelf(TestInterface*, ErrorResult&);
void PassOptionalSelf(const Optional<TestInterface*> &, ErrorResult&);
void PassOptionalNonNullSelf(const Optional<NonNull<TestInterface> >&, ErrorResult&);
void PassOptionalSelfWithDefault(TestInterface*, ErrorResult&);
already_AddRefed<TestNonCastableInterface> ReceiveOther(ErrorResult&);
already_AddRefed<TestNonCastableInterface> ReceiveNullableOther(ErrorResult&);
@ -123,6 +150,9 @@ public:
void SetNonNullOther(TestNonCastableInterface&, ErrorResult&);
already_AddRefed<TestNonCastableInterface> GetNullableOther(ErrorResult&);
void SetNullableOther(TestNonCastableInterface*, ErrorResult&);
void PassOptionalOther(const Optional<TestNonCastableInterface*>&, ErrorResult&);
void PassOptionalNonNullOther(const Optional<NonNull<TestNonCastableInterface> >&, ErrorResult&);
void PassOptionalOtherWithDefault(TestNonCastableInterface*, ErrorResult&);
already_AddRefed<TestExternalInterface> ReceiveExternal(ErrorResult&);
already_AddRefed<TestExternalInterface> ReceiveNullableExternal(ErrorResult&);
@ -135,7 +165,11 @@ public:
void SetNonNullExternal(TestExternalInterface*, ErrorResult&);
already_AddRefed<TestExternalInterface> GetNullableExternal(ErrorResult&);
void SetNullableExternal(TestExternalInterface*, ErrorResult&);
void PassOptionalExternal(const Optional<TestExternalInterface*>&, ErrorResult&);
void PassOptionalNonNullExternal(const Optional<TestExternalInterface*>&, ErrorResult&);
void PassOptionalExternalWithDefault(TestExternalInterface*, ErrorResult&);
// Sequence types
void ReceiveSequence(nsTArray<int32_t>&, ErrorResult&);
void ReceiveNullableSequence(Nullable< nsTArray<int32_t> >&, ErrorResult&);
void PassSequence(const Sequence<int32_t> &, ErrorResult&);
@ -168,6 +202,56 @@ public:
ErrorResult&);
void PassNullableCastableObjectNullableSequence(const Nullable< Sequence< nsRefPtr<TestInterface> > >&,
ErrorResult&);
void PassOptionalSequence(const Optional<Sequence<int32_t> >&,
ErrorResult&);
void PassOptionalNullableSequence(const Optional<Nullable<Sequence<int32_t> > >&,
ErrorResult&);
void PassOptionalNullableSequenceWithDefaultValue(const Nullable< Sequence<int32_t> >&,
ErrorResult&);
void PassOptionalObjectSequence(const Optional<Sequence<OwningNonNull<TestInterface> > >&,
ErrorResult&);
// Typed array types
void PassArrayBuffer(ArrayBuffer&, ErrorResult&);
void PassNullableArrayBuffer(ArrayBuffer*, ErrorResult&);
void PassOptionalArrayBuffer(const Optional<ArrayBuffer>&, ErrorResult&);
void PassOptionalNullableArrayBuffer(const Optional<ArrayBuffer*>&, ErrorResult&);
void PassOptionalNullableArrayBufferWithDefaultValue(ArrayBuffer*, ErrorResult&);
// String types
void PassString(const nsAString&, ErrorResult&);
void PassNullableString(const nsAString&, ErrorResult&);
void PassOptionalString(const Optional<nsAString>&, ErrorResult&);
void PassOptionalNullableString(const Optional<nsAString>&, ErrorResult&);
void PassOptionalNullableStringWithDefaultValue(const nsAString&, ErrorResult&);
// Enumarated types
void PassEnum(TestEnum, ErrorResult&);
void PassOptionalEnum(const Optional<TestEnum>&, ErrorResult&);
TestEnum ReceiveEnum(ErrorResult&);
// Callback types
void PassCallback(JSObject*, ErrorResult&);
void PassNullableCallback(JSObject*, ErrorResult&);
void PassOptionalCallback(const Optional<JSObject*>&, ErrorResult&);
void PassOptionalNullableCallback(const Optional<JSObject*>&, ErrorResult&);
void PassOptionalNullableCallbackWithDefaultValue(JSObject*, ErrorResult&);
JSObject* ReceiveCallback(ErrorResult&);
JSObject* ReceiveNullableCallback(ErrorResult&);
// Any types
void PassAny(JS::Value, ErrorResult&);
void PassOptionalAny(const Optional<JS::Value>&, ErrorResult&);
JS::Value ReceiveAny(ErrorResult&);
void PassObject(JSContext*, JSObject&, ErrorResult&);
void PassNullableObject(JSContext*, JSObject*, ErrorResult&);
void PassOptionalObject(JSContext*, const Optional<NonNull<JSObject> >&, ErrorResult&);
void PassOptionalNullableObject(JSContext*, const Optional<JSObject*>&, ErrorResult&);
void PassOptionalNullableObjectWithDefaultValue(JSContext*, JSObject*, ErrorResult&);
JSObject* ReceiveObject(JSContext*, ErrorResult&);
JSObject* ReceiveNullableObject(JSContext*, ErrorResult&);
private:
// We add signatures here that _could_ start matching if the codegen
// got data types wrong. That way if it ever does we'll have a call
@ -177,51 +261,123 @@ private:
void SetWritableByte(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassByte(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalByte(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalByteWithDefault(T, ErrorResult&) MOZ_DELETE;
void SetReadonlyShort(int16_t, ErrorResult&) MOZ_DELETE;
template<typename T>
void SetWritableShort(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassShort(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalShort(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalShortWithDefault(T, ErrorResult&) MOZ_DELETE;
void SetReadonlyLong(int32_t, ErrorResult&) MOZ_DELETE;
template<typename T>
void SetWritableLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalLongWithDefault(T, ErrorResult&) MOZ_DELETE;
void SetReadonlyLongLong(int64_t, ErrorResult&) MOZ_DELETE;
template<typename T>
void SetWritableLongLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassLongLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalLongLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalLongLongWithDefault(T, ErrorResult&) MOZ_DELETE;
void SetReadonlyOctet(uint8_t, ErrorResult&) MOZ_DELETE;
template<typename T>
void SetWritableOctet(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOctet(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalOctet(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalOctetWithDefault(T, ErrorResult&) MOZ_DELETE;
void SetReadonlyUnsignedShort(uint16_t, ErrorResult&) MOZ_DELETE;
template<typename T>
void SetWritableUnsignedShort(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassUnsignedShort(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalUnsignedShort(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalUnsignedShortWithDefault(T, ErrorResult&) MOZ_DELETE;
void SetReadonlyUnsignedLong(uint32_t, ErrorResult&) MOZ_DELETE;
template<typename T>
void SetWritableUnsignedLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassUnsignedLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalUnsignedLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalUnsignedLongWithDefault(T, ErrorResult&) MOZ_DELETE;
void SetReadonlyUnsignedLongLong(uint64_t, ErrorResult&) MOZ_DELETE;
template<typename T>
void SetWritableUnsignedLongLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassUnsignedLongLong(T, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalUnsignedLongLong(const Optional<T>&, ErrorResult&) MOZ_DELETE;
template<typename T>
void PassOptionalUnsignedLongLongWithDefault(T, ErrorResult&) MOZ_DELETE;
// Enforce that only const things are passed for sequences
void PassSequence(Sequence<int32_t> &, ErrorResult&) MOZ_DELETE;
void PassNullableSequence(Nullable< Sequence<int32_t> >&, ErrorResult&) MOZ_DELETE;
void PassOptionalNullableSequenceWithDefaultValue(Nullable< Sequence<int32_t> >&,
ErrorResult&) MOZ_DELETE;
// Enforce that only const things are passed for optional
void PassOptionalByte(Optional<int8_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalNullableByte(Optional<Nullable<int8_t> >&,
ErrorResult&) MOZ_DELETE;
void PassOptionalShort(Optional<int16_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalLong(Optional<int32_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalLongLong(Optional<int64_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalOctet(Optional<uint8_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalUnsignedShort(Optional<uint16_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalUnsignedLong(Optional<uint32_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalUnsignedLongLong(Optional<uint64_t>&, ErrorResult&) MOZ_DELETE;
void PassOptionalSelf(Optional<TestInterface*> &, ErrorResult&) MOZ_DELETE;
void PassOptionalNonNullSelf(Optional<NonNull<TestInterface> >&, ErrorResult&) MOZ_DELETE;
void PassOptionalOther(Optional<TestNonCastableInterface*>&, ErrorResult&);
void PassOptionalNonNullOther(Optional<NonNull<TestNonCastableInterface> >&, ErrorResult&);
void PassOptionalExternal(Optional<TestExternalInterface*>&, ErrorResult&) MOZ_DELETE;
void PassOptionalNonNullExternal(Optional<TestExternalInterface*>&, ErrorResult&) MOZ_DELETE;
void PassOptionalSequence(Optional<Sequence<int32_t> >&, ErrorResult&) MOZ_DELETE;
void PassOptionalNullableSequence(Optional<Nullable<Sequence<int32_t> > >&,
ErrorResult&) MOZ_DELETE;
void PassOptionalObjectSequence(Optional<Sequence<OwningNonNull<TestInterface> > >&,
ErrorResult&) MOZ_DELETE;
void PassOptionalArrayBuffer(Optional<ArrayBuffer>&, ErrorResult&) MOZ_DELETE;
void PassOptionalNullableArrayBuffer(Optional<ArrayBuffer*>&, ErrorResult&) MOZ_DELETE;
void PassOptionalEnum(Optional<TestEnum>&, ErrorResult&) MOZ_DELETE;
void PassOptionalCallback(Optional<JSObject*>&, ErrorResult&) MOZ_DELETE;
void PassOptionalNullableCallback(Optional<JSObject*>&, ErrorResult&) MOZ_DELETE;
void PassOptionalAny(Optional<JS::Value>&, ErrorResult) MOZ_DELETE;
// And test that string stuff is always const
void PassString(nsAString&, ErrorResult&) MOZ_DELETE;
void PassNullableString(nsAString&, ErrorResult&) MOZ_DELETE;
void PassOptionalString(Optional<nsAString>&, ErrorResult&) MOZ_DELETE;
void PassOptionalNullableString(Optional<nsAString>&, ErrorResult&) MOZ_DELETE;
void PassOptionalNullableStringWithDefaultValue(nsAString&, ErrorResult&) MOZ_DELETE;
};
} // namespace dom

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

@ -9,6 +9,13 @@ interface TestExternalInterface;
interface TestNonCastableInterface {
};
enum TestEnum {
"a",
"b"
};
callback TestCallback = void();
interface TestInterface {
// Integer types
// XXXbz add tests for infallible versions of all the integer stuff
@ -16,41 +23,59 @@ interface TestInterface {
attribute byte writableByte;
void passByte(byte arg);
byte receiveByte();
void passOptionalByte(optional byte arg);
void passOptionalByteWithDefault(optional byte arg = 0);
void passNullableByte(byte? arg);
void passOptionalNullableByte(optional byte? arg);
readonly attribute short readonlyShort;
attribute short writableShort;
void passShort(short arg);
short receiveShort();
void passOptionalShort(optional short arg);
void passOptionalShortWithDefault(optional short arg = 0);
readonly attribute long readonlyLong;
attribute long writableLong;
void passLong(long arg);
long receiveLong();
void passOptionalLong(optional long arg);
void passOptionalLongWithDefault(optional long arg = 0);
readonly attribute long long readonlyLongLong;
attribute long long writableLongLong;
attribute long long writableLongLong;
void passLongLong(long long arg);
long long receiveLongLong();
void passOptionalLongLong(optional long long arg);
void passOptionalLongLongWithDefault(optional long long arg = 0);
readonly attribute octet readonlyOctet;
attribute octet writableOctet;
void passOctet(octet arg);
octet receiveOctet();
void passOptionalOctet(optional octet arg);
void passOptionalOctetWithDefault(optional octet arg = 0);
readonly attribute unsigned short readonlyUnsignedShort;
attribute unsigned short writableUnsignedShort;
void passUnsignedShort(unsigned short arg);
unsigned short receiveUnsignedShort();
void passOptionalUnsignedShort(optional unsigned short arg);
void passOptionalUnsignedShortWithDefault(optional unsigned short arg = 0);
readonly attribute unsigned long readonlyUnsignedLong;
attribute unsigned long writableUnsignedLong;
void passUnsignedLong(unsigned long arg);
unsigned long receiveUnsignedLong();
void passOptionalUnsignedLong(optional unsigned long arg);
void passOptionalUnsignedLongWithDefault(optional unsigned long arg = 0);
readonly attribute unsigned long long readonlyUnsignedLongLong;
attribute unsigned long long writableUnsignedLongLong;
void passUnsignedLongLong(unsigned long long arg);
unsigned long long receiveUnsignedLongLong();
void passOptionalUnsignedLongLong(optional unsigned long long arg);
void passOptionalUnsignedLongLongWithDefault(optional unsigned long long arg = 0);
// Castable interface types
// XXXbz add tests for infallible versions of all the castable interface stuff
@ -65,6 +90,10 @@ interface TestInterface {
void passNullableSelf(TestInterface? arg);
attribute TestInterface nonNullSelf;
attribute TestInterface? nullableSelf;
// Optional arguments
void passOptionalSelf(optional TestInterface? arg);
void passOptionalNonNullSelf(optional TestInterface arg);
void passOptionalSelfWithDefault(optional TestInterface? arg = null);
// Non-castable interface types
TestNonCastableInterface receiveOther();
@ -78,6 +107,10 @@ interface TestInterface {
void passNullableOther(TestNonCastableInterface? arg);
attribute TestNonCastableInterface nonNullOther;
attribute TestNonCastableInterface? nullableOther;
// Optional arguments
void passOptionalOther(optional TestNonCastableInterface? arg);
void passOptionalNonNullOther(optional TestNonCastableInterface arg);
void passOptionalOtherWithDefault(optional TestNonCastableInterface? arg = null);
// External interface types
TestExternalInterface receiveExternal();
@ -91,6 +124,10 @@ interface TestInterface {
void passNullableExternal(TestExternalInterface? arg);
attribute TestExternalInterface nonNullExternal;
attribute TestExternalInterface? nullableExternal;
// Optional arguments
void passOptionalExternal(optional TestExternalInterface? arg);
void passOptionalNonNullExternal(optional TestExternalInterface arg);
void passOptionalExternalWithDefault(optional TestExternalInterface? arg = null);
// Sequence types
sequence<long> receiveSequence();
@ -109,4 +146,54 @@ interface TestInterface {
void passNullableCastableObjectSequence(sequence<TestInterface?> arg);
void passCastableObjectNullableSequence(sequence<TestInterface>? arg);
void passNullableCastableObjectNullableSequence(sequence<TestInterface?>? arg);
void passOptionalSequence(optional sequence<long> arg);
void passOptionalNullableSequence(optional sequence<long>? arg);
void passOptionalNullableSequenceWithDefaultValue(optional sequence<long>? arg = null);
void passOptionalObjectSequence(optional sequence<TestInterface> arg);
// Typed array types
void passArrayBuffer(ArrayBuffer arg);
void passNullableArrayBuffer(ArrayBuffer? arg);
void passOptionalArrayBuffer(optional ArrayBuffer arg);
void passOptionalNullableArrayBuffer(optional ArrayBuffer? arg);
void passOptionalNullableArrayBufferWithDefaultValue(optional ArrayBuffer? arg= null);
// String types
void passString(DOMString arg);
void passNullableString(DOMString? arg);
void passOptionalString(optional DOMString arg);
void passOptionalNullableString(optional DOMString? arg);
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
// Enumerated types
void passEnum(TestEnum arg);
// No support for nullable enums yet
// void passNullableEnum(TestEnum? arg);
void passOptionalEnum(optional TestEnum arg);
// void passOptionalNullableEnum(optional TestEnum? arg);
// void passOptionalNullableEnumWithDefaultValue(optional TestEnum? arg = null);
TestEnum receiveEnum();
// Callback types
void passCallback(TestCallback arg);
void passNullableCallback(TestCallback? arg);
void passOptionalCallback(optional TestCallback arg);
void passOptionalNullableCallback(optional TestCallback? arg);
void passOptionalNullableCallbackWithDefaultValue(optional TestCallback? arg = null);
TestCallback receiveCallback();
TestCallback? receiveNullableCallback();
// Any types
void passAny(any arg);
void passOptionalAny(optional any arg);
any receiveAny();
// object types
void passObject(object arg);
void passNullableObject(object? arg);
void passOptionalObject(optional object arg);
void passOptionalNullableObject(optional object? arg);
void passOptionalNullableObjectWithDefaultValue(optional object? arg = null);
object receiveObject();
object? receiveNullableObject();
};

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

@ -1028,10 +1028,12 @@ public:
class OpenRunnable : public WorkerThreadProxySyncRunnable
{
nsCString mMethod;
nsCString mURL;
nsString mUser;
nsString mPassword;
nsString mMethod;
nsString mURL;
Optional<nsAString> mUser;
nsString mUserStr;
Optional<nsAString> mPassword;
nsString mPasswordStr;
bool mMultipart;
bool mBackgroundRequest;
bool mWithCredentials;
@ -1039,15 +1041,25 @@ class OpenRunnable : public WorkerThreadProxySyncRunnable
public:
OpenRunnable(WorkerPrivate* aWorkerPrivate, Proxy* aProxy,
const nsACString& aMethod, const nsACString& aURL,
const nsAString& aUser, const nsAString& aPassword,
const nsAString& aMethod, const nsAString& aURL,
const Optional<nsAString>& aUser,
const Optional<nsAString>& aPassword,
bool aMultipart, bool aBackgroundRequest, bool aWithCredentials,
PRUint32 aTimeout)
: WorkerThreadProxySyncRunnable(aWorkerPrivate, aProxy), mMethod(aMethod),
mURL(aURL), mUser(aUser), mPassword(aPassword), mMultipart(aMultipart),
mURL(aURL), mMultipart(aMultipart),
mBackgroundRequest(aBackgroundRequest), mWithCredentials(aWithCredentials),
mTimeout(aTimeout)
{ }
{
if (aUser.WasPassed()) {
mUserStr = aUser.Value();
mUser = &mUserStr;
}
if (aPassword.WasPassed()) {
mPasswordStr = aPassword.Value();
mPassword = &mPasswordStr;
}
}
nsresult
MainThreadRun()
@ -1093,15 +1105,18 @@ public:
NS_ASSERTION(!mProxy->mInOpen, "Reentrancy is bad!");
mProxy->mInOpen = true;
rv = mProxy->mXHR->Open(mMethod, mURL, true, mUser, mPassword, 1);
ErrorResult rv2;
mProxy->mXHR->Open(mMethod, mURL, true, mUser, mPassword, rv2);
NS_ASSERTION(mProxy->mInOpen, "Reentrancy is bad!");
mProxy->mInOpen = false;
if (NS_SUCCEEDED(rv)) {
rv = mProxy->mXHR->SetResponseType(NS_LITERAL_STRING("text"));
if (rv2.Failed()) {
return rv2.ErrorCode();
}
rv = mProxy->mXHR->SetResponseType(NS_LITERAL_STRING("text"));
return rv;
}
};
@ -1702,8 +1717,8 @@ XMLHttpRequest::Notify(JSContext* aCx, Status aStatus)
void
XMLHttpRequest::Open(const nsAString& aMethod, const nsAString& aUrl,
bool aAsync, const nsAString& aUser,
const nsAString& aPassword, ErrorResult& aRv)
bool aAsync, const Optional<nsAString>& aUser,
const Optional<nsAString>& aPassword, ErrorResult& aRv)
{
mWorkerPrivate->AssertIsOnWorkerThread();
@ -1725,9 +1740,9 @@ XMLHttpRequest::Open(const nsAString& aMethod, const nsAString& aUrl,
mProxy->mOuterEventStreamId++;
nsRefPtr<OpenRunnable> runnable =
new OpenRunnable(mWorkerPrivate, mProxy, NS_ConvertUTF16toUTF8(aMethod),
NS_ConvertUTF16toUTF8(aUrl), aUser, aPassword, mMultipart,
mBackgroundRequest, mWithCredentials, mTimeout);
new OpenRunnable(mWorkerPrivate, mProxy, aMethod, aUrl, aUser, aPassword,
mMultipart, mBackgroundRequest, mWithCredentials,
mTimeout);
if (!runnable->Dispatch(GetJSContext())) {
ReleaseProxy();

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

@ -103,7 +103,8 @@ public:
void
Open(const nsAString& aMethod, const nsAString& aUrl, bool aAsync,
const nsAString& aUser, const nsAString& aPassword, ErrorResult& aRv);
const Optional<nsAString>& aUser, const Optional<nsAString>& aPassword,
ErrorResult& aRv);
void
SetRequestHeader(const nsAString& aHeader, const nsAString& aValue,