0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-16 21:46:22 -05:00

[ci] format

This commit is contained in:
Matthew Phillips 2024-02-14 15:15:02 +00:00 committed by astrobot-houston
parent d469bebd7b
commit e34eeb146e
4 changed files with 84 additions and 75 deletions

View file

@ -95,8 +95,8 @@ ${Array.from({ length: 1000 })
}; };
export const renderPages = []; export const renderPages = [];
for(const file of Object.keys(renderFiles)) { for (const file of Object.keys(renderFiles)) {
if(file.startsWith('pages/')) { if (file.startsWith('pages/')) {
renderPages.push(file.replace('pages/', '')); renderPages.push(file.replace('pages/', ''));
} }
} }

View file

@ -177,19 +177,18 @@ export async function renderToAsyncIterable(
isPage = false, isPage = false,
route?: RouteData route?: RouteData
): Promise<AsyncIterable<Uint8Array> | Response> { ): Promise<AsyncIterable<Uint8Array> | Response> {
const templateResult = await callComponentAsTemplateResultOrResponse( const templateResult = await callComponentAsTemplateResultOrResponse(
result, result,
componentFactory, componentFactory,
props, props,
children, children,
route route
); );
if (templateResult instanceof Response) if (templateResult instanceof Response) return templateResult;
return templateResult; let renderedFirstPageChunk = false;
let renderedFirstPageChunk = false; if (isPage) {
if (isPage) { await bufferHeadContent(result);
await bufferHeadContent(result); }
}
// This implements the iterator protocol: // This implements the iterator protocol:
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#the_async_iterator_and_async_iterable_protocols
@ -197,90 +196,92 @@ export async function renderToAsyncIterable(
// The `buffer` array acts like a buffer. During render the `destination` pushes // The `buffer` array acts like a buffer. During render the `destination` pushes
// chunks of Uint8Arrays into the buffer. The response calls `next()` and we combine // chunks of Uint8Arrays into the buffer. The response calls `next()` and we combine
// all of the chunks into one Uint8Array and then empty it. // all of the chunks into one Uint8Array and then empty it.
let error: Error | null = null; let error: Error | null = null;
// The `next` is an object `{ promise, resolve, reject }` that we use to wait // The `next` is an object `{ promise, resolve, reject }` that we use to wait
// for chunks to be pushed into the buffer. // for chunks to be pushed into the buffer.
let next = promiseWithResolvers<void>(); let next = promiseWithResolvers<void>();
const buffer: Uint8Array[] = []; // []Uint8Array const buffer: Uint8Array[] = []; // []Uint8Array
const iterator = { const iterator = {
async next() { async next() {
await next.promise; await next.promise;
// If an error occurs during rendering, throw the error as we cannot proceed. // If an error occurs during rendering, throw the error as we cannot proceed.
if(error) { if (error) {
throw error; throw error;
} }
// Get the total length of all arrays. // Get the total length of all arrays.
let length = 0; let length = 0;
for(let i = 0, len = buffer.length; i < len; i++) { for (let i = 0, len = buffer.length; i < len; i++) {
length += buffer[i].length; length += buffer[i].length;
} }
// Create a new array with total length and merge all source arrays. // Create a new array with total length and merge all source arrays.
let mergedArray = new Uint8Array(length); let mergedArray = new Uint8Array(length);
let offset = 0; let offset = 0;
for(let i = 0, len = buffer.length; i < len; i++) { for (let i = 0, len = buffer.length; i < len; i++) {
const item = buffer[i]; const item = buffer[i];
mergedArray.set(item, offset); mergedArray.set(item, offset);
offset += item.length; offset += item.length;
} }
// Empty the array. We do this so that we can reuse the same array. // Empty the array. We do this so that we can reuse the same array.
buffer.length = 0; buffer.length = 0;
const returnValue = { const returnValue = {
// The iterator is done if there are no chunks to return. // The iterator is done if there are no chunks to return.
done: length === 0, done: length === 0,
value: mergedArray value: mergedArray,
}; };
return returnValue; return returnValue;
} },
}; };
const destination: RenderDestination = { const destination: RenderDestination = {
write(chunk) { write(chunk) {
if (isPage && !renderedFirstPageChunk) { if (isPage && !renderedFirstPageChunk) {
renderedFirstPageChunk = true; renderedFirstPageChunk = true;
if (!result.partial && !DOCTYPE_EXP.test(String(chunk))) { if (!result.partial && !DOCTYPE_EXP.test(String(chunk))) {
const doctype = result.compressHTML ? "<!DOCTYPE html>" : "<!DOCTYPE html>\n"; const doctype = result.compressHTML ? '<!DOCTYPE html>' : '<!DOCTYPE html>\n';
buffer.push(encoder.encode(doctype)); buffer.push(encoder.encode(doctype));
} }
} }
if (chunk instanceof Response) { if (chunk instanceof Response) {
throw new AstroError(AstroErrorData.ResponseSentError); throw new AstroError(AstroErrorData.ResponseSentError);
} }
const bytes = chunkToByteArray(result, chunk); const bytes = chunkToByteArray(result, chunk);
// It might be possible that we rendered a chunk with no content, in which // It might be possible that we rendered a chunk with no content, in which
// case we don't want to resolve the promise. // case we don't want to resolve the promise.
if(bytes.length > 0) { if (bytes.length > 0) {
// Push the chunks into the buffer and resolve the promise so that next() // Push the chunks into the buffer and resolve the promise so that next()
// will run. // will run.
buffer.push(bytes); buffer.push(bytes);
next.resolve(); next.resolve();
next = promiseWithResolvers<void>(); next = promiseWithResolvers<void>();
} }
} },
}; };
const renderPromise = templateResult.render(destination); const renderPromise = templateResult.render(destination);
renderPromise.then(() => { renderPromise
// Once rendering is complete, calling resolve() allows the iterator to finish running. .then(() => {
next.resolve(); // Once rendering is complete, calling resolve() allows the iterator to finish running.
}).catch(err => { next.resolve();
// If an error occurs, save it in the scope so that we throw it when next() is called. })
error = err; .catch((err) => {
next.resolve(); // If an error occurs, save it in the scope so that we throw it when next() is called.
}); error = err;
next.resolve();
});
// This is the Iterator protocol, an object with a `Symbol.asyncIterator` // This is the Iterator protocol, an object with a `Symbol.asyncIterator`
// function that returns an object like `{ next(): Promise<{ done: boolean; value: any }> }` // function that returns an object like `{ next(): Promise<{ done: boolean; value: any }> }`
return { return {
[Symbol.asyncIterator]() { [Symbol.asyncIterator]() {
return iterator; return iterator;
} },
}; };
} }

View file

@ -48,8 +48,15 @@ export async function renderPage(
let body: BodyInit | Response; let body: BodyInit | Response;
if (streaming) { if (streaming) {
if(isNode) { if (isNode) {
const nodeBody = await renderToAsyncIterable(result, componentFactory, props, children, true, route); const nodeBody = await renderToAsyncIterable(
result,
componentFactory,
props,
children,
true,
route
);
// Node.js allows passing in an AsyncIterable to the Response constructor. // Node.js allows passing in an AsyncIterable to the Response constructor.
// This is non-standard so using `any` here to preserve types everywhere else. // This is non-standard so using `any` here to preserve types everywhere else.
body = nodeBody as any; body = nodeBody as any;

View file

@ -197,14 +197,15 @@ export function renderToBufferDestination(bufferRenderFunction: RenderFunction):
}; };
} }
export const isNode = typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]'; export const isNode =
typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]';
// We can get rid of this when Promise.withResolvers() is ready // We can get rid of this when Promise.withResolvers() is ready
export type PromiseWithResolvers<T> = { export type PromiseWithResolvers<T> = {
promise: Promise<T> promise: Promise<T>;
resolve: (value: T) => void; resolve: (value: T) => void;
reject: (reason?: any) => void; reject: (reason?: any) => void;
} };
// This is an implementation of Promise.withResolvers(), which we can't yet rely on. // This is an implementation of Promise.withResolvers(), which we can't yet rely on.
// We can remove this once the native function is available in Node.js // We can remove this once the native function is available in Node.js
@ -217,6 +218,6 @@ export function promiseWithResolvers<T = any>(): PromiseWithResolvers<T> {
return { return {
promise, promise,
resolve, resolve,
reject reject,
}; };
} }