Repository navigation
perf: skip unused transform options in strip-only mode - #484
Merged
marco-ippolito merged 2 commits intoOct 19, 2026
Merged
Conversation
`transform` is only read by swc in "transform" mode, but it was sent on every call and deserialized through serde's flatten path. Leaving it out in "strip-only" mode cuts the JS/wasm boundary calls per transformSync call from 389 to 214 with identical output. Signed-off-by: Murat Kirazkaya <groophylifefor@gmail.com> Assisted-by: Claude Opus 5.5
Member
|
it makes sense but I think we can refactor the whole function in a cleaner way, give there are only 2 possible options |
Contributor
Author
|
Hey @marco-ippolito, What's the idea you have in mind? I can work on it. |
marco-ippolito
left a comment
Member
There was a problem hiding this comment.
In the object signature we could default options to type stripping default options. Then in the body if mode is transform, merge default transform object with options.
Contributor
Author
|
Is it something like this? const DEFAULT_OPTIONS = {
mode: "strip-only",
deprecatedTsModuleAsError: true,
} as Options;
const DEFAULT_TRANSFORM_OPTIONS = {
verbatimModuleSyntax: true,
nativeClassProperties: true,
noEmptyExport: true,
importNotUsedAsValues: "preserve",
} as Options["transform"];
export function transformSync(
source: string,
options: Options = DEFAULT_OPTIONS,
): TransformOutput {
const input = `${source ?? ""}`;
const opts = { ...DEFAULT_OPTIONS, ...options };
if (opts.mode === "transform") {
opts.transform = { ...DEFAULT_TRANSFORM_OPTIONS, ...opts.transform };
}
return swc.transformSync(input, opts);
}Two things to check:
|
Member
|
I was thinking something simple like: const DEFAULT_OPTIONS = {
mode: "strip-only",
deprecatedTsModuleAsError: true,
} satisfies Options;
// swc only reads `transform` in "transform" mode, so these defaults are kept
// out of strip-only calls to avoid deserializing them on every call.
const DEFAULT_TRANSFORM_OPTIONS = {
mode: "transform",
deprecatedTsModuleAsError: true,
transform: {
verbatimModuleSyntax: true,
nativeClassProperties: true,
noEmptyExport: true,
importNotUsedAsValues: "preserve",
},
} satisfies Options;
export function transformSync(
source: string,
options?: Options,
): TransformOutput {
// Ensure that the source code is a string
const input = `${source ?? ""}`;
const defaults =
options?.mode === "transform" ? DEFAULT_TRANSFORM_OPTIONS : DEFAULT_OPTIONS;
return swc.transformSync(input, { ...defaults, ...options });
} |
Contributor
Author
|
Pretty clear, let me implement in this PR. |
Keep the default options for "strip-only" and "transform" mode in two separate objects and pick one based on the requested mode, as suggested in review. The options sent to swc are unchanged. Signed-off-by: Murat Kirazkaya <groophylifefor@gmail.com> Assisted-by: Claude Sonnet 5.5
marco-ippolito
approved these changes
Oct 19, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
swc only reads
options.transformin"transform"mode, buttransformSyncsends it on every call and swc deserializes it each time. In"strip-only"mode (the default, used by Node.js) this change leaves it out."transform"mode and caller-provided options are unchanged.JS ↔ wasm calls per
transformSynccall: 389 -> 214. Output is identical (all TypeScript fixtures in Node.jstest/fixtures, including error cases).npm testpasses.Benchmark
Node.js
benchmark/ts/strip-typescript.jswithcompare.js, 30 runs per binary. Same Node.js build before and after; only the bundled amaro differs.main(1.2.1).tsmain(1.2.1).js(control).ts.js(control)Environment
taskset -c 0balanced, governorpowersavemainat269cab6320(v27.0.0-pre), built with ninjamain:dist/index.jsanddist/internal.jsbundled into one file with esbuild so Node.js can embed it, the same way before and after