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 argumentErrorValue, patch; | 7 import 'dart:_js_helper' show argumentErrorValue, 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, ListIterable; | 10 import 'dart:_internal' show MappedIterable, ListIterable; |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 // reference to the list, but the compiler will likely never be able to | 116 // reference to the list, but the compiler will likely never be able to |
117 // tell that this instance of the list cannot have its length changed by | 117 // tell that this instance of the list cannot have its length changed by |
118 // the reviver even though it later will be passed to the reviver at the | 118 // the reviver even though it later will be passed to the reviver at the |
119 // outer level. | 119 // outer level. |
120 var item = JS('', '#[#]', object, i); | 120 var item = JS('', '#[#]', object, i); |
121 JS('', '#[#]=#', object, i, _convertJsonToDartLazy(item)); | 121 JS('', '#[#]=#', object, i, _convertJsonToDartLazy(item)); |
122 } | 122 } |
123 return object; | 123 return object; |
124 } | 124 } |
125 | 125 |
126 class _JsonMap implements LinkedHashMap { | 126 class _JsonMap implements Map<String, dynamic> { |
127 // The original JavaScript object remains unchanged until | 127 // The original JavaScript object remains unchanged until |
128 // the map is eventually upgraded, in which case we null it | 128 // the map is eventually upgraded, in which case we null it |
129 // out to reclaim the memory used by it. | 129 // out to reclaim the memory used by it. |
130 var _original; | 130 var _original; |
131 | 131 |
132 // We keep track of the map entries that we have already | 132 // We keep track of the map entries that we have already |
133 // processed by adding them to a separate JavaScript object. | 133 // processed by adding them to a separate JavaScript object. |
134 var _processed = _newJavaScriptObject(); | 134 var _processed = _newJavaScriptObject(); |
135 | 135 |
136 // If the data slot isn't null, it represents either the list | 136 // If the data slot isn't null, it represents either the list |
(...skipping 12 matching lines...) Expand all Loading... | |
149 if (_isUnprocessed(result)) result = _process(key); | 149 if (_isUnprocessed(result)) result = _process(key); |
150 return result; | 150 return result; |
151 } | 151 } |
152 } | 152 } |
153 | 153 |
154 int get length => _isUpgraded ? _upgradedMap.length : _computeKeys().length; | 154 int get length => _isUpgraded ? _upgradedMap.length : _computeKeys().length; |
155 | 155 |
156 bool get isEmpty => length == 0; | 156 bool get isEmpty => length == 0; |
157 bool get isNotEmpty => length > 0; | 157 bool get isNotEmpty => length > 0; |
158 | 158 |
159 Iterable get keys { | 159 Iterable<String> get keys { |
160 if (_isUpgraded) return _upgradedMap.keys; | 160 if (_isUpgraded) return _upgradedMap.keys; |
161 return new _JsonMapKeyIterable(this); | 161 return new _JsonMapKeyIterable(this); |
162 } | 162 } |
163 | 163 |
164 Iterable get values { | 164 Iterable get values { |
165 if (_isUpgraded) return _upgradedMap.values; | 165 if (_isUpgraded) return _upgradedMap.values; |
166 return new MappedIterable(_computeKeys(), (each) => this[each]); | 166 return new MappedIterable(_computeKeys(), (each) => this[each]); |
167 } | 167 } |
168 | 168 |
169 operator []=(key, value) { | 169 operator []=(key, value) { |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 | 273 |
274 List<String> _computeKeys() { | 274 List<String> _computeKeys() { |
275 assert(!_isUpgraded); | 275 assert(!_isUpgraded); |
276 List keys = _data; | 276 List keys = _data; |
277 if (keys == null) { | 277 if (keys == null) { |
278 keys = _data = _getPropertyNames(_original); | 278 keys = _data = _getPropertyNames(_original); |
279 } | 279 } |
280 return JS('JSExtendableArray', '#', keys); | 280 return JS('JSExtendableArray', '#', keys); |
281 } | 281 } |
282 | 282 |
283 Map _upgrade() { | 283 Map<String, dynamic> _upgrade() { |
284 if (_isUpgraded) return _upgradedMap; | 284 if (_isUpgraded) return _upgradedMap; |
285 | 285 |
286 // Copy all the (key, value) pairs to a freshly allocated | 286 // Copy all the (key, value) pairs to a freshly allocated |
287 // linked hash map thus preserving the ordering. | 287 // linked hash map thus preserving the ordering. |
288 Map result = {}; | 288 Map result = <String, dynamic>{}; |
vsm
2017/05/24 00:02:18
If we have Map here, the static type of result is
| |
289 List<String> keys = _computeKeys(); | 289 List<String> keys = _computeKeys(); |
290 for (int i = 0; i < keys.length; i++) { | 290 for (int i = 0; i < keys.length; i++) { |
291 String key = keys[i]; | 291 String key = keys[i]; |
292 result[key] = this[key]; | 292 result[key] = this[key]; |
293 } | 293 } |
294 | 294 |
295 // We only upgrade when we need to extend the map, so we can | 295 // We only upgrade when we need to extend the map, so we can |
296 // safely force a concurrent modification error in case | 296 // safely force a concurrent modification error in case |
297 // someone is iterating over the map here. | 297 // someone is iterating over the map here. |
298 if (keys.isEmpty) { | 298 if (keys.isEmpty) { |
(...skipping 25 matching lines...) Expand all Loading... | |
324 static _getProperty(object, String key) => JS('', '#[#]', object, key); | 324 static _getProperty(object, String key) => JS('', '#[#]', object, key); |
325 static _setProperty(object, String key, value) => | 325 static _setProperty(object, String key, value) => |
326 JS('', '#[#]=#', object, key, value); | 326 JS('', '#[#]=#', object, key, value); |
327 static List _getPropertyNames(object) => | 327 static List _getPropertyNames(object) => |
328 JS('JSExtendableArray', 'Object.keys(#)', object); | 328 JS('JSExtendableArray', 'Object.keys(#)', object); |
329 static bool _isUnprocessed(object) => | 329 static bool _isUnprocessed(object) => |
330 JS('bool', 'typeof(#)=="undefined"', object); | 330 JS('bool', 'typeof(#)=="undefined"', object); |
331 static _newJavaScriptObject() => JS('=Object', 'Object.create(null)'); | 331 static _newJavaScriptObject() => JS('=Object', 'Object.create(null)'); |
332 } | 332 } |
333 | 333 |
334 class _JsonMapKeyIterable extends ListIterable { | 334 class _JsonMapKeyIterable extends ListIterable<String> { |
335 final _JsonMap _parent; | 335 final _JsonMap _parent; |
336 | 336 |
337 _JsonMapKeyIterable(this._parent); | 337 _JsonMapKeyIterable(this._parent); |
338 | 338 |
339 int get length => _parent.length; | 339 int get length => _parent.length; |
340 | 340 |
341 String elementAt(int index) { | 341 String elementAt(int index) { |
342 return _parent._isUpgraded | 342 return _parent._isUpgraded |
343 ? _parent.keys.elementAt(index) | 343 ? _parent.keys.elementAt(index) |
344 : _parent._computeKeys()[index]; | 344 : _parent._computeKeys()[index]; |
345 } | 345 } |
346 | 346 |
347 /// Although [ListIterable] defines its own iterator, we return the iterator | 347 /// Although [ListIterable] defines its own iterator, we return the iterator |
348 /// of the underlying list [_keys] in order to propagate | 348 /// of the underlying list [_keys] in order to propagate |
349 /// [ConcurrentModificationError]s. | 349 /// [ConcurrentModificationError]s. |
350 Iterator get iterator { | 350 Iterator<String> get iterator { |
351 return _parent._isUpgraded | 351 return _parent._isUpgraded |
352 ? _parent.keys.iterator | 352 ? _parent.keys.iterator |
353 : _parent._computeKeys().iterator; | 353 : _parent._computeKeys().iterator; |
354 } | 354 } |
355 | 355 |
356 /// Delegate to [parent.containsKey] to ensure the performance expected | 356 /// Delegate to [parent.containsKey] to ensure the performance expected |
357 /// from [Map.keys.containsKey]. | 357 /// from [Map.keys.containsKey]. |
358 bool contains(Object key) => _parent.containsKey(key); | 358 bool contains(Object key) => _parent.containsKey(key); |
359 } | 359 } |
360 | 360 |
361 @patch | 361 @patch |
362 class JsonDecoder { | 362 class JsonDecoder { |
363 @patch | 363 @patch |
364 StringConversionSink startChunkedConversion(Sink<Object> sink) { | 364 StringConversionSink startChunkedConversion(Sink<Object> sink) { |
365 return new _JsonDecoderSink(_reviver, sink); | 365 return new _JsonDecoderSink(_reviver, sink); |
366 } | 366 } |
367 } | 367 } |
368 | 368 |
369 /** | 369 /** |
370 * Implements the chunked conversion from a JSON string to its corresponding | 370 * Implements the chunked conversion from a JSON string to its corresponding |
371 * object. | 371 * object. |
372 * | 372 * |
373 * The sink only creates one object, but its input can be chunked. | 373 * The sink only creates one object, but its input can be chunked. |
374 */ | 374 */ |
375 // TODO(floitsch): don't accumulate everything before starting to decode. | 375 // TODO(floitsch): don't accumulate everything before starting to decode. |
376 class _JsonDecoderSink extends _StringSinkConversionSink { | 376 class _JsonDecoderSink extends _StringSinkConversionSink { |
377 final _Reviver _reviver; | 377 final _Reviver _reviver; |
378 final Sink<Object> _sink; | 378 final Sink<Object> _sink; |
379 | 379 |
380 _JsonDecoderSink(this._reviver, this._sink) : super(new StringBuffer()); | 380 _JsonDecoderSink(this._reviver, this._sink) : super(new StringBuffer('')); |
381 | 381 |
382 void close() { | 382 void close() { |
383 super.close(); | 383 super.close(); |
384 StringBuffer buffer = _stringSink; | 384 StringBuffer buffer = _stringSink; |
385 String accumulated = buffer.toString(); | 385 String accumulated = buffer.toString(); |
386 buffer.clear(); | 386 buffer.clear(); |
387 Object decoded = _parseJson(accumulated, _reviver); | 387 Object decoded = _parseJson(accumulated, _reviver); |
388 _sink.add(decoded); | 388 _sink.add(decoded); |
389 _sink.close(); | 389 _sink.close(); |
390 } | 390 } |
391 } | 391 } |
392 | 392 |
393 @patch | 393 @patch |
394 class Utf8Decoder { | 394 class Utf8Decoder { |
395 @patch | 395 @patch |
396 Converter<List<int>, dynamic/*=T*/ > fuse/*<T>*/( | 396 Converter<List<int>, T> fuse<T>(Converter<String, T> next) { |
397 Converter<String, dynamic/*=T*/ > next) { | 397 return super.fuse(next); |
398 return super.fuse/*<T>*/(next); | |
399 } | 398 } |
400 | 399 |
401 // Currently not intercepting UTF8 decoding. | 400 // Currently not intercepting UTF8 decoding. |
402 @patch | 401 @patch |
403 static String _convertIntercepted( | 402 static String _convertIntercepted( |
404 bool allowMalformed, List<int> codeUnits, int start, int end) { | 403 bool allowMalformed, List<int> codeUnits, int start, int end) { |
405 return null; // This call was not intercepted. | 404 return null; // This call was not intercepted. |
406 } | 405 } |
407 } | 406 } |
OLD | NEW |