@actview/plugin-babel 1.0.6 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +64 -7
  2. package/package.json +6 -2
package/dist/index.js CHANGED
@@ -130,9 +130,10 @@ function defineComponentPlugin() {
130
130
  if (!node.id) return;
131
131
  const name = node.id.name;
132
132
  if (!/^[A-Z]/.test(name)) return;
133
+ assertNoSetupStyleEarlyReturns(path, name);
133
134
  const fn = t.functionExpression(null, node.params, node.body, false, false);
134
135
  if (node.typeParameters) fn.typeParameters = node.typeParameters;
135
- const wrapped = wrapComponentFn(fn, name);
136
+ const wrapped = wrapComponentFn(fn, name, path);
136
137
  if (!wrapped) return;
137
138
  const call = wrapped;
138
139
  hasTransformed = true;
@@ -153,11 +154,12 @@ function defineComponentPlugin() {
153
154
  const init = node.init;
154
155
  const isFn = t.isFunctionExpression(init) || t.isArrowFunctionExpression(init);
155
156
  if (!isFn) return;
156
- const wrapped = wrapComponentFn(init, id.name);
157
+ const initPath = path.get("init");
158
+ assertNoSetupStyleEarlyReturns(initPath, id.name);
159
+ const wrapped = wrapComponentFn(init, id.name, initPath);
157
160
  if (!wrapped) return;
158
161
  const call = wrapped;
159
162
  hasTransformed = true;
160
- const initPath = path.get("init");
161
163
  wrapEarlyReturns(initPath);
162
164
  node.init = call;
163
165
  },
@@ -184,18 +186,19 @@ function defineComponentPlugin() {
184
186
  ;
185
187
  fn.typeParameters = decl.typeParameters;
186
188
  }
187
- const wrapped = wrapComponentFn(fn);
189
+ const declPath = path.get("declaration");
190
+ assertNoSetupStyleEarlyReturns(declPath);
191
+ const wrapped = wrapComponentFn(fn, void 0, path);
188
192
  if (!wrapped) return;
189
193
  const call = wrapped;
190
194
  hasTransformed = true;
191
- const declPath = path.get("declaration");
192
195
  wrapEarlyReturns(declPath);
193
196
  path.node.declaration = call;
194
197
  }
195
198
  }
196
199
  };
197
200
  }
198
- function wrapComponentFn(fn, name) {
201
+ function wrapComponentFn(fn, name, fnPath) {
199
202
  const body = fn.body;
200
203
  const isExprBody = !t.isBlockStatement(body);
201
204
  let last = null;
@@ -214,7 +217,13 @@ function wrapComponentFn(fn, name) {
214
217
  const isJsxCall = t.isCallExpression(ret) && t.isIdentifier(ret.callee) && /^_?jsx/.test(ret.callee.name);
215
218
  const isNullRet = t.isNullLiteral(ret);
216
219
  const isCondRet = isRenderExpr(ret);
217
- if (!isJsx && !isJsxCall && !isNullRet && !isCondRet) return null;
220
+ if (!isJsx && !isJsxCall && !isNullRet && !isCondRet) {
221
+ const returnsFn = t.isArrowFunctionExpression(ret) || t.isFunctionExpression(ret);
222
+ if (returnsFn && (name !== void 0 || containsRenderNode(ret))) {
223
+ throw buildSetupStyleError(fnPath, name);
224
+ }
225
+ return null;
226
+ }
218
227
  if (isJsx) walkJSX(ret);
219
228
  if (isExprBody) {
220
229
  fn.body = t.blockStatement([
@@ -229,6 +238,54 @@ function wrapComponentFn(fn, name) {
229
238
  if (name) args.push(t.stringLiteral(name));
230
239
  return t.callExpression(t.identifier("defineComponent"), args);
231
240
  }
241
+ function assertNoSetupStyleEarlyReturns(fnPath, name) {
242
+ const body = fnPath.node.body;
243
+ if (!t.isBlockStatement(body)) return;
244
+ const stmts = body.body;
245
+ const trailing = stmts.length ? stmts[stmts.length - 1] : null;
246
+ fnPath.traverse({
247
+ ReturnStatement(retPath) {
248
+ if (retPath.getFunctionParent() !== fnPath) return;
249
+ if (trailing && retPath.node === trailing) return;
250
+ const arg = retPath.node.argument;
251
+ if (t.isArrowFunctionExpression(arg) || t.isFunctionExpression(arg)) {
252
+ throw buildSetupStyleError(retPath, name);
253
+ }
254
+ }
255
+ });
256
+ }
257
+ function buildSetupStyleError(fnPath, name) {
258
+ const label = name ? `\u7EC4\u4EF6 ${name}` : "\u7EC4\u4EF6\u51FD\u6570";
259
+ const msg = `[actview] \u5DF2\u5E9F\u5F03\u7684 setup \u98CE\u683C\uFF1A${label}\u4F53\u5185 return \u4E86\u6E32\u67D3\u51FD\u6570\uFF08() => JSX / function () { JSX }\uFF09\u3002
260
+ ActView \u53EA\u652F\u6301\u7B80\u5199\u7EC4\u4EF6\u2014\u2014\u76F4\u63A5 return JSX\uFF0C\u63D2\u4EF6\u4F1A\u81EA\u52A8\u5305\u88C5 render \u51FD\u6570\uFF1A
261
+
262
+ \u2717 function App() { return () => <div /> }
263
+ \u2713 function App() { return <div /> }
264
+ `;
265
+ try {
266
+ return fnPath.buildCodeFrameError(msg);
267
+ } catch {
268
+ return new Error(msg);
269
+ }
270
+ }
271
+ function containsRenderNode(node, seen = /* @__PURE__ */ new Set()) {
272
+ if (!node || typeof node !== "object" || seen.has(node)) return false;
273
+ seen.add(node);
274
+ if (t.isJSXElement(node) || t.isJSXFragment(node)) return true;
275
+ if (t.isCallExpression(node) && t.isIdentifier(node.callee) && /^_?jsx/.test(node.callee.name)) {
276
+ return true;
277
+ }
278
+ for (const k in node) {
279
+ if (k === "leadingComments" || k === "trailingComments") continue;
280
+ const v = node[k];
281
+ if (Array.isArray(v)) {
282
+ if (v.some((c) => containsRenderNode(c, seen))) return true;
283
+ } else if (v !== null && typeof v === "object") {
284
+ if (containsRenderNode(v, seen)) return true;
285
+ }
286
+ }
287
+ return false;
288
+ }
232
289
  function wrapEarlyReturns(fnPath) {
233
290
  fnPath.traverse({
234
291
  ReturnStatement(innerPath) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actview/plugin-babel",
3
- "version": "1.0.6",
3
+ "version": "2.0.0",
4
4
  "type": "module",
5
5
  "description": "Babel 插件:JSX 组件自动 defineComponent 转换(ActView 编译核心,独立于 Vite 宿主)",
6
6
  "exports": {
@@ -9,7 +9,11 @@
9
9
  "import": "./dist/index.js"
10
10
  }
11
11
  },
12
- "dependencies": {
12
+ "peerDependencies": {
13
+ "@babel/core": "^8.0.0",
14
+ "@babel/generator": "^8.0.0"
15
+ },
16
+ "devDependencies": {
13
17
  "@babel/core": "^8.0.1",
14
18
  "@babel/generator": "^8.0.0"
15
19
  },