@askrjs/askr 0.0.33 → 0.0.35
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.
- package/dist/benchmark.js +2 -2
- package/dist/common/router.d.ts +8 -1
- package/dist/common/router.d.ts.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/renderer/children.js +2 -2
- package/dist/renderer/children.js.map +1 -1
- package/dist/renderer/dom.js +28 -5
- package/dist/renderer/dom.js.map +1 -1
- package/dist/renderer/evaluate.js +2 -2
- package/dist/renderer/evaluate.js.map +1 -1
- package/dist/router/index.d.ts +3 -3
- package/dist/router/index.js +2 -2
- package/dist/router/navigate.d.ts.map +1 -1
- package/dist/router/navigate.js +4 -1
- package/dist/router/navigate.js.map +1 -1
- package/dist/router/route.d.ts +11 -2
- package/dist/router/route.d.ts.map +1 -1
- package/dist/router/route.js +271 -81
- package/dist/router/route.js.map +1 -1
- package/dist/runtime/fastlane.js +2 -2
- package/dist/runtime/fastlane.js.map +1 -1
- package/dist/runtime/for.d.ts.map +1 -1
- package/dist/runtime/for.js +9 -4
- package/dist/runtime/for.js.map +1 -1
- package/dist/runtime/readable.d.ts +1 -1
- package/dist/runtime/readable.d.ts.map +1 -1
- package/dist/runtime/readable.js +2 -1
- package/dist/runtime/readable.js.map +1 -1
- package/package.json +2 -2
package/dist/benchmark.js
CHANGED
|
@@ -10,8 +10,8 @@ import { BenchmarkTable } from "./bench/components/benchmark-table.js";
|
|
|
10
10
|
installRendererBridge();
|
|
11
11
|
const benchmarkMetadata = {
|
|
12
12
|
packageName: "@askrjs/askr",
|
|
13
|
-
packageVersion: "0.0.
|
|
14
|
-
buildLabel: "0.0.
|
|
13
|
+
packageVersion: "0.0.35",
|
|
14
|
+
buildLabel: "0.0.35-local"
|
|
15
15
|
};
|
|
16
16
|
function getBenchmarkMetadata() {
|
|
17
17
|
return { ...benchmarkMetadata };
|
package/dist/common/router.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ interface RouteOptions extends CommonAccessOptions {
|
|
|
73
73
|
title?: string;
|
|
74
74
|
namespace?: string;
|
|
75
75
|
}
|
|
76
|
+
interface PageHelperOptions extends CommonAccessOptions {}
|
|
76
77
|
/**
|
|
77
78
|
* A single parsed segment from a route path.
|
|
78
79
|
*
|
|
@@ -92,6 +93,10 @@ interface LayoutScopeRecord {
|
|
|
92
93
|
children?: unknown;
|
|
93
94
|
}) => unknown;
|
|
94
95
|
}
|
|
96
|
+
/** Resolved page host component as stored in a route record's page chain. */
|
|
97
|
+
interface PageScopeRecord {
|
|
98
|
+
component: RouteComponent;
|
|
99
|
+
}
|
|
95
100
|
interface RegisterRoutesOptions {
|
|
96
101
|
auth?: RouteAuthOptions;
|
|
97
102
|
}
|
|
@@ -132,6 +137,8 @@ interface RouteRecord {
|
|
|
132
137
|
rank: number;
|
|
133
138
|
/** Layout chain from outermost to innermost, applied automatically on render */
|
|
134
139
|
layoutChain: LayoutScopeRecord[];
|
|
140
|
+
/** Page chain from outermost to innermost, composed through Outlet before layouts apply */
|
|
141
|
+
pageChain: PageScopeRecord[];
|
|
135
142
|
/** Route metadata: loader, entries, policies, title, namespace */
|
|
136
143
|
options: RouteOptions;
|
|
137
144
|
/** True when this is the `/*` catch-all fallback route */
|
|
@@ -193,5 +200,5 @@ interface RouteSnapshot {
|
|
|
193
200
|
matches: readonly RouteMatch[];
|
|
194
201
|
}
|
|
195
202
|
//#endregion
|
|
196
|
-
export { AccessDecision, AccessDenyDecision, AccessDenyStatus, AccessRedirectDecision, AccessRedirectStatus, GroupHelperOptions, LayoutScopeRecord, ParsedSegment, RegisterRoutesOptions, ResolvedRoute, Route, RouteAuthMode, RouteAuthOptions, RouteAuthResolver, RouteAuthState, RouteComponent, RouteContext, RouteDefinition, RouteHandler, RouteManifest, RouteMatch, RouteMode, RouteOptions, RoutePolicy, RouteQuery, RouteRecord, RouteRenderResult, RouteRequestOptions, RouteRequestResult, RouteSnapshot };
|
|
203
|
+
export { AccessDecision, AccessDenyDecision, AccessDenyStatus, AccessRedirectDecision, AccessRedirectStatus, GroupHelperOptions, LayoutScopeRecord, PageHelperOptions, PageScopeRecord, ParsedSegment, RegisterRoutesOptions, ResolvedRoute, Route, RouteAuthMode, RouteAuthOptions, RouteAuthResolver, RouteAuthState, RouteComponent, RouteContext, RouteDefinition, RouteHandler, RouteManifest, RouteMatch, RouteMode, RouteOptions, RoutePolicy, RouteQuery, RouteRecord, RouteRenderResult, RouteRequestOptions, RouteRequestResult, RouteSnapshot };
|
|
197
204
|
//# sourceMappingURL=router.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","names":[],"sources":["../../src/common/router.ts"],"mappings":";;AAUA;;;;;AAEA;;;KAFY,cAAA,IAAkB,KAAA,EAAO,MAAA;AAAA,KAEzB,SAAA;AAAA,KACA,aAAA;AAAA,KACA,oBAAA;AAAA,KACA,gBAAA;AAAA,UAEK,mBAAA;EACf,IAAA;AAAA;AAAA,UAGe,sBAAA;EACf,IAAA;EACA,EAAA;EACA,MAAA,GAAS,oBAAA;EACT,OAAA;AAAA;AAAA,UAGe,kBAAA;EACf,IAAA;EACA,MAAA,EAAQ,gBAAA;AAAA;AAAA,KAGE,cAAA,GACR,mBAAA,GACA,sBAAA,GACA,kBAAA;AAAA,UAEa,YAAA;EACf,IAAA,EAAM,SAAA;EACN,MAAA,EAAQ,MAAA;EACR,QAAA;EACA,MAAA;EACA,IAAA;EACA,IAAA;EACA,OAAA,EAAS,OAAA;EACT,IAAA,EAAM,IAAA;EACN,MAAA,EAAQ,WAAA;AAAA;AAAA,KAGE,WAAA,IACV,OAAA,EAAS,YAAA,KACN,cAAA,GAAiB,OAAA,CAAQ,cAAA;AAAA,UAEb,cAAA;EACf,OAAA,EAAS,OAAA;EACT,IAAA,EAAM,IAAA;AAAA;AAAA,KAGI,iBAAA,uCACV,OAAA,EAAS,IAAA,CAAK,YAAA,CAAa,OAAA,EAAS,IAAA,2BACjC,cAAA,CAAe,OAAA,EAAS,IAAA,IAAQ,OAAA,CAAQ,cAAA,CAAe,OAAA,EAAS,IAAA;AAAA,UAEpD,gBAAA;EACf,OAAA,EAAS,iBAAA,CAAkB,OAAA,EAAS,IAAA;EACpC,SAAA,cAEM,OAAA,EAAS,YAAA,CAAa,OAAA,EAAS,IAAA,eAAmB,OAAA;EACxD,eAAA,cAEM,OAAA,EAAS,YAAA,CAAa,OAAA,EAAS,IAAA,eAAmB,OAAA;EACxD,OAAA,IACE,IAAA,EAAM,IAAA,EACN,IAAA,UACA,OAAA,EAAS,YAAA,CAAa,OAAA,EAAS,IAAA,gBAClB,OAAA;EACf,aAAA,IACE,IAAA,EAAM,IAAA,EACN,UAAA,UACA,OAAA,EAAS,YAAA,CAAa,OAAA,EAAS,IAAA,gBAClB,OAAA;AAAA;AAAA,UAGA,mBAAA;EACf,IAAA,GAAO,aAAA;EACP,IAAA;EACA,UAAA;EACA,QAAA,YAAoB,WAAA;AAAA;;;;;;;AAjDtB;;UA4DiB,YAAA,SAAqB,mBAAA;EACpC,MAAA,IAAU,OAAA;IAAW,MAAA,EAAQ,MAAA;EAAA;EAC7B,OAAA,SACI,KAAA,CAAM,MAAA,oBACN,OAAA,CAAQ,KAAA,CAAM,MAAA;EAClB,KAAA;EACA,SAAA;AAAA;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"router.d.ts","names":[],"sources":["../../src/common/router.ts"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -4,7 +4,7 @@ import { State, state } from "./runtime/state.js";
|
|
|
4
4
|
import { Context, defineContext, readContext } from "./runtime/context.js";
|
|
5
5
|
import { getSignal } from "./runtime/component.js";
|
|
6
6
|
import { For, ForProps } from "./control/for.js";
|
|
7
|
-
import { AccessDecision, AccessDenyDecision, AccessRedirectDecision, GroupHelperOptions, RegisterRoutesOptions, RouteAuthMode, RouteAuthOptions, RouteAuthResolver, RouteAuthState, RouteComponent, RouteContext, RouteDefinition, RouteManifest, RouteMatch, RouteMode, RouteOptions, RoutePolicy, RouteRecord, RouteRenderResult, RouteRequestOptions, RouteRequestResult, RouteSnapshot } from "./common/router.js";
|
|
7
|
+
import { AccessDecision, AccessDenyDecision, AccessRedirectDecision, GroupHelperOptions, PageHelperOptions, PageScopeRecord, RegisterRoutesOptions, RouteAuthMode, RouteAuthOptions, RouteAuthResolver, RouteAuthState, RouteComponent, RouteContext, RouteDefinition, RouteManifest, RouteMatch, RouteMode, RouteOptions, RoutePolicy, RouteRecord, RouteRenderResult, RouteRequestOptions, RouteRequestResult, RouteSnapshot } from "./common/router.js";
|
|
8
8
|
import { HistoryScrollBehavior, NavigateOptions, NavigationScrollBehavior, ScrollRestorationOptions, navigate } from "./router/navigate.js";
|
|
9
9
|
import { HydrateSPAConfig, IslandConfig, IslandsConfig, SPAConfig, cleanupApp, createIsland, createIslands, createSPA, hasApp, hydrateSPA } from "./boot/index.js";
|
|
10
10
|
import { Show, ShowProps } from "./control/show.js";
|
|
@@ -16,8 +16,8 @@ import { Derived, derive } from "./runtime/derive.js";
|
|
|
16
16
|
import { Selector, selector } from "./runtime/selector.js";
|
|
17
17
|
import { ResourceResult, resource } from "./runtime/operations.js";
|
|
18
18
|
import { Mutation, Query, QueryConsistency, createMutation, createQuery, invalidate } from "./data/index.js";
|
|
19
|
-
import { currentRoute, fallback, group, lazy, registerRoutes, resolveRouteRequest, route } from "./router/route.js";
|
|
19
|
+
import { Outlet, currentRoute, fallback, group, index, lazy, page, registerRoutes, resolveRouteRequest, route } from "./router/route.js";
|
|
20
20
|
import { allow, deny, forbidden, notFound, redirect, requireAuth, requirePermission, requireRole, unauthorized } from "./router/policy.js";
|
|
21
21
|
import { Link, LinkProps } from "./components/link.js";
|
|
22
22
|
import { ErrorBoundary, ErrorBoundaryFallbackRender, ErrorBoundaryProps } from "./components/error-boundary.js";
|
|
23
|
-
export { type AccessDecision, type AccessDenyDecision, type AccessRedirectDecision, Case, type CaseProps, type Context, DefaultPortal, type Derived, ErrorBoundary, type ErrorBoundaryFallbackRender, type ErrorBoundaryProps, For, type ForProps, Fragment, type GroupHelperOptions, type HistoryScrollBehavior, type HydrateSPAConfig, type IslandConfig, type IslandsConfig, Link, type LinkProps, Match, type MatchProps, type Mutation, type NavigateOptions, type NavigationScrollBehavior, Portal, type PortalProps, type Props, type Query, type QueryConsistency, type RegisterRoutesOptions, type ResourceResult, type RouteAuthMode, type RouteAuthOptions, type RouteAuthResolver, type RouteAuthState, type RouteComponent, type RouteContext, type RouteDefinition, type RouteManifest, type RouteMatch, type RouteMode, type RouteOptions, type RoutePolicy, type RouteRecord, type RouteRenderResult, type RouteRequestOptions, type RouteRequestResult, type RouteSnapshot, type SPAConfig, type ScrollRestorationOptions, type Selector, Show, type ShowProps, Slot, type SlotProps, type State, allow, cleanupApp, createIsland, createIslands, createMutation, createQuery, createSPA, currentRoute, defineContext, definePortal, deny, derive, fallback, forbidden, getSignal, group, hasApp, hydrateSPA, invalidate, jsx, jsxs, lazy, navigate, notFound, readContext, redirect, registerRoutes, requireAuth, requirePermission, requireRole, resolveRouteRequest, resource, route, selector, state, unauthorized };
|
|
23
|
+
export { type AccessDecision, type AccessDenyDecision, type AccessRedirectDecision, Case, type CaseProps, type Context, DefaultPortal, type Derived, ErrorBoundary, type ErrorBoundaryFallbackRender, type ErrorBoundaryProps, For, type ForProps, Fragment, type GroupHelperOptions, type HistoryScrollBehavior, type HydrateSPAConfig, type IslandConfig, type IslandsConfig, Link, type LinkProps, Match, type MatchProps, type Mutation, type NavigateOptions, type NavigationScrollBehavior, Outlet, type PageHelperOptions, type PageScopeRecord, Portal, type PortalProps, type Props, type Query, type QueryConsistency, type RegisterRoutesOptions, type ResourceResult, type RouteAuthMode, type RouteAuthOptions, type RouteAuthResolver, type RouteAuthState, type RouteComponent, type RouteContext, type RouteDefinition, type RouteManifest, type RouteMatch, type RouteMode, type RouteOptions, type RoutePolicy, type RouteRecord, type RouteRenderResult, type RouteRequestOptions, type RouteRequestResult, type RouteSnapshot, type SPAConfig, type ScrollRestorationOptions, type Selector, Show, type ShowProps, Slot, type SlotProps, type State, allow, cleanupApp, createIsland, createIslands, createMutation, createQuery, createSPA, currentRoute, defineContext, definePortal, deny, derive, fallback, forbidden, getSignal, group, hasApp, hydrateSPA, index, invalidate, jsx, jsxs, lazy, navigate, notFound, page, readContext, redirect, registerRoutes, requireAuth, requirePermission, requireRole, resolveRouteRequest, resource, route, selector, state, unauthorized };
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { selector } from "./runtime/selector.js";
|
|
|
10
10
|
import { resource } from "./runtime/operations.js";
|
|
11
11
|
import { createMutation, createQuery, invalidate } from "./data/index.js";
|
|
12
12
|
import { allow, deny, forbidden, notFound, redirect, requireAuth, requirePermission, requireRole, unauthorized } from "./router/policy.js";
|
|
13
|
-
import { currentRoute, fallback, group, lazy, registerRoutes, resolveRouteRequest, route } from "./router/route.js";
|
|
13
|
+
import { Outlet, currentRoute, fallback, group, index, lazy, page, registerRoutes, resolveRouteRequest, route } from "./router/route.js";
|
|
14
14
|
import { DefaultPortal, Portal, definePortal } from "./foundations/structures/portal.js";
|
|
15
15
|
import { navigate } from "./router/navigate.js";
|
|
16
16
|
import { cleanupApp, createIsland, createIslands, createSPA, hasApp, hydrateSPA } from "./boot/index.js";
|
|
@@ -31,6 +31,6 @@ import "./foundations/structures.js";
|
|
|
31
31
|
*/
|
|
32
32
|
installRendererBridge();
|
|
33
33
|
//#endregion
|
|
34
|
-
export { Case, DefaultPortal, ErrorBoundary, For, Fragment, Link, Match, Portal, Show, Slot, allow, cleanupApp, createIsland, createIslands, createMutation, createQuery, createSPA, currentRoute, defineContext, definePortal, deny, derive, fallback, forbidden, getSignal, group, hasApp, hydrateSPA, invalidate, jsx, jsxs, lazy, navigate, notFound, readContext, redirect, registerRoutes, requireAuth, requirePermission, requireRole, resolveRouteRequest, resource, route, selector, state, unauthorized };
|
|
34
|
+
export { Case, DefaultPortal, ErrorBoundary, For, Fragment, Link, Match, Outlet, Portal, Show, Slot, allow, cleanupApp, createIsland, createIslands, createMutation, createQuery, createSPA, currentRoute, defineContext, definePortal, deny, derive, fallback, forbidden, getSignal, group, hasApp, hydrateSPA, index, invalidate, jsx, jsxs, lazy, navigate, notFound, page, readContext, redirect, registerRoutes, requireAuth, requirePermission, requireRole, resolveRouteRequest, resource, route, selector, state, unauthorized };
|
|
35
35
|
|
|
36
36
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Askr: Actor-backed deterministic UI framework\n *\n * Public API surface — only users should import from here\n */\n\nimport { installRendererBridge } from './renderer';\n\ninstallRendererBridge();\n\n// Runtime primitives\nexport { state } from './runtime/state';\nexport type { State } from './runtime/state';\nexport { derive } from './runtime/derive';\nexport type { Derived } from './runtime/derive';\nexport { getSignal } from './runtime/component';\nexport { selector } from './runtime/selector';\nexport type { Selector } from './runtime/selector';\n\n// Context\nexport { defineContext, readContext } from './runtime/context';\nexport type { Context } from './runtime/context';\n\n// Resources\nexport { resource } from './runtime/operations';\nexport type { ResourceResult } from './runtime/operations';\n\n// Data\nexport { createQuery, createMutation, invalidate } from './data';\nexport type { Query, Mutation, QueryConsistency } from './data';\n\n// App bootstrap\nexport {\n createIsland,\n createIslands,\n createSPA,\n hydrateSPA,\n cleanupApp,\n hasApp,\n} from './boot';\nexport type {\n IslandConfig,\n IslandsConfig,\n SPAConfig,\n HydrateSPAConfig,\n} from './boot';\n\n// Routing\nexport {\n registerRoutes,\n route,\n currentRoute,\n group,\n fallback,\n lazy,\n allow,\n redirect,\n deny,\n unauthorized,\n forbidden,\n notFound,\n requireAuth,\n requireRole,\n requirePermission,\n resolveRouteRequest,\n type RouteSnapshot,\n type RouteMatch,\n type RouteComponent,\n type RouteMode,\n type RouteAuthMode,\n type RouteContext,\n type RoutePolicy,\n type RouteOptions,\n type RouteRecord,\n type RouteManifest,\n type AccessDecision,\n type AccessDenyDecision,\n type AccessRedirectDecision,\n type GroupHelperOptions,\n type RegisterRoutesOptions,\n type RouteDefinition,\n type RouteAuthOptions,\n type RouteAuthResolver,\n type RouteAuthState,\n type RouteRenderResult,\n type RouteRequestOptions,\n type RouteRequestResult,\n} from './router';\nexport { navigate } from './router/navigate';\nexport type {\n NavigateOptions,\n NavigationScrollBehavior,\n HistoryScrollBehavior,\n ScrollRestorationOptions,\n} from './router/navigate';\n\n// Components\nexport { Link } from './components/link';\nexport type { LinkProps } from './components/link';\nexport { ErrorBoundary } from './components/error-boundary';\nexport type {\n ErrorBoundaryProps,\n ErrorBoundaryFallbackRender,\n} from './components/error-boundary';\nexport { Case, For, Match, Show } from './control';\nexport type { CaseProps, ForProps, MatchProps, ShowProps } from './control';\nexport {\n Slot,\n definePortal,\n DefaultPortal,\n Portal,\n} from './foundations/structures';\nexport type { SlotProps, PortalProps } from './foundations/structures';\n\n// Re-export JSX runtime for tsconfig jsxImportSource\nexport { jsx, jsxs, Fragment } from './jsx-runtime';\n\n// Public types\nexport type { Props } from './common/props';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,uBAAuB"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Askr: Actor-backed deterministic UI framework\n *\n * Public API surface — only users should import from here\n */\n\nimport { installRendererBridge } from './renderer';\n\ninstallRendererBridge();\n\n// Runtime primitives\nexport { state } from './runtime/state';\nexport type { State } from './runtime/state';\nexport { derive } from './runtime/derive';\nexport type { Derived } from './runtime/derive';\nexport { getSignal } from './runtime/component';\nexport { selector } from './runtime/selector';\nexport type { Selector } from './runtime/selector';\n\n// Context\nexport { defineContext, readContext } from './runtime/context';\nexport type { Context } from './runtime/context';\n\n// Resources\nexport { resource } from './runtime/operations';\nexport type { ResourceResult } from './runtime/operations';\n\n// Data\nexport { createQuery, createMutation, invalidate } from './data';\nexport type { Query, Mutation, QueryConsistency } from './data';\n\n// App bootstrap\nexport {\n createIsland,\n createIslands,\n createSPA,\n hydrateSPA,\n cleanupApp,\n hasApp,\n} from './boot';\nexport type {\n IslandConfig,\n IslandsConfig,\n SPAConfig,\n HydrateSPAConfig,\n} from './boot';\n\n// Routing\nexport {\n registerRoutes,\n route,\n page,\n index,\n Outlet,\n currentRoute,\n group,\n fallback,\n lazy,\n allow,\n redirect,\n deny,\n unauthorized,\n forbidden,\n notFound,\n requireAuth,\n requireRole,\n requirePermission,\n resolveRouteRequest,\n type RouteSnapshot,\n type RouteMatch,\n type RouteComponent,\n type RouteMode,\n type RouteAuthMode,\n type RouteContext,\n type RoutePolicy,\n type RouteOptions,\n type RouteRecord,\n type RouteManifest,\n type PageScopeRecord,\n type AccessDecision,\n type AccessDenyDecision,\n type AccessRedirectDecision,\n type GroupHelperOptions,\n type PageHelperOptions,\n type RegisterRoutesOptions,\n type RouteDefinition,\n type RouteAuthOptions,\n type RouteAuthResolver,\n type RouteAuthState,\n type RouteRenderResult,\n type RouteRequestOptions,\n type RouteRequestResult,\n} from './router';\nexport { navigate } from './router/navigate';\nexport type {\n NavigateOptions,\n NavigationScrollBehavior,\n HistoryScrollBehavior,\n ScrollRestorationOptions,\n} from './router/navigate';\n\n// Components\nexport { Link } from './components/link';\nexport type { LinkProps } from './components/link';\nexport { ErrorBoundary } from './components/error-boundary';\nexport type {\n ErrorBoundaryProps,\n ErrorBoundaryFallbackRender,\n} from './components/error-boundary';\nexport { Case, For, Match, Show } from './control';\nexport type { CaseProps, ForProps, MatchProps, ShowProps } from './control';\nexport {\n Slot,\n definePortal,\n DefaultPortal,\n Portal,\n} from './foundations/structures';\nexport type { SlotProps, PortalProps } from './foundations/structures';\n\n// Re-export JSX runtime for tsconfig jsxImportSource\nexport { jsx, jsxs, Fragment } from './jsx-runtime';\n\n// Public types\nexport type { Props } from './common/props';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQA,uBAAuB"}
|
|
@@ -85,7 +85,7 @@ function updateTextContent(el, children, vnode) {
|
|
|
85
85
|
if (!tryUpdateTwoChildTextPattern(el, vnode)) updateElementFromVnode(el, vnode);
|
|
86
86
|
}
|
|
87
87
|
function tryUpdateTwoChildTextPattern(parentEl, vnode) {
|
|
88
|
-
const vnodeChildren = vnode.children
|
|
88
|
+
const vnodeChildren = vnode.props?.children ?? vnode.children;
|
|
89
89
|
if (!Array.isArray(vnodeChildren) || vnodeChildren.length !== 2) return false;
|
|
90
90
|
const firstChild = vnodeChildren[0];
|
|
91
91
|
const secondChild = vnodeChildren[1];
|
|
@@ -276,7 +276,7 @@ function countSimpleChildren(children) {
|
|
|
276
276
|
return { simple };
|
|
277
277
|
}
|
|
278
278
|
function isSimpleElement(dom) {
|
|
279
|
-
const children = dom.children
|
|
279
|
+
const children = dom.props?.children ?? dom.children;
|
|
280
280
|
if (children === null || children === void 0) return true;
|
|
281
281
|
if (typeof children === "string" || typeof children === "number") return true;
|
|
282
282
|
if (Array.isArray(children) && children.length === 1 && (typeof children[0] === "string" || typeof children[0] === "number")) return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"children.js","names":[],"sources":["../../src/renderer/children.ts"],"sourcesContent":["import { setDevValue, incDevCounter } from '../runtime/dev-namespace';\nimport { getRuntimeEnv } from './env';\nimport { keyedElements } from './keyed';\nimport { teardownNodeSubtree } from './cleanup';\nimport { createDOMNode, updateElementFromVnode } from './dom';\nimport { _isDOMElement, type DOMElement, type VNode } from './types';\nimport {\n hasNonTrivialProps,\n logFastPathDebug,\n now,\n recordDOMReplace,\n recordFastPathStats,\n tagNamesEqualIgnoreCase,\n} from './utils';\n\nfunction upperCommonTagName(tag: string): string | null {\n switch (tag) {\n case 'div':\n return 'DIV';\n case 'span':\n return 'SPAN';\n case 'p':\n return 'P';\n case 'a':\n return 'A';\n case 'button':\n return 'BUTTON';\n case 'input':\n return 'INPUT';\n case 'ul':\n return 'UL';\n case 'ol':\n return 'OL';\n case 'li':\n return 'LI';\n default:\n return null;\n }\n}\n\nfunction tagsEqualIgnoreCase(\n elementTagName: string,\n vnodeType: string\n): boolean {\n if (elementTagName === vnodeType) return true;\n\n const upperCommon = upperCommonTagName(vnodeType);\n if (upperCommon !== null && elementTagName === upperCommon) return true;\n\n return tagNamesEqualIgnoreCase(elementTagName, vnodeType);\n}\n\nexport function performBulkPositionalKeyedTextUpdate(\n parent: Element,\n keyedVnodes: Array<{ key: string | number; vnode: VNode }>\n) {\n const total = keyedVnodes.length;\n let reused = 0;\n let updatedKeys = 0;\n const start = now();\n const env = getRuntimeEnv();\n const debugFastPath =\n env.ASKR_FASTPATH_DEBUG === '1' || env.ASKR_FASTPATH_DEBUG === 'true';\n\n for (let index = 0; index < total; index += 1) {\n const { key, vnode } = keyedVnodes[index];\n const child = parent.children[index] as Element | undefined;\n\n if (\n child &&\n _isDOMElement(vnode) &&\n typeof (vnode as DOMElement).type === 'string'\n ) {\n const vnodeType = (vnode as DOMElement).type as string;\n\n if (tagsEqualIgnoreCase(child.tagName, vnodeType)) {\n const children =\n (vnode as DOMElement).children ||\n (vnode as DOMElement).props?.children;\n\n if (debugFastPath) {\n logFastPathDebug('positional idx', index, {\n chTag: child.tagName,\n vnodeType,\n chChildNodes: child.childNodes.length,\n childrenType: Array.isArray(children) ? 'array' : typeof children,\n });\n }\n\n updateTextContent(child, children, vnode as DOMElement);\n setDataKey(child, key, () => (updatedKeys += 1));\n reused += 1;\n continue;\n }\n\n if (debugFastPath) {\n logFastPathDebug('positional tag mismatch', index, {\n chTag: child.tagName,\n vnodeType,\n });\n }\n } else if (debugFastPath) {\n logFastPathDebug('positional missing or invalid', index, { ch: !!child });\n }\n\n replaceNodeAtPosition(parent, index, vnode);\n }\n\n const elapsed = now() - start;\n updateKeyedElementsMap(parent, keyedVnodes);\n\n const stats = { n: total, reused, updatedKeys, t: elapsed } as const;\n recordFastPathStats(stats, 'bulkKeyedPositionalHits');\n\n return stats;\n}\n\nfunction updateTextContent(\n el: Element,\n children: unknown,\n vnode: DOMElement\n): void {\n if (typeof children === 'string' || typeof children === 'number') {\n setTextNodeData(el, String(children));\n if (vnode.props && hasNonTrivialProps(vnode.props)) {\n updateElementFromVnode(el, vnode, false);\n }\n return;\n }\n\n if (\n Array.isArray(children) &&\n children.length === 1 &&\n (typeof children[0] === 'string' || typeof children[0] === 'number')\n ) {\n setTextNodeData(el, String(children[0]));\n if (vnode.props && hasNonTrivialProps(vnode.props)) {\n updateElementFromVnode(el, vnode, false);\n }\n return;\n }\n\n if (!tryUpdateTwoChildTextPattern(el, vnode)) {\n updateElementFromVnode(el, vnode);\n }\n}\n\nfunction tryUpdateTwoChildTextPattern(\n parentEl: Element,\n vnode: DOMElement\n): boolean {\n const vnodeChildren = vnode.children || vnode.props?.children;\n if (!Array.isArray(vnodeChildren) || vnodeChildren.length !== 2) return false;\n\n const firstChild = vnodeChildren[0];\n const secondChild = vnodeChildren[1];\n if (!_isDOMElement(firstChild) || !_isDOMElement(secondChild)) return false;\n if (\n typeof firstChild.type !== 'string' ||\n typeof secondChild.type !== 'string'\n ) {\n return false;\n }\n\n const firstElement = parentEl.children[0] as Element | undefined;\n const secondElement = parentEl.children[1] as Element | undefined;\n if (!firstElement || !secondElement) return false;\n if (parentEl.children.length !== 2 || parentEl.childNodes.length !== 2) {\n return false;\n }\n\n if (!tagsEqualIgnoreCase(firstElement.tagName, firstChild.type)) return false;\n if (!tagsEqualIgnoreCase(secondElement.tagName, secondChild.type))\n return false;\n\n const firstText = (firstChild.children ||\n firstChild.props?.children) as unknown;\n const secondText = (secondChild.children ||\n secondChild.props?.children) as unknown;\n\n if (typeof firstText === 'string' || typeof firstText === 'number') {\n setTextNodeData(firstElement, String(firstText));\n } else if (\n Array.isArray(firstText) &&\n firstText.length === 1 &&\n (typeof firstText[0] === 'string' || typeof firstText[0] === 'number')\n ) {\n setTextNodeData(firstElement, String(firstText[0]));\n } else {\n return false;\n }\n\n if (typeof secondText === 'string' || typeof secondText === 'number') {\n setTextNodeData(secondElement, String(secondText));\n } else if (\n Array.isArray(secondText) &&\n secondText.length === 1 &&\n (typeof secondText[0] === 'string' || typeof secondText[0] === 'number')\n ) {\n setTextNodeData(secondElement, String(secondText[0]));\n } else {\n return false;\n }\n\n return true;\n}\n\nfunction setTextNodeData(el: Element, text: string): void {\n if (el.childNodes.length === 1 && el.firstChild?.nodeType === 3) {\n const textNode = el.firstChild as Text;\n if (textNode.data !== text) textNode.data = text;\n } else {\n el.textContent = text;\n }\n}\n\nfunction setDataKey(\n el: Element,\n key: string | number,\n onSet: () => void\n): void {\n try {\n const next = String(key);\n if (el.getAttribute('data-key') === next) return;\n el.setAttribute('data-key', next);\n onSet();\n } catch {\n // Ignore errors setting data-key\n }\n}\n\nfunction replaceNodeAtPosition(\n parent: Element,\n index: number,\n vnode: VNode\n): void {\n const dom = createDOMNode(vnode);\n if (dom) {\n const existing = parent.children[index];\n if (existing) {\n teardownNodeSubtree(existing);\n parent.replaceChild(dom, existing);\n } else {\n parent.appendChild(dom);\n }\n }\n}\n\nfunction updateKeyedElementsMap(\n parent: Element,\n keyedVnodes: Array<{ key: string | number; vnode: VNode }>\n): void {\n try {\n const existing = keyedElements.get(parent);\n const newKeyMap = existing\n ? (existing.clear(), existing)\n : new Map<string | number, Element>();\n\n for (let index = 0; index < keyedVnodes.length; index += 1) {\n const key = keyedVnodes[index].key;\n const child = parent.children[index] as Element | undefined;\n if (child) newKeyMap.set(key, child);\n }\n\n keyedElements.set(parent, newKeyMap);\n } catch {\n // Ignore errors updating key map\n }\n}\n\nexport function performBulkTextReplace(parent: Element, newChildren: VNode[]) {\n const start = now();\n const existing = Array.from(parent.childNodes);\n const finalNodes: Node[] = [];\n let reused = 0;\n let created = 0;\n\n for (let index = 0; index < newChildren.length; index += 1) {\n const result = processChildNode(\n newChildren[index],\n existing[index],\n finalNodes\n );\n if (result === 'reused') reused += 1;\n else if (result === 'created') created += 1;\n }\n\n const tBuild = now() - start;\n const tCommit = commitBulkReplace(parent, finalNodes);\n\n keyedElements.delete(parent);\n\n const stats = {\n n: newChildren.length,\n reused,\n created,\n tBuild,\n tCommit,\n } as const;\n recordBulkTextStats(stats);\n\n return stats;\n}\n\nfunction processChildNode(\n vnode: VNode,\n existingNode: ChildNode | undefined,\n finalNodes: Node[]\n): 'reused' | 'created' | 'skipped' {\n if (typeof vnode === 'string' || typeof vnode === 'number') {\n return processTextVnode(String(vnode), existingNode, finalNodes);\n }\n\n if (typeof vnode === 'object' && vnode !== null && 'type' in vnode) {\n return processElementVnode(vnode, existingNode, finalNodes);\n }\n\n return 'skipped';\n}\n\nfunction processTextVnode(\n text: string,\n existingNode: ChildNode | undefined,\n finalNodes: Node[]\n): 'reused' | 'created' {\n if (existingNode && existingNode.nodeType === 3) {\n (existingNode as Text).data = text;\n finalNodes.push(existingNode);\n return 'reused';\n }\n\n finalNodes.push(document.createTextNode(text));\n return 'created';\n}\n\nfunction processElementVnode(\n vnode: VNode,\n existingNode: ChildNode | undefined,\n finalNodes: Node[]\n): 'reused' | 'created' | 'skipped' {\n const vnodeObj = vnode as unknown as { type?: unknown };\n\n if (typeof vnodeObj.type === 'string') {\n const tag = vnodeObj.type;\n if (\n existingNode &&\n existingNode.nodeType === 1 &&\n tagsEqualIgnoreCase((existingNode as Element).tagName, tag)\n ) {\n updateElementFromVnode(existingNode as Element, vnode);\n finalNodes.push(existingNode);\n return 'reused';\n }\n }\n\n const dom = createDOMNode(vnode);\n if (dom) {\n finalNodes.push(dom);\n return 'created';\n }\n\n return 'skipped';\n}\n\nfunction commitBulkReplace(parent: Element, nodes: Node[]): number {\n const startedAt = Date.now();\n const fragment = document.createDocumentFragment();\n\n for (let index = 0; index < nodes.length; index += 1) {\n fragment.appendChild(nodes[index]);\n }\n\n try {\n for (let node = parent.firstChild; node; ) {\n const next = node.nextSibling;\n teardownNodeSubtree(node);\n node = next;\n }\n } catch {\n // SLOW PATH: cleanup failure\n }\n\n recordDOMReplace('bulk-text-replace');\n parent.replaceChildren(fragment);\n return Date.now() - startedAt;\n}\n\nfunction recordBulkTextStats(stats: {\n n: number;\n reused: number;\n created: number;\n tBuild: number;\n tCommit: number;\n}): void {\n try {\n setDevValue('__LAST_BULK_TEXT_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_COMMIT_COUNT', 1);\n incDevCounter('bulkTextFastpathHits');\n } catch {\n // Ignore stats errors\n }\n}\n\nexport function isBulkTextFastPathEligible(\n parent: Element,\n newChildren: VNode[]\n) {\n const env = getRuntimeEnv();\n const threshold = Number(env.ASKR_BULK_TEXT_THRESHOLD) || 1024;\n const requiredFraction = 0.8;\n\n const total = Array.isArray(newChildren) ? newChildren.length : 0;\n\n if (total < threshold) {\n recordBulkDiag({\n phase: 'bulk-unkeyed-eligible',\n reason: 'too-small',\n total,\n threshold,\n });\n return false;\n }\n\n const result = countSimpleChildren(newChildren);\n if (result.componentFound !== undefined) {\n recordBulkDiag({\n phase: 'bulk-unkeyed-eligible',\n reason: 'component-child',\n index: result.componentFound,\n });\n return false;\n }\n\n const fraction = result.simple / total;\n const eligible =\n fraction >= requiredFraction && parent.childNodes.length >= total;\n\n recordBulkDiag({\n phase: 'bulk-unkeyed-eligible',\n total,\n simple: result.simple,\n fraction,\n requiredFraction,\n eligible,\n });\n\n return eligible;\n}\n\nfunction countSimpleChildren(children: VNode[]): {\n simple: number;\n componentFound?: number;\n} {\n let simple = 0;\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index];\n\n if (typeof child === 'string' || typeof child === 'number') {\n simple += 1;\n continue;\n }\n\n if (typeof child === 'object' && child !== null && 'type' in child) {\n const dom = child as DOMElement;\n\n if (typeof dom.type === 'function') {\n return { simple, componentFound: index };\n }\n\n if (typeof dom.type === 'string' && isSimpleElement(dom)) {\n simple += 1;\n }\n }\n }\n\n return { simple };\n}\n\nfunction isSimpleElement(dom: DOMElement): boolean {\n const children = dom.children || dom.props?.children;\n\n if (children === null || children === undefined) return true;\n\n if (typeof children === 'string' || typeof children === 'number') {\n return true;\n }\n\n if (\n Array.isArray(children) &&\n children.length === 1 &&\n (typeof children[0] === 'string' || typeof children[0] === 'number')\n ) {\n return true;\n }\n\n return false;\n}\n\nfunction recordBulkDiag(data: Record<string, unknown>): void {\n const env = getRuntimeEnv();\n if (env.NODE_ENV !== 'production' || env.ASKR_FASTPATH_DEBUG === '1') {\n try {\n setDevValue('__BULK_DIAG', data);\n } catch {\n // Ignore\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"children.js","names":[],"sources":["../../src/renderer/children.ts"],"sourcesContent":["import { setDevValue, incDevCounter } from '../runtime/dev-namespace';\nimport { getRuntimeEnv } from './env';\nimport { keyedElements } from './keyed';\nimport { teardownNodeSubtree } from './cleanup';\nimport { createDOMNode, updateElementFromVnode } from './dom';\nimport { _isDOMElement, type DOMElement, type VNode } from './types';\nimport {\n hasNonTrivialProps,\n logFastPathDebug,\n now,\n recordDOMReplace,\n recordFastPathStats,\n tagNamesEqualIgnoreCase,\n} from './utils';\n\nfunction upperCommonTagName(tag: string): string | null {\n switch (tag) {\n case 'div':\n return 'DIV';\n case 'span':\n return 'SPAN';\n case 'p':\n return 'P';\n case 'a':\n return 'A';\n case 'button':\n return 'BUTTON';\n case 'input':\n return 'INPUT';\n case 'ul':\n return 'UL';\n case 'ol':\n return 'OL';\n case 'li':\n return 'LI';\n default:\n return null;\n }\n}\n\nfunction tagsEqualIgnoreCase(\n elementTagName: string,\n vnodeType: string\n): boolean {\n if (elementTagName === vnodeType) return true;\n\n const upperCommon = upperCommonTagName(vnodeType);\n if (upperCommon !== null && elementTagName === upperCommon) return true;\n\n return tagNamesEqualIgnoreCase(elementTagName, vnodeType);\n}\n\nexport function performBulkPositionalKeyedTextUpdate(\n parent: Element,\n keyedVnodes: Array<{ key: string | number; vnode: VNode }>\n) {\n const total = keyedVnodes.length;\n let reused = 0;\n let updatedKeys = 0;\n const start = now();\n const env = getRuntimeEnv();\n const debugFastPath =\n env.ASKR_FASTPATH_DEBUG === '1' || env.ASKR_FASTPATH_DEBUG === 'true';\n\n for (let index = 0; index < total; index += 1) {\n const { key, vnode } = keyedVnodes[index];\n const child = parent.children[index] as Element | undefined;\n\n if (\n child &&\n _isDOMElement(vnode) &&\n typeof (vnode as DOMElement).type === 'string'\n ) {\n const vnodeType = (vnode as DOMElement).type as string;\n\n if (tagsEqualIgnoreCase(child.tagName, vnodeType)) {\n const children =\n (vnode as DOMElement).children ||\n (vnode as DOMElement).props?.children;\n\n if (debugFastPath) {\n logFastPathDebug('positional idx', index, {\n chTag: child.tagName,\n vnodeType,\n chChildNodes: child.childNodes.length,\n childrenType: Array.isArray(children) ? 'array' : typeof children,\n });\n }\n\n updateTextContent(child, children, vnode as DOMElement);\n setDataKey(child, key, () => (updatedKeys += 1));\n reused += 1;\n continue;\n }\n\n if (debugFastPath) {\n logFastPathDebug('positional tag mismatch', index, {\n chTag: child.tagName,\n vnodeType,\n });\n }\n } else if (debugFastPath) {\n logFastPathDebug('positional missing or invalid', index, { ch: !!child });\n }\n\n replaceNodeAtPosition(parent, index, vnode);\n }\n\n const elapsed = now() - start;\n updateKeyedElementsMap(parent, keyedVnodes);\n\n const stats = { n: total, reused, updatedKeys, t: elapsed } as const;\n recordFastPathStats(stats, 'bulkKeyedPositionalHits');\n\n return stats;\n}\n\nfunction updateTextContent(\n el: Element,\n children: unknown,\n vnode: DOMElement\n): void {\n if (typeof children === 'string' || typeof children === 'number') {\n setTextNodeData(el, String(children));\n if (vnode.props && hasNonTrivialProps(vnode.props)) {\n updateElementFromVnode(el, vnode, false);\n }\n return;\n }\n\n if (\n Array.isArray(children) &&\n children.length === 1 &&\n (typeof children[0] === 'string' || typeof children[0] === 'number')\n ) {\n setTextNodeData(el, String(children[0]));\n if (vnode.props && hasNonTrivialProps(vnode.props)) {\n updateElementFromVnode(el, vnode, false);\n }\n return;\n }\n\n if (!tryUpdateTwoChildTextPattern(el, vnode)) {\n updateElementFromVnode(el, vnode);\n }\n}\n\nfunction tryUpdateTwoChildTextPattern(\n parentEl: Element,\n vnode: DOMElement\n): boolean {\n const vnodeChildren = vnode.props?.children ?? vnode.children;\n if (!Array.isArray(vnodeChildren) || vnodeChildren.length !== 2) return false;\n\n const firstChild = vnodeChildren[0];\n const secondChild = vnodeChildren[1];\n if (!_isDOMElement(firstChild) || !_isDOMElement(secondChild)) return false;\n if (\n typeof firstChild.type !== 'string' ||\n typeof secondChild.type !== 'string'\n ) {\n return false;\n }\n\n const firstElement = parentEl.children[0] as Element | undefined;\n const secondElement = parentEl.children[1] as Element | undefined;\n if (!firstElement || !secondElement) return false;\n if (parentEl.children.length !== 2 || parentEl.childNodes.length !== 2) {\n return false;\n }\n\n if (!tagsEqualIgnoreCase(firstElement.tagName, firstChild.type)) return false;\n if (!tagsEqualIgnoreCase(secondElement.tagName, secondChild.type))\n return false;\n\n const firstText = (firstChild.children ||\n firstChild.props?.children) as unknown;\n const secondText = (secondChild.children ||\n secondChild.props?.children) as unknown;\n\n if (typeof firstText === 'string' || typeof firstText === 'number') {\n setTextNodeData(firstElement, String(firstText));\n } else if (\n Array.isArray(firstText) &&\n firstText.length === 1 &&\n (typeof firstText[0] === 'string' || typeof firstText[0] === 'number')\n ) {\n setTextNodeData(firstElement, String(firstText[0]));\n } else {\n return false;\n }\n\n if (typeof secondText === 'string' || typeof secondText === 'number') {\n setTextNodeData(secondElement, String(secondText));\n } else if (\n Array.isArray(secondText) &&\n secondText.length === 1 &&\n (typeof secondText[0] === 'string' || typeof secondText[0] === 'number')\n ) {\n setTextNodeData(secondElement, String(secondText[0]));\n } else {\n return false;\n }\n\n return true;\n}\n\nfunction setTextNodeData(el: Element, text: string): void {\n if (el.childNodes.length === 1 && el.firstChild?.nodeType === 3) {\n const textNode = el.firstChild as Text;\n if (textNode.data !== text) textNode.data = text;\n } else {\n el.textContent = text;\n }\n}\n\nfunction setDataKey(\n el: Element,\n key: string | number,\n onSet: () => void\n): void {\n try {\n const next = String(key);\n if (el.getAttribute('data-key') === next) return;\n el.setAttribute('data-key', next);\n onSet();\n } catch {\n // Ignore errors setting data-key\n }\n}\n\nfunction replaceNodeAtPosition(\n parent: Element,\n index: number,\n vnode: VNode\n): void {\n const dom = createDOMNode(vnode);\n if (dom) {\n const existing = parent.children[index];\n if (existing) {\n teardownNodeSubtree(existing);\n parent.replaceChild(dom, existing);\n } else {\n parent.appendChild(dom);\n }\n }\n}\n\nfunction updateKeyedElementsMap(\n parent: Element,\n keyedVnodes: Array<{ key: string | number; vnode: VNode }>\n): void {\n try {\n const existing = keyedElements.get(parent);\n const newKeyMap = existing\n ? (existing.clear(), existing)\n : new Map<string | number, Element>();\n\n for (let index = 0; index < keyedVnodes.length; index += 1) {\n const key = keyedVnodes[index].key;\n const child = parent.children[index] as Element | undefined;\n if (child) newKeyMap.set(key, child);\n }\n\n keyedElements.set(parent, newKeyMap);\n } catch {\n // Ignore errors updating key map\n }\n}\n\nexport function performBulkTextReplace(parent: Element, newChildren: VNode[]) {\n const start = now();\n const existing = Array.from(parent.childNodes);\n const finalNodes: Node[] = [];\n let reused = 0;\n let created = 0;\n\n for (let index = 0; index < newChildren.length; index += 1) {\n const result = processChildNode(\n newChildren[index],\n existing[index],\n finalNodes\n );\n if (result === 'reused') reused += 1;\n else if (result === 'created') created += 1;\n }\n\n const tBuild = now() - start;\n const tCommit = commitBulkReplace(parent, finalNodes);\n\n keyedElements.delete(parent);\n\n const stats = {\n n: newChildren.length,\n reused,\n created,\n tBuild,\n tCommit,\n } as const;\n recordBulkTextStats(stats);\n\n return stats;\n}\n\nfunction processChildNode(\n vnode: VNode,\n existingNode: ChildNode | undefined,\n finalNodes: Node[]\n): 'reused' | 'created' | 'skipped' {\n if (typeof vnode === 'string' || typeof vnode === 'number') {\n return processTextVnode(String(vnode), existingNode, finalNodes);\n }\n\n if (typeof vnode === 'object' && vnode !== null && 'type' in vnode) {\n return processElementVnode(vnode, existingNode, finalNodes);\n }\n\n return 'skipped';\n}\n\nfunction processTextVnode(\n text: string,\n existingNode: ChildNode | undefined,\n finalNodes: Node[]\n): 'reused' | 'created' {\n if (existingNode && existingNode.nodeType === 3) {\n (existingNode as Text).data = text;\n finalNodes.push(existingNode);\n return 'reused';\n }\n\n finalNodes.push(document.createTextNode(text));\n return 'created';\n}\n\nfunction processElementVnode(\n vnode: VNode,\n existingNode: ChildNode | undefined,\n finalNodes: Node[]\n): 'reused' | 'created' | 'skipped' {\n const vnodeObj = vnode as unknown as { type?: unknown };\n\n if (typeof vnodeObj.type === 'string') {\n const tag = vnodeObj.type;\n if (\n existingNode &&\n existingNode.nodeType === 1 &&\n tagsEqualIgnoreCase((existingNode as Element).tagName, tag)\n ) {\n updateElementFromVnode(existingNode as Element, vnode);\n finalNodes.push(existingNode);\n return 'reused';\n }\n }\n\n const dom = createDOMNode(vnode);\n if (dom) {\n finalNodes.push(dom);\n return 'created';\n }\n\n return 'skipped';\n}\n\nfunction commitBulkReplace(parent: Element, nodes: Node[]): number {\n const startedAt = Date.now();\n const fragment = document.createDocumentFragment();\n\n for (let index = 0; index < nodes.length; index += 1) {\n fragment.appendChild(nodes[index]);\n }\n\n try {\n for (let node = parent.firstChild; node; ) {\n const next = node.nextSibling;\n teardownNodeSubtree(node);\n node = next;\n }\n } catch {\n // SLOW PATH: cleanup failure\n }\n\n recordDOMReplace('bulk-text-replace');\n parent.replaceChildren(fragment);\n return Date.now() - startedAt;\n}\n\nfunction recordBulkTextStats(stats: {\n n: number;\n reused: number;\n created: number;\n tBuild: number;\n tCommit: number;\n}): void {\n try {\n setDevValue('__LAST_BULK_TEXT_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_STATS', stats);\n setDevValue('__LAST_FASTPATH_COMMIT_COUNT', 1);\n incDevCounter('bulkTextFastpathHits');\n } catch {\n // Ignore stats errors\n }\n}\n\nexport function isBulkTextFastPathEligible(\n parent: Element,\n newChildren: VNode[]\n) {\n const env = getRuntimeEnv();\n const threshold = Number(env.ASKR_BULK_TEXT_THRESHOLD) || 1024;\n const requiredFraction = 0.8;\n\n const total = Array.isArray(newChildren) ? newChildren.length : 0;\n\n if (total < threshold) {\n recordBulkDiag({\n phase: 'bulk-unkeyed-eligible',\n reason: 'too-small',\n total,\n threshold,\n });\n return false;\n }\n\n const result = countSimpleChildren(newChildren);\n if (result.componentFound !== undefined) {\n recordBulkDiag({\n phase: 'bulk-unkeyed-eligible',\n reason: 'component-child',\n index: result.componentFound,\n });\n return false;\n }\n\n const fraction = result.simple / total;\n const eligible =\n fraction >= requiredFraction && parent.childNodes.length >= total;\n\n recordBulkDiag({\n phase: 'bulk-unkeyed-eligible',\n total,\n simple: result.simple,\n fraction,\n requiredFraction,\n eligible,\n });\n\n return eligible;\n}\n\nfunction countSimpleChildren(children: VNode[]): {\n simple: number;\n componentFound?: number;\n} {\n let simple = 0;\n\n for (let index = 0; index < children.length; index += 1) {\n const child = children[index];\n\n if (typeof child === 'string' || typeof child === 'number') {\n simple += 1;\n continue;\n }\n\n if (typeof child === 'object' && child !== null && 'type' in child) {\n const dom = child as DOMElement;\n\n if (typeof dom.type === 'function') {\n return { simple, componentFound: index };\n }\n\n if (typeof dom.type === 'string' && isSimpleElement(dom)) {\n simple += 1;\n }\n }\n }\n\n return { simple };\n}\n\nfunction isSimpleElement(dom: DOMElement): boolean {\n const children = dom.props?.children ?? dom.children;\n\n if (children === null || children === undefined) return true;\n\n if (typeof children === 'string' || typeof children === 'number') {\n return true;\n }\n\n if (\n Array.isArray(children) &&\n children.length === 1 &&\n (typeof children[0] === 'string' || typeof children[0] === 'number')\n ) {\n return true;\n }\n\n return false;\n}\n\nfunction recordBulkDiag(data: Record<string, unknown>): void {\n const env = getRuntimeEnv();\n if (env.NODE_ENV !== 'production' || env.ASKR_FASTPATH_DEBUG === '1') {\n try {\n setDevValue('__BULK_DIAG', data);\n } catch {\n // Ignore\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/renderer/dom.js
CHANGED
|
@@ -1318,7 +1318,7 @@ function createComponentElement(node, type, props, parentNamespace) {
|
|
|
1318
1318
|
*/
|
|
1319
1319
|
function createFragmentElement(node, props, parentNamespace) {
|
|
1320
1320
|
const fragment = document.createDocumentFragment();
|
|
1321
|
-
const children = props.children
|
|
1321
|
+
const children = props.children ?? node.children;
|
|
1322
1322
|
if (children) if (Array.isArray(children)) {
|
|
1323
1323
|
maybeWarnMissingKeys(children);
|
|
1324
1324
|
for (const child of children) {
|
|
@@ -1549,7 +1549,7 @@ function normalizeStableIntrinsicChildren(children) {
|
|
|
1549
1549
|
return Array.isArray(children) ? children : [children];
|
|
1550
1550
|
}
|
|
1551
1551
|
function getStableIntrinsicChildren(vnode) {
|
|
1552
|
-
return normalizeStableIntrinsicChildren(vnode.children
|
|
1552
|
+
return normalizeStableIntrinsicChildren(vnode.props?.children ?? vnode.children);
|
|
1553
1553
|
}
|
|
1554
1554
|
function patchStableIntrinsicText(domNode, nextVNode) {
|
|
1555
1555
|
if (domNode.nodeType !== 3 || typeof nextVNode !== "string" && typeof nextVNode !== "number") return false;
|
|
@@ -1926,6 +1926,29 @@ function commitForBoundaryChildren(parent, controlState, childrenVNodes) {
|
|
|
1926
1926
|
}
|
|
1927
1927
|
removeForBoundaryNodes(parent, forState.lastRemovedNodes);
|
|
1928
1928
|
syncKeyedMapFromForState(parent, forState, forState.lastCommitStrategy, forState.lastRemovedNodes);
|
|
1929
|
+
const syncExactForBoundaryChildren = () => {
|
|
1930
|
+
const expectedNodes = [];
|
|
1931
|
+
for (let i = 0; i < forState.orderedKeys.length; i++) {
|
|
1932
|
+
const itemKey = forState.orderedKeys[i];
|
|
1933
|
+
const itemInstance = forState.items.get(itemKey);
|
|
1934
|
+
if (!itemInstance) continue;
|
|
1935
|
+
const dom = itemInstance.scope.dom ?? syncForItemDom(parent, itemInstance.scope, childrenVNodes[i]);
|
|
1936
|
+
if (dom) expectedNodes.push(dom);
|
|
1937
|
+
}
|
|
1938
|
+
const currentNodes = Array.from(parent.childNodes);
|
|
1939
|
+
if (currentNodes.length === expectedNodes.length && currentNodes.every((node, index) => node === expectedNodes[index])) return;
|
|
1940
|
+
const expectedNodeSet = new Set(expectedNodes);
|
|
1941
|
+
for (const currentNode of currentNodes) {
|
|
1942
|
+
if (expectedNodeSet.has(currentNode)) continue;
|
|
1943
|
+
if (currentNode instanceof Element) teardownNodeSubtree(currentNode);
|
|
1944
|
+
if (currentNode.parentNode === parent) {
|
|
1945
|
+
recordBenchEvent("domRemove");
|
|
1946
|
+
currentNode.remove();
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
parent.replaceChildren(...expectedNodes);
|
|
1950
|
+
};
|
|
1951
|
+
syncExactForBoundaryChildren();
|
|
1929
1952
|
forState._hasResolvedItemDom = true;
|
|
1930
1953
|
recordBenchTiming("domCommit", performance.now() - domCommitStart);
|
|
1931
1954
|
clearForDomUpdateState(forState);
|
|
@@ -1947,7 +1970,7 @@ function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
|
1947
1970
|
if ((!existingListeners || existingListeners.size === 0) && (!existingReactiveProps || existingReactiveProps.size === 0)) {
|
|
1948
1971
|
if (hasMatchingStaticProps(el, props, vnode.type)) {
|
|
1949
1972
|
if (updateChildren) {
|
|
1950
|
-
const children =
|
|
1973
|
+
const children = props.children ?? vnode.children;
|
|
1951
1974
|
if (canReuseStaticSubtree(el, domVNode)) return;
|
|
1952
1975
|
updateElementChildren(el, children);
|
|
1953
1976
|
}
|
|
@@ -2097,7 +2120,7 @@ function updateElementFromVnode(el, vnode, updateChildren = true) {
|
|
|
2097
2120
|
if (existingReactiveProps.size === 0) elementReactivePropsCleanup.delete(el);
|
|
2098
2121
|
}
|
|
2099
2122
|
if (updateChildren) {
|
|
2100
|
-
const children =
|
|
2123
|
+
const children = props.children ?? vnode.children;
|
|
2101
2124
|
if (usesReactiveChildren) return;
|
|
2102
2125
|
updateElementChildren(el, children);
|
|
2103
2126
|
}
|
|
@@ -2278,7 +2301,7 @@ function canReuseStaticSubtree(el, vnode) {
|
|
|
2278
2301
|
if (typeof vnode.type !== "string" || !tagsEqualIgnoreCase(el.tagName, vnode.type)) return false;
|
|
2279
2302
|
const props = vnode.props || {};
|
|
2280
2303
|
if (!hasMatchingStaticProps(el, props, vnode.type)) return false;
|
|
2281
|
-
const slots = getStaticChildSlots(
|
|
2304
|
+
const slots = getStaticChildSlots(props.children ?? vnode.children);
|
|
2282
2305
|
if (!slots) return false;
|
|
2283
2306
|
if (el.childNodes.length !== slots.length) return false;
|
|
2284
2307
|
for (let index = 0; index < slots.length; index += 1) {
|