@wcstack/typescript 4.3.0 → 4.4.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.
- package/README.ja.md +16 -1
- package/README.md +15 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +46 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/schema-core.cjs +698 -129
- package/dist/tsc-core.cjs +25 -1
- package/dist/wcs-schema.mjs +63 -6
- package/dist/wcs-schema.mjs.map +1 -1
- package/dist/wcs-tsc.mjs +1 -1
- package/package.json +1 -1
package/dist/schema-core.cjs
CHANGED
|
@@ -53,8 +53,12 @@ var WcsDiagnosticCode = {
|
|
|
53
53
|
// --- path / type resolution against a stateSchema ---
|
|
54
54
|
PathNonexistent: "wcs/path-nonexistent",
|
|
55
55
|
PathTypeMismatch: "wcs/path-type-mismatch",
|
|
56
|
+
// 書き戻す束縛(`value:` / `checked:` / `radio:` / `checkbox:`、`#ro` なし)が、setter の無い getter を指す。ランタイムは
|
|
57
|
+
// 入力のたびに `"<path>" is a getter without a setter` を投げる(code なし — 7GUIs の評価の Temperature)。error。
|
|
56
58
|
PathReadonly: "wcs/path-readonly",
|
|
57
59
|
PathReservedName: "wcs/path-reserved-name",
|
|
60
|
+
// lint の限界の告知(作者の誤りではない): `export default { … }` のトップレベルの spread が持ち込むキーは読めないので、
|
|
61
|
+
// stateSchema の無い state のパスは検査しない — それを spread の上で 1 回だけ言う。info。
|
|
58
62
|
PathDynamicUnknown: "wcs/path-dynamic-unknown",
|
|
59
63
|
// --- existing binding-expression validators (retrofitted) ---
|
|
60
64
|
FilterUnknown: "wcs/filter-unknown",
|
|
@@ -65,6 +69,17 @@ var WcsDiagnosticCode = {
|
|
|
65
69
|
BindingTypeExpectation: "wcs/binding-type-expectation",
|
|
66
70
|
TokenUndeclared: "wcs/token-undeclared",
|
|
67
71
|
TokenMisconfigured: "wcs/token-misconfigured",
|
|
72
|
+
// 宣言したコマンドトークンを emit する(スクリプトの `.emit()`・マークアップの `on*: $command.x`)のに、どの
|
|
73
|
+
// `command.<method>:` 束縛にも結ばれていない。emit は誰にも届かず、ランタイムは何も言わない(7GUIs の評価)。warning
|
|
74
|
+
// (ページの外 — 別ファイルのルートのテンプレート — で束ねる形は見えない)。
|
|
75
|
+
CommandTokenUnbound: "wcs/command-token-unbound",
|
|
76
|
+
// state が宣言していないトップレベルのキーへの書き込み(`this.selectedID = …` と `selectedId`)。新しいキーができる
|
|
77
|
+
// だけで、宣言したキーの束縛は変わらない。ランタイムは何も言わない。近い名前(打ち間違い)があるときだけ、warning。
|
|
78
|
+
WritePathMissing: "wcs/write-path-missing",
|
|
79
|
+
// getter・メソッドの中で読む state のパス(`this["items.*.amout"]`・`$getAll("items.*.amout")`・`this.totl`)が宣言に無い。
|
|
80
|
+
// 入れ子のパスの読みは undefined になり、そこから計算した金額が黙って違う(確定申告の下書きツールの評価)。トップレベルの
|
|
81
|
+
// キーは読んだ時点で throw する。近い名前(打ち間違い)があるときだけ、warning。ランタイムの diagnostics も同じ code。
|
|
82
|
+
ReadPathMissing: "wcs/read-path-missing",
|
|
68
83
|
NestedAssign: "wcs/nested-assign",
|
|
69
84
|
// --- 意味論(構文・存在検査では捕まらない取り違え。service/semanticValidator.ts) ---
|
|
70
85
|
// `$getAll` / `$setAll` / `$resolve` の添字の本数がパスの `*` の本数と噛み合わない。
|
|
@@ -448,8 +463,8 @@ function derefUnion(node, rootDefs) {
|
|
|
448
463
|
}
|
|
449
464
|
return { kind: "ok", nodes: out };
|
|
450
465
|
}
|
|
451
|
-
function firstDefined(
|
|
452
|
-
for (const n of
|
|
466
|
+
function firstDefined(nodes2, pick) {
|
|
467
|
+
for (const n of nodes2) {
|
|
453
468
|
const v = pick(n);
|
|
454
469
|
if (v !== void 0) return v;
|
|
455
470
|
}
|
|
@@ -1012,8 +1027,8 @@ function checkPathLikeGetPathInfo(path) {
|
|
|
1012
1027
|
function recursionUnsupported(path) {
|
|
1013
1028
|
raise(1101, [path]);
|
|
1014
1029
|
}
|
|
1015
|
-
function parseStatePart(
|
|
1016
|
-
const [stateAndPath, filters] = splitFilters(
|
|
1030
|
+
function parseStatePart(statePart2) {
|
|
1031
|
+
const [stateAndPath, filters] = splitFilters(statePart2, "output", cacheFilterInfos);
|
|
1017
1032
|
if (stateAndPath.includes("@")) {
|
|
1018
1033
|
raise(32, [stateAndPath]);
|
|
1019
1034
|
}
|
|
@@ -1022,7 +1037,7 @@ function parseStatePart(statePart) {
|
|
|
1022
1037
|
const body = isLoopRelative ? statePathName.slice(DELIMITER.length) : statePathName;
|
|
1023
1038
|
const hasEmptySegment = body.length > 0 && body.split(DELIMITER).some((segment) => segment.length === 0);
|
|
1024
1039
|
if (hasEmptySegment || !isLoopRelative && body.length === 0) {
|
|
1025
|
-
raise(119, [
|
|
1040
|
+
raise(119, [statePart2]);
|
|
1026
1041
|
}
|
|
1027
1042
|
checkPathLikeGetPathInfo(statePathName);
|
|
1028
1043
|
return {
|
|
@@ -1584,7 +1599,7 @@ function parseBindTextsForElement(bindText) {
|
|
|
1584
1599
|
raise(101, [bindText2]);
|
|
1585
1600
|
}
|
|
1586
1601
|
const propPart = bindText2.slice(0, separatorIndex).trim();
|
|
1587
|
-
const
|
|
1602
|
+
const statePart2 = bindText2.slice(separatorIndex + 1).trim();
|
|
1588
1603
|
const keyword = propPart.split(MODIFIER_SEPARATOR)[0].split(FILTER_SEPARATOR)[0].trim();
|
|
1589
1604
|
if (KEYWORDS_WITHOUT_MODIFIERS.has(keyword)) {
|
|
1590
1605
|
if (keyword !== propPart) {
|
|
@@ -1592,20 +1607,20 @@ function parseBindTextsForElement(bindText) {
|
|
|
1592
1607
|
}
|
|
1593
1608
|
let stateResult2;
|
|
1594
1609
|
if (keyword === ELSE_KEYWORD) {
|
|
1595
|
-
if (
|
|
1610
|
+
if (statePart2.length > 0) {
|
|
1596
1611
|
raise(103, [bindText2]);
|
|
1597
1612
|
}
|
|
1598
1613
|
stateResult2 = { statePathName: "#else", outFilters: [] };
|
|
1599
1614
|
} else if (keyword === SPREAD_PROP) {
|
|
1600
|
-
if (
|
|
1615
|
+
if (statePart2.length === 0) {
|
|
1601
1616
|
raise(104, [bindText2]);
|
|
1602
1617
|
}
|
|
1603
|
-
stateResult2 = parseStatePart(
|
|
1618
|
+
stateResult2 = parseStatePart(statePart2);
|
|
1604
1619
|
if (stateResult2.outFilters.length > 0) {
|
|
1605
1620
|
raise(105, [bindText2]);
|
|
1606
1621
|
}
|
|
1607
1622
|
} else {
|
|
1608
|
-
stateResult2 = parseStatePart(
|
|
1623
|
+
stateResult2 = parseStatePart(statePart2);
|
|
1609
1624
|
if (keyword === "for" && stateResult2.outFilters.length > 0) {
|
|
1610
1625
|
raise(121, [bindText2]);
|
|
1611
1626
|
}
|
|
@@ -1622,7 +1637,7 @@ function parseBindTextsForElement(bindText) {
|
|
|
1622
1637
|
if (keyword === CLASS_NAMESPACE || keyword === ATTR_NAMESPACE) {
|
|
1623
1638
|
raise(122, [bindText2, keyword]);
|
|
1624
1639
|
}
|
|
1625
|
-
const stateResult = parseStatePart(
|
|
1640
|
+
const stateResult = parseStatePart(statePart2);
|
|
1626
1641
|
const propResult = parsePropPart(propPart);
|
|
1627
1642
|
const [head] = propResult.propSegments;
|
|
1628
1643
|
if (head === "" && propResult.propSegments.length > 1) {
|
|
@@ -1868,6 +1883,9 @@ function parseWcsStateElements(html, stateTagName = "wcs-state") {
|
|
|
1868
1883
|
const jsonAttr = extractAttribute(wcsMatch.tagContent, "json") ?? void 0;
|
|
1869
1884
|
const stateAttr = extractAttribute(wcsMatch.tagContent, "state") ?? void 0;
|
|
1870
1885
|
const srcAttr = extractAttribute(wcsMatch.tagContent, "src") ?? void 0;
|
|
1886
|
+
const contentAt = pos + 1 + stateTagName.length;
|
|
1887
|
+
const srcSpan = extractAttributeSpan(wcsMatch.tagContent, "src", contentAt);
|
|
1888
|
+
const jsonSpan = extractAttributeSpan(wcsMatch.tagContent, "json", contentAt);
|
|
1871
1889
|
const tagStart = pos;
|
|
1872
1890
|
const tagEnd = wcsMatch.end;
|
|
1873
1891
|
pos = wcsMatch.end;
|
|
@@ -1911,7 +1929,18 @@ function parseWcsStateElements(html, stateTagName = "wcs-state") {
|
|
|
1911
1929
|
wcsEnd = wcsCloseIdx === -1 ? len : wcsCloseIdx;
|
|
1912
1930
|
}
|
|
1913
1931
|
}
|
|
1914
|
-
elements.push({
|
|
1932
|
+
elements.push({
|
|
1933
|
+
mountPath,
|
|
1934
|
+
bindComponent,
|
|
1935
|
+
jsonAttr,
|
|
1936
|
+
stateAttr,
|
|
1937
|
+
srcAttr,
|
|
1938
|
+
scriptBlocks,
|
|
1939
|
+
tagStart,
|
|
1940
|
+
tagEnd,
|
|
1941
|
+
...srcSpan !== null ? { srcSpan } : {},
|
|
1942
|
+
...jsonSpan !== null ? { jsonSpan } : {}
|
|
1943
|
+
});
|
|
1915
1944
|
pos = wcsEnd;
|
|
1916
1945
|
if (wcsCloseIdx !== -1) pos = afterCloseTag(html, wcsCloseIdx);
|
|
1917
1946
|
}
|
|
@@ -2046,13 +2075,13 @@ function findCloseTag(html, startPos, tagName, lower2 = asciiLowerCase(html)) {
|
|
|
2046
2075
|
return -1;
|
|
2047
2076
|
}
|
|
2048
2077
|
function parseAttributeNames(tagContent) {
|
|
2049
|
-
const
|
|
2078
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
2050
2079
|
const attribute = /([^\s"'<>/=]+)(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s"'<>`=]+))?/g;
|
|
2051
2080
|
let match;
|
|
2052
2081
|
while ((match = attribute.exec(tagContent)) !== null) {
|
|
2053
|
-
|
|
2082
|
+
names2.add(match[1].toLowerCase());
|
|
2054
2083
|
}
|
|
2055
|
-
return
|
|
2084
|
+
return names2;
|
|
2056
2085
|
}
|
|
2057
2086
|
function extractAttribute(tagContent, attrName) {
|
|
2058
2087
|
const regex = new RegExp(
|
|
@@ -2063,6 +2092,16 @@ function extractAttribute(tagContent, attrName) {
|
|
|
2063
2092
|
if (!match) return null;
|
|
2064
2093
|
return match[1] ?? match[2] ?? match[3] ?? null;
|
|
2065
2094
|
}
|
|
2095
|
+
function extractAttributeSpan(tagContent, attrName, at2) {
|
|
2096
|
+
const regex = new RegExp(`(^|\\s)${attrName}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|(\\S+))`, "i");
|
|
2097
|
+
const match = regex.exec(tagContent);
|
|
2098
|
+
if (match === null) return null;
|
|
2099
|
+
const start = at2 + match.index + match[1].length;
|
|
2100
|
+
const end = at2 + match.index + match[0].length;
|
|
2101
|
+
const value = match[2] ?? match[3] ?? match[4] ?? "";
|
|
2102
|
+
const valueEnd = match[4] === void 0 ? end - 1 : end;
|
|
2103
|
+
return { start, end, valueStart: valueEnd - value.length, valueEnd };
|
|
2104
|
+
}
|
|
2066
2105
|
var IGNORE_VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
2067
2106
|
"area",
|
|
2068
2107
|
"base",
|
|
@@ -3417,17 +3456,25 @@ function hasDefaultExportObject(scriptContent) {
|
|
|
3417
3456
|
return locateDefaultExportObject(scriptContent) !== null;
|
|
3418
3457
|
}
|
|
3419
3458
|
function hasTopLevelSpread(scriptContent) {
|
|
3459
|
+
return findTopLevelSpread(scriptContent) !== null;
|
|
3460
|
+
}
|
|
3461
|
+
function findTopLevelSpread(scriptContent) {
|
|
3420
3462
|
const root = locateDefaultExportObject(scriptContent);
|
|
3421
|
-
if (!root) return
|
|
3463
|
+
if (!root) return null;
|
|
3422
3464
|
const scan = maskCommentsAndStrings(root.content);
|
|
3423
3465
|
let depth = 0;
|
|
3466
|
+
let start = -1;
|
|
3424
3467
|
for (let i = 0; i < scan.length; i++) {
|
|
3425
3468
|
const ch = scan[i];
|
|
3426
3469
|
if (ch === "(" || ch === "[" || ch === "{") depth++;
|
|
3427
3470
|
else if (ch === ")" || ch === "]" || ch === "}") depth--;
|
|
3428
|
-
else if (depth === 0 && ch === "." && scan.startsWith("...", i))
|
|
3471
|
+
else if (depth === 0 && start < 0 && ch === "." && scan.startsWith("...", i)) start = i;
|
|
3472
|
+
else if (depth === 0 && start >= 0 && ch === ",") return spreadRange(root.start, scan, start, i);
|
|
3429
3473
|
}
|
|
3430
|
-
return
|
|
3474
|
+
return start < 0 ? null : spreadRange(root.start, scan, start, scan.length);
|
|
3475
|
+
}
|
|
3476
|
+
function spreadRange(base, scan, start, stop) {
|
|
3477
|
+
return { start: base + start, end: base + start + scan.slice(start, stop).trimEnd().length };
|
|
3431
3478
|
}
|
|
3432
3479
|
function analyzeObjectEntries(scriptContent, key, allowEmptyKeys = false) {
|
|
3433
3480
|
const root = locateDefaultExportObject(scriptContent);
|
|
@@ -4381,9 +4428,9 @@ function derefSchemaNodes(node, defs) {
|
|
|
4381
4428
|
}
|
|
4382
4429
|
return out;
|
|
4383
4430
|
}
|
|
4384
|
-
function schemaTypeHint(
|
|
4431
|
+
function schemaTypeHint(nodes2) {
|
|
4385
4432
|
const hints = /* @__PURE__ */ new Set();
|
|
4386
|
-
for (const n of
|
|
4433
|
+
for (const n of nodes2) {
|
|
4387
4434
|
const types2 = typeof n.type === "string" ? [n.type] : Array.isArray(n.type) ? n.type : [];
|
|
4388
4435
|
if (types2.length > 0) {
|
|
4389
4436
|
for (const t of types2) {
|
|
@@ -4422,10 +4469,10 @@ function collectSchemaObjectPaths(node, prefix, paths, defs, depth) {
|
|
|
4422
4469
|
}
|
|
4423
4470
|
}
|
|
4424
4471
|
function pushSchemaValuePaths(path, node, paths, defs, depth) {
|
|
4425
|
-
const
|
|
4426
|
-
const typeHint = schemaTypeHint(
|
|
4472
|
+
const nodes2 = derefSchemaNodes(node, defs);
|
|
4473
|
+
const typeHint = schemaTypeHint(nodes2);
|
|
4427
4474
|
paths.push(withHint({ path, kind: "data", fromSchema: true }, typeHint));
|
|
4428
|
-
const items =
|
|
4475
|
+
const items = nodes2.map((n) => n.items).find((i) => i !== void 0 && i !== null && typeof i === "object");
|
|
4429
4476
|
const isArray2 = items !== void 0 || (typeHint?.split("|").includes("array") ?? false);
|
|
4430
4477
|
if (isArray2) {
|
|
4431
4478
|
const itemNodes = items !== void 0 ? derefSchemaNodes(items, defs) : [];
|
|
@@ -4442,7 +4489,7 @@ function pushSchemaValuePaths(path, node, paths, defs, depth) {
|
|
|
4442
4489
|
}
|
|
4443
4490
|
return;
|
|
4444
4491
|
}
|
|
4445
|
-
if (
|
|
4492
|
+
if (nodes2.some((n) => n.properties !== void 0)) {
|
|
4446
4493
|
collectSchemaObjectPaths(node, path, paths, defs, depth + 1);
|
|
4447
4494
|
}
|
|
4448
4495
|
}
|
|
@@ -4541,9 +4588,12 @@ function fromJson(text3) {
|
|
|
4541
4588
|
const paths = analyzeJsonPaths(text3);
|
|
4542
4589
|
return { paths, readable: paths.length > 0 || isJsonObject(text3) };
|
|
4543
4590
|
}
|
|
4591
|
+
function scriptReadable(script, paths) {
|
|
4592
|
+
return !hasTopLevelSpread(script) && (paths.length > 0 || hasDefaultExportObject(script));
|
|
4593
|
+
}
|
|
4544
4594
|
function fromScript(script) {
|
|
4545
4595
|
const paths = analyzeStatePaths(script);
|
|
4546
|
-
return { paths, readable:
|
|
4596
|
+
return { paths, readable: scriptReadable(script, paths) };
|
|
4547
4597
|
}
|
|
4548
4598
|
function resolveElementPathsRaw(element2, html, fileReader) {
|
|
4549
4599
|
let readable = false;
|
|
@@ -4566,19 +4616,23 @@ function resolveElementPathsRaw(element2, html, fileReader) {
|
|
|
4566
4616
|
readable ||= resolved.readable;
|
|
4567
4617
|
}
|
|
4568
4618
|
if (element2.scriptBlocks.length > 0) {
|
|
4569
|
-
const
|
|
4619
|
+
const blocks = element2.scriptBlocks.map((block) => ({ script: block.content, paths: analyzeStatePaths(block.content) }));
|
|
4570
4620
|
return {
|
|
4571
|
-
paths,
|
|
4572
|
-
readable:
|
|
4621
|
+
paths: blocks.flatMap((block) => block.paths),
|
|
4622
|
+
readable: readable || blocks.some((block) => scriptReadable(block.script, block.paths))
|
|
4573
4623
|
};
|
|
4574
4624
|
}
|
|
4575
4625
|
return readable ? { paths: [], readable } : UNREADABLE;
|
|
4576
4626
|
}
|
|
4577
4627
|
function readStateScript(srcPath, fileReader) {
|
|
4578
|
-
|
|
4579
|
-
|
|
4628
|
+
return readStateScriptFile(srcPath, fileReader)?.text;
|
|
4629
|
+
}
|
|
4630
|
+
function readStateScriptFile(srcPath, fileReader) {
|
|
4631
|
+
const paths = srcPath.endsWith(".js") ? [srcPath.replace(/\.js$/, ".ts"), srcPath] : srcPath.endsWith(".ts") ? [srcPath] : [];
|
|
4632
|
+
for (const path of paths) {
|
|
4633
|
+
const text3 = fileReader(path);
|
|
4634
|
+
if (text3) return { path, text: text3 };
|
|
4580
4635
|
}
|
|
4581
|
-
if (srcPath.endsWith(".ts")) return fileReader(srcPath) || void 0;
|
|
4582
4636
|
return void 0;
|
|
4583
4637
|
}
|
|
4584
4638
|
function resolveSrcAttribute(srcPath, fileReader) {
|
|
@@ -4611,10 +4665,6 @@ function isInsideForTemplate(html, offset2, bindAttrName = "data-wcs") {
|
|
|
4611
4665
|
}
|
|
4612
4666
|
return false;
|
|
4613
4667
|
}
|
|
4614
|
-
function getInnermostForPath(html, offset2, bindAttrName = "data-wcs") {
|
|
4615
|
-
const chain = getEnclosingForPaths(html, offset2, bindAttrName);
|
|
4616
|
-
return chain.length === 0 ? null : chain[chain.length - 1];
|
|
4617
|
-
}
|
|
4618
4668
|
var BINDING_SYNTAX_MARKER = `[${WcsDiagnosticCode.BindingSyntax}]`;
|
|
4619
4669
|
function isForBindingRefused(bindText) {
|
|
4620
4670
|
try {
|
|
@@ -4860,10 +4910,10 @@ function analyzeElementContexts(html, offsets, bindAttrName = "data-wcs", stateT
|
|
|
4860
4910
|
}
|
|
4861
4911
|
const match3 = bindAttr.exec(attrs);
|
|
4862
4912
|
const value = match3 === null ? null : match3[1] ?? match3[2] ?? match3[3];
|
|
4863
|
-
const
|
|
4864
|
-
const structural = name === "template" &&
|
|
4913
|
+
const names2 = value === null ? [] : propertyNamesOf(value);
|
|
4914
|
+
const structural = name === "template" && names2.length === 1 && STRUCTURAL_DIRECTIVES2.has(names2[0]) && !value.slice(0, Math.max(0, indexOfOutsideQuotes2(value, ":"))).includes("#");
|
|
4865
4915
|
const plainTemplate = name === "template" && !structural;
|
|
4866
|
-
const blocks = plainTemplate && stack.some((e) => e.name === "template") || name !== "template" &&
|
|
4916
|
+
const blocks = plainTemplate && stack.some((e) => e.name === "template") || name !== "template" && names2.some((n) => CONTENT_PROPERTIES.has(n));
|
|
4867
4917
|
const scope = plainTemplate ? { hasOwnState: false, id: extractAttribute(attrs, "id"), underRouter: stack.some((e) => e.name === ROUTER_TAG) } : null;
|
|
4868
4918
|
stack.push({ name, structural, scope, blocks });
|
|
4869
4919
|
}
|
|
@@ -6320,7 +6370,7 @@ pp$8.parseClassElement = function(constructorAllowsSuper) {
|
|
|
6320
6370
|
}
|
|
6321
6371
|
var ecmaVersion = this.options.ecmaVersion;
|
|
6322
6372
|
var node = this.startNode();
|
|
6323
|
-
var
|
|
6373
|
+
var keyName2 = "";
|
|
6324
6374
|
var isGenerator = false;
|
|
6325
6375
|
var isAsync = false;
|
|
6326
6376
|
var kind = "method";
|
|
@@ -6333,34 +6383,34 @@ pp$8.parseClassElement = function(constructorAllowsSuper) {
|
|
|
6333
6383
|
if (this.isClassElementNameStart() || this.type === types$1.star) {
|
|
6334
6384
|
isStatic = true;
|
|
6335
6385
|
} else {
|
|
6336
|
-
|
|
6386
|
+
keyName2 = "static";
|
|
6337
6387
|
}
|
|
6338
6388
|
}
|
|
6339
6389
|
node.static = isStatic;
|
|
6340
|
-
if (!
|
|
6390
|
+
if (!keyName2 && ecmaVersion >= 8 && this.eatContextual("async")) {
|
|
6341
6391
|
if ((this.isClassElementNameStart() || this.type === types$1.star) && !this.canInsertSemicolon()) {
|
|
6342
6392
|
isAsync = true;
|
|
6343
6393
|
} else {
|
|
6344
|
-
|
|
6394
|
+
keyName2 = "async";
|
|
6345
6395
|
}
|
|
6346
6396
|
}
|
|
6347
|
-
if (!
|
|
6397
|
+
if (!keyName2 && (ecmaVersion >= 9 || !isAsync) && this.eat(types$1.star)) {
|
|
6348
6398
|
isGenerator = true;
|
|
6349
6399
|
}
|
|
6350
|
-
if (!
|
|
6400
|
+
if (!keyName2 && !isAsync && !isGenerator) {
|
|
6351
6401
|
var lastValue = this.value;
|
|
6352
6402
|
if (this.eatContextual("get") || this.eatContextual("set")) {
|
|
6353
6403
|
if (this.isClassElementNameStart()) {
|
|
6354
6404
|
kind = lastValue;
|
|
6355
6405
|
} else {
|
|
6356
|
-
|
|
6406
|
+
keyName2 = lastValue;
|
|
6357
6407
|
}
|
|
6358
6408
|
}
|
|
6359
6409
|
}
|
|
6360
|
-
if (
|
|
6410
|
+
if (keyName2) {
|
|
6361
6411
|
node.computed = false;
|
|
6362
6412
|
node.key = this.startNodeAt(this.lastTokStart, this.lastTokStartLoc);
|
|
6363
|
-
node.key.name =
|
|
6413
|
+
node.key.name = keyName2;
|
|
6364
6414
|
this.finishNode(node.key, "Identifier");
|
|
6365
6415
|
} else {
|
|
6366
6416
|
this.parseClassElementName(node);
|
|
@@ -6661,7 +6711,7 @@ pp$8.parseExportSpecifier = function(exports$1) {
|
|
|
6661
6711
|
return this.finishNode(node, "ExportSpecifier");
|
|
6662
6712
|
};
|
|
6663
6713
|
pp$8.parseExportSpecifiers = function(exports$1) {
|
|
6664
|
-
var
|
|
6714
|
+
var nodes2 = [], first = true;
|
|
6665
6715
|
this.expect(types$1.braceL);
|
|
6666
6716
|
while (!this.eat(types$1.braceR)) {
|
|
6667
6717
|
if (!first) {
|
|
@@ -6672,9 +6722,9 @@ pp$8.parseExportSpecifiers = function(exports$1) {
|
|
|
6672
6722
|
} else {
|
|
6673
6723
|
first = false;
|
|
6674
6724
|
}
|
|
6675
|
-
|
|
6725
|
+
nodes2.push(this.parseExportSpecifier(exports$1));
|
|
6676
6726
|
}
|
|
6677
|
-
return
|
|
6727
|
+
return nodes2;
|
|
6678
6728
|
};
|
|
6679
6729
|
pp$8.parseImport = function(node) {
|
|
6680
6730
|
this.next();
|
|
@@ -6719,16 +6769,16 @@ pp$8.parseImportNamespaceSpecifier = function() {
|
|
|
6719
6769
|
return this.finishNode(node, "ImportNamespaceSpecifier");
|
|
6720
6770
|
};
|
|
6721
6771
|
pp$8.parseImportSpecifiers = function() {
|
|
6722
|
-
var
|
|
6772
|
+
var nodes2 = [], first = true;
|
|
6723
6773
|
if (this.type === types$1.name) {
|
|
6724
|
-
|
|
6774
|
+
nodes2.push(this.parseImportDefaultSpecifier());
|
|
6725
6775
|
if (!this.eat(types$1.comma)) {
|
|
6726
|
-
return
|
|
6776
|
+
return nodes2;
|
|
6727
6777
|
}
|
|
6728
6778
|
}
|
|
6729
6779
|
if (this.type === types$1.star) {
|
|
6730
|
-
|
|
6731
|
-
return
|
|
6780
|
+
nodes2.push(this.parseImportNamespaceSpecifier());
|
|
6781
|
+
return nodes2;
|
|
6732
6782
|
}
|
|
6733
6783
|
this.expect(types$1.braceL);
|
|
6734
6784
|
while (!this.eat(types$1.braceR)) {
|
|
@@ -6740,14 +6790,14 @@ pp$8.parseImportSpecifiers = function() {
|
|
|
6740
6790
|
} else {
|
|
6741
6791
|
first = false;
|
|
6742
6792
|
}
|
|
6743
|
-
|
|
6793
|
+
nodes2.push(this.parseImportSpecifier());
|
|
6744
6794
|
}
|
|
6745
|
-
return
|
|
6795
|
+
return nodes2;
|
|
6746
6796
|
};
|
|
6747
6797
|
pp$8.parseWithClause = function() {
|
|
6748
|
-
var
|
|
6798
|
+
var nodes2 = [];
|
|
6749
6799
|
if (!this.eat(types$1._with)) {
|
|
6750
|
-
return
|
|
6800
|
+
return nodes2;
|
|
6751
6801
|
}
|
|
6752
6802
|
this.expect(types$1.braceL);
|
|
6753
6803
|
var attributeKeys = {};
|
|
@@ -6762,14 +6812,14 @@ pp$8.parseWithClause = function() {
|
|
|
6762
6812
|
first = false;
|
|
6763
6813
|
}
|
|
6764
6814
|
var attr = this.parseImportAttribute();
|
|
6765
|
-
var
|
|
6766
|
-
if (hasOwn(attributeKeys,
|
|
6767
|
-
this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" +
|
|
6815
|
+
var keyName2 = attr.key.type === "Identifier" ? attr.key.name : attr.key.value;
|
|
6816
|
+
if (hasOwn(attributeKeys, keyName2)) {
|
|
6817
|
+
this.raiseRecoverable(attr.key.start, "Duplicate attribute key '" + keyName2 + "'");
|
|
6768
6818
|
}
|
|
6769
|
-
attributeKeys[
|
|
6770
|
-
|
|
6819
|
+
attributeKeys[keyName2] = true;
|
|
6820
|
+
nodes2.push(attr);
|
|
6771
6821
|
}
|
|
6772
|
-
return
|
|
6822
|
+
return nodes2;
|
|
6773
6823
|
};
|
|
6774
6824
|
pp$8.parseImportAttribute = function() {
|
|
6775
6825
|
var node = this.startNode();
|
|
@@ -10918,7 +10968,7 @@ function visitDestructure(pattern, prefix, scope, out) {
|
|
|
10918
10968
|
emit(out, segments, { form: "destructure", callee: false, written: false }, property.start, property.end);
|
|
10919
10969
|
}
|
|
10920
10970
|
}
|
|
10921
|
-
function collectThisMemberRefs(body,
|
|
10971
|
+
function collectThisMemberRefs(body, names2) {
|
|
10922
10972
|
let program;
|
|
10923
10973
|
try {
|
|
10924
10974
|
program = parse3(PREFIX + body + SUFFIX, { ecmaVersion: "latest", sourceType: "module" });
|
|
@@ -10927,11 +10977,11 @@ function collectThisMemberRefs(body, names) {
|
|
|
10927
10977
|
}
|
|
10928
10978
|
const fn = unwrapWrapper(program);
|
|
10929
10979
|
if (fn === null) return null;
|
|
10930
|
-
return walkThisMembers(fn.body,
|
|
10980
|
+
return walkThisMembers(fn.body, names2, PREFIX.length);
|
|
10931
10981
|
}
|
|
10932
10982
|
var VALUE_PREFIX = "(async function* () {\n(";
|
|
10933
10983
|
var VALUE_SUFFIX = ")\n})";
|
|
10934
|
-
function collectThisMemberRefsInValue(value,
|
|
10984
|
+
function collectThisMemberRefsInValue(value, names2) {
|
|
10935
10985
|
let program;
|
|
10936
10986
|
try {
|
|
10937
10987
|
program = parse3(VALUE_PREFIX + value + VALUE_SUFFIX, { ecmaVersion: "latest", sourceType: "module" });
|
|
@@ -10944,9 +10994,9 @@ function collectThisMemberRefsInValue(value, names) {
|
|
|
10944
10994
|
if (statement.type !== "ExpressionStatement") return null;
|
|
10945
10995
|
const expression = statement.expression;
|
|
10946
10996
|
if (expression.type !== "FunctionExpression") return [];
|
|
10947
|
-
return walkThisMembers(expression.body,
|
|
10997
|
+
return walkThisMembers(expression.body, names2, VALUE_PREFIX.length);
|
|
10948
10998
|
}
|
|
10949
|
-
function walkThisMembers(root,
|
|
10999
|
+
function walkThisMembers(root, names2, offsetShift) {
|
|
10950
11000
|
const out = [];
|
|
10951
11001
|
const walk = (node, thisIsState) => {
|
|
10952
11002
|
if (isClassNode(node)) return;
|
|
@@ -10957,7 +11007,7 @@ function walkThisMembers(root, names, offsetShift) {
|
|
|
10957
11007
|
}
|
|
10958
11008
|
if (thisIsState && node.type === "MemberExpression" && node.object.type === "ThisExpression") {
|
|
10959
11009
|
const hit = thisMemberName(node);
|
|
10960
|
-
if (hit !== null &&
|
|
11010
|
+
if (hit !== null && names2.has(hit.name)) {
|
|
10961
11011
|
out.push({ name: hit.name, start: hit.start - offsetShift, end: hit.end - offsetShift });
|
|
10962
11012
|
}
|
|
10963
11013
|
}
|
|
@@ -11124,13 +11174,13 @@ function findInPlaceChanges(text3, kind, root) {
|
|
|
11124
11174
|
const collect2 = (node) => {
|
|
11125
11175
|
if (isFunctionNode(node)) {
|
|
11126
11176
|
if (node.type === "FunctionDeclaration" && node.id !== null) bind(node.id.name);
|
|
11127
|
-
const
|
|
11128
|
-
for (const param of node.params) bindingNames(param,
|
|
11129
|
-
|
|
11177
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
11178
|
+
for (const param of node.params) bindingNames(param, names2);
|
|
11179
|
+
names2.forEach(bind);
|
|
11130
11180
|
} else if (node.type === "VariableDeclarator") {
|
|
11131
|
-
const
|
|
11132
|
-
bindingNames(node.id,
|
|
11133
|
-
|
|
11181
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
11182
|
+
bindingNames(node.id, names2);
|
|
11183
|
+
names2.forEach(bind);
|
|
11134
11184
|
const init = node.init ? unwrapChain(node.init) : null;
|
|
11135
11185
|
if (init !== null && node.id.type === "Identifier" && init.type === "MemberExpression") {
|
|
11136
11186
|
const chain = memberChain(init, source);
|
|
@@ -11148,9 +11198,9 @@ function findInPlaceChanges(text3, kind, root) {
|
|
|
11148
11198
|
}
|
|
11149
11199
|
}
|
|
11150
11200
|
} else if (node.type === "CatchClause" && node.param) {
|
|
11151
|
-
const
|
|
11152
|
-
bindingNames(node.param,
|
|
11153
|
-
|
|
11201
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
11202
|
+
bindingNames(node.param, names2);
|
|
11203
|
+
names2.forEach(bind);
|
|
11154
11204
|
} else if (node.type === "ClassDeclaration" && node.id !== null) {
|
|
11155
11205
|
bind(node.id.name);
|
|
11156
11206
|
} else if (node.type === "AssignmentExpression" && node.left.type === "Identifier") {
|
|
@@ -11212,14 +11262,14 @@ function findLocationRead(body) {
|
|
|
11212
11262
|
}
|
|
11213
11263
|
const wrapper = unwrapWrapper(program);
|
|
11214
11264
|
if (wrapper === null) return null;
|
|
11215
|
-
const
|
|
11265
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
11216
11266
|
const scan = (node) => {
|
|
11217
|
-
if (isFunctionNode(node)) for (const param of node.params) bindingNames(param,
|
|
11218
|
-
if (node.type === "VariableDeclarator") bindingNames(node.id,
|
|
11267
|
+
if (isFunctionNode(node)) for (const param of node.params) bindingNames(param, names2);
|
|
11268
|
+
if (node.type === "VariableDeclarator") bindingNames(node.id, names2);
|
|
11219
11269
|
forEachChild(node, scan);
|
|
11220
11270
|
};
|
|
11221
11271
|
scan(wrapper.body);
|
|
11222
|
-
if (
|
|
11272
|
+
if (names2.has("location")) return null;
|
|
11223
11273
|
const isLocation = (node) => {
|
|
11224
11274
|
const n = unwrapChain(node);
|
|
11225
11275
|
if (n.type === "Identifier") return n.name === "location";
|
|
@@ -11296,6 +11346,13 @@ var ja = {
|
|
|
11296
11346
|
updatedCallbackUnbound: (p) => `$renderedCallback \u306F binding \u99C6\u52D5\u3067\u3059\u3002"${p}" \u306F\u3053\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u3069\u306E\u30D0\u30A4\u30F3\u30C7\u30A3\u30F3\u30B0\u306B\u3082\u73FE\u308C\u306A\u3044\u305F\u3081\u3001\u3053\u306E\u5206\u5C90\u306F\u4E00\u5EA6\u3082\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\u3002\u63CF\u753B\u306B\u4F9D\u5B58\u305B\u305A\u53CD\u5FDC\u3059\u308B\u306A\u3089 $watch \u3092\u4F7F\u3063\u3066\u304F\u3060\u3055\u3044`,
|
|
11297
11347
|
onHandlerThis: (name) => `$on \u306E\u30CF\u30F3\u30C9\u30E9 "${name}" \u304C this \u3092\u4F7F\u3063\u3066\u3044\u307E\u3059\u3002$on \u306E\u30CF\u30F3\u30C9\u30E9\u306F state \u3092\u7B2C 1 \u5F15\u6570\u3067\u53D7\u3051\u53D6\u308A\uFF08\`${name}(state, event) { state.x = \u2026 }\`\uFF09\u3001this \u306F undefined \u306A\u306E\u3067\u3001this.\u2026 \u306F\u547C\u3070\u308C\u305F\u3068\u304D\u306B\u4F8B\u5916\u306B\u306A\u308A\u307E\u3059\u3002$watch \u3084\u30E1\u30BD\u30C3\u30C9\u3068\u9055\u3046\u70B9\u306B\u6CE8\u610F`,
|
|
11298
11348
|
getterReadsLocation: (read) => `\u3053\u306E getter \u306F ${read} \u3092\u8AAD\u3093\u3067\u3044\u307E\u3059\u304C\u3001location \u306F state \u3067\u306F\u306A\u3044\u306E\u3067\u3001\u6700\u521D\u306B\u8AAD\u3093\u3060 URL \u3092\u6301\u3061\u7D9A\u3051\u307E\u3059\uFF08\u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u3067\u518D\u8A55\u4FA1\u3055\u308C\u307E\u305B\u3093\uFF09\u3002URL \u306F state \u3092\u901A\u3057\u3066\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044 \u2014 <wcs-router> \u306E path / searchParams \u3092\u675F\u306D\u308B`,
|
|
11349
|
+
getterReadsClock: (read) => `\u3053\u306E getter \u306F ${read} \u3092\u8AAD\u3093\u3067\u3044\u307E\u3059\u304C\u3001\u6642\u523B\u306F state \u3067\u306F\u306A\u3044\u306E\u3067\u4F9D\u5B58\u3068\u3057\u3066\u767B\u9332\u3055\u308C\u305A\u3001getter \u306F\u30AD\u30E3\u30C3\u30B7\u30E5\u3057\u305F\u6700\u521D\u306E\u5024\u3092\u8FD4\u3057\u7D9A\u3051\u307E\u3059\uFF08\u30A4\u30D9\u30F3\u30C8\u30C8\u30FC\u30AF\u30F3\u3067\u6BCE\u30D5\u30EC\u30FC\u30E0\u300C\u63CF\u304D\u76F4\u3057\u300D\u3066\u3082\u5909\u308F\u308A\u307E\u305B\u3093\uFF09\u3002\u6642\u523B\u3092 state \u306B\u7F6E\u3044\u3066\u304F\u3060\u3055\u3044 \u2014 <wcs-raf> \u3084 <wcs-timer> \u304C\u66F8\u304F\u5024\u3092\u675F\u306D\u308B`,
|
|
11350
|
+
updatedCallbackUnknownPath: (p) => `"${p}" \u306F state \u306E\u30D1\u30B9\u3067\u306F\u306A\u3044\u306E\u3067 $renderedCallback \u306E paths \u306B\u73FE\u308C\u305A\u3001\u3053\u306E\u5206\u5C90\u306F\u4E00\u5EA6\u3082\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093`,
|
|
11351
|
+
commandTokenUnbound: (t) => `\u30B3\u30DE\u30F3\u30C9\u30C8\u30FC\u30AF\u30F3 "${t}" \u3092 emit \u3057\u3066\u3044\u307E\u3059\u304C\u3001\u3053\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306B\u305D\u308C\u3092\u53D7\u3051\u308B command.<\u30E1\u30BD\u30C3\u30C9>: ${t} \u306E\u675F\u7E1B\u304C\u3042\u308A\u307E\u305B\u3093\u3002emit \u306F\u8AB0\u306B\u3082\u5C4A\u304D\u307E\u305B\u3093\u3002\u30E1\u30BD\u30C3\u30C9\u3092\u547C\u3076\u8981\u7D20\u306B\u675F\u306D\u3066\u304F\u3060\u3055\u3044\uFF08command.focus: ${t}\uFF09`,
|
|
11352
|
+
writePathMissing: (k) => `"${k}" \u306F state \u304C\u5BA3\u8A00\u3057\u3066\u3044\u306A\u3044\u30AD\u30FC\u3067\u3059\u3002\u66F8\u304D\u8FBC\u307F\u306F\u65B0\u3057\u3044\u30AD\u30FC\u3092\u4F5C\u308B\u3060\u3051\u3067\u3001\u5BA3\u8A00\u3057\u305F\u30AD\u30FC\u306E\u675F\u7E1B\u306B\u306F\u5C4A\u304D\u307E\u305B\u3093`,
|
|
11353
|
+
readPathMissing: (p, top) => top ? `"${p}" \u306F state \u304C\u5BA3\u8A00\u3057\u3066\u3044\u306A\u3044\u30AD\u30FC\u3067\u3059\u3002\u8AAD\u3093\u3060\u6642\u70B9\u3067\u4F8B\u5916\u306B\u306A\u308A\u307E\u3059\uFF08#301\uFF09` : `\u30D1\u30B9 "${p}" \u306F\u72B6\u614B\u5B9A\u7FA9\u306B\u5B58\u5728\u3057\u307E\u305B\u3093\u3002\u8AAD\u307F\u306F undefined \u306B\u306A\u308A\u3001\u305D\u3053\u304B\u3089\u8A08\u7B97\u3057\u305F\u5024\u306F\u9ED9\u3063\u3066\u9055\u3044\u307E\u3059`,
|
|
11354
|
+
pathDynamicUnknownSpread: (sp) => `${sp} \u304C\u6301\u3061\u8FBC\u3080\u30AD\u30FC\u306F\u9759\u7684\u306B\u8AAD\u3081\u306A\u3044\u306E\u3067\u3001\u3053\u306E state \u306E\u30D1\u30B9\u306F\u691C\u67FB\u3057\u3066\u3044\u307E\u305B\u3093\uFF08\u675F\u7E1B\u30FBgetter \u306E\u4E2D\u306E\u8AAD\u307F\u30FB$watch \u306E\u30AD\u30FC\uFF09\u3002\u30AD\u30FC\u3092 wcstack.manifest.json \u306E stateSchema \u306B\u5BA3\u8A00\u3059\u308B\u3068\u691C\u67FB\u3055\u308C\u307E\u3059\u3002npx wcs-schema\uFF08@wcstack/typescript\uFF09\u304C state \u306E\u578B\uFF08JSDoc\u30FBTypeScript\uFF09\u304B\u3089\u4F5C\u308C\u307E\u3059`,
|
|
11355
|
+
pathReadonlyTwoWay: (p, prop) => `"${p}" \u306F setter \u306E\u7121\u3044 getter \u3067\u3059\u304C\u3001${prop}: \u306F\u8AAD\u8005\u306E\u5165\u529B\u3092\u66F8\u304D\u623B\u3059\u306E\u3067\u3001\u5165\u529B\u306E\u305F\u3073\u306B\u66F8\u304D\u8FBC\u307F\u304C\u5931\u6557\u3057\u307E\u3059\uFF08"${p}" is a getter without a setter\uFF09\u3002setter \u3092\u8DB3\u3059\uFF08set "${p}"(v) { \u2026 }\uFF09\u304B\u3001#ro \u3067\u4E00\u65B9\u5411\u306B\u3057\u3066\u304F\u3060\u3055\u3044\uFF08${prop}#ro: ${p}\uFF09`,
|
|
11299
11356
|
submitWithoutPrevent: (h) => `onsubmit \u306B #prevent \u304C\u7121\u304F\u3001"${h}" \u3082 preventDefault \u3092\u547C\u3073\u307E\u305B\u3093\u3002\u30D6\u30E9\u30A6\u30B6\u306F\u30D5\u30A9\u30FC\u30E0\u3082\u9001\u308B\u306E\u3067\u3001\u30DA\u30FC\u30B8\u304C\u8AAD\u307F\u76F4\u3055\u308C\u308B\u304B\u3001router \u304C\u3042\u308C\u3070 GET \u304C\u6B04\u306E\u5024\uFF08\u30D1\u30B9\u30EF\u30FC\u30C9\u3082\uFF09\u3092 URL \u3068\u5C65\u6B74\u306B\u8F09\u305B\u307E\u3059\u3002onsubmit#prevent: ${h} \u3068\u66F8\u304F\u304B\u3001\u30CF\u30F3\u30C9\u30E9\u3067 event.preventDefault() \u3092\u547C\u3093\u3067\u304F\u3060\u3055\u3044`,
|
|
11300
11357
|
getterUntrackedRead: (root, sp) => `\u3053\u3053\u3067\u8FFD\u8DE1\u3055\u308C\u308B\u306E\u306F "${root}" \u3060\u3051\u3067\u3059\u3002"${sp}" \u304C\u5909\u308F\u3063\u3066\u3082\u3053\u306E getter \u306F\u518D\u8A55\u4FA1\u3055\u308C\u307E\u305B\u3093\uFF08\u30D1\u30B9\u8AAD\u307F\u53D6\u308A\u306E\u5148\u306E\u7D20\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u30A2\u30AF\u30BB\u30B9\u306F\u8FFD\u8DE1\u3055\u308C\u306A\u3044\uFF09\u3002this["${sp}"] \u3067\u8AAD\u3093\u3067\u304F\u3060\u3055\u3044`,
|
|
11301
11358
|
handlerFilterNotAllowed: (prop) => `\u30A4\u30D9\u30F3\u30C8\u30CF\u30F3\u30C9\u30E9 "${prop}" \u306B\u30D5\u30A3\u30EB\u30BF\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093`,
|
|
@@ -11332,7 +11389,7 @@ var ja = {
|
|
|
11332
11389
|
behaviorValueType: (key, type) => `$behavior \u306E "${key}" \u306F ${type === "boolean" ? "true \u304B false" : type} \u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u8AAD\u307F\u8FBC\u307F\u6642\u306B throw \u3057\u307E\u3059\uFF09`,
|
|
11333
11390
|
configInVolume: (key, mountPath) => `${key} \u306F\u30DC\u30EA\u30E5\u30FC\u30E0\uFF08mount="${mountPath}"\uFF09\u3067\u306F\u5BA3\u8A00\u3067\u304D\u307E\u305B\u3093\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u63A5\u304E\u6728\u3092\u62D2\u307F\u3001console.error \u3067\u5831\u544A\u3057\u307E\u3059 \u2014 \u3053\u306E state \u306F\u6728\u306B\u8F09\u308A\u307E\u305B\u3093\uFF09\u3002root \u306E state \u306B\u5BA3\u8A00\u3057\u3066\u304F\u3060\u3055\u3044 \u2014 \u30DC\u30EA\u30E5\u30FC\u30E0\u306F root \u306E\u30A8\u30F3\u30B8\u30F3\u306B\u63A5\u304E\u6728\u3055\u308C\u307E\u3059`,
|
|
11334
11391
|
featuresNotArray: () => `$features \u306F\u5F8C\u4ED8\u3051\u306E\u540D\u524D\u306E\u914D\u5217\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\uFF08\u4F8B: ["temporal", "formats"]\u3002\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u8AAD\u307F\u8FBC\u307F\u6642\u306B throw \u3057\u307E\u3059\uFF09`,
|
|
11335
|
-
featureUnknown: (name,
|
|
11392
|
+
featureUnknown: (name, names2, suggestion2) => `"${name}" \u306F\u5F8C\u4ED8\u3051\u306E\u540D\u524D\u3067\u306F\u3042\u308A\u307E\u305B\u3093\uFF08${names2.join("\u30FB")}\uFF09${suggestion2}`,
|
|
11336
11393
|
volumeDeclarationRejected: (key, mountPath) => `${key} \u306F\u30DC\u30EA\u30E5\u30FC\u30E0\uFF08mount="${mountPath}"\uFF09\u3067\u306F\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\u3002\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u63A5\u304E\u6728\u3092\u62D2\u3093\u3067 console.error \u3067\u5831\u544A\u3057\u307E\u3059\uFF08\u3053\u306E state \u306F\u6728\u306B\u8F09\u308A\u307E\u305B\u3093\uFF09\u3002root \u306E state \u306B\u5BA3\u8A00\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
11337
11394
|
volumeDeclarationNotRun: (key, mountPath) => `${key} \u306F\u30DC\u30EA\u30E5\u30FC\u30E0\uFF08mount="${mountPath}"\uFF09\u3067\u306F\u5B9F\u884C\u3055\u308C\u307E\u305B\u3093\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F console.warn \u3067\u77E5\u3089\u305B\u3001\u3053\u306E\u5BA3\u8A00\u3092\u7121\u8996\u3057\u307E\u3059 \u2014 root \u306E state \u306E\u3082\u306E\u3067\u3059\uFF09\u3002root \u306E state \u306B\u5BA3\u8A00\u3057\u3066\u304F\u3060\u3055\u3044`,
|
|
11338
11395
|
secondRoot: () => '\u540C\u3058 root \u306B 2 \u3064\u76EE\u306E <wcs-state> \u304C\u3042\u308A\u307E\u3059\u3002state \u306E\u6728\u306F root \u3054\u3068\u306B 1 \u3064\u3067\u3059\uFF08\u30E9\u30F3\u30BF\u30A4\u30E0\u306F\u5F8C\u304B\u3089\u8AAD\u307F\u8FBC\u3093\u3060\u65B9\u3092\u62D2\u3093\u3067 console.error \u3067\u5831\u544A\u3057\u307E\u3059\uFF09\u3002\u90E8\u5206\u6728\u306F <wcs-state mount="path"> \u3067\u63A5\u304E\u6728\u3057\u3066\u304F\u3060\u3055\u3044',
|
|
@@ -11497,6 +11554,13 @@ var en = {
|
|
|
11497
11554
|
updatedCallbackUnbound: (p) => `$renderedCallback is binding-driven. "${p}" is not bound anywhere in this document, so this branch never runs. Use $watch to react without depending on what is rendered`,
|
|
11498
11555
|
onHandlerThis: (name) => `The $on handler "${name}" uses this. A $on handler receives the state as its first argument (\`${name}(state, event) { state.x = \u2026 }\`) and this is undefined, so this.\u2026 throws when it is called \u2014 unlike $watch handlers and methods`,
|
|
11499
11556
|
getterReadsLocation: (read) => `This getter reads ${read}, which is not state: it keeps the URL it first read (a navigation does not re-evaluate it). Read the URL through state \u2014 bind <wcs-router>'s path / searchParams`,
|
|
11557
|
+
getterReadsClock: (read) => `This getter reads ${read}. The time is not state, so it is not a dependency: the getter is cached and keeps returning its first value (an event token "redrawing" every frame does not change it). Keep the time in state \u2014 bind the value <wcs-raf> or <wcs-timer> writes`,
|
|
11558
|
+
updatedCallbackUnknownPath: (p) => `"${p}" is not a path of this state, so it is never in $renderedCallback's paths and this branch never runs`,
|
|
11559
|
+
commandTokenUnbound: (t) => `The command token "${t}" is emitted, but no command.<method>: ${t} binding in this document receives it, so the emit reaches nothing. Bind it on the element whose method it should call (command.focus: ${t})`,
|
|
11560
|
+
writePathMissing: (k) => `"${k}" is not a key the state declares. The write creates a new key and reaches no binding of a declared one`,
|
|
11561
|
+
readPathMissing: (p, top) => top ? `"${p}" is not a key the state declares. Reading it throws (#301)` : `Path "${p}" does not exist in the state definition. The read gives undefined, and what is computed from it is wrong without a word`,
|
|
11562
|
+
pathDynamicUnknownSpread: (sp) => `The keys ${sp} brings in cannot be read statically, so this state's paths are not checked (bindings, reads in getters, $watch keys). Declare the keys in the stateSchema of wcstack.manifest.json to have them checked; npx wcs-schema (@wcstack/typescript) derives it from the state's types (JSDoc or TypeScript)`,
|
|
11563
|
+
pathReadonlyTwoWay: (p, prop) => `"${p}" is a getter without a setter, and ${prop}: writes back what the reader enters, so every edit fails ("${p}" is a getter without a setter). Add a setter (set "${p}"(v) { \u2026 }), or bind it one way with #ro (${prop}#ro: ${p})`,
|
|
11500
11564
|
submitWithoutPrevent: (h) => `onsubmit has no #prevent and "${h}" does not call preventDefault, so the browser submits the form too: the page reloads, or with the router a GET puts the fields (a password too) in the URL and the history. Write onsubmit#prevent: ${h}, or call event.preventDefault() in the handler`,
|
|
11501
11565
|
getterUntrackedRead: (root, sp) => `Only "${root}" is tracked here: the getter is not re-evaluated when "${sp}" changes (plain property access after a path read is not tracked). Read this["${sp}"] instead`,
|
|
11502
11566
|
handlerFilterNotAllowed: (prop) => `Filters cannot be applied to event handler "${prop}"`,
|
|
@@ -11533,7 +11597,7 @@ var en = {
|
|
|
11533
11597
|
behaviorValueType: (key, type) => `$behavior "${key}" must be ${type === "boolean" ? "true or false" : type} (the runtime throws at load time)`,
|
|
11534
11598
|
configInVolume: (key, mountPath) => `${key} cannot be declared in a volume (mount="${mountPath}"): the runtime refuses to graft the volume and reports that with console.error (this state is not on the tree). Declare it on the root state \u2014 a volume is grafted onto the root's engine`,
|
|
11535
11599
|
featuresNotArray: () => `$features must be an array of add-on names (for example ["temporal", "formats"]; the runtime throws at load time)`,
|
|
11536
|
-
featureUnknown: (name,
|
|
11600
|
+
featureUnknown: (name, names2, suggestion2) => `"${name}" is not an add-on (${names2.join(", ")})${suggestion2}`,
|
|
11537
11601
|
volumeDeclarationRejected: (key, mountPath) => `${key} is not run in a volume (mount="${mountPath}"): the runtime refuses to graft the volume and reports that with console.error (this state is not on the tree). Declare it on the root state`,
|
|
11538
11602
|
volumeDeclarationNotRun: (key, mountPath) => `${key} is not run in a volume (mount="${mountPath}"): the runtime says so with console.warn and ignores this declaration \u2014 it belongs to the root state. Declare it there`,
|
|
11539
11603
|
secondRoot: () => 'A second <wcs-state> on the same root: there is one state tree per root (the runtime refuses the one that loads second and reports it with console.error). Graft a subtree with <wcs-state mount="path">',
|
|
@@ -11785,11 +11849,11 @@ var DELEGATED_EVENTS = /* @__PURE__ */ new Set([
|
|
|
11785
11849
|
]);
|
|
11786
11850
|
var CUSTOM_ELEMENT_OWN_EVENTS = /* @__PURE__ */ new Set(["input", "change", "submit"]);
|
|
11787
11851
|
function collectCurrentTargetHandlers(elements, html, fileReader) {
|
|
11788
|
-
const
|
|
11852
|
+
const names2 = /* @__PURE__ */ new Set();
|
|
11789
11853
|
forEachStateMethod(elements, html, fileReader, "currentTarget", (name, params, body) => {
|
|
11790
|
-
if (readsEventCurrentTarget(params, body))
|
|
11854
|
+
if (readsEventCurrentTarget(params, body)) names2.add(name);
|
|
11791
11855
|
});
|
|
11792
|
-
return
|
|
11856
|
+
return names2;
|
|
11793
11857
|
}
|
|
11794
11858
|
function collectPreventDefaultHandlers(elements, html, fileReader) {
|
|
11795
11859
|
const handlers = /* @__PURE__ */ new Map();
|
|
@@ -12036,6 +12100,18 @@ function validateBindings(html, attrName, stateTagName = "wcs-state", locale2, f
|
|
|
12036
12100
|
message: `${verdict.message}${pathTrimmed.startsWith(".") ? msgs.expansionSuffix(checkPath) : ""}`,
|
|
12037
12101
|
severity: verdict.severity
|
|
12038
12102
|
});
|
|
12103
|
+
} else if (writesBack(attr, propNoMod, parsed.property)) {
|
|
12104
|
+
const target = scopedPaths.find((p) => p.path === checkPath);
|
|
12105
|
+
if (target !== void 0 && target.kind === "computed" && target.settable !== true) {
|
|
12106
|
+
const pathStart = bindingStart + binding.indexOf(parsed.path);
|
|
12107
|
+
diagnostics.push({
|
|
12108
|
+
code: WcsDiagnosticCode.PathReadonly,
|
|
12109
|
+
start: pathStart,
|
|
12110
|
+
end: pathStart + pathTrimmed.length,
|
|
12111
|
+
message: msgs.pathReadonlyTwoWay(checkPath, propNoMod),
|
|
12112
|
+
severity: "error"
|
|
12113
|
+
});
|
|
12114
|
+
}
|
|
12039
12115
|
}
|
|
12040
12116
|
}
|
|
12041
12117
|
}
|
|
@@ -12222,6 +12298,19 @@ function openTagBefore(html, valueStart) {
|
|
|
12222
12298
|
const lt2 = html.lastIndexOf("<", valueStart);
|
|
12223
12299
|
return lt2 === -1 ? "" : html.slice(lt2, valueStart);
|
|
12224
12300
|
}
|
|
12301
|
+
function writesBack(attr, prop, written) {
|
|
12302
|
+
if (written.split("#").slice(1).some((modifier) => modifier.trim() === "ro")) return false;
|
|
12303
|
+
if (prop === "radio" || prop === "checkbox") return true;
|
|
12304
|
+
const tag = attr.tagName;
|
|
12305
|
+
if (tag === void 0 || tag.includes("-")) return false;
|
|
12306
|
+
if (tag === "input") {
|
|
12307
|
+
const type = (attr.inputType || "text").toLowerCase();
|
|
12308
|
+
if (type === "button") return false;
|
|
12309
|
+
if ((type === "radio" || type === "checkbox") && prop === "checked") return true;
|
|
12310
|
+
return prop === "value" || prop === "valueAsNumber" || prop === "valueAsDate";
|
|
12311
|
+
}
|
|
12312
|
+
return (tag === "select" || tag === "textarea") && prop === "value";
|
|
12313
|
+
}
|
|
12225
12314
|
function findAllBindAttributes(html, attrName) {
|
|
12226
12315
|
const attrs = [];
|
|
12227
12316
|
const escaped = attrName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -12235,7 +12324,8 @@ function findAllBindAttributes(html, attrName) {
|
|
|
12235
12324
|
const valueStart = tag.start + match.index + match[0].length;
|
|
12236
12325
|
const valueEnd = html.indexOf(quote, valueStart);
|
|
12237
12326
|
if (valueEnd === -1 || valueEnd > tag.end) continue;
|
|
12238
|
-
|
|
12327
|
+
const inputType = tag.tagName === "input" ? extractAttribute(attrsText, "type") ?? void 0 : void 0;
|
|
12328
|
+
attrs.push({ value: html.slice(valueStart, valueEnd), valueStart, tagName: tag.tagName, ...inputType !== void 0 ? { inputType } : {} });
|
|
12239
12329
|
regex.lastIndex = valueEnd - tag.start;
|
|
12240
12330
|
}
|
|
12241
12331
|
}
|
|
@@ -14387,6 +14477,162 @@ var BUILTIN_TAGS = {
|
|
|
14387
14477
|
}
|
|
14388
14478
|
};
|
|
14389
14479
|
|
|
14480
|
+
// src/service/pageElements.ts
|
|
14481
|
+
var MAX_FILES = 32;
|
|
14482
|
+
var JS_TYPES = /* @__PURE__ */ new Set(["", "module", "text/javascript", "application/javascript", "text/ecmascript"]);
|
|
14483
|
+
function pageScripts(html) {
|
|
14484
|
+
const inline = [];
|
|
14485
|
+
const srcs = [];
|
|
14486
|
+
const re = /<script\b((?:"[^"]*"|'[^']*'|[^>"'])*)>([\s\S]*?)<\/script\s*>/gi;
|
|
14487
|
+
const text3 = html.replace(/<!--[\s\S]*?-->/g, (c) => " ".repeat(c.length));
|
|
14488
|
+
let m;
|
|
14489
|
+
while ((m = re.exec(text3)) !== null) {
|
|
14490
|
+
const attrs = m[1];
|
|
14491
|
+
const type = (extractAttribute(attrs, "type") ?? "").trim().toLowerCase();
|
|
14492
|
+
if (!JS_TYPES.has(type)) continue;
|
|
14493
|
+
const src = extractAttribute(attrs, "src");
|
|
14494
|
+
if (src !== null) srcs.push(src);
|
|
14495
|
+
else if (m[2].trim() !== "") inline.push(m[2]);
|
|
14496
|
+
}
|
|
14497
|
+
return { inline, srcs };
|
|
14498
|
+
}
|
|
14499
|
+
function joinRelative(from, spec) {
|
|
14500
|
+
if (!spec.startsWith("./") && !spec.startsWith("../")) return null;
|
|
14501
|
+
const dir = from.includes("/") ? from.slice(0, from.lastIndexOf("/") + 1) : "";
|
|
14502
|
+
const out = [];
|
|
14503
|
+
for (const seg of `${dir}${spec}`.split("/")) {
|
|
14504
|
+
if (seg === "" || seg === ".") continue;
|
|
14505
|
+
if (seg === ".." && out.length > 0 && out[out.length - 1] !== "..") out.pop();
|
|
14506
|
+
else out.push(seg);
|
|
14507
|
+
}
|
|
14508
|
+
return `./${out.join("/")}`;
|
|
14509
|
+
}
|
|
14510
|
+
function parseScript(source) {
|
|
14511
|
+
for (const sourceType of ["module", "script"]) {
|
|
14512
|
+
try {
|
|
14513
|
+
return parse3(source, { ecmaVersion: "latest", sourceType, allowHashBang: true });
|
|
14514
|
+
} catch {
|
|
14515
|
+
}
|
|
14516
|
+
}
|
|
14517
|
+
return null;
|
|
14518
|
+
}
|
|
14519
|
+
function* nodes(node) {
|
|
14520
|
+
yield node;
|
|
14521
|
+
for (const value of Object.values(node)) {
|
|
14522
|
+
if (Array.isArray(value)) {
|
|
14523
|
+
for (const v of value) if (v !== null && typeof v === "object" && typeof v.type === "string") yield* nodes(v);
|
|
14524
|
+
} else if (value !== null && typeof value === "object" && typeof value.type === "string") {
|
|
14525
|
+
yield* nodes(value);
|
|
14526
|
+
}
|
|
14527
|
+
}
|
|
14528
|
+
}
|
|
14529
|
+
var keyName = (key, computed) => computed ? null : key.type === "Identifier" ? key.name : key.type === "Literal" && typeof key.value === "string" ? key.value : null;
|
|
14530
|
+
function names(obj, key) {
|
|
14531
|
+
const prop = obj.properties.find((p) => p.type === "Property" && keyName(p.key, p.computed) === key);
|
|
14532
|
+
if (prop === void 0 || prop.type !== "Property") return void 0;
|
|
14533
|
+
if (prop.value.type !== "ArrayExpression") return null;
|
|
14534
|
+
const out = [];
|
|
14535
|
+
for (const el of prop.value.elements) {
|
|
14536
|
+
if (el === null || el.type !== "ObjectExpression" || el.properties.some((p) => p.type !== "Property")) return null;
|
|
14537
|
+
const name = el.properties.find((p) => p.type === "Property" && keyName(p.key, p.computed) === "name");
|
|
14538
|
+
if (name === void 0 || name.type !== "Property" || name.value.type !== "Literal" || typeof name.value.value !== "string") return null;
|
|
14539
|
+
out.push(name.value.value);
|
|
14540
|
+
}
|
|
14541
|
+
return out;
|
|
14542
|
+
}
|
|
14543
|
+
function contractOf(value) {
|
|
14544
|
+
if (value.type !== "ObjectExpression" || value.properties.some((p) => p.type !== "Property")) return "unknown";
|
|
14545
|
+
const properties = names(value, "properties");
|
|
14546
|
+
const inputs = names(value, "inputs");
|
|
14547
|
+
const commands = names(value, "commands");
|
|
14548
|
+
if (properties === null || inputs === null || commands === null) return "unknown";
|
|
14549
|
+
return {
|
|
14550
|
+
properties: properties ?? [],
|
|
14551
|
+
inputs: Object.fromEntries((inputs ?? []).map((n) => [n, null])),
|
|
14552
|
+
commands: commands ?? []
|
|
14553
|
+
};
|
|
14554
|
+
}
|
|
14555
|
+
function declaredBy(cls) {
|
|
14556
|
+
let declared = "none";
|
|
14557
|
+
for (const member of cls.body.body) {
|
|
14558
|
+
if (member.type !== "PropertyDefinition" && member.type !== "MethodDefinition" || !member.static) continue;
|
|
14559
|
+
if (keyName(member.key, member.computed) !== "wcBindable") continue;
|
|
14560
|
+
if (member.type === "PropertyDefinition") {
|
|
14561
|
+
declared = member.value === null || member.value === void 0 ? "unknown" : contractOf(member.value);
|
|
14562
|
+
} else {
|
|
14563
|
+
const body = member.kind === "get" ? member.value.body.body : [];
|
|
14564
|
+
const ret = body.length === 1 && body[0].type === "ReturnStatement" ? body[0].argument : null;
|
|
14565
|
+
declared = ret === null || ret === void 0 ? "unknown" : contractOf(ret);
|
|
14566
|
+
}
|
|
14567
|
+
}
|
|
14568
|
+
const sup = cls.superClass;
|
|
14569
|
+
return { declared, superName: sup !== null && sup !== void 0 && sup.type === "Identifier" ? sup.name : null };
|
|
14570
|
+
}
|
|
14571
|
+
function isDefine(callee) {
|
|
14572
|
+
if (callee.type !== "MemberExpression" || keyName(callee.property, callee.computed) !== "define") return false;
|
|
14573
|
+
const o = callee.object;
|
|
14574
|
+
return o.type === "Identifier" && o.name === "customElements" || o.type === "MemberExpression" && keyName(o.property, o.computed) === "customElements";
|
|
14575
|
+
}
|
|
14576
|
+
function collectPageElementContracts(html, fileReader) {
|
|
14577
|
+
const { inline, srcs } = pageScripts(html);
|
|
14578
|
+
const programs = [];
|
|
14579
|
+
const read = /* @__PURE__ */ new Set();
|
|
14580
|
+
const queue = srcs.map((spec) => ({ from: "", spec: spec.startsWith(".") ? spec : `./${spec}` }));
|
|
14581
|
+
const visit2 = (program, from) => {
|
|
14582
|
+
programs.push(program);
|
|
14583
|
+
for (const n of nodes(program)) {
|
|
14584
|
+
const source = n.type === "ImportDeclaration" || n.type === "ExportAllDeclaration" || n.type === "ExportNamedDeclaration" ? n.source : n.type === "ImportExpression" ? n.source : null;
|
|
14585
|
+
if (source !== null && source !== void 0 && source.type === "Literal" && typeof source.value === "string") queue.push({ from, spec: source.value });
|
|
14586
|
+
}
|
|
14587
|
+
};
|
|
14588
|
+
for (const source of inline) {
|
|
14589
|
+
const program = parseScript(source);
|
|
14590
|
+
if (program !== null) visit2(program, "");
|
|
14591
|
+
}
|
|
14592
|
+
while (queue.length > 0 && fileReader !== void 0 && read.size < MAX_FILES) {
|
|
14593
|
+
const { from, spec } = queue.shift();
|
|
14594
|
+
const path = joinRelative(from, spec);
|
|
14595
|
+
if (path === null || read.has(path) || !/\.m?js$/.test(path)) continue;
|
|
14596
|
+
read.add(path);
|
|
14597
|
+
const text3 = fileReader(path);
|
|
14598
|
+
const program = text3 === void 0 ? null : parseScript(text3);
|
|
14599
|
+
if (program !== null) visit2(program, path);
|
|
14600
|
+
}
|
|
14601
|
+
const classes = /* @__PURE__ */ new Map();
|
|
14602
|
+
const defines = [];
|
|
14603
|
+
for (const program of programs) {
|
|
14604
|
+
for (const n of nodes(program)) {
|
|
14605
|
+
if (n.type === "ClassDeclaration" && n.id !== null && !classes.has(n.id.name)) classes.set(n.id.name, declaredBy(n));
|
|
14606
|
+
else if (n.type === "VariableDeclarator" && n.id.type === "Identifier" && n.init?.type === "ClassExpression" && !classes.has(n.id.name)) {
|
|
14607
|
+
classes.set(n.id.name, declaredBy(n.init));
|
|
14608
|
+
} else if (n.type === "CallExpression" && isDefine(n.callee) && n.arguments.length >= 2) {
|
|
14609
|
+
const [tag, cls] = n.arguments;
|
|
14610
|
+
if (tag.type !== "Literal" || typeof tag.value !== "string") continue;
|
|
14611
|
+
if (cls.type === "ClassExpression") defines.push({ tag: tag.value, info: declaredBy(cls) });
|
|
14612
|
+
else if (cls.type === "Identifier") defines.push({ tag: tag.value, info: cls.name });
|
|
14613
|
+
}
|
|
14614
|
+
}
|
|
14615
|
+
}
|
|
14616
|
+
const resolve = (info, depth) => {
|
|
14617
|
+
if (info.declared === "unknown") return null;
|
|
14618
|
+
if (info.declared !== "none") return info.declared;
|
|
14619
|
+
const sup = info.superName === null ? void 0 : classes.get(info.superName);
|
|
14620
|
+
return sup === void 0 || depth > 16 ? null : resolve(sup, depth + 1);
|
|
14621
|
+
};
|
|
14622
|
+
const out = /* @__PURE__ */ new Map();
|
|
14623
|
+
for (const { tag, info } of defines) {
|
|
14624
|
+
const name = tag.toLowerCase();
|
|
14625
|
+
if (name.startsWith("wcs-") || out.has(name)) continue;
|
|
14626
|
+
const cls = typeof info === "string" ? classes.get(info) : info;
|
|
14627
|
+
const contract = cls === void 0 ? null : resolve(cls, 0);
|
|
14628
|
+
if (contract !== null) out.set(name, contract);
|
|
14629
|
+
}
|
|
14630
|
+
return out;
|
|
14631
|
+
}
|
|
14632
|
+
function mayDefineElements(html) {
|
|
14633
|
+
return /customElements|<script\b[^>]*\bsrc\s*=/i.test(html);
|
|
14634
|
+
}
|
|
14635
|
+
|
|
14390
14636
|
// src/service/ioNodeValidator.ts
|
|
14391
14637
|
var HTML_SINK_PROPERTIES = /* @__PURE__ */ new Set(["html", "innerHTML", "outerHTML", "srcdoc"]);
|
|
14392
14638
|
var STRUCTURAL_DIRECTIVES3 = /* @__PURE__ */ new Set(["for", "if", "elseif", "else"]);
|
|
@@ -14401,7 +14647,6 @@ function validateIoNodes(html, bindAttribute = "data-wcs", stateTagName = "wcs-s
|
|
|
14401
14647
|
const diagnostics = [];
|
|
14402
14648
|
const msgs = getMessages(locale2);
|
|
14403
14649
|
const occurrences = findBuiltinTagOccurrences(html);
|
|
14404
|
-
if (occurrences.length === 0) return diagnostics;
|
|
14405
14650
|
let statePaths = null;
|
|
14406
14651
|
const getPaths = () => statePaths ??= getStatePathsFromHtml(html, stateTagName, fileReader);
|
|
14407
14652
|
for (const occ of occurrences) {
|
|
@@ -14429,32 +14674,35 @@ function validateIoNodes(html, bindAttribute = "data-wcs", stateTagName = "wcs-s
|
|
|
14429
14674
|
}
|
|
14430
14675
|
if (contract.properties.length === 0 && contract.commands.length === 0 && Object.keys(contract.inputs).length === 0) continue;
|
|
14431
14676
|
const hasManual = hasBooleanAttribute(occ.attrsText, "manual");
|
|
14432
|
-
|
|
14433
|
-
|
|
14434
|
-
|
|
14435
|
-
|
|
14436
|
-
|
|
14437
|
-
|
|
14438
|
-
|
|
14439
|
-
|
|
14440
|
-
|
|
14441
|
-
const
|
|
14442
|
-
|
|
14443
|
-
occ.tagName,
|
|
14444
|
-
contract,
|
|
14445
|
-
parsed,
|
|
14446
|
-
property,
|
|
14447
|
-
start,
|
|
14448
|
-
end,
|
|
14449
|
-
hasManual,
|
|
14450
|
-
getPaths,
|
|
14451
|
-
diagnostics,
|
|
14452
|
-
msgs
|
|
14453
|
-
);
|
|
14677
|
+
checkBindings(occ.tagName, contract, bindAttr.value, valueStart, hasManual, getPaths, diagnostics, msgs);
|
|
14678
|
+
}
|
|
14679
|
+
if (mayDefineElements(html)) {
|
|
14680
|
+
const own2 = findPageTagOccurrences(html, bindAttribute);
|
|
14681
|
+
const contracts = own2.length > 0 ? collectPageElementContracts(html, fileReader) : null;
|
|
14682
|
+
for (const occ of own2) {
|
|
14683
|
+
const contract = contracts.get(occ.tagName);
|
|
14684
|
+
if (contract === void 0) continue;
|
|
14685
|
+
if (contract.properties.length === 0 && contract.commands.length === 0 && Object.keys(contract.inputs).length === 0) continue;
|
|
14686
|
+
const bindAttr = extractAttributeValue(occ.attrsText, bindAttribute);
|
|
14687
|
+
checkBindings(occ.tagName, contract, bindAttr.value, occ.attrsStart + bindAttr.valueOffsetInAttrs, false, getPaths, diagnostics, msgs);
|
|
14454
14688
|
}
|
|
14455
14689
|
}
|
|
14456
14690
|
return diagnostics;
|
|
14457
14691
|
}
|
|
14692
|
+
function checkBindings(tagName, contract, value, valueStart, hasManual, getPaths, diagnostics, msgs) {
|
|
14693
|
+
let exprOffset = 0;
|
|
14694
|
+
for (const expr of splitBindingExpressions(value)) {
|
|
14695
|
+
const exprStart = valueStart + exprOffset;
|
|
14696
|
+
exprOffset += expr.length + 1;
|
|
14697
|
+
const parsed = parseBindingExpression(expr);
|
|
14698
|
+
const property = parsed.property;
|
|
14699
|
+
if (!property) continue;
|
|
14700
|
+
const propIndex = expr.indexOf(property);
|
|
14701
|
+
const start = propIndex === -1 ? exprStart : exprStart + propIndex;
|
|
14702
|
+
const end = propIndex === -1 ? exprStart + expr.length : start + property.length;
|
|
14703
|
+
validateBindingAgainstContract(tagName, contract, parsed, property, start, end, hasManual, getPaths, diagnostics, msgs);
|
|
14704
|
+
}
|
|
14705
|
+
}
|
|
14458
14706
|
function validateBindingAgainstContract(tagName, contract, parsed, property, start, end, hasManual, getPaths, diagnostics, msgs) {
|
|
14459
14707
|
const hashIndex = property.indexOf("#");
|
|
14460
14708
|
const modifiers = hashIndex === -1 ? "" : property.slice(hashIndex + 1);
|
|
@@ -14513,6 +14761,7 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
|
|
|
14513
14761
|
}
|
|
14514
14762
|
return;
|
|
14515
14763
|
}
|
|
14764
|
+
if (!tagName.startsWith("wcs-") && property.includes(".")) return;
|
|
14516
14765
|
if (!contract.properties.includes(property) && !(property in contract.inputs) && !HTML_SINK_PROPERTIES.has(property)) {
|
|
14517
14766
|
const members = [...contract.properties, ...inputNames];
|
|
14518
14767
|
diagnostics.push({
|
|
@@ -14526,7 +14775,7 @@ function validateBindingAgainstContract(tagName, contract, parsed, property, sta
|
|
|
14526
14775
|
});
|
|
14527
14776
|
return;
|
|
14528
14777
|
}
|
|
14529
|
-
if (property === "trigger" && "trigger" in contract.inputs && parsed.path) {
|
|
14778
|
+
if (tagName.startsWith("wcs-") && property === "trigger" && "trigger" in contract.inputs && parsed.path) {
|
|
14530
14779
|
const cand = findDataSlot(getPaths(), parsed.path);
|
|
14531
14780
|
if (cand?.rawInitial === "true") {
|
|
14532
14781
|
diagnostics.push({
|
|
@@ -14603,6 +14852,17 @@ function findBuiltinTagOccurrences(html) {
|
|
|
14603
14852
|
}
|
|
14604
14853
|
return out;
|
|
14605
14854
|
}
|
|
14855
|
+
function findPageTagOccurrences(html, bindAttribute) {
|
|
14856
|
+
const out = [];
|
|
14857
|
+
for (const region of findStartTagRegions(html)) {
|
|
14858
|
+
const tagName = region.tagName;
|
|
14859
|
+
if (!tagName.includes("-") || tagName.startsWith("wcs-")) continue;
|
|
14860
|
+
const attrsText = html.slice(region.start, region.end);
|
|
14861
|
+
if (extractAttributeValue(attrsText, bindAttribute) === null) continue;
|
|
14862
|
+
out.push({ tagName, tagStart: region.start - tagName.length - 1, attrsText, attrsStart: region.start });
|
|
14863
|
+
}
|
|
14864
|
+
return out;
|
|
14865
|
+
}
|
|
14606
14866
|
function extractAttributeValue(attrsText, attrName) {
|
|
14607
14867
|
const escaped = attrName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14608
14868
|
const regex = new RegExp(`(?:^|\\s)${escaped}\\s*=\\s*(["'])`, "i");
|
|
@@ -15048,7 +15308,7 @@ function validateWatchDeclarations(html, stateTagName = "wcs-state", locale2, fi
|
|
|
15048
15308
|
const scopes = {
|
|
15049
15309
|
mounts: volumes?.scopes.mounts ?? [],
|
|
15050
15310
|
unresolvedMounts: volumes?.scopes.unresolvedMounts ?? NO_MOUNTS,
|
|
15051
|
-
rootUnresolved:
|
|
15311
|
+
rootUnresolved: !scriptReadable(block.content, own2)
|
|
15052
15312
|
};
|
|
15053
15313
|
for (const entry of entries) {
|
|
15054
15314
|
const diagnostic = validateEntry(entry, pathSet, paths, scopes, msgs);
|
|
@@ -15069,10 +15329,10 @@ var NO_MOUNTS = /* @__PURE__ */ new Set();
|
|
|
15069
15329
|
function assignVolumes(elements, html) {
|
|
15070
15330
|
const chainOf = createTemplateChain(html);
|
|
15071
15331
|
const innermost = (chain) => chain.length > 0 ? chain[chain.length - 1] : -1;
|
|
15072
|
-
const
|
|
15332
|
+
const treeOf2 = (root) => innermost(chainOf(root.tagStart));
|
|
15073
15333
|
const rootTrees = /* @__PURE__ */ new Set();
|
|
15074
15334
|
for (const element2 of elements) {
|
|
15075
|
-
if (element2.mountPath === null && !element2.bindComponent) rootTrees.add(
|
|
15335
|
+
if (element2.mountPath === null && !element2.bindComponent) rootTrees.add(treeOf2(element2));
|
|
15076
15336
|
}
|
|
15077
15337
|
const volumes = /* @__PURE__ */ new Map();
|
|
15078
15338
|
for (const element2 of elements) {
|
|
@@ -15089,7 +15349,7 @@ function assignVolumes(elements, html) {
|
|
|
15089
15349
|
if (list === void 0) volumes.set(tree, [element2]);
|
|
15090
15350
|
else list.push(element2);
|
|
15091
15351
|
}
|
|
15092
|
-
return { treeOf, volumes };
|
|
15352
|
+
return { treeOf: treeOf2, volumes };
|
|
15093
15353
|
}
|
|
15094
15354
|
function validateEntry(entry, pathSet, paths, scopes, msgs) {
|
|
15095
15355
|
const { key } = entry;
|
|
@@ -16077,8 +16337,8 @@ function validateVolumeBlock2(block, mountPath, msgs, out) {
|
|
|
16077
16337
|
}
|
|
16078
16338
|
function validateBindComponentSource(html, tagStart, tagEnd, hasInlineScript, msgs, out) {
|
|
16079
16339
|
const tag = html.slice(tagStart, tagEnd);
|
|
16080
|
-
const
|
|
16081
|
-
const sources = BIND_COMPONENT_SOURCE_ATTRIBUTES.filter((name) =>
|
|
16340
|
+
const names2 = parseAttributeNames(tag);
|
|
16341
|
+
const sources = BIND_COMPONENT_SOURCE_ATTRIBUTES.filter((name) => names2.has(name));
|
|
16082
16342
|
if (hasInlineScript) sources.push('<script type="module">');
|
|
16083
16343
|
if (sources.length === 0) return;
|
|
16084
16344
|
const prop = /\sbind-component\s*=\s*(?:"([^"]*)"|'([^']*)'|([^\s"'<>`=]+))/i.exec(tag);
|
|
@@ -16206,7 +16466,7 @@ var OLD_DECLARATION_KEY = /(^|[{,;\s])(\$streams|\$updatedCallback)(?=\s*(?:[:(]
|
|
|
16206
16466
|
function collectDeclarationAliasReads(script) {
|
|
16207
16467
|
return collectStateThisReads(script, OLD_DECLARATION_MEMBER_NAMES);
|
|
16208
16468
|
}
|
|
16209
|
-
function collectStateThisReads(script,
|
|
16469
|
+
function collectStateThisReads(script, names2) {
|
|
16210
16470
|
if (!hasDefaultExportObject(script)) return null;
|
|
16211
16471
|
const out = [];
|
|
16212
16472
|
const take = (refs, base) => {
|
|
@@ -16215,10 +16475,10 @@ function collectStateThisReads(script, names) {
|
|
|
16215
16475
|
return true;
|
|
16216
16476
|
};
|
|
16217
16477
|
for (const callable of analyzeCallableBodies(script)) {
|
|
16218
|
-
if (!take(collectThisMemberRefs(callable.body,
|
|
16478
|
+
if (!take(collectThisMemberRefs(callable.body, names2), callable.bodyStart)) return null;
|
|
16219
16479
|
}
|
|
16220
16480
|
for (const handler of analyzeWatchHandlerSources(script)) {
|
|
16221
|
-
const refs = handler.kind === "body" ? collectThisMemberRefs(handler.text,
|
|
16481
|
+
const refs = handler.kind === "body" ? collectThisMemberRefs(handler.text, names2) : collectThisMemberRefsInValue(handler.text, names2);
|
|
16222
16482
|
if (!take(refs, handler.start)) return null;
|
|
16223
16483
|
}
|
|
16224
16484
|
out.sort((a, b) => a.start - b.start);
|
|
@@ -16426,6 +16686,26 @@ function validateGetterLocationReads(script, scriptStart, locale2) {
|
|
|
16426
16686
|
}
|
|
16427
16687
|
return out;
|
|
16428
16688
|
}
|
|
16689
|
+
var CLOCK_READ = /\bDate\s*\.\s*now\s*\(|\bnew\s+Date\s*\(\s*\)|\bperformance\s*\.\s*now\s*\(/;
|
|
16690
|
+
function validateGetterClockReads(script, scriptStart, locale2) {
|
|
16691
|
+
if (!/Date|performance/.test(script)) return [];
|
|
16692
|
+
const msgs = getMessages(locale2);
|
|
16693
|
+
const out = [];
|
|
16694
|
+
for (const getter of analyzeCallableBodies(script)) {
|
|
16695
|
+
if (getter.kind !== "getter" || getter.accessor !== "get") continue;
|
|
16696
|
+
const read = CLOCK_READ.exec(maskCommentsAndStrings(getter.body));
|
|
16697
|
+
if (read === null) continue;
|
|
16698
|
+
const text3 = read[0].startsWith("new") ? "new Date()" : read[0].startsWith("performance") ? "performance.now()" : "Date.now()";
|
|
16699
|
+
out.push({
|
|
16700
|
+
code: WcsDiagnosticCode.GetterUntrackedRead,
|
|
16701
|
+
start: scriptStart + getter.bodyStart + read.index,
|
|
16702
|
+
end: scriptStart + getter.bodyStart + read.index + read[0].length,
|
|
16703
|
+
message: msgs.getterReadsClock(text3),
|
|
16704
|
+
severity: "warning"
|
|
16705
|
+
});
|
|
16706
|
+
}
|
|
16707
|
+
return out;
|
|
16708
|
+
}
|
|
16429
16709
|
function onHandlerStateParam(script, handler) {
|
|
16430
16710
|
if (handler.kind === "body") {
|
|
16431
16711
|
const head = script.slice(Math.max(0, handler.start - 400), handler.start);
|
|
@@ -16623,15 +16903,22 @@ function validateUpdatedCallbackDemand(html, stateTagName, bindAttrName, locale2
|
|
|
16623
16903
|
const reported = /* @__PURE__ */ new Set();
|
|
16624
16904
|
while ((match = PATH_TEST_LITERAL.exec(body)) !== null) {
|
|
16625
16905
|
const path = match[2];
|
|
16626
|
-
if (path.length === 0 ||
|
|
16627
|
-
|
|
16906
|
+
if (path.length === 0 || bound.has(path) || reported.has(path)) continue;
|
|
16907
|
+
let message;
|
|
16908
|
+
if (declared.has(path)) {
|
|
16909
|
+
message = msgs.updatedCallbackUnbound(path);
|
|
16910
|
+
} else {
|
|
16911
|
+
const near = suggestion(path, [...declared, ...bound], msgs);
|
|
16912
|
+
if (near === "") continue;
|
|
16913
|
+
message = msgs.updatedCallbackUnknownPath(path) + near;
|
|
16914
|
+
}
|
|
16628
16915
|
reported.add(path);
|
|
16629
16916
|
const quoteAt = match.index + match[0].length - path.length - 1;
|
|
16630
16917
|
out.push({
|
|
16631
16918
|
code: WcsDiagnosticCode.UpdatedCallbackUnbound,
|
|
16632
16919
|
start: block.contentStart + callback.bodyStart + quoteAt,
|
|
16633
16920
|
end: block.contentStart + callback.bodyStart + quoteAt + path.length,
|
|
16634
|
-
message
|
|
16921
|
+
message,
|
|
16635
16922
|
severity: "warning"
|
|
16636
16923
|
});
|
|
16637
16924
|
}
|
|
@@ -16644,8 +16931,8 @@ function collectBoundPaths(html, stateTagName, bindAttrName) {
|
|
|
16644
16931
|
for (const occurrence of index.occurrences) {
|
|
16645
16932
|
bound.add(occurrence.path);
|
|
16646
16933
|
if (!occurrence.path.startsWith(".")) continue;
|
|
16647
|
-
const forPath =
|
|
16648
|
-
if (forPath === null
|
|
16934
|
+
const forPath = getResolvedForListPath(html, occurrence.pathRange.start, bindAttrName);
|
|
16935
|
+
if (forPath === null) continue;
|
|
16649
16936
|
bound.add(
|
|
16650
16937
|
occurrence.path === "." ? `${forPath}.*` : `${forPath}.*.${occurrence.path.slice(1)}`
|
|
16651
16938
|
);
|
|
@@ -16718,6 +17005,7 @@ function validateSemantics(html, stateTagName = "wcs-state", locale2, bindAttrNa
|
|
|
16718
17005
|
out.push(...validateGetterCycles(block.content, block.contentStart, locale2));
|
|
16719
17006
|
out.push(...validateGetterUntrackedReads(block.content, block.contentStart, getNestedWriteRoots, locale2));
|
|
16720
17007
|
out.push(...validateGetterLocationReads(block.content, block.contentStart, locale2));
|
|
17008
|
+
out.push(...validateGetterClockReads(block.content, block.contentStart, locale2));
|
|
16721
17009
|
out.push(...validateOnHandlerThis(block.content, block.contentStart, locale2));
|
|
16722
17010
|
out.push(...validateInPlaceChanges(block.content, block.contentStart, locale2));
|
|
16723
17011
|
}
|
|
@@ -16726,6 +17014,169 @@ function validateSemantics(html, stateTagName = "wcs-state", locale2, bindAttrNa
|
|
|
16726
17014
|
return out;
|
|
16727
17015
|
}
|
|
16728
17016
|
|
|
17017
|
+
// src/service/scriptStateUseValidator.ts
|
|
17018
|
+
var COMMAND_USE = /\.\s*\$command\s*\.\s*([A-Za-z_$][\w$]*)/dg;
|
|
17019
|
+
var EMIT_AFTER = /^\s*\.\s*emit\s*\(/;
|
|
17020
|
+
var THIS_WRITE = /\bthis\s*\.\s*([A-Za-z_][\w$]*)\s*(?:=(?![=>])|[-+*/%&|^]=|\*\*=|<<=|>>>?=|&&=|\|\|=|\?\?=|\+\+|--)/dg;
|
|
17021
|
+
var PRE_THIS_WRITE = /(?:\+\+|--)\s*this\s*\.\s*([A-Za-z_][\w$]*)/dg;
|
|
17022
|
+
function validateScriptStateUses(html, stateTagName = "wcs-state", locale2, bindAttrName = "data-wcs") {
|
|
17023
|
+
const blocks = parseLoadedScriptBlocks(html, stateTagName).filter((block) => isReadableStateScript(block.content));
|
|
17024
|
+
if (blocks.length === 0) return [];
|
|
17025
|
+
const msgs = getMessages(locale2);
|
|
17026
|
+
const out = [];
|
|
17027
|
+
let receivers = null;
|
|
17028
|
+
let markupEmits = null;
|
|
17029
|
+
const bindings = () => {
|
|
17030
|
+
if (receivers !== null) return;
|
|
17031
|
+
receivers = /* @__PURE__ */ new Set();
|
|
17032
|
+
markupEmits = /* @__PURE__ */ new Map();
|
|
17033
|
+
for (const o of buildReferenceIndex(html, { bindAttribute: bindAttrName, stateTagName }).occurrences) {
|
|
17034
|
+
if (!o.path.startsWith("$command.")) continue;
|
|
17035
|
+
const name = o.path.slice("$command.".length);
|
|
17036
|
+
const prop = o.propName ?? "";
|
|
17037
|
+
if (prop.startsWith("command.")) receivers.add(name);
|
|
17038
|
+
else if (prop.startsWith("on") && !markupEmits.has(name)) markupEmits.set(name, o.pathRange);
|
|
17039
|
+
}
|
|
17040
|
+
};
|
|
17041
|
+
for (const block of blocks) {
|
|
17042
|
+
const paths = analyzeStatePaths(block.content);
|
|
17043
|
+
const masked = maskCommentsAndStrings(block.content);
|
|
17044
|
+
const declared = paths.filter((p) => p.kind === "command").map((p) => p.path.slice("$command.".length));
|
|
17045
|
+
if (block.mountPath === null && declared.length > 0) {
|
|
17046
|
+
const emitted = /* @__PURE__ */ new Map();
|
|
17047
|
+
COMMAND_USE.lastIndex = 0;
|
|
17048
|
+
let match;
|
|
17049
|
+
while ((match = COMMAND_USE.exec(masked)) !== null) {
|
|
17050
|
+
const name = match[1];
|
|
17051
|
+
const [start, end] = match.indices[1];
|
|
17052
|
+
if (!declared.includes(name)) {
|
|
17053
|
+
out.push({
|
|
17054
|
+
code: WcsDiagnosticCode.TokenUndeclared,
|
|
17055
|
+
start: block.contentStart + start,
|
|
17056
|
+
end: block.contentStart + end,
|
|
17057
|
+
// `$command` holds the declared tokens only: `.emit()` on what it lacks is a TypeError
|
|
17058
|
+
message: msgs.commandTokenUndeclared(`$command.${name}`) + suggestion(name, declared, msgs),
|
|
17059
|
+
severity: "error"
|
|
17060
|
+
});
|
|
17061
|
+
} else if (!emitted.has(name) && EMIT_AFTER.test(masked.slice(match.index + match[0].length))) {
|
|
17062
|
+
emitted.set(name, { start: block.contentStart + start, end: block.contentStart + end });
|
|
17063
|
+
}
|
|
17064
|
+
}
|
|
17065
|
+
bindings();
|
|
17066
|
+
for (const name of declared) {
|
|
17067
|
+
if (receivers.has(name)) continue;
|
|
17068
|
+
const at2 = emitted.get(name) ?? markupEmits.get(name);
|
|
17069
|
+
if (at2 === void 0) continue;
|
|
17070
|
+
out.push({
|
|
17071
|
+
code: WcsDiagnosticCode.CommandTokenUnbound,
|
|
17072
|
+
start: at2.start,
|
|
17073
|
+
end: at2.end,
|
|
17074
|
+
message: msgs.commandTokenUnbound(`$command.${name}`),
|
|
17075
|
+
severity: "warning"
|
|
17076
|
+
});
|
|
17077
|
+
}
|
|
17078
|
+
}
|
|
17079
|
+
const keys = [...new Set(paths.map((p) => p.path.split(".")[0]).filter((key) => key !== "" && !key.startsWith("$")))];
|
|
17080
|
+
const reported = /* @__PURE__ */ new Set();
|
|
17081
|
+
for (const pattern of [THIS_WRITE, PRE_THIS_WRITE]) {
|
|
17082
|
+
pattern.lastIndex = 0;
|
|
17083
|
+
let match;
|
|
17084
|
+
while ((match = pattern.exec(masked)) !== null) {
|
|
17085
|
+
const key = match[1];
|
|
17086
|
+
if (keys.includes(key) || reported.has(key)) continue;
|
|
17087
|
+
const near = suggestion(key, keys, msgs);
|
|
17088
|
+
if (near === "") continue;
|
|
17089
|
+
reported.add(key);
|
|
17090
|
+
const [start, end] = match.indices[1];
|
|
17091
|
+
out.push({
|
|
17092
|
+
code: WcsDiagnosticCode.WritePathMissing,
|
|
17093
|
+
start: block.contentStart + start,
|
|
17094
|
+
end: block.contentStart + end,
|
|
17095
|
+
message: msgs.writePathMissing(key) + near,
|
|
17096
|
+
severity: "warning"
|
|
17097
|
+
});
|
|
17098
|
+
}
|
|
17099
|
+
}
|
|
17100
|
+
}
|
|
17101
|
+
return out;
|
|
17102
|
+
}
|
|
17103
|
+
|
|
17104
|
+
// src/service/scriptReadValidator.ts
|
|
17105
|
+
function validateScriptReads(html, stateTagName = "wcs-state", locale2, fileReader, applicationSchema) {
|
|
17106
|
+
const blocks = parseLoadedScriptBlocks(html, stateTagName);
|
|
17107
|
+
if (blocks.length === 0) return [];
|
|
17108
|
+
const msgs = getMessages(locale2);
|
|
17109
|
+
const index = getStatePathIndex(html, stateTagName, fileReader);
|
|
17110
|
+
const candidates = mergeSchemaCandidates(index.paths, applicationSchema);
|
|
17111
|
+
const candidateSet = new Set(candidates.map((p) => p.path));
|
|
17112
|
+
let tree = null;
|
|
17113
|
+
const out = [];
|
|
17114
|
+
for (const block of blocks) {
|
|
17115
|
+
const spread = applicationSchema === void 0 ? findTopLevelSpread(block.content) : null;
|
|
17116
|
+
if (spread !== null) {
|
|
17117
|
+
out.push({
|
|
17118
|
+
code: WcsDiagnosticCode.PathDynamicUnknown,
|
|
17119
|
+
start: block.contentStart + spread.start,
|
|
17120
|
+
end: block.contentStart + spread.end,
|
|
17121
|
+
message: msgs.pathDynamicUnknownSpread(block.content.slice(spread.start, spread.end)),
|
|
17122
|
+
severity: "info"
|
|
17123
|
+
});
|
|
17124
|
+
}
|
|
17125
|
+
const prefix = block.mountPath === null || block.mountPath === "" ? "" : `${block.mountPath}.`;
|
|
17126
|
+
for (const callable of analyzeCallableBodies(block.content)) {
|
|
17127
|
+
for (const read of collectGetterReads(callable.body) ?? []) {
|
|
17128
|
+
if (read.written || read.path.split(".").some((s) => s === "" || s.startsWith("$")) || hasRecursionWildcard(read.path)) continue;
|
|
17129
|
+
const path = prefix + read.path;
|
|
17130
|
+
if (pathExistsInCandidates(path, candidates, candidateSet)) continue;
|
|
17131
|
+
if (applicationSchema !== void 0 ? resolveIndexedSchemaPath(applicationSchema, path).kind !== "nonexistent" : isUnresolvedPath(path, index.scopes)) continue;
|
|
17132
|
+
const near = nearName(path, tree ??= treeOf(candidates));
|
|
17133
|
+
if (near === null) continue;
|
|
17134
|
+
const said = suggestion(near.segment, near.names, msgs);
|
|
17135
|
+
if (said === "") continue;
|
|
17136
|
+
const at2 = block.contentStart + callable.bodyStart;
|
|
17137
|
+
out.push({
|
|
17138
|
+
code: WcsDiagnosticCode.ReadPathMissing,
|
|
17139
|
+
start: at2 + read.start,
|
|
17140
|
+
end: read.form === "member" ? at2 + read.start + statePart(callable.body.slice(read.start, read.end)) : at2 + read.end,
|
|
17141
|
+
message: msgs.readPathMissing(read.path, !read.path.includes(".")) + said,
|
|
17142
|
+
// a stateSchema says the path is not there, as for a binding's `wcs/path-nonexistent`
|
|
17143
|
+
severity: applicationSchema !== void 0 ? "error" : "warning"
|
|
17144
|
+
});
|
|
17145
|
+
}
|
|
17146
|
+
}
|
|
17147
|
+
}
|
|
17148
|
+
return out;
|
|
17149
|
+
}
|
|
17150
|
+
var THIS_PART = /^this\s*(?:\?\.\s*|\.\s*)(?:[A-Za-z_$][\w$]*)|^this\s*(?:\?\.)?\s*\[\s*(["'`])[^"'`]*\1\s*\]/;
|
|
17151
|
+
function statePart(text3) {
|
|
17152
|
+
return THIS_PART.exec(text3)?.[0].length ?? text3.length;
|
|
17153
|
+
}
|
|
17154
|
+
function treeOf(candidates) {
|
|
17155
|
+
const tree = /* @__PURE__ */ new Map();
|
|
17156
|
+
for (const c of candidates) {
|
|
17157
|
+
let parent = "";
|
|
17158
|
+
for (const segment of c.path.split(".")) {
|
|
17159
|
+
let names2 = tree.get(parent);
|
|
17160
|
+
if (names2 === void 0) tree.set(parent, names2 = /* @__PURE__ */ new Set());
|
|
17161
|
+
names2.add(segment);
|
|
17162
|
+
parent = parent === "" ? segment : `${parent}.${segment}`;
|
|
17163
|
+
}
|
|
17164
|
+
}
|
|
17165
|
+
return tree;
|
|
17166
|
+
}
|
|
17167
|
+
function nearName(path, tree) {
|
|
17168
|
+
let parent = "";
|
|
17169
|
+
for (const segment of (hasIndexSegment(path) ? toWildcardForm(path) : path).split(".")) {
|
|
17170
|
+
const names2 = tree.get(parent);
|
|
17171
|
+
if (names2?.has(segment)) {
|
|
17172
|
+
parent = parent === "" ? segment : `${parent}.${segment}`;
|
|
17173
|
+
continue;
|
|
17174
|
+
}
|
|
17175
|
+
return { segment, names: [...names2 ?? []].filter((name) => name !== "*" && !name.startsWith("$")) };
|
|
17176
|
+
}
|
|
17177
|
+
return null;
|
|
17178
|
+
}
|
|
17179
|
+
|
|
16729
17180
|
// src/core/sidecar/discover.ts
|
|
16730
17181
|
var APPLICATION_MANIFEST_FILENAME = "wcstack.manifest.json";
|
|
16731
17182
|
var MAX_ASCEND = 16;
|
|
@@ -16750,13 +17201,129 @@ function applicationSchemaOf(loaded) {
|
|
|
16750
17201
|
return void 0;
|
|
16751
17202
|
}
|
|
16752
17203
|
|
|
17204
|
+
// src/core/offsetToPosition.ts
|
|
17205
|
+
function createPositionMapper(text3) {
|
|
17206
|
+
const lineStarts = [0];
|
|
17207
|
+
for (let i = 0; i < text3.length; i++) {
|
|
17208
|
+
const c = text3.charCodeAt(i);
|
|
17209
|
+
if (c === 10) {
|
|
17210
|
+
lineStarts.push(i + 1);
|
|
17211
|
+
} else if (c === 13) {
|
|
17212
|
+
if (text3.charCodeAt(i + 1) === 10) i++;
|
|
17213
|
+
lineStarts.push(i + 1);
|
|
17214
|
+
}
|
|
17215
|
+
}
|
|
17216
|
+
return (offset2) => {
|
|
17217
|
+
const clamped = Math.max(0, Math.min(offset2, text3.length));
|
|
17218
|
+
let lo = 0;
|
|
17219
|
+
let hi = lineStarts.length - 1;
|
|
17220
|
+
while (lo < hi) {
|
|
17221
|
+
const mid = lo + hi + 1 >> 1;
|
|
17222
|
+
if (lineStarts[mid] <= clamped) lo = mid;
|
|
17223
|
+
else hi = mid - 1;
|
|
17224
|
+
}
|
|
17225
|
+
return { line: lo + 1, column: clamped - lineStarts[lo] + 1 };
|
|
17226
|
+
};
|
|
17227
|
+
}
|
|
17228
|
+
|
|
17229
|
+
// src/core/externalState.ts
|
|
17230
|
+
var OPEN = '<script type="module">';
|
|
17231
|
+
var CLOSE = "</script>";
|
|
17232
|
+
function inlineExternalStates(html, stateTagName, fileReader) {
|
|
17233
|
+
let text3 = "";
|
|
17234
|
+
let from = 0;
|
|
17235
|
+
let shift = 0;
|
|
17236
|
+
const states = [];
|
|
17237
|
+
for (const element2 of parseWcsStateElements(html, stateTagName)) {
|
|
17238
|
+
const src = element2.srcSpan;
|
|
17239
|
+
if (src === void 0 || element2.srcAttr === void 0 || element2.stateAttr !== void 0 || element2.bindComponent) continue;
|
|
17240
|
+
const file = readStateScriptFile(element2.srcAttr, fileReader);
|
|
17241
|
+
if (file === void 0) continue;
|
|
17242
|
+
const blanks = [src];
|
|
17243
|
+
if (element2.jsonSpan !== void 0) blanks.push(element2.jsonSpan);
|
|
17244
|
+
blanks.sort((a, b) => a.start - b.start);
|
|
17245
|
+
for (const span of blanks) {
|
|
17246
|
+
text3 += html.slice(from, span.start) + " ".repeat(span.end - span.start);
|
|
17247
|
+
from = span.end;
|
|
17248
|
+
}
|
|
17249
|
+
text3 += html.slice(from, element2.tagEnd);
|
|
17250
|
+
from = element2.tagEnd;
|
|
17251
|
+
const content = file.text.replace(/<\/(script)/gi, "<\\$1");
|
|
17252
|
+
const at2 = element2.tagEnd + shift;
|
|
17253
|
+
const length = OPEN.length + content.length + CLOSE.length;
|
|
17254
|
+
text3 += OPEN + content + CLOSE;
|
|
17255
|
+
states.push({
|
|
17256
|
+
path: file.path,
|
|
17257
|
+
text: file.text,
|
|
17258
|
+
at: at2,
|
|
17259
|
+
contentAt: at2 + OPEN.length,
|
|
17260
|
+
length,
|
|
17261
|
+
valueStart: src.valueStart,
|
|
17262
|
+
valueEnd: src.valueEnd,
|
|
17263
|
+
position: createPositionMapper(file.text)
|
|
17264
|
+
});
|
|
17265
|
+
shift += length;
|
|
17266
|
+
}
|
|
17267
|
+
if (states.length === 0) return null;
|
|
17268
|
+
return { text: text3 + html.slice(from), states };
|
|
17269
|
+
}
|
|
17270
|
+
function locateInlined(page, offset2) {
|
|
17271
|
+
let shift = 0;
|
|
17272
|
+
for (const state of page.states) {
|
|
17273
|
+
if (offset2 < state.at) break;
|
|
17274
|
+
if (offset2 < state.at + state.length) {
|
|
17275
|
+
return { state, offset: Math.min(Math.max(offset2 - state.contentAt, 0), state.text.length) };
|
|
17276
|
+
}
|
|
17277
|
+
shift += state.length;
|
|
17278
|
+
}
|
|
17279
|
+
return { offset: offset2 - shift };
|
|
17280
|
+
}
|
|
17281
|
+
|
|
16753
17282
|
// src/core/validateDocument.ts
|
|
16754
17283
|
function validateDocument(text3, options = {}) {
|
|
17284
|
+
const stateTagName = options.stateTagName ?? "wcs-state";
|
|
17285
|
+
const fileReader = options.fileReader;
|
|
17286
|
+
const applicationSchema = options.applicationSchema ?? (fileReader !== void 0 ? discoverApplicationManifest(fileReader)?.schema : void 0);
|
|
17287
|
+
const found = validateText(text3, options, applicationSchema);
|
|
17288
|
+
const page = fileReader === void 0 ? null : inlineExternalStates(text3, stateTagName, fileReader);
|
|
17289
|
+
if (page === null) return found;
|
|
17290
|
+
const key = (d) => [d.code, d.start, d.end, d.message, d.origin?.path, d.origin?.start].join("\0");
|
|
17291
|
+
const seen2 = new Set(found.map(key));
|
|
17292
|
+
const out = [...found];
|
|
17293
|
+
for (const d of validateText(page.text, options, applicationSchema)) {
|
|
17294
|
+
const start = locateInlined(page, d.start);
|
|
17295
|
+
const end = locateInlined(page, d.end);
|
|
17296
|
+
let mapped;
|
|
17297
|
+
if (start.state !== void 0) {
|
|
17298
|
+
const state = start.state;
|
|
17299
|
+
const fileEnd = end.state === state ? Math.max(end.offset, start.offset) : start.offset;
|
|
17300
|
+
mapped = {
|
|
17301
|
+
...d,
|
|
17302
|
+
start: state.valueStart,
|
|
17303
|
+
end: state.valueEnd,
|
|
17304
|
+
origin: {
|
|
17305
|
+
path: state.path,
|
|
17306
|
+
start: start.offset,
|
|
17307
|
+
end: fileEnd,
|
|
17308
|
+
startPosition: state.position(start.offset),
|
|
17309
|
+
endPosition: state.position(fileEnd)
|
|
17310
|
+
}
|
|
17311
|
+
};
|
|
17312
|
+
} else {
|
|
17313
|
+
mapped = { ...d, start: start.offset, end: end.state === void 0 ? Math.max(end.offset, start.offset) : start.offset };
|
|
17314
|
+
}
|
|
17315
|
+
const k = key(mapped);
|
|
17316
|
+
if (seen2.has(k)) continue;
|
|
17317
|
+
seen2.add(k);
|
|
17318
|
+
out.push(mapped);
|
|
17319
|
+
}
|
|
17320
|
+
return sortDiagnostics(out);
|
|
17321
|
+
}
|
|
17322
|
+
function validateText(text3, options, applicationSchema) {
|
|
16755
17323
|
const bindAttribute = options.bindAttribute ?? "data-wcs";
|
|
16756
17324
|
const stateTagName = options.stateTagName ?? "wcs-state";
|
|
16757
17325
|
const locale2 = options.locale;
|
|
16758
17326
|
const fileReader = options.fileReader;
|
|
16759
|
-
const applicationSchema = options.applicationSchema ?? (fileReader !== void 0 ? discoverApplicationManifest(fileReader)?.schema : void 0);
|
|
16760
17327
|
const out = [];
|
|
16761
17328
|
out.push(...validateBindings(text3, bindAttribute, stateTagName, locale2, fileReader, applicationSchema));
|
|
16762
17329
|
out.push(...validateTemplateSyntax(text3, stateTagName, bindAttribute, locale2, fileReader, applicationSchema));
|
|
@@ -16765,6 +17332,8 @@ function validateDocument(text3, options = {}) {
|
|
|
16765
17332
|
out.push(...validateAriaAttributes(text3, bindAttribute, locale2));
|
|
16766
17333
|
out.push(...validateDocumentEnv(text3, locale2));
|
|
16767
17334
|
out.push(...validateSemantics(text3, stateTagName, locale2, bindAttribute));
|
|
17335
|
+
out.push(...validateScriptStateUses(text3, stateTagName, locale2, bindAttribute));
|
|
17336
|
+
out.push(...validateScriptReads(text3, stateTagName, locale2, fileReader, applicationSchema));
|
|
16768
17337
|
out.push(...validateArrayMutations(text3, stateTagName, locale2));
|
|
16769
17338
|
out.push(...validateWatchDeclarations(text3, stateTagName, locale2, fileReader));
|
|
16770
17339
|
out.push(...validateScanDeclarations(text3, stateTagName, locale2));
|