author | Ed Morley <emorley@mozilla.com> |
Fri, 11 Jul 2014 15:46:29 +0100 | |
changeset 193598 | 1166b5c0e91646128201c4491218d81d9efa44f4 |
parent 193597 | a58ad2a9b06170bb0fa6c2d2af5f4f529298ee6a |
child 193599 | 6904f207728c0a630deffdb16c020d67ba37232d |
push id | 27123 |
push user | ryanvm@gmail.com |
push date | Fri, 11 Jul 2014 20:35:05 +0000 |
treeherder | mozilla-central@84bd8d9f4256 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
bugs | 1034627 |
milestone | 33.0a1 |
backs out | bcba40acc0ac6dd9fb287f72a36653bdb166734b |
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
|
--- 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; } }