12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115 |
- 'use strict';
- Object.defineProperty(exports, '__esModule', {
- value: true
- });
- exports.createScriptTransformer = createScriptTransformer;
- exports.createTranspilingRequire = createTranspilingRequire;
- function _crypto() {
- const data = require('crypto');
- _crypto = function () {
- return data;
- };
- return data;
- }
- function path() {
- const data = _interopRequireWildcard(require('path'));
- path = function () {
- return data;
- };
- return data;
- }
- function _core() {
- const data = require('@babel/core');
- _core = function () {
- return data;
- };
- return data;
- }
- function _babelPluginIstanbul() {
- const data = _interopRequireDefault(require('babel-plugin-istanbul'));
- _babelPluginIstanbul = function () {
- return data;
- };
- return data;
- }
- function _convertSourceMap() {
- const data = require('convert-source-map');
- _convertSourceMap = function () {
- return data;
- };
- return data;
- }
- function _fastJsonStableStringify() {
- const data = _interopRequireDefault(require('fast-json-stable-stringify'));
- _fastJsonStableStringify = function () {
- return data;
- };
- return data;
- }
- function fs() {
- const data = _interopRequireWildcard(require('graceful-fs'));
- fs = function () {
- return data;
- };
- return data;
- }
- function _pirates() {
- const data = require('pirates');
- _pirates = function () {
- return data;
- };
- return data;
- }
- function _slash() {
- const data = _interopRequireDefault(require('slash'));
- _slash = function () {
- return data;
- };
- return data;
- }
- function _writeFileAtomic() {
- const data = require('write-file-atomic');
- _writeFileAtomic = function () {
- return data;
- };
- return data;
- }
- function _jestHasteMap() {
- const data = _interopRequireDefault(require('jest-haste-map'));
- _jestHasteMap = function () {
- return data;
- };
- return data;
- }
- function _jestUtil() {
- const data = require('jest-util');
- _jestUtil = function () {
- return data;
- };
- return data;
- }
- var _enhanceUnexpectedTokenMessage = _interopRequireDefault(
- require('./enhanceUnexpectedTokenMessage')
- );
- var _runtimeErrorsAndWarnings = require('./runtimeErrorsAndWarnings');
- var _shouldInstrument = _interopRequireDefault(require('./shouldInstrument'));
- function _interopRequireDefault(obj) {
- return obj && obj.__esModule ? obj : {default: obj};
- }
- function _getRequireWildcardCache(nodeInterop) {
- if (typeof WeakMap !== 'function') return null;
- var cacheBabelInterop = new WeakMap();
- var cacheNodeInterop = new WeakMap();
- return (_getRequireWildcardCache = function (nodeInterop) {
- return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
- })(nodeInterop);
- }
- function _interopRequireWildcard(obj, nodeInterop) {
- if (!nodeInterop && obj && obj.__esModule) {
- return obj;
- }
- if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
- return {default: obj};
- }
- var cache = _getRequireWildcardCache(nodeInterop);
- if (cache && cache.has(obj)) {
- return cache.get(obj);
- }
- var newObj = {};
- var hasPropertyDescriptor =
- Object.defineProperty && Object.getOwnPropertyDescriptor;
- for (var key in obj) {
- if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
- var desc = hasPropertyDescriptor
- ? Object.getOwnPropertyDescriptor(obj, key)
- : null;
- if (desc && (desc.get || desc.set)) {
- Object.defineProperty(newObj, key, desc);
- } else {
- newObj[key] = obj[key];
- }
- }
- }
- newObj.default = obj;
- if (cache) {
- cache.set(obj, newObj);
- }
- return newObj;
- }
- function _defineProperty(obj, key, value) {
- if (key in obj) {
- Object.defineProperty(obj, key, {
- value: value,
- enumerable: true,
- configurable: true,
- writable: true
- });
- } else {
- obj[key] = value;
- }
- return obj;
- }
- // Use `require` to avoid TS rootDir
- const {version: VERSION} = require('../package.json');
- // This data structure is used to avoid recalculating some data every time that
- // we need to transform a file. Since ScriptTransformer is instantiated for each
- // file we need to keep this object in the local scope of this module.
- const projectCaches = new Map(); // To reset the cache for specific changesets (rather than package version).
- const CACHE_VERSION = '1';
- async function waitForPromiseWithCleanup(promise, cleanup) {
- try {
- await promise;
- } finally {
- cleanup();
- }
- }
- class ScriptTransformer {
- constructor(_config, _cacheFS) {
- _defineProperty(this, '_cache', void 0);
- _defineProperty(this, '_transformCache', new Map());
- _defineProperty(this, '_transformsAreLoaded', false);
- this._config = _config;
- this._cacheFS = _cacheFS;
- const configString = (0, _fastJsonStableStringify().default)(this._config);
- let projectCache = projectCaches.get(configString);
- if (!projectCache) {
- projectCache = {
- configString,
- ignorePatternsRegExp: calcIgnorePatternRegExp(this._config),
- transformRegExp: calcTransformRegExp(this._config),
- transformedFiles: new Map()
- };
- projectCaches.set(configString, projectCache);
- }
- this._cache = projectCache;
- }
- _buildCacheKeyFromFileInfo(
- fileData,
- filename,
- transformOptions,
- transformerCacheKey
- ) {
- if (transformerCacheKey) {
- return (0, _crypto().createHash)('md5')
- .update(transformerCacheKey)
- .update(CACHE_VERSION)
- .digest('hex');
- }
- return (0, _crypto().createHash)('md5')
- .update(fileData)
- .update(transformOptions.configString)
- .update(transformOptions.instrument ? 'instrument' : '')
- .update(filename)
- .update(CACHE_VERSION)
- .digest('hex');
- }
- _getCacheKey(fileData, filename, options) {
- const configString = this._cache.configString;
- const {transformer, transformerConfig = {}} =
- this._getTransformer(filename) || {};
- let transformerCacheKey = undefined;
- const transformOptions = {
- ...options,
- cacheFS: this._cacheFS,
- config: this._config,
- configString,
- transformerConfig
- };
- if (
- typeof (transformer === null || transformer === void 0
- ? void 0
- : transformer.getCacheKey) === 'function'
- ) {
- transformerCacheKey = transformer.getCacheKey(
- fileData,
- filename,
- transformOptions
- );
- }
- return this._buildCacheKeyFromFileInfo(
- fileData,
- filename,
- transformOptions,
- transformerCacheKey
- );
- }
- async _getCacheKeyAsync(fileData, filename, options) {
- const configString = this._cache.configString;
- const {transformer, transformerConfig = {}} =
- this._getTransformer(filename) || {};
- let transformerCacheKey = undefined;
- const transformOptions = {
- ...options,
- cacheFS: this._cacheFS,
- config: this._config,
- configString,
- transformerConfig
- };
- if (transformer) {
- const getCacheKey =
- transformer.getCacheKeyAsync || transformer.getCacheKey;
- if (typeof getCacheKey === 'function') {
- transformerCacheKey = await getCacheKey(
- fileData,
- filename,
- transformOptions
- );
- }
- }
- return this._buildCacheKeyFromFileInfo(
- fileData,
- filename,
- transformOptions,
- transformerCacheKey
- );
- }
- _createFolderFromCacheKey(filename, cacheKey) {
- const HasteMapClass = _jestHasteMap().default.getStatic(this._config);
- const baseCacheDir = HasteMapClass.getCacheFilePath(
- this._config.cacheDirectory,
- 'jest-transform-cache-' + this._config.name,
- VERSION
- ); // Create sub folders based on the cacheKey to avoid creating one
- // directory with many files.
- const cacheDir = path().join(baseCacheDir, cacheKey[0] + cacheKey[1]);
- const cacheFilenamePrefix = path()
- .basename(filename, path().extname(filename))
- .replace(/\W/g, '');
- const cachePath = (0, _slash().default)(
- path().join(cacheDir, cacheFilenamePrefix + '_' + cacheKey)
- );
- (0, _jestUtil().createDirectory)(cacheDir);
- return cachePath;
- }
- _getFileCachePath(filename, content, options) {
- const cacheKey = this._getCacheKey(content, filename, options);
- return this._createFolderFromCacheKey(filename, cacheKey);
- }
- async _getFileCachePathAsync(filename, content, options) {
- const cacheKey = await this._getCacheKeyAsync(content, filename, options);
- return this._createFolderFromCacheKey(filename, cacheKey);
- }
- _getTransformPath(filename) {
- const transformRegExp = this._cache.transformRegExp;
- if (!transformRegExp) {
- return undefined;
- }
- for (let i = 0; i < transformRegExp.length; i++) {
- if (transformRegExp[i][0].test(filename)) {
- return transformRegExp[i][1];
- }
- }
- return undefined;
- }
- async loadTransformers() {
- await Promise.all(
- this._config.transform.map(
- async ([, transformPath, transformerConfig]) => {
- let transformer = await (0, _jestUtil().requireOrImportModule)(
- transformPath
- );
- if (!transformer) {
- throw new Error(
- (0, _runtimeErrorsAndWarnings.makeInvalidTransformerError)(
- transformPath
- )
- );
- }
- if (typeof transformer.createTransformer === 'function') {
- transformer = transformer.createTransformer(transformerConfig);
- }
- if (
- typeof transformer.process !== 'function' &&
- typeof transformer.processAsync !== 'function'
- ) {
- throw new Error(
- (0, _runtimeErrorsAndWarnings.makeInvalidTransformerError)(
- transformPath
- )
- );
- }
- const res = {
- transformer,
- transformerConfig
- };
- this._transformCache.set(transformPath, res);
- }
- )
- );
- this._transformsAreLoaded = true;
- }
- _getTransformer(filename) {
- if (!this._transformsAreLoaded) {
- throw new Error(
- 'Jest: Transformers have not been loaded yet - make sure to run `loadTransformers` and wait for it to complete before starting to transform files'
- );
- }
- if (this._config.transform.length === 0) {
- return null;
- }
- const transformPath = this._getTransformPath(filename);
- if (!transformPath) {
- return null;
- }
- const cached = this._transformCache.get(transformPath);
- if (cached) {
- return cached;
- }
- throw new Error(
- `Jest was unable to load the transformer defined for ${filename}. This is a bug in Jest, please open up an issue`
- );
- }
- _instrumentFile(filename, input, canMapToInput, options) {
- const inputCode = typeof input === 'string' ? input : input.code;
- const inputMap = typeof input === 'string' ? null : input.map;
- const result = (0, _core().transformSync)(inputCode, {
- auxiliaryCommentBefore: ' istanbul ignore next ',
- babelrc: false,
- caller: {
- name: '@jest/transform',
- supportsDynamicImport: options.supportsDynamicImport,
- supportsExportNamespaceFrom: options.supportsExportNamespaceFrom,
- supportsStaticESM: options.supportsStaticESM,
- supportsTopLevelAwait: options.supportsTopLevelAwait
- },
- configFile: false,
- filename,
- plugins: [
- [
- _babelPluginIstanbul().default,
- {
- compact: false,
- // files outside `cwd` will not be instrumented
- cwd: this._config.rootDir,
- exclude: [],
- extension: false,
- inputSourceMap: inputMap,
- useInlineSourceMaps: false
- }
- ]
- ],
- sourceMaps: canMapToInput ? 'both' : false
- });
- if (result && result.code) {
- return result;
- }
- return input;
- }
- _buildTransformResult(
- filename,
- cacheFilePath,
- content,
- transformer,
- shouldCallTransform,
- options,
- processed,
- sourceMapPath
- ) {
- let transformed = {
- code: content,
- map: null
- };
- if (transformer && shouldCallTransform) {
- if (typeof processed === 'string') {
- transformed.code = processed;
- } else if (processed != null && typeof processed.code === 'string') {
- transformed = processed;
- } else {
- throw new Error(
- (0, _runtimeErrorsAndWarnings.makeInvalidReturnValueError)()
- );
- }
- }
- if (!transformed.map) {
- try {
- //Could be a potential freeze here.
- //See: https://github.com/facebook/jest/pull/5177#discussion_r158883570
- const inlineSourceMap = (0, _convertSourceMap().fromSource)(
- transformed.code
- );
- if (inlineSourceMap) {
- transformed.map = inlineSourceMap.toObject();
- }
- } catch {
- const transformPath = this._getTransformPath(filename);
- invariant(transformPath);
- console.warn(
- (0, _runtimeErrorsAndWarnings.makeInvalidSourceMapWarning)(
- filename,
- transformPath
- )
- );
- }
- } // That means that the transform has a custom instrumentation
- // logic and will handle it based on `config.collectCoverage` option
- const transformWillInstrument =
- shouldCallTransform && transformer && transformer.canInstrument; // Apply instrumentation to the code if necessary, keeping the instrumented code and new map
- let map = transformed.map;
- let code;
- if (!transformWillInstrument && options.instrument) {
- /**
- * We can map the original source code to the instrumented code ONLY if
- * - the process of transforming the code produced a source map e.g. ts-jest
- * - we did not transform the source code
- *
- * Otherwise we cannot make any statements about how the instrumented code corresponds to the original code,
- * and we should NOT emit any source maps
- *
- */
- const shouldEmitSourceMaps =
- (transformer != null && map != null) || transformer == null;
- const instrumented = this._instrumentFile(
- filename,
- transformed,
- shouldEmitSourceMaps,
- options
- );
- code =
- typeof instrumented === 'string' ? instrumented : instrumented.code;
- map = typeof instrumented === 'string' ? null : instrumented.map;
- } else {
- code = transformed.code;
- }
- if (map) {
- const sourceMapContent =
- typeof map === 'string' ? map : JSON.stringify(map);
- invariant(sourceMapPath, 'We should always have default sourceMapPath');
- writeCacheFile(sourceMapPath, sourceMapContent);
- } else {
- sourceMapPath = null;
- }
- writeCodeCacheFile(cacheFilePath, code);
- return {
- code,
- originalCode: content,
- sourceMapPath
- };
- }
- transformSource(filepath, content, options) {
- const filename = (0, _jestUtil().tryRealpath)(filepath);
- const {transformer, transformerConfig = {}} =
- this._getTransformer(filename) || {};
- const cacheFilePath = this._getFileCachePath(filename, content, options);
- const sourceMapPath = cacheFilePath + '.map'; // Ignore cache if `config.cache` is set (--no-cache)
- const code = this._config.cache ? readCodeCacheFile(cacheFilePath) : null;
- if (code) {
- // This is broken: we return the code, and a path for the source map
- // directly from the cache. But, nothing ensures the source map actually
- // matches that source code. They could have gotten out-of-sync in case
- // two separate processes write concurrently to the same cache files.
- return {
- code,
- originalCode: content,
- sourceMapPath
- };
- }
- let processed = null;
- let shouldCallTransform = false;
- if (transformer && this.shouldTransform(filename)) {
- shouldCallTransform = true;
- assertSyncTransformer(transformer, this._getTransformPath(filename));
- processed = transformer.process(content, filename, {
- ...options,
- cacheFS: this._cacheFS,
- config: this._config,
- configString: this._cache.configString,
- transformerConfig
- });
- }
- return this._buildTransformResult(
- filename,
- cacheFilePath,
- content,
- transformer,
- shouldCallTransform,
- options,
- processed,
- sourceMapPath
- );
- }
- async transformSourceAsync(filepath, content, options) {
- const filename = (0, _jestUtil().tryRealpath)(filepath);
- const {transformer, transformerConfig = {}} =
- this._getTransformer(filename) || {};
- const cacheFilePath = await this._getFileCachePathAsync(
- filename,
- content,
- options
- );
- const sourceMapPath = cacheFilePath + '.map'; // Ignore cache if `config.cache` is set (--no-cache)
- const code = this._config.cache ? readCodeCacheFile(cacheFilePath) : null;
- if (code) {
- // This is broken: we return the code, and a path for the source map
- // directly from the cache. But, nothing ensures the source map actually
- // matches that source code. They could have gotten out-of-sync in case
- // two separate processes write concurrently to the same cache files.
- return {
- code,
- originalCode: content,
- sourceMapPath
- };
- }
- let processed = null;
- let shouldCallTransform = false;
- if (transformer && this.shouldTransform(filename)) {
- shouldCallTransform = true;
- const process = transformer.processAsync || transformer.process; // This is probably dead code since `_getTransformerAsync` already asserts this
- invariant(
- typeof process === 'function',
- 'A transformer must always export either a `process` or `processAsync`'
- );
- processed = await process(content, filename, {
- ...options,
- cacheFS: this._cacheFS,
- config: this._config,
- configString: this._cache.configString,
- transformerConfig
- });
- }
- return this._buildTransformResult(
- filename,
- cacheFilePath,
- content,
- transformer,
- shouldCallTransform,
- options,
- processed,
- sourceMapPath
- );
- }
- async _transformAndBuildScriptAsync(
- filename,
- options,
- transformOptions,
- fileSource
- ) {
- const {isInternalModule} = options;
- let fileContent =
- fileSource !== null && fileSource !== void 0
- ? fileSource
- : this._cacheFS.get(filename);
- if (!fileContent) {
- fileContent = fs().readFileSync(filename, 'utf8');
- this._cacheFS.set(filename, fileContent);
- }
- const content = stripShebang(fileContent);
- let code = content;
- let sourceMapPath = null;
- const willTransform =
- !isInternalModule &&
- (transformOptions.instrument || this.shouldTransform(filename));
- try {
- if (willTransform) {
- const transformedSource = await this.transformSourceAsync(
- filename,
- content,
- transformOptions
- );
- code = transformedSource.code;
- sourceMapPath = transformedSource.sourceMapPath;
- }
- return {
- code,
- originalCode: content,
- sourceMapPath
- };
- } catch (e) {
- throw (0, _enhanceUnexpectedTokenMessage.default)(e);
- }
- }
- _transformAndBuildScript(filename, options, transformOptions, fileSource) {
- const {isInternalModule} = options;
- let fileContent =
- fileSource !== null && fileSource !== void 0
- ? fileSource
- : this._cacheFS.get(filename);
- if (!fileContent) {
- fileContent = fs().readFileSync(filename, 'utf8');
- this._cacheFS.set(filename, fileContent);
- }
- const content = stripShebang(fileContent);
- let code = content;
- let sourceMapPath = null;
- const willTransform =
- !isInternalModule &&
- (transformOptions.instrument || this.shouldTransform(filename));
- try {
- if (willTransform) {
- const transformedSource = this.transformSource(
- filename,
- content,
- transformOptions
- );
- code = transformedSource.code;
- sourceMapPath = transformedSource.sourceMapPath;
- }
- return {
- code,
- originalCode: content,
- sourceMapPath
- };
- } catch (e) {
- throw (0, _enhanceUnexpectedTokenMessage.default)(e);
- }
- }
- async transformAsync(filename, options, fileSource) {
- const instrument =
- options.coverageProvider === 'babel' &&
- (0, _shouldInstrument.default)(filename, options, this._config);
- const scriptCacheKey = getScriptCacheKey(filename, instrument);
- let result = this._cache.transformedFiles.get(scriptCacheKey);
- if (result) {
- return result;
- }
- result = await this._transformAndBuildScriptAsync(
- filename,
- options,
- {...options, instrument},
- fileSource
- );
- if (scriptCacheKey) {
- this._cache.transformedFiles.set(scriptCacheKey, result);
- }
- return result;
- }
- transform(filename, options, fileSource) {
- const instrument =
- options.coverageProvider === 'babel' &&
- (0, _shouldInstrument.default)(filename, options, this._config);
- const scriptCacheKey = getScriptCacheKey(filename, instrument);
- let result = this._cache.transformedFiles.get(scriptCacheKey);
- if (result) {
- return result;
- }
- result = this._transformAndBuildScript(
- filename,
- options,
- {...options, instrument},
- fileSource
- );
- if (scriptCacheKey) {
- this._cache.transformedFiles.set(scriptCacheKey, result);
- }
- return result;
- }
- transformJson(filename, options, fileSource) {
- const {isInternalModule} = options;
- const willTransform = !isInternalModule && this.shouldTransform(filename);
- if (willTransform) {
- const {code: transformedJsonSource} = this.transformSource(
- filename,
- fileSource,
- {...options, instrument: false}
- );
- return transformedJsonSource;
- }
- return fileSource;
- }
- async requireAndTranspileModule(
- moduleName,
- callback,
- options = {
- applyInteropRequireDefault: true,
- instrument: false,
- supportsDynamicImport: false,
- supportsExportNamespaceFrom: false,
- supportsStaticESM: false,
- supportsTopLevelAwait: false
- }
- ) {
- let transforming = false;
- const {applyInteropRequireDefault, ...transformOptions} = options;
- const revertHook = (0, _pirates().addHook)(
- (code, filename) => {
- try {
- transforming = true;
- return (
- this.transformSource(filename, code, transformOptions).code || code
- );
- } finally {
- transforming = false;
- }
- },
- {
- exts: this._config.moduleFileExtensions.map(ext => `.${ext}`),
- ignoreNodeModules: false,
- matcher: filename => {
- if (transforming) {
- // Don't transform any dependency required by the transformer itself
- return false;
- }
- return this.shouldTransform(filename);
- }
- }
- );
- try {
- const module = await (0, _jestUtil().requireOrImportModule)(
- moduleName,
- applyInteropRequireDefault
- );
- if (!callback) {
- revertHook();
- return module;
- }
- const cbResult = callback(module);
- if ((0, _jestUtil().isPromise)(cbResult)) {
- return waitForPromiseWithCleanup(cbResult, revertHook).then(
- () => module
- );
- }
- return module;
- } finally {
- revertHook();
- }
- }
- shouldTransform(filename) {
- const ignoreRegexp = this._cache.ignorePatternsRegExp;
- const isIgnored = ignoreRegexp ? ignoreRegexp.test(filename) : false;
- return this._config.transform.length !== 0 && !isIgnored;
- }
- } // TODO: do we need to define the generics twice?
- async function createTranspilingRequire(config) {
- const transformer = await createScriptTransformer(config);
- return async function requireAndTranspileModule(
- resolverPath,
- applyInteropRequireDefault = false
- ) {
- const transpiledModule = await transformer.requireAndTranspileModule(
- resolverPath,
- () => {},
- {
- applyInteropRequireDefault,
- instrument: false,
- supportsDynamicImport: false,
- // this might be true, depending on node version.
- supportsExportNamespaceFrom: false,
- supportsStaticESM: false,
- supportsTopLevelAwait: false
- }
- );
- return transpiledModule;
- };
- }
- const removeFile = path => {
- try {
- fs().unlinkSync(path);
- } catch {}
- };
- const stripShebang = content => {
- // If the file data starts with a shebang remove it. Leaves the empty line
- // to keep stack trace line numbers correct.
- if (content.startsWith('#!')) {
- return content.replace(/^#!.*/, '');
- } else {
- return content;
- }
- };
- /**
- * This is like `writeCacheFile` but with an additional sanity checksum. We
- * cannot use the same technique for source maps because we expose source map
- * cache file paths directly to callsites, with the expectation they can read
- * it right away. This is not a great system, because source map cache file
- * could get corrupted, out-of-sync, etc.
- */
- function writeCodeCacheFile(cachePath, code) {
- const checksum = (0, _crypto().createHash)('md5').update(code).digest('hex');
- writeCacheFile(cachePath, checksum + '\n' + code);
- }
- /**
- * Read counterpart of `writeCodeCacheFile`. We verify that the content of the
- * file matches the checksum, in case some kind of corruption happened. This
- * could happen if an older version of `jest-runtime` writes non-atomically to
- * the same cache, for example.
- */
- function readCodeCacheFile(cachePath) {
- const content = readCacheFile(cachePath);
- if (content == null) {
- return null;
- }
- const code = content.substring(33);
- const checksum = (0, _crypto().createHash)('md5').update(code).digest('hex');
- if (checksum === content.substring(0, 32)) {
- return code;
- }
- return null;
- }
- /**
- * Writing to the cache atomically relies on 'rename' being atomic on most
- * file systems. Doing atomic write reduces the risk of corruption by avoiding
- * two processes to write to the same file at the same time. It also reduces
- * the risk of reading a file that's being overwritten at the same time.
- */
- const writeCacheFile = (cachePath, fileData) => {
- try {
- (0, _writeFileAtomic().sync)(cachePath, fileData, {
- encoding: 'utf8',
- fsync: false
- });
- } catch (e) {
- if (cacheWriteErrorSafeToIgnore(e, cachePath)) {
- return;
- }
- e.message =
- 'jest: failed to cache transform results in: ' +
- cachePath +
- '\nFailure message: ' +
- e.message;
- removeFile(cachePath);
- throw e;
- }
- };
- /**
- * On Windows, renames are not atomic, leading to EPERM exceptions when two
- * processes attempt to rename to the same target file at the same time.
- * If the target file exists we can be reasonably sure another process has
- * legitimately won a cache write race and ignore the error.
- */
- const cacheWriteErrorSafeToIgnore = (e, cachePath) =>
- process.platform === 'win32' &&
- e.code === 'EPERM' &&
- fs().existsSync(cachePath);
- const readCacheFile = cachePath => {
- if (!fs().existsSync(cachePath)) {
- return null;
- }
- let fileData;
- try {
- fileData = fs().readFileSync(cachePath, 'utf8');
- } catch (e) {
- e.message =
- 'jest: failed to read cache file: ' +
- cachePath +
- '\nFailure message: ' +
- e.message;
- removeFile(cachePath);
- throw e;
- }
- if (fileData == null) {
- // We must have somehow created the file but failed to write to it,
- // let's delete it and retry.
- removeFile(cachePath);
- }
- return fileData;
- };
- const getScriptCacheKey = (filename, instrument) => {
- const mtime = fs().statSync(filename).mtime;
- return filename + '_' + mtime.getTime() + (instrument ? '_instrumented' : '');
- };
- const calcIgnorePatternRegExp = config => {
- if (
- !config.transformIgnorePatterns ||
- config.transformIgnorePatterns.length === 0
- ) {
- return undefined;
- }
- return new RegExp(config.transformIgnorePatterns.join('|'));
- };
- const calcTransformRegExp = config => {
- if (!config.transform.length) {
- return undefined;
- }
- const transformRegexp = [];
- for (let i = 0; i < config.transform.length; i++) {
- transformRegexp.push([
- new RegExp(config.transform[i][0]),
- config.transform[i][1],
- config.transform[i][2]
- ]);
- }
- return transformRegexp;
- };
- function invariant(condition, message) {
- if (!condition) {
- throw new Error(message);
- }
- }
- function assertSyncTransformer(transformer, name) {
- invariant(name);
- invariant(
- typeof transformer.process === 'function',
- (0, _runtimeErrorsAndWarnings.makeInvalidSyncTransformerError)(name)
- );
- }
- async function createScriptTransformer(config, cacheFS = new Map()) {
- const transformer = new ScriptTransformer(config, cacheFS);
- await transformer.loadTransformers();
- return transformer;
- }
|