Backed out changeset bcba40acc0ac (bug 1034627)
authorEd Morley <emorley@mozilla.com>
Fri, 11 Jul 2014 15:46:29 +0100
changeset 193598 1166b5c0e91646128201c4491218d81d9efa44f4
parent 193597 a58ad2a9b06170bb0fa6c2d2af5f4f529298ee6a
child 193599 6904f207728c0a630deffdb16c020d67ba37232d
push id27123
push userryanvm@gmail.com
push dateFri, 11 Jul 2014 20:35:05 +0000
treeherdermozilla-central@84bd8d9f4256 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1034627
milestone33.0a1
backs outbcba40acc0ac6dd9fb287f72a36653bdb166734b
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out changeset bcba40acc0ac (bug 1034627)
js/xpconnect/src/XPCConvert.cpp
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -2,29 +2,27 @@
 /* vim: set ts=8 sts=4 et sw=4 tw=99: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Data conversion between native and JavaScript types. */
 
 #include "mozilla/ArrayUtils.h"
-#include "mozilla/Range.h"
 
 #include "xpcprivate.h"
 #include "nsIAtom.h"
 #include "nsWrapperCache.h"
 #include "nsJSUtils.h"
 #include "WrapperFactory.h"
 
 #include "nsWrapperCacheInlines.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
-#include "js/CharacterEncoding.h"
 #include "jsprf.h"
 #include "JavaScriptParent.h"
 
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/DOMException.h"
 #include "mozilla/dom/PrimitiveConversions.h"
 
 using namespace xpc;
@@ -361,26 +359,16 @@ CheckJSCharInCharRange(jschar c)
         char msg[MSG_BUF_SIZE];
         JS_snprintf(msg, MSG_BUF_SIZE, "jschar out of char range; high bits of data lost: 0x%x", c);
         NS_WARNING(msg);
         return false;
     }
 
     return true;
 }
-
-template<typename CharT>
-static void
-CheckCharsInCharRange(const CharT *chars, size_t len)
-{
-    for (size_t i = 0; i < len; i++) {
-        if (!CheckJSCharInCharRange(chars[i]))
-            break;
-    }
-}
 #endif
 
 template<typename T>
 bool ConvertToPrimitive(JSContext *cx, HandleValue v, T *retval)
 {
     return ValueToPrimitive<T, eDefault>(cx, v, retval);
 }
 
@@ -421,47 +409,44 @@ XPCConvert::JSData2Native(void* d, Handl
     case nsXPTType::T_BOOL   :
         return ConvertToPrimitive(cx, s, static_cast<bool*>(d));
     case nsXPTType::T_CHAR   :
     {
         JSString* str = ToString(cx, s);
         if (!str) {
             return false;
         }
-
-        jschar ch;
-        if (JS_GetStringLength(str) == 0) {
-            ch = 0;
-        } else {
-            if (!JS_GetStringCharAt(cx, str, 0, &ch))
-                return false;
+        size_t length;
+        const jschar* chars = JS_GetStringCharsAndLength(cx, str, &length);
+        if (!chars) {
+            return false;
         }
+        jschar ch = length ? chars[0] : 0;
 #ifdef DEBUG
         CheckJSCharInCharRange(ch);
 #endif
         *((char*)d) = char(ch);
         break;
     }
     case nsXPTType::T_WCHAR  :
     {
         JSString* str;
         if (!(str = ToString(cx, s))) {
             return false;
         }
-        size_t length = JS_GetStringLength(str);
+        size_t length;
+        const jschar* chars = JS_GetStringCharsAndLength(cx, str, &length);
+        if (!chars) {
+            return false;
+        }
         if (length == 0) {
             *((uint16_t*)d) = 0;
             break;
         }
-
-        jschar ch;
-        if (!JS_GetStringCharAt(cx, str, 0, &ch))
-            return false;
-
-        *((uint16_t*)d) = uint16_t(ch);
+        *((uint16_t*)d) = uint16_t(chars[0]);
         break;
     }
     case nsXPTType::T_JSVAL :
         *((jsval*)d) = s;
         break;
     case nsXPTType::T_VOID:
         XPC_LOG_ERROR(("XPCConvert::JSData2Native : void* params not supported"));
         NS_ERROR("void* params not supported");
@@ -502,23 +487,28 @@ XPCConvert::JSData2Native(void* d, Handl
         if (s.isNull()) {
             if (useAllocator)
                 *((const nsAString**)d) = &NullString();
             else
                 (**((nsAString**)d)).SetIsVoid(true);
             return true;
         }
         size_t length = 0;
+        const char16_t* chars = nullptr;
         JSString* str = nullptr;
         if (!s.isUndefined()) {
             str = ToString(cx, s);
             if (!str)
                 return false;
 
-            length = JS_GetStringLength(str);
+            chars = useAllocator ? JS_GetStringCharsZAndLength(cx, str, &length)
+                                 : JS_GetStringCharsAndLength(cx, str, &length);
+            if (!chars)
+                return false;
+
             if (!length) {
                 if (useAllocator)
                     *((const nsAString**)d) = &EmptyString();
                 else
                     (**((nsAString**)d)).Truncate();
                 return true;
             }
         }
@@ -531,54 +521,53 @@ XPCConvert::JSData2Native(void* d, Handl
             ws = *((nsString**)d);
         }
 
         if (!str) {
             ws->AssignLiteral(MOZ_UTF16("undefined"));
         } else if (XPCStringConvert::IsDOMString(str)) {
             // The characters represent an existing nsStringBuffer that
             // was shared by XPCStringConvert::ReadableToJSVal.
-            const jschar *chars = JS_GetTwoByteExternalStringChars(str);
             nsStringBuffer::FromData((void *)chars)->ToString(length, *ws);
         } else if (XPCStringConvert::IsLiteral(str)) {
             // The characters represent a literal char16_t string constant
             // compiled into libxul, such as the string "undefined" above.
-            const jschar *chars = JS_GetTwoByteExternalStringChars(str);
             ws->AssignLiteral(chars, length);
+        } else if (useAllocator && STRING_TO_JSVAL(str) == s) {
+            // The JS string will exist over the function call.
+            // We don't need to copy the characters in this case.
+            ws->Rebind(chars, length);
         } else {
-            if (!AssignJSString(cx, *ws, str))
-                return false;
+            ws->Assign(chars, length);
         }
         return true;
     }
 
     case nsXPTType::T_CHAR_STR:
     {
         if (s.isUndefined() || s.isNull()) {
             *((char**)d) = nullptr;
             return true;
         }
 
         JSString* str = ToString(cx, s);
         if (!str) {
             return false;
         }
 #ifdef DEBUG
-        if (JS_StringHasLatin1Chars(str)) {
-            size_t len;
-            AutoCheckCannotGC nogc;
-            const Latin1Char *chars = JS_GetLatin1StringCharsAndLength(cx, nogc, str, &len);
-            if (chars)
-                CheckCharsInCharRange(chars, len);
-        } else {
-            size_t len;
-            AutoCheckCannotGC nogc;
-            const jschar *chars = JS_GetTwoByteStringCharsAndLength(cx, nogc, str, &len);
-            if (chars)
-                CheckCharsInCharRange(chars, len);
+        const jschar* chars=nullptr;
+        if (nullptr != (chars = JS_GetStringCharsZ(cx, str))) {
+            bool legalRange = true;
+            int len = JS_GetStringLength(str);
+            const jschar* t;
+            int32_t i=0;
+            for (t=chars; (i< len) && legalRange ; i++,t++) {
+                if (!CheckJSCharInCharRange(*t))
+                    break;
+            }
         }
 #endif // DEBUG
         size_t length = JS_GetStringEncodingLength(cx, str);
         if (length == size_t(-1)) {
             return false;
         }
         char *buffer = static_cast<char *>(nsMemory::Alloc(length + 1));
         if (!buffer) {
@@ -587,58 +576,66 @@ XPCConvert::JSData2Native(void* d, Handl
         JS_EncodeStringToBuffer(cx, str, buffer, length);
         buffer[length] = '\0';
         *((void**)d) = buffer;
         return true;
     }
 
     case nsXPTType::T_WCHAR_STR:
     {
+        const jschar* chars=nullptr;
         JSString* str;
 
         if (s.isUndefined() || s.isNull()) {
             *((jschar**)d) = nullptr;
             return true;
         }
 
         if (!(str = ToString(cx, s))) {
             return false;
         }
+        if (!(chars = JS_GetStringCharsZ(cx, str))) {
+            return false;
+        }
         int len = JS_GetStringLength(str);
         int byte_len = (len+1)*sizeof(jschar);
         if (!(*((void**)d) = nsMemory::Alloc(byte_len))) {
             // XXX should report error
             return false;
         }
-        mozilla::Range<jschar> destChars(*((jschar**)d), len + 1);
-        if (!JS_CopyStringChars(cx, destChars, str))
-            return false;
-        destChars[len] = 0;
+        jschar* destchars = *((jschar**)d);
+        memcpy(destchars, chars, byte_len);
+        destchars[len] = 0;
 
         return true;
     }
 
     case nsXPTType::T_UTF8STRING:
     {
+        const jschar* chars;
+        size_t length;
+        JSString* str;
+
         if (s.isNull() || s.isUndefined()) {
             if (useAllocator) {
                 *((const nsACString**)d) = &NullCString();
             } else {
                 nsCString* rs = *((nsCString**)d);
                 rs->SetIsVoid(true);
             }
             return true;
         }
 
         // The JS val is neither null nor void...
-        JSString *str = ToString(cx, s);
-        if (!str)
+
+        if (!(str = ToString(cx, s))||
+            !(chars = JS_GetStringCharsAndLength(cx, str, &length))) {
             return false;
+        }
 
-        size_t length = JS_GetStringLength(str);
         if (!length) {
             if (useAllocator) {
                 *((const nsACString**)d) = &EmptyCString();
             } else {
                 nsCString* rs = *((nsCString**)d);
                 rs->Truncate();
             }
             return true;
@@ -650,26 +647,17 @@ XPCConvert::JSData2Native(void* d, Handl
             rs = new nsCString();
             if (!rs)
                 return false;
 
             *((const nsCString**)d) = rs;
         } else {
             rs = *((nsCString**)d);
         }
-
-        JSFlatString *flat = JS_FlattenString(cx, str);
-        if (!flat)
-            return false;
-
-        size_t utf8Length = JS::GetDeflatedUTF8StringLength(flat);
-        rs->SetLength(utf8Length);
-
-        JS::DeflateStringToUTF8Buffer(flat, mozilla::RangedPtr<char>(rs->BeginWriting(), utf8Length));
-        MOZ_ASSERT(rs->get()[utf8Length] == '\0');
+        CopyUTF16toUTF8(Substring(chars, length), *rs);
         return true;
     }
 
     case nsXPTType::T_CSTRING:
     {
         if (s.isNull() || s.isUndefined()) {
             if (useAllocator) {
                 nsACString *rs = new nsCString();
@@ -736,23 +724,25 @@ XPCConvert::JSData2Native(void* d, Handl
             if (!variant)
                 return false;
 
             variant.forget(static_cast<nsISupports**>(d));
             return true;
         } else if (iid->Equals(NS_GET_IID(nsIAtom)) && s.isString()) {
             // We're trying to pass a string as an nsIAtom.  Let's atomize!
             JSString* str = s.toString();
-            nsAutoJSString autoStr;
-            if (!autoStr.init(cx, str)) {
+            const char16_t* chars = JS_GetStringCharsZ(cx, str);
+            if (!chars) {
                 if (pErr)
                     *pErr = NS_ERROR_XPC_BAD_CONVERT_JS_NULL_REF;
                 return false;
             }
-            nsCOMPtr<nsIAtom> atom = NS_NewAtom(autoStr);
+            uint32_t length = JS_GetStringLength(str);
+            nsCOMPtr<nsIAtom> atom =
+                NS_NewAtom(nsDependentSubstring(chars, chars + length));
             atom.forget((nsISupports**)d);
             return true;
         }
         //else ...
 
         if (s.isNullOrUndefined()) {
             *((nsISupports**)d) = nullptr;
             return true;
@@ -1798,16 +1788,17 @@ XPCConvert::JSStringWithSize2Native(void
             buffer[len] = '\0';
             *((char**)d) = buffer;
 
             return true;
         }
 
         case nsXPTType::T_PWSTRING_SIZE_IS:
         {
+            const jschar* chars=nullptr;
             JSString* str;
 
             if (s.isUndefined() || s.isNull()) {
                 if (0 != count) {
                     if (pErr)
                         *pErr = NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING;
                     return false;
                 }
@@ -1829,28 +1820,29 @@ XPCConvert::JSStringWithSize2Native(void
             }
 
             len = JS_GetStringLength(str);
             if (len > count) {
                 if (pErr)
                     *pErr = NS_ERROR_XPC_NOT_ENOUGH_CHARS_IN_STRING;
                 return false;
             }
+            if (len < count)
+                len = count;
 
-            len = count;
-
+            if (!(chars = JS_GetStringCharsZ(cx, str))) {
+                return false;
+            }
             uint32_t alloc_len = (len + 1) * sizeof(jschar);
             if (!(*((void**)d) = nsMemory::Alloc(alloc_len))) {
                 // XXX should report error
                 return false;
             }
-            mozilla::Range<jschar> destChars(*((jschar**)d), len + 1);
-            if (!JS_CopyStringChars(cx, destChars, str))
-                return false;
-            destChars[count] = 0;
+            memcpy(*((jschar**)d), chars, alloc_len);
+            (*((jschar**)d))[count] = 0;
 
             return true;
         }
         default:
             XPC_LOG_ERROR(("XPCConvert::JSStringWithSize2Native : unsupported type"));
             return false;
     }
 }