| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 // Patch file for dart:convert library. | 5 // Patch file for dart:convert library. |
| 6 | 6 |
| 7 import 'dart:_js_helper' show patch; | 7 import 'dart:_js_helper' show patch; |
| 8 import 'dart:_foreign_helper' show JS; | 8 import 'dart:_foreign_helper' show JS; |
| 9 import 'dart:_interceptors' show JSExtendableArray; | 9 import 'dart:_interceptors' show JSExtendableArray; |
| 10 import 'dart:_internal' show MappedIterable; | 10 import 'dart:_internal' show MappedIterable; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 45 return _convertJsonToDart(parsed, reviver); | 45 return _convertJsonToDart(parsed, reviver); |
| 46 } | 46 } |
| 47 } | 47 } |
| 48 | 48 |
| 49 /** | 49 /** |
| 50 * Walks the raw JavaScript value [json], replacing JavaScript Objects with | 50 * Walks the raw JavaScript value [json], replacing JavaScript Objects with |
| 51 * Maps. [json] is expected to be freshly allocated so elements can be replaced | 51 * Maps. [json] is expected to be freshly allocated so elements can be replaced |
| 52 * in-place. | 52 * in-place. |
| 53 */ | 53 */ |
| 54 _convertJsonToDart(json, reviver(key, value)) { | 54 _convertJsonToDart(json, reviver(key, value)) { |
| 55 var revive = reviver == null ? (key, value) => value : reviver; | 55 assert(reviver != null); |
| 56 | |
| 57 walk(e) { | 56 walk(e) { |
| 58 // JavaScript null, string, number, bool are in the correct representation. | 57 // JavaScript null, string, number, bool are in the correct representation. |
| 59 if (JS('bool', '# == null', e) || JS('bool', 'typeof # != "object"', e)) { | 58 if (JS('bool', '# == null', e) || JS('bool', 'typeof # != "object"', e)) { |
| 60 return e; | 59 return e; |
| 61 } | 60 } |
| 62 | 61 |
| 63 // This test is needed to avoid identifing '{"__proto__":[]}' as an Array. | 62 // This test is needed to avoid identifing '{"__proto__":[]}' as an Array. |
| 64 // TODO(sra): Replace this test with cheaper '#.constructor === Array' when | 63 // TODO(sra): Replace this test with cheaper '#.constructor === Array' when |
| 65 // bug 621 below is fixed. | 64 // bug 621 below is fixed. |
| 66 if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) { | 65 if (JS('bool', 'Object.getPrototypeOf(#) === Array.prototype', e)) { |
| 67 // Teach compiler the type is known by passing it through a JS-expression. | |
| 68 var list = JS('JSExtendableArray', '#', e); | |
| 69 // In-place update of the elements since JS Array is a Dart List. | 66 // In-place update of the elements since JS Array is a Dart List. |
| 70 for (int i = 0; i < list.length; i++) { | 67 for (int i = 0; i < JS('int', '#.length', e); i++) { |
| 71 // Use JS indexing to avoid range checks. We know this is the only | 68 // Use JS indexing to avoid range checks. We know this is the only |
| 72 // reference to the list, but the compiler will likely never be able to | 69 // reference to the list, but the compiler will likely never be able to |
| 73 // tell that this instance of the list cannot have its length changed by | 70 // tell that this instance of the list cannot have its length changed by |
| 74 // the reviver even though it later will be passed to the reviver at the | 71 // the reviver even though it later will be passed to the reviver at the |
| 75 // outer level. | 72 // outer level. |
| 76 var item = JS('', '#[#]', list, i); | 73 var item = JS('', '#[#]', e, i); |
| 77 JS('', '#[#]=#', list, i, revive(i, walk(item))); | 74 JS('', '#[#]=#', e, i, reviver(i, walk(item))); |
| 78 } | 75 } |
| 79 return list; | 76 return e; |
| 80 } | 77 } |
| 81 | 78 |
| 82 // Otherwise it is a plain Object, so copy to a Map. | 79 // Otherwise it is a plain object, so copy to a JSON map, so we process |
| 83 var keys = JS('JSExtendableArray', 'Object.keys(#)', e); | 80 // and revive all entries recursively. |
| 84 Map map = {}; | 81 _JsonMap map = new _JsonMap(e); |
| 82 var processed = map._processed; |
| 83 List<String> keys = map._computeKeys(); |
| 85 for (int i = 0; i < keys.length; i++) { | 84 for (int i = 0; i < keys.length; i++) { |
| 86 String key = keys[i]; | 85 String key = keys[i]; |
| 87 map[key] = revive(key, walk(JS('', '#[#]', e, key))); | 86 var revived = reviver(key, walk(JS('', '#[#]', e, key))); |
| 87 JS('', '#[#]=#', processed, key, revived); |
| 88 } | 88 } |
| 89 // V8 has a bug with properties named "__proto__" | 89 |
| 90 // https://code.google.com/p/v8/issues/detail?id=621 | 90 // Update the JSON map structure so future access is cheaper. |
| 91 var proto = JS('', '#.__proto__', e); | 91 map._original = processed; // Don't keep two objects around. |
| 92 // __proto__ can be undefined on IE9. | |
| 93 if (JS('bool', | |
| 94 'typeof # !== "undefined" && # !== Object.prototype', | |
| 95 proto, proto)) { | |
| 96 map['__proto__'] = revive('__proto__', walk(proto)); | |
| 97 } | |
| 98 return map; | 92 return map; |
| 99 } | 93 } |
| 100 | 94 |
| 101 return revive(null, walk(json)); | 95 return reviver(null, walk(json)); |
| 102 } | 96 } |
| 103 | 97 |
| 104 _convertJsonToDartLazy(object) { | 98 _convertJsonToDartLazy(object) { |
| 105 // JavaScript null and undefined are represented as null. | 99 // JavaScript null and undefined are represented as null. |
| 106 if (object == null) return null; | 100 if (object == null) return null; |
| 107 | 101 |
| 108 // JavaScript string, number, bool already has the correct representation. | 102 // JavaScript string, number, bool already has the correct representation. |
| 109 if (JS('bool', 'typeof # != "object"', object)) { | 103 if (JS('bool', 'typeof # != "object"', object)) { |
| 110 return object; | 104 return object; |
| 111 } | 105 } |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 166 |
| 173 Iterable get values { | 167 Iterable get values { |
| 174 if (_isUpgraded) return _upgradedMap.values; | 168 if (_isUpgraded) return _upgradedMap.values; |
| 175 return new MappedIterable(_computeKeys(), (each) => this[each]); | 169 return new MappedIterable(_computeKeys(), (each) => this[each]); |
| 176 } | 170 } |
| 177 | 171 |
| 178 operator[]=(key, value) { | 172 operator[]=(key, value) { |
| 179 if (_isUpgraded) { | 173 if (_isUpgraded) { |
| 180 _upgradedMap[key] = value; | 174 _upgradedMap[key] = value; |
| 181 } else if (containsKey(key)) { | 175 } else if (containsKey(key)) { |
| 182 _setProperty(_processed, key, value); | 176 var processed = _processed; |
| 183 _setProperty(_original, key, null); // Reclaim memory. | 177 _setProperty(processed, key, value); |
| 178 var original = _original; |
| 179 if (!identical(original, processed)) { |
| 180 _setProperty(original, key, null); // Reclaim memory. |
| 181 } |
| 184 } else { | 182 } else { |
| 185 _upgrade()[key] = value; | 183 _upgrade()[key] = value; |
| 186 } | 184 } |
| 187 } | 185 } |
| 188 | 186 |
| 189 void addAll(Map other) { | 187 void addAll(Map other) { |
| 190 other.forEach((key, value) { | 188 other.forEach((key, value) { |
| 191 this[key] = value; | 189 this[key] = value; |
| 192 }); | 190 }); |
| 193 } | 191 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 static _newJavaScriptObject() | 334 static _newJavaScriptObject() |
| 337 => JS('=Object', 'Object.create(null)'); | 335 => JS('=Object', 'Object.create(null)'); |
| 338 } | 336 } |
| 339 | 337 |
| 340 @patch | 338 @patch |
| 341 class _Utf8Encoder { | 339 class _Utf8Encoder { |
| 342 // Use Uint8List when supported on all platforms. | 340 // Use Uint8List when supported on all platforms. |
| 343 @patch | 341 @patch |
| 344 static List<int> _createBuffer(int size) => new List<int>(size); | 342 static List<int> _createBuffer(int size) => new List<int>(size); |
| 345 } | 343 } |
| OLD | NEW |