Fix playground tabs always showing the same HIR or reactive function
Previously we were storing a pointer to the HIR or ReactiveFunction prior to printing, so when we printed them it would always print the results of the last pass. This commit changes it so we print them to strings when iterating through the compiler pipeline so each snapshot is correctly preserved 
Lauren Tan committed
Jan 26, 2023 at 16:33 UTC
98cb9eff929aa7363e6369ed3bc38c09cdd57198
2 files changed
+65
-15
compiler/forget/packages/playground/components/Editor/Output.tsx
+20
-10
@@ -8,12 +8,7 @@
8
import generate from "@babel/generator";
9
import * as t from "@babel/types";
10
import MonacoEditor from "@monaco-editor/react";
11
-import {
12
- printHIR,
13
- printReactiveFunction,
14
- type CompilerError,
15
- type CompilerPipelineValue,
16
-} from "babel-plugin-react-forget";
11
+import { type CompilerError } from "babel-plugin-react-forget";
12
import prettier from "prettier";
13
import prettierParserBabel from "prettier/parser-babel";
14
import { memo, useMemo, useState } from "react";
@@ -24,8 +19,23 @@ const MemoizedOutput = memo(Output);
19
20
export default MemoizedOutput;
21
22
+export type PrintedCompilerPipelineValue =
23
+ | {
24
+ kind: "ast";
25
+ name: string;
26
+ fnName: string | null;
27
+ value: t.FunctionDeclaration;
28
+ }
29
+ | {
30
+ kind: "hir";
31
+ name: string;
32
+ fnName: string | null;
33
+ value: string;
34
+ }
35
+ | { kind: "reactive"; name: string; fnName: string | null; value: string };
36
+
37
export type CompilerOutput =
28
- | { kind: "ok"; results: Map<string, CompilerPipelineValue[]> }
38
+ | { kind: "ok"; results: Map<string, PrintedCompilerPipelineValue[]> }
39
| { kind: "err"; error: CompilerError };
40
41
type Props = {
@@ -45,8 +55,8 @@ function tabify(source: string, compilerOutput: CompilerOutput) {
55
switch (result.kind) {
56
case "hir": {
57
const prev = concattedResults.get(result.name);
48
- const next = printHIR(result.value.body);
49
- const identName = `function ${result.value.id?.name}`;
58
+ const next = result.value;
59
+ const identName = `function ${result.fnName}`;
60
if (prev != null) {
61
concattedResults.set(passName, `${prev}\n\n${identName}\n${next}`);
62
} else {
@@ -56,7 +66,7 @@ function tabify(source: string, compilerOutput: CompilerOutput) {
66
}
67
case "reactive": {
68
const prev = concattedResults.get(passName);
59
- const next = printReactiveFunction(result.value);
69
+ const next = result.value;
70
if (prev != null) {
71
concattedResults.set(passName, `${prev}\n\n${next}`);
72
} else {
compiler/forget/packages/playground/components/Editor/index.tsx
+45
-5
@@ -8,7 +8,11 @@
8
import { parse } from "@babel/parser";
9
import traverse, { NodePath } from "@babel/traverse";
10
import * as t from "@babel/types";
11
-import { CompilerPipelineValue, run } from "babel-plugin-react-forget";
11
+import {
12
+ printHIR,
13
+ printReactiveFunction,
14
+ run,
15
+} from "babel-plugin-react-forget";
16
import clsx from "clsx";
17
import invariant from "invariant";
18
import { useSnackbar } from "notistack";
@@ -24,7 +28,11 @@ import {
28
} from "../../lib/stores";
29
import { useStore, useStoreDispatch } from "../StoreContext";
30
import Input from "./Input";
27
-import { CompilerOutput, default as Output } from "./Output";
31
+import {
32
+ CompilerOutput,
33
+ default as Output,
34
+ PrintedCompilerPipelineValue,
35
+} from "./Output";
36
37
function parseFunctions(
38
source: string
@@ -50,8 +58,8 @@ function parseFunctions(
58
59
function compile(source: string): CompilerOutput {
60
try {
53
- const results = new Map<string, CompilerPipelineValue[]>();
54
- const upsert = (result: CompilerPipelineValue) => {
61
+ const results = new Map<string, PrintedCompilerPipelineValue[]>();
62
+ const upsert = (result: PrintedCompilerPipelineValue) => {
63
const entry = results.get(result.name);
64
if (Array.isArray(entry)) {
65
entry.push(result);
@@ -61,7 +69,39 @@ function compile(source: string): CompilerOutput {
69
};
70
for (const fn of parseFunctions(source)) {
71
for (const result of run(fn)) {
64
- upsert(result);
72
+ const fnName = fn.node.id?.name ?? null;
73
+ switch (result.kind) {
74
+ case "ast": {
75
+ upsert({
76
+ kind: "ast",
77
+ fnName,
78
+ name: result.name,
79
+ value: result.value,
80
+ });
81
+ break;
82
+ }
83
+ case "hir": {
84
+ upsert({
85
+ kind: "hir",
86
+ fnName,
87
+ name: result.name,
88
+ value: printHIR(result.value.body),
89
+ });
90
+ break;
91
+ }
92
+ case "reactive": {
93
+ upsert({
94
+ kind: "reactive",
95
+ fnName,
96
+ name: result.name,
97
+ value: printReactiveFunction(result.value),
98
+ });
99
+ break;
100
+ }
101
+ default: {
102
+ throw new Error(`Unhandled result ${result}`);
103
+ }
104
+ }
105
}
106
}
107
return { kind: "ok", results };