diff --git a/packages/metro-transform-worker/src/__tests__/__snapshots__/index-test.js.snap b/packages/metro-transform-worker/src/__tests__/__snapshots__/index-test.js.snap index 6611d9ac8a..feedb87dc2 100644 --- a/packages/metro-transform-worker/src/__tests__/__snapshots__/index-test.js.snap +++ b/packages/metro-transform-worker/src/__tests__/__snapshots__/index-test.js.snap @@ -123,6 +123,10 @@ Array [ 4, 23, ], + Array [ + 9, + 3, + ], ] `; @@ -175,6 +179,10 @@ Array [ 1, 15, ], + Array [ + 3, + 3, + ], ] `; @@ -227,6 +235,10 @@ Array [ 1, 25, ], + Array [ + 3, + 140, + ], ] `; @@ -315,6 +327,10 @@ Array [ 1, 20, ], + Array [ + 5, + 3, + ], ] `; diff --git a/packages/metro-transform-worker/src/__tests__/index-test.js b/packages/metro-transform-worker/src/__tests__/index-test.js index 40bfcb1d15..6c86699cde 100644 --- a/packages/metro-transform-worker/src/__tests__/index-test.js +++ b/packages/metro-transform-worker/src/__tests__/index-test.js @@ -192,7 +192,7 @@ it('transforms an es module with asyncToGenerator', async () => { expect(result.output[0].type).toBe('js/module'); expect(result.output[0].data.code).toMatchSnapshot(); - expect(result.output[0].data.map).toHaveLength(13); + expect(result.output[0].data.map).toHaveLength(14); expect(result.output[0].data.functionMap).toMatchSnapshot(); expect(result.dependencies).toEqual([ { diff --git a/packages/metro-transform-worker/src/index.js b/packages/metro-transform-worker/src/index.js index e5f1d55439..c0f2d9e637 100644 --- a/packages/metro-transform-worker/src/index.js +++ b/packages/metro-transform-worker/src/index.js @@ -44,7 +44,6 @@ const { toSegmentTuple, } = require('metro-source-map'); const metroTransformPlugins = require('metro-transform-plugins'); -const countLines = require('metro/src/lib/countLines'); const collectDependencies = require('metro/src/ModuleGraph/worker/collectDependencies'); const { InvalidRequireCallError: InternalInvalidRequireCallError, @@ -441,11 +440,14 @@ async function transformJS( )); } + let lineCount; + ({lineCount, map} = countLinesAndTerminateMap(code, map)); + const output: Array = [ { data: { code, - lineCount: countLines(code), + lineCount, map, functionMap: file.functionMap, }, @@ -552,9 +554,11 @@ async function transformJSON( jsType = 'js/module'; } + let lineCount; + ({lineCount, map} = countLinesAndTerminateMap(code, map)); const output: Array = [ { - data: {code, lineCount: countLines(code), map, functionMap: null}, + data: {code, lineCount, map, functionMap: null}, type: jsType, }, ]; @@ -652,6 +656,7 @@ module.exports = { const {babelTransformerPath, minifierPath, ...remainingConfig} = config; const filesKey = getCacheKey([ + __filename, require.resolve(babelTransformerPath), require.resolve(minifierPath), require.resolve('./utils/getMinifier'), @@ -670,3 +675,42 @@ module.exports = { ].join('$'); }, }; + +function countLinesAndTerminateMap( + code: string, + map: $ReadOnlyArray, +): { + lineCount: number, + map: Array, +} { + const NEWLINE = /\r\n?|\n|\u2028|\u2029/g; + let lineCount = 1; + let lastLineStart = 0; + + // Count lines and keep track of where the last line starts + for (const match of code.matchAll(NEWLINE)) { + lineCount++; + lastLineStart = match.index + match[0].length; + } + const lastLineLength = code.length - lastLineStart; + const lastLineIndex1Based = lineCount; + const lastLineNextColumn0Based = lastLineLength; + + // If there isn't a mapping at one-past-the-last column of the last line, + // add one that maps to nothing. This ensures out-of-bounds lookups hit the + // null mapping rather than aliasing to whichever mapping happens to be last. + // ASSUMPTION: Mappings are generated in order of increasing line and column. + const lastMapping = map[map.length - 1]; + const terminatingMapping = [lastLineIndex1Based, lastLineNextColumn0Based]; + if ( + !lastMapping || + lastMapping[0] !== terminatingMapping[0] || + lastMapping[1] !== terminatingMapping[1] + ) { + return { + lineCount, + map: map.concat([terminatingMapping]), + }; + } + return {lineCount, map: [...map]}; +} diff --git a/packages/metro/src/integration_tests/__tests__/__snapshots__/buildGraph-test.js.snap b/packages/metro/src/integration_tests/__tests__/__snapshots__/buildGraph-test.js.snap index 386f55e8e6..54e826ce1e 100644 --- a/packages/metro/src/integration_tests/__tests__/__snapshots__/buildGraph-test.js.snap +++ b/packages/metro/src/integration_tests/__tests__/__snapshots__/buildGraph-test.js.snap @@ -389,6 +389,10 @@ Array [ 20, 40, ], + Array [ + 24, + 3, + ], ], }, "type": "js/module",