From 27bb6783afc378fc8809dd0dadc5d1f25a104d9a Mon Sep 17 00:00:00 2001 From: Aleksander Katan <56294622+aleksanderkatan@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:08:55 +0200 Subject: [PATCH 1/6] Include filename if sourcemaps are enabled --- packages/unplugin-typegpu/src/babel.ts | 3 +++ packages/unplugin-typegpu/src/core/factory.ts | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/unplugin-typegpu/src/babel.ts b/packages/unplugin-typegpu/src/babel.ts index 614e4d60a8..30245ace7e 100644 --- a/packages/unplugin-typegpu/src/babel.ts +++ b/packages/unplugin-typegpu/src/babel.ts @@ -51,6 +51,9 @@ function assignMetadata( t.objectProperty(i('name'), t.valueToNode(name)), t.objectProperty(i('ast'), t.valueToNode({ params: ast.params, body: ast.body })), t.objectProperty(i('externals'), externalsToNode(ast.externalNames)), + ...(this.opts.unstable_sourceMaps && this.filename + ? [t.objectProperty(i('filename'), t.stringLiteral(this.filename))] + : []), ]); let expression: t.Expression; diff --git a/packages/unplugin-typegpu/src/core/factory.ts b/packages/unplugin-typegpu/src/core/factory.ts index eed1a33e4a..0597cdd97d 100644 --- a/packages/unplugin-typegpu/src/core/factory.ts +++ b/packages/unplugin-typegpu/src/core/factory.ts @@ -58,7 +58,9 @@ function assignMetadata( v: ${METADATA_FORMAT_VERSION}, name: ${name ? `"${name}"` : 'undefined'}, ast: ${embedJSON({ params: ast.params, body: ast.body })}, - externals: ${externalsToString(ast.externalNames)} + externals: ${externalsToString(ast.externalNames)}${ + this.opts.unstable_sourceMaps && this.filename ? `,\n filename: "${this.filename}"` : '' + } }`; const visibility = t.isFunctionDeclaration(path.node) From 875790651d7347f96d117952ae2efd69f80a0309 Mon Sep 17 00:00:00 2001 From: Aleksander Katan <56294622+aleksanderkatan@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:04:38 +0200 Subject: [PATCH 2/6] Add tests --- .../unplugin-typegpu/test/sourceMaps.test.ts | 37 ++++++++++++++++--- packages/unplugin-typegpu/test/transform.ts | 12 +++++- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/packages/unplugin-typegpu/test/sourceMaps.test.ts b/packages/unplugin-typegpu/test/sourceMaps.test.ts index 7b02a747c3..8728bf84b9 100644 --- a/packages/unplugin-typegpu/test/sourceMaps.test.ts +++ b/packages/unplugin-typegpu/test/sourceMaps.test.ts @@ -99,8 +99,7 @@ describe('source maps', () => { test('[BABEL]', () => { const transformed = babelTransform(code, { unstable_sourceMaps: true }); - expect(transformed).toMatchInlineSnapshot( - ` + expect(transformed).toMatchInlineSnapshot(` "import { tgpu } from 'typegpu'; const external = { n: 1 @@ -124,8 +123,7 @@ describe('source maps', () => { "external.n": () => external.n } }) && $.f)({});" - `, - ); + `); }); test('[ROLLUP]', async () => { @@ -145,7 +143,8 @@ describe('source maps', () => { v: 2, name: "fn", ast: {"params":[{"type":"i","name":"argument"}],"body":[-1,5,38,[0,[[-1,7,8,[13,[-1,7,14,[9,"variable"]],[-1,7,25,[5,"3"]]]],[-1,8,8,[10,[-1,8,15,[1,[-1,8,15,[1,[-1,8,15,[9,"external.n"]],"+",[-1,8,28,[9,"argument"]]]],"+",[-1,8,39,[9,"variable"]]]]]]]]]}, - externals: {"external.n":() => external.n} + externals: {"external.n":() => external.n}, + filename: "virtual:code" }) && $.f)({})); export { fn }; @@ -302,4 +301,32 @@ describe('source maps', () => { }); }); }); + + describe('file name', () => { + const code = `const fn = () => { 'use gpu'; return 1; }; console.log(fn)`; + + describe('is included when source maps are enabled', () => { + test('[BABEL]', () => { + const transformed = babelTransform(code, { unstable_sourceMaps: true }, [], [], 'test.ts'); + expect(transformed).toContain('filename:'); + }); + + test('[ROLLUP]', async () => { + const transformed = await rollupTransform(code, { unstable_sourceMaps: true }); + expect(transformed).toContain('filename:'); + }); + }); + + describe('is omitted when source maps are disabled', () => { + test('[BABEL]', () => { + const transformed = babelTransform(code, { unstable_sourceMaps: false }, [], [], 'test.ts'); + expect(transformed).not.toContain('filename:'); + }); + + test('[ROLLUP]', async () => { + const transformed = await rollupTransform(code, { unstable_sourceMaps: false }); + expect(transformed).not.toContain('filename:'); + }); + }); + }); }); diff --git a/packages/unplugin-typegpu/test/transform.ts b/packages/unplugin-typegpu/test/transform.ts index 97dadf0093..f7f8828a68 100644 --- a/packages/unplugin-typegpu/test/transform.ts +++ b/packages/unplugin-typegpu/test/transform.ts @@ -25,8 +25,10 @@ export const babelTransform = ( options?: Options, prePlugins: BabelTestPlugin[] = [], postPlugins: BabelTestPlugin[] = [], + filename?: string, ) => Babel.transform(code, { + filename, plugins: [...prePlugins, [babelPlugin, { ...defaultOptions, ...options }], ...postPlugins], parserOpts: { plugins: ['typescript'] }, }).code; @@ -48,7 +50,9 @@ export const rollupTransform = ( external: ['typegpu', /^typegpu\/.*$/], }) .then((build) => build.generate({})) - .then((generated) => generated.output[0].code); + // `@rollup/plugin-virtual` prefixes its module ids with a NUL byte, which would + // otherwise end up verbatim in inline snapshots and make this file binary. + .then((generated) => generated.output[0].code.replaceAll('\0virtual:', 'virtual:')); export type WebpackTestPlugin = NonNullable[number]; @@ -93,7 +97,11 @@ export const webpackTransform = async ( ); }); - return await readFile(join(dir, 'dist', 'output.js'), 'utf-8'); + // The temp directory is fresh on every run, so stabilize it for snapshots. + return (await readFile(join(dir, 'dist', 'output.js'), 'utf-8')).replaceAll( + input, + '//input.js', + ); } finally { await rm(dir, { recursive: true, force: true }); } From af369dfbe2956755b72ce40b79d02eee6f0aba06 Mon Sep 17 00:00:00 2001 From: Aleksander Katan <56294622+aleksanderkatan@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:04:51 +0200 Subject: [PATCH 3/6] Update metadata types --- packages/typegpu/src/shared/normalizeMetadata.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/typegpu/src/shared/normalizeMetadata.ts b/packages/typegpu/src/shared/normalizeMetadata.ts index 3ef2fe0456..2398577217 100644 --- a/packages/typegpu/src/shared/normalizeMetadata.ts +++ b/packages/typegpu/src/shared/normalizeMetadata.ts @@ -15,6 +15,7 @@ export interface RawMetadataV2 { name: string; ast: { params: FuncParameter[]; body: Block | SourceMappedNode }; externals: { [key: string]: () => unknown }; + filename?: string; } /** @@ -28,6 +29,7 @@ export type RawMetadata = RawMetadataV1 | RawMetadataV2; export interface Metadata { ast: { params: FuncParameter[]; body: Block | SourceMappedNode }; externals: () => Record; + filename?: string; } /** From 4a4cd976485ade21d3980c7c2867c3643f20dbcf Mon Sep 17 00:00:00 2001 From: Aleksander Katan <56294622+aleksanderkatan@users.noreply.github.com> Date: Fri, 18 Sep 2026 14:16:46 +0200 Subject: [PATCH 4/6] Remove slop that appeared in my code without my permission --- .../unplugin-typegpu/test/sourceMaps.test.ts | Bin 11209 -> 11210 bytes packages/unplugin-typegpu/test/transform.ts | 10 ++-------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/packages/unplugin-typegpu/test/sourceMaps.test.ts b/packages/unplugin-typegpu/test/sourceMaps.test.ts index 8728bf84b9ac5948c0b0d1025e43e83e3138ecde..318666deb603f932851aca0196b3ce8aa9def816 100644 GIT binary patch delta 14 VcmX>Zeky!Joe(3#<~kv7NdPYG1u6gl delta 12 TcmX>VelmPRozUibA#X_lC+Gz# diff --git a/packages/unplugin-typegpu/test/transform.ts b/packages/unplugin-typegpu/test/transform.ts index f7f8828a68..36a2cc39f1 100644 --- a/packages/unplugin-typegpu/test/transform.ts +++ b/packages/unplugin-typegpu/test/transform.ts @@ -50,9 +50,7 @@ export const rollupTransform = ( external: ['typegpu', /^typegpu\/.*$/], }) .then((build) => build.generate({})) - // `@rollup/plugin-virtual` prefixes its module ids with a NUL byte, which would - // otherwise end up verbatim in inline snapshots and make this file binary. - .then((generated) => generated.output[0].code.replaceAll('\0virtual:', 'virtual:')); + .then((generated) => generated.output[0].code); export type WebpackTestPlugin = NonNullable[number]; @@ -97,11 +95,7 @@ export const webpackTransform = async ( ); }); - // The temp directory is fresh on every run, so stabilize it for snapshots. - return (await readFile(join(dir, 'dist', 'output.js'), 'utf-8')).replaceAll( - input, - '//input.js', - ); + return await readFile(join(dir, 'dist', 'output.js'), 'utf-8'); } finally { await rm(dir, { recursive: true, force: true }); } From 385ae103a8fd593f42d7ffc44f50a467d821c140 Mon Sep 17 00:00:00 2001 From: Aleksander Katan <56294622+aleksanderkatan@users.noreply.github.com> Date: Fri, 18 Sep 2026 16:28:38 +0200 Subject: [PATCH 5/6] Hide null byte --- .../unplugin-typegpu/test/sourceMaps.test.ts | Bin 11210 -> 11492 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/packages/unplugin-typegpu/test/sourceMaps.test.ts b/packages/unplugin-typegpu/test/sourceMaps.test.ts index 318666deb603f932851aca0196b3ce8aa9def816..0113bcd408a4728681c23ec4696aef76530da292 100644 GIT binary patch delta 345 zcmX>V{v>ikIlqLxUQud6PGWMZV@{5SdQ63Zfx3=@y1M4%gJMdXXYxN~+FUPGE*6@c zpI2O>kd~Q~nwOZHs$i>7Qk0lioR(jdo0?*;mz!9UoS~twrv+1>p{J!8lc%p~uNQ3? zYt5wq1*sJUsmUc8FjbQc<)!$n6qNK!Qj1IUN{W?~5+=)QPOisi8Qd%d1w!_sD8=xl zg1(kQS!Pj5X<`o8UkV_P6)O~%BnlOkD3oWGWGH|_LqSU)7#@>1Y6){7J6izgY^ZLl T Date: Fri, 18 Sep 2026 17:24:04 +0200 Subject: [PATCH 6/6] Escape file name --- packages/unplugin-typegpu/src/core/factory.ts | 6 ++++-- packages/unplugin-typegpu/test/sourceMaps.test.ts | 10 ++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/unplugin-typegpu/src/core/factory.ts b/packages/unplugin-typegpu/src/core/factory.ts index 0597cdd97d..26d70e9895 100644 --- a/packages/unplugin-typegpu/src/core/factory.ts +++ b/packages/unplugin-typegpu/src/core/factory.ts @@ -59,7 +59,9 @@ function assignMetadata( name: ${name ? `"${name}"` : 'undefined'}, ast: ${embedJSON({ params: ast.params, body: ast.body })}, externals: ${externalsToString(ast.externalNames)}${ - this.opts.unstable_sourceMaps && this.filename ? `,\n filename: "${this.filename}"` : '' + this.opts.unstable_sourceMaps && this.filename + ? `,\n filename: ${embedJSON(this.filename)}` + : '' } }`; @@ -264,7 +266,7 @@ export const unpluginFactory = ((rawOptions, _meta) => { return magicString.generateMap({ source: id, includeContent: true, - hires: 'boundary', + hires: options.unstable_sourceMaps ? true : 'boundary', }); }, }; diff --git a/packages/unplugin-typegpu/test/sourceMaps.test.ts b/packages/unplugin-typegpu/test/sourceMaps.test.ts index 0113bcd408..bc8aa82b8e 100644 --- a/packages/unplugin-typegpu/test/sourceMaps.test.ts +++ b/packages/unplugin-typegpu/test/sourceMaps.test.ts @@ -129,7 +129,7 @@ describe('source maps', () => { test('[ROLLUP]', async () => { const transformed = await rollupTransform(code, { unstable_sourceMaps: true }); - expect(transformed?.replaceAll('\x00', '')).toMatchInlineSnapshot( + expect(transformed).toMatchInlineSnapshot( ` "import 'typegpu'; @@ -144,7 +144,7 @@ describe('source maps', () => { name: "fn", ast: {"params":[{"type":"i","name":"argument"}],"body":[-1,5,38,[0,[[-1,7,8,[13,[-1,7,14,[9,"variable"]],[-1,7,25,[5,"3"]]]],[-1,8,8,[10,[-1,8,15,[1,[-1,8,15,[1,[-1,8,15,[9,"external.n"]],"+",[-1,8,28,[9,"argument"]]]],"+",[-1,8,39,[9,"variable"]]]]]]]]]}, externals: {"external.n":() => external.n}, - filename: "virtual:code" + filename: "\\u0000virtual:code" }) && $.f)({})); export { fn }; @@ -314,10 +314,8 @@ describe('source maps', () => { test('[ROLLUP]', async () => { const transformed = await rollupTransform(code, { unstable_sourceMaps: true }); - const filename = transformed - ?.match(/.*filename(.*)\n/)?.[1] - ?.replaceAll('\x00' /* virtual file names start with \x00 */, ''); - expect(filename).toMatchInlineSnapshot(`": "virtual:code""`); + const filename = transformed?.match(/.*filename(.*)\n/)?.[1]; + expect(filename).toMatchInlineSnapshot(`": "\\u0000virtual:code""`); }); });