diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e88eb8eb88b..d2f7ea265aa8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ - `[jest-snapshot]` Distinguish empty string from external snapshot not written ([#8880](https://github.com/facebook/jest/pull/8880)) - `[jest-snapshot]` [**BREAKING**] Distinguish empty string from internal snapshot not written ([#8898](https://github.com/facebook/jest/pull/8898)) - `[jest-transform]` Properly cache transformed files across tests ([#8890](https://github.com/facebook/jest/pull/8890)) +- `[jest-transform]` Don't fail the test suite when a generated source map is invalid ([#9058](https://github.com/facebook/jest/pull/9058)) ### Chore & Maintenance diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts index b2765e909a35..e8a971aa2905 100644 --- a/packages/jest-transform/src/ScriptTransformer.ts +++ b/packages/jest-transform/src/ScriptTransformer.ts @@ -296,12 +296,21 @@ export default class ScriptTransformer { } if (!transformed.map) { - //Could be a potential freeze here. - //See: https://github.com/facebook/jest/pull/5177#discussion_r158883570 - const inlineSourceMap = sourcemapFromSource(transformed.code); + try { + //Could be a potential freeze here. + //See: https://github.com/facebook/jest/pull/5177#discussion_r158883570 + const inlineSourceMap = sourcemapFromSource(transformed.code); - if (inlineSourceMap) { - transformed.map = inlineSourceMap.toJSON(); + if (inlineSourceMap) { + transformed.map = inlineSourceMap.toJSON(); + } + } catch (e) { + const transformPath = this._getTransformPath(filename); + console.warn( + `jest-transform: The source map produced for the file ${filename} ` + + `by ${transformPath} was invalid. Proceeding without source ` + + 'mapping for that file.', + ); } } diff --git a/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap b/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap index 49de0f86ac1c..b95aa2b36b0f 100644 --- a/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap +++ b/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap @@ -254,3 +254,5 @@ exports[`ScriptTransformer uses the supplied preprocessor 2`] = ` "({\\"Object.\\":function(module,exports,require,__dirname,__filename,global,jest){module.exports = \\"react\\"; }});" `; + +exports[`ScriptTransformer warns of unparseable inlined source maps from the preprocessor 1`] = `"jest-transform: The source map produced for the file /fruits/banana.js by preprocessor-with-sourcemaps was invalid. Proceeding without source mapping for that file."`; diff --git a/packages/jest-transform/src/__tests__/script_transformer.test.js b/packages/jest-transform/src/__tests__/script_transformer.test.js index 7a826e079600..ddb7792b35a2 100644 --- a/packages/jest-transform/src/__tests__/script_transformer.test.js +++ b/packages/jest-transform/src/__tests__/script_transformer.test.js @@ -406,6 +406,7 @@ describe('ScriptTransformer', () => { }); expect(result.sourceMapPath).toEqual(expect.any(String)); const mapStr = JSON.stringify(map); + expect(writeFileAtomic.sync).toBeCalledTimes(2); expect(writeFileAtomic.sync).toBeCalledWith(result.sourceMapPath, mapStr, { encoding: 'utf8', }); @@ -434,6 +435,7 @@ describe('ScriptTransformer', () => { collectCoverage: true, }); expect(result.sourceMapPath).toEqual(expect.any(String)); + expect(writeFileAtomic.sync).toBeCalledTimes(2); expect(writeFileAtomic.sync).toBeCalledWith( result.sourceMapPath, sourceMap, @@ -441,6 +443,42 @@ describe('ScriptTransformer', () => { ); }); + it('warns of unparseable inlined source maps from the preprocessor', () => { + const warn = console.warn; + console.warn = jest.fn(); + + config = { + ...config, + transform: [['^.+\\.js$', 'preprocessor-with-sourcemaps']], + }; + const scriptTransformer = new ScriptTransformer(config); + + const sourceMap = JSON.stringify({ + mappings: 'AAAA,IAAM,CAAC,GAAW,CAAC,CAAC', + version: 3, + }); + + // Cut off the inlined map prematurely with slice so the JSON ends abruptly + const content = + 'var x = 1;\n' + + '//# sourceMappingURL=data:application/json;base64,' + + Buffer.from(sourceMap) + .toString('base64') + .slice(0, 16); + + require('preprocessor-with-sourcemaps').process.mockReturnValue(content); + + const result = scriptTransformer.transform('/fruits/banana.js', { + collectCoverage: true, + }); + expect(result.sourceMapPath).toBeNull(); + expect(writeFileAtomic.sync).toBeCalledTimes(1); + + expect(console.warn).toHaveBeenCalledTimes(1); + expect(console.warn.mock.calls[0][0]).toMatchSnapshot(); + console.warn = warn; + }); + it('writes source maps if given by the transformer', () => { config = { ...config, @@ -462,6 +500,7 @@ describe('ScriptTransformer', () => { collectCoverage: true, }); expect(result.sourceMapPath).toEqual(expect.any(String)); + expect(writeFileAtomic.sync).toBeCalledTimes(2); expect(writeFileAtomic.sync).toBeCalledWith( result.sourceMapPath, JSON.stringify(map),