From d1dd0e768b1767df7ce3a9fd3963682c62fbbf1b Mon Sep 17 00:00:00 2001 From: GroophyLifefor Date: Sat, 17 Oct 2026 23:49:17 +0300 Subject: [PATCH 1/2] perf: skip unused transform options in strip-only mode `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 Assisted-by: Claude Opus 5.5 --- src/internal.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/internal.ts b/src/internal.ts index c866253e8..4fda5c27e 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -17,14 +17,22 @@ const DEFAULT_OPTIONS = { }, } as Options; +const STRIP_ONLY_DEFAULT_OPTIONS = { + mode: DEFAULT_OPTIONS.mode, + deprecatedTsModuleAsError: DEFAULT_OPTIONS.deprecatedTsModuleAsError, +} as Options; + export function transformSync( source: string, options?: Options, ): TransformOutput { // Ensure that the source code is a string const input = `${source ?? ""}`; + const mode = options?.mode ?? DEFAULT_OPTIONS.mode; + // `transform` is only read in "transform" mode; leaving it out in + // "strip-only" mode saves deserializing it on every call. return swc.transformSync(input, { - ...DEFAULT_OPTIONS, + ...(mode === "strip-only" ? STRIP_ONLY_DEFAULT_OPTIONS : DEFAULT_OPTIONS), ...options, }); } From 190305417a9b165cc68fb18fb60bf13eef38191b Mon Sep 17 00:00:00 2001 From: GroophyLifefor Date: Sun, 18 Oct 2026 22:49:54 +0300 Subject: [PATCH 2/2] refactor: use separate default options per mode 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 Assisted-by: Claude Sonnet 5.5 --- src/internal.ts | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/internal.ts b/src/internal.ts index 4fda5c27e..ba1334864 100644 --- a/src/internal.ts +++ b/src/internal.ts @@ -8,19 +8,20 @@ import swc from "../lib/wasm.js"; const DEFAULT_OPTIONS = { mode: "strip-only", deprecatedTsModuleAsError: true, - // default transform will only work when mode is "transform" +} 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", }, -} as Options; - -const STRIP_ONLY_DEFAULT_OPTIONS = { - mode: DEFAULT_OPTIONS.mode, - deprecatedTsModuleAsError: DEFAULT_OPTIONS.deprecatedTsModuleAsError, -} as Options; +} satisfies Options; export function transformSync( source: string, @@ -28,13 +29,9 @@ export function transformSync( ): TransformOutput { // Ensure that the source code is a string const input = `${source ?? ""}`; - const mode = options?.mode ?? DEFAULT_OPTIONS.mode; - // `transform` is only read in "transform" mode; leaving it out in - // "strip-only" mode saves deserializing it on every call. - return swc.transformSync(input, { - ...(mode === "strip-only" ? STRIP_ONLY_DEFAULT_OPTIONS : DEFAULT_OPTIONS), - ...options, - }); + const defaults = + options?.mode === "transform" ? DEFAULT_TRANSFORM_OPTIONS : DEFAULT_OPTIONS; + return swc.transformSync(input, { ...defaults, ...options }); } export function transformModuleSyntax(