• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright JS Foundation and other contributors, http://js.foundation
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// This test will not pass on FLOAT32 due to precision issues
16
17// Checking primitve types
18var str;
19var result;
20var log;
21
22function check_parse_error (str)
23{
24  try {
25    JSON.parse (str);
26    // Should throw a parse error.
27    assert (false);
28  } catch (e) {
29  }
30}
31
32str = ' null ';
33assert (JSON.parse (str) === null);
34str = 'true';
35assert (JSON.parse (str) === true);
36str = 'false';
37assert (JSON.parse (str) === false);
38str = '-32.5e002';
39assert (JSON.parse (str) == -3250);
40str = '"str"';
41assert (JSON.parse (str) == "str");
42str = '"\\b\\f\\n\\t\\r"'
43assert (JSON.parse (str) === "\b\f\n\t\r");
44/* Note: \u is parsed by the lexer, \\u is by the JSON parser. */
45str = '"\\u0000\\u001f"';
46assert (JSON.parse (str) === "\x00\x1f");
47str = '"\\ud801\\udc00\\ud801\udc00\ud801\\udc00\ud801\udc00"';
48assert (JSON.parse (str) === "\ud801\udc00\ud801\udc00\ud801\udc00\ud801\udc00");
49/* These surrogates do not form a valid surrogate pairs. */
50str = '"\\ud801,\\udc00,\\ud801,\udc00,\ud801,\\udc00,\ud801,\udc00"';
51assert (JSON.parse (str) === "\ud801,\udc00,\ud801,\udc00,\ud801,\udc00,\ud801,\udc00");
52
53check_parse_error ('undefined');
54check_parse_error ('falses');
55check_parse_error ('+5');
56check_parse_error ('5.');
57check_parse_error ('01');
58check_parse_error ('0x1');
59check_parse_error ('0e-');
60check_parse_error ('3e+a');
61check_parse_error ('55e4,');
62check_parse_error ('5 true');
63check_parse_error ("'str'");
64check_parse_error ('\x00');
65check_parse_error ('"\x00"');
66check_parse_error ('"\x1f"');
67
68// Checking objects
69str = ' { "x": 0, "yy": null, "zzz": { "A": 4.0, "BB": { "1": 63e-1 }, "CCC" : false } } ';
70result = JSON.parse (str);
71assert (typeof result == "object");
72assert (result.x === 0);
73assert (result.yy === null);
74assert (typeof result.zzz == "object");
75assert (result.zzz.A === 4);
76assert (typeof result.zzz.BB == "object");
77assert (result.zzz.BB["1"] === 6.3);
78assert (result.zzz.CCC === false);
79
80check_parse_error ('{');
81check_parse_error ('{{{}');
82check_parse_error ('{x:5}');
83check_parse_error ('{true:4}');
84check_parse_error ('{"x":5 "y":6}');
85check_parse_error ('{"x":5,"y":6,}');
86check_parse_error ('{"x":5,,"y":6}');
87
88// Checking arrays
89str = '[{"x":[]},[[]],{}, [ null ] ]';
90result = JSON.parse (str);
91assert (result.length === 4);
92assert (typeof result === "object");
93assert (typeof result[0] === "object");
94assert (typeof result[0].x === "object");
95assert (result[0].x.length === 0);
96assert (result[1].length === 1);
97assert (result[1][0].length === 0);
98assert (typeof result[2] === "object");
99assert (result[3].length === 1);
100assert (result[3][0] === null);
101
102check_parse_error ('[');
103check_parse_error ('[[[]');
104check_parse_error ('[ true null ]');
105check_parse_error ('[1,,2]');
106check_parse_error ('[1,2,]');
107check_parse_error ('[1] [2]');
108
109// Checking parse with different primitive types
110
111assert (JSON.parse (null) == null);
112assert (JSON.parse (true) == true);
113assert (JSON.parse (3) == 3);
114
115try {
116  JSON.parse (undefined);
117  // Should not be reached.
118  assert (false);
119} catch (e) {
120  assert (e instanceof SyntaxError);
121}
122
123// Checking parse with different object types
124
125object = { toString: function() { return false; } };
126assert (JSON.parse (object) == false);
127
128object = {"a": 3, "b": "foo"};
129try {
130  JSON.parse (object);
131  // Should not be reached.
132  assert (false);
133} catch (e) {
134  assert (e instanceof SyntaxError);
135}
136
137array = [3, "foo"];
138try {
139  JSON.parse (array);
140  // Should not be reached.
141  assert (false);
142} catch (e) {
143  assert (e instanceof SyntaxError);
144}
145
146assert (JSON.parse (new Number (3)) == 3);
147assert (JSON.parse (new Boolean (true)) == true);
148
149object = new String ('{"a": 3, "b": "foo"}');
150result = JSON.parse (object);
151
152assert (result.a == 3);
153assert (result.b == "foo");
154
155// Checking reviver
156
157function toStringReviver(k, v)
158{
159  log += "<" + k + ">:" + (typeof v == "number" ? v : "(obj)") + ", ";
160  return v;
161}
162
163str = '{ "a":1, "b":2, "c": { "d":4, "e": { "f":6 } } }';
164log = "";
165JSON.parse (str, toStringReviver);
166assert (log === "<a>:1, <b>:2, <d>:4, <f>:6, <e>:(obj), <c>:(obj), <>:(obj), ");
167
168str = '[ 32, 47, 33 ]';
169log = "";
170JSON.parse (str, toStringReviver);
171assert (log === "<0>:32, <1>:47, <2>:33, <>:(obj), ");
172
173// Defining properties multiple times
174
175str = ' { "a":1, "b":2, "a":3 } ';
176log = "";
177JSON.parse (str, toStringReviver);
178assert (log === "<a>:3, <b>:2, <>:(obj), ");
179
180str = ' { "a":1, "b":2, "b":3 } ';
181log = "";
182JSON.parse (str, toStringReviver);
183assert (log === "<a>:1, <b>:3, <>:(obj), ");
184
185str = ' { "a":1, "b":{}, "b":[], "a":2, "b":3, "c":4 } ';
186log = "";
187JSON.parse (str, toStringReviver);
188assert (log === "<a>:2, <b>:3, <c>:4, <>:(obj), ");
189
190// Changing property value
191
192str = ' { "a":1, "b":2, "c":3 } ';
193result = JSON.parse (str, function (k, v) {
194  if (k == "a")
195  {
196    return 8;
197  }
198  if (k == "b")
199  {
200    return 9;
201  }
202  if (k == "c")
203  {
204    return void 0;
205  }
206  return v;
207});
208
209assert (result.a === 8);
210assert (result.b === 9);
211assert (result.c === void 0);
212
213// Adding / deleting properties
214
215str = ' { "a":1, "b":2 } ';
216log = "";
217result = JSON.parse (str, function (k, v) {
218  if (k == "a")
219  {
220    // Deleted properties must still be enumerated.
221    delete this["b"];
222    // New properties must not be enumerated.
223    this.c = 4;
224  }
225  if (k != "")
226  {
227    log += "<" + k + ">:" + v + " ";
228  }
229  return v;
230});
231
232assert (log === "<a>:1 <b>:undefined ");
233assert (result.a === 1);
234assert (result.b === void 0);
235assert (result.c === 4);
236
237// Changing properties to accessors
238
239str = ' { "a":1, "b":2, "c":3 } ';
240log = "";
241JSON.parse (str, function (k, v) {
242  if (k == "a")
243  {
244    Object.defineProperty(this, "b", {
245      enumerable: true,
246      configurable: true,
247      get: function() { return 12; }
248    });
249    Object.defineProperty(this, "c", {
250      enumerable: true,
251      configurable: true,
252      set: function(val) { }
253    });
254  }
255  if (k != "")
256  {
257    log += "<" + k + ">:" + v + " ";
258  }
259  return v;
260});
261assert (log === "<a>:1 <b>:12 <c>:undefined ");
262
263// Forcing extra walk steps
264
265str = ' { "a":1, "b":2 } ';
266log = "";
267JSON.parse (str, function (k, v) {
268  if (k == "a")
269  {
270     this.b = { x:3, y:4 };
271  }
272  if (k != "")
273  {
274    log += "<" + k + ">:" + v + " ";
275  }
276  return v;
277});
278assert (log === "<a>:1 <x>:3 <y>:4 <b>:[object Object] ");
279
280// Setting a property to read-only, and change its value.
281
282str = ' { "a":1, "b":2 } ';
283result = JSON.parse (str, function (k, v) {
284  if (k == "a")
285  {
286    Object.defineProperty(this, "b", {
287      enumerable: true,
288      // FIXME: Should work with configurable: true.
289      configurable: false,
290      writable: false,
291      value: 2
292    });
293    return 8;
294  }
295  if (k == "b")
296  {
297    return 9;
298  }
299  return v;
300});
301
302assert (result.a === 8);
303assert (result.b === 2);
304
305// Throw error in the reviver
306
307try {
308  str = ' { "a":1, "b":2 } ';
309  result = JSON.parse (str, function (k, v) { throw new ReferenceError("error"); } );
310  assert(false);
311} catch (e) {
312  assert (e.message === "error");
313  assert (e instanceof ReferenceError);
314}
315
316// Throw error in a getter
317
318try {
319  str = ' { "a":1, "b":2 } ';
320  JSON.parse (str, function (k, v) {
321    if (k == "a")
322    {
323      Object.defineProperty(this, "b", {
324        enumerable: true,
325        configurable: true,
326        get: function() { throw new ReferenceError("error"); }
327      });
328    }
329    return v;
330  });
331  assert(false);
332} catch (e) {
333  assert (e.message === "error");
334  assert (e instanceof ReferenceError);
335}
336
337// Checking reviver with different primitive types
338
339str = ' { "a":1 } ';
340
341result = JSON.parse (str, 4);
342assert (result.a == 1);
343
344result = JSON.parse (str, null);
345assert (result.a == 1);
346
347result = JSON.parse (str, undefined);
348assert (result.a == 1);
349
350result = JSON.parse (str, true);
351assert (result.a == 1);
352
353result = JSON.parse (str, "foo");
354assert (result.a == 1);
355
356// Checking reviver with different object types
357
358str = ' { "a":1 } ';
359
360result = JSON.parse(str, new Boolean (true));
361assert (result.a == 1);
362
363result = JSON.parse(str, new String ("foo"));
364assert (result.a == 1);
365
366result = JSON.parse(str, new Number (3));
367assert (result.a == 1);
368
369result = JSON.parse(str, {"a": 2});
370assert (result.a == 1);
371
372result = JSON.parse(str, [1, 2, 3]);
373assert (result.a == 1);
374