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

fix(angular.copy) support for Map and Set #15697

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/Angular.js
Original file line number Diff line number Diff line change
Expand Up @@ -1031,6 +1031,24 @@ function copy(source, destination, maxDepth) {

case '[object Blob]':
return new source.constructor([source], {type: source.type});
case '[object Map]':
// If we're in this case we know the environment supports Map
/* eslint-disable no-undef */
var copiedMap = new Map();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We access globals through the window in order to support non-browser environments (such as jsdom).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had originally used new source.constructor() here, tried changing it to Map/Set to deal /w the IE11 issue that is failing the build. My next update I will change it back

/* eslint-enable */
source.forEach(function(value, key) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't return new Map(source) work as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand this correctly, IE11 does not support Map and Set constructor with arguments ? https://developer.mozilla.org/nl/docs/Web/JavaScript/Reference/Global_Objects/Map

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also needs to copy the keys/values, not just assign them, probably by invoking copyRecurse so we also get the maxDepth behavior.

copiedMap.set(key, value);
});
return copiedMap;
case '[object Set]':
// If we're in this case we know the environment supports Set
/* eslint-disable no-undef */
var copiedSet = new Set();
/* eslint-enable */
source.forEach(function(value) {
copiedSet.add(value);
});
return copiedSet;
}

if (isFunction(source.cloneNode)) {
Expand Down
26 changes: 25 additions & 1 deletion test/AngularSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Lots of typed array globals are used in this file and ESLint is
// not smart enough to understand the `typeof !== 'undefined'` guards.
/* globals Blob, Uint8ClampedArray, Uint16Array, Uint32Array, Int8Array, Int16Array, Int32Array,
Float32Array, Float64Array, */
Float32Array, Float64Array, Map, Set */

describe('angular', function() {
var element, document;
Expand Down Expand Up @@ -249,6 +249,30 @@ describe('angular', function() {
}
});

it('should handle Map objects', function() {
if (typeof Map !== 'undefined') {
var src = new Map();
src.set('foo', 'bar');
var dst = copy(src);
expect(dst).not.toBe(src);
expect(dst.size).toBe(1);
expect(dst instanceof Map).toBeTruthy();
expect(dst.get('foo')).toBe('bar');
}
});

it('should handle Set objects', function() {
if (typeof Set !== 'undefined') {
var src = new Set();
src.add('foo');
var dst = copy(src);
expect(dst).not.toBe(src);
expect(dst.size).toBe(1);
expect(dst instanceof Set).toBeTruthy();
expect(dst.has('foo')).toBeTruthy();
}
});

it('should handle Uint16Array subarray', function() {
if (typeof Uint16Array !== 'undefined') {
var arr = new Uint16Array(4);
Expand Down