perf(packages/codegen): remove node param from write and markMap functions in sourcemap builds (#25989)

Optimization to sourcemaps builds.

#25986 made the `node` param passed to `writeWithMap` etc redundant in sourcemap release builds.

Alter the TSDown plugin to remove the param from these functions in sourcemap release builds, and also remove the `node` argument from all call sites.

It was already removed in no-sourcemap builds - this only affects sourcemaps builds.
This commit is contained in:
overlookmotel committed 2026-08-24 09:20:19 +00:00
1 parent 6253b2ccc5
commit 20711f4995
3 files changed
+45 -18

No files matched your search

+9 -2
View File
@@ -391,8 +391,11 @@ A plugin silently doing nothing is a failure mode worth guarding against.
#### `unmap_writes`
Rewrites every mapped write into the plain one it becomes with no mapping to record - so
`writeWithMap(state, code, cat, node.start, node.end, node)` turns into `write(state, code, cat)` -
Runs in two modes, one per build flavour (sourcemaps / no sourcemaps), in both cases stripping arguments
nothing in that build reads.
**Without source maps**, rewrites every mapped write into the plain one it becomes with no mapping to record -
so `writeWithMap(state, code, cat, node.start, node.end, node)` turns into `write(state, code, cat)` -
and rewrites the import to match.
`writeWithMapEnd` becomes `write` too, and every `NoLast` form becomes `writeNoLast`.
`writeWithMapNamed` and `writeWithMapNamedPrivate` become `writeIdent` and `writePrivate`, which fix the category
@@ -402,6 +405,10 @@ instead of taking it. `writePrivate` exists only for the rewrite to land on.
They keep their names, but the arguments come off every call, and the parameters off their declarations -
which, unlike the mapped writes, survive into the build.
**With source maps**, in release builds only, just the trailing `node` comes off - from every call,
and from every declaration. The mappings are real in these builds so the offsets stay, but `node` isn't read
except by debug asserts. Debug builds get neither mode - the `node` parameter stays for the debug asserts to read.
Without it, the offsets would still be read and held live across a call which ignores them.
The three `markMap*` calls write nothing, so they have no plain form to become, and keep their names -
+4 -1
View File
@@ -73,6 +73,9 @@ const minifyConfig = DEBUG
// In builds without source maps, nothing reads the mapping arguments the mapped writes take,
// so `unmap_writes` rewrites every mapped write call, and the imports which bring them in,
// into the plain `write` / `writeNoLast` they become without the mapping arguments.
//
// In sourcemap release builds the same plugin removes only the trailing `node` argument,
// which nothing but the debug asserts those builds have lost ever read.
const printerConfig = (name: string, { sourcemaps, ts }: { sourcemaps: boolean; ts: boolean }) => ({
...commonConfig,
minify: minifyConfig,
@@ -89,7 +92,7 @@ const printerConfig = (name: string, { sourcemaps, ts }: { sourcemaps: boolean;
// `const_functions` runs last, so the plugins before it still see function declarations.
...(ts ? [] : [stripTsPlugin()]),
...assertPlugins,
...(sourcemaps ? [] : [unmapWritesPlugin()]),
unmapWritesPlugin(sourcemaps, DEBUG),
constFunctionsPlugin,
],
});
+32 -15
View File
@@ -49,6 +49,8 @@ const REWRITES = {
markMapStart: { arity: 4, remove: 3, rename: null },
markMapAfter: { arity: 4, remove: 3, rename: null },
markMapAtStartOffset: { arity: 5, remove: 4, rename: null },
markMapEnd: { arity: 4, remove: 3, rename: null },
markMapNamed: { arity: 7, remove: 6, rename: null },
// `rename: null` to transform the function declarations, removing the dropped params
printString: { arity: 5, remove: 3, rename: null },
printNonNegativeFloat: { arity: 5, remove: 3, rename: null },
@@ -59,11 +61,13 @@ const WRITE_MODULE = "./write.ts";
type MappedName = keyof typeof REWRITES;
/**
* Create the plugin.
* Create the plugin for one build flavour.
*
* @param sourcemaps - `true` to strip only `node`, `false` to unmap the writes entirely
* @param debug - `true` if is a debug build
* @returns The plugin
*/
export default function unmapWritesPlugin(): Plugin {
export default function unmapWritesPlugin(sourcemaps: boolean, debug: boolean): Plugin {
return {
name: "unmap-writes",
transform: {
@@ -71,6 +75,10 @@ export default function unmapWritesPlugin(): Plugin {
filter: { id: /\/src-js\/print\/.+\.ts$/ },
handler(code, path, meta) {
// Don't alter anything in debug sourcemap builds.
// No functions are renamed and no arguments to those functions are removed.
if (sourcemaps && debug) return;
// Parse file
const magicString = meta.magicString!;
const { program, errors } = parseSync(path, code);
@@ -92,7 +100,7 @@ export default function unmapWritesPlugin(): Plugin {
const rewrite = REWRITES[name];
if (rewrite === undefined) return;
const { arity, remove, rename } = rewrite;
const { arity, rename } = rewrite;
const args = node.arguments;
if (args.length !== arity) {
throw new Error(
@@ -101,11 +109,14 @@ export default function unmapWritesPlugin(): Plugin {
);
}
// Remove the dropped arguments, from the end of the last kept one to the end of the last
// Remove the dropped arguments, from the end of the last kept one to the end of the last.
// In sourcemaps builds, remove only the last argument (`node`).
const remove = sourcemaps ? 1 : rewrite.remove;
magicString.remove(args[arity - remove - 1].end, args[arity - 1].end);
// If callee needs to be renamed, rename it, and record that it needs to be imported under new name
if (rename !== null) {
// If callee needs to be renamed, rename it, and record that it needs to be imported under new name.
// Nothing is renamed in sourcemap builds.
if (!sourcemaps && rename !== null) {
magicString.overwrite(callee.start, callee.end, rename);
neededImportReplacements.add(name);
}
@@ -120,7 +131,7 @@ export default function unmapWritesPlugin(): Plugin {
const rewrite = REWRITES[name];
if (rewrite === undefined) return;
const { arity, remove } = rewrite;
const { arity } = rewrite;
const { params } = node;
if (params.length !== arity) {
throw new Error(
@@ -129,7 +140,9 @@ export default function unmapWritesPlugin(): Plugin {
);
}
// Remove the dropped params, from the end of the last kept one to the end of the last
// Remove the dropped params, from the end of the last kept one to the end of the last.
// In sourcemaps builds, remove only the last param (`node`).
const remove = sourcemaps ? 1 : rewrite.remove;
magicString.remove(params[arity - remove - 1].end, params[arity - 1].end);
},
@@ -158,13 +171,17 @@ export default function unmapWritesPlugin(): Plugin {
}
const name = specifier.imported.name as MappedName;
const rewrite = REWRITES[name];
if (rewrite !== undefined) {
const { rename } = rewrite;
if (rename !== null) {
specifierNames.add(rename);
importReplacements.push(name);
continue;
// Only rename imports in no-sourcemap builds
if (!sourcemaps) {
const rewrite = REWRITES[name];
if (rewrite !== undefined) {
const { rename } = rewrite;
if (rename !== null) {
specifierNames.add(rename);
importReplacements.push(name);
continue;
}
}
}