tutuca 0.9.32 → 0.9.33

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.
@@ -734,9 +734,11 @@ class ValParser {
734
734
  const charCode = s.charCodeAt(0);
735
735
  switch (charCode) {
736
736
  case 94: {
737
- const newS = px.frame.macroVars?.[s.slice(1)];
737
+ const name = s.slice(1);
738
+ const newS = px.frame.macroVars?.[name];
738
739
  if (newS !== undefined)
739
740
  return this.parse(newS, px);
741
+ px.onParseIssue("bad-value", { role: "macro-var", name, value: s });
740
742
  return null;
741
743
  }
742
744
  case 39:
@@ -1057,6 +1059,8 @@ class AttrParser {
1057
1059
  this.attrs ??= [];
1058
1060
  this.attrs.push(new Attr(name, val));
1059
1061
  this.hasDynamic ||= !(val instanceof ConstVal);
1062
+ } else {
1063
+ this.px.onParseIssue("bad-value", { role: "attr", attr: name, value });
1060
1064
  }
1061
1065
  }
1062
1066
  pushWrapper(name, raw, val) {
@@ -1072,6 +1076,9 @@ class AttrParser {
1072
1076
  this.attrs ??= [];
1073
1077
  this.attrs.push(this.ifAttr);
1074
1078
  this.hasDynamic = true;
1079
+ } else {
1080
+ const info = { role: "if", attr: directiveName.slice(3), value };
1081
+ this.px.onParseIssue("bad-value", info);
1075
1082
  }
1076
1083
  }
1077
1084
  parseThen(s) {
@@ -1094,36 +1101,44 @@ class AttrParser {
1094
1101
  this.events.add(eventName, handler, modifiers);
1095
1102
  }
1096
1103
  }
1104
+ _parseDirectiveValue(directiveName, s, parserFn) {
1105
+ const val = parserFn.call(vp, s, this.px);
1106
+ if (val === null) {
1107
+ const info = { role: "directive", directive: directiveName, value: s };
1108
+ this.px.onParseIssue("bad-value", info);
1109
+ }
1110
+ return val;
1111
+ }
1097
1112
  parseDirective(s, directiveName) {
1098
1113
  switch (directiveName) {
1099
1114
  case "dangerouslysetinnerhtml":
1100
1115
  this.attrs ??= [];
1101
- this.attrs.push(new RawHtmlAttr(vp.parseText(s, this.px)));
1116
+ this.attrs.push(new RawHtmlAttr(this._parseDirectiveValue(directiveName, s, vp.parseText)));
1102
1117
  this.hasDynamic = true;
1103
1118
  return;
1104
1119
  case "slot":
1105
1120
  this.pushWrapper("slot", s, vp.const(s));
1106
1121
  return;
1107
1122
  case "push-view":
1108
- this.pushWrapper("push-view", s, vp.parseText(s, this.px));
1123
+ this.pushWrapper("push-view", s, this._parseDirectiveValue(directiveName, s, vp.parseText));
1109
1124
  return;
1110
1125
  case "text":
1111
- this.textChild = vp.parseText(s, this.px);
1126
+ this.textChild = this._parseDirectiveValue(directiveName, s, vp.parseText);
1112
1127
  return;
1113
1128
  case "show":
1114
- this.pushWrapper("show", s, vp.parseCondValue(s, this.px));
1129
+ this.pushWrapper("show", s, this._parseDirectiveValue(directiveName, s, vp.parseCondValue));
1115
1130
  return;
1116
1131
  case "hide":
1117
- this.pushWrapper("hide", s, vp.parseCondValue(s, this.px));
1132
+ this.pushWrapper("hide", s, this._parseDirectiveValue(directiveName, s, vp.parseCondValue));
1118
1133
  return;
1119
1134
  case "each":
1120
- this.eachAttr = this.pushWrapper("each", s, vp.parseEach(s, this.px));
1135
+ this.eachAttr = this.pushWrapper("each", s, this._parseDirectiveValue(directiveName, s, vp.parseEach));
1121
1136
  return;
1122
1137
  case "enrich-with":
1123
1138
  if (this.eachAttr !== null) {
1124
- this.eachAttr.enrichWithVal = vp.parseAlter(s, this.px);
1139
+ this.eachAttr.enrichWithVal = this._parseDirectiveValue(directiveName, s, vp.parseAlter);
1125
1140
  } else {
1126
- this.pushWrapper("scope", s, vp.parseAlter(s, this.px));
1141
+ this.pushWrapper("scope", s, this._parseDirectiveValue(directiveName, s, vp.parseAlter));
1127
1142
  }
1128
1143
  return;
1129
1144
  case "when":
@@ -1147,16 +1162,18 @@ class AttrParser {
1147
1162
  this.parseThen(s);
1148
1163
  else if (directiveName.startsWith("else."))
1149
1164
  this.parseElse(s);
1150
- else
1151
- this.px.onParseIssue("unknown-directive", { name: directiveName, value: s });
1165
+ else {
1166
+ const info = { name: directiveName, value: s };
1167
+ this.px.onParseIssue("unknown-directive", info);
1168
+ }
1152
1169
  }
1153
1170
  _parseWhen(s) {
1154
1171
  if (this.eachAttr !== null)
1155
- this.eachAttr.whenVal = vp.parseAlter(s, this.px);
1172
+ this.eachAttr.whenVal = this._parseDirectiveValue("when", s, vp.parseAlter);
1156
1173
  }
1157
1174
  _parseLoopWith(s) {
1158
1175
  if (this.eachAttr !== null)
1159
- this.eachAttr.loopWithVal = vp.parseAlter(s, this.px);
1176
+ this.eachAttr.loopWithVal = this._parseDirectiveValue("loop-with", s, vp.parseAlter);
1160
1177
  }
1161
1178
  parse(attributes, parseAll = false) {
1162
1179
  for (const { name, value } of attributes) {
@@ -1202,13 +1219,22 @@ class EventHandler {
1202
1219
  static parse(s, px) {
1203
1220
  const [handlerName, ...rawArgs] = s.trim().split(/\s+/);
1204
1221
  const handlerVal = vp.parseHandlerName(handlerName, px);
1205
- if (handlerVal === null)
1222
+ if (handlerVal === null) {
1223
+ const info = { role: "handler-name", value: handlerName };
1224
+ px.onParseIssue("bad-value", info);
1206
1225
  return null;
1226
+ }
1207
1227
  const args = new Array(rawArgs.length);
1208
1228
  vp.allowHandlerArg();
1209
1229
  for (let i = 0;i < rawArgs.length; i++) {
1210
1230
  const val = vp.parse(rawArgs[i], px);
1211
- args[i] = val !== null ? val : vp.nullConstVal;
1231
+ if (val !== null) {
1232
+ args[i] = val;
1233
+ } else {
1234
+ const info = { role: "handler-arg", value: rawArgs[i] };
1235
+ px.onParseIssue("bad-value", info);
1236
+ args[i] = vp.nullConstVal;
1237
+ }
1212
1238
  }
1213
1239
  return new EventHandler(handlerVal, args);
1214
1240
  }
@@ -1334,6 +1360,50 @@ function optimizeNode(node) {
1334
1360
  node.optimize();
1335
1361
  return node;
1336
1362
  }
1363
+ function parseXOp(attrs, childs, opIdx, px) {
1364
+ if (attrs.length === 0)
1365
+ return maybeFragment(childs);
1366
+ const { name, value } = attrs[opIdx];
1367
+ const as = attrs.getNamedItem("as")?.value ?? null;
1368
+ let node;
1369
+ switch (name) {
1370
+ case "slot":
1371
+ node = new SlotNode(null, vp.const(value), maybeFragment(childs));
1372
+ break;
1373
+ case "text":
1374
+ node = px.addNodeIf(RenderTextNode, parseXOpVal(name, value, px, vp.parseText));
1375
+ break;
1376
+ case "render":
1377
+ node = px.addNodeIf(RenderNode, parseXOpVal(name, value, px, vp.parseRender), as);
1378
+ break;
1379
+ case "render-it":
1380
+ node = px.addNodeIf(RenderItNode, vp.bindValIt, as);
1381
+ break;
1382
+ case "render-each":
1383
+ node = RenderEachNode.parse(px, vp, value, as, attrs);
1384
+ break;
1385
+ case "show": {
1386
+ const val = parseXOpVal(name, value, px, vp.parseCondValue);
1387
+ node = px.addNodeIf(ShowNode, val, maybeFragment(childs));
1388
+ break;
1389
+ }
1390
+ case "hide": {
1391
+ const val = parseXOpVal(name, value, px, vp.parseCondValue);
1392
+ node = px.addNodeIf(HideNode, val, maybeFragment(childs));
1393
+ break;
1394
+ }
1395
+ default:
1396
+ px.onParseIssue("unknown-x-op", { name, value });
1397
+ return new CommentNode(`Error: InvalidSpecialTagOp ${name}=${value}`);
1398
+ }
1399
+ return processXExtras(node, attrs, name, opIdx + 1, px);
1400
+ }
1401
+ function parseXOpVal(opName, value, px, parserFn) {
1402
+ const val = parserFn.call(vp, value, px);
1403
+ if (val === null)
1404
+ px.onParseIssue("bad-value", { role: "x-op", op: opName, value });
1405
+ return val;
1406
+ }
1337
1407
  function processXExtras(node, attrs, opName, startIdx, px) {
1338
1408
  const consumed = X_OP_CONSUMED[opName];
1339
1409
  const wrappable = X_OP_WRAPPABLE.has(opName);
@@ -1665,44 +1735,15 @@ var init_anode = __esm(() => {
1665
1735
  else if (node instanceof px.Comment)
1666
1736
  return new CommentNode(node.textContent);
1667
1737
  const { childNodes, attributes: attrs, tagName: tag } = node;
1668
- const childs = new Array(childNodes.length);
1669
- for (let i = 0;i < childNodes.length; i++)
1670
- childs[i] = ANode.fromDOM(childNodes[i], px);
1738
+ const childs = [];
1739
+ for (let i = 0;i < childNodes.length; i++) {
1740
+ const child = ANode.fromDOM(childNodes[i], px);
1741
+ if (child !== null)
1742
+ childs.push(child);
1743
+ }
1671
1744
  const isPseudoX = attrs[0]?.name === "@x";
1672
1745
  if (tag === "X" || isPseudoX) {
1673
- if (attrs.length === 0)
1674
- return maybeFragment(childs);
1675
- const opIdx = isPseudoX ? 1 : 0;
1676
- const { name, value } = attrs[opIdx];
1677
- const as = attrs.getNamedItem("as")?.value ?? null;
1678
- let node2;
1679
- switch (name) {
1680
- case "slot":
1681
- node2 = new SlotNode(null, vp.const(value), maybeFragment(childs));
1682
- break;
1683
- case "text":
1684
- node2 = px.addNodeIf(RenderTextNode, vp.parseText(value, px));
1685
- break;
1686
- case "render":
1687
- node2 = px.addNodeIf(RenderNode, vp.parseRender(value, px), as);
1688
- break;
1689
- case "render-it":
1690
- node2 = px.addNodeIf(RenderItNode, vp.bindValIt, as);
1691
- break;
1692
- case "render-each":
1693
- node2 = RenderEachNode.parse(px, vp, value, as, attrs);
1694
- break;
1695
- case "show":
1696
- node2 = px.addNodeIf(ShowNode, vp.parseCondValue(value, px), maybeFragment(childs));
1697
- break;
1698
- case "hide":
1699
- node2 = px.addNodeIf(HideNode, vp.parseCondValue(value, px), maybeFragment(childs));
1700
- break;
1701
- default:
1702
- px.onParseIssue("unknown-x-op", { name, value });
1703
- return new CommentNode(`Error: InvalidSpecialTagOp ${name}=${value}`);
1704
- }
1705
- return processXExtras(node2, attrs, name, (isPseudoX ? 1 : 0) + 1, px);
1746
+ return parseXOp(attrs, childs, isPseudoX ? 1 : 0, px);
1706
1747
  } else if (tag.charCodeAt(1) === 58 && tag.charCodeAt(0) === 88) {
1707
1748
  const macroName = tag.slice(2).toLowerCase();
1708
1749
  if (macroName === "slot") {
@@ -1788,7 +1829,7 @@ var init_anode = __esm(() => {
1788
1829
  return rx.renderEach(stack, this.iterInfo, this.nodeId, this.viewId);
1789
1830
  }
1790
1831
  static parse(px, vp2, s, as, attrs) {
1791
- const node = px.addNodeIf(RenderEachNode, vp2.parseEach(s, px), as);
1832
+ const node = px.addNodeIf(RenderEachNode, parseXOpVal("render-each", s, px, vp2.parseEach), as);
1792
1833
  if (node !== null) {
1793
1834
  const attrParser = getAttrParser(px);
1794
1835
  attrParser.eachAttr = attrParser.pushWrapper("each", s, node.val);
@@ -2448,13 +2489,14 @@ class LintContext {
2448
2489
  this.reports.push({ id, info, level, context: { ...this.frame } });
2449
2490
  }
2450
2491
  }
2451
- var ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", COMPUTED_VAL_NOT_DEFINED = "COMPUTED_VAL_NOT_DEFINED", COMPUTED_NOT_REFERENCED = "COMPUTED_NOT_REFERENCED", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", PARSE_ISSUE_KIND_TO_LINT_ID, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, AT_PREFIX_HINT_KNOWN_BY_KIND, LEVEL_WARN = "warn", LEVEL_ERROR = "error", LEVEL_HINT = "hint", NO_WRAPPERS, KNOWN_HANDLER_NAMES, LintParseContext;
2492
+ var ALT_HANDLER_NOT_DEFINED = "ALT_HANDLER_NOT_DEFINED", ALT_HANDLER_NOT_REFERENCED = "ALT_HANDLER_NOT_REFERENCED", RENDER_IT_OUTSIDE_OF_LOOP = "RENDER_IT_OUTSIDE_OF_LOOP", UNKNOWN_EVENT_MODIFIER = "UNKNOWN_EVENT_MODIFIER", UNKNOWN_HANDLER_ARG_NAME = "UNKNOWN_HANDLER_ARG_NAME", INPUT_HANDLER_NOT_IMPLEMENTED = "INPUT_HANDLER_NOT_IMPLEMENTED", INPUT_HANDLER_NOT_REFERENCED = "INPUT_HANDLER_NOT_REFERENCED", INPUT_HANDLER_METHOD_NOT_IMPLEMENTED = "INPUT_HANDLER_METHOD_NOT_IMPLEMENTED", INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD = "INPUT_HANDLER_FOR_INPUT_HANDLER_METHOD", INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER = "INPUT_HANDLER_METHOD_FOR_INPUT_HANDLER", FIELD_VAL_NOT_DEFINED = "FIELD_VAL_NOT_DEFINED", COMPUTED_VAL_NOT_DEFINED = "COMPUTED_VAL_NOT_DEFINED", COMPUTED_NOT_REFERENCED = "COMPUTED_NOT_REFERENCED", DUPLICATE_ATTR_DEFINITION = "DUPLICATE_ATTR_DEFINITION", UNKNOWN_REQUEST_NAME = "UNKNOWN_REQUEST_NAME", UNKNOWN_COMPONENT_NAME = "UNKNOWN_COMPONENT_NAME", UNKNOWN_MACRO_ARG = "UNKNOWN_MACRO_ARG", UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE", UNKNOWN_X_OP = "UNKNOWN_X_OP", UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR", MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX", BAD_VALUE = "BAD_VALUE", PARSE_ISSUE_KIND_TO_LINT_ID, X_KNOWN_OP_NAMES, X_KNOWN_ATTR_NAMES, AT_PREFIX_HINT_KNOWN_BY_KIND, LEVEL_WARN = "warn", LEVEL_ERROR = "error", LEVEL_HINT = "hint", NO_WRAPPERS, KNOWN_HANDLER_NAMES, LintParseContext;
2452
2493
  var init_lint_check = __esm(() => {
2453
2494
  init_anode();
2454
2495
  PARSE_ISSUE_KIND_TO_LINT_ID = {
2455
2496
  "unknown-directive": UNKNOWN_DIRECTIVE,
2456
2497
  "unknown-x-op": UNKNOWN_X_OP,
2457
- "unknown-x-attr": UNKNOWN_X_ATTR
2498
+ "unknown-x-attr": UNKNOWN_X_ATTR,
2499
+ "bad-value": BAD_VALUE
2458
2500
  };
2459
2501
  X_KNOWN_OP_NAMES = new Set([
2460
2502
  "slot",
@@ -293,9 +293,11 @@ class ValParser {
293
293
  const charCode = s.charCodeAt(0);
294
294
  switch (charCode) {
295
295
  case 94: {
296
- const newS = px.frame.macroVars?.[s.slice(1)];
296
+ const name = s.slice(1);
297
+ const newS = px.frame.macroVars?.[name];
297
298
  if (newS !== undefined)
298
299
  return this.parse(newS, px);
300
+ px.onParseIssue("bad-value", { role: "macro-var", name, value: s });
299
301
  return null;
300
302
  }
301
303
  case 39:
@@ -632,6 +634,8 @@ class AttrParser {
632
634
  this.attrs ??= [];
633
635
  this.attrs.push(new Attr(name, val));
634
636
  this.hasDynamic ||= !(val instanceof ConstVal);
637
+ } else {
638
+ this.px.onParseIssue("bad-value", { role: "attr", attr: name, value });
635
639
  }
636
640
  }
637
641
  pushWrapper(name, raw, val) {
@@ -647,6 +651,9 @@ class AttrParser {
647
651
  this.attrs ??= [];
648
652
  this.attrs.push(this.ifAttr);
649
653
  this.hasDynamic = true;
654
+ } else {
655
+ const info = { role: "if", attr: directiveName.slice(3), value };
656
+ this.px.onParseIssue("bad-value", info);
650
657
  }
651
658
  }
652
659
  parseThen(s) {
@@ -669,36 +676,44 @@ class AttrParser {
669
676
  this.events.add(eventName, handler, modifiers);
670
677
  }
671
678
  }
679
+ _parseDirectiveValue(directiveName, s, parserFn) {
680
+ const val = parserFn.call(vp, s, this.px);
681
+ if (val === null) {
682
+ const info = { role: "directive", directive: directiveName, value: s };
683
+ this.px.onParseIssue("bad-value", info);
684
+ }
685
+ return val;
686
+ }
672
687
  parseDirective(s, directiveName) {
673
688
  switch (directiveName) {
674
689
  case "dangerouslysetinnerhtml":
675
690
  this.attrs ??= [];
676
- this.attrs.push(new RawHtmlAttr(vp.parseText(s, this.px)));
691
+ this.attrs.push(new RawHtmlAttr(this._parseDirectiveValue(directiveName, s, vp.parseText)));
677
692
  this.hasDynamic = true;
678
693
  return;
679
694
  case "slot":
680
695
  this.pushWrapper("slot", s, vp.const(s));
681
696
  return;
682
697
  case "push-view":
683
- this.pushWrapper("push-view", s, vp.parseText(s, this.px));
698
+ this.pushWrapper("push-view", s, this._parseDirectiveValue(directiveName, s, vp.parseText));
684
699
  return;
685
700
  case "text":
686
- this.textChild = vp.parseText(s, this.px);
701
+ this.textChild = this._parseDirectiveValue(directiveName, s, vp.parseText);
687
702
  return;
688
703
  case "show":
689
- this.pushWrapper("show", s, vp.parseCondValue(s, this.px));
704
+ this.pushWrapper("show", s, this._parseDirectiveValue(directiveName, s, vp.parseCondValue));
690
705
  return;
691
706
  case "hide":
692
- this.pushWrapper("hide", s, vp.parseCondValue(s, this.px));
707
+ this.pushWrapper("hide", s, this._parseDirectiveValue(directiveName, s, vp.parseCondValue));
693
708
  return;
694
709
  case "each":
695
- this.eachAttr = this.pushWrapper("each", s, vp.parseEach(s, this.px));
710
+ this.eachAttr = this.pushWrapper("each", s, this._parseDirectiveValue(directiveName, s, vp.parseEach));
696
711
  return;
697
712
  case "enrich-with":
698
713
  if (this.eachAttr !== null) {
699
- this.eachAttr.enrichWithVal = vp.parseAlter(s, this.px);
714
+ this.eachAttr.enrichWithVal = this._parseDirectiveValue(directiveName, s, vp.parseAlter);
700
715
  } else {
701
- this.pushWrapper("scope", s, vp.parseAlter(s, this.px));
716
+ this.pushWrapper("scope", s, this._parseDirectiveValue(directiveName, s, vp.parseAlter));
702
717
  }
703
718
  return;
704
719
  case "when":
@@ -722,16 +737,18 @@ class AttrParser {
722
737
  this.parseThen(s);
723
738
  else if (directiveName.startsWith("else."))
724
739
  this.parseElse(s);
725
- else
726
- this.px.onParseIssue("unknown-directive", { name: directiveName, value: s });
740
+ else {
741
+ const info = { name: directiveName, value: s };
742
+ this.px.onParseIssue("unknown-directive", info);
743
+ }
727
744
  }
728
745
  _parseWhen(s) {
729
746
  if (this.eachAttr !== null)
730
- this.eachAttr.whenVal = vp.parseAlter(s, this.px);
747
+ this.eachAttr.whenVal = this._parseDirectiveValue("when", s, vp.parseAlter);
731
748
  }
732
749
  _parseLoopWith(s) {
733
750
  if (this.eachAttr !== null)
734
- this.eachAttr.loopWithVal = vp.parseAlter(s, this.px);
751
+ this.eachAttr.loopWithVal = this._parseDirectiveValue("loop-with", s, vp.parseAlter);
735
752
  }
736
753
  parse(attributes, parseAll = false) {
737
754
  for (const { name, value } of attributes) {
@@ -859,13 +876,22 @@ class EventHandler {
859
876
  static parse(s, px) {
860
877
  const [handlerName, ...rawArgs] = s.trim().split(/\s+/);
861
878
  const handlerVal = vp.parseHandlerName(handlerName, px);
862
- if (handlerVal === null)
879
+ if (handlerVal === null) {
880
+ const info = { role: "handler-name", value: handlerName };
881
+ px.onParseIssue("bad-value", info);
863
882
  return null;
883
+ }
864
884
  const args = new Array(rawArgs.length);
865
885
  vp.allowHandlerArg();
866
886
  for (let i = 0;i < rawArgs.length; i++) {
867
887
  const val = vp.parse(rawArgs[i], px);
868
- args[i] = val !== null ? val : vp.nullConstVal;
888
+ if (val !== null) {
889
+ args[i] = val;
890
+ } else {
891
+ const info = { role: "handler-arg", value: rawArgs[i] };
892
+ px.onParseIssue("bad-value", info);
893
+ args[i] = vp.nullConstVal;
894
+ }
869
895
  }
870
896
  return new EventHandler(handlerVal, args);
871
897
  }
@@ -1029,44 +1055,15 @@ class ANode extends BaseNode {
1029
1055
  else if (node instanceof px.Comment)
1030
1056
  return new CommentNode(node.textContent);
1031
1057
  const { childNodes, attributes: attrs, tagName: tag } = node;
1032
- const childs = new Array(childNodes.length);
1033
- for (let i = 0;i < childNodes.length; i++)
1034
- childs[i] = ANode.fromDOM(childNodes[i], px);
1058
+ const childs = [];
1059
+ for (let i = 0;i < childNodes.length; i++) {
1060
+ const child = ANode.fromDOM(childNodes[i], px);
1061
+ if (child !== null)
1062
+ childs.push(child);
1063
+ }
1035
1064
  const isPseudoX = attrs[0]?.name === "@x";
1036
1065
  if (tag === "X" || isPseudoX) {
1037
- if (attrs.length === 0)
1038
- return maybeFragment(childs);
1039
- const opIdx = isPseudoX ? 1 : 0;
1040
- const { name, value } = attrs[opIdx];
1041
- const as = attrs.getNamedItem("as")?.value ?? null;
1042
- let node2;
1043
- switch (name) {
1044
- case "slot":
1045
- node2 = new SlotNode(null, vp.const(value), maybeFragment(childs));
1046
- break;
1047
- case "text":
1048
- node2 = px.addNodeIf(RenderTextNode, vp.parseText(value, px));
1049
- break;
1050
- case "render":
1051
- node2 = px.addNodeIf(RenderNode, vp.parseRender(value, px), as);
1052
- break;
1053
- case "render-it":
1054
- node2 = px.addNodeIf(RenderItNode, vp.bindValIt, as);
1055
- break;
1056
- case "render-each":
1057
- node2 = RenderEachNode.parse(px, vp, value, as, attrs);
1058
- break;
1059
- case "show":
1060
- node2 = px.addNodeIf(ShowNode, vp.parseCondValue(value, px), maybeFragment(childs));
1061
- break;
1062
- case "hide":
1063
- node2 = px.addNodeIf(HideNode, vp.parseCondValue(value, px), maybeFragment(childs));
1064
- break;
1065
- default:
1066
- px.onParseIssue("unknown-x-op", { name, value });
1067
- return new CommentNode(`Error: InvalidSpecialTagOp ${name}=${value}`);
1068
- }
1069
- return processXExtras(node2, attrs, name, (isPseudoX ? 1 : 0) + 1, px);
1066
+ return parseXOp(attrs, childs, isPseudoX ? 1 : 0, px);
1070
1067
  } else if (tag.charCodeAt(1) === 58 && tag.charCodeAt(0) === 88) {
1071
1068
  const macroName = tag.slice(2).toLowerCase();
1072
1069
  if (macroName === "slot") {
@@ -1087,6 +1084,50 @@ class ANode extends BaseNode {
1087
1084
  return new CommentNode(`Error: InvalidTagName ${tag}`);
1088
1085
  }
1089
1086
  }
1087
+ function parseXOp(attrs, childs, opIdx, px) {
1088
+ if (attrs.length === 0)
1089
+ return maybeFragment(childs);
1090
+ const { name, value } = attrs[opIdx];
1091
+ const as = attrs.getNamedItem("as")?.value ?? null;
1092
+ let node;
1093
+ switch (name) {
1094
+ case "slot":
1095
+ node = new SlotNode(null, vp.const(value), maybeFragment(childs));
1096
+ break;
1097
+ case "text":
1098
+ node = px.addNodeIf(RenderTextNode, parseXOpVal(name, value, px, vp.parseText));
1099
+ break;
1100
+ case "render":
1101
+ node = px.addNodeIf(RenderNode, parseXOpVal(name, value, px, vp.parseRender), as);
1102
+ break;
1103
+ case "render-it":
1104
+ node = px.addNodeIf(RenderItNode, vp.bindValIt, as);
1105
+ break;
1106
+ case "render-each":
1107
+ node = RenderEachNode.parse(px, vp, value, as, attrs);
1108
+ break;
1109
+ case "show": {
1110
+ const val = parseXOpVal(name, value, px, vp.parseCondValue);
1111
+ node = px.addNodeIf(ShowNode, val, maybeFragment(childs));
1112
+ break;
1113
+ }
1114
+ case "hide": {
1115
+ const val = parseXOpVal(name, value, px, vp.parseCondValue);
1116
+ node = px.addNodeIf(HideNode, val, maybeFragment(childs));
1117
+ break;
1118
+ }
1119
+ default:
1120
+ px.onParseIssue("unknown-x-op", { name, value });
1121
+ return new CommentNode(`Error: InvalidSpecialTagOp ${name}=${value}`);
1122
+ }
1123
+ return processXExtras(node, attrs, name, opIdx + 1, px);
1124
+ }
1125
+ function parseXOpVal(opName, value, px, parserFn) {
1126
+ const val = parserFn.call(vp, value, px);
1127
+ if (val === null)
1128
+ px.onParseIssue("bad-value", { role: "x-op", op: opName, value });
1129
+ return val;
1130
+ }
1090
1131
  function processXExtras(node, attrs, opName, startIdx, px) {
1091
1132
  const consumed = X_OP_CONSUMED[opName];
1092
1133
  const wrappable = X_OP_WRAPPABLE.has(opName);
@@ -1213,7 +1254,7 @@ class RenderEachNode extends RenderViewId {
1213
1254
  return rx.renderEach(stack, this.iterInfo, this.nodeId, this.viewId);
1214
1255
  }
1215
1256
  static parse(px, vp2, s, as, attrs) {
1216
- const node = px.addNodeIf(RenderEachNode, vp2.parseEach(s, px), as);
1257
+ const node = px.addNodeIf(RenderEachNode, parseXOpVal("render-each", s, px, vp2.parseEach), as);
1217
1258
  if (node !== null) {
1218
1259
  const attrParser = getAttrParser(px);
1219
1260
  attrParser.eachAttr = attrParser.pushWrapper("each", s, node.val);
@@ -1631,10 +1672,12 @@ var UNKNOWN_DIRECTIVE = "UNKNOWN_DIRECTIVE";
1631
1672
  var UNKNOWN_X_OP = "UNKNOWN_X_OP";
1632
1673
  var UNKNOWN_X_ATTR = "UNKNOWN_X_ATTR";
1633
1674
  var MAYBE_DROP_AT_PREFIX = "MAYBE_DROP_AT_PREFIX";
1675
+ var BAD_VALUE = "BAD_VALUE";
1634
1676
  var PARSE_ISSUE_KIND_TO_LINT_ID = {
1635
1677
  "unknown-directive": UNKNOWN_DIRECTIVE,
1636
1678
  "unknown-x-op": UNKNOWN_X_OP,
1637
- "unknown-x-attr": UNKNOWN_X_ATTR
1679
+ "unknown-x-attr": UNKNOWN_X_ATTR,
1680
+ "bad-value": BAD_VALUE
1638
1681
  };
1639
1682
  var X_KNOWN_OP_NAMES = new Set([
1640
1683
  "slot",
@@ -2018,6 +2061,27 @@ class LintParseContext extends ParseContext {
2018
2061
  }
2019
2062
 
2020
2063
  // tools/format/lint.js
2064
+ function badValueMessage(info) {
2065
+ const v = JSON.stringify(info.value);
2066
+ switch (info.role) {
2067
+ case "attr":
2068
+ return `Cannot parse value ${v} for attribute ':${info.attr}'`;
2069
+ case "directive":
2070
+ return `Cannot parse value ${v} for directive '@${info.directive}'`;
2071
+ case "if":
2072
+ return `Cannot parse condition ${v} for '@if.${info.attr}'`;
2073
+ case "x-op":
2074
+ return `Cannot parse value ${v} for <x ${info.op}>`;
2075
+ case "handler-name":
2076
+ return `Cannot parse handler name ${v}`;
2077
+ case "handler-arg":
2078
+ return `Cannot parse handler argument ${v}`;
2079
+ case "macro-var":
2080
+ return `Macro variable '^${info.name}' is not defined`;
2081
+ default:
2082
+ return `Cannot parse value ${v}`;
2083
+ }
2084
+ }
2021
2085
  function lintIdToMessage(id, info) {
2022
2086
  switch (id) {
2023
2087
  case "RENDER_IT_OUTSIDE_OF_LOOP":
@@ -2062,6 +2126,8 @@ function lintIdToMessage(id, info) {
2062
2126
  return `Unknown attribute '${info.name}=${JSON.stringify(info.value)}' on <x ${info.op}>`;
2063
2127
  case "MAYBE_DROP_AT_PREFIX":
2064
2128
  return `Did you mean '${info.suggestion}'? Drop the '@' prefix on <x>.`;
2129
+ case "BAD_VALUE":
2130
+ return badValueMessage(info);
2065
2131
  case "LINT_ERROR":
2066
2132
  return info.message;
2067
2133
  default:
@@ -7819,7 +7885,7 @@ initCollectionConversions();
7819
7885
  var { version } = pkg;
7820
7886
 
7821
7887
  // src/oo.js
7822
- var BAD_VALUE = Symbol("BadValue");
7888
+ var BAD_VALUE2 = Symbol("BadValue");
7823
7889
  var nullCoercer = (v) => v;
7824
7890
 
7825
7891
  class Field {
@@ -7866,8 +7932,8 @@ class Field {
7866
7932
  const setName = `set${uname}`;
7867
7933
  const that = this;
7868
7934
  proto[setName] = function(v) {
7869
- const v1 = that.coerceOr(v, BAD_VALUE);
7870
- if (v1 === BAD_VALUE) {
7935
+ const v1 = that.coerceOr(v, BAD_VALUE2);
7936
+ if (v1 === BAD_VALUE2) {
7871
7937
  console.warn("invalid value", v);
7872
7938
  return this;
7873
7939
  }
@@ -8840,6 +8906,7 @@ export {
8840
8906
  Collection,
8841
8907
  COMPUTED_VAL_NOT_DEFINED,
8842
8908
  COMPUTED_NOT_REFERENCED,
8909
+ BAD_VALUE,
8843
8910
  ALT_HANDLER_NOT_REFERENCED,
8844
8911
  ALT_HANDLER_NOT_DEFINED
8845
8912
  };