@compelem/compiler 0.30.0-beta.4 → 0.30.0-beta.6
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.
- package/dist/index.d.ts +75 -1
- package/dist/index.js +2 -2
- package/dist/{vite-CY_6E-Ut.js → vite-C95uwtJI.js} +459 -134
- package/dist/vite-C95uwtJI.js.map +1 -0
- package/dist/vite.js +1 -1
- package/package.json +1 -1
- package/dist/vite-CY_6E-Ut.js.map +0 -1
|
@@ -494,12 +494,21 @@ function extractClassInfo(node, resolve) {
|
|
|
494
494
|
const imported = resolve(d);
|
|
495
495
|
return imported === "query" || imported === "queryAll";
|
|
496
496
|
})) queryFields.add(name);
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
497
|
+
const resDeco = (member.decorators ?? []).find((d) => {
|
|
498
|
+
const n = decoratorName(d);
|
|
499
|
+
return n ? resolve(n) === "resource" : false;
|
|
500
|
+
});
|
|
501
|
+
if (member.type === "MethodDefinition") if (member.kind === "get") {
|
|
502
|
+
getters.add(name);
|
|
503
|
+
const fn = member.value;
|
|
504
|
+
if (fn?.body) bodies.set(name, fn.body);
|
|
505
|
+
} else {
|
|
506
|
+
methods.add(name);
|
|
500
507
|
const fn = member.value;
|
|
501
508
|
if (fn?.body) bodies.set(name, fn.body);
|
|
502
|
-
}
|
|
509
|
+
}
|
|
510
|
+
else if (member.type === "PropertyDefinition") if (resDeco) getters.add(name);
|
|
511
|
+
else {
|
|
503
512
|
const init = member.value;
|
|
504
513
|
if (init && (init.type === "ArrowFunctionExpression" || init.type === "FunctionExpression")) {
|
|
505
514
|
methods.add(name);
|
|
@@ -1804,6 +1813,7 @@ function buildStaticLiteral(opts, codes = {}) {
|
|
|
1804
1813
|
parts.push(mark("props", `props: ${emitFamily("props", codes.props)}`));
|
|
1805
1814
|
parts.push(mark("states", `states: ${emitFamily("states", codes.states)}`));
|
|
1806
1815
|
parts.push(mark("computedGetters", `computedGetters: ${emitFamily("computedGetters", codes.computedGetters)}`));
|
|
1816
|
+
parts.push(mark("resources", `resources: ${emitFamily("resources", codes.resources)}`));
|
|
1807
1817
|
const watchCode = emitWatchEffects(codes.watchEffects, codes.inlinedWatchAncestors);
|
|
1808
1818
|
if (watchCode !== void 0) parts.push(mark("watchEffects", `watchEffects: ${watchCode}`));
|
|
1809
1819
|
if (codes.cssEffect) parts.push(mark("cssEffect", `cssEffect: ${codes.cssEffect}`));
|
|
@@ -2595,8 +2605,8 @@ function checkConventions(comp, ctx) {
|
|
|
2595
2605
|
function record(ctx, path) {
|
|
2596
2606
|
addDepPath(ctx.deps, path);
|
|
2597
2607
|
}
|
|
2598
|
-
/** TS 包装节点解包(`this as any` / `that!` 等)—— 统一实现在 utils/ast#unwrapExpr
|
|
2599
|
-
*
|
|
2608
|
+
/** TS 包装节点解包(`this as any` / `that!` / `<T>x` 等)—— 统一实现在 utils/ast#unwrapExpr,
|
|
2609
|
+
* 认 TSInstantiationExpression 与 TSTypeAssertion。 */
|
|
2600
2610
|
/** 置失败标记;DEPS_TRACE=1 时输出原因标签(见文件头)。 */
|
|
2601
2611
|
function failAt(ctx, where) {
|
|
2602
2612
|
if (typeof process !== "undefined" && process.env?.DEPS_TRACE) console.error("[deps-fail]", where);
|
|
@@ -4399,6 +4409,234 @@ function extractFieldAccessors(comp, code, ctx, bindings = {}, inheritedAccessor
|
|
|
4399
4409
|
};
|
|
4400
4410
|
}
|
|
4401
4411
|
|
|
4412
|
+
//#endregion
|
|
4413
|
+
//#region src/analyze/resource-extract.ts
|
|
4414
|
+
const CODE = "E-RESOURCE";
|
|
4415
|
+
/** 选项闭集,逐字对齐运行期 `ResourceDecoratorOptions` */
|
|
4416
|
+
const OPT_KEYS = new Set([
|
|
4417
|
+
"timeout",
|
|
4418
|
+
"immediate",
|
|
4419
|
+
"track",
|
|
4420
|
+
"source"
|
|
4421
|
+
]);
|
|
4422
|
+
/** 合法标识符:资源名要拼进 `get <name>()`,非法名会生成坏代码 */
|
|
4423
|
+
const IDENT = /^[A-Za-z_$][\w$]*$/;
|
|
4424
|
+
/**
|
|
4425
|
+
* 不能用作资源名的成员:`CompElem` 原型上的访问器、方法与生命周期回调,
|
|
4426
|
+
* 外加 `Object.prototype` 的成员。
|
|
4427
|
+
*
|
|
4428
|
+
* 运行期按 `__ce_static__.resources` 在原型上装 `get <name>()`,安装前会检查
|
|
4429
|
+
* 原型链上是否已有同名键,有则跳过 —— 撞名的结果是资源**静默不可用**。
|
|
4430
|
+
* 编译器无法读到运行期原型(`CompElem` 继承 `HTMLElement`,Node 侧无法加载),
|
|
4431
|
+
* 这份名单与 `src/CompElem.ts` 的成员表同步维护。
|
|
4432
|
+
*/
|
|
4433
|
+
const RESERVED_NAMES = new Set([
|
|
4434
|
+
"cid",
|
|
4435
|
+
"attrs",
|
|
4436
|
+
"props",
|
|
4437
|
+
"renderRoot",
|
|
4438
|
+
"renderRoots",
|
|
4439
|
+
"parentComponent",
|
|
4440
|
+
"wrapperComponent",
|
|
4441
|
+
"rootComponent",
|
|
4442
|
+
"slots",
|
|
4443
|
+
"slotHooks",
|
|
4444
|
+
"cssSheets",
|
|
4445
|
+
"cssVars",
|
|
4446
|
+
"isMounted",
|
|
4447
|
+
"isDestroyed",
|
|
4448
|
+
"insertStyleSheet",
|
|
4449
|
+
"setup",
|
|
4450
|
+
"propsReady",
|
|
4451
|
+
"render",
|
|
4452
|
+
"beforeMount",
|
|
4453
|
+
"mounted",
|
|
4454
|
+
"beforeDestroyed",
|
|
4455
|
+
"destroyed",
|
|
4456
|
+
"destroy",
|
|
4457
|
+
"slotChange",
|
|
4458
|
+
"afterUpdate",
|
|
4459
|
+
"updateProps",
|
|
4460
|
+
"getSubViewNodes",
|
|
4461
|
+
"emit",
|
|
4462
|
+
"nextTick",
|
|
4463
|
+
"defineSignalField",
|
|
4464
|
+
"forceUpdate",
|
|
4465
|
+
"connectedCallback",
|
|
4466
|
+
"disconnectedCallback",
|
|
4467
|
+
"attributeChangedCallback",
|
|
4468
|
+
"constructor",
|
|
4469
|
+
"toString",
|
|
4470
|
+
"toLocaleString",
|
|
4471
|
+
"valueOf",
|
|
4472
|
+
"hasOwnProperty",
|
|
4473
|
+
"isPrototypeOf",
|
|
4474
|
+
"propertyIsEnumerable",
|
|
4475
|
+
"__proto__"
|
|
4476
|
+
]);
|
|
4477
|
+
/** 编译期注入的私有方法前缀 */
|
|
4478
|
+
const LOADER_PREFIX = "__rl_";
|
|
4479
|
+
const SOURCE_PREFIX = "__rs_";
|
|
4480
|
+
/** 迁移提示:给出可直接照抄的写法 */
|
|
4481
|
+
const MIGRATE = "\n 正确形态(loader 是第一个参数,选项可选):\n @resource((self, signal) => …, { timeout: 3000 })\n rows!: ResourceView<Row[]>\n 之后模板里写 this.rows.data / this.rows.busy / this.rows.load()。";
|
|
4482
|
+
function extractResources(comp, code, ctx) {
|
|
4483
|
+
const result = {
|
|
4484
|
+
accessors: "",
|
|
4485
|
+
removals: [],
|
|
4486
|
+
runtimeHelpers: [],
|
|
4487
|
+
errors: []
|
|
4488
|
+
};
|
|
4489
|
+
const cls = comp.cls ?? ctx.localClasses.get(comp.className);
|
|
4490
|
+
if (!cls) return result;
|
|
4491
|
+
const isResourceDeco = (d) => comp.compelemImports.get(d) === "resource";
|
|
4492
|
+
const members = cls.body?.body ?? [];
|
|
4493
|
+
const targets = [];
|
|
4494
|
+
for (const member of members) {
|
|
4495
|
+
const dec = (member.decorators ?? []).find((d) => {
|
|
4496
|
+
const n = decoratorName(d);
|
|
4497
|
+
return n ? isResourceDeco(n) : false;
|
|
4498
|
+
});
|
|
4499
|
+
if (!dec) continue;
|
|
4500
|
+
targets.push({
|
|
4501
|
+
member,
|
|
4502
|
+
dec,
|
|
4503
|
+
rawName: keyName(member.key) ?? ""
|
|
4504
|
+
});
|
|
4505
|
+
}
|
|
4506
|
+
if (!targets.length) return result;
|
|
4507
|
+
const fail = (member, dec, message) => {
|
|
4508
|
+
const dStart = dec?.start ?? member.start;
|
|
4509
|
+
result.errors.push({
|
|
4510
|
+
start: Math.min(member.start, dStart),
|
|
4511
|
+
end: member.end,
|
|
4512
|
+
message
|
|
4513
|
+
});
|
|
4514
|
+
};
|
|
4515
|
+
/** 本族已提交的资源名,用于同类内重复检查(TS 也会报,但这里给更直白的 E 码) */
|
|
4516
|
+
const emitted = /* @__PURE__ */ new Set();
|
|
4517
|
+
const entries = [];
|
|
4518
|
+
let accessors = "";
|
|
4519
|
+
const removals = [];
|
|
4520
|
+
for (const { member, dec, rawName } of targets) {
|
|
4521
|
+
if (member.type !== "PropertyDefinition") {
|
|
4522
|
+
fail(member, dec, `${CODE}: @resource 只能装饰字段声明。${MIGRATE}`);
|
|
4523
|
+
continue;
|
|
4524
|
+
}
|
|
4525
|
+
if (!rawName) {
|
|
4526
|
+
fail(member, dec, `${CODE}: 无法识别被装饰的字段名(计算属性键不支持)`);
|
|
4527
|
+
continue;
|
|
4528
|
+
}
|
|
4529
|
+
if (rawName.startsWith("#")) {
|
|
4530
|
+
fail(member, dec, `${CODE}: 不支持私有字段('${rawName}')——视图访问器要挂在原型上才能被模板读取`);
|
|
4531
|
+
continue;
|
|
4532
|
+
}
|
|
4533
|
+
if (!IDENT.test(rawName)) {
|
|
4534
|
+
fail(member, dec, `${CODE}: 资源名 '${rawName}' 不是合法标识符(要用作 get ${rawName}())`);
|
|
4535
|
+
continue;
|
|
4536
|
+
}
|
|
4537
|
+
if (RESERVED_NAMES.has(rawName)) {
|
|
4538
|
+
fail(member, dec, `${CODE}: 资源名 '${rawName}' 与 CompElem 原型链上的成员同名——访问器不会安装,this.${rawName} 取不到资源视图。请改用其它字段名`);
|
|
4539
|
+
continue;
|
|
4540
|
+
}
|
|
4541
|
+
if (member.static === true) {
|
|
4542
|
+
fail(member, dec, `${CODE}: 不支持静态资源('${rawName}')——注入的是实例 getter,static 成员会被整段删掉`);
|
|
4543
|
+
continue;
|
|
4544
|
+
}
|
|
4545
|
+
if (member.value != null) {
|
|
4546
|
+
fail(member, dec, `${CODE}: 字段不能带初始值('${rawName} = …')——值只由 loader 提供,写在字段上的初始值会被删掉,且不会报错`);
|
|
4547
|
+
continue;
|
|
4548
|
+
}
|
|
4549
|
+
if (emitted.has(rawName)) {
|
|
4550
|
+
fail(member, dec, `${CODE}: '${rawName}' 已经有另一个 @resource,资源名必须唯一`);
|
|
4551
|
+
continue;
|
|
4552
|
+
}
|
|
4553
|
+
const otherDecos = (member.decorators ?? []).map(decoratorName).filter((d) => d && !isResourceDeco(d));
|
|
4554
|
+
if (otherDecos.length) {
|
|
4555
|
+
fail(member, dec, `${CODE}: @resource 不能与其它装饰器同用('${rawName}' 上还有 @${otherDecos.join(" / @")})`);
|
|
4556
|
+
continue;
|
|
4557
|
+
}
|
|
4558
|
+
const callArgs = dec.expression?.type === "CallExpression" ? dec.expression.arguments ?? [] : [];
|
|
4559
|
+
if (callArgs.length < 1 || callArgs.length > 2) {
|
|
4560
|
+
fail(member, dec, `${CODE}: @resource 需要 (loader, options?) 两个参数以内${MIGRATE}`);
|
|
4561
|
+
continue;
|
|
4562
|
+
}
|
|
4563
|
+
const loaderNode = unwrapExpr(callArgs[0]);
|
|
4564
|
+
if (loaderNode?.type !== "ArrowFunctionExpression") {
|
|
4565
|
+
fail(member, dec, loaderNode?.type === "ObjectExpression" ? `${CODE}: 形态已改为 @resource(loader, options?)——loader 从选项对象移到第一个参数${MIGRATE}` : `${CODE}: 第一个参数须是内联箭头函数 (self, signal) => …——编译期要把这段表达式搬进实例方法,引用式写法拿不到组件实例`);
|
|
4566
|
+
continue;
|
|
4567
|
+
}
|
|
4568
|
+
if ((loaderNode.params ?? []).length !== 2) {
|
|
4569
|
+
fail(member, dec, `${CODE}: loader 必须声明两个形参 (self, signal) —— 装饰器实参里没有 this,组件实例要显式传进来`);
|
|
4570
|
+
continue;
|
|
4571
|
+
}
|
|
4572
|
+
/** loader 表达式切片(搬进方法体后 `this` 才是实例) */
|
|
4573
|
+
const loaderExpr = `(${code.slice(loaderNode.start, loaderNode.end)})`;
|
|
4574
|
+
let sourceExpr;
|
|
4575
|
+
const keep = [];
|
|
4576
|
+
let optsBad = false;
|
|
4577
|
+
let optsNode;
|
|
4578
|
+
if (callArgs.length === 2) {
|
|
4579
|
+
optsNode = unwrapExpr(callArgs[1]);
|
|
4580
|
+
if (optsNode?.type !== "ObjectExpression") {
|
|
4581
|
+
fail(member, dec, `${CODE}: 第二个参数须是内联对象字面量(变量/import 无法静态前移)`);
|
|
4582
|
+
continue;
|
|
4583
|
+
}
|
|
4584
|
+
}
|
|
4585
|
+
for (const p of optsNode?.properties ?? []) {
|
|
4586
|
+
if (p.type === "SpreadElement" || p.type === "ExperimentalSpreadProperty") {
|
|
4587
|
+
fail(member, dec, `${CODE}: 选项不支持展开(spread 无法静态前移),请逐项写出`);
|
|
4588
|
+
optsBad = true;
|
|
4589
|
+
break;
|
|
4590
|
+
}
|
|
4591
|
+
if (p.computed) {
|
|
4592
|
+
fail(member, dec, `${CODE}: 选项键无法静态解析(计算属性键不支持)`);
|
|
4593
|
+
optsBad = true;
|
|
4594
|
+
break;
|
|
4595
|
+
}
|
|
4596
|
+
const k = keyName(p.key);
|
|
4597
|
+
if (!k) {
|
|
4598
|
+
fail(member, dec, `${CODE}: 选项键无法静态解析(计算属性键不支持)`);
|
|
4599
|
+
optsBad = true;
|
|
4600
|
+
break;
|
|
4601
|
+
}
|
|
4602
|
+
if (!OPT_KEYS.has(k)) {
|
|
4603
|
+
fail(member, dec, `${CODE}: ${k === "loader" || k === "fetch" || k === "fetcher" ? `'${k}' 不是选项——loader 是第一个参数,写成 @resource((self, signal) => …)${MIGRATE}` : ""}未知选项 '${k}'——ResourceDecoratorOptions 仅支持 ${[...OPT_KEYS].join(" / ")}`);
|
|
4604
|
+
optsBad = true;
|
|
4605
|
+
break;
|
|
4606
|
+
}
|
|
4607
|
+
if (k === "source") {
|
|
4608
|
+
const v = unwrapExpr(p.value);
|
|
4609
|
+
if (v?.type !== "ArrowFunctionExpression") {
|
|
4610
|
+
fail(member, dec, `${CODE}: source 须是内联箭头函数 (self) => …——编译期要把这段表达式搬进实例方法,引用式写法拿不到组件实例`);
|
|
4611
|
+
optsBad = true;
|
|
4612
|
+
break;
|
|
4613
|
+
}
|
|
4614
|
+
if ((v.params ?? []).length > 1) {
|
|
4615
|
+
fail(member, dec, `${CODE}: source 最多接收一个形参 (self)`);
|
|
4616
|
+
optsBad = true;
|
|
4617
|
+
break;
|
|
4618
|
+
}
|
|
4619
|
+
sourceExpr = `(${code.slice(v.start, v.end)})`;
|
|
4620
|
+
continue;
|
|
4621
|
+
}
|
|
4622
|
+
keep.push(code.slice(p.start, p.end));
|
|
4623
|
+
}
|
|
4624
|
+
if (optsBad) continue;
|
|
4625
|
+
emitted.add(rawName);
|
|
4626
|
+
const keyLit = JSON.stringify(rawName);
|
|
4627
|
+
accessors += `${DEBUG_DIV} resource ${rawName}\n${LOADER_PREFIX}${rawName}(__signal) { return ${loaderExpr}(this, __signal) }\n` + (sourceExpr ? `${SOURCE_PREFIX}${rawName}() { return ${sourceExpr}(this) }\n` : "");
|
|
4628
|
+
const parts = keep.slice();
|
|
4629
|
+
if (sourceExpr) parts.push("source: true");
|
|
4630
|
+
entries.push(`${keyLit}: { ${parts.join(", ")} }`);
|
|
4631
|
+
removals.push(lineSpan(code, Math.min(member.start, dec.start ?? member.start), member.end));
|
|
4632
|
+
}
|
|
4633
|
+
if (!removals.length) return result;
|
|
4634
|
+
result.accessors = accessors;
|
|
4635
|
+
result.removals = removals;
|
|
4636
|
+
result.resourcesCode = `{ ${entries.join(", ")} }`;
|
|
4637
|
+
return result;
|
|
4638
|
+
}
|
|
4639
|
+
|
|
4402
4640
|
//#endregion
|
|
4403
4641
|
//#region src/analyze/method-deco-extract.ts
|
|
4404
4642
|
/** 本地变量前缀(避开用户标识符;`__` 前缀与框架其余注入一致)。 */
|
|
@@ -4712,8 +4950,7 @@ function staticHtmlFragmentOf(e, comp) {
|
|
|
4712
4950
|
* 非 this 起始 / 含 computed 访问时返回 null。
|
|
4713
4951
|
*
|
|
4714
4952
|
* 统一实现在 utils/ast#thisChain(属性名走 keyName,`#private` 带 `#` 前缀,
|
|
4715
|
-
*
|
|
4716
|
-
* `this.x` 混成同一个依赖键)。
|
|
4953
|
+
* 否则 `this.#x` 与 `this.x` 会混成同一个依赖键)。
|
|
4717
4954
|
*/
|
|
4718
4955
|
/**
|
|
4719
4956
|
* 提取 TAG 指令实参中的 this 链全前缀路径。
|
|
@@ -5287,78 +5524,93 @@ function checkTemplateRules(tree, tmpl, comp, ctx, knownTags) {
|
|
|
5287
5524
|
});
|
|
5288
5525
|
}
|
|
5289
5526
|
}
|
|
5290
|
-
for (const el of elements)
|
|
5291
|
-
|
|
5292
|
-
const
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5296
|
-
const
|
|
5297
|
-
|
|
5298
|
-
|
|
5299
|
-
|
|
5300
|
-
|
|
5301
|
-
|
|
5527
|
+
for (const el of elements) {
|
|
5528
|
+
const seenDirectives = /* @__PURE__ */ new Set();
|
|
5529
|
+
for (const a of el.attrs) {
|
|
5530
|
+
if (!a.name.includes("⟬")) continue;
|
|
5531
|
+
const dm = /⟬Ċ⟭(\d+)/.exec(a.name);
|
|
5532
|
+
if (!dm) continue;
|
|
5533
|
+
const dv = tmpl.vars[+dm[1]];
|
|
5534
|
+
if (!dv?.isDirectiveCall || !dv.directiveName) continue;
|
|
5535
|
+
if (seenDirectives.has(dv.directiveName)) errs.push({
|
|
5536
|
+
...pos,
|
|
5537
|
+
message: `E-DIRECTIVE-DUP: 元素 <${el.tag}> 上的指令 '${dv.directiveName}' 出现了两次以上;同一元素每种指令只能写一次(重复的那份运行期会被静默丢弃)`
|
|
5538
|
+
});
|
|
5539
|
+
else seenDirectives.add(dv.directiveName);
|
|
5540
|
+
}
|
|
5541
|
+
for (const a of el.attrs) {
|
|
5542
|
+
if (a.name.includes("⟬")) continue;
|
|
5543
|
+
const varPart = a.parts.find((p) => p.type === "var");
|
|
5544
|
+
const varCount = a.parts.filter((p) => p.type === "var").length;
|
|
5545
|
+
if (a.name.startsWith("@") && !a.name.startsWith("@mutate")) {
|
|
5546
|
+
const segs = a.name.slice(1).split(".");
|
|
5547
|
+
const evName = (segs[0] ?? "").toLowerCase();
|
|
5548
|
+
const mods = segs.slice(1);
|
|
5549
|
+
const compEmits = localEmits.get(el.tag.toLowerCase());
|
|
5550
|
+
if (!!compEmits && matchEmitName(compEmits, evName)) {
|
|
5551
|
+
const bad = mods.filter((mo) => !COMP_EVENT_MODS.has(mo) && !EVENT_FLOW_MOD_RE.test(mo));
|
|
5552
|
+
if (bad.length) errs.push({
|
|
5553
|
+
...pos,
|
|
5554
|
+
severity: "warn",
|
|
5555
|
+
message: `W-EVENT-COMP-MODIFIER: '${a.name}' 是组件事件(${el.tag} 的 @emits 已声明 '${evName}'),运行期只应用 debounce/throttle/once,[${bad.join(", ")}] 会被静默丢弃`
|
|
5556
|
+
});
|
|
5557
|
+
} else if (!KEY_EVENTS.has(evName) && NATIVE_EVENTS.has(evName)) {
|
|
5558
|
+
const bad = mods.filter((mo) => !EVENT_PLAIN_MODS.has(mo) && !EVENT_FLOW_MOD_RE.test(mo));
|
|
5559
|
+
if (bad.length) errs.push({
|
|
5560
|
+
...pos,
|
|
5561
|
+
message: `E-EVENT-MODIFIER: '${a.name}' 中的 [${bad.join(", ")}] 不是内置修饰符;运行期会把它当作 KeyboardEvent.key 过滤,而 '${evName}' 不是键盘事件 ⇒ 处理器恒不触发`
|
|
5562
|
+
});
|
|
5563
|
+
}
|
|
5564
|
+
if (varCount === 0 && mods.length === 0) errs.push({
|
|
5302
5565
|
...pos,
|
|
5303
5566
|
severity: "warn",
|
|
5304
|
-
message: `W-EVENT-
|
|
5305
|
-
});
|
|
5306
|
-
} else if (!KEY_EVENTS.has(evName) && NATIVE_EVENTS.has(evName)) {
|
|
5307
|
-
const bad = mods.filter((mo) => !EVENT_PLAIN_MODS.has(mo) && !EVENT_FLOW_MOD_RE.test(mo));
|
|
5308
|
-
if (bad.length) errs.push({
|
|
5309
|
-
...pos,
|
|
5310
|
-
message: `E-EVENT-MODIFIER: '${a.name}' 中的 [${bad.join(", ")}] 不是内置修饰符;运行期会把它当作 KeyboardEvent.key 过滤,而 '${evName}' 不是键盘事件 ⇒ 处理器恒不触发`
|
|
5567
|
+
message: `W-EVENT-NO-HANDLER: '${a.name}' 没有插值处理器,运行期只注册空监听器(noop)——是否遗漏了 \${…}?`
|
|
5311
5568
|
});
|
|
5312
5569
|
}
|
|
5313
|
-
if (
|
|
5314
|
-
...pos,
|
|
5315
|
-
severity: "warn",
|
|
5316
|
-
message: `W-EVENT-NO-HANDLER: '${a.name}' 没有插值处理器,运行期只注册空监听器(noop)——是否遗漏了 \${…}?`
|
|
5317
|
-
});
|
|
5318
|
-
}
|
|
5319
|
-
if (a.name.startsWith(".") && varCount === 0) {
|
|
5320
|
-
errs.push({
|
|
5321
|
-
...pos,
|
|
5322
|
-
message: `E-PROP-INTERP: Prop '${a.name}' 必须是插值(.foo="\${expr}");静态值请直接写属性或改用 bind 指令`
|
|
5323
|
-
});
|
|
5324
|
-
continue;
|
|
5325
|
-
}
|
|
5326
|
-
if (a.name.startsWith("@mutate")) {
|
|
5327
|
-
if (!a.name.slice(1).split(".").slice(1).some((mo) => MUTATE_TYPE_MODS.has(mo))) errs.push({
|
|
5328
|
-
...pos,
|
|
5329
|
-
message: `E-MUTATE-MODIFIER: 事件 '${a.name}' 缺少变异类型修饰符,必须使用 @mutate.attr/child/char/tree 之一(裸 @mutate 运行期无法 observe)`
|
|
5330
|
-
});
|
|
5331
|
-
}
|
|
5332
|
-
if (a.name.startsWith("@") && varCount === 1 && varPart) {
|
|
5333
|
-
const exprSource = tmpl.vars[varPart.index]?.exprSource ?? "";
|
|
5334
|
-
if (INLINE_FN_RE.test(exprSource)) continue;
|
|
5335
|
-
const m = THIS_MEMBER_RE.exec(exprSource);
|
|
5336
|
-
if (m) {
|
|
5337
|
-
const name = m[1];
|
|
5338
|
-
if (members === null || members.has(name) || KNOWN_BASE_MEMBERS.has(name)) continue;
|
|
5570
|
+
if (a.name.startsWith(".") && varCount === 0) {
|
|
5339
5571
|
errs.push({
|
|
5340
5572
|
...pos,
|
|
5341
|
-
message: `E-
|
|
5573
|
+
message: `E-PROP-INTERP: Prop '${a.name}' 必须是插值(.foo="\${expr}");静态值请直接写属性或改用 bind 指令`
|
|
5342
5574
|
});
|
|
5575
|
+
continue;
|
|
5343
5576
|
}
|
|
5344
|
-
|
|
5345
|
-
|
|
5346
|
-
if (a.name === "ref" && varCount === 1 && varPart) {
|
|
5347
|
-
const exprSource = tmpl.vars[varPart.index]?.exprSource ?? "";
|
|
5348
|
-
const m = THIS_MEMBER_RE.exec(exprSource);
|
|
5349
|
-
if (m && members !== null) {
|
|
5350
|
-
const name = m[1];
|
|
5351
|
-
if (!members.has(name)) errs.push({
|
|
5577
|
+
if (a.name.startsWith("@mutate")) {
|
|
5578
|
+
if (!a.name.slice(1).split(".").slice(1).some((mo) => MUTATE_TYPE_MODS.has(mo))) errs.push({
|
|
5352
5579
|
...pos,
|
|
5353
|
-
message: `E-
|
|
5580
|
+
message: `E-MUTATE-MODIFIER: 事件 '${a.name}' 缺少变异类型修饰符,必须使用 @mutate.attr/child/char/tree 之一(裸 @mutate 运行期无法 observe)`
|
|
5354
5581
|
});
|
|
5355
|
-
|
|
5356
|
-
|
|
5357
|
-
|
|
5358
|
-
|
|
5359
|
-
|
|
5360
|
-
|
|
5361
|
-
|
|
5582
|
+
}
|
|
5583
|
+
if (a.name.startsWith("@") && varCount === 1 && varPart) {
|
|
5584
|
+
const exprSource = tmpl.vars[varPart.index]?.exprSource ?? "";
|
|
5585
|
+
if (INLINE_FN_RE.test(exprSource)) continue;
|
|
5586
|
+
const m = THIS_MEMBER_RE.exec(exprSource);
|
|
5587
|
+
if (m) {
|
|
5588
|
+
const name = m[1];
|
|
5589
|
+
if (members === null || members.has(name) || KNOWN_BASE_MEMBERS.has(name)) continue;
|
|
5590
|
+
errs.push({
|
|
5591
|
+
...pos,
|
|
5592
|
+
message: `E-EVENT-FN: 事件 '${a.name}' 的处理器 '${exprSource}' 不是组件 ${comp.className} 的成员`
|
|
5593
|
+
});
|
|
5594
|
+
}
|
|
5595
|
+
continue;
|
|
5596
|
+
}
|
|
5597
|
+
if (a.name === "ref" && varCount === 1 && varPart) {
|
|
5598
|
+
const exprSource = tmpl.vars[varPart.index]?.exprSource ?? "";
|
|
5599
|
+
const m = THIS_MEMBER_RE.exec(exprSource);
|
|
5600
|
+
if (m && members !== null) {
|
|
5601
|
+
const name = m[1];
|
|
5602
|
+
if (!members.has(name)) errs.push({
|
|
5603
|
+
...pos,
|
|
5604
|
+
message: `E-REF-TYPE: ref 绑定的 '${exprSource}' 不是组件 ${comp.className} 的成员`
|
|
5605
|
+
});
|
|
5606
|
+
else {
|
|
5607
|
+
const member = findMemberNode(comp, ctx, name);
|
|
5608
|
+
if (member?.type === "PropertyDefinition" && member.value != null) {
|
|
5609
|
+
if (!isCreateRefCall(member.value, comp)) errs.push({
|
|
5610
|
+
...pos,
|
|
5611
|
+
message: `E-REF-TYPE: ref 绑定的 '${exprSource}' 初始化器不是 createRef() 调用,运行时将报「Ref must be a RefObject」`
|
|
5612
|
+
});
|
|
5613
|
+
}
|
|
5362
5614
|
}
|
|
5363
5615
|
}
|
|
5364
5616
|
}
|
|
@@ -7929,16 +8181,21 @@ function compileFile(code, id, options = {}) {
|
|
|
7929
8181
|
const mdRes = extractMethodDecos(comp, code, convCtx);
|
|
7930
8182
|
conventionErrors.push(...mdRes.errors);
|
|
7931
8183
|
const mdHelpers = mdRes.runtimeHelpers.map((n) => helperBindings[n] ?? n);
|
|
8184
|
+
const resRes = extractResources(comp, code, convCtx);
|
|
8185
|
+
conventionErrors.push(...resRes.errors);
|
|
8186
|
+
const resHelpers = resRes.runtimeHelpers.map((n) => helperBindings[n] ?? n);
|
|
7932
8187
|
const allRemovals = [
|
|
7933
8188
|
...watchRemovals,
|
|
7934
8189
|
...fieldRes.removals,
|
|
7935
|
-
...mdRes.removals
|
|
8190
|
+
...mdRes.removals,
|
|
8191
|
+
...resRes.removals
|
|
7936
8192
|
];
|
|
7937
8193
|
const fieldCodes = {
|
|
7938
8194
|
props: fieldRes.propsCode,
|
|
7939
8195
|
states: fieldRes.statesCode,
|
|
7940
8196
|
computedGetters: fieldRes.computedCode,
|
|
7941
|
-
|
|
8197
|
+
resources: resRes.resourcesCode,
|
|
8198
|
+
accessors: fieldRes.accessors + resRes.accessors || void 0
|
|
7942
8199
|
};
|
|
7943
8200
|
const ctorPlan = fieldRes.fieldInits.length > 0 || !!mdRes.ctorStmts ? planCtorInsert(comp, comp.cls ?? convCtx.localClasses.get(comp.className), code) : void 0;
|
|
7944
8201
|
if (ctorPlan?.warn) conventionErrors.push({
|
|
@@ -7954,7 +8211,11 @@ function compileFile(code, id, options = {}) {
|
|
|
7954
8211
|
methodDecoCtor: mdRes.ctorStmts || void 0,
|
|
7955
8212
|
methodDecoDestroy: mdRes.destroyStmts || void 0,
|
|
7956
8213
|
get helpers() {
|
|
7957
|
-
const all = [
|
|
8214
|
+
const all = [
|
|
8215
|
+
...fieldHelpers,
|
|
8216
|
+
...resHelpers,
|
|
8217
|
+
...writers
|
|
8218
|
+
];
|
|
7958
8219
|
return all.length ? [...new Set(all)] : void 0;
|
|
7959
8220
|
},
|
|
7960
8221
|
myfxHelpers: mdHelpers.length ? [...mdHelpers] : void 0
|
|
@@ -7999,19 +8260,20 @@ function compileFile(code, id, options = {}) {
|
|
|
7999
8260
|
continue;
|
|
8000
8261
|
}
|
|
8001
8262
|
if (comp.skipInjection) {
|
|
8002
|
-
if (!!fieldRes.accessors || fieldRes.propsCode !== void 0 || fieldRes.statesCode !== void 0 || fieldRes.computedCode !== void 0 || !!cssEffectCode || watchEffectsCode) {
|
|
8263
|
+
if (!!fieldRes.accessors || !!resRes.accessors || fieldRes.propsCode !== void 0 || fieldRes.statesCode !== void 0 || fieldRes.computedCode !== void 0 || resRes.resourcesCode !== void 0 || !!cssEffectCode || watchEffectsCode) {
|
|
8003
8264
|
const mk = (label, body) => `${DEBUG_DIV} ${label}\n${body}`;
|
|
8004
8265
|
const parts = [
|
|
8005
8266
|
mk("inherits", `...Reflect.getPrototypeOf(this).__ce_static__`),
|
|
8006
8267
|
mk("props", `props: ${emitFamily("props", fieldRes.propsCode)}`),
|
|
8007
8268
|
mk("states", `states: ${emitFamily("states", fieldRes.statesCode)}`),
|
|
8008
|
-
mk("computedGetters", `computedGetters: ${emitFamily("computedGetters", fieldRes.computedCode)}`)
|
|
8269
|
+
mk("computedGetters", `computedGetters: ${emitFamily("computedGetters", fieldRes.computedCode)}`),
|
|
8270
|
+
mk("resources", `resources: ${emitFamily("resources", resRes.resourcesCode)}`)
|
|
8009
8271
|
];
|
|
8010
8272
|
if (watchEffectsCode) parts.push(mk("watchEffects", `watchEffects: ${emitWatchEffects(watchEffectsCode, watchRes.inlinedAncestors)}`));
|
|
8011
8273
|
if (cssEffectCode) parts.push(mk("cssEffect", `cssEffect: ${cssEffectCode}`));
|
|
8012
8274
|
edits.push({
|
|
8013
8275
|
comp,
|
|
8014
|
-
literal: `static __ce_static__ = {\n${parts.join(",\n")}\n};\n` + (fieldRes.accessors || ""),
|
|
8276
|
+
literal: `static __ce_static__ = {\n${parts.join(",\n")}\n};\n` + (fieldRes.accessors + resRes.accessors || ""),
|
|
8015
8277
|
removals: allRemovals,
|
|
8016
8278
|
...fieldExtras
|
|
8017
8279
|
});
|
|
@@ -8444,55 +8706,28 @@ function compileFile(code, id, options = {}) {
|
|
|
8444
8706
|
additions
|
|
8445
8707
|
};
|
|
8446
8708
|
}
|
|
8447
|
-
|
|
8448
|
-
//#endregion
|
|
8449
|
-
//#region src/vite.ts
|
|
8450
|
-
const TAG_RE = /@tag\(\s*['"]([^'"]+)['"]/g;
|
|
8451
8709
|
/**
|
|
8452
|
-
*
|
|
8453
|
-
|
|
8454
|
-
|
|
8455
|
-
|
|
8456
|
-
*
|
|
8710
|
+
* 编译**已确定要编译**的源码,跳过 `include` 判定。
|
|
8711
|
+
*
|
|
8712
|
+
* 与 {@link compileFile} 的分工:
|
|
8713
|
+
* - `compileFile` 面向「磁盘上可能是组件、也可能不是」的输入,先按扩展名 +
|
|
8714
|
+
* 特征做 include 判定;
|
|
8715
|
+
* - `compileSource` 面向「调用方已经决定要编译」的输入 —— 典型是 SFC 插件把
|
|
8716
|
+
* `.ce` 分段拼成的虚拟 TypeScript 模块。虚拟模块的 id 仍是 `.ce`(为了
|
|
8717
|
+
* sourcemap 指向真实文件),天然过不了 `defaultInclude` 的扩展名检查,
|
|
8718
|
+
* 以前只能传 `include: () => true` 绕过整个判定(连 node_modules 排除也一起绕过)。
|
|
8719
|
+
*
|
|
8720
|
+
* `options.include` 在这里被忽略。
|
|
8457
8721
|
*/
|
|
8458
|
-
function
|
|
8459
|
-
|
|
8460
|
-
|
|
8461
|
-
|
|
8462
|
-
|
|
8463
|
-
inter.sort();
|
|
8464
|
-
return hash32(inter.join("\n"));
|
|
8465
|
-
}
|
|
8466
|
-
const SKIP_DIRS = new Set([
|
|
8467
|
-
"node_modules",
|
|
8468
|
-
"dist",
|
|
8469
|
-
"build",
|
|
8470
|
-
"out",
|
|
8471
|
-
"coverage"
|
|
8472
|
-
]);
|
|
8473
|
-
/** 递归收集 root 下 .ts/.tsx 的 @tag 名(跨文件标签注册表,TEMPLATE-CODEGEN.md §4)。 */
|
|
8474
|
-
function scanKnownTags(root, out, depth = 0) {
|
|
8475
|
-
if (depth > 20) return;
|
|
8476
|
-
let entries;
|
|
8477
|
-
try {
|
|
8478
|
-
entries = readdirSync(root, { withFileTypes: true });
|
|
8479
|
-
} catch {
|
|
8480
|
-
return;
|
|
8481
|
-
}
|
|
8482
|
-
for (const e of entries) {
|
|
8483
|
-
if (e.name.startsWith(".")) continue;
|
|
8484
|
-
if (e.isDirectory()) {
|
|
8485
|
-
if (SKIP_DIRS.has(e.name)) continue;
|
|
8486
|
-
scanKnownTags(join(root, e.name), out, depth + 1);
|
|
8487
|
-
} else if (/\.tsx?$/.test(e.name) && !e.name.endsWith(".d.ts")) try {
|
|
8488
|
-
const code = readFileSync(join(root, e.name), "utf-8");
|
|
8489
|
-
if (code.indexOf("@tag") < 0 && code.indexOf("CompElem") < 0) continue;
|
|
8490
|
-
TAG_RE.lastIndex = 0;
|
|
8491
|
-
let m;
|
|
8492
|
-
while (m = TAG_RE.exec(code)) out.add(m[1].toLowerCase());
|
|
8493
|
-
} catch {}
|
|
8494
|
-
}
|
|
8722
|
+
function compileSource(code, id, options = {}) {
|
|
8723
|
+
return compileFile(code, id, {
|
|
8724
|
+
...options,
|
|
8725
|
+
include: () => true
|
|
8726
|
+
});
|
|
8495
8727
|
}
|
|
8728
|
+
|
|
8729
|
+
//#endregion
|
|
8730
|
+
//#region src/diagnostics.ts
|
|
8496
8731
|
/** 惰性构建换行偏移索引(升序;仅在有诊断时付费一次)。 */
|
|
8497
8732
|
function newlineIndex(code) {
|
|
8498
8733
|
const arr = [];
|
|
@@ -8519,13 +8754,22 @@ function offsetToLineCol(code, offset, nl) {
|
|
|
8519
8754
|
const lastNl = lo > 0 ? nl[lo - 1] : -1;
|
|
8520
8755
|
return `${lo + 1}:${offset - lastNl}`;
|
|
8521
8756
|
}
|
|
8757
|
+
/** 相对 root 的展示路径(统一正斜杠,便于点击跳转)。 */
|
|
8758
|
+
function relativeToRoot(id, root) {
|
|
8759
|
+
const norm = (s) => s.replace(/\\/g, "/");
|
|
8760
|
+
const rel = norm(id);
|
|
8761
|
+
const base = norm(root);
|
|
8762
|
+
return rel.startsWith(base) ? rel.slice(base.length + 1) : id;
|
|
8763
|
+
}
|
|
8522
8764
|
/**
|
|
8523
|
-
* 从 diagnostics 收集**约定诊断**为可上报文本,按 severity 分为 errs(E-*)与 warns(W
|
|
8765
|
+
* 从 diagnostics 收集**约定诊断**为可上报文本,按 severity 分为 errs(E-*)与 warns(W-*)。
|
|
8766
|
+
*
|
|
8767
|
+
* `root` 只用于把绝对路径压成相对路径,不影响判定。
|
|
8524
8768
|
*/
|
|
8525
|
-
function
|
|
8769
|
+
function collectDiagnostics(res, code, id, root) {
|
|
8526
8770
|
const errs = [];
|
|
8527
8771
|
const warns = [];
|
|
8528
|
-
const rel =
|
|
8772
|
+
const rel = relativeToRoot(id, root);
|
|
8529
8773
|
let nl;
|
|
8530
8774
|
for (const d of res.diagnostics) {
|
|
8531
8775
|
const list = d.conventionErrors?.map((e) => ({
|
|
@@ -8544,8 +8788,13 @@ function collectErrors(res, code, id, root) {
|
|
|
8544
8788
|
warns
|
|
8545
8789
|
};
|
|
8546
8790
|
}
|
|
8547
|
-
/**
|
|
8548
|
-
|
|
8791
|
+
/**
|
|
8792
|
+
* 按 mode 上报违规:error 走插件上下文的 `this.error`(阻断构建),warn 走控制台。
|
|
8793
|
+
*
|
|
8794
|
+
* `thisArg` 是 Rollup/Vite 的插件上下文;纯 API 调用时传 undefined 也能工作
|
|
8795
|
+
* (退化为 `throw`)。
|
|
8796
|
+
*/
|
|
8797
|
+
function reportDiagnostics(msgs, mode, head, thisArg) {
|
|
8549
8798
|
if (mode === "silent" || !msgs.length) return;
|
|
8550
8799
|
const text = head + "\n " + msgs.join("\n ");
|
|
8551
8800
|
if (mode === "error") {
|
|
@@ -8554,6 +8803,86 @@ function reportErrors(msgs, mode, head, thisArg) {
|
|
|
8554
8803
|
else throw new Error(text);
|
|
8555
8804
|
} else console.warn(text);
|
|
8556
8805
|
}
|
|
8806
|
+
/**
|
|
8807
|
+
* 一站式上报:W 码恒为控制台提示(不随档位阻断),E 码按 mode 处理。
|
|
8808
|
+
*
|
|
8809
|
+
* 返回是否发生了阻断(仅用于调用方决定是否继续)。
|
|
8810
|
+
*/
|
|
8811
|
+
function reportConventionDiagnostics(collected, mode, thisArg, tag = "[compelem/compiler]") {
|
|
8812
|
+
if (mode === "silent") return;
|
|
8813
|
+
const { errs, warns } = collected;
|
|
8814
|
+
if (warns.length) console.warn(`${tag} ${warns.length} 条提示:\n ` + warns.join("\n "));
|
|
8815
|
+
reportDiagnostics(errs, mode, `${tag} 检测到 ${errs.length} 处约定错误:`, thisArg);
|
|
8816
|
+
}
|
|
8817
|
+
|
|
8818
|
+
//#endregion
|
|
8819
|
+
//#region src/tag-registry.ts
|
|
8820
|
+
/** `@tag('x-foo')` / `@tag(\`x-foo\`)`;一次扫描内复用,调用方负责重置 lastIndex。 */
|
|
8821
|
+
const TAG_RE = /@tag\s*\(\s*['"`]([^'"`]+)['"`]/g;
|
|
8822
|
+
/** 默认只把 `.ts` / `.tsx` 当作组件来源。 */
|
|
8823
|
+
const DEFAULT_TAG_EXT = /\.tsx?$/;
|
|
8824
|
+
const SKIP_DIRS = new Set([
|
|
8825
|
+
"node_modules",
|
|
8826
|
+
"dist",
|
|
8827
|
+
"build",
|
|
8828
|
+
"out",
|
|
8829
|
+
"coverage"
|
|
8830
|
+
]);
|
|
8831
|
+
/**
|
|
8832
|
+
* 递归收集 root 下匹配 `extensions` 的文件里的 `@tag` 名,写入 `out`。
|
|
8833
|
+
*
|
|
8834
|
+
* 读失败的文件直接跳过:注册表是 best-effort 的,它只会**放宽**校验,
|
|
8835
|
+
* 不该让一次权限错误打断构建。`node_modules` 等目录不参与扫描。
|
|
8836
|
+
*/
|
|
8837
|
+
function scanKnownTags(root, out, options = {}) {
|
|
8838
|
+
const { extensions = DEFAULT_TAG_EXT, maxDepth = 20 } = options;
|
|
8839
|
+
scanDir(root, out, extensions, 0, maxDepth);
|
|
8840
|
+
}
|
|
8841
|
+
function scanDir(root, out, ext, depth, maxDepth) {
|
|
8842
|
+
if (depth > maxDepth) return;
|
|
8843
|
+
let entries;
|
|
8844
|
+
try {
|
|
8845
|
+
entries = readdirSync(root, { withFileTypes: true });
|
|
8846
|
+
} catch {
|
|
8847
|
+
return;
|
|
8848
|
+
}
|
|
8849
|
+
for (const e of entries) {
|
|
8850
|
+
if (e.name.startsWith(".")) continue;
|
|
8851
|
+
if (e.isDirectory()) {
|
|
8852
|
+
if (SKIP_DIRS.has(e.name)) continue;
|
|
8853
|
+
scanDir(join(root, e.name), out, ext, depth + 1, maxDepth);
|
|
8854
|
+
} else if (ext.test(e.name) && !e.name.endsWith(".d.ts")) {
|
|
8855
|
+
let code;
|
|
8856
|
+
try {
|
|
8857
|
+
code = readFileSync(join(root, e.name), "utf-8");
|
|
8858
|
+
} catch {
|
|
8859
|
+
continue;
|
|
8860
|
+
}
|
|
8861
|
+
if (code.indexOf("@tag") < 0 && code.indexOf("CompElem") < 0) continue;
|
|
8862
|
+
TAG_RE.lastIndex = 0;
|
|
8863
|
+
let m;
|
|
8864
|
+
while (m = TAG_RE.exec(code)) out.add(m[1].toLowerCase());
|
|
8865
|
+
}
|
|
8866
|
+
}
|
|
8867
|
+
}
|
|
8868
|
+
|
|
8869
|
+
//#endregion
|
|
8870
|
+
//#region src/vite.ts
|
|
8871
|
+
/**
|
|
8872
|
+
* 用于 transform 缓存键的按文件指纹(见 tagFingerprint)。
|
|
8873
|
+
*/
|
|
8874
|
+
const FILE_HYPHEN_TAG_RE = /<([a-z][a-z0-9]*(?:-[a-z0-9]+)+)/g;
|
|
8875
|
+
/**
|
|
8876
|
+
* 按文件标签指纹(替代全局 `knownTags.size`)。
|
|
8877
|
+
*/
|
|
8878
|
+
function tagFingerprint(usedTags, knownTags) {
|
|
8879
|
+
if (usedTags.size === 0) return "";
|
|
8880
|
+
const inter = [];
|
|
8881
|
+
for (const t of usedTags) if (knownTags.has(t)) inter.push(t);
|
|
8882
|
+
if (inter.length === 0) return "";
|
|
8883
|
+
inter.sort();
|
|
8884
|
+
return hash32(inter.join("\n"));
|
|
8885
|
+
}
|
|
8557
8886
|
/** compelem 编译期优化插件。 */
|
|
8558
8887
|
function compelemCompiler(options = {}) {
|
|
8559
8888
|
let root = process.cwd();
|
|
@@ -8607,11 +8936,7 @@ function compelemCompiler(options = {}) {
|
|
|
8607
8936
|
}
|
|
8608
8937
|
transformCache.set(cacheKey, res);
|
|
8609
8938
|
}
|
|
8610
|
-
if (convMode !== "silent")
|
|
8611
|
-
const { errs, warns } = collectErrors(res, code, id, root);
|
|
8612
|
-
if (warns.length) console.warn(`[compelem/compiler] ${warns.length} 条提示:\n ` + warns.join("\n "));
|
|
8613
|
-
reportErrors(errs, convMode, `[compelem/compiler] 检测到 ${errs.length} 处约定错误:`, this);
|
|
8614
|
-
}
|
|
8939
|
+
if (convMode !== "silent") reportConventionDiagnostics(collectDiagnostics(res, code, id, root), convMode, this);
|
|
8615
8940
|
if (!res.changed) return null;
|
|
8616
8941
|
if (options.emitJs) emitCompiledJs(id, res.code, root);
|
|
8617
8942
|
if (options.verbose) {
|
|
@@ -8646,5 +8971,5 @@ function emitCompiledJs(id, code, root) {
|
|
|
8646
8971
|
var vite_default = compelemCompiler;
|
|
8647
8972
|
|
|
8648
8973
|
//#endregion
|
|
8649
|
-
export {
|
|
8650
|
-
//# sourceMappingURL=vite-
|
|
8974
|
+
export { collectCompelemImports as C, analyzeFile as S, parse$1 as T, DEBUG_DIV as _, scanKnownTags as a, inlineTemplateMethods as b, offsetToLineCol as c, reportDiagnostics as d, compileFile as f, injectInto as g, buildStaticLiteral as h, TAG_RE as i, relativeToRoot as l, defaultInclude as m, vite_default as n, collectDiagnostics as o, compileSource as p, DEFAULT_TAG_EXT as r, newlineIndex as s, compelemCompiler as t, reportConventionDiagnostics as u, StaticAnalysisError as v, isCompelemSource as w, analyzeRender as x, assertStaticAnalysis as y };
|
|
8975
|
+
//# sourceMappingURL=vite-C95uwtJI.js.map
|