astro 7.0.0-alpha.2 → 7.0.0-beta.3
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/assets/fonts/core/collect-font-data.js +1 -0
- package/dist/assets/fonts/types.d.ts +1 -0
- package/dist/cli/add/index.js +0 -44
- package/dist/cli/dev/background.js +1 -1
- package/dist/cli/dev/index.js +1 -1
- package/dist/cli/flags.js +4 -6
- package/dist/cli/help/index.js +1 -2
- package/dist/cli/index.js +1 -15
- package/dist/cli/infra/build-time-astro-version-provider.js +1 -1
- package/dist/container/index.js +1 -4
- package/dist/content/content-layer.js +3 -3
- package/dist/core/app/base.d.ts +1 -1
- package/dist/core/app/base.js +7 -9
- package/dist/core/app/dev/pipeline.js +0 -9
- package/dist/core/app/manifest.d.ts +0 -2
- package/dist/core/app/manifest.js +0 -8
- package/dist/core/app/types.d.ts +1 -8
- package/dist/core/base-pipeline.d.ts +3 -9
- package/dist/core/base-pipeline.js +4 -23
- package/dist/core/build/app.d.ts +0 -2
- package/dist/core/build/app.js +0 -5
- package/dist/core/build/generate.js +0 -14
- package/dist/core/build/pipeline.js +0 -9
- package/dist/core/build/plugins/plugin-manifest.js +4 -9
- package/dist/core/config/config.js +3 -2
- package/dist/core/config/schemas/base.d.ts +6 -19
- package/dist/core/config/schemas/base.js +8 -24
- package/dist/core/config/schemas/relative.d.ts +15 -36
- package/dist/core/constants.js +1 -1
- package/dist/core/dev/dev.js +1 -1
- package/dist/core/fetch/fetch-state.js +0 -14
- package/dist/core/fetch/types.d.ts +1 -1
- package/dist/core/fetch/vite-plugin.js +4 -6
- package/dist/core/hono/index.d.ts +1 -0
- package/dist/core/hono/index.js +1 -0
- package/dist/core/logger/impls/node.js +0 -1
- package/dist/core/logger/load.js +3 -2
- package/dist/core/messages/runtime.js +1 -1
- package/dist/core/middleware/index.js +8 -1
- package/dist/manifest/serialized.js +4 -5
- package/dist/runtime/server/index.d.ts +1 -1
- package/dist/runtime/server/index.js +4 -0
- package/dist/runtime/server/render/astro/render-template.d.ts +1 -1
- package/dist/runtime/server/render/astro/render.d.ts +0 -4
- package/dist/runtime/server/render/astro/render.js +76 -68
- package/dist/runtime/server/render/index.d.ts +1 -0
- package/dist/runtime/server/render/index.js +2 -0
- package/dist/runtime/server/render/page.js +9 -44
- package/dist/runtime/server/render/streaming.d.ts +23 -0
- package/dist/runtime/server/render/streaming.js +238 -0
- package/dist/runtime/server/render/util.js +1 -1
- package/dist/types/public/config.d.ts +58 -121
- package/dist/types/public/context.d.ts +1 -1
- package/dist/types/public/internal.d.ts +0 -15
- package/dist/vite-plugin-app/app.js +1 -1
- package/dist/vite-plugin-app/pipeline.js +0 -9
- package/package.json +1 -1
- package/dist/cli/db/index.d.ts +0 -4
- package/dist/cli/db/index.js +0 -25
- package/dist/runtime/server/html-string-cache.d.ts +0 -48
- package/dist/runtime/server/html-string-cache.js +0 -119
- package/dist/runtime/server/render/queue/builder.d.ts +0 -14
- package/dist/runtime/server/render/queue/builder.js +0 -182
- package/dist/runtime/server/render/queue/jsx-builder.d.ts +0 -33
- package/dist/runtime/server/render/queue/jsx-builder.js +0 -146
- package/dist/runtime/server/render/queue/pool.d.ts +0 -123
- package/dist/runtime/server/render/queue/pool.js +0 -203
- package/dist/runtime/server/render/queue/renderer.d.ts +0 -12
- package/dist/runtime/server/render/queue/renderer.js +0 -103
- package/dist/runtime/server/render/queue/types.d.ts +0 -81
- package/dist/runtime/server/render/queue/types.js +0 -0
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import { HTMLString } from './escape.js';
|
|
2
|
-
/**
|
|
3
|
-
* LRU (Least Recently Used) cache for HTMLString objects.
|
|
4
|
-
*
|
|
5
|
-
* This cache reduces memory allocations by reusing identical HTMLString objects
|
|
6
|
-
* across both recursive rendering (.astro files) and queue rendering (MDX files).
|
|
7
|
-
*
|
|
8
|
-
* When the cache reaches maxSize, the least recently used item is evicted.
|
|
9
|
-
* This keeps memory usage bounded while maintaining good cache hit rates.
|
|
10
|
-
*
|
|
11
|
-
* Example:
|
|
12
|
-
* - 10,000 identical `<li class="foo">` tags → single cached HTMLString object
|
|
13
|
-
* - Memory savings: ~30KB (10,000 objects) → ~3 bytes (1 object + Map overhead)
|
|
14
|
-
*/
|
|
15
|
-
export declare class HTMLStringCache {
|
|
16
|
-
private cache;
|
|
17
|
-
private readonly maxSize;
|
|
18
|
-
constructor(maxSize?: number);
|
|
19
|
-
/**
|
|
20
|
-
* Get or create an HTMLString for the given content.
|
|
21
|
-
* If cached, the existing object is returned and moved to end (most recently used).
|
|
22
|
-
* If not cached, a new HTMLString is created, cached, and returned.
|
|
23
|
-
*
|
|
24
|
-
* @param content - The HTML string content
|
|
25
|
-
* @returns HTMLString object (cached or newly created)
|
|
26
|
-
*/
|
|
27
|
-
getOrCreate(content: string): HTMLString;
|
|
28
|
-
/**
|
|
29
|
-
* Get current cache size
|
|
30
|
-
*/
|
|
31
|
-
size(): number;
|
|
32
|
-
/**
|
|
33
|
-
* Pre-warms the cache with common HTML patterns.
|
|
34
|
-
* This ensures first-render cache hits for frequently used tags.
|
|
35
|
-
*
|
|
36
|
-
* @param patterns - Array of HTML strings to pre-cache
|
|
37
|
-
*/
|
|
38
|
-
warm(patterns: string[]): void;
|
|
39
|
-
/**
|
|
40
|
-
* Clear the entire cache
|
|
41
|
-
*/
|
|
42
|
-
clear(): void;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Common HTML patterns that appear frequently in Astro pages.
|
|
46
|
-
* Pre-warming the cache with these patterns ensures first-render cache hits.
|
|
47
|
-
*/
|
|
48
|
-
export declare const COMMON_HTML_PATTERNS: string[];
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import { HTMLString } from "./escape.js";
|
|
2
|
-
class HTMLStringCache {
|
|
3
|
-
cache = /* @__PURE__ */ new Map();
|
|
4
|
-
maxSize;
|
|
5
|
-
constructor(maxSize = 1e3) {
|
|
6
|
-
this.maxSize = maxSize;
|
|
7
|
-
this.warm(COMMON_HTML_PATTERNS);
|
|
8
|
-
}
|
|
9
|
-
/**
|
|
10
|
-
* Get or create an HTMLString for the given content.
|
|
11
|
-
* If cached, the existing object is returned and moved to end (most recently used).
|
|
12
|
-
* If not cached, a new HTMLString is created, cached, and returned.
|
|
13
|
-
*
|
|
14
|
-
* @param content - The HTML string content
|
|
15
|
-
* @returns HTMLString object (cached or newly created)
|
|
16
|
-
*/
|
|
17
|
-
getOrCreate(content) {
|
|
18
|
-
const cached = this.cache.get(content);
|
|
19
|
-
if (cached) {
|
|
20
|
-
this.cache.delete(content);
|
|
21
|
-
this.cache.set(content, cached);
|
|
22
|
-
return cached;
|
|
23
|
-
}
|
|
24
|
-
const htmlString = new HTMLString(content);
|
|
25
|
-
this.cache.set(content, htmlString);
|
|
26
|
-
if (this.cache.size > this.maxSize) {
|
|
27
|
-
const firstKey = this.cache.keys().next().value;
|
|
28
|
-
if (firstKey !== void 0) {
|
|
29
|
-
this.cache.delete(firstKey);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
return htmlString;
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Get current cache size
|
|
36
|
-
*/
|
|
37
|
-
size() {
|
|
38
|
-
return this.cache.size;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Pre-warms the cache with common HTML patterns.
|
|
42
|
-
* This ensures first-render cache hits for frequently used tags.
|
|
43
|
-
*
|
|
44
|
-
* @param patterns - Array of HTML strings to pre-cache
|
|
45
|
-
*/
|
|
46
|
-
warm(patterns) {
|
|
47
|
-
for (const pattern of patterns) {
|
|
48
|
-
if (!this.cache.has(pattern)) {
|
|
49
|
-
this.cache.set(pattern, new HTMLString(pattern));
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Clear the entire cache
|
|
55
|
-
*/
|
|
56
|
-
clear() {
|
|
57
|
-
this.cache.clear();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
const COMMON_HTML_PATTERNS = [
|
|
61
|
-
// Structural elements
|
|
62
|
-
"<div>",
|
|
63
|
-
"</div>",
|
|
64
|
-
"<span>",
|
|
65
|
-
"</span>",
|
|
66
|
-
"<p>",
|
|
67
|
-
"</p>",
|
|
68
|
-
"<section>",
|
|
69
|
-
"</section>",
|
|
70
|
-
"<article>",
|
|
71
|
-
"</article>",
|
|
72
|
-
"<header>",
|
|
73
|
-
"</header>",
|
|
74
|
-
"<footer>",
|
|
75
|
-
"</footer>",
|
|
76
|
-
"<nav>",
|
|
77
|
-
"</nav>",
|
|
78
|
-
"<main>",
|
|
79
|
-
"</main>",
|
|
80
|
-
"<aside>",
|
|
81
|
-
"</aside>",
|
|
82
|
-
// List elements
|
|
83
|
-
"<ul>",
|
|
84
|
-
"</ul>",
|
|
85
|
-
"<ol>",
|
|
86
|
-
"</ol>",
|
|
87
|
-
"<li>",
|
|
88
|
-
"</li>",
|
|
89
|
-
// Void/self-closing elements
|
|
90
|
-
"<br>",
|
|
91
|
-
"<hr>",
|
|
92
|
-
"<br/>",
|
|
93
|
-
"<hr/>",
|
|
94
|
-
// Heading elements
|
|
95
|
-
"<h1>",
|
|
96
|
-
"</h1>",
|
|
97
|
-
"<h2>",
|
|
98
|
-
"</h2>",
|
|
99
|
-
"<h3>",
|
|
100
|
-
"</h3>",
|
|
101
|
-
"<h4>",
|
|
102
|
-
"</h4>",
|
|
103
|
-
// Inline elements
|
|
104
|
-
"<a>",
|
|
105
|
-
"</a>",
|
|
106
|
-
"<strong>",
|
|
107
|
-
"</strong>",
|
|
108
|
-
"<em>",
|
|
109
|
-
"</em>",
|
|
110
|
-
"<code>",
|
|
111
|
-
"</code>",
|
|
112
|
-
// Common whitespace
|
|
113
|
-
" ",
|
|
114
|
-
"\n"
|
|
115
|
-
];
|
|
116
|
-
export {
|
|
117
|
-
COMMON_HTML_PATTERNS,
|
|
118
|
-
HTMLStringCache
|
|
119
|
-
};
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { SSRResult } from '../../../../types/public/internal.js';
|
|
2
|
-
import type { RenderQueue } from './types.js';
|
|
3
|
-
import type { NodePool } from './pool.js';
|
|
4
|
-
/**
|
|
5
|
-
* Builds a render queue from a component tree.
|
|
6
|
-
* This function traverses the tree depth-first and creates a flat queue
|
|
7
|
-
* of nodes to be rendered, with parent tracking.
|
|
8
|
-
*
|
|
9
|
-
* @param root - The root component/value to render
|
|
10
|
-
* @param result - SSR result context
|
|
11
|
-
* @param pool
|
|
12
|
-
* @returns A render queue ready for rendering
|
|
13
|
-
*/
|
|
14
|
-
export declare function buildRenderQueue(root: any, result: SSRResult, pool: NodePool): Promise<RenderQueue>;
|
|
@@ -1,182 +0,0 @@
|
|
|
1
|
-
import { isPromise } from "../../util.js";
|
|
2
|
-
import { isHTMLString, markHTMLString } from "../../escape.js";
|
|
3
|
-
import { isAstroComponentFactory, isAPropagatingComponent } from "../astro/factory.js";
|
|
4
|
-
import { createAstroComponentInstance, isAstroComponentInstance } from "../astro/instance.js";
|
|
5
|
-
import { isRenderInstance } from "../common.js";
|
|
6
|
-
import { isRenderInstruction } from "../instruction.js";
|
|
7
|
-
import { SlotString } from "../slot.js";
|
|
8
|
-
import { isRenderTemplateResult } from "../astro/render-template.js";
|
|
9
|
-
import { isHeadAndContent } from "../astro/head-and-content.js";
|
|
10
|
-
import { isVNode } from "../../../../jsx-runtime/index.js";
|
|
11
|
-
import { renderJSXToQueue } from "./jsx-builder.js";
|
|
12
|
-
async function buildRenderQueue(root, result, pool) {
|
|
13
|
-
const queue = {
|
|
14
|
-
nodes: [],
|
|
15
|
-
result,
|
|
16
|
-
pool,
|
|
17
|
-
htmlStringCache: result._experimentalQueuedRendering?.htmlStringCache
|
|
18
|
-
};
|
|
19
|
-
const stack = [{ node: root, parent: null }];
|
|
20
|
-
while (stack.length > 0) {
|
|
21
|
-
const item = stack.pop();
|
|
22
|
-
if (!item) {
|
|
23
|
-
continue;
|
|
24
|
-
}
|
|
25
|
-
let { node, parent } = item;
|
|
26
|
-
if (isPromise(node)) {
|
|
27
|
-
try {
|
|
28
|
-
const resolved = await node;
|
|
29
|
-
stack.push({ node: resolved, parent, metadata: item.metadata });
|
|
30
|
-
} catch (error) {
|
|
31
|
-
throw error;
|
|
32
|
-
}
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
if (node == null || node === false) {
|
|
36
|
-
continue;
|
|
37
|
-
}
|
|
38
|
-
if (typeof node === "string") {
|
|
39
|
-
const queueNode = pool.acquire("text", node);
|
|
40
|
-
queueNode.content = node;
|
|
41
|
-
queue.nodes.push(queueNode);
|
|
42
|
-
continue;
|
|
43
|
-
}
|
|
44
|
-
if (typeof node === "number" || typeof node === "boolean") {
|
|
45
|
-
const str = String(node);
|
|
46
|
-
const queueNode = pool.acquire("text", str);
|
|
47
|
-
queueNode.content = str;
|
|
48
|
-
queue.nodes.push(queueNode);
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
if (isHTMLString(node)) {
|
|
52
|
-
const html = node.toString();
|
|
53
|
-
const queueNode = pool.acquire("html-string", html);
|
|
54
|
-
queueNode.html = html;
|
|
55
|
-
queue.nodes.push(queueNode);
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
if (node instanceof SlotString) {
|
|
59
|
-
const html = node.toString();
|
|
60
|
-
const queueNode = pool.acquire("html-string", html);
|
|
61
|
-
queueNode.html = html;
|
|
62
|
-
queue.nodes.push(queueNode);
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
if (isVNode(node)) {
|
|
66
|
-
renderJSXToQueue(node, result, queue, pool, stack, parent, item.metadata);
|
|
67
|
-
continue;
|
|
68
|
-
}
|
|
69
|
-
if (Array.isArray(node)) {
|
|
70
|
-
for (const n of node) {
|
|
71
|
-
stack.push({ node: n, parent, metadata: item.metadata });
|
|
72
|
-
}
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
if (isRenderInstruction(node)) {
|
|
76
|
-
const queueNode = pool.acquire("instruction");
|
|
77
|
-
queueNode.instruction = node;
|
|
78
|
-
queue.nodes.push(queueNode);
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
if (isRenderTemplateResult(node)) {
|
|
82
|
-
const htmlParts = node["htmlParts"];
|
|
83
|
-
const expressions = node["expressions"];
|
|
84
|
-
if (htmlParts[0]) {
|
|
85
|
-
const htmlString = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(htmlParts[0]) : markHTMLString(htmlParts[0]);
|
|
86
|
-
stack.push({
|
|
87
|
-
node: htmlString,
|
|
88
|
-
parent,
|
|
89
|
-
metadata: item.metadata
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
for (let i = 0; i < expressions.length; i = i + 1) {
|
|
93
|
-
stack.push({ node: expressions[i], parent, metadata: item.metadata });
|
|
94
|
-
if (htmlParts[i + 1]) {
|
|
95
|
-
const htmlString = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(htmlParts[i + 1]) : markHTMLString(htmlParts[i + 1]);
|
|
96
|
-
stack.push({
|
|
97
|
-
node: htmlString,
|
|
98
|
-
parent,
|
|
99
|
-
metadata: item.metadata
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
continue;
|
|
104
|
-
}
|
|
105
|
-
if (isAstroComponentInstance(node)) {
|
|
106
|
-
const queueNode = pool.acquire("component");
|
|
107
|
-
queueNode.instance = node;
|
|
108
|
-
queue.nodes.push(queueNode);
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
if (isAstroComponentFactory(node)) {
|
|
112
|
-
const factory = node;
|
|
113
|
-
const props = item.metadata?.props || {};
|
|
114
|
-
const slots = item.metadata?.slots || {};
|
|
115
|
-
const displayName = item.metadata?.displayName || factory.name || "Anonymous";
|
|
116
|
-
const instance = createAstroComponentInstance(result, displayName, factory, props, slots);
|
|
117
|
-
const queueNode = pool.acquire("component");
|
|
118
|
-
queueNode.instance = instance;
|
|
119
|
-
if (isAPropagatingComponent(result, factory)) {
|
|
120
|
-
try {
|
|
121
|
-
const returnValue = await instance.init(result);
|
|
122
|
-
if (isHeadAndContent(returnValue) && returnValue.head) {
|
|
123
|
-
result._metadata.extraHead.push(returnValue.head);
|
|
124
|
-
}
|
|
125
|
-
} catch (error) {
|
|
126
|
-
throw error;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
queue.nodes.push(queueNode);
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
if (isRenderInstance(node)) {
|
|
133
|
-
const queueNode = pool.acquire("component");
|
|
134
|
-
queueNode.instance = node;
|
|
135
|
-
queue.nodes.push(queueNode);
|
|
136
|
-
continue;
|
|
137
|
-
}
|
|
138
|
-
if (typeof node === "object" && Symbol.iterator in node) {
|
|
139
|
-
const items = Array.from(node);
|
|
140
|
-
for (const iterItem of items) {
|
|
141
|
-
stack.push({ node: iterItem, parent, metadata: item.metadata });
|
|
142
|
-
}
|
|
143
|
-
continue;
|
|
144
|
-
}
|
|
145
|
-
if (typeof node === "object" && Symbol.asyncIterator in node) {
|
|
146
|
-
try {
|
|
147
|
-
const items = [];
|
|
148
|
-
for await (const asyncItem of node) {
|
|
149
|
-
items.push(asyncItem);
|
|
150
|
-
}
|
|
151
|
-
for (const iterItem of items) {
|
|
152
|
-
stack.push({ node: iterItem, parent, metadata: item.metadata });
|
|
153
|
-
}
|
|
154
|
-
} catch (error) {
|
|
155
|
-
throw error;
|
|
156
|
-
}
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
if (node instanceof Response) {
|
|
160
|
-
const queueNode = pool.acquire("html-string", "");
|
|
161
|
-
queueNode.html = "";
|
|
162
|
-
queue.nodes.push(queueNode);
|
|
163
|
-
continue;
|
|
164
|
-
}
|
|
165
|
-
if (isHTMLString(node)) {
|
|
166
|
-
const html = String(node);
|
|
167
|
-
const queueNode = pool.acquire("html-string", html);
|
|
168
|
-
queueNode.html = html;
|
|
169
|
-
queue.nodes.push(queueNode);
|
|
170
|
-
} else {
|
|
171
|
-
const str = String(node);
|
|
172
|
-
const queueNode = pool.acquire("text", str);
|
|
173
|
-
queueNode.content = str;
|
|
174
|
-
queue.nodes.push(queueNode);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
queue.nodes.reverse();
|
|
178
|
-
return queue;
|
|
179
|
-
}
|
|
180
|
-
export {
|
|
181
|
-
buildRenderQueue
|
|
182
|
-
};
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import type { SSRResult } from '../../../../types/public/internal.js';
|
|
2
|
-
import type { RenderQueue, StackItem, QueueNode } from './types.js';
|
|
3
|
-
import type { NodePool } from './pool.js';
|
|
4
|
-
/**
|
|
5
|
-
* Get JSX queue rendering statistics
|
|
6
|
-
*/
|
|
7
|
-
export declare function getJSXQueueStats(): {
|
|
8
|
-
vnodeCount: number;
|
|
9
|
-
elementCount: number;
|
|
10
|
-
componentCount: number;
|
|
11
|
-
hasLogged: boolean;
|
|
12
|
-
};
|
|
13
|
-
/**
|
|
14
|
-
* Reset JSX queue rendering statistics
|
|
15
|
-
*/
|
|
16
|
-
export declare function resetJSXQueueStats(): void;
|
|
17
|
-
/**
|
|
18
|
-
* Processes JSX VNodes and adds them to the render queue.
|
|
19
|
-
* Unlike renderJSX(), this doesn't build strings recursively -
|
|
20
|
-
* it pushes nodes directly to the queue for batching and memory efficiency.
|
|
21
|
-
*
|
|
22
|
-
* This function handles JSX created by astro:jsx (JSX in .astro files).
|
|
23
|
-
* It converts VNodes to queue nodes, enabling content-aware pooling and batching.
|
|
24
|
-
*
|
|
25
|
-
* @param vnode - JSX VNode to process
|
|
26
|
-
* @param result - SSR result context
|
|
27
|
-
* @param queue - Queue to append nodes to
|
|
28
|
-
* @param pool - Node pool for memory efficiency
|
|
29
|
-
* @param stack - Stack for depth-first traversal
|
|
30
|
-
* @param parent - Parent queue node (for tracking)
|
|
31
|
-
* @param metadata - Metadata passed through stack (props, slots, displayName)
|
|
32
|
-
*/
|
|
33
|
-
export declare function renderJSXToQueue(vnode: any, result: SSRResult, queue: RenderQueue, pool: NodePool, stack: StackItem[], parent: QueueNode | null, metadata?: StackItem['metadata']): void;
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { isVNode } from "../../../../jsx-runtime/index.js";
|
|
2
|
-
import { HTMLString, markHTMLString, spreadAttributes, voidElementNames } from "../../index.js";
|
|
3
|
-
import { isAstroComponentFactory } from "../astro/factory.js";
|
|
4
|
-
import { createAstroComponentInstance } from "../astro/instance.js";
|
|
5
|
-
import { renderJSX } from "../../jsx.js";
|
|
6
|
-
const ClientOnlyPlaceholder = "astro-client-only";
|
|
7
|
-
let jsxQueueStats = {
|
|
8
|
-
vnodeCount: 0,
|
|
9
|
-
elementCount: 0,
|
|
10
|
-
componentCount: 0,
|
|
11
|
-
hasLogged: false
|
|
12
|
-
};
|
|
13
|
-
function getJSXQueueStats() {
|
|
14
|
-
return { ...jsxQueueStats };
|
|
15
|
-
}
|
|
16
|
-
function resetJSXQueueStats() {
|
|
17
|
-
jsxQueueStats = {
|
|
18
|
-
vnodeCount: 0,
|
|
19
|
-
elementCount: 0,
|
|
20
|
-
componentCount: 0,
|
|
21
|
-
hasLogged: false
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
function renderJSXToQueue(vnode, result, queue, pool, stack, parent, metadata) {
|
|
25
|
-
jsxQueueStats.vnodeCount = jsxQueueStats.vnodeCount + 1;
|
|
26
|
-
if (vnode instanceof HTMLString) {
|
|
27
|
-
const html = vnode.toString();
|
|
28
|
-
if (html.trim() === "") return;
|
|
29
|
-
const node = pool.acquire("html-string", html);
|
|
30
|
-
node.html = html;
|
|
31
|
-
queue.nodes.push(node);
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
if (typeof vnode === "string") {
|
|
35
|
-
const node = pool.acquire("text", vnode);
|
|
36
|
-
node.content = vnode;
|
|
37
|
-
queue.nodes.push(node);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
if (typeof vnode === "number" || typeof vnode === "boolean") {
|
|
41
|
-
const str = String(vnode);
|
|
42
|
-
const node = pool.acquire("text", str);
|
|
43
|
-
node.content = str;
|
|
44
|
-
queue.nodes.push(node);
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
if (vnode == null || vnode === false) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
if (Array.isArray(vnode)) {
|
|
51
|
-
for (let i = vnode.length - 1; i >= 0; i = i - 1) {
|
|
52
|
-
stack.push({ node: vnode[i], parent, metadata });
|
|
53
|
-
}
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
if (!isVNode(vnode)) {
|
|
57
|
-
const str = String(vnode);
|
|
58
|
-
const node = pool.acquire("text", str);
|
|
59
|
-
node.content = str;
|
|
60
|
-
queue.nodes.push(node);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
handleVNode(vnode, result, queue, pool, stack, parent, metadata);
|
|
64
|
-
}
|
|
65
|
-
function handleVNode(vnode, result, queue, pool, stack, parent, metadata) {
|
|
66
|
-
if (!vnode.type) {
|
|
67
|
-
throw new Error(
|
|
68
|
-
`Unable to render ${result.pathname} because it contains an undefined Component!
|
|
69
|
-
Did you forget to import the component or is it possible there is a typo?`
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
if (vnode.type === /* @__PURE__ */ Symbol.for("astro:fragment")) {
|
|
73
|
-
stack.push({ node: vnode.props?.children, parent, metadata });
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
if (isAstroComponentFactory(vnode.type)) {
|
|
77
|
-
jsxQueueStats.componentCount = jsxQueueStats.componentCount + 1;
|
|
78
|
-
const factory = vnode.type;
|
|
79
|
-
let props = {};
|
|
80
|
-
let slots = {};
|
|
81
|
-
for (const [key, value] of Object.entries(vnode.props ?? {})) {
|
|
82
|
-
if (key === "children" || value && typeof value === "object" && value["$$slot"]) {
|
|
83
|
-
slots[key === "children" ? "default" : key] = () => renderJSX(result, value);
|
|
84
|
-
} else {
|
|
85
|
-
props[key] = value;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const displayName = metadata?.displayName || factory.name || "Anonymous";
|
|
89
|
-
const instance = createAstroComponentInstance(result, displayName, factory, props, slots);
|
|
90
|
-
const queueNode = pool.acquire("component");
|
|
91
|
-
queueNode.instance = instance;
|
|
92
|
-
queue.nodes.push(queueNode);
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
if (typeof vnode.type === "string" && vnode.type !== ClientOnlyPlaceholder) {
|
|
96
|
-
jsxQueueStats.elementCount = jsxQueueStats.elementCount + 1;
|
|
97
|
-
renderHTMLElement(vnode, result, queue, pool, stack, parent, metadata);
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
if (typeof vnode.type === "function") {
|
|
101
|
-
if (vnode.props?.["server:root"]) {
|
|
102
|
-
const output3 = vnode.type(vnode.props ?? {});
|
|
103
|
-
stack.push({ node: output3, parent, metadata });
|
|
104
|
-
return;
|
|
105
|
-
}
|
|
106
|
-
const output2 = vnode.type(vnode.props ?? {});
|
|
107
|
-
stack.push({ node: output2, parent, metadata });
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
const output = renderJSX(result, vnode);
|
|
111
|
-
stack.push({ node: output, parent, metadata });
|
|
112
|
-
}
|
|
113
|
-
function renderHTMLElement(vnode, _result, queue, pool, stack, parent, metadata) {
|
|
114
|
-
const tag = vnode.type;
|
|
115
|
-
const { children, ...props } = vnode.props ?? {};
|
|
116
|
-
const attrs = spreadAttributes(props);
|
|
117
|
-
const isVoidElement = (children == null || children === "") && voidElementNames.test(tag);
|
|
118
|
-
if (isVoidElement) {
|
|
119
|
-
const html = `<${tag}${attrs}/>`;
|
|
120
|
-
const node = pool.acquire("html-string", html);
|
|
121
|
-
node.html = html;
|
|
122
|
-
queue.nodes.push(node);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
const openTag = `<${tag}${attrs}>`;
|
|
126
|
-
const openTagHtml = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(openTag) : markHTMLString(openTag);
|
|
127
|
-
stack.push({ node: openTagHtml, parent, metadata });
|
|
128
|
-
if (children != null && children !== "") {
|
|
129
|
-
const processedChildren = prerenderElementChildren(tag, children, queue.htmlStringCache);
|
|
130
|
-
stack.push({ node: processedChildren, parent, metadata });
|
|
131
|
-
}
|
|
132
|
-
const closeTag = `</${tag}>`;
|
|
133
|
-
const closeTagHtml = queue.htmlStringCache ? queue.htmlStringCache.getOrCreate(closeTag) : markHTMLString(closeTag);
|
|
134
|
-
stack.push({ node: closeTagHtml, parent, metadata });
|
|
135
|
-
}
|
|
136
|
-
function prerenderElementChildren(tag, children, htmlStringCache) {
|
|
137
|
-
if (typeof children === "string" && (tag === "style" || tag === "script")) {
|
|
138
|
-
return htmlStringCache ? htmlStringCache.getOrCreate(children) : markHTMLString(children);
|
|
139
|
-
}
|
|
140
|
-
return children;
|
|
141
|
-
}
|
|
142
|
-
export {
|
|
143
|
-
getJSXQueueStats,
|
|
144
|
-
renderJSXToQueue,
|
|
145
|
-
resetJSXQueueStats
|
|
146
|
-
};
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import type { QueueNode } from './types.js';
|
|
2
|
-
import type { SSRManifest } from '../../../../core/app/types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Raw statistics tracked by the node pool.
|
|
5
|
-
*/
|
|
6
|
-
export interface PoolStats {
|
|
7
|
-
/** Number of times a node was successfully acquired from the pool */
|
|
8
|
-
acquireFromPool: number;
|
|
9
|
-
/** Number of times a new node had to be created (pool was empty) */
|
|
10
|
-
acquireNew: number;
|
|
11
|
-
/** Number of nodes successfully returned to the pool */
|
|
12
|
-
released: number;
|
|
13
|
-
/** Number of nodes that couldn't be returned (pool was full) */
|
|
14
|
-
releasedDropped: number;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Extended statistics report with computed metrics.
|
|
18
|
-
* Returned by NodePool.getStats() for debugging and monitoring.
|
|
19
|
-
*/
|
|
20
|
-
export interface PoolStatsReport extends PoolStats {
|
|
21
|
-
/** Current number of nodes available in the pool */
|
|
22
|
-
poolSize: number;
|
|
23
|
-
/** Maximum pool capacity */
|
|
24
|
-
maxSize: number;
|
|
25
|
-
/** Pool hit rate as a percentage (0-100) - higher is better */
|
|
26
|
-
hitRate: number;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
* Object pool for `QueueNode` instances to reduce allocations and GC pressure.
|
|
30
|
-
*
|
|
31
|
-
* Uses type-aware sub-pools so that released nodes are reused by the same
|
|
32
|
-
* node type, preserving V8 hidden classes and avoiding shape transitions.
|
|
33
|
-
* Nodes are acquired from the pool, used during queue building, and released
|
|
34
|
-
* back to the pool for reuse across renders.
|
|
35
|
-
*
|
|
36
|
-
* String deduplication is handled separately by `HTMLStringCache`.
|
|
37
|
-
*/
|
|
38
|
-
export declare class NodePool {
|
|
39
|
-
private textPool;
|
|
40
|
-
private htmlStringPool;
|
|
41
|
-
private componentPool;
|
|
42
|
-
private instructionPool;
|
|
43
|
-
readonly maxSize: number;
|
|
44
|
-
private readonly enableStats;
|
|
45
|
-
private stats;
|
|
46
|
-
/**
|
|
47
|
-
* Creates a new object pool for queue nodes.
|
|
48
|
-
*
|
|
49
|
-
* @param maxSize - Maximum number of nodes to keep in the pool (default: 1000).
|
|
50
|
-
* The cap is shared across all typed sub-pools.
|
|
51
|
-
* @param enableStats - Enable statistics tracking (default: false for performance)
|
|
52
|
-
*/
|
|
53
|
-
constructor(maxSize?: number, enableStats?: boolean);
|
|
54
|
-
/**
|
|
55
|
-
* Acquires a queue node from the pool or creates a new one if the pool is empty.
|
|
56
|
-
* Pops from the type-specific sub-pool to reuse an existing object when available.
|
|
57
|
-
*
|
|
58
|
-
* @param type - The type of queue node to acquire
|
|
59
|
-
* @param content - Optional content to set on the node (for text or html-string types)
|
|
60
|
-
* @returns A queue node ready to be populated with data
|
|
61
|
-
*/
|
|
62
|
-
acquire(type: QueueNode['type'], content?: string): QueueNode;
|
|
63
|
-
/**
|
|
64
|
-
* Creates a new node of the specified type with the given content.
|
|
65
|
-
* Helper method to reduce branching in acquire().
|
|
66
|
-
*/
|
|
67
|
-
private createNode;
|
|
68
|
-
/**
|
|
69
|
-
* Pops a node from the type-specific sub-pool.
|
|
70
|
-
* Returns undefined if the sub-pool for the requested type is empty.
|
|
71
|
-
*/
|
|
72
|
-
private popFromTypedPool;
|
|
73
|
-
/**
|
|
74
|
-
* Resets the content/value field on a reused pooled node.
|
|
75
|
-
* The type discriminant is already correct since we pop from the matching sub-pool.
|
|
76
|
-
*/
|
|
77
|
-
private resetNodeContent;
|
|
78
|
-
/**
|
|
79
|
-
* Returns the total number of nodes across all typed sub-pools.
|
|
80
|
-
*/
|
|
81
|
-
private totalPoolSize;
|
|
82
|
-
/**
|
|
83
|
-
* Releases a queue node back to the pool for reuse.
|
|
84
|
-
* If the pool is at max capacity, the node is discarded (will be GC'd).
|
|
85
|
-
*
|
|
86
|
-
* @param node - The node to release back to the pool
|
|
87
|
-
*/
|
|
88
|
-
release(node: QueueNode): void;
|
|
89
|
-
/**
|
|
90
|
-
* Releases all nodes in an array back to the pool.
|
|
91
|
-
* This is a convenience method for releasing multiple nodes at once.
|
|
92
|
-
*
|
|
93
|
-
* @param nodes - Array of nodes to release
|
|
94
|
-
*/
|
|
95
|
-
releaseAll(nodes: QueueNode[]): void;
|
|
96
|
-
/**
|
|
97
|
-
* Clears all typed sub-pools, discarding all cached nodes.
|
|
98
|
-
* This can be useful if you want to free memory after a large render.
|
|
99
|
-
*/
|
|
100
|
-
clear(): void;
|
|
101
|
-
/**
|
|
102
|
-
* Gets the current total number of nodes across all typed sub-pools.
|
|
103
|
-
* Useful for monitoring pool usage and tuning maxSize.
|
|
104
|
-
*
|
|
105
|
-
* @returns Number of nodes currently available in the pool
|
|
106
|
-
*/
|
|
107
|
-
size(): number;
|
|
108
|
-
/**
|
|
109
|
-
* Gets pool statistics for debugging.
|
|
110
|
-
*
|
|
111
|
-
* @returns Pool usage statistics including computed metrics
|
|
112
|
-
*/
|
|
113
|
-
getStats(): PoolStatsReport;
|
|
114
|
-
/**
|
|
115
|
-
* Resets pool statistics.
|
|
116
|
-
*/
|
|
117
|
-
resetStats(): void;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Returns an instance of the `NodePool` based on its configuration.
|
|
121
|
-
* @param config - The queued rendering configuration from the SSR manifest
|
|
122
|
-
*/
|
|
123
|
-
export declare function newNodePool(config: NonNullable<SSRManifest['experimentalQueuedRendering']>): NodePool;
|