diff --git a/package.json b/package.json index bc37273..dc704dd 100644 --- a/package.json +++ b/package.json @@ -41,9 +41,9 @@ "webpack": "4 || 5" }, "dependencies": { + "@cspotcode/source-map-support": "^0.8.1", "fs-require": "^1.6.0", "memfs": "^3.5.0", - "source-map-support": "^0.5.21", "yargs": "^16.2.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3052abe..9bd09ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,15 +1,19 @@ lockfileVersion: '6.0' +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + dependencies: + '@cspotcode/source-map-support': + specifier: ^0.8.1 + version: 0.8.1 fs-require: specifier: ^1.6.0 version: 1.6.0 memfs: specifier: ^3.5.0 version: 3.5.0 - source-map-support: - specifier: ^0.5.21 - version: 0.5.21 yargs: specifier: ^16.2.0 version: 16.2.0 @@ -105,6 +109,13 @@ packages: js-tokens: 4.0.0 dev: true + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: false + /@esbuild-kit/cjs-loader@2.4.2: resolution: {integrity: sha512-BDXFbYOJzT/NBEtp71cvsrGPwGAMGRB/349rwKuoxNSiKjPraNNnlK6MIIabViCjqZugu6j+xeMDlEkWdHHJSg==} dependencies: @@ -425,9 +436,20 @@ packages: chalk: 4.1.2 dev: true + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: false + /@jridgewell/sourcemap-codec@1.4.15: resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} - dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: false /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -1192,6 +1214,7 @@ packages: /anymatch@2.0.0: resolution: {integrity: sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==} + requiresBuild: true dependencies: micromatch: 3.1.10 normalize-path: 2.1.1 @@ -1304,6 +1327,7 @@ packages: /async-each@1.0.6: resolution: {integrity: sha512-c646jH1avxr+aVpndVMeAfYw7wAa6idufrlN3LPA4PmKS0QEGp6PIC9nwz0WQkkvBGAMEki3pFdtxaF39J9vvg==} + requiresBuild: true dev: true optional: true @@ -1341,6 +1365,7 @@ packages: /binary-extensions@1.13.1: resolution: {integrity: sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==} engines: {node: '>=0.10.0'} + requiresBuild: true dev: true optional: true @@ -1351,6 +1376,7 @@ packages: /bindings@1.5.0: resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + requiresBuild: true dependencies: file-uri-to-path: 1.0.0 dev: true @@ -1487,6 +1513,7 @@ packages: /buffer-from@1.1.1: resolution: {integrity: sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==} + dev: true /buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -1623,6 +1650,7 @@ packages: /chokidar@2.1.8: resolution: {integrity: sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==} deprecated: Chokidar 2 does not receive security updates since 2019. Upgrade to chokidar 3 with 15x fewer dependencies + requiresBuild: true dependencies: anymatch: 2.0.0 async-each: 1.0.6 @@ -2152,7 +2180,7 @@ packages: resolution: {integrity: sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ==} engines: {node: '>=10.13.0'} dependencies: - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 tapable: 2.2.1 dev: true @@ -3037,6 +3065,7 @@ packages: /file-uri-to-path@1.0.0: resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + requiresBuild: true dev: true optional: true @@ -3162,7 +3191,7 @@ packages: resolution: {integrity: sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==} engines: {node: '>= 4.0'} os: [darwin] - deprecated: fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2. + deprecated: The v1 package contains DANGEROUS / INSECURE binaries. Upgrade to safe fsevents v2 requiresBuild: true dependencies: bindings: 1.5.0 @@ -3245,6 +3274,7 @@ packages: /glob-parent@3.1.0: resolution: {integrity: sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==} + requiresBuild: true dependencies: is-glob: 3.1.0 path-dirname: 1.0.2 @@ -3275,7 +3305,7 @@ packages: fs.realpath: 1.0.0 inflight: 1.0.6 inherits: 2.0.4 - minimatch: 3.0.4 + minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 dev: true @@ -3596,6 +3626,7 @@ packages: /is-binary-path@1.0.1: resolution: {integrity: sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==} engines: {node: '>=0.10.0'} + requiresBuild: true dependencies: binary-extensions: 1.13.1 dev: true @@ -3735,6 +3766,7 @@ packages: /is-glob@3.1.0: resolution: {integrity: sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==} engines: {node: '>=0.10.0'} + requiresBuild: true dependencies: is-extglob: 2.1.1 dev: true @@ -3936,7 +3968,7 @@ packages: '@jest/types': 29.3.1 '@types/stack-utils': 2.0.1 chalk: 4.1.2 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 micromatch: 4.0.5 pretty-format: 29.3.1 slash: 3.0.0 @@ -3951,7 +3983,7 @@ packages: '@types/node': 18.11.9 chalk: 4.1.2 ci-info: 3.6.1 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 picomatch: 2.3.1 dev: true @@ -4013,13 +4045,6 @@ packages: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} dev: true - /json5@1.0.1: - resolution: {integrity: sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==} - hasBin: true - dependencies: - minimist: 1.2.7 - dev: true - /json5@1.0.2: resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} hasBin: true @@ -4446,10 +4471,6 @@ packages: brace-expansion: 2.0.1 dev: true - /minimist@1.2.7: - resolution: {integrity: sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==} - dev: true - /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true @@ -4601,6 +4622,7 @@ packages: /nan@2.17.0: resolution: {integrity: sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==} + requiresBuild: true dev: true optional: true @@ -4697,6 +4719,7 @@ packages: /normalize-path@2.1.1: resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} engines: {node: '>=0.10.0'} + requiresBuild: true dependencies: remove-trailing-separator: 1.1.0 dev: true @@ -4959,6 +4982,7 @@ packages: /path-dirname@1.0.2: resolution: {integrity: sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==} + requiresBuild: true dev: true optional: true @@ -5254,6 +5278,7 @@ packages: /readdirp@2.2.1: resolution: {integrity: sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==} engines: {node: '>=0.10'} + requiresBuild: true dependencies: graceful-fs: 4.2.11 micromatch: 3.1.10 @@ -5326,6 +5351,7 @@ packages: /remove-trailing-separator@1.1.0: resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} + requiresBuild: true dev: true optional: true @@ -5683,6 +5709,7 @@ packages: dependencies: buffer-from: 1.1.1 source-map: 0.6.1 + dev: true /source-map-url@0.4.1: resolution: {integrity: sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==} @@ -5697,6 +5724,7 @@ packages: /source-map@0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + dev: true /source-map@0.7.4: resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} @@ -5995,7 +6023,7 @@ packages: engines: {node: '>=10'} hasBin: true dependencies: - acorn: 8.8.1 + acorn: 8.8.2 commander: 2.20.3 source-map: 0.7.4 source-map-support: 0.5.21 @@ -6070,8 +6098,8 @@ packages: resolution: {integrity: sha512-fxDhWnFSLt3VuTwtvJt5fpwxBHg5AdKWMsgcPOOIilyjymcYVZoCQF8fvFRezCNfblEXmi+PcM1eYHeOAgXCOQ==} dependencies: '@types/json5': 0.0.29 - json5: 1.0.1 - minimist: 1.2.7 + json5: 1.0.2 + minimist: 1.2.8 strip-bom: 3.0.0 dev: true @@ -6202,6 +6230,7 @@ packages: /upath@1.2.0: resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} engines: {node: '>=4'} + requiresBuild: true dev: true optional: true @@ -6300,7 +6329,7 @@ packages: engines: {node: '>=10.13.0'} dependencies: glob-to-regexp: 0.4.1 - graceful-fs: 4.2.10 + graceful-fs: 4.2.11 dev: true /webpack-sources@1.4.3: diff --git a/src/lib/memfs.ts b/src/lib/memfs.ts index 105ef2e..0354113 100644 --- a/src/lib/memfs.ts +++ b/src/lib/memfs.ts @@ -1,24 +1,36 @@ import path from 'path'; import { createFsFromVolume, Volume } from 'memfs'; import { createFsRequire } from 'fs-require'; -import sourceMapSupport from 'source-map-support'; +import sourceMapSupport from '@cspotcode/source-map-support'; export const mfs = createFsFromVolume(new Volume()); // @ts-expect-error To support Webpack 4. No longer needed in WP5 mfs.join = path.join; +let id: number; + +export const mRequire = (modulePath: string): any => { + const require = createFsRequire(mfs, { + fs: true, + }); + + id = require.id; + + return require(modulePath); +}; + sourceMapSupport.install({ environment: 'node', retrieveFile(filePath: string) { + const fsRequirePrefix = `fs-require://${id}/`; + + if (filePath.startsWith(fsRequirePrefix)) { + filePath = filePath.slice(fsRequirePrefix.length - 1); + } + if (mfs.existsSync(filePath)) { return mfs.readFileSync(filePath).toString(); } }, }); - -export const mRequire = (modulePath: string): any => ( - createFsRequire(mfs, { - fs: true, - })(modulePath) -); diff --git a/tests/specs/instant-mocha.mts b/tests/specs/instant-mocha.mts index c0e81b4..88f966d 100644 --- a/tests/specs/instant-mocha.mts +++ b/tests/specs/instant-mocha.mts @@ -21,6 +21,25 @@ const mochaVersions: [string, AliasMap][] = [ ['Mocha 8', { mocha: 'mocha8' }], ]; +const devtoolTestData = [ + [undefined, [ + /\/tests\/failing-test.js\?:9:47/, + /\/tests\/failing-test.js\?:16:47/, + ]], + ['eval-source-map', [ + /\/tests\/failing-test.js:9:47/, + /\/tests\/failing-test.js:16:47/, + ]], + ['source-map', [ + /\/tests\/failing-test.js:5:8/, + /\/tests\/failing-test.js:12:8/, + ]], + ['inline-source-map', [ + /\/tests\/failing-test.js:5:8/, + /\/tests\/failing-test.js:12:8/, + ]], +]; + export default testSuite(({ describe }) => { describe('instant-mocha', ({ test }) => { test('top level await', async () => { @@ -217,6 +236,47 @@ export default testSuite(({ describe }) => { await fixture.rm(); }); + + for (const [devtool, matches] of devtoolTestData) { + test(`source map support with devtool: ${devtool}`, async () => { + const fixture = await createFixture(fixturePath); + await fixture.writeFile( + 'webpack.config.js', + ` + const path = require('path'); + module.exports = { + mode: 'development', + devtool: ${JSON.stringify(devtool)}, + resolve: { + alias: { + '~': path.resolve(__dirname, 'src/'), + }, + }, + }; + `, + ); + + try { + const { stdout } = await instantMocha( + [ + '--webpackConfig', + 'webpack.config.js', + 'tests/failing-test.js', + ], + { + env: { ALIASES }, + cwd: fixture.path, + }, + ); + + for (const match of matches) { + expect(stdout).toMatch(match); + } + } finally { + await fixture.rm(); + } + }); + } }); } }