From 497f69a65bc12b961c1114cd036063721cf6aa94 Mon Sep 17 00:00:00 2001
From: Nathan Sarang-Walters <nwalters512@gmail.com>
Date: Fri, 17 Nov 2023 01:54:48 -0800
Subject: [PATCH] fix(source map): handle source map in middle of file (#392)

Co-authored-by: Hiroki Osame <hiroki.osame@gmail.com>
---
 src/source-map.ts         |  9 ++++++---
 tests/index.ts            |  1 +
 tests/specs/smoke.ts      |  9 +++++++--
 tests/specs/source-map.ts | 23 +++++++++++++++++++++++
 4 files changed, 37 insertions(+), 5 deletions(-)
 create mode 100644 tests/specs/source-map.ts

diff --git a/src/source-map.ts b/src/source-map.ts
index 9e026b5a7..7a08d79cd 100644
--- a/src/source-map.ts
+++ b/src/source-map.ts
@@ -20,10 +20,13 @@ const sourceMapPrefix = '\n//# sourceMappingURL=';
 
 export const stripSourceMap = (code: string) => {
 	const sourceMapIndex = code.indexOf(sourceMapPrefix);
-	if (sourceMapIndex !== -1) {
-		return code.slice(0, sourceMapIndex);
+	if (sourceMapIndex === -1) {
+		return code;
 	}
-	return code;
+
+	const nextNewLine = code.indexOf('\n', sourceMapIndex + sourceMapPrefix.length);
+	const afterSourceMap = nextNewLine === -1 ? '' : code.slice(nextNewLine);
+	return code.slice(0, sourceMapIndex) + afterSourceMap;
 };
 
 const inlineSourceMapPrefix = `${sourceMapPrefix}data:application/json;base64,`;
diff --git a/tests/index.ts b/tests/index.ts
index 7e7d0cb16..cdfb4f4e0 100644
--- a/tests/index.ts
+++ b/tests/index.ts
@@ -7,6 +7,7 @@ import { nodeVersions } from './utils/node-versions';
 		await runTestSuite(import('./specs/cli'));
 		await runTestSuite(import('./specs/watch'));
 		await runTestSuite(import('./specs/repl'));
+		await runTestSuite(import('./specs/source-map'));
 
 		for (const nodeVersion of nodeVersions) {
 			const node = await createNode(nodeVersion);
diff --git a/tests/specs/smoke.ts b/tests/specs/smoke.ts
index bb658d4a2..0b6c5580c 100644
--- a/tests/specs/smoke.ts
+++ b/tests/specs/smoke.ts
@@ -2,6 +2,7 @@ import path from 'path';
 import { pathToFileURL } from 'url';
 import { testSuite, expect } from 'manten';
 import { createFixture } from 'fs-fixture';
+import outdent from 'outdent';
 import type { NodeApis } from '../utils/tsx';
 
 const cjsContextCheck = 'typeof module !== \'undefined\'';
@@ -329,10 +330,12 @@ export default testSuite(async ({ describe }, { tsx }: NodeApis) => {
 					const fixture = await createFixture({
 						...files,
 						'package.json': JSON.stringify({ type: packageType }),
-						'import-from-js.js': `
+						'import-from-js.js': outdent`
 						import assert from 'assert';
 						import { expectErrors } from './expect-errors';
 		
+						//# sourceMappingURL=shouldnt affect the file
+
 						// node: prefix
 						import 'node:fs';
 
@@ -453,10 +456,12 @@ export default testSuite(async ({ describe }, { tsx }: NodeApis) => {
 						...files,
 						'package.json': JSON.stringify({ type: packageType }),
 
-						'import-from-ts.ts': `
+						'import-from-ts.ts': outdent`
 						import assert from 'assert';
 						import { expectErrors } from './expect-errors';
 
+						//# sourceMappingURL=shouldnt affect the file
+
 						// node: prefix
 						import 'node:fs';
 
diff --git a/tests/specs/source-map.ts b/tests/specs/source-map.ts
new file mode 100644
index 000000000..38e321670
--- /dev/null
+++ b/tests/specs/source-map.ts
@@ -0,0 +1,23 @@
+import { testSuite, expect } from 'manten';
+import { stripSourceMap } from '../../src/source-map';
+
+export default testSuite(({ describe }) => {
+	describe('Source Map', ({ describe }) => {
+		describe('stripSourceMap', ({ test }) => {
+			test('end of file, no trailing newline', () => {
+				const file = 'const foo = 1;\n//# sourceMappingURL=foo.js.map';
+				expect(stripSourceMap(file)).toBe('const foo = 1;');
+			});
+
+			test('end of file, with trailing newlines', () => {
+				const file = 'const foo = 1;\n//# sourceMappingURL=foo.js.map\n';
+				expect(stripSourceMap(file)).toBe('const foo = 1;\n');
+			});
+
+			test('middle of file', () => {
+				const file = 'const foo = 1;\n//# sourceMappingURL=foo.js.map\nconst bar = 2;';
+				expect(stripSourceMap(file)).toBe('const foo = 1;\nconst bar = 2;');
+			});
+		});
+	});
+});