UNPKG

mocha

Version:

simple, flexible, fun test framework

110 lines (103 loc) 3.55 kB
const path = require('path'); const url = require('url'); const formattedImport = async file => { if (path.isAbsolute(file)) { try { return await import(url.pathToFileURL(file)); } catch (err) { // This is a hack created because ESM in Node.js (at least in Node v15.5.1) does not emit // the location of the syntax error in the error thrown. // This is problematic because the user can't see what file has the problem, // so we add the file location to the error. // This `if` should be removed once Node.js fixes the problem. if ( err instanceof SyntaxError && err.message && err.stack && !err.stack.includes(file) ) { const newErrorWithFilename = new SyntaxError(err.message); newErrorWithFilename.stack = err.stack.replace( /^SyntaxError/, `SyntaxError[ @${file} ]` ); throw newErrorWithFilename; } throw err; } } return import(file); }; const hasStableEsmImplementation = (() => { const [major, minor] = process.version.split('.'); // ESM is stable from v12.22.0 onward // https://nodejs.org/api/esm.html#esm_modules_ecmascript_modules const majorNumber = parseInt(major.slice(1), 10); const minorNumber = parseInt(minor, 10); return majorNumber > 12 || (majorNumber === 12 && minorNumber >= 22); })(); exports.requireOrImport = hasStableEsmImplementation ? async file => { if (path.extname(file) === '.mjs') { return formattedImport(file); } try { return dealWithExports(await formattedImport(file)); } catch (err) { if ( err.code === 'ERR_MODULE_NOT_FOUND' || err.code === 'ERR_UNKNOWN_FILE_EXTENSION' || err.code === 'ERR_UNSUPPORTED_DIR_IMPORT' ) { try { return require(file); } catch (requireErr) { if (requireErr.code === 'ERR_REQUIRE_ESM') { // This happens when the test file is a JS file, but via type:module is actually ESM, // AND has an import to a file that doesn't exist. // This throws an `ERR_MODULE_NOT_FOUND` // error above, // and when we try to `require` it here, it throws an `ERR_REQUIRE_ESM`. // What we want to do is throw the original error (the `ERR_MODULE_NOT_FOUND`), // and not the `ERR_REQUIRE_ESM` error, which is a red herring. throw err; } else { throw requireErr; } } } else { throw err; } } } : implementationOfRequireOrImportForUnstableEsm; function dealWithExports(module) { if (module.default) { return module.default; } else { return {...module, default: undefined}; } } exports.loadFilesAsync = async (files, preLoadFunc, postLoadFunc) => { for (const file of files) { preLoadFunc(file); const result = await exports.requireOrImport(path.resolve(file)); postLoadFunc(file, result); } }; /* istanbul ignore next */ async function implementationOfRequireOrImportForUnstableEsm(file) { if (path.extname(file) === '.mjs') { return formattedImport(file); } // This is currently the only known way of figuring out whether a file is CJS or ESM in // Node.js that doesn't necessitate calling `import` first. try { return require(file); } catch (err) { if (err.code === 'ERR_REQUIRE_ESM') { return formattedImport(file); } else { throw err; } } }