Bug 805080 - Remove unused CESU8 support from SpiderMonkey; r=luke

We have many CESU8 paths in SpiderMonkey which are completely unused and
untested. We have many more "UTF-8" paths which are really mislabled CESU8 paths
and visa-versa. This patch attempts to disentable all of the various encoding
options in SpiderMonkey.
This commit is contained in:
Terrence Cole 2012-10-29 13:55:17 -07:00
Родитель b75203c1e9
Коммит a80f8cc0af
20 изменённых файлов: 242 добавлений и 606 удалений

Просмотреть файл

@ -597,7 +597,7 @@ ProcessFile(JSContext *cx,
}
bufp += strlen(bufp);
lineno++;
} while (!JS_BufferIsCompilableUnit(cx, JS_FALSE, obj, buffer, strlen(buffer)));
} while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
/* Clear any pending exception from previous failed compiles. */
JS_ClearPendingException(cx);

Просмотреть файл

@ -39,6 +39,114 @@ using namespace std;
namespace js {
namespace ctypes {
size_t
GetDeflatedUTF8StringLength(JSContext *maybecx, const jschar *chars,
size_t nchars)
{
size_t nbytes;
const jschar *end;
unsigned c, c2;
char buffer[10];
nbytes = nchars;
for (end = chars + nchars; chars != end; chars++) {
c = *chars;
if (c < 0x80)
continue;
if (0xD800 <= c && c <= 0xDFFF) {
/* Surrogate pair. */
chars++;
/* nbytes sets 1 length since this is surrogate pair. */
nbytes--;
if (c >= 0xDC00 || chars == end)
goto bad_surrogate;
c2 = *chars;
if (c2 < 0xDC00 || c2 > 0xDFFF)
goto bad_surrogate;
c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
}
c >>= 11;
nbytes++;
while (c) {
c >>= 5;
nbytes++;
}
}
return nbytes;
bad_surrogate:
if (maybecx) {
JS_snprintf(buffer, 10, "0x%x", c);
JS_ReportErrorFlagsAndNumber(maybecx, JSREPORT_ERROR, js_GetErrorMessage,
NULL, JSMSG_BAD_SURROGATE_CHAR, buffer);
}
return (size_t) -1;
}
bool
DeflateStringToUTF8Buffer(JSContext *maybecx, const jschar *src, size_t srclen,
char *dst, size_t *dstlenp)
{
size_t i, utf8Len;
jschar c, c2;
uint32_t v;
uint8_t utf8buf[6];
size_t dstlen = *dstlenp;
size_t origDstlen = dstlen;
while (srclen) {
c = *src++;
srclen--;
if (c >= 0xDC00 && c <= 0xDFFF)
goto badSurrogate;
if (c < 0xD800 || c > 0xDBFF) {
v = c;
} else {
if (srclen < 1)
goto badSurrogate;
c2 = *src;
if ((c2 < 0xDC00) || (c2 > 0xDFFF))
goto badSurrogate;
src++;
srclen--;
v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
}
if (v < 0x0080) {
/* no encoding necessary - performance hack */
if (dstlen == 0)
goto bufferTooSmall;
*dst++ = (char) v;
utf8Len = 1;
} else {
utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
if (utf8Len > dstlen)
goto bufferTooSmall;
for (i = 0; i < utf8Len; i++)
*dst++ = (char) utf8buf[i];
}
dstlen -= utf8Len;
}
*dstlenp = (origDstlen - dstlen);
return JS_TRUE;
badSurrogate:
*dstlenp = (origDstlen - dstlen);
/* Delegate error reporting to the measurement function. */
if (maybecx)
GetDeflatedUTF8StringLength(maybecx, src - 1, srclen + 1);
return JS_FALSE;
bufferTooSmall:
*dstlenp = (origDstlen - dstlen);
if (maybecx) {
JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL,
JSMSG_BUFFER_TOO_SMALL);
}
return JS_FALSE;
}
/*******************************************************************************
** JSAPI function prototypes
*******************************************************************************/

Просмотреть файл

@ -155,6 +155,15 @@ PrependString(Vector<jschar, N, AP> &v, JSString* str)
memcpy(v.begin(), chars, alen * sizeof(jschar));
}
extern size_t
GetDeflatedUTF8StringLength(JSContext *maybecx, const jschar *chars,
size_t charsLength);
bool
DeflateStringToUTF8Buffer(JSContext *maybecx, const jschar *src, size_t srclen,
char *dst, size_t *dstlenp);
/*******************************************************************************
** Function and struct API definitions
*******************************************************************************/

Просмотреть файл

@ -60,7 +60,6 @@ CPPSRCS = \
testStringBuffer.cpp \
testTrap.cpp \
testTypedArrays.cpp \
testUTF8.cpp \
testValueABI.cpp \
testVersion.cpp \
testXDR.cpp \

Просмотреть файл

@ -1,25 +0,0 @@
/* -*- 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"
BEGIN_TEST(testUTF8_bug589917)
{
const jschar surrogate_pair[] = { 0xd800, 0xdc00 };
char output_buffer[10];
size_t utf8_len = sizeof(output_buffer);
CHECK(JS_EncodeCharacters(cx, surrogate_pair, 2, output_buffer, &utf8_len));
CHECK_EQUAL(utf8_len, 4);
CHECK(JS_EncodeCharacters(cx, surrogate_pair, 2, NULL, &utf8_len));
CHECK_EQUAL(utf8_len, 4);
return true;
}
END_TEST(testUTF8_bug589917)

Просмотреть файл

@ -25,10 +25,12 @@ CompileScriptForPrincipalsVersionOrigin(JSContext *cx, JS::HandleObject obj,
if (!chars)
return NULL;
JS_ALWAYS_TRUE(JS_DecodeBytes(cx, bytes, nbytes, chars, &nchars));
JSScript *script = JS_CompileUCScriptForPrincipalsVersionOrigin(cx, obj,
principals, originPrincipals,
chars, nchars,
filename, lineno, version);
JS::CompileOptions options(cx);
options.setPrincipals(principals)
.setOriginPrincipals(originPrincipals)
.setFileAndLine(filename, lineno)
.setVersion(version);
JSScript *script = JS::Compile(cx, obj, options, chars, nchars);
free(chars);
return script;
}

Просмотреть файл

@ -76,8 +76,6 @@ int main(int argc, char *argv[])
int failures = 0;
const char *filter = (argc == 2) ? argv[1] : NULL;
JS_SetCStringsAreUTF8();
for (JSAPITest *test = JSAPITest::list; test; test = test->next) {
const char *name = test->name();
if (filter && strstr(name, filter) == NULL)

Просмотреть файл

@ -668,9 +668,8 @@ JS_IsBuiltinFunctionConstructor(JSFunction *fun)
/************************************************************************/
/*
* Has a new runtime ever been created? This flag is used to detect unsafe
* changes to js_CStringsAreUTF8 after a runtime has been created, and to
* control things that should happen only once across all runtimes.
* Has a new runtime ever been created? This flag is used to control things
* that should happen only once across all runtimes.
*/
static JSBool js_NewRuntimeWasCalled = JS_FALSE;
@ -5211,7 +5210,7 @@ JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options,
{
jschar *chars;
if (options.utf8)
chars = InflateString(cx, bytes, &length, CESU8Encoding);
chars = InflateUTF8String(cx, bytes, &length);
else
chars = InflateString(cx, bytes, &length);
if (!chars)
@ -5244,40 +5243,6 @@ JS::Compile(JSContext *cx, HandleObject obj, CompileOptions options, const char
return script;
}
extern JS_PUBLIC_API(JSScript *)
JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg,
JSPrincipals *principals,
const jschar *chars, size_t length,
const char *filename, unsigned lineno,
JSVersion version)
{
RootedObject obj(cx, objArg);
CompileOptions options(cx);
options.setPrincipals(principals)
.setFileAndLine(filename, lineno)
.setVersion(version);
return Compile(cx, obj, options, chars, length);
}
extern JS_PUBLIC_API(JSScript *)
JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *objArg,
JSPrincipals *principals,
JSPrincipals *originPrincipals,
const jschar *chars, size_t length,
const char *filename, unsigned lineno,
JSVersion version)
{
RootedObject obj(cx, objArg);
CompileOptions options(cx);
options.setPrincipals(principals)
.setOriginPrincipals(originPrincipals)
.setFileAndLine(filename, lineno)
.setVersion(version);
return Compile(cx, obj, options, chars, length);
}
JS_PUBLIC_API(JSScript *)
JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *objArg, JSPrincipals *principals,
const jschar *chars, size_t length,
@ -5302,26 +5267,10 @@ JS_CompileUCScript(JSContext *cx, JSObject *objArg, const jschar *chars, size_t
return Compile(cx, obj, options, chars, length);
}
JS_PUBLIC_API(JSScript *)
JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *objArg,
JSPrincipals *principals,
const char *bytes, size_t length,
const char *filename, unsigned lineno,
JSVersion version)
{
RootedObject obj(cx, objArg);
CompileOptions options(cx);
options.setPrincipals(principals)
.setFileAndLine(filename, lineno)
.setVersion(version);
return Compile(cx, obj, options, bytes, length);
}
JS_PUBLIC_API(JSScript *)
JS_CompileScriptForPrincipals(JSContext *cx, JSObject *objArg,
JSPrincipals *principals,
const char *bytes, size_t length,
const char *ascii, size_t length,
const char *filename, unsigned lineno)
{
RootedObject obj(cx, objArg);
@ -5329,25 +5278,24 @@ JS_CompileScriptForPrincipals(JSContext *cx, JSObject *objArg,
options.setPrincipals(principals)
.setFileAndLine(filename, lineno);
return Compile(cx, obj, options, bytes, length);
return Compile(cx, obj, options, ascii, length);
}
JS_PUBLIC_API(JSScript *)
JS_CompileScript(JSContext *cx, JSObject *objArg, const char *bytes, size_t length,
JS_CompileScript(JSContext *cx, JSObject *objArg, const char *ascii, size_t length,
const char *filename, unsigned lineno)
{
RootedObject obj(cx, objArg);
CompileOptions options(cx);
options.setFileAndLine(filename, lineno);
return Compile(cx, obj, options, bytes, length);
return Compile(cx, obj, options, ascii, length);
}
JS_PUBLIC_API(JSBool)
JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *objArg, const char *bytes, size_t length)
JS_BufferIsCompilableUnit(JSContext *cx, JSObject *objArg, const char *utf8, size_t length)
{
RootedObject obj(cx, objArg);
jschar *chars;
JSBool result;
JSExceptionState *exnState;
JSErrorReporter older;
@ -5355,10 +5303,7 @@ JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8, JSObject *objArg
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
assertSameCompartment(cx, obj);
if (bytes_are_utf8)
chars = InflateString(cx, bytes, &length, CESU8Encoding);
else
chars = InflateString(cx, bytes, &length);
jschar *chars = InflateUTF8String(cx, utf8, &length);
if (!chars)
return JS_TRUE;
@ -5415,20 +5360,6 @@ JS_CompileUTF8FileHandleForPrincipals(JSContext *cx, JSObject *objArg, const cha
return Compile(cx, obj, options, file);
}
JS_PUBLIC_API(JSScript *)
JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *objArg, const char *filename,
FILE *file, JSPrincipals *principals, JSVersion version)
{
RootedObject obj(cx, objArg);
CompileOptions options(cx);
options.setUTF8(true)
.setFileAndLine(filename, 1)
.setPrincipals(principals)
.setVersion(version);
return Compile(cx, obj, options, file);
}
JS_PUBLIC_API(JSScript *)
JS_CompileUTF8FileHandle(JSContext *cx, JSObject *objArg, const char *filename, FILE *file)
{
@ -5504,7 +5435,7 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options,
{
jschar *chars;
if (options.utf8)
chars = InflateString(cx, bytes, &length, CESU8Encoding);
chars = InflateUTF8String(cx, bytes, &length);
else
chars = InflateString(cx, bytes, &length);
if (!chars)
@ -5515,39 +5446,6 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options,
return fun;
}
JS_PUBLIC_API(JSFunction *)
JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj_,
JSPrincipals *principals, const char *name,
unsigned nargs, const char **argnames,
const jschar *chars, size_t length,
const char *filename, unsigned lineno,
JSVersion version)
{
RootedObject obj(cx, obj_);
CompileOptions options(cx);
options.setPrincipals(principals)
.setFileAndLine(filename, lineno)
.setVersion(version);
return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
}
JS_PUBLIC_API(JSFunction *)
JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *objArg,
JSPrincipals *principals, const char *name,
unsigned nargs, const char **argnames,
const jschar *chars, size_t length,
const char *filename, unsigned lineno)
{
RootedObject obj(cx, objArg);
CompileOptions options(cx);
options.setPrincipals(principals)
.setFileAndLine(filename, lineno);
return CompileFunction(cx, obj, options, name, nargs, argnames, chars, length);
}
JS_PUBLIC_API(JSFunction *)
JS_CompileUCFunction(JSContext *cx, JSObject *objArg, const char *name,
unsigned nargs, const char **argnames,
@ -5565,7 +5463,7 @@ JS_PUBLIC_API(JSFunction *)
JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *objArg,
JSPrincipals *principals, const char *name,
unsigned nargs, const char **argnames,
const char *bytes, size_t length,
const char *ascii, size_t length,
const char *filename, unsigned lineno)
{
RootedObject obj(cx, objArg);
@ -5573,20 +5471,20 @@ JS_CompileFunctionForPrincipals(JSContext *cx, JSObject *objArg,
options.setPrincipals(principals)
.setFileAndLine(filename, lineno);
return CompileFunction(cx, obj, options, name, nargs, argnames, bytes, length);
return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
}
JS_PUBLIC_API(JSFunction *)
JS_CompileFunction(JSContext *cx, JSObject *objArg, const char *name,
unsigned nargs, const char **argnames,
const char *bytes, size_t length,
const char *ascii, size_t length,
const char *filename, unsigned lineno)
{
RootedObject obj(cx, objArg);
CompileOptions options(cx);
options.setFileAndLine(filename, lineno);
return CompileFunction(cx, obj, options, name, nargs, argnames, bytes, length);
return CompileFunction(cx, obj, options, name, nargs, argnames, ascii, length);
}
JS_PUBLIC_API(JSString *)
@ -5703,7 +5601,7 @@ JS::Evaluate(JSContext *cx, HandleObject obj, CompileOptions options,
{
jschar *chars;
if (options.utf8)
chars = InflateString(cx, bytes, &length, CESU8Encoding);
chars = InflateUTF8String(cx, bytes, &length);
else
chars = InflateString(cx, bytes, &length);
if (!chars)
@ -6282,26 +6180,6 @@ JS_UndependString(JSContext *cx, JSString *str)
return str->getCharsZ(cx);
}
JS_PUBLIC_API(JSBool)
JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst, size_t *dstlenp)
{
AssertHeapIsIdle(cx);
CHECK_REQUEST(cx);
size_t n;
if (!dst) {
n = GetDeflatedStringLength(cx, src, srclen);
if (n == (size_t)-1) {
*dstlenp = 0;
return JS_FALSE;
}
*dstlenp = n;
return JS_TRUE;
}
return DeflateStringToBuffer(cx, src, srclen, dst, dstlenp);
}
JS_PUBLIC_API(JSBool)
JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst, size_t *dstlenp)
{
@ -6368,11 +6246,7 @@ JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length)
size_t necessaryLength = GetDeflatedStringLength(NULL, chars, str->length());
if (necessaryLength == size_t(-1))
return size_t(-1);
if (writtenLength != length) {
/* Make sure that the buffer contains only valid UTF-8 sequences. */
JS_ASSERT(js_CStringsAreUTF8);
PodZero(buffer + writtenLength, length - writtenLength);
}
JS_ASSERT(writtenLength == length); // C strings are NOT encoded.
return necessaryLength;
}
@ -6639,31 +6513,6 @@ JS_WriteBytes(JSStructuredCloneWriter *w, const void *p, size_t len)
return w->output().writeBytes(p, len);
}
/*
* The following determines whether C Strings are to be treated as UTF-8
* or ISO-8859-1. For correct operation, it must be set prior to the
* first call to JS_NewRuntime.
*/
#ifndef JS_C_STRINGS_ARE_UTF8
JSBool js_CStringsAreUTF8 = JS_FALSE;
#endif
JS_PUBLIC_API(JSBool)
JS_CStringsAreUTF8()
{
return js_CStringsAreUTF8;
}
JS_PUBLIC_API(void)
JS_SetCStringsAreUTF8()
{
JS_ASSERT(!js_NewRuntimeWasCalled);
#ifndef JS_C_STRINGS_ARE_UTF8
js_CStringsAreUTF8 = JS_TRUE;
#endif
}
/************************************************************************/
JS_PUBLIC_API(void)

Просмотреть файл

@ -1974,7 +1974,7 @@ typedef enum JSExnType {
} JSExnType;
typedef struct JSErrorFormatString {
/* The error format string (UTF-8 if js_CStringsAreUTF8). */
/* The error format string in ASCII. */
const char *format;
/* The number of arguments to expand in the formatted error message. */
@ -4948,27 +4948,19 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSRawObject parent);
* the compiler.
*/
extern JS_PUBLIC_API(JSBool)
JS_BufferIsCompilableUnit(JSContext *cx, JSBool bytes_are_utf8,
JSObject *obj, const char *bytes, size_t length);
JS_BufferIsCompilableUnit(JSContext *cx, JSObject *obj, const char *utf8, size_t length);
extern JS_PUBLIC_API(JSScript *)
JS_CompileScript(JSContext *cx, JSObject *obj,
const char *bytes, size_t length,
const char *ascii, size_t length,
const char *filename, unsigned lineno);
extern JS_PUBLIC_API(JSScript *)
JS_CompileScriptForPrincipals(JSContext *cx, JSObject *obj,
JSPrincipals *principals,
const char *bytes, size_t length,
const char *ascii, size_t length,
const char *filename, unsigned lineno);
extern JS_PUBLIC_API(JSScript *)
JS_CompileScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
JSPrincipals *principals,
const char *bytes, size_t length,
const char *filename, unsigned lineno,
JSVersion version);
extern JS_PUBLIC_API(JSScript *)
JS_CompileUCScript(JSContext *cx, JSObject *obj,
const jschar *chars, size_t length,
@ -4980,24 +4972,6 @@ JS_CompileUCScriptForPrincipals(JSContext *cx, JSObject *obj,
const jschar *chars, size_t length,
const char *filename, unsigned lineno);
extern JS_PUBLIC_API(JSScript *)
JS_CompileUCScriptForPrincipalsVersion(JSContext *cx, JSObject *obj,
JSPrincipals *principals,
const jschar *chars, size_t length,
const char *filename, unsigned lineno,
JSVersion version);
/*
* If originPrincipals is null, then the value of principals is used as origin
* principals for the compiled script.
*/
extern JS_PUBLIC_API(JSScript *)
JS_CompileUCScriptForPrincipalsVersionOrigin(JSContext *cx, JSObject *obj,
JSPrincipals *principals,
JSPrincipals *originPrincipals,
const jschar *chars, size_t length,
const char *filename, unsigned lineno,
JSVersion version);
extern JS_PUBLIC_API(JSScript *)
JS_CompileUTF8File(JSContext *cx, JSObject *obj, const char *filename);
@ -5010,12 +4984,6 @@ JS_CompileUTF8FileHandleForPrincipals(JSContext *cx, JSObject *obj,
const char *filename, FILE *fh,
JSPrincipals *principals);
extern JS_PUBLIC_API(JSScript *)
JS_CompileUTF8FileHandleForPrincipalsVersion(JSContext *cx, JSObject *obj,
const char *filename, FILE *fh,
JSPrincipals *principals,
JSVersion version);
extern JS_PUBLIC_API(JSObject *)
JS_GetGlobalFromScript(JSScript *script);
@ -5038,21 +5006,6 @@ JS_CompileUCFunction(JSContext *cx, JSObject *obj, const char *name,
const jschar *chars, size_t length,
const char *filename, unsigned lineno);
extern JS_PUBLIC_API(JSFunction *)
JS_CompileUCFunctionForPrincipals(JSContext *cx, JSObject *obj,
JSPrincipals *principals, const char *name,
unsigned nargs, const char **argnames,
const jschar *chars, size_t length,
const char *filename, unsigned lineno);
extern JS_PUBLIC_API(JSFunction *)
JS_CompileUCFunctionForPrincipalsVersion(JSContext *cx, JSObject *obj,
JSPrincipals *principals, const char *name,
unsigned nargs, const char **argnames,
const jschar *chars, size_t length,
const char *filename, unsigned lineno,
JSVersion version);
#ifdef __cplusplus
JS_END_EXTERN_C
@ -5537,48 +5490,19 @@ extern JS_PUBLIC_API(const jschar *)
JS_UndependString(JSContext *cx, JSString *str);
/*
* Return JS_TRUE if C (char []) strings passed via the API and internally
* are UTF-8.
*/
JS_PUBLIC_API(JSBool)
JS_CStringsAreUTF8(void);
/*
* Update the value to be returned by JS_CStringsAreUTF8(). Once set, it
* can never be changed. This API must be called before the first call to
* JS_NewRuntime.
*/
JS_PUBLIC_API(void)
JS_SetCStringsAreUTF8(void);
/*
* Character encoding support.
*
* For both JS_EncodeCharacters and JS_DecodeBytes, set *dstlenp to the size
* of the destination buffer before the call; on return, *dstlenp contains the
* number of bytes (JS_EncodeCharacters) or jschars (JS_DecodeBytes) actually
* stored. To determine the necessary destination buffer size, make a sizing
* call that passes NULL for dst.
* For JS_DecodeBytes, set *dstlenp to the size of the destination buffer before
* the call; on return, *dstlenp contains the number of jschars actually stored.
* To determine the necessary destination buffer size, make a sizing call that
* passes NULL for dst.
*
* On errors, the functions report the error. In that case, *dstlenp contains
* the number of characters or bytes transferred so far. If cx is NULL, no
* error is reported on failure, and the functions simply return JS_FALSE.
*
* NB: Neither function stores an additional zero byte or jschar after the
* NB: This function does not store an additional zero byte or jschar after the
* transcoded string.
*
* If JS_CStringsAreUTF8() is true then JS_EncodeCharacters encodes to
* UTF-8, and JS_DecodeBytes decodes from UTF-8, which may create additional
* errors if the character sequence is malformed. If UTF-8 support is
* disabled, the functions deflate and inflate, respectively.
*
* JS_DecodeUTF8() always behaves the same independently of JS_CStringsAreUTF8().
*/
JS_PUBLIC_API(JSBool)
JS_EncodeCharacters(JSContext *cx, const jschar *src, size_t srclen, char *dst,
size_t *dstlenp);
JS_PUBLIC_API(JSBool)
JS_DecodeBytes(JSContext *cx, const char *src, size_t srclen, jschar *dst,
size_t *dstlenp);
@ -5608,11 +5532,6 @@ JS_GetStringEncodingLength(JSContext *cx, JSString *str);
* of bytes that are necessary to encode the string. If that exceeds the
* length parameter, the string will be cut and only length bytes will be
* written into the buffer.
*
* If JS_CStringsAreUTF8() is true, the string does not fit into the buffer
* and the the first length bytes ends in the middle of utf-8 encoding for
* some character, then such partial utf-8 encoding is replaced by zero bytes.
* This way the result always represents the valid UTF-8 sequence.
*/
JS_PUBLIC_API(size_t)
JS_EncodeStringToBuffer(JSString *str, char *buffer, size_t length);

Просмотреть файл

@ -319,7 +319,7 @@ js::AtomizeString(JSContext *cx, JSString *str, InternBehavior ib)
}
JSAtom *
js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib, FlationCoding fc)
js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib)
{
CHECK_REQUEST(cx);
@ -340,15 +340,12 @@ js::Atomize(JSContext *cx, const char *bytes, size_t length, InternBehavior ib,
const jschar *chars;
OwnCharsBehavior ocb = CopyChars;
if (length < ATOMIZE_BUF_MAX) {
if (fc == CESU8Encoding)
InflateUTF8StringToBuffer(cx, bytes, length, inflated, &inflatedLength, fc);
else
InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
InflateStringToBuffer(cx, bytes, length, inflated, &inflatedLength);
inflated[inflatedLength] = 0;
chars = inflated;
} else {
inflatedLength = length;
chars = InflateString(cx, bytes, &inflatedLength, fc);
chars = InflateString(cx, bytes, &inflatedLength);
if (!chars)
return NULL;
ocb = TakeCharOwnership;

Просмотреть файл

@ -119,29 +119,6 @@ struct AtomHasher
typedef HashSet<AtomStateEntry, AtomHasher, SystemAllocPolicy> AtomSet;
/*
* On encodings:
*
* - Some string functions have an optional FlationCoding argument that allow
* the caller to force CESU-8 encoding handling.
* - Functions that don't take a FlationCoding base their NormalEncoding
* behavior on the js_CStringsAreUTF8 value. NormalEncoding is either raw
* (simple zero-extension) or UTF-8 depending on js_CStringsAreUTF8.
* - Functions that explicitly state their encoding do not use the
* js_CStringsAreUTF8 value.
*
* CESU-8 (Compatibility Encoding Scheme for UTF-16: 8-bit) is a variant of
* UTF-8 that allows us to store any wide character string as a narrow
* character string. For strings containing mostly ascii, it saves space.
* http://www.unicode.org/reports/tr26/
*/
enum FlationCoding
{
NormalEncoding,
CESU8Encoding
};
class PropertyName;
} /* namespace js */
@ -246,8 +223,7 @@ enum InternBehavior
extern JSAtom *
Atomize(JSContext *cx, const char *bytes, size_t length,
js::InternBehavior ib = js::DoNotInternAtom,
js::FlationCoding fc = js::NormalEncoding);
js::InternBehavior ib = js::DoNotInternAtom);
extern JSAtom *
AtomizeChars(JSContext *cx, const jschar *chars, size_t length,

Просмотреть файл

@ -668,8 +668,6 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
struct NumArgState nasArray[ NAS_DEFAULT_NUM ];
char pattern[20];
const char *dolPt = NULL; /* in "%4$.2f", dolPt will poiont to . */
uint8_t utf8buf[6];
int utf8len;
/*
** build an argument array, IF the fmt is numbered argument
@ -906,13 +904,6 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
}
switch (type) {
case TYPE_INT16:
/* Treat %hc as %c unless js_CStringsAreUTF8. */
if (js_CStringsAreUTF8) {
u.wch = va_arg(ap, int);
utf8len = js_OneUcs4ToUtf8Char (utf8buf, u.wch);
rv = (*ss->stuff)(ss, (char *)utf8buf, utf8len);
break;
}
case TYPE_INTN:
u.ch = va_arg(ap, int);
rv = (*ss->stuff)(ss, &u.ch, 1);
@ -957,10 +948,6 @@ static int dosprintf(SprintfState *ss, const char *fmt, va_list ap)
case 's':
if(type == TYPE_INT16) {
/*
* This would do a simple string/byte conversion
* unless js_CStringsAreUTF8.
*/
u.ws = va_arg(ap, const jschar*);
rv = cvt_ws(ss, u.ws, width, prec, flags);
} else {

Просмотреть файл

@ -16,10 +16,9 @@
** %hd, %hu, %hx, %hX, %ho - 16-bit versions of above
** %ld, %lu, %lx, %lX, %lo - 32-bit versions of above
** %lld, %llu, %llx, %llX, %llo - 64 bit versions of above
** %s - string
** %hs - 16-bit version of above (only available if js_CStringsAreUTF8)
** %s - ascii string
** %hs - ucs2 string
** %c - character
** %hc - 16-bit version of above (only available if js_CStringsAreUTF8)
** %p - pointer (deals with machine dependent pointer size)
** %f - float
** %g - float

Просмотреть файл

@ -379,16 +379,6 @@ typedef JSObject *
typedef JSObject *
(* JSIteratorOp)(JSContext *cx, JSHandleObject obj, JSBool keysonly);
/*
* The following determines whether JS_EncodeCharacters and JS_DecodeBytes
* treat char[] as utf-8 or simply as bytes that need to be inflated/deflated.
*/
#ifdef JS_C_STRINGS_ARE_UTF8
# define js_CStringsAreUTF8 JS_TRUE
#else
extern JSBool js_CStringsAreUTF8;
#endif
JS_END_EXTERN_C
#endif /* jsprvtd_h___ */

Просмотреть файл

@ -3297,23 +3297,11 @@ NewShortString(JSContext *cx, const char *chars, size_t length)
if (!str)
return NULL;
jschar *storage = str->init(length);
if (js_CStringsAreUTF8) {
#ifdef DEBUG
size_t oldLength = length;
#endif
if (!InflateUTF8StringToBuffer(cx, chars, length, storage, &length))
return NULL;
JS_ASSERT(length <= oldLength);
storage[length] = 0;
str->resetLength(length);
} else {
size_t n = length;
jschar *p = storage;
while (n--)
*p++ = (unsigned char)*chars++;
*p = 0;
}
size_t n = length;
jschar *p = str->init(length);
while (n--)
*p++ = (unsigned char)*chars++;
*p = 0;
Probes::createString(cx, str, length);
return str;
}
@ -3615,7 +3603,34 @@ js_strchr_limit(const jschar *s, jschar c, const jschar *limit)
namespace js {
jschar *
InflateString(JSContext *cx, const char *bytes, size_t *lengthp, FlationCoding fc)
InflateString(JSContext *cx, const char *bytes, size_t *lengthp)
{
AssertCanGC();
size_t nchars;
jschar *chars;
size_t nbytes = *lengthp;
nchars = nbytes;
chars = cx->pod_malloc<jschar>(nchars + 1);
if (!chars)
goto bad;
for (size_t i = 0; i < nchars; i++)
chars[i] = (unsigned char) bytes[i];
*lengthp = nchars;
chars[nchars] = 0;
return chars;
bad:
/*
* For compatibility with callers of JS_DecodeBytes we must zero lengthp
* on errors.
*/
*lengthp = 0;
return NULL;
}
jschar *
InflateUTF8String(JSContext *cx, const char *bytes, size_t *lengthp)
{
AssertCanGC();
size_t nchars;
@ -3625,21 +3640,12 @@ InflateString(JSContext *cx, const char *bytes, size_t *lengthp, FlationCoding f
// Malformed UTF8 chars could trigger errors and hence GC
MaybeCheckStackRoots(cx);
if (js_CStringsAreUTF8 || fc == CESU8Encoding) {
if (!InflateUTF8StringToBuffer(cx, bytes, nbytes, NULL, &nchars, fc))
goto bad;
chars = cx->pod_malloc<jschar>(nchars + 1);
if (!chars)
goto bad;
JS_ALWAYS_TRUE(InflateUTF8StringToBuffer(cx, bytes, nbytes, chars, &nchars, fc));
} else {
nchars = nbytes;
chars = cx->pod_malloc<jschar>(nchars + 1);
if (!chars)
goto bad;
for (size_t i = 0; i < nchars; i++)
chars[i] = (unsigned char) bytes[i];
}
if (!InflateUTF8StringToBuffer(cx, bytes, nbytes, NULL, &nchars))
goto bad;
chars = cx->pod_malloc<jschar>(nchars + 1);
if (!chars)
goto bad;
JS_ALWAYS_TRUE(InflateUTF8StringToBuffer(cx, bytes, nbytes, chars, &nchars));
*lengthp = nchars;
chars[nchars] = 0;
return chars;
@ -3657,27 +3663,17 @@ InflateString(JSContext *cx, const char *bytes, size_t *lengthp, FlationCoding f
* May be called with null cx.
*/
char *
DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
DeflateString(JSContext *maybecx, const jschar *chars, size_t nchars)
{
size_t nbytes, i;
char *bytes;
if (js_CStringsAreUTF8) {
nbytes = GetDeflatedStringLength(cx, chars, nchars);
if (nbytes == (size_t) -1)
return NULL;
bytes = (char *) (cx ? cx->malloc_(nbytes + 1) : js_malloc(nbytes + 1));
if (!bytes)
return NULL;
JS_ALWAYS_TRUE(DeflateStringToBuffer(cx, chars, nchars, bytes, &nbytes));
} else {
nbytes = nchars;
bytes = (char *) (cx ? cx->malloc_(nbytes + 1) : js_malloc(nbytes + 1));
if (!bytes)
return NULL;
for (i = 0; i < nbytes; i++)
bytes[i] = (char) chars[i];
}
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;
}
@ -3685,172 +3681,46 @@ DeflateString(JSContext *cx, const jschar *chars, size_t nchars)
size_t
GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t nchars)
{
if (!js_CStringsAreUTF8)
return nchars;
return GetDeflatedUTF8StringLength(cx, chars, nchars);
}
/*
* May be called with null cx through public API, see below.
*/
size_t
GetDeflatedUTF8StringLength(JSContext *cx, const jschar *chars,
size_t nchars, FlationCoding fc)
{
size_t nbytes;
const jschar *end;
unsigned c, c2;
char buffer[10];
bool useCESU8 = fc == CESU8Encoding;
nbytes = nchars;
for (end = chars + nchars; chars != end; chars++) {
c = *chars;
if (c < 0x80)
continue;
if (0xD800 <= c && c <= 0xDFFF && !useCESU8) {
/* Surrogate pair. */
chars++;
/* nbytes sets 1 length since this is surrogate pair. */
nbytes--;
if (c >= 0xDC00 || chars == end)
goto bad_surrogate;
c2 = *chars;
if (c2 < 0xDC00 || c2 > 0xDFFF)
goto bad_surrogate;
c = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
}
c >>= 11;
nbytes++;
while (c) {
c >>= 5;
nbytes++;
}
}
return nbytes;
bad_surrogate:
if (cx) {
JS_snprintf(buffer, 10, "0x%x", c);
JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, js_GetErrorMessage,
NULL, JSMSG_BAD_SURROGATE_CHAR, buffer);
}
return (size_t) -1;
return nchars;
}
bool
DeflateStringToBuffer(JSContext *cx, const jschar *src, size_t srclen,
DeflateStringToBuffer(JSContext *maybecx, const jschar *src, size_t srclen,
char *dst, size_t *dstlenp)
{
size_t dstlen, i;
dstlen = *dstlenp;
if (!js_CStringsAreUTF8) {
if (srclen > dstlen) {
for (i = 0; i < dstlen; i++)
dst[i] = (char) src[i];
if (cx) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BUFFER_TOO_SMALL);
}
return JS_FALSE;
}
for (i = 0; i < srclen; i++)
dst[i] = (char) src[i];
*dstlenp = srclen;
return JS_TRUE;
}
return DeflateStringToUTF8Buffer(cx, src, srclen, dst, dstlenp);
}
bool
DeflateStringToUTF8Buffer(JSContext *cx, const jschar *src, size_t srclen,
char *dst, size_t *dstlenp, FlationCoding fc)
{
size_t i, utf8Len;
jschar c, c2;
uint32_t v;
uint8_t utf8buf[6];
bool useCESU8 = fc == CESU8Encoding;
size_t dstlen = *dstlenp;
size_t origDstlen = dstlen;
while (srclen) {
c = *src++;
srclen--;
if ((c >= 0xDC00) && (c <= 0xDFFF) && !useCESU8)
goto badSurrogate;
if (c < 0xD800 || c > 0xDBFF || useCESU8) {
v = c;
} else {
if (srclen < 1)
goto badSurrogate;
c2 = *src;
if ((c2 < 0xDC00) || (c2 > 0xDFFF))
goto badSurrogate;
src++;
srclen--;
v = ((c - 0xD800) << 10) + (c2 - 0xDC00) + 0x10000;
if (srclen > dstlen) {
for (size_t i = 0; i < dstlen; i++)
dst[i] = (char) src[i];
if (maybecx) {
JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL,
JSMSG_BUFFER_TOO_SMALL);
}
if (v < 0x0080) {
/* no encoding necessary - performance hack */
if (dstlen == 0)
goto bufferTooSmall;
*dst++ = (char) v;
utf8Len = 1;
} else {
utf8Len = js_OneUcs4ToUtf8Char(utf8buf, v);
if (utf8Len > dstlen)
goto bufferTooSmall;
for (i = 0; i < utf8Len; i++)
*dst++ = (char) utf8buf[i];
}
dstlen -= utf8Len;
return JS_FALSE;
}
*dstlenp = (origDstlen - dstlen);
for (size_t i = 0; i < srclen; i++)
dst[i] = (char) src[i];
*dstlenp = srclen;
return JS_TRUE;
badSurrogate:
*dstlenp = (origDstlen - dstlen);
/* Delegate error reporting to the measurement function. */
if (cx)
GetDeflatedStringLength(cx, src - 1, srclen + 1);
return JS_FALSE;
bufferTooSmall:
*dstlenp = (origDstlen - dstlen);
if (cx) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
JSMSG_BUFFER_TOO_SMALL);
}
return JS_FALSE;
}
bool
InflateStringToBuffer(JSContext *cx, const char *src, size_t srclen,
InflateStringToBuffer(JSContext *maybecx, const char *src, size_t srclen,
jschar *dst, size_t *dstlenp)
{
size_t dstlen, i;
if (js_CStringsAreUTF8)
return InflateUTF8StringToBuffer(cx, src, srclen, dst, dstlenp);
if (dst) {
dstlen = *dstlenp;
size_t dstlen = *dstlenp;
if (srclen > dstlen) {
for (i = 0; i < dstlen; i++)
for (size_t i = 0; i < dstlen; i++)
dst[i] = (unsigned char) src[i];
if (cx) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
if (maybecx) {
JS_ReportErrorNumber(maybecx, js_GetErrorMessage, NULL,
JSMSG_BUFFER_TOO_SMALL);
}
return JS_FALSE;
}
for (i = 0; i < srclen; i++)
for (size_t i = 0; i < srclen; i++)
dst[i] = (unsigned char) src[i];
}
*dstlenp = srclen;
@ -3859,7 +3729,7 @@ InflateStringToBuffer(JSContext *cx, const char *src, size_t srclen,
bool
InflateUTF8StringToBuffer(JSContext *cx, const char *src, size_t srclen,
jschar *dst, size_t *dstlenp, FlationCoding fc)
jschar *dst, size_t *dstlenp)
{
size_t dstlen, origDstlen, offset, j, n;
uint32_t v;
@ -3867,7 +3737,6 @@ InflateUTF8StringToBuffer(JSContext *cx, const char *src, size_t srclen,
dstlen = dst ? *dstlenp : (size_t) -1;
origDstlen = dstlen;
offset = 0;
bool useCESU8 = fc == CESU8Encoding;
while (srclen) {
v = (uint8_t) *src;
@ -3884,7 +3753,7 @@ InflateUTF8StringToBuffer(JSContext *cx, const char *src, size_t srclen,
goto badCharacter;
}
v = Utf8ToOneUcs4Char((uint8_t *)src, n);
if (v >= 0x10000 && !useCESU8) {
if (v >= 0x10000) {
v -= 0x10000;
if (v > 0xFFFFF || dstlen < 2) {
*dstlenp = (origDstlen - dstlen);

Просмотреть файл

@ -208,13 +208,20 @@ js_strdup(JSContext *cx, const jschar *s);
namespace js {
/*
* Inflate bytes to jschars. Return null on error, otherwise return the jschar
* or byte vector that was malloc'ed. length is updated to the length of the
* Inflate bytes in ASCII encoding to jschars. Return null on error, otherwise
* return the jschar that was malloc'ed. length is updated to the length of the
* new string (in jschars).
*/
extern jschar *
InflateString(JSContext *cx, const char *bytes, size_t *length,
FlationCoding fc = NormalEncoding);
InflateString(JSContext *cx, const char *bytes, size_t *length);
/*
* Inflate bytes in UTF-8 encoding to jschars. Return null on error, otherwise
* return the jschar vector that was malloc'ed. length is updated to the length
* of the new string (in jschars).
*/
extern jschar *
InflateUTF8String(JSContext *cx, const char *bytes, size_t *length);
extern char *
DeflateString(JSContext *cx, const jschar *chars, size_t length);
@ -232,37 +239,22 @@ InflateStringToBuffer(JSContext *cx, const char *bytes, size_t length,
extern bool
InflateUTF8StringToBuffer(JSContext *cx, const char *bytes, size_t length,
jschar *chars, size_t *charsLength,
FlationCoding fc = NormalEncoding);
jschar *chars, size_t *charsLength);
/* Get number of bytes in the deflated sequence of characters. */
extern size_t
GetDeflatedStringLength(JSContext *cx, const jschar *chars, size_t charsLength);
/* This function will never fail (return -1) in CESU-8 mode. */
extern size_t
GetDeflatedUTF8StringLength(JSContext *cx, const jschar *chars,
size_t charsLength,
FlationCoding fc = NormalEncoding);
/*
* Deflate JS chars to bytes into a buffer. 'bytes' must be large enough for
* 'length chars. The buffer is NOT null-terminated. The destination length
* must to be initialized with the buffer size and will contain on return the
* number of copied bytes. Conversion behavior depends on js_CStringsAreUTF8.
* number of copied bytes.
*/
extern bool
DeflateStringToBuffer(JSContext *cx, const jschar *chars,
size_t charsLength, char *bytes, size_t *length);
/*
* Same as DeflateStringToBuffer, but treats 'bytes' as UTF-8 or CESU-8.
*/
extern bool
DeflateStringToUTF8Buffer(JSContext *cx, const jschar *chars,
size_t charsLength, char *bytes, size_t *length,
FlationCoding fc = NormalEncoding);
/*
* The String.prototype.replace fast-native entry point is exported for joined
* function optimization in js{interp,tracer}.cpp.

Просмотреть файл

@ -359,9 +359,6 @@ SetContextOptions(JSContext *cx)
static void
SkipUTF8BOM(FILE* file)
{
if (!js_CStringsAreUTF8)
return;
int ch1 = fgetc(file);
int ch2 = fgetc(file);
int ch3 = fgetc(file);
@ -509,7 +506,7 @@ Process(JSContext *cx, JSObject *obj_, const char *filename, bool forceTTY)
hitEOF = true;
break;
}
} while (!JS_BufferIsCompilableUnit(cx, true, obj, buffer, len));
} while (!JS_BufferIsCompilableUnit(cx, obj, buffer, len));
if (hitEOF && !buffer)
break;
@ -2300,13 +2297,6 @@ ToInt32(JSContext *cx, unsigned argc, jsval *vp)
return true;
}
static JSBool
StringsAreUTF8(JSContext *cx, unsigned argc, jsval *vp)
{
*vp = JS_CStringsAreUTF8() ? JSVAL_TRUE : JSVAL_FALSE;
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 };
@ -2334,7 +2324,7 @@ TestUTF8(JSContext *cx, unsigned argc, jsval *vp)
break;
/* mode 3: bad surrogate character. */
case 3:
JS_EncodeCharacters(cx, badSurrogate, 6, bytes, &bytesLength);
DeflateStringToBuffer(cx, badSurrogate, 6, bytes, &bytesLength);
break;
/* mode 4: use a too small buffer. */
case 4:
@ -3541,10 +3531,6 @@ static JSFunctionSpecWithHelp shell_functions[] = {
"pc2line(fun[, pc])",
" Map PC to line number."),
JS_FN_HELP("stringsAreUTF8", StringsAreUTF8, 0, 0,
"stringsAreUTF8()",
" Check if strings are UTF-8 encoded."),
JS_FN_HELP("testUTF8", TestUTF8, 1, 0,
"testUTF8(mode)",
" Perform UTF-8 tests (modes are 1 to 4)."),
@ -4873,7 +4859,6 @@ main(int argc, char **argv, char **envp)
|| !op.addIntOption('A', "oom-after", "COUNT", "Trigger OOM after COUNT allocations", -1)
|| !op.addBoolOption('O', "print-alloc", "Print the number of allocations at exit")
#endif
|| !op.addBoolOption('U', "utf8", "C strings passed to the JSAPI are UTF-8 encoded")
|| !op.addOptionalStringArg("script", "A script to execute (after all options)")
|| !op.addOptionalMultiStringArg("scriptArgs",
"String arguments to bind as |arguments| in the "
@ -4938,10 +4923,6 @@ main(int argc, char **argv, char **envp)
OOM_printAllocationCount = true;
#endif
/* Must be done before we create the JSRuntime. */
if (op.getBoolOption('U'))
JS_SetCStringsAreUTF8();
#ifdef XP_WIN
// Set the timer calibration delay count to 0 so we get high
// resolution right away, which we need for precise benchmarking.

Просмотреть файл

@ -146,19 +146,5 @@ function test()
reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]);
}
for (var i=5; i<=9; i++)
status = summary + ': UTF-8 test: bad UTF-8 sequence ' + i;
expect = 'Error';
actual = 'No error!';
try
{
testUTF8(i);
}
catch (e)
{
actual = 'Error';
}
reportCompare(expect, actual, status);
exitFunc('test');
}

Просмотреть файл

@ -4607,7 +4607,7 @@ DebuggerEnv_getType(JSContext *cx, unsigned argc, Value *vp)
else
s = "object";
JSAtom *str = Atomize(cx, s, strlen(s), InternAtom, NormalEncoding);
JSAtom *str = Atomize(cx, s, strlen(s), InternAtom);
if (!str)
return false;
args.rval().setString(str);

Просмотреть файл

@ -1039,7 +1039,7 @@ ProcessFile(JSContext *cx, JSObject *obj, const char *filename, FILE *file,
}
bufp += strlen(bufp);
lineno++;
} while (!JS_BufferIsCompilableUnit(cx, false, obj, buffer, strlen(buffer)));
} while (!JS_BufferIsCompilableUnit(cx, obj, buffer, strlen(buffer)));
DoBeginRequest(cx);
/* Clear any pending exception from previous failed compiles. */