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

Commit 986647a

Browse files
jbedardlgalfaso
authored andcommitted
fix(copy): add support for ArrayBuffer, handle multiple references to ArrayBuffer
Closes: #13640
1 parent 7b51243 commit 986647a

File tree

2 files changed

+75
-2
lines changed

2 files changed

+75
-2
lines changed

src/Angular.js

+15-2
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) {
@@ -907,7 +911,16 @@ function copy(source, destination) {
907911
case '[object Uint8ClampedArray]':
908912
case '[object Uint16Array]':
909913
case '[object Uint32Array]':
910-
return new source.constructor(source);
914+
return new source.constructor(copyElement(source.buffer));
915+
916+
case '[object ArrayBuffer]':
917+
//Support: IE10
918+
if (!source.slice) {
919+
var copied = new ArrayBuffer(source.byteLength);
920+
new Uint8Array(copied).set(new Uint8Array(source));
921+
return copied;
922+
}
923+
return source.slice(0);
911924

912925
case '[object Boolean]':
913926
case '[object Number]':

test/AngularSpec.js

+60
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,49 @@ 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(8);
192+
new Int32Array(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);
213+
}
214+
});
215+
216+
it('should handle Int32Array objects with multiple references', function() {
217+
if (typeof Int32Array !== 'undefined') {
218+
var arr = new Int32Array(2);
219+
var src = [arr, arr];
220+
arr.set([1, 2]);
221+
222+
var dst = copy(src);
223+
expect(dst).toEqual(src);
224+
expect(dst).not.toBe(src);
225+
expect(dst[0]).not.toBe(src[0]);
226+
expect(dst[0]).toBe(dst[1]);
227+
expect(dst[0].buffer).toBe(dst[1].buffer);
177228
}
178229
});
179230

@@ -258,6 +309,15 @@ describe('angular', function() {
258309
}
259310
});
260311

312+
it("should throw an exception if an ArrayBuffer is the destination", function() {
313+
if (typeof ArrayBuffer !== 'undefined') {
314+
var src = new ArrayBuffer(5);
315+
var dst = new ArrayBuffer(5);
316+
expect(function() { copy(src, dst); })
317+
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
318+
}
319+
});
320+
261321
it("should deeply copy an array into an existing array", function() {
262322
var src = [1, {name:"value"}];
263323
var dst = [{key:"v"}];

0 commit comments

Comments
 (0)