diff --git a/packages/astro/src/core/render/core.ts b/packages/astro/src/core/render/core.ts index c9c46fda1..2487a79e4 100644 --- a/packages/astro/src/core/render/core.ts +++ b/packages/astro/src/core/render/core.ts @@ -83,9 +83,7 @@ export interface RenderOptions { request: Request; } -export async function render( - opts: RenderOptions -): Promise { +export async function render(opts: RenderOptions): Promise { const { links, styles, diff --git a/packages/astro/src/runtime/server/index.ts b/packages/astro/src/runtime/server/index.ts index 92cb5b4c8..c55328c16 100644 --- a/packages/astro/src/runtime/server/index.ts +++ b/packages/astro/src/runtime/server/index.ts @@ -41,19 +41,19 @@ const svgEnumAttributes = /^(autoReverse|externalResourcesRequired|focusable|pre // INVESTIGATE: Can we have more specific types both for the argument and output? // If these are intentional, add comments that these are intention and why. // Or maybe type UserValue = any; ? -async function * _render(child: any): AsyncIterable { +async function* _render(child: any): AsyncIterable { child = await child; if (child instanceof HTMLString) { yield child; } else if (Array.isArray(child)) { - for(const value of child) { + for (const value of child) { yield markHTMLString(await _render(value)); } } else if (typeof child === 'function') { // Special: If a child is a function, call it automatically. // This lets you do {() => ...} without the extra boilerplate // of wrapping it in a function and calling it. - yield * _render(child()); + yield* _render(child()); } else if (typeof child === 'string') { yield markHTMLString(escapeHTML(child)); } else if (!child && child !== 0) { @@ -65,9 +65,9 @@ async function * _render(child: any): AsyncIterable { child instanceof AstroComponent || Object.prototype.toString.call(child) === '[object AstroComponent]' ) { - yield * renderAstroComponent(child); - } else if(typeof child === 'object' && Symbol.asyncIterator in child) { - yield * child; + yield* renderAstroComponent(child); + } else if (typeof child === 'object' && Symbol.asyncIterator in child) { + yield* child; } else { yield child; } @@ -96,7 +96,7 @@ export class AstroComponent { const expression = expressions[i]; yield markHTMLString(html); - yield * _render(expression); + yield* _render(expression); } } } @@ -129,7 +129,7 @@ export async function renderSlot(_result: any, slotted: string, fallback?: any): if (slotted) { let iterator = _render(slotted); let content = ''; - for await(const chunk of iterator) { + for await (const chunk of iterator) { content += chunk; } return markHTMLString(content); @@ -334,7 +334,7 @@ If you're still stuck, please open an issue on GitHub or join us at https://astr )}` ); html = ''; - for await(const chunk of iterable) { + for await (const chunk of iterable) { html += chunk; } } @@ -617,7 +617,7 @@ export async function renderToString( } let html = ''; - for await(const chunk of renderAstroComponent(Component)) { + for await (const chunk of renderAstroComponent(Component)) { html += chunk; } return html; @@ -632,7 +632,9 @@ export async function renderToIterable( const Component = await componentFactory(result, props, children); if (!isAstroComponent(Component)) { - console.warn(`Returning a Response is only supported inside of page components. Consider refactoring this logic into something like a function that can be used in the page.`); + console.warn( + `Returning a Response is only supported inside of page components. Consider refactoring this logic into something like a function that can be used in the page.` + ); const response: Response = Component; throw response; } @@ -656,9 +658,9 @@ export async function renderPage( start(controller) { async function read() { let i = 0; - for await(const chunk of iterable) { + for await (const chunk of iterable) { let html = chunk.toString(); - if(i === 0) { + if (i === 0) { if (!/\n')); } @@ -669,7 +671,7 @@ export async function renderPage( controller.close(); } read(); - } + }, }); let init = result.response; let response = createResponse(stream, init); @@ -716,10 +718,12 @@ export function maybeRenderHead(result: SSRResult): string | Promise { return renderHead(result); } -export async function * renderAstroComponent(component: InstanceType): AsyncIterable { +export async function* renderAstroComponent( + component: InstanceType +): AsyncIterable { for await (const value of component) { if (value || value === 0) { - for await(const chunk of _render(value)) { + for await (const chunk of _render(value)) { yield markHTMLString(chunk); } } diff --git a/packages/astro/src/runtime/server/response.ts b/packages/astro/src/runtime/server/response.ts index d0bf8fefd..084ea7436 100644 --- a/packages/astro/src/runtime/server/response.ts +++ b/packages/astro/src/runtime/server/response.ts @@ -1,5 +1,5 @@ - -const isNodeJS = typeof process === 'object' && Object.prototype.toString.call(process) === '[object process]'; +const isNodeJS = + typeof process === 'object' && Object.prototype.toString.call(process) === '[object process]'; let StreamingCompatibleResponse: typeof Response | undefined; @@ -13,59 +13,61 @@ function createResponseClass() { this.#isStream = isStream; this.#body = body; } - + get body() { return this.#body; } - + async text(): Promise { - if(this.#isStream && isNodeJS) { - let decoder = new TextDecoder(); - let body = this.#body as ReadableStream; - let reader = body.getReader(); - let buffer: number[] = []; - while(true) { - let r = await reader.read(); - if(r.value) { - buffer.push(...r.value); - } - if(r.done) { - break; - } + if (this.#isStream && isNodeJS) { + let decoder = new TextDecoder(); + let body = this.#body as ReadableStream; + let reader = body.getReader(); + let buffer: number[] = []; + while (true) { + let r = await reader.read(); + if (r.value) { + buffer.push(...r.value); + } + if (r.done) { + break; } - return decoder.decode(Uint8Array.from(buffer)); } - return super.text(); + return decoder.decode(Uint8Array.from(buffer)); + } + return super.text(); } - + async arrayBuffer(): Promise { - if(this.#isStream && isNodeJS) { - let body = this.#body as ReadableStream; - let reader = body.getReader(); - let chunks: number[] = []; - while(true) { - let r = await reader.read(); - if(r.value) { - chunks.push(...r.value); - } - if(r.done) { - break; - } + if (this.#isStream && isNodeJS) { + let body = this.#body as ReadableStream; + let reader = body.getReader(); + let chunks: number[] = []; + while (true) { + let r = await reader.read(); + if (r.value) { + chunks.push(...r.value); + } + if (r.done) { + break; } - return Uint8Array.from(chunks); } - return super.arrayBuffer(); + return Uint8Array.from(chunks); + } + return super.arrayBuffer(); } - } - + }; + return StreamingCompatibleResponse; } type CreateResponseFn = (body?: BodyInit | null, init?: ResponseInit) => Response; -export const createResponse: CreateResponseFn = isNodeJS ? (body, init) => { - if(typeof StreamingCompatibleResponse === 'undefined') { - return new (createResponseClass())(body, init); - } - return new StreamingCompatibleResponse(body, init); -} : (body, init) => new Response(body, init); +export const createResponse: CreateResponseFn = isNodeJS + ? (body, init) => { + if (typeof StreamingCompatibleResponse === 'undefined') { + return new (createResponseClass())(body, init); + } + return new StreamingCompatibleResponse(body, init); + } + : (body, init) => new Response(body, init); diff --git a/packages/astro/src/vite-plugin-astro-server/index.ts b/packages/astro/src/vite-plugin-astro-server/index.ts index a26e66a98..bf1a57a51 100644 --- a/packages/astro/src/vite-plugin-astro-server/index.ts +++ b/packages/astro/src/vite-plugin-astro-server/index.ts @@ -76,9 +76,9 @@ async function writeWebResponse(res: http.ServerResponse, webResponse: Response) res.writeHead(status, _headers); if (body) { - if(Symbol.for('astro.responseBody') in webResponse) { + if (Symbol.for('astro.responseBody') in webResponse) { let stream = (webResponse as any)[Symbol.for('astro.responseBody')]; - for await(const chunk of stream) { + for await (const chunk of stream) { res.write(chunk.toString()); } } else if (body instanceof Readable) { @@ -98,10 +98,7 @@ async function writeWebResponse(res: http.ServerResponse, webResponse: Response) res.end(); } -async function writeSSRResult( - webResponse: Response, - res: http.ServerResponse -) { +async function writeSSRResult(webResponse: Response, res: http.ServerResponse) { return writeWebResponse(res, webResponse); } diff --git a/packages/astro/test/streaming.test.js b/packages/astro/test/streaming.test.js index 489e2ab19..7d28387d3 100644 --- a/packages/astro/test/streaming.test.js +++ b/packages/astro/test/streaming.test.js @@ -3,7 +3,6 @@ import { expect } from 'chai'; import testAdapter from './test-adapter.js'; import * as cheerio from 'cheerio'; - describe('Streaming', () => { if (isWindows) return; @@ -35,7 +34,7 @@ describe('Streaming', () => { it('Body is chunked', async () => { let res = await fixture.fetch('/'); let chunks = []; - for await(const bytes of res.body) { + for await (const bytes of res.body) { let chunk = bytes.toString('utf-8'); chunks.push(chunk); } @@ -64,7 +63,7 @@ describe('Streaming', () => { const response = await app.render(request); let chunks = []; let decoder = new TextDecoder(); - for await(const bytes of response.body) { + for await (const bytes of response.body) { let chunk = decoder.decode(bytes); chunks.push(chunk); }