Files
react/compiler/forget/src/CompilerDriver.ts
Joseph Savona 00a58cdab1 Option to validate output with ESLint
Adds a new compiler option `validateNoUseBeforeDefine`, which enables a 
post-codegen pass to validate that there are no usages of values before they are 
defined (which causes a ReferenceError at runtime). This can occur when a value 
is accessed when its in the TDZ (temporary dead zone), after the hoisted 
_declaration_ but before the variable is defined: 

```javascript 

function foo() { 

x; // x is in the TDX here: the binding from the subsequent statement is 
hoisted, but x is not yet defined. 

let x; 

} 

``` 

* The validation is off by default, but enabled in transform-test 

* The validation crashes compilation, rather than bailout, because the code has 
already been mangled and we can't roll back at the point the validation runs. 

* The validator uses ESLint's no-use-before-define rule by printing the program 
to source and then configuring ESLint to use Hermes parser. 

* transform-test now supports tests prefixed with "error." to indicate tests for 
which compilation is expected to crash (not just bailout), and the expect file 
includes the error message.
2022-10-19 13:00:47 -07:00

68 lines
1.8 KiB
TypeScript

/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { NodePath } from "@babel/traverse";
import * as t from "@babel/types";
import * as BE from "./BackEnd";
import { CompilerContext } from "./CompilerContext";
import { CompilerOptions } from "./CompilerOptions";
import * as ME from "./MiddleEnd";
import { PassManager } from "./PassManager";
/**
* Compiler Driver
*
* Owns {@link CompilerContext} and source program.
*/
export interface CompilerDriver {
context: CompilerContext;
program: NodePath<t.Program>;
compile(): void;
}
export function createCompilerDriver(
options: CompilerOptions,
program: NodePath<t.Program>
): CompilerDriver {
const context = new CompilerContext(options, program);
return {
context,
program,
compile() {
const passManager = new PassManager(program, context);
// Syntax Analysis and IR Generation.
passManager.addPass(ME.ReactFuncsInfer);
passManager.addPass(ME.ParamAnalysis);
passManager.addPass(ME.BodyAnalysis);
passManager.addPass(ME.SketchyCodeCheck);
passManager.addPass(ME.RefKindInfer);
passManager.addPass(ME.DumpIR);
passManager.addPass(ME.IRCheck);
passManager.addPass(ME.DumpCFG);
// Dependency Analysis via DepGraph.
passManager.addPass(ME.DepGraphAnalysis);
// LIR Generation.
passManager.addPass(BE.LIRGen);
passManager.addPass(BE.MemoCacheAlloc);
passManager.addPass(BE.DumpLIR);
passManager.addPass(BE.SanityCheck);
// JS Generation.
passManager.addPass(BE.JSGen);
// Optionally sanity-check the transformed output
passManager.addPass(BE.PostCodegenValidator);
passManager.runAll();
},
};
}