Skip to content

Commit 1882679

Browse files
MaxGraeydcodeIO
authored andcommitted
Implement Array.isArray and Array#copyWithin (#331)
1 parent 4e89456 commit 1882679

File tree

13 files changed

+3400
-2176
lines changed

13 files changed

+3400
-2176
lines changed

std/assembly/array.ts

Lines changed: 52 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,19 @@ import {
2727
MAX_DOUBLE_LENGTH
2828
} from "./internal/number";
2929

30+
import {
31+
isArray as builtin_isArray
32+
} from "./builtins";
33+
3034
export class Array<T> {
3135

3236
/* @internal */ buffer_: ArrayBuffer;
3337
/* @internal */ length_: i32;
3438

39+
@inline static isArray<U>(value: U): bool {
40+
return builtin_isArray(value) && value !== null;
41+
}
42+
3543
constructor(length: i32 = 0) {
3644
const MAX_LENGTH = MAX_BLENGTH >>> alignof<T>();
3745
if (<u32>length > <u32>MAX_LENGTH) throw new RangeError("Invalid array length");
@@ -116,8 +124,10 @@ export class Array<T> {
116124
fill(value: T, start: i32 = 0, end: i32 = i32.MAX_VALUE): this {
117125
var buffer = this.buffer_;
118126
var len = this.length_;
127+
119128
start = start < 0 ? max(len + start, 0) : min(start, len);
120129
end = end < 0 ? max(len + end, 0) : min(end, len);
130+
121131
if (sizeof<T>() == 1) {
122132
if (start < end) {
123133
memory.fill(
@@ -182,24 +192,55 @@ export class Array<T> {
182192
}
183193

184194
concat(items: Array<T>): Array<T> {
185-
var thisLen: isize = this.length_;
186-
var otherLen = (items == null) ? 0 : items.length_;
187-
var outLen = thisLen + otherLen;
188-
var out: Array<T> = new Array<T>(outLen);
195+
var thisLen = this.length_;
196+
var otherLen = items === null ? 0 : items.length_;
197+
var outLen = thisLen + otherLen;
198+
var out = new Array<T>(outLen);
189199

190200
if (thisLen) {
191-
memory.copy(changetype<usize>(out.buffer_) + HEADER_SIZE,
192-
changetype<usize>(this.buffer_) + HEADER_SIZE,
193-
<usize>(thisLen << alignof<T>()));
201+
memory.copy(
202+
changetype<usize>(out.buffer_) + HEADER_SIZE,
203+
changetype<usize>(this.buffer_) + HEADER_SIZE,
204+
<usize>thisLen << alignof<T>()
205+
);
194206
}
195207
if (otherLen) {
196-
memory.copy(changetype<usize>(out.buffer_) + HEADER_SIZE + <usize>(thisLen << alignof<T>()),
197-
changetype<usize>(items.buffer_) + HEADER_SIZE,
198-
<usize>(otherLen << alignof<T>()));
208+
memory.copy(
209+
changetype<usize>(out.buffer_) + HEADER_SIZE + (<usize>thisLen << alignof<T>()),
210+
changetype<usize>(items.buffer_) + HEADER_SIZE,
211+
<usize>otherLen << alignof<T>()
212+
);
199213
}
200214
return out;
201215
}
202216

217+
copyWithin(target: i32, start: i32, end: i32 = i32.MAX_VALUE): this {
218+
var buffer = this.buffer_;
219+
var len = this.length_;
220+
221+
end = min<i32>(end, len);
222+
var to = target < 0 ? max(len + target, 0) : min(target, len);
223+
var from = start < 0 ? max(len + start, 0) : min(start, len);
224+
var last = end < 0 ? max(len + end, 0) : min(end, len);
225+
var count = min(last - from, len - to);
226+
227+
if (from < to && to < (from + count)) {
228+
from += count - 1;
229+
to += count - 1;
230+
while (count) {
231+
storeUnsafe<T,T>(buffer, to, loadUnsafe<T,T>(buffer, from));
232+
--from, --to, --count;
233+
}
234+
} else {
235+
memory.copy(
236+
changetype<usize>(buffer) + HEADER_SIZE + (<usize>to << alignof<T>()),
237+
changetype<usize>(buffer) + HEADER_SIZE + (<usize>from << alignof<T>()),
238+
<usize>count << alignof<T>()
239+
);
240+
}
241+
return this;
242+
}
243+
203244
pop(): T {
204245
var length = this.length_;
205246
if (length < 1) throw new RangeError("Array is empty");
@@ -309,6 +350,7 @@ export class Array<T> {
309350
}
310351

311352
slice(begin: i32 = 0, end: i32 = i32.MAX_VALUE): Array<T> {
353+
var len = this.length_;
312354
var length = this.length_;
313355
if (begin < 0) begin = max(length + begin, 0);
314356
else if (begin > length) begin = length;

std/assembly/index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,11 +541,15 @@ declare class Float64Array extends TypedArray<f64> {}
541541

542542
/** Class representing a sequence of values of type `T`. */
543543
declare class Array<T> {
544+
545+
static isArray<U>(value: any): value is Array<any>;
546+
544547
[key: number]: T;
545548
/** Current length of the array. */
546549
length: i32;
547550
/** Constructs a new array. */
548551
constructor(capacity?: i32);
552+
549553
fill(value: T, start?: i32, end?: i32): this;
550554
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
551555
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
@@ -554,6 +558,7 @@ declare class Array<T> {
554558
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
555559
push(element: T): i32;
556560
concat(items: T[]): T[];
561+
copyWithin(target: i32, start: i32, end?: i32): this;
557562
pop(): T;
558563
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void;
559564
map<U>(callbackfn: (value: T, index: i32, array: Array<T>) => U): Array<U>;

std/portable/index.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,13 @@ declare class DataView {
344344
}
345345

346346
declare class Array<T> {
347+
348+
static isArray<U>(value: any): value is Array<any>;
349+
347350
[key: number]: T;
348351
length: i32;
349352
constructor(capacity?: i32);
353+
350354
fill(value: T, start?: i32, end?: i32): this;
351355
every(callbackfn: (element: T, index: i32, array?: Array<T>) => bool): bool;
352356
findIndex(predicate: (element: T, index: i32, array?: Array<T>) => bool): i32;
@@ -355,6 +359,7 @@ declare class Array<T> {
355359
lastIndexOf(searchElement: T, fromIndex?: i32): i32;
356360
push(element: T): i32;
357361
concat(items: T[]): T[];
362+
copyWithin(target: i32, start: i32, end?: i32): this;
358363
pop(): T;
359364
forEach(callbackfn: (value: T, index: i32, array: Array<T>) => void): void;
360365
map<U>(callbackfn: (value: T, index: i32, array: Array<T>) => U): Array<U>;

tests/compiler/std/array-literal.untouched.wat

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@
471471
if
472472
i32.const 0
473473
i32.const 136
474-
i32.const 37
474+
i32.const 45
475475
i32.const 39
476476
call $~lib/env/abort
477477
unreachable
@@ -545,7 +545,7 @@
545545
if
546546
i32.const 0
547547
i32.const 136
548-
i32.const 37
548+
i32.const 45
549549
i32.const 39
550550
call $~lib/env/abort
551551
unreachable
@@ -619,7 +619,7 @@
619619
if
620620
i32.const 0
621621
i32.const 136
622-
i32.const 37
622+
i32.const 45
623623
i32.const 39
624624
call $~lib/env/abort
625625
unreachable
@@ -709,7 +709,7 @@
709709
if
710710
i32.const 0
711711
i32.const 136
712-
i32.const 37
712+
i32.const 45
713713
i32.const 39
714714
call $~lib/env/abort
715715
unreachable

0 commit comments

Comments
 (0)