From 0bda22cd98b4d281846687c4dcf29f395ac5f9d2 Mon Sep 17 00:00:00 2001
From: Michael Rawlings
Date: Mon, 8 Nov 2021 12:23:42 -0800
Subject: [PATCH] feat: move non-serialized internal values out of scope array
and into props
---
.sizes.json | 6 ++--
.../basic-counter/ssr-hydrate.expected.md | 32 +++++++++----------
.../fixtures/basic-counter/server.ts | 3 +-
packages/runtime/src/common/types.ts | 19 +++++------
packages/runtime/src/dom/control-flow.ts | 16 +++-------
packages/runtime/src/dom/dom.ts | 16 +++++-----
packages/runtime/src/dom/hydrate.ts | 19 ++++++-----
packages/runtime/src/dom/queue.ts | 6 ++--
packages/runtime/src/dom/renderer.ts | 10 +++---
packages/runtime/src/dom/scope.ts | 17 +++++-----
packages/runtime/src/html/writer.ts | 18 ++++-------
11 files changed, 74 insertions(+), 88 deletions(-)
diff --git a/.sizes.json b/.sizes.json
index d0ecb94b5..7ac4ef996 100644
--- a/.sizes.json
+++ b/.sizes.json
@@ -6,9 +6,9 @@
{
"name": "*",
"individual": {
- "min": 11962,
- "gzip": 5140,
- "brotli": 4628
+ "min": 11615,
+ "gzip": 5073,
+ "brotli": 4574
}
}
]
diff --git a/packages/runtime/src/__tests__/__snapshots__/runtime/basic-counter/ssr-hydrate.expected.md b/packages/runtime/src/__tests__/__snapshots__/runtime/basic-counter/ssr-hydrate.expected.md
index 9100fdd82..a997d3d24 100644
--- a/packages/runtime/src/__tests__/__snapshots__/runtime/basic-counter/ssr-hydrate.expected.md
+++ b/packages/runtime/src/__tests__/__snapshots__/runtime/basic-counter/ssr-hydrate.expected.md
@@ -1,5 +1,5 @@
# Write
-
+
# Render "End"
@@ -8,13 +8,13 @@
-
+
@@ -43,13 +43,13 @@ inserted #document/html1/body1/script2/#text0
-
+
@@ -70,13 +70,13 @@ container.querySelector("button").click();
-
+
@@ -97,13 +97,13 @@ container.querySelector("button").click();
-
+
@@ -124,13 +124,13 @@ container.querySelector("button").click();
-
+
diff --git a/packages/runtime/src/__tests__/fixtures/basic-counter/server.ts b/packages/runtime/src/__tests__/fixtures/basic-counter/server.ts
index 708db8a22..25dee5b3a 100644
--- a/packages/runtime/src/__tests__/fixtures/basic-counter/server.ts
+++ b/packages/runtime/src/__tests__/fixtures/basic-counter/server.ts
@@ -6,7 +6,6 @@ export default (
currentScope: Scope,
currentOffset: number
) => {
- currentScope[0] = "ROOT";
write("");
counter(_input, currentScope, currentOffset);
write("");
@@ -27,5 +26,5 @@ const counter = (
)}${count}`
);
writeScope(currentScope);
- writeCall("counter", currentOffset, currentScope[0]);
+ writeCall("counter", currentOffset, currentScope.___id);
};
diff --git a/packages/runtime/src/common/types.ts b/packages/runtime/src/common/types.ts
index 2a7fb9411..c3a681a43 100644
--- a/packages/runtime/src/common/types.ts
+++ b/packages/runtime/src/common/types.ts
@@ -9,14 +9,15 @@ export type HydrateInstance = [
];
export type Scope = [
- string, // ID
- Node | number | undefined, // START_NODE
- Node | number | undefined, // END_NODE
- Set | undefined, // CLEANUP
Scope | undefined, // OWNER_SCOPE
number | undefined, // OWNER_OFFSET
...unknown[]
] & {
+ ___id: string;
+ ___startNode: Node | number | undefined;
+ ___endNode: Node | number | undefined;
+ ___cleanup: Set | undefined;
+} & {
___insertBefore: (
this: Scope,
parent: Node & ParentNode,
@@ -30,13 +31,9 @@ export type Scope = [
};
export const enum ScopeOffsets {
- ID = 0,
- START_NODE = 1,
- END_NODE = 2,
- CLEANUP = 3,
- OWNER_SCOPE = 4,
- OWNER_OFFSET = 5,
- BEGIN_DATA = 6,
+ OWNER_SCOPE = 0,
+ OWNER_OFFSET = 1,
+ BEGIN_DATA = 2,
}
export const enum HydrateSymbols {
diff --git a/packages/runtime/src/dom/control-flow.ts b/packages/runtime/src/dom/control-flow.ts
index 2c30c5444..ee8f1948e 100644
--- a/packages/runtime/src/dom/control-flow.ts
+++ b/packages/runtime/src/dom/control-flow.ts
@@ -46,7 +46,7 @@ export function queueInBranch(
export function getConditionalFirstNode(
this: Scope,
- conditionalIndex: number = this[ScopeOffsets.START_NODE] as number,
+ conditionalIndex: number = this.___startNode as number,
last?: boolean
) {
const scope = this[
@@ -62,11 +62,7 @@ export function getConditionalFirstNode(
}
export function getConditionalLastNode(this: Scope) {
- return getConditionalFirstNode.call(
- this,
- this[ScopeOffsets.END_NODE] as number,
- true
- );
+ return getConditionalFirstNode.call(this, this.___endNode as number, true);
}
export function setConditionalRenderer(
@@ -179,7 +175,7 @@ export function queueForEach(
export function getLoopFirstNode(
this: Scope,
- loopIndex: number = this[ScopeOffsets.START_NODE] as number,
+ loopIndex: number = this.___startNode as number,
last?: boolean
) {
const scopes = this[
@@ -195,11 +191,7 @@ export function getLoopFirstNode(
}
export function getLoopLastNode(this: Scope) {
- return getLoopFirstNode.call(
- this,
- this[ScopeOffsets.END_NODE] as number,
- true
- );
+ return getLoopFirstNode.call(this, this.___endNode as number, true);
}
export function setLoopOf(
diff --git a/packages/runtime/src/dom/dom.ts b/packages/runtime/src/dom/dom.ts
index 48218ebfb..fdf8f514a 100644
--- a/packages/runtime/src/dom/dom.ts
+++ b/packages/runtime/src/dom/dom.ts
@@ -1,5 +1,5 @@
import type { Renderer } from "./renderer";
-import { Scope, ScopeOffsets } from "../common/types";
+import { Scope } from "../common/types";
import { onDestroy, read, write } from "./scope";
import { withQueueNext } from "./queue";
@@ -25,10 +25,10 @@ export type DOMMethods = {
export const staticNodeMethods: DOMMethods = {
___insertBefore(parent, nextSibling) {
- parent.insertBefore(this[ScopeOffsets.START_NODE] as Node, nextSibling);
+ parent.insertBefore(this.___startNode as Node, nextSibling);
},
___remove() {
- (this[ScopeOffsets.START_NODE] as ChildNode).remove();
+ (this.___startNode as ChildNode).remove();
},
___getParentNode() {
return this.___getFirstNode().parentNode!;
@@ -37,27 +37,27 @@ export const staticNodeMethods: DOMMethods = {
return this.___getLastNode().nextSibling;
},
___getFirstNode() {
- return this[ScopeOffsets.START_NODE] as ChildNode;
+ return this.___startNode as ChildNode;
},
___getLastNode() {
- return this[ScopeOffsets.END_NODE] as ChildNode;
+ return this.___endNode as ChildNode;
},
};
// export const staticNodePropertiesDef = {
// ___insertBefore: {
// value(parent, nextSibling) {
-// parent.insertBefore(this[ScopeOffsets.START_NODE] as Node, nextSibling);
+// parent.insertBefore(this.___startNode as Node, nextSibling);
// }
// },
// ___remove: {
// value() {
-// (this[ScopeOffsets.START_NODE] as ChildNode).remove();
+// (this.___startNode as ChildNode).remove();
// }
// },
// ___parentNode: {
// get() {
-// return this[ScopeOffsets.START_NODE].parentNode;
+// return this.___startNode.parentNode;
// },
// },
// ___afterNode: {
diff --git a/packages/runtime/src/dom/hydrate.ts b/packages/runtime/src/dom/hydrate.ts
index f35d72f58..38766d620 100644
--- a/packages/runtime/src/dom/hydrate.ts
+++ b/packages/runtime/src/dom/hydrate.ts
@@ -1,4 +1,4 @@
-import { Scope, ScopeOffsets, HydrateSymbols } from "../common/types";
+import { Scope, HydrateSymbols } from "../common/types";
import { bind, runWithScope } from "./scope";
type HydrateFn = () => void;
@@ -66,8 +66,10 @@ export function init(runtimeId = "M" /* [a-zA-Z0-9]+ */) {
if (storedScope !== scope) {
if (storedScope) {
Object.assign(scope, storedScope);
+ } else {
+ scope.___id = scopeId;
+ scopeLookup[scopeId] = scope;
}
- scopeLookup[scopeId] = scope;
if (currentScope === storedScope) {
currentScope = scope;
}
@@ -83,7 +85,7 @@ export function init(runtimeId = "M" /* [a-zA-Z0-9]+ */) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
const [offset, scopeId, index] = data.split(" ");
- if (scopeId !== currentScope[ScopeOffsets.ID]) {
+ if (scopeId !== currentScope.___id) {
throw new Error("INVALID_MARKER_NESTING: " + nodeValue);
}
if (parseInt(offset) + currentOffset !== parseInt(index)) {
@@ -96,22 +98,23 @@ export function init(runtimeId = "M" /* [a-zA-Z0-9]+ */) {
currentScope[(currentOffset += offset)] = node;
} else if (token === HydrateSymbols.SCOPE_START) {
if (currentScope) {
- stack.push(currentScope[ScopeOffsets.ID] as string, currentOffset);
+ stack.push(currentScope.___id, currentOffset);
}
currentScope = scopeLookup[data]!;
currentOffset = 0;
if (!currentScope) {
- scopeLookup[data] = currentScope = [data] as unknown as Scope;
+ scopeLookup[data] = currentScope = [] as unknown as Scope;
+ currentScope.___id = data;
}
- currentScope[ScopeOffsets.START_NODE] = currentNode;
+ currentScope.___startNode = currentNode;
} else if (token === HydrateSymbols.SCOPE_END) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
- if (data !== currentScope[ScopeOffsets.ID]) {
+ if (data !== currentScope.___id) {
throw new Error("SCOPE_END_MISMATCH: " + nodeValue);
}
}
- currentScope[ScopeOffsets.END_NODE] = currentNode;
+ currentScope.___endNode = currentNode;
currentOffset = stack.pop() as number;
currentScope = scopeLookup[stack.pop() as string]!;
// eslint-disable-next-line no-constant-condition
diff --git a/packages/runtime/src/dom/queue.ts b/packages/runtime/src/dom/queue.ts
index b87a8bfb3..250c9775c 100644
--- a/packages/runtime/src/dom/queue.ts
+++ b/packages/runtime/src/dom/queue.ts
@@ -1,4 +1,4 @@
-import { Scope, ScopeOffsets } from "../common/types";
+import { Scope } from "../common/types";
import {
runWithScope,
currentScope,
@@ -129,8 +129,8 @@ function findQueueIndex(scope: Scope, sortValue: number) {
function compareQueue(index: number, scope: Scope, sortValue: number) {
return (
compare(
- (queuedFns[index + QueueOffsets.SCOPE] as Scope)[ScopeOffsets.ID],
- scope[ScopeOffsets.ID]
+ (queuedFns[index + QueueOffsets.SCOPE] as Scope).___id,
+ scope.___id
) || (queuedFns[index + QueueOffsets.SORT_VALUE] as number) - sortValue
);
}
diff --git a/packages/runtime/src/dom/renderer.ts b/packages/runtime/src/dom/renderer.ts
index ccc6fd510..3e574dd88 100644
--- a/packages/runtime/src/dom/renderer.ts
+++ b/packages/runtime/src/dom/renderer.ts
@@ -36,21 +36,21 @@ type RenderResult = Node & {
export function initRenderer(renderer: Renderer, scope: Scope) {
const dom = renderer.___clone();
- scope[ScopeOffsets.START_NODE] =
+ scope.___startNode =
dom.nodeType === NodeType.DocumentFragment ? dom.firstChild! : dom;
- scope[ScopeOffsets.END_NODE] =
+ scope.___endNode =
dom.nodeType === NodeType.DocumentFragment ? dom.lastChild! : dom;
- walk(scope[ScopeOffsets.START_NODE] as Node, renderer.___walks!, scope);
+ walk(scope.___startNode as Node, renderer.___walks!, scope);
if (renderer.___render) {
runWithScope(renderer.___render, ScopeOffsets.BEGIN_DATA, scope);
}
if (renderer.___dynamicStartNodeMethod) {
scope.___getFirstNode = renderer.___dynamicStartNodeMethod;
- scope[ScopeOffsets.START_NODE] = renderer.___dynamicStartNodeOffset!;
+ scope.___startNode = renderer.___dynamicStartNodeOffset!;
}
if (renderer.___dynamicEndNodeMethod) {
scope.___getLastNode = renderer.___dynamicEndNodeMethod;
- scope[ScopeOffsets.END_NODE] = renderer.___dynamicEndNodeOffset!;
+ scope.___endNode = renderer.___dynamicEndNodeOffset!;
}
return dom;
}
diff --git a/packages/runtime/src/dom/scope.ts b/packages/runtime/src/dom/scope.ts
index b03fcb477..45e004e8e 100644
--- a/packages/runtime/src/dom/scope.ts
+++ b/packages/runtime/src/dom/scope.ts
@@ -9,7 +9,7 @@ let scopeId = 0;
export function createScope(size: number, methods: DOMMethods): Scope {
const scope = new Array(size) as Scope;
- scope[ScopeOffsets.ID] = "" + scopeId++;
+ scope.___id = "" + scopeId++;
scope[ScopeOffsets.OWNER_SCOPE] = currentScope;
scope[ScopeOffsets.OWNER_OFFSET] = currentOffset;
return Object.assign(scope, methods);
@@ -17,8 +17,7 @@ export function createScope(size: number, methods: DOMMethods): Scope {
const emptyScope = createScope(0, staticNodeMethods);
export function getEmptyScope(marker?: Comment) {
- emptyScope[ScopeOffsets.START_NODE] = emptyScope[ScopeOffsets.END_NODE] =
- marker;
+ emptyScope.___startNode = emptyScope.___endNode = marker;
return emptyScope;
}
@@ -106,9 +105,9 @@ export function runInChild(fn: () => void, offset: number) {
}
export function destroyScope(scope: Scope) {
- scope[ScopeOffsets.OWNER_SCOPE]?.[ScopeOffsets.CLEANUP]?.delete(scope);
+ scope[ScopeOffsets.OWNER_SCOPE]?.___cleanup?.delete(scope);
- const cleanup = scope[ScopeOffsets.CLEANUP];
+ const cleanup = scope.___cleanup;
if (cleanup) {
for (const instance of cleanup) {
if (typeof instance === "number") {
@@ -124,11 +123,11 @@ export function destroyScope(scope: Scope) {
export function onDestroy(localIndex: number) {
const parentScope = currentScope[ScopeOffsets.OWNER_SCOPE];
if (parentScope) {
- (parentScope[ScopeOffsets.CLEANUP] =
- parentScope[ScopeOffsets.CLEANUP] || new Set()).add(currentScope);
+ (parentScope.___cleanup = parentScope.___cleanup || new Set()).add(
+ currentScope
+ );
}
- (currentScope[ScopeOffsets.CLEANUP] =
- currentScope[ScopeOffsets.CLEANUP] || new Set()).add(
+ (currentScope.___cleanup = currentScope.___cleanup || new Set()).add(
currentOffset + localIndex
);
}
diff --git a/packages/runtime/src/html/writer.ts b/packages/runtime/src/html/writer.ts
index 18e995e2c..e2baa3ecf 100644
--- a/packages/runtime/src/html/writer.ts
+++ b/packages/runtime/src/html/writer.ts
@@ -43,7 +43,9 @@ export function createRenderer(renderer: Renderer, hydrateRoot?: boolean) {
try {
let renderedPromises: typeof $_promises;
try {
- const scope = hydrateRoot ? (["ROOT"] as any as Scope) : nullScope;
+ const scope = hydrateRoot
+ ? (Object.assign([], { ___id: "ROOT" }) as any as Scope)
+ : nullScope;
hydrateRoot && write(markScopeStart(scope));
renderer(input, scope, ScopeOffsets.BEGIN_DATA);
hydrateRoot && write(markScopeEnd(scope));
@@ -74,7 +76,7 @@ export function writeCall(fnId: string, offset: number, scopeId: string) {
export function writeScope(scope: Scope) {
$_buffer!.scopes = $_buffer!.scopes || {};
- $_buffer!.scopes[scope[ScopeOffsets.ID]] = scope;
+ $_buffer!.scopes[scope.___id] = scope;
}
export function fork(
@@ -254,25 +256,19 @@ export function markScopeOffset(index: number, scope: Scope) {
lastIndex.set(scope, index);
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
- return ``;
+ return ``;
}
return ``;
}
export function markScopeStart(scope: Scope) {
- return ``;
+ return ``;
}
export function markScopeEnd(scope: Scope) {
// eslint-disable-next-line no-constant-condition
if ("MARKO_DEBUG") {
- return ``;
+ return ``;
}
return ``;
}