diff --git a/doc/api/cli.md b/doc/api/cli.md index 8f1ddc95d0b64b..51b400e7014a32 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -1861,6 +1861,9 @@ changes: - version: REPLACEME pr-url: https://github.com/nodejs/node/pull/53032 description: NODE_RUN_SCRIPT_NAME environment variable is added. + - version: REPLACEME + pr-url: https://github.com/nodejs/node/pull/53058 + description: NODE_RUN_PACKAGE_JSON_PATH environment variable is added. --> > Stability: 1.1 - Active development @@ -1907,6 +1910,8 @@ The following environment variables are set when running a script with `--run`: * `NODE_RUN_SCRIPT_NAME`: The name of the script being run. For example, if `--run` is used to run `test`, the value of this variable will be `test`. +* `NODE_RUN_PACKAGE_JSON_PATH`: The path to the `package.json` that is being + processed. ### `--secure-heap=n` diff --git a/src/node_task_runner.cc b/src/node_task_runner.cc index 45f6e0f307e8ec..82dcfdc5c3cf70 100644 --- a/src/node_task_runner.cc +++ b/src/node_task_runner.cc @@ -1,6 +1,7 @@ #include "node_task_runner.h" #include "util.h" +#include #include // NOLINT(build/c++11) namespace node::task_runner { @@ -12,7 +13,8 @@ static constexpr const char* bin_path = "/node_modules/.bin"; #endif // _WIN32 ProcessRunner::ProcessRunner(std::shared_ptr result, - const std::string& script_name, + std::string_view package_json_path, + std::string_view script_name, std::string_view command, const PositionalArgs& positional_args) { memset(&options_, 0, sizeof(uv_process_options_t)); @@ -52,7 +54,10 @@ ProcessRunner::ProcessRunner(std::shared_ptr result, // callback. process_.data = this; - SetEnvironmentVariables(current_bin_path, script_name); + SetEnvironmentVariables(current_bin_path, + std::string_view(cwd, cwd_size), + package_json_path, + script_name); std::string command_str(command); @@ -102,7 +107,9 @@ ProcessRunner::ProcessRunner(std::shared_ptr result, } void ProcessRunner::SetEnvironmentVariables(const std::string& current_bin_path, - const std::string& script_name) { + std::string_view cwd, + std::string_view package_json_path, + std::string_view script_name) { uv_env_item_t* env_items; int env_count; CHECK_EQ(0, uv_os_environ(&env_items, &env_count)); @@ -132,7 +139,19 @@ void ProcessRunner::SetEnvironmentVariables(const std::string& current_bin_path, // Add NODE_RUN_SCRIPT_NAME environment variable to the environment // to indicate which script is being run. - env_vars_.push_back("NODE_RUN_SCRIPT_NAME=" + script_name); + env_vars_.push_back("NODE_RUN_SCRIPT_NAME=" + std::string(script_name)); + + // Add NODE_RUN_PACKAGE_JSON_PATH environment variable to the environment to + // indicate which package.json is being processed. + if (std::filesystem::path(package_json_path).is_absolute()) { + // TODO(anonrig): Traverse up the directory tree until we find a + // package.json + env_vars_.push_back("NODE_RUN_PACKAGE_JSON_PATH=" + + std::string(package_json_path)); + } else { + auto path = std::filesystem::path(cwd) / std::string(package_json_path); + env_vars_.push_back("NODE_RUN_PACKAGE_JSON_PATH=" + path.string()); + } env = std::unique_ptr(new char*[env_vars_.size() + 1]); options_.env = env.get(); @@ -284,7 +303,7 @@ void RunTask(std::shared_ptr result, } auto runner = - ProcessRunner(result, std::string(command_id), command, positional_args); + ProcessRunner(result, path, command_id, command, positional_args); runner.Run(); } diff --git a/src/node_task_runner.h b/src/node_task_runner.h index 65ddef71d6f487..ea430a6e32c747 100644 --- a/src/node_task_runner.h +++ b/src/node_task_runner.h @@ -23,7 +23,8 @@ using PositionalArgs = std::vector; class ProcessRunner { public: ProcessRunner(std::shared_ptr result, - const std::string& script_name, + std::string_view package_json_path, + std::string_view script_name, std::string_view command_id, const PositionalArgs& positional_args); void Run(); @@ -45,7 +46,9 @@ class ProcessRunner { // OnExit is the callback function that is called when the process exits. void OnExit(int64_t exit_status, int term_signal); void SetEnvironmentVariables(const std::string& bin_path, - const std::string& script_name); + std::string_view cwd, + std::string_view package_json_path, + std::string_view script_name); #ifdef _WIN32 std::string file_ = "cmd.exe"; diff --git a/test/fixtures/run-script/node_modules/.bin/special-env-variables b/test/fixtures/run-script/node_modules/.bin/special-env-variables index df687e823224f6..3377b056cd4809 100755 --- a/test/fixtures/run-script/node_modules/.bin/special-env-variables +++ b/test/fixtures/run-script/node_modules/.bin/special-env-variables @@ -1,2 +1,3 @@ #!/bin/sh echo "$NODE_RUN_SCRIPT_NAME" +echo "$NODE_RUN_PACKAGE_JSON_PATH" diff --git a/test/fixtures/run-script/node_modules/.bin/special-env-variables.bat b/test/fixtures/run-script/node_modules/.bin/special-env-variables.bat index ecfcf9262f68c0..320854483cd747 100755 --- a/test/fixtures/run-script/node_modules/.bin/special-env-variables.bat +++ b/test/fixtures/run-script/node_modules/.bin/special-env-variables.bat @@ -1,2 +1,3 @@ @shift echo %NODE_RUN_SCRIPT_NAME% +echo %NODE_RUN_PACKAGE_JSON_PATH% diff --git a/test/parallel/test-node-run.js b/test/parallel/test-node-run.js index ffbf227049d763..89c014bddd2f1b 100644 --- a/test/parallel/test-node-run.js +++ b/test/parallel/test-node-run.js @@ -83,12 +83,14 @@ describe('node run [command]', () => { it('should set special environment variables', async () => { const scriptName = `special-env-variables${envSuffix}`; + const packageJsonPath = fixtures.path('run-script/package.json'); const child = await common.spawnPromisified( process.execPath, [ '--no-warnings', '--run', scriptName], { cwd: fixtures.path('run-script') }, ); assert.ok(child.stdout.includes(scriptName)); + assert.ok(child.stdout.includes(packageJsonPath)); assert.strictEqual(child.stderr, ''); assert.strictEqual(child.code, 0); });