mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 794323 - Remove the legacy JSON parsing mode, now that Firefox session store code doesn't need it. r=luke for the JS bits, r=jlebar for the DOM bits, r=mak77 for the browser/toolkit bits
--HG-- extra : rebase_source : b7a422eb52fe8e435143dfcc435d56e4886859e6
This commit is contained in:
parent
2286d2480d
commit
bb39a16a0e
@ -1 +1 @@
|
||||
{"title":"","id":1,"dateAdded":1233157910552624,"lastModified":1233157955206833,"type":"text/x-moz-place-container","root":"placesRoot","children":[{"title":"Bookmarks Menu","id":2,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157993171424,"type":"text/x-moz-place-container","root":"bookmarksMenuFolder","children":[{"title":"examplejson","id":27,"parent":2,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":1,"title":"Bookmarks Toolbar","id":3,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157972101126,"annos":[{"name":"bookmarkProperties/description","flags":0,"expires":4,"mimeType":null,"type":3,"value":"Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar"}],"type":"text/x-moz-place-container","root":"toolbarFolder","children":[{"title":"examplejson","id":26,"parent":3,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":2,"title":"Tags","id":4,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157910582667,"type":"text/x-moz-place-container","root":"tagsFolder","children":[]},{"index":3,"title":"Unsorted Bookmarks","id":5,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157911033315,"type":"text/x-moz-place-container","root":"unfiledBookmarksFolder","children":[]},]}
|
||||
{"title":"","id":1,"dateAdded":1233157910552624,"lastModified":1233157955206833,"type":"text/x-moz-place-container","root":"placesRoot","children":[{"title":"Bookmarks Menu","id":2,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157993171424,"type":"text/x-moz-place-container","root":"bookmarksMenuFolder","children":[{"title":"examplejson","id":27,"parent":2,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":1,"title":"Bookmarks Toolbar","id":3,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157972101126,"annos":[{"name":"bookmarkProperties/description","flags":0,"expires":4,"mimeType":null,"type":3,"value":"Add bookmarks to this folder to see them displayed on the Bookmarks Toolbar"}],"type":"text/x-moz-place-container","root":"toolbarFolder","children":[{"title":"examplejson","id":26,"parent":3,"dateAdded":1233157972101126,"lastModified":1233157984999673,"type":"text/x-moz-place","uri":"http://example.com/"}]},{"index":2,"title":"Tags","id":4,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157910582667,"type":"text/x-moz-place-container","root":"tagsFolder","children":[]},{"index":3,"title":"Unsorted Bookmarks","id":5,"parent":1,"dateAdded":1233157910552624,"lastModified":1233157911033315,"type":"text/x-moz-place-container","root":"unfiledBookmarksFolder","children":[]}]}
|
||||
|
@ -13,9 +13,9 @@ interface nsIScriptGlobalObject;
|
||||
[ptr] native JSContext(JSContext);
|
||||
|
||||
/**
|
||||
* Encode and decode JSON text.
|
||||
* Don't use this! Use JSON.parse and JSON.stringify directly.
|
||||
*/
|
||||
[scriptable, uuid(43845d58-1054-47fb-8be3-970b3f7bd7ea)]
|
||||
[scriptable, uuid(083aebb0-7790-43b2-ae81-9e404e626236)]
|
||||
interface nsIJSON : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -54,29 +54,4 @@ interface nsIJSON : nsISupports
|
||||
|
||||
// Make sure you GCroot the result of this function before using it.
|
||||
[noscript] jsval decodeToJSVal(in AString str, in JSContext cx);
|
||||
|
||||
|
||||
/*
|
||||
* Decode a JSON string, but also accept some strings in non-JSON format, as
|
||||
* the decoding methods here did previously before tightening.
|
||||
*
|
||||
* This method is provided only as a temporary transition path for users of
|
||||
* the old code who depended on the ability to decode leniently; new users
|
||||
* should use JSON.parse.
|
||||
*
|
||||
* This method must only be called from script.
|
||||
*
|
||||
* @param str the string to parse
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
jsval legacyDecode(in AString str);
|
||||
|
||||
/* Identical to legacyDecode, but decode the contents of stream. */
|
||||
[implicit_jscontext]
|
||||
jsval legacyDecodeFromStream(in nsIInputStream stream,
|
||||
in long contentLength);
|
||||
|
||||
/* Identical to legacyDecode, but decode into a jsval. */
|
||||
// Make sure you GCroot the result of this function before using it.
|
||||
[noscript] jsval legacyDecodeToJSVal(in AString str, in JSContext cx);
|
||||
};
|
||||
|
@ -401,8 +401,7 @@ nsJSON::DecodeInternal(JSContext* cx,
|
||||
nsIInputStream *aStream,
|
||||
int32_t aContentLength,
|
||||
bool aNeedsConverter,
|
||||
JS::Value* aRetval,
|
||||
DecodingMode mode /* = STRICT */)
|
||||
JS::Value* aRetval)
|
||||
{
|
||||
// Consume the stream
|
||||
nsCOMPtr<nsIChannel> jsonChannel;
|
||||
@ -419,7 +418,7 @@ nsJSON::DecodeInternal(JSContext* cx,
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsRefPtr<nsJSONListener> jsonListener =
|
||||
new nsJSONListener(cx, aRetval, aNeedsConverter, mode);
|
||||
new nsJSONListener(cx, aRetval, aNeedsConverter);
|
||||
|
||||
//XXX this stream pattern should be consolidated in netwerk
|
||||
rv = jsonListener->OnStartRequest(jsonChannel, nullptr);
|
||||
@ -468,44 +467,6 @@ nsJSON::DecodeInternal(JSContext* cx,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::LegacyDecode(const nsAString& json, JSContext* cx, JS::Value* aRetval)
|
||||
{
|
||||
const PRUnichar *data;
|
||||
uint32_t len = NS_StringGetData(json, &data);
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
|
||||
(const char*) data,
|
||||
len * sizeof(PRUnichar),
|
||||
NS_ASSIGNMENT_DEPEND);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return DecodeInternal(cx, stream, len, false, aRetval, LEGACY);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::LegacyDecodeFromStream(nsIInputStream *aStream, int32_t aContentLength,
|
||||
JSContext* cx, JS::Value* aRetval)
|
||||
{
|
||||
return DecodeInternal(cx, aStream, aContentLength, true, aRetval, LEGACY);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::LegacyDecodeToJSVal(const nsAString &str, JSContext *cx, JS::Value *result)
|
||||
{
|
||||
JS::RootedValue reviver(cx, JS::NullValue()), value(cx);
|
||||
|
||||
JS::StableCharPtr chars(static_cast<const jschar*>(PromiseFlatString(str).get()),
|
||||
str.Length());
|
||||
if (!js::ParseJSONWithReviver(cx, chars, str.Length(), reviver,
|
||||
&value, LEGACY)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
*result = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewJSON(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
||||
{
|
||||
@ -520,12 +481,10 @@ NS_NewJSON(nsISupports* aOuter, REFNSIID aIID, void** aResult)
|
||||
}
|
||||
|
||||
nsJSONListener::nsJSONListener(JSContext *cx, JS::Value *rootVal,
|
||||
bool needsConverter,
|
||||
DecodingMode mode /* = STRICT */)
|
||||
bool needsConverter)
|
||||
: mNeedsConverter(needsConverter),
|
||||
mCx(cx),
|
||||
mRootVal(rootVal),
|
||||
mDecodingMode(mode)
|
||||
mRootVal(rootVal)
|
||||
{
|
||||
}
|
||||
|
||||
@ -568,10 +527,9 @@ nsJSONListener::OnStopRequest(nsIRequest *aRequest, nsISupports *aContext,
|
||||
|
||||
JS::StableCharPtr chars(reinterpret_cast<const jschar*>(mBufferedChars.Elements()),
|
||||
mBufferedChars.Length());
|
||||
JSBool ok = js::ParseJSONWithReviver(mCx, chars,
|
||||
(uint32_t) mBufferedChars.Length(),
|
||||
reviver, &value,
|
||||
mDecodingMode);
|
||||
JSBool ok = JS_ParseJSONWithReviver(mCx, chars.get(),
|
||||
uint32_t(mBufferedChars.Length()),
|
||||
reviver, value.address());
|
||||
|
||||
*mRootVal = value;
|
||||
mBufferedChars.TruncateLength(0);
|
||||
|
@ -7,7 +7,6 @@
|
||||
#define nsJSON_h__
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "json.h"
|
||||
#include "nsIJSON.h"
|
||||
#include "nsString.h"
|
||||
#include "nsCOMPtr.h"
|
||||
@ -61,8 +60,7 @@ protected:
|
||||
nsIInputStream* aStream,
|
||||
int32_t aContentLength,
|
||||
bool aNeedsConverter,
|
||||
JS::Value* aRetVal,
|
||||
DecodingMode mode = STRICT);
|
||||
JS::Value* aRetVal);
|
||||
nsCOMPtr<nsIURI> mURI;
|
||||
};
|
||||
|
||||
@ -72,8 +70,7 @@ NS_NewJSON(nsISupports* aOuter, REFNSIID aIID, void** aResult);
|
||||
class nsJSONListener : public nsIStreamListener
|
||||
{
|
||||
public:
|
||||
nsJSONListener(JSContext *cx, JS::Value *rootVal, bool needsConverter,
|
||||
DecodingMode mode);
|
||||
nsJSONListener(JSContext *cx, JS::Value *rootVal, bool needsConverter);
|
||||
virtual ~nsJSONListener();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
@ -87,7 +84,6 @@ protected:
|
||||
nsCOMPtr<nsIUnicodeDecoder> mDecoder;
|
||||
nsCString mSniffBuffer;
|
||||
nsTArray<PRUnichar> mBufferedChars;
|
||||
DecodingMode mDecodingMode;
|
||||
nsresult ProcessBytes(const char* aBuffer, uint32_t aByteLength);
|
||||
nsresult ConsumeConverted(const char* aBuffer, uint32_t aByteLength);
|
||||
nsresult Consume(const PRUnichar *data, uint32_t len);
|
||||
|
@ -177,7 +177,7 @@ TryEvalJSON(JSContext *cx, JSScript *callerScript,
|
||||
if (cp == end) {
|
||||
bool isArray = (chars[0] == '[');
|
||||
JSONParser parser(cx, isArray ? chars : chars + 1U, isArray ? length : length - 2,
|
||||
JSONParser::StrictJSON, JSONParser::NoError);
|
||||
JSONParser::NoError);
|
||||
RootedValue tmp(cx);
|
||||
if (!parser.parse(&tmp))
|
||||
return EvalJSON_Failure;
|
||||
|
@ -1,7 +0,0 @@
|
||||
// |jit-test| error: InternalError
|
||||
function rec(x, self) {
|
||||
if (a = parseLegacyJSON("[1 , ]").length)
|
||||
self(x - 001 , self);
|
||||
self(NaN, self);
|
||||
}
|
||||
rec(1, rec);
|
111
js/src/json.cpp
111
js/src/json.cpp
@ -46,58 +46,6 @@ Class js::JSONClass = {
|
||||
JS_ConvertStub
|
||||
};
|
||||
|
||||
/* ES5 15.12.2. */
|
||||
JSBool
|
||||
js_json_parse(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
/* Step 1. */
|
||||
JSString *str = (argc >= 1) ? ToString<CanGC>(cx, args[0]) : cx->names().undefined;
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
JSStableString *stable = str->ensureStable(cx);
|
||||
if (!stable)
|
||||
return false;
|
||||
|
||||
JS::Anchor<JSString *> anchor(stable);
|
||||
|
||||
RootedValue reviver(cx, (argc >= 2) ? args[1] : UndefinedValue());
|
||||
|
||||
/* Steps 2-5. */
|
||||
return ParseJSONWithReviver(cx, stable->chars(), stable->length(), reviver, args.rval());
|
||||
}
|
||||
|
||||
/* ES5 15.12.3. */
|
||||
JSBool
|
||||
js_json_stringify(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
RootedObject replacer(cx, (argc >= 2 && vp[3].isObject())
|
||||
? &vp[3].toObject()
|
||||
: NULL);
|
||||
RootedValue value(cx, (argc >= 1) ? vp[2] : UndefinedValue());
|
||||
RootedValue space(cx, (argc >= 3) ? vp[4] : UndefinedValue());
|
||||
|
||||
StringBuffer sb(cx);
|
||||
if (!js_Stringify(cx, &value, replacer, space, sb))
|
||||
return false;
|
||||
|
||||
// XXX This can never happen to nsJSON.cpp, but the JSON object
|
||||
// needs to support returning undefined. So this is a little awkward
|
||||
// for the API, because we want to support streaming writers.
|
||||
if (!sb.empty()) {
|
||||
JSString *str = sb.finishString();
|
||||
if (!str)
|
||||
return false;
|
||||
vp->setString(str);
|
||||
} else {
|
||||
vp->setUndefined();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool IsQuoteSpecialCharacter(jschar c)
|
||||
{
|
||||
JS_STATIC_ASSERT('\b' < ' ');
|
||||
@ -855,13 +803,12 @@ Revive(JSContext *cx, HandleValue reviver, MutableHandleValue vp)
|
||||
return Walk(cx, obj, id, reviver, vp);
|
||||
}
|
||||
|
||||
JSBool
|
||||
bool
|
||||
js::ParseJSONWithReviver(JSContext *cx, StableCharPtr chars, size_t length, HandleValue reviver,
|
||||
MutableHandleValue vp, DecodingMode decodingMode /* = STRICT */)
|
||||
MutableHandleValue vp)
|
||||
{
|
||||
/* 15.12.2 steps 2-3. */
|
||||
JSONParser parser(cx, chars, length,
|
||||
decodingMode == STRICT ? JSONParser::StrictJSON : JSONParser::LegacyJSON);
|
||||
JSONParser parser(cx, chars, length);
|
||||
if (!parser.parse(vp))
|
||||
return false;
|
||||
|
||||
@ -880,6 +827,58 @@ json_toSource(JSContext *cx, unsigned argc, Value *vp)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ES5 15.12.2. */
|
||||
JSBool
|
||||
js_json_parse(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
/* Step 1. */
|
||||
JSString *str = (argc >= 1) ? ToString<CanGC>(cx, args[0]) : cx->names().undefined;
|
||||
if (!str)
|
||||
return false;
|
||||
|
||||
JSStableString *stable = str->ensureStable(cx);
|
||||
if (!stable)
|
||||
return false;
|
||||
|
||||
JS::Anchor<JSString *> anchor(stable);
|
||||
|
||||
RootedValue reviver(cx, (argc >= 2) ? args[1] : UndefinedValue());
|
||||
|
||||
/* Steps 2-5. */
|
||||
return ParseJSONWithReviver(cx, stable->chars(), stable->length(), reviver, args.rval());
|
||||
}
|
||||
|
||||
/* ES5 15.12.3. */
|
||||
JSBool
|
||||
js_json_stringify(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
RootedObject replacer(cx, (argc >= 2 && vp[3].isObject())
|
||||
? &vp[3].toObject()
|
||||
: NULL);
|
||||
RootedValue value(cx, (argc >= 1) ? vp[2] : UndefinedValue());
|
||||
RootedValue space(cx, (argc >= 3) ? vp[4] : UndefinedValue());
|
||||
|
||||
StringBuffer sb(cx);
|
||||
if (!js_Stringify(cx, &value, replacer, space, sb))
|
||||
return false;
|
||||
|
||||
// XXX This can never happen to nsJSON.cpp, but the JSON object
|
||||
// needs to support returning undefined. So this is a little awkward
|
||||
// for the API, because we want to support streaming writers.
|
||||
if (!sb.empty()) {
|
||||
JSString *str = sb.finishString();
|
||||
if (!str)
|
||||
return false;
|
||||
vp->setString(str);
|
||||
} else {
|
||||
vp->setUndefined();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const JSFunctionSpec json_static_methods[] = {
|
||||
#if JS_HAS_TOSOURCE
|
||||
JS_FN(js_toSource_str, json_toSource, 0, 0),
|
||||
|
@ -7,42 +7,25 @@
|
||||
#ifndef json_h___
|
||||
#define json_h___
|
||||
|
||||
#include "jsprvtd.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jsapi.h"
|
||||
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/Value.h"
|
||||
#include "js/Vector.h"
|
||||
|
||||
#define JSON_MAX_DEPTH 2048
|
||||
#define JSON_PARSER_BUFSIZE 1024
|
||||
#include "vm/StringBuffer.h"
|
||||
|
||||
extern JSObject *
|
||||
js_InitJSONClass(JSContext *cx, js::HandleObject obj);
|
||||
|
||||
extern JSBool
|
||||
js_Stringify(JSContext *cx, js::MutableHandleValue vp,
|
||||
JSObject *replacer, js::Value space,
|
||||
js::StringBuffer &sb);
|
||||
|
||||
// Avoid build errors on certain platforms that define these names as constants
|
||||
#undef STRICT
|
||||
#undef LEGACY
|
||||
|
||||
/*
|
||||
* The type of JSON decoding to perform. Strict decoding is to-the-spec;
|
||||
* legacy decoding accepts a few non-JSON syntaxes historically accepted by the
|
||||
* implementation. (Full description of these deviations is deliberately
|
||||
* omitted.) New users should use strict decoding rather than legacy decoding,
|
||||
* as legacy decoding might be removed at a future time.
|
||||
*/
|
||||
enum DecodingMode { STRICT, LEGACY };
|
||||
js_Stringify(JSContext *cx, js::MutableHandleValue vp, JSObject *replacer,
|
||||
js::Value space, js::StringBuffer &sb);
|
||||
|
||||
namespace js {
|
||||
|
||||
extern JS_FRIEND_API(JSBool)
|
||||
ParseJSONWithReviver(JSContext *cx, JS::StableCharPtr chars, size_t length, HandleValue filter,
|
||||
MutableHandleValue vp, DecodingMode decodingMode = STRICT);
|
||||
extern bool
|
||||
ParseJSONWithReviver(JSContext *cx, JS::StableCharPtr chars, size_t length, HandleValue reviver,
|
||||
MutableHandleValue vp);
|
||||
|
||||
} /* namespace js */
|
||||
} // namespace js
|
||||
|
||||
#endif /* json_h___ */
|
||||
|
@ -465,19 +465,6 @@ JSONParser::advancePropertyName()
|
||||
if (*current == '"')
|
||||
return readString<PropertyName>();
|
||||
|
||||
if (parsingMode == LegacyJSON && *current == '}') {
|
||||
/*
|
||||
* Previous JSON parsing accepted trailing commas in non-empty object
|
||||
* syntax, and some users depend on this. (Specifically, Places data
|
||||
* serialization in versions of Firefox before 4.0. We can remove this
|
||||
* mode when profile upgrades from 3.6 become unsupported.) Permit
|
||||
* such trailing commas only when legacy parsing is specifically
|
||||
* requested.
|
||||
*/
|
||||
current++;
|
||||
return token(ObjectClose);
|
||||
}
|
||||
|
||||
error("expected double-quoted property name");
|
||||
return token(Error);
|
||||
}
|
||||
@ -659,13 +646,6 @@ JSONParser::parse(MutableHandleValue vp)
|
||||
}
|
||||
goto JSONValue;
|
||||
}
|
||||
if (token == ObjectClose) {
|
||||
JS_ASSERT(state == FinishObjectMember);
|
||||
JS_ASSERT(parsingMode == LegacyJSON);
|
||||
if (!finishObject(&value, stack.back().properties()))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
if (token == OOM)
|
||||
return false;
|
||||
if (token != Error)
|
||||
@ -754,24 +734,6 @@ JSONParser::parse(MutableHandleValue vp)
|
||||
}
|
||||
|
||||
case ArrayClose:
|
||||
if (parsingMode == LegacyJSON &&
|
||||
!stack.empty() &&
|
||||
stack.back().state == FinishArrayElement) {
|
||||
/*
|
||||
* Previous JSON parsing accepted trailing commas in
|
||||
* non-empty array syntax, and some users depend on this.
|
||||
* (Specifically, Places data serialization in versions of
|
||||
* Firefox prior to 4.0. We can remove this mode when
|
||||
* profile upgrades from 3.6 become unsupported.) Permit
|
||||
* such trailing commas only when specifically
|
||||
* instructed to do so.
|
||||
*/
|
||||
if (!finishArray(&value, stack.back().elements()))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
|
||||
case ObjectClose:
|
||||
case Colon:
|
||||
case Comma:
|
||||
|
@ -21,7 +21,6 @@ class JSONParser : private AutoGCRooter
|
||||
{
|
||||
public:
|
||||
enum ErrorHandling { RaiseError, NoError };
|
||||
enum ParsingMode { StrictJSON, LegacyJSON };
|
||||
|
||||
private:
|
||||
/* Data members */
|
||||
@ -32,7 +31,6 @@ class JSONParser : private AutoGCRooter
|
||||
|
||||
Value v;
|
||||
|
||||
const ParsingMode parsingMode;
|
||||
const ErrorHandling errorHandling;
|
||||
|
||||
enum Token { String, Number, True, False, Null,
|
||||
@ -113,20 +111,13 @@ class JSONParser : private AutoGCRooter
|
||||
public:
|
||||
/* Public API */
|
||||
|
||||
/*
|
||||
* Create a parser for the provided JSON data. The parser will accept
|
||||
* certain legacy, non-JSON syntax if decodingMode is LegacyJSON.
|
||||
* Description of this syntax is deliberately omitted: new code should only
|
||||
* use strict JSON parsing.
|
||||
*/
|
||||
/* Create a parser for the provided JSON data. */
|
||||
JSONParser(JSContext *cx, JS::StableCharPtr data, size_t length,
|
||||
ParsingMode parsingMode = StrictJSON,
|
||||
ErrorHandling errorHandling = RaiseError)
|
||||
: AutoGCRooter(cx, JSONPARSER),
|
||||
cx(cx),
|
||||
current(data),
|
||||
end((data + length).get(), data.get(), length),
|
||||
parsingMode(parsingMode),
|
||||
errorHandling(errorHandling),
|
||||
stack(cx),
|
||||
freeElements(cx),
|
||||
|
@ -41,7 +41,6 @@ EXPORTS += [
|
||||
'jsdhash.h',
|
||||
'jsfriendapi.h',
|
||||
'jslock.h',
|
||||
'json.h',
|
||||
'jsperf.h',
|
||||
'jsprf.h',
|
||||
'jsprototypes.h',
|
||||
|
@ -3506,28 +3506,6 @@ NewGlobal(JSContext *cx, unsigned argc, jsval *vp)
|
||||
return true;
|
||||
}
|
||||
|
||||
static JSBool
|
||||
ParseLegacyJSON(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (argc != 1 || !JSVAL_IS_STRING(args[0])) {
|
||||
JS_ReportErrorNumber(cx, my_GetErrorMessage, NULL, JSSMSG_INVALID_ARGS, "parseLegacyJSON");
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString *str = JSVAL_TO_STRING(args[0]);
|
||||
|
||||
size_t length;
|
||||
const jschar *chars = JS_GetStringCharsAndLength(cx, str, &length);
|
||||
if (!chars)
|
||||
return false;
|
||||
|
||||
RootedValue value(cx, NullValue());
|
||||
return js::ParseJSONWithReviver(cx, StableCharPtr(chars, length), length,
|
||||
value, args.rval(), LEGACY);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
EnableStackWalkingAssertion(JSContext *cx, unsigned argc, jsval *vp)
|
||||
{
|
||||
@ -3895,11 +3873,6 @@ static JSFunctionSpecWithHelp shell_functions[] = {
|
||||
" Return a new global object in a new compartment. If obj\n"
|
||||
" is given, the compartment will be in the same zone as obj."),
|
||||
|
||||
JS_FN_HELP("parseLegacyJSON", ParseLegacyJSON, 1, 0,
|
||||
"parseLegacyJSON(str)",
|
||||
" Parse str as legacy JSON, returning the result if the\n"
|
||||
" parse succeeded and throwing a SyntaxError if not."),
|
||||
|
||||
JS_FN_HELP("enableStackWalkingAssertion", EnableStackWalkingAssertion, 1, 0,
|
||||
"enableStackWalkingAssertion(enabled)",
|
||||
" Enables or disables a particularly expensive assertion in stack-walking\n"
|
||||
|
@ -1,55 +0,0 @@
|
||||
// |reftest| skip-if(!xulRuntime.shell) -- needs parseLegacyJSON
|
||||
// Any copyright is dedicated to the Public Domain.
|
||||
// http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
try
|
||||
{
|
||||
parseLegacyJSON("[,]");
|
||||
throw new Error("didn't throw");
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
assertEq(e instanceof SyntaxError, true, "didn't get syntax error, got: " + e);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
parseLegacyJSON("{,}");
|
||||
throw new Error("didn't throw");
|
||||
}
|
||||
catch (e)
|
||||
{
|
||||
assertEq(e instanceof SyntaxError, true, "didn't get syntax error, got: " + e);
|
||||
}
|
||||
|
||||
assertEq(parseLegacyJSON("[1,]").length, 1);
|
||||
assertEq(parseLegacyJSON("[1, ]").length, 1);
|
||||
assertEq(parseLegacyJSON("[1 , ]").length, 1);
|
||||
assertEq(parseLegacyJSON("[1 ,]").length, 1);
|
||||
assertEq(parseLegacyJSON("[1,2,]").length, 2);
|
||||
assertEq(parseLegacyJSON("[1,2, ]").length, 2);
|
||||
assertEq(parseLegacyJSON("[1,2 , ]").length, 2);
|
||||
assertEq(parseLegacyJSON("[1,2 ,]").length, 2);
|
||||
|
||||
assertEq(parseLegacyJSON('{"a": 2,}').a, 2);
|
||||
assertEq(parseLegacyJSON('{"a": 2, }').a, 2);
|
||||
assertEq(parseLegacyJSON('{"a": 2 , }').a, 2);
|
||||
assertEq(parseLegacyJSON('{"a": 2 ,}').a, 2);
|
||||
|
||||
var obj;
|
||||
|
||||
obj = parseLegacyJSON('{"a": 2,"b": 3,}');
|
||||
assertEq(obj.a + obj.b, 5);
|
||||
obj = parseLegacyJSON('{"a": 2,"b": 3, }');
|
||||
assertEq(obj.a + obj.b, 5);
|
||||
obj = parseLegacyJSON('{"a": 2,"b": 3 , }');
|
||||
assertEq(obj.a + obj.b, 5);
|
||||
obj = parseLegacyJSON('{"a": 2,"b": 3 ,}');
|
||||
assertEq(obj.a + obj.b, 5);
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
||||
|
||||
print("Tests complete");
|
@ -688,13 +688,7 @@ this.PlacesUtils = {
|
||||
case this.TYPE_X_MOZ_PLACE:
|
||||
case this.TYPE_X_MOZ_PLACE_SEPARATOR:
|
||||
case this.TYPE_X_MOZ_PLACE_CONTAINER:
|
||||
var json = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
|
||||
// Old profiles (pre-Firefox 4) may contain bookmarks.json files with
|
||||
// trailing commas, which we once accepted but no longer do -- except
|
||||
// when decoded using the legacy decoder. This can be reverted to
|
||||
// json.decode (better yet, to the ECMA-standard JSON.parse) when we no
|
||||
// longer support upgrades from pre-Firefox 4 profiles.
|
||||
nodes = json.legacyDecode("[" + blob + "]");
|
||||
nodes = JSON.parse("[" + blob + "]");
|
||||
break;
|
||||
case this.TYPE_X_MOZ_URL:
|
||||
var parts = blob.split("\n");
|
||||
|
Loading…
Reference in New Issue
Block a user