You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

665 lines
9.9 KiB

/*===
typeof, class, etc
typeof: object
class: Null
typeof: boolean
class: Boolean
typeof: boolean
class: Boolean
typeof: number
class: Number
typeof: object
class: Array
typeof: object
class: Object
array prototype expected: true
object prototype expected: true
===*/
/* Test typeof, class etc of parsed values. */
print('typeof, class, etc');
function getClass(v) {
var txt;
txt = Object.prototype.toString.call(v); /* -> "[object <class>]" */
m = /^\[object\u0020(.*)\]$/.exec(txt);
if (m) {
return m[1];
} else {
return;
}
}
function testTypeofEtc(x) {
var v = JSON.parse(x);
print('typeof: ' + typeof v);
print('class: ' + getClass(v));
}
function testObjectAndArrayPrototypes() {
var v;
/* Both Object.prototype and Array.prototype are non-writable,
* non-configurable properties, so we can't test (and don't need
* to test) what happens if Object.prototype or Array.prototype
* is replaced with a custom value.
*/
v = JSON.parse("[1,2]");
print('array prototype expected: ' + (Object.getPrototypeOf(v) === Array.prototype));
v = JSON.parse('{"foo":1,"bar":2}');
print('object prototype expected: ' + (Object.getPrototypeOf(v) === Object.prototype));
}
try {
testTypeofEtc("null");
testTypeofEtc("true");
testTypeofEtc("false");
testTypeofEtc("1.23");
testTypeofEtc("[1,2]");
testTypeofEtc('{"foo":1,"bar":2}');
// test Object and Array prototypes
testObjectAndArrayPrototypes();
} catch (e) {
print(e.name);
}
/*===
nan/inf
SyntaxError
SyntaxError
SyntaxError
===*/
/* JSONNumber does not accept NaN, Infinity, -Infinity. Ecmascript also
* does not but they parse as identifier references (and unary minus for
* -Infinity) and usually evaluate to something useful.
*
* These are tested explicitly because they might be a risk with shared
* parser handling and because these forms might be used in an extended
* JSON encoding format.
*/
print('nan/inf');
try {
print(JSON.parse('NaN'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('Infinity'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('-Infinity'));
} catch (e) {
print(e.name);
}
/*===
hex/octal literal
SyntaxError
SyntaxError
SyntaxError
===*/
/* JSONNumber does not allow hex or octal literals. */
print('hex/octal literal');
try {
print(JSON.parse('0x41'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('077'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('099'));
} catch (e) {
print(e.name);
}
/*===
leading plus
1
SyntaxError
===*/
/* JSONNumber does not allow a plus sign. Actually Ecmascript doesn't either,
* a leading plus sign is an unary plus operator.
*/
print('leading plus');
try {
print(eval('+1'));
print(JSON.parse('+1'));
} catch (e) {
print(e.name);
}
/*===
empty fractions
1
SyntaxError
===*/
/* JSONNumber does not allow empty fractions part.
*
* (Rhino allows it.)
*/
print('empty fractions');
try {
print(eval('1.'));
print(JSON.parse('1.'));
} catch (e) {
print(e.name);
}
/*===
missing integer part
0.123
SyntaxError
===*/
/* JSONNumber does not allow fractions without an integer part. */
print('missing integer part');
try {
print(eval('.123'));
print(JSON.parse('.123'));
} catch (e) {
print(e.name);
}
/*===
leading zeroes
0
SyntaxError
SyntaxError
SyntaxError
===*/
/* JSONNumber does not allow additional leading zeroes. This is probably a
* good thing even if Ecmascript parsing allows octal literals.
*/
print('leading zeroes');
try {
print(JSON.parse('0'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('00'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('012'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('019'));
} catch (e) {
print(e.name);
}
/*===
single quotes
foo
SyntaxError
===*/
/* JSONString does not allow single quotes, Ecmascript does. */
print('single quotes');
try {
print(eval("'foo'"));
print(JSON.parse("'foo'"));
} catch (e) {
print(e.name);
}
/*===
string codepoints
cp 0
eval 1 0
json SyntaxError
cp 1
eval 1 1
json SyntaxError
cp 2
eval 1 2
json SyntaxError
cp 3
eval 1 3
json SyntaxError
cp 4
eval 1 4
json SyntaxError
cp 5
eval 1 5
json SyntaxError
cp 6
eval 1 6
json SyntaxError
cp 7
eval 1 7
json SyntaxError
cp 8
eval 1 8
json SyntaxError
cp 9
eval 1 9
json SyntaxError
cp 10
eval SyntaxError
json SyntaxError
cp 11
eval 1 11
json SyntaxError
cp 12
eval 1 12
json SyntaxError
cp 13
eval SyntaxError
json SyntaxError
cp 14
eval 1 14
json SyntaxError
cp 15
eval 1 15
json SyntaxError
cp 16
eval 1 16
json SyntaxError
cp 17
eval 1 17
json SyntaxError
cp 18
eval 1 18
json SyntaxError
cp 19
eval 1 19
json SyntaxError
cp 20
eval 1 20
json SyntaxError
cp 21
eval 1 21
json SyntaxError
cp 22
eval 1 22
json SyntaxError
cp 23
eval 1 23
json SyntaxError
cp 24
eval 1 24
json SyntaxError
cp 25
eval 1 25
json SyntaxError
cp 26
eval 1 26
json SyntaxError
cp 27
eval 1 27
json SyntaxError
cp 28
eval 1 28
json SyntaxError
cp 29
eval 1 29
json SyntaxError
cp 30
eval 1 30
json SyntaxError
cp 31
eval 1 31
json SyntaxError
===*/
/* JSONString does not accept codepoints U+0000 to U+001F (Ecmascript does). */
print('string codepoints');
function testStringCodepoint(x) {
var lit = '"' + String.fromCharCode(x) + '"';
var t;
print('cp', x);
// Codepoints 0x0a and 0x0d will cause eval to fail: newline inside
// a string
try {
t = eval(lit);
print('eval', t.length, t.charCodeAt(0));
} catch (e) {
print('eval', e.name);
}
try {
t = JSON.parse(lit);
print('json', t.length, t.charCodeAt(0));
} catch (e) {
print('json', e.name);
}
}
function testStringCodepoints() {
var i;
for (i = 0; i < 32; i++) {
testStringCodepoint(i);
}
}
try {
testStringCodepoints();
} catch (e) {
print(e.name, e);
}
/*===
unicode escape
1 4660
2 43981 61185
2 43981 61185
===*/
print('unicode escape');
function testUnicodeEscape() {
var t;
t = JSON.parse('"\\u1234"');
print(t.length, t.charCodeAt(0));
t = JSON.parse('"\\uabcd\\uef01"');
print(t.length, t.charCodeAt(0), t.charCodeAt(1));
// both lowercase and uppercase hex digits are required
t = JSON.parse('"\\uABCD\\uEF01"');
print(t.length, t.charCodeAt(0), t.charCodeAt(1));
}
try {
testUnicodeEscape();
} catch (e) {
print(e);
}
/*===
character escapes
cp 97 a
eval 1 97
json SyntaxError
cp 98 b
eval 1 8
json 1 8
cp 99 c
eval 1 99
json SyntaxError
cp 100 d
eval 1 100
json SyntaxError
cp 101 e
eval 1 101
json SyntaxError
cp 102 f
eval 1 12
json 1 12
cp 103 g
eval 1 103
json SyntaxError
cp 104 h
eval 1 104
json SyntaxError
cp 105 i
eval 1 105
json SyntaxError
cp 106 j
eval 1 106
json SyntaxError
cp 107 k
eval 1 107
json SyntaxError
cp 108 l
eval 1 108
json SyntaxError
cp 109 m
eval 1 109
json SyntaxError
cp 110 n
eval 1 10
json 1 10
cp 111 o
eval 1 111
json SyntaxError
cp 112 p
eval 1 112
json SyntaxError
cp 113 q
eval 1 113
json SyntaxError
cp 114 r
eval 1 13
json 1 13
cp 115 s
eval 1 115
json SyntaxError
cp 116 t
eval 1 9
json 1 9
cp 117 u
eval 1 117
json SyntaxError
cp 118 v
eval 1 11
json SyntaxError
cp 119 w
eval 1 119
json SyntaxError
cp 120 x
eval 1 120
json SyntaxError
cp 121 y
eval 1 121
json SyntaxError
cp 122 z
eval 1 122
json SyntaxError
===*/
/* JSONString does not allow "unknown" backslash escapes. These are handled
* by the Ecmascript grammar as "no-ops", e.g. "\d" === "" but must be rejected
* by JSON parsing.
*/
print('character escapes');
function testCharacterEscape(x) {
var lit = '"' + '\\' + String.fromCharCode(x) + '"';
var t;
print('cp', x, String.fromCharCode(x));
// Escape chars 'b', 'f', 'n', 't', 'v' will decode to special characters.
// Escape chars 'x' and 'u' will be rejected as unterminated hex/unicode
// escapes.
try {
t = eval(lit);
print('eval', t.length, t.charCodeAt(0));
} catch (e) {
print('eval', e.name);
}
try {
t = JSON.parse(lit);
print('json', t.length, t.charCodeAt(0));
} catch (e) {
print('json', e.name);
}
}
function testCharacterEscapes() {
var i;
var cp;
for (i = 0; i < 26; i++) {
cp = 97 + i; /* a to z */
testCharacterEscape(cp);
}
}
try {
testCharacterEscapes();
} catch (e) {
print(e.name);
}
/*===
zero escape
0
SyntaxError
===*/
/* Ecmascript strings accept a zero escape, JSONString does not. */
print('zero escape');
try {
print(eval('"\\0"').charCodeAt(0));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('"\\0"').charCodeAt(0));
} catch (e) {
print(e.name);
}
/*===
forward slash escape
/
===*/
/* JSONString accepts forward slash escape (although JSON.stringify() never
* produces it).
*/
print('forward slash escape');
try {
print(JSON.parse('"\\/"'));
} catch (e) {
print(e.name);
}
/*===
hex escape
A
SyntaxError
===*/
/* JSONString does not accept hex escapes, Ecmascript strings do. */
print('hex escape');
try {
print(eval('"\\x41"'));
print(JSON.parse('"\\x41"'));
} catch (e) {
print(e.name);
}
/*===
null literal
null
===*/
print('null literal');
try {
print(JSON.parse('null'));
} catch (e) {
print(e.name);
}
/*===
boolean literal
true
false
===*/
print('boolean literal');
try {
print(JSON.parse('true'));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse('false'));
} catch (e) {
print(e.name);
}
/*===
tostring coercion of true/false/null
true
false
null
===*/
/* parse() argument is ToString() coerced, so these will parse back;
* e.g. true -> "true" -> true.
*/
print('tostring coercion of true/false/null');
try {
print(JSON.parse(true));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse(false));
} catch (e) {
print(e.name);
}
try {
print(JSON.parse(null));
} catch (e) {
print(e.name);
}