mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 811060 - Move DeflateString out of jsstr and make it Typey; r=Waldo
--HG-- extra : rebase_source : 9d239c525e8b0c04a63770d4ed732c9c6da54a2c
This commit is contained in:
parent
7845a8d5e0
commit
b97ee61fd5
@ -915,19 +915,20 @@ jsdProperty::GetValue(jsdIValue **_rval)
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS2(jsdScript, jsdIScript, jsdIEphemeral)
|
||||
|
||||
static NS_IMETHODIMP
|
||||
AssignToJSString(nsACString *x, JSString *str)
|
||||
AssignToJSString(JSDContext *aCx, nsACString *x, JSString *str)
|
||||
{
|
||||
if (!str) {
|
||||
x->SetLength(0);
|
||||
return NS_OK;
|
||||
}
|
||||
size_t length = JS_GetStringEncodingLength(NULL, str);
|
||||
JSContext *cx = JSD_GetDefaultJSContext(aCx);
|
||||
size_t length = JS_GetStringEncodingLength(cx, str);
|
||||
if (length == size_t(-1))
|
||||
return NS_ERROR_FAILURE;
|
||||
x->SetLength(uint32_t(length));
|
||||
if (x->Length() != uint32_t(length))
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
JS_EncodeStringToBuffer(str, x->BeginWriting(), length);
|
||||
JS_EncodeStringToBuffer(cx, str, x->BeginWriting(), length);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -953,7 +954,7 @@ jsdScript::jsdScript (JSDContext *aCx, JSDScript *aScript) : mValid(false),
|
||||
if (mFunctionName) {
|
||||
JSString *str = JSD_GetScriptFunctionId(mCx, mScript);
|
||||
if (str)
|
||||
AssignToJSString(mFunctionName, str);
|
||||
AssignToJSString(mCx, mFunctionName, str);
|
||||
}
|
||||
mBaseLineNumber = JSD_GetScriptBaseLineNumber(mCx, mScript);
|
||||
mLineExtent = JSD_GetScriptLineExtent(mCx, mScript);
|
||||
@ -1908,7 +1909,7 @@ jsdStackFrame::GetFunctionName(nsACString &_rval)
|
||||
ASSERT_VALID_EPHEMERAL;
|
||||
JSString *str = JSD_GetIdForStackFrame(mCx, mThreadState, mStackFrameInfo);
|
||||
if (str)
|
||||
return AssignToJSString(&_rval, str);
|
||||
return AssignToJSString(mCx, &_rval, str);
|
||||
|
||||
_rval.Assign("anonymous");
|
||||
return NS_OK;
|
||||
@ -2238,7 +2239,7 @@ NS_IMETHODIMP
|
||||
jsdValue::GetJsFunctionName(nsACString &_rval)
|
||||
{
|
||||
ASSERT_VALID_EPHEMERAL;
|
||||
return AssignToJSString(&_rval, JSD_GetValueFunctionId(mCx, mValue));
|
||||
return AssignToJSString(mCx, &_rval, JSD_GetValueFunctionId(mCx, mValue));
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
126
js/public/CharacterEncoding.h
Normal file
126
js/public/CharacterEncoding.h
Normal file
@ -0,0 +1,126 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#ifndef js_CharacterEncoding_h___
|
||||
#define js_CharacterEncoding_h___
|
||||
|
||||
#include "mozilla/Range.h"
|
||||
|
||||
#include "js/Utility.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
namespace JS {
|
||||
|
||||
/*
|
||||
* By default, all C/C++ 1-byte-per-character strings passed into the JSAPI
|
||||
* are treated as ISO/IEC 8859-1, also known as Latin-1. That is, each
|
||||
* byte is treated as a 2-byte character, and there is no way to pass in a
|
||||
* string containing characters beyond U+00FF.
|
||||
*/
|
||||
class Latin1Chars : public mozilla::Range<unsigned char>
|
||||
{
|
||||
typedef mozilla::Range<unsigned char> Base;
|
||||
|
||||
public:
|
||||
Latin1Chars() : Base() {}
|
||||
Latin1Chars(char *bytes, size_t length) : Base(reinterpret_cast<unsigned char *>(bytes), length) {}
|
||||
};
|
||||
|
||||
/*
|
||||
* A Latin1Chars, but with \0 termination for C compatibility.
|
||||
*/
|
||||
class Latin1CharsZ : public mozilla::RangedPtr<unsigned char>
|
||||
{
|
||||
typedef mozilla::RangedPtr<unsigned char> Base;
|
||||
|
||||
public:
|
||||
Latin1CharsZ() : Base(NULL, 0) {}
|
||||
|
||||
Latin1CharsZ(char *bytes, size_t length)
|
||||
: Base(reinterpret_cast<unsigned char *>(bytes), length)
|
||||
{
|
||||
JS_ASSERT(bytes[length] == '\0');
|
||||
}
|
||||
|
||||
Latin1CharsZ(unsigned char *bytes, size_t length)
|
||||
: Base(bytes, length)
|
||||
{
|
||||
JS_ASSERT(bytes[length] == '\0');
|
||||
}
|
||||
|
||||
char *c_str() { return reinterpret_cast<char *>(get()); }
|
||||
};
|
||||
|
||||
/*
|
||||
* SpiderMonkey also deals directly with UTF-8 encoded text in some places.
|
||||
*/
|
||||
class UTF8CharsZ : public mozilla::RangedPtr<unsigned char>
|
||||
{
|
||||
typedef mozilla::RangedPtr<unsigned char> Base;
|
||||
|
||||
public:
|
||||
UTF8CharsZ() : Base(NULL, 0) {}
|
||||
|
||||
UTF8CharsZ(char *bytes, size_t length)
|
||||
: Base(reinterpret_cast<unsigned char *>(bytes), length)
|
||||
{
|
||||
JS_ASSERT(bytes[length] == '\0');
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* SpiderMonkey uses a 2-byte character representation: it is a
|
||||
* 2-byte-at-a-time view of a UTF-16 byte stream. This is similar to UCS-2,
|
||||
* but unlike UCS-2, we do not strip UTF-16 extension bytes. This allows a
|
||||
* sufficiently dedicated JavaScript program to be fully unicode-aware by
|
||||
* manually interpreting UTF-16 extension characters embedded in the JS
|
||||
* string.
|
||||
*/
|
||||
class TwoByteChars : public mozilla::Range<jschar>
|
||||
{
|
||||
typedef mozilla::Range<jschar> Base;
|
||||
|
||||
public:
|
||||
TwoByteChars() : Base() {}
|
||||
TwoByteChars(jschar *chars, size_t length) : Base(chars, length) {}
|
||||
TwoByteChars(const jschar *chars, size_t length) : Base(const_cast<jschar *>(chars), length) {}
|
||||
};
|
||||
|
||||
/*
|
||||
* A TwoByteChars, but \0 terminated for compatibility with JSFlatString.
|
||||
*/
|
||||
class TwoByteCharsZ : public mozilla::RangedPtr<jschar>
|
||||
{
|
||||
typedef mozilla::RangedPtr<jschar> Base;
|
||||
|
||||
public:
|
||||
TwoByteCharsZ(jschar *chars, size_t length)
|
||||
: Base(chars, length)
|
||||
{
|
||||
JS_ASSERT(chars[length] = '\0');
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
* Convert a 2-byte character sequence to "ISO-Latin-1". This works by
|
||||
* truncating each 2-byte pair in the sequence to a 1-byte pair. If the source
|
||||
* contains any UTF-16 extension characters, then this may give invalid Latin1
|
||||
* output. The returned string is zero terminated. The returned string or the
|
||||
* returned string's |start()| must be freed with JS_free or js_free,
|
||||
* respectively. If allocation fails, an OOM error will be set and the method
|
||||
* will return a NULL chars (which can be tested for with the ! operator).
|
||||
* This method cannot trigger GC.
|
||||
*/
|
||||
extern Latin1CharsZ
|
||||
LossyTwoByteCharsToNewLatin1CharsZ(JSContext *cx, TwoByteChars tbchars);
|
||||
|
||||
} // namespace JS
|
||||
|
||||
inline void JS_free(JS::Latin1CharsZ &ptr) { js_free((void*)ptr.get()); }
|
||||
|
||||
#endif // js_CharacterEncoding_h___
|
@ -127,6 +127,7 @@ CPPSRCS = \
|
||||
String.cpp \
|
||||
BytecodeCompiler.cpp \
|
||||
BytecodeEmitter.cpp \
|
||||
CharacterEncoding.cpp \
|
||||
FoldConstants.cpp \
|
||||
Intl.cpp \
|
||||
NameFunctions.cpp \
|
||||
@ -216,6 +217,7 @@ EXPORTS_NAMESPACES += js
|
||||
# that we ensure we don't over-expose our internal integer typedefs. Note that
|
||||
# LegacyIntTypes.h below is deliberately exempted from this requirement.
|
||||
EXPORTS_js = \
|
||||
CharacterEncoding.h \
|
||||
HashTable.h \
|
||||
HeapAPI.h \
|
||||
LegacyIntTypes.h \
|
||||
|
@ -32,6 +32,7 @@
|
||||
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "vm/Keywords.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
@ -564,7 +565,8 @@ TokenStream::reportCompileErrorNumberVA(ParseNode *pn, unsigned flags, unsigned
|
||||
err.report.uclinebuf = windowBuf.extractWellSized();
|
||||
if (!err.report.uclinebuf)
|
||||
return false;
|
||||
err.report.linebuf = DeflateString(cx, err.report.uclinebuf, windowLength);
|
||||
TwoByteChars tbchars(err.report.uclinebuf, windowLength);
|
||||
err.report.linebuf = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
if (!err.report.linebuf)
|
||||
return false;
|
||||
|
||||
@ -728,7 +730,8 @@ TokenStream::getXMLEntity()
|
||||
bad:
|
||||
/* No match: throw a TypeError per ECMA-357 10.3.2.1 step 8(a). */
|
||||
JS_ASSERT((tb.end() - bp) >= 1);
|
||||
bytes = DeflateString(cx, bp + 1, (tb.end() - bp) - 1);
|
||||
TwoByteChars tbchars(bp + 1, (tb.end() - bp) - 1);
|
||||
bytes = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
if (bytes) {
|
||||
reportError(msg, bytes);
|
||||
js_free(bytes);
|
||||
|
@ -68,6 +68,7 @@ CPPSRCS = \
|
||||
testStringBuffer.cpp \
|
||||
testTrap.cpp \
|
||||
testTypedArrays.cpp \
|
||||
testUTF8.cpp \
|
||||
testVersion.cpp \
|
||||
testXDR.cpp \
|
||||
$(NULL)
|
||||
|
46
js/src/jsapi-tests/testUTF8.cpp
Normal file
46
js/src/jsapi-tests/testUTF8.cpp
Normal file
@ -0,0 +1,46 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et 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/. */
|
||||
|
||||
#include "tests.h"
|
||||
#include "jsapi.h"
|
||||
#include "jsstr.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
BEGIN_TEST(testUTF8_badUTF8)
|
||||
{
|
||||
static const char badUTF8[] = "...\xC0...";
|
||||
JSString *str = JS_NewStringCopyZ(cx, badUTF8);
|
||||
CHECK(str);
|
||||
const jschar *chars = JS_GetStringCharsZ(cx, str);
|
||||
CHECK(chars);
|
||||
CHECK(chars[3] == 0x00C0);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testUTF8_badUTF8)
|
||||
|
||||
BEGIN_TEST(testUTF8_bigUTF8)
|
||||
{
|
||||
static const char bigUTF8[] = "...\xFB\xBF\xBF\xBF\xBF...";
|
||||
JSString *str = JS_NewStringCopyZ(cx, bigUTF8);
|
||||
CHECK(str);
|
||||
const jschar *chars = JS_GetStringCharsZ(cx, str);
|
||||
CHECK(chars);
|
||||
CHECK(chars[3] == 0x00FB);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testUTF8_bigUTF8)
|
||||
|
||||
BEGIN_TEST(testUTF8_badSurrogate)
|
||||
{
|
||||
static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
|
||||
JS::TwoByteChars tbchars(badSurrogate, js_strlen(badSurrogate));
|
||||
JS::Latin1CharsZ latin1 = JS::LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars);
|
||||
CHECK(latin1);
|
||||
CHECK(latin1[3] == 0x00EE);
|
||||
return true;
|
||||
}
|
||||
END_TEST(testUTF8_badSurrogate)
|
@ -64,6 +64,7 @@
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "gc/Memory.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/MemoryMetrics.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/NumericConversions.h"
|
||||
@ -6231,27 +6232,24 @@ JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(char *)
|
||||
JS_EncodeString(JSContext *cx, JSRawString strArg)
|
||||
JS_EncodeString(JSContext *cx, JSRawString str)
|
||||
{
|
||||
RootedString str(cx, strArg);
|
||||
|
||||
AutoAssertNoGC nogc;
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
const jschar *chars = str->getChars(cx);
|
||||
if (!chars)
|
||||
JSLinearString *linear = str->ensureLinear(cx);
|
||||
if (!linear)
|
||||
return NULL;
|
||||
return DeflateString(cx, chars, str->length());
|
||||
|
||||
return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(size_t)
|
||||
JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
||||
{
|
||||
/* jsd calls us with a NULL cx. Ugh. */
|
||||
if (cx) {
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
}
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
const jschar *chars = str->getChars(cx);
|
||||
if (!chars)
|
||||
@ -6260,8 +6258,11 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str)
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(size_t)
|
||||
JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
|
||||
JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length)
|
||||
{
|
||||
AssertHeapIsIdle(cx);
|
||||
CHECK_REQUEST(cx);
|
||||
|
||||
/*
|
||||
* FIXME bug 612141 - fix DeflateStringToBuffer interface so the result
|
||||
* would allow to distinguish between insufficient buffer and encoding
|
||||
|
@ -5554,7 +5554,7 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str);
|
||||
* written into the buffer.
|
||||
*/
|
||||
JS_PUBLIC_API(size_t)
|
||||
JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length);
|
||||
JS_EncodeStringToBuffer(JSContext *cx, JSString *str, char *buffer, size_t length);
|
||||
|
||||
class JSAutoByteString
|
||||
{
|
||||
|
@ -23,6 +23,8 @@
|
||||
# include <string>
|
||||
#endif // ANDROID
|
||||
|
||||
#include "mozilla/Util.h"
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jsutil.h"
|
||||
#include "jsclist.h"
|
||||
@ -55,6 +57,7 @@
|
||||
# include "methodjit/MethodJIT.h"
|
||||
#endif
|
||||
#include "gc/Marking.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/MemoryMetrics.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "frontend/ParseMaps.h"
|
||||
@ -69,6 +72,7 @@ using namespace js;
|
||||
using namespace js::gc;
|
||||
|
||||
using mozilla::DebugOnly;
|
||||
using mozilla::PointerRangeSize;
|
||||
|
||||
bool
|
||||
js::AutoCycleDetector::init()
|
||||
@ -832,8 +836,10 @@ js_ExpandErrorArguments(JSContext *cx, JSErrorCallback callback,
|
||||
JS_ASSERT(expandedArgs == argCount);
|
||||
*out = 0;
|
||||
js_free(buffer);
|
||||
*messagep = DeflateString(cx, reportp->ucmessage,
|
||||
size_t(out - reportp->ucmessage));
|
||||
TwoByteChars ucmsg(reportp->ucmessage,
|
||||
PointerRangeSize(static_cast<const jschar *>(reportp->ucmessage),
|
||||
static_cast<const jschar *>(out)));
|
||||
*messagep = LossyTwoByteCharsToNewLatin1CharsZ(cx, ucmsg).c_str();
|
||||
if (!*messagep)
|
||||
goto error;
|
||||
}
|
||||
|
@ -291,13 +291,13 @@ MakeTypeId(JSContext *cx, jsid id)
|
||||
*/
|
||||
if (JSID_IS_STRING(id)) {
|
||||
JSFlatString *str = JSID_TO_FLAT_STRING(id);
|
||||
const jschar *cp = str->getCharsZ(cx);
|
||||
if (JS7_ISDEC(*cp) || *cp == '-') {
|
||||
cp++;
|
||||
while (JS7_ISDEC(*cp))
|
||||
cp++;
|
||||
if (*cp == 0)
|
||||
return JSID_VOID;
|
||||
TwoByteChars cp = str->range();
|
||||
if (JS7_ISDEC(cp[0]) || cp[0] == '-') {
|
||||
for (size_t i = 1; i < cp.length(); ++i) {
|
||||
if (!JS7_ISDEC(cp[i]))
|
||||
return id;
|
||||
}
|
||||
return JSID_VOID;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
@ -38,9 +38,9 @@
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "ds/Sort.h"
|
||||
|
||||
#include "frontend/BytecodeEmitter.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "vm/Debugger.h"
|
||||
#include "vm/StringBuffer.h"
|
||||
|
||||
@ -6262,10 +6262,11 @@ js::DecompileValueGenerator(JSContext *cx, int spindex, HandleValue v,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Rooted<JSStableString *> stable(cx, fallback->ensureStable(cx));
|
||||
if (!stable)
|
||||
Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
|
||||
if (!linear)
|
||||
return NULL;
|
||||
return DeflateString(cx, stable->chars().get(), stable->length());
|
||||
TwoByteChars tbchars(linear->chars(), linear->length());
|
||||
return LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -6352,10 +6353,10 @@ js::DecompileArgument(JSContext *cx, int formalIndex, HandleValue v)
|
||||
if (!fallback)
|
||||
return NULL;
|
||||
|
||||
Rooted<JSStableString *> stable(cx, fallback->ensureStable(cx));
|
||||
if (!stable)
|
||||
Rooted<JSLinearString *> linear(cx, fallback->ensureLinear(cx));
|
||||
if (!linear)
|
||||
return NULL;
|
||||
return DeflateString(cx, stable->chars().get(), stable->length());
|
||||
return LossyTwoByteCharsToNewLatin1CharsZ(cx, linear->range()).c_str();
|
||||
}
|
||||
|
||||
static char *
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "jspubtd.h"
|
||||
#include "jsstr.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
/*
|
||||
@ -360,8 +362,8 @@ static int cvt_s(SprintfState *ss, const char *s, int width, int prec,
|
||||
return fill2(ss, s ? s : "(null)", slen, width, flags);
|
||||
}
|
||||
|
||||
static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
|
||||
int flags)
|
||||
static int
|
||||
cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec, int flags)
|
||||
{
|
||||
int result;
|
||||
/*
|
||||
@ -369,12 +371,15 @@ static int cvt_ws(SprintfState *ss, const jschar *ws, int width, int prec,
|
||||
* and malloc() is used to allocate the buffer buffer.
|
||||
*/
|
||||
if (ws) {
|
||||
int slen = js_strlen(ws);
|
||||
char *s = DeflateString(NULL, ws, slen);
|
||||
if (!s)
|
||||
size_t wslen = js_strlen(ws);
|
||||
char *latin1 = js_pod_malloc<char>(wslen + 1);
|
||||
if (!latin1)
|
||||
return -1; /* JSStuffFunc error indicator. */
|
||||
result = cvt_s(ss, s, width, prec, flags);
|
||||
js_free(s);
|
||||
for (size_t i = 0; i < wslen; ++i)
|
||||
latin1[i] = (char)ws[i];
|
||||
latin1[wslen] = '\0';
|
||||
result = cvt_s(ss, latin1, width, prec, flags);
|
||||
js_free(latin1);
|
||||
} else {
|
||||
result = cvt_s(ss, NULL, width, prec, flags);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
|
||||
#include "frontend/Parser.h"
|
||||
#include "frontend/TokenStream.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
#include "jsscriptinlines.h"
|
||||
@ -3442,7 +3443,8 @@ reflect_parse(JSContext *cx, uint32_t argc, jsval *vp)
|
||||
if (!chars)
|
||||
return JS_FALSE;
|
||||
|
||||
filename = DeflateString(cx, chars, length);
|
||||
TwoByteChars tbchars(chars, length);
|
||||
filename = LossyTwoByteCharsToNewLatin1CharsZ(cx, tbchars).c_str();
|
||||
if (!filename)
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -3726,25 +3726,6 @@ js::InflateUTF8String(JSContext *cx, const char *bytes, size_t *lengthp)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* May be called with null cx.
|
||||
*/
|
||||
char *
|
||||
js::DeflateString(JSContext *maybecx, const jschar *chars, size_t nchars)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
size_t nbytes = nchars;
|
||||
char *bytes = maybecx
|
||||
? maybecx->pod_malloc<char>(nbytes + 1)
|
||||
: js_pod_malloc<char>(nbytes + 1);
|
||||
if (!bytes)
|
||||
return NULL;
|
||||
for (size_t i = 0; i < nbytes; i++)
|
||||
bytes[i] = (char) chars[i];
|
||||
bytes[nbytes] = 0;
|
||||
return bytes;
|
||||
}
|
||||
|
||||
size_t
|
||||
js::GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
|
||||
{
|
||||
|
@ -224,9 +224,6 @@ InflateString(JSContext *cx, const char *bytes, size_t *length);
|
||||
extern jschar *
|
||||
InflateUTF8String(JSContext *cx, const char *bytes, size_t *length);
|
||||
|
||||
extern char *
|
||||
DeflateString(JSContext *cx, const jschar *chars, size_t length);
|
||||
|
||||
/*
|
||||
* Inflate bytes to JS chars in an existing buffer. 'chars' must be large
|
||||
* enough for 'length' jschars. The buffer is NOT null-terminated.
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "jsinterpinlines.h"
|
||||
#include "jsautooplen.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
#include "vm/ScopeObject-inl.h"
|
||||
#include "vm/StringObject-inl.h"
|
||||
|
||||
@ -2409,12 +2411,12 @@ GetElementIC::attachGetProp(VMFrame &f, HandleObject obj, HandleValue v, HandleP
|
||||
|
||||
CodeLocationLabel cs = buffer.finalize(f);
|
||||
#if DEBUG
|
||||
char *chars = DeflateString(cx, v.toString()->getChars(cx), v.toString()->length());
|
||||
Latin1CharsZ latin1 = LossyTwoByteCharsToNewLatin1CharsZ(cx, v.toString()->ensureLinear(cx)->range());
|
||||
JaegerSpew(JSpew_PICs, "generated %s stub at %p for atom %p (\"%s\") shape %p (%s: %d)\n",
|
||||
js_CodeName[JSOp(*f.pc())], cs.executableAddress(), (void*)name, chars,
|
||||
js_CodeName[JSOp(*f.pc())], cs.executableAddress(), (void*)name, latin1.get(),
|
||||
(void*)holder->lastProperty(), cx->fp()->script()->filename,
|
||||
CurrentLine(cx));
|
||||
js_free(chars);
|
||||
JS_free(latin1);
|
||||
#endif
|
||||
|
||||
// Update the inline guards, if needed.
|
||||
|
@ -2440,47 +2440,6 @@ ToInt32(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char* badUTF8 = "...\xC0...";
|
||||
static const char* bigUTF8 = "...\xFB\xBF\xBF\xBF\xBF...";
|
||||
static const jschar badSurrogate[] = { 'A', 'B', 'C', 0xDEEE, 'D', 'E', 0 };
|
||||
|
||||
static JSBool
|
||||
TestUTF8(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
int32_t mode = 1;
|
||||
jschar chars[20];
|
||||
size_t charsLength = 5;
|
||||
char bytes[20];
|
||||
size_t bytesLength = 20;
|
||||
if (argc && !JS_ValueToInt32(cx, *JS_ARGV(cx, vp), &mode))
|
||||
return false;
|
||||
|
||||
/* The following throw errors if compiled with UTF-8. */
|
||||
switch (mode) {
|
||||
/* mode 1: malformed UTF-8 string. */
|
||||
case 1:
|
||||
JS_NewStringCopyZ(cx, badUTF8);
|
||||
break;
|
||||
/* mode 2: big UTF-8 character. */
|
||||
case 2:
|
||||
JS_NewStringCopyZ(cx, bigUTF8);
|
||||
break;
|
||||
/* mode 3: bad surrogate character. */
|
||||
case 3:
|
||||
DeflateStringToBuffer(cx, badSurrogate, 6, bytes, &bytesLength);
|
||||
break;
|
||||
/* mode 4: use a too small buffer. */
|
||||
case 4:
|
||||
JS_DecodeBytes(cx, "1234567890", 10, chars, &charsLength);
|
||||
break;
|
||||
default:
|
||||
JS_ReportError(cx, "invalid mode parameter");
|
||||
return false;
|
||||
}
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
return !JS_IsExceptionPending (cx);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ThrowError(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
@ -3740,10 +3699,6 @@ static JSFunctionSpecWithHelp shell_functions[] = {
|
||||
"pc2line(fun[, pc])",
|
||||
" Map PC to line number."),
|
||||
|
||||
JS_FN_HELP("testUTF8", TestUTF8, 1, 0,
|
||||
"testUTF8(mode)",
|
||||
" Perform UTF-8 tests (modes are 1 to 4)."),
|
||||
|
||||
JS_FN_HELP("throwError", ThrowError, 0, 0,
|
||||
"throwError()",
|
||||
" Throw an error from JS_ReportError."),
|
||||
|
@ -1,122 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
var BUGNUMBER = 232182;
|
||||
var summary = 'Display non-ascii characters in JS exceptions';
|
||||
var actual = '';
|
||||
var expect = 'no error';
|
||||
|
||||
printBugNumber(BUGNUMBER);
|
||||
printStatus (summary);
|
||||
|
||||
/*
|
||||
* This test accesses an undefined Unicode symbol. If the code has not been
|
||||
* compiled with JS_C_STRINGS_ARE_UTF8, the thrown error truncates Unicode
|
||||
* characters to bytes. Accessing \u0440\u0441, therefore, results in a
|
||||
* message talking about an undefined variable 'AB' (\x41\x42).
|
||||
*/
|
||||
var utf8Enabled = false;
|
||||
try
|
||||
{
|
||||
\u0441\u0442;
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
utf8Enabled = (e.message.charAt (0) == '\u0441');
|
||||
}
|
||||
|
||||
// Run the tests only if UTF-8 is enabled
|
||||
|
||||
printStatus('UTF-8 is ' + (utf8Enabled?'':'not ') + 'enabled');
|
||||
|
||||
if (!utf8Enabled)
|
||||
{
|
||||
reportCompare('Not run', 'Not run', 'utf8 is not enabled');
|
||||
}
|
||||
else
|
||||
{
|
||||
status = summary + ': Throw Error with Unicode message';
|
||||
expect = 'test \u0440\u0441';
|
||||
try
|
||||
{
|
||||
throw Error (expect);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = e.message;
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
|
||||
var inShell = (typeof stringsAreUTF8 == "function");
|
||||
if (!inShell)
|
||||
{
|
||||
inShell = (typeof stringsAreUtf8 == "function");
|
||||
if (inShell)
|
||||
{
|
||||
this.stringsAreUTF8 = stringsAreUtf8;
|
||||
this.testUTF8 = testUtf8;
|
||||
}
|
||||
}
|
||||
|
||||
if (inShell && stringsAreUTF8())
|
||||
{
|
||||
status = summary + ': UTF-8 test: bad UTF-08 sequence';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(1);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
|
||||
status = summary + ': UTF-8 character too big to fit into Unicode surrogate pairs';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(2);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
|
||||
status = summary + ': bad Unicode surrogate character';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(3);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
}
|
||||
|
||||
if (inShell)
|
||||
{
|
||||
status = summary + ': conversion target buffer overrun';
|
||||
expect = 'Error';
|
||||
actual = 'No error!';
|
||||
try
|
||||
{
|
||||
testUTF8(4);
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
actual = 'Error';
|
||||
}
|
||||
reportCompare(expect, actual, status);
|
||||
}
|
||||
}
|
28
js/src/vm/CharacterEncoding.cpp
Normal file
28
js/src/vm/CharacterEncoding.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sw=4 et tw=78:
|
||||
*
|
||||
* 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/. */
|
||||
|
||||
#include "jscntxt.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
using namespace JS;
|
||||
|
||||
Latin1CharsZ
|
||||
JS::LossyTwoByteCharsToNewLatin1CharsZ(JSContext *cx, TwoByteChars tbchars)
|
||||
{
|
||||
AutoAssertNoGC nogc;
|
||||
JS_ASSERT(cx);
|
||||
size_t len = tbchars.length();
|
||||
unsigned char *latin1 = cx->pod_malloc<unsigned char>(len + 1);
|
||||
if (!latin1)
|
||||
return Latin1CharsZ();
|
||||
for (size_t i = 0; i < len; ++i)
|
||||
latin1[i] = static_cast<unsigned char>(tbchars[i]);
|
||||
latin1[len] = '\0';
|
||||
return Latin1CharsZ(latin1, len);
|
||||
}
|
||||
|
@ -11,6 +11,8 @@
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/GuardObjects.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsatom.h"
|
||||
#include "jsfriendapi.h"
|
||||
@ -477,6 +479,11 @@ class JSLinearString : public JSString
|
||||
JS_ASSERT(JSString::isLinear());
|
||||
return d.u1.chars;
|
||||
}
|
||||
|
||||
JS::TwoByteChars range() const {
|
||||
JS_ASSERT(JSString::isLinear());
|
||||
return JS::TwoByteChars(d.u1.chars, length());
|
||||
}
|
||||
};
|
||||
|
||||
JS_STATIC_ASSERT(sizeof(JSLinearString) == sizeof(JSString));
|
||||
|
@ -575,7 +575,7 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if (!buffer) {
|
||||
return false;
|
||||
}
|
||||
JS_EncodeStringToBuffer(str, buffer, length);
|
||||
JS_EncodeStringToBuffer(cx, str, buffer, length);
|
||||
buffer[length] = '\0';
|
||||
*((void**)d) = buffer;
|
||||
return true;
|
||||
@ -701,7 +701,7 @@ XPCConvert::JSData2Native(JSContext* cx, void* d, jsval s,
|
||||
if (rs->Length() != uint32_t(length)) {
|
||||
return false;
|
||||
}
|
||||
JS_EncodeStringToBuffer(str, rs->BeginWriting(), length);
|
||||
JS_EncodeStringToBuffer(cx, str, rs->BeginWriting(), length);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -1875,7 +1875,7 @@ XPCConvert::JSStringWithSize2Native(XPCCallContext& ccx, void* d, jsval s,
|
||||
if (!buffer) {
|
||||
return false;
|
||||
}
|
||||
JS_EncodeStringToBuffer(str, buffer, len);
|
||||
JS_EncodeStringToBuffer(cx, str, buffer, len);
|
||||
buffer[len] = '\0';
|
||||
*((char**)d) = buffer;
|
||||
|
||||
|
@ -122,7 +122,7 @@ XPCJSStackFrame::CreateStack(JSContext* cx, XPCJSStackFrame** stack)
|
||||
if (length != size_t(-1)) {
|
||||
self->mFunname = static_cast<char *>(nsMemory::Alloc(length + 1));
|
||||
if (self->mFunname) {
|
||||
JS_EncodeStringToBuffer(funid, self->mFunname, length);
|
||||
JS_EncodeStringToBuffer(cx, funid, self->mFunname, length);
|
||||
self->mFunname[length] = '\0';
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user