Skip to content

Commit

Permalink
Make slots lazy
Browse files Browse the repository at this point in the history
  • Loading branch information
bluwy committed Apr 18, 2024
1 parent f7d0840 commit 92470e8
Showing 1 changed file with 28 additions and 10 deletions.
38 changes: 28 additions & 10 deletions packages/astro/src/core/render-context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,13 @@ export class RenderContext {
return result;
}

#astroPagePartial?: Omit<AstroGlobal, 'props' | 'self' | 'slots'>;
/**
* The Astro global is sourced in 3 different phases:
* - **Static**: `.generator` and `.glob` is printed by the compiler, instantiated once per process per astro file
* - **Page-level**: `.request`, `.cookies`, `.locals` etc. These remain the same for the duration of the request.
* - **Component-level**: `.props`, `.slots`, and `.self` are unique to each _use_ of each component.
*
*
* The page level partial is used as the prototype of the user-visible `Astro` global object, which is instantiated once per use of a component.
*/
createAstro(
Expand All @@ -256,24 +257,41 @@ export class RenderContext {
props: Record<string, any>,
slotValues: Record<string, any> | null
): AstroGlobal {
const slots = new Slots(result, slotValues, this.pipeline.logger) as unknown as AstroGlobal['slots'];
// Create page partial with static partial so they can be cached together.
const astroPagePartial = (this.#astroPagePartial ??= this.createAstroPagePartial(
result,
astroStaticPartial
));
// Create component-level partials. `Astro.self` is added by the compiler.
const astroComponentPartial = { props, self: null };

const astroPagePartial = this.#astroPagePartial ??= this.createAstroPagePartial(result, astroStaticPartial)
const astroComponentPartial = { props, self: null, slots }

// `Astro.self` is added by the compiler
const Astro: Omit<AstroGlobal, 'self'> = Object.assign(
// Create final object. `Astro.slots` will be lazily created.
const Astro: Omit<AstroGlobal, 'self' | 'slots'> = Object.assign(
Object.create(astroPagePartial),
astroComponentPartial
);

// Handle `Astro.slots`
let _slots: AstroGlobal['slots'];
Object.defineProperty(Astro, 'slots', {
get: () => {
if (!_slots) {
_slots = new Slots(
result,
slotValues,
this.pipeline.logger
) as unknown as AstroGlobal['slots'];
}
return _slots;
},
});

return Astro as AstroGlobal;
}

#astroPagePartial?: Omit<AstroGlobal, 'props' | 'self' | 'slots'>
createAstroPagePartial(
result: SSRResult,
astroStaticPartial: AstroGlobalPartial,
astroStaticPartial: AstroGlobalPartial
): Omit<AstroGlobal, 'props' | 'self' | 'slots'> {
const renderContext = this;
const { cookies, locals, params, pipeline, request, url } = this;
Expand All @@ -287,7 +305,7 @@ export class RenderContext {
}
return new Response(null, { status, headers: { Location: path } });
};

return {
generator: astroStaticPartial.generator,
glob: astroStaticPartial.glob,
Expand Down

0 comments on commit 92470e8

Please sign in to comment.