| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 // Patch file for dart:json library. | |
| 6 | |
| 7 import 'dart:_foreign_helper' show JS; | |
| 8 | |
| 9 /** | |
| 10 * Parses [json] and builds the corresponding parsed JSON value. | |
| 11 * | |
| 12 * Parsed JSON values are of the types [num], [String], [bool], [Null], | |
| 13 * [List]s of parsed JSON values or [Map]s from [String] to parsed | |
| 14 * JSON values. | |
| 15 * | |
| 16 * The optional [reviver] function, if provided, is called once for each object | |
| 17 * or list property parsed. The arguments are the property name ([String]) or | |
| 18 * list index ([int]), and the value is the parsed value. The return value of | |
| 19 * the reviver will be used as the value of that property instead of the parsed | |
| 20 * value. The top level value is passed to the reviver with the empty string as | |
| 21 * a key. | |
| 22 * | |
| 23 * Throws [FormatException] if the input is not valid JSON text. | |
| 24 */ | |
| 25 patch parse(String json, [reviver(var key, var value)]) { | |
| 26 if (json is! String) throw new ArgumentError(json); | |
| 27 | |
| 28 var parsed; | |
| 29 try { | |
| 30 parsed = JS('=Object|=List|Null|bool|num|String', 'JSON.parse(#)', json); | |
| 31 } catch (e) { | |
| 32 throw new FormatException(JS('String', 'String(#)', e)); | |
| 33 } | |
| 34 | |
| 35 return _convertJsonToDart(parsed, reviver); | |
| 36 } | |
| 37 | |
| 38 /** | |
| 39 * Walks the raw JavaScript value [json], replacing JavaScript Objects with | |
| 40 * Maps. [json] is expected to be freshly allocated so elements can be replaced | |
| 41 * in-place. | |
| 42 */ | |
| 43 _convertJsonToDart(json, reviver(key, value)) { | |
| 44 | |
| 45 var revive = reviver == null ? (key, value) => value : reviver; | |
| 46 | |
| 47 walk(e) { | |
| 48 // JavaScript null, string, number, bool are in the correct representation. | |
| 49 if (JS('bool', '# == null', e) || JS('bool', 'typeof # != "object"', e)) { | |
| 50 return e; | |
| 51 } | |
| 52 | |
| 53 // This test is needed to avoid identifing '{"__proto__":[]}' as an Array. | |
| 54 // TODO(sra): Replace this test with cheaper '#.constructor === Array' when | |
| 55 // bug 621 below is fixed. | |
| 56 if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) { | |
| 57 var list = JS('=List', '#', e); // Teach compiler the type is known. | |
| 58 // In-place update of the elements since JS Array is a Dart List. | |
| 59 for (int i = 0; i < list.length; i++) { | |
| 60 list[i] = revive(i, walk(list[i])); | |
| 61 } | |
| 62 return list; | |
| 63 } | |
| 64 | |
| 65 // Otherwise it is a plain Object, so copy to a Map. | |
| 66 var keys = JS('=List', 'Object.keys(#)', e); | |
| 67 var map = {}; | |
| 68 for (int i = 0; i < keys.length; i++) { | |
| 69 String key = keys[i]; | |
| 70 map[key] = revive(key, walk(JS('', '#[#]', e, key))); | |
| 71 } | |
| 72 // V8 has a bug with properties named "__proto__" | |
| 73 // https://code.google.com/p/v8/issues/detail?id=621 | |
| 74 var proto = JS('', '#.__proto__', e); | |
| 75 if (JS('bool', '# !== Object.prototype', proto)) { | |
| 76 map['__proto__'] = revive('__proto__', walk(proto)); | |
| 77 } | |
| 78 return map; | |
| 79 } | |
| 80 | |
| 81 return revive('', walk(json)); | |
| 82 } | |
| OLD | NEW |