mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-05 05:30:29 +00:00
Bug 1387788 - Remove [deprecated] methods from nsIJSON. r=Ehsan
MozReview-Commit-ID: 9OsQacbPsFo --HG-- extra : rebase_source : 8c905a48306e957026af9dd8fcbf83eae41b8a38
This commit is contained in:
parent
407f690fc8
commit
706ca23396
@ -6,7 +6,6 @@
|
||||
#include "domstubs.idl"
|
||||
|
||||
interface nsIInputStream;
|
||||
interface nsIOutputStream;
|
||||
interface nsIScriptGlobalObject;
|
||||
|
||||
[ptr] native JSValPtr(JS::Value);
|
||||
@ -22,34 +21,6 @@ interface nsIScriptGlobalObject;
|
||||
[scriptable, uuid(083aebb0-7790-43b2-ae81-9e404e626236)]
|
||||
interface nsIJSON : nsISupports
|
||||
{
|
||||
/**
|
||||
* New users should use JSON.stringify!
|
||||
* The encode() method is only present for backward compatibility.
|
||||
* encode() is not a conforming JSON stringify implementation!
|
||||
*/
|
||||
[deprecated,implicit_jscontext,optional_argc]
|
||||
AString encode([optional] in jsval value);
|
||||
|
||||
/**
|
||||
* New users should use JSON.stringify.
|
||||
* You may also want to have a look at nsIConverterOutputStream.
|
||||
*
|
||||
* The encodeToStream() method is only present for backward compatibility.
|
||||
* encodeToStream() is not a conforming JSON stringify implementation!
|
||||
*/
|
||||
[deprecated,implicit_jscontext,optional_argc]
|
||||
void encodeToStream(in nsIOutputStream stream,
|
||||
in string charset,
|
||||
in boolean writeBOM,
|
||||
[optional] in jsval value);
|
||||
|
||||
/**
|
||||
* New users should use JSON.parse!
|
||||
* The decode() method is only present for backward compatibility.
|
||||
*/
|
||||
[deprecated,implicit_jscontext]
|
||||
jsval decode(in AString str);
|
||||
|
||||
[implicit_jscontext]
|
||||
jsval decodeFromStream(in nsIInputStream stream,
|
||||
in long contentLength);
|
||||
|
@ -4,9 +4,10 @@
|
||||
* 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 "nsJSON.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "nsJSON.h"
|
||||
#include "nsIXPConnect.h"
|
||||
#include "nsIXPCScriptable.h"
|
||||
#include "nsStreamUtils.h"
|
||||
@ -43,109 +44,6 @@ nsJSON::~nsJSON()
|
||||
{
|
||||
}
|
||||
|
||||
enum DeprecationWarning { EncodeWarning, DecodeWarning };
|
||||
|
||||
static nsresult
|
||||
WarnDeprecatedMethod(DeprecationWarning warning)
|
||||
{
|
||||
return nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("DOM Core"), nullptr,
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
warning == EncodeWarning
|
||||
? "nsIJSONEncodeDeprecatedWarning"
|
||||
: "nsIJSONDecodeDeprecatedWarning");
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::Encode(JS::Handle<JS::Value> aValue, JSContext* cx, uint8_t aArgc,
|
||||
nsAString &aJSON)
|
||||
{
|
||||
// This function should only be called from JS.
|
||||
nsresult rv = WarnDeprecatedMethod(EncodeWarning);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
if (aArgc == 0) {
|
||||
aJSON.SetIsVoid(true);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsJSONWriter writer;
|
||||
rv = EncodeInternal(cx, aValue, &writer);
|
||||
|
||||
// FIXME: bug 408838. Get exception types sorted out
|
||||
if (NS_SUCCEEDED(rv) || rv == NS_ERROR_INVALID_ARG) {
|
||||
rv = NS_OK;
|
||||
// if we didn't consume anything, it's not JSON, so return null
|
||||
if (!writer.DidWrite()) {
|
||||
aJSON.SetIsVoid(true);
|
||||
} else {
|
||||
writer.FlushBuffer();
|
||||
aJSON.Append(writer.mOutputString);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static const char UTF8BOM[] = "\xEF\xBB\xBF";
|
||||
|
||||
static nsresult CheckCharset(const char* aCharset)
|
||||
{
|
||||
// Check that the charset is permissible
|
||||
if (!(strcmp(aCharset, "UTF-8") == 0)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::EncodeToStream(nsIOutputStream *aStream,
|
||||
const char* aCharset,
|
||||
const bool aWriteBOM,
|
||||
JS::Handle<JS::Value> val,
|
||||
JSContext* cx,
|
||||
uint8_t aArgc)
|
||||
{
|
||||
// This function should only be called from JS.
|
||||
NS_ENSURE_ARG(aStream);
|
||||
nsresult rv;
|
||||
|
||||
rv = CheckCharset(aCharset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check to see if we have a buffered stream
|
||||
nsCOMPtr<nsIOutputStream> bufferedStream;
|
||||
// FIXME: bug 408514.
|
||||
// NS_OutputStreamIsBuffered(aStream) asserts on file streams...
|
||||
//if (!NS_OutputStreamIsBuffered(aStream)) {
|
||||
rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedStream),
|
||||
aStream, 4096);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// aStream = bufferedStream;
|
||||
//}
|
||||
|
||||
uint32_t ignored;
|
||||
if (aWriteBOM) {
|
||||
rv = aStream->Write(UTF8BOM, 3, &ignored);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsJSONWriter writer(bufferedStream);
|
||||
|
||||
if (aArgc == 0) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = EncodeInternal(cx, val, &writer);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = bufferedStream->Flush();
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static bool
|
||||
WriteCallback(const char16_t *buf, uint32_t len, void *data)
|
||||
{
|
||||
@ -181,60 +79,6 @@ nsJSON::EncodeFromJSVal(JS::Value *value, JSContext *cx, nsAString &result)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsJSON::EncodeInternal(JSContext* cx, const JS::Value& aValue,
|
||||
nsJSONWriter* writer)
|
||||
{
|
||||
// Backward compatibility:
|
||||
// nsIJSON does not allow to serialize anything other than objects
|
||||
if (!aValue.isObject()) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
JS::Rooted<JSObject*> obj(cx, &aValue.toObject());
|
||||
|
||||
/* Backward compatibility:
|
||||
* Manually call toJSON if implemented by the object and check that
|
||||
* the result is still an object
|
||||
* Note: It is perfectly fine to not implement toJSON, so it is
|
||||
* perfectly fine for GetMethod to fail
|
||||
*/
|
||||
JS::Rooted<JS::Value> val(cx, aValue);
|
||||
JS::Rooted<JS::Value> toJSON(cx);
|
||||
if (JS_GetProperty(cx, obj, "toJSON", &toJSON) &&
|
||||
toJSON.isObject() && JS::IsCallable(&toJSON.toObject())) {
|
||||
// If toJSON is implemented, it must not throw
|
||||
if (!JS_CallFunctionValue(cx, obj, toJSON, JS::HandleValueArray::empty(), &val)) {
|
||||
if (JS_IsExceptionPending(cx))
|
||||
// passing NS_OK will throw the pending exception
|
||||
return NS_OK;
|
||||
|
||||
// No exception, but still failed
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Backward compatibility:
|
||||
// nsIJSON does not allow to serialize anything other than objects
|
||||
if (val.isPrimitive())
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
// GetMethod may have thrown
|
||||
else if (JS_IsExceptionPending(cx))
|
||||
// passing NS_OK will throw the pending exception
|
||||
return NS_OK;
|
||||
|
||||
// Backward compatibility:
|
||||
// function shall not pass, just "plain" objects and arrays
|
||||
JSType type = JS_TypeOfValue(cx, val);
|
||||
if (type == JSTYPE_FUNCTION)
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
// We're good now; try to stringify
|
||||
if (!JS_Stringify(cx, &val, nullptr, JS::NullHandleValue, WriteCallback, writer))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsJSONWriter::nsJSONWriter() : mStream(nullptr),
|
||||
mBuffer(nullptr),
|
||||
@ -329,25 +173,6 @@ nsJSONWriter::WriteToStream(nsIOutputStream* aStream,
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::Decode(const nsAString& json, JSContext* cx,
|
||||
JS::MutableHandle<JS::Value> aRetval)
|
||||
{
|
||||
nsresult rv = WarnDeprecatedMethod(DecodeWarning);
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
const char16_t *data = json.BeginReading();
|
||||
uint32_t len = json.Length();
|
||||
nsCOMPtr<nsIInputStream> stream;
|
||||
rv = NS_NewByteInputStream(getter_AddRefs(stream),
|
||||
reinterpret_cast<const char*>(data),
|
||||
len * sizeof(char16_t),
|
||||
NS_ASSIGNMENT_DEPEND);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return DecodeInternal(cx, stream, len, false, aRetval);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSON::DecodeFromStream(nsIInputStream *aStream, int32_t aContentLength,
|
||||
JSContext* cx, JS::MutableHandle<JS::Value> aRetval)
|
||||
|
@ -42,7 +42,7 @@ protected:
|
||||
mozilla::UniquePtr<mozilla::Encoder> mEncoder;
|
||||
};
|
||||
|
||||
class nsJSON : public nsIJSON
|
||||
class nsJSON final : public nsIJSON
|
||||
{
|
||||
public:
|
||||
nsJSON();
|
||||
@ -53,10 +53,6 @@ public:
|
||||
protected:
|
||||
virtual ~nsJSON();
|
||||
|
||||
nsresult EncodeInternal(JSContext* cx,
|
||||
const JS::Value& val,
|
||||
nsJSONWriter* writer);
|
||||
|
||||
nsresult DecodeInternal(JSContext* cx,
|
||||
nsIInputStream* aStream,
|
||||
int32_t aContentLength,
|
||||
|
File diff suppressed because one or more lines are too long
@ -1,136 +0,0 @@
|
||||
var Ci = Components.interfaces;
|
||||
var Cc = Components.classes;
|
||||
|
||||
var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON);
|
||||
|
||||
var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
var workingDir = dirSvc.get("TmpD", Ci.nsIFile);
|
||||
|
||||
var outputName = "json-test-output";
|
||||
var outputDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
outputDir.initWithFile(workingDir);
|
||||
outputDir.append(outputName);
|
||||
|
||||
if (!outputDir.exists()) {
|
||||
outputDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0o777);
|
||||
} else if (!outputDir.isDirectory()) {
|
||||
do_throw(outputName + " is not a directory?")
|
||||
}
|
||||
|
||||
function testStringEncode()
|
||||
{
|
||||
var obj1 = {a:1};
|
||||
var obj2 = {foo:"bar"};
|
||||
do_check_eq(nativeJSON.encode(obj1), '{"a":1}');
|
||||
do_check_eq(nativeJSON.encode(obj2), '{"foo":"bar"}');
|
||||
|
||||
do_check_eq(nativeJSON.encode(), null);
|
||||
|
||||
// useless roots are dropped
|
||||
do_check_eq(nativeJSON.encode(null), null);
|
||||
do_check_eq(nativeJSON.encode(""), null);
|
||||
do_check_eq(nativeJSON.encode(undefined), null);
|
||||
do_check_eq(nativeJSON.encode(5), null);
|
||||
do_check_eq(nativeJSON.encode(function(){}), null);
|
||||
do_check_eq(nativeJSON.encode(dump), null);
|
||||
|
||||
// All other testing should occur in js/src/tests/ecma_5/JSON/ using
|
||||
// the otherwise-exactly-identical JSON.stringify.
|
||||
}
|
||||
|
||||
function testToJSON() {
|
||||
var obj1 = {a:1};
|
||||
var obj2 = {foo:"bar"};
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => obj1}), '{"a":1}');
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => obj2}), '{"foo":"bar"}');
|
||||
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => null}), null);
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => ""}), null);
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => undefined }), null);
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => 5}), null);
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => function(){}}), null);
|
||||
do_check_eq(nativeJSON.encode({toJSON: () => dump}), null);
|
||||
}
|
||||
|
||||
function testThrowingToJSON() {
|
||||
var obj1 = {
|
||||
"b": 1,
|
||||
"c": 2,
|
||||
toJSON: function() { throw("uh oh"); }
|
||||
};
|
||||
try {
|
||||
var y = nativeJSON.encode(obj1);
|
||||
throw "didn't throw";
|
||||
} catch (ex) {
|
||||
do_check_eq(ex, "uh oh");
|
||||
}
|
||||
|
||||
var obj2 = {
|
||||
"b": 1,
|
||||
"c": 2,
|
||||
get toJSON() { throw("crash and burn"); }
|
||||
};
|
||||
try {
|
||||
var y = nativeJSON.encode(obj2);
|
||||
throw "didn't throw";
|
||||
} catch (ex) {
|
||||
do_check_eq(ex, "crash and burn");
|
||||
}
|
||||
}
|
||||
|
||||
function testOutputStreams() {
|
||||
function writeToFile(obj, charset, writeBOM) {
|
||||
var jsonFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
|
||||
jsonFile.initWithFile(outputDir);
|
||||
jsonFile.append("test.json");
|
||||
jsonFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0o600);
|
||||
var stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
|
||||
try {
|
||||
stream.init(jsonFile, 0x04 | 0x08 | 0x20, 0o600, 0); // write, create, truncate
|
||||
nativeJSON.encodeToStream(stream, charset, writeBOM, obj);
|
||||
} finally {
|
||||
stream.close();
|
||||
}
|
||||
return jsonFile;
|
||||
}
|
||||
|
||||
var pairs = [
|
||||
["{}", {}],
|
||||
['{"foo":"bar"}', {"foo":"bar"}],
|
||||
['{"null":null}', {"null":null}],
|
||||
['{"five":5}', {"five":5}],
|
||||
['{"true":true}', {"true":true}],
|
||||
['{"x":{"y":"z"}}', {"x":{"y":"z"}}],
|
||||
['{"w":{"x":{"y":"z"}}}', {"w":{"x":{"y":"z"}}}],
|
||||
["[]", []],
|
||||
['[1,2,3]', [1,2,3]],
|
||||
['[1,null,3]',[1,,3]],
|
||||
];
|
||||
for (var i = 0; i < pairs.length; i++)
|
||||
{
|
||||
var pair = pairs[i];
|
||||
if (pair[1] && (typeof pair[1] == "object")) {
|
||||
var utf8File = writeToFile(pair[1], "UTF-8", false);
|
||||
|
||||
// all ascii with no BOMs, so this will work
|
||||
do_check_eq(utf8File.fileSize, pair[0].length);
|
||||
}
|
||||
}
|
||||
|
||||
// check BOMs
|
||||
// the clone() calls are there to work around -- bug 410005
|
||||
var f = writeToFile({},"UTF-8", true).clone();
|
||||
do_check_eq(f.fileSize, 5);
|
||||
|
||||
outputDir.remove(true);
|
||||
}
|
||||
|
||||
function run_test()
|
||||
{
|
||||
testStringEncode();
|
||||
testToJSON();
|
||||
testThrowingToJSON();
|
||||
|
||||
testOutputStreams();
|
||||
|
||||
}
|
@ -4,7 +4,5 @@ support-files =
|
||||
decodeFromStream-01.json
|
||||
decodeFromStream-small.json
|
||||
|
||||
[test_decode_long_input.js]
|
||||
[test_decodeFromStream.js]
|
||||
[test_encode.js]
|
||||
|
||||
|
@ -60,8 +60,6 @@ CreateAttributeNSWarning=Use of document.createAttributeNS() is deprecated. Use
|
||||
NodeValueWarning=Use of attributes’ nodeValue attribute is deprecated. Use value instead.
|
||||
TextContentWarning=Use of attributes’ textContent attribute is deprecated. Use value instead.
|
||||
EnablePrivilegeWarning=Use of enablePrivilege is deprecated. Please use code that runs with the system principal (e.g. an extension) instead.
|
||||
nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated. Please use JSON.parse instead.
|
||||
nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated. Please use JSON.stringify instead.
|
||||
FullscreenDeniedDisabled=Request for fullscreen was denied because Fullscreen API is disabled by user preference.
|
||||
FullscreenDeniedFocusedPlugin=Request for fullscreen was denied because a windowed plugin is focused.
|
||||
FullscreenDeniedHidden=Request for fullscreen was denied because the document is no longer visible.
|
||||
|
Loading…
x
Reference in New Issue
Block a user