michael@0: var Ci = Components.interfaces; michael@0: var Cc = Components.classes; michael@0: michael@0: var nativeJSON = Cc["@mozilla.org/dom/json;1"].createInstance(Ci.nsIJSON); michael@0: michael@0: var dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties); michael@0: var workingDir = dirSvc.get("TmpD", Ci.nsIFile); michael@0: michael@0: var outputName = "json-test-output"; michael@0: var outputDir = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); michael@0: outputDir.initWithFile(workingDir); michael@0: outputDir.append(outputName); michael@0: michael@0: if (!outputDir.exists()) { michael@0: outputDir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777); michael@0: } else if (!outputDir.isDirectory()) { michael@0: do_throw(outputName + " is not a directory?") michael@0: } michael@0: michael@0: function testStringEncode() michael@0: { michael@0: var obj1 = {a:1}; michael@0: var obj2 = {foo:"bar"}; michael@0: do_check_eq(nativeJSON.encode(obj1), '{"a":1}'); michael@0: do_check_eq(nativeJSON.encode(obj2), '{"foo":"bar"}'); michael@0: michael@0: do_check_eq(nativeJSON.encode(), null); michael@0: michael@0: // useless roots are dropped michael@0: do_check_eq(nativeJSON.encode(null), null); michael@0: do_check_eq(nativeJSON.encode(""), null); michael@0: do_check_eq(nativeJSON.encode(undefined), null); michael@0: do_check_eq(nativeJSON.encode(5), null); michael@0: do_check_eq(nativeJSON.encode(function(){}), null); michael@0: do_check_eq(nativeJSON.encode(dump), null); michael@0: michael@0: // All other testing should occur in js/src/tests/ecma_5/JSON/ using michael@0: // the otherwise-exactly-identical JSON.stringify. michael@0: } michael@0: michael@0: function testToJSON() { michael@0: var obj1 = {a:1}; michael@0: var obj2 = {foo:"bar"}; michael@0: do_check_eq(nativeJSON.encode({toJSON: function() obj1}), '{"a":1}'); michael@0: do_check_eq(nativeJSON.encode({toJSON: function() obj2}), '{"foo":"bar"}'); michael@0: michael@0: do_check_eq(nativeJSON.encode({toJSON: function() null}), null); michael@0: do_check_eq(nativeJSON.encode({toJSON: function() ""}), null); michael@0: do_check_eq(nativeJSON.encode({toJSON: function() undefined }), null); michael@0: do_check_eq(nativeJSON.encode({toJSON: function() 5}), null); michael@0: do_check_eq(nativeJSON.encode({toJSON: function() function(){}}), null); michael@0: do_check_eq(nativeJSON.encode({toJSON: function() dump}), null); michael@0: } michael@0: michael@0: function testThrowingToJSON() { michael@0: var obj1 = { michael@0: "b": 1, michael@0: "c": 2, michael@0: toJSON: function() { throw("uh oh"); } michael@0: }; michael@0: try { michael@0: var y = nativeJSON.encode(obj1); michael@0: throw "didn't throw"; michael@0: } catch (ex) { michael@0: do_check_eq(ex, "uh oh"); michael@0: } michael@0: michael@0: var obj2 = { michael@0: "b": 1, michael@0: "c": 2, michael@0: get toJSON() { throw("crash and burn"); } michael@0: }; michael@0: try { michael@0: var y = nativeJSON.encode(obj2); michael@0: throw "didn't throw"; michael@0: } catch (ex) { michael@0: do_check_eq(ex, "crash and burn"); michael@0: } michael@0: } michael@0: michael@0: function testOutputStreams() { michael@0: function writeToFile(obj, charset, writeBOM) { michael@0: var jsonFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile); michael@0: jsonFile.initWithFile(outputDir); michael@0: jsonFile.append("test.json"); michael@0: jsonFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0600); michael@0: var stream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream); michael@0: try { michael@0: stream.init(jsonFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate michael@0: nativeJSON.encodeToStream(stream, charset, writeBOM, obj); michael@0: } finally { michael@0: stream.close(); michael@0: } michael@0: return jsonFile; michael@0: } michael@0: michael@0: var pairs = [ michael@0: ["{}", {}], michael@0: ['{"foo":"bar"}', {"foo":"bar"}], michael@0: ['{"null":null}', {"null":null}], michael@0: ['{"five":5}', {"five":5}], michael@0: ['{"true":true}', {"true":true}], michael@0: ['{"x":{"y":"z"}}', {"x":{"y":"z"}}], michael@0: ['{"w":{"x":{"y":"z"}}}', {"w":{"x":{"y":"z"}}}], michael@0: ["[]", []], michael@0: ['[1,2,3]', [1,2,3]], michael@0: ['[1,null,3]',[1,,3]], michael@0: ]; michael@0: for (var i = 0; i < pairs.length; i++) michael@0: { michael@0: var pair = pairs[i]; michael@0: if (pair[1] && (typeof pair[1] == "object")) { michael@0: var utf8File = writeToFile(pair[1], "UTF-8", false); michael@0: var utf16LEFile = writeToFile(pair[1], "UTF-16LE", false); michael@0: var utf16BEFile = writeToFile(pair[1], "UTF-16BE", false); michael@0: michael@0: // all ascii with no BOMs, so this will work michael@0: do_check_eq(utf16LEFile.fileSize / 2, utf8File.fileSize); michael@0: do_check_eq(utf16LEFile.fileSize, utf16BEFile.fileSize); michael@0: } michael@0: } michael@0: michael@0: // check BOMs michael@0: // the clone() calls are there to work around -- bug 410005 michael@0: var f = writeToFile({},"UTF-8", true).clone(); michael@0: do_check_eq(f.fileSize, 5); michael@0: var f = writeToFile({},"UTF-16LE", true).clone(); michael@0: do_check_eq(f.fileSize, 6); michael@0: var f = writeToFile({},"UTF-16BE", true).clone(); michael@0: do_check_eq(f.fileSize, 6); michael@0: michael@0: outputDir.remove(true); michael@0: } michael@0: michael@0: function run_test() michael@0: { michael@0: testStringEncode(); michael@0: testToJSON(); michael@0: testThrowingToJSON(); michael@0: michael@0: testOutputStreams(); michael@0: michael@0: }