astro 2.9.2 → 2.9.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.
Files changed (31) hide show
  1. package/components/ViewTransitions.astro +23 -0
  2. package/dist/core/constants.js +1 -1
  3. package/dist/core/dev/dev.js +1 -1
  4. package/dist/core/messages.js +2 -2
  5. package/dist/core/render/result.js +4 -7
  6. package/dist/runtime/server/index.d.ts +1 -1
  7. package/dist/runtime/server/index.js +0 -6
  8. package/dist/runtime/server/jsx.js +4 -13
  9. package/dist/runtime/server/render/any.d.ts +2 -1
  10. package/dist/runtime/server/render/any.js +18 -22
  11. package/dist/runtime/server/render/astro/index.d.ts +1 -1
  12. package/dist/runtime/server/render/astro/index.js +1 -6
  13. package/dist/runtime/server/render/astro/instance.d.ts +3 -2
  14. package/dist/runtime/server/render/astro/instance.js +8 -4
  15. package/dist/runtime/server/render/astro/render-template.d.ts +2 -4
  16. package/dist/runtime/server/render/astro/render-template.js +8 -29
  17. package/dist/runtime/server/render/astro/render.js +4 -24
  18. package/dist/runtime/server/render/common.d.ts +17 -13
  19. package/dist/runtime/server/render/common.js +4 -20
  20. package/dist/runtime/server/render/component.d.ts +10 -4
  21. package/dist/runtime/server/render/component.js +131 -54
  22. package/dist/runtime/server/render/dom.d.ts +1 -1
  23. package/dist/runtime/server/render/index.d.ts +3 -3
  24. package/dist/runtime/server/render/index.js +6 -11
  25. package/dist/runtime/server/render/page.d.ts +2 -7
  26. package/dist/runtime/server/render/page.js +13 -62
  27. package/dist/runtime/server/render/slot.d.ts +2 -1
  28. package/dist/runtime/server/render/slot.js +23 -16
  29. package/dist/runtime/server/render/util.d.ts +0 -18
  30. package/dist/runtime/server/render/util.js +0 -101
  31. package/package.json +1 -1
@@ -25,6 +25,7 @@ const { fallback = 'animate' } = Astro.props as Props;
25
25
  const supportsViewTransitions = !!document.startViewTransition;
26
26
  const transitionEnabledOnThisPage = () =>
27
27
  !!document.querySelector('[name="astro-view-transitions-enabled"]');
28
+ const onload = () => document.dispatchEvent(new Event('astro:load'));
28
29
 
29
30
  async function getHTML(href: string) {
30
31
  const res = await fetch(href);
@@ -40,6 +41,25 @@ const { fallback = 'animate' } = Astro.props as Props;
40
41
  return 'animate';
41
42
  }
42
43
 
44
+ function runScripts() {
45
+ let wait = Promise.resolve();
46
+ for (const script of Array.from(document.scripts)) {
47
+ const s = document.createElement('script');
48
+ s.innerHTML = script.innerHTML;
49
+ for (const attr of script.attributes) {
50
+ if (attr.name === 'src') {
51
+ const p = new Promise((r) => {
52
+ s.onload = r;
53
+ });
54
+ wait = wait.then(() => p as any);
55
+ }
56
+ s.setAttribute(attr.name, attr.value);
57
+ }
58
+ script.replaceWith(s);
59
+ }
60
+ return wait;
61
+ }
62
+
43
63
  const parser = new DOMParser();
44
64
 
45
65
  async function updateDOM(dir: Direction, html: string, fallback?: Fallback) {
@@ -95,6 +115,8 @@ const { fallback = 'animate' } = Astro.props as Props;
95
115
  await finished;
96
116
  } finally {
97
117
  document.documentElement.removeAttribute('data-astro-transition');
118
+ await runScripts();
119
+ onload();
98
120
  }
99
121
  }
100
122
 
@@ -171,5 +193,6 @@ const { fallback = 'animate' } = Astro.props as Props;
171
193
  { passive: true, capture: true }
172
194
  );
173
195
  });
196
+ addEventListener('load', onload);
174
197
  }
175
198
  </script>
@@ -1,4 +1,4 @@
1
- const ASTRO_VERSION = "2.9.2";
1
+ const ASTRO_VERSION = "2.9.3";
2
2
  const SUPPORTED_MARKDOWN_FILE_EXTENSIONS = [
3
3
  ".markdown",
4
4
  ".mdown",
@@ -54,7 +54,7 @@ async function dev(settings, options) {
54
54
  isRestart: options.isRestart
55
55
  })
56
56
  );
57
- const currentVersion = "2.9.2";
57
+ const currentVersion = "2.9.3";
58
58
  if (currentVersion.includes("-")) {
59
59
  warn(options.logging, null, msg.prerelease({ currentVersion }));
60
60
  }
@@ -47,7 +47,7 @@ function serverStart({
47
47
  base,
48
48
  isRestart = false
49
49
  }) {
50
- const version = "2.9.2";
50
+ const version = "2.9.3";
51
51
  const localPrefix = `${dim("\u2503")} Local `;
52
52
  const networkPrefix = `${dim("\u2503")} Network `;
53
53
  const emptyPrefix = " ".repeat(11);
@@ -233,7 +233,7 @@ function printHelp({
233
233
  message.push(
234
234
  linebreak(),
235
235
  ` ${bgGreen(black(` ${commandName} `))} ${green(
236
- `v${"2.9.2"}`
236
+ `v${"2.9.3"}`
237
237
  )} ${headline}`
238
238
  );
239
239
  }
@@ -1,9 +1,6 @@
1
- import { isHTMLString } from "../../runtime/server/escape.js";
2
- import {
3
- renderSlotToString,
4
- stringifyChunk
5
- } from "../../runtime/server/index.js";
1
+ import { renderSlotToString } from "../../runtime/server/index.js";
6
2
  import { renderJSX } from "../../runtime/server/jsx.js";
3
+ import { chunkToString } from "../../runtime/server/render/index.js";
7
4
  import { AstroCookies } from "../cookies/index.js";
8
5
  import { AstroError, AstroErrorData } from "../errors/index.js";
9
6
  import { warn } from "../logger/core.js";
@@ -62,7 +59,7 @@ class Slots {
62
59
  const component = typeof slotValue === "function" ? await slotValue(result) : await slotValue;
63
60
  const expression = getFunctionExpression(component);
64
61
  if (expression) {
65
- const slot = async () => isHTMLString(await expression) ? expression : expression(...args);
62
+ const slot = async () => typeof expression === "function" ? expression(...args) : expression;
66
63
  return await renderSlotToString(result, slot).then((res) => {
67
64
  return res != null ? String(res) : res;
68
65
  });
@@ -74,7 +71,7 @@ class Slots {
74
71
  }
75
72
  }
76
73
  const content = await renderSlotToString(result, this.#slots[name]);
77
- const outHTML = stringifyChunk(result, content);
74
+ const outHTML = chunkToString(result, content);
78
75
  return outHTML;
79
76
  }
80
77
  }
@@ -3,7 +3,7 @@ export { createAstro } from './astro-global.js';
3
3
  export { renderEndpoint } from './endpoint.js';
4
4
  export { escapeHTML, HTMLBytes, HTMLString, isHTMLString, markHTMLString, unescapeHTML, } from './escape.js';
5
5
  export { renderJSX } from './jsx.js';
6
- export { addAttribute, createHeadAndContent, defineScriptVars, Fragment, maybeRenderHead, renderTemplate as render, renderAstroTemplateResult as renderAstroComponent, renderComponent, renderComponentToIterable, Renderer as Renderer, renderHead, renderHTMLElement, renderPage, renderScriptElement, renderSlot, renderSlotToString, renderTemplate, renderToString, renderUniqueStylesheet, stringifyChunk, voidElementNames, } from './render/index.js';
6
+ export { addAttribute, createHeadAndContent, defineScriptVars, Fragment, maybeRenderHead, renderTemplate as render, renderComponent, Renderer as Renderer, renderHead, renderHTMLElement, renderPage, renderScriptElement, renderSlot, renderSlotToString, renderTemplate, renderToString, renderUniqueStylesheet, voidElementNames, } from './render/index.js';
7
7
  export type { AstroComponentFactory, AstroComponentInstance, ComponentSlots, RenderInstruction, } from './render/index.js';
8
8
  export { renderTransition } from './transition.js';
9
9
  export declare function mergeSlots(...slotted: unknown[]): Record<string, () => any>;
@@ -17,9 +17,7 @@ import {
17
17
  Fragment,
18
18
  maybeRenderHead,
19
19
  renderTemplate,
20
- renderAstroTemplateResult,
21
20
  renderComponent,
22
- renderComponentToIterable,
23
21
  Renderer,
24
22
  renderHead,
25
23
  renderHTMLElement,
@@ -30,7 +28,6 @@ import {
30
28
  renderTemplate as renderTemplate2,
31
29
  renderToString,
32
30
  renderUniqueStylesheet,
33
- stringifyChunk,
34
31
  voidElementNames
35
32
  } from "./render/index.js";
36
33
  import { renderTransition } from "./transition.js";
@@ -106,9 +103,7 @@ export {
106
103
  maybeRenderHead,
107
104
  mergeSlots,
108
105
  renderTemplate as render,
109
- renderAstroTemplateResult as renderAstroComponent,
110
106
  renderComponent,
111
- renderComponentToIterable,
112
107
  renderEndpoint,
113
108
  renderHTMLElement,
114
109
  renderHead,
@@ -122,7 +117,6 @@ export {
122
117
  renderTransition,
123
118
  renderUniqueStylesheet,
124
119
  spreadAttributes,
125
- stringifyChunk,
126
120
  unescapeHTML,
127
121
  voidElementNames
128
122
  };
@@ -3,12 +3,11 @@ import {
3
3
  HTMLString,
4
4
  escapeHTML,
5
5
  markHTMLString,
6
- renderComponentToIterable,
7
6
  renderToString,
8
7
  spreadAttributes,
9
8
  voidElementNames
10
9
  } from "./index.js";
11
- import { HTMLParts } from "./render/common.js";
10
+ import { renderComponentToString } from "./render/component.js";
12
11
  const ClientOnlyPlaceholder = "astro-client-only";
13
12
  class Skip {
14
13
  constructor(vnode) {
@@ -164,7 +163,7 @@ Did you forget to import the component or is it possible there is a typo?`);
164
163
  props[Skip.symbol] = skip;
165
164
  let output;
166
165
  if (vnode.type === ClientOnlyPlaceholder && vnode.props["client:only"]) {
167
- output = await renderComponentToIterable(
166
+ output = await renderComponentToString(
168
167
  result,
169
168
  vnode.props["client:display-name"] ?? "",
170
169
  null,
@@ -172,7 +171,7 @@ Did you forget to import the component or is it possible there is a typo?`);
172
171
  slots
173
172
  );
174
173
  } else {
175
- output = await renderComponentToIterable(
174
+ output = await renderComponentToString(
176
175
  result,
177
176
  typeof vnode.type === "function" ? vnode.type.name : vnode.type,
178
177
  vnode.type,
@@ -180,15 +179,7 @@ Did you forget to import the component or is it possible there is a typo?`);
180
179
  slots
181
180
  );
182
181
  }
183
- if (typeof output !== "string" && Symbol.asyncIterator in output) {
184
- let parts = new HTMLParts();
185
- for await (const chunk of output) {
186
- parts.append(chunk, result);
187
- }
188
- return markHTMLString(parts.toString());
189
- } else {
190
- return markHTMLString(output);
191
- }
182
+ return markHTMLString(output);
192
183
  }
193
184
  }
194
185
  return markHTMLString(`${vnode}`);
@@ -1 +1,2 @@
1
- export declare function renderChild(child: any): AsyncIterable<any>;
1
+ import { type RenderDestination } from './common.js';
2
+ export declare function renderChild(destination: RenderDestination, child: any): Promise<void>;
@@ -1,40 +1,36 @@
1
1
  import { escapeHTML, isHTMLString, markHTMLString } from "../escape.js";
2
- import {
3
- isAstroComponentInstance,
4
- isRenderTemplateResult,
5
- renderAstroTemplateResult
6
- } from "./astro/index.js";
2
+ import { isAstroComponentInstance, isRenderTemplateResult } from "./astro/index.js";
3
+ import { isRenderInstance } from "./common.js";
7
4
  import { SlotString } from "./slot.js";
8
- import { bufferIterators } from "./util.js";
9
- async function* renderChild(child) {
5
+ async function renderChild(destination, child) {
10
6
  child = await child;
11
7
  if (child instanceof SlotString) {
12
- if (child.instructions) {
13
- yield* child.instructions;
14
- }
15
- yield child;
8
+ destination.write(child);
16
9
  } else if (isHTMLString(child)) {
17
- yield child;
10
+ destination.write(child);
18
11
  } else if (Array.isArray(child)) {
19
- const bufferedIterators = bufferIterators(child.map((c) => renderChild(c)));
20
- for (const value of bufferedIterators) {
21
- yield markHTMLString(await value);
12
+ for (const c of child) {
13
+ await renderChild(destination, c);
22
14
  }
23
15
  } else if (typeof child === "function") {
24
- yield* renderChild(child());
16
+ await renderChild(destination, child());
25
17
  } else if (typeof child === "string") {
26
- yield markHTMLString(escapeHTML(child));
18
+ destination.write(markHTMLString(escapeHTML(child)));
27
19
  } else if (!child && child !== 0) {
20
+ } else if (isRenderInstance(child)) {
21
+ await child.render(destination);
28
22
  } else if (isRenderTemplateResult(child)) {
29
- yield* renderAstroTemplateResult(child);
23
+ await child.render(destination);
30
24
  } else if (isAstroComponentInstance(child)) {
31
- yield* child.render();
25
+ await child.render(destination);
32
26
  } else if (ArrayBuffer.isView(child)) {
33
- yield child;
27
+ destination.write(child);
34
28
  } else if (typeof child === "object" && (Symbol.asyncIterator in child || Symbol.iterator in child)) {
35
- yield* child;
29
+ for await (const value of child) {
30
+ await renderChild(destination, value);
31
+ }
36
32
  } else {
37
- yield child;
33
+ destination.write(child);
38
34
  }
39
35
  }
40
36
  export {
@@ -3,5 +3,5 @@ export { isAstroComponentFactory } from './factory.js';
3
3
  export { createHeadAndContent, isHeadAndContent } from './head-and-content.js';
4
4
  export type { AstroComponentInstance } from './instance';
5
5
  export { createAstroComponentInstance, isAstroComponentInstance } from './instance.js';
6
- export { isRenderTemplateResult, renderAstroTemplateResult, renderTemplate, } from './render-template.js';
6
+ export { isRenderTemplateResult, renderTemplate } from './render-template.js';
7
7
  export { renderToReadableStream, renderToString } from './render.js';
@@ -1,11 +1,7 @@
1
1
  import { isAstroComponentFactory } from "./factory.js";
2
2
  import { createHeadAndContent, isHeadAndContent } from "./head-and-content.js";
3
3
  import { createAstroComponentInstance, isAstroComponentInstance } from "./instance.js";
4
- import {
5
- isRenderTemplateResult,
6
- renderAstroTemplateResult,
7
- renderTemplate
8
- } from "./render-template.js";
4
+ import { isRenderTemplateResult, renderTemplate } from "./render-template.js";
9
5
  import { renderToReadableStream, renderToString } from "./render.js";
10
6
  export {
11
7
  createAstroComponentInstance,
@@ -14,7 +10,6 @@ export {
14
10
  isAstroComponentInstance,
15
11
  isHeadAndContent,
16
12
  isRenderTemplateResult,
17
- renderAstroTemplateResult,
18
13
  renderTemplate,
19
14
  renderToReadableStream,
20
15
  renderToString
@@ -1,6 +1,7 @@
1
1
  import type { SSRResult } from '../../../../@types/astro';
2
2
  import type { ComponentSlots } from '../slot.js';
3
3
  import type { AstroComponentFactory, AstroFactoryReturnValue } from './factory.js';
4
+ import type { RenderDestination } from '../common.js';
4
5
  type ComponentProps = Record<string | number, any>;
5
6
  declare const astroComponentInstanceSym: unique symbol;
6
7
  export declare class AstroComponentInstance {
@@ -12,8 +13,8 @@ export declare class AstroComponentInstance {
12
13
  private returnValue;
13
14
  constructor(result: SSRResult, props: ComponentProps, slots: ComponentSlots, factory: AstroComponentFactory);
14
15
  init(result: SSRResult): Promise<AstroFactoryReturnValue>;
15
- render(): AsyncGenerator<any, void, undefined>;
16
+ render(destination: RenderDestination): Promise<void>;
16
17
  }
17
- export declare function createAstroComponentInstance(result: SSRResult, displayName: string, factory: AstroComponentFactory, props: ComponentProps, slots?: any): AstroComponentInstance;
18
+ export declare function createAstroComponentInstance(result: SSRResult, displayName: string, factory: AstroComponentFactory, props: ComponentProps, slots?: any): Promise<AstroComponentInstance>;
18
19
  export declare function isAstroComponentInstance(obj: unknown): obj is AstroComponentInstance;
19
20
  export {};
@@ -20,7 +20,7 @@ class AstroComponentInstance {
20
20
  this.returnValue = this.factory(result, this.props, this.slotValues);
21
21
  return this.returnValue;
22
22
  }
23
- async *render() {
23
+ async render(destination) {
24
24
  if (this.returnValue === void 0) {
25
25
  await this.init(this.result);
26
26
  }
@@ -29,9 +29,9 @@ class AstroComponentInstance {
29
29
  value = await value;
30
30
  }
31
31
  if (isHeadAndContent(value)) {
32
- yield* value.content;
32
+ await value.content.render(destination);
33
33
  } else {
34
- yield* renderChild(value);
34
+ await renderChild(destination, value);
35
35
  }
36
36
  }
37
37
  }
@@ -47,11 +47,15 @@ function validateComponentProps(props, displayName) {
47
47
  }
48
48
  }
49
49
  }
50
- function createAstroComponentInstance(result, displayName, factory, props, slots = {}) {
50
+ async function createAstroComponentInstance(result, displayName, factory, props, slots = {}) {
51
51
  validateComponentProps(props, displayName);
52
52
  const instance = new AstroComponentInstance(result, props, slots, factory);
53
53
  if (isAPropagatingComponent(result, factory) && !result._metadata.propagators.has(factory)) {
54
54
  result._metadata.propagators.set(factory, instance);
55
+ const returnValue = await instance.init(result);
56
+ if (isHeadAndContent(returnValue)) {
57
+ result._metadata.extraHead.push(returnValue.head);
58
+ }
55
59
  }
56
60
  return instance;
57
61
  }
@@ -1,5 +1,4 @@
1
- import type { RenderInstruction } from '../types';
2
- import { HTMLBytes } from '../../escape.js';
1
+ import type { RenderDestination } from '../common.js';
3
2
  declare const renderTemplateResultSym: unique symbol;
4
3
  export declare class RenderTemplateResult {
5
4
  [renderTemplateResultSym]: boolean;
@@ -7,9 +6,8 @@ export declare class RenderTemplateResult {
7
6
  private expressions;
8
7
  private error;
9
8
  constructor(htmlParts: TemplateStringsArray, expressions: unknown[]);
10
- [Symbol.asyncIterator](): AsyncGenerator<any, void, undefined>;
9
+ render(destination: RenderDestination): Promise<void>;
11
10
  }
12
11
  export declare function isRenderTemplateResult(obj: unknown): obj is RenderTemplateResult;
13
- export declare function renderAstroTemplateResult(component: RenderTemplateResult): AsyncIterable<string | HTMLBytes | RenderInstruction>;
14
12
  export declare function renderTemplate(htmlParts: TemplateStringsArray, ...expressions: any[]): RenderTemplateResult;
15
13
  export {};
@@ -2,7 +2,6 @@ var _a;
2
2
  import { markHTMLString } from "../../escape.js";
3
3
  import { isPromise } from "../../util.js";
4
4
  import { renderChild } from "../any.js";
5
- import { bufferIterators } from "../util.js";
6
5
  const renderTemplateResultSym = Symbol.for("astro.renderTemplateResult");
7
6
  class RenderTemplateResult {
8
7
  constructor(htmlParts, expressions) {
@@ -21,46 +20,26 @@ class RenderTemplateResult {
21
20
  return expression;
22
21
  });
23
22
  }
24
- async *[(_a = renderTemplateResultSym, Symbol.asyncIterator)]() {
25
- const { htmlParts, expressions } = this;
26
- let iterables = bufferIterators(expressions.map((e) => renderChild(e)));
27
- for (let i = 0; i < htmlParts.length; i++) {
28
- const html = htmlParts[i];
29
- const iterable = iterables[i];
30
- yield markHTMLString(html);
31
- if (iterable) {
32
- yield* iterable;
23
+ async render(destination) {
24
+ for (let i = 0; i < this.htmlParts.length; i++) {
25
+ const html = this.htmlParts[i];
26
+ const exp = this.expressions[i];
27
+ destination.write(markHTMLString(html));
28
+ if (exp || exp === 0) {
29
+ await renderChild(destination, exp);
33
30
  }
34
31
  }
35
32
  }
36
33
  }
34
+ _a = renderTemplateResultSym;
37
35
  function isRenderTemplateResult(obj) {
38
36
  return typeof obj === "object" && !!obj[renderTemplateResultSym];
39
37
  }
40
- async function* renderAstroTemplateResult(component) {
41
- for await (const value of component) {
42
- if (value || value === 0) {
43
- for await (const chunk of renderChild(value)) {
44
- switch (chunk.type) {
45
- case "directive": {
46
- yield chunk;
47
- break;
48
- }
49
- default: {
50
- yield markHTMLString(chunk);
51
- break;
52
- }
53
- }
54
- }
55
- }
56
- }
57
- }
58
38
  function renderTemplate(htmlParts, ...expressions) {
59
39
  return new RenderTemplateResult(htmlParts, expressions);
60
40
  }
61
41
  export {
62
42
  RenderTemplateResult,
63
43
  isRenderTemplateResult,
64
- renderAstroTemplateResult,
65
44
  renderTemplate
66
45
  };
@@ -1,7 +1,7 @@
1
1
  import { AstroError, AstroErrorData } from "../../../../core/errors/index.js";
2
2
  import { chunkToByteArray, chunkToString, encoder } from "../common.js";
3
3
  import { isHeadAndContent } from "./head-and-content.js";
4
- import { isRenderTemplateResult, renderAstroTemplateResult } from "./render-template.js";
4
+ import { isRenderTemplateResult } from "./render-template.js";
5
5
  async function renderToString(result, componentFactory, props, children, isPage = false, route) {
6
6
  const templateResult = await callComponentAsTemplateResultOrResponse(
7
7
  result,
@@ -28,9 +28,7 @@ async function renderToString(result, componentFactory, props, children, isPage
28
28
  str += chunkToString(result, chunk);
29
29
  }
30
30
  };
31
- for await (const chunk of renderAstroTemplateResult(templateResult)) {
32
- destination.write(chunk);
33
- }
31
+ await templateResult.render(destination);
34
32
  return str;
35
33
  }
36
34
  async function renderToReadableStream(result, componentFactory, props, children, isPage = false, route) {
@@ -43,9 +41,6 @@ async function renderToReadableStream(result, componentFactory, props, children,
43
41
  );
44
42
  if (templateResult instanceof Response)
45
43
  return templateResult;
46
- if (isPage) {
47
- await bufferHeadContent(result);
48
- }
49
44
  let renderedFirstPageChunk = false;
50
45
  return new ReadableStream({
51
46
  start(controller) {
@@ -69,9 +64,7 @@ async function renderToReadableStream(result, componentFactory, props, children,
69
64
  };
70
65
  (async () => {
71
66
  try {
72
- for await (const chunk of renderAstroTemplateResult(templateResult)) {
73
- destination.write(chunk);
74
- }
67
+ await templateResult.render(destination);
75
68
  controller.close();
76
69
  } catch (e) {
77
70
  if (AstroError.is(e) && !e.loc) {
@@ -79,7 +72,7 @@ async function renderToReadableStream(result, componentFactory, props, children,
79
72
  file: route == null ? void 0 : route.component
80
73
  });
81
74
  }
82
- controller.error(e);
75
+ setTimeout(() => controller.error(e), 0);
83
76
  }
84
77
  })();
85
78
  }
@@ -100,19 +93,6 @@ async function callComponentAsTemplateResultOrResponse(result, componentFactory,
100
93
  }
101
94
  return isHeadAndContent(factoryResult) ? factoryResult.content : factoryResult;
102
95
  }
103
- async function bufferHeadContent(result) {
104
- const iterator = result._metadata.propagators.values();
105
- while (true) {
106
- const { value, done } = iterator.next();
107
- if (done) {
108
- break;
109
- }
110
- const returnValue = await value.init(result);
111
- if (isHeadAndContent(returnValue)) {
112
- result._metadata.extraHead.push(returnValue.head);
113
- }
114
- }
115
- }
116
96
  export {
117
97
  renderToReadableStream,
118
98
  renderToString
@@ -1,25 +1,29 @@
1
1
  import type { SSRResult } from '../../../@types/astro';
2
2
  import type { RenderInstruction } from './types.js';
3
- import { HTMLBytes } from '../escape.js';
3
+ import { HTMLBytes, HTMLString } from '../escape.js';
4
4
  import { type SlotString } from './slot.js';
5
+ /**
6
+ * Possible chunk types to be written to the destination, and it'll
7
+ * handle stringifying them at the end.
8
+ *
9
+ * NOTE: Try to reduce adding new types here. If possible, serialize
10
+ * the custom types to a string in `renderChild` in `any.ts`.
11
+ */
12
+ export type RenderDestinationChunk = string | HTMLBytes | HTMLString | SlotString | ArrayBufferView | RenderInstruction | Response;
5
13
  export interface RenderDestination {
6
14
  /**
7
15
  * Any rendering logic should call this to construct the HTML output.
8
- * See the `chunk` parameter for possible writable values
16
+ * See the `chunk` parameter for possible writable values.
9
17
  */
10
- write(chunk: string | HTMLBytes | RenderInstruction | Response): void;
18
+ write(chunk: RenderDestinationChunk): void;
19
+ }
20
+ export interface RenderInstance {
21
+ render(destination: RenderDestination): Promise<void> | void;
11
22
  }
12
23
  export declare const Fragment: unique symbol;
13
24
  export declare const Renderer: unique symbol;
14
25
  export declare const encoder: TextEncoder;
15
26
  export declare const decoder: TextDecoder;
16
- export declare function stringifyChunk(result: SSRResult, chunk: string | SlotString | RenderInstruction): string;
17
- export declare class HTMLParts {
18
- parts: string;
19
- constructor();
20
- append(part: string | HTMLBytes | RenderInstruction, result: SSRResult): void;
21
- toString(): string;
22
- toArrayBuffer(): Uint8Array;
23
- }
24
- export declare function chunkToString(result: SSRResult, chunk: string | HTMLBytes | RenderInstruction): string;
25
- export declare function chunkToByteArray(result: SSRResult, chunk: string | HTMLBytes | RenderInstruction): Uint8Array;
27
+ export declare function chunkToString(result: SSRResult, chunk: Exclude<RenderDestinationChunk, Response>): string;
28
+ export declare function chunkToByteArray(result: SSRResult, chunk: Exclude<RenderDestinationChunk, Response>): Uint8Array;
29
+ export declare function isRenderInstance(obj: unknown): obj is RenderInstance;
@@ -60,24 +60,6 @@ function stringifyChunk(result, chunk) {
60
60
  return chunk.toString();
61
61
  }
62
62
  }
63
- class HTMLParts {
64
- constructor() {
65
- this.parts = "";
66
- }
67
- append(part, result) {
68
- if (ArrayBuffer.isView(part)) {
69
- this.parts += decoder.decode(part);
70
- } else {
71
- this.parts += stringifyChunk(result, part);
72
- }
73
- }
74
- toString() {
75
- return this.parts;
76
- }
77
- toArrayBuffer() {
78
- return encoder.encode(this.parts);
79
- }
80
- }
81
63
  function chunkToString(result, chunk) {
82
64
  if (ArrayBuffer.isView(chunk)) {
83
65
  return decoder.decode(chunk);
@@ -93,13 +75,15 @@ function chunkToByteArray(result, chunk) {
93
75
  return encoder.encode(stringified.toString());
94
76
  }
95
77
  }
78
+ function isRenderInstance(obj) {
79
+ return !!obj && typeof obj === "object" && "render" in obj && typeof obj.render === "function";
80
+ }
96
81
  export {
97
82
  Fragment,
98
- HTMLParts,
99
83
  Renderer,
100
84
  chunkToByteArray,
101
85
  chunkToString,
102
86
  decoder,
103
87
  encoder,
104
- stringifyChunk
88
+ isRenderInstance
105
89
  };
@@ -1,7 +1,13 @@
1
- import type { SSRResult } from '../../../@types/astro';
1
+ import type { RouteData, SSRResult } from '../../../@types/astro';
2
2
  import type { RenderInstruction } from './types.js';
3
3
  import { HTMLBytes } from '../escape.js';
4
- import { type AstroComponentInstance } from './astro/index.js';
4
+ import { type RenderInstance } from './common.js';
5
+ declare const needsHeadRenderingSymbol: unique symbol;
5
6
  export type ComponentIterable = AsyncIterable<string | HTMLBytes | RenderInstruction>;
6
- export declare function renderComponent(result: SSRResult, displayName: string, Component: unknown, props: Record<string | number, any>, slots?: any): Promise<ComponentIterable> | ComponentIterable | AstroComponentInstance;
7
- export declare function renderComponentToIterable(result: SSRResult, displayName: string, Component: unknown, props: Record<string | number, any>, slots?: any): Promise<ComponentIterable> | ComponentIterable;
7
+ export declare function renderComponent(result: SSRResult, displayName: string, Component: unknown, props: Record<string | number, any>, slots?: any): Promise<RenderInstance>;
8
+ export declare function renderComponentToString(result: SSRResult, displayName: string, Component: unknown, props: Record<string | number, any>, slots?: any, isPage?: boolean, route?: RouteData): Promise<string>;
9
+ export type NonAstroPageComponent = {
10
+ name: string;
11
+ [needsHeadRenderingSymbol]: boolean;
12
+ };
13
+ export {};
@@ -7,14 +7,18 @@ import { isPromise } from "../util.js";
7
7
  import {
8
8
  createAstroComponentInstance,
9
9
  isAstroComponentFactory,
10
- isAstroComponentInstance,
11
- renderAstroTemplateResult,
12
10
  renderTemplate
13
11
  } from "./astro/index.js";
14
- import { Fragment, Renderer, stringifyChunk } from "./common.js";
12
+ import {
13
+ Fragment,
14
+ Renderer,
15
+ chunkToString
16
+ } from "./common.js";
15
17
  import { componentIsHTMLElement, renderHTMLElement } from "./dom.js";
18
+ import { maybeRenderHead } from "./head.js";
16
19
  import { renderSlotToString, renderSlots } from "./slot.js";
17
20
  import { formatList, internalSpreadAttributes, renderElement, voidElementNames } from "./util.js";
21
+ const needsHeadRenderingSymbol = Symbol.for("astro.needsHeadRendering");
18
22
  const rendererAliases = /* @__PURE__ */ new Map([["solid", "solid-js"]]);
19
23
  function guessRenderers(componentUrl) {
20
24
  const extname = componentUrl == null ? void 0 : componentUrl.split(".").pop();
@@ -102,8 +106,17 @@ Did you forget to import the component or is it possible there is a typo?`
102
106
  }
103
107
  }
104
108
  if (!renderer && typeof HTMLElement === "function" && componentIsHTMLElement(Component)) {
105
- const output = renderHTMLElement(result, Component, _props, slots);
106
- return output;
109
+ const output = await renderHTMLElement(
110
+ result,
111
+ Component,
112
+ _props,
113
+ slots
114
+ );
115
+ return {
116
+ render(destination) {
117
+ destination.write(output);
118
+ }
119
+ };
107
120
  }
108
121
  } else {
109
122
  if (metadata.hydrateArgs) {
@@ -199,32 +212,41 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr
199
212
  if (!html && typeof Component === "string") {
200
213
  const Tag = sanitizeElementName(Component);
201
214
  const childSlots = Object.values(children).join("");
202
- const iterable = renderAstroTemplateResult(
203
- await renderTemplate`<${Tag}${internalSpreadAttributes(props)}${markHTMLString(
204
- childSlots === "" && voidElementNames.test(Tag) ? `/>` : `>${childSlots}</${Tag}>`
205
- )}`
206
- );
215
+ const renderTemplateResult = renderTemplate`<${Tag}${internalSpreadAttributes(
216
+ props
217
+ )}${markHTMLString(
218
+ childSlots === "" && voidElementNames.test(Tag) ? `/>` : `>${childSlots}</${Tag}>`
219
+ )}`;
207
220
  html = "";
208
- for await (const chunk of iterable) {
209
- html += chunk;
210
- }
221
+ const destination = {
222
+ write(chunk) {
223
+ if (chunk instanceof Response)
224
+ return;
225
+ html += chunkToString(result, chunk);
226
+ }
227
+ };
228
+ await renderTemplateResult.render(destination);
211
229
  }
212
230
  if (!hydration) {
213
- return async function* () {
214
- var _a2;
215
- if (slotInstructions) {
216
- yield* slotInstructions;
217
- }
218
- if (isPage || (renderer == null ? void 0 : renderer.name) === "astro:jsx") {
219
- yield html;
220
- } else if (html && html.length > 0) {
221
- yield markHTMLString(
222
- removeStaticAstroSlot(html, ((_a2 = renderer == null ? void 0 : renderer.ssr) == null ? void 0 : _a2.supportsAstroStaticSlot) ?? false)
223
- );
224
- } else {
225
- yield "";
231
+ return {
232
+ render(destination) {
233
+ var _a2;
234
+ if (slotInstructions) {
235
+ for (const instruction of slotInstructions) {
236
+ destination.write(instruction);
237
+ }
238
+ }
239
+ if (isPage || (renderer == null ? void 0 : renderer.name) === "astro:jsx") {
240
+ destination.write(html);
241
+ } else if (html && html.length > 0) {
242
+ destination.write(
243
+ markHTMLString(
244
+ removeStaticAstroSlot(html, ((_a2 = renderer == null ? void 0 : renderer.ssr) == null ? void 0 : _a2.supportsAstroStaticSlot) ?? false)
245
+ )
246
+ );
247
+ }
226
248
  }
227
- }();
249
+ };
228
250
  }
229
251
  const astroId = shorthash(
230
252
  `<!--${metadata.componentExport.value}:${metadata.componentUrl}-->
@@ -259,14 +281,17 @@ ${serializeProps(
259
281
  if (island.children) {
260
282
  island.props["await-children"] = "";
261
283
  }
262
- async function* renderAll() {
263
- if (slotInstructions) {
264
- yield* slotInstructions;
284
+ return {
285
+ render(destination) {
286
+ if (slotInstructions) {
287
+ for (const instruction of slotInstructions) {
288
+ destination.write(instruction);
289
+ }
290
+ }
291
+ destination.write({ type: "directive", hydration });
292
+ destination.write(markHTMLString(renderElement("astro-island", island, false)));
265
293
  }
266
- yield { type: "directive", hydration, result };
267
- yield markHTMLString(renderElement("astro-island", island, false));
268
- }
269
- return renderAll();
294
+ };
270
295
  }
271
296
  function sanitizeElementName(tag) {
272
297
  const unsafe = /[&<>'"\s]+/g;
@@ -276,42 +301,94 @@ function sanitizeElementName(tag) {
276
301
  }
277
302
  async function renderFragmentComponent(result, slots = {}) {
278
303
  const children = await renderSlotToString(result, slots == null ? void 0 : slots.default);
279
- if (children == null) {
280
- return children;
281
- }
282
- return markHTMLString(children);
304
+ return {
305
+ render(destination) {
306
+ if (children == null)
307
+ return;
308
+ destination.write(children);
309
+ }
310
+ };
283
311
  }
284
312
  async function renderHTMLComponent(result, Component, _props, slots = {}) {
285
313
  const { slotInstructions, children } = await renderSlots(result, slots);
286
314
  const html = Component({ slots: children });
287
- const hydrationHtml = slotInstructions ? slotInstructions.map((instr) => stringifyChunk(result, instr)).join("") : "";
288
- return markHTMLString(hydrationHtml + html);
315
+ const hydrationHtml = slotInstructions ? slotInstructions.map((instr) => chunkToString(result, instr)).join("") : "";
316
+ return {
317
+ render(destination) {
318
+ destination.write(markHTMLString(hydrationHtml + html));
319
+ }
320
+ };
321
+ }
322
+ async function renderAstroComponent(result, displayName, Component, props, slots = {}) {
323
+ const instance = await createAstroComponentInstance(result, displayName, Component, props, slots);
324
+ const chunks = [];
325
+ const temporaryDestination = {
326
+ write: (chunk) => chunks.push(chunk)
327
+ };
328
+ await instance.render(temporaryDestination);
329
+ return {
330
+ render(destination) {
331
+ for (const chunk of chunks) {
332
+ destination.write(chunk);
333
+ }
334
+ }
335
+ };
289
336
  }
290
- function renderComponent(result, displayName, Component, props, slots = {}) {
337
+ async function renderComponent(result, displayName, Component, props, slots = {}) {
291
338
  if (isPromise(Component)) {
292
- return Promise.resolve(Component).then((Unwrapped) => {
293
- return renderComponent(result, displayName, Unwrapped, props, slots);
294
- });
339
+ Component = await Component;
295
340
  }
296
341
  if (isFragmentComponent(Component)) {
297
- return renderFragmentComponent(result, slots);
342
+ return await renderFragmentComponent(result, slots);
298
343
  }
299
344
  if (isHTMLComponent(Component)) {
300
- return renderHTMLComponent(result, Component, props, slots);
345
+ return await renderHTMLComponent(result, Component, props, slots);
301
346
  }
302
347
  if (isAstroComponentFactory(Component)) {
303
- return createAstroComponentInstance(result, displayName, Component, props, slots);
348
+ return await renderAstroComponent(result, displayName, Component, props, slots);
304
349
  }
305
- return renderFrameworkComponent(result, displayName, Component, props, slots);
350
+ return await renderFrameworkComponent(result, displayName, Component, props, slots);
306
351
  }
307
- function renderComponentToIterable(result, displayName, Component, props, slots = {}) {
308
- const renderResult = renderComponent(result, displayName, Component, props, slots);
309
- if (isAstroComponentInstance(renderResult)) {
310
- return renderResult.render();
352
+ async function renderComponentToString(result, displayName, Component, props, slots = {}, isPage = false, route) {
353
+ let str = "";
354
+ let renderedFirstPageChunk = false;
355
+ let head = "";
356
+ if (nonAstroPageNeedsHeadInjection(Component)) {
357
+ for (const headChunk of maybeRenderHead()) {
358
+ head += chunkToString(result, headChunk);
359
+ }
311
360
  }
312
- return renderResult;
361
+ try {
362
+ const destination = {
363
+ write(chunk) {
364
+ if (isPage && !renderedFirstPageChunk) {
365
+ renderedFirstPageChunk = true;
366
+ if (!/<!doctype html/i.test(String(chunk))) {
367
+ const doctype = result.compressHTML ? "<!DOCTYPE html>" : "<!DOCTYPE html>\n";
368
+ str += doctype + head;
369
+ }
370
+ }
371
+ if (chunk instanceof Response)
372
+ return;
373
+ str += chunkToString(result, chunk);
374
+ }
375
+ };
376
+ const renderInstance = await renderComponent(result, displayName, Component, props, slots);
377
+ await renderInstance.render(destination);
378
+ } catch (e) {
379
+ if (AstroError.is(e) && !e.loc) {
380
+ e.setLocation({
381
+ file: route == null ? void 0 : route.component
382
+ });
383
+ }
384
+ throw e;
385
+ }
386
+ return str;
387
+ }
388
+ function nonAstroPageNeedsHeadInjection(pageComponent) {
389
+ return !!(pageComponent == null ? void 0 : pageComponent[needsHeadRenderingSymbol]);
313
390
  }
314
391
  export {
315
392
  renderComponent,
316
- renderComponentToIterable
393
+ renderComponentToString
317
394
  };
@@ -1,3 +1,3 @@
1
1
  import type { SSRResult } from '../../../@types/astro';
2
2
  export declare function componentIsHTMLElement(Component: unknown): boolean;
3
- export declare function renderHTMLElement(result: SSRResult, constructor: typeof HTMLElement, props: any, slots: any): Promise<any>;
3
+ export declare function renderHTMLElement(result: SSRResult, constructor: typeof HTMLElement, props: any, slots: any): Promise<string>;
@@ -1,7 +1,7 @@
1
1
  export type { AstroComponentFactory, AstroComponentInstance } from './astro/index';
2
- export { createHeadAndContent, renderAstroTemplateResult, renderTemplate, renderToString, } from './astro/index.js';
3
- export { Fragment, Renderer, stringifyChunk } from './common.js';
4
- export { renderComponent, renderComponentToIterable } from './component.js';
2
+ export { createHeadAndContent, renderTemplate, renderToString } from './astro/index.js';
3
+ export { Fragment, Renderer, chunkToByteArray, chunkToString } from './common.js';
4
+ export { renderComponent, renderComponentToString } from './component.js';
5
5
  export { renderHTMLElement } from './dom.js';
6
6
  export { maybeRenderHead, renderHead } from './head.js';
7
7
  export { renderPage } from './page.js';
@@ -1,11 +1,6 @@
1
- import {
2
- createHeadAndContent,
3
- renderAstroTemplateResult,
4
- renderTemplate,
5
- renderToString
6
- } from "./astro/index.js";
7
- import { Fragment, Renderer, stringifyChunk } from "./common.js";
8
- import { renderComponent, renderComponentToIterable } from "./component.js";
1
+ import { createHeadAndContent, renderTemplate, renderToString } from "./astro/index.js";
2
+ import { Fragment, Renderer, chunkToByteArray, chunkToString } from "./common.js";
3
+ import { renderComponent, renderComponentToString } from "./component.js";
9
4
  import { renderHTMLElement } from "./dom.js";
10
5
  import { maybeRenderHead, renderHead } from "./head.js";
11
6
  import { renderPage } from "./page.js";
@@ -16,12 +11,13 @@ export {
16
11
  Fragment,
17
12
  Renderer,
18
13
  addAttribute,
14
+ chunkToByteArray,
15
+ chunkToString,
19
16
  createHeadAndContent,
20
17
  defineScriptVars,
21
18
  maybeRenderHead,
22
- renderAstroTemplateResult,
23
19
  renderComponent,
24
- renderComponentToIterable,
20
+ renderComponentToString,
25
21
  renderHTMLElement,
26
22
  renderHead,
27
23
  renderPage,
@@ -31,6 +27,5 @@ export {
31
27
  renderTemplate,
32
28
  renderToString,
33
29
  renderUniqueStylesheet,
34
- stringifyChunk,
35
30
  voidElementNames
36
31
  };
@@ -1,9 +1,4 @@
1
1
  import type { RouteData, SSRResult } from '../../../@types/astro';
2
+ import { type NonAstroPageComponent } from './component.js';
2
3
  import type { AstroComponentFactory } from './index';
3
- declare const needsHeadRenderingSymbol: unique symbol;
4
- type NonAstroPageComponent = {
5
- name: string;
6
- [needsHeadRenderingSymbol]: boolean;
7
- };
8
- export declare function renderPage(result: SSRResult, componentFactory: AstroComponentFactory | NonAstroPageComponent, props: any, children: any, streaming: boolean, route?: RouteData | undefined): Promise<Response>;
9
- export {};
4
+ export declare function renderPage(result: SSRResult, componentFactory: AstroComponentFactory | NonAstroPageComponent, props: any, children: any, streaming: boolean, route?: RouteData): Promise<Response>;
@@ -1,72 +1,23 @@
1
- import { AstroError } from "../../../core/errors/index.js";
2
- import { isHTMLString } from "../escape.js";
1
+ import { renderComponentToString } from "./component.js";
3
2
  import { createResponse } from "../response.js";
4
- import { isAstroComponentFactory, isAstroComponentInstance } from "./astro/index.js";
3
+ import { isAstroComponentFactory } from "./astro/index.js";
5
4
  import { renderToReadableStream, renderToString } from "./astro/render.js";
6
- import { HTMLParts, encoder } from "./common.js";
7
- import { renderComponent } from "./component.js";
8
- import { maybeRenderHead } from "./head.js";
9
- const needsHeadRenderingSymbol = Symbol.for("astro.needsHeadRendering");
10
- function nonAstroPageNeedsHeadInjection(pageComponent) {
11
- return needsHeadRenderingSymbol in pageComponent && !!pageComponent[needsHeadRenderingSymbol];
12
- }
13
- async function iterableToHTMLBytes(result, iterable, onDocTypeInjection) {
14
- const parts = new HTMLParts();
15
- let i = 0;
16
- for await (const chunk of iterable) {
17
- if (isHTMLString(chunk)) {
18
- if (i === 0) {
19
- i++;
20
- if (!/<!doctype html/i.test(String(chunk))) {
21
- parts.append(`${result.compressHTML ? "<!DOCTYPE html>" : "<!DOCTYPE html>\n"}`, result);
22
- if (onDocTypeInjection) {
23
- await onDocTypeInjection(parts);
24
- }
25
- }
26
- }
27
- }
28
- parts.append(chunk, result);
29
- }
30
- return parts.toArrayBuffer();
31
- }
5
+ import { encoder } from "./common.js";
32
6
  async function renderPage(result, componentFactory, props, children, streaming, route) {
33
7
  var _a, _b;
34
8
  if (!isAstroComponentFactory(componentFactory)) {
35
9
  result._metadata.headInTree = ((_a = result.componentMetadata.get(componentFactory.moduleId)) == null ? void 0 : _a.containsHead) ?? false;
36
10
  const pageProps = { ...props ?? {}, "server:root": true };
37
- let output;
38
- let head = "";
39
- try {
40
- if (nonAstroPageNeedsHeadInjection(componentFactory)) {
41
- const parts = new HTMLParts();
42
- for await (const chunk of maybeRenderHead()) {
43
- parts.append(chunk, result);
44
- }
45
- head = parts.toString();
46
- }
47
- const renderResult = await renderComponent(
48
- result,
49
- componentFactory.name,
50
- componentFactory,
51
- pageProps,
52
- null
53
- );
54
- if (isAstroComponentInstance(renderResult)) {
55
- output = renderResult.render();
56
- } else {
57
- output = renderResult;
58
- }
59
- } catch (e) {
60
- if (AstroError.is(e) && !e.loc) {
61
- e.setLocation({
62
- file: route == null ? void 0 : route.component
63
- });
64
- }
65
- throw e;
66
- }
67
- const bytes = await iterableToHTMLBytes(result, output, async (parts) => {
68
- parts.append(head, result);
69
- });
11
+ const str = await renderComponentToString(
12
+ result,
13
+ componentFactory.name,
14
+ componentFactory,
15
+ pageProps,
16
+ null,
17
+ true,
18
+ route
19
+ );
20
+ const bytes = encoder.encode(str);
70
21
  return new Response(bytes, {
71
22
  headers: new Headers([
72
23
  ["Content-Type", "text/html; charset=utf-8"],
@@ -2,6 +2,7 @@ import type { SSRResult } from '../../../@types/astro.js';
2
2
  import type { renderTemplate } from './astro/render-template.js';
3
3
  import type { RenderInstruction } from './types.js';
4
4
  import { HTMLString } from '../escape.js';
5
+ import { type RenderInstance } from './common.js';
5
6
  type RenderTemplateResult = ReturnType<typeof renderTemplate>;
6
7
  export type ComponentSlots = Record<string, ComponentSlotValue>;
7
8
  export type ComponentSlotValue = (result: SSRResult) => RenderTemplateResult | Promise<RenderTemplateResult>;
@@ -12,7 +13,7 @@ export declare class SlotString extends HTMLString {
12
13
  constructor(content: string, instructions: null | RenderInstruction[]);
13
14
  }
14
15
  export declare function isSlotString(str: string): str is any;
15
- export declare function renderSlot(result: SSRResult, slotted: ComponentSlotValue | RenderTemplateResult, fallback?: ComponentSlotValue | RenderTemplateResult): AsyncGenerator<any, void, undefined>;
16
+ export declare function renderSlot(result: SSRResult, slotted: ComponentSlotValue | RenderTemplateResult, fallback?: ComponentSlotValue | RenderTemplateResult): RenderInstance;
16
17
  export declare function renderSlotToString(result: SSRResult, slotted: ComponentSlotValue | RenderTemplateResult, fallback?: ComponentSlotValue | RenderTemplateResult): Promise<string>;
17
18
  interface RenderSlotsResult {
18
19
  slotInstructions: null | RenderInstruction[];
@@ -1,5 +1,6 @@
1
1
  import { HTMLString, markHTMLString } from "../escape.js";
2
2
  import { renderChild } from "./any.js";
3
+ import { chunkToString } from "./common.js";
3
4
  const slotString = Symbol.for("astro:slot-string");
4
5
  class SlotString extends HTMLString {
5
6
  constructor(content, instructions) {
@@ -12,29 +13,35 @@ slotString;
12
13
  function isSlotString(str) {
13
14
  return !!str[slotString];
14
15
  }
15
- async function* renderSlot(result, slotted, fallback) {
16
- if (slotted) {
17
- let iterator = renderChild(typeof slotted === "function" ? slotted(result) : slotted);
18
- yield* iterator;
19
- }
20
- if (fallback && !slotted) {
21
- yield* renderSlot(result, fallback);
16
+ function renderSlot(result, slotted, fallback) {
17
+ if (!slotted && fallback) {
18
+ return renderSlot(result, fallback);
22
19
  }
20
+ return {
21
+ async render(destination) {
22
+ await renderChild(destination, typeof slotted === "function" ? slotted(result) : slotted);
23
+ }
24
+ };
23
25
  }
24
26
  async function renderSlotToString(result, slotted, fallback) {
25
27
  let content = "";
26
28
  let instructions = null;
27
- let iterator = renderSlot(result, slotted, fallback);
28
- for await (const chunk of iterator) {
29
- if (typeof chunk.type === "string") {
30
- if (instructions === null) {
31
- instructions = [];
29
+ const temporaryDestination = {
30
+ write(chunk) {
31
+ if (chunk instanceof Response)
32
+ return;
33
+ if (typeof chunk === "object" && "type" in chunk && typeof chunk.type === "string") {
34
+ if (instructions === null) {
35
+ instructions = [];
36
+ }
37
+ instructions.push(chunk);
38
+ } else {
39
+ content += chunkToString(result, chunk);
32
40
  }
33
- instructions.push(chunk);
34
- } else {
35
- content += chunk;
36
41
  }
37
- }
42
+ };
43
+ const renderInstance = renderSlot(result, slotted, fallback);
44
+ await renderInstance.render(temporaryDestination);
38
45
  return markHTMLString(new SlotString(content, instructions));
39
46
  }
40
47
  async function renderSlots(result, slots = {}) {
@@ -6,21 +6,3 @@ export declare function formatList(values: string[]): string;
6
6
  export declare function addAttribute(value: any, key: string, shouldEscape?: boolean): any;
7
7
  export declare function internalSpreadAttributes(values: Record<any, any>, shouldEscape?: boolean): any;
8
8
  export declare function renderElement(name: string, { props: _props, children }: SSRElement, shouldEscape?: boolean): string;
9
- /**
10
- * This will take an array of async iterables and start buffering them eagerly.
11
- * To avoid useless buffering, it will only start buffering the next tick, so the
12
- * first sync iterables won't be buffered.
13
- */
14
- export declare function bufferIterators<T>(iterators: AsyncIterable<T>[]): AsyncIterable<T>[];
15
- export declare class EagerAsyncIterableIterator {
16
- #private;
17
- constructor(iterable: AsyncIterable<any>);
18
- /**
19
- * Starts to eagerly fetch the inner iterator and cache the results.
20
- * Note: This might not be called after next() has been called once, e.g. the iterator is started
21
- */
22
- buffer(): Promise<void>;
23
- next(): Promise<IteratorResult<any, any>>;
24
- isStarted(): boolean;
25
- [Symbol.asyncIterator](): this;
26
- }
@@ -103,109 +103,8 @@ function renderElement(name, { props: _props, children = "" }, shouldEscape = tr
103
103
  }
104
104
  return `<${name}${internalSpreadAttributes(props, shouldEscape)}>${children}</${name}>`;
105
105
  }
106
- const iteratorQueue = [];
107
- function queueIteratorBuffers(iterators) {
108
- if (iteratorQueue.length === 0) {
109
- setTimeout(() => {
110
- iteratorQueue.forEach((its) => its.forEach((it) => !it.isStarted() && it.buffer()));
111
- iteratorQueue.length = 0;
112
- });
113
- }
114
- iteratorQueue.push(iterators);
115
- }
116
- function bufferIterators(iterators) {
117
- const eagerIterators = iterators.map((it) => new EagerAsyncIterableIterator(it));
118
- queueIteratorBuffers(eagerIterators);
119
- return eagerIterators;
120
- }
121
- class EagerAsyncIterableIterator {
122
- #iterable;
123
- #queue = new Queue();
124
- #error = void 0;
125
- #next;
126
- /**
127
- * Whether the proxy is running in buffering or pass-through mode
128
- */
129
- #isBuffering = false;
130
- #gen = void 0;
131
- #isStarted = false;
132
- constructor(iterable) {
133
- this.#iterable = iterable;
134
- }
135
- /**
136
- * Starts to eagerly fetch the inner iterator and cache the results.
137
- * Note: This might not be called after next() has been called once, e.g. the iterator is started
138
- */
139
- async buffer() {
140
- if (this.#gen) {
141
- throw new Error("Cannot not switch from non-buffer to buffer mode");
142
- }
143
- this.#isBuffering = true;
144
- this.#isStarted = true;
145
- this.#gen = this.#iterable[Symbol.asyncIterator]();
146
- let value = void 0;
147
- do {
148
- this.#next = this.#gen.next();
149
- try {
150
- value = await this.#next;
151
- this.#queue.push(value);
152
- } catch (e) {
153
- this.#error = e;
154
- }
155
- } while (value && !value.done);
156
- }
157
- async next() {
158
- if (this.#error) {
159
- throw this.#error;
160
- }
161
- if (!this.#isBuffering) {
162
- if (!this.#gen) {
163
- this.#isStarted = true;
164
- this.#gen = this.#iterable[Symbol.asyncIterator]();
165
- }
166
- return await this.#gen.next();
167
- }
168
- if (!this.#queue.isEmpty()) {
169
- return this.#queue.shift();
170
- }
171
- await this.#next;
172
- return this.#queue.shift();
173
- }
174
- isStarted() {
175
- return this.#isStarted;
176
- }
177
- [Symbol.asyncIterator]() {
178
- return this;
179
- }
180
- }
181
- class Queue {
182
- constructor() {
183
- this.head = void 0;
184
- this.tail = void 0;
185
- }
186
- push(item) {
187
- if (this.head === void 0) {
188
- this.head = { item };
189
- this.tail = this.head;
190
- } else {
191
- this.tail.next = { item };
192
- this.tail = this.tail.next;
193
- }
194
- }
195
- isEmpty() {
196
- return this.head === void 0;
197
- }
198
- shift() {
199
- var _a, _b;
200
- const val = (_a = this.head) == null ? void 0 : _a.item;
201
- this.head = (_b = this.head) == null ? void 0 : _b.next;
202
- return val;
203
- }
204
- }
205
106
  export {
206
- EagerAsyncIterableIterator,
207
107
  addAttribute,
208
- bufferIterators,
209
108
  defineScriptVars,
210
109
  formatList,
211
110
  internalSpreadAttributes,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "astro",
3
- "version": "2.9.2",
3
+ "version": "2.9.3",
4
4
  "description": "Astro is a modern site builder with web best practices, performance, and DX front-of-mind.",
5
5
  "type": "module",
6
6
  "author": "withastro",