mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[babel] Don't use source location for hoisting check
Instead of using the source location to check for hoisting, just stop checking for a given component after we reach it's declaration. By definition all references to it before are (potential) hoisting errors. Note that there could be false positives but that's ok.
This commit is contained in:
@@ -618,7 +618,18 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel(
|
||||
program.traverse({
|
||||
Identifier(id) {
|
||||
const fn = fnNames.get(id.node.name);
|
||||
if (fnIds.has(id.node) || !fn) {
|
||||
// We're not tracking this identifier.
|
||||
if (!fn) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* We've reached the declaration, hoisting is no longer possible, stop
|
||||
* checking for this component name.
|
||||
*/
|
||||
if (fnIds.has(id.node)) {
|
||||
fnIds.delete(id.node);
|
||||
fnNames.delete(id.node.name);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -627,12 +638,7 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel(
|
||||
* A null scope means there's no function scope, which means we're at the
|
||||
* top level scope.
|
||||
*/
|
||||
if (
|
||||
scope === null &&
|
||||
id.node.loc &&
|
||||
fn.loc &&
|
||||
occursBefore(id.node.loc, fn.loc)
|
||||
) {
|
||||
if (scope === null) {
|
||||
errors.pushErrorDetail(
|
||||
new CompilerErrorDetail({
|
||||
reason: `Encountered ${fn.name} used before declaration which breaks Forget's gating codegen due to hoisting`,
|
||||
@@ -649,15 +655,3 @@ function checkFunctionReferencedBeforeDeclarationAtTopLevel(
|
||||
|
||||
return errors.details.length > 0 ? errors : null;
|
||||
}
|
||||
|
||||
function occursBefore(a: t.SourceLocation, b: t.SourceLocation): boolean {
|
||||
if (a.start.line > b.start.line) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.start.line < b.start.line) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return a.start.column < b.start.column;
|
||||
}
|
||||
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @flow @gating
|
||||
component Foo(ref: React.RefSetter<Controls>) {
|
||||
return <Bar ref={ref}/>;
|
||||
}
|
||||
```
|
||||
|
||||
## Code
|
||||
|
||||
```javascript
|
||||
import { isForgetEnabled_Fixtures } from "ReactForgetFeatureFlag";
|
||||
import { unstable_useMemoCache as useMemoCache } from "react";
|
||||
const Foo = React.forwardRef(Foo_withRef);
|
||||
const Foo_withRef = isForgetEnabled_Fixtures()
|
||||
? function Foo_withRef(_$$empty_props_placeholder$$, ref) {
|
||||
const $ = useMemoCache(2);
|
||||
let t0;
|
||||
if ($[0] !== ref) {
|
||||
t0 = <Bar ref={ref} />;
|
||||
$[0] = ref;
|
||||
$[1] = t0;
|
||||
} else {
|
||||
t0 = $[1];
|
||||
}
|
||||
return t0;
|
||||
}
|
||||
: function Foo_withRef(
|
||||
_$$empty_props_placeholder$$: $ReadOnly<{ ... }>,
|
||||
ref: React.RefSetter<Controls>
|
||||
) {
|
||||
return <Bar ref={ref} />;
|
||||
};
|
||||
|
||||
```
|
||||
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
|
||||
## Input
|
||||
|
||||
```javascript
|
||||
// @flow @gating
|
||||
component Foo(ref: React.RefSetter<Controls>) {
|
||||
return <Bar ref={ref}/>;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Error
|
||||
|
||||
```
|
||||
[ReactForget] Invariant: Encountered Foo_withRef used before declaration which breaks Forget's gating codegen due to hoisting. Rewrite the reference to not use hoisting to fix this issue (2:2)
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user