Commit Graph
953 Commits
Author SHA1 Message Date
Joe Savona bbb5840e73 Handle phi nodes for ValidateFrozenLambdas
Extends ValidateFrozenLambdas to find cases where a mutable lambda flows into a 
phi node and the phi is later frozen.
2023-06-20 15:16:56 -07:00
Joe Savona 6efd1f99d7 Make function name a string not an identifier
Fixes #1751. Function ids can be plain strings, and we can refer to them as 
globals rather than via a local identifier. In addition to the bug from $1751 
this also cleans up an existing todo.
2023-06-20 15:16:55 -07:00
Joe Savona 4a36b83796 Ref validation allows passing refs as props
Updates ValidateNoRefAccessInRender to allow passing refs to JSX, but continue 
disallowing passing ref values (so `ref` is okay but not `ref.current`)
2023-06-20 10:11:56 -07:00
Joe Savona a9868cc2b1 Fix memoization of lambdas in @enableOptimizeFunctionExpr feature
This is a fix specifically for the `enableOptimizeFunctionExpression` feature 
(disabled by default). I tried running all of our fixtures with that flag on 
everywhere, and this was the only issue. It's actually extracted from another 
fixture which is more complicated, this is a distilled version. There were two 
bugs: 

* DCE was running after LeaveSSA when it needs to run before. Fixing the order 
means code inside the function expression stops getting removed. 

* In the feature flag, context variables share Identifier instances with the 
surrounding code, whereas they are distinct instances without the feature. This 
meant that mutable ranges from inside the function propagated outside the 
function, throwing off our inference. The fix was to reset the ranges of context 
variables after inferring the function expression's effects.
2023-06-16 14:42:19 -07:00
Joe Savona 04f4b50997 Integrate mutable context identifier inference, improve frozen function
inference 

Integrates the new inference to detect definitive mutations of context 
variables. This allows us to more precisely infer mutable function expressions 
and validate that they aren't passed where frozen values are expected.
2023-06-16 14:42:19 -07:00
Joe Savona a2af8776a4 Add InferMutableContextVariables (unused)
New pass to infer context variables which are definitively mutated, 
distinguishing from context variables which _may_  have been mutated. See the 
code comment on the new pass for more details.
2023-06-16 14:42:18 -07:00
Joe Savona 59a1f2a5b0 AnalyzeFunction: ref values take priority over other mutations
Small tweak necessary for the subsequent PRs, refs and ref values take 
precedence over other mutations when computing the effect type of context 
variables. We always want to record ref access within a function as capture 
(since we have later validation) rather than a mutation. For now this has no 
impact, either order records a Capture. But it allows later diffs to make 
non-ref cases have other effects.
2023-06-16 14:42:17 -07:00
Joe Savona 278c7f56ba ValidateFrozenLambdas: visit terminals
The original version of the code wasn't checking return values. I missed this 
since my examples were passing functions _into_ the return value, as opposed to 
return the functions directly. This revealed some existing test fixtures that 
were technically invalid, but easy to fix by changing the return value.
2023-06-16 14:42:16 -07:00
Joe Savona 1db2619807 InferReferenceEffects: distinguish conditional mutations in HIR
In InferReferenceEffects, locations that are ConditionallyMutate are either 
recorded as a Mutate or Read, which means we lose the distinction btw 
conditional/unconditional mutation in later passes. This PR changes to remember 
that these places were conditionally mutable, used in later analysis.
2023-06-16 14:42:16 -07:00
Joe Savona 19976d5f83 [ez] Real location for function context values 2023-06-16 14:42:15 -07:00
Lauren Tan f467774487 [babel-plugin][ez] Rename shouldCompile to shouldVisitNode 2023-06-20 12:30:07 -04:00
Lauren Tan 46fa83d854 [eslint-plugin] Disambiguate compiler errors without instanceof
Babel re-emits errors from plugins so the `instanceof` check was no longer 
working
2023-06-20 12:30:07 -04:00
Lauren Tan 2f0ab0ec9d [eslint-plugin] Temporarily disable validateFrozenLambdas 2023-06-20 12:30:06 -04:00
Lauren Tan 98633d10a6 Add a noEmit compiler option
Defaults to false, ie it runs the codegen pass. When enabled it will simply run 
all passes up to codegen and then skip over it. Naming of this option is copied 
from [TypeScript](https://www.typescriptlang.org/tsconfig#noEmit) which has the 
same named option that makes the compiler only perform typechecking. 

I'm adding this option primarily to get around some issues running the eslint 
plugin on Meta code. The plugin would error because Forget would report 
duplicate Babel AST nodes, which I presume would only occur during codegen. It 
should also make it a tiny bit faster to not run codegen, which is a nice plus.
2023-06-20 12:30:06 -04:00
Lauren Tan 79dbf6fc19 [eslint-plugin] Try using HermesParser 2023-06-20 12:30:05 -04:00
Lauren Tan 059365d726 [eslint-plugin] Temporarily only lint on 'use forget'
Temporarily enabling 'use forget' only mode for the linter to address #1751 so 
we can land the stack internally
2023-06-20 12:30:05 -04:00
Lauren Tan 5c0622af39 Add failing test for InferReferenceEffects bug 2023-06-20 12:30:04 -04:00
Lauren Tan e378eed0f3 [eslint-plugin] Use babel plugin instead of manual traversal
This was causing some issues in the eslint plugin where the babel `hub` wasn't 
defined. afaik the hub is only setup when running the plugin as part of a babel 
pipeline, instead of a manual parse/traversal. We're using some of that infra 
for printing codeframes
2023-06-16 16:23:18 -04:00
Lauren Tan a90b5371cc [eslint-plugin] babel-plugin-fbt is a dependency 2023-06-16 14:12:35 -04:00
Lauren Tan daa23543ef [ci] Run all tests
CI will now run tests for all packages
2023-06-16 14:05:45 -04:00
Lauren Tan 0fc4c94ef1 Echo 'no tests' for packages without tests 2023-06-16 14:05:43 -04:00
Lauren Tan a558b1536a [babel-plugin] buildFunctionDeclaration errors are todos
The existing errors thrown were marked as InvalidInput, which is now considered 
critical. This was causing an error in the sync since we had 2 occurrences of 
the errors being thrown. These are really todos and not invalid code.
2023-06-16 12:18:45 -04:00
Lauren Tan 501cf92f1e Unify UnsafeInput and InvalidInput 2023-06-15 15:13:37 -04:00
Lauren Tan 0d01d5f69c [eslint-plugin] Enable validation passes 2023-06-15 14:57:10 -04:00
Lauren Tan 0fdb1e5ac7 [eslint-plugin] Add test for invariants
Turning off this flag makes only critical errors throw, so TODO errors will no 
longer be surfaced by the plugin. The previously failing test for unsupported 
syntax is now valid.
2023-06-15 14:57:07 -04:00
Lauren Tan 87a39e1995 Mark InvalidInput errors as critical 2023-06-15 14:34:49 -04:00
Lauren Tan b68c409a6b [eslint-plugin] Throw non CompilerErrors 2023-06-15 14:34:46 -04:00
Lauren Tan fe91cd8ac1 [eslint-plugin] Parse flow 2023-06-15 14:34:43 -04:00
Lauren Tan c402d8de76 [eslint-plugin] Fall back to context.getSourceCode()
Older versions of eslint use the deprecated method, so add a fallback in the 
event a modern version of eslint isn't available
2023-06-15 12:52:57 -04:00
Lauren Tan c416fb16ca [make-read-only] Make tsconfig more consistent with other pkgs 2023-06-15 12:52:56 -04:00
Lauren Tan 6810ddbf56 [react-forget-runtime] Compile with typescript 2023-06-15 12:52:55 -04:00
Lauren Tan b6c1ca9718 [build] yarn bundle:meta builds and uploads all packages
Some changes to our build infra to create a Meta bundle containing all packages. 
Needs corresponding changes in the internal upgrade commands
2023-06-15 12:52:55 -04:00
Joe Savona aae9b01f91 Test cases for inferring mutability of function expressions (as values)
This PR contains just the test cases from #1717, showing some tricky cases 
around function expression mutability inference.
2023-06-15 09:32:30 -07:00
Joe Savona 8fcceb715c Rename feature flag for function expr optimization
This got lost in a rebase, just renaming for clarity.
2023-06-12 15:56:48 -07:00
Joe Savona a21660de00 Fix calculation of nested function dependencies
We were incorrectly calculating the dependencies of nested lambdas, because the 
"component" scope was incorrectly set to the next closest parent rather than 
outermost React function (component/hook) being compiled.
2023-06-14 14:04:26 -07:00
Joe Savona a8fff7cc5c Feature to optimize function expressions
This PR adds a new feature which enables additional validation/optimization of 
function expressions, gated by the `enableOptimizeFunctionExpressions` feature 
flag. When disabled, we actually revert the changes earlier in this stack, and 
do all our lowering of function expressions in AnalyzeFunctions. 

When the feature is enabled, we incrementally process function expressions in 
the various compilation stages, eg InferTypes infers into function expressions, 
ConstantPropagation propagates constants into function expressions, etc. Because 
this stage optimizes function expressions, in this mode codegen uses the HIR as 
the source rather than the original babel node. 

The feature is disabled by default so it has no impact on generated code. For 
now i've enabled the feature on just one test to demonstrate constant 
propagation into a function expression.
2023-06-08 18:05:41 -04:00
Joe Savona 4d7d2cf4dc Type inference across function expressions boundaries
Updates InferTypes to perform type inference across function boundaries. 
Specifically InferTypes is now responsible for driving type inference of 
function expressions (rather than deferring to AnalyzeFunctions to infer 
functions), and type inference now traverses into function expressions and 
infers types of free variables taking into account information from the outer 
context. This relies on the fact that identifier ids are consistent across 
function expression boundaries and that all free variables in functions are 
guaranteed to be effectively `const`, since we promote non-const variables used 
in function expressions to context variables.
2023-06-08 14:02:04 -04:00
Joe Savona 5775102b85 InferTypes traverses function expressions 2023-06-08 14:02:04 -04:00
Joe Savona 11d4ff430f ConstantPropagation traverses function expressions 2023-06-08 14:02:03 -04:00
Joe Savona e39855d251 EliminateRedundantPhi traverses function expressions 2023-06-08 14:02:03 -04:00
Joe Savona 638e45c928 EnterSSA traverses function expressions 2023-06-08 14:02:02 -04:00
Joe Savona c2c221a452 MergeConsecutiveBlocks traverses function expressions
Currently the process of lowering function expression bodies is deferred until 
AnalyzeFunctions. However, per the motivation of the previous PR, we'd like to 
be able to perform inference across function expression boundaries. To do that 
we need to use consistent identifier ids across function expression boundaries. 
This requires SSA conversion of function expressions at the same time as we 
enter SSA. 

To start, this PR moves MergeConsecutiveBlocks for function expressions into 
that phase.
2023-06-08 14:02:02 -04:00
Lauren Tan 3673272ca4 [eslint-plugin] Add basic test for unsupported syntax
Kinda works?
2023-06-07 15:41:22 -04:00
Mofei Zhang 246936ca57 [prettier] add expected prettierrc file 2023-06-08 14:32:22 -04:00
Mofei Zhang 166f47a41e [snap] Fix snap ignored paths 2023-06-08 14:32:22 -04:00
Joe Savona 8192cd253d Fix missing memoization of scope-less variable being reassigned 2023-06-07 22:15:59 -04:00
Lauren Tan 5673672ff9 Move playground to apps
Generally we should reserve the `packages` directory for packages that 

are needed to run the compiler, while `apps` is for frontends that might 

make use of the compiler (and optionally, related packages)
2023-06-07 14:40:42 -04:00
Joe Savona bf631a0bb6 Change rules for context variable promotion
This PR updates the conditions for which variables are promoted to context 
variables. 

The previous rule was to promote any variable where the variable was reassigned 
in some function expression other than the function that declared the variable. 
Notably, this meant that we did not use context variables for variables which 
were captured in a function expression, but reassigned _outside_ a function 
expression. 

The new rule is more consistent: we promote any variable which is a) reassigned 
somewhere and b) referenced in some function expression outside of their 
declaring function. The implementation builds two sets of identifiers, one for 
each criteria, then takes the union of these two sets. 

## Motivation 

The motivation for this change is to unblock additional validations and 
optimizations of function expressions. It's currently difficult to translate 
metadata that we infer about identifiers outside of a function expression into 
metadata about the identifiers within a function expression — for example to 
infer types within function expression bodies based on type information outside, 
propagate constants into functions, infer reference effects, etc. 

After this change, the only free variables inside function expressions will be 
variables that are effectively `const` - never reassigned anywhere. Thus it will 
be safe to renumber those identifiers to match the outer context (during 
EnterSSA), making it trivial to map metadata from outside the function into the 
function. 

This change also more closely models the runtime representation — any variable 
referenced in a function, and reassigned somewhere, would have to be compiled 
(ie in a JS engine) to use a context variable.
2023-06-05 22:11:08 -04:00
Lauren Tan 4e22fa6451 Try to fix test262 in ci 2023-06-06 15:25:20 -04:00
Lauren Tan 5ebb7f1a8e Try to compile with Forget in eslint plugin
Nothing interesting for now, but it does seem to successfully run the compiler
2023-06-06 10:56:21 -04:00