Skip to content

Conversation

@harmony7
Copy link
Member

@harmony7 harmony7 commented Dec 23, 2025

This PR is a refactor that makes no changes to functionality but reorganizes the "compile" procedure into a pipeline of steps.

Below is the implementation of the "compile" procedure in `compileApplicationToWasm.ts" before this PR:

if (doBundle) {
tmpDir = await getTmpDir();
const sourceMaps = [];
const bundleFilename = '__input_bundled.js';
const bundleOutputFilePath = resolve(tmpDir, bundleFilename);
// esbuild respects input source map, works if it's linked via sourceMappingURL
// either inline or as separate file
try {
await bundle(input, bundleOutputFilePath, {
moduleMode,
enableStackTraces,
});
} catch (maybeError: unknown) {
const error =
maybeError instanceof Error
? maybeError
: new Error(String(maybeError));
console.error(`Error:`, error.message);
process.exit(1);
}
if (debugIntermediateFilesDir != null) {
await copyFile(
bundleOutputFilePath,
resolve(debugIntermediateFilesDir, '__1_bundled.js'),
);
if (enableStackTraces) {
await copyFile(
bundleOutputFilePath + '.map',
resolve(debugIntermediateFilesDir, '__1_bundled.js.map'),
);
}
}
if (enableStackTraces) {
sourceMaps.push({ f: bundleFilename, s: bundleOutputFilePath + '.map' });
}
const postbundleFilename = '__fastly_post_bundle.js';
const postbundleOutputFilepath = resolve(tmpDir, postbundleFilename);
await postbundle(bundleOutputFilePath, postbundleOutputFilepath, {
moduleMode,
enableStackTraces,
});
if (debugIntermediateFilesDir != null) {
await copyFile(
postbundleOutputFilepath,
resolve(debugIntermediateFilesDir, '__2_postbundled.js'),
);
if (enableStackTraces) {
await copyFile(
postbundleOutputFilepath + '.map',
resolve(debugIntermediateFilesDir, '__2_postbundled.js.map'),
);
}
}
if (enableStackTraces) {
sourceMaps.push({
f: postbundleFilename,
s: postbundleOutputFilepath + '.map',
});
}
if (enableStackTraces) {
// Compose source maps
const replaceSourceMapToken = '__FINAL_SOURCE_MAP__';
let excludePatterns: ExcludePattern[] = [
'forbid-entry:/**',
'node_modules/**',
];
if (excludeSources) {
excludePatterns = [() => true];
}
const composed = await composeSourcemaps(sourceMaps, excludePatterns);
const outputWithSourcemaps = '__fastly_bundle_with_sourcemaps.js';
const outputWithSourcemapsFilePath = resolve(
tmpDir,
outputWithSourcemaps,
);
const postBundleContent = await readFile(postbundleOutputFilepath, {
encoding: 'utf-8',
});
const outputWithSourcemapsContent = postBundleContent.replace(
replaceSourceMapToken,
() => JSON.stringify(composed),
);
await writeFile(
outputWithSourcemapsFilePath,
outputWithSourcemapsContent,
);
if (debugIntermediateFilesDir != null) {
await copyFile(
outputWithSourcemapsFilePath,
resolve(debugIntermediateFilesDir, 'fastly_bundle.js'),
);
await writeFile(
resolve(debugIntermediateFilesDir, 'fastly_sourcemaps.json'),
composed,
);
}
// the output with sourcemaps is now the Wizer input
input = outputWithSourcemapsFilePath;
} else {
// the bundled output is now the Wizer input
input = postbundleOutputFilepath;
if (debugIntermediateFilesDir != null) {
await copyFile(
postbundleOutputFilepath,
resolve(debugIntermediateFilesDir, 'fastly_bundle.js'),
);
}
}
}

As more functionality was added to this procedure it became harder to reason about, and it became desirable to have a way to separate out the steps into logical units.

The new class CompilerContext contains the state of the pipeline and exposes a function ctx.addCompilerPipelineStep(step). A step is expected to implement the type CompilerPipelineStep which contains an output filename for that step, as well as a function that is passed the CompilerContext and the step number, and is expected to return a Promise<void>.

The following steps are separated into files in the /src/compiler-steps directory for easier maintenance and added to this pipeline.

Name Filename Identifier Description
Bundle bundle.ts bundleStep bundle input -> apply esbuild (bundle package imports, apply Fastly Plugin)
Precompile regexes precompileRegexes.ts precompileRegexesStep precompile regexes
Stack mapping *1 addStackMappingHelpers.ts addStackMappingHelpersStep add stack mapping helpers
Fastly helpers addFastlyHelpers.ts addFastlyHelpersStep add Fastly helpers
Compose/Inject source maps *1 composeSourcemaps.ts composeSourcemapsStep compile sourcemaps up to this point and inject into bundle

*1 - Add this step only when --enable-stack-traces is enabled

After all steps are added, await ctx.applyCompilerPipeline() is called, which applies the steps in order, awaiting on each step and using the output of each step as the input of the next step.

Below is the updated implementation that utilizes the pipeline to perform the "compile" procedure:

// bundle input -> apply esbuild (bundle package imports, apply Fastly Plugin)
ctx.addCompilerPipelineStep(bundleStep);
// precompile regexes
ctx.addCompilerPipelineStep(precompileRegexesStep);
// add stack mapping helpers
if (enableStackTraces) {
ctx.addCompilerPipelineStep(addStackMappingHelpersStep);
}
// add Fastly helpers
ctx.addCompilerPipelineStep(addFastlyHelpersStep);
// compile sourcemaps up to this point and inject into bundle
if (enableStackTraces) {
ctx.addCompilerPipelineStep(composeSourcemapsStep);
}
await ctx.applyCompilerPipeline();

@harmony7 harmony7 force-pushed the kats/refactor-pipeline branch 3 times, most recently from 44d4a4a to 51b1ce6 Compare December 24, 2025 09:40
@harmony7 harmony7 force-pushed the kats/refactor-pipeline branch from 51b1ce6 to b8628ed Compare January 7, 2026 05:20
@harmony7 harmony7 self-assigned this Jan 7, 2026
@harmony7 harmony7 requested a review from TartanLlama January 7, 2026 05:47
@harmony7 harmony7 changed the title Separate compile code into a pipeline refactor: Separate compile code into a pipeline Jan 7, 2026
@harmony7 harmony7 marked this pull request as ready for review January 7, 2026 05:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants