Repository: electron/electron
Pull request: fix: `window.open` popups are always resizable

#### Description of Change

Closes https://github.com/electron/electron/issues/43591.

Per current WHATWG spec, the `window.open` API should always create a resizable popup window. This change updates the `parseFeaturesString` function to ensure that windows opened with `window.open` are always resizable, regardless of the `resizable` feature string.

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [x] `npm test` passes
- [x] relevant API documentation, tutorials, and examples are updated and follow the [documentation style guide](https://github.com/electron/electron/blob/main/docs/development/style-guide.md)
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Fixed a spec compliance issue with `window.open` where it should always create a resizable popup window but did not.


Changed files:
filename: docs/breaking-changes.md
patch: @@ -21,6 +21,23 @@ macOS 11 (Big Sur) is no longer supported by [Chromium](https://chromium-review.
 Older versions of Electron will continue to run on Big Sur, but macOS 12 (Monterey)
 or later will be required to run Electron v38.0.0 and higher.
 
+### Behavior Changed: window.open popups are always resizable
+
+Per current [WHATWG spec](https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-open-dev), the `window.open` API will now always create a resizable popup window.
+
+To restore previous behavior:
+
+```js
+webContents.setWindowOpenHandler((details) => {
+  return {
+    action: 'allow',
+    overrideBrowserWindowOptions: {
+      resizable: details.features.includes('resizable=yes')
+    }
+  }
+})
+```
+
 ## Planned Breaking API Changes (37.0)
 
 ### Utility Process unhandled rejection behavior change

filename: lib/browser/parse-features-string.ts
patch: @@ -91,6 +91,12 @@ export function parseFeatures (features: string) {
     delete parsed[key];
   }
 
+  // Per spec - https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-open-dev
+  // windows are always resizable.
+  if (parsed.resizable !== undefined) {
+    delete parsed.resizable;
+  }
+
   if (parsed.left !== undefined) parsed.x = parsed.left;
   if (parsed.top !== undefined) parsed.y = parsed.top;
 

filename: spec/chromium-spec.ts
patch: @@ -1273,6 +1273,16 @@ describe('chromium features', () => {
       });
     }
 
+    it('is always resizable', async () => {
+      const w = new BrowserWindow({ show: false });
+      w.loadFile(path.resolve(__dirname, 'fixtures', 'blank.html'));
+      w.webContents.executeJavaScript(`
+        { b = window.open('about:blank', '', 'resizable=no,show=no'); null }
+      `);
+      const [, popup] = await once(app, 'browser-window-created') as [any, BrowserWindow];
+      expect(popup.isResizable()).to.be.true();
+    });
+
     // FIXME(zcbenz): This test is making the spec runner hang on exit on Windows.
     ifit(process.platform !== 'win32')('disables node integration when it is disabled on the parent window', async () => {
       const windowUrl = url.pathToFileURL(path.join(fixturesPath, 'pages', 'window-opener-no-node-integration.html'));