123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- // Copied from several files in node's source code.
- // https://github.com/nodejs/node/blob/2d5d77306f6dff9110c1f77fefab25f973415770/lib/internal/modules/cjs/loader.js
- // Each function and variable below must have a comment linking to the source in node's github repo.
- const path = require('path');
- const packageJsonReader = require('./node-package-json-reader');
- const {JSONParse} = require('./node-primordials');
- module.exports.assertScriptCanLoadAsCJSImpl = assertScriptCanLoadAsCJSImpl;
- // copied from Module._extensions['.js']
- // https://github.com/nodejs/node/blob/v15.3.0/lib/internal/modules/cjs/loader.js#L1113-L1120
- function assertScriptCanLoadAsCJSImpl(filename) {
- const pkg = readPackageScope(filename);
- // Function require shouldn't be used in ES modules.
- if (pkg && pkg.data && pkg.data.type === 'module') {
- const parentPath = module.parent && module.parent.filename;
- const packageJsonPath = path.resolve(pkg.path, 'package.json');
- throw createErrRequireEsm(filename, parentPath, packageJsonPath);
- }
- }
- // Copied from https://github.com/nodejs/node/blob/2d5d77306f6dff9110c1f77fefab25f973415770/lib/internal/modules/cjs/loader.js#L285-L301
- function readPackageScope(checkPath) {
- const rootSeparatorIndex = checkPath.indexOf(path.sep);
- let separatorIndex;
- while (
- (separatorIndex = checkPath.lastIndexOf(path.sep)) > rootSeparatorIndex
- ) {
- checkPath = checkPath.slice(0, separatorIndex);
- if (checkPath.endsWith(path.sep + 'node_modules'))
- return false;
- const pjson = readPackage(checkPath);
- if (pjson) return {
- path: checkPath,
- data: pjson
- };
- }
- return false;
- }
- // Copied from https://github.com/nodejs/node/blob/2d5d77306f6dff9110c1f77fefab25f973415770/lib/internal/modules/cjs/loader.js#L249
- const packageJsonCache = new Map();
- // Copied from https://github.com/nodejs/node/blob/v15.3.0/lib/internal/modules/cjs/loader.js#L275-L304
- function readPackage(requestPath) {
- const jsonPath = path.resolve(requestPath, 'package.json');
- const existing = packageJsonCache.get(jsonPath);
- if (existing !== undefined) return existing;
- const result = packageJsonReader.read(jsonPath);
- const json = result.containsKeys === false ? '{}' : result.string;
- if (json === undefined) {
- packageJsonCache.set(jsonPath, false);
- return false;
- }
- try {
- const parsed = JSONParse(json);
- const filtered = {
- name: parsed.name,
- main: parsed.main,
- exports: parsed.exports,
- imports: parsed.imports,
- type: parsed.type
- };
- packageJsonCache.set(jsonPath, filtered);
- return filtered;
- } catch (e) {
- e.path = jsonPath;
- e.message = 'Error parsing ' + jsonPath + ': ' + e.message;
- throw e;
- }
- }
- // Native ERR_REQUIRE_ESM Error is declared here:
- // https://github.com/nodejs/node/blob/2d5d77306f6dff9110c1f77fefab25f973415770/lib/internal/errors.js#L1294-L1313
- // Error class factory is implemented here:
- // function E: https://github.com/nodejs/node/blob/2d5d77306f6dff9110c1f77fefab25f973415770/lib/internal/errors.js#L323-L341
- // function makeNodeErrorWithCode: https://github.com/nodejs/node/blob/2d5d77306f6dff9110c1f77fefab25f973415770/lib/internal/errors.js#L251-L278
- // The code below should create an error that matches the native error as closely as possible.
- // Third-party libraries which attempt to catch the native ERR_REQUIRE_ESM should recognize our imitation error.
- function createErrRequireEsm(filename, parentPath, packageJsonPath) {
- const code = 'ERR_REQUIRE_ESM'
- const err = new Error(getMessage(filename, parentPath, packageJsonPath))
- // Set `name` to be used in stack trace, generate stack trace with that name baked in, then re-declare the `name` field.
- // This trick is copied from node's source.
- err.name = `Error [${ code }]`
- err.stack
- Object.defineProperty(err, 'name', {
- value: 'Error',
- enumerable: false,
- writable: true,
- configurable: true
- })
- err.code = code
- return err
- // Copy-pasted from https://github.com/nodejs/node/blob/b533fb3508009e5f567cc776daba8fbf665386a6/lib/internal/errors.js#L1293-L1311
- // so that our error message is identical to the native message.
- function getMessage(filename, parentPath = null, packageJsonPath = null) {
- const ext = path.extname(filename)
- let msg = `Must use import to load ES Module: ${filename}`;
- if (parentPath && packageJsonPath) {
- const path = require('path');
- const basename = path.basename(filename) === path.basename(parentPath) ?
- filename : path.basename(filename);
- msg +=
- '\nrequire() of ES modules is not supported.\nrequire() of ' +
- `${filename} ${parentPath ? `from ${parentPath} ` : ''}` +
- `is an ES module file as it is a ${ext} file whose nearest parent ` +
- `package.json contains "type": "module" which defines all ${ext} ` +
- 'files in that package scope as ES modules.\nInstead ' +
- 'change the requiring code to use ' +
- 'import(), or remove "type": "module" from ' +
- `${packageJsonPath}.\n`;
- return msg;
- }
- return msg;
- }
- }
|