Index: sdk/lib/html/html_common/conversions.dart |
diff --git a/sdk/lib/html/html_common/conversions.dart b/sdk/lib/html/html_common/conversions.dart |
index de0d423258d971447938882f573cc9e49e86fd09..fa7f43c0e55fff2aa9fd49cc3886c423bd2d4c7d 100644 |
--- a/sdk/lib/html/html_common/conversions.dart |
+++ b/sdk/lib/html/html_common/conversions.dart |
@@ -58,21 +58,15 @@ convertNativeToDart_SerializedScriptValue(object) { |
*/ |
abstract class _StructuredClone { |
- // TODO(sra): Replace slots with identity hash table. |
- var values = []; |
- var copies = []; // initially 'null', 'true' during initial DFS, then a copy. |
- |
- int findSlot(value) { |
- int length = values.length; |
- for (int i = 0; i < length; i++) { |
- if (identical(values[i], value)) return i; |
- } |
- values.add(value); |
- copies.add(null); |
- return length; |
+ // Keep track of the clones, keyed by the original object. If we're |
+ // not copying, these may be the same. |
+ var clones = new HashMap.identity(); |
sra1
2016/03/22 00:54:21
Be careful here.
The implementation of identityHa
Alan Knight
2016/03/22 18:00:01
OK, I moved the code to use an identity map down i
|
+ |
+ Object findSlot(value) { |
+ return clones.putIfAbsent(value, () => null); |
} |
- readSlot(int i) => copies[i]; |
- writeSlot(int i, x) { copies[i] = x; } |
+ readSlot(Object original) => clones[original]; |
+ writeSlot(Object original, clone) { clones[original] = clone; } |
cleanupSlots() {} // Will be needed if we mark objects with a property. |
bool cloneNotRequired(object); |
newJsMap(); |
@@ -109,11 +103,10 @@ abstract class _StructuredClone { |
if (cloneNotRequired(e)) return e; |
if (e is Map) { |
- var slot = findSlot(e); |
- var copy = readSlot(slot); |
+ var copy = findSlot(e); |
if (copy != null) return copy; |
copy = newJsMap(); |
- writeSlot(slot, copy); |
+ writeSlot(e, copy); |
e.forEach((key, value) { |
putIntoMap(copy, key, walk(value)); |
}); |
@@ -126,21 +119,20 @@ abstract class _StructuredClone { |
// to copy anything reachable from the array. However, the list may have |
// non-native properties or methods from interceptors and such, e.g. |
// an immutability marker. So we had to stop doing that. |
- var slot = findSlot(e); |
- var copy = readSlot(slot); |
+ var copy = findSlot(e); |
if (copy != null) return copy; |
- copy = copyList(e, slot); |
+ copy = copyList(e); |
return copy; |
} |
throw new UnimplementedError('structured clone of other type'); |
} |
- copyList(List e, int slot) { |
+ copyList(List e) { |
int i = 0; |
int length = e.length; |
var copy = newJsList(length); |
- writeSlot(slot, copy); |
+ writeSlot(e, copy); |
for ( ; i < length; i++) { |
copy[i] = walk(e[i]); |
} |
@@ -174,26 +166,19 @@ abstract class _StructuredClone { |
*/ |
abstract class _AcceptStructuredClone { |
- // TODO(sra): Replace slots with identity hash table. |
- var values = []; |
- var copies = []; // initially 'null', 'true' during initial DFS, then a copy. |
+ // Keep track of the clones, keyed by the original object. If we're |
+ // not copying, these may be the same. |
+ var clones = new HashMap.identity(); |
bool mustCopy = false; |
- int findSlot(value) { |
- int length = values.length; |
- for (int i = 0; i < length; i++) { |
- if (identicalInJs(values[i], value)) return i; |
- } |
- values.add(value); |
- copies.add(null); |
- return length; |
+ Object findSlot(value) { |
+ return clones.putIfAbsent(value, () => null); |
} |
/// Are the two objects identical, but taking into account that two JsObject |
/// wrappers may not be identical, but their underlying Js Object might be. |
bool identicalInJs(a, b); |
- readSlot(int i) => copies[i]; |
- writeSlot(int i, x) { copies[i] = x; } |
+ writeSlot(original, x) { clones[original] = x; } |
/// Iterate over the JS properties. |
forEachJsField(object, action); |
@@ -224,26 +209,24 @@ abstract class _AcceptStructuredClone { |
if (isJavaScriptSimpleObject(e)) { |
// TODO(sra): If mustCopy is false, swizzle the prototype for one of a Map |
// implementation that uses the properies as storage. |
- var slot = findSlot(e); |
- var copy = readSlot(slot); |
+ var copy = findSlot(e); |
if (copy != null) return copy; |
copy = {}; |
- writeSlot(slot, copy); |
+ writeSlot(e, copy); |
forEachJsField(e, (key, value) => copy[key] = walk(value)); |
return copy; |
} |
if (isJavaScriptArray(e)) { |
- var slot = findSlot(e); |
- var copy = readSlot(slot); |
+ var copy = findSlot(e); |
if (copy != null) return copy; |
int length = e.length; |
// Since a JavaScript Array is an instance of Dart List, we can modify it |
// in-place unless we must copy. |
copy = mustCopy ? newDartList(length) : e; |
- writeSlot(slot, copy); |
+ writeSlot(e, copy); |
for (int i = 0; i < length; i++) { |
copy[i] = walk(e[i]); |