Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 49 additions & 16 deletions packages/angular/build/src/tools/esbuild/i18n-inliner-worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ interface InlineFileBatchRequest {
* The locale specifiers or locale objects that should be used during the inlining process of the file.
*/
locales: (string | { locale: string; translation?: Blob })[];

/**
* Whether the file data should be treated as ephemeral and not cached long-term in the Worker.
* Typically true when all remaining locales for the file are processed in a single batch.
*/
ephemeral?: boolean;
Comment thread
clydin marked this conversation as resolved.

/**
* The list of active locales in the current inlining window. Any cached translation dictionaries
* not present in this list will be evicted from the Worker's memory cache.
*/
activeLocales?: string[];
}

/**
Expand Down Expand Up @@ -124,23 +136,35 @@ const fileDataCache = new Map<string, Promise<CachedFileData>>();
const deserializedTranslations = new Map<string, Promise<Record<string, unknown>>>();

/**
* Retrieves the cached file data for a filename, loading and extracting it on the first request.
* Retrieves the file data for a filename, loading and extracting localization metadata.
* If `cache` is true, the result is cached in `fileDataCache` across requests in this Worker.
* If `cache` is false (ephemeral), the result is not retained in `fileDataCache`, allowing it
* to be garbage-collected once the batch request finishes.
*
* @param filename The name of the file to load.
* @returns The cached code and localization metadata.
* @param cache Whether to cache the loaded file data in the Worker's long-term cache.
* @returns The cached or newly extracted code and localization metadata.
*/
function getFileData(filename: string): Promise<CachedFileData> {
let fileDataPromise = fileDataCache.get(filename);
if (!fileDataPromise) {
fileDataPromise = (async () => {
const data = files.get(filename);
assert(data !== undefined, `Invalid inline request for file '${filename}'.`);

const code = await data.text();
const metadata = extractLocalizeMetadata(filename, code);

return { code, metadata };
})();
function loadFileData(filename: string, cache = true): Promise<CachedFileData> {
const existing = fileDataCache.get(filename);
if (existing) {
return existing;
}

const fileDataPromise = (async () => {
const data = files.get(filename);
assert(data !== undefined, `Invalid inline request for file '${filename}'.`);

const code = await data.text();
const metadata = extractLocalizeMetadata(filename, code);

return { code, metadata };
})();

if (cache) {
fileDataPromise.catch(() => {
fileDataCache.delete(filename);
});
fileDataCache.set(filename, fileDataPromise);
}

Expand Down Expand Up @@ -186,7 +210,7 @@ function loadTranslation(
* @returns An object containing the inlined file and optional map content.
*/
export default async function inlineFile(request: InlineFileRequest) {
const { code, metadata } = await getFileData(request.filename);
const { code, metadata } = await loadFileData(request.filename, true);

// Sourcemaps are parsed on demand per request rather than cached long-term to prevent
// monotonic memory growth as a worker processes multiple files across the build.
Expand Down Expand Up @@ -219,7 +243,16 @@ export default async function inlineFile(request: InlineFileRequest) {
export async function inlineFileBatch(
request: InlineFileBatchRequest,
): Promise<InlineFileBatchResult> {
const { code, metadata } = await getFileData(request.filename);
if (request.activeLocales) {
const activeSet = new Set(request.activeLocales);
for (const locale of deserializedTranslations.keys()) {
if (!activeSet.has(locale)) {
deserializedTranslations.delete(locale);
}
}
}

const { code, metadata } = await loadFileData(request.filename, !request.ephemeral);
Comment thread
clydin marked this conversation as resolved.

// Parse the sourcemap once for the entire batch.
// It will naturally be garbage-collected after this batch action returns.
Expand Down
Loading