зеркало из https://github.com/electron/electron.git
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:
Родитель
9107157073
Коммит
83124889e5
|
@ -16,80 +16,66 @@ app.whenReady().then(() => {
|
|||
})
|
||||
```
|
||||
|
||||
## --ignore-connections-limit=`domains`
|
||||
## Electron CLI Flags
|
||||
|
||||
Ignore the connections limit for `domains` list separated by `,`.
|
||||
### --auth-server-whitelist=`url`
|
||||
|
||||
## --disable-http-cache
|
||||
|
||||
Disables the disk cache for HTTP requests.
|
||||
|
||||
## --disable-http2
|
||||
|
||||
Disable HTTP/2 and SPDY/3.1 protocols.
|
||||
|
||||
## --lang
|
||||
|
||||
Set a custom locale.
|
||||
|
||||
## --inspect=`port` and --inspect-brk=`port`
|
||||
|
||||
Debug-related flags, see the [Debugging the Main Process][debugging-main-process] guide for details.
|
||||
|
||||
## --remote-debugging-port=`port`
|
||||
|
||||
Enables remote debugging over HTTP on the specified `port`.
|
||||
|
||||
## --disk-cache-size=`size`
|
||||
|
||||
Forces the maximum disk space to be used by the disk cache, in bytes.
|
||||
|
||||
## --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.
|
||||
|
||||
```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.
|
||||
|
||||
## --proxy-server=`address:port`
|
||||
|
||||
Use a specified proxy server, which overrides the system setting. This switch
|
||||
only affects requests with HTTP protocol, including HTTPS and WebSocket
|
||||
requests. It is also noteworthy that not all proxy servers support HTTPS and
|
||||
WebSocket requests. The proxy URL does not support username and password
|
||||
authentication [per Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).
|
||||
|
||||
## --proxy-bypass-list=`hosts`
|
||||
|
||||
Instructs Electron to bypass the proxy server for the given semi-colon-separated
|
||||
list of hosts. This flag has an effect only if used in tandem with
|
||||
`--proxy-server`.
|
||||
A comma-separated list of servers for which integrated authentication is enabled.
|
||||
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
const { app } = require('electron')
|
||||
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
|
||||
```sh
|
||||
--auth-server-whitelist='*example.com, *foobar.com, *baz'
|
||||
```
|
||||
|
||||
Will use the proxy server for all hosts except for local addresses (`localhost`,
|
||||
`127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix
|
||||
`foo.com` and anything at `1.2.3.4:5678`.
|
||||
then any `url` ending with `example.com`, `foobar.com`, `baz` will be considered
|
||||
for integrated authentication. Without `*` prefix the URL has to match exactly.
|
||||
|
||||
## --proxy-pac-url=`url`
|
||||
### --auth-negotiate-delegate-whitelist=`url`
|
||||
|
||||
Uses the PAC script at the specified `url`.
|
||||
A comma-separated list of servers for which delegation of user credentials is required.
|
||||
Without `*` prefix the URL has to match exactly.
|
||||
|
||||
## --no-proxy-server
|
||||
### --disable-http-cache
|
||||
|
||||
Don't use a proxy server and always make direct connections. Overrides any other
|
||||
proxy server flags that are passed.
|
||||
Disables the disk cache for HTTP requests.
|
||||
|
||||
## --host-rules=`rules`
|
||||
### --disable-http2
|
||||
|
||||
Disable HTTP/2 and SPDY/3.1 protocols.
|
||||
|
||||
### --disable-renderer-backgrounding
|
||||
|
||||
Prevents Chromium from lowering the priority of invisible pages' renderer
|
||||
processes.
|
||||
|
||||
This flag is global to all renderer processes, if you only want to disable
|
||||
throttling in one window, you can take the hack of
|
||||
[playing silent audio][play-silent-audio].
|
||||
|
||||
### --disk-cache-size=`size`
|
||||
|
||||
Forces the maximum disk space to be used by the disk cache, in bytes.
|
||||
|
||||
### --enable-api-filtering-logging
|
||||
|
||||
Enables caller stack logging for the following APIs (filtering events):
|
||||
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
|
||||
- `remote.require()` / `remote-require`
|
||||
- `remote.getGlobal()` / `remote-get-builtin`
|
||||
- `remote.getBuiltin()` / `remote-get-global`
|
||||
- `remote.getCurrentWindow()` / `remote-get-current-window`
|
||||
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
|
||||
|
||||
### --enable-logging
|
||||
|
||||
Prints Chromium's logging into console.
|
||||
|
||||
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
|
||||
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
|
||||
environment variable to achieve the same effect.
|
||||
|
||||
### --host-rules=`rules`
|
||||
|
||||
A comma-separated list of `rules` that control how hostnames are mapped.
|
||||
|
||||
|
@ -107,69 +93,96 @@ These mappings apply to the endpoint host in a net request (the TCP connect
|
|||
and host resolver in a direct connection, and the `CONNECT` in an HTTP proxy
|
||||
connection, and the endpoint host in a `SOCKS` proxy connection).
|
||||
|
||||
## --host-resolver-rules=`rules`
|
||||
### --host-resolver-rules=`rules`
|
||||
|
||||
Like `--host-rules` but these `rules` only apply to the host resolver.
|
||||
|
||||
## --auth-server-whitelist=`url`
|
||||
|
||||
A comma-separated list of servers for which integrated authentication is enabled.
|
||||
|
||||
For example:
|
||||
|
||||
```sh
|
||||
--auth-server-whitelist='*example.com, *foobar.com, *baz'
|
||||
```
|
||||
|
||||
then any `url` ending with `example.com`, `foobar.com`, `baz` will be considered
|
||||
for integrated authentication. Without `*` prefix the URL has to match exactly.
|
||||
|
||||
## --auth-negotiate-delegate-whitelist=`url`
|
||||
|
||||
A comma-separated list of servers for which delegation of user credentials is required.
|
||||
Without `*` prefix the URL has to match exactly.
|
||||
|
||||
## --ignore-certificate-errors
|
||||
### --ignore-certificate-errors
|
||||
|
||||
Ignores certificate related errors.
|
||||
|
||||
## --ppapi-flash-path=`path`
|
||||
### --ignore-connections-limit=`domains`
|
||||
|
||||
Sets the `path` of the pepper flash plugin.
|
||||
Ignore the connections limit for `domains` list separated by `,`.
|
||||
|
||||
## --ppapi-flash-version=`version`
|
||||
### --js-flags=`flags`
|
||||
|
||||
Sets the `version` of the pepper flash plugin.
|
||||
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.
|
||||
|
||||
## --log-net-log=`path`
|
||||
```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.
|
||||
|
||||
### --lang
|
||||
|
||||
Set a custom locale.
|
||||
|
||||
### --log-net-log=`path`
|
||||
|
||||
Enables net log events to be saved and writes them to `path`.
|
||||
|
||||
## --disable-renderer-backgrounding
|
||||
### --no-proxy-server
|
||||
|
||||
Prevents Chromium from lowering the priority of invisible pages' renderer
|
||||
processes.
|
||||
Don't use a proxy server and always make direct connections. Overrides any other
|
||||
proxy server flags that are passed.
|
||||
|
||||
This flag is global to all renderer processes, if you only want to disable
|
||||
throttling in one window, you can take the hack of
|
||||
[playing silent audio][play-silent-audio].
|
||||
### --no-sandbox
|
||||
|
||||
## --enable-logging
|
||||
Disables Chromium sandbox, which is now enabled by default.
|
||||
Should only be used for testing.
|
||||
|
||||
Prints Chromium's logging into console.
|
||||
### --proxy-bypass-list=`hosts`
|
||||
|
||||
This switch can not be used in `app.commandLine.appendSwitch` since it is parsed
|
||||
earlier than user's app is loaded, but you can set the `ELECTRON_ENABLE_LOGGING`
|
||||
environment variable to achieve the same effect.
|
||||
Instructs Electron to bypass the proxy server for the given semi-colon-separated
|
||||
list of hosts. This flag has an effect only if used in tandem with
|
||||
`--proxy-server`.
|
||||
|
||||
## --v=`log_level`
|
||||
For example:
|
||||
|
||||
```javascript
|
||||
const { app } = require('electron')
|
||||
app.commandLine.appendSwitch('proxy-bypass-list', '<local>;*.google.com;*foo.com;1.2.3.4:5678')
|
||||
```
|
||||
|
||||
Will use the proxy server for all hosts except for local addresses (`localhost`,
|
||||
`127.0.0.1` etc.), `google.com` subdomains, hosts that contain the suffix
|
||||
`foo.com` and anything at `1.2.3.4:5678`.
|
||||
|
||||
### --proxy-pac-url=`url`
|
||||
|
||||
Uses the PAC script at the specified `url`.
|
||||
|
||||
### --proxy-server=`address:port`
|
||||
|
||||
Use a specified proxy server, which overrides the system setting. This switch
|
||||
only affects requests with HTTP protocol, including HTTPS and WebSocket
|
||||
requests. It is also noteworthy that not all proxy servers support HTTPS and
|
||||
WebSocket requests. The proxy URL does not support username and password
|
||||
authentication [per Chromium issue](https://bugs.chromium.org/p/chromium/issues/detail?id=615947).
|
||||
|
||||
### --remote-debugging-port=`port`
|
||||
|
||||
Enables remote debugging over HTTP on the specified `port`.
|
||||
|
||||
### --ppapi-flash-path=`path`
|
||||
|
||||
Sets the `path` of the pepper flash plugin.
|
||||
|
||||
### --ppapi-flash-version=`version`
|
||||
|
||||
Sets the `version` of the pepper flash plugin.
|
||||
|
||||
### --v=`log_level`
|
||||
|
||||
Gives the default maximal active V-logging level; 0 is the default. Normally
|
||||
positive values are used for V-logging levels.
|
||||
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
||||
## --vmodule=`pattern`
|
||||
### --vmodule=`pattern`
|
||||
|
||||
Gives the per-module maximal V-logging levels to override the value given by
|
||||
`--v`. E.g. `my_module=2,foo*=3` would change the logging level for all code in
|
||||
|
@ -181,20 +194,38 @@ logging level for all code in the source files under a `foo/bar` directory.
|
|||
|
||||
This switch only works when `--enable-logging` is also passed.
|
||||
|
||||
## --enable-api-filtering-logging
|
||||
## Node.js Flags
|
||||
|
||||
Enables caller stack logging for the following APIs (filtering events):
|
||||
- `desktopCapturer.getSources()` / `desktop-capturer-get-sources`
|
||||
- `remote.require()` / `remote-require`
|
||||
- `remote.getGlobal()` / `remote-get-builtin`
|
||||
- `remote.getBuiltin()` / `remote-get-global`
|
||||
- `remote.getCurrentWindow()` / `remote-get-current-window`
|
||||
- `remote.getCurrentWebContents()` / `remote-get-current-web-contents`
|
||||
Electron supports some of the [CLI flags][node-cli] supported by Node.js.
|
||||
|
||||
## --no-sandbox
|
||||
**Note:** Passing unsupported command line switches to Electron when it is not running in `ELECTRON_RUN_AS_NODE` will have no effect.
|
||||
|
||||
Disables Chromium sandbox, which is now enabled by default.
|
||||
Should only be used for testing.
|
||||
### --inspect-brk[=[host:]port]
|
||||
|
||||
Activate inspector on host:port and break at start of user script. Default host:port is 127.0.0.1:9229.
|
||||
|
||||
Aliased to `--debug-brk=[host:]port`.
|
||||
|
||||
### --inspect-port=[host:]port
|
||||
|
||||
Set the `host:port` to be used when the inspector is activated. Useful when activating the inspector by sending the SIGUSR1 signal. Default host is `127.0.0.1`.
|
||||
|
||||
Aliased to `--debug-port=[host:]port`.
|
||||
|
||||
### --inspect[=[host:]port]
|
||||
|
||||
Activate inspector on `host:port`. Default is `127.0.0.1:9229`.
|
||||
|
||||
V8 inspector integration allows tools such as Chrome DevTools and IDEs to debug and profile Electron instances. The tools attach to Electron instances via a tcp port and communicate using the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/).
|
||||
|
||||
See the [Debugging the Main Process][debugging-main-process] guide for more details.
|
||||
|
||||
Aliased to `--debug[=[host:]port`.
|
||||
|
||||
### --inspect-publish-uid=stderr,http
|
||||
Specify ways of the inspector web socket url exposure.
|
||||
|
||||
By default inspector websocket url is available in stderr and under /json/list endpoint on http://host:port/json/list.
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: app.md#appcommandlineappendswitchswitch-value
|
||||
|
|
|
@ -80,6 +80,18 @@ and spawned child processes that set `ELECTRON_RUN_AS_NODE`.
|
|||
|
||||
Starts the process as a normal Node.js process.
|
||||
|
||||
In this mode, you will be able to pass [cli options](https://nodejs.org/api/cli.html) to Node.js as
|
||||
you would when running the normal Node.js executable, with the exception of the following flags:
|
||||
|
||||
* "--openssl-config"
|
||||
* "--use-bundled-ca"
|
||||
* "--use-openssl-ca",
|
||||
* "--force-fips"
|
||||
* "--enable-fips"
|
||||
|
||||
These flags are disabled owing to the fact that Electron uses BoringSSL instead of OpenSSL when building Node.js'
|
||||
`crypto` module, and so will not work as designed.
|
||||
|
||||
### `ELECTRON_NO_ATTACH_CONSOLE` _Windows_
|
||||
|
||||
Don't attach to the current console session.
|
||||
|
|
|
@ -36,3 +36,4 @@ remove_serialization_deserialization_of_wasmmoduleobject.patch
|
|||
64bit_bump_typedarray_max_length_to_2_32-1_elements.patch
|
||||
test_use_tmpdir_refresh_in_test-esm-windows_js.patch
|
||||
override_existing_v8_reallocate.patch
|
||||
feat_enable_passing_cli_flags.patch
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Wed, 13 Nov 2019 15:39:48 +0000
|
||||
Subject: feat: enable passing cli flags
|
||||
|
||||
This patches enables passing safelisted cli flags to Node.js.
|
||||
Upstreamed in https://github.com/nodejs/node/pull/30466.
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 461f736beacec67b35c89a42319f99178a1e38e9..c00bfb6ccbe603604fca29268d15d67b208b2e6a 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -113,8 +113,6 @@
|
||||
namespace node {
|
||||
|
||||
using native_module::NativeModuleEnv;
|
||||
-using options_parser::kAllowedInEnvironment;
|
||||
-using options_parser::kDisallowedInEnvironment;
|
||||
|
||||
using v8::Boolean;
|
||||
using v8::EscapableHandleScope;
|
||||
@@ -670,7 +668,7 @@ void ResetStdio() {
|
||||
int ProcessGlobalArgs(std::vector<std::string>* args,
|
||||
std::vector<std::string>* exec_args,
|
||||
std::vector<std::string>* errors,
|
||||
- bool is_env) {
|
||||
+ OptionEnvvarSettings settings) {
|
||||
// Parse a few arguments which are specific to Node.
|
||||
std::vector<std::string> v8_args;
|
||||
|
||||
@@ -680,7 +678,7 @@ int ProcessGlobalArgs(std::vector<std::string>* args,
|
||||
exec_args,
|
||||
&v8_args,
|
||||
per_process::cli_options.get(),
|
||||
- is_env ? kAllowedInEnvironment : kDisallowedInEnvironment,
|
||||
+ settings,
|
||||
errors);
|
||||
|
||||
if (!errors->empty()) return 9;
|
||||
@@ -851,7 +849,7 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
|
||||
return 9;
|
||||
}
|
||||
|
||||
- const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, true);
|
||||
+ const int exit_code = ProcessGlobalArgs(&env_argv, nullptr, errors, kAllowedInEnvironment);
|
||||
if (exit_code != 0) return exit_code;
|
||||
}
|
||||
#endif
|
||||
@@ -859,7 +857,7 @@ int InitializeNodeWithArgs(std::vector<std::string>* argv,
|
||||
if (g_upstream_node_mode) {
|
||||
// NOTE(jeremy): indentation is intentionally wrong here, to ease rebasing.
|
||||
|
||||
- const int exit_code = ProcessGlobalArgs(argv, exec_argv, errors, false);
|
||||
+ const int exit_code = ProcessGlobalArgs(argv, exec_argv, errors, kDisallowedInEnvironment);
|
||||
if (exit_code != 0) return exit_code;
|
||||
|
||||
// Set the process.title immediately after processing argv if --title is set.
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 9c6dcbf7014f7cf87f7f66886cbf255978c244fa..4f2da9a46966199465a33c1fa275d0116d395a56 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -223,6 +223,16 @@ NODE_EXTERN void Init(int* argc,
|
||||
int* exec_argc,
|
||||
const char*** exec_argv);
|
||||
|
||||
+enum OptionEnvvarSettings {
|
||||
+ kAllowedInEnvironment,
|
||||
+ kDisallowedInEnvironment
|
||||
+};
|
||||
+
|
||||
+NODE_EXTERN int ProcessGlobalArgs(std::vector<std::string>* args,
|
||||
+ std::vector<std::string>* exec_args,
|
||||
+ std::vector<std::string>* errors,
|
||||
+ OptionEnvvarSettings settings);
|
||||
+
|
||||
class NodeArrayBufferAllocator;
|
||||
|
||||
// An ArrayBuffer::Allocator class with some Node.js-specific tweaks. If you do
|
||||
diff --git a/src/node_options.h b/src/node_options.h
|
||||
index 4ce5551284bb5b1b4194905a9fe619f852933405..404cb72536cdaf8f0320770392e02ac75c303cae 100644
|
||||
--- a/src/node_options.h
|
||||
+++ b/src/node_options.h
|
||||
@@ -248,11 +248,6 @@ HostPort NODE_EXTERN SplitHostPort(const std::string& arg,
|
||||
std::vector<std::string>* errors);
|
||||
void GetOptions(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
-enum OptionEnvvarSettings {
|
||||
- kAllowedInEnvironment,
|
||||
- kDisallowedInEnvironment
|
||||
-};
|
||||
-
|
||||
enum OptionType {
|
||||
kNoOp,
|
||||
kV8Option,
|
||||
diff --git a/src/node_worker.cc b/src/node_worker.cc
|
||||
index c8b2e1699f26ac9bfeb373653d35271f9b6c841f..a4db86ad99c75e07960a95247a41ed78e5bf55ca 100644
|
||||
--- a/src/node_worker.cc
|
||||
+++ b/src/node_worker.cc
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
-using node::options_parser::kDisallowedInEnvironment;
|
||||
+using node::kDisallowedInEnvironment;
|
||||
using v8::Array;
|
||||
using v8::Boolean;
|
||||
using v8::Context;
|
||||
|
|
@ -51,14 +51,8 @@
|
|||
"parallel/test-buffer-constructor-node-modules-paths",
|
||||
"parallel/test-buffer-constructor-outside-node-modules",
|
||||
"parallel/test-child-process-fork-exec-path",
|
||||
"parallel/test-child-process-windows-hide",
|
||||
"parallel/test-cli-bad-options",
|
||||
"parallel/test-cli-eval",
|
||||
"parallel/test-cli-node-options",
|
||||
"parallel/test-cli-node-print-help",
|
||||
"parallel/test-cli-syntax-eval",
|
||||
"parallel/test-cli-syntax-piped-bad",
|
||||
"parallel/test-cli-syntax-piped-good",
|
||||
"parallel/test-cli-eval",
|
||||
"parallel/test-code-cache",
|
||||
"parallel/test-common-gc",
|
||||
"parallel/test-crypto",
|
||||
|
@ -86,7 +80,6 @@
|
|||
"parallel/test-debug-usage",
|
||||
"parallel/test-debugger-pid",
|
||||
"parallel/test-domain-abort-on-uncaught",
|
||||
"parallel/test-domain-async-id-map-leak",
|
||||
"parallel/test-domain-with-abort-on-uncaught-exception",
|
||||
"parallel/test-dummy-stdio",
|
||||
"parallel/test-freeze-intrinsics",
|
||||
|
@ -108,8 +101,7 @@
|
|||
"parallel/test-inspector-tracing-domain",
|
||||
"parallel/test-inspector-vm-global-accessors-getter-sideeffect",
|
||||
"parallel/test-inspector-vm-global-accessors-sideeffects",
|
||||
"parallel/test-inspector-workers-flat-list",
|
||||
"parallel/test-internal-util-weakreference",
|
||||
"parallel/test-inspector-heap-allocation-tracker",
|
||||
"parallel/test-module-loading-globalpaths",
|
||||
"parallel/test-module-version",
|
||||
"parallel/test-openssl-ca-options",
|
||||
|
@ -121,12 +113,11 @@
|
|||
"parallel/test-process-exception-capture",
|
||||
"parallel/test-process-exception-capture-should-abort-on-uncaught",
|
||||
"parallel/test-process-exception-capture-should-abort-on-uncaught-setflagsfromstring",
|
||||
"parallel/test-process-exec-argv",
|
||||
"parallel/test-process-exit-code",
|
||||
"parallel/test-process-external-stdio-close",
|
||||
"parallel/test-process-external-stdio-close-spawn",
|
||||
"parallel/test-process-versions",
|
||||
"parallel/test-readline-interface",
|
||||
"parallel/test-inspector-tracing-domain",
|
||||
"parallel/test-repl",
|
||||
"parallel/test-repl-harmony",
|
||||
"parallel/test-repl-pretty-custom-stack",
|
||||
|
@ -136,7 +127,6 @@
|
|||
"parallel/test-repl-tab-complete",
|
||||
"parallel/test-repl-uncaught-exception",
|
||||
"parallel/test-repl-underscore",
|
||||
"parallel/test-security-revert-unknown",
|
||||
"parallel/test-signal-handler",
|
||||
"parallel/test-source-map",
|
||||
"parallel/test-stdout-close-catch",
|
||||
|
@ -242,9 +232,6 @@
|
|||
"report/test-report-uncaught-exception",
|
||||
"report/test-report-writereport",
|
||||
"sequential/test-child-process-execsync",
|
||||
"sequential/test-cli-syntax-bad",
|
||||
"sequential/test-cli-syntax-good",
|
||||
"sequential/test-cli-syntax-require",
|
||||
"sequential/test-cpu-prof-default",
|
||||
"sequential/test-cpu-prof-dir-absolute",
|
||||
"sequential/test-cpu-prof-dir-and-name",
|
||||
|
@ -252,11 +239,9 @@
|
|||
"sequential/test-cpu-prof-dir-worker",
|
||||
"sequential/test-cpu-prof-drained",
|
||||
"sequential/test-cpu-prof-exit",
|
||||
"sequential/test-cpu-prof-invalid-options",
|
||||
"sequential/test-cpu-prof-kill",
|
||||
"sequential/test-cpu-prof-name",
|
||||
"sequential/test-cpu-prof-worker-argv",
|
||||
"sequential/test-deprecation-flags",
|
||||
"sequential/test-fs-watch",
|
||||
"sequential/test-heap-prof",
|
||||
"sequential/test-heapdump",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -12,7 +12,7 @@ describe('node feature', () => {
|
|||
const fixtures = path.join(__dirname, '..', 'spec', 'fixtures')
|
||||
describe('child_process', () => {
|
||||
describe('child_process.fork', () => {
|
||||
it('works in browser process', (done) => {
|
||||
it('Works in browser process', (done) => {
|
||||
const child = childProcess.fork(path.join(fixtures, 'module', 'ping.js'))
|
||||
child.on('message', (msg) => {
|
||||
expect(msg).to.equal('message')
|
||||
|
@ -25,11 +25,11 @@ describe('node feature', () => {
|
|||
|
||||
describe('contexts', () => {
|
||||
describe('setTimeout called under Chromium event loop in browser process', () => {
|
||||
it('can be scheduled in time', (done) => {
|
||||
it('Can be scheduled in time', (done) => {
|
||||
setTimeout(done, 0)
|
||||
})
|
||||
|
||||
it('can be promisified', (done) => {
|
||||
it('Can be promisified', (done) => {
|
||||
util.promisify(setTimeout)(0).then(done)
|
||||
})
|
||||
})
|
||||
|
@ -57,54 +57,104 @@ describe('node feature', () => {
|
|||
let child: childProcess.ChildProcessWithoutNullStreams
|
||||
let exitPromise: Promise<any[]>
|
||||
|
||||
afterEach(async () => {
|
||||
if (child && exitPromise) {
|
||||
it('Fails for options disallowed by Node.js itself', (done) => {
|
||||
after(async () => {
|
||||
const [code, signal] = await exitPromise
|
||||
expect(signal).to.equal(null)
|
||||
expect(code).to.equal(0)
|
||||
} else if (child) {
|
||||
child.kill()
|
||||
}
|
||||
})
|
||||
|
||||
it('fails for options disallowed by Node.js itself', (done) => {
|
||||
// Exit code 9 indicates cli flag parsing failure
|
||||
expect(code).to.equal(9)
|
||||
child.kill()
|
||||
})
|
||||
|
||||
const env = Object.assign({}, process.env, { NODE_OPTIONS: '--v8-options' })
|
||||
child = childProcess.spawn(process.execPath, { env })
|
||||
exitPromise = emittedOnce(child, 'exit')
|
||||
|
||||
function cleanup () {
|
||||
let output = ''
|
||||
let success = false
|
||||
const cleanup = () => {
|
||||
child.stderr.removeListener('data', listener)
|
||||
child.stdout.removeListener('data', listener)
|
||||
}
|
||||
|
||||
let output = ''
|
||||
function listener (data: Buffer) {
|
||||
const listener = (data: Buffer) => {
|
||||
output += data
|
||||
if (/electron: --v8-options is not allowed in NODE_OPTIONS/m.test(output)) {
|
||||
success = true
|
||||
cleanup()
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
child.stderr.on('data', listener)
|
||||
child.stdout.on('data', listener)
|
||||
child.on('exit', () => {
|
||||
if (!success) {
|
||||
cleanup()
|
||||
done(new Error(`Unexpected output: ${output.toString()}`))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
it('disallows crypto-related options', (done) => {
|
||||
it('Disallows crypto-related options', (done) => {
|
||||
after(() => {
|
||||
child.kill()
|
||||
})
|
||||
|
||||
const env = Object.assign({}, process.env, { NODE_OPTIONS: '--use-openssl-ca' })
|
||||
child = childProcess.spawn(process.execPath, ['--enable-logging'], { env })
|
||||
|
||||
function cleanup () {
|
||||
let output = ''
|
||||
const cleanup = () => {
|
||||
child.stderr.removeListener('data', listener)
|
||||
child.stdout.removeListener('data', listener)
|
||||
}
|
||||
|
||||
let output = ''
|
||||
function listener (data: Buffer) {
|
||||
const listener = (data: Buffer) => {
|
||||
output += data
|
||||
if (/The NODE_OPTION --use-openssl-ca is not supported in Electron/m.test(output)) {
|
||||
cleanup()
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
child.stderr.on('data', listener)
|
||||
child.stdout.on('data', listener)
|
||||
})
|
||||
})
|
||||
|
||||
describe('Node.js cli flags', () => {
|
||||
let child: childProcess.ChildProcessWithoutNullStreams
|
||||
let exitPromise: Promise<any[]>
|
||||
|
||||
it('Prohibits crypto-related flags in ELECTRON_RUN_AS_NODE mode', (done) => {
|
||||
after(async () => {
|
||||
const [code, signal] = await exitPromise
|
||||
expect(signal).to.equal(null)
|
||||
expect(code).to.equal(9)
|
||||
child.kill()
|
||||
})
|
||||
|
||||
child = childProcess.spawn(process.execPath, ['--force-fips'], {
|
||||
env: { ELECTRON_RUN_AS_NODE: 'true' }
|
||||
})
|
||||
exitPromise = emittedOnce(child, 'exit')
|
||||
|
||||
let output = ''
|
||||
const cleanup = () => {
|
||||
child.stderr.removeListener('data', listener)
|
||||
child.stdout.removeListener('data', listener)
|
||||
}
|
||||
|
||||
const listener = (data: Buffer) => {
|
||||
output += data
|
||||
if (/.*The Node.js cli flag --force-fips is not supported in Electron/m.test(output)) {
|
||||
cleanup()
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
child.stderr.on('data', listener)
|
||||
child.stdout.on('data', listener)
|
||||
})
|
||||
|
@ -124,72 +174,63 @@ describe('node feature', () => {
|
|||
}
|
||||
})
|
||||
|
||||
it('supports starting the v8 inspector with --inspect/--inspect-brk', (done) => {
|
||||
it('Supports starting the v8 inspector with --inspect/--inspect-brk', (done) => {
|
||||
child = childProcess.spawn(process.execPath, ['--inspect-brk', path.join(fixtures, 'module', 'run-as-node.js')], {
|
||||
env: {
|
||||
ELECTRON_RUN_AS_NODE: 'true'
|
||||
}
|
||||
env: { ELECTRON_RUN_AS_NODE: 'true' }
|
||||
})
|
||||
|
||||
let output = ''
|
||||
function cleanup () {
|
||||
child.stderr.removeListener('data', errorDataListener)
|
||||
child.stdout.removeListener('data', outDataHandler)
|
||||
const cleanup = () => {
|
||||
child.stderr.removeListener('data', listener)
|
||||
child.stdout.removeListener('data', listener)
|
||||
}
|
||||
function errorDataListener (data: Buffer) {
|
||||
|
||||
const listener = (data: Buffer) => {
|
||||
output += data
|
||||
if (/^Debugger listening on ws:/m.test(output)) {
|
||||
if (/Debugger listening on ws:/m.test(output)) {
|
||||
cleanup()
|
||||
done()
|
||||
}
|
||||
}
|
||||
function outDataHandler (data: Buffer) {
|
||||
cleanup()
|
||||
done(new Error(`Unexpected output: ${data.toString()}`))
|
||||
}
|
||||
child.stderr.on('data', errorDataListener)
|
||||
child.stdout.on('data', outDataHandler)
|
||||
|
||||
child.stderr.on('data', listener)
|
||||
child.stdout.on('data', listener)
|
||||
})
|
||||
|
||||
it('supports starting the v8 inspector with --inspect and a provided port', (done) => {
|
||||
it('Supports starting the v8 inspector with --inspect and a provided port', (done) => {
|
||||
child = childProcess.spawn(process.execPath, ['--inspect=17364', path.join(fixtures, 'module', 'run-as-node.js')], {
|
||||
env: {
|
||||
ELECTRON_RUN_AS_NODE: 'true'
|
||||
}
|
||||
env: { ELECTRON_RUN_AS_NODE: 'true' }
|
||||
})
|
||||
exitPromise = emittedOnce(child, 'exit')
|
||||
|
||||
let output = ''
|
||||
function cleanup () {
|
||||
child.stderr.removeListener('data', errorDataListener)
|
||||
child.stdout.removeListener('data', outDataHandler)
|
||||
const listener = (data: Buffer) => { output += data }
|
||||
const cleanup = () => {
|
||||
child.stderr.removeListener('data', listener)
|
||||
child.stdout.removeListener('data', listener)
|
||||
}
|
||||
function errorDataListener (data: Buffer) {
|
||||
output += data
|
||||
|
||||
child.stderr.on('data', listener)
|
||||
child.stdout.on('data', listener)
|
||||
child.on('exit', () => {
|
||||
cleanup()
|
||||
if (/^Debugger listening on ws:/m.test(output)) {
|
||||
expect(output.trim()).to.contain(':17364', 'should be listening on port 17364')
|
||||
cleanup()
|
||||
done()
|
||||
} else {
|
||||
done(new Error(`Unexpected output: ${output.toString()}`))
|
||||
}
|
||||
}
|
||||
function outDataHandler (data: Buffer) {
|
||||
cleanup()
|
||||
done(new Error(`Unexpected output: ${data.toString()}`))
|
||||
}
|
||||
child.stderr.on('data', errorDataListener)
|
||||
child.stdout.on('data', outDataHandler)
|
||||
})
|
||||
})
|
||||
|
||||
it('does not start the v8 inspector when --inspect is after a -- argument', (done) => {
|
||||
it('Does not start the v8 inspector when --inspect is after a -- argument', (done) => {
|
||||
child = childProcess.spawn(process.execPath, [path.join(fixtures, 'module', 'noop.js'), '--', '--inspect'])
|
||||
exitPromise = emittedOnce(child, 'exit')
|
||||
|
||||
let output = ''
|
||||
function dataListener (data: Buffer) {
|
||||
output += data
|
||||
}
|
||||
child.stderr.on('data', dataListener)
|
||||
child.stdout.on('data', dataListener)
|
||||
const listener = (data: Buffer) => { output += data }
|
||||
child.stderr.on('data', listener)
|
||||
child.stdout.on('data', listener)
|
||||
child.on('exit', () => {
|
||||
if (output.trim().startsWith('Debugger listening on ws://')) {
|
||||
done(new Error('Inspector was started when it should not have been'))
|
||||
|
@ -200,22 +241,24 @@ describe('node feature', () => {
|
|||
})
|
||||
|
||||
// IPC Electron child process not supported on Windows
|
||||
ifit(process.platform !== 'win32')('does does not crash when quitting with the inspector connected', function (done) {
|
||||
ifit(process.platform !== 'win32')('Does does not crash when quitting with the inspector connected', function (done) {
|
||||
child = childProcess.spawn(process.execPath, [path.join(fixtures, 'module', 'delay-exit'), '--inspect=0'], {
|
||||
stdio: ['ipc']
|
||||
}) as childProcess.ChildProcessWithoutNullStreams
|
||||
exitPromise = emittedOnce(child, 'exit')
|
||||
|
||||
let output = ''
|
||||
function dataListener (data: Buffer) {
|
||||
output += data
|
||||
const cleanup = () => {
|
||||
child.stderr.removeListener('data', listener)
|
||||
child.stdout.removeListener('data', listener)
|
||||
}
|
||||
|
||||
let output = ''
|
||||
let success = false
|
||||
function listener (data: Buffer) {
|
||||
output += data
|
||||
if (output.trim().indexOf('Debugger listening on ws://') > -1 && output.indexOf('\n') > -1) {
|
||||
const socketMatch = output.trim().match(/(ws:\/\/.+:[0-9]+\/.+?)\n/gm)
|
||||
if (socketMatch && socketMatch[0]) {
|
||||
child.stderr.removeListener('data', dataListener)
|
||||
child.stdout.removeListener('data', dataListener)
|
||||
|
||||
const w = (webContents as any).create({}) as WebContents
|
||||
w.loadURL('about:blank')
|
||||
.then(() => w.executeJavaScript(`new Promise(resolve => {
|
||||
|
@ -228,20 +271,24 @@ describe('node feature', () => {
|
|||
.then(() => {
|
||||
(w as any).destroy()
|
||||
child.send('plz-quit')
|
||||
success = true
|
||||
cleanup()
|
||||
done()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
child.stderr.on('data', dataListener)
|
||||
child.stdout.on('data', dataListener)
|
||||
|
||||
child.stderr.on('data', listener)
|
||||
child.stdout.on('data', listener)
|
||||
child.on('exit', () => {
|
||||
if (!success) cleanup()
|
||||
})
|
||||
})
|
||||
|
||||
it('supports js binding', (done) => {
|
||||
it('Supports js binding', (done) => {
|
||||
child = childProcess.spawn(process.execPath, ['--inspect', path.join(fixtures, 'module', 'inspector-binding.js')], {
|
||||
env: {
|
||||
ELECTRON_RUN_AS_NODE: 'true'
|
||||
},
|
||||
env: { ELECTRON_RUN_AS_NODE: 'true' },
|
||||
stdio: ['ipc']
|
||||
}) as childProcess.ChildProcessWithoutNullStreams
|
||||
exitPromise = emittedOnce(child, 'exit')
|
||||
|
@ -256,7 +303,7 @@ describe('node feature', () => {
|
|||
})
|
||||
})
|
||||
|
||||
it('can find a module using a package.json main field', () => {
|
||||
it('Can find a module using a package.json main field', () => {
|
||||
const result = childProcess.spawnSync(process.execPath, [path.resolve(fixtures, 'api', 'electron-main-module', 'app.asar')])
|
||||
expect(result.status).to.equal(0)
|
||||
})
|
||||
|
|
Загрузка…
Ссылка в новой задаче