OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 | 5 |
6 // Conversions for IDBKey. | 6 // Conversions for IDBKey. |
7 // | 7 // |
8 // Per http://www.w3.org/TR/IndexedDB/#key-construct | 8 // Per http://www.w3.org/TR/IndexedDB/#key-construct |
9 // | 9 // |
10 // "A value is said to be a valid key if it is one of the following types: Array | 10 // "A value is said to be a valid key if it is one of the following types: Array |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 } | 92 } |
93 return imageData; | 93 return imageData; |
94 } | 94 } |
95 | 95 |
96 | 96 |
97 /// Converts a JavaScript object with properties into a Dart Map. | 97 /// Converts a JavaScript object with properties into a Dart Map. |
98 /// Not suitable for nested objects. | 98 /// Not suitable for nested objects. |
99 Map _convertNativeToDart_Dictionary(object) { | 99 Map _convertNativeToDart_Dictionary(object) { |
100 if (object == null) return null; | 100 if (object == null) return null; |
101 var dict = {}; | 101 var dict = {}; |
102 for (final key in JS('List', 'Object.getOwnPropertyNames(#)', object)) { | 102 for (final key in JS('=List', 'Object.getOwnPropertyNames(#)', object)) { |
103 dict[key] = JS('var', '#[#]', object, key); | 103 dict[key] = JS('var', '#[#]', object, key); |
104 } | 104 } |
105 return dict; | 105 return dict; |
106 } | 106 } |
107 | 107 |
108 /// Converts a flat Dart map into a JavaScript object with properties. | 108 /// Converts a flat Dart map into a JavaScript object with properties. |
109 _convertDartToNative_Dictionary(Map dict) { | 109 _convertDartToNative_Dictionary(Map dict) { |
110 if (dict == null) return null; | 110 if (dict == null) return null; |
111 var object = JS('var', '{}'); | 111 var object = JS('var', '{}'); |
112 dict.forEach((String key, value) { | 112 dict.forEach((String key, value) { |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 if (e is List) { | 269 if (e is List) { |
270 // Since a JavaScript Array is an instance of Dart List it is possible to | 270 // Since a JavaScript Array is an instance of Dart List it is possible to |
271 // avoid making a copy of the list if there is no need to copy anything | 271 // avoid making a copy of the list if there is no need to copy anything |
272 // reachable from the array. We defer creating a new array until a cycle | 272 // reachable from the array. We defer creating a new array until a cycle |
273 // is detected or a subgraph was copied. | 273 // is detected or a subgraph was copied. |
274 int length = e.length; | 274 int length = e.length; |
275 var slot = findSlot(e); | 275 var slot = findSlot(e); |
276 var copy = readSlot(slot); | 276 var copy = readSlot(slot); |
277 if (copy != null) { | 277 if (copy != null) { |
278 if (true == copy) { // Cycle, so commit to making a copy. | 278 if (true == copy) { // Cycle, so commit to making a copy. |
279 copy = JS('List', 'new Array(#)', length); | 279 copy = JS('=List', 'new Array(#)', length); |
280 writeSlot(slot, copy); | 280 writeSlot(slot, copy); |
281 } | 281 } |
282 return copy; | 282 return copy; |
283 } | 283 } |
284 | 284 |
285 int i = 0; | 285 int i = 0; |
286 | 286 |
287 if (_isJavaScriptArray(e) && | 287 if (_isJavaScriptArray(e) && |
288 // We have to copy immutable lists, otherwise the structured clone | 288 // We have to copy immutable lists, otherwise the structured clone |
289 // algorithm will copy the .immutable$list marker property, making the | 289 // algorithm will copy the .immutable$list marker property, making the |
290 // list immutable when received! | 290 // list immutable when received! |
291 !_isImmutableJavaScriptArray(e)) { | 291 !_isImmutableJavaScriptArray(e)) { |
292 writeSlot(slot, true); // Deferred copy. | 292 writeSlot(slot, true); // Deferred copy. |
293 for ( ; i < length; i++) { | 293 for ( ; i < length; i++) { |
294 var element = e[i]; | 294 var element = e[i]; |
295 var elementCopy = walk(element); | 295 var elementCopy = walk(element); |
296 if (!identical(elementCopy, element)) { | 296 if (!identical(elementCopy, element)) { |
297 copy = readSlot(slot); // Cyclic reference may have created it. | 297 copy = readSlot(slot); // Cyclic reference may have created it. |
298 if (true == copy) { | 298 if (true == copy) { |
299 copy = JS('List', 'new Array(#)', length); | 299 copy = JS('=List', 'new Array(#)', length); |
300 writeSlot(slot, copy); | 300 writeSlot(slot, copy); |
301 } | 301 } |
302 for (int j = 0; j < i; j++) { | 302 for (int j = 0; j < i; j++) { |
303 copy[j] = e[j]; | 303 copy[j] = e[j]; |
304 } | 304 } |
305 copy[i] = elementCopy; | 305 copy[i] = elementCopy; |
306 i++; | 306 i++; |
307 break; | 307 break; |
308 } | 308 } |
309 } | 309 } |
310 if (copy == null) { | 310 if (copy == null) { |
311 copy = e; | 311 copy = e; |
312 writeSlot(slot, copy); | 312 writeSlot(slot, copy); |
313 } | 313 } |
314 } else { | 314 } else { |
315 // Not a JavaScript Array. We are forced to make a copy. | 315 // Not a JavaScript Array. We are forced to make a copy. |
316 copy = JS('List', 'new Array(#)', length); | 316 copy = JS('=List', 'new Array(#)', length); |
317 writeSlot(slot, copy); | 317 writeSlot(slot, copy); |
318 } | 318 } |
319 | 319 |
320 for ( ; i < length; i++) { | 320 for ( ; i < length; i++) { |
321 copy[i] = walk(e[i]); | 321 copy[i] = walk(e[i]); |
322 } | 322 } |
323 return copy; | 323 return copy; |
324 } | 324 } |
325 | 325 |
326 throw new UnimplementedError('structured clone of other type'); | 326 throw new UnimplementedError('structured clone of other type'); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
386 | 386 |
387 if (_isJavaScriptSimpleObject(e)) { | 387 if (_isJavaScriptSimpleObject(e)) { |
388 // TODO(sra): If mustCopy is false, swizzle the prototype for one of a Map | 388 // TODO(sra): If mustCopy is false, swizzle the prototype for one of a Map |
389 // implementation that uses the properies as storage. | 389 // implementation that uses the properies as storage. |
390 var slot = findSlot(e); | 390 var slot = findSlot(e); |
391 var copy = readSlot(slot); | 391 var copy = readSlot(slot); |
392 if (copy != null) return copy; | 392 if (copy != null) return copy; |
393 copy = {}; | 393 copy = {}; |
394 | 394 |
395 writeSlot(slot, copy); | 395 writeSlot(slot, copy); |
396 for (final key in JS('List', 'Object.keys(#)', e)) { | 396 for (final key in JS('=List', 'Object.keys(#)', e)) { |
397 copy[key] = walk(JS('var', '#[#]', e, key)); | 397 copy[key] = walk(JS('var', '#[#]', e, key)); |
398 } | 398 } |
399 return copy; | 399 return copy; |
400 } | 400 } |
401 | 401 |
402 if (_isJavaScriptArray(e)) { | 402 if (_isJavaScriptArray(e)) { |
403 var slot = findSlot(e); | 403 var slot = findSlot(e); |
404 var copy = readSlot(slot); | 404 var copy = readSlot(slot); |
405 if (copy != null) return copy; | 405 if (copy != null) return copy; |
406 | 406 |
407 int length = e.length; | 407 int length = e.length; |
408 // Since a JavaScript Array is an instance of Dart List, we can modify it | 408 // Since a JavaScript Array is an instance of Dart List, we can modify it |
409 // in-place unless we must copy. | 409 // in-place unless we must copy. |
410 copy = mustCopy ? JS('List', 'new Array(#)', length) : e; | 410 copy = mustCopy ? JS('=List', 'new Array(#)', length) : e; |
411 writeSlot(slot, copy); | 411 writeSlot(slot, copy); |
412 | 412 |
413 for (int i = 0; i < length; i++) { | 413 for (int i = 0; i < length; i++) { |
414 copy[i] = walk(e[i]); | 414 copy[i] = walk(e[i]); |
415 } | 415 } |
416 return copy; | 416 return copy; |
417 } | 417 } |
418 | 418 |
419 // Assume anything else is already a valid Dart object, either by having | 419 // Assume anything else is already a valid Dart object, either by having |
420 // already been processed, or e.g. a clonable native class. | 420 // already been processed, or e.g. a clonable native class. |
421 return e; | 421 return e; |
422 } | 422 } |
423 | 423 |
424 var copy = walk(object); | 424 var copy = walk(object); |
425 return copy; | 425 return copy; |
426 } | 426 } |
427 | 427 |
428 | 428 |
429 bool _isJavaScriptDate(value) => JS('bool', '# instanceof Date', value); | 429 bool _isJavaScriptDate(value) => JS('bool', '# instanceof Date', value); |
430 bool _isJavaScriptRegExp(value) => JS('bool', '# instanceof RegExp', value); | 430 bool _isJavaScriptRegExp(value) => JS('bool', '# instanceof RegExp', value); |
431 bool _isJavaScriptArray(value) => JS('bool', '# instanceof Array', value); | 431 bool _isJavaScriptArray(value) => JS('bool', '# instanceof Array', value); |
432 bool _isJavaScriptSimpleObject(value) => | 432 bool _isJavaScriptSimpleObject(value) => |
433 JS('bool', 'Object.getPrototypeOf(#) === Object.prototype', value); | 433 JS('bool', 'Object.getPrototypeOf(#) === Object.prototype', value); |
434 bool _isImmutableJavaScriptArray(value) => | 434 bool _isImmutableJavaScriptArray(value) => |
435 JS('bool', r'!!(#.immutable$list)', value); | 435 JS('bool', r'!!(#.immutable$list)', value); |
| 436 |
| 437 |
| 438 |
| 439 const String _serializedScriptValue = |
| 440 'num|String|bool|' |
| 441 '=List|=Object|' |
| 442 'Blob|File|ArrayBuffer|ArrayBufferView' |
| 443 // TODO(sra): Add Date, RegExp. |
| 444 ; |
| 445 const _annotation_Creates_SerializedScriptValue = |
| 446 const Creates(_serializedScriptValue); |
| 447 const _annotation_Returns_SerializedScriptValue = |
| 448 const Returns(_serializedScriptValue); |
| 449 |
| 450 const String _idbKey = '=List|=Object|num|String'; // TODO(sra): Add Date. |
| 451 const _annotation_Creates_IDBKey = const Creates(_idbKey); |
| 452 const _annotation_Returns_IDBKey = const Returns(_idbKey); |
OLD | NEW |