mirror of
https://github.com/nodejs/node.git
synced 2026-10-14 10:26:26 -04:00
module: Allow runMain to be ESM
This follows the EPS an allows the node CLI to have ESM as an entry point. `node ./example.mjs`. A newer V8 is needed for `import()` so that is not included. `import.meta` is still in specification stage so that also is not included. PR-URL: https://github.com/nodejs/node/pull/14369 Author: Bradley Farias <bradley.meck@gmail.com> Author: Guy Bedford <guybedford@gmail.com> Author: Jan Krems <jan.krems@groupon.com> Author: Timothy Gu <timothygu99@gmail.com> Author: Michaël Zasso <targos@protonmail.com> Author: Anna Henningsen <anna@addaleax.net> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jeremiah Senkpiel <fishrock123@rocketmail.com>
This commit is contained in:
1 parent
46133b5beb
commit
c8a389e19f
46 files changed
+1578
-40
No files matched your search
@@ -13,6 +13,7 @@ const path = require('path');
|
||||
module.exports = function(context) {
|
||||
// trim required module names
|
||||
var requiredModules = context.options;
|
||||
const isESM = context.parserOptions.sourceType === 'module';
|
||||
|
||||
const foundModules = [];
|
||||
|
||||
@@ -39,39 +40,35 @@ module.exports = function(context) {
|
||||
return node.callee.type === 'Identifier' && node.callee.name === 'require';
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to check if the path is a required module and return its name.
|
||||
* @param {String} str The path to check
|
||||
* @returns {undefined|String} required module name or undefined
|
||||
*/
|
||||
function getRequiredModuleName(str) {
|
||||
var value = path.basename(str);
|
||||
|
||||
// check if value is in required modules array
|
||||
return requiredModules.indexOf(value) !== -1 ? value : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to check if a node has an argument that is a required module and
|
||||
* return its name.
|
||||
* @param {ASTNode} node The node to check
|
||||
* @returns {undefined|String} required module name or undefined
|
||||
*/
|
||||
function getRequiredModuleName(node) {
|
||||
var moduleName;
|
||||
|
||||
function getRequiredModuleNameFromCall(node) {
|
||||
// node has arguments and first argument is string
|
||||
if (node.arguments.length && isString(node.arguments[0])) {
|
||||
var argValue = path.basename(node.arguments[0].value.trim());
|
||||
|
||||
// check if value is in required modules array
|
||||
if (requiredModules.indexOf(argValue) !== -1) {
|
||||
moduleName = argValue;
|
||||
}
|
||||
return getRequiredModuleName(node.arguments[0].value.trim());
|
||||
}
|
||||
|
||||
return moduleName;
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
'CallExpression': function(node) {
|
||||
if (isRequireCall(node)) {
|
||||
var requiredModuleName = getRequiredModuleName(node);
|
||||
|
||||
if (requiredModuleName) {
|
||||
foundModules.push(requiredModuleName);
|
||||
}
|
||||
}
|
||||
},
|
||||
'Program:exit': function(node) {
|
||||
const rules = {
|
||||
'Program:exit'(node) {
|
||||
if (foundModules.length < requiredModules.length) {
|
||||
var missingModules = requiredModules.filter(
|
||||
function(module) {
|
||||
@@ -88,6 +85,27 @@ module.exports = function(context) {
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (isESM) {
|
||||
rules.ImportDeclaration = (node) => {
|
||||
var requiredModuleName = getRequiredModuleName(node.source.value);
|
||||
if (requiredModuleName) {
|
||||
foundModules.push(requiredModuleName);
|
||||
}
|
||||
};
|
||||
} else {
|
||||
rules.CallExpression = (node) => {
|
||||
if (isRequireCall(node)) {
|
||||
var requiredModuleName = getRequiredModuleNameFromCall(node);
|
||||
|
||||
if (requiredModuleName) {
|
||||
foundModules.push(requiredModuleName);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return rules;
|
||||
};
|
||||
|
||||
module.exports.schema = {
|
||||
|
||||
+9
-9
@@ -279,9 +279,7 @@ class TapProgressIndicator(SimpleProgressIndicator):
|
||||
# hard to decipher what test is running when only the filename is printed.
|
||||
prefix = abspath(join(dirname(__file__), '../test')) + os.sep
|
||||
command = output.command[-1]
|
||||
if command.endswith('.js'): command = command[:-3]
|
||||
if command.startswith(prefix): command = command[len(prefix):]
|
||||
command = command.replace('\\', '/')
|
||||
command = NormalizePath(command, prefix)
|
||||
|
||||
if output.UnexpectedOutput():
|
||||
status_line = 'not ok %i %s' % (self._done, command)
|
||||
@@ -352,9 +350,7 @@ class DeoptsCheckProgressIndicator(SimpleProgressIndicator):
|
||||
# hard to decipher what test is running when only the filename is printed.
|
||||
prefix = abspath(join(dirname(__file__), '../test')) + os.sep
|
||||
command = output.command[-1]
|
||||
if command.endswith('.js'): command = command[:-3]
|
||||
if command.startswith(prefix): command = command[len(prefix):]
|
||||
command = command.replace('\\', '/')
|
||||
command = NormalizePath(command, prefix)
|
||||
|
||||
stdout = output.output.stdout.strip()
|
||||
printed_file = False
|
||||
@@ -1509,12 +1505,16 @@ def SplitPath(s):
|
||||
stripped = [ c.strip() for c in s.split('/') ]
|
||||
return [ Pattern(s) for s in stripped if len(s) > 0 ]
|
||||
|
||||
def NormalizePath(path):
|
||||
def NormalizePath(path, prefix='test/'):
|
||||
# strip the extra path information of the specified test
|
||||
if path.startswith('test/'):
|
||||
path = path[5:]
|
||||
prefix = prefix.replace('\\', '/')
|
||||
path = path.replace('\\', '/')
|
||||
if path.startswith(prefix):
|
||||
path = path[len(prefix):]
|
||||
if path.endswith('.js'):
|
||||
path = path[:-3]
|
||||
elif path.endswith('.mjs'):
|
||||
path = path[:-4]
|
||||
return path
|
||||
|
||||
def GetSpecialCommandProcessor(value):
|
||||
|
||||
Reference in new issue
Block a user