Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit 4069853

Browse files
committed
perf(copy): use ES6 Map to track source/destination objects
1 parent 35eada6 commit 4069853

File tree

3 files changed

+84
-9
lines changed

3 files changed

+84
-9
lines changed

src/Angular.js

+49-9
Original file line numberDiff line numberDiff line change
@@ -740,6 +740,49 @@ function arrayRemove(array, value) {
740740
return index;
741741
}
742742

743+
744+
function ES6MapShim() {
745+
this._keys = [];
746+
this._values = [];
747+
}
748+
ES6MapShim.prototype = {
749+
get: function(key) {
750+
var idx = this._keys.indexOf(key);
751+
if (idx !== -1) {
752+
return this._values[idx];
753+
}
754+
},
755+
set: function(key, value) {
756+
var idx = this._keys.indexOf(key);
757+
if (idx === -1) {
758+
idx = this._keys.length;
759+
}
760+
this._keys[idx] = key;
761+
this._values[idx] = value;
762+
return this;
763+
}
764+
};
765+
766+
function testES6Map(Map) {
767+
var m, o = {};
768+
return isFunction(Map) && (m = new Map())
769+
770+
// Required functions
771+
&& isFunction(m.get) && isFunction(m.set)
772+
773+
// Number keys, must not call toString
774+
&& m.get(1) === undefined
775+
&& m.set(1, o) === m
776+
&& m.get(1) === o
777+
&& m.get("1") === undefined
778+
779+
// Object keys, must use instance as key and not call toString
780+
&& m.set(o, 2) === m && m.get(o) === 2
781+
&& m.get({}) === undefined;
782+
}
783+
784+
var ES6Map = testES6Map(window.Map) ? window.Map : ES6MapShim;
785+
743786
/**
744787
* @ngdoc function
745788
* @name angular.copy
@@ -799,8 +842,7 @@ function arrayRemove(array, value) {
799842
</example>
800843
*/
801844
function copy(source, destination) {
802-
var stackSource = [];
803-
var stackDest = [];
845+
var stack = new ES6Map();
804846

805847
if (destination) {
806848
if (isTypedArray(destination)) {
@@ -821,8 +863,7 @@ function copy(source, destination) {
821863
});
822864
}
823865

824-
stackSource.push(source);
825-
stackDest.push(destination);
866+
stack.set(source, destination);
826867
return copyRecurse(source, destination);
827868
}
828869

@@ -866,9 +907,9 @@ function copy(source, destination) {
866907
}
867908

868909
// Already copied values
869-
var index = stackSource.indexOf(source);
870-
if (index !== -1) {
871-
return stackDest[index];
910+
var existingCopy = stack.get(source);
911+
if (existingCopy) {
912+
return existingCopy;
872913
}
873914

874915
if (isWindow(source) || isScope(source)) {
@@ -896,8 +937,7 @@ function copy(source, destination) {
896937
needsRecurse = true;
897938
}
898939

899-
stackSource.push(source);
900-
stackDest.push(destination);
940+
stack.set(source, destination);
901941

902942
return needsRecurse
903943
? copyRecurse(source, destination)

test/.jshintrc

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@
8585
"getBlockNodes": false,
8686
"createMap": false,
8787
"VALIDITY_STATE_PROPERTY": true,
88+
"testES6Map": true,
89+
"ES6MapShim": true,
8890

8991
/* AngularPublic.js */
9092
"version": false,

test/AngularSpec.js

+33
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,39 @@ describe('angular', function() {
1616
});
1717
});
1818

19+
describe("ES6Map", function() {
20+
it("should test for bad Map objects", function() {
21+
expect(testES6Map()).toBe(false);
22+
expect(testES6Map(null)).toBe(false);
23+
expect(testES6Map(3)).toBe(false);
24+
expect(testES6Map({})).toBe(false);
25+
});
26+
27+
it("should test for bad Map shims", function() {
28+
function NoMethods() {}
29+
30+
function ToStringOnKeys() {
31+
this._vals = {};
32+
}
33+
ToStringOnKeys.prototype = {
34+
get: function(key) {
35+
return this._vals[key];
36+
},
37+
set: function(key, val) {
38+
this._vals[key] = val;
39+
return this;
40+
}
41+
};
42+
43+
expect(testES6Map(NoMethods)).toBe(false);
44+
expect(testES6Map(ToStringOnKeys)).toBe(false);
45+
});
46+
47+
it("should pass the ES6Map test with ES6MapShim", function() {
48+
expect(testES6Map(ES6MapShim)).toBe(true);
49+
});
50+
});
51+
1952
describe("copy", function() {
2053
it("should return same object", function() {
2154
var obj = {};

0 commit comments

Comments
 (0)