Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Tests for JSON#parse and JSON#stringify.
Browse files Browse the repository at this point in the history
es-shims#258

Ported the latest JSON3 test suite.
Xotic750 committed Nov 18, 2015
1 parent 8584079 commit bdbdbbc
Showing 3 changed files with 533 additions and 2 deletions.
2 changes: 1 addition & 1 deletion tests/index.html
Original file line number Diff line number Diff line change
@@ -27,7 +27,7 @@
<script src="spec/s-number.js"></script>
<script src="spec/s-object.js"></script>
<script src="spec/s-string.js"></script>

<script src="spec/s-json.js"></script>

<script type="text/javascript">
(function() {
2 changes: 1 addition & 1 deletion tests/native.html
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
<script src="spec/s-number.js"></script>
<script src="spec/s-object.js"></script>
<script src="spec/s-string.js"></script>

<script src="spec/s-json.js"></script>

<script type="text/javascript">
(function() {
531 changes: 531 additions & 0 deletions tests/spec/s-json.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,531 @@
/* global describe, it, expect */

/* Ported from JSON 3 Unit Test Suite | https://bestiejs.github.io/json3 */
describe('JSON', function () {
// Ensures that `JSON.parse` throws an exception when parsing the given
// `source` string.
var parseError = function (source, message, callback) {
try {
expect(JSON.parse(source, callback)).toThrow();
} catch (e) {
expect(e instanceof SyntaxError).toBe(true);
}
};
// Ensures that `JSON.parse` parses the given source string correctly.
var parses = function (expected, source, message, callback) {
expect(JSON.parse(source, callback)).toEqual(expected);
};
// Ensures that `JSON.stringify` serializes the given object correctly.
var serializes = function (expected, value, message, filter, width) {
expect(JSON.stringify(value, filter, width)).toBe(expected);
};
// Ensures that `JSON.stringify` throws a `TypeError` if the given object
// contains a circular reference.
var cyclicError = function (value) {
try {
expect(JSON.stringify(value)).toThrow();
} catch (e) {
expect(e instanceof TypeError).toBe(true);
}
};
// Tests
// -----
it('`parse`: Empty Source Strings', function () {
parseError('', 'Empty JSON source string');
parseError('\n\n\r\n', 'Source string containing only line terminators');
parseError(' ', 'Source string containing a single space character');
parseError(' ', 'Source string containing multiple space characters');
});
it('`parse`: Whitespace', function () {
// The only valid JSON whitespace characters are tabs, spaces, and line
// terminators. All other Unicode category `Z` (`Zs`, `Zl`, and `Zp`)
// characters are invalid (note that the `Zs` category includes the
// space character).
var characters = [
'{\u00a0}',
'{\u1680}',
'{\u180e}',
'{\u2000}',
'{\u2001}',
'{\u2002}',
'{\u2003}',
'{\u2004}',
'{\u2005}',
'{\u2006}',
'{\u2007}',
'{\u2008}',
'{\u2009}',
'{\u200a}',
'{\u202f}',
'{\u205f}',
'{\u3000}',
'{\u2028}',
'{\u2029}'
];
characters.forEach(function (value) {
parseError(value, 'Source string containing an invalid Unicode whitespace character');
});
parseError('{\u000b}', 'Source string containing a vertical tab');
parseError('{\u000c}', 'Source string containing a form feed');
parseError('{\ufeff}', 'Source string containing a byte-order mark');
parses({}, '{\r\n}', 'Source string containing a CRLF line ending');
parses({}, '{\n\n\r\n}', 'Source string containing multiple line terminators');
parses({}, '{\t}', 'Source string containing a tab character');
parses({}, '{ }', 'Source string containing a space character');
});
it('`parse`: Octal Values', function () {
// `08` and `018` are invalid octal values.
var octal = ['00', '01', '02', '03', '04', '05', '06', '07', '010', '011', '08', '018'];
octal.forEach(function (value) {
parseError(value, 'Octal literal');
parseError('-' + value, 'Negative octal literal');
parseError('"\\' + value + '"', 'Octal escape sequence in a string');
parseError('"\\x' + value + '"', 'Hex escape sequence in a string');
});
});
it('`parse`: Numeric Literals', function () {
parses(100, '100', 'Integer');
parses(-100, '-100', 'Negative integer');
parses(10.5, '10.5', 'Float');
parses(-3.141, '-3.141', 'Negative float');
parses(0.625, '0.625', 'Decimal');
parses(-0.03125, '-0.03125', 'Negative decimal');
parses(1000, '1e3', 'Exponential');
parses(100, '1e+2', 'Positive exponential');
parses(-0.01, '-1e-2', 'Negative exponential');
parses(3125, '0.03125e+5', 'Decimalized exponential');
parses(100, '1E2', 'Case-insensitive exponential delimiter');
parseError('+1', 'Leading `+`');
parseError('1.', 'Trailing decimal point');
parseError('.1', 'Leading decimal point');
parseError('1e', 'Missing exponent');
parseError('1e-', 'Missing signed exponent');
parseError('--1', 'Leading `--`');
parseError('1-+', 'Trailing `-+`');
parseError('0xaf', 'Hex literal');
// The native `JSON.parse` implementation in IE 9 allows this syntax, but
// the feature tests should detect the broken implementation.
parseError('- 5', 'Invalid negative sign');
});
it('`parse`: String Literals', function () {
var expected = 48;
var controlCharacters = [
'\u0001',
'\u0002',
'\u0003',
'\u0004',
'\u0005',
'\u0006',
'\u0007',
'\b',
'\t',
'\n',
'\u000b',
'\f',
'\r',
'\u000e',
'\u000f',
'\u0010',
'\u0011',
'\u0012',
'\u0013',
'\u0014',
'\u0015',
'\u0016',
'\u0017',
'\u0018',
'\u0019',
'\u001a',
'\u001b',
'\u001c',
'\u001d',
'\u001e',
'\u001f'
];
// Opera 7 discards null characters in strings.
if ('\0'.length) {
expected += 1;
controlCharacters.push('\u0000');
}
parses('value', '"value"', 'Double-quoted string literal');
parses('', '""', 'Empty string literal');
parses('\u2028', '"\\u2028"', 'String containing an escaped Unicode line separator');
parses('\u2029', '"\\u2029"', 'String containing an escaped Unicode paragraph separator');
// ExtendScript doesn't handle surrogate pairs correctly; attempting to
// parse `"\ud834\udf06"` will throw an uncatchable error (issue #29).
parses('\ud834\udf06', '"\ud834\udf06"', 'String containing an unescaped Unicode surrogate pair');
parses('\u0001', '"\\u0001"', 'String containing an escaped ASCII control character');
parses('\b', '"\\b"', 'String containing an escaped backspace');
parses('\f', '"\\f"', 'String containing an escaped form feed');
parses('\n', '"\\n"', 'String containing an escaped line feed');
parses('\r', '"\\r"', 'String containing an escaped carriage return');
parses('\t', '"\\t"', 'String containing an escaped tab');
parses('hello/world', '"hello\\/world"', 'String containing an escaped solidus');
parses('hello\\world', '"hello\\\\world"', 'String containing an escaped reverse solidus');
parses('hello"world', '"hello\\"world"', 'String containing an escaped double-quote character');
parseError('\'hello\'', 'Single-quoted string literal');
parseError('"\\x61"', 'String containing a hex escape sequence');
parseError('"hello \r\n world"', 'String containing an unescaped CRLF line ending');
controlCharacters.forEach(function (value) {
parseError('"' + value + '"', 'String containing an unescaped ASCII control character');
});
});
it('`parse`: Array Literals', function () {
parseError('[1, 2, 3,]', 'Trailing comma in array literal');
parses([1, 2, [3, [4, 5]], 6, [true, false], [null], [[]]], '[1, 2, [3, [4, 5]], 6, [true, false], [null], [[]]]', 'Nested arrays');
parses([{}], '[{}]', 'Array containing empty object literal');
var expected = [
100,
true,
false,
null,
{
a: ['hello'],
b: ['world']
},
[0.01]
];
parses(expected, '[1e2, true, false, null, {"a": ["hello"], "b": ["world"]}, [1e-2]]', 'Mixed array');
});
it('`parse`: Object Literals', function () {
parses({
hello: 'world'
}, '{"hello": "world"}', 'Object literal containing one member');
parses({
hello: 'world',
foo: ['bar', true],
fox: {
quick: true,
purple: false
}
}, '{"hello": "world", "foo": ["bar", true], "fox": {"quick": true, "purple": false}}', 'Object literal containing multiple members');
parseError('{key: 1}', 'Unquoted identifier used as a property name');
parseError('{false: 1}', '`false` used as a property name');
parseError('{true: 1}', '`true` used as a property name');
parseError('{null: 1}', '`null` used as a property name');
parseError('{\'key\': 1}', 'Single-quoted string used as a property name');
parseError('{1: 2, 3: 4}', 'Number used as a property name');
parseError('{"hello": "world", "foo": "bar",}', 'Trailing comma in object literal');
});
// JavaScript expressions should never be evaluated, as JSON 3 does not use
// `eval`.
it('`parse`: Invalid Expressions', function () {
var expressions = [
'1 + 1',
'1 * 2',
'var value = 123;',
'{});value = 123;({}',
'call()',
'1, 2, 3, "value"'
];
expressions.forEach(function (expression) {
parseError(expression, 'Source string containing a JavaScript expression');
});
});
it('`stringify` and `parse`: Optional Arguments', function () {
parses({
a: 1,
b: 16
}, '{"a": 1, "b": "10000"}', 'Callback function provided', function (key, value) {
return typeof value === 'string' ? parseInt(value, 2) : value;
});
serializes('{\n "bar": 456\n}', {
foo: 123,
bar: 456
}, 'Object; optional `filter` and `whitespace` arguments', ['bar'], 2);
// Test adapted from the Opera JSON test suite via Ken Snyder.
// See http://testsuites.opera.com/JSON/correctness/scripts/045.js
// The regular expression is necessary because the ExtendScript engine
// only approximates pi to 14 decimal places (ES 3 and ES 5 approximate
// pi to 15 places).
expect(/^\{"PI":3\.\d{14,15}\}$/.test(JSON.stringify(Math, ['PI'])), 'List of non-enumerable property names specified as the `filter` argument').toBe(true);
expect(JSON.parse('[1, 2, 3]', function (key, value) {
if (typeof value === 'object' && value) {
return value;
}
}).length, 'Issue #10: `walk` should not use `splice` when removing an array element').toBe(3);
});
it('`stringify`', function () {
var expected = 30;
// Special values.
serializes('null', null, '`null` is represented literally');
serializes('null', 1 / 0, '`Infinity` is serialized as `null`');
serializes('null', 0 / 0, '`NaN` is serialized as `null`');
serializes('null', -1 / 0, '`-Infinity` is serialized as `null`');
serializes('true', true, 'Boolean primitives are represented literally');
serializes('false', Object(false), 'Boolean objects are represented literally');
serializes('"\\\\\\"How\\bquickly\\tdaft\\njumping\\fzebras\\rvex\\""', Object('\\"How\bquickly\tdaft\njumping\fzebras\rvex"'), 'All control characters in strings are escaped');
serializes('[false,1,"Kit"]', [Object(false), Object(1), Object('Kit')], 'Arrays are serialized recursively');
serializes('[null]', [void 0], '`[undefined]` is serialized as `[null]`');
// Property enumeration is implementation-dependent.
var value = {
jdalton: ['John-David', 29],
kitcambridge: ['Kit', 18],
mathias: ['Mathias', 23]
};
parses(value, JSON.stringify(value), 'Objects are serialized recursively');
// Complex cyclic structures.
value = {
foo: {
b: {
foo: {
c: {
foo: null
}
}
}
}
};
serializes('{"foo":{"b":{"foo":{"c":{"foo":null}}}}}', value, 'Nested objects containing identically-named properties should serialize correctly');
var S = [], N = {};
S.push(N, N);
serializes('[{},{}]', S, 'Objects containing duplicate references should not throw a `TypeError`');
value.foo.b.foo.c.foo = value;
cyclicError(value, 'Objects containing complex circular references should throw a `TypeError`');
// Sparse arrays.
value = [];
value[5] = 1;
serializes('[null,null,null,null,null,1]', value, 'Sparse arrays should serialize correctly');
// Dates.
serializes('"1994-07-03T00:00:00.000Z"', new Date(Date.UTC(1994, 6, 3)), 'Dates should be serialized according to the simplified date time string format');
serializes('"1993-06-02T02:10:28.224Z"', new Date(Date.UTC(1993, 5, 2, 2, 10, 28, 224)), 'The date time string should conform to the format outlined in the spec');
serializes('"-271821-04-20T00:00:00.000Z"', new Date(-8.64e15), 'The minimum valid date value should serialize correctly');
serializes('"+275760-09-13T00:00:00.000Z"', new Date(8.64e15), 'The maximum valid date value should serialize correctly');
serializes('"+010000-01-01T00:00:00.000Z"', new Date(Date.UTC(10000, 0, 1)), 'https://bugs.ecmascript.org/show_bug.cgi?id=119');
value = new Date();
value.toJSON = function () {
return 'date';
};
serializes('"date"', value);
// Tests based on research by @Yaffle. See kriskowal/es5-shim#111.
serializes('"1969-12-31T23:59:59.999Z"', new Date(-1), 'Millisecond values < 1000 should be serialized correctly');
serializes('"-000001-01-01T00:00:00.000Z"', new Date(-621987552e5), 'Years prior to 0 should be serialized as extended years');
serializes('"+010000-01-01T00:00:00.000Z"', new Date(2534023008e5), 'Years after 9999 should be serialized as extended years');
serializes('"-109252-01-01T10:37:06.708Z"', new Date(-3509827334573292), 'Issue #4: Opera > 9.64 should correctly serialize a date with a year of `-109252`');
// Opera 7 normalizes dates with invalid time values to represent the
// current date.
value = new Date('Kit');
if (!isFinite(value)) {
expected += 1;
serializes('null', value, 'Invalid dates should serialize as `null`');
}
// Additional arguments.
serializes('[\n 1,\n 2,\n 3,\n [\n 4,\n 5\n ]\n]', [1, 2, 3, [4, 5]], 'Nested arrays; optional `whitespace` argument', null, ' ');
serializes('[]', [], 'Empty array; optional string `whitespace` argument', null, ' ');
serializes('{}', {}, 'Empty object; optional numeric `whitespace` argument', null, 2);
serializes('[\n 1\n]', [1], 'Single-element array; optional numeric `whitespace` argument', null, 2);
serializes('{\n "foo": 123\n}', {
foo: 123
}, 'Single-member object; optional string `whitespace` argument', null, ' ');
serializes('{\n "foo": {\n "bar": [\n 123\n ]\n }\n}', {
foo: {
bar: [123]
}
}, 'Nested objects; optional numeric `whitespace` argument', null, 2);
});

/*
* The following tests are adapted from the ECMAScript 5 Conformance Suite.
* Copyright 2009, Microsoft Corporation. Distributed under the New BSD License.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of Microsoft nor the names of its contributors may be
* used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
it('ECMAScript 5 Conformance', function () {
var value = {
a1: {
b1: [1, 2, 3, 4],
b2: {
c1: 1,
c2: 2
}
},
a2: 'a2'
};
// Section 15.12.1.1: The JSON Grammar.
// ------------------------------------
// Tests 15.12.1.1-0-1 thru 15.12.1.1-0-8.
parseError('12\t\r\n 34', 'Valid whitespace characters may not separate two discrete tokens');
parseError('\u000b1234', 'The vertical tab is not a valid whitespace character');
parseError('\u000c1234', 'The form feed is not a valid whitespace character');
parseError('\u00a01234', 'The non-breaking space is not a valid whitespace character');
parseError('\u200b1234', 'The zero-width space is not a valid whitespace character');
parseError('\ufeff1234', 'The byte order mark (zero-width non-breaking space) is not a valid whitespace character');
parseError('\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u30001234', 'Other Unicode category `Z` characters are not valid whitespace characters');
parseError('\u2028\u20291234', 'The line (U+2028) and paragraph (U+2029) separators are not valid whitespace characters');
// Test 15.12.1.1-0-9.
parses({
property: {},
prop2: [true, null, 123.456]
},
'\t\r \n{\t\r \n' +
'"property"\t\r \n:\t\r \n{\t\r \n}\t\r \n,\t\r \n' +
'"prop2"\t\r \n:\t\r \n' +
'[\t\r \ntrue\t\r \n,\t\r \nnull\t\r \n,123.456\t\r \n]' +
'\t\r \n}\t\r \n',
'Valid whitespace characters may precede and follow all tokens');
// Tests 15.12.1.1-g1-1 thru 15.12.1.1-g1-4.
parses(1234, '\t1234', 'Leading tab characters should be ignored');
parseError('12\t34', 'A tab character may not separate two disparate tokens');
parses(1234, '\r1234', 'Leading carriage returns should be ignored');
parseError('12\r34', 'A carriage return may not separate two disparate tokens');
parses(1234, '\n1234', 'Leading line feeds should be ignored');
parseError('12\n34', 'A line feed may not separate two disparate tokens');
parses(1234, ' 1234', 'Leading space characters should be ignored');
parseError('12 34', 'A space character may not separate two disparate tokens');
// Tests 15.12.1.1-g2-1 thru 15.12.1.1-g2-5.
parses('abc', '"abc"', 'Strings must be enclosed in double quotes');
parseError('\'abc\'', 'Single-quoted strings are not permitted');
// Note: the original test 15.12.1.1-g2-3 (`"\u0022abc\u0022"`) is incorrect,
// as the JavaScript interpreter will always convert `\u0022` to `"`.
parseError('\\u0022abc\\u0022', 'Unicode-escaped double quote delimiters are not permitted');
parseError('"abc\'', 'Strings must terminate with a double quote character');
parses('', '""', 'Strings may be empty');
// Tests 15.12.1.1-g4-1 thru 15.12.1.1-g4-4.
parseError('"\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007"', 'Unescaped control characters in the range [U+0000, U+0007] are not permitted within strings');
parseError('"\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f"', 'Unescaped control characters in the range [U+0008, U+000F] are not permitted within strings');
parseError('"\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017"', 'Unescaped control characters in the range [U+0010, U+0017] are not permitted within strings');
parseError('"\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"', 'Unescaped control characters in the range [U+0018, U+001F] are not permitted within strings');
// Tests 15.12.1.1-g5-1 thru 15.12.1.1-g5-3.
parses('X', '"\\u0058"', 'Unicode escape sequences are permitted within strings');
parseError('"\\u005"', 'Unicode escape sequences may not comprise fewer than four hexdigits');
parseError('"\\u0X50"', 'Unicode escape sequences may not contain non-hex characters');
// Tests 15.12.1.1-g6-1 thru 15.12.1.1-g6-7.
parses('/', '"\\/"', 'Escaped solidus');
parses('\\', '"\\\\"', 'Escaped reverse solidus');
parses('\b', '"\\b"', 'Escaped backspace');
parses('\f', '"\\f"', 'Escaped form feed');
parses('\n', '"\\n"', 'Escaped line feed');
parses('\r', '"\\r"', 'Escaped carriage return');
parses('\t', '"\\t"', 'Escaped tab');

// Section 15.12.3: `JSON.stringify()`.
// ------------------------------------
// Test 15.12.3-11-1 thru 5.12.3-11-15.
serializes(void 0, void 0, '`JSON.stringify(undefined)` should return `undefined`');
serializes('"replacement"', void 0, 'The `JSON.stringify` callback function can be called on a top-level `undefined` value', function () {
return 'replacement';
});
serializes('"a string"', 'a string', '`JSON.stringify` should serialize top-level string primitives');
serializes('123', 123, '`JSON.stringify` should serialize top-level number primitives');
serializes('true', true, '`JSON.stringify` should serialize top-level Boolean primitives');
serializes('null', null, '`JSON.stringify` should serialize top-level `null` values');
serializes('42', Object(42), '`JSON.stringify` should serialize top-level number objects');
serializes('"wrapped"', Object('wrapped'), '`JSON.stringify` should serialize top-level string objects');
serializes('false', Object(false), '`JSON.stringify` should serialize top-level Boolean objects');
serializes(void 0, 42, 'The `JSON.stringify` callback function may return `undefined` when called on a top-level number primitive', function () {
return void 0;
});
serializes(void 0, {
prop: 1
}, 'The `JSON.stringify` callback function may return `undefined` when called on a top-level object', function () {
return void 0;
});
serializes('[4,2]', 42, 'The `JSON.stringify` callback function may return an array when called on a top-level number primitive', function (key, value) {
return value === 42 ? [4, 2] : value;
});
serializes('{"forty":2}', 42, 'The `JSON.stringify` callback function may return an object literal when called on a top-level number primitive', function (key, value) {
return value === 42 ? {
forty: 2
} : value;
});
serializes(void 0, function () {}, '`JSON.stringify` should return `undefined` when called on a top-level function');
serializes('99', function () {}, 'The `JSON.stringify` callback function may return a number primitive when called on a top-level function', function () {
return 99;
});
// Test 15.12.3-4-1.
serializes('[42]', [42], '`JSON.stringify` should ignore `filter` arguments that are not functions or arrays', {});
// Test 15.12.3-5-a-i-1 and 15.12.3-5-b-i-1.
expect(JSON.stringify(value, null, 5), 'Optional `width` argument: Number object and primitive width values should produce identical results').toBe(JSON.stringify(value, null, Object(5)));
expect(JSON.stringify(value, null, 'xxx'), 'Optional `width` argument: String object and primitive width values should produce identical results').toBe(JSON.stringify(value, null, Object('xxx')));
// Test 15.12.3-6-a-1 and 15.12.3-6-a-2.
expect(JSON.stringify(value, null, 100), 'Optional `width` argument: The maximum numeric width value should be 10').toBe(JSON.stringify(value, null, 10));
expect(JSON.stringify(value, null, 5.99999), 'Optional `width` argument: Numeric values should be converted to integers').toBe(JSON.stringify(value, null, 5));
// Test 15.12.3-6-b-1 and 15.12.3-6-b-4.
expect(JSON.stringify(value, null, 0.999999), 'Optional `width` argument: Numeric width values between 0 and 1 should be ignored').toBe(JSON.stringify(value));
expect(JSON.stringify(value, null, 0), 'Optional `width` argument: Zero should be ignored').toBe(JSON.stringify(value));
expect(JSON.stringify(value, null, -5), 'Optional `width` argument: Negative numeric values should be ignored').toBe(JSON.stringify(value));
expect(JSON.stringify(value, null, 5), 'Optional `width` argument: Numeric width values in the range [1, 10] should produce identical results to that of string values containing `width` spaces').toBe(JSON.stringify(value, null, ' '));
// Test 15.12.3-7-a-1.
expect(JSON.stringify(value, null, '0123456789xxxxxxxxx'), 'Optional `width` argument: String width values longer than 10 characters should be truncated').toBe(JSON.stringify(value, null, '0123456789'));
// Test 15.12.3-8-a-1 thru 15.12.3-8-a-5.
expect(JSON.stringify(value, null, ''), 'Empty string `width` arguments should be ignored').toBe(JSON.stringify(value));
expect(JSON.stringify(value, null, true), 'Boolean primitive `width` arguments should be ignored').toBe(JSON.stringify(value));
expect(JSON.stringify(value, null, null), '`null` `width` arguments should be ignored').toBe(JSON.stringify(value));
expect(JSON.stringify(value, null, Object(false)), 'Boolean object `width` arguments should be ignored').toBe(JSON.stringify(value));
expect(JSON.stringify(value, null, value), 'Object literal `width` arguments should be ignored').toBe(JSON.stringify(value));
// Test 15.12.3@2-2-b-i-1.
serializes('["fortytwo objects"]', [
{
prop: 42,
toJSON: function () {
return 'fortytwo objects';
}
}
], 'An object literal with a custom `toJSON` method nested within an array may return a string primitive for serialization');
// Test 15.12.3@2-2-b-i-2.
serializes('[42]', [
{
prop: 42,
toJSON: function () {
return Object(42);
}
}
], 'An object literal with a custom `toJSON` method nested within an array may return a number object for serialization');
// Test 15.12.3@2-2-b-i-3.
serializes('[true]', [
{
prop: 42,
toJSON: function () {
return Object(true);
}
}
], 'An object literal with a custom `toJSON` method nested within an array may return a Boolean object for serialization');
// Test 15.12.3@2-3-a-1.
serializes('["fortytwo"]', [42], 'The `JSON.stringify` callback function may return a string object when called on an array', function (key, value) {
return value === 42 ? Object('fortytwo') : value;
});
// Test 15.12.3@2-3-a-2.
serializes('[84]', [42], 'The `JSON.stringify` callback function may return a number object when called on an array', function (key, value) {
return value === 42 ? Object(84) : value;
});
// Test 15.12.3@2-3-a-3.
serializes('[false]', [42], 'The `JSON.stringify` callback function may return a Boolean object when called on an array', function (key, value) {
return value === 42 ? Object(false) : value;
});
// Test 15.12.3@4-1-2. 15.12.3@4-1-1 only tests whether an exception is
// thrown; the type of the exception is not checked.
value = {};
value.prop = value;
cyclicError(value, 'An object containing a circular reference should throw a `TypeError`');
// Test 15.12.3@4-1-3, modified to ensure that a `TypeError` is thrown.
value = {
p1: {
p2: {}
}
};
value.p1.p2.prop = value;
cyclicError(value, 'A nested cyclic structure should throw a `TypeError`');
});
});

0 comments on commit bdbdbbc

Please sign in to comment.