diff --git a/docs/api/command-line-switches.md b/docs/api/command-line-switches.md index fd63da4f1c..8237cf53f2 100644 --- a/docs/api/command-line-switches.md +++ b/docs/api/command-line-switches.md @@ -116,14 +116,20 @@ Ignore the connections limit for `domains` list separated by `,`. ### --js-flags=`flags` -Specifies the flags passed to the Node.js engine. It has to be passed when starting -Electron if you want to enable the `flags` in the main process. +Specifies the flags passed to the [V8 engine](https://v8.dev). In order to enable the `flags` in the main process, +this switch must be passed on startup. ```sh $ electron --js-flags="--harmony_proxies --harmony_collections" your-app ``` -See the [Node.js documentation][node-cli] or run `node --help` in your terminal for a list of available flags. Additionally, run `node --v8-options` to see a list of flags that specifically refer to Node.js's V8 JavaScript engine. +Run `node --v8-options` or `electron --js-flags="--help"` in your terminal for the list of available flags. These can be used to enable early-stage JavaScript features, or log and manipulate garbage collection, among other things. + +For example, to trace V8 optimization and deoptimization: + +```sh +$ electron --js-flags="--trace-opt --trace-deopt" your-app +``` ### --lang diff --git a/shell/app/node_main.cc b/shell/app/node_main.cc index 8d06bef9a7..79483e2fae 100644 --- a/shell/app/node_main.cc +++ b/shell/app/node_main.cc @@ -50,10 +50,10 @@ namespace { -// Initialize Node.js cli options to pass to Node.js +// Preparse Node.js cli options to pass to Node.js // See https://nodejs.org/api/cli.html#cli_options -int SetNodeCliFlags() { - // Options that are unilaterally disallowed +void ExitIfContainsDisallowedFlags(const std::vector& argv) { + // Options that are unilaterally disallowed. static constexpr auto disallowed = base::MakeFixedFlatSet({ "--enable-fips", "--force-fips", @@ -62,40 +62,18 @@ int SetNodeCliFlags() { "--use-openssl-ca", }); - const auto argv = base::CommandLine::ForCurrentProcess()->argv(); - std::vector 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 BUILDFLAG(IS_WIN) - const auto& option = base::WideToUTF8(arg); -#else - const auto& option = arg; -#endif - const auto stripped = base::StringPiece(option).substr(0, option.find('=')); - if (disallowed.contains(stripped)) { - LOG(ERROR) << "The Node.js cli flag " << stripped + const auto key = base::StringPiece(arg).substr(0, arg.find('=')); + if (disallowed.contains(key)) { + LOG(ERROR) << "The Node.js cli flag " << key << " is not supported in Electron"; // Node.js returns 9 from ProcessGlobalArgs for any errors encountered // when setting up cli flags and env vars. Since we're outlawing these - // flags (making them errors) return 9 here for consistency. - return 9; - } else { - args.push_back(option); + // flags (making them errors) exit with the same error code for + // consistency. + exit(9); } } - - std::vector errors; - - // Node.js itself will output parsing errors to - // console so we don't need to handle that ourselves - return ProcessGlobalArgs(&args, nullptr, &errors, - node::kDisallowedInEnvironment); } #if IS_MAS_BUILD() @@ -116,7 +94,11 @@ v8::Local GetParameters(v8::Isolate* isolate) { } int NodeMain(int argc, char* argv[]) { - base::CommandLine::Init(argc, argv); + bool initialized = base::CommandLine::Init(argc, argv); + if (!initialized) { + LOG(ERROR) << "Failed to initialize CommandLine"; + exit(1); + } #if BUILDFLAG(IS_WIN) v8_crashpad_support::SetUp(); @@ -153,15 +135,13 @@ int NodeMain(int argc, char* argv[]) { // Explicitly register electron's builtin bindings. NodeBindings::RegisterBuiltinBindings(); - // Parse and set Node.js cli flags. - int flags_exit_code = SetNodeCliFlags(); - if (flags_exit_code != 0) - exit(flags_exit_code); - // Hack around with the argv pointer. Used for process.title = "blah". argv = uv_setup_args(argc, argv); + // Parse Node.js cli flags and strip out disallowed options. std::vector args(argv, argv + argc); + ExitIfContainsDisallowedFlags(args); + std::unique_ptr result = node::InitializeOncePerProcess( args, diff --git a/shell/common/node_bindings.cc b/shell/common/node_bindings.cc index 766d043059..815dbb7d28 100644 --- a/shell/common/node_bindings.cc +++ b/shell/common/node_bindings.cc @@ -386,7 +386,7 @@ bool NodeBindings::IsInitialized() { // Initialize Node.js cli options to pass to Node.js // See https://nodejs.org/api/cli.html#cli_options -void NodeBindings::SetNodeCliFlags() { +std::vector NodeBindings::ParseNodeCliFlags() { const auto argv = base::CommandLine::ForCurrentProcess()->argv(); std::vector args; @@ -403,9 +403,7 @@ void NodeBindings::SetNodeCliFlags() { const auto& option = arg; #endif const auto stripped = base::StringPiece(option).substr(0, option.find('=')); - - // Only allow in no-op (--) option or a small set of debug - // and trace related options. + // Only allow no-op or a small set of debug/trace related options. if (IsAllowedOption(stripped) || stripped == "--") args.push_back(option); } @@ -417,16 +415,7 @@ void NodeBindings::SetNodeCliFlags() { args.push_back("--no-experimental-fetch"); } - std::vector errors; - const int exit_code = ProcessGlobalArgs(&args, nullptr, &errors, - node::kDisallowedInEnvironment); - - const std::string err_str = "Error parsing Node.js cli flags "; - if (exit_code != 0) { - LOG(ERROR) << err_str; - } else if (!errors.empty()) { - LOG(ERROR) << err_str << base::JoinString(errors, " "); - } + return args; } void NodeBindings::Initialize(v8::Local context) { @@ -442,13 +431,11 @@ void NodeBindings::Initialize(v8::Local context) { // Explicitly register electron's builtin bindings. RegisterBuiltinBindings(); - // Parse and set Node.js cli flags. - SetNodeCliFlags(); - auto env = base::Environment::Create(); SetNodeOptions(env.get()); - std::vector argv = {"electron"}; + // Parse and set Node.js cli flags. + std::vector argv = ParseNodeCliFlags(); std::vector exec_argv; std::vector errors; uint64_t process_flags = node::ProcessFlags::kNoFlags; diff --git a/shell/common/node_bindings.h b/shell/common/node_bindings.h index cb0dd998c9..9182f5440b 100644 --- a/shell/common/node_bindings.h +++ b/shell/common/node_bindings.h @@ -92,7 +92,7 @@ class NodeBindings { // Setup V8, libuv. void Initialize(v8::Local context); - void SetNodeCliFlags(); + std::vector ParseNodeCliFlags(); // Create the environment and load node.js. node::Environment* CreateEnvironment(v8::Handle context,