You get a debugger and you get a debugger and you get a
Adds support for DebuggerStatement.
Joe Savona committed
Apr 26, 2023 at 11:27 UTC
8e7b68506f0b490c7eca3ee886bfd1ff7991d07c
12 files changed
+85
-8
compiler/forget/src/HIR/BuildHIR.ts
+14
-1
@@ -866,9 +866,22 @@ function lowerStatement(
866
);
867
return;
868
}
869
+ case "DebuggerStatement": {
870
+ const stmt = stmtPath as NodePath<t.DebuggerStatement>;
871
+ const loc = stmt.node.loc ?? GeneratedSource;
872
+ builder.push({
873
+ id: makeInstructionId(0),
874
+ lvalue: buildTemporaryPlace(builder, loc),
875
+ value: {
876
+ kind: "Debugger",
877
+ loc,
878
+ },
879
+ loc,
880
+ });
881
+ return;
882
+ }
883
case "ForInStatement":
884
case "ClassDeclaration":
871
- case "DebuggerStatement":
885
case "DeclareClass":
886
case "DeclareExportAllDeclaration":
887
case "DeclareExportDeclaration":
compiler/forget/src/HIR/HIR.ts
+2
@@ -710,6 +710,8 @@ export type InstructionValue =
710
value: Place;
711
loc: SourceLocation;
712
}
713
+ // `debugger` statement
714
+ | { kind: "Debugger"; loc: SourceLocation }
715
/**
716
* Catch-all for statements such as type imports, nested class declarations, etc
717
* which are not directly represented, but included for completeness and to allow
compiler/forget/src/HIR/PrintHIR.ts
+4
@@ -478,6 +478,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
478
value = `ExpressionStatement ${printPlace(instrValue.value)}`;
479
break;
480
}
481
+ case "Debugger": {
482
+ value = `Debugger`;
483
+ break;
484
+ }
485
default: {
486
assertExhaustive(
487
instrValue,
compiler/forget/src/HIR/visitors.ts
+2
@@ -184,6 +184,7 @@ export function* eachInstructionValueOperand(
184
yield instrValue.value;
185
break;
186
}
187
+ case "Debugger":
188
case "RegExpLiteral":
189
case "LoadGlobal":
190
case "UnsupportedNode":
@@ -451,6 +452,7 @@ export function mapInstructionOperands(
452
instrValue.value = fn(instrValue.value);
453
break;
454
}
455
+ case "Debugger":
456
case "RegExpLiteral":
457
case "LoadGlobal":
458
case "UnsupportedNode":
compiler/forget/src/Inference/InferReferenceEffects.ts
+1
@@ -673,6 +673,7 @@ function inferBlock(
673
effectKind = Effect.Mutate;
674
break;
675
}
676
+ case "Debugger":
677
case "LoadGlobal":
678
case "JSXText":
679
case "Primitive": {
compiler/forget/src/Optimization/DeadCodeElimination.ts
+4
@@ -190,6 +190,10 @@ function pruneableValue(value: InstructionValue, state: State): boolean {
190
}
191
return true;
192
}
193
+ case "Debugger": {
194
+ // explicitly retain debugger statements to not break debugging workflows
195
+ return false;
196
+ }
197
case "ExpressionStatement": {
198
// We create ExpressionStatements specifically for expressions that would otherwise
199
// be dropped but which we don't want to eliminate.
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+8
-6
@@ -439,7 +439,6 @@ function codegenInstructionNullable(
439
cx: Context,
440
instr: ReactiveInstruction
441
): t.Statement | null {
442
- let statement;
442
if (
443
instr.value.kind === "StoreLocal" ||
444
instr.value.kind === "Destructure" ||
@@ -514,14 +513,16 @@ function codegenInstructionNullable(
513
assertExhaustive(kind, `Unexpected instruction kind '${kind}'`);
514
}
515
}
516
+ } else if (instr.value.kind === "Debugger") {
517
+ return t.debuggerStatement();
518
} else {
519
const value = codegenInstructionValue(cx, instr.value);
519
- statement = codegenInstruction(cx, instr, value);
520
- }
521
- if (statement.type === "EmptyStatement") {
522
- return null;
520
+ const statement = codegenInstruction(cx, instr, value);
521
+ if (statement.type === "EmptyStatement") {
522
+ return null;
523
+ }
524
+ return statement;
525
}
524
- return statement;
526
}
527
528
function codegenForInit(
@@ -1000,6 +1001,7 @@ function codegenInstructionValue(
1001
value = codegenPlace(cx, instrValue.value);
1002
break;
1003
}
1004
+ case "Debugger":
1005
case "DeclareLocal":
1006
case "Destructure":
1007
case "StoreLocal": {
compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts
+2
-1
@@ -235,7 +235,8 @@ function mayAllocate(value: InstructionValue): boolean {
235
case "TemplateLiteral":
236
case "Primitive":
237
case "NextIterableOf":
238
- case "ExpressionStatement": {
238
+ case "ExpressionStatement":
239
+ case "Debugger": {
240
return false;
241
}
242
case "RegExpLiteral":
compiler/forget/src/ReactiveScopes/PruneNonEscapingScopes.ts
+1
@@ -417,6 +417,7 @@ function computeMemoizationInputs(
417
rvalues: value.children,
418
};
419
}
420
+ case "Debugger":
421
case "ComputedDelete":
422
case "PropertyDelete":
423
case "LoadGlobal":
compiler/forget/src/TypeInference/InferTypes.ts
+1
@@ -212,6 +212,7 @@ function* generateInstructionTypes(
212
case "NextIterableOf":
213
case "ExpressionStatement":
214
case "UnsupportedNode":
215
+ case "Debugger":
216
break;
217
default:
218
assertExhaustive(value, `Unhandled instruction value kind: ${value}`);
compiler/forget/src/__tests__/fixtures/compiler/debugger.expect.md
new
+35
@@ -0,0 +1,35 @@
1
+
2
+## Input
3
+
4
+```javascript
5
+function Component(props) {
6
+ debugger;
7
+ if (props.cond) {
8
+ debugger;
9
+ } else {
10
+ while (props.cond) {
11
+ debugger;
12
+ }
13
+ }
14
+ debugger;
15
+}
16
+
17
+```
18
+
19
+## Code
20
+
21
+```javascript
22
+function Component(props) {
23
+ debugger;
24
+ if (props.cond) {
25
+ debugger;
26
+ } else {
27
+ while (props.cond) {
28
+ debugger;
29
+ }
30
+ }
31
+ debugger;
32
+}
33
+
34
+```
35
+
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/debugger.js
new
+11
@@ -0,0 +1,11 @@
1
+function Component(props) {
2
+ debugger;
3
+ if (props.cond) {
4
+ debugger;
5
+ } else {
6
+ while (props.cond) {
7
+ debugger;
8
+ }
9
+ }
10
+ debugger;
11
+}