Compare commits

..

3 Commits

Author SHA1 Message Date
Samuel Attard
0d6eec0137 ci: bump patched siso to v1.5.7-electron.2
Picks up the stderr logging for ERROR_INVALID_PARAMETER retries so
they're visible in the Windows build step output rather than only in
the glog .WARNING file.
2026-04-08 16:48:42 -07:00
Samuel Attard
463c0d5e24 ci: use patched siso on Windows to retry transient ninja-load failures
Downloads a checksum-pinned build from electron/siso and sets SISO_PATH
so depot_tools picks it up instead of the CIPD binary. The patched build
retries ERROR_INVALID_PARAMETER from CreateFileW during the subninja
scan, which intermittently fires on container bind-mounted out/ dirs and
otherwise aborts the whole build. Drop this once the fix rolls into
Chromium's siso_version.
2026-04-08 15:41:34 -07:00
Samuel Attard
aa8cc40afa ci: use 32-core Windows ARC runners for builds 2026-04-08 13:22:45 -07:00
16 changed files with 53 additions and 113 deletions

View File

@@ -30,3 +30,19 @@ runs:
echo "$HOME/.electron_build_tools/third_party/depot_tools" >> $GITHUB_PATH
echo "$HOME/.electron_build_tools/third_party/depot_tools/python-bin" >> $GITHUB_PATH
fi
- name: Install patched siso (Windows)
# Overrides the CIPD siso with a build from electron/siso that carries a
# retry for transient ERROR_INVALID_PARAMETER during the subninja scan on
# container bind-mounted out/ directories. Remove once the fix has rolled
# into Chromium's siso_version.
if: ${{ runner.os == 'Windows' }}
shell: bash
env:
ELECTRON_SISO_URL: https://github.com/electron/siso/releases/download/v1.5.7-electron.2/siso-windows-amd64.exe
ELECTRON_SISO_SHA256: 0e6b754820be3324d5ea4ca3af3634b4cfcf806d89140d78fec4e2a8ef636c9d
run: |
set -eo pipefail
mkdir -p /c/electron-siso
curl --fail --retry 3 -sSL "$ELECTRON_SISO_URL" -o /c/electron-siso/siso.exe
echo "$ELECTRON_SISO_SHA256 /c/electron-siso/siso.exe" | sha256sum --check --strict -
echo "SISO_PATH=C:\\electron-siso\\siso.exe" >> "$GITHUB_ENV"

View File

@@ -387,7 +387,7 @@ jobs:
needs: checkout-windows
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
with:
build-runs-on: electron-arc-centralus-windows-amd64-16core
build-runs-on: electron-arc-centralus-windows-amd64-32core
test-runs-on: windows-latest
target-platform: win
target-arch: x64
@@ -406,7 +406,7 @@ jobs:
needs: checkout-windows
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
with:
build-runs-on: electron-arc-centralus-windows-amd64-16core
build-runs-on: electron-arc-centralus-windows-amd64-32core
test-runs-on: windows-latest
target-platform: win
target-arch: x86
@@ -425,7 +425,7 @@ jobs:
needs: checkout-windows
if: ${{ needs.setup.outputs.src == 'true' && !inputs.skip-windows }}
with:
build-runs-on: electron-arc-centralus-windows-amd64-16core
build-runs-on: electron-arc-centralus-windows-amd64-32core
test-runs-on: windows-11-arm
target-platform: win
target-arch: arm64

View File

@@ -61,7 +61,7 @@ jobs:
needs: checkout-windows
with:
environment: production-release
build-runs-on: electron-arc-centralus-windows-amd64-16core
build-runs-on: electron-arc-centralus-windows-amd64-32core
target-platform: win
target-arch: x64
is-release: true
@@ -80,7 +80,7 @@ jobs:
needs: checkout-windows
with:
environment: production-release
build-runs-on: electron-arc-centralus-windows-amd64-16core
build-runs-on: electron-arc-centralus-windows-amd64-32core
target-platform: win
target-arch: arm64
is-release: true
@@ -99,7 +99,7 @@ jobs:
needs: checkout-windows
with:
environment: production-release
build-runs-on: electron-arc-centralus-windows-amd64-16core
build-runs-on: electron-arc-centralus-windows-amd64-32core
target-platform: win
target-arch: x86
is-release: true

View File

@@ -21,7 +21,7 @@
"@types/semver": "^7.5.8",
"@types/stream-json": "^1.7.8",
"@types/temp": "^0.9.4",
"@xmldom/xmldom": "^0.8.12",
"@xmldom/xmldom": "^0.8.11",
"buffer": "^6.0.3",
"chalk": "^4.1.0",
"check-for-leaks": "^1.2.1",

View File

@@ -8,9 +8,7 @@ from pathlib import Path
SRC_DIR = Path(__file__).resolve().parents[3]
sys.path.append(os.path.join(SRC_DIR, 'third_party/electron_node/tools'))
sys.path.append(str(Path(__file__).resolve().parents[1])) # electron/script/
from lib.util import get_out_dir
import install
class LoadPythonDictionaryError(Exception):
@@ -33,6 +31,13 @@ def LoadPythonDictionary(path):
)
return file_data
def get_out_dir():
out_dir = 'Testing'
override = os.environ.get('ELECTRON_OUT_DIR')
if override is not None:
out_dir = override
return os.path.join(SRC_DIR, 'out', out_dir)
if __name__ == '__main__':
node_root_dir = os.path.join(SRC_DIR, 'third_party/electron_node')
out = {}

View File

@@ -276,7 +276,6 @@ void Menu::OnMenuWillClose() {
}
void Menu::OnMenuWillShow() {
keep_alive_ = this;
Emit("menu-will-show");
}

View File

@@ -132,7 +132,7 @@ class Menu : public gin::Wrappable<Menu>,
int GetIndexOfCommandId(int command_id) const;
int GetItemCount() const;
gin_helper::SelfKeepAlive<Menu> keep_alive_{nullptr};
gin_helper::SelfKeepAlive<Menu> keep_alive_{this};
};
} // namespace electron::api

View File

@@ -1357,11 +1357,7 @@ void ElectronBrowserClient::WillCreateURLLoaderFactory(
DCHECK(web_request);
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
// If Electron's webRequest API has no listeners, proxy requests using
// chrome.webRequest extension APIs.
// Note that Electron's net.fetch and protocol.handle APIs do not include the
// frame host which is required for proxying requests.
if (!web_request->HasListener() && frame_host) {
if (!web_request->HasListener()) {
auto* web_request_api = extensions::BrowserContextKeyedAPIFactory<
extensions::WebRequestAPI>::Get(browser_context);

View File

@@ -158,43 +158,45 @@ using TitleBarStyle = electron::NativeWindowMac::TitleBarStyle;
windowSize.width() - contentSize.width() + extraSize.width();
double extraHeightPlusFrame = titleBarHeight + extraSize.height();
auto widthForHeight = [&](double h) {
return (h - extraHeightPlusFrame) * aspectRatio + extraWidthPlusFrame;
};
auto heightForWidth = [&](double w) {
return (w - extraWidthPlusFrame) / aspectRatio + extraHeightPlusFrame;
};
newSize.width = roundf(widthForHeight(frameSize.height));
newSize.height = roundf(heightForWidth(newSize.width));
newSize.width =
roundf((frameSize.height - extraHeightPlusFrame) * aspectRatio +
extraWidthPlusFrame);
newSize.height =
roundf((newSize.width - extraWidthPlusFrame) / aspectRatio +
extraHeightPlusFrame);
// Clamp to minimum width/height while ensuring aspect ratio remains.
NSSize minSize = [window minSize];
NSSize zeroSize =
shell_->has_frame() ? NSMakeSize(0, titleBarHeight) : NSZeroSize;
if (!NSEqualSizes(minSize, zeroSize)) {
double minWidthForAspectRatio =
(minSize.height - titleBarHeight) * aspectRatio;
bool atMinHeight =
minSize.height > zeroSize.height && newSize.height <= minSize.height;
newSize.width = atMinHeight ? widthForHeight(minSize.height)
newSize.width = atMinHeight ? minWidthForAspectRatio
: std::max(newSize.width, minSize.width);
double minHeightForAspectRatio = minSize.width / aspectRatio;
bool atMinWidth =
minSize.width > zeroSize.width && newSize.width <= minSize.width;
newSize.height = atMinWidth ? heightForWidth(minSize.width)
newSize.height = atMinWidth ? minHeightForAspectRatio
: std::max(newSize.height, minSize.height);
}
// Clamp to maximum width/height while ensuring aspect ratio remains.
NSSize maxSize = [window maxSize];
if (!NSEqualSizes(maxSize, NSMakeSize(FLT_MAX, FLT_MAX))) {
double maxWidthForAspectRatio = maxSize.height * aspectRatio;
bool atMaxHeight =
maxSize.height < FLT_MAX && newSize.height >= maxSize.height;
newSize.width = atMaxHeight ? widthForHeight(maxSize.height)
newSize.width = atMaxHeight ? maxWidthForAspectRatio
: std::min(newSize.width, maxSize.width);
double maxHeightForAspectRatio = maxSize.width / aspectRatio;
bool atMaxWidth =
maxSize.width < FLT_MAX && newSize.width >= maxSize.width;
newSize.height = atMaxWidth ? heightForWidth(maxSize.width)
newSize.height = atMaxWidth ? maxHeightForAspectRatio
: std::min(newSize.height, maxSize.height);
}
}

View File

@@ -5,11 +5,11 @@
#include "shell/common/crash_keys.h"
#include <cstdint>
#include <deque>
#include <map>
#include <string>
#include "base/command_line.h"
#include "base/containers/circular_deque.h"
#include "base/environment.h"
#include "base/no_destructor.h"
#include "base/strings/strcat.h"
@@ -28,22 +28,17 @@ namespace electron::crash_keys {
namespace {
// Do NOT replace with base::circular_deque. CrashKeyString wraps a
// crashpad::Annotation that holds self-referential pointers and registers
// in a process-global linked list; relocating elements (as circular_deque
// does on growth) corrupts that list and hangs the crashpad handler.
// std::deque never relocates existing elements. See #50795.
auto& GetExtraCrashKeys() {
constexpr size_t kMaxCrashKeyValueSize = 20320;
static_assert(kMaxCrashKeyValueSize < crashpad::Annotation::kValueMaxSize,
"max crash key value length above what crashpad supports");
using CrashKeyString = crash_reporter::CrashKeyString<kMaxCrashKeyValueSize>;
static base::NoDestructor<std::deque<CrashKeyString>> extra_keys;
static base::NoDestructor<base::circular_deque<CrashKeyString>> extra_keys;
return *extra_keys;
}
auto& GetExtraCrashKeyNames() {
static base::NoDestructor<std::deque<std::string>> crash_key_names;
static base::NoDestructor<base::circular_deque<std::string>> crash_key_names;
return *crash_key_names;
}

View File

@@ -250,34 +250,6 @@ ifdescribe(!isLinuxOnArm && !process.mas && !process.env.DISABLE_CRASH_REPORTER_
expect(crash.addedThenRemoved).to.be.undefined();
});
// Regression: base::circular_deque relocates elements on growth,
// corrupting crashpad::Annotation's self-referential pointers and
// causing missing crash keys or a hung handler. See crash_keys.cc.
it('does not corrupt the crashpad annotation list after deque reallocation', async function () {
// Tight timeout so a hanging handler fails fast instead of waiting
// for the mocha default of 120s.
this.timeout(45000);
const { port, waitForCrash } = await startServer();
runCrashApp('renderer-dynamic-keys', port);
const crash = await Promise.race([
waitForCrash(),
new Promise<never>((_resolve, reject) => {
global.setTimeout(
() => reject(new Error('crashpad handler hung walking corrupted annotation list; crash upload did not arrive within 30s')),
30000
);
})
]);
expect(crash.process_type).to.equal('renderer');
const missing: string[] = [];
for (let i = 0; i < 50; i++) {
if ((crash as any)[`dyn-key-${i}`] !== `val-${i}`) {
missing.push(`dyn-key-${i}`);
}
}
expect(missing, `missing dynamic crash keys: ${missing.join(', ')}`).to.be.empty();
});
it('contains v8 crash keys when a v8 crash occurs', async () => {
const { remotely } = await startRemoteControlApp();
const { port, waitForCrash } = await startServer();

View File

@@ -1,4 +1,4 @@
import { app, session, webFrameMain, BrowserWindow, ipcMain, net, WebContents, Extension, Session, ServiceWorkerInfo, ServiceWorkersRunningStatusChangedEventParams } from 'electron/main';
import { app, session, webFrameMain, BrowserWindow, ipcMain, WebContents, Extension, Session, ServiceWorkerInfo, ServiceWorkersRunningStatusChangedEventParams } from 'electron/main';
import { expect } from 'chai';
import * as WebSocket from 'ws';
@@ -434,12 +434,6 @@ describe('chrome extensions', () => {
});
});
});
it('does not crash when net.fetch is called', async () => {
await session.defaultSession.loadExtension(path.join(fixtures, 'extensions', 'chrome-webRequest-non-blocking'));
const requestUrl = `${url}/test.zip`;
await net.fetch(requestUrl);
});
});
describe('chrome.tabs', () => {

View File

@@ -51,19 +51,6 @@ app.whenReady().then(() => {
});
w.loadURL(`about:blank?set_extra=${setExtraParameters ? 1 : 0}`);
w.webContents.on('render-process-gone', () => process.exit(0));
} else if (crashType === 'renderer-dynamic-keys') {
const w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, contextIsolation: false } });
w.webContents.on('render-process-gone', () => process.exit(0));
w.webContents.on('did-finish-load', () => {
w.webContents.executeJavaScript(`
const { crashReporter } = require('electron');
for (let i = 0; i < 50; i++) {
crashReporter.addExtraParameter('dyn-key-' + i, 'val-' + i);
}
process.crash();
`);
});
w.loadURL('about:blank');
} else if (crashType === 'node') {
const crashPath = path.join(__dirname, 'node-crash.js');
const child = childProcess.fork(crashPath, { silent: true });

View File

@@ -1,9 +0,0 @@
/* global chrome */
chrome.webRequest.onBeforeRequest.addListener(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(details) => {
console.log(details);
},
{ urls: ['<all_urls>'] }
);

View File

@@ -1,10 +0,0 @@
{
"name": "chrome-webRequest-non-blocking",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"permissions": ["webRequest"],
"manifest_version": 3,
"host_permissions": ["<all_urls>"]
}

View File

@@ -590,7 +590,7 @@ __metadata:
"@types/semver": "npm:^7.5.8"
"@types/stream-json": "npm:^1.7.8"
"@types/temp": "npm:^0.9.4"
"@xmldom/xmldom": "npm:^0.8.12"
"@xmldom/xmldom": "npm:^0.8.11"
buffer: "npm:^6.0.3"
chalk: "npm:^4.1.0"
check-for-leaks: "npm:^1.2.1"
@@ -2503,14 +2503,7 @@ __metadata:
languageName: node
linkType: hard
"@xmldom/xmldom@npm:^0.8.12":
version: 0.8.12
resolution: "@xmldom/xmldom@npm:0.8.12"
checksum: 10c0/b733c84292d1bee32ef21a05aba8f9063456b51a54068d0b4a1abf5545156ee0b9894b7ae23775b5881b11c35a8a03871d1b514fb7e1b11654cdbee57e1c2707
languageName: node
linkType: hard
"@xmldom/xmldom@npm:^0.8.8":
"@xmldom/xmldom@npm:^0.8.11, @xmldom/xmldom@npm:^0.8.8":
version: 0.8.11
resolution: "@xmldom/xmldom@npm:0.8.11"
checksum: 10c0/e768623de72c95d3dae6b5da8e33dda0d81665047811b5498d23a328d45b13feb5536fe921d0308b96a4a8dd8addf80b1f6ef466508051c0b581e63e0dc74ed5