Chromium Code Reviews| Index: sdk/lib/_internal/compiler/implementation/lib/json_patch.dart |
| diff --git a/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..2e70c9bceeb2cc54bf0cfe3cbb6cadf8897003a0 |
| --- /dev/null |
| +++ b/sdk/lib/_internal/compiler/implementation/lib/json_patch.dart |
| @@ -0,0 +1,80 @@ |
| +// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
|
ngeoffray
2013/02/01 08:49:12
2012 -> 2013
|
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| + |
| +// Patch file for dart:json library. |
| + |
| +import 'dart:_foreign_helper' show JS; |
| + |
| +/** |
| + * Parses [json] and build the corresponding parsed JSON value. |
|
ngeoffray
2013/02/01 08:49:12
build -> builds
sra1
2013/02/01 21:52:44
Done.
|
| + * |
| + * Parsed JSON values are of the types [num], [String], [bool], [Null], |
| + * [List]s of parsed JSON values or [Map]s from [String] to parsed |
| + * JSON values. |
| + * |
| + * The optional [reviver] function, if provided, is called once for each object |
| + * or list property parsed. The arguments are the property name ([String]) or |
| + * list index ([int]), and the value is the parsed value. The return value of |
| + * the reviver will be used as the value of that property instead the parsed |
|
ngeoffray
2013/02/01 08:49:12
instead *of*
sra1
2013/02/01 21:52:44
Done.
|
| + * value. The top level value is passed to the reviver with the empty string as |
| + * a key. |
| + * |
| + * Throws [FormatException] if the input is not valid JSON text. |
| + */ |
| +patch parse(String json, [reviver(var key, var value)]) { |
| + if (json is! String) throw new ArgumentError(json); |
| + |
| + var parsed; |
| + try { |
| + parsed = JS('=Object|=List|Null|bool|num|String', 'JSON.parse(#)', json); |
| + } catch (e) { |
|
ngeoffray
2013/02/01 08:49:12
`e` not being a Dart exception, I wonder how well
|
| + throw new FormatException(JS('String', 'String(#)', e)); |
| + } |
| + |
| + return _convertJsonToDart(parsed, reviver); |
| +} |
| + |
| +/** |
| + * Walks the raw JavaScript value [json], replacing JavaScript Objects with |
| + * Maps. [json] is expected to be freshly allocated so elements can be replaced |
| + * in-place. |
| + */ |
| +_convertJsonToDart(json, reviver(key, value)) { |
| + |
| + var revive = reviver == null ? (key, value) => value : reviver; |
| + |
| + walk(e) { |
| + // JavaScript null, string, number, bool are in the correct representation. |
| + if (e == null || JS('bool', 'typeof # != "object"', e)) { |
|
ngeoffray
2013/02/01 08:49:12
Since `e` can be anything, it's safer to use JS(bo
sra1
2013/02/01 21:52:44
Done.
|
| + return e; |
| + } |
| + // TODO(sra): Replace this test with cheaper '#.constructor === Array' when |
| + // bug 621 below is fixed. |
|
ngeoffray
2013/02/01 08:49:12
Why is the getPrototypeOf needed?
sra1
2013/02/01 21:52:44
Done.
|
| + if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) { |
| + var list = JS('=List', '#', e); // Teach compiler the type is known. |
| + // In-place update of the elements since JS Array is a Dart List. |
| + for (int i = 0; i < list.length; i++) { |
| + list[i] = revive(i, walk(list[i])); |
| + } |
| + return list; |
| + } |
| + |
| + // Otherwise it is a plain Object, so copy to a Map. |
| + var keys = JS('=List', 'Object.keys(#)', e); |
| + var map = {}; |
| + for (int i = 0; i < keys.length; i++) { |
| + String key = keys[i]; |
|
Lasse Reichstein Nielsen
2013/02/01 12:33:32
Keys also gets property names from the prototype,
sra1
2013/02/01 21:52:44
"Returns an array of a given object's own enumerab
Lasse Reichstein Nielsen
2013/02/02 11:16:23
Ack, my bad.
|
| + map[key] = revive(key, walk(JS('', '#[#]', e, key))); |
| + } |
| + // V8 has a bug with properties named "__proto__" |
| + // https://code.google.com/p/v8/issues/detail?id=621 |
| + var proto = JS('', '#.__proto__', e); |
| + if (JS('bool', '# !== Object.prototype', proto)) { |
| + map['__proto__'] = revive('__proto__', walk(proto)); |
| + } |
| + return map; |
| + } |
| + |
| + return revive('', walk(json)); |
| +} |