From 5bffd5e5b297f9129f16aa451e0fa322900610ea Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Tue, 30 Nov 2010 13:18:15 -0500 Subject: [PATCH] Bug 605296 part 1. Infrastructure for supporting AUTF8String in quickstubs. r=jorendorff --- js/src/xpconnect/src/qsgen.py | 9 +- js/src/xpconnect/src/xpcquickstubs.cpp | 97 ++++++-------------- js/src/xpconnect/src/xpcquickstubs.h | 121 +++++++++++++++++++------ 3 files changed, 129 insertions(+), 98 deletions(-) diff --git a/js/src/xpconnect/src/qsgen.py b/js/src/xpconnect/src/qsgen.py index 45639fb76c37..800fe0d5bf09 100644 --- a/js/src/xpconnect/src/qsgen.py +++ b/js/src/xpconnect/src/qsgen.py @@ -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", diff --git a/js/src/xpconnect/src/xpcquickstubs.cpp b/js/src/xpconnect/src/xpcquickstubs.cpp index a966acc504d7..26209c31441c 100644 --- a/js/src/xpconnect/src/xpcquickstubs.cpp +++ b/js/src/xpconnect/src/xpcquickstubs.cpp @@ -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(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(JS_GetStringChars(s))); + size_t len = s->length(); + const PRUnichar* chars = + (len == 0 ? traits::sEmptyBuffer : + reinterpret_cast(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(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 traits; + // From the T_UTF8STRING case in XPCConvert::JSData2Native. + JSString *s = InitOrStringify(cx, v, pval, eNull, eNull); + if (!s) + return; + + size_t len = s->length(); + const PRUnichar* chars = + reinterpret_cast(JS_GetStringChars(s)); + + new(mBuf) implementation_type(chars, len); + mValid = JS_TRUE; +} + static nsresult getNative(nsISupports *idobj, QITableEntry* entries, diff --git a/js/src/xpconnect/src/xpcquickstubs.h b/js/src/xpconnect/src/xpcquickstubs.h index 602b492bc31d..de3fa1276ea9 100644 --- a/js/src/xpconnect/src/xpcquickstubs.h +++ b/js/src/xpconnect/src/xpcquickstubs.h @@ -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 -{ -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 + 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 +{ +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 +{ +public: + xpc_qsAUTF8String(JSContext* cx, jsval v, jsval *pval); +}; + struct xpc_qsSelfRef { xpc_qsSelfRef() : ptr(nsnull) {}