Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/typed-array-copy-within.fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Type `copyWithin` and `copyAllWithin` of typed arrays as returning the typed array instead of an `array`.
1 change: 1 addition & 0 deletions changes/typed-array-map-element-type.breaking.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- `TypedArray.map` and `TypedArray.mapWithIndex` now keep the element type, because a typed array converts the results of `map` to its own element type.
26 changes: 13 additions & 13 deletions packages/@rescript/runtime/Stdlib_TypedArray.res
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ TypedArray.length(view) == 3
external length: t<'a> => int = "length"

/**
`copyAllWithin(typedArray, ~target)` copies values starting at index `0` over the positions beginning at `target`.
`copyAllWithin(typedArray, ~target)` copies values starting at index `0` over the positions beginning at `target`, and returns `typedArray`.

Beware this will *mutate* the typed array.

Expand All @@ -125,9 +125,9 @@ let _ = TypedArray.copyAllWithin(view, ~target=1)
TypedArray.toString(view) == "10,10,20"
```
*/
@send external copyAllWithin: (t<'a>, ~target: int) => array<'a> = "copyWithin"
@send external copyAllWithin: (t<'a>, ~target: int) => t<'a> = "copyWithin"
/**
`copyWithin(typedArray, ~target, ~start, ~end)` copies the section `[start, end)` onto the range beginning at `target`.
`copyWithin(typedArray, ~target, ~start, ~end)` copies the section `[start, end)` onto the range beginning at `target`, and returns `typedArray`.

Beware this will *mutate* the typed array.

Expand All @@ -141,8 +141,8 @@ let _ = TypedArray.copyWithin(view, ~target=1, ~start=2, ~end=4)
TypedArray.toString(view) == "1,3,4,4"
```
*/
@send @send
external copyWithin: (t<'a>, ~target: int, ~start: int, ~end: int=?) => array<'a> = "copyWithin"
@send
external copyWithin: (t<'a>, ~target: int, ~start: int, ~end: int=?) => t<'a> = "copyWithin"

/**
`fillAll(typedArray, value)` fills every element with `value`.
Expand Down Expand Up @@ -409,15 +409,15 @@ See [`TypedArray.prototype.forEach`](https://developer.mozilla.org/en-US/docs/We
@send external forEachWithIndex: (t<'a>, ('a, int) => unit) => unit = "forEach"

/**
`map(typedArray, f)` returns a new typed array whose elements are produced by applying `f` to each element.
`map(typedArray, f)` returns a new typed array of the same kind whose elements are produced by applying `f` to each element.

See [`TypedArray.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/map) on MDN.
*/
@send external map: (t<'a>, 'a => 'b) => t<'b> = "map"
@send external map: (t<'a>, 'a => 'a) => t<'a> = "map"
/**
`mapWithIndex(typedArray, f)` behaves like `map`, but `f` also receives the index.
*/
@send external mapWithIndex: (t<'a>, ('a, int) => 'b) => t<'b> = "map"
@send external mapWithIndex: (t<'a>, ('a, int) => 'a) => t<'a> = "map"

/**
`reduce(typedArray, reducer, initial)` combines the elements from left to right using `reducer`.
Expand Down Expand Up @@ -582,7 +582,7 @@ module Impl = (
external length: T.t => int = "length"

/**
`copyAllWithin(typedArray, ~target)` copies values starting at index `0` over the positions beginning at `target`.
`copyAllWithin(typedArray, ~target)` copies values starting at index `0` over the positions beginning at `target`, and returns `typedArray`.

Beware this will *mutate* the typed array.

Expand All @@ -597,10 +597,10 @@ module Impl = (
```
*/
@send
external copyAllWithin: (T.t, ~target: int) => array<T.elt> = "copyWithin"
external copyAllWithin: (T.t, ~target: int) => T.t = "copyWithin"

/**
`copyWithin(typedArray, ~target, ~start, ~end)` copies the section `[start, end)` onto the range beginning at `target`.
`copyWithin(typedArray, ~target, ~start, ~end)` copies the section `[start, end)` onto the range beginning at `target`, and returns `typedArray`.

Beware this will *mutate* the typed array.

Expand All @@ -615,7 +615,7 @@ module Impl = (
```
*/
@send
external copyWithin: (T.t, ~target: int, ~start: int, ~end: int=?) => array<T.elt> = "copyWithin"
external copyWithin: (T.t, ~target: int, ~start: int, ~end: int=?) => T.t = "copyWithin"

/**
`fillAll(typedArray, value)` fills every element with `value`.
Expand Down Expand Up @@ -926,7 +926,7 @@ module Impl = (
external forEachWithIndex: (T.t, (T.elt, int) => unit) => unit = "forEach"

/**
`map(typedArray, f)` returns a new typed array whose elements are produced by applying `f` to each element.
`map(typedArray, f)` returns a new typed array of the same kind whose elements are produced by applying `f` to each element.

See [`TypedArray.prototype.map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray/map) on MDN.
*/
Expand Down
110 changes: 55 additions & 55 deletions tests/analysis_tests/tests/src/expected/CompletionTypedArrays.res.txt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

We've found a bug for you!
/.../fixtures/TypedArrayMapElementType.res:2:32-46

1 │ let v = (Int32Array.fromArray([1, 2, 3]) :> TypedArray.t<int>)
2 │ let s = v->TypedArray.map(x => Int.toString(x))
3 │

This has type: string
But it's expected to have type: int

You can convert string to int with Int.fromString.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
let v = (Int32Array.fromArray([1, 2, 3]) :> TypedArray.t<int>)
let s = v->TypedArray.map(x => Int.toString(x))
73 changes: 73 additions & 0 deletions tests/tests/src/stdlib/Stdlib_TypedArrayTests.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,79 @@ function o(x, map) {
return BigInt64Array.from(x, map);
}

assertTrue("copyAllWithin returns the typed array it mutated", () => {
let x = new Int32Array([
1,
2,
3
]);
let r = x.copyWithin(1);
if (r === x) {
return r.toString() === "1,1,2";
} else {
return false;
}
});

assertTrue("copyWithin returns the typed array it mutated", () => {
let x = new Int32Array([
1,
2,
3,
4
]);
let r = x.copyWithin(1, 2, 4);
if (r === x) {
return r.toString() === "1,3,4,4";
} else {
return false;
}
});

assertTrue("TypedArray.copyAllWithin returns the typed array it mutated", () => {
let x = new Int32Array([
1,
2,
3
]);
let r = x.copyWithin(1);
if (r === x) {
return r.toString() === "1,1,2";
} else {
return false;
}
});

assertTrue("TypedArray.copyWithin returns the typed array it mutated", () => {
let x = new Int32Array([
1,
2,
3,
4
]);
let r = x.copyWithin(1, 2, 4);
if (r === x) {
return r.toString() === "1,3,4,4";
} else {
return false;
}
});

assertTrue("TypedArray.map keeps the element type", () => {
let x = new Int32Array([
1,
2,
3
]);
let r = x.map(v => (v << 1));
let s = x.map((v, i) => v + i | 0);
if (r.toString() === "2,4,6") {
return s.toString() === "1,3,5";
} else {
return false;
}
});

export {
eq,
num1,
Expand Down
33 changes: 33 additions & 0 deletions tests/tests/src/stdlib/Stdlib_TypedArrayTests.res
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,36 @@ assertTrue("a typed array is a TypedArray.t through a coercion", () => {
TypedArray.length(x :> TypedArray.t<bigint>) == 2
})
let o = (x, map) => BigInt64Array.fromArrayLikeOrIterable(x, ~map)

// ===== copyWithin and map keep the typed array =====

assertTrue("copyAllWithin returns the typed array it mutated", () => {
let x = Int32Array.fromArray([1, 2, 3])
let r: Int32Array.t = x->Int32Array.copyAllWithin(~target=1)
r === x && Int32Array.toString(r) == "1,1,2"
})

assertTrue("copyWithin returns the typed array it mutated", () => {
let x = Int32Array.fromArray([1, 2, 3, 4])
let r: Int32Array.t = x->Int32Array.copyWithin(~target=1, ~start=2, ~end=4)
r === x && Int32Array.toString(r) == "1,3,4,4"
})

assertTrue("TypedArray.copyAllWithin returns the typed array it mutated", () => {
let x = (Int32Array.fromArray([1, 2, 3]) :> TypedArray.t<int>)
let r: TypedArray.t<int> = x->TypedArray.copyAllWithin(~target=1)
r === x && TypedArray.toString(r) == "1,1,2"
})

assertTrue("TypedArray.copyWithin returns the typed array it mutated", () => {
let x = (Int32Array.fromArray([1, 2, 3, 4]) :> TypedArray.t<int>)
let r: TypedArray.t<int> = x->TypedArray.copyWithin(~target=1, ~start=2, ~end=4)
r === x && TypedArray.toString(r) == "1,3,4,4"
})

assertTrue("TypedArray.map keeps the element type", () => {
let x = (Int32Array.fromArray([1, 2, 3]) :> TypedArray.t<int>)
let r: TypedArray.t<int> = x->TypedArray.map(v => v * 2)
let s: TypedArray.t<int> = x->TypedArray.mapWithIndex((v, i) => v + i)
TypedArray.toString(r) == "2,4,6" && TypedArray.toString(s) == "1,3,5"
})
Loading