Repository: electron/electron (language: cpp)

Issue:
[Bug]: Unfulfilled loadURL promise on invalid URL load.
### 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

v30.0.0-nightly.20240130

### What operating system are you using?

Windows

### Operating System Version

Windows 10 but not system specific bug.

### What arch are you using?

x64

### Last Known Working Electron version

_No response_

### Expected Behavior

webcontents.loadURL("invalidURL") promise is rejected.

### Actual Behavior

webcontents.loadURL("invalidURL") promise is never fulfilled.

### Testcase Gist URL

https://gist.github.com/38969978ec04e1f315312b2daa02146e

### Additional Information

This is regression after #40640 (#40661).
Invalid URLs navigation never happens and only did-failt-load event is emitted immediately at electron api level (see for example https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_web_contents.cc#L2392 and https://github.com/electron/electron/blob/main/shell/browser/api/electron_api_web_contents.cc#L2447). Navigations are not started so will never finish.


Discussion / hints:

Fix patch:
diff --git a/lib/browser/api/web-contents.ts b/lib/browser/api/web-contents.ts
index 7fcd5dec3f04e..070db86390554 100644
--- a/lib/browser/api/web-contents.ts
+++ b/lib/browser/api/web-contents.ts
@@ -366,11 +366,6 @@ WebContents.prototype.loadURL = function (url, options) {
         resolveAndCleanup();
       }
     };
-    const failListener = (event: Electron.Event, errorCode: number, errorDescription: string, validatedURL: string, isMainFrame: boolean) => {
-      if (!error && isMainFrame) {
-        error = { errorCode, errorDescription, url: validatedURL };
-      }
-    };
 
     let navigationStarted = false;
     let browserInitiatedInPageNavigation = false;
@@ -392,6 +387,14 @@ WebContents.prototype.loadURL = function (url, options) {
         navigationStarted = true;
       }
     };
+    const failListener = (event: Electron.Event, errorCode: number, errorDescription: string, validatedURL: string, isMainFrame: boolean) => {
+      if (!error && isMainFrame) {
+        error = { errorCode, errorDescription, url: validatedURL };
+      }
+      if (!navigationStarted && isMainFrame) {
+        finishListener();
+      }
+    };
     const stopLoadingListener = () => {
       // By the time we get here, either 'finish' or 'fail' should have fired
       // if the navigation occurred. However, in some situations (e.g. when
diff --git a/spec/api-web-contents-spec.ts b/spec/api-web-contents-spec.ts
index 12f1c623fd421..4f6185dd4ce73 100644
--- a/spec/api-web-contents-spec.ts
+++ b/spec/api-web-contents-spec.ts
@@ -519,6 +519,10 @@ describe('webContents module', () => {
       await expect(w.loadURL('file:non-existent')).to.eventually.be.rejected();
       await expect(w.loadURL('file:non-existent')).to.eventually.be.rejected();
     });
+
+    it('invalid URL load rejects', async () => {
+      await expect(w.loadURL('invalidURL')).to.eventually.be.rejected();
+    });
   });
 
   describe('getFocusedWebContents() API', () => {


Test patch: