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

Commit

Permalink
fix(angular.copy): support copying %TypedArray%s
Browse files Browse the repository at this point in the history
angular.copy can now copy a %TypedArray%s.

Limitations: It is not possible to update the length of a %TypedArray%, so currently an error is thrown
if the destination object is a %TypedArray%. However, it is possible to change values in a typed array,
so in the future this may only be a problem if the length of the source and destination is different.

Closes #10745
  • Loading branch information
DropsOfSerenity authored and caitp committed Jan 29, 2015
1 parent e61eae1 commit aa0f644
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 0 deletions.
7 changes: 7 additions & 0 deletions docs/content/error/ng/cpta.ngdoc
@@ -0,0 +1,7 @@
@ngdoc error
@name ng:cpta
@fullName Copying TypedArray
@description

Copying TypedArray's with a destination is not supported because TypedArray
objects can not be mutated, they are fixed length.
12 changes: 12 additions & 0 deletions src/Angular.js
Expand Up @@ -584,6 +584,12 @@ function isPromiseLike(obj) {
}


var TYPED_ARRAY_REGEXP = /^\[object (Uint8(Clamped)?)|(Uint16)|(Uint32)|(Int8)|(Int16)|(Int32)|(Float(32)|(64))Array\]$/;
function isTypedArray(value) {
return TYPED_ARRAY_REGEXP.test(toString.call(value));
}


var trim = function(value) {
return isString(value) ? value.trim() : value;
};
Expand Down Expand Up @@ -705,12 +711,18 @@ function copy(source, destination, stackSource, stackDest) {
throw ngMinErr('cpws',
"Can't copy! Making copies of Window or Scope instances is not supported.");
}
if (isTypedArray(destination)) {
throw ngMinErr('cpta',
"Can't copy! TypedArray destination cannot be mutated.");
}

if (!destination) {
destination = source;
if (source) {
if (isArray(source)) {
destination = copy(source, [], stackSource, stackDest);
} else if (isTypedArray(source)) {
destination = new source.constructor(source);
} else if (isDate(source)) {
destination = new Date(source.getTime());
} else if (isRegExp(source)) {
Expand Down
180 changes: 180 additions & 0 deletions test/AngularSpec.js
Expand Up @@ -78,6 +78,186 @@ describe('angular', function() {
expect(copy(objWithRegExp.re) === objWithRegExp.re).toBeFalsy();
});

it("should copy a Uint8Array with no destination", function() {
if (typeof Uint8Array !== 'undefined') {
var src = new Uint8Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Uint8Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Uint8ClampedArray with no destination", function() {
if (typeof Uint8ClampedArray !== 'undefined') {
var src = new Uint8ClampedArray(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Uint8ClampedArray).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Uint16Array with no destination", function() {
if (typeof Uint16Array !== 'undefined') {
var src = new Uint16Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Uint16Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Uint32Array with no destination", function() {
if (typeof Uint32Array !== 'undefined') {
var src = new Uint32Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Uint32Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Int8Array with no destination", function() {
if (typeof Int8Array !== 'undefined') {
var src = new Int8Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Int8Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Int16Array with no destination", function() {
if (typeof Int16Array !== 'undefined') {
var src = new Int16Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Int16Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Int32Array with no destination", function() {
if (typeof Int32Array !== 'undefined') {
var src = new Int32Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Int32Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Float32Array with no destination", function() {
if (typeof Float32Array !== 'undefined') {
var src = new Float32Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Float32Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should copy a Float64Array with no destination", function() {
if (typeof Float64Array !== 'undefined') {
var src = new Float64Array(2);
src[1] = 1;
var dst = copy(src);
expect(copy(src) instanceof Float64Array).toBeTruthy();
expect(dst).toEqual(src);
expect(dst).not.toBe(src);
}
});

it("should throw an exception if a Uint8Array is the destination", function() {
if (typeof Uint8Array !== 'undefined') {
var src = new Uint8Array();
var dst = new Uint8Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Uint8ClampedArray is the destination", function() {
if (typeof Uint8ClampedArray !== 'undefined') {
var src = new Uint8ClampedArray();
var dst = new Uint8ClampedArray(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Uint16Array is the destination", function() {
if (typeof Uint16Array !== 'undefined') {
var src = new Uint16Array();
var dst = new Uint16Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Uint32Array is the destination", function() {
if (typeof Uint32Array !== 'undefined') {
var src = new Uint32Array();
var dst = new Uint32Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Int8Array is the destination", function() {
if (typeof Int8Array !== 'undefined') {
var src = new Int8Array();
var dst = new Int8Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Int16Array is the destination", function() {
if (typeof Int16Array !== 'undefined') {
var src = new Int16Array();
var dst = new Int16Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Int32Array is the destination", function() {
if (typeof Int32Array !== 'undefined') {
var src = new Int32Array();
var dst = new Int32Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Float32Array is the destination", function() {
if (typeof Float32Array !== 'undefined') {
var src = new Float32Array();
var dst = new Float32Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should throw an exception if a Float64Array is the destination", function() {
if (typeof Float64Array !== 'undefined') {
var src = new Float64Array();
var dst = new Float64Array(5);
expect(function() { copy(src, dst); })
.toThrowMinErr("ng", "cpta", "Can't copy! TypedArray destination cannot be mutated.");
}
});

it("should deeply copy an array into an existing array", function() {
var src = [1, {name:"value"}];
var dst = [{key:"v"}];
Expand Down

0 comments on commit aa0f644

Please sign in to comment.