-
Notifications
You must be signed in to change notification settings - Fork 648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add support for ES2023 Array.prototype.toSorted
#1298
base: main
Are you sure you want to change the base?
Conversation
d908a0d
to
86032d7
Compare
Summary: ### Overview This PR implements partial support for new `Array.prototype` non-mutating methods introduced in ES2023. These are: - [`Array.prototype.toReversed()`](https://262.ecma-international.org/14.0/#sec-array.prototype.toreversed) - [`Array.prototype.toSpliced(start, skipCount, ...items)`](https://262.ecma-international.org/14.0/#sec-array.prototype.tospliced) - [`Array.prototype.with(index, value)`](https://262.ecma-international.org/14.0/#sec-array.prototype.with) `Array.prototype.toSorted()` is implemented in separate PR #1298 as per request. Other Array methods introduced in ES14 seem to already be implemented (`findLast`, `findLastIndex`). Implementation for `TypedArray` methods are not included in this PR and will be provided in another one. ### Motivation Aforementioned methods see support in all major browsers for quite some time [^toReversed][^toSorted][^toSpliced][^with]. Adding support brings hermes closer to full ES2023 coverage and will improve interoperability with browsers. It also should provide slight performance gains across all applications upon adoption. <img width="1438" alt="obraz" src="https://github.com/facebook/hermes/assets/681837/e6f405b7-0645-4d27-8ca7-54f2c0aaf5d6"> [^toReversed]: https://caniuse.com/?search=toReversed [^toSorted]: https://caniuse.com/?search=toSorted [^toSpliced]: https://caniuse.com/?search=toSpliced [^with]: https://caniuse.com/?search=array.with - [x] Implementation - [x] Add tests - [x] Format changes - [ ] Add documentation somewhere? ### Implementation/review notes This is my first contribution to this project. While I have some experience in C++ and have spent some time studying hermes codebase, there might be some slight misusages of your APIs (most notably handles and memory management) and breaking code-style. If so, please let me know and I will try fix them promptly 🙂 Most of the code was inspired/taken from already existing mutating functions. I also tried to apply optimisations that I've noticed in some of the methods (most notably fast path for array element accessing). Pull Request resolved: #1286 Test Plan: In the description Reviewed By: avp Differential Revision: D53206784 Pulled By: tmikov fbshipit-source-id: abe00e8143e6adf57e575fe0e189038c21787bf4
Thanks for putting this together! I think there are a couple lingering conflicts and test failures, but I believe rebasing will resolve both. EDIT: Ah, the tests re-ran and the test failures have cleared already. |
There are a couple of issues that will need to be addressed here:
When looking into this, I noticed that Hermes itself is not spec-compliant when using Array.prototype.sort() on a dense array. We are sorting the array in place, but we should be copying it first as per the spec, which in turn will allow us to reuse the second part of sortSparse() (this then should enable us to optimize SortModel, but that is a different story altogether). In the end there should be a lot of reuse between all these cases. What I am proposing is that we can fix Array.prototype.sort() and if you wait a little you can base toSorted() on top of the same infra. |
@tmikov Sure thing! I can wait for the fix and rebase my PR on top of it, but if it is a low priority for you, maybe I can be of any help and dive into this topic. Would need a small guidance of how do you see it and some context 🙂 |
@robik that is excellent! If you are interested, here is what I think needs to be done, in a few incremental stages, each adding more optimization: Stage 1: correct implementation of sort
At the end of this stage, we should have spec compliant Stage 2: optionally implement fast path for JSArray inputIf the input object is a JSArray, we can use a fast path when copying the properties in We can also use a fast path for copying the elements back into JSArray in Again, if we get here, we should land a PR as an incremental improvement (though it will be a big one perf-wise). Stage 3: optionally improve SortModel
So we can do a couple of things:
Anyway, it would be great if you implemented any of these stages. Stage 1 would be great, since it simplifies the code and makes us compliant. Let me know, so I can remove it from my TODO list :-) |
Summary: Original Author: [email protected] Original Git: b30f0e4 Original Reviewed By: avp Original Revision: D53206784 ### Overview This PR implements partial support for new `Array.prototype` non-mutating methods introduced in ES2023. These are: - [`Array.prototype.toReversed()`](https://262.ecma-international.org/14.0/#sec-array.prototype.toreversed) - [`Array.prototype.toSpliced(start, skipCount, ...items)`](https://262.ecma-international.org/14.0/#sec-array.prototype.tospliced) - [`Array.prototype.with(index, value)`](https://262.ecma-international.org/14.0/#sec-array.prototype.with) `Array.prototype.toSorted()` is implemented in separate PR #1298 as per request. Other Array methods introduced in ES14 seem to already be implemented (`findLast`, `findLastIndex`). Implementation for `TypedArray` methods are not included in this PR and will be provided in another one. ### Motivation Aforementioned methods see support in all major browsers for quite some time [^toReversed][^toSorted][^toSpliced][^with]. Adding support brings hermes closer to full ES2023 coverage and will improve interoperability with browsers. It also should provide slight performance gains across all applications upon adoption. <img width="1438" alt="obraz" src="https://github.com/facebook/hermes/assets/681837/e6f405b7-0645-4d27-8ca7-54f2c0aaf5d6"> [^toReversed]: https://caniuse.com/?search=toReversed [^toSorted]: https://caniuse.com/?search=toSorted [^toSpliced]: https://caniuse.com/?search=toSpliced [^with]: https://caniuse.com/?search=array.with - [x] Implementation - [x] Add tests - [x] Format changes - [ ] Add documentation somewhere? ### Implementation/review notes This is my first contribution to this project. While I have some experience in C++ and have spent some time studying hermes codebase, there might be some slight misusages of your APIs (most notably handles and memory management) and breaking code-style. If so, please let me know and I will try fix them promptly 🙂 Most of the code was inspired/taken from already existing mutating functions. I also tried to apply optimisations that I've noticed in some of the methods (most notably fast path for array element accessing). Pull Request resolved: #1286 Pulled By: tmikov Reviewed By: avp Differential Revision: D54092069 fbshipit-source-id: cc4b58cf9d832538ff22df954e6655075a709aa3
86032d7
to
359f9c9
Compare
Hey @tmikov, sorry for the delay and thanks for great write-up! I've pushed the changes covering stage 1. If all is good I will work on next stage :) However, the tests seem to be failing on |
@tmikov has imported this pull request. If you are a Meta employee, you can view this diff on Phabricator. |
@robik thanks! We will start reviewing it ASAP. |
359f9c9
to
82d5ba9
Compare
@robik has updated the pull request. You must reimport the pull request before landing. |
Summary
Overview
This PR implements support for new
Array.prototype.toSorted(comparefn)
method introduced in ES2023. Remaining methods are implemented in #1286.Tasks
Implementation/review notes
Also I'd like to highlight proposed
toSorted
implementation. I usedsparseSort
unconditionally, that might have some quirks when used with proxes, although from what I understand it only relates to modifying the original object and should not be an issue because we are creating a new array.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.
Quick test: