marko 6.3.15 → 6.3.16

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.
@@ -1,6 +1,8 @@
1
1
  export declare function assertValidAttrValue(name: string, value: unknown): void;
2
2
  export declare function assertValidTextValue(value: unknown): void;
3
3
  export declare function assertValidLoopKey(key: unknown, seenKeys?: Set<unknown>): void;
4
+ export declare function assertValidList(value: unknown): void;
5
+ export declare function assertValidRangeBound(name: string, value: unknown): void;
4
6
  export declare function assertValidAttrName(name: string): void;
5
7
  export declare function _el_read_error(): void;
6
8
  export declare function _hoist_read_error(): void;
package/dist/debug/dom.js CHANGED
@@ -159,6 +159,15 @@ function assertValidLoopKey(key, seenKeys) {
159
159
  seenKeys.add(key);
160
160
  }
161
161
  }
162
+ function assertValidList(value) {
163
+ if (value && typeof value[Symbol.iterator] !== "function") throw new Error(`A \`<for>\` tag's \`of\` attribute must be an iterable, such as an array, but received ${describeForValue(value)}.`);
164
+ }
165
+ function assertValidRangeBound(name, value) {
166
+ if (!isFinite(value)) throw new Error(`A \`<for>\` tag's \`${name}\` attribute must be a finite number, but received ${describeForValue(value)}.`);
167
+ }
168
+ function describeForValue(value) {
169
+ return typeof value === "number" || typeof value === "bigint" ? `\`${value}\`` : value === null ? "null" : `type "${typeof value}"`;
170
+ }
162
171
  function assertValidAttrName(name) {
163
172
  if (htmlAttrNameReg.test(name)) throw new Error(`Invalid attribute name: ${JSON.stringify(name)}`);
164
173
  const suggestion = getWrongAttrSuggestion(name);
@@ -211,17 +220,20 @@ function forIn(obj, cb) {
211
220
  for (const key in obj) cb(key, obj[key]);
212
221
  }
213
222
  function forOf(list, cb) {
223
+ assertValidList(list);
214
224
  if (list) {
215
225
  let i = 0;
216
226
  for (const item of list) cb(item, i++);
217
227
  }
218
228
  }
219
229
  function forTo(to, from, step, cb) {
230
+ assertValidRangeBound("to", to);
220
231
  const start = from || 0;
221
232
  const delta = step || 1;
222
233
  for (let steps = (to - start) / delta, i = 0; i <= steps; i++) cb(start + i * delta);
223
234
  }
224
235
  function forUntil(until, from, step, cb) {
236
+ assertValidRangeBound("until", until);
225
237
  const start = from || 0;
226
238
  const delta = step || 1;
227
239
  for (let steps = (until - start) / delta, i = 0; i < steps; i++) cb(start + i * delta);
@@ -157,6 +157,15 @@ function assertValidLoopKey(key, seenKeys) {
157
157
  seenKeys.add(key);
158
158
  }
159
159
  }
160
+ function assertValidList(value) {
161
+ if (value && typeof value[Symbol.iterator] !== "function") throw new Error(`A \`<for>\` tag's \`of\` attribute must be an iterable, such as an array, but received ${describeForValue(value)}.`);
162
+ }
163
+ function assertValidRangeBound(name, value) {
164
+ if (!isFinite(value)) throw new Error(`A \`<for>\` tag's \`${name}\` attribute must be a finite number, but received ${describeForValue(value)}.`);
165
+ }
166
+ function describeForValue(value) {
167
+ return typeof value === "number" || typeof value === "bigint" ? `\`${value}\`` : value === null ? "null" : `type "${typeof value}"`;
168
+ }
160
169
  function assertValidAttrName(name) {
161
170
  if (htmlAttrNameReg.test(name)) throw new Error(`Invalid attribute name: ${JSON.stringify(name)}`);
162
171
  const suggestion = getWrongAttrSuggestion(name);
@@ -209,17 +218,20 @@ function forIn(obj, cb) {
209
218
  for (const key in obj) cb(key, obj[key]);
210
219
  }
211
220
  function forOf(list, cb) {
221
+ assertValidList(list);
212
222
  if (list) {
213
223
  let i = 0;
214
224
  for (const item of list) cb(item, i++);
215
225
  }
216
226
  }
217
227
  function forTo(to, from, step, cb) {
228
+ assertValidRangeBound("to", to);
218
229
  const start = from || 0;
219
230
  const delta = step || 1;
220
231
  for (let steps = (to - start) / delta, i = 0; i <= steps; i++) cb(start + i * delta);
221
232
  }
222
233
  function forUntil(until, from, step, cb) {
234
+ assertValidRangeBound("until", until);
223
235
  const start = from || 0;
224
236
  const delta = step || 1;
225
237
  for (let steps = (until - start) / delta, i = 0; i < steps; i++) cb(start + i * delta);
@@ -158,6 +158,15 @@ function assertValidLoopKey(key, seenKeys) {
158
158
  seenKeys.add(key);
159
159
  }
160
160
  }
161
+ function assertValidList(value) {
162
+ if (value && typeof value[Symbol.iterator] !== "function") throw new Error(`A \`<for>\` tag's \`of\` attribute must be an iterable, such as an array, but received ${describeForValue(value)}.`);
163
+ }
164
+ function assertValidRangeBound(name, value) {
165
+ if (!isFinite(value)) throw new Error(`A \`<for>\` tag's \`${name}\` attribute must be a finite number, but received ${describeForValue(value)}.`);
166
+ }
167
+ function describeForValue(value) {
168
+ return typeof value === "number" || typeof value === "bigint" ? `\`${value}\`` : value === null ? "null" : `type "${typeof value}"`;
169
+ }
161
170
  function assertValidAttrName(name) {
162
171
  if (htmlAttrNameReg.test(name)) throw new Error(`Invalid attribute name: ${JSON.stringify(name)}`);
163
172
  const suggestion = getWrongAttrSuggestion(name);
@@ -1528,17 +1537,20 @@ function forIn(obj, cb) {
1528
1537
  for (const key in obj) cb(key, obj[key]);
1529
1538
  }
1530
1539
  function forOf(list, cb) {
1540
+ assertValidList(list);
1531
1541
  if (list) {
1532
1542
  let i = 0;
1533
1543
  for (const item of list) cb(item, i++);
1534
1544
  }
1535
1545
  }
1536
1546
  function forTo(to, from, step, cb) {
1547
+ assertValidRangeBound("to", to);
1537
1548
  const start = from || 0;
1538
1549
  const delta = step || 1;
1539
1550
  for (let steps = (to - start) / delta, i = 0; i <= steps; i++) cb(start + i * delta);
1540
1551
  }
1541
1552
  function forUntil(until, from, step, cb) {
1553
+ assertValidRangeBound("until", until);
1542
1554
  const start = from || 0;
1543
1555
  const delta = step || 1;
1544
1556
  for (let steps = (until - start) / delta, i = 0; i < steps; i++) cb(start + i * delta);
@@ -2754,7 +2766,7 @@ function normalizedValueMatches(a, b) {
2754
2766
  return false;
2755
2767
  }
2756
2768
  function normalizeStrAttrValue(value) {
2757
- return value && value !== true || value === 0 ? value + "" : "";
2769
+ return isNotVoid(value) && value !== true ? value + "" : "";
2758
2770
  }
2759
2771
  //#endregion
2760
2772
  //#region src/html/dynamic-tag.ts
@@ -2833,6 +2845,7 @@ const patchDynamicTag = ((originalDynamicTag) => (patch) => {
2833
2845
  })(_dynamic_tag);
2834
2846
  //#endregion
2835
2847
  //#region src/html/template.ts
2848
+ const CONSUMED_RESULT_MESSAGE = "Cannot read from a consumed render result";
2836
2849
  const _template = (templateId, renderer, page) => {
2837
2850
  renderer.render = render;
2838
2851
  renderer["embed"] = !page;
@@ -2995,7 +3008,7 @@ var ServerRendered = class {
2995
3008
  return this.#cachedPromise ||= new Promise((resolve, reject) => {
2996
3009
  const head = this.#head;
2997
3010
  this.#head = null;
2998
- if (!head) return reject(/* @__PURE__ */ new Error("Cannot read from a consumed render result"));
3011
+ if (!head) return reject(/* @__PURE__ */ new Error(CONSUMED_RESULT_MESSAGE));
2999
3012
  const { boundary } = head;
3000
3013
  (boundary.onNext = () => {
3001
3014
  switch (!boundary.count && boundary.flush()) {
@@ -3017,7 +3030,7 @@ var ServerRendered = class {
3017
3030
  let head = this.#head;
3018
3031
  this.#head = null;
3019
3032
  if (!head) {
3020
- onAbort(/* @__PURE__ */ new Error("Cannot read from a consumed render result"));
3033
+ onAbort(/* @__PURE__ */ new Error(CONSUMED_RESULT_MESSAGE));
3021
3034
  return;
3022
3035
  }
3023
3036
  const { boundary } = head;
@@ -3047,7 +3060,7 @@ var ServerRendered = class {
3047
3060
  toString() {
3048
3061
  const head = this.#head;
3049
3062
  this.#head = null;
3050
- if (!head) throw new Error("Cannot read from a consumed render result");
3063
+ if (!head) throw new Error(CONSUMED_RESULT_MESSAGE);
3051
3064
  const { boundary } = head;
3052
3065
  switch (boundary.flush()) {
3053
3066
  case 2: throw boundary.signal.reason;
@@ -156,6 +156,15 @@ function assertValidLoopKey(key, seenKeys) {
156
156
  seenKeys.add(key);
157
157
  }
158
158
  }
159
+ function assertValidList(value) {
160
+ if (value && typeof value[Symbol.iterator] !== "function") throw new Error(`A \`<for>\` tag's \`of\` attribute must be an iterable, such as an array, but received ${describeForValue(value)}.`);
161
+ }
162
+ function assertValidRangeBound(name, value) {
163
+ if (!isFinite(value)) throw new Error(`A \`<for>\` tag's \`${name}\` attribute must be a finite number, but received ${describeForValue(value)}.`);
164
+ }
165
+ function describeForValue(value) {
166
+ return typeof value === "number" || typeof value === "bigint" ? `\`${value}\`` : value === null ? "null" : `type "${typeof value}"`;
167
+ }
159
168
  function assertValidAttrName(name) {
160
169
  if (htmlAttrNameReg.test(name)) throw new Error(`Invalid attribute name: ${JSON.stringify(name)}`);
161
170
  const suggestion = getWrongAttrSuggestion(name);
@@ -1526,17 +1535,20 @@ function forIn(obj, cb) {
1526
1535
  for (const key in obj) cb(key, obj[key]);
1527
1536
  }
1528
1537
  function forOf(list, cb) {
1538
+ assertValidList(list);
1529
1539
  if (list) {
1530
1540
  let i = 0;
1531
1541
  for (const item of list) cb(item, i++);
1532
1542
  }
1533
1543
  }
1534
1544
  function forTo(to, from, step, cb) {
1545
+ assertValidRangeBound("to", to);
1535
1546
  const start = from || 0;
1536
1547
  const delta = step || 1;
1537
1548
  for (let steps = (to - start) / delta, i = 0; i <= steps; i++) cb(start + i * delta);
1538
1549
  }
1539
1550
  function forUntil(until, from, step, cb) {
1551
+ assertValidRangeBound("until", until);
1540
1552
  const start = from || 0;
1541
1553
  const delta = step || 1;
1542
1554
  for (let steps = (until - start) / delta, i = 0; i < steps; i++) cb(start + i * delta);
@@ -2752,7 +2764,7 @@ function normalizedValueMatches(a, b) {
2752
2764
  return false;
2753
2765
  }
2754
2766
  function normalizeStrAttrValue(value) {
2755
- return value && value !== true || value === 0 ? value + "" : "";
2767
+ return isNotVoid(value) && value !== true ? value + "" : "";
2756
2768
  }
2757
2769
  //#endregion
2758
2770
  //#region src/html/dynamic-tag.ts
@@ -2831,6 +2843,7 @@ const patchDynamicTag = ((originalDynamicTag) => (patch) => {
2831
2843
  })(_dynamic_tag);
2832
2844
  //#endregion
2833
2845
  //#region src/html/template.ts
2846
+ const CONSUMED_RESULT_MESSAGE = "Cannot read from a consumed render result";
2834
2847
  const _template = (templateId, renderer, page) => {
2835
2848
  renderer.render = render;
2836
2849
  renderer["embed"] = !page;
@@ -2993,7 +3006,7 @@ var ServerRendered = class {
2993
3006
  return this.#cachedPromise ||= new Promise((resolve, reject) => {
2994
3007
  const head = this.#head;
2995
3008
  this.#head = null;
2996
- if (!head) return reject(/* @__PURE__ */ new Error("Cannot read from a consumed render result"));
3009
+ if (!head) return reject(/* @__PURE__ */ new Error(CONSUMED_RESULT_MESSAGE));
2997
3010
  const { boundary } = head;
2998
3011
  (boundary.onNext = () => {
2999
3012
  switch (!boundary.count && boundary.flush()) {
@@ -3015,7 +3028,7 @@ var ServerRendered = class {
3015
3028
  let head = this.#head;
3016
3029
  this.#head = null;
3017
3030
  if (!head) {
3018
- onAbort(/* @__PURE__ */ new Error("Cannot read from a consumed render result"));
3031
+ onAbort(/* @__PURE__ */ new Error(CONSUMED_RESULT_MESSAGE));
3019
3032
  return;
3020
3033
  }
3021
3034
  const { boundary } = head;
@@ -3045,7 +3058,7 @@ var ServerRendered = class {
3045
3058
  toString() {
3046
3059
  const head = this.#head;
3047
3060
  this.#head = null;
3048
- if (!head) throw new Error("Cannot read from a consumed render result");
3061
+ if (!head) throw new Error(CONSUMED_RESULT_MESSAGE);
3049
3062
  const { boundary } = head;
3050
3063
  switch (boundary.flush()) {
3051
3064
  case 2: throw boundary.signal.reason;
package/dist/html.js CHANGED
@@ -279,7 +279,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
279
279
  let patched = patch(tag, scopeId, accessor);
280
280
  return patched !== tag && (patched.a = tag), originalDynamicTag(scopeId, accessor, patched, input, content, inputIsArgs, resume);
281
281
  };
282
- })(_dynamic_tag), _template = (templateId, renderer, page) => (renderer.render = render, renderer.i = !page, renderer._ = renderer, _content_resume(templateId, renderer)), kAssets = Symbol(), kBlockIndex = Symbol(), kDeferIndex = Symbol(), assetFlush, SET_SCOPE_REGISTER_ID = "$C_s", K_TAGS_API_STATE = Symbol(), COMPAT_REGISTRY = /* @__PURE__ */ new WeakMap(), compat = {
282
+ })(_dynamic_tag), CONSUMED_RESULT_MESSAGE = "Cannot read from a consumed render result", _template = (templateId, renderer, page) => (renderer.render = render, renderer.i = !page, renderer._ = renderer, _content_resume(templateId, renderer)), kAssets = Symbol(), kBlockIndex = Symbol(), kDeferIndex = Symbol(), assetFlush, SET_SCOPE_REGISTER_ID = "$C_s", K_TAGS_API_STATE = Symbol(), COMPAT_REGISTRY = /* @__PURE__ */ new WeakMap(), compat = {
283
283
  $global,
284
284
  fork: _await,
285
285
  write: _html,
@@ -1830,7 +1830,7 @@ function normalizedValueMatches(a, b) {
1830
1830
  return !1;
1831
1831
  }
1832
1832
  function normalizeStrAttrValue(value) {
1833
- return value && value !== !0 || value === 0 ? value + "" : "";
1833
+ return isNotVoid(value) && value !== !0 ? value + "" : "";
1834
1834
  }
1835
1835
  //#endregion
1836
1836
  //#region src/html/dynamic-tag.ts
@@ -1954,7 +1954,7 @@ var ServerRendered = class {
1954
1954
  #promise() {
1955
1955
  return this.#cachedPromise ||= new Promise((resolve, reject) => {
1956
1956
  let head = this.#head;
1957
- if (this.#head = null, !head) return reject(/* @__PURE__ */ Error("Cannot read from a consumed render result"));
1957
+ if (this.#head = null, !head) return reject(/* @__PURE__ */ Error(CONSUMED_RESULT_MESSAGE));
1958
1958
  let { boundary } = head;
1959
1959
  (boundary.onNext = () => {
1960
1960
  switch (!boundary.count && boundary.flush()) {
@@ -1973,7 +1973,7 @@ var ServerRendered = class {
1973
1973
  #read(onWrite, onAbort, onClose) {
1974
1974
  let tick = !0, head = this.#head;
1975
1975
  if (this.#head = null, !head) {
1976
- onAbort(/* @__PURE__ */ Error("Cannot read from a consumed render result"));
1976
+ onAbort(/* @__PURE__ */ Error(CONSUMED_RESULT_MESSAGE));
1977
1977
  return;
1978
1978
  }
1979
1979
  let { boundary } = head, onNext = boundary.onNext = (write) => {
@@ -1989,7 +1989,7 @@ var ServerRendered = class {
1989
1989
  }
1990
1990
  toString() {
1991
1991
  let head = this.#head;
1992
- if (this.#head = null, !head) throw Error("Cannot read from a consumed render result");
1992
+ if (this.#head = null, !head) throw Error(CONSUMED_RESULT_MESSAGE);
1993
1993
  let { boundary } = head;
1994
1994
  switch (boundary.flush()) {
1995
1995
  case 2: throw boundary.signal.reason;
package/dist/html.mjs CHANGED
@@ -279,7 +279,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
279
279
  let patched = patch(tag, scopeId, accessor);
280
280
  return patched !== tag && (patched.a = tag), originalDynamicTag(scopeId, accessor, patched, input, content, inputIsArgs, resume);
281
281
  };
282
- })(_dynamic_tag), _template = (templateId, renderer, page) => (renderer.render = render, renderer.i = !page, renderer._ = renderer, _content_resume(templateId, renderer)), kAssets = Symbol(), kBlockIndex = Symbol(), kDeferIndex = Symbol(), assetFlush, SET_SCOPE_REGISTER_ID = "$C_s", K_TAGS_API_STATE = Symbol(), COMPAT_REGISTRY = /* @__PURE__ */ new WeakMap(), compat = {
282
+ })(_dynamic_tag), CONSUMED_RESULT_MESSAGE = "Cannot read from a consumed render result", _template = (templateId, renderer, page) => (renderer.render = render, renderer.i = !page, renderer._ = renderer, _content_resume(templateId, renderer)), kAssets = Symbol(), kBlockIndex = Symbol(), kDeferIndex = Symbol(), assetFlush, SET_SCOPE_REGISTER_ID = "$C_s", K_TAGS_API_STATE = Symbol(), COMPAT_REGISTRY = /* @__PURE__ */ new WeakMap(), compat = {
283
283
  $global,
284
284
  fork: _await,
285
285
  write: _html,
@@ -1829,7 +1829,7 @@ function normalizedValueMatches(a, b) {
1829
1829
  return !1;
1830
1830
  }
1831
1831
  function normalizeStrAttrValue(value) {
1832
- return value && value !== !0 || value === 0 ? value + "" : "";
1832
+ return isNotVoid(value) && value !== !0 ? value + "" : "";
1833
1833
  }
1834
1834
  //#endregion
1835
1835
  //#region src/html/dynamic-tag.ts
@@ -1953,7 +1953,7 @@ var ServerRendered = class {
1953
1953
  #promise() {
1954
1954
  return this.#cachedPromise ||= new Promise((resolve, reject) => {
1955
1955
  let head = this.#head;
1956
- if (this.#head = null, !head) return reject(/* @__PURE__ */ Error("Cannot read from a consumed render result"));
1956
+ if (this.#head = null, !head) return reject(/* @__PURE__ */ Error(CONSUMED_RESULT_MESSAGE));
1957
1957
  let { boundary } = head;
1958
1958
  (boundary.onNext = () => {
1959
1959
  switch (!boundary.count && boundary.flush()) {
@@ -1972,7 +1972,7 @@ var ServerRendered = class {
1972
1972
  #read(onWrite, onAbort, onClose) {
1973
1973
  let tick = !0, head = this.#head;
1974
1974
  if (this.#head = null, !head) {
1975
- onAbort(/* @__PURE__ */ Error("Cannot read from a consumed render result"));
1975
+ onAbort(/* @__PURE__ */ Error(CONSUMED_RESULT_MESSAGE));
1976
1976
  return;
1977
1977
  }
1978
1978
  let { boundary } = head, onNext = boundary.onNext = (write) => {
@@ -1988,7 +1988,7 @@ var ServerRendered = class {
1988
1988
  }
1989
1989
  toString() {
1990
1990
  let head = this.#head;
1991
- if (this.#head = null, !head) throw Error("Cannot read from a consumed render result");
1991
+ if (this.#head = null, !head) throw Error(CONSUMED_RESULT_MESSAGE);
1992
1992
  let { boundary } = head;
1993
1993
  switch (boundary.flush()) {
1994
1994
  case 2: throw boundary.signal.reason;
@@ -0,0 +1,3 @@
1
+ import type { Tag } from "@marko/compiler/babel-utils";
2
+ declare const _default: Tag;
3
+ export default _default;
@@ -2,6 +2,7 @@ declare const _default: {
2
2
  taglibId: string;
3
3
  "<attrs>": import("@marko/compiler/babel-utils").Tag;
4
4
  "<await>": import("@marko/compiler/babel-utils").Tag;
5
+ "<class>": import("@marko/compiler/babel-utils").Tag;
5
6
  "<client>": import("@marko/compiler/babel-utils").Tag;
6
7
  "<const>": import("@marko/compiler/babel-utils").Tag;
7
8
  "<debug>": import("@marko/compiler/babel-utils").Tag;
@@ -10,6 +10,7 @@ export declare const taglibs: (string | {
10
10
  taglibId: string;
11
11
  "<attrs>": import("@marko/compiler/babel-utils").Tag;
12
12
  "<await>": import("@marko/compiler/babel-utils").Tag;
13
+ "<class>": import("@marko/compiler/babel-utils").Tag;
13
14
  "<client>": import("@marko/compiler/babel-utils").Tag;
14
15
  "<const>": import("@marko/compiler/babel-utils").Tag;
15
16
  "<debug>": import("@marko/compiler/babel-utils").Tag;
@@ -1146,62 +1146,67 @@ function analyzeTagNameType(tag, allowDynamic) {
1146
1146
  }
1147
1147
  function analyzeExpressionTagName(name, extra) {
1148
1148
  const pending = [name];
1149
+ const seen = /* @__PURE__ */ new Set();
1149
1150
  let path;
1150
1151
  let type;
1151
1152
  let nullable = false;
1152
1153
  let tagNameImported;
1153
1154
  let tagNameLoad;
1154
- while ((path = pending.pop()) && type !== 2) if (path.isConditionalExpression()) {
1155
- pending.push(path.get("consequent"));
1156
- if (path.node.alternate) pending.push(path.get("alternate"));
1157
- } else if (path.isLogicalExpression()) {
1158
- if (path.node.operator === "&&") nullable = true;
1159
- else pending.push(path.get("left"));
1160
- pending.push(path.get("right"));
1161
- } else if (path.isAssignmentExpression()) pending.push(path.get("right"));
1162
- else if (path.isBinaryExpression()) type = path.node.operator !== "+" || type === void 0 || type === 0 ? 0 : 2;
1163
- else if (path.isStringLiteral() || path.isTemplateLiteral()) type = type === void 0 || type === 0 ? 0 : 2;
1164
- else if (path.isNullLiteral()) nullable = true;
1165
- else if (path.isIdentifier()) {
1166
- if (path.node.name === "undefined") {
1167
- nullable = true;
1168
- continue;
1169
- }
1170
- const binding = path.scope.getBinding(path.node.name);
1171
- if (!binding) {
1172
- type = 2;
1173
- continue;
1174
- }
1175
- if (binding.kind === "module") {
1176
- const decl = binding.path.parent;
1177
- if (MARKO_FILE_REG.test(decl.source.value) && decl.specifiers.some((it) => _marko_compiler.types.isImportDefaultSpecifier(it))) {
1178
- const resolvedImport = decl.extra?.tagImport || decl.source.value;
1179
- if (type === void 0) {
1180
- type = 1;
1181
- tagNameImported = resolvedImport;
1182
- tagNameLoad = decl.extra?.loadImport;
1183
- } else if (type === 0) {
1184
- type = 2;
1185
- tagNameImported = void 0;
1186
- } else if (tagNameImported !== resolvedImport) tagNameImported = void 0;
1187
- } else type = 2;
1188
- continue;
1189
- }
1190
- const bindingTag = binding.path;
1191
- if (bindingTag.isMarkoTag() && binding.kind === "local") {
1192
- const bindingTagName = bindingTag.get("name").node.value;
1193
- if (bindingTagName === "const") {
1194
- pending.push(bindingTag.get("attributes")[0].get("value"));
1155
+ while ((path = pending.pop()) && type !== 2) {
1156
+ if (seen.has(path.node)) continue;
1157
+ seen.add(path.node);
1158
+ if (path.isConditionalExpression()) {
1159
+ pending.push(path.get("consequent"));
1160
+ if (path.node.alternate) pending.push(path.get("alternate"));
1161
+ } else if (path.isLogicalExpression()) {
1162
+ if (path.node.operator === "&&") nullable = true;
1163
+ else pending.push(path.get("left"));
1164
+ pending.push(path.get("right"));
1165
+ } else if (path.isAssignmentExpression()) pending.push(path.get("right"));
1166
+ else if (path.isBinaryExpression()) type = path.node.operator !== "+" || type === void 0 || type === 0 ? 0 : 2;
1167
+ else if (path.isStringLiteral() || path.isTemplateLiteral()) type = type === void 0 || type === 0 ? 0 : 2;
1168
+ else if (path.isNullLiteral()) nullable = true;
1169
+ else if (path.isIdentifier()) {
1170
+ if (path.node.name === "undefined") {
1171
+ nullable = true;
1195
1172
  continue;
1196
1173
  }
1197
- if (bindingTagName === "let") {
1174
+ const binding = path.scope.getBinding(path.node.name);
1175
+ if (!binding) {
1198
1176
  type = 2;
1199
1177
  continue;
1200
1178
  }
1201
- continue;
1202
- }
1203
- type = 2;
1204
- } else type = 2;
1179
+ if (binding.kind === "module") {
1180
+ const decl = binding.path.parent;
1181
+ if (MARKO_FILE_REG.test(decl.source.value) && decl.specifiers.some((it) => _marko_compiler.types.isImportDefaultSpecifier(it))) {
1182
+ const resolvedImport = decl.extra?.tagImport || decl.source.value;
1183
+ if (type === void 0) {
1184
+ type = 1;
1185
+ tagNameImported = resolvedImport;
1186
+ tagNameLoad = decl.extra?.loadImport;
1187
+ } else if (type === 0) {
1188
+ type = 2;
1189
+ tagNameImported = void 0;
1190
+ } else if (tagNameImported !== resolvedImport) tagNameImported = void 0;
1191
+ } else type = 2;
1192
+ continue;
1193
+ }
1194
+ const bindingTag = binding.path;
1195
+ if (bindingTag.isMarkoTag() && binding.kind === "local") {
1196
+ const bindingTagName = bindingTag.get("name").node.value;
1197
+ if (bindingTagName === "const") {
1198
+ pending.push(bindingTag.get("attributes")[0].get("value"));
1199
+ continue;
1200
+ }
1201
+ if (bindingTagName === "let") {
1202
+ type = 2;
1203
+ continue;
1204
+ }
1205
+ continue;
1206
+ }
1207
+ type = 2;
1208
+ } else type = 2;
1209
+ }
1205
1210
  extra.tagNameType = type ?? 2;
1206
1211
  extra.tagNameNullable = nullable;
1207
1212
  if (type === 1 && tagNameImported) {
@@ -1475,9 +1480,10 @@ function finalizeFunctionRegistry() {
1475
1480
  function canIgnoreRegister(markoRoot, exprRoot) {
1476
1481
  return markoRoot.isMarkoPlaceholder() || markoRoot.isMarkoScriptlet() && (!markoRoot.node.static || markoRoot.node.target === "server") || markoRoot.isMarkoTag() && markoRoot.node.name == exprRoot.node || isMarkoAttribute(markoRoot) && (analyzeTagNameType(markoRoot.parentPath) === 0 && /^on[A-Z-]/.test(markoRoot.node.name) && !hasSpreadAttributeAfter(markoRoot) || isCoreTagName(markoRoot.parentPath, "script") || isCoreTagName(markoRoot.parentPath, "lifecycle") || isCoreTagName(markoRoot.parentPath, "for"));
1477
1482
  }
1478
- function getStaticDeclRefs(fnExtra, path, refs = /* @__PURE__ */ new Set()) {
1483
+ function getStaticDeclRefs(fnExtra, path, refs = /* @__PURE__ */ new Set(), seen = /* @__PURE__ */ new Set()) {
1479
1484
  const decl = getDeclarationRoot(path);
1480
- if (decl) {
1485
+ if (decl && !seen.has(decl.node)) {
1486
+ seen.add(decl.node);
1481
1487
  const ids = decl.getOuterBindingIdentifiers();
1482
1488
  if (ids) for (const name in ids) {
1483
1489
  const binding = decl.scope.getBinding(name);
@@ -1488,7 +1494,7 @@ function getStaticDeclRefs(fnExtra, path, refs = /* @__PURE__ */ new Set()) {
1488
1494
  const markoRoot = getMarkoRoot(exprRoot);
1489
1495
  if (!markoRoot || canIgnoreRegister(markoRoot, exprRoot)) continue;
1490
1496
  if (isStaticRoot(markoRoot)) {
1491
- if (getStaticDeclRefs(fnExtra, ref, refs) === true) return true;
1497
+ if (getStaticDeclRefs(fnExtra, ref, refs, seen) === true) return true;
1492
1498
  } else if (shouldAlwaysRegister(markoRoot)) return true;
1493
1499
  else refs.add(exprRoot.node.extra ??= {});
1494
1500
  }
@@ -1974,7 +1980,7 @@ function normalizedValueMatches(a, b) {
1974
1980
  return false;
1975
1981
  }
1976
1982
  function normalizeStrAttrValue(value) {
1977
- return value && value !== true || value === 0 ? value + "" : "";
1983
+ return isNotVoid(value) && value !== true ? value + "" : "";
1978
1984
  }
1979
1985
  //#endregion
1980
1986
  //#region src/html/dynamic-tag.ts
@@ -2119,16 +2125,8 @@ function getCompatRuntimeFile() {
2119
2125
  //#endregion
2120
2126
  //#region src/translator/util/setup-statements.ts
2121
2127
  /**
2122
- * Tracks, during analyze, whether translate will add statements to a
2123
- * section's setup signal (the signal keyed by no referenced bindings).
2124
- * Sites that key statements by an expression's resolved references register
2125
- * the expression with `addSetupExpr`; sites that always target the setup
2126
- * signal call `addSetupStatement`. Expressions that resolve references
2127
- * through `mergeReferences` are covered centrally by `finalizeReferences`.
2128
- *
2129
- * This lets a template's analyze phase prove its setup export is a noop so
2130
- * parent templates can skip importing and calling it. The proof is checked
2131
- * when the template itself is translated (see `visitors/program/dom.ts`).
2128
+ * Tracks during analyze whether translate will add setup-signal statements, so a
2129
+ * template can prove its setup export is a noop and parents can skip calling it.
2132
2130
  */
2133
2131
  const [getSetupInfo] = createSectionState("setupStatements", () => ({
2134
2132
  forced: false,
@@ -2898,7 +2896,6 @@ function getSignal(section, referencedBindings, name) {
2898
2896
  build: void 0,
2899
2897
  export: !!exportName,
2900
2898
  hasSideEffect: !!(referencedBindings && (Array.isArray(referencedBindings) || referencedBindings.type === 0 || referencedBindings.type === 1 || referencedBindings.section !== section || referencedBindings.closureSections || referencedBindings.hoists)),
2901
- hasDynamicSubscribers: false,
2902
2899
  forcePersist: false,
2903
2900
  inline: void 0,
2904
2901
  extraArgs: void 0,
@@ -3803,7 +3800,7 @@ var for_default = {
3803
3800
  "step"
3804
3801
  ];
3805
3802
  break;
3806
- default: throw tag.buildCodeFrameError("The [`<for>` tag](https://markojs.com/docs/reference/core-tag#for) requires an `of=`, `in=`, or `to=` attribute.");
3803
+ default: throw tag.buildCodeFrameError("The [`<for>` tag](https://markojs.com/docs/reference/core-tag#for) requires an `of=`, `in=`, `to=`, or `until=` attribute.");
3807
3804
  }
3808
3805
  if (!isAttrTag) allowAttrs.push("by");
3809
3806
  const keyAttr = tag.node.attributes.find((attr) => attr.type === "MarkoAttribute" && attr.name === "key");
@@ -4356,6 +4353,10 @@ var native_tag_default = {
4356
4353
  const valueExtra = attr.value.extra ??= {};
4357
4354
  if (_marko_compiler.types.isMarkoAttribute(attr)) {
4358
4355
  if (seen[attr.name]) {
4356
+ (0, _marko_compiler_babel_utils.diagnosticWarn)(tag, {
4357
+ label: `The \`${attr.name}\` attribute is set more than once on \`<${tagName}>\`; only the last value is used.`,
4358
+ loc: attr.loc ?? void 0
4359
+ });
4359
4360
  dropNodes(attr.value);
4360
4361
  continue;
4361
4362
  }
@@ -4397,7 +4398,7 @@ var native_tag_default = {
4397
4398
  if (node.var || hasDynamicAttributes || hasEventHandlers || textPlaceholders || injectNonce || isDynamicControllable(relatedControllable)) {
4398
4399
  const tagExtra = node.extra ??= {};
4399
4400
  const tagSection = getOrCreateSection(tag);
4400
- const nodeBinding = tagExtra[kNativeTagBinding] = createBinding("#" + tagName, 0, tagSection, void 0, void 0, void 0, void 0, !!node.var);
4401
+ const nodeBinding = tagExtra[kNativeTagBinding] = createBinding("#" + tagName.toLowerCase(), 0, tagSection, void 0, void 0, void 0, void 0, !!node.var);
4401
4402
  if (hasEventHandlers) (0, _marko_compiler_babel_utils.getProgram)().node.extra.isInteractive = true;
4402
4403
  if (spreadReferenceNodes) {
4403
4404
  const isMergedSpread = !!relatedControllable;
@@ -5067,7 +5068,7 @@ function getOptimizedOnlyChildNodeBinding(tag, section, branchSize = 1) {
5067
5068
  if (getOnlyChildParentTagName(tag, branchSize)) {
5068
5069
  const parentTag = getParentTag(tag).node;
5069
5070
  const parentTagName = parentTag.name?.value;
5070
- return (parentTag.extra ??= {})[kNativeTagBinding] ??= createBinding("#" + parentTagName, 0, section);
5071
+ return (parentTag.extra ??= {})[kNativeTagBinding] ??= createBinding("#" + parentTagName.toLowerCase(), 0, section);
5071
5072
  } else return (tag.node.extra ??= {})[kNodeRef] ??= createBinding("#text", 0, section);
5072
5073
  }
5073
5074
  //#endregion
@@ -5362,6 +5363,8 @@ function isRoot(tag) {
5362
5363
  //#region src/translator/core/textarea.ts
5363
5364
  function preAnalyze$1(tag) {
5364
5365
  if (tag.node.body.body.length) {
5366
+ const [firstChild] = tag.node.body.body;
5367
+ if (firstChild.type === "MarkoText") firstChild.value = firstChild.value.replace(/^\r?\n/, "");
5365
5368
  const parts = [];
5366
5369
  for (const child of tag.node.body.body) if (child.type === "MarkoText" || child.type === "MarkoPlaceholder" && child.escape) parts.push(child.value);
5367
5370
  else throw tag.hub.file.hub.buildError(child, "Unexpected content in textarea, only text and placeholders are supported.", SyntaxError);
@@ -5602,9 +5605,6 @@ function buildUndefined() {
5602
5605
  //#endregion
5603
5606
  //#region src/translator/visitors/program/index.ts
5604
5607
  let scopeIdentifier;
5605
- function isScopeIdentifier(node) {
5606
- return node === scopeIdentifier;
5607
- }
5608
5608
  var program_default = {
5609
5609
  migrate: {
5610
5610
  enter(program) {
@@ -5922,7 +5922,7 @@ function analyzeParams(rootTagExtra, section, tag, propTree, rootAttrExprs) {
5922
5922
  dropNodes(getAllTagReferenceNodes(tag.node));
5923
5923
  return inputExpr;
5924
5924
  }
5925
- if (!propTree.props || tag.node.arguments?.some((node) => _marko_compiler.types.isSpreadElement(node))) {
5925
+ if (!propTree.props || propTree.rest || tag.node.arguments?.some((node) => _marko_compiler.types.isSpreadElement(node))) {
5926
5926
  const extra = inputExpr.value = mergeReferences(section, tag.node, getAllTagReferenceNodes(tag.node));
5927
5927
  setBindingDownstream(propTree.binding, extra);
5928
5928
  return inputExpr;
@@ -5930,14 +5930,13 @@ function analyzeParams(rootTagExtra, section, tag, propTree, rootAttrExprs) {
5930
5930
  const known = inputExpr.known = {};
5931
5931
  let i = 0;
5932
5932
  if (tag.node.arguments) for (const arg of tag.node.arguments) {
5933
- if (!propTree.props[i]) {
5934
- dropNodes(arg);
5935
- continue;
5936
- }
5937
- const argValueExtra = arg.extra ??= {};
5938
- known[i++] = { value: argValueExtra };
5939
- rootAttrExprs.add(argValueExtra);
5940
- addSetupExpr(section, arg);
5933
+ if (propTree.props[i]) {
5934
+ const argValueExtra = arg.extra ??= {};
5935
+ known[i] = { value: argValueExtra };
5936
+ rootAttrExprs.add(argValueExtra);
5937
+ addSetupExpr(section, arg);
5938
+ } else dropNodes(arg);
5939
+ i++;
5941
5940
  }
5942
5941
  const attrPropsTree = propTree.props[i];
5943
5942
  if (attrPropsTree) known[i] = analyzeAttrs(rootTagExtra, section, tag, attrPropsTree, rootAttrExprs);
@@ -6112,7 +6111,7 @@ function getSingleKnownSpread(attributes) {
6112
6111
  };
6113
6112
  }
6114
6113
  function writeParamsToSignals(tag, propTree, importAlias, info) {
6115
- if (!propTree.props || tag.node.arguments?.some((node) => _marko_compiler.types.isSpreadElement(node))) {
6114
+ if (!propTree.props || propTree.rest || tag.node.arguments?.some((node) => _marko_compiler.types.isSpreadElement(node))) {
6116
6115
  const referencedBindings = tag.node.extra?.referencedBindings;
6117
6116
  const tagInputIdentifier = info.getBindingIdentifier(propTree.binding, `${importAlias}_params`);
6118
6117
  const translatedAttrs = translateAttrs(tag);
@@ -7210,8 +7209,7 @@ function getSectionInstancesAccessor(section) {
7210
7209
  return section.sectionAccessor ? section.sectionAccessor.prefix + getScopeAccessor(section.sectionAccessor.binding) : getAccessorPrefix().ClosureScopes + section.id;
7211
7210
  }
7212
7211
  function getSectionInstancesAccessorLiteral(section) {
7213
- const accessor = getSectionInstancesAccessor(section);
7214
- return accessor ? typeof accessor === "number" ? _marko_compiler.types.numericLiteral(accessor) : _marko_compiler.types.stringLiteral(accessor) : void 0;
7212
+ return _marko_compiler.types.stringLiteral(getSectionInstancesAccessor(section));
7215
7213
  }
7216
7214
  function getReadReplacement(node, signal) {
7217
7215
  const { extra } = node;
@@ -7655,6 +7653,17 @@ var await_default = {
7655
7653
  types: runtime_info_default.name + "/tags/await.d.marko"
7656
7654
  };
7657
7655
  //#endregion
7656
+ //#region src/translator/core/class.ts
7657
+ var class_default = {
7658
+ parse(tag) {
7659
+ throw tag.hub.buildError(tag.node.name, "class {} component blocks are no longer supported. Use <let> and <const> tags for state.");
7660
+ },
7661
+ parseOptions: {
7662
+ statement: true,
7663
+ rawOpenTag: true
7664
+ }
7665
+ };
7666
+ //#endregion
7658
7667
  //#region src/translator/core/client.ts
7659
7668
  var client_default = {
7660
7669
  parse(tag) {
@@ -8246,9 +8255,7 @@ var script_default = {
8246
8255
  if (isOutputDOM()) {
8247
8256
  const isFunction = _marko_compiler.types.isFunctionExpression(value) || _marko_compiler.types.isArrowFunctionExpression(value);
8248
8257
  let inlineBody = null;
8249
- let referencesScope = false;
8250
- if (isFunction) if (value.async || value.generator) referencesScope = traverseContains(value, isScopeIdentifier);
8251
- else if (_marko_compiler.types.isBlockStatement(value.body)) {
8258
+ if (isFunction) if (value.async || value.generator) {} else if (_marko_compiler.types.isBlockStatement(value.body)) {
8252
8259
  if (!traverseContains(value.body, isReturnStatement)) {
8253
8260
  let hasDeclaration = false;
8254
8261
  for (const child of value.body.body) if (_marko_compiler.types.isDeclaration(child)) {
@@ -8258,7 +8265,7 @@ var script_default = {
8258
8265
  inlineBody = hasDeclaration ? value.body : value.body.body;
8259
8266
  }
8260
8267
  } else inlineBody = _marko_compiler.types.expressionStatement(value.body);
8261
- addStatement("effect", section, referencedBindings, inlineBody || _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(value, referencesScope ? [scopeIdentifier] : [])));
8268
+ addStatement("effect", section, referencedBindings, inlineBody || _marko_compiler.types.expressionStatement(_marko_compiler.types.callExpression(value, [])));
8262
8269
  } else addHTMLEffectCall(section, referencedBindings);
8263
8270
  tag.remove();
8264
8271
  } },
@@ -8570,6 +8577,7 @@ const cssGluedBefore = /[\w%]$/;
8570
8577
  //#region src/translator/core/style.ts
8571
8578
  const STYLE_EXT_REG = /^style((?:\.[a-zA-Z0-9$_-]+)+)?/;
8572
8579
  const programStyleCounts = /* @__PURE__ */ new WeakMap();
8580
+ const programDynamicStyleNameCounts = /* @__PURE__ */ new WeakMap();
8573
8581
  var style_default = {
8574
8582
  analyze(tag) {
8575
8583
  (0, _marko_compiler_babel_utils.assertNoArgs)(tag);
@@ -8616,25 +8624,14 @@ function analyzeDynamicStyle(tag, names) {
8616
8624
  }
8617
8625
  function collectDynamicStyleNames(tag) {
8618
8626
  let names;
8619
- let index = 0;
8620
8627
  for (const child of tag.node.body.body) if (_marko_compiler.types.isMarkoPlaceholder(child)) {
8621
- if (!names) {
8622
- names = [];
8623
- index = dynamicStyleNameOffset(tag);
8624
- }
8625
- names.push(dynamicStyleName(tag, index++));
8628
+ const program = (0, _marko_compiler_babel_utils.getProgram)().node;
8629
+ const index = programDynamicStyleNameCounts.get(program) ?? 0;
8630
+ programDynamicStyleNameCounts.set(program, index + 1);
8631
+ (names ??= []).push(dynamicStyleName(tag, index));
8626
8632
  } else if (!_marko_compiler.types.isMarkoText(child)) throw tag.hub.buildError(child, "The [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) only supports text and `${...}` interpolations. For a native html [`<style>` tag](https://markojs.com/docs/reference/core-tag#style) use the `html-style` core tag instead.");
8627
8633
  return names;
8628
8634
  }
8629
- function dynamicStyleNameOffset(tag) {
8630
- const { start } = tag.node;
8631
- let offset = 0;
8632
- if (start != null) _marko_compiler.types.traverseFast((0, _marko_compiler_babel_utils.getProgram)().node, (node) => {
8633
- const dynamicStyle = node.extra?.dynamicStyle;
8634
- if (dynamicStyle && node.start != null && node.start < start) offset += dynamicStyle.names.length;
8635
- });
8636
- return offset;
8637
- }
8638
8635
  const styleNameUnsafeReg = /[^a-zA-Z0-9_]/g;
8639
8636
  const encodeStyleNameChar = (c) => "-" + c.charCodeAt(0).toString(36);
8640
8637
  function dynamicStyleName(tag, index) {
@@ -8718,9 +8715,8 @@ function buildStyleDecls(node) {
8718
8715
  return normalizeStringExpression(parts);
8719
8716
  }
8720
8717
  /**
8721
- * Resolves a `<style>` block's text content to its client side import path
8722
- * (eg `./template.marko.css`) by handing the css off to the configured
8723
- * `resolveVirtualDependency` hook.
8718
+ * Resolves a `<style>` block's text to its client-side import path by handing
8719
+ * the css to the configured `resolveVirtualDependency` hook.
8724
8720
  */
8725
8721
  function getStyleImportPath(file, node, names) {
8726
8722
  const { resolveVirtualDependency, sourceMaps } = file.markoOpts;
@@ -8861,6 +8857,7 @@ var core_default = {
8861
8857
  taglibId: runtime_info_default.taglibId,
8862
8858
  "<attrs>": attrs_default,
8863
8859
  "<await>": await_default,
8860
+ "<class>": class_default,
8864
8861
  "<client>": client_default,
8865
8862
  "<const>": const_default,
8866
8863
  "<debug>": debug_default,
@@ -154,7 +154,7 @@ export declare function getDebugName(binding: Binding): string;
154
154
  export declare function getDebugNames(refs: ReferencedBindings): string;
155
155
  export declare function getDebugNamesAsIdentifier(refs: ReferencedBindings): string;
156
156
  export declare function getSectionInstancesAccessor(section: Section): string;
157
- export declare function getSectionInstancesAccessorLiteral(section: Section): t.NumericLiteral | t.StringLiteral | undefined;
157
+ export declare function getSectionInstancesAccessorLiteral(section: Section): t.StringLiteral;
158
158
  export declare function getReadReplacement(node: t.Identifier | t.MemberExpression | t.OptionalMemberExpression, signal?: Signal): t.Expression | undefined;
159
159
  export declare function isInvokeOnlyBinding(binding: Binding): boolean;
160
160
  export declare function hasNonConstantPropertyAlias(ref: Binding): boolean;
@@ -18,7 +18,6 @@ export interface Signal {
18
18
  renderReferencedBindings: ReferencedBindings;
19
19
  effect: t.Statement[];
20
20
  effectReferencedBindings: ReferencedBindings;
21
- hasDynamicSubscribers: boolean;
22
21
  hasSideEffect: boolean;
23
22
  forcePersist: boolean;
24
23
  inline: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marko",
3
- "version": "6.3.15",
3
+ "version": "6.3.16",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",