From dc214506a32c5e3dab365de12cb057c48c5bfaa5 Mon Sep 17 00:00:00 2001 From: Unitech Date: Mon, 13 Jan 2020 14:52:59 +0100 Subject: [PATCH] feat: #4540 support ES import --- examples/import/circle.js | 9 +++ examples/import/index.js | 7 ++ examples/import/package.json | 12 ++++ lib/ProcessContainer.js | 8 ++- lib/ProcessContainerFork.js | 12 +++- lib/ProcessUtils.js | 21 ++++++ test/e2e.sh | 2 + test/e2e/esmodule.sh | 65 +++++++++++++++++++ test/fixtures/esmodules/mjs/circle.mjs | 9 +++ test/fixtures/esmodules/mjs/index.mjs | 10 +++ .../esmodules/packagemodule/circle.js | 9 +++ .../fixtures/esmodules/packagemodule/index.js | 10 +++ .../esmodules/packagemodule/package.json | 12 ++++ 13 files changed, 181 insertions(+), 5 deletions(-) create mode 100644 examples/import/circle.js create mode 100644 examples/import/index.js create mode 100644 examples/import/package.json create mode 100644 test/e2e/esmodule.sh create mode 100644 test/fixtures/esmodules/mjs/circle.mjs create mode 100644 test/fixtures/esmodules/mjs/index.mjs create mode 100644 test/fixtures/esmodules/packagemodule/circle.js create mode 100644 test/fixtures/esmodules/packagemodule/index.js create mode 100644 test/fixtures/esmodules/packagemodule/package.json diff --git a/examples/import/circle.js b/examples/import/circle.js new file mode 100644 index 000000000..4ef483f1e --- /dev/null +++ b/examples/import/circle.js @@ -0,0 +1,9 @@ +const PI = 3.14159265359; + +export function area(radius) { + return (radius ** 2) * PI; +} + +export function circumference(radius) { + return 2 * radius * PI; +} diff --git a/examples/import/index.js b/examples/import/index.js new file mode 100644 index 000000000..d0e5cee71 --- /dev/null +++ b/examples/import/index.js @@ -0,0 +1,7 @@ +import { area, circumference } from './circle.js'; + +const r = 3; + +console.log(`Circle with radius ${r} has + area: ${area(r)}; + circunference: ${circumference(r)}`); diff --git a/examples/import/package.json b/examples/import/package.json new file mode 100644 index 000000000..cf3a9d04a --- /dev/null +++ b/examples/import/package.json @@ -0,0 +1,12 @@ +{ + "name": "import", + "version": "1.0.0", + "description": "", + "main": "index.js", + "type":"module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} diff --git a/lib/ProcessContainer.js b/lib/ProcessContainer.js index 922d7124e..4ae92db13 100644 --- a/lib/ProcessContainer.js +++ b/lib/ProcessContainer.js @@ -12,6 +12,7 @@ var p = require('path'); var cst = require('../constants'); var Utility = require('./Utility.js'); +var ProcessUtils = require('./ProcessUtils'); // Load all env-vars from master. var pm2_env = JSON.parse(process.env.pm2_env); @@ -30,7 +31,7 @@ delete process.env.pm2_env; (function ProcessContainer() { var fs = require('fs'); - require('./ProcessUtils').injectModules(); + ProcessUtils.injectModules() var stdFile = pm2_env.pm_log_path; var outFile = pm2_env.pm_out_log_path; @@ -294,7 +295,10 @@ function exec(script, stds) { // Change dir to fix process.cwd process.chdir(pm2_env.pm_cwd || process.env.PWD || p.dirname(script)); - require('module')._load(script, null, true); + if (ProcessUtils.isESModule(script) === true) + import(process.env.pm_exec_path); + else + require('module')._load(script, null, true); function logError(types, error){ try { diff --git a/lib/ProcessContainerFork.js b/lib/ProcessContainerFork.js index a782c2ff6..a3d4aa5be 100644 --- a/lib/ProcessContainerFork.js +++ b/lib/ProcessContainerFork.js @@ -4,7 +4,8 @@ * can be found in the LICENSE file. */ // Inject custom modules -require('./ProcessUtils').injectModules(); +var ProcessUtils = require('./ProcessUtils') +ProcessUtils.injectModules() if (typeof(process.env.source_map_support) != "undefined" && process.env.source_map_support !== "false") { @@ -23,8 +24,13 @@ if (process.connected && }); // Require the real application -if (process.env.pm_exec_path) - require('module')._load(process.env.pm_exec_path, null, true); +if (process.env.pm_exec_path) { + if (ProcessUtils.isESModule(process.env.pm_exec_path) === true) { + import(process.env.pm_exec_path); + } + else + require('module')._load(process.env.pm_exec_path, null, true); +} else throw new Error('Could not _load() the script'); diff --git a/lib/ProcessUtils.js b/lib/ProcessUtils.js index e5157e78c..1bd29cfef 100644 --- a/lib/ProcessUtils.js +++ b/lib/ProcessUtils.js @@ -18,5 +18,26 @@ module.exports = { tracing: process.env.trace === 'true' || false }, conf)) } + }, + isESModule(exec_path) { + var fs = require('fs') + var path = require('path') + var semver = require('semver') + + if (semver.satisfies(process.version, '< 13.3.0')) + return false + + if (path.extname(exec_path) === '.mjs') + return true + + try { + var data = JSON.parse(fs.readFileSync(path.join(path.dirname(exec_path), 'package.json'))) + if (data.type === 'module') + return true + else + return false + } catch(e) { + return false + } } }; diff --git a/test/e2e.sh b/test/e2e.sh index 8f4bcb098..bb7891b2a 100644 --- a/test/e2e.sh +++ b/test/e2e.sh @@ -35,6 +35,8 @@ if [ $SUPV = '<6' ]; then exit fi +runTest ./test/e2e/esmodule.sh + runTest ./test/e2e/cli/monit.sh runTest ./test/e2e/cli/cli-actions-1.sh runTest ./test/e2e/cli/cli-actions-2.sh diff --git a/test/e2e/esmodule.sh b/test/e2e/esmodule.sh new file mode 100644 index 000000000..b4717c0c8 --- /dev/null +++ b/test/e2e/esmodule.sh @@ -0,0 +1,65 @@ +#!/usr/bin/env bash + +SRC=$(cd $(dirname "$0"); pwd) +source "${SRC}/include.sh" + +# Bootstrap one app +cd $file_path/esmodules/mjs + +#### FORK MODE + +$pm2 delete all + +$pm2 start index.mjs +sleep 2 +should 'should have detected es module via .mjs file extension and started 1 app' 'online' 1 +should 'should have application in stable state' 'restart_time: 0' 1 + +$pm2 restart index +sleep 2 +should 'should have detected es module via .mjs file extension and started 1 app' 'online' 1 +should 'should have application in stable state' 'restart_time: 1' 1 + +$pm2 delete all + +cd $file_path/esmodules/packagemodule + +$pm2 start index.js +sleep 2 +should 'should have detected es module via .mjs file extension and started 1 app' 'online' 1 +should 'should have application in stable state' 'restart_time: 0' 1 + +$pm2 restart index +sleep 2 +should 'should have detected es module via .mjs file extension and started 1 app' 'online' 1 +should 'should have application in stable state' 'restart_time: 1' 1 + +#### CLUSTER MODE + +$pm2 delete all + +$pm2 start index.mjs -i 4 +sleep 2 +should 'should have detected es module via .mjs file extension and started 4 apps' 'online' 4 +should 'should have application in stable state' 'restart_time: 0' 4 + +$pm2 restart index +sleep 2 +should 'should have detected es module via .mjs file extension and started 4 app' 'online' 4 +should 'should have application in stable state' 'restart_time: 1' 4 + +$pm2 delete all + +cd $file_path/esmodules/packagemodule + +$pm2 start index.js -i 4 +sleep 2 +should 'should have detected es module via .mjs file extension and started 4 apps' 'online' 4 +should 'should have application in stable state' 'restart_time: 0' 4 + +$pm2 restart index +sleep 2 +should 'should have detected es module via .mjs file extension and started 4 app' 'online' 4 +should 'should have application in stable state' 'restart_time: 1' 4 + +$pm2 delete all diff --git a/test/fixtures/esmodules/mjs/circle.mjs b/test/fixtures/esmodules/mjs/circle.mjs new file mode 100644 index 000000000..4ef483f1e --- /dev/null +++ b/test/fixtures/esmodules/mjs/circle.mjs @@ -0,0 +1,9 @@ +const PI = 3.14159265359; + +export function area(radius) { + return (radius ** 2) * PI; +} + +export function circumference(radius) { + return 2 * radius * PI; +} diff --git a/test/fixtures/esmodules/mjs/index.mjs b/test/fixtures/esmodules/mjs/index.mjs new file mode 100644 index 000000000..5646816b9 --- /dev/null +++ b/test/fixtures/esmodules/mjs/index.mjs @@ -0,0 +1,10 @@ +import { area, circumference } from './circle.mjs'; + +const r = 3; + +console.log(`Circle with radius ${r} has + area: ${area(r)}; + circunference: ${circumference(r)}`); + +setInterval(() => { +}, 1000) diff --git a/test/fixtures/esmodules/packagemodule/circle.js b/test/fixtures/esmodules/packagemodule/circle.js new file mode 100644 index 000000000..4ef483f1e --- /dev/null +++ b/test/fixtures/esmodules/packagemodule/circle.js @@ -0,0 +1,9 @@ +const PI = 3.14159265359; + +export function area(radius) { + return (radius ** 2) * PI; +} + +export function circumference(radius) { + return 2 * radius * PI; +} diff --git a/test/fixtures/esmodules/packagemodule/index.js b/test/fixtures/esmodules/packagemodule/index.js new file mode 100644 index 000000000..2a83e3ae0 --- /dev/null +++ b/test/fixtures/esmodules/packagemodule/index.js @@ -0,0 +1,10 @@ +import { area, circumference } from './circle.js'; + +const r = 3; + +console.log(`Circle with radius ${r} has + area: ${area(r)}; + circunference: ${circumference(r)}`); + +setInterval(() => { +}, 1000) diff --git a/test/fixtures/esmodules/packagemodule/package.json b/test/fixtures/esmodules/packagemodule/package.json new file mode 100644 index 000000000..cf3a9d04a --- /dev/null +++ b/test/fixtures/esmodules/packagemodule/package.json @@ -0,0 +1,12 @@ +{ + "name": "import", + "version": "1.0.0", + "description": "", + "main": "index.js", + "type":"module", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +}