mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-04-25 07:02:13 +00:00
Implement Array.isArray and Array#copyWithin (#331)
This commit is contained in:
parent
4e89456dcb
commit
1882679807
@ -27,11 +27,19 @@ import {
|
|||||||
MAX_DOUBLE_LENGTH
|
MAX_DOUBLE_LENGTH
|
||||||
} from "./internal/number";
|
} from "./internal/number";
|
||||||
|
|
||||||
|
import {
|
||||||
|
isArray as builtin_isArray
|
||||||
|
} from "./builtins";
|
||||||
|
|
||||||
export class Array<T> {
|
export class Array<T> {
|
||||||
|
|
||||||
/* @internal */ buffer_: ArrayBuffer;
|
/* @internal */ buffer_: ArrayBuffer;
|
||||||
/* @internal */ length_: i32;
|
/* @internal */ length_: i32;
|
||||||
|
|
||||||
|
@inline static isArray<U>(value: U): bool {
|
||||||
|
return builtin_isArray(value) && value !== null;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(length: i32 = 0) {
|
constructor(length: i32 = 0) {
|
||||||
const MAX_LENGTH = MAX_BLENGTH >>> alignof<T>();
|
const MAX_LENGTH = MAX_BLENGTH >>> alignof<T>();
|
||||||
if (<u32>length > <u32>MAX_LENGTH) throw new RangeError("Invalid array length");
|
if (<u32>length > <u32>MAX_LENGTH) throw new RangeError("Invalid array length");
|
||||||
@ -116,8 +124,10 @@ export class Array<T> {
|
|||||||
fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
|
fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
|
||||||
var buffer = this.buffer_;
|
var buffer = this.buffer_;
|
||||||
var len = this.length_;
|
var len = this.length_;
|
||||||
|
|
||||||
start = start < 0 ? max(len + start, 0) : min(start, len);
|
start = start < 0 ? max(len + start, 0) : min(start, len);
|
||||||
end = end < 0 ? max(len + end, 0) : min(end, len);
|
end = end < 0 ? max(len + end, 0) : min(end, len);
|
||||||
|
|
||||||
if (sizeof<T>() == 1) {
|
if (sizeof<T>() == 1) {
|
||||||
if (start < end) {
|
if (start < end) {
|
||||||
memory.fill(
|
memory.fill(
|
||||||
@ -182,24 +192,55 @@ export class Array<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
concat(items: Array<T>): Array<T> {
|
concat(items: Array<T>): Array<T> {
|
||||||
var thisLen: isize = this.length_;
|
var thisLen = this.length_;
|
||||||
var otherLen = (items == null) ? 0 : items.length_;
|
var otherLen = items === null ? 0 : items.length_;
|
||||||
var outLen = thisLen + otherLen;
|
var outLen = thisLen + otherLen;
|
||||||
var out: Array<T> = new Array<T>(outLen);
|
var out = new Array<T>(outLen);
|
||||||
|
|
||||||
if (thisLen) {
|
if (thisLen) {
|
||||||
memory.copy(changetype<usize>(out.buffer_) + HEADER_SIZE,
|
memory.copy(
|
||||||
changetype<usize>(this.buffer_) + HEADER_SIZE,
|
changetype<usize>(out.buffer_) + HEADER_SIZE,
|
||||||
<usize>(thisLen << alignof<T>()));
|
changetype<usize>(this.buffer_) + HEADER_SIZE,
|
||||||
|
<usize>thisLen << alignof<T>()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (otherLen) {
|
if (otherLen) {
|
||||||
memory.copy(changetype<usize>(out.buffer_) + HEADER_SIZE + <usize>(thisLen << alignof<T>()),
|
memory.copy(
|
||||||
changetype<usize>(items.buffer_) + HEADER_SIZE,
|
changetype<usize>(out.buffer_) + HEADER_SIZE + (<usize>thisLen << alignof<T>()),
|
||||||
<usize>(otherLen << alignof<T>()));
|
changetype<usize>(items.buffer_) + HEADER_SIZE,
|
||||||
|
<usize>otherLen << alignof<T>()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copyWithin(target: i32, start: i32, end: i32 = i32.MAX_VALUE): this {
|
||||||
|
var buffer = this.buffer_;
|
||||||
|
var len = this.length_;
|
||||||
|
|
||||||
|
end = min<i32>(end, len);
|
||||||
|
var to = target < 0 ? max(len + target, 0) : min(target, len);
|
||||||
|
var from = start < 0 ? max(len + start, 0) : min(start, len);
|
||||||
|
var last = end < 0 ? max(len + end, 0) : min(end, len);
|
||||||
|
var count = min(last - from, len - to);
|
||||||
|
|
||||||
|
if (from < to && to < (from + count)) {
|
||||||
|
from += count - 1;
|
||||||
|
to += count - 1;
|
||||||
|
while (count) {
|
||||||
|
storeUnsafe<T,T>(buffer, to, loadUnsafe<T,T>(buffer, from));
|
||||||
|
--from, --to, --count;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memory.copy(
|
||||||
|
changetype<usize>(buffer) + HEADER_SIZE + (<usize>to << alignof<T>()),
|
||||||
|
changetype<usize>(buffer) + HEADER_SIZE + (<usize>from << alignof<T>()),
|
||||||
|
<usize>count << alignof<T>()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
pop(): T {
|
pop(): T {
|
||||||
var length = this.length_;
|
var length = this.length_;
|
||||||
if (length < 1) throw new RangeError("Array is empty");
|
if (length < 1) throw new RangeError("Array is empty");
|
||||||
@ -309,6 +350,7 @@ export class Array<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
slice(begin: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
|
slice(begin: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
|
||||||
|
var len = this.length_;
|
||||||
var length = this.length_;
|
var length = this.length_;
|
||||||
if (begin < 0) begin = max(length + begin, 0);
|
if (begin < 0) begin = max(length + begin, 0);
|
||||||
else if (begin > length) begin = length;
|
else if (begin > length) begin = length;
|
||||||
|
5
std/assembly/index.d.ts
vendored
5
std/assembly/index.d.ts
vendored
@ -541,11 +541,15 @@ declare class Float64Array extends TypedArray<f64> {}
|
|||||||
|
|
||||||
/** Class representing a sequence of values of type `T`. */
|
/** Class representing a sequence of values of type `T`. */
|
||||||
declare class Array<T> {
|
declare class Array<T> {
|
||||||
|
|
||||||
|
static isArray<U>(value: any): value is Array<any>;
|
||||||
|
|
||||||
[key: number]: T;
|
[key: number]: T;
|
||||||
/** Current length of the array. */
|
/** Current length of the array. */
|
||||||
length: i32;
|
length: i32;
|
||||||
/** Constructs a new array. */
|
/** Constructs a new array. */
|
||||||
constructor(capacity?: i32);
|
constructor(capacity?: i32);
|
||||||
|
|
||||||
fill(value: T, start?: i32, end?: i32): this;
|
fill(value: T, start?: i32, end?: i32): this;
|
||||||
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
|
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
|
||||||
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
|
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
|
||||||
@ -554,6 +558,7 @@ declare class Array<T> {
|
|||||||
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
|
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
|
||||||
push(element: T): i32;
|
push(element: T): i32;
|
||||||
concat(items: T[]): T[];
|
concat(items: T[]): T[];
|
||||||
|
copyWithin(target: i32, start: i32, end?: i32): this;
|
||||||
pop(): T;
|
pop(): T;
|
||||||
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void;
|
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void;
|
||||||
map<U>(callbackfn: (value: T, index: i32, array: Array<T>) => U): Array<U>;
|
map<U>(callbackfn: (value: T, index: i32, array: Array<T>) => U): Array<U>;
|
||||||
|
5
std/portable/index.d.ts
vendored
5
std/portable/index.d.ts
vendored
@ -344,9 +344,13 @@ declare class DataView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
declare class Array<T> {
|
declare class Array<T> {
|
||||||
|
|
||||||
|
static isArray<U>(value: any): value is Array<any>;
|
||||||
|
|
||||||
[key: number]: T;
|
[key: number]: T;
|
||||||
length: i32;
|
length: i32;
|
||||||
constructor(capacity?: i32);
|
constructor(capacity?: i32);
|
||||||
|
|
||||||
fill(value: T, start?: i32, end?: i32): this;
|
fill(value: T, start?: i32, end?: i32): this;
|
||||||
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
|
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
|
||||||
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
|
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
|
||||||
@ -355,6 +359,7 @@ declare class Array<T> {
|
|||||||
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
|
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
|
||||||
push(element: T): i32;
|
push(element: T): i32;
|
||||||
concat(items: T[]): T[];
|
concat(items: T[]): T[];
|
||||||
|
copyWithin(target: i32, start: i32, end?: i32): this;
|
||||||
pop(): T;
|
pop(): T;
|
||||||
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void;
|
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void;
|
||||||
map<U>(callbackfn: (value: T, index: i32, array: Array<T>) => U): Array<U>;
|
map<U>(callbackfn: (value: T, index: i32, array: Array<T>) => U): Array<U>;
|
||||||
|
@ -471,7 +471,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 136
|
i32.const 136
|
||||||
i32.const 37
|
i32.const 45
|
||||||
i32.const 39
|
i32.const 39
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -545,7 +545,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 136
|
i32.const 136
|
||||||
i32.const 37
|
i32.const 45
|
||||||
i32.const 39
|
i32.const 39
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -619,7 +619,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 136
|
i32.const 136
|
||||||
i32.const 37
|
i32.const 45
|
||||||
i32.const 39
|
i32.const 39
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -709,7 +709,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 136
|
i32.const 136
|
||||||
i32.const 37
|
i32.const 45
|
||||||
i32.const 39
|
i32.const 39
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -28,6 +28,17 @@ function isArraysEqual<T>(a: Array<T>, b: Array<T>, len: i32 = 0): bool {
|
|||||||
|
|
||||||
var arr = new Array<i32>();
|
var arr = new Array<i32>();
|
||||||
|
|
||||||
|
// Array.isArray ///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class P {}
|
||||||
|
var num = 1;
|
||||||
|
var Null: i32[] | null = null;
|
||||||
|
assert(Array.isArray(Null) == false);
|
||||||
|
assert(Array.isArray(arr) == true);
|
||||||
|
assert(Array.isArray(new P()) == false);
|
||||||
|
// assert(Array.isArray(new Uint8Array(1)) == false); fail
|
||||||
|
assert(Array.isArray(num) == false);
|
||||||
|
|
||||||
// Array#fill //////////////////////////////////////////////////////////////////////////////////////
|
// Array#fill //////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
var arr8: u8[] = [1, 2, 3, 4, 5];
|
var arr8: u8[] = [1, 2, 3, 4, 5];
|
||||||
@ -145,6 +156,34 @@ out = source.concat(arr);
|
|||||||
assert(out.length == 3);
|
assert(out.length == 3);
|
||||||
assert(source.length == 0);
|
assert(source.length == 0);
|
||||||
|
|
||||||
|
// Array#copyWithin ////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
var cwArr: i32[];
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(0, 3), <i32[]>[4, 5, 3, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(1, 3), <i32[]>[1, 4, 5, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(1, 2), <i32[]>[1, 3, 4, 5, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(2, 2), <i32[]>[1, 2, 3, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(0, 3, 4), <i32[]>[4, 2, 3, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(1, 3, 4), <i32[]>[1, 4, 3, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(1, 2, 4), <i32[]>[1, 3, 4, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(0, -2), <i32[]>[4, 5, 3, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(0, -2, -1), <i32[]>[4, 2, 3, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(-4, -3, -2), <i32[]>[1, 3, 3, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(-4, -3, -1), <i32[]>[1, 3, 4, 4, 5]));
|
||||||
|
cwArr = [1, 2, 3, 4, 5];
|
||||||
|
assert(isArraysEqual<i32>(cwArr.copyWithin(-4, -3), <i32[]>[1, 3, 4, 5, 5]));
|
||||||
|
|
||||||
// Array#unshift ///////////////////////////////////////////////////////////////////////////////////
|
// Array#unshift ///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
arr.unshift(42);
|
arr.unshift(42);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1903,7 +1903,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 72
|
i32.const 72
|
||||||
i32.const 101
|
i32.const 109
|
||||||
i32.const 41
|
i32.const 41
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
|
@ -2436,7 +2436,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 72
|
i32.const 72
|
||||||
i32.const 101
|
i32.const 109
|
||||||
i32.const 41
|
i32.const 41
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
|
@ -2002,7 +2002,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 184
|
i32.const 184
|
||||||
i32.const 101
|
i32.const 109
|
||||||
i32.const 41
|
i32.const 41
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -2077,7 +2077,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 184
|
i32.const 184
|
||||||
i32.const 101
|
i32.const 109
|
||||||
i32.const 41
|
i32.const 41
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -2152,7 +2152,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 184
|
i32.const 184
|
||||||
i32.const 101
|
i32.const 109
|
||||||
i32.const 41
|
i32.const 41
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -2227,7 +2227,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 184
|
i32.const 184
|
||||||
i32.const 101
|
i32.const 109
|
||||||
i32.const 41
|
i32.const 41
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
|
@ -3319,7 +3319,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 776
|
i32.const 776
|
||||||
i32.const 37
|
i32.const 45
|
||||||
i32.const 39
|
i32.const 39
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -3467,7 +3467,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 776
|
i32.const 776
|
||||||
i32.const 174
|
i32.const 184
|
||||||
i32.const 42
|
i32.const 42
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
|
@ -4101,7 +4101,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 776
|
i32.const 776
|
||||||
i32.const 37
|
i32.const 45
|
||||||
i32.const 39
|
i32.const 39
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
@ -4310,7 +4310,7 @@
|
|||||||
if
|
if
|
||||||
i32.const 0
|
i32.const 0
|
||||||
i32.const 776
|
i32.const 776
|
||||||
i32.const 174
|
i32.const 184
|
||||||
i32.const 42
|
i32.const 42
|
||||||
call $~lib/env/abort
|
call $~lib/env/abort
|
||||||
unreachable
|
unreachable
|
||||||
|
@ -33,7 +33,8 @@
|
|||||||
"check-type-operator",
|
"check-type-operator",
|
||||||
"check-preblock"
|
"check-preblock"
|
||||||
]
|
]
|
||||||
}
|
},
|
||||||
|
"restrict-plus-operands": false
|
||||||
},
|
},
|
||||||
"jsRules": {
|
"jsRules": {
|
||||||
"max-line-length": {
|
"max-line-length": {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user