-
Notifications
You must be signed in to change notification settings - Fork 27.4k
perf(copy): use ES6 Map to track source/destination objects #13209
Changes from all commits
d8f593c
ed16ce1
6a102ef
5606fe8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -743,6 +743,46 @@ function arrayRemove(array, value) { | |
return index; | ||
} | ||
|
||
// A minimal ES6 Map implementation. | ||
// Should be bug/feature equivelent to the native implementations of supported browsers. | ||
// See https://kangax.github.io/compat-table/es6/#test-Map | ||
function ES6MapShim() { | ||
this._keys = []; | ||
this._values = []; | ||
this._lastKey = NaN; | ||
this._lastIndex = -1; | ||
} | ||
ES6MapShim.prototype = { | ||
_idx: function(key) { | ||
if (key === this._lastKey) { | ||
return this._lastIndex; | ||
} | ||
return (this._lastIndex = (this._keys.indexOf(this._lastKey = key))); | ||
}, | ||
get: function(key) { | ||
var idx = this._idx(key); | ||
if (idx !== -1) { | ||
return this._values[idx]; | ||
} | ||
}, | ||
set: function(key, value) { | ||
var idx = this._idx(key); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can we abuse of the fact that we know we are never going to override a value? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am thinking something like set: function(key, value) {
this._keys.push(key);
this._values.push(value);
}
get: function(key) {
var idx = this._keys.lastIndexOf(key);
if (idx != -1) return this._values[idx];
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could for this |
||
if (idx === -1) { | ||
idx = this._lastIndex = this._keys.length; | ||
this._lastKey = key; | ||
} | ||
this._keys[idx] = key; | ||
this._values[idx] = value; | ||
|
||
// Support: IE11 | ||
// Do not `return this` to simulate the partial IE11 implementation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LOL |
||
} | ||
}; | ||
|
||
var ES6Map = isFunction(window.Map) && toString.call(window.Map.prototype) === '[object Map]' | ||
? window.Map | ||
: ES6MapShim; | ||
|
||
/** | ||
* @ngdoc function | ||
* @name angular.copy | ||
|
@@ -809,8 +849,7 @@ function arrayRemove(array, value) { | |
</example> | ||
*/ | ||
function copy(source, destination) { | ||
var stackSource = []; | ||
var stackDest = []; | ||
var stack; | ||
|
||
if (destination) { | ||
if (isTypedArray(destination) || isArrayBuffer(destination)) { | ||
|
@@ -831,14 +870,14 @@ function copy(source, destination) { | |
}); | ||
} | ||
|
||
stackSource.push(source); | ||
stackDest.push(destination); | ||
return copyRecurse(source, destination); | ||
} | ||
|
||
return copyElement(source); | ||
|
||
function copyRecurse(source, destination) { | ||
(stack || (stack = new ES6Map())).set(source, destination); | ||
|
||
var h = destination.$$hashKey; | ||
var key; | ||
if (isArray(source)) { | ||
|
@@ -876,30 +915,25 @@ function copy(source, destination) { | |
} | ||
|
||
// Already copied values | ||
var index = stackSource.indexOf(source); | ||
if (index !== -1) { | ||
return stackDest[index]; | ||
var existingCopy = stack && stack.get(source); | ||
if (existingCopy) { | ||
return existingCopy; | ||
} | ||
|
||
if (isWindow(source) || isScope(source)) { | ||
throw ngMinErr('cpws', | ||
'Can\'t copy! Making copies of Window or Scope instances is not supported.'); | ||
} | ||
|
||
var needsRecurse = false; | ||
var destination = copyType(source); | ||
|
||
if (destination === undefined) { | ||
destination = isArray(source) ? [] : Object.create(getPrototypeOf(source)); | ||
needsRecurse = true; | ||
destination = copyRecurse(source, isArray(source) ? [] : Object.create(getPrototypeOf(source))); | ||
} else if (stack) { | ||
stack.set(source, destination); | ||
} | ||
|
||
stackSource.push(source); | ||
stackDest.push(destination); | ||
|
||
return needsRecurse | ||
? copyRecurse(source, destination) | ||
: destination; | ||
return destination; | ||
} | ||
|
||
function copyType(source) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -103,6 +103,8 @@ | |
"getBlockNodes": false, | ||
"createMap": false, | ||
"VALIDITY_STATE_PROPERTY": true, | ||
"testES6Map": true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Redundant |
||
"ES6MapShim": true, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't that redundant too, actually? |
||
|
||
/* AngularPublic.js */ | ||
"version": false, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
equivelent --> equivalent