feat: enable passing Node.js cli flags (#21110)

* feat: enable passing Node.js cli flags

* Allow cli flags in ELECTRON_RUN_AS_NODE mode
This commit is contained in:
Shelley Vohr 2020-02-07 02:59:38 +00:00 committed by GitHub
parent 9107157073
commit 83124889e5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 484 additions and 202 deletions

View file

@ -6,10 +6,14 @@
#include <memory>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/thread_task_runner_handle.h"
#include "electron/electron_version.h"
@ -29,6 +33,49 @@
#include "shell/common/crash_reporter/crash_reporter_win.h"
#endif
namespace {
// Initialize Node.js cli options to pass to Node.js
// See https://nodejs.org/api/cli.html#cli_options
void SetNodeCliFlags() {
// Options that are unilaterally disallowed
const std::unordered_set<base::StringPiece, base::StringPieceHash>
disallowed = {"--openssl-config", "--use-bundled-ca", "--use-openssl-ca",
"--force-fips", "--enable-fips"};
const auto argv = base::CommandLine::ForCurrentProcess()->argv();
std::vector<std::string> args;
// TODO(codebytere): We need to set the first entry in args to the
// process name owing to src/node_options-inl.h#L286-L290 but this is
// redundant and so should be refactored upstream.
args.reserve(argv.size() + 1);
args.emplace_back("electron");
for (const auto& arg : argv) {
#if defined(OS_WIN)
const auto& option = base::UTF16ToUTF8(arg);
#else
const auto& option = arg;
#endif
const auto stripped = base::StringPiece(option).substr(0, option.find('='));
if (disallowed.count(stripped) != 0) {
LOG(ERROR) << "The Node.js cli flag " << stripped
<< " is not supported in Electron";
} else {
args.push_back(option);
}
}
std::vector<std::string> errors;
// Node.js itself will output parsing errors to
// console so we don't need to handle that ourselves
ProcessGlobalArgs(&args, nullptr, &errors, node::kDisallowedInEnvironment);
}
} // namespace
namespace electron {
#if !defined(OS_LINUX)
@ -64,6 +111,9 @@ int NodeMain(int argc, char* argv[]) {
// Explicitly register electron's builtin modules.
NodeBindings::RegisterBuiltinModules();
// Parse and set Node.js cli flags.
SetNodeCliFlags();
int exec_argc;
const char** exec_argv;
node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);

View file

@ -41,9 +41,9 @@ void NodeDebugger::Start() {
std::vector<std::string> v8_args;
std::vector<std::string> errors;
// TODO(codebytere): remove this parsing and use ProcessGlobalArgs
node::options_parser::Parse(&args, &exec_args, &v8_args, &options,
node::options_parser::kDisallowedInEnvironment,
&errors);
node::kDisallowedInEnvironment, &errors);
if (!errors.empty()) {
// TODO(jeremy): what's the appropriate behaviour here?

View file

@ -8,6 +8,7 @@
#include <memory>
#include <set>
#include <string>
#include <unordered_set>
#include <utility>
#include <vector>
@ -136,7 +137,51 @@ bool IsPackagedApp() {
#endif
}
// Initialize Node.js cli options to pass to Node.js
// See https://nodejs.org/api/cli.html#cli_options
void SetNodeCliFlags() {
// Only allow DebugOptions in non-ELECTRON_RUN_AS_NODE mode
const std::unordered_set<base::StringPiece, base::StringPieceHash> allowed = {
"--inspect", "--inspect-brk",
"--inspect-port", "--debug",
"--debug-brk", "--debug-port",
"--inspect-brk-node", "--inspect-publish-uid",
};
const auto argv = base::CommandLine::ForCurrentProcess()->argv();
std::vector<std::string> args;
// TODO(codebytere): We need to set the first entry in args to the
// process name owing to src/node_options-inl.h#L286-L290 but this is
// redundant and so should be refactored upstream.
args.reserve(argv.size() + 1);
args.emplace_back("electron");
for (const auto& arg : argv) {
#if defined(OS_WIN)
const auto& option = base::UTF16ToUTF8(arg);
#else
const auto& option = arg;
#endif
const auto stripped = base::StringPiece(option).substr(0, option.find('='));
if (allowed.count(stripped) != 0)
args.push_back(option);
}
std::vector<std::string> errors;
const int exit_code = ProcessGlobalArgs(&args, nullptr, &errors,
node::kDisallowedInEnvironment);
if (exit_code != 0) {
if (!errors.empty())
LOG(INFO) << base::JoinString(errors, " ");
else
LOG(INFO) << "Error parsing Node.js cli flags";
}
}
// Initialize NODE_OPTIONS to pass to Node.js
// See https://nodejs.org/api/cli.html#cli_node_options_options
void SetNodeOptions(base::Environment* env) {
// Options that are unilaterally disallowed
const std::set<std::string> disallowed = {
@ -157,7 +202,7 @@ void SetNodeOptions(base::Environment* env) {
for (const auto& part : parts) {
// Strip off values passed to individual NODE_OPTIONs
std::string option = part.substr(0, part.find("="));
std::string option = part.substr(0, part.find('='));
if (is_packaged_app &&
allowed_in_packaged.find(option) == allowed_in_packaged.end()) {
@ -270,6 +315,9 @@ void NodeBindings::Initialize() {
// Explicitly register electron's builtin modules.
RegisterBuiltinModules();
// Parse and set Node.js cli flags.
SetNodeCliFlags();
// pass non-null program name to argv so it doesn't crash
// trying to index into a nullptr
int argc = 1;