From 8e7b68506f0b490c7eca3ee886bfd1ff7991d07c Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Wed, 26 Apr 2023 11:27:37 -0700 Subject: [PATCH] You get a debugger and you get a debugger and you get a Adds support for DebuggerStatement. --- compiler/forget/src/HIR/BuildHIR.ts | 15 +++++++- compiler/forget/src/HIR/HIR.ts | 2 ++ compiler/forget/src/HIR/PrintHIR.ts | 4 +++ compiler/forget/src/HIR/visitors.ts | 2 ++ .../src/Inference/InferReferenceEffects.ts | 1 + .../src/Optimization/DeadCodeElimination.ts | 4 +++ .../ReactiveScopes/CodegenReactiveFunction.ts | 14 ++++---- .../InferReactiveScopeVariables.ts | 3 +- .../ReactiveScopes/PruneNonEscapingScopes.ts | 1 + .../forget/src/TypeInference/InferTypes.ts | 1 + .../fixtures/compiler/debugger.expect.md | 35 +++++++++++++++++++ .../__tests__/fixtures/compiler/debugger.js | 11 ++++++ 12 files changed, 85 insertions(+), 8 deletions(-) create mode 100644 compiler/forget/src/__tests__/fixtures/compiler/debugger.expect.md create mode 100644 compiler/forget/src/__tests__/fixtures/compiler/debugger.js diff --git a/compiler/forget/src/HIR/BuildHIR.ts b/compiler/forget/src/HIR/BuildHIR.ts index 9be5f9e5e1..188e92b5b1 100644 --- a/compiler/forget/src/HIR/BuildHIR.ts +++ b/compiler/forget/src/HIR/BuildHIR.ts @@ -866,9 +866,22 @@ function lowerStatement( ); return; } + case "DebuggerStatement": { + const stmt = stmtPath as NodePath; + const loc = stmt.node.loc ?? GeneratedSource; + builder.push({ + id: makeInstructionId(0), + lvalue: buildTemporaryPlace(builder, loc), + value: { + kind: "Debugger", + loc, + }, + loc, + }); + return; + } case "ForInStatement": case "ClassDeclaration": - case "DebuggerStatement": case "DeclareClass": case "DeclareExportAllDeclaration": case "DeclareExportDeclaration": diff --git a/compiler/forget/src/HIR/HIR.ts b/compiler/forget/src/HIR/HIR.ts index 377a71c875..d9fe6f231c 100644 --- a/compiler/forget/src/HIR/HIR.ts +++ b/compiler/forget/src/HIR/HIR.ts @@ -710,6 +710,8 @@ export type InstructionValue = value: Place; loc: SourceLocation; } + // `debugger` statement + | { kind: "Debugger"; loc: SourceLocation } /** * Catch-all for statements such as type imports, nested class declarations, etc * which are not directly represented, but included for completeness and to allow diff --git a/compiler/forget/src/HIR/PrintHIR.ts b/compiler/forget/src/HIR/PrintHIR.ts index ed37e23be6..d59e2e11a0 100644 --- a/compiler/forget/src/HIR/PrintHIR.ts +++ b/compiler/forget/src/HIR/PrintHIR.ts @@ -478,6 +478,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string { value = `ExpressionStatement ${printPlace(instrValue.value)}`; break; } + case "Debugger": { + value = `Debugger`; + break; + } default: { assertExhaustive( instrValue, diff --git a/compiler/forget/src/HIR/visitors.ts b/compiler/forget/src/HIR/visitors.ts index 87a8bbacd1..f73ccce33b 100644 --- a/compiler/forget/src/HIR/visitors.ts +++ b/compiler/forget/src/HIR/visitors.ts @@ -184,6 +184,7 @@ export function* eachInstructionValueOperand( yield instrValue.value; break; } + case "Debugger": case "RegExpLiteral": case "LoadGlobal": case "UnsupportedNode": @@ -451,6 +452,7 @@ export function mapInstructionOperands( instrValue.value = fn(instrValue.value); break; } + case "Debugger": case "RegExpLiteral": case "LoadGlobal": case "UnsupportedNode": diff --git a/compiler/forget/src/Inference/InferReferenceEffects.ts b/compiler/forget/src/Inference/InferReferenceEffects.ts index d70c335c9f..9704e67e9e 100644 --- a/compiler/forget/src/Inference/InferReferenceEffects.ts +++ b/compiler/forget/src/Inference/InferReferenceEffects.ts @@ -673,6 +673,7 @@ function inferBlock( effectKind = Effect.Mutate; break; } + case "Debugger": case "LoadGlobal": case "JSXText": case "Primitive": { diff --git a/compiler/forget/src/Optimization/DeadCodeElimination.ts b/compiler/forget/src/Optimization/DeadCodeElimination.ts index cbc6025361..c7a9b3272e 100644 --- a/compiler/forget/src/Optimization/DeadCodeElimination.ts +++ b/compiler/forget/src/Optimization/DeadCodeElimination.ts @@ -190,6 +190,10 @@ function pruneableValue(value: InstructionValue, state: State): boolean { } return true; } + case "Debugger": { + // explicitly retain debugger statements to not break debugging workflows + return false; + } case "ExpressionStatement": { // We create ExpressionStatements specifically for expressions that would otherwise // be dropped but which we don't want to eliminate. diff --git a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts index 3be220d796..0ec506b548 100644 --- a/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts +++ b/compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts @@ -439,7 +439,6 @@ function codegenInstructionNullable( cx: Context, instr: ReactiveInstruction ): t.Statement | null { - let statement; if ( instr.value.kind === "StoreLocal" || instr.value.kind === "Destructure" || @@ -514,14 +513,16 @@ function codegenInstructionNullable( assertExhaustive(kind, `Unexpected instruction kind '${kind}'`); } } + } else if (instr.value.kind === "Debugger") { + return t.debuggerStatement(); } else { const value = codegenInstructionValue(cx, instr.value); - statement = codegenInstruction(cx, instr, value); + const statement = codegenInstruction(cx, instr, value); + if (statement.type === "EmptyStatement") { + return null; + } + return statement; } - if (statement.type === "EmptyStatement") { - return null; - } - return statement; } function codegenForInit( @@ -1000,6 +1001,7 @@ function codegenInstructionValue( value = codegenPlace(cx, instrValue.value); break; } + case "Debugger": case "DeclareLocal": case "Destructure": case "StoreLocal": { diff --git a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts index 09d530f553..951b584d65 100644 --- a/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts +++ b/compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts @@ -235,7 +235,8 @@ function mayAllocate(value: InstructionValue): boolean { case "TemplateLiteral": case "Primitive": case "NextIterableOf": - case "ExpressionStatement": { + case "ExpressionStatement": + case "Debugger": { return false; } case "RegExpLiteral": diff --git a/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts b/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts index 3a0db37932..a3f9464c9c 100644 --- a/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts +++ b/compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts @@ -417,6 +417,7 @@ function computeMemoizationInputs( rvalues: value.children, }; } + case "Debugger": case "ComputedDelete": case "PropertyDelete": case "LoadGlobal": diff --git a/compiler/forget/src/TypeInference/InferTypes.ts b/compiler/forget/src/TypeInference/InferTypes.ts index 4b4cbe67f9..33f452d6dd 100644 --- a/compiler/forget/src/TypeInference/InferTypes.ts +++ b/compiler/forget/src/TypeInference/InferTypes.ts @@ -212,6 +212,7 @@ function* generateInstructionTypes( case "NextIterableOf": case "ExpressionStatement": case "UnsupportedNode": + case "Debugger": break; default: assertExhaustive(value, `Unhandled instruction value kind: ${value}`); diff --git a/compiler/forget/src/__tests__/fixtures/compiler/debugger.expect.md b/compiler/forget/src/__tests__/fixtures/compiler/debugger.expect.md new file mode 100644 index 0000000000..3adba77589 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/debugger.expect.md @@ -0,0 +1,35 @@ + +## Input + +```javascript +function Component(props) { + debugger; + if (props.cond) { + debugger; + } else { + while (props.cond) { + debugger; + } + } + debugger; +} + +``` + +## Code + +```javascript +function Component(props) { + debugger; + if (props.cond) { + debugger; + } else { + while (props.cond) { + debugger; + } + } + debugger; +} + +``` + \ No newline at end of file diff --git a/compiler/forget/src/__tests__/fixtures/compiler/debugger.js b/compiler/forget/src/__tests__/fixtures/compiler/debugger.js new file mode 100644 index 0000000000..a5779466e7 --- /dev/null +++ b/compiler/forget/src/__tests__/fixtures/compiler/debugger.js @@ -0,0 +1,11 @@ +function Component(props) { + debugger; + if (props.cond) { + debugger; + } else { + while (props.cond) { + debugger; + } + } + debugger; +}