Skip to content

Commit aad7970

Browse files
committed
Fix valid check, tree-shaking and binding trace
1 parent 90d31aa commit aad7970

3 files changed

Lines changed: 46 additions & 19 deletions

File tree

packages/start/src/directives/compile.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import path from "node:path";
21
import * as babel from "@babel/core";
2+
import path from "node:path";
33
import { directivesPlugin, type StateContext } from "./plugin.ts";
44
import xxHash32 from "./xxhash32.ts";
55

@@ -9,23 +9,21 @@ export interface CompileResult {
99
map: babel.BabelFileResult["map"];
1010
}
1111

12-
export type CompileOptions = Omit<StateContext, "count" | "hash" | "imports">;
12+
export type CompileOptions = Omit<StateContext, "count" | "hash" | "imports" | "valid">;
1313

1414
export async function compile(
1515
id: string,
1616
code: string,
1717
options: CompileOptions,
1818
): Promise<CompileResult> {
1919
const context: StateContext = {
20-
...options,
21-
hash: xxHash32(id).toString(16),
22-
count: 0,
23-
imports: new Map(),
24-
}
25-
const pluginOption = [
26-
directivesPlugin,
27-
context,
28-
];
20+
...options,
21+
valid: false,
22+
hash: xxHash32(id).toString(16),
23+
count: 0,
24+
imports: new Map(),
25+
};
26+
const pluginOption = [directivesPlugin, context];
2927
const plugins: NonNullable<NonNullable<babel.TransformOptions["parserOpts"]>["plugins"]> = [
3028
"jsx",
3129
];
@@ -47,7 +45,7 @@ export async function compile(
4745

4846
if (result) {
4947
return {
50-
valid: context.count > 0,
48+
valid: context.valid,
5149
code: result.code || "",
5250
map: result.map,
5351
};

packages/start/src/directives/plugin.ts

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface StateContext {
1818
hash: string;
1919
count: number;
2020
imports: Map<string, t.Identifier>;
21+
valid: boolean;
2122

2223
definitions: {
2324
register: ImportDefinition;
@@ -146,7 +147,12 @@ function traceBinding(path: babel.NodePath, name: string): Binding | undefined {
146147
if (right) {
147148
return traceBinding(path, right.node.name);
148149
}
149-
return current;
150+
151+
// Only valid for functions
152+
const func = unwrapPath(current.path.get('init'), isValidFunction);
153+
if (func) {
154+
return current;
155+
}
150156
}
151157
}
152158
return undefined;
@@ -329,10 +335,16 @@ function transformModuleLevelDirective(ctx: StateContext, program: babel.NodePat
329335
}
330336
}
331337

332-
program.pushContainer("body", [
333-
t.variableDeclaration("const", declarations),
334-
t.exportNamedDeclaration(null, specifiers, null),
335-
]);
338+
const body: t.Statement[] = [];
339+
340+
if (declarations.length > 0) {
341+
body.push(t.variableDeclaration("const", declarations));
342+
}
343+
if (specifiers.length > 0) {
344+
body.push(t.exportNamedDeclaration(null, specifiers, null));
345+
}
346+
347+
program.pushContainer("body", body);
336348
}
337349
}
338350

@@ -344,6 +356,7 @@ export function directivesPlugin(): babel.PluginObj<State> {
344356
const isModuleLevel = isDirectiveValid(ctx.opts, program.node.directives);
345357
if (isModuleLevel) {
346358
transformModuleLevelDirective(ctx.opts, program);
359+
ctx.opts.valid = true;
347360
} else {
348361
// First, bubble up function declarations
349362
program.traverse({
@@ -366,6 +379,7 @@ export function directivesPlugin(): babel.PluginObj<State> {
366379
program.scope.crawl();
367380

368381
if (ctx.opts.count > 0) {
382+
ctx.opts.valid = true;
369383
removeUnusedVariables(program);
370384
}
371385
}

packages/start/src/directives/remove-unused-variables.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type * as babel from "@babel/core";
2-
import type * as t from "@babel/types";
2+
import * as t from "@babel/types";
3+
import { isPathValid } from "./paths.ts";
34

45
export function removeUnusedVariables(program: babel.NodePath<t.Program>) {
56
// TODO(Alexis):
@@ -23,7 +24,16 @@ export function removeUnusedVariables(program: babel.NodePath<t.Program>) {
2324
case "hoisted":
2425
case "module":
2526
if (binding.references === 0 && !binding.path.removed) {
26-
binding.path.remove();
27+
if (isPathValid(path.parentPath, t.isImportDeclaration)) {
28+
const parent = path.parentPath;
29+
if (parent.node.specifiers.length === 1) {
30+
parent.remove();
31+
} else {
32+
binding.path.remove();
33+
}
34+
} else {
35+
binding.path.remove();
36+
}
2737
dirty = true;
2838
}
2939
break;
@@ -34,6 +44,11 @@ export function removeUnusedVariables(program: babel.NodePath<t.Program>) {
3444
}
3545
}
3646
},
47+
VariableDeclaration(path) {
48+
if (path.node.declarations.length === 0) {
49+
path.remove();
50+
}
51+
},
3752
});
3853
program.scope.crawl();
3954
}

0 commit comments

Comments
 (0)