facebook / hermes

A JavaScript engine optimized for running React Native.
https://hermesengine.dev/
MIT License
9.41k stars 596 forks source link

Implement `TypedArray.prototype.with` #1365

Open robik opened 1 month ago

robik commented 1 month ago

Summary

This PR implements ES2023 TypedArray.prototype.with method. This is a follow-up of PR #1286 which added with method on standard Array prototype.

See also:

I am creating separate PRs for each method in case there are any suggestions or change requests from your side, so that PRs are more independent.

Test Plan

Code is annotated with algorithm steps from EcmaScript specification for easier verification and maintenance. I also added tests to verify that methods work as intended. There might be some more edge cases that might be covered based on your experience.

$ echo "new Int8Array([0]).with(0, 5)" | ./bin/hermes
# >> Int8Array [ 5 ]
robik commented 1 month ago

Also, as an future improvement area, is it possible to determine if an array is an rvalue (as in a temporary value, which reference to was not captured yet)?

I was thinking of implementing a basic copy-ellision. If there's a way right now, I might create a follow-up PR that implements it, e.g: checks if the target array is an rvalue, and if so, changes it in-place for some non mutating methods so that we do not allocate new array on every call.

This would be beneficial for cases like below:

const finalArray = [0, 0, 2]
  .with(1, 1)
  .toReversed();
facebook-github-bot commented 1 month ago

@dannysu has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator.

tmikov commented 1 month ago

@robik, high level optimizations like that are definitely something we are planning for in Static Hermes, but unfortunately they are almost impossible to do ahead of time in a regular untyped JS.

In regular JS, when we encounter x.with(1, 1).toReversed(), we don't know whether x is an Array, what with() does, whether it has been overridden by a polyfill, etc.

Things change dramatically in Static Hermes:

let x : any[];
...
x.with(1,1).toReversed()