Actively seeking a champion for this proposal. If you're a TC39 member, please feel free to reach out - I'd deeply appreciate it.
The whole idea of this is two-fold:
- Port the existing
%TypedArray%.prototype.set
to arrays, so they can reap its benefits, too. - Expand both to align with the existing
copyWithin
method present on both arrays and typed arrays and accept the same list of parameters.
In effect, this makes array.copyWithin(...args)
on both very similar to array.set(array, ...args)
, and engines could just delegate the first to the second internally after processing the parameters. It would also simplify the spec, as they could share an implementation within it.
This assigns to this
, starting at offset
, the items in array
from start
to end
. I included more spec-like text modeled after Array.prototype.copyWithin
and %TypedArray%.prototype.set
to make it a little clearer what I'm looking for.
The defaults for each of these are as follows:
- offset:
0
(same as with%TypedArray%.prototype.set
today) - start:
0
- end:
target.length
Implementation-wise, it'd work just like copyWithin
, just it would read from array rather than this
. For consistency with the existing %TypedArray%.prototype.set
, it'd throw a RangeError if any of its parameters are negative or if start > end.
For Array.prototype.set
, consider the surprisingly frequent usage of System.arraycopy
within Java circles. In performance-sensitive code when you need to copy items across two arrays, it'd be nice to have a native JIT primitive that can do it in a very highly vectorized fashion. (In fact, I'd say most of my simple loops are literally just copying between arrays.) Such a method already exists in typed arrays, but it'd be nice to have that parity be moved over to normal arrays, too, since most normal JS code (even perf-sensitive code) can't lower all operations into plain numbers. As for other precedent:
- JS already has
%TypedArray%.prototype.set
, and the non-typed-array variant is almost literally what's proposed here minus typed array-specific coercions and the extra parameters. (It's complete with Get and Set calls in the spec.) - I've seen
Object.assign(array, values)
in the wild more than once, even though it's clearly wrong. - Python has the
s[i:j] = t
idiom, which replaces one sublist with another (an extended version of our.splice
). You can have a more exact analogue vias[i:j] = t[k:k+(j-i)]
, and I've seen similar code out in the wild before. - C# has
System.Array.Copy
(which is effectively Java'sSystem.arraycopy
),System.Buffer.BlockCopy
(equivalent specialized for primitives), andSystem.Array.CopyTo
for the common case of copying a smaller array's contents into a larger array. - Rust has
Vec::copy_from_slice
. - OCaml has
Array.blit
that's effectively Java'sSystem.arraycopy
. - C++ has
std::copy
, which operates on both pointer offsets and iterators. - C, of course, has
memcpy
andmemmove
, which are commonly used for this purpose. - There's other examples in other languages, too (like Julia), but you get the point.
Update the offset handling to work similarly to above. Note that typedArray.set(overloaded, offset = 0)
would remain identical to what's currently in the spec, so the risk of breakage I suspect would be very low.
I find it surprising that they're not there in the typed array variant, and I feel it limits its utility by quite a bit. Engines already have to use a start offset just to perform the algorithm, and it's pretty trivial to go from source end offset to target end offset (it's just a couple subtracts), so it shouldn't be that hard to allow users to provide info to hook into it. Also, most the above precedent for Array.prototype.set
contains such functionality.