Bug 605296 part 1. Infrastructure for supporting AUTF8String in quickstubs. r=jorendorff

This commit is contained in:
Boris Zbarsky 2010-11-30 13:18:15 -05:00
parent 325022b283
commit 71fbf19546
3 changed files with 129 additions and 98 deletions

View File

@ -496,6 +496,11 @@ argumentUnboxingTemplates = {
" 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"
}
@ -580,7 +585,7 @@ def writeArgumentUnboxing(f, i, name, type, haveCcx, optional, rvdeclared,
" }\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:
@ -1131,7 +1136,7 @@ traceableArgumentConversionTemplates = {
" XPCReadableJSStringWrapper ${name}(${argVal});\n",
'[domstring]':
" XPCReadableJSStringWrapper ${name}(${argVal});\n",
'[cstring]':
'[utf8string]':
" NS_ConvertUTF16toUTF8 ${name}("
"(const PRUnichar *)JS_GetStringChars(${argVal}), "
"JS_GetStringLength(${argVal}));\n",

View File

@ -694,83 +694,28 @@ xpc_qsDOMString::xpc_qsDOMString(JSContext *cx, jsval v, jsval *pval,
StringificationBehavior nullBehavior,
StringificationBehavior undefinedBehavior)
{
// From the T_DOMSTRING case in XPCConvert::JSData2Native.
typedef implementation_type::char_traits traits;
JSString *s;
const PRUnichar *chars;
size_t len;
// From the T_DOMSTRING case in XPCConvert::JSData2Native.
JSString *s = InitOrStringify<traits>(cx, v, pval, nullBehavior,
undefinedBehavior);
if (!s)
return;
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;
}
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)
@ -783,6 +728,22 @@ xpc_qsACString::xpc_qsACString(JSContext *cx, jsval v, jsval *pval)
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,

View File

@ -1,4 +1,4 @@
/* -*- 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
@ -313,33 +313,6 @@ public:
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;
@ -360,6 +333,88 @@ public:
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);
@ -387,6 +442,16 @@ 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) {}