Bug 657013 - Remove the old JSON parser. r=njn

--HG--
extra : rebase_source : 5c11e9179d2291d498667c17c05ff7e5f8ace3f2
This commit is contained in:
Jeff Walden 2011-05-13 14:27:07 -07:00
parent ac8938a32d
commit 4cf43e2ca4
8 changed files with 34 additions and 741 deletions

View File

@ -1182,20 +1182,7 @@ EvalKernel(JSContext *cx, const CallArgs &call, EvalType evalType, StackFrame *c
* will be lost.
*/
if (length > 2 && chars[0] == '(' && chars[length - 1] == ')') {
#if USE_OLD_AND_BUSTED_JSON_PARSER
Value tmp;
JSONParser *jp = js_BeginJSONParse(cx, &tmp, /* suppressErrors = */true);
if (jp != NULL) {
/* Run JSON-parser on string inside ( and ). */
bool ok = js_ConsumeJSONText(cx, jp, chars + 1, length - 2);
ok &= js_FinishJSONParse(cx, jp, NullValue());
if (ok) {
call.rval() = tmp;
return true;
}
#else
JSONSourceParser parser(cx, chars + 1, length - 2, JSONSourceParser::StrictJSON,
JSONSourceParser::NoError);
JSONParser parser(cx, chars + 1, length - 2, JSONParser::StrictJSON, JSONParser::NoError);
Value tmp;
if (!parser.parse(&tmp))
return false;
@ -1203,7 +1190,6 @@ EvalKernel(JSContext *cx, const CallArgs &call, EvalType evalType, StackFrame *c
call.rval() = tmp;
return true;
}
#endif
}
/*

View File

@ -72,35 +72,6 @@
using namespace js;
using namespace js::gc;
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable:4351)
#endif
struct JSONParser
{
JSONParser(JSContext *cx)
: hexChar(), numHex(), statep(), stateStack(), rootVal(), objectStack(),
objectKey(cx), buffer(cx), suppressErrors(false)
{}
/* Used while handling \uNNNN in strings */
jschar hexChar;
uint8 numHex;
JSONParserState *statep;
JSONParserState stateStack[JSON_MAX_DEPTH];
Value *rootVal;
JSObject *objectStack;
js::Vector<jschar, 8> objectKey;
js::Vector<jschar, 8> buffer;
bool suppressErrors;
};
#ifdef _MSC_VER
#pragma warning(pop)
#endif
Class js_JSONClass = {
js_JSON_str,
JSCLASS_HAS_CACHED_PROTO(JSProto_JSON),
@ -796,18 +767,6 @@ js_Stringify(JSContext *cx, Value *vp, JSObject *replacer, Value space, StringBu
return Str(cx, *vp, &scx);
}
// helper to determine whether a character could be part of a number
static JSBool IsNumChar(jschar c)
{
return ((c <= '9' && c >= '0') || c == '.' || c == '-' || c == '+' || c == 'e' || c == 'E');
}
static JSBool HandleDataString(JSContext *cx, JSONParser *jp);
static JSBool HandleDataKeyString(JSContext *cx, JSONParser *jp);
static JSBool HandleDataNumber(JSContext *cx, JSONParser *jp);
static JSBool HandleDataKeyword(JSContext *cx, JSONParser *jp);
static JSBool PopState(JSContext *cx, JSONParser *jp);
/* ES5 15.12.2 Walk. */
static bool
Walk(JSContext *cx, JSObject *holder, jsid name, const Value &reviver, Value *vp)
@ -910,14 +869,6 @@ Walk(JSContext *cx, JSObject *holder, jsid name, const Value &reviver, Value *vp
return true;
}
static JSBool
JSONParseError(JSONParser *jp, JSContext *cx)
{
if (!jp->suppressErrors)
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE, "syntax error");
return JS_FALSE;
}
static bool
Revive(JSContext *cx, const Value &reviver, Value *vp)
{
@ -935,96 +886,15 @@ Revive(JSContext *cx, const Value &reviver, Value *vp)
return Walk(cx, obj, ATOM_TO_JSID(cx->runtime->atomState.emptyAtom), reviver, vp);
}
JSONParser *
js_BeginJSONParse(JSContext *cx, Value *rootVal, bool suppressErrors /*= false*/)
{
if (!cx)
return NULL;
JSObject *arr = NewDenseEmptyArray(cx);
if (!arr)
return NULL;
JSONParser *jp = cx->new_<JSONParser>(cx);
if (!jp)
return NULL;
jp->objectStack = arr;
if (!JS_AddNamedObjectRoot(cx, &jp->objectStack, "JSON parse stack"))
goto bad;
jp->statep = jp->stateStack;
*jp->statep = JSON_PARSE_STATE_INIT;
jp->rootVal = rootVal;
jp->suppressErrors = suppressErrors;
return jp;
bad:
js_FinishJSONParse(cx, jp, NullValue());
return NULL;
}
bool
js_FinishJSONParse(JSContext *cx, JSONParser *jp, const Value &reviver)
{
if (!jp)
return true;
JSBool early_ok = JS_TRUE;
// Check for unprocessed primitives at the root. This doesn't happen for
// strings because a closing quote triggers value processing.
if ((jp->statep - jp->stateStack) == 1) {
if (*jp->statep == JSON_PARSE_STATE_KEYWORD) {
early_ok = HandleDataKeyword(cx, jp);
if (early_ok)
PopState(cx, jp);
} else if (*jp->statep == JSON_PARSE_STATE_NUMBER) {
early_ok = HandleDataNumber(cx, jp);
if (early_ok)
PopState(cx, jp);
}
}
// This internal API is infallible, in spite of its JSBool return type.
js_RemoveRoot(cx->runtime, &jp->objectStack);
bool ok = *jp->statep == JSON_PARSE_STATE_FINISHED;
Value *vp = jp->rootVal;
if (!early_ok) {
ok = false;
} else if (!ok) {
JSONParseError(jp, cx);
} else if (js_IsCallable(reviver)) {
ok = Revive(cx, reviver, vp);
}
cx->delete_(jp);
return ok;
}
namespace js {
JSBool
ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, const Value &reviver,
Value *vp, DecodingMode decodingMode /* = STRICT */)
{
#if USE_OLD_AND_BUSTED_JSON_PARSER
JSONParser *jp = js_BeginJSONParse(cx, vp);
if (!jp)
return false;
JSBool ok = js_ConsumeJSONText(cx, jp, chars, length, decodingMode);
ok &= !!js_FinishJSONParse(cx, jp, reviver);
return ok;
#else
/* 15.12.2 steps 2-3. */
JSONSourceParser parser(cx, chars, length,
decodingMode == STRICT
? JSONSourceParser::StrictJSON
: JSONSourceParser::LegacyJSON);
JSONParser parser(cx, chars, length,
decodingMode == STRICT ? JSONParser::StrictJSON : JSONParser::LegacyJSON);
if (!parser.parse(vp))
return false;
@ -1032,494 +902,10 @@ ParseJSONWithReviver(JSContext *cx, const jschar *chars, size_t length, const Va
if (js_IsCallable(reviver))
return Revive(cx, reviver, vp);
return true;
#endif
}
} /* namespace js */
static JSBool
PushState(JSContext *cx, JSONParser *jp, JSONParserState state)
{
if (*jp->statep == JSON_PARSE_STATE_FINISHED) {
// extra input
return JSONParseError(jp, cx);
}
jp->statep++;
if ((uint32)(jp->statep - jp->stateStack) >= JS_ARRAY_LENGTH(jp->stateStack)) {
// too deep
return JSONParseError(jp, cx);
}
*jp->statep = state;
return JS_TRUE;
}
static JSBool
PopState(JSContext *cx, JSONParser *jp)
{
jp->statep--;
if (jp->statep < jp->stateStack) {
jp->statep = jp->stateStack;
return JSONParseError(jp, cx);
}
if (*jp->statep == JSON_PARSE_STATE_INIT)
*jp->statep = JSON_PARSE_STATE_FINISHED;
return JS_TRUE;
}
static JSBool
PushValue(JSContext *cx, JSONParser *jp, JSObject *parent, const Value &value)
{
JSBool ok;
if (parent->isArray()) {
jsuint len;
ok = js_GetLengthProperty(cx, parent, &len);
if (ok) {
jsid index;
if (!IndexToId(cx, len, &index))
return JS_FALSE;
ok = parent->defineProperty(cx, index, value, NULL, NULL, JSPROP_ENUMERATE);
}
} else {
ok = JS_DefineUCProperty(cx, parent, jp->objectKey.begin(),
jp->objectKey.length(), Jsvalify(value),
NULL, NULL, JSPROP_ENUMERATE);
jp->objectKey.clear();
}
return ok;
}
static JSBool
PushObject(JSContext *cx, JSONParser *jp, JSObject *obj)
{
jsuint len;
if (!js_GetLengthProperty(cx, jp->objectStack, &len))
return JS_FALSE;
if (len >= JSON_MAX_DEPTH)
return JSONParseError(jp, cx);
AutoObjectRooter tvr(cx, obj);
Value v = ObjectOrNullValue(obj);
// Check if this is the root object
if (len == 0) {
*jp->rootVal = v;
// This property must be enumerable to keep the array dense
if (!jp->objectStack->defineProperty(cx, INT_TO_JSID(0), *jp->rootVal,
NULL, NULL, JSPROP_ENUMERATE)) {
return JS_FALSE;
}
return JS_TRUE;
}
Value p;
if (!jp->objectStack->getProperty(cx, INT_TO_JSID(len - 1), &p))
return JS_FALSE;
JSObject *parent = &p.toObject();
if (!PushValue(cx, jp, parent, v))
return JS_FALSE;
// This property must be enumerable to keep the array dense
if (!jp->objectStack->defineProperty(cx, INT_TO_JSID(len), v,
NULL, NULL, JSPROP_ENUMERATE)) {
return JS_FALSE;
}
return JS_TRUE;
}
static JSBool
OpenObject(JSContext *cx, JSONParser *jp)
{
JSObject *obj = NewBuiltinClassInstance(cx, &js_ObjectClass);
if (!obj)
return JS_FALSE;
return PushObject(cx, jp, obj);
}
static JSBool
OpenArray(JSContext *cx, JSONParser *jp)
{
// Add an array to an existing array or object
JSObject *arr = NewDenseEmptyArray(cx);
if (!arr)
return JS_FALSE;
return PushObject(cx, jp, arr);
}
static JSBool
CloseObject(JSContext *cx, JSONParser *jp)
{
jsuint len;
if (!js_GetLengthProperty(cx, jp->objectStack, &len))
return JS_FALSE;
if (!js_SetLengthProperty(cx, jp->objectStack, len - 1))
return JS_FALSE;
return JS_TRUE;
}
static JSBool
CloseArray(JSContext *cx, JSONParser *jp)
{
return CloseObject(cx, jp);
}
static JSBool
PushPrimitive(JSContext *cx, JSONParser *jp, const Value &value)
{
AutoValueRooter tvr(cx, value);
jsuint len;
if (!js_GetLengthProperty(cx, jp->objectStack, &len))
return JS_FALSE;
if (len > 0) {
Value o;
if (!jp->objectStack->getProperty(cx, INT_TO_JSID(len - 1), &o))
return JS_FALSE;
return PushValue(cx, jp, &o.toObject(), value);
}
// root value must be primitive
*jp->rootVal = value;
return JS_TRUE;
}
static JSBool
HandleNumber(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
{
const jschar *ep;
double val;
if (!js_strtod(cx, buf, buf + len, &ep, &val))
return JS_FALSE;
if (ep != buf + len) {
// bad number input
return JSONParseError(jp, cx);
}
return PushPrimitive(cx, jp, NumberValue(val));
}
static JSBool
HandleString(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
{
JSString *str = js_NewStringCopyN(cx, buf, len);
if (!str)
return JS_FALSE;
return PushPrimitive(cx, jp, StringValue(str));
}
static JSBool
HandleKeyword(JSContext *cx, JSONParser *jp, const jschar *buf, uint32 len)
{
const KeywordInfo *ki = FindKeyword(buf, len);
if (!ki || ki->tokentype != TOK_PRIMARY) {
// bad keyword
return JSONParseError(jp, cx);
}
Value keyword;
if (buf[0] == 'n') {
keyword.setNull();
} else if (buf[0] == 't') {
keyword.setBoolean(true);
} else if (buf[0] == 'f') {
keyword.setBoolean(false);
} else {
return JSONParseError(jp, cx);
}
return PushPrimitive(cx, jp, keyword);
}
static JSBool
HandleDataString(JSContext *cx, JSONParser *jp)
{
JSBool ok = HandleString(cx, jp, jp->buffer.begin(), jp->buffer.length());
if (ok)
jp->buffer.clear();
return ok;
}
static JSBool
HandleDataKeyString(JSContext *cx, JSONParser *jp)
{
JSBool ok = jp->objectKey.append(jp->buffer.begin(), jp->buffer.end());
if (ok)
jp->buffer.clear();
return ok;
}
static JSBool
HandleDataNumber(JSContext *cx, JSONParser *jp)
{
JSBool ok = HandleNumber(cx, jp, jp->buffer.begin(), jp->buffer.length());
if (ok)
jp->buffer.clear();
return ok;
}
static JSBool
HandleDataKeyword(JSContext *cx, JSONParser *jp)
{
JSBool ok = HandleKeyword(cx, jp, jp->buffer.begin(), jp->buffer.length());
if (ok)
jp->buffer.clear();
return ok;
}
JSBool
js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len,
DecodingMode decodingMode)
{
CHECK_REQUEST(cx);
if (*jp->statep == JSON_PARSE_STATE_INIT) {
PushState(cx, jp, JSON_PARSE_STATE_VALUE);
}
for (uint32 i = 0; i < len; i++) {
jschar c = data[i];
switch (*jp->statep) {
case JSON_PARSE_STATE_ARRAY_INITIAL_VALUE:
if (c == ']') {
if (!PopState(cx, jp))
return JS_FALSE;
JS_ASSERT(*jp->statep == JSON_PARSE_STATE_ARRAY_AFTER_ELEMENT);
if (!CloseArray(cx, jp) || !PopState(cx, jp))
return JS_FALSE;
break;
}
// fall through if non-empty array or whitespace
case JSON_PARSE_STATE_VALUE:
if (c == '"') {
*jp->statep = JSON_PARSE_STATE_STRING;
break;
}
if (IsNumChar(c)) {
*jp->statep = JSON_PARSE_STATE_NUMBER;
if (!jp->buffer.append(c))
return JS_FALSE;
break;
}
if (JS7_ISLET(c)) {
*jp->statep = JSON_PARSE_STATE_KEYWORD;
if (!jp->buffer.append(c))
return JS_FALSE;
break;
}
if (c == '{') {
*jp->statep = JSON_PARSE_STATE_OBJECT_AFTER_PAIR;
if (!OpenObject(cx, jp) || !PushState(cx, jp, JSON_PARSE_STATE_OBJECT_INITIAL_PAIR))
return JS_FALSE;
} else if (c == '[') {
*jp->statep = JSON_PARSE_STATE_ARRAY_AFTER_ELEMENT;
if (!OpenArray(cx, jp) || !PushState(cx, jp, JSON_PARSE_STATE_ARRAY_INITIAL_VALUE))
return JS_FALSE;
} else if (JS_ISXMLSPACE(c)) {
// nothing to do
} else if (decodingMode == LEGACY && c == ']') {
if (!PopState(cx, jp))
return JS_FALSE;
JS_ASSERT(*jp->statep == JSON_PARSE_STATE_ARRAY_AFTER_ELEMENT);
if (!CloseArray(cx, jp) || !PopState(cx, jp))
return JS_FALSE;
} else {
return JSONParseError(jp, cx);
}
break;
case JSON_PARSE_STATE_ARRAY_AFTER_ELEMENT:
if (c == ',') {
if (!PushState(cx, jp, JSON_PARSE_STATE_VALUE))
return JS_FALSE;
} else if (c == ']') {
if (!CloseArray(cx, jp) || !PopState(cx, jp))
return JS_FALSE;
} else if (!JS_ISXMLSPACE(c)) {
return JSONParseError(jp, cx);
}
break;
case JSON_PARSE_STATE_OBJECT_AFTER_PAIR:
if (c == ',') {
if (!PushState(cx, jp, JSON_PARSE_STATE_OBJECT_PAIR))
return JS_FALSE;
} else if (c == '}') {
if (!CloseObject(cx, jp) || !PopState(cx, jp))
return JS_FALSE;
} else if (!JS_ISXMLSPACE(c)) {
return JSONParseError(jp, cx);
}
break;
case JSON_PARSE_STATE_OBJECT_INITIAL_PAIR:
if (c == '}') {
if (!PopState(cx, jp))
return JS_FALSE;
JS_ASSERT(*jp->statep == JSON_PARSE_STATE_OBJECT_AFTER_PAIR);
if (!CloseObject(cx, jp) || !PopState(cx, jp))
return JS_FALSE;
break;
}
// fall through if non-empty object or whitespace
case JSON_PARSE_STATE_OBJECT_PAIR:
if (c == '"') {
// we want to be waiting for a : when the string has been read
*jp->statep = JSON_PARSE_STATE_OBJECT_IN_PAIR;
if (!PushState(cx, jp, JSON_PARSE_STATE_STRING))
return JS_FALSE;
} else if (JS_ISXMLSPACE(c)) {
// nothing to do
} else if (decodingMode == LEGACY && c == '}') {
if (!PopState(cx, jp))
return JS_FALSE;
JS_ASSERT(*jp->statep == JSON_PARSE_STATE_OBJECT_AFTER_PAIR);
if (!CloseObject(cx, jp) || !PopState(cx, jp))
return JS_FALSE;
} else {
return JSONParseError(jp, cx);
}
break;
case JSON_PARSE_STATE_OBJECT_IN_PAIR:
if (c == ':') {
*jp->statep = JSON_PARSE_STATE_VALUE;
} else if (!JS_ISXMLSPACE(c)) {
return JSONParseError(jp, cx);
}
break;
case JSON_PARSE_STATE_STRING:
if (c == '"') {
if (!PopState(cx, jp))
return JS_FALSE;
if (*jp->statep == JSON_PARSE_STATE_OBJECT_IN_PAIR) {
if (!HandleDataKeyString(cx, jp))
return JS_FALSE;
} else {
if (!HandleDataString(cx, jp))
return JS_FALSE;
}
} else if (c == '\\') {
*jp->statep = JSON_PARSE_STATE_STRING_ESCAPE;
} else if (c <= 0x1F) {
// The JSON lexical grammer does not allow a JSONStringCharacter to be
// any of the Unicode characters U+0000 thru U+001F (control characters).
return JSONParseError(jp, cx);
} else {
if (!jp->buffer.append(c))
return JS_FALSE;
}
break;
case JSON_PARSE_STATE_STRING_ESCAPE:
switch (c) {
case '"':
case '\\':
case '/':
break;
case 'b' : c = '\b'; break;
case 'f' : c = '\f'; break;
case 'n' : c = '\n'; break;
case 'r' : c = '\r'; break;
case 't' : c = '\t'; break;
default :
if (c == 'u') {
jp->numHex = 0;
jp->hexChar = 0;
*jp->statep = JSON_PARSE_STATE_STRING_HEX;
continue;
} else {
return JSONParseError(jp, cx);
}
}
if (!jp->buffer.append(c))
return JS_FALSE;
*jp->statep = JSON_PARSE_STATE_STRING;
break;
case JSON_PARSE_STATE_STRING_HEX:
if (('0' <= c) && (c <= '9')) {
jp->hexChar = (jp->hexChar << 4) | (c - '0');
} else if (('a' <= c) && (c <= 'f')) {
jp->hexChar = (jp->hexChar << 4) | (c - 'a' + 0x0a);
} else if (('A' <= c) && (c <= 'F')) {
jp->hexChar = (jp->hexChar << 4) | (c - 'A' + 0x0a);
} else {
return JSONParseError(jp, cx);
}
if (++(jp->numHex) == 4) {
if (!jp->buffer.append(jp->hexChar))
return JS_FALSE;
jp->hexChar = 0;
jp->numHex = 0;
*jp->statep = JSON_PARSE_STATE_STRING;
}
break;
case JSON_PARSE_STATE_KEYWORD:
if (JS7_ISLET(c)) {
if (!jp->buffer.append(c))
return JS_FALSE;
} else {
// this character isn't part of the keyword, process it again
i--;
if (!PopState(cx, jp))
return JS_FALSE;
if (!HandleDataKeyword(cx, jp))
return JS_FALSE;
}
break;
case JSON_PARSE_STATE_NUMBER:
if (IsNumChar(c)) {
if (!jp->buffer.append(c))
return JS_FALSE;
} else {
// this character isn't part of the number, process it again
i--;
if (!PopState(cx, jp))
return JS_FALSE;
if (!HandleDataNumber(cx, jp))
return JS_FALSE;
}
break;
case JSON_PARSE_STATE_FINISHED:
if (!JS_ISXMLSPACE(c)) {
// extra input
return JSONParseError(jp, cx);
}
break;
default:
JS_NOT_REACHED("Invalid JSON parser state");
}
}
return JS_TRUE;
}
#if JS_HAS_TOSOURCE
static JSBool
json_toSource(JSContext *cx, uintN argc, Value *vp)

View File

@ -57,59 +57,6 @@ js_Stringify(JSContext *cx, js::Value *vp, JSObject *replacer, js::Value space,
extern JSBool js_TryJSON(JSContext *cx, js::Value *vp);
/* JSON parsing states; most permit leading whitespace. */
enum JSONParserState {
/* Start of string. */
JSON_PARSE_STATE_INIT,
/* JSON fully processed, expecting only trailing whitespace. */
JSON_PARSE_STATE_FINISHED,
/* Start of JSON value. */
JSON_PARSE_STATE_VALUE,
/* Start of first key/value pair in object, or at }. */
JSON_PARSE_STATE_OBJECT_INITIAL_PAIR,
/* Start of subsequent key/value pair in object, after delimiting comma. */
JSON_PARSE_STATE_OBJECT_PAIR,
/* At : in key/value pair in object. */
JSON_PARSE_STATE_OBJECT_IN_PAIR,
/* Immediately after key/value pair in object: at , or }. */
JSON_PARSE_STATE_OBJECT_AFTER_PAIR,
/* Start of first element of array or at ]. */
JSON_PARSE_STATE_ARRAY_INITIAL_VALUE,
/* Immediately after element in array: at , or ]. */
JSON_PARSE_STATE_ARRAY_AFTER_ELEMENT,
/* The following states allow no leading whitespace. */
/* Within string literal. */
JSON_PARSE_STATE_STRING,
/* At first character after \ in string literal. */
JSON_PARSE_STATE_STRING_ESCAPE,
/* Within numbers in \uXXXX in string literal. */
JSON_PARSE_STATE_STRING_HEX,
/* Within numeric literal. */
JSON_PARSE_STATE_NUMBER,
/* Handling keywords (only null/true/false pass validity post-check). */
JSON_PARSE_STATE_KEYWORD
};
struct JSONParser;
extern JSONParser *
js_BeginJSONParse(JSContext *cx, js::Value *rootVal, bool suppressErrors = false);
/* Aargh, Windows. */
#ifdef STRICT
#undef STRICT
@ -127,13 +74,6 @@ js_BeginJSONParse(JSContext *cx, js::Value *rootVal, bool suppressErrors = false
*/
enum DecodingMode { STRICT, LEGACY };
extern JS_FRIEND_API(JSBool)
js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len,
DecodingMode decodingMode = STRICT);
extern bool
js_FinishJSONParse(JSContext *cx, JSONParser *jp, const js::Value &reviver);
namespace js {
extern JS_FRIEND_API(JSBool)

View File

@ -48,21 +48,21 @@
using namespace js;
void
JSONSourceParser::error(const char *msg)
JSONParser::error(const char *msg)
{
if (errorHandling == RaiseError)
JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, JSMSG_JSON_BAD_PARSE, msg);
}
bool
JSONSourceParser::errorReturn()
JSONParser::errorReturn()
{
return errorHandling == NoError;
}
template<JSONSourceParser::StringType ST>
JSONSourceParser::Token
JSONSourceParser::readString()
template<JSONParser::StringType ST>
JSONParser::Token
JSONParser::readString()
{
JS_ASSERT(current < end);
JS_ASSERT(*current == '"');
@ -86,7 +86,7 @@ JSONSourceParser::readString()
if (*current == '"') {
size_t length = current - start;
current++;
JSFlatString *str = (ST == JSONSourceParser::PropertyName)
JSFlatString *str = (ST == JSONParser::PropertyName)
? js_AtomizeChars(cx, start, length)
: js_NewStringCopyN(cx, start, length);
if (!str)
@ -118,7 +118,7 @@ JSONSourceParser::readString()
jschar c = *current++;
if (c == '"') {
JSFlatString *str = (ST == JSONSourceParser::PropertyName)
JSFlatString *str = (ST == JSONParser::PropertyName)
? buffer.finishAtom()
: buffer.finishString();
if (!str)
@ -181,8 +181,8 @@ JSONSourceParser::readString()
return token(Error);
}
JSONSourceParser::Token
JSONSourceParser::readNumber()
JSONParser::Token
JSONParser::readNumber()
{
JS_ASSERT(current < end);
JS_ASSERT(JS7_ISDEC(*current) || *current == '-');
@ -276,8 +276,8 @@ IsJSONWhitespace(jschar c)
return c == '\t' || c == '\r' || c == '\n' || c == ' ';
}
JSONSourceParser::Token
JSONSourceParser::advance()
JSONParser::Token
JSONParser::advance()
{
while (current < end && IsJSONWhitespace(*current))
current++;
@ -357,8 +357,8 @@ JSONSourceParser::advance()
}
}
JSONSourceParser::Token
JSONSourceParser::advanceAfterObjectOpen()
JSONParser::Token
JSONParser::advanceAfterObjectOpen()
{
JS_ASSERT(current[-1] == '{');
@ -408,8 +408,8 @@ AssertPastValue(const jschar *current)
JS7_ISDEC(current[-1]));
}
JSONSourceParser::Token
JSONSourceParser::advanceAfterArrayElement()
JSONParser::Token
JSONParser::advanceAfterArrayElement()
{
AssertPastValue(current);
@ -434,8 +434,8 @@ JSONSourceParser::advanceAfterArrayElement()
return token(Error);
}
JSONSourceParser::Token
JSONSourceParser::advancePropertyName()
JSONParser::Token
JSONParser::advancePropertyName()
{
JS_ASSERT(current[-1] == ',');
@ -466,8 +466,8 @@ JSONSourceParser::advancePropertyName()
return token(Error);
}
JSONSourceParser::Token
JSONSourceParser::advancePropertyColon()
JSONParser::Token
JSONParser::advancePropertyColon()
{
JS_ASSERT(current[-1] == '"');
@ -487,8 +487,8 @@ JSONSourceParser::advancePropertyColon()
return token(Error);
}
JSONSourceParser::Token
JSONSourceParser::advanceAfterProperty()
JSONParser::Token
JSONParser::advanceAfterProperty()
{
AssertPastValue(current);
@ -514,13 +514,13 @@ JSONSourceParser::advanceAfterProperty()
}
/*
* This enum is local to JSONSourceParser::parse, below, but ISO C++98 doesn't
* allow templates to depend on local types. Boo-urns!
* This enum is local to JSONParser::parse, below, but ISO C++98 doesn't allow
* templates to depend on local types. Boo-urns!
*/
enum ParserState { FinishArrayElement, FinishObjectMember, JSONValue };
bool
JSONSourceParser::parse(Value *vp)
JSONParser::parse(Value *vp)
{
Vector<ParserState> stateStack(cx);
AutoValueVector valueStack(cx);

View File

@ -47,12 +47,9 @@
#include "jsvalue.h"
/*
* This class should be JSONParser, but the old JSON parser uses that name, so
* until we remove the old parser the class name will be overlong.
*
* NB: This class must only be used on the stack as it contains a js::Value.
*/
class JSONSourceParser
class JSONParser
{
public:
enum ErrorHandling { RaiseError, NoError };
@ -88,9 +85,9 @@ class JSONSourceParser
* Description of this syntax is deliberately omitted: new code should only
* use strict JSON parsing.
*/
JSONSourceParser(JSContext *cx, const jschar *data, size_t length,
ParsingMode parsingMode = StrictJSON,
ErrorHandling errorHandling = RaiseError)
JSONParser(JSContext *cx, const jschar *data, size_t length,
ParsingMode parsingMode = StrictJSON,
ErrorHandling errorHandling = RaiseError)
: cx(cx),
current(data, data, length),
end(data + length, data, length),

View File

@ -161,7 +161,6 @@ typedef struct JSXDRState JSXDRState;
typedef struct JSExceptionState JSExceptionState;
typedef struct JSLocaleCallbacks JSLocaleCallbacks;
typedef struct JSSecurityCallbacks JSSecurityCallbacks;
typedef struct JSONParser JSONParser;
typedef struct JSCompartment JSCompartment;
typedef struct JSCrossCompartmentCall JSCrossCompartmentCall;
typedef struct JSStructuredCloneWriter JSStructuredCloneWriter;

View File

@ -219,13 +219,3 @@
* support likely to be made opt-in at some future time.
*/
#define OLD_GETTER_SETTER_METHODS 1
/*
* Embedders: don't change this: it's a bake-until-ready hack only!
*
* NB: Changing this value requires adjusting the pass/fail state of a handful
* of tests in ecma_5/JSON/ which the old parser implemented incorrectly.
* Also make sure to rename JSONSourceParser to just JSONParser when the
* old parser is removed completely.
*/
#define USE_OLD_AND_BUSTED_JSON_PARSER 0

View File

@ -4,11 +4,14 @@ script small-codepoints.js
script parse.js
script parse-arguments.js
script parse-crockford-01.js
script parse-number-syntax.js
script parse-octal-syntax-error.js
script parse-primitives.js
script parse-reviver.js
script parse-reviver-array-delete.js
script parse-syntax-errors-01.js
script parse-syntax-errors-02.js
script parse-syntax-errors-03.js
script stringify.js
script stringify-boxed-primitives.js
script stringify-call-replacer-once.js
@ -28,11 +31,3 @@ script stringify-replacer-with-array-indexes.js
script stringify-special-escapes.js
script stringify-toJSON-arguments.js
script trailing-comma.js
# These tests pass with the new parser but fail with the old one. If you're
# changing which parser is used, you'll need to change these test declarations
# accordingly. (And if you're removing the old parser, re-alphabetize these
# tests into the list above.)
script parse-number-syntax.js
script parse-octal-syntax-error.js
script parse-syntax-errors-03.js