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

Commit 39293d1

Browse files
committed
fix(copy): add support for ArrayBuffer, handle multiple references to ArrayBuffer
1 parent e4e5677 commit 39293d1

File tree

2 files changed

+59
-2
lines changed

2 files changed

+59
-2
lines changed

src/Angular.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,10 @@ function isTypedArray(value) {
683683
return value && isNumber(value.length) && TYPED_ARRAY_REGEXP.test(toString.call(value));
684684
}
685685

686+
function isArrayBuffer(obj) {
687+
return toString.call(obj) === '[object ArrayBuffer]';
688+
}
689+
686690

687691
var trim = function(value) {
688692
return isString(value) ? value.trim() : value;
@@ -807,7 +811,7 @@ function copy(source, destination) {
807811
var stackDest = [];
808812

809813
if (destination) {
810-
if (isTypedArray(destination)) {
814+
if (isTypedArray(destination) || isArrayBuffer(destination)) {
811815
throw ngMinErr('cpta', "Can't copy! TypedArray destination cannot be mutated.");
812816
}
813817
if (source === destination) {
@@ -886,8 +890,16 @@ function copy(source, destination) {
886890
if (isArray(source)) {
887891
destination = [];
888892
needsRecurse = true;
893+
} else if (isArrayBuffer(source)) {
894+
if (source.slice) {
895+
destination = source.slice();
896+
} else {
897+
//Support: IE10
898+
destination = new ArrayBuffer(source.byteLength);
899+
new Uint8Array(destination).set(new Uint8Array(source));
900+
}
889901
} else if (isTypedArray(source)) {
890-
destination = new source.constructor(source);
902+
destination = new source.constructor(copyElement(source.buffer));
891903
} else if (isDate(source)) {
892904
destination = new Date(source.getTime());
893905
} else if (isRegExp(source)) {

test/AngularSpec.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ describe('angular', function() {
8686
expect(copy(src) instanceof Uint8Array).toBeTruthy();
8787
expect(dst).toEqual(src);
8888
expect(dst).not.toBe(src);
89+
expect(dst.buffer).not.toBe(src.buffer);
8990
}
9091
});
9192

@@ -97,6 +98,7 @@ describe('angular', function() {
9798
expect(copy(src) instanceof Uint8ClampedArray).toBeTruthy();
9899
expect(dst).toEqual(src);
99100
expect(dst).not.toBe(src);
101+
expect(dst.buffer).not.toBe(src.buffer);
100102
}
101103
});
102104

@@ -108,6 +110,7 @@ describe('angular', function() {
108110
expect(copy(src) instanceof Uint16Array).toBeTruthy();
109111
expect(dst).toEqual(src);
110112
expect(dst).not.toBe(src);
113+
expect(dst.buffer).not.toBe(src.buffer);
111114
}
112115
});
113116

@@ -119,6 +122,7 @@ describe('angular', function() {
119122
expect(copy(src) instanceof Uint32Array).toBeTruthy();
120123
expect(dst).toEqual(src);
121124
expect(dst).not.toBe(src);
125+
expect(dst.buffer).not.toBe(src.buffer);
122126
}
123127
});
124128

@@ -130,6 +134,7 @@ describe('angular', function() {
130134
expect(copy(src) instanceof Int8Array).toBeTruthy();
131135
expect(dst).toEqual(src);
132136
expect(dst).not.toBe(src);
137+
expect(dst.buffer).not.toBe(src.buffer);
133138
}
134139
});
135140

@@ -141,6 +146,7 @@ describe('angular', function() {
141146
expect(copy(src) instanceof Int16Array).toBeTruthy();
142147
expect(dst).toEqual(src);
143148
expect(dst).not.toBe(src);
149+
expect(dst.buffer).not.toBe(src.buffer);
144150
}
145151
});
146152

@@ -152,6 +158,7 @@ describe('angular', function() {
152158
expect(copy(src) instanceof Int32Array).toBeTruthy();
153159
expect(dst).toEqual(src);
154160
expect(dst).not.toBe(src);
161+
expect(dst.buffer).not.toBe(src.buffer);
155162
}
156163
});
157164

@@ -163,6 +170,7 @@ describe('angular', function() {
163170
expect(copy(src) instanceof Float32Array).toBeTruthy();
164171
expect(dst).toEqual(src);
165172
expect(dst).not.toBe(src);
173+
expect(dst.buffer).not.toBe(src.buffer);
166174
}
167175
});
168176

@@ -174,6 +182,34 @@ describe('angular', function() {
174182
expect(copy(src) instanceof Float64Array).toBeTruthy();
175183
expect(dst).toEqual(src);
176184
expect(dst).not.toBe(src);
185+
expect(dst.buffer).not.toBe(src.buffer);
186+
}
187+
});
188+
189+
it('should copy an ArrayBuffer with no destination', function() {
190+
if (typeof ArrayBuffer !== 'undefined') {
191+
var src = new ArrayBuffer(2);
192+
new Uint8Array(src).set([1, 2]);
193+
194+
var dst = copy(src);
195+
expect(dst instanceof ArrayBuffer).toBeTruthy();
196+
expect(dst).toEqual(src);
197+
expect(dst).not.toBe(src);
198+
}
199+
});
200+
201+
it('should handle ArrayBuffer objects with multiple references', function() {
202+
if (typeof ArrayBuffer !== 'undefined') {
203+
var buffer = new ArrayBuffer(8);
204+
var src = [new Int32Array(buffer), new Float32Array(buffer)];
205+
src[0].set([1, 2]);
206+
207+
var dst = copy(src);
208+
expect(dst).toEqual(src);
209+
expect(dst[0]).not.toBe(src[0]);
210+
expect(dst[1]).not.toBe(src[1]);
211+
expect(dst[0].buffer).toBe(dst[1].buffer);
212+
expect(dst[0].buffer).not.toBe(buffer);
177213
}
178214
});
179215

@@ -258,6 +294,15 @@ describe('angular', function() {
258294
}
259295
});
260296

297+
it("should throw an exception if an ArrayBuffer is the destination", function() {
298+
if (typeof ArrayBuffer !== 'undefined') {
299+
var src = new ArrayBuffer(5);
300+
var dst = new ArrayBuffer(5);
301+
expect(function() { copy(src, dst); })
302+
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
303+
}
304+
});
305+
261306
it("should deeply copy an array into an existing array", function() {
262307
var src = [1, {name:"value"}];
263308
var dst = [{key:"v"}];

0 commit comments

Comments
 (0)