@marko/runtime-tags 6.3.3 → 6.3.5

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.
@@ -8,7 +8,6 @@ export declare enum AccessorPrefix {
8
8
  ControlledValue = "G",
9
9
  DynamicHTMLLastChild = "H",
10
10
  EventAttributes = "I",
11
- Getter = "J",
12
11
  KeyedScopes = "O",
13
12
  Lifecycle = "K",
14
13
  Promise = "L",
@@ -8,7 +8,6 @@ export declare enum AccessorPrefix {
8
8
  ControlledValue = "ControlledValue:",
9
9
  DynamicHTMLLastChild = "DynamicHTMLLastChild:",
10
10
  EventAttributes = "EventAttributes:",
11
- Getter = "Getter:",
12
11
  KeyedScopes = "KeyedScopes:",
13
12
  Lifecycle = "Lifecycle:",
14
13
  Promise = "Promise:",
package/dist/debug/dom.js CHANGED
@@ -1974,6 +1974,7 @@ const RENDER_BODY_ID = "$compat_renderBody";
1974
1974
  //#endregion
1975
1975
  //#region src/dom/compat.ts
1976
1976
  const classIdToBranch = /* @__PURE__ */ new Map();
1977
+ let classEventResolver;
1977
1978
  const scopesByRender = /* @__PURE__ */ new WeakMap();
1978
1979
  const getRenderScopes = ($global) => {
1979
1980
  const render = self[$global.runtimeId]?.[$global.renderId];
@@ -1988,9 +1989,16 @@ const compat = {
1988
1989
  _resume(SET_SCOPE_REGISTER_ID, (scope) => {
1989
1990
  getRenderScopes(scope["$global"])[scope["#Id"]] = scope;
1990
1991
  if (scope.m5c) classIdToBranch.set(scope.m5c, scope);
1992
+ if (classEventResolver) for (const key in scope) {
1993
+ const resolved = classEventResolver(scope[key], scope);
1994
+ if (resolved !== scope[key]) scope[key] = resolved;
1995
+ }
1991
1996
  });
1992
1997
  _resume(RENDER_BODY_ID, warp10Noop);
1993
1998
  },
1999
+ setClassEventResolver(fn) {
2000
+ classEventResolver = fn;
2001
+ },
1994
2002
  getScope($global, scopeId) {
1995
2003
  return getRenderScopes($global)?.[scopeId];
1996
2004
  },
@@ -1972,6 +1972,7 @@ const RENDER_BODY_ID = "$compat_renderBody";
1972
1972
  //#endregion
1973
1973
  //#region src/dom/compat.ts
1974
1974
  const classIdToBranch = /* @__PURE__ */ new Map();
1975
+ let classEventResolver;
1975
1976
  const scopesByRender = /* @__PURE__ */ new WeakMap();
1976
1977
  const getRenderScopes = ($global) => {
1977
1978
  const render = self[$global.runtimeId]?.[$global.renderId];
@@ -1986,9 +1987,16 @@ const compat = {
1986
1987
  _resume(SET_SCOPE_REGISTER_ID, (scope) => {
1987
1988
  getRenderScopes(scope["$global"])[scope["#Id"]] = scope;
1988
1989
  if (scope.m5c) classIdToBranch.set(scope.m5c, scope);
1990
+ if (classEventResolver) for (const key in scope) {
1991
+ const resolved = classEventResolver(scope[key], scope);
1992
+ if (resolved !== scope[key]) scope[key] = resolved;
1993
+ }
1989
1994
  });
1990
1995
  _resume(RENDER_BODY_ID, warp10Noop);
1991
1996
  },
1997
+ setClassEventResolver(fn) {
1998
+ classEventResolver = fn;
1999
+ },
1992
2000
  getScope($global, scopeId) {
1993
2001
  return getRenderScopes($global)?.[scopeId];
1994
2002
  },
@@ -247,6 +247,8 @@ function _escape_comment(val) {
247
247
  const K_SCOPE_ID = Symbol("Scope ID");
248
248
  const kTouchedIterator = Symbol.for("marko.touchedIterator");
249
249
  const { hasOwnProperty: hasOwnProperty$1 } = {};
250
+ const objectProto = Object.prototype;
251
+ const arrayProto = Array.prototype;
250
252
  const Generator = (function* () {})().constructor;
251
253
  const AsyncGenerator = (async function* () {})().constructor;
252
254
  patchIteratorNext(Generator.prototype);
@@ -685,12 +687,6 @@ function writeProp(state, val, parent, accessor) {
685
687
  }
686
688
  }
687
689
  function writeReferenceOr(state, write, val, parent, accessor) {
688
- const scopeId = val[K_SCOPE_ID];
689
- if (scopeId !== void 0) {
690
- trackScope(state, val, scopeId);
691
- state.buf.push("_(" + scopeId + ")");
692
- return true;
693
- }
694
690
  let ref = state.refs.get(val);
695
691
  if (ref) {
696
692
  if (!trackChannel(state, ref)) {
@@ -811,6 +807,12 @@ function writeNull(state) {
811
807
  }
812
808
  function writeObject(state, val, parent, accessor) {
813
809
  if (val === null) return writeNull(state);
810
+ const scopeId = val[K_SCOPE_ID];
811
+ if (scopeId !== void 0) {
812
+ trackScope(state, val, scopeId);
813
+ state.buf.push("_(" + scopeId + ")");
814
+ return true;
815
+ }
814
816
  const wellKnownObject = KNOWN_OBJECTS.get(val);
815
817
  if (wellKnownObject) {
816
818
  state.buf.push(wellKnownObject);
@@ -819,7 +821,10 @@ function writeObject(state, val, parent, accessor) {
819
821
  return writeReferenceOr(state, writeUnknownObject, val, parent, accessor);
820
822
  }
821
823
  function writeUnknownObject(state, val, ref) {
822
- switch (Object.getPrototypeOf(val)?.constructor) {
824
+ const proto = Object.getPrototypeOf(val);
825
+ if (proto === objectProto) return writePlainObject(state, val, ref);
826
+ if (proto === arrayProto) return writeArray(state, val, ref);
827
+ switch (proto?.constructor) {
823
828
  case void 0: return writeNullObject(state, val, ref);
824
829
  case Object: return writePlainObject(state, val, ref);
825
830
  case Array: return writeArray(state, val, ref);
@@ -863,7 +868,7 @@ function writeUnknownObject(state, val, ref) {
863
868
  }
864
869
  function writePlainObject(state, val, ref) {
865
870
  state.buf.push("{");
866
- writeObjectProps(state, val, ref);
871
+ writeMaybeIterableProps(state, val, ref);
867
872
  state.buf.push("}");
868
873
  return true;
869
874
  }
@@ -1212,7 +1217,7 @@ function writeAsyncGenerator(state, iter, ref) {
1212
1217
  }
1213
1218
  function writeNullObject(state, val, ref) {
1214
1219
  state.buf.push("{");
1215
- state.buf.push(writeObjectProps(state, val, ref) + "__proto__:null}");
1220
+ state.buf.push(writeMaybeIterableProps(state, val, ref) + "__proto__:null}");
1216
1221
  return true;
1217
1222
  }
1218
1223
  function writeObjectProps(state, val, ref) {
@@ -1223,6 +1228,10 @@ function writeObjectProps(state, val, ref) {
1223
1228
  if (writeProp(state, val[key], ref, escapedKey)) sep = ",";
1224
1229
  else state.buf.pop();
1225
1230
  }
1231
+ return sep;
1232
+ }
1233
+ function writeMaybeIterableProps(state, val, ref) {
1234
+ let sep = writeObjectProps(state, val, ref);
1226
1235
  if (hasSymbolIterator(val)) {
1227
1236
  let yieldSelf = "";
1228
1237
  const iterArr = [];
@@ -1309,14 +1318,19 @@ function isCircular(parent, ref) {
1309
1318
  function toObjectKey(name) {
1310
1319
  if (name === "") return "\"\"";
1311
1320
  if (name === "__proto__") return "[\"__proto__\"]";
1312
- const startChar = name[0];
1313
- if (isDigit(startChar)) {
1314
- if (startChar === "0") {
1315
- if (name !== "0") return quote(name, 1);
1316
- } else for (let i = 1; i < name.length; i++) if (!isDigit(name[i])) return quote(name, i);
1317
- } else if (isWord(startChar)) {
1318
- for (let i = 1; i < name.length; i++) if (!isWordOrDigit(name[i])) return quote(name, i);
1319
- } else return quote(name, 0);
1321
+ const len = name.length;
1322
+ const c0 = name.charCodeAt(0);
1323
+ if (c0 >= 48 && c0 <= 57) if (c0 === 48) {
1324
+ if (len !== 1) return quote(name, 1);
1325
+ } else for (let i = 1; i < len; i++) {
1326
+ const c = name.charCodeAt(i);
1327
+ if (c < 48 || c > 57) return quote(name, i);
1328
+ }
1329
+ else if (c0 >= 97 && c0 <= 122 || c0 >= 65 && c0 <= 90 || c0 === 95 || c0 === 36) for (let i = 1; i < len; i++) {
1330
+ const c = name.charCodeAt(i);
1331
+ if (!(c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 95 || c === 36)) return quote(name, i);
1332
+ }
1333
+ else return quote(name, 0);
1320
1334
  return name;
1321
1335
  }
1322
1336
  function toAccess(accessor) {
@@ -1459,15 +1473,6 @@ function hasOnlyZeros(typedArray) {
1459
1473
  for (let i = 0; i < typedArray.length; i++) if (typedArray[i] !== 0) return false;
1460
1474
  return true;
1461
1475
  }
1462
- function isWordOrDigit(char) {
1463
- return isWord(char) || isDigit(char);
1464
- }
1465
- function isDigit(char) {
1466
- return char >= "0" && char <= "9";
1467
- }
1468
- function isWord(char) {
1469
- return char >= "a" && char <= "z" || char >= "A" && char <= "Z" || char === "_" || char === "$";
1470
- }
1471
1476
  function patchIteratorNext(proto) {
1472
1477
  if (proto.next[kTouchedIterator]) return;
1473
1478
  const { next } = proto;
@@ -2900,6 +2905,7 @@ var ServerRendered = class {
2900
2905
  pipe(stream) {
2901
2906
  this.#read((html) => {
2902
2907
  stream.write(html);
2908
+ stream.flush?.();
2903
2909
  }, (err) => {
2904
2910
  const socket = "socket" in stream && stream.socket;
2905
2911
  if (socket && typeof socket.destroySoon === "function") socket.destroySoon();
@@ -2910,10 +2916,13 @@ var ServerRendered = class {
2910
2916
  }
2911
2917
  toReadable() {
2912
2918
  let cancelled = false;
2919
+ let started = false;
2913
2920
  let boundary;
2914
2921
  const encoder = new TextEncoder();
2915
2922
  return new ReadableStream({
2916
- start: (ctrl) => {
2923
+ pull: (ctrl) => {
2924
+ if (started) return;
2925
+ started = true;
2917
2926
  boundary = this.#read((html) => {
2918
2927
  ctrl.enqueue(encoder.encode(html));
2919
2928
  }, (err) => {
@@ -2928,7 +2937,7 @@ var ServerRendered = class {
2928
2937
  cancelled = true;
2929
2938
  boundary?.abort(reason);
2930
2939
  }
2931
- });
2940
+ }, { highWaterMark: 0 });
2932
2941
  }
2933
2942
  then(onfulfilled, onrejected) {
2934
2943
  return this.#promise().then(onfulfilled, onrejected);
@@ -3153,7 +3162,7 @@ const compat = {
3153
3162
  if (boundary.flush() === 1) throw new Error("Cannot serialize promise across tags/class compat layer.");
3154
3163
  return new Chunk(boundary, null, null, state).flushScript().scripts;
3155
3164
  },
3156
- render(renderer, willRerender, classAPIOut, component, input, completeChunks) {
3165
+ render(renderer, willRerender, classAPIOut, component, input, completeChunks, registerChildScope) {
3157
3166
  const state = this.ensureState(classAPIOut.global);
3158
3167
  const boundary = new Boundary(state);
3159
3168
  let head = new Chunk(boundary, null, null, state);
@@ -3163,7 +3172,7 @@ const compat = {
3163
3172
  for (const key in input) normalizedInput[key === "renderBody" ? "content" : key] = input[key];
3164
3173
  }
3165
3174
  head.render(() => {
3166
- if (willRerender) {
3175
+ if (willRerender || registerChildScope) {
3167
3176
  const scopeId = _peek_scope_id();
3168
3177
  writeScope(scopeId, { m5c: component.id });
3169
3178
  _script(scopeId, SET_SCOPE_REGISTER_ID);
@@ -245,6 +245,8 @@ function _escape_comment(val) {
245
245
  const K_SCOPE_ID = Symbol("Scope ID");
246
246
  const kTouchedIterator = Symbol.for("marko.touchedIterator");
247
247
  const { hasOwnProperty: hasOwnProperty$1 } = {};
248
+ const objectProto = Object.prototype;
249
+ const arrayProto = Array.prototype;
248
250
  const Generator = (function* () {})().constructor;
249
251
  const AsyncGenerator = (async function* () {})().constructor;
250
252
  patchIteratorNext(Generator.prototype);
@@ -683,12 +685,6 @@ function writeProp(state, val, parent, accessor) {
683
685
  }
684
686
  }
685
687
  function writeReferenceOr(state, write, val, parent, accessor) {
686
- const scopeId = val[K_SCOPE_ID];
687
- if (scopeId !== void 0) {
688
- trackScope(state, val, scopeId);
689
- state.buf.push("_(" + scopeId + ")");
690
- return true;
691
- }
692
688
  let ref = state.refs.get(val);
693
689
  if (ref) {
694
690
  if (!trackChannel(state, ref)) {
@@ -809,6 +805,12 @@ function writeNull(state) {
809
805
  }
810
806
  function writeObject(state, val, parent, accessor) {
811
807
  if (val === null) return writeNull(state);
808
+ const scopeId = val[K_SCOPE_ID];
809
+ if (scopeId !== void 0) {
810
+ trackScope(state, val, scopeId);
811
+ state.buf.push("_(" + scopeId + ")");
812
+ return true;
813
+ }
812
814
  const wellKnownObject = KNOWN_OBJECTS.get(val);
813
815
  if (wellKnownObject) {
814
816
  state.buf.push(wellKnownObject);
@@ -817,7 +819,10 @@ function writeObject(state, val, parent, accessor) {
817
819
  return writeReferenceOr(state, writeUnknownObject, val, parent, accessor);
818
820
  }
819
821
  function writeUnknownObject(state, val, ref) {
820
- switch (Object.getPrototypeOf(val)?.constructor) {
822
+ const proto = Object.getPrototypeOf(val);
823
+ if (proto === objectProto) return writePlainObject(state, val, ref);
824
+ if (proto === arrayProto) return writeArray(state, val, ref);
825
+ switch (proto?.constructor) {
821
826
  case void 0: return writeNullObject(state, val, ref);
822
827
  case Object: return writePlainObject(state, val, ref);
823
828
  case Array: return writeArray(state, val, ref);
@@ -861,7 +866,7 @@ function writeUnknownObject(state, val, ref) {
861
866
  }
862
867
  function writePlainObject(state, val, ref) {
863
868
  state.buf.push("{");
864
- writeObjectProps(state, val, ref);
869
+ writeMaybeIterableProps(state, val, ref);
865
870
  state.buf.push("}");
866
871
  return true;
867
872
  }
@@ -1210,7 +1215,7 @@ function writeAsyncGenerator(state, iter, ref) {
1210
1215
  }
1211
1216
  function writeNullObject(state, val, ref) {
1212
1217
  state.buf.push("{");
1213
- state.buf.push(writeObjectProps(state, val, ref) + "__proto__:null}");
1218
+ state.buf.push(writeMaybeIterableProps(state, val, ref) + "__proto__:null}");
1214
1219
  return true;
1215
1220
  }
1216
1221
  function writeObjectProps(state, val, ref) {
@@ -1221,6 +1226,10 @@ function writeObjectProps(state, val, ref) {
1221
1226
  if (writeProp(state, val[key], ref, escapedKey)) sep = ",";
1222
1227
  else state.buf.pop();
1223
1228
  }
1229
+ return sep;
1230
+ }
1231
+ function writeMaybeIterableProps(state, val, ref) {
1232
+ let sep = writeObjectProps(state, val, ref);
1224
1233
  if (hasSymbolIterator(val)) {
1225
1234
  let yieldSelf = "";
1226
1235
  const iterArr = [];
@@ -1307,14 +1316,19 @@ function isCircular(parent, ref) {
1307
1316
  function toObjectKey(name) {
1308
1317
  if (name === "") return "\"\"";
1309
1318
  if (name === "__proto__") return "[\"__proto__\"]";
1310
- const startChar = name[0];
1311
- if (isDigit(startChar)) {
1312
- if (startChar === "0") {
1313
- if (name !== "0") return quote(name, 1);
1314
- } else for (let i = 1; i < name.length; i++) if (!isDigit(name[i])) return quote(name, i);
1315
- } else if (isWord(startChar)) {
1316
- for (let i = 1; i < name.length; i++) if (!isWordOrDigit(name[i])) return quote(name, i);
1317
- } else return quote(name, 0);
1319
+ const len = name.length;
1320
+ const c0 = name.charCodeAt(0);
1321
+ if (c0 >= 48 && c0 <= 57) if (c0 === 48) {
1322
+ if (len !== 1) return quote(name, 1);
1323
+ } else for (let i = 1; i < len; i++) {
1324
+ const c = name.charCodeAt(i);
1325
+ if (c < 48 || c > 57) return quote(name, i);
1326
+ }
1327
+ else if (c0 >= 97 && c0 <= 122 || c0 >= 65 && c0 <= 90 || c0 === 95 || c0 === 36) for (let i = 1; i < len; i++) {
1328
+ const c = name.charCodeAt(i);
1329
+ if (!(c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 95 || c === 36)) return quote(name, i);
1330
+ }
1331
+ else return quote(name, 0);
1318
1332
  return name;
1319
1333
  }
1320
1334
  function toAccess(accessor) {
@@ -1457,15 +1471,6 @@ function hasOnlyZeros(typedArray) {
1457
1471
  for (let i = 0; i < typedArray.length; i++) if (typedArray[i] !== 0) return false;
1458
1472
  return true;
1459
1473
  }
1460
- function isWordOrDigit(char) {
1461
- return isWord(char) || isDigit(char);
1462
- }
1463
- function isDigit(char) {
1464
- return char >= "0" && char <= "9";
1465
- }
1466
- function isWord(char) {
1467
- return char >= "a" && char <= "z" || char >= "A" && char <= "Z" || char === "_" || char === "$";
1468
- }
1469
1474
  function patchIteratorNext(proto) {
1470
1475
  if (proto.next[kTouchedIterator]) return;
1471
1476
  const { next } = proto;
@@ -2898,6 +2903,7 @@ var ServerRendered = class {
2898
2903
  pipe(stream) {
2899
2904
  this.#read((html) => {
2900
2905
  stream.write(html);
2906
+ stream.flush?.();
2901
2907
  }, (err) => {
2902
2908
  const socket = "socket" in stream && stream.socket;
2903
2909
  if (socket && typeof socket.destroySoon === "function") socket.destroySoon();
@@ -2908,10 +2914,13 @@ var ServerRendered = class {
2908
2914
  }
2909
2915
  toReadable() {
2910
2916
  let cancelled = false;
2917
+ let started = false;
2911
2918
  let boundary;
2912
2919
  const encoder = new TextEncoder();
2913
2920
  return new ReadableStream({
2914
- start: (ctrl) => {
2921
+ pull: (ctrl) => {
2922
+ if (started) return;
2923
+ started = true;
2915
2924
  boundary = this.#read((html) => {
2916
2925
  ctrl.enqueue(encoder.encode(html));
2917
2926
  }, (err) => {
@@ -2926,7 +2935,7 @@ var ServerRendered = class {
2926
2935
  cancelled = true;
2927
2936
  boundary?.abort(reason);
2928
2937
  }
2929
- });
2938
+ }, { highWaterMark: 0 });
2930
2939
  }
2931
2940
  then(onfulfilled, onrejected) {
2932
2941
  return this.#promise().then(onfulfilled, onrejected);
@@ -3151,7 +3160,7 @@ const compat = {
3151
3160
  if (boundary.flush() === 1) throw new Error("Cannot serialize promise across tags/class compat layer.");
3152
3161
  return new Chunk(boundary, null, null, state).flushScript().scripts;
3153
3162
  },
3154
- render(renderer, willRerender, classAPIOut, component, input, completeChunks) {
3163
+ render(renderer, willRerender, classAPIOut, component, input, completeChunks, registerChildScope) {
3155
3164
  const state = this.ensureState(classAPIOut.global);
3156
3165
  const boundary = new Boundary(state);
3157
3166
  let head = new Chunk(boundary, null, null, state);
@@ -3161,7 +3170,7 @@ const compat = {
3161
3170
  for (const key in input) normalizedInput[key === "renderBody" ? "content" : key] = input[key];
3162
3171
  }
3163
3172
  head.render(() => {
3164
- if (willRerender) {
3173
+ if (willRerender || registerChildScope) {
3165
3174
  const scopeId = _peek_scope_id();
3166
3175
  writeScope(scopeId, { m5c: component.id });
3167
3176
  _script(scopeId, SET_SCOPE_REGISTER_ID);
@@ -6,6 +6,7 @@ export declare const compat: {
6
6
  patchDynamicTag: typeof patchDynamicTag;
7
7
  queueEffect: typeof queueEffect;
8
8
  init(warp10Noop: any): void;
9
+ setClassEventResolver(fn: (value: unknown, scope: Scope) => unknown): void;
9
10
  getScope($global: Record<string, unknown>, scopeId: unknown): Scope | undefined;
10
11
  setRendererId(renderer: any, id: unknown): void;
11
12
  isRenderer(renderer: any): any;
package/dist/dom.js CHANGED
@@ -51,7 +51,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
51
51
  typeof by == "string" ? forOf(all, (item, i) => cb(item[by], [item, i])) : forOf(all, (item, i) => cb(by(item, i), [item, i]));
52
52
  }), _for_in = /* @__PURE__ */ loop(([obj, by = byFirstArg], cb) => forIn(obj, (key, value) => cb(by(key, value), [key, value]))), _for_to = /* @__PURE__ */ loop(([to, from, step, by = byFirstArg], cb) => forTo(to, from, step, (v) => cb(by(v), [v]))), _for_until = /* @__PURE__ */ loop(([until, from, step, by = byFirstArg], cb) => forUntil(until, from, step, (v) => cb(by(v), [v]))), rendering, runId = 2, caughtError = /* @__PURE__ */ new WeakSet(), placeholderShown = /* @__PURE__ */ new WeakSet(), pendingEffects = [], pendingRenders = [], runEffects = ((effects) => {
53
53
  for (let i = 0; i < effects.length;) effects[i++](effects[i++]);
54
- }), runRender = (render) => render.c(render.b, render.d), catchEnabled, classIdToBranch = /* @__PURE__ */ new Map(), scopesByRender = /* @__PURE__ */ new WeakMap(), getRenderScopes = ($global) => {
54
+ }), runRender = (render) => render.c(render.b, render.d), catchEnabled, classIdToBranch = /* @__PURE__ */ new Map(), classEventResolver, scopesByRender = /* @__PURE__ */ new WeakMap(), getRenderScopes = ($global) => {
55
55
  let render = self[$global.runtimeId]?.[$global.renderId], scopes = render && scopesByRender.get(render);
56
56
  return render && !scopes && scopesByRender.set(render, scopes = {}), scopes;
57
57
  }, compat = {
@@ -59,9 +59,15 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
59
59
  queueEffect,
60
60
  init(warp10Noop) {
61
61
  _resume("$C_s", (scope) => {
62
- getRenderScopes(scope.$)[scope.L] = scope, scope.m5c && classIdToBranch.set(scope.m5c, scope);
62
+ if (getRenderScopes(scope.$)[scope.L] = scope, scope.m5c && classIdToBranch.set(scope.m5c, scope), classEventResolver) for (let key in scope) {
63
+ let resolved = classEventResolver(scope[key], scope);
64
+ resolved !== scope[key] && (scope[key] = resolved);
65
+ }
63
66
  }), _resume("$C_b", warp10Noop);
64
67
  },
68
+ setClassEventResolver(fn) {
69
+ classEventResolver = fn;
70
+ },
65
71
  getScope($global, scopeId) {
66
72
  return getRenderScopes($global)?.[scopeId];
67
73
  },
package/dist/dom.mjs CHANGED
@@ -51,7 +51,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
51
51
  typeof by == "string" ? forOf(all, (item, i) => cb(item[by], [item, i])) : forOf(all, (item, i) => cb(by(item, i), [item, i]));
52
52
  }), _for_in = /* @__PURE__ */ loop(([obj, by = byFirstArg], cb) => forIn(obj, (key, value) => cb(by(key, value), [key, value]))), _for_to = /* @__PURE__ */ loop(([to, from, step, by = byFirstArg], cb) => forTo(to, from, step, (v) => cb(by(v), [v]))), _for_until = /* @__PURE__ */ loop(([until, from, step, by = byFirstArg], cb) => forUntil(until, from, step, (v) => cb(by(v), [v]))), rendering, runId = 2, caughtError = /* @__PURE__ */ new WeakSet(), placeholderShown = /* @__PURE__ */ new WeakSet(), pendingEffects = [], pendingRenders = [], runEffects = ((effects) => {
53
53
  for (let i = 0; i < effects.length;) effects[i++](effects[i++]);
54
- }), runRender = (render) => render.c(render.b, render.d), catchEnabled, classIdToBranch = /* @__PURE__ */ new Map(), scopesByRender = /* @__PURE__ */ new WeakMap(), getRenderScopes = ($global) => {
54
+ }), runRender = (render) => render.c(render.b, render.d), catchEnabled, classIdToBranch = /* @__PURE__ */ new Map(), classEventResolver, scopesByRender = /* @__PURE__ */ new WeakMap(), getRenderScopes = ($global) => {
55
55
  let render = self[$global.runtimeId]?.[$global.renderId], scopes = render && scopesByRender.get(render);
56
56
  return render && !scopes && scopesByRender.set(render, scopes = {}), scopes;
57
57
  }, compat = {
@@ -59,9 +59,15 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
59
59
  queueEffect,
60
60
  init(warp10Noop) {
61
61
  _resume("$C_s", (scope) => {
62
- getRenderScopes(scope.$)[scope.L] = scope, scope.m5c && classIdToBranch.set(scope.m5c, scope);
62
+ if (getRenderScopes(scope.$)[scope.L] = scope, scope.m5c && classIdToBranch.set(scope.m5c, scope), classEventResolver) for (let key in scope) {
63
+ let resolved = classEventResolver(scope[key], scope);
64
+ resolved !== scope[key] && (scope[key] = resolved);
65
+ }
63
66
  }), _resume("$C_b", warp10Noop);
64
67
  },
68
+ setClassEventResolver(fn) {
69
+ classEventResolver = fn;
70
+ },
65
71
  getScope($global, scopeId) {
66
72
  return getRenderScopes($global)?.[scopeId];
67
73
  },
@@ -16,7 +16,7 @@ export declare const compat: {
16
16
  writeSetScopeForComponent(branchId: number, m5c: string, m5i: unknown): void;
17
17
  toJSON(): (this: WeakKey) => [registryId: string, scopeId: unknown] | undefined;
18
18
  flushScript($global: any): string;
19
- render(renderer: ServerRenderer, willRerender: boolean, classAPIOut: any, component: any, input: any, completeChunks: Chunk[]): void;
19
+ render(renderer: ServerRenderer, willRerender: boolean, classAPIOut: any, component: any, input: any, completeChunks: Chunk[], registerChildScope?: boolean): void;
20
20
  register: typeof register;
21
21
  registerRenderBody(fn: any): void;
22
22
  };
package/dist/html.js CHANGED
@@ -4,7 +4,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
4
4
  else if (Array.isArray(val)) for (let v of val) part = toDelimitedString(v, delimiter, stringify), part && (str += sep + part, sep = delimiter);
5
5
  else for (let name in val) part = stringify(name, val[name]), part && (str += sep + part, sep = delimiter);
6
6
  return str;
7
- }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<(\/?script|!--)/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
7
+ }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<(\/?script|!--)/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, objectProto = Object.prototype, arrayProto = Array.prototype, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
8
8
  let KNOWN_SYMBOLS = /* @__PURE__ */ new Map();
9
9
  for (let name of Object.getOwnPropertyNames(Symbol)) {
10
10
  let symbol = Symbol[name];
@@ -323,14 +323,14 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
323
323
  if (boundary.flush() === 1) throw Error("Cannot serialize promise across tags/class compat layer.");
324
324
  return new Chunk(boundary, null, null, state).flushScript().scripts;
325
325
  },
326
- render(renderer, willRerender, classAPIOut, component, input, completeChunks) {
326
+ render(renderer, willRerender, classAPIOut, component, input, completeChunks, registerChildScope) {
327
327
  let state = this.ensureState(classAPIOut.global), boundary = new Boundary(state), head = new Chunk(boundary, null, null, state), normalizedInput = input;
328
328
  if ("renderBody" in input) {
329
329
  normalizedInput = {};
330
330
  for (let key in input) normalizedInput[key === "renderBody" ? "content" : key] = input[key];
331
331
  }
332
332
  head.render(() => {
333
- if (willRerender) {
333
+ if (willRerender || registerChildScope) {
334
334
  let scopeId = _peek_scope_id();
335
335
  writeScope(scopeId, { m5c: component.id }), _script(scopeId, SET_SCOPE_REGISTER_ID);
336
336
  }
@@ -565,8 +565,6 @@ function writeProp(state, val, parent, accessor) {
565
565
  }
566
566
  }
567
567
  function writeReferenceOr(state, write, val, parent, accessor) {
568
- let scopeId = val[K_SCOPE_ID];
569
- if (scopeId !== void 0) return trackScope(state, val, scopeId), state.buf.push("_(" + scopeId + ")"), !0;
570
568
  let ref = state.refs.get(val);
571
569
  if (ref) {
572
570
  if (!trackChannel(state, ref)) return !1;
@@ -639,11 +637,16 @@ function writeNull(state) {
639
637
  }
640
638
  function writeObject(state, val, parent, accessor) {
641
639
  if (val === null) return writeNull(state);
640
+ let scopeId = val[K_SCOPE_ID];
641
+ if (scopeId !== void 0) return trackScope(state, val, scopeId), state.buf.push("_(" + scopeId + ")"), !0;
642
642
  let wellKnownObject = KNOWN_OBJECTS.get(val);
643
643
  return wellKnownObject ? (state.buf.push(wellKnownObject), !0) : writeReferenceOr(state, writeUnknownObject, val, parent, accessor);
644
644
  }
645
645
  function writeUnknownObject(state, val, ref) {
646
- switch (Object.getPrototypeOf(val)?.constructor) {
646
+ let proto = Object.getPrototypeOf(val);
647
+ if (proto === objectProto) return writePlainObject(state, val, ref);
648
+ if (proto === arrayProto) return writeArray(state, val, ref);
649
+ switch (proto?.constructor) {
647
650
  case void 0: return writeNullObject(state, val, ref);
648
651
  case Object: return writePlainObject(state, val, ref);
649
652
  case Array: return writeArray(state, val, ref);
@@ -685,7 +688,7 @@ function writeUnknownObject(state, val, ref) {
685
688
  return !1;
686
689
  }
687
690
  function writePlainObject(state, val, ref) {
688
- return state.buf.push("{"), writeObjectProps(state, val, ref), state.buf.push("}"), !0;
691
+ return state.buf.push("{"), writeMaybeIterableProps(state, val, ref), state.buf.push("}"), !0;
689
692
  }
690
693
  function writeArray(state, val, ref) {
691
694
  let sep = "[";
@@ -843,7 +846,7 @@ function writeAsyncGenerator(state, iter, ref) {
843
846
  return state.buf.push("(async function*(_,f,v,l,i,p=a=>l=new Promise((r,j)=>{f=_.r=r;_.j=j}),a=((_.f=v=>{f(v);a.push(p())}),[p()])){for(i of a)v=await i,i!=l&&(yield v);return v})(" + iterId + "={})"), iter.next().then(onFulfilled, onRejected), boundary.startAsync(), !0;
844
847
  }
845
848
  function writeNullObject(state, val, ref) {
846
- return state.buf.push("{"), state.buf.push(writeObjectProps(state, val, ref) + "__proto__:null}"), !0;
849
+ return state.buf.push("{"), state.buf.push(writeMaybeIterableProps(state, val, ref) + "__proto__:null}"), !0;
847
850
  }
848
851
  function writeObjectProps(state, val, ref) {
849
852
  let sep = "";
@@ -851,6 +854,10 @@ function writeObjectProps(state, val, ref) {
851
854
  let escapedKey = toObjectKey(key);
852
855
  state.buf.push(sep + escapedKey + ":"), writeProp(state, val[key], ref, escapedKey) ? sep = "," : state.buf.pop();
853
856
  }
857
+ return sep;
858
+ }
859
+ function writeMaybeIterableProps(state, val, ref) {
860
+ let sep = writeObjectProps(state, val, ref);
854
861
  if (hasSymbolIterator(val)) {
855
862
  let yieldSelf = "", iterArr = [];
856
863
  for (let item of val) item === val && !(yieldSelf || iterArr.length) ? yieldSelf = "yield this;" : iterArr.push(item);
@@ -892,14 +899,18 @@ function isCircular(parent, ref) {
892
899
  function toObjectKey(name) {
893
900
  if (name === "") return "\"\"";
894
901
  if (name === "__proto__") return "[\"__proto__\"]";
895
- let startChar = name[0];
896
- if (isDigit(startChar)) {
897
- if (startChar === "0") {
898
- if (name !== "0") return quote(name, 1);
899
- } else for (let i = 1; i < name.length; i++) if (!isDigit(name[i])) return quote(name, i);
900
- } else if (isWord(startChar)) {
901
- for (let i = 1; i < name.length; i++) if (!isWordOrDigit(name[i])) return quote(name, i);
902
- } else return quote(name, 0);
902
+ let len = name.length, c0 = name.charCodeAt(0);
903
+ if (c0 >= 48 && c0 <= 57) if (c0 === 48) {
904
+ if (len !== 1) return quote(name, 1);
905
+ } else for (let i = 1; i < len; i++) {
906
+ let c = name.charCodeAt(i);
907
+ if (c < 48 || c > 57) return quote(name, i);
908
+ }
909
+ else if (c0 >= 97 && c0 <= 122 || c0 >= 65 && c0 <= 90 || c0 === 95 || c0 === 36) for (let i = 1; i < len; i++) {
910
+ let c = name.charCodeAt(i);
911
+ if (!(c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 95 || c === 36)) return quote(name, i);
912
+ }
913
+ else return quote(name, 0);
903
914
  return name;
904
915
  }
905
916
  function toAccess(accessor) {
@@ -1009,15 +1020,6 @@ function hasOnlyZeros(typedArray) {
1009
1020
  for (let i = 0; i < typedArray.length; i++) if (typedArray[i] !== 0) return !1;
1010
1021
  return !0;
1011
1022
  }
1012
- function isWordOrDigit(char) {
1013
- return isWord(char) || isDigit(char);
1014
- }
1015
- function isDigit(char) {
1016
- return char >= "0" && char <= "9";
1017
- }
1018
- function isWord(char) {
1019
- return char >= "a" && char <= "z" || char >= "A" && char <= "Z" || char === "_" || char === "$";
1020
- }
1021
1023
  function patchIteratorNext(proto) {
1022
1024
  if (proto.next[kTouchedIterator]) return;
1023
1025
  let { next } = proto;
@@ -1885,7 +1887,7 @@ var ServerRendered = class {
1885
1887
  }
1886
1888
  pipe(stream) {
1887
1889
  this.#read((html) => {
1888
- stream.write(html);
1890
+ stream.write(html), stream.flush?.();
1889
1891
  }, (err) => {
1890
1892
  let socket = "socket" in stream && stream.socket;
1891
1893
  if (socket && typeof socket.destroySoon == "function" && socket.destroySoon(), !stream.emit?.("error", err)) throw err;
@@ -1894,21 +1896,21 @@ var ServerRendered = class {
1894
1896
  });
1895
1897
  }
1896
1898
  toReadable() {
1897
- let cancelled = !1, boundary, encoder = new TextEncoder();
1899
+ let cancelled = !1, started = !1, boundary, encoder = new TextEncoder();
1898
1900
  return new ReadableStream({
1899
- start: (ctrl) => {
1900
- boundary = this.#read((html) => {
1901
+ pull: (ctrl) => {
1902
+ started || (started = !0, boundary = this.#read((html) => {
1901
1903
  ctrl.enqueue(encoder.encode(html));
1902
1904
  }, (err) => {
1903
1905
  boundary = void 0, cancelled || ctrl.error(err);
1904
1906
  }, () => {
1905
1907
  boundary = void 0, ctrl.close();
1906
- });
1908
+ }));
1907
1909
  },
1908
1910
  cancel: (reason) => {
1909
1911
  cancelled = !0, boundary?.abort(reason);
1910
1912
  }
1911
- });
1913
+ }, { highWaterMark: 0 });
1912
1914
  }
1913
1915
  then(onfulfilled, onrejected) {
1914
1916
  return this.#promise().then(onfulfilled, onrejected);
package/dist/html.mjs CHANGED
@@ -4,7 +4,7 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
4
4
  else if (Array.isArray(val)) for (let v of val) part = toDelimitedString(v, delimiter, stringify), part && (str += sep + part, sep = delimiter);
5
5
  else for (let name in val) part = stringify(name, val[name]), part && (str += sep + part, sep = delimiter);
6
6
  return str;
7
- }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<(\/?script|!--)/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
7
+ }, unsafeXMLReg = /[<&]/g, replaceUnsafeXML = (c) => c === "&" ? "&amp;" : "&lt;", escapeXMLStr = (str) => unsafeXMLReg.test(str) ? str.replace(unsafeXMLReg, replaceUnsafeXML) : str, unsafeScriptReg = /<(\/?script|!--)/gi, escapeScriptStr = (str) => unsafeScriptReg.test(str) ? str.replace(unsafeScriptReg, "\\x3C$1") : str, unsafeStyleReg = /<\/style/gi, escapeStyleStr = (str) => unsafeStyleReg.test(str) ? str.replace(unsafeStyleReg, "\\3C/style") : str, unsafeCommentReg = />/g, escapeCommentStr = (str) => unsafeCommentReg.test(str) ? str.replace(unsafeCommentReg, "&gt;") : str, K_SCOPE_ID = Symbol("Scope ID"), kTouchedIterator = Symbol.for("marko.touchedIterator"), { hasOwnProperty: hasOwnProperty$1 } = {}, objectProto = Object.prototype, arrayProto = Array.prototype, Generator = (function* () {})().constructor, AsyncGenerator = (async function* () {})().constructor, REGISTRY = /* @__PURE__ */ new WeakMap(), KNOWN_SYMBOLS = (() => {
8
8
  let KNOWN_SYMBOLS = /* @__PURE__ */ new Map();
9
9
  for (let name of Object.getOwnPropertyNames(Symbol)) {
10
10
  let symbol = Symbol[name];
@@ -323,14 +323,14 @@ let empty = [], rest = Symbol(), toDelimitedString = function toDelimitedString(
323
323
  if (boundary.flush() === 1) throw Error("Cannot serialize promise across tags/class compat layer.");
324
324
  return new Chunk(boundary, null, null, state).flushScript().scripts;
325
325
  },
326
- render(renderer, willRerender, classAPIOut, component, input, completeChunks) {
326
+ render(renderer, willRerender, classAPIOut, component, input, completeChunks, registerChildScope) {
327
327
  let state = this.ensureState(classAPIOut.global), boundary = new Boundary(state), head = new Chunk(boundary, null, null, state), normalizedInput = input;
328
328
  if ("renderBody" in input) {
329
329
  normalizedInput = {};
330
330
  for (let key in input) normalizedInput[key === "renderBody" ? "content" : key] = input[key];
331
331
  }
332
332
  head.render(() => {
333
- if (willRerender) {
333
+ if (willRerender || registerChildScope) {
334
334
  let scopeId = _peek_scope_id();
335
335
  writeScope(scopeId, { m5c: component.id }), _script(scopeId, SET_SCOPE_REGISTER_ID);
336
336
  }
@@ -564,8 +564,6 @@ function writeProp(state, val, parent, accessor) {
564
564
  }
565
565
  }
566
566
  function writeReferenceOr(state, write, val, parent, accessor) {
567
- let scopeId = val[K_SCOPE_ID];
568
- if (scopeId !== void 0) return trackScope(state, val, scopeId), state.buf.push("_(" + scopeId + ")"), !0;
569
567
  let ref = state.refs.get(val);
570
568
  if (ref) {
571
569
  if (!trackChannel(state, ref)) return !1;
@@ -638,11 +636,16 @@ function writeNull(state) {
638
636
  }
639
637
  function writeObject(state, val, parent, accessor) {
640
638
  if (val === null) return writeNull(state);
639
+ let scopeId = val[K_SCOPE_ID];
640
+ if (scopeId !== void 0) return trackScope(state, val, scopeId), state.buf.push("_(" + scopeId + ")"), !0;
641
641
  let wellKnownObject = KNOWN_OBJECTS.get(val);
642
642
  return wellKnownObject ? (state.buf.push(wellKnownObject), !0) : writeReferenceOr(state, writeUnknownObject, val, parent, accessor);
643
643
  }
644
644
  function writeUnknownObject(state, val, ref) {
645
- switch (Object.getPrototypeOf(val)?.constructor) {
645
+ let proto = Object.getPrototypeOf(val);
646
+ if (proto === objectProto) return writePlainObject(state, val, ref);
647
+ if (proto === arrayProto) return writeArray(state, val, ref);
648
+ switch (proto?.constructor) {
646
649
  case void 0: return writeNullObject(state, val, ref);
647
650
  case Object: return writePlainObject(state, val, ref);
648
651
  case Array: return writeArray(state, val, ref);
@@ -684,7 +687,7 @@ function writeUnknownObject(state, val, ref) {
684
687
  return !1;
685
688
  }
686
689
  function writePlainObject(state, val, ref) {
687
- return state.buf.push("{"), writeObjectProps(state, val, ref), state.buf.push("}"), !0;
690
+ return state.buf.push("{"), writeMaybeIterableProps(state, val, ref), state.buf.push("}"), !0;
688
691
  }
689
692
  function writeArray(state, val, ref) {
690
693
  let sep = "[";
@@ -842,7 +845,7 @@ function writeAsyncGenerator(state, iter, ref) {
842
845
  return state.buf.push("(async function*(_,f,v,l,i,p=a=>l=new Promise((r,j)=>{f=_.r=r;_.j=j}),a=((_.f=v=>{f(v);a.push(p())}),[p()])){for(i of a)v=await i,i!=l&&(yield v);return v})(" + iterId + "={})"), iter.next().then(onFulfilled, onRejected), boundary.startAsync(), !0;
843
846
  }
844
847
  function writeNullObject(state, val, ref) {
845
- return state.buf.push("{"), state.buf.push(writeObjectProps(state, val, ref) + "__proto__:null}"), !0;
848
+ return state.buf.push("{"), state.buf.push(writeMaybeIterableProps(state, val, ref) + "__proto__:null}"), !0;
846
849
  }
847
850
  function writeObjectProps(state, val, ref) {
848
851
  let sep = "";
@@ -850,6 +853,10 @@ function writeObjectProps(state, val, ref) {
850
853
  let escapedKey = toObjectKey(key);
851
854
  state.buf.push(sep + escapedKey + ":"), writeProp(state, val[key], ref, escapedKey) ? sep = "," : state.buf.pop();
852
855
  }
856
+ return sep;
857
+ }
858
+ function writeMaybeIterableProps(state, val, ref) {
859
+ let sep = writeObjectProps(state, val, ref);
853
860
  if (hasSymbolIterator(val)) {
854
861
  let yieldSelf = "", iterArr = [];
855
862
  for (let item of val) item === val && !(yieldSelf || iterArr.length) ? yieldSelf = "yield this;" : iterArr.push(item);
@@ -891,14 +898,18 @@ function isCircular(parent, ref) {
891
898
  function toObjectKey(name) {
892
899
  if (name === "") return "\"\"";
893
900
  if (name === "__proto__") return "[\"__proto__\"]";
894
- let startChar = name[0];
895
- if (isDigit(startChar)) {
896
- if (startChar === "0") {
897
- if (name !== "0") return quote(name, 1);
898
- } else for (let i = 1; i < name.length; i++) if (!isDigit(name[i])) return quote(name, i);
899
- } else if (isWord(startChar)) {
900
- for (let i = 1; i < name.length; i++) if (!isWordOrDigit(name[i])) return quote(name, i);
901
- } else return quote(name, 0);
901
+ let len = name.length, c0 = name.charCodeAt(0);
902
+ if (c0 >= 48 && c0 <= 57) if (c0 === 48) {
903
+ if (len !== 1) return quote(name, 1);
904
+ } else for (let i = 1; i < len; i++) {
905
+ let c = name.charCodeAt(i);
906
+ if (c < 48 || c > 57) return quote(name, i);
907
+ }
908
+ else if (c0 >= 97 && c0 <= 122 || c0 >= 65 && c0 <= 90 || c0 === 95 || c0 === 36) for (let i = 1; i < len; i++) {
909
+ let c = name.charCodeAt(i);
910
+ if (!(c >= 97 && c <= 122 || c >= 65 && c <= 90 || c >= 48 && c <= 57 || c === 95 || c === 36)) return quote(name, i);
911
+ }
912
+ else return quote(name, 0);
902
913
  return name;
903
914
  }
904
915
  function toAccess(accessor) {
@@ -1008,15 +1019,6 @@ function hasOnlyZeros(typedArray) {
1008
1019
  for (let i = 0; i < typedArray.length; i++) if (typedArray[i] !== 0) return !1;
1009
1020
  return !0;
1010
1021
  }
1011
- function isWordOrDigit(char) {
1012
- return isWord(char) || isDigit(char);
1013
- }
1014
- function isDigit(char) {
1015
- return char >= "0" && char <= "9";
1016
- }
1017
- function isWord(char) {
1018
- return char >= "a" && char <= "z" || char >= "A" && char <= "Z" || char === "_" || char === "$";
1019
- }
1020
1022
  function patchIteratorNext(proto) {
1021
1023
  if (proto.next[kTouchedIterator]) return;
1022
1024
  let { next } = proto;
@@ -1884,7 +1886,7 @@ var ServerRendered = class {
1884
1886
  }
1885
1887
  pipe(stream) {
1886
1888
  this.#read((html) => {
1887
- stream.write(html);
1889
+ stream.write(html), stream.flush?.();
1888
1890
  }, (err) => {
1889
1891
  let socket = "socket" in stream && stream.socket;
1890
1892
  if (socket && typeof socket.destroySoon == "function" && socket.destroySoon(), !stream.emit?.("error", err)) throw err;
@@ -1893,21 +1895,21 @@ var ServerRendered = class {
1893
1895
  });
1894
1896
  }
1895
1897
  toReadable() {
1896
- let cancelled = !1, boundary, encoder = new TextEncoder();
1898
+ let cancelled = !1, started = !1, boundary, encoder = new TextEncoder();
1897
1899
  return new ReadableStream({
1898
- start: (ctrl) => {
1899
- boundary = this.#read((html) => {
1900
+ pull: (ctrl) => {
1901
+ started || (started = !0, boundary = this.#read((html) => {
1900
1902
  ctrl.enqueue(encoder.encode(html));
1901
1903
  }, (err) => {
1902
1904
  boundary = void 0, cancelled || ctrl.error(err);
1903
1905
  }, () => {
1904
1906
  boundary = void 0, ctrl.close();
1905
- });
1907
+ }));
1906
1908
  },
1907
1909
  cancel: (reason) => {
1908
1910
  cancelled = !0, boundary?.abort(reason);
1909
1911
  }
1910
- });
1912
+ }, { highWaterMark: 0 });
1911
1913
  }
1912
1914
  then(onfulfilled, onrejected) {
1913
1915
  return this.#promise().then(onfulfilled, onrejected);
@@ -104,7 +104,6 @@ let AccessorPrefix$1 = /* @__PURE__ */ function(AccessorPrefix) {
104
104
  AccessorPrefix["ControlledValue"] = "ControlledValue:";
105
105
  AccessorPrefix["DynamicHTMLLastChild"] = "DynamicHTMLLastChild:";
106
106
  AccessorPrefix["EventAttributes"] = "EventAttributes:";
107
- AccessorPrefix["Getter"] = "Getter:";
108
107
  AccessorPrefix["KeyedScopes"] = "KeyedScopes:";
109
108
  AccessorPrefix["Lifecycle"] = "Lifecycle:";
110
109
  AccessorPrefix["Promise"] = "Promise:";
@@ -302,6 +301,7 @@ const decodeAccessor = (num) => (num + (num < 26 ? 10 : num < 962 ? 334 : 11998)
302
301
  const K_SCOPE_ID = Symbol("Scope ID");
303
302
  const kTouchedIterator = Symbol.for("marko.touchedIterator");
304
303
  const { hasOwnProperty: hasOwnProperty$1 } = {};
304
+ Array.prototype;
305
305
  const Generator = (function* () {})().constructor;
306
306
  const AsyncGenerator = (async function* () {})().constructor;
307
307
  patchIteratorNext(Generator.prototype);
@@ -856,7 +856,6 @@ let AccessorPrefix = /* @__PURE__ */ function(AccessorPrefix) {
856
856
  AccessorPrefix["ControlledValue"] = "G";
857
857
  AccessorPrefix["DynamicHTMLLastChild"] = "H";
858
858
  AccessorPrefix["EventAttributes"] = "I";
859
- AccessorPrefix["Getter"] = "J";
860
859
  AccessorPrefix["KeyedScopes"] = "O";
861
860
  AccessorPrefix["Lifecycle"] = "K";
862
861
  AccessorPrefix["Promise"] = "L";
@@ -2078,6 +2077,7 @@ const pureDOMFunctions = /* @__PURE__ */ new Set([
2078
2077
  "_load_race_trigger"
2079
2078
  ]);
2080
2079
  function importRuntime(name) {
2080
+ if (!isTranslate()) throw new Error(`\`importRuntime(${JSON.stringify(name)})\` may only be called during the translate stage.`);
2081
2081
  const { output } = getMarkoOpts();
2082
2082
  return (0, _marko_compiler_babel_utils.importNamed)((0, _marko_compiler_babel_utils.getFile)(), getRuntimePath(output), name);
2083
2083
  }
@@ -3692,7 +3692,28 @@ function getRegisteredFnExpression(node) {
3692
3692
  }
3693
3693
  //#endregion
3694
3694
  //#region src/translator/util/body-to-text-literal.ts
3695
+ const kRawText = Symbol("raw text placeholder");
3695
3696
  function bodyToTextLiteral(body) {
3697
+ return buildTextLiteral(body, toText, false);
3698
+ }
3699
+ function bodyToRawTextLiteral(body) {
3700
+ return buildTextLiteral(body, (value) => value, true);
3701
+ }
3702
+ function injectTextCoercion(expr) {
3703
+ switch (expr.type) {
3704
+ case "ConditionalExpression":
3705
+ injectTextCoercion(expr.consequent);
3706
+ injectTextCoercion(expr.alternate);
3707
+ break;
3708
+ case "TemplateLiteral":
3709
+ expr.expressions = expr.expressions.map((child) => toText(child));
3710
+ break;
3711
+ }
3712
+ }
3713
+ function toText(value) {
3714
+ return callRuntime("_to_text", value);
3715
+ }
3716
+ function buildTextLiteral(body, coerce, bareSingle) {
3696
3717
  const templateQuasis = [];
3697
3718
  const templateExpressions = [];
3698
3719
  let currentQuasi = "";
@@ -3701,10 +3722,11 @@ function bodyToTextLiteral(body) {
3701
3722
  else if (_marko_compiler.types.isMarkoPlaceholder(child)) {
3702
3723
  placeholderExtra ||= child.value.extra;
3703
3724
  templateQuasis.push(templateElement(currentQuasi, false));
3704
- templateExpressions.push(callRuntime("_to_text", child.value));
3725
+ templateExpressions.push(coerce(child.value));
3705
3726
  currentQuasi = "";
3706
3727
  }
3707
3728
  if (templateExpressions.length) {
3729
+ if (bareSingle && templateExpressions.length === 1 && !currentQuasi && !templateQuasis[0].value.cooked) return templateExpressions[0];
3708
3730
  templateQuasis.push(templateElement(currentQuasi, true));
3709
3731
  const literal = _marko_compiler.types.templateLiteral(templateQuasis, templateExpressions);
3710
3732
  literal.extra = placeholderExtra;
@@ -5205,13 +5227,17 @@ function flattenTextOnlyConditional(rootTag) {
5205
5227
  } while (cur.node && (isCoreTagName(cur, "else-if") || isCoreTagName(cur, "else")));
5206
5228
  for (const branchTag of branches) assertValidCondition(branchTag);
5207
5229
  let expr = _marko_compiler.types.stringLiteral("");
5230
+ let rawText = false;
5208
5231
  for (let i = branches.length; i--;) {
5209
5232
  const branchTag = branches[i];
5210
- const text = bodyToTextLiteral(branchTag.node.body);
5233
+ const text = bodyToRawTextLiteral(branchTag.node.body);
5234
+ rawText ||= _marko_compiler.types.isTemplateLiteral(text);
5211
5235
  expr = isCoreTagName(branchTag, "else") ? text : _marko_compiler.types.conditionalExpression(branchTag.node.attributes[0].value, text, expr);
5212
5236
  }
5213
5237
  for (let i = branches.length; i-- > 1;) branches[i].remove();
5214
- rootTag.replaceWith(_marko_compiler.types.markoPlaceholder(expr, true));
5238
+ const placeholder = _marko_compiler.types.markoPlaceholder(expr, true);
5239
+ if (rawText) (placeholder.extra ??= {})[kRawText] = true;
5240
+ rootTag.replaceWith(placeholder);
5215
5241
  }
5216
5242
  function assertValidCondition(tag) {
5217
5243
  const conditionTagName = getTagName(tag);
@@ -5825,7 +5851,7 @@ function knownTagTranslateDOM(tag, propTree, getBindingIdentifier, callSetup) {
5825
5851
  if (node.var) {
5826
5852
  const varBinding = node.var.extra.binding;
5827
5853
  const source = initValue(varBinding);
5828
- source.register = true;
5854
+ source.register = !!getSerializeReason(tagSection, childScopeBinding) || !signalHasStatements(source);
5829
5855
  source.buildAssignment = (valueSection, value) => {
5830
5856
  const changeArgs = [createScopeReadExpression(childScopeBinding, valueSection), value];
5831
5857
  if (!isOptimize()) changeArgs.push(_marko_compiler.types.stringLiteral(varBinding.name));
@@ -8991,6 +9017,7 @@ var placeholder_default = {
8991
9017
  if (isNonHTMLText(placeholder)) return;
8992
9018
  const { node } = placeholder;
8993
9019
  const { value } = node;
9020
+ if (node.extra?.[kRawText]) injectTextCoercion(value);
8994
9021
  const valueExtra = evaluate(value);
8995
9022
  const { confident, computed } = valueExtra;
8996
9023
  if (confident && isVoid(computed)) {
@@ -9312,8 +9339,9 @@ function getTagRelativePath(tag) {
9312
9339
  const { node, hub: { file } } = tag;
9313
9340
  let relativePath;
9314
9341
  if (_marko_compiler.types.isStringLiteral(node.name)) {
9315
- const template = node.extra?.featureType === "class" && (0, _marko_compiler_babel_utils.getTagDef)(tag)?.renderer || (0, _marko_compiler_babel_utils.getTagTemplate)(tag);
9316
- relativePath = template && (0, _marko_compiler_babel_utils.resolveRelativePath)(file, template);
9342
+ const tagDef = (0, _marko_compiler_babel_utils.getTagDef)(tag);
9343
+ const template = node.extra?.featureType === "class" && tagDef?.renderer || (0, _marko_compiler_babel_utils.getTagTemplate)(tag);
9344
+ relativePath = template && (0, _marko_compiler_babel_utils.resolveRelativePath)(file, template, tagDef);
9317
9345
  } else if (node.extra?.tagNameImported) relativePath = node.extra.tagNameImported;
9318
9346
  if (!relativePath) throw tagNotFoundError(tag);
9319
9347
  return relativePath;
@@ -1,2 +1,10 @@
1
1
  import { types as t } from "@marko/compiler";
2
- export declare function bodyToTextLiteral(body: t.MarkoTagBody): t.StringLiteral | t.TemplateLiteral;
2
+ export declare const kRawText: unique symbol;
3
+ declare module "@marko/compiler/dist/types" {
4
+ interface MarkoPlaceholderExtra {
5
+ [kRawText]?: true;
6
+ }
7
+ }
8
+ export declare function bodyToTextLiteral(body: t.MarkoTagBody): t.Expression;
9
+ export declare function bodyToRawTextLiteral(body: t.MarkoTagBody): t.Expression;
10
+ export declare function injectTextCoercion(expr: t.Expression): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marko/runtime-tags",
3
- "version": "6.3.3",
3
+ "version": "6.3.5",
4
4
  "description": "Optimized runtime for Marko templates.",
5
5
  "keywords": [
6
6
  "api",
@@ -51,7 +51,7 @@
51
51
  "build": "node -r ~ts ./scripts/bundle.mts"
52
52
  },
53
53
  "dependencies": {
54
- "@marko/compiler": "^5.40.2",
54
+ "@marko/compiler": "^5.41.0",
55
55
  "csstype": "^3.2.3",
56
56
  "fastest-levenshtein": "^1.0.16",
57
57
  "magic-string": "^0.30.21"