From 2b8e256e8ce9c657a906400a646fbea0a4c7abd3 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 17 Feb 2018 15:23:02 +0100 Subject: [PATCH 01/15] Remove usage of `retainLines` --- .babelrc | 3 +- .../__snapshots__/failures.test.js.snap | 2 +- .../__tests__/location_in_results.test.js | 4 +- .../location-in-results/__tests__/test.js | 3 +- packages/babel-jest/src/index.js | 1 - packages/jest-jasmine2/package.json | 1 + packages/jest-jasmine2/src/index.js | 55 +++++++++++++++++-- packages/jest-runtime/src/index.js | 10 ++++ packages/jest-util/src/buffered_console.js | 1 + 9 files changed, 68 insertions(+), 12 deletions(-) diff --git a/.babelrc b/.babelrc index 902f1e07dbe8..7743d00e7c9a 100644 --- a/.babelrc +++ b/.babelrc @@ -8,6 +8,5 @@ "transform-async-to-generator", "transform-strict-mode", ["transform-es2015-modules-commonjs", {"allowTopLevelThis": true}] - ], - "retainLines": true + ] } diff --git a/integration-tests/__tests__/__snapshots__/failures.test.js.snap b/integration-tests/__tests__/__snapshots__/failures.test.js.snap index 80542fc0622e..6ebf606f5060 100644 --- a/integration-tests/__tests__/__snapshots__/failures.test.js.snap +++ b/integration-tests/__tests__/__snapshots__/failures.test.js.snap @@ -118,7 +118,7 @@ exports[`works with async failures 1`] = ` + \\"foo\\": \\"bar\\", } - at ../../packages/expect/build/index.js:145:57 + at ../../packages/expect/build/index.js:104:76 " `; diff --git a/integration-tests/__tests__/location_in_results.test.js b/integration-tests/__tests__/location_in_results.test.js index 19891b542a1d..2e7b78565ab4 100644 --- a/integration-tests/__tests__/location_in_results.test.js +++ b/integration-tests/__tests__/location_in_results.test.js @@ -28,6 +28,6 @@ it('adds correct location info when provided with flag', () => { const assertions = result.testResults[0].assertionResults; expect(result.success).toBe(true); expect(result.numTotalTests).toBe(2); - expect(assertions[0].location).toEqual({column: 1, line: 9}); - expect(assertions[1].location).toEqual({column: 3, line: 14}); + expect(assertions[0].location).toEqual({column: 1, line: 10}); + expect(assertions[1].location).toEqual({column: 2, line: 15}); }); diff --git a/integration-tests/location-in-results/__tests__/test.js b/integration-tests/location-in-results/__tests__/test.js index 55c08de1379c..810c033d474a 100644 --- a/integration-tests/location-in-results/__tests__/test.js +++ b/integration-tests/location-in-results/__tests__/test.js @@ -4,7 +4,8 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ -'use strict'; +// This file is missing 'use strict' to force babel into doing something +// as we have `transform-strict-mode` it('no ancestors', () => { expect(true).toBeTruthy(); diff --git a/packages/babel-jest/src/index.js b/packages/babel-jest/src/index.js index 810abb73a579..34ea2f1d2886 100644 --- a/packages/babel-jest/src/index.js +++ b/packages/babel-jest/src/index.js @@ -74,7 +74,6 @@ const createTransformer = (options: any): Transformer => { options = Object.assign({}, options, { plugins: (options && options.plugins) || [], presets: ((options && options.presets) || []).concat([jestPreset]), - retainLines: true, sourceMaps: 'both', }); delete options.cacheDirectory; diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index 85ff3969646b..eab3c664b1ea 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -18,6 +18,7 @@ "jest-matcher-utils": "^22.2.0", "jest-message-util": "^22.2.0", "jest-snapshot": "^22.2.0", + "source-map": "^0.6.0", "source-map-support": "^0.5.0" }, "devDependencies": { diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 38422b08d5b2..557dbf44e031 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -15,13 +15,48 @@ import type {TestResult} from 'types/TestResult'; import type Runtime from 'jest-runtime'; import path from 'path'; -import fs from 'fs'; import callsites from 'callsites'; +import {SourceMapConsumer} from 'source-map'; import JasmineReporter from './reporter'; import {install as jasmineAsyncInstall} from './jasmine_async'; const JASMINE = require.resolve('./jasmine/jasmine_light.js'); +// Copied from https://github.com/rexxars/sourcemap-decorate-callsites/blob/5b9735a156964973a75dc62fd2c7f0c1975458e8/lib/index.js#L113-L158 +function extendCallsite(callsite, consumer) { + const getLineNumber = callsite.getLineNumber; + const getColumnNumber = callsite.getColumnNumber; + let position = null; + + function getPosition() { + if (!position) { + position = consumer.originalPositionFor({ + column: getColumnNumber.call(callsite), + line: getLineNumber.call(callsite), + }); + } + + return position; + } + + Object.defineProperties(callsite, { + getColumnNumber: { + value() { + return getPosition().column || getColumnNumber.call(callsite); + }, + writable: false, + }, + getLineNumber: { + value() { + return getPosition().line || getLineNumber.call(callsite); + }, + writable: false, + }, + }); + + return callsite; +} + async function jasmine2( globalConfig: GlobalConfig, config: ProjectConfig, @@ -53,6 +88,17 @@ async function jasmine2( environment.global.it = (...args) => { const stack = callsites()[1]; const it = originalIt(...args); + const sourceMapForFile = runtime.getSourceMapForFile(stack.getFileName()); + + if (sourceMapForFile) { + try { + const consumer = new SourceMapConsumer(sourceMapForFile); + + extendCallsite(stack, consumer); + } catch (e) { + // ignored + } + } it.result.__callsite = stack; @@ -125,12 +171,11 @@ async function jasmine2( environment: 'node', handleUncaughtExceptions: false, retrieveSourceMap: source => { - if (runtime._sourceMapRegistry[source]) { + const sourceMap = runtime.getSourceMapForFile(source); + if (sourceMap) { try { return { - map: JSON.parse( - fs.readFileSync(runtime._sourceMapRegistry[source]), - ), + map: JSON.parse(sourceMap), url: source, }; } catch (e) {} diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index a75e091d5e78..a5fc74186037 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -449,6 +449,16 @@ class Runtime { }, {}); } + getSourceMapForFile(filename: string): ?string { + const sourceMap = this._sourceMapRegistry[filename]; + + if (sourceMap && fs.existsSync(sourceMap)) { + return fs.readFileSync(sourceMap, 'utf8'); + } + + return null; + } + setMock( from: string, moduleName: string, diff --git a/packages/jest-util/src/buffered_console.js b/packages/jest-util/src/buffered_console.js index 1a563b500ca2..118ba925c62f 100644 --- a/packages/jest-util/src/buffered_console.js +++ b/packages/jest-util/src/buffered_console.js @@ -41,6 +41,7 @@ export default class BufferedConsole extends Console { message: LogMessage, level: ?number, ) { + // TODO: This callsite needs to read sourcemaps const call = callsites()[level != null ? level : 2]; const origin = call.getFileName() + ':' + call.getLineNumber(); From 0c1dd5c37b7886ea46797990e9edda882b9073e5 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sat, 17 Feb 2018 15:56:18 +0100 Subject: [PATCH 02/15] update changelog --- CHANGELOG.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f9bc1036e5c..507e81ab5b90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,15 @@ ### Fixes -* `[jest-cli]` Don't skip matchers for exact files ([#5582](https://github.com/facebook/jest/pull/5582)) -* `[docs]` Update discord links ([#5586](https://github.com/facebook/jest/pull/5586)) +* `[jest-cli]` Don't skip matchers for exact files + ([#5582](https://github.com/facebook/jest/pull/5582)) +* `[docs]` Update discord links + ([#5586](https://github.com/facebook/jest/pull/5586)) * `[jest-runtime]` Align handling of testRegex on Windows between searching for tests and instrumentation checks ([#5560](https://github.com/facebook/jest/pull/5560)) +* `[babel-jest]` Remove `retainLines` argument to babel. + ([#5594](https://github.com/facebook/jest/pull/5594)) ### Features From 8f9e54f82a977455175d58c69cba6bc4778a7d9f Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Sat, 17 Feb 2018 16:31:10 -0500 Subject: [PATCH 03/15] Move callsite to jest-util, add sourcemap support --- packages/jest-jasmine2/package.json | 3 +- packages/jest-jasmine2/src/index.js | 16 +----- packages/jest-runner/src/run_test.js | 13 ++++- packages/jest-runtime/src/index.js | 7 ++- packages/jest-util/package.json | 3 +- packages/jest-util/src/buffered_console.js | 10 ++-- packages/jest-util/src/get_callsite.js | 63 ++++++++++++++++++++++ packages/jest-util/src/index.js | 2 + types/SourceMaps.js | 10 ++++ 9 files changed, 103 insertions(+), 24 deletions(-) create mode 100644 packages/jest-util/src/get_callsite.js create mode 100644 types/SourceMaps.js diff --git a/packages/jest-jasmine2/package.json b/packages/jest-jasmine2/package.json index eab3c664b1ea..9b3020cde3ca 100644 --- a/packages/jest-jasmine2/package.json +++ b/packages/jest-jasmine2/package.json @@ -8,7 +8,6 @@ "license": "MIT", "main": "build/index.js", "dependencies": { - "callsites": "^2.0.0", "chalk": "^2.0.1", "co": "^4.6.0", "expect": "^22.3.0", @@ -18,7 +17,7 @@ "jest-matcher-utils": "^22.2.0", "jest-message-util": "^22.2.0", "jest-snapshot": "^22.2.0", - "source-map": "^0.6.0", + "jest-util": "^22.3.0", "source-map-support": "^0.5.0" }, "devDependencies": { diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 557dbf44e031..563890834653 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -15,8 +15,7 @@ import type {TestResult} from 'types/TestResult'; import type Runtime from 'jest-runtime'; import path from 'path'; -import callsites from 'callsites'; -import {SourceMapConsumer} from 'source-map'; +import {getCallsite} from 'jest-util'; import JasmineReporter from './reporter'; import {install as jasmineAsyncInstall} from './jasmine_async'; @@ -86,19 +85,8 @@ async function jasmine2( if (config.testLocationInResults === true) { const originalIt = environment.global.it; environment.global.it = (...args) => { - const stack = callsites()[1]; + const stack = getCallsite(1, runtime.getSourceMaps()); const it = originalIt(...args); - const sourceMapForFile = runtime.getSourceMapForFile(stack.getFileName()); - - if (sourceMapForFile) { - try { - const consumer = new SourceMapConsumer(sourceMapForFile); - - extendCallsite(stack, consumer); - } catch (e) { - // ignored - } - } it.result.__callsite = stack; diff --git a/packages/jest-runner/src/run_test.js b/packages/jest-runner/src/run_test.js index 0a225dbaad1f..7fc0743bdf22 100644 --- a/packages/jest-runner/src/run_test.js +++ b/packages/jest-runner/src/run_test.js @@ -21,6 +21,7 @@ import { NullConsole, getConsoleOutput, setGlobal, + getCallsite, } from 'jest-util'; import jasmine2 from 'jest-jasmine2'; import LeakDetector from 'jest-leak-detector'; @@ -74,13 +75,21 @@ async function runTestInternal( RuntimeClass, >); + let runtime = undefined; + const consoleOut = globalConfig.useStderr ? process.stderr : process.stdout; const consoleFormatter = (type, message) => getConsoleOutput( config.cwd, !!globalConfig.verbose, // 4 = the console call is buried 4 stack frames deep - BufferedConsole.write([], type, message, 4), + BufferedConsole.write( + [], + type, + message, + 4, + runtime && runtime.getSourceMaps(), + ), ); let testConsole; @@ -101,7 +110,7 @@ async function runTestInternal( const cacheFS = {[path]: testSource}; setGlobal(environment.global, 'console', testConsole); - const runtime = new Runtime(config, environment, resolver, cacheFS, { + runtime = new Runtime(config, environment, resolver, cacheFS, { collectCoverage: globalConfig.collectCoverage, collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index a5fc74186037..f235265caf21 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -15,6 +15,7 @@ import type {Context} from 'types/Context'; import type {Jest, LocalModuleRequire} from 'types/Jest'; import type {ModuleMap} from 'jest-haste-map'; import type {MockFunctionMetadata, ModuleMocker} from 'types/Mock'; +import type {SourceMapRegistry} from 'types/SourceMaps'; import path from 'path'; import HasteMap from 'jest-haste-map'; @@ -100,7 +101,7 @@ class Runtime { _shouldAutoMock: boolean; _shouldMockModuleCache: BooleanObject; _shouldUnmockTransitiveDependenciesCache: BooleanObject; - _sourceMapRegistry: {[key: string]: string, __proto__: null}; + _sourceMapRegistry: SourceMapRegistry; _scriptTransformer: ScriptTransformer; _transitiveShouldMock: BooleanObject; _unmockList: ?RegExp; @@ -459,6 +460,10 @@ class Runtime { return null; } + getSourceMaps(): SourceMapRegistry { + return this._sourceMapRegistry; + } + setMock( from: string, moduleName: string, diff --git a/packages/jest-util/package.json b/packages/jest-util/package.json index 0e378d8ea03c..f26f8521dce4 100644 --- a/packages/jest-util/package.json +++ b/packages/jest-util/package.json @@ -13,7 +13,8 @@ "graceful-fs": "^4.1.11", "is-ci": "^1.0.10", "jest-message-util": "^22.2.0", - "mkdirp": "^0.5.1" + "mkdirp": "^0.5.1", + "source-map": "^0.6.0" }, "devDependencies": { "jest-mock": "^22.2.0" diff --git a/packages/jest-util/src/buffered_console.js b/packages/jest-util/src/buffered_console.js index 118ba925c62f..61ba96b41e71 100644 --- a/packages/jest-util/src/buffered_console.js +++ b/packages/jest-util/src/buffered_console.js @@ -15,10 +15,12 @@ import type { LogTimers, } from 'types/Console'; +import type {SourceMapRegistry} from 'types/SourceMaps'; + import {Console} from 'console'; import {format} from 'util'; import chalk from 'chalk'; -import callsites from 'callsites'; +import getCallsite from './get_callsite'; export default class BufferedConsole extends Console { _buffer: ConsoleBuffer; @@ -40,10 +42,10 @@ export default class BufferedConsole extends Console { type: LogType, message: LogMessage, level: ?number, + sourceMaps: ?SourceMapRegistry, ) { - // TODO: This callsite needs to read sourcemaps - const call = callsites()[level != null ? level : 2]; - const origin = call.getFileName() + ':' + call.getLineNumber(); + const callsite = getCallsite(level != null ? level : 2, sourceMaps); + const origin = callsite.getFileName() + ':' + callsite.getLineNumber(); buffer.push({ message, diff --git a/packages/jest-util/src/get_callsite.js b/packages/jest-util/src/get_callsite.js new file mode 100644 index 000000000000..8c5c5cf63f87 --- /dev/null +++ b/packages/jest-util/src/get_callsite.js @@ -0,0 +1,63 @@ +import {SourceMapRegistry} from 'types/SourceMaps'; + +import fs from 'fs'; +import callsites from 'callsites'; +import {SourceMapConsumer} from 'source-map'; + +// Copied from https://github.com/rexxars/sourcemap-decorate-callsites/blob/5b9735a156964973a75dc62fd2c7f0c1975458e8/lib/index.js#L113-L158 +const addSourceMapConsumer = (callsite, consumer) => { + try { + const getLineNumber = callsite.getLineNumber; + const getColumnNumber = callsite.getColumnNumber; + let position = null; + + function getPosition() { + if (!position) { + position = consumer.originalPositionFor({ + column: getColumnNumber.call(callsite), + line: getLineNumber.call(callsite), + }); + } + + return position; + } + + Object.defineProperties(callsite, { + getColumnNumber: { + value() { + return getPosition().column || getColumnNumber.call(callsite); + }, + writable: false, + }, + getLineNumber: { + value() { + return getPosition().line || getLineNumber.call(callsite); + }, + writable: false, + }, + }); + + return callsite; + } catch (e) { + // ignored + } +}; + +export default (level: number, sourceMaps: SourceMapRegistry) => { + const sites = callsites(); + const call = sites[level + 1]; + const sourceMapFileName = sourceMaps && sourceMaps[call.getFileName()]; + + try { + if (sourceMaps && sourceMapFileName) { + const fileData = fs.readFileSync(sourceMapFileName, 'utf8'); + if (fileData) { + addSourceMapConsumer(call, new SourceMapConsumer(fileData)); + } + } + + return call; + } catch (e) { + return null; + } +}; diff --git a/packages/jest-util/src/index.js b/packages/jest-util/src/index.js index 1b3a6cf27b20..be4389bfa810 100644 --- a/packages/jest-util/src/index.js +++ b/packages/jest-util/src/index.js @@ -19,6 +19,7 @@ import getConsoleOutput from './get_console_output'; import installCommonGlobals from './install_common_globals'; import NullConsole from './null_console'; import isInteractive from './is_interative'; +import getCallsite from './get_callsite'; import setGlobal from './set_global'; import deepCyclicCopy from './deep_cyclic_copy'; @@ -41,6 +42,7 @@ module.exports = { createDirectory, deepCyclicCopy, formatTestResults, + getCallsite, getConsoleOutput, getFailedSnapshotTests, installCommonGlobals, diff --git a/types/SourceMaps.js b/types/SourceMaps.js new file mode 100644 index 000000000000..aa21bae1252e --- /dev/null +++ b/types/SourceMaps.js @@ -0,0 +1,10 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + +export type SourceMapRegistry = {[key: string]: string, __proto__: null}; From ab818920e1f7b118ab0edc177f0005a1181a590f Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Sat, 17 Feb 2018 16:36:10 -0500 Subject: [PATCH 04/15] This is a type --- packages/jest-util/src/get_callsite.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jest-util/src/get_callsite.js b/packages/jest-util/src/get_callsite.js index 8c5c5cf63f87..a4714e90be8c 100644 --- a/packages/jest-util/src/get_callsite.js +++ b/packages/jest-util/src/get_callsite.js @@ -1,4 +1,4 @@ -import {SourceMapRegistry} from 'types/SourceMaps'; +import type {SourceMapRegistry} from 'types/SourceMaps'; import fs from 'fs'; import callsites from 'callsites'; From 8e50d0f2ce6a8460e46c4a80621fff1fe028efbe Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Sat, 17 Feb 2018 16:38:57 -0500 Subject: [PATCH 05/15] Remove unused function moved to jest-util --- packages/jest-jasmine2/src/index.js | 35 ----------------------------- 1 file changed, 35 deletions(-) diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 563890834653..c6172a27b641 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -21,41 +21,6 @@ import {install as jasmineAsyncInstall} from './jasmine_async'; const JASMINE = require.resolve('./jasmine/jasmine_light.js'); -// Copied from https://github.com/rexxars/sourcemap-decorate-callsites/blob/5b9735a156964973a75dc62fd2c7f0c1975458e8/lib/index.js#L113-L158 -function extendCallsite(callsite, consumer) { - const getLineNumber = callsite.getLineNumber; - const getColumnNumber = callsite.getColumnNumber; - let position = null; - - function getPosition() { - if (!position) { - position = consumer.originalPositionFor({ - column: getColumnNumber.call(callsite), - line: getLineNumber.call(callsite), - }); - } - - return position; - } - - Object.defineProperties(callsite, { - getColumnNumber: { - value() { - return getPosition().column || getColumnNumber.call(callsite); - }, - writable: false, - }, - getLineNumber: { - value() { - return getPosition().line || getLineNumber.call(callsite); - }, - writable: false, - }, - }); - - return callsite; -} - async function jasmine2( globalConfig: GlobalConfig, config: ProjectConfig, From 6ad720291dab63110b09e3d6a10c48fa72fe50ed Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Sat, 17 Feb 2018 16:55:23 -0500 Subject: [PATCH 06/15] Fix lint --- packages/jest-runner/src/run_test.js | 1 - packages/jest-runtime/src/index.js | 5 +++-- packages/jest-util/src/get_callsite.js | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/jest-runner/src/run_test.js b/packages/jest-runner/src/run_test.js index 7fc0743bdf22..0f0f545ecfb2 100644 --- a/packages/jest-runner/src/run_test.js +++ b/packages/jest-runner/src/run_test.js @@ -21,7 +21,6 @@ import { NullConsole, getConsoleOutput, setGlobal, - getCallsite, } from 'jest-util'; import jasmine2 from 'jest-jasmine2'; import LeakDetector from 'jest-leak-detector'; diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index f235265caf21..bf1fd6b34bfe 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -453,10 +453,11 @@ class Runtime { getSourceMapForFile(filename: string): ?string { const sourceMap = this._sourceMapRegistry[filename]; - if (sourceMap && fs.existsSync(sourceMap)) { + try { return fs.readFileSync(sourceMap, 'utf8'); + } catch (e) { + // ignore } - return null; } diff --git a/packages/jest-util/src/get_callsite.js b/packages/jest-util/src/get_callsite.js index a4714e90be8c..72eac0617dd5 100644 --- a/packages/jest-util/src/get_callsite.js +++ b/packages/jest-util/src/get_callsite.js @@ -36,8 +36,6 @@ const addSourceMapConsumer = (callsite, consumer) => { writable: false, }, }); - - return callsite; } catch (e) { // ignored } From 6ec7b74d5ee8b1f7d113e132f804d25609127524 Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Sat, 17 Feb 2018 17:00:03 -0500 Subject: [PATCH 07/15] Minor clean `up --- packages/jest-util/src/get_callsite.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/jest-util/src/get_callsite.js b/packages/jest-util/src/get_callsite.js index 72eac0617dd5..b286cf837a4c 100644 --- a/packages/jest-util/src/get_callsite.js +++ b/packages/jest-util/src/get_callsite.js @@ -42,19 +42,19 @@ const addSourceMapConsumer = (callsite, consumer) => { }; export default (level: number, sourceMaps: SourceMapRegistry) => { - const sites = callsites(); - const call = sites[level + 1]; - const sourceMapFileName = sourceMaps && sourceMaps[call.getFileName()]; + const levelAfterThisCall = level + 1; + const stack = callsites()[levelAfterThisCall]; + const sourceMapFileName = sourceMaps && sourceMaps[stack.getFileName()]; try { - if (sourceMaps && sourceMapFileName) { - const fileData = fs.readFileSync(sourceMapFileName, 'utf8'); - if (fileData) { - addSourceMapConsumer(call, new SourceMapConsumer(fileData)); + if (sourceMapFileName) { + const sourceMap = fs.readFileSync(sourceMapFileName, 'utf8'); + if (sourceMap) { + addSourceMapConsumer(stack, new SourceMapConsumer(sourceMap)); } } - return call; + return stack; } catch (e) { return null; } From 11948b86df6e5920c906dc027adcd517ed031058 Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Sat, 17 Feb 2018 18:25:29 -0500 Subject: [PATCH 08/15] Feedback updates --- packages/jest-jasmine2/src/index.js | 12 +++-- packages/jest-runtime/src/index.js | 11 ---- packages/jest-util/src/get_callsite.js | 72 ++++++++++++-------------- 3 files changed, 42 insertions(+), 53 deletions(-) diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index c6172a27b641..98e4cca044a9 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -15,6 +15,7 @@ import type {TestResult} from 'types/TestResult'; import type Runtime from 'jest-runtime'; import path from 'path'; +import fs from 'graceful-fs'; import {getCallsite} from 'jest-util'; import JasmineReporter from './reporter'; import {install as jasmineAsyncInstall} from './jasmine_async'; @@ -124,14 +125,19 @@ async function jasmine2( environment: 'node', handleUncaughtExceptions: false, retrieveSourceMap: source => { - const sourceMap = runtime.getSourceMapForFile(source); - if (sourceMap) { + const sourceMaps = runtime.getSourceMaps(); + const sourceMapSource = sourceMaps && sourceMaps[source]; + + if (sourceMapSource) { try { + const sourceMap = fs.readFileSync(sourceMapSource, 'utf8'); return { map: JSON.parse(sourceMap), url: source, }; - } catch (e) {} + } catch (e) { + // ignore + } } return null; }, diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index bf1fd6b34bfe..7783e415a1fd 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -450,17 +450,6 @@ class Runtime { }, {}); } - getSourceMapForFile(filename: string): ?string { - const sourceMap = this._sourceMapRegistry[filename]; - - try { - return fs.readFileSync(sourceMap, 'utf8'); - } catch (e) { - // ignore - } - return null; - } - getSourceMaps(): SourceMapRegistry { return this._sourceMapRegistry; } diff --git a/packages/jest-util/src/get_callsite.js b/packages/jest-util/src/get_callsite.js index b286cf837a4c..cf487969a3ac 100644 --- a/packages/jest-util/src/get_callsite.js +++ b/packages/jest-util/src/get_callsite.js @@ -6,56 +6,50 @@ import {SourceMapConsumer} from 'source-map'; // Copied from https://github.com/rexxars/sourcemap-decorate-callsites/blob/5b9735a156964973a75dc62fd2c7f0c1975458e8/lib/index.js#L113-L158 const addSourceMapConsumer = (callsite, consumer) => { - try { - const getLineNumber = callsite.getLineNumber; - const getColumnNumber = callsite.getColumnNumber; - let position = null; - - function getPosition() { - if (!position) { - position = consumer.originalPositionFor({ - column: getColumnNumber.call(callsite), - line: getLineNumber.call(callsite), - }); - } - - return position; + const getLineNumber = callsite.getLineNumber; + const getColumnNumber = callsite.getColumnNumber; + let position = null; + + function getPosition() { + if (!position) { + position = consumer.originalPositionFor({ + column: getColumnNumber.call(callsite), + line: getLineNumber.call(callsite), + }); } - Object.defineProperties(callsite, { - getColumnNumber: { - value() { - return getPosition().column || getColumnNumber.call(callsite); - }, - writable: false, + return position; + } + + Object.defineProperties(callsite, { + getColumnNumber: { + value() { + return getPosition().column || getColumnNumber.call(callsite); }, - getLineNumber: { - value() { - return getPosition().line || getLineNumber.call(callsite); - }, - writable: false, + writable: false, + }, + getLineNumber: { + value() { + return getPosition().line || getLineNumber.call(callsite); }, - }); - } catch (e) { - // ignored - } + writable: false, + }, + }); }; -export default (level: number, sourceMaps: SourceMapRegistry) => { +export default (level: number, sourceMaps?: SourceMapRegistry) => { const levelAfterThisCall = level + 1; const stack = callsites()[levelAfterThisCall]; const sourceMapFileName = sourceMaps && sourceMaps[stack.getFileName()]; - try { - if (sourceMapFileName) { + if (sourceMapFileName) { + try { const sourceMap = fs.readFileSync(sourceMapFileName, 'utf8'); - if (sourceMap) { - addSourceMapConsumer(stack, new SourceMapConsumer(sourceMap)); - } + addSourceMapConsumer(stack, new SourceMapConsumer(sourceMap)); + } catch (e) { + // ignore } - - return stack; - } catch (e) { - return null; } + + return stack; }; From 765f78a758ac7cdb41f1aba46344ca842ff23678 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 18 Feb 2018 08:48:52 +0100 Subject: [PATCH 09/15] fix flow violations and minimize diff --- packages/jest-jasmine2/src/index.js | 7 ++----- packages/jest-util/src/get_callsite.js | 13 +++++++++++-- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/jest-jasmine2/src/index.js b/packages/jest-jasmine2/src/index.js index 98e4cca044a9..3e822d1420c8 100644 --- a/packages/jest-jasmine2/src/index.js +++ b/packages/jest-jasmine2/src/index.js @@ -130,14 +130,11 @@ async function jasmine2( if (sourceMapSource) { try { - const sourceMap = fs.readFileSync(sourceMapSource, 'utf8'); return { - map: JSON.parse(sourceMap), + map: JSON.parse(fs.readFileSync(sourceMapSource)), url: source, }; - } catch (e) { - // ignore - } + } catch (e) {} } return null; }, diff --git a/packages/jest-util/src/get_callsite.js b/packages/jest-util/src/get_callsite.js index cf487969a3ac..b3600e063405 100644 --- a/packages/jest-util/src/get_callsite.js +++ b/packages/jest-util/src/get_callsite.js @@ -1,6 +1,15 @@ +/** + * Copyright (c) 2014-present, Facebook, Inc. All rights reserved. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow + */ + import type {SourceMapRegistry} from 'types/SourceMaps'; -import fs from 'fs'; +import fs from 'graceful-fs'; import callsites from 'callsites'; import {SourceMapConsumer} from 'source-map'; @@ -37,7 +46,7 @@ const addSourceMapConsumer = (callsite, consumer) => { }); }; -export default (level: number, sourceMaps?: SourceMapRegistry) => { +export default (level: number, sourceMaps: ?SourceMapRegistry) => { const levelAfterThisCall = level + 1; const stack = callsites()[levelAfterThisCall]; const sourceMapFileName = sourceMaps && sourceMaps[stack.getFileName()]; From f0c6e08aa8b49e963fe64019f87b69d4188c3c75 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Sun, 18 Feb 2018 08:53:56 +0100 Subject: [PATCH 10/15] add todo --- packages/jest-runner/src/run_test.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/jest-runner/src/run_test.js b/packages/jest-runner/src/run_test.js index 0f0f545ecfb2..2267731639d7 100644 --- a/packages/jest-runner/src/run_test.js +++ b/packages/jest-runner/src/run_test.js @@ -98,6 +98,7 @@ async function runTestInternal( } else if (globalConfig.verbose) { testConsole = new Console(consoleOut, process.stderr, consoleFormatter); } else { + // TODO: Should `BufferedConsole` receive `consoleFormatter` as well? testConsole = new BufferedConsole(); } From 7ce154d2a6421ab8313f937d2a7766c69ebdf647 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Mon, 19 Feb 2018 23:10:40 +0100 Subject: [PATCH 11/15] use sourcemaps in buffered console as well --- packages/jest-runner/src/run_test.js | 3 +-- packages/jest-util/src/buffered_console.js | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/jest-runner/src/run_test.js b/packages/jest-runner/src/run_test.js index 2267731639d7..a209ffca7c51 100644 --- a/packages/jest-runner/src/run_test.js +++ b/packages/jest-runner/src/run_test.js @@ -98,8 +98,7 @@ async function runTestInternal( } else if (globalConfig.verbose) { testConsole = new Console(consoleOut, process.stderr, consoleFormatter); } else { - // TODO: Should `BufferedConsole` receive `consoleFormatter` as well? - testConsole = new BufferedConsole(); + testConsole = new BufferedConsole(() => runtime && runtime.getSourceMaps()); } const environment = new TestEnvironment(config, {console: testConsole}); diff --git a/packages/jest-util/src/buffered_console.js b/packages/jest-util/src/buffered_console.js index cd755ccf467a..8a9b9912cc27 100644 --- a/packages/jest-util/src/buffered_console.js +++ b/packages/jest-util/src/buffered_console.js @@ -28,10 +28,15 @@ export default class BufferedConsole extends Console { _counters: LogCounters; _timers: LogTimers; _groupDepth: number; + _getSourceMaps: () => ?SourceMapRegistry; - constructor() { + constructor(getSourceMaps: () => ?SourceMapRegistry) { const buffer = []; - super({write: message => BufferedConsole.write(buffer, 'log', message)}); + super({ + write: message => + BufferedConsole.write(buffer, 'log', message, null, getSourceMaps()), + }); + this._getSourceMaps = getSourceMaps; this._buffer = buffer; this._counters = {}; this._timers = {}; @@ -63,6 +68,7 @@ export default class BufferedConsole extends Console { type, ' '.repeat(this._groupDepth) + message, 3, + this._getSourceMasp(), ); } From 3f2ccb8c834198981050f2a2434568f58fec90db Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Tue, 20 Feb 2018 00:16:01 +0100 Subject: [PATCH 12/15] fix stupid typo --- packages/jest-util/src/__tests__/buffered_console.test.js | 2 +- packages/jest-util/src/buffered_console.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/jest-util/src/__tests__/buffered_console.test.js b/packages/jest-util/src/__tests__/buffered_console.test.js index 103b9091a81b..ede81e84c810 100644 --- a/packages/jest-util/src/__tests__/buffered_console.test.js +++ b/packages/jest-util/src/__tests__/buffered_console.test.js @@ -19,7 +19,7 @@ describe('CustomConsole', () => { .join('\n'); beforeEach(() => { - _console = new BufferedConsole(); + _console = new BufferedConsole(() => null); }); describe('assert', () => { diff --git a/packages/jest-util/src/buffered_console.js b/packages/jest-util/src/buffered_console.js index 8a9b9912cc27..5cee80665474 100644 --- a/packages/jest-util/src/buffered_console.js +++ b/packages/jest-util/src/buffered_console.js @@ -68,7 +68,7 @@ export default class BufferedConsole extends Console { type, ' '.repeat(this._groupDepth) + message, 3, - this._getSourceMasp(), + this._getSourceMaps(), ); } From e73423d7a9fead1c3eb2429c314f0dcc60738fba Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Tue, 20 Feb 2018 11:40:50 -0500 Subject: [PATCH 13/15] Add unit tests for get_callsite --- .../src/__tests__/get_callsite.test.js | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 packages/jest-util/src/__tests__/get_callsite.test.js diff --git a/packages/jest-util/src/__tests__/get_callsite.test.js b/packages/jest-util/src/__tests__/get_callsite.test.js new file mode 100644 index 000000000000..964cafa9f9f8 --- /dev/null +++ b/packages/jest-util/src/__tests__/get_callsite.test.js @@ -0,0 +1,58 @@ +import fs from 'fs'; +import SourceMap from 'source-map'; +import getCallsite from '../get_callsite'; + +jest.mock('fs'); + +describe('getCallsite', () => { + beforeEach(() => { + fs.readFileSync = jest.fn(); + }); + + test('without source map', () => { + const site = getCallsite(0); + + expect(site.getFileName()).toEqual(__filename); + expect(site.getColumnNumber()).toEqual(expect.any(Number)); + expect(site.getLineNumber()).toEqual(expect.any(Number)); + expect(fs.readFileSync).not.toHaveBeenCalled(); + }); + + test('ignores errors when fs throws', () => { + fs.readFileSync.mockImplementation(() => { + throw new Error('Mock error'); + }); + + const site = getCallsite(0, {[__filename]: 'mockedSourceMapFile'}); + + expect(site.getFileName()).toEqual(__filename); + expect(site.getColumnNumber()).toEqual(expect.any(Number)); + expect(site.getLineNumber()).toEqual(expect.any(Number)); + expect(fs.readFileSync).toHaveBeenCalledWith('mockedSourceMapFile', 'utf8'); + }); + + test('reads source map file to determine line and column', () => { + const sourceMapColumn = 1; + const sourceMapLine = 2; + SourceMap.SourceMapConsumer = class { + originalPositionFor(params) { + expect(params).toMatchObject({ + column: expect.any(Number), + line: expect.any(Number), + }); + + return { + column: sourceMapColumn, + line: sourceMapLine, + }; + } + }; + + const site = getCallsite(0, {[__filename]: 'mockedSourceMapFile'}); + + expect(site.getFileName()).toEqual(__filename); + expect(site.getColumnNumber()).toEqual(sourceMapColumn); + expect(site.getLineNumber()).toEqual(sourceMapLine); + expect(fs.readFileSync).toHaveBeenCalledWith('mockedSourceMapFile', 'utf8'); + }); +}); From 0a29175b7b01c987e0f10d213f93fd5922022912 Mon Sep 17 00:00:00 2001 From: rickhanlonii Date: Tue, 20 Feb 2018 14:00:54 -0500 Subject: [PATCH 14/15] Fix tests --- packages/jest-util/src/__tests__/get_callsite.test.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/jest-util/src/__tests__/get_callsite.test.js b/packages/jest-util/src/__tests__/get_callsite.test.js index 964cafa9f9f8..c6f3237c126c 100644 --- a/packages/jest-util/src/__tests__/get_callsite.test.js +++ b/packages/jest-util/src/__tests__/get_callsite.test.js @@ -5,10 +5,6 @@ import getCallsite from '../get_callsite'; jest.mock('fs'); describe('getCallsite', () => { - beforeEach(() => { - fs.readFileSync = jest.fn(); - }); - test('without source map', () => { const site = getCallsite(0); @@ -32,6 +28,8 @@ describe('getCallsite', () => { }); test('reads source map file to determine line and column', () => { + fs.readFileSync.mockImplementation(() => 'file data'); + const sourceMapColumn = 1; const sourceMapLine = 2; SourceMap.SourceMapConsumer = class { From 736eb2b20fe9db1a14a2e3012dff5a3a95673ca1 Mon Sep 17 00:00:00 2001 From: Simen Bekkhus Date: Wed, 21 Feb 2018 07:46:46 +0100 Subject: [PATCH 15/15] move changelog entry --- CHANGELOG.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 088dd0f45ef4..97fa9b96adce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,14 @@ * `[jest-runtime]` Provide `require.main` property set to module with test suite ([#5618](https://github.com/facebook/jest/pull/5618)) + +### Fixes + +* `[babel-jest]` Remove `retainLines` argument to babel. + ([#5594](https://github.com/facebook/jest/pull/5594)) + +### Chore & Maintenance + * `[docs]` Add note about Node version support ([#5622](https://github.com/facebook/jest/pull/5622)) * `[docs]` Update to use yarn @@ -30,8 +38,6 @@ ([#5505](https://github.com/facebook/jest/pull/5505)) * `[jest-util]` Fix `console.assert` behavior in custom & buffered consoles ([#5576](https://github.com/facebook/jest/pull/5576)) -* `[babel-jest]` Remove `retainLines` argument to babel. - ([#5594](https://github.com/facebook/jest/pull/5594)) ### Features