Bug 605296 part 1. Infrastructure for supporting AUTF8String in quickstubs. r=jorendorff
--- a/js/src/xpconnect/src/qsgen.py
+++ b/js/src/xpconnect/src/qsgen.py
@@ -491,16 +491,21 @@ argumentUnboxingTemplates = {
" if (!xpc_qsJsvalToWcharStr(cx, ${argVal}, ${argPtr}, &${name}))\n"
" return JS_FALSE;\n",
'[cstring]':
" xpc_qsACString ${name}(cx, ${argVal}, ${argPtr});\n"
" if (!${name}.IsValid())\n"
" return JS_FALSE;\n",
+ '[utf8string]':
+ " xpc_qsAUTF8String ${name}(cx, ${argVal}, ${argPtr});\n"
+ " if (!${name}.IsValid())\n"
+ " return JS_FALSE;\n",
+
'[jsval]':
" jsval ${name} = ${argVal};\n"
}
# From JSData2Native.
#
# Omitted optional arguments are treated as though the caller had passed JS
# `null`; this behavior is from XPCWrappedNative::CallMethod.
@@ -575,17 +580,17 @@ def writeArgumentUnboxing(f, i, name, ty
elif haveCcx:
f.write(" xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
else:
f.write(" xpc_qsThrowBadArg(cx, rv, vp, %d);\n" % i)
f.write(" return JS_FALSE;\n"
" }\n")
return True
- warn("Unable to unbox argument of type %s" % type.name)
+ warn("Unable to unbox argument of type %s (native type %s)" % (type.name, typeName))
if i is None:
src = '*vp'
else:
src = 'argv[%d]' % i
f.write(" !; // TODO - Unbox argument %s = %s\n" % (name, src))
return rvdeclared
def writeResultDecl(f, type, varname):
@@ -1126,17 +1131,17 @@ traceableArgumentConversionTemplates = {
'float':
" float ${name} = (float) ${argVal};\n",
'double':
" jsdouble ${name} = ${argVal};\n",
'[astring]':
" XPCReadableJSStringWrapper ${name}(${argVal});\n",
'[domstring]':
" XPCReadableJSStringWrapper ${name}(${argVal});\n",
- '[cstring]':
+ '[utf8string]':
" NS_ConvertUTF16toUTF8 ${name}("
"(const PRUnichar *)JS_GetStringChars(${argVal}), "
"JS_GetStringLength(${argVal}));\n",
'string':
" NS_ConvertUTF16toUTF8 ${name}_utf8("
"(const PRUnichar *)JS_GetStringChars(${argVal}), "
"JS_GetStringLength(${argVal}));\n"
" const char *${name} = ${name}_utf8.get();\n",
--- a/js/src/xpconnect/src/xpcquickstubs.cpp
+++ b/js/src/xpconnect/src/xpcquickstubs.cpp
@@ -689,105 +689,66 @@ xpc_qsGetterOnlyPropertyStub(JSContext *
js_GetErrorMessage, NULL,
JSMSG_GETTER_ONLY);
}
xpc_qsDOMString::xpc_qsDOMString(JSContext *cx, jsval v, jsval *pval,
StringificationBehavior nullBehavior,
StringificationBehavior undefinedBehavior)
{
+ typedef implementation_type::char_traits traits;
// From the T_DOMSTRING case in XPCConvert::JSData2Native.
- typedef implementation_type::char_traits traits;
- JSString *s;
- const PRUnichar *chars;
- size_t len;
-
- if(JSVAL_IS_STRING(v))
- {
- s = JSVAL_TO_STRING(v);
- }
- else
- {
- StringificationBehavior behavior = eStringify;
- if(JSVAL_IS_NULL(v))
- {
- behavior = nullBehavior;
- }
- else if(JSVAL_IS_VOID(v))
- {
- behavior = undefinedBehavior;
- }
+ JSString *s = InitOrStringify<traits>(cx, v, pval, nullBehavior,
+ undefinedBehavior);
+ if (!s)
+ return;
- // If pval is null, that means the argument was optional and
- // not passed; turn those into void strings if they're
- // supposed to be stringified.
- if (behavior != eStringify || !pval)
- {
- // Here behavior == eStringify implies !pval, so both eNull and
- // eStringify should end up with void strings.
- (new(mBuf) implementation_type(
- traits::sEmptyBuffer, PRUint32(0)))->SetIsVoid(behavior != eEmpty);
- mValid = JS_TRUE;
- return;
- }
-
- s = JS_ValueToString(cx, v);
- if(!s)
- {
- mValid = JS_FALSE;
- return;
- }
- *pval = STRING_TO_JSVAL(s); // Root the new string.
- }
-
- len = s->length();
- chars = (len == 0 ? traits::sEmptyBuffer :
- reinterpret_cast<const PRUnichar*>(JS_GetStringChars(s)));
+ size_t len = s->length();
+ const PRUnichar* chars =
+ (len == 0 ? traits::sEmptyBuffer :
+ reinterpret_cast<const PRUnichar*>(JS_GetStringChars(s)));
new(mBuf) implementation_type(chars, len);
mValid = JS_TRUE;
}
xpc_qsACString::xpc_qsACString(JSContext *cx, jsval v, jsval *pval)
{
+ typedef implementation_type::char_traits traits;
// From the T_CSTRING case in XPCConvert::JSData2Native.
- JSString *s;
-
- if(JSVAL_IS_STRING(v))
- {
- s = JSVAL_TO_STRING(v);
- }
- else
- {
- if(JSVAL_IS_NULL(v) || JSVAL_IS_VOID(v))
- {
- (new(mBuf) implementation_type())->SetIsVoid(PR_TRUE);
- mValid = JS_TRUE;
- return;
- }
-
- s = JS_ValueToString(cx, v);
- if(!s)
- {
- mValid = JS_FALSE;
- return;
- }
- *pval = STRING_TO_JSVAL(s); // Root the new string.
- }
+ JSString *s = InitOrStringify<traits>(cx, v, pval, eNull, eNull);
+ if (!s)
+ return;
JSAutoByteString bytes(cx, s);
if(!bytes)
{
mValid = JS_FALSE;
return;
}
new(mBuf) implementation_type(bytes.ptr(), strlen(bytes.ptr()));
mValid = JS_TRUE;
}
+xpc_qsAUTF8String::xpc_qsAUTF8String(JSContext *cx, jsval v, jsval *pval)
+{
+ typedef nsCharTraits<PRUnichar> traits;
+ // From the T_UTF8STRING case in XPCConvert::JSData2Native.
+ JSString *s = InitOrStringify<traits>(cx, v, pval, eNull, eNull);
+ if (!s)
+ return;
+
+ size_t len = s->length();
+ const PRUnichar* chars =
+ reinterpret_cast<const PRUnichar*>(JS_GetStringChars(s));
+
+ new(mBuf) implementation_type(chars, len);
+ mValid = JS_TRUE;
+}
+
static nsresult
getNative(nsISupports *idobj,
QITableEntry* entries,
JSObject *obj,
const nsIID &iid,
void **ppThis,
nsISupports **pThisRef,
jsval *vp)
--- a/js/src/xpconnect/src/xpcquickstubs.h
+++ b/js/src/xpconnect/src/xpcquickstubs.h
@@ -1,9 +1,9 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
@@ -308,43 +308,16 @@ public:
return reinterpret_cast<implementation_type *>(mBuf);
}
operator interface_type &()
{
return *Ptr();
}
-protected:
- /*
- * Neither field is initialized; that is left to the derived class
- * constructor. However, the destructor destroys the string object
- * stored in mBuf, if mValid is true.
- */
- void *mBuf[JS_HOWMANY(sizeof(implementation_type), sizeof(void *))];
- JSBool mValid;
-};
-
-/**
- * Class for converting a jsval to DOMString.
- *
- * xpc_qsDOMString arg0(cx, &argv[0]);
- * if (!arg0.IsValid())
- * return JS_FALSE;
- *
- * The second argument to the constructor is an in-out parameter. It must
- * point to a rooted jsval, such as a JSNative argument or return value slot.
- * The value in the jsval on entry is converted to a string. The constructor
- * may overwrite that jsval with a string value, to protect the characters of
- * the string from garbage collection. The caller must leave the jsval alone
- * for the lifetime of the xpc_qsDOMString.
- */
-class xpc_qsDOMString : public xpc_qsBasicString<nsAString, nsDependentString>
-{
-public:
/* Enum that defines how JS |null| and |undefined| should be treated. See
* the WebIDL specification. eStringify means convert to the string "null"
* or "undefined" respectively, via the standard JS ToString() operation;
* eEmpty means convert to the string ""; eNull means convert to an empty
* string with the void bit set.
*
* Per webidl the default behavior of an unannotated interface is
* eStringify, but our de-facto behavior has been eNull for |null| and
@@ -355,16 +328,98 @@ public:
enum StringificationBehavior {
eStringify,
eEmpty,
eNull,
eDefaultNullBehavior = eNull,
eDefaultUndefinedBehavior = eStringify
};
+protected:
+ /*
+ * Neither field is initialized; that is left to the derived class
+ * constructor. However, the destructor destroys the string object
+ * stored in mBuf, if mValid is true.
+ */
+ void *mBuf[JS_HOWMANY(sizeof(implementation_type), sizeof(void *))];
+ JSBool mValid;
+
+ /*
+ * If null is returned, then we either failed or fully initialized
+ * |this|; in either case the caller should return immediately
+ * without doing anything else. Otherwise, the JSString* created
+ * from |v| will be returned. It'll be rooted, as needed, in
+ * *pval. nullBehavior and undefinedBehavior control what happens
+ * when |v| is JSVAL_IS_NULL and JSVAL_IS_VOID respectively.
+ */
+ template<class traits>
+ JSString* InitOrStringify(JSContext* cx, jsval v, jsval* pval,
+ StringificationBehavior nullBehavior,
+ StringificationBehavior undefinedBehavior) {
+ JSString *s;
+ if(JSVAL_IS_STRING(v))
+ {
+ s = JSVAL_TO_STRING(v);
+ }
+ else
+ {
+ StringificationBehavior behavior = eStringify;
+ if(JSVAL_IS_NULL(v))
+ {
+ behavior = nullBehavior;
+ }
+ else if(JSVAL_IS_VOID(v))
+ {
+ behavior = undefinedBehavior;
+ }
+
+ // If pval is null, that means the argument was optional and
+ // not passed; turn those into void strings if they're
+ // supposed to be stringified.
+ if (behavior != eStringify || !pval)
+ {
+ // Here behavior == eStringify implies !pval, so both eNull and
+ // eStringify should end up with void strings.
+ (new(mBuf) implementation_type(
+ traits::sEmptyBuffer, PRUint32(0)))->
+ SetIsVoid(behavior != eEmpty);
+ mValid = JS_TRUE;
+ return nsnull;
+ }
+
+ s = JS_ValueToString(cx, v);
+ if(!s)
+ {
+ mValid = JS_FALSE;
+ return nsnull;
+ }
+ *pval = STRING_TO_JSVAL(s); // Root the new string.
+ }
+
+ return s;
+ }
+};
+
+/**
+ * Class for converting a jsval to DOMString.
+ *
+ * xpc_qsDOMString arg0(cx, &argv[0]);
+ * if (!arg0.IsValid())
+ * return JS_FALSE;
+ *
+ * The second argument to the constructor is an in-out parameter. It must
+ * point to a rooted jsval, such as a JSNative argument or return value slot.
+ * The value in the jsval on entry is converted to a string. The constructor
+ * may overwrite that jsval with a string value, to protect the characters of
+ * the string from garbage collection. The caller must leave the jsval alone
+ * for the lifetime of the xpc_qsDOMString.
+ */
+class xpc_qsDOMString : public xpc_qsBasicString<nsAString, nsDependentString>
+{
+public:
xpc_qsDOMString(JSContext *cx, jsval v, jsval *pval,
StringificationBehavior nullBehavior,
StringificationBehavior undefinedBehavior);
};
/**
* The same as xpc_qsDOMString, but with slightly different conversion behavior,
* corresponding to the [astring] magic XPIDL annotation rather than [domstring].
@@ -382,16 +437,26 @@ public:
* with [cstring] rather than [domstring] or [astring].
*/
class xpc_qsACString : public xpc_qsBasicString<nsACString, nsCString>
{
public:
xpc_qsACString(JSContext *cx, jsval v, jsval *pval);
};
+/**
+ * And similar for AUTF8String.
+ */
+class xpc_qsAUTF8String :
+ public xpc_qsBasicString<nsACString, NS_ConvertUTF16toUTF8>
+{
+public:
+ xpc_qsAUTF8String(JSContext* cx, jsval v, jsval *pval);
+};
+
struct xpc_qsSelfRef
{
xpc_qsSelfRef() : ptr(nsnull) {}
explicit xpc_qsSelfRef(nsISupports *p) : ptr(p) {}
~xpc_qsSelfRef() { NS_IF_RELEASE(ptr); }
nsISupports* ptr;
};