mirror of
https://github.com/nodejs/node.git
synced 2024-11-24 20:29:23 +01:00
module: deprecate module.parent
This feature does not work when a module is imported using ECMAScript modules specification, therefore it is deprecated. Fixes: https://github.com/nodejs/modules/issues/469 PR-URL: https://github.com/nodejs/node/pull/32217 Reviewed-By: Gus Caplan <me@gus.host> Reviewed-By: Bradley Farias <bradley.meck@gmail.com> Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Tobias Nießen <tniessen@tnie.de> Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
This commit is contained in:
parent
039cd00a9a
commit
6443ab9595
@ -2712,6 +2712,39 @@ The `repl` module exports a `_builtinLibs` property that contains an array with
|
||||
native modules. It was incomplete so far and instead it's better to rely upon
|
||||
`require('module').builtinModules`.
|
||||
|
||||
<a id="DEP0143"></a>
|
||||
### DEP0143: `module.parent`
|
||||
<!-- YAML
|
||||
changes:
|
||||
- version: REPLACEME
|
||||
pr-url: https://github.com/nodejs/node/pull/32217
|
||||
description: Documentation-only deprecation.
|
||||
-->
|
||||
|
||||
Type: Documentation-only (supports [`--pending-deprecation`][])
|
||||
|
||||
A CommonJS module can access the first module that required it using
|
||||
`module.parent`. This feature is deprecated because it does not work
|
||||
consistently in the presence of ECMAScript modules and because it gives an
|
||||
inaccurate representation of the CommonJS module graph.
|
||||
|
||||
Some modules use it to check if they are the entry point of the current process.
|
||||
Instead, it is recommended to compare `require.main` and `module`:
|
||||
|
||||
```js
|
||||
if (require.main === module) {
|
||||
// Code section that will run only if current file is the entry point.
|
||||
}
|
||||
```
|
||||
|
||||
When looking for the CommonJS modules that have required the current one,
|
||||
`require.cache` and `module.children` can be used:
|
||||
|
||||
```js
|
||||
const moduleParents = Object.values(require.cache)
|
||||
.filter((m) => m.children.includes(module));
|
||||
```
|
||||
|
||||
[`--pending-deprecation`]: cli.html#cli_pending_deprecation
|
||||
[`--throw-deprecation`]: cli.html#cli_throw_deprecation
|
||||
[`Buffer.allocUnsafeSlow(size)`]: buffer.html#buffer_class_method_buffer_allocunsafeslow_size
|
||||
|
@ -690,7 +690,6 @@ Module {
|
||||
id: '.',
|
||||
path: '/absolute/path/to',
|
||||
exports: {},
|
||||
parent: null,
|
||||
filename: '/absolute/path/to/entry.js',
|
||||
loaded: false,
|
||||
children: [],
|
||||
@ -894,11 +893,17 @@ loading.
|
||||
### `module.parent`
|
||||
<!-- YAML
|
||||
added: v0.1.16
|
||||
deprecated: REPLACEME
|
||||
-->
|
||||
|
||||
* {module}
|
||||
> Stability: 0 - Deprecated: Please use [`require.main`][] and
|
||||
> [`module.children`][] instead.
|
||||
|
||||
The module that first required this one.
|
||||
* {module | null | undefined}
|
||||
|
||||
The module that first required this one, or `null` if the current module is the
|
||||
entry point of the current process, or `undefined` if the module was loaded by
|
||||
something that is not a CommonJS module (E.G.: REPL or `import`). Read only.
|
||||
|
||||
### `module.path`
|
||||
<!-- YAML
|
||||
@ -1122,6 +1127,7 @@ consists of the following keys:
|
||||
[`createRequire()`]: #modules_module_createrequire_filename
|
||||
[`module` object]: #modules_the_module_object
|
||||
[`module.id`]: #modules_module_id
|
||||
[`module.children`]: #modules_module_children
|
||||
[`path.dirname()`]: path.html#path_path_dirname_path
|
||||
[ECMAScript Modules]: esm.html
|
||||
[an error]: errors.html#errors_err_require_esm
|
||||
@ -1129,6 +1135,7 @@ consists of the following keys:
|
||||
[module resolution]: #modules_all_together
|
||||
[module wrapper]: #modules_the_module_wrapper
|
||||
[native addons]: addons.html
|
||||
[`require.main`]: #modules_require_main
|
||||
[source map include directives]: https://sourcemaps.info/spec.html#h.lmz475t4mvbx
|
||||
[`--enable-source-maps`]: cli.html#cli_enable_source_maps
|
||||
[`NODE_V8_COVERAGE=dir`]: cli.html#cli_node_v8_coverage_dir
|
||||
|
@ -39,6 +39,7 @@ const {
|
||||
ReflectSet,
|
||||
RegExpPrototypeTest,
|
||||
SafeMap,
|
||||
SafeWeakMap,
|
||||
String,
|
||||
StringPrototypeIndexOf,
|
||||
StringPrototypeLastIndexOf,
|
||||
@ -160,11 +161,12 @@ function updateChildren(parent, child, scan) {
|
||||
children.push(child);
|
||||
}
|
||||
|
||||
const moduleParentCache = new SafeWeakMap();
|
||||
function Module(id = '', parent) {
|
||||
this.id = id;
|
||||
this.path = path.dirname(id);
|
||||
this.exports = {};
|
||||
this.parent = parent;
|
||||
moduleParentCache.set(this, parent);
|
||||
updateChildren(parent, this, false);
|
||||
this.filename = null;
|
||||
this.loaded = false;
|
||||
@ -233,6 +235,18 @@ ObjectDefineProperty(Module, 'wrapper', {
|
||||
}
|
||||
});
|
||||
|
||||
function getModuleParent() {
|
||||
return moduleParentCache.get(this);
|
||||
}
|
||||
ObjectDefineProperty(Module.prototype, 'parent', {
|
||||
get: pendingDeprecation ? deprecate(
|
||||
getModuleParent,
|
||||
'module.parent is deprecated due to accuracy issues. Please use ' +
|
||||
'require.main to find program entry point instead.',
|
||||
'DEP0143'
|
||||
) : getModuleParent
|
||||
});
|
||||
|
||||
const debug = require('internal/util/debuglog').debuglog('module');
|
||||
Module._debug = deprecate(debug, 'Module._debug is deprecated.', 'DEP0077');
|
||||
|
||||
@ -1020,7 +1034,7 @@ Module._resolveFilename = function(request, parent, isMain, options) {
|
||||
const requireStack = [];
|
||||
for (let cursor = parent;
|
||||
cursor;
|
||||
cursor = cursor.parent) {
|
||||
cursor = moduleParentCache.get(cursor)) {
|
||||
requireStack.push(cursor.filename || cursor.id);
|
||||
}
|
||||
let message = `Cannot find module '${request}'`;
|
||||
@ -1213,7 +1227,8 @@ Module._extensions['.js'] = function(module, 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 parent = moduleParentCache.get(module);
|
||||
const parentPath = parent && parent.filename;
|
||||
const packageJsonPath = path.resolve(pkg.path, 'package.json');
|
||||
throw new ERR_REQUIRE_ESM(filename, parentPath, packageJsonPath);
|
||||
}
|
||||
|
@ -59,12 +59,12 @@ if (process.argv.length === 2 &&
|
||||
!process.env.NODE_SKIP_FLAG_CHECK &&
|
||||
isMainThread &&
|
||||
hasCrypto &&
|
||||
module.parent &&
|
||||
require.main &&
|
||||
require('cluster').isMaster) {
|
||||
// The copyright notice is relatively big and the flags could come afterwards.
|
||||
const bytesToRead = 1500;
|
||||
const buffer = Buffer.allocUnsafe(bytesToRead);
|
||||
const fd = fs.openSync(module.parent.filename, 'r');
|
||||
const fd = fs.openSync(require.main.filename, 'r');
|
||||
const bytesRead = fs.readSync(fd, buffer, 0, bytesToRead);
|
||||
fs.closeSync(fd);
|
||||
const source = buffer.toString('utf8', 0, bytesRead);
|
||||
|
@ -1,7 +1,7 @@
|
||||
/* eslint-disable node-core/require-common-first, node-core/required-modules */
|
||||
'use strict';
|
||||
|
||||
if (module.parent) {
|
||||
if (require.main !== module) {
|
||||
const { spawnSync } = require('child_process');
|
||||
|
||||
function runModuleAs(filename, flags, spawnOptions, role) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
const common = require('../../common');
|
||||
const assert = require('assert');
|
||||
|
||||
if (module.parent) {
|
||||
if (module !== require.main) {
|
||||
// When required as a module, run the tests.
|
||||
const test_instance_data =
|
||||
require(`./build/${common.buildType}/test_instance_data`);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
const common = require('../../common');
|
||||
|
||||
if (module.parent) {
|
||||
if (module !== require.main) {
|
||||
// When required as a module, run the tests.
|
||||
const test_instance_data =
|
||||
require(`./build/${common.buildType}/test_instance_data`);
|
||||
|
@ -20,7 +20,7 @@
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
'use strict';
|
||||
if (module.parent) {
|
||||
if (module !== require.main) {
|
||||
// Signal we've been loaded as a module.
|
||||
// The following console.log() is part of the test.
|
||||
console.log('Loaded as a module, exiting with status code 42.');
|
||||
|
14
test/parallel/test-module-parent-deprecation.js
Normal file
14
test/parallel/test-module-parent-deprecation.js
Normal file
@ -0,0 +1,14 @@
|
||||
// Flags: --pending-deprecation
|
||||
|
||||
'use strict';
|
||||
const common = require('../common');
|
||||
const assert = require('assert');
|
||||
|
||||
common.expectWarning(
|
||||
'DeprecationWarning',
|
||||
'module.parent is deprecated due to accuracy issues. Please use ' +
|
||||
'require.main to find program entry point instead.',
|
||||
'DEP0143'
|
||||
);
|
||||
|
||||
assert.strictEqual(module.parent, null);
|
Loading…
Reference in New Issue
Block a user