diff --git a/CHANGELOG.md b/CHANGELOG.md index 88cc0354d2c1..c0abed449e6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ - `[jest-resolve]`: Migrate to TypeScript ([#7871](https://github.com/facebook/jest/pull/7871)) - `[@jest/reporter]`: New package extracted from `jest-cli` ([#7902](https://github.com/facebook/jest/pull/7902)) - `[jest-snapshot]`: Migrate to TypeScript ([#7899](https://github.com/facebook/jest/pull/7899)) +- `[@jest/transform]`: New package extracted from `jest-runtime` ([#7915](https://github.com/facebook/jest/pull/7915)) ### Performance diff --git a/packages/jest-cli/package.json b/packages/jest-cli/package.json index c168519633fc..4267412020a5 100644 --- a/packages/jest-cli/package.json +++ b/packages/jest-cli/package.json @@ -5,6 +5,7 @@ "main": "build/jest.js", "dependencies": { "@jest/reporters": "^24.1.0", + "@jest/transform": "^24.1.0", "ansi-escapes": "^3.0.0", "chalk": "^2.0.1", "exit": "^0.1.2", diff --git a/packages/jest-cli/src/runGlobalHook.js b/packages/jest-cli/src/runGlobalHook.js index 855d21df57e3..6c89f943f4f0 100644 --- a/packages/jest-cli/src/runGlobalHook.js +++ b/packages/jest-cli/src/runGlobalHook.js @@ -13,7 +13,7 @@ import type {Test} from 'types/TestRunner'; import {extname} from 'path'; import pEachSeries from 'p-each-series'; import {addHook} from 'pirates'; -import Runtime from 'jest-runtime'; +import {ScriptTransformer} from '@jest/transform'; // copied from https://github.com/babel/babel/blob/56044c7851d583d498f919e9546caddf8f80a72f/packages/babel-helpers/src/helpers.js#L558-L562 function _interopRequireDefault(obj) { @@ -52,7 +52,7 @@ export default ({ : // Fallback to first config allTests[0].context.config; - const transformer = new Runtime.ScriptTransformer(projectConfig); + const transformer = new ScriptTransformer(projectConfig); // Load the transformer to avoid a cycle where we need to load a // transformer in order to transform it in the require hooks diff --git a/packages/jest-reporters/package.json b/packages/jest-reporters/package.json index ac961627707c..fceb1f9e0de0 100644 --- a/packages/jest-reporters/package.json +++ b/packages/jest-reporters/package.json @@ -4,10 +4,10 @@ "version": "24.1.0", "main": "build/index.js", "dependencies": { + "@jest/transform": "^24.1.0", "chalk": "^2.0.1", "exit": "^0.1.2", "glob": "^7.1.2", - "jest-runtime": "^24.1.0", "istanbul-api": "^2.1.1", "istanbul-lib-coverage": "^2.0.2", "istanbul-lib-instrument": "^3.0.1", diff --git a/packages/jest-reporters/src/__tests__/generateEmptyCoverage.test.js b/packages/jest-reporters/src/__tests__/generateEmptyCoverage.test.js index 00e97f93a024..de5b901249fd 100644 --- a/packages/jest-reporters/src/__tests__/generateEmptyCoverage.test.js +++ b/packages/jest-reporters/src/__tests__/generateEmptyCoverage.test.js @@ -6,18 +6,19 @@ * * @flow */ -'use strict'; import istanbulCoverage from 'istanbul-lib-coverage'; import libSourceMaps from 'istanbul-lib-source-maps'; import generateEmptyCoverage from '../generateEmptyCoverage'; -import Runtime from 'jest-runtime'; -const path = require('path'); -const os = require('os'); -const {makeGlobalConfig, makeProjectConfig} = require('../../../../TestUtils'); +import path from 'path'; +import os from 'os'; +import {makeGlobalConfig, makeProjectConfig} from '../../../../TestUtils'; -jest.spyOn(Runtime, 'shouldInstrument').mockImplementation(() => true); +jest.mock('@jest/transform', () => ({ + ...jest.requireActual('@jest/transform'), + shouldInstrument: () => true, +})); const src = ` throw new Error('this should not be thrown'); diff --git a/packages/jest-reporters/src/generateEmptyCoverage.js b/packages/jest-reporters/src/generateEmptyCoverage.js index d43f2de65dab..493d251646d6 100644 --- a/packages/jest-reporters/src/generateEmptyCoverage.js +++ b/packages/jest-reporters/src/generateEmptyCoverage.js @@ -11,7 +11,7 @@ import type {GlobalConfig, ProjectConfig, Path} from 'types/Config'; import {readInitialCoverage} from 'istanbul-lib-instrument'; import {classes} from 'istanbul-lib-coverage'; -import Runtime from 'jest-runtime'; +import {shouldInstrument, ScriptTransformer} from '@jest/transform'; export type CoverageWorkerResult = {| coverage: any, @@ -33,9 +33,9 @@ export default function( collectCoverageFrom: globalConfig.collectCoverageFrom, collectCoverageOnlyFrom: globalConfig.collectCoverageOnlyFrom, }; - if (Runtime.shouldInstrument(filename, coverageOptions, config)) { + if (shouldInstrument(filename, coverageOptions, config)) { // Transform file with instrumentation to make sure initial coverage data is well mapped to original code. - const {code, mapCoverage, sourceMapPath} = new Runtime.ScriptTransformer( + const {code, mapCoverage, sourceMapPath} = new ScriptTransformer( config, ).transformSource(filename, source, true); const extracted = readInitialCoverage(code); diff --git a/packages/jest-runtime/package.json b/packages/jest-runtime/package.json index 8524b6900536..a4890ce50f79 100644 --- a/packages/jest-runtime/package.json +++ b/packages/jest-runtime/package.json @@ -9,12 +9,9 @@ "license": "MIT", "main": "build/index.js", "dependencies": { - "@babel/core": "^7.1.0", - "babel-plugin-istanbul": "^5.1.0", + "@jest/transform": "^24.1.0", "chalk": "^2.0.1", - "convert-source-map": "^1.4.0", "exit": "^0.1.2", - "fast-json-stable-stringify": "^2.0.0", "glob": "^7.1.3", "graceful-fs": "^4.1.15", "jest-config": "^24.1.0", @@ -25,24 +22,18 @@ "jest-snapshot": "^24.1.0", "jest-util": "^24.0.0", "jest-validate": "^24.0.0", - "micromatch": "^3.1.10", "realpath-native": "^1.1.0", "slash": "^2.0.0", "strip-bom": "^3.0.0", - "write-file-atomic": "2.4.1", "yargs": "^12.0.2" }, "devDependencies": { - "@types/babel__core": "^7.0.4", - "@types/convert-source-map": "^1.5.1", "@types/exit": "^0.1.30", "@types/glob": "^7.1.1", "@types/graceful-fs": "^4.1.2", - "@types/micromatch": "^3.1.0", - "@types/strip-bom": "3.0.0", - "@types/write-file-atomic": "^2.1.1", + "@types/slash": "^2.0.0", + "@types/strip-bom": "^3.0.0", "@types/yargs": "^12.0.2", - "jest-environment-jsdom": "^24.0.0", "jest-environment-node": "^24.0.0" }, "bin": { diff --git a/packages/jest-runtime/src/__tests__/instrumentation.test.js b/packages/jest-runtime/src/__tests__/instrumentation.test.js index 8a6ce4be03d8..8f6188d86ca3 100644 --- a/packages/jest-runtime/src/__tests__/instrumentation.test.js +++ b/packages/jest-runtime/src/__tests__/instrumentation.test.js @@ -11,7 +11,7 @@ import vm from 'vm'; import path from 'path'; import os from 'os'; -import ScriptTransformer from '../ScriptTransformer'; +import {ScriptTransformer} from '@jest/transform'; jest.mock('vm'); diff --git a/packages/jest-runtime/src/helpers.js b/packages/jest-runtime/src/helpers.js index c80f82755d4c..19265d836044 100644 --- a/packages/jest-runtime/src/helpers.js +++ b/packages/jest-runtime/src/helpers.js @@ -5,41 +5,9 @@ import type {Path} from 'types/Config'; import path from 'path'; -import chalk from 'chalk'; import slash from 'slash'; import glob from 'glob'; -const DOT = ' \u2022 '; - -export const enhanceUnexpectedTokenMessage = (e: Error) => { - e.stack = - `${chalk.bold.red('Jest encountered an unexpected token')} - -This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript. - -By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules". - -Here's what you can do: -${DOT}To have some of your "node_modules" files transformed, you can specify a custom ${chalk.bold( - '"transformIgnorePatterns"', - )} in your config. -${DOT}If you need a custom transformation specify a ${chalk.bold( - '"transform"', - )} option in your config. -${DOT}If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the ${chalk.bold( - '"moduleNameMapper"', - )} config option. - -You'll find more details and examples of these config options in the docs: -${chalk.cyan('https://jestjs.io/docs/en/configuration.html')} - -${chalk.bold.red('Details:')} - -` + e.stack; - - return e; -}; - export const findSiblingsWithFileExtension = ( moduleFileExtensions: Array, from: Path, diff --git a/packages/jest-runtime/src/index.js b/packages/jest-runtime/src/index.js index 2f7290c73711..e6f393eef733 100644 --- a/packages/jest-runtime/src/index.js +++ b/packages/jest-runtime/src/index.js @@ -24,10 +24,9 @@ import Resolver from 'jest-resolve'; import {createDirectory, deepCyclicCopy} from 'jest-util'; import {escapePathForRegex} from 'jest-regex-util'; import Snapshot from 'jest-snapshot'; +import {ScriptTransformer, shouldInstrument} from '@jest/transform'; import fs from 'graceful-fs'; import stripBOM from 'strip-bom'; -import ScriptTransformer from './ScriptTransformer'; -import shouldInstrument from './shouldInstrument'; import {run as cliRun} from './cli'; import {options as cliOptions} from './cli/args'; import {findSiblingsWithFileExtension} from './helpers'; diff --git a/packages/jest-transform/.npmignore b/packages/jest-transform/.npmignore new file mode 100644 index 000000000000..85e48fe7b0a4 --- /dev/null +++ b/packages/jest-transform/.npmignore @@ -0,0 +1,3 @@ +**/__mocks__/** +**/__tests__/** +src diff --git a/packages/jest-transform/package.json b/packages/jest-transform/package.json new file mode 100644 index 000000000000..345321986283 --- /dev/null +++ b/packages/jest-transform/package.json @@ -0,0 +1,37 @@ +{ + "name": "@jest/transform", + "version": "24.1.0", + "repository": { + "type": "git", + "url": "https://github.com/facebook/jest.git", + "directory": "packages/jest-transform" + }, + "license": "MIT", + "main": "build/index.js", + "dependencies": { + "@babel/core": "^7.1.0", + "babel-plugin-istanbul": "^5.1.0", + "chalk": "^2.0.1", + "convert-source-map": "^1.4.0", + "fast-json-stable-stringify": "^2.0.0", + "graceful-fs": "^4.1.15", + "jest-haste-map": "^24.0.0", + "jest-regex-util": "^24.0.0", + "jest-util": "^24.0.0", + "micromatch": "^3.1.10", + "realpath-native": "^1.1.0", + "slash": "^2.0.0", + "write-file-atomic": "2.4.1" + }, + "devDependencies": { + "@types/babel__core": "^7.0.4", + "@types/convert-source-map": "^1.5.1", + "@types/graceful-fs": "^4.1.2", + "@types/micromatch": "^3.1.0", + "@types/write-file-atomic": "^2.1.1" + }, + "engines": { + "node": ">= 6" + }, + "gitHead": "b16789230fd45056a7f2fa199bae06c7a1780deb" +} diff --git a/packages/jest-runtime/src/ScriptTransformer.js b/packages/jest-transform/src/ScriptTransformer.js similarity index 97% rename from packages/jest-runtime/src/ScriptTransformer.js rename to packages/jest-transform/src/ScriptTransformer.js index 72ba88f9fabd..44b5959fb39e 100644 --- a/packages/jest-runtime/src/ScriptTransformer.js +++ b/packages/jest-transform/src/ScriptTransformer.js @@ -7,13 +7,14 @@ * @flow */ -import type {Glob, Path, ProjectConfig} from 'types/Config'; +import type {Path, ProjectConfig} from 'types/Config'; import type { Transformer, TransformedSource, TransformResult, } from 'types/Transform'; import type {ErrorWithCode} from 'types/Errors'; +import type {Options} from './types'; import crypto from 'crypto'; import path from 'path'; @@ -30,17 +31,7 @@ import {version as VERSION} from '../package.json'; import shouldInstrument from './shouldInstrument'; import writeFileAtomic from 'write-file-atomic'; import {sync as realpath} from 'realpath-native'; -import {enhanceUnexpectedTokenMessage} from './helpers'; - -export type Options = {| - changedFiles: ?Set, - collectCoverage: boolean, - collectCoverageFrom: Array, - collectCoverageOnlyFrom: ?{[key: string]: boolean, __proto__: null}, - extraGlobals?: Array, - isCoreModule?: boolean, - isInternalModule?: boolean, -|}; +import enhanceUnexpectedTokenMessage from './enhanceUnexpectedTokenMessage'; type ProjectCache = {| configString: string, @@ -175,7 +166,7 @@ export default class ScriptTransformer { auxiliaryCommentBefore: ' istanbul ignore next ', babelrc: false, caller: { - name: 'jest-runtime', + name: '@jest/transform', supportsStaticESM: false, }, configFile: false, diff --git a/packages/jest-runtime/src/__tests__/__snapshots__/script_transformer.test.js.snap b/packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap similarity index 100% rename from packages/jest-runtime/src/__tests__/__snapshots__/script_transformer.test.js.snap rename to packages/jest-transform/src/__tests__/__snapshots__/script_transformer.test.js.snap diff --git a/packages/jest-runtime/src/__tests__/script_transformer.test.js b/packages/jest-transform/src/__tests__/script_transformer.test.js similarity index 99% rename from packages/jest-runtime/src/__tests__/script_transformer.test.js rename to packages/jest-transform/src/__tests__/script_transformer.test.js index 7058e0f22f31..bc61eaa04b1b 100644 --- a/packages/jest-runtime/src/__tests__/script_transformer.test.js +++ b/packages/jest-transform/src/__tests__/script_transformer.test.js @@ -32,11 +32,10 @@ jest .mock('jest-haste-map', () => ({ getCacheFilePath: (cacheDir, baseDir, version) => cacheDir + baseDir, })) - .mock('jest-util', () => { - const util = jest.requireActual('jest-util'); - util.createDirectory = jest.fn(); - return util; - }) + .mock('jest-util', () => ({ + ...jest.requireActual('jest-util'), + createDirectory: jest.fn(), + })) .mock('vm') .mock('path', () => jest.requireActual('path').posix); diff --git a/packages/jest-runtime/src/__tests__/should_instrument.test.js b/packages/jest-transform/src/__tests__/should_instrument.test.js similarity index 98% rename from packages/jest-runtime/src/__tests__/should_instrument.test.js rename to packages/jest-transform/src/__tests__/should_instrument.test.js index dc3ba29e8ce3..c05dacc5677e 100644 --- a/packages/jest-runtime/src/__tests__/should_instrument.test.js +++ b/packages/jest-transform/src/__tests__/should_instrument.test.js @@ -6,20 +6,15 @@ * */ -import {normalize} from 'jest-config'; import shouldInstrument from '../shouldInstrument'; +import {makeGlobalConfig} from '../../../../TestUtils'; describe('shouldInstrument', () => { const defaultFilename = 'source_file.test.js'; const defaultOptions = { collectCoverage: true, }; - const defaultConfig = normalize( - { - rootDir: '/', - }, - {}, - ).options; + const defaultConfig = makeGlobalConfig({rootDir: '/'}); describe('should return true', () => { const testShouldInstrument = ( diff --git a/packages/jest-transform/src/enhanceUnexpectedTokenMessage.js b/packages/jest-transform/src/enhanceUnexpectedTokenMessage.js new file mode 100644 index 000000000000..af941fa7cf53 --- /dev/null +++ b/packages/jest-transform/src/enhanceUnexpectedTokenMessage.js @@ -0,0 +1,36 @@ +// Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved. + +// @flow + +import chalk from 'chalk'; + +const DOT = ' \u2022 '; + +export default function enhanceUnexpectedTokenMessage(e: Error) { + e.stack = + `${chalk.bold.red('Jest encountered an unexpected token')} + +This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript. + +By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules". + +Here's what you can do: +${DOT}To have some of your "node_modules" files transformed, you can specify a custom ${chalk.bold( + '"transformIgnorePatterns"', + )} in your config. +${DOT}If you need a custom transformation specify a ${chalk.bold( + '"transform"', + )} option in your config. +${DOT}If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the ${chalk.bold( + '"moduleNameMapper"', + )} config option. + +You'll find more details and examples of these config options in the docs: +${chalk.cyan('https://jestjs.io/docs/en/configuration.html')} + +${chalk.bold.red('Details:')} + +` + e.stack; + + return e; +} diff --git a/packages/jest-transform/src/index.js b/packages/jest-transform/src/index.js new file mode 100644 index 000000000000..37cbb258b92a --- /dev/null +++ b/packages/jest-transform/src/index.js @@ -0,0 +1,11 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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 {default as ScriptTransformer} from './ScriptTransformer'; +export {default as shouldInstrument} from './shouldInstrument'; diff --git a/packages/jest-runtime/src/shouldInstrument.js b/packages/jest-transform/src/shouldInstrument.js similarity index 98% rename from packages/jest-runtime/src/shouldInstrument.js rename to packages/jest-transform/src/shouldInstrument.js index ecfe24fb14f1..c0b869d4318b 100644 --- a/packages/jest-runtime/src/shouldInstrument.js +++ b/packages/jest-transform/src/shouldInstrument.js @@ -8,7 +8,7 @@ */ import type {Path, ProjectConfig} from 'types/Config'; -import type {Options} from './ScriptTransformer'; +import type {Options} from './types'; import path from 'path'; import {escapePathForRegex} from 'jest-regex-util'; diff --git a/packages/jest-transform/src/types.js b/packages/jest-transform/src/types.js new file mode 100644 index 000000000000..00f577bdad80 --- /dev/null +++ b/packages/jest-transform/src/types.js @@ -0,0 +1,21 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. 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 {Glob, Path} from 'types/Config'; + +// TODO: Pick from `GlobalConfig` +export type Options = {| + changedFiles: ?Set, + collectCoverage: boolean, + collectCoverageFrom: Array, + collectCoverageOnlyFrom: ?{[key: string]: boolean, __proto__: null}, + extraGlobals?: Array, + isCoreModule?: boolean, + isInternalModule?: boolean, +|}; diff --git a/yarn.lock b/yarn.lock index d14756f8cfac..467177c5e637 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1801,7 +1801,7 @@ resolved "https://registry.yarnpkg.com/@types/strip-ansi/-/strip-ansi-3.0.0.tgz#9b63d453a6b54aa849182207711a08be8eea48ae" integrity sha1-m2PUU6a1SqhJGCIHcRoIvo7qSK4= -"@types/strip-bom@3.0.0": +"@types/strip-bom@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" integrity sha1-FKjsOVbC6B7bdSB5CuzyHCkK69I=