Skip to content

Commit d6695de

Browse files
authored
Merge pull request #33 from ef4/fix-unbalanced-exit
Fix unbalanced exit
2 parents 879bd65 + 2fb38b7 commit d6695de

File tree

2 files changed

+67
-15
lines changed

2 files changed

+67
-15
lines changed

Diff for: src/index.ts

+13-6
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import type * as Babel from "@babel/core";
22
import type { types as t, NodePath } from "@babel/core";
3-
import { createRequire } from "node:module";
43
import { ImportUtil, type Importer } from "babel-import-util";
54
import { globalId } from "./global-id.ts";
6-
const req = createRequire(import.meta.url);
7-
const { default: decoratorSyntax } = req("@babel/plugin-syntax-decorators");
5+
6+
// @ts-expect-error no upstream types
7+
import decoratorSyntax from "@babel/plugin-syntax-decorators";
88

99
interface State extends Babel.PluginPass {
1010
currentClassBodies: t.ClassBody[];
1111
currentObjectExpressions: {
12+
node: t.ObjectExpression;
1213
decorated: [
1314
"field" | "method",
1415
t.Expression, // for the property name
@@ -54,8 +55,10 @@ function makeVisitor(babel: typeof Babel): Babel.Visitor<State> {
5455
enter(path, state) {
5556
state.currentClassBodies.unshift(path.node);
5657
},
57-
exit(_path, state) {
58-
state.currentClassBodies.shift();
58+
exit(path, state) {
59+
if (state.currentClassBodies[0] === path.node) {
60+
state.currentClassBodies.shift();
61+
}
5962
},
6063
},
6164
ClassExpression(path, state) {
@@ -241,12 +244,16 @@ function makeVisitor(babel: typeof Babel): Babel.Visitor<State> {
241244
}
242245
},
243246
ObjectExpression: {
244-
enter(_path, state) {
247+
enter(path, state) {
245248
state.currentObjectExpressions.unshift({
249+
node: path.node,
246250
decorated: [],
247251
});
248252
},
249253
exit(path, state) {
254+
if (state.currentObjectExpressions[0]?.node !== path.node) {
255+
return;
256+
}
250257
let { decorated } = state.currentObjectExpressions.shift()!;
251258
if (decorated.length > 0) {
252259
state.util.replaceWith(path, (i) =>

Diff for: tests/plugin-interop-test.ts

+54-9
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,22 @@
11
import { module, test } from "qunit";
2-
import { builder, Builder } from "./helpers.ts";
2+
import { builder } from "./helpers.ts";
33
import { type LegacyClassDecorator } from "../src/runtime.ts";
44
import * as runtimeImpl from "../src/runtime.ts";
55
import ourDecorators from "../src/index.ts";
66
import { createRequire } from "node:module";
77
import { mkdtemp, writeFile } from "node:fs/promises";
88
import { join } from "node:path";
99
import { tmpdir } from "node:os";
10+
import type * as Babel from "@babel/core";
1011

1112
const require = createRequire(import.meta.url);
1213
const Colocation = require("@embroider/shared-internals/src/template-colocation-plugin");
1314

14-
module("plugin-interop", (hooks) => {
15-
let build: Builder;
16-
17-
hooks.before(async () => {
15+
module("plugin-interop", () => {
16+
test("colocation", async (assert) => {
1817
let dir = await mkdtemp(join(tmpdir(), "decorator-transforms-"));
1918
await writeFile(join(dir, "example.hbs"), "");
20-
build = builder(
19+
let build = builder(
2120
[],
2221
[
2322
[
@@ -29,9 +28,6 @@ module("plugin-interop", (hooks) => {
2928
[],
3029
join(dir, "example.js")
3130
);
32-
});
33-
34-
test("colocation", async (assert) => {
3531
let red: LegacyClassDecorator = (target) => {
3632
return class extends target {
3733
get red() {
@@ -77,4 +73,53 @@ module("plugin-interop", (hooks) => {
7773
assert.strictEqual(new Example().red, "#ff0000");
7874
assert.strictEqual(setComponents, 1);
7975
});
76+
77+
// This models a behavior that @embroider/macros uses when trying to optimize
78+
// `getConfig().with.a.path`, since it uses parentPath to go higher and
79+
// replace a larger part of the expression.
80+
test("parentPath replace", async (assert) => {
81+
function inserter(babel: typeof Babel): Babel.PluginObj {
82+
let t = babel.types;
83+
return {
84+
visitor: {
85+
CallExpression: {
86+
enter(path) {
87+
let callee = path.node.callee;
88+
if (callee.type === "Identifier" && callee.name === "expandMe") {
89+
path.parentPath.replaceWith(
90+
t.objectExpression([
91+
t.objectProperty(
92+
t.identifier("value"),
93+
t.stringLiteral("it worked")
94+
),
95+
])
96+
);
97+
}
98+
},
99+
},
100+
},
101+
};
102+
}
103+
104+
let build = builder(
105+
[],
106+
[
107+
[
108+
ourDecorators,
109+
{ runtime: { import: "decorator-transforms/runtime" } },
110+
],
111+
[inserter],
112+
],
113+
[]
114+
);
115+
116+
let { default: Example } = await build.module(
117+
`
118+
export default expandMe().a;
119+
`,
120+
{}
121+
);
122+
123+
assert.strictEqual(Example.value, "it worked");
124+
});
80125
});

0 commit comments

Comments
 (0)