9
import * as t from '@babel/types';
10
import prettyFormat from 'pretty-format';
11
import {CompilerOutputMode, Logger, ProgramContext} from '.';
12
+import {CompilerError} from '../CompilerError';
13
+import {Err, Ok, Result} from '../Utils/Result';
14
import {
15
HIRFunction,
16
+ IdentifierId,
17
ReactiveFunction,
18
assertConsistentIdentifiers,
19
assertTerminalPredsExist,
92
import {propagateScopeDependenciesHIR} from '../HIR/PropagateScopeDependenciesHIR';
93
import {outlineJSX} from '../Optimization/OutlineJsx';
94
import {optimizePropsMethodCalls} from '../Optimization/OptimizePropsMethodCalls';
92
-import {validateNoImpureFunctionsInRender} from '../Validation/ValidateNoImpureFunctionsInRender';
95
import {validateStaticComponents} from '../Validation/ValidateStaticComponents';
96
import {validateNoFreezingKnownMutableFunctions} from '../Validation/ValidateNoFreezingKnownMutableFunctions';
97
import {inferMutationAliasingEffects} from '../Inference/InferMutationAliasingEffects';
120
logger: Logger | null,
121
filename: string | null,
122
code: string | null,
121
-): CodegenFunction {
123
+): Result<CodegenFunction, CompilerError> {
124
const contextIdentifiers = findContextIdentifiers(func);
125
const env = new Environment(
126
func.scope,
151
t.FunctionDeclaration | t.ArrowFunctionExpression | t.FunctionExpression
152
>,
153
env: Environment,
152
-): CodegenFunction {
154
+): Result<CodegenFunction, CompilerError> {
155
const log = (value: CompilerPipelineValue): void => {
156
env.logger?.debugLogIRs?.(value);
157
};
161
pruneMaybeThrows(hir);
162
log({kind: 'hir', name: 'PruneMaybeThrows', value: hir});
163
162
- validateContextVariableLValues(hir);
163
- validateUseMemo(hir).unwrap();
164
+ env.tryRecord(() => {
165
+ validateContextVariableLValues(hir);
166
+ });
167
+ env.tryRecord(() => {
168
+ validateUseMemo(hir).unwrap();
169
+ });
170
171
if (env.enableDropManualMemoization) {
166
- dropManualMemoization(hir).unwrap();
172
+ env.tryRecord(() => {
173
+ dropManualMemoization(hir).unwrap();
174
+ });
175
log({kind: 'hir', name: 'DropManualMemoization', value: hir});
176
}
177
204
205
if (env.enableValidations) {
206
if (env.config.validateHooksUsage) {
199
- validateHooksUsage(hir).unwrap();
207
+ env.tryRecord(() => {
208
+ validateHooksUsage(hir).unwrap();
209
+ });
210
}
211
if (env.config.validateNoCapitalizedCalls) {
202
- validateNoCapitalizedCalls(hir).unwrap();
212
+ env.tryRecord(() => {
213
+ validateNoCapitalizedCalls(hir).unwrap();
214
+ });
215
}
216
}
217
225
log({kind: 'hir', name: 'InferMutationAliasingEffects', value: hir});
226
if (env.enableValidations) {
227
if (mutabilityAliasingErrors.isErr()) {
216
- throw mutabilityAliasingErrors.unwrapErr();
228
+ env.recordErrors(mutabilityAliasingErrors.unwrapErr());
229
}
230
}
231
246
log({kind: 'hir', name: 'InferMutationAliasingRanges', value: hir});
247
if (env.enableValidations) {
248
if (mutabilityAliasingRangeErrors.isErr()) {
237
- throw mutabilityAliasingRangeErrors.unwrapErr();
249
+ env.recordErrors(mutabilityAliasingRangeErrors.unwrapErr());
250
}
239
- validateLocalsNotReassignedAfterRender(hir);
251
+ env.tryRecord(() => {
252
+ validateLocalsNotReassignedAfterRender(hir);
253
+ });
254
}
255
256
if (env.enableValidations) {
259
}
260
261
if (env.config.validateRefAccessDuringRender) {
248
- validateNoRefAccessInRender(hir).unwrap();
262
+ env.tryRecord(() => {
263
+ validateNoRefAccessInRender(hir).unwrap();
264
+ });
265
}
266
267
if (env.config.validateNoSetStateInRender) {
252
- validateNoSetStateInRender(hir).unwrap();
268
+ env.tryRecord(() => {
269
+ validateNoSetStateInRender(hir).unwrap();
270
+ });
271
}
272
273
if (
276
) {
277
env.logErrors(validateNoDerivedComputationsInEffects_exp(hir));
278
} else if (env.config.validateNoDerivedComputationsInEffects) {
261
- validateNoDerivedComputationsInEffects(hir);
279
+ env.tryRecord(() => {
280
+ validateNoDerivedComputationsInEffects(hir);
281
+ });
282
}
283
284
if (env.config.validateNoSetStateInEffects && env.outputMode === 'lint') {
289
env.logErrors(validateNoJSXInTryStatement(hir));
290
}
291
272
- if (env.config.validateNoImpureFunctionsInRender) {
273
- validateNoImpureFunctionsInRender(hir).unwrap();
274
- }
275
-
276
- validateNoFreezingKnownMutableFunctions(hir).unwrap();
292
+ env.tryRecord(() => {
293
+ validateNoFreezingKnownMutableFunctions(hir).unwrap();
294
+ });
295
}
296
297
inferReactivePlaces(hir);
303
env.config.validateExhaustiveEffectDependencies
304
) {
305
// NOTE: this relies on reactivity inference running first
288
- validateExhaustiveDependencies(hir).unwrap();
306
+ env.tryRecord(() => {
307
+ validateExhaustiveDependencies(hir).unwrap();
308
+ });
309
}
310
}
311
334
log({kind: 'hir', name: 'InferReactiveScopeVariables', value: hir});
335
}
336
317
- const fbtOperands = memoizeFbtAndMacroOperandsInSameScope(hir);
337
+ let fbtOperands: Set<IdentifierId> = new Set();
338
+ fbtOperands = memoizeFbtAndMacroOperandsInSameScope(hir);
339
log({
340
kind: 'hir',
341
name: 'MemoizeFbtAndMacroOperandsInSameScope',
427
value: hir,
428
});
429
409
- const reactiveFunction = buildReactiveFunction(hir);
430
+ let reactiveFunction!: ReactiveFunction;
431
+ reactiveFunction = buildReactiveFunction(hir);
432
log({
433
kind: 'reactive',
434
name: 'BuildReactiveFunction',
515
value: reactiveFunction,
516
});
517
496
- const uniqueIdentifiers = renameVariables(reactiveFunction);
518
+ let uniqueIdentifiers: Set<string> = new Set();
519
+ uniqueIdentifiers = renameVariables(reactiveFunction);
520
log({
521
kind: 'reactive',
522
name: 'RenameVariables',
534
env.config.enablePreserveExistingMemoizationGuarantees ||
535
env.config.validatePreserveExistingMemoizationGuarantees
536
) {
514
- validatePreservedManualMemoization(reactiveFunction).unwrap();
537
+ env.tryRecord(() => {
538
+ validatePreservedManualMemoization(reactiveFunction).unwrap();
539
+ });
540
}
541
517
- const ast = codegenFunction(reactiveFunction, {
542
+ const codegenResult = codegenFunction(reactiveFunction, {
543
uniqueIdentifiers,
544
fbtOperands,
520
- }).unwrap();
545
+ });
546
+ if (codegenResult.isErr()) {
547
+ env.recordErrors(codegenResult.unwrapErr());
548
+ return Err(env.aggregateErrors());
549
+ }
550
+ const ast = codegenResult.unwrap();
551
log({kind: 'ast', name: 'Codegen', value: ast});
552
for (const outlined of ast.outlined) {
553
log({kind: 'ast', name: 'Codegen (outlined)', value: outlined.fn});
554
}
555
556
if (env.config.validateSourceLocations) {
527
- validateSourceLocations(func, ast).unwrap();
557
+ env.tryRecord(() => {
558
+ validateSourceLocations(func, ast).unwrap();
559
+ });
560
}
561
562
/**
568
throw new Error('unexpected error');
569
}
570
539
- return ast;
571
+ if (env.hasErrors()) {
572
+ return Err(env.aggregateErrors());
573
+ }
574
+ return Ok(ast);
575
}
576
577
export function compileFn(
585
logger: Logger | null,
586
filename: string | null,
587
code: string | null,
553
-): CodegenFunction {
588
+): Result<CodegenFunction, CompilerError> {
589
return run(
590
func,
591
config,