From 2687edc5a285bc32f1c2e55d290fa888c3c2b906 Mon Sep 17 00:00:00 2001 From: dpiercey Date: Sat, 15 Feb 2025 16:31:25 -0700 Subject: [PATCH] fix: serializing attr tag iterators --- .changeset/tender-horses-hug.md | 5 ++ .changeset/wild-flowers-beam.md | 5 ++ .sizes.json | 4 +- .sizes/dom.js | 5 +- .../__snapshots__/resume.expected.md | 16 ++-- .../__snapshots__/ssr.expected.md | 4 +- .../__snapshots__/resume.expected.md | 4 +- .../__snapshots__/ssr.expected.md | 4 +- .../__snapshots__/resume.expected.md | 16 ++-- .../__snapshots__/ssr.expected.md | 4 +- .../src/__tests__/serializer.test.ts | 21 ++++- packages/runtime-tags/src/common/helpers.ts | 9 ++- packages/runtime-tags/src/common/types.ts | 1 - packages/runtime-tags/src/html/serializer.ts | 76 +++++++++++-------- 14 files changed, 108 insertions(+), 66 deletions(-) create mode 100644 .changeset/tender-horses-hug.md create mode 100644 .changeset/wild-flowers-beam.md diff --git a/.changeset/tender-horses-hug.md b/.changeset/tender-horses-hug.md new file mode 100644 index 0000000000..bf6638cf47 --- /dev/null +++ b/.changeset/tender-horses-hug.md @@ -0,0 +1,5 @@ +--- +"@marko/runtime-tags": patch +--- + +Fix issue serializing attribute tag iterables. diff --git a/.changeset/wild-flowers-beam.md b/.changeset/wild-flowers-beam.md new file mode 100644 index 0000000000..dbcd00177b --- /dev/null +++ b/.changeset/wild-flowers-beam.md @@ -0,0 +1,5 @@ +--- +"@marko/runtime-tags": patch +--- + +Improve non dimensional css property regexp (minor improvement to bundle size). diff --git a/.sizes.json b/.sizes.json index d464f08010..9a3eae084c 100644 --- a/.sizes.json +++ b/.sizes.json @@ -7,8 +7,8 @@ { "name": "*", "total": { - "min": 18072, - "brotli": 6823 + "min": 18061, + "brotli": 6798 } }, { diff --git a/.sizes/dom.js b/.sizes/dom.js index 342e3a4d92..ab8da96360 100644 --- a/.sizes/dom.js +++ b/.sizes/dom.js @@ -1,4 +1,4 @@ -// size: 18072 (min) 6823 (brotli) +// size: 18061 (min) 6798 (brotli) var empty = [], rest = Symbol(); function attrTag(attrs2) { @@ -35,10 +35,9 @@ function forTo(to, from, step, cb) { function stringifyClassObject(name, value2) { return value2 ? name : ""; } -var NON_DIMENSIONAL = /^(--|ta|or|li|z)|n-c|i(do|nk|m|t)|w$|we/; function stringifyStyleObject(name, value2) { return value2 || 0 === value2 - ? `${name}:${"number" == typeof value2 && value2 && !NON_DIMENSIONAL.test(name) ? value2 + "px" : value2}` + ? `${name}:${"number" == typeof value2 && value2 && !/^(--|ta|or|li|z)|cou|nk|it|ag|we|do|w$/.test(name) ? value2 + "px" : value2}` : ""; } function toDelimitedString(val, delimiter, stringify) { diff --git a/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/resume.expected.md b/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/resume.expected.md index 2d461a4369..e3bc414896 100644 --- a/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/resume.expected.md +++ b/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/resume.expected.md @@ -85,7 +85,7 @@ Inner mounted @@ -175,7 +175,7 @@ Inner destroyed @@ -249,7 +249,7 @@ Middle destroyed @@ -302,7 +302,7 @@ Outer destroyed @@ -355,7 +355,7 @@ Outer destroyed @@ -400,7 +400,7 @@ Outer destroyed @@ -478,7 +478,7 @@ Inner mounted @@ -553,7 +553,7 @@ Outer destroyed diff --git a/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/ssr.expected.md b/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/ssr.expected.md index d076300d89..754892d090 100644 --- a/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/ssr.expected.md +++ b/packages/runtime-tags/src/__tests__/fixtures/cleanup-n-child-if-deep/__snapshots__/ssr.expected.md @@ -1,6 +1,6 @@ # Write ```html -
Outer a
Outer a

Outer a

Middle a
Middle a

Middle a

Inner a
Inner a

Inner a

+
Outer a
Outer a

Outer a

Middle a
Middle a

Middle a

Inner a
Inner a

Inner a

``` # Render End @@ -85,7 +85,7 @@ diff --git a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/resume.expected.md b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/resume.expected.md index 3e399dad63..e5ed4bbec1 100644 --- a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/resume.expected.md +++ b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/resume.expected.md @@ -98,7 +98,7 @@ @@ -173,7 +173,7 @@ destroyed 2.3 diff --git a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/ssr.expected.md b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/ssr.expected.md index 616093f5c8..82b28e87b3 100644 --- a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/ssr.expected.md +++ b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-for-deep/__snapshots__/ssr.expected.md @@ -1,6 +1,6 @@ # Write ```html -
1
1.1
1.2
1.3
2
2.1
2.2
2.3
3
3.1
3.2
3.3
+
1
1.1
1.2
1.3
2
2.1
2.2
2.3
3
3.1
3.2
3.3
``` # Render End @@ -103,7 +103,7 @@ diff --git a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/resume.expected.md b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/resume.expected.md index 06c93a436b..9f5b2a9643 100644 --- a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/resume.expected.md +++ b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/resume.expected.md @@ -51,7 +51,7 @@ Inner mounted @@ -119,7 +119,7 @@ Inner destroyed @@ -179,7 +179,7 @@ Middle destroyed @@ -232,7 +232,7 @@ Outer destroyed @@ -285,7 +285,7 @@ Outer destroyed @@ -330,7 +330,7 @@ Outer destroyed @@ -390,7 +390,7 @@ Inner mounted @@ -459,7 +459,7 @@ Outer destroyed diff --git a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/ssr.expected.md b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/ssr.expected.md index a5594eab62..d89d5d2658 100644 --- a/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/ssr.expected.md +++ b/packages/runtime-tags/src/__tests__/fixtures/cleanup-single-child-if-deep/__snapshots__/ssr.expected.md @@ -1,6 +1,6 @@ # Write ```html -

Outer

Middle

Inner

+

Outer

Middle

Inner

``` # Render End @@ -51,7 +51,7 @@ diff --git a/packages/runtime-tags/src/__tests__/serializer.test.ts b/packages/runtime-tags/src/__tests__/serializer.test.ts index 7e1342729e..966ab0826a 100644 --- a/packages/runtime-tags/src/__tests__/serializer.test.ts +++ b/packages/runtime-tags/src/__tests__/serializer.test.ts @@ -406,11 +406,28 @@ describe("serializer", () => { assertStringify( obj, - `{x:1,[Symbol.iterator]:(a=>()=>a.values())(_.a=[1,2,3])}`, + `{x:1,*[(_.a=[1,2,3],Symbol.iterator)](){yield*_.a}}`, ); }); - it("Symbol.iterator registered", () => { + it("Symbol.iterator circular", () => { + const obj = { + x: 1, + *[Symbol.iterator]() { + yield 1; + yield 2; + yield obj; + }, + }; + + assertStringify( + obj, + `{x:1,*[(_.a=[1,2,],Symbol.iterator)](){yield*_.a}},_.a[2]=_.b`, + ); + }); + + it.skip("Symbol.iterator registered", () => { + // Unsupported for now since we share the reference for iterators on attribute tags. const obj = { y: 2, [Symbol.iterator]: iterate, diff --git a/packages/runtime-tags/src/common/helpers.ts b/packages/runtime-tags/src/common/helpers.ts index c4860f0f54..98a89861a0 100644 --- a/packages/runtime-tags/src/common/helpers.ts +++ b/packages/runtime-tags/src/common/helpers.ts @@ -10,10 +10,15 @@ export function styleValue(value: unknown) { return toDelimitedString(value, ";", stringifyStyleObject); } -const NON_DIMENSIONAL = /^(--|ta|or|li|z)|n-c|i(do|nk|m|t)|w$|we/; function stringifyStyleObject(name: string, value: unknown) { return value || value === 0 - ? `${name}:${typeof value === "number" && value && !NON_DIMENSIONAL.test(name) ? value + "px" : value}` + ? `${name}:${ + typeof value === "number" && + value && + !/^(--|ta|or|li|z)|cou|nk|it|ag|we|do|w$/.test(name) + ? value + "px" + : value + }` : ""; } diff --git a/packages/runtime-tags/src/common/types.ts b/packages/runtime-tags/src/common/types.ts index 54ff60f88a..e5aca5660e 100644 --- a/packages/runtime-tags/src/common/types.ts +++ b/packages/runtime-tags/src/common/types.ts @@ -135,5 +135,4 @@ export enum ControlledType { SelectValue, DetailsOrDialogOpen, None, - Pending, } diff --git a/packages/runtime-tags/src/html/serializer.ts b/packages/runtime-tags/src/html/serializer.ts index 4819012a85..c15af893fe 100644 --- a/packages/runtime-tags/src/html/serializer.ts +++ b/packages/runtime-tags/src/html/serializer.ts @@ -376,16 +376,11 @@ function writeRoot(state: State, root: unknown) { if (writeProp(state, root, null, "")) { const rootRef = state.refs.get(root as object); if (rootRef) { - ensureId(state, rootRef); - } - - if (assigned.size) { - if (assigned.delete(rootRef!)) { - assigned.add(rootRef!); - writeAssigned(state); - } else { + const rootId = ensureId(state, rootRef); + if (assigned.size) { + assigned.delete(rootRef); writeAssigned(state); - buf.push("," + rootRef!.id!); + buf.push("," + rootRef.assigns + rootId); } } @@ -410,8 +405,10 @@ function writeRoot(state: State, root: unknown) { function writeAssigned(state: State) { for (const valueRef of state.assigned) { - state.buf.push("," + valueRef.assigns + (valueRef.init || valueRef.id)); - valueRef.init = ""; + if (valueRef.assigns || valueRef.init) { + state.buf.push("," + valueRef.assigns + (valueRef.init || valueRef.id)); + valueRef.init = ""; + } } } @@ -513,6 +510,10 @@ function writeRegistered( state.refs.set(val, fnRef); if (scopeRef) { if (isCircular(parent, scopeRef)) { + // TODO: adding parent here is is probably wrong, but is currently needed to ensure the + // parent of the function has it's assignments before the function so that when the + // function is called the parent is complete. + state.assigned.add(parent); state.assigned.add(fnRef); fnRef.init = access + "(" + ensureId(state, scopeRef) + ")"; fnRef.assigns += ensureId(state, parent) + toAccess(accessor) + "="; @@ -528,6 +529,10 @@ function writeRegistered( const scopeId = scopeRef && ensureId(state, scopeRef); if (scopeId && assigns !== state.assigned.size) { + // TODO: adding parent here is is probably wrong, but is currently needed to ensure the + // parent of the function has it's assignments before the function so that when the + // function is called the parent is complete. + state.assigned.add(parent); state.assigned.add(fnRef); fnRef.init = access + "(" + scopeId + ")"; fnRef.assigns += ensureId(state, parent) + toAccess(accessor) + "="; @@ -1186,28 +1191,35 @@ function writeObjectProps(state: State, val: object, ref: Reference) { } if (hasSymbolIterator(val)) { - state.buf.push(sep + "[Symbol.iterator]:"); - sep = ","; - if ( - !writeReferenceOr( - state, - writeNever, - val[Symbol.iterator], - ref, - "Symbol.iterator", - ) - ) { - const arrayRef = new Reference( - ref, - null, - state.flush, - null, - nextRefAccess(state), - ); - state.buf.push("(a=>()=>a.values())(" + arrayRef.id + "="); - writeArray(state, [...val], arrayRef); - state.buf.push(")"); + const iterArr = [...val]; + switch (iterArr.length) { + case 0: + state.buf.push(sep + "*[Symbol.iterator](){}"); + break; + case 1: + state.buf.push( + sep + + "*[Symbol.iterator](){yield " + + (iterArr[0] === val ? "this" : ensureId(state, ref)) + + "}", + ); + break; + default: { + const iterRef = new Reference( + ref, + null, + state.flush, + null, + nextRefAccess(state), + ); + state.buf.push(sep + "*[(" + iterRef.id + "="); + writeArray(state, iterArr, iterRef); + state.buf.push(",Symbol.iterator)](){yield*" + iterRef.id + "}"); + break; + } } + + sep = ","; } return sep;