Repository: electron/electron (language: cpp)

Issue:
[Bug]: app.relaunch loses args when execPath specified.
### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

18.0.1

### What operating system are you using?

macOS

### Operating System Version

10.14.6

### What arch are you using?

x64

### Last Known Working Electron version

17.0.0-alpha.3

### Expected Behavior

When invoking `app.relaunch` and specifying both `execPath` and `args`, I expect the args to be passed to the new process.

### Actual Behavior

The binary specified by `execPath` is spawned as a new process, but the `args` are not applied.

### Testcase Gist URL

https://gist.github.com/p120ph37/98cf0fb13790feed702f3e90cbddfbf6

### Additional Information

This bug was introduced in `17.0.0-alpha.4`, and is present in all newer stable versions up to and including at least `19.0.0-alpha.1`  Also note that `app.relaunch()` doesn't work at all from within Electron Fiddle, so to run this gist, you must launch Electron directly (e.g.: via `npm start`).
[Bug]: app.relaunch loses args when execPath specified.
### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

18.0.1

### What operating system are you using?

macOS

### Operating System Version

10.14.6

### What arch are you using?

x64

### Last Known Working Electron version

17.0.0-alpha.3

### Expected Behavior

When invoking `app.relaunch` and specifying both `execPath` and `args`, I expect the args to be passed to the new process.

### Actual Behavior

The binary specified by `execPath` is spawned as a new process, but the `args` are not applied.

### Testcase Gist URL

https://gist.github.com/p120ph37/98cf0fb13790feed702f3e90cbddfbf6

### Additional Information

This bug was introduced in `17.0.0-alpha.4`, and is present in all newer stable versions up to and including at least `19.0.0-alpha.1`  Also note that `app.relaunch()` doesn't work at all from within Electron Fiddle, so to run this gist, you must launch Electron directly (e.g.: via `npm start`).


Discussion / hints:
Just a note: this does not seem to be MacOS-specific.  I've observed the same issue on Windows too at least.  And it affects the release versions of 17 as well (it was introduced during the 17 alpha phase)
problem from this commit
[https://github.com/electron/electron/commit/1e371621dca5104fc0d91358828579f2b0d65f0a](https://github.com/electron/electron/commit/1e371621dca5104fc0d91358828579f2b0d65f0a)
merged in
[https://github.com/electron/electron/pull/31555/files](https://github.com/electron/electron/pull/31555/files)
Short-circuit evaluation problem
Makes sense.  The similar changes in `native_window.cc` from that same commit appear to have also caused an issue which has already been fixed: #33025
Just a note: this does not seem to be MacOS-specific.  I've observed the same issue on Windows too at least.  And it affects the release versions of 17 as well (it was introduced during the 17 alpha phase)
problem from this commit
[https://github.com/electron/electron/commit/1e371621dca5104fc0d91358828579f2b0d65f0a](https://github.com/electron/electron/commit/1e371621dca5104fc0d91358828579f2b0d65f0a)
merged in
[https://github.com/electron/electron/pull/31555/files](https://github.com/electron/electron/pull/31555/files)
Short-circuit evaluation problem
Makes sense.  The similar changes in `native_window.cc` from that same commit appear to have also caused an issue which has already been fixed: #33025

Fix patch:
diff --git a/shell/browser/api/electron_api_app.cc b/shell/browser/api/electron_api_app.cc
index c3f9bf1ed827c..73ff1d4956309 100644
--- a/shell/browser/api/electron_api_app.cc
+++ b/shell/browser/api/electron_api_app.cc
@@ -1151,7 +1151,9 @@ bool App::Relaunch(gin::Arguments* js_args) {
 
   gin_helper::Dictionary options;
   if (js_args->GetNext(&options)) {
-    if (options.Get("execPath", &exec_path) || options.Get("args", &args))
+    bool has_exec_path = options.Get("execPath", &exec_path);
+    bool has_args = options.Get("args", &args);
+    if (has_exec_path || has_args)
       override_argv = true;
   }
 
diff --git a/spec-main/api-app-spec.ts b/spec-main/api-app-spec.ts
index 347dae24d2b79..a08df928fad1e 100644
--- a/spec-main/api-app-spec.ts
+++ b/spec-main/api-app-spec.ts
@@ -370,9 +370,11 @@ describe('app module', () => {
       server!.once('error', error => done(error));
       server!.on('connection', client => {
         client.once('data', data => {
-          if (String(data) === 'false' && state === 'none') {
+          if (String(data) === '--first' && state === 'none') {
             state = 'first-launch';
-          } else if (String(data) === 'true' && state === 'first-launch') {
+          } else if (String(data) === '--second' && state === 'first-launch') {
+            state = 'second-launch';
+          } else if (String(data) === '--third' && state === 'second-launch') {
             done();
           } else {
             done(`Unexpected state: "${state}", data: "${data}"`);
@@ -381,7 +383,7 @@ describe('app module', () => {
       });
 
       const appPath = path.join(fixturesPath, 'api', 'relaunch');
-      const child = cp.spawn(process.execPath, [appPath]);
+      const child = cp.spawn(process.execPath, [appPath, '--first']);
       child.stdout.on('data', (c) => console.log(c.toString()));
       child.stderr.on('data', (c) => console.log(c.toString()));
       child.on('exit', (code, signal) => {
diff --git a/spec/fixtures/api/relaunch/main.js b/spec/fixtures/api/relaunch/main.js
index 272c41f4421aa..94898f6059d65 100644
--- a/spec/fixtures/api/relaunch/main.js
+++ b/spec/fixtures/api/relaunch/main.js
@@ -11,11 +11,15 @@ app.whenReady().then(() => {
   const lastArg = process.argv[process.argv.length - 1];
   const client = net.connect(socketPath);
   client.once('connect', () => {
-    client.end(String(lastArg === '--second'));
+    client.end(lastArg);
   });
   client.once('end', () => {
-    if (lastArg !== '--second') {
-      app.relaunch({ args: process.argv.slice(1).concat('--second') });
+    if (lastArg === '--first') {
+      // Once without execPath specified
+      app.relaunch({ args: process.argv.slice(1, -1).concat('--second') });
+    } else if (lastArg === '--second') {
+      // And once with execPath specified
+      app.relaunch({ execPath: process.argv[0], args: process.argv.slice(1, -1).concat('--third') });
     }
     app.exit(0);
   });


Test patch: