mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
This is a first pass at porting EnterSSA to Rust. First pass in the sense that it's hard to fully test it, and also in the sense that we'll likely figure out even better ways to work w the HIR as we iterate. Oh and i didn't do recusing into function expressions yet, since we can't even represent function expressions yet, and that may require modifying the design a bit (though i have an idea that i think will work, which is for the Builder to have an optional parent. When we encounter a block with no predecessors, we check the parent. I _think_ this will make all the borrowing "just work"). A few notes: Rust's compilation model parallelizes and incrementally computes at the crate granularity, so builds are faster if we split up our code into more but smaller crates. Setting up a clean dependency graph can dramatically improve build performance too. For example, to run the `fixtures` tests we can build `estree` and `hir` in parallel, then once those build _all_ of our other crates can be built in parallel until we get to `fixtures` which depends on the everything else. The various passes don't have any build dependencies on each other so they can build in parallel. Hence the new code for SSA stuff is in a separate `hir-ssa` crate. We should similarly group other passes (approximately one crate per folder in the babel-plugin-react-forget/src/ directory, eg SSA, Inference, Optimization, etc). Second, shared mutable ownership can be modeled in Rust but requires wrappers such as `Rc<RefCell<>>`. It's generally more efficient and more idiomatic to rethink the data model and algorithm. For EnterSSA, the Builder object holds a reference into the HIR that it only ever reads, and the pass (which drives the builder) also holds a reference into the HIR, which it mutates. The previous PR split up Blocks and Instructions, and the value of that is more apparent in `enter_ssa()`. The Rust equivalent of the builder holds a _shared_ (immutable) reference to just the HIR's blocks, while the pass (driving the builder) holds a _unique_ (mutable) reference to just the HIR's instructions. This lets us keep the overall feel of the algorithm while keeping Rust happy. Also note that the other change — to making operands be InstrIx indices into the instructions array — means that the SSA logic is simpler. Most instructions don't have to be visited at all, since they don't deal with loads/stores. Terminals also don't need to be visited, since they reference instructions, not identifiers. The Phi concept seems to just work too. I also updated the printer to print predecessors and phis.
test262
@ 83a46bfe0e
React Forget
React Forget is an experimental Babel plugin to automatically memoize React Hooks and Components.
Development
# tsc --watch
$ yarn dev
# in another terminal window
$ yarn test --watch
Notes
An overview of the implementation can be found in the Architecture Overview.
This transform
- needs plugin-syntax-jsx as a dependency to inherit the syntax from.
- should be run before plugin-transform-react-jsx
- assume the enforcement of rules of hooks, i.e.
- only call hooks from React functions
- only call hooks at the top level
- https://www.npmjs.com/package/eslint-plugin-react-hooks
Scaffolding
- https://github.com/facebook/flow/tree/master/packages/babel-plugin-transform-flow-enums
- https://github.com/babel/babel/blob/main/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts
Reference