Compare commits

...

12 Commits

Author SHA1 Message Date
David Sanders
efb3fd98c6 build: lint commits on Chromium roller branches (#49655)
* build: lint commits on Chromium roller branches

Assisted-By: Claude Opus 4.5

* chore: add ability to skip linting CLs by adding #nolint

* chore: only exit with non-zero exit code in CI
2026-02-18 20:45:44 -08:00
Shelley Vohr
9ca9311b73 docs: note required windows in 'new-window-for-tab' event (#49851)
docs: note required windows in new-window-for-tab
2026-02-18 19:30:43 -08:00
Samuel Attard
8b05717661 docs: clarify ASAR integrity is supported in MAS builds (#49852)
* docs: clarify ASAR integrity is supported in MAS builds

Add a note to the ASAR integrity documentation explicitly stating
that this feature is fully supported and recommended in Mac App
Store builds. While MAS-installed apps have system-level protections,
ASAR integrity provides an additional security layer and is important
for MAS builds distributed outside the Mac App Store.

Slack thread: https://electronhq.slack.com/archives/CB6CG54DB/p1771449093872419?thread_ts=1771446183.473289&cid=CB6CG54DB

https://claude.ai/code/session_01A97nfiqHUVxLNaQyHVXS7j

* docs: clarify ASAR integrity support for MAS builds

Updates the ASAR integrity documentation to explicitly mention that
it is supported and recommended in Mac App Store builds. Clarifies
that while MAS-installed apps have system-level protections (Resources
folder owned by root), ASAR integrity is especially important when
distributing MAS builds through other channels like direct download,
since those installations won't have the read-only protections.

https://claude.ai/code/session_012mBNZQW34h91NRcdFaLxNh

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-02-18 14:14:00 -08:00
John Kleinschmidt
be45b5f8e7 ci: fixup build stats upload on Windows (#49845) 2026-02-18 15:00:30 -05:00
dependabot[bot]
87597a99de build(deps-dev): bump webpack from 5.95.0 to 5.104.1 in the npm_and_yarn group across 1 directory (#49779)
build(deps-dev): bump webpack

Bumps the npm_and_yarn group with 1 update in the / directory: [webpack](https://github.com/webpack/webpack).


Updates `webpack` from 5.95.0 to 5.104.1
- [Release notes](https://github.com/webpack/webpack/releases)
- [Changelog](https://github.com/webpack/webpack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack/compare/v5.95.0...v5.104.1)

---
updated-dependencies:
- dependency-name: webpack
  dependency-version: 5.104.1
  dependency-type: direct:development
  dependency-group: npm_and_yarn
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-02-18 14:22:25 -05:00
Shelley Vohr
3ed52a3ded build: roll sysroots (#49844) 2026-02-18 13:24:29 -05:00
Shelley Vohr
dfdf04976e fix: draggable region position with docked DevTools (#49822) 2026-02-18 11:49:18 -05:00
Shelley Vohr
f4ba25a3da fix: frameless window resize in MAS builds (#49780) 2026-02-18 10:35:10 -05:00
Robo
05061544ab feat: enable WASM trap handlers in all Node.js processes (#48983)
fix: enable WASM trap handlers in all Node.js processes

```
Original reason for revert:

Some apps started throwing exception on startup
https://github.com/electron/electron/issues/48956
```

We now move the trap handler registeration before
any user script execution. Add a fuse to support
disabling the feature is application needs to run
in memory constrained environments.
2026-02-18 12:08:03 +09:00
Sam Maddock
10566c2d5f test: MAS for private API usage (#49712) 2026-02-17 15:29:21 -05:00
Mitchell Cohen
931c257de7 fix: accurate window sizing and support for content sizing on Linux/Wayland with CSD (#49209)
* fix window sizing and content sizing on Linux when CSD is in use

* fixed size constraints

* simplify min/max size calculation

* use base window size for min/max

* moved windows min/max size overrides

* remove unnecessary checks for client frame

* cleanup
2026-02-17 15:23:54 -05:00
Ronald Eddy Jr
459a88f788 docs: fix typos across tutorial documentation (#49736) 2026-02-17 14:47:45 -05:00
57 changed files with 1144 additions and 423 deletions

View File

@@ -98,7 +98,7 @@ runs:
# Upload build stats to Datadog
if ($env:DD_API_KEY) {
try {
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats ; $LASTEXITCODE = 0
} catch {
Write-Host "Build stats upload failed, continuing..."
}

View File

@@ -9,5 +9,6 @@
"embedded_asar_integrity_validation": "0",
"only_load_app_from_asar": "0",
"load_browser_process_specific_v8_snapshot": "0",
"grant_file_protocol_extra_privileges": "1"
"grant_file_protocol_extra_privileges": "1",
"wasm_trap_handlers": "1"
}

View File

@@ -250,7 +250,9 @@ Returns:
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current `BrowserWindow` has a
`tabbingIdentifier`
`tabbingIdentifier`.
You must create a window in this handler in order for macOS tabbing to work as expected.
### Event: 'browser-window-blur'

View File

@@ -351,7 +351,11 @@ Emitted when the window has closed a sheet.
#### Event: 'new-window-for-tab' _macOS_
Emitted when the native new tab button is clicked.
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current `BrowserWindow` has a
`tabbingIdentifier`.
You must create a window in this handler in order for macOS tabbing to work as expected.
#### Event: 'system-context-menu' _Windows_ _Linux_

View File

@@ -435,7 +435,11 @@ Emitted when the window has closed a sheet.
#### Event: 'new-window-for-tab' _macOS_
Emitted when the native new tab button is clicked.
Emitted when the user clicks the native macOS new tab button. The new
tab button is only visible if the current `BrowserWindow` has a
`tabbingIdentifier`.
You must create a window in this handler in order for macOS tabbing to work as expected.
#### Event: 'system-context-menu' _Windows_ _Linux_

View File

@@ -6,7 +6,7 @@ hide_title: false
---
After creating an [application distribution](application-distribution.md), the
app's source code are usually bundled into an [ASAR archive](https://github.com/electron/asar),
app's source code is usually bundled into an [ASAR archive](https://github.com/electron/asar),
which is a simple extensive archive format designed for Electron apps. By bundling the app
we can mitigate issues around long path names on Windows, speed up `require` and conceal your source
code from cursory inspection.
@@ -134,7 +134,7 @@ underlying system calls, Electron will extract the needed file into a
temporary file and pass the path of the temporary file to the APIs to make them
work. This adds a little overhead for those APIs.
APIs that requires extra unpacking are:
APIs that require extra unpacking are:
* `child_process.execFile`
* `child_process.execFileSync`

View File

@@ -15,6 +15,14 @@ Currently, ASAR integrity checking is supported on:
* macOS as of `electron>=16.0.0`
* Windows as of `electron>=30.0.0`
> [!NOTE]
> ASAR integrity is fully supported in Mac App Store (MAS) builds and is recommended
> as a best practice. While MAS-installed applications have their `Resources/` folder
> protected by the system (owned by root), ASAR integrity still provides an additional
> layer of security. It is especially important if you use Electron's MAS build but
> distribute your app through channels other than the Mac App Store (such as direct
> download), since those installations won't have the system-level read-only protections.
In order to enable ASAR integrity checking, you also need to ensure that your `app.asar` file
was generated by a version of the `@electron/asar` npm package that supports ASAR integrity.
@@ -24,7 +32,7 @@ All versions of `@electron/asar` support ASAR integrity.
## How it works
Each ASAR archive contains a JSON string header. The header format includes an `integrity` object
that contain a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
that contains a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
block of `blockSize` bytes.
```json

View File

@@ -203,7 +203,7 @@ test('launch app', async () => {
})
```
After that, you will access to an instance of Playwright's `ElectronApp` class. This
After that, you will have access to an instance of Playwright's `ElectronApp` class. This
is a powerful class that has access to main process modules for example:
```js {5-10} @ts-nocheck
@@ -237,7 +237,7 @@ test('save screenshot', async () => {
})
```
Putting all this together using the Playwright test-runner, let's create a `example.spec.js`
Putting all this together using the Playwright test-runner, let's create an `example.spec.js`
test file with a single test and assertion:
```js title='example.spec.js' @ts-nocheck
@@ -377,7 +377,7 @@ class TestDriver {
module.exports = { TestDriver }
```
In your app code, can then write a simple handler to receive RPC calls:
In your app code, you can then write a simple handler to receive RPC calls:
```js title='main.js'
const METHODS = {

View File

@@ -17,7 +17,7 @@ run them, users need to go through multiple advanced and manual steps.
If you are building an Electron app that you intend to package and distribute,
it should be code signed. The Electron ecosystem tooling makes codesigning your
apps straightforward - this documentation explains how sign your apps on both
apps straightforward - this documentation explains how to sign your apps on both
Windows and macOS.
## Signing & notarizing macOS builds

View File

@@ -110,7 +110,7 @@ const win = new BrowserWindow({
#### Show and hide the traffic lights programmatically _macOS_
You can also show and hide the traffic lights programmatically from the main process.
The `win.setWindowButtonVisibility` forces traffic lights to be show or hidden depending
The `win.setWindowButtonVisibility` forces traffic lights to be shown or hidden depending
on the value of its boolean parameter.
```js title='main.js'

View File

@@ -5,12 +5,12 @@
By default, windows are dragged using the title bar provided by the OS chrome. Apps
that remove the default title bar need to use the `app-region` CSS property to define
specific areas that can be used to drag the window. Setting `app-region: drag` marks
a rectagular area as draggable.
a rectangular area as draggable.
It is important to note that draggable areas ignore all pointer events. For example,
a button element that overlaps a draggable region will not emit mouse clicks or mouse
enter/exit events within that overlapping area. Setting `app-region: no-drag` reenables
pointer events by excluding a rectagular area from a draggable region.
pointer events by excluding a rectangular area from a draggable region.
To make the whole window draggable, you can add `app-region: drag` as
`body`'s style:

View File

@@ -29,7 +29,7 @@ be updated accordingly.
In macOS 10.14 Mojave, Apple introduced a new [system-wide dark mode][system-wide-dark-mode]
for all macOS computers. If your Electron app has a dark mode, you can make it
follow the system-wide dark mode setting using
[the `nativeTheme` api](../api/native-theme.md).
[the `nativeTheme` API](../api/native-theme.md).
In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option
for all macOS computers. In order for the `nativeTheme.shouldUseDarkColors` and

View File

@@ -137,6 +137,33 @@ The extra privileges granted to the `file://` protocol by this fuse are incomple
* `file://` protocol pages have universal access granted to child frames also running on `file://`
protocols regardless of sandbox settings
### `wasmTrapHandlers`
**Default:** Enabled
**@electron/fuses:** `FuseV1Options.WasmTrapHandlers`
The `wasmTrapHandlers` fuse controls whether V8 will use signal handlers to trap Out of Bounds memory
access from WebAssembly. The feature works by surrounding the WebAssembly memory with large guard regions
and then installing a signal handler that traps attempt to access memory in the guard region. The feature
is only supported on the following 64-bit systems.
Linux. MacOS, Windows - x86_64
Linux, MacOS - aarch64
| Guard Pages | WASM heap | Guard Pages |
|-----8GB-----| |-----8GB-----|
When the fuse is disabled V8 will use explicit bound checks in the generated WebAssembly code to ensure
memory safety. However, this method has some downsides
* The compiler generates extra nodes for each memory reference, leading to longer compile times due to the
additional processing time needed for these nodes.
* In turn, these extra nodes lead to lots of extra code being generated, making WebAssembly modules bigger
than they ideally should be.
* This extra code, particularly the compare and branch before every memory reference,
incurs a significant runtime cost.
## How do I flip fuses?
### The easy way

View File

@@ -171,7 +171,7 @@ sections.
In the main process, we'll be creating a `handleFileOpen()` function that calls
`dialog.showOpenDialog` and returns the value of the file path selected by the user. This function
is used as a callback whenever an `ipcRender.invoke` message is sent through the `dialog:openFile`
is used as a callback whenever an `ipcRenderer.invoke` message is sent through the `dialog:openFile`
channel from the renderer process. The return value is then returned as a Promise to the original
`invoke` call.
@@ -446,7 +446,7 @@ After loading the preload script, your renderer process should have access to th
We don't directly expose the whole `ipcRenderer.on` API for [security reasons][]. Make sure to
limit the renderer's access to Electron APIs as much as possible.
Also don't just pass the callback to `ipcRenderer.on` as this will leak `ipcRenderer` via `event.sender`.
Use a custom handler that invoke the `callback` only with the desired arguments.
Use a custom handler that invokes the `callback` only with the desired arguments.
:::
:::info

View File

@@ -10,7 +10,7 @@ hide_title: false
## Accelerators
Accelerators are strings that can be used to represent keyboard shortcuts throughout your Electron.
These strings can contain multiple modifiers keys and a single key code joined by the `+` character.
These strings can contain multiple modifier keys and a single key code joined by the `+` character.
> [!NOTE]
> Accelerators are **case-insensitive**.

View File

@@ -62,9 +62,9 @@ const createWindow = () => {
}
```
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
This code will be different in Windows and Linux compared to MacOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
This code will be different in Windows and Linux compared to macOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
#### Windows and Linux code:
@@ -91,7 +91,7 @@ if (!gotTheLock) {
}
```
#### MacOS code:
#### macOS code:
```js @ts-type={createWindow:()=>void}
// This method will be called when Electron has finished

View File

@@ -65,7 +65,7 @@ The full list of certificate types can be found
Apps signed with "Apple Development" and "Apple Distribution" certificates can
only run under [App Sandbox][app-sandboxing], so they must use the MAS build of
Electron. However, the "Developer ID Application" certificate does not have this
restrictions, so apps signed with it can use either the normal build or the MAS
restriction, so apps signed with it can use either the normal build or the MAS
build of Electron.
#### Legacy certificate names
@@ -208,7 +208,7 @@ signAsync({
After signing the app with the "Apple Distribution" certificate, you can
continue to submit it to Mac App Store.
However, this guide do not ensure your app will be approved by Apple; you
However, this guide does not ensure your app will be approved by Apple; you
still need to read Apple's [Submitting Your App][submitting-your-app] guide on
how to meet the Mac App Store requirements.

View File

@@ -25,7 +25,7 @@ Electron application, and this property only exists on macOS.
One of the main uses for your app's Dock icon is to expose additional app menus. The Dock menu is
triggered by right-clicking or <kbd>Ctrl</kbd>-clicking the app icon. By default, the app's Dock menu
will come with system-provided window management utilities, including the ability to show all windows,
hide the app, and switch betweeen different open windows.
hide the app, and switch between different open windows.
To set an app-defined custom Dock menu, pass any [Menu](../api/menu.md) instance into the
[`dock.setMenu`](../api/dock.md#docksetmenumenu-macos) API.

View File

@@ -1339,7 +1339,7 @@ For developers wanting to learn more, you can refer to the [official N-API docum
### Putting `cpp_addon.cc` together
We've now finished the bridge part our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
We've now finished the bridge part of our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
```cpp title='src/cpp_addon.cc'
#include <napi.h>

View File

@@ -4,13 +4,13 @@ This tutorial builds on the [general introduction to Native Code and Electron](.
Specifically, we'll be integrating with two commonly used native Windows libraries:
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are advanced and alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are more advanced alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
* `shcore.lib`, a library that provides high-DPI awareness functionality and other Shell-related features around managing displays and UI elements.
This tutorial will be most useful to those who already have some familiarity with native C++ GUI development on Windows. You should have experience with basic window classes and procedures, like `WNDCLASSEXW` and `WindowProc` functions. You should also be familiar with the Windows message loop, which is the heart of any native application - our code will be using `GetMessage`, `TranslateMessage`, and `DispatchMessage` to handle messages. Lastly, we'll be using (but not explaining) standard Win32 controls like `WC_EDITW` or `WC_BUTTONW`.
> [!NOTE]
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particular for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particularly for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
## Requirements
@@ -1333,7 +1333,7 @@ npm run build
## Conclusion
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of things we've done here are:
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of the things we've done here are:
1. Creating a native Windows GUI from C++
2. Implementing a Todo list application with Add, Edit, and Delete functionality

View File

@@ -1167,7 +1167,7 @@ The approach demonstrated here allows you to:
* Setting up bidirectional communication using callbacks and events
* Configuring a custom build process to compile Swift code
For more information on developing with Swift and Swift, refer to Apple's developer documentation:
For more information on developing with Swift and SwiftUI, refer to Apple's developer documentation:
* [Swift Programming Language](https://developer.apple.com/swift/)
* [SwiftUI Framework](https://developer.apple.com/documentation/swiftui)

View File

@@ -36,7 +36,7 @@ setting.
This is an advanced feature requiring a native node module to work with your own code.
The frames are directly copied in GPU textures, thus this mode is very fast because
there's no CPU-GPU memory copies overhead, and you can directly import the shared
texture to your own rendering program. You can read more details at
texture to your own rendering program. You can read more details
[here](https://github.com/electron/electron/blob/main/shell/browser/osr/README.md).
2. Use CPU shared memory bitmap

View File

@@ -294,7 +294,7 @@ particularly useful if users complain about your app sometimes "stuttering".
Generally speaking, all advice for building performant web apps for modern
browsers apply to Electron's renderers, too. The two primary tools at your
disposal are currently `requestIdleCallback()` for small operations and
disposal are currently `requestIdleCallback()` for small operations and
`Web Workers` for long-running operations.
_`requestIdleCallback()`_ allows developers to queue up a function to be
@@ -360,7 +360,7 @@ turning into a desktop application. As web developers, we are used to loading
resources from a variety of content delivery networks. Now that you are
shipping a proper desktop application, attempt to "cut the cord" where possible
and avoid letting your users wait for resources that never change and could
easily be included in your app.
easily be included in your app.
A typical example is Google Fonts. Many developers make use of Google's
impressive collection of free fonts, which comes with a content delivery

View File

@@ -113,7 +113,7 @@ For a full list of Electron's main process modules, check out our API documentat
Each Electron app spawns a separate renderer process for each open `BrowserWindow`
(and each web embed). As its name implies, a renderer is responsible for
_rendering_ web content. For all intents and purposes, code ran in renderer processes
_rendering_ web content. For all intents and purposes, code run in renderer processes
should behave according to web standards (insofar as Chromium does, at least).
Therefore, all user interfaces and app functionality within a single browser

View File

@@ -771,7 +771,7 @@ ipcMain.handle('get-secrets', (e) => {
})
function validateSender (frame) {
// Value the host of the URL using an actual URL parser and an allowlist
// Validate the host of the URL using an actual URL parser and an allowlist
if ((new URL(frame.url)).host === 'electronjs.org') return true
return false
}

View File

@@ -2,8 +2,8 @@
Being based on Chromium, Electron requires a display driver to function.
If Chromium can't find a display driver, Electron will fail to launch -
and therefore not executing any of your tests, regardless of how you are running
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar Systems
and therefore not execute any of your tests, regardless of how you are running
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar systems
requires therefore a little bit of configuration. In essence, we need to use
a virtual display driver.

View File

@@ -44,7 +44,7 @@ following JSON format:
"updateTo": {
"version": "1.2.1",
"pub_date": "2023-09-18T12:29:53+01:00",
"notes": "Theses are some release notes innit",
"notes": "These are some release notes innit",
"name": "1.2.1",
"url": "https://mycompany.example.com/myapp/releases/myrelease"
}
@@ -54,7 +54,7 @@ following JSON format:
"updateTo": {
"version": "1.2.3",
"pub_date": "2024-09-18T12:29:53+01:00",
"notes": "Theses are some more release notes innit",
"notes": "These are some more release notes innit",
"name": "1.2.3",
"url": "https://mycompany.example.com/myapp/releases/myrelease3"
}
@@ -307,7 +307,7 @@ app update. All other properties in the object are optional.
{
"url": "https://your-static.storage/your-app-1.2.3-darwin.zip",
"name": "1.2.3",
"notes": "Theses are some release notes innit",
"notes": "These are some release notes innit",
"pub_date": "2024-09-18T12:29:53+01:00"
}
```

View File

@@ -149,7 +149,7 @@ for an example delay-load hook if you're implementing your own.
native Node modules with prebuilt binaries for multiple versions of Node
and Electron.
If the `prebuild`-powered module provide binaries for the usage in Electron,
If the `prebuild`-powered module provides binaries for the usage in Electron,
make sure to omit `--build-from-source` and the `npm_config_build_from_source`
environment variable in order to take full advantage of the prebuilt binaries.

View File

@@ -38,7 +38,7 @@ To test your app, use a Windows on Arm device running Windows 10 (version 1903 o
### Node.js/node-gyp
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
### Visual Studio 2017

View File

@@ -134,7 +134,7 @@ system.
Before running the CLI for the first time, you will have to setup the "Windows Desktop App
Converter". This will take a few minutes, but don't worry - you only have to do
this once. Download and Desktop App Converter from [here][app-converter].
this once. Download the Desktop App Converter from [here][app-converter].
You will receive two files: `DesktopAppConverter.zip` and `BaseImage-14316.wim`.
1. Unzip `DesktopAppConverter.zip`. From an elevated PowerShell (opened with

View File

@@ -56,7 +56,7 @@
"ts-node": "6.2.0",
"typescript": "^5.8.3",
"url": "^0.11.4",
"webpack": "^5.95.0",
"webpack": "^5.104.1",
"webpack-cli": "^6.0.1",
"wrapper-webpack-plugin": "^2.2.0",
"yaml": "^2.8.1"
@@ -65,7 +65,7 @@
"scripts": {
"asar": "asar",
"generate-version-json": "node script/generate-version-json.js",
"lint": "node ./script/lint.js && npm run lint:docs",
"lint": "node ./script/lint.js && npm run lint:docs && npm run lint:chromium-roller",
"lint:js": "node ./script/lint.js --js",
"lint:clang-format": "python3 script/run-clang-format.py -r -c shell/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
"lint:clang-tidy": "ts-node ./script/run-clang-tidy.ts",
@@ -80,6 +80,7 @@
"lint:ts-check-js-in-markdown": "lint-roller-markdown-ts-check --root docs \"**/*.md\" --ignore \"breaking-changes.md\"",
"lint:js-in-markdown": "lint-roller-markdown-standard --root docs \"**/*.md\"",
"lint:api-history": "lint-roller-markdown-api-history --root \"./docs/api/\" --schema \"./docs/api-history.schema.json\" --breaking-changes-file \"./docs/breaking-changes.md\" --check-placement --check-strings \"*.md\"",
"lint:chromium-roller": "node ./script/lint-roller-chromium-changes.mjs",
"create-api-json": "node script/create-api-json.mjs",
"create-typescript-definitions": "npm run create-api-json && electron-typescript-definitions --api=electron-api.json && node spec/ts-smoke/runner.js",
"gn-typescript-definitions": "npm run create-typescript-definitions && node script/cp.mjs electron.d.ts",
@@ -103,6 +104,9 @@
"electron"
],
"lint-staged": {
"*": [
"npm run lint:chromium-roller"
],
"*.{js,ts}": [
"node script/lint.js --js --fix --only --"
],

View File

@@ -23,10 +23,10 @@ additional headless changes from breaking macOS window behavior.
https://chromium-review.googlesource.com/c/chromium/src/+/7487666
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index 2a195724de141fd4f0f06c03314e6096a0d0ed3f..2532ae21d9244b2ec9747ef7d9916668dcad145c 100644
index 94bd32ce1ddd3f8b4315cd06be59d7550b591891..ad005e0a19a7763da089fccc659d93c8815dc860 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -218,6 +218,7 @@ @implementation NativeWidgetMacNSWindow {
@@ -231,6 +231,7 @@ @implementation NativeWidgetMacNSWindow {
BOOL _isEnforcingNeverMadeVisible;
BOOL _activationIndependence;
BOOL _isTooltip;
@@ -34,7 +34,7 @@ index 2a195724de141fd4f0f06c03314e6096a0d0ed3f..2532ae21d9244b2ec9747ef7d9916668
BOOL _isShufflingForOrdering;
BOOL _miniaturizationInProgress;
std::unique_ptr<NativeWidgetMacNSWindowHeadlessInfo> _headless_info;
@@ -225,6 +226,7 @@ @implementation NativeWidgetMacNSWindow {
@@ -238,6 +239,7 @@ @implementation NativeWidgetMacNSWindow {
@synthesize bridgedNativeWidgetId = _bridgedNativeWidgetId;
@synthesize bridge = _bridge;
@synthesize isTooltip = _isTooltip;
@@ -42,7 +42,7 @@ index 2a195724de141fd4f0f06c03314e6096a0d0ed3f..2532ae21d9244b2ec9747ef7d9916668
@synthesize isShufflingForOrdering = _isShufflingForOrdering;
@synthesize preventKeyWindow = _preventKeyWindow;
@synthesize childWindowAddedHandler = _childWindowAddedHandler;
@@ -246,23 +248,6 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
@@ -259,23 +261,6 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
return self;
}

View File

@@ -640,7 +640,7 @@ index 48f47bf3eeb8464d1c3925f0f73f62c790cac2f0..b7b2b7c1b7e99927012ce1676cc753b2
// The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
// can only be accomplished by overriding methods.
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096a0d0ed3f 100644
index a5fc9193711a7cc2eee45171178c070321177ca2..94bd32ce1ddd3f8b4315cd06be59d7550b591891 100644
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
@@ -22,6 +22,7 @@
@@ -677,7 +677,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
@end
struct NSEdgeAndCornerThicknesses {
@@ -159,13 +164,17 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
@@ -159,13 +164,30 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
@implementation NSView (CRFrameViewAdditions)
// If a mouseDown: falls through to the frame view, turn it into a window drag.
- (void)cr_mouseDownOnFrameView:(NSEvent*)event {
@@ -685,6 +685,19 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
if ([self.window _resizeDirectionForMouseLocation:event.locationInWindow] !=
-1)
return;
+#else
+ // For MAS builds, approximate the resize direction check.
+ if (self.window.styleMask & NSWindowStyleMaskResizable) {
+ constexpr CGFloat kResizeThreshold = 5.0;
+ NSPoint location = event.locationInWindow;
+ NSRect frame = self.window.frame;
+ CGFloat width = NSWidth(frame);
+ CGFloat height = NSHeight(frame);
+ if (location.x < kResizeThreshold || location.x > width - kResizeThreshold ||
+ location.y < kResizeThreshold || location.y > height - kResizeThreshold) {
+ return;
+ }
+ }
+#endif
[self.window performWindowDragWithEvent:event];
}
@@ -695,7 +708,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
@implementation NativeWidgetMacNSWindowTitledFrame
- (void)mouseDown:(NSEvent*)event {
if (self.window.isMovable)
@@ -193,6 +202,8 @@ - (BOOL)usesCustomDrawing {
@@ -193,6 +215,8 @@ - (BOOL)usesCustomDrawing {
}
@end
@@ -704,7 +717,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
@implementation NativeWidgetMacNSWindow {
@private
CommandDispatcher* __strong _commandDispatcher;
@@ -268,6 +279,7 @@ - (BOOL)invokeOriginalIsVisibleForTesting {
@@ -268,6 +292,7 @@ - (BOOL)invokeOriginalIsVisibleForTesting {
// bubbles and the find bar, but these should not be movable.
// Instead, let's push this up to the parent window which should be
// the browser.
@@ -712,7 +725,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
- (void)_zoomToScreenEdge:(NSUInteger)edge {
if (self.parentWindow) {
[self.parentWindow _zoomToScreenEdge:edge];
@@ -275,6 +287,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
@@ -275,6 +300,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
[super _zoomToScreenEdge:edge];
}
}
@@ -720,7 +733,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
// This override helps diagnose lifetime issues in crash stacktraces by
// inserting a symbol on NativeWidgetMacNSWindow and should be kept even if it
@@ -407,6 +420,8 @@ - (NSAccessibilityRole)accessibilityRole {
@@ -407,6 +433,8 @@ - (NSAccessibilityRole)accessibilityRole {
// NSWindow overrides.
@@ -729,7 +742,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
if (windowStyle & NSWindowStyleMaskTitled) {
if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
@@ -418,6 +433,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
@@ -418,6 +446,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
return [super frameViewClassForStyleMask:windowStyle];
}
@@ -738,7 +751,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
- (NSRect)constrainFrameRect:(NSRect)frameRect toScreen:(NSScreen*)screen {
if (self.isHeadless || self.parentWindow) {
// AppKit's default implementation moves child windows down to avoid
@@ -455,12 +472,14 @@ - (BOOL)_usesCustomDrawing {
@@ -455,12 +485,14 @@ - (BOOL)_usesCustomDrawing {
// if it were valid to set that style for windows, setting the window style
// recalculates and re-caches a bunch of stuff, so a surgical override is the
// cleanest approach.
@@ -753,7 +766,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
+ (void)_getExteriorResizeEdgeThicknesses:
(NSEdgeAndCornerThicknesses*)outThicknesses
@@ -714,9 +733,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
@@ -714,9 +746,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
}
- (void)saveRestorableState {
@@ -765,7 +778,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
// Certain conditions, such as in the Speedometer 3 benchmark, can trigger a
// rapid succession of calls to saveRestorableState. If there's no pending
@@ -783,6 +804,7 @@ - (void)reallySaveRestorableState {
@@ -783,6 +817,7 @@ - (void)reallySaveRestorableState {
// affects its restorable state changes.
- (void)invalidateRestorableState {
[super invalidateRestorableState];
@@ -773,7 +786,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
if ([self _isConsideredOpenForPersistentState]) {
if (_willUpdateRestorableState)
return;
@@ -795,6 +817,7 @@ - (void)invalidateRestorableState {
@@ -795,6 +830,7 @@ - (void)invalidateRestorableState {
_willUpdateRestorableState = NO;
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
@@ -781,7 +794,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
}
// On newer SDKs, _canMiniaturize respects NSWindowStyleMaskMiniaturizable in
@@ -971,6 +994,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
@@ -971,6 +1007,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
// Since _removeFromGroups: is not documented it could go away in newer
// versions of macOS. If the selector does not exist, DumpWithoutCrashing() so
// we hear about the change.
@@ -789,7 +802,7 @@ index a5fc9193711a7cc2eee45171178c070321177ca2..2a195724de141fd4f0f06c03314e6096
if (![NSWindow instancesRespondToSelector:@selector(_removeFromGroups:)]) {
base::debug::DumpWithoutCrashing();
return;
@@ -988,6 +1012,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
@@ -988,6 +1025,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
[currentWindow _removeFromGroups:child];
}
}

View File

@@ -142,8 +142,29 @@ async function findMatchingFiles (top, test) {
});
}
function compareVersions (v1, v2) {
const [split1, split2] = [v1.split('.'), v2.split('.')];
if (split1.length !== split2.length) {
throw new Error(
`Expected version strings to have same number of sections: ${split1} and ${split2}`
);
}
for (let i = 0; i < split1.length; i++) {
const p1 = parseInt(split1[i], 10);
const p2 = parseInt(split2[i], 10);
if (p1 > p2) return 1;
else if (p1 < p2) return -1;
// Continue checking the value if this portion is equal
}
return 0;
}
module.exports = {
chunkFilenames,
compareVersions,
findMatchingFiles,
getCurrentBranch,
getElectronExec,

View File

@@ -0,0 +1,287 @@
#!/usr/bin/env node
import { execSync } from 'node:child_process';
import * as fs from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { compareVersions } from './lib/utils.js';
const __dirname = dirname(fileURLToPath(import.meta.url));
const ELECTRON_DIR = resolve(__dirname, '..');
const DEPS_REGEX = /chromium_version':\n +'(.+?)',/m;
const CL_REGEX = /https:\/\/chromium-review\.googlesource\.com\/c\/(?:chromium\/src|v8\/v8)\/\+\/(\d+)(#\S+)?/g;
const ROLLER_BRANCH_PATTERN = /^roller\/chromium\/(.+)$/;
function getCommitsSinceMergeBase (mergeBase) {
try {
const output = execSync(`git log --format=%H%n%B%n---COMMIT_END--- ${mergeBase}..HEAD`, {
cwd: ELECTRON_DIR,
encoding: 'utf8'
});
const commits = [];
const parts = output.split('---COMMIT_END---');
for (const part of parts) {
const trimmed = part.trim();
if (!trimmed) continue;
const lines = trimmed.split('\n');
const sha = lines[0];
const message = lines.slice(1).join('\n');
if (sha && message) {
commits.push({ sha, message });
}
}
return commits;
} catch {
return [];
}
}
async function fetchChromiumDashCommit (commitSha, repo) {
const url = `https://chromiumdash.appspot.com/fetch_commit?commit=${commitSha}&repo=${repo}`;
const response = await fetch(url);
if (!response.ok) {
return null;
}
try {
return await response.json();
} catch {
return null;
}
}
async function getGerritPatchDetails (clUrl) {
const parsedUrl = new URL(clUrl);
const match = /^\/c\/(.+?)\/\+\/(\d+)/.exec(parsedUrl.pathname);
if (!match) {
return null;
}
const [, repo, number] = match;
const changeId = `${repo}~${number}`;
const url = `https://chromium-review.googlesource.com/changes/${encodeURIComponent(changeId)}?o=CURRENT_REVISION`;
const response = await fetch(url);
if (!response.ok) {
return null;
}
try {
// Gerrit returns JSON with a magic prefix
const text = await response.text();
const jsonText = text.startsWith(")]}'") ? text.substring(4) : text;
const data = JSON.parse(jsonText);
// Get the current revision's commit SHA
const currentRevision = data.current_revision;
return {
commitSha: currentRevision,
project: data.project
};
} catch {
return null;
}
}
async function main () {
let currentBranch;
try {
currentBranch = execSync('git rev-parse --abbrev-ref HEAD', {
cwd: ELECTRON_DIR,
encoding: 'utf8'
}).trim();
} catch {
console.error('Could not determine current git branch');
process.exit(1);
}
// Check if we're on a roller/chromium/* branch
const branchMatch = ROLLER_BRANCH_PATTERN.exec(currentBranch);
if (!branchMatch) {
console.log(`Not on a roller/chromium/* branch (current: ${currentBranch}), skipping lint.`);
process.exit(0);
}
const targetBranch = branchMatch[1];
console.log(`Linting roller branch: ${currentBranch} (target: ${targetBranch})`);
// Get the merge base with the target branch
let mergeBase;
try {
mergeBase = execSync(`git merge-base ${currentBranch} origin/${targetBranch}`, {
cwd: ELECTRON_DIR,
encoding: 'utf8'
}).trim();
} catch {
console.error(`Could not determine merge base with origin/${targetBranch}`);
process.exit(1);
}
// Get version range
let baseVersion = null;
try {
const baseDepsContent = execSync(`git show ${mergeBase}:DEPS`, {
cwd: ELECTRON_DIR,
encoding: 'utf8'
});
baseVersion = DEPS_REGEX.exec(baseDepsContent)?.[1] ?? null;
} catch {
// baseVersion remains null
}
const depsContent = await fs.readFile(resolve(ELECTRON_DIR, 'DEPS'), 'utf8');
const newVersion = DEPS_REGEX.exec(depsContent)?.[1] ?? null;
if (!baseVersion || !newVersion) {
console.error('Could not determine Chromium version range');
console.error(` Base version: ${baseVersion ?? 'unknown'}`);
console.error(` New version: ${newVersion ?? 'unknown'}`);
process.exit(1);
}
console.log(`Chromium version range: ${baseVersion} -> ${newVersion}`);
// Get all commits since merge base
const commits = getCommitsSinceMergeBase(mergeBase);
console.log(`Found ${commits.length} commits to check`);
let hasErrors = false;
const checkedCLs = new Map(); // Cache CL check results
for (const commit of commits) {
const shortSha = commit.sha.substring(0, 7);
const firstLine = commit.message.split('\n')[0];
// Check for Skip-Lint trailer
const skipLintMatch = /^Skip-Lint:\s*(.+)$/m.exec(commit.message);
if (skipLintMatch) {
console.log(`\nSkipping commit ${shortSha}: ${firstLine}`);
console.log(` ⏭️ Reason: ${skipLintMatch[1]}`);
continue;
}
const cls = [...commit.message.matchAll(CL_REGEX)].map((match) => ({
url: match[0],
clNumber: match[1],
fragment: match[2] ?? null
}));
if (cls.length === 0) {
// No CLs in this commit, skip
continue;
}
console.log(`\nChecking commit ${shortSha}: ${firstLine}`);
for (const cl of cls) {
// Skip CLs annotated with #nolint
if (cl.fragment === '#nolint') {
console.log(` ⏭️ CL ${cl.clNumber}: skipped (#nolint)`);
continue;
}
// Check cache first (use URL as key to distinguish same CL number across repos)
if (checkedCLs.has(cl.url)) {
const cached = checkedCLs.get(cl.url);
if (cached.valid) {
console.log(` ✅ CL ${cl.clNumber}: (already validated)`);
} else {
console.error(` ❌ CL ${cl.clNumber}: ${cached.error}`);
hasErrors = true;
}
continue;
}
// Determine repo from URL
const isV8 = cl.url.startsWith('https://chromium-review.googlesource.com/c/v8/v8/');
const repo = isV8 ? 'v8' : 'chromium';
// Fetch Gerrit details to get commit SHA
const gerritDetails = await getGerritPatchDetails(cl.url);
if (!gerritDetails) {
const error = 'Could not fetch CL details from Gerrit';
checkedCLs.set(cl.url, { valid: false, error });
console.error(` ❌ CL ${cl.clNumber}: ${error}`);
hasErrors = true;
continue;
}
// Fetch from Chromium Dash to get the earliest version
const dashDetails = await fetchChromiumDashCommit(gerritDetails.commitSha, repo);
if (!dashDetails) {
const error = 'Could not fetch commit details from Chromium Dash';
checkedCLs.set(cl.url, { valid: false, error });
console.error(` ❌ CL ${cl.clNumber}: ${error}`);
hasErrors = true;
continue;
}
const clEarliestVersion = dashDetails.earliest;
if (!clEarliestVersion) {
const error = 'CL has no earliest version (may not be merged yet)';
checkedCLs.set(cl.url, { valid: false, error });
console.error(` ❌ CL ${cl.clNumber}: ${error}`);
hasErrors = true;
continue;
}
// For V8 CLs, we need to find the corresponding Chromium commit
let chromiumVersion = clEarliestVersion;
if (isV8 && dashDetails.relations) {
const chromiumRelation = dashDetails.relations.find(
(rel) => rel.from_commit === gerritDetails.commitSha
);
if (chromiumRelation) {
const chromiumDash = await fetchChromiumDashCommit(chromiumRelation.to_commit, 'chromium');
if (chromiumDash?.earliest) {
chromiumVersion = chromiumDash.earliest;
}
}
}
// CL should have landed after the base version and at or before the new version
const isInRange =
compareVersions(chromiumVersion, baseVersion) > 0 &&
compareVersions(chromiumVersion, newVersion) <= 0;
if (!isInRange) {
const error = `CL earliest version ${chromiumVersion} is outside roller range (${baseVersion} -> ${newVersion})`;
checkedCLs.set(cl.url, { valid: false, error });
console.error(` ❌ CL ${cl.clNumber}: ${error}`);
hasErrors = true;
continue;
}
checkedCLs.set(cl.url, { valid: true });
console.log(` ✅ CL ${cl.clNumber}: version ${chromiumVersion} is within range`);
}
}
console.log(hasErrors ? '\n❌ Lint failed' : '\n✅ Lint passed');
if (hasErrors) {
console.log(' NOTE: Add "Skip-Lint: <reason>" to a commit message to skip linting that commit.');
}
process.exit(hasErrors && process.env.CI ? 1 : 0);
}
if ((await fs.realpath(process.argv[1])) === fileURLToPath(import.meta.url)) {
main()
.then(() => {
process.exit(0);
})
.catch((err) => {
console.error(`ERROR: ${err.message}`);
process.exit(1);
});
}

View File

@@ -6,7 +6,7 @@ import { spawnSync } from 'node:child_process';
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
import { resolve as _resolve } from 'node:path';
import { ELECTRON_DIR } from '../../lib/utils';
import { compareVersions, ELECTRON_DIR } from '../../lib/utils';
import { createGitHubTokenStrategy } from '../github-token';
import { ELECTRON_ORG, ELECTRON_REPO } from '../types';
@@ -612,26 +612,6 @@ const getNotes = async (fromRef: string, toRef: string, newVersion: string) => {
return notes;
};
const compareVersions = (v1: string, v2: string) => {
const [split1, split2] = [v1.split('.'), v2.split('.')];
if (split1.length !== split2.length) {
throw new Error(
`Expected version strings to have same number of sections: ${split1} and ${split2}`
);
}
for (let i = 0; i < split1.length; i++) {
const p1 = parseInt(split1[i], 10);
const p2 = parseInt(split2[i], 10);
if (p1 > p2) return 1;
else if (p1 < p2) return -1;
// Continue checking the value if this portion is equal
}
return 0;
};
const removeSupercededStackUpdates = (commits: Commit[]) => {
const updateRegex = /^Updated ([a-zA-Z.]+) to v?([\d.]+)/;
const notupdates = [];

View File

@@ -1,14 +1,14 @@
{
"bullseye_amd64": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "986ffe8f444b650c38de1786a930516bf9447ec7003a6c367de4aade8ebdb186",
"Sha256Sum": "f2e052b0cdab9b6f9bfe311c5269264d5f4e38a018bbc27ba2314b73ac8f7053",
"SysrootDir": "debian_bullseye_amd64-sysroot",
"Tarball": "debian_bullseye_amd64_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
},
"bullseye_arm64": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "6be0900393d73e69518f0996807dbc542c0d47cab1c4903c9d188347f945114a",
"Sha256Sum": "f4f680a60e314418f95513ac63e9942ad565005ebbd36b660b20cd605d11a664",
"SysrootDir": "debian_bullseye_arm64-sysroot",
"Tarball": "debian_bullseye_arm64_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
@@ -22,44 +22,44 @@
},
"bullseye_armhf": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "060631cd0583b5204c646d41a5fbbe6080fd7a822feefba01900bd8e41a67b13",
"Sha256Sum": "f99ef848d2f6046437d3277da4442f82dafba040cafdf7f461c9726298e45653",
"SysrootDir": "debian_bullseye_armhf-sysroot",
"Tarball": "debian_bullseye_armhf_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
},
"bullseye_i386": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "a6b63543ac2a57f477a6ea54b1e36dc8bfeb2f19c963866f79b1b2a93ed43a6e",
"Sha256Sum": "4c35cf12fc7f53def4f0b105ba7a09e4a5ef5671aa5a898ab19be09e1e8d16b9",
"SysrootDir": "debian_bullseye_i386-sysroot",
"Tarball": "debian_bullseye_i386_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
},
"bullseye_mips64el": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "814ccd5d9524020b23a16a5a581644ca8ba2f1e3515a1ddcbb62e938d4f4e0b0",
"Sha256Sum": "a84374ea0966f1026088fdbe34521ff56760878aa93f9af21160caf4155659fc",
"SysrootDir": "debian_bullseye_mips64el-sysroot",
"Tarball": "debian_bullseye_mips64el_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
},
"bullseye_mipsel": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "7f3218966b7bc636409a0f3d5104d9046b03faf660847f9026df9ce2c9775d53",
"Sha256Sum": "f7f06a49f92ee8c9a1d16c424b668c6dfed33006f2ef015124c660143bb89ee8",
"SysrootDir": "debian_bullseye_mipsel-sysroot",
"Tarball": "debian_bullseye_mipsel_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
},
"bullseye_ppc64el": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "bdab0a372cf5bfdc154226cc5ed72d417096c725085d193509d1f12e0debec66",
"Sha256Sum": "9e3c152f17c292c3e9be31b3fe63666eebac3e13d2e0d83f8de0acaa77417ac2",
"SysrootDir": "debian_bullseye_ppc64el-sysroot",
"Tarball": "debian_bullseye_ppc64el_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
},
"trixie_riscv64": {
"Key": "20250129T203412Z-2",
"Sha256Sum": "2183652af753225da2371d7bccddcb0269ee388e4508ed1fdeb810cb05cba898",
"Sha256Sum": "d997eaa308ce148c4a429549ca360bf3f58b5861fe7f5f1d826ccf0a8eccbe48",
"SysrootDir": "debian_trixie_riscv64-sysroot",
"Tarball": "debian_trixie_riscv64_sysroot.tar.xz",
"URL": "https://dev-cdn.electronjs.org/linux-sysroots"
}
}
}

View File

@@ -83,8 +83,16 @@ void WebContentsView::ApplyBorderRadius() {
int WebContentsView::NonClientHitTest(const gfx::Point& point) {
if (api_web_contents_) {
// Convert the point to the contents view's coordinate space rather than
// the InspectableWebContentsView's coordinate space, because the draggable
// region is relative to the web content area. When DevTools is docked
// (e.g. to the left), the contents view is offset within the parent,
// so we need to account for that offset.
auto* inspectable_view =
api_web_contents_->inspectable_web_contents()->GetView();
auto* contents_view = inspectable_view->GetContentsView();
gfx::Point local_point(point);
views::View::ConvertPointFromWidget(view(), &local_point);
views::View::ConvertPointFromWidget(contents_view, &local_point);
SkRegion* region = api_web_contents_->draggable_region();
if (region && region->contains(local_point.x(), local_point.y()))
return HTCAPTION;

View File

@@ -41,6 +41,7 @@
#include "content/public/common/process_type.h"
#include "content/public/common/result_codes.h"
#include "electron/buildflags/buildflags.h"
#include "electron/fuses.h"
#include "media/base/localized_strings.h"
#include "services/network/public/cpp/features.h"
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
@@ -62,6 +63,7 @@
#include "shell/common/logging.h"
#include "shell/common/node_bindings.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "ui/base/idle/idle.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/ui_base_switches.h"
@@ -238,6 +240,15 @@ void ElectronBrowserMainParts::PostEarlyInitialization() {
v8::Isolate* const isolate = js_env_->isolate();
v8::HandleScope scope(isolate);
// Enable trap handlers before user script execution.
#if ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) && \
defined(ARCH_CPU_X86_64)) || \
((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)) && defined(ARCH_CPU_ARM64))
if (electron::fuses::IsWasmTrapHandlersEnabled()) {
electron::SetUpWebAssemblyTrapHandler();
}
#endif
node_bindings_->Initialize(isolate, isolate->GetCurrentContext());
// Create the global environment.
node_env_ = node_bindings_->CreateEnvironment(

View File

@@ -29,6 +29,7 @@
#include "shell/browser/api/electron_api_system_preferences.h"
#include "shell/browser/api/electron_api_web_contents.h"
#include "shell/browser/ui/inspectable_web_contents_view.h"
#include "shell/browser/ui/views/frameless_view.h"
#include "shell/browser/ui/views/root_view.h"
#include "shell/browser/web_contents_preferences.h"
#include "shell/browser/web_view_manager.h"
@@ -41,14 +42,19 @@
#include "ui/base/hit_test.h"
#include "ui/compositor/compositor.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/outsets.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/native_ui_types.h"
#include "ui/ozone/public/ozone_platform.h"
#include "ui/views/background.h"
#include "ui/views/controls/webview/webview.h"
#include "ui/views/view_utils.h"
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/client_view.h"
#include "ui/views/window/frame_view.h"
#include "ui/views/window/non_client_view.h"
#include "ui/wm/core/shadow_types.h"
#include "ui/wm/core/window_util.h"
@@ -432,9 +438,12 @@ NativeWindowViews::NativeWindowViews(const int32_t base_window_id,
window->AddPreTargetHandler(this);
#if BUILDFLAG(IS_LINUX)
// On linux after the widget is initialized we might have to force set the
// bounds if the bounds are smaller than the current display
SetBounds(gfx::Rect(GetPosition(), bounds.size()), false);
// We need to set bounds again after widget init for two reasons:
// 1. For CSD windows, user-specified bounds need to be inflated by frame
// insets, but the frame view isn't available at first.
// 2. The widget clamps bounds to fit the screen, but we want to allow
// windows larger than the display.
SetBounds(gfx::Rect(GetPosition(), size), false);
#endif
}
@@ -875,16 +884,14 @@ void NativeWindowViews::SetBounds(const gfx::Rect& bounds, bool animate) {
}
#endif
widget()->SetBounds(bounds);
widget()->SetBounds(LogicalToWidgetBounds(bounds));
}
gfx::Rect NativeWindowViews::GetBounds() const {
#if BUILDFLAG(IS_WIN)
if (IsMinimized())
return widget()->GetRestoredBounds();
#endif
return WidgetToLogicalBounds(widget()->GetRestoredBounds());
return widget()->GetWindowBoundsInScreen();
return WidgetToLogicalBounds(widget()->GetWindowBoundsInScreen());
}
gfx::Rect NativeWindowViews::GetContentBounds() const {
@@ -905,7 +912,7 @@ gfx::Rect NativeWindowViews::GetNormalBounds() const {
if (IsMaximized() && transparent())
return restore_bounds_;
#endif
return widget()->GetRestoredBounds();
return WidgetToLogicalBounds(widget()->GetRestoredBounds());
}
void NativeWindowViews::SetContentSizeConstraints(
@@ -1481,6 +1488,22 @@ gfx::NativeWindow NativeWindowViews::GetNativeWindow() const {
return widget()->GetNativeWindow();
}
gfx::Insets NativeWindowViews::GetRestoredFrameBorderInsets() const {
auto* non_client_view = widget()->non_client_view();
if (!non_client_view)
return gfx::Insets();
auto* frame_view = non_client_view->frame_view();
if (!frame_view)
return gfx::Insets();
if (auto* frameless = views::AsViewClass<FramelessView>(frame_view)) {
return frameless->RestoredFrameBorderInsets();
}
return gfx::Insets();
}
void NativeWindowViews::SetProgressBar(double progress,
NativeWindow::ProgressState state) {
#if BUILDFLAG(IS_WIN)
@@ -1646,21 +1669,42 @@ NativeWindowHandle NativeWindowViews::GetNativeWindowHandle() const {
return GetAcceleratedWidget();
}
gfx::Rect NativeWindowViews::LogicalToWidgetBounds(
const gfx::Rect& bounds) const {
gfx::Rect widget_bounds(bounds);
const gfx::Insets frame_insets = GetRestoredFrameBorderInsets();
widget_bounds.Outset(
gfx::Outsets::TLBR(frame_insets.top(), frame_insets.left(),
frame_insets.bottom(), frame_insets.right()));
return widget_bounds;
}
gfx::Rect NativeWindowViews::WidgetToLogicalBounds(
const gfx::Rect& bounds) const {
gfx::Rect logical_bounds(bounds);
logical_bounds.Inset(GetRestoredFrameBorderInsets());
return logical_bounds;
}
gfx::Rect NativeWindowViews::ContentBoundsToWindowBounds(
const gfx::Rect& bounds) const {
if (!has_frame())
return bounds;
gfx::Rect window_bounds(bounds);
if (auto* ncv = widget()->non_client_view()) {
#if BUILDFLAG(IS_WIN)
if (widget()->non_client_view()) {
HWND hwnd = GetAcceleratedWidget();
gfx::Rect dpi_bounds = DIPToScreenRect(hwnd, bounds);
window_bounds = ScreenToDIPRect(
hwnd, widget()->non_client_view()->GetWindowBoundsForClientBounds(
dpi_bounds));
}
window_bounds =
ScreenToDIPRect(hwnd, ncv->GetWindowBoundsForClientBounds(dpi_bounds));
#else
window_bounds = WidgetToLogicalBounds(
ncv->GetWindowBoundsForClientBounds(window_bounds));
#endif
}
if (root_view_.HasMenu() && root_view_.is_menu_bar_visible()) {
int menu_bar_height = root_view_.GetMenuBarHeight();
@@ -1687,6 +1731,10 @@ gfx::Rect NativeWindowViews::WindowBoundsToContentBounds(
content_bounds.set_width(content_bounds.width() - (rect.right - rect.left));
content_bounds.set_height(content_bounds.height() - (rect.bottom - rect.top));
content_bounds.set_size(ScreenToDIPRect(hwnd, content_bounds).size());
#else
if (auto* frame_view = widget()->non_client_view()->frame_view()) {
content_bounds = frame_view->GetBoundsForClientView();
}
#endif
if (root_view_.HasMenu() && root_view_.is_menu_bar_visible()) {

View File

@@ -16,6 +16,7 @@
#include "shell/browser/ui/views/root_view.h"
#include "third_party/abseil-cpp/absl/container/flat_hash_set.h"
#include "ui/base/ozone_buildflags.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
#include "ui/views/widget/widget_observer.h"
@@ -156,6 +157,12 @@ class NativeWindowViews : public NativeWindow,
gfx::Rect ContentBoundsToWindowBounds(const gfx::Rect& bounds) const override;
gfx::Rect WindowBoundsToContentBounds(const gfx::Rect& bounds) const override;
// Translates between logical/opaque window bounds exposed to callers
// and the absolute bounds of the underlying widget, which can be larger to
// fit CSD, e.g. transparent outer regions for shadows and resize targets.
gfx::Rect LogicalToWidgetBounds(const gfx::Rect& bounds) const;
gfx::Rect WidgetToLogicalBounds(const gfx::Rect& bounds) const;
void IncrementChildModals();
void DecrementChildModals();
@@ -205,6 +212,8 @@ class NativeWindowViews : public NativeWindow,
overlay_symbol_color_ = color;
}
gfx::Insets GetRestoredFrameBorderInsets() const;
// views::WidgetObserver:
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
void OnWidgetBoundsChanged(views::Widget* widget,

View File

@@ -53,10 +53,11 @@ void ElectronDesktopWindowTreeHostLinux::OnWidgetInitDone() {
UpdateFrameHints();
}
bool ElectronDesktopWindowTreeHostLinux::IsShowingFrame() const {
return !native_window_view_->IsFullscreen() &&
!native_window_view_->IsMaximized() &&
!native_window_view_->IsMinimized();
bool ElectronDesktopWindowTreeHostLinux::IsShowingFrame(
ui::PlatformWindowState window_state) const {
return window_state != ui::PlatformWindowState::kFullScreen &&
window_state != ui::PlatformWindowState::kMaximized &&
window_state != ui::PlatformWindowState::kMinimized;
}
void ElectronDesktopWindowTreeHostLinux::SetWindowIcons(
@@ -80,7 +81,7 @@ void ElectronDesktopWindowTreeHostLinux::Show(
gfx::Insets ElectronDesktopWindowTreeHostLinux::CalculateInsetsInDIP(
ui::PlatformWindowState window_state) const {
// If we are not showing frame, the insets should be zero.
if (!IsShowingFrame()) {
if (!IsShowingFrame(window_state)) {
return gfx::Insets();
}
@@ -88,9 +89,7 @@ gfx::Insets ElectronDesktopWindowTreeHostLinux::CalculateInsetsInDIP(
if (!view)
return {};
gfx::Insets insets = view->RestoredMirroredFrameBorderInsets();
if (base::i18n::IsRTL())
insets.set_left_right(insets.right(), insets.left());
gfx::Insets insets = view->RestoredFrameBorderInsets();
return insets;
}
@@ -207,7 +206,7 @@ void ElectronDesktopWindowTreeHostLinux::UpdateFrameHints() {
if (ui::OzonePlatform::GetInstance()->IsWindowCompositingSupported()) {
// Set the opaque region.
std::vector<gfx::Rect> opaque_region;
if (IsShowingFrame()) {
if (IsShowingFrame(window_state)) {
// The opaque region is a list of rectangles that contain only fully
// opaque pixels of the window. We need to convert the clipping
// rounded-rect into this format.

View File

@@ -74,7 +74,7 @@ class ElectronDesktopWindowTreeHostLinux
private:
void UpdateWindowState(ui::PlatformWindowState new_state);
bool IsShowingFrame() const;
bool IsShowingFrame(ui::PlatformWindowState window_state) const;
gfx::ImageSkia saved_window_icon_;

View File

@@ -62,9 +62,9 @@ class InspectableWebContentsView : public views::View {
// views::View:
void Layout(PassKey) override;
private:
views::View* GetContentsView() const;
private:
// Owns us.
raw_ptr<InspectableWebContents> inspectable_web_contents_;

View File

@@ -142,13 +142,6 @@ void ClientFrameViewLinux::Init(NativeWindowViews* window,
UpdateThemeValues();
}
gfx::Insets ClientFrameViewLinux::RestoredMirroredFrameBorderInsets() const {
auto border = RestoredFrameBorderInsets();
return base::i18n::IsRTL() ? gfx::Insets::TLBR(border.top(), border.right(),
border.bottom(), border.left())
: border;
}
gfx::Insets ClientFrameViewLinux::RestoredFrameBorderInsets() const {
gfx::Insets insets = GetFrameProvider()->GetFrameThicknessDip();
const gfx::Insets input = GetInputInsets();
@@ -163,7 +156,9 @@ gfx::Insets ClientFrameViewLinux::RestoredFrameBorderInsets() const {
merged.set_bottom(expand_if_visible(insets.bottom(), input.bottom()));
merged.set_right(expand_if_visible(insets.right(), input.right()));
return merged;
return base::i18n::IsRTL() ? gfx::Insets::TLBR(merged.top(), merged.right(),
merged.bottom(), merged.left())
: merged;
}
gfx::Insets ClientFrameViewLinux::GetInputInsets() const {
@@ -174,7 +169,7 @@ gfx::Insets ClientFrameViewLinux::GetInputInsets() const {
gfx::Rect ClientFrameViewLinux::GetWindowContentBounds() const {
gfx::Rect content_bounds = bounds();
content_bounds.Inset(RestoredMirroredFrameBorderInsets());
content_bounds.Inset(RestoredFrameBorderInsets());
return content_bounds;
}
@@ -208,13 +203,13 @@ void ClientFrameViewLinux::OnWindowButtonOrderingChange() {
}
int ClientFrameViewLinux::ResizingBorderHitTest(const gfx::Point& point) {
return ResizingBorderHitTestImpl(point, RestoredMirroredFrameBorderInsets());
return ResizingBorderHitTestImpl(point, RestoredFrameBorderInsets());
}
gfx::Rect ClientFrameViewLinux::GetBoundsForClientView() const {
gfx::Rect client_bounds = bounds();
if (!frame_->IsFullscreen()) {
client_bounds.Inset(RestoredMirroredFrameBorderInsets());
client_bounds.Inset(RestoredFrameBorderInsets());
client_bounds.Inset(
gfx::Insets::TLBR(GetTitlebarBounds().height(), 0, 0, 0));
}
@@ -268,20 +263,6 @@ void ClientFrameViewLinux::SizeConstraintsChanged() {
InvalidateLayout();
}
gfx::Size ClientFrameViewLinux::CalculatePreferredSize(
const views::SizeBounds& available_size) const {
return SizeWithDecorations(
FramelessView::CalculatePreferredSize(available_size));
}
gfx::Size ClientFrameViewLinux::GetMinimumSize() const {
return SizeWithDecorations(FramelessView::GetMinimumSize());
}
gfx::Size ClientFrameViewLinux::GetMaximumSize() const {
return SizeWithDecorations(FramelessView::GetMaximumSize());
}
void ClientFrameViewLinux::Layout(PassKey) {
LayoutSuperclass<FramelessView>(this);
@@ -474,7 +455,7 @@ gfx::Rect ClientFrameViewLinux::GetTitlebarBounds() const {
std::max(font_height, theme_values_.titlebar_min_height) +
GetTitlebarContentInsets().height();
gfx::Insets decoration_insets = RestoredMirroredFrameBorderInsets();
gfx::Insets decoration_insets = RestoredFrameBorderInsets();
// We add the inset height here, so the .Inset() that follows won't reduce it
// to be too small.
@@ -493,15 +474,6 @@ gfx::Rect ClientFrameViewLinux::GetTitlebarContentBounds() const {
titlebar.Inset(GetTitlebarContentInsets());
return titlebar;
}
gfx::Size ClientFrameViewLinux::SizeWithDecorations(gfx::Size size) const {
gfx::Insets decoration_insets = RestoredMirroredFrameBorderInsets();
size.Enlarge(0, GetTitlebarBounds().height());
size.Enlarge(decoration_insets.width(), decoration_insets.height());
return size;
}
views::View* ClientFrameViewLinux::TargetForRect(views::View* root,
const gfx::Rect& rect) {
return views::FrameView::TargetForRect(root, rect);

View File

@@ -42,9 +42,9 @@ class ClientFrameViewLinux : public FramelessView,
void Init(NativeWindowViews* window, views::Widget* frame) override;
// These are here for ElectronDesktopWindowTreeHostLinux to use.
gfx::Insets RestoredMirroredFrameBorderInsets() const;
gfx::Insets RestoredFrameBorderInsets() const;
// FramelessView:
gfx::Insets RestoredFrameBorderInsets() const override;
gfx::Insets GetInputInsets() const;
gfx::Rect GetWindowContentBounds() const;
SkRRect GetRoundedWindowContentBounds() const;
@@ -74,10 +74,6 @@ class ClientFrameViewLinux : public FramelessView,
void SizeConstraintsChanged() override;
// Overridden from View:
gfx::Size CalculatePreferredSize(
const views::SizeBounds& available_size) const override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
void Layout(PassKey) override;
void OnPaint(gfx::Canvas* canvas) override;
@@ -127,8 +123,6 @@ class ClientFrameViewLinux : public FramelessView,
gfx::Insets GetTitlebarContentInsets() const;
gfx::Rect GetTitlebarContentBounds() const;
gfx::Size SizeWithDecorations(gfx::Size size) const;
raw_ptr<ui::NativeTheme> theme_;
ThemeValues theme_values_;

View File

@@ -30,6 +30,10 @@ void FramelessView::Init(NativeWindowViews* window, views::Widget* frame) {
frame_ = frame;
}
gfx::Insets FramelessView::RestoredFrameBorderInsets() const {
return gfx::Insets();
}
int FramelessView::ResizingBorderHitTest(const gfx::Point& point) {
return ResizingBorderHitTestImpl(point, gfx::Insets(kResizeInsideBoundsSize));
}
@@ -108,16 +112,16 @@ gfx::Size FramelessView::CalculatePreferredSize(
}
gfx::Size FramelessView::GetMinimumSize() const {
return window_->GetContentMinimumSize();
if (!window_)
return gfx::Size();
return window_->GetMinimumSize();
}
gfx::Size FramelessView::GetMaximumSize() const {
gfx::Size size = window_->GetContentMaximumSize();
// Electron public APIs returns (0, 0) when maximum size is not set, but it
// would break internal window APIs like HWNDMessageHandler::SetAspectRatio.
return size.IsEmpty() ? gfx::Size(INT_MAX, INT_MAX) : size;
if (!window_)
return gfx::Size();
return window_->GetMaximumSize();
}
BEGIN_METADATA(FramelessView)
END_METADATA

View File

@@ -7,6 +7,7 @@
#include "base/memory/raw_ptr.h"
#include "ui/base/metadata/metadata_header_macros.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/window/non_client_view.h"
namespace views {
@@ -37,6 +38,10 @@ class FramelessView : public views::FrameView {
// and forces a re-layout and re-paint.
virtual void InvalidateCaptionButtons() {}
// Any insets from the (transparent) widget bounds to the logical/opaque
// bounds of the view, used for CSD and resize targets on some platforms.
virtual gfx::Insets RestoredFrameBorderInsets() const;
NativeWindowViews* window() const { return window_; }
views::Widget* frame() const { return frame_; }

View File

@@ -39,6 +39,7 @@ class OpaqueFrameView : public FramelessView {
void Init(NativeWindowViews* window, views::Widget* frame) override;
int ResizingBorderHitTest(const gfx::Point& point) override;
void InvalidateCaptionButtons() override;
gfx::Insets RestoredFrameBorderInsets() const override;
// views::FrameView:
gfx::Rect GetBoundsForClientView() const override;
@@ -99,11 +100,6 @@ class OpaqueFrameView : public FramelessView {
// rather than having extra vertical space above the tabs.
bool IsFrameCondensed() const;
// The insets from the native window edge to the client view when the window
// is restored. This goes all the way to the web contents on the left, right,
// and bottom edges.
gfx::Insets RestoredFrameBorderInsets() const;
// The insets from the native window edge to the flat portion of the
// window border. That is, this function returns the "3D portion" of the
// border when the window is restored. The returned insets will not be larger

View File

@@ -274,6 +274,21 @@ bool WinFrameView::GetShouldPaintAsActive() {
return ShouldPaintAsActive();
}
gfx::Size WinFrameView::GetMinimumSize() const {
// Chromium expects minimum size to be in content dimensions on Windows
// because it adds the frame border automatically in OnGetMinMaxInfo.
return window_->GetContentMinimumSize();
}
gfx::Size WinFrameView::GetMaximumSize() const {
// Chromium expects minimum size to be in content dimensions on Windows
// because it adds the frame border automatically in OnGetMinMaxInfo.
gfx::Size size = window_->GetContentMaximumSize();
// Electron public APIs returns (0, 0) when maximum size is not set, but it
// would break internal window APIs like HWNDMessageHandler::SetAspectRatio.
return size.IsEmpty() ? gfx::Size(INT_MAX, INT_MAX) : size;
}
BEGIN_METADATA(WinFrameView)
END_METADATA

View File

@@ -35,6 +35,8 @@ class WinFrameView : public FramelessView {
gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const override;
int NonClientHitTest(const gfx::Point& point) override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
WinCaptionButtonContainer* caption_button_container() {
return caption_button_container_;

View File

@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
#include "base/base_switches.h"
#include "base/memory/raw_ptr.h"
#include "gin/converter.h"
#include "shell/common/api/electron_api_native_image.h"
@@ -17,6 +18,15 @@
#include "ui/gfx/image/image_skia.h"
#include "v8/include/v8.h"
#if BUILDFLAG(IS_LINUX) && (defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64))
#define ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "components/crash/core/app/crashpad.h" // nogncheck
#include "content/public/common/content_switches.h"
#include "v8/include/v8-wasm-trap-handler-posix.h"
#endif
namespace electron {
namespace {
@@ -240,6 +250,51 @@ v8::Local<v8::Value> DeserializeV8Value(v8::Isolate* isolate,
return V8Deserializer(isolate, data).Deserialize();
}
void SetUpWebAssemblyTrapHandler() {
#if BUILDFLAG(IS_WIN)
// On Windows we use the default trap handler provided by V8.
v8::V8::EnableWebAssemblyTrapHandler(true);
#elif BUILDFLAG(IS_MAC)
// On macOS, Crashpad uses exception ports to handle signals in a
// different process. As we cannot just pass a callback to this other
// process, we ask V8 to install its own signal handler to deal with
// WebAssembly traps.
v8::V8::EnableWebAssemblyTrapHandler(true);
#elif defined(ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX)
const bool crash_reporter_enabled =
crash_reporter::GetHandlerSocket(nullptr, nullptr);
if (crash_reporter_enabled) {
// If either --enable-crash-reporter or --enable-crash-reporter-for-testing
// is enabled it should take care of signal handling for us, use the default
// implementation which doesn't register an additional handler.
v8::V8::EnableWebAssemblyTrapHandler(false);
return;
}
const bool use_v8_default_handler =
base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kDisableInProcessStackTraces);
if (use_v8_default_handler) {
// There is no signal handler yet, but it's okay if v8 registers one.
v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/true);
return;
}
if (base::debug::SetStackDumpFirstChanceCallback(
v8::TryHandleWebAssemblyTrapPosix)) {
// Crashpad and Breakpad are disabled, but the in-process stack dump
// handlers are enabled, so set the callback on the stack dump handlers.
v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/false);
return;
}
// As the registration of the callback failed, we don't enable trap
// handlers.
#endif
}
namespace util {
/**

View File

@@ -30,6 +30,8 @@ v8::Local<v8::Value> DeserializeV8Value(v8::Isolate* isolate,
v8::Local<v8::Value> DeserializeV8Value(v8::Isolate* isolate,
base::span<const uint8_t> data);
void SetUpWebAssemblyTrapHandler();
namespace util {
[[nodiscard]] base::span<uint8_t> as_byte_span(

View File

@@ -6,10 +6,9 @@
#include <algorithm>
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/debug/stack_trace.h"
#include "content/public/renderer/render_frame.h"
#include "electron/fuses.h"
#include "net/http/http_request_headers.h"
#include "shell/common/api/electron_bindings.h"
#include "shell/common/gin_helper/dictionary.h"
@@ -18,6 +17,7 @@
#include "shell/common/node_includes.h"
#include "shell/common/node_util.h"
#include "shell/common/options_switches.h"
#include "shell/common/v8_util.h"
#include "shell/renderer/electron_render_frame_observer.h"
#include "shell/renderer/web_worker_observer.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
@@ -26,13 +26,6 @@
#include "third_party/blink/renderer/core/execution_context/execution_context.h" // nogncheck
#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" // nogncheck
#if BUILDFLAG(IS_LINUX) && (defined(ARCH_CPU_X86_64) || defined(ARCH_CPU_ARM64))
#define ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX
#include "components/crash/core/app/crashpad.h" // nogncheck
#include "content/public/common/content_switches.h"
#include "v8/include/v8-wasm-trap-handler-posix.h"
#endif
namespace electron {
ElectronRendererClient::ElectronRendererClient()
@@ -247,45 +240,13 @@ void ElectronRendererClient::WillDestroyWorkerContextOnWorkerThread(
}
void ElectronRendererClient::SetUpWebAssemblyTrapHandler() {
// See CL:5372409 - copied from ShellContentRendererClient.
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
// Mac and Windows use the default implementation (where the default v8 trap
// handler gets set up).
ContentRendererClient::SetUpWebAssemblyTrapHandler();
return;
#elif defined(ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX)
const bool crash_reporter_enabled =
crash_reporter::GetHandlerSocket(nullptr, nullptr);
if (crash_reporter_enabled) {
// If either --enable-crash-reporter or --enable-crash-reporter-for-testing
// is enabled it should take care of signal handling for us, use the default
// implementation which doesn't register an additional handler.
ContentRendererClient::SetUpWebAssemblyTrapHandler();
return;
#if ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) && \
defined(ARCH_CPU_X86_64)) || \
((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)) && defined(ARCH_CPU_ARM64))
if (electron::fuses::IsWasmTrapHandlersEnabled()) {
electron::SetUpWebAssemblyTrapHandler();
}
const bool use_v8_default_handler =
base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kDisableInProcessStackTraces);
if (use_v8_default_handler) {
// There is no signal handler yet, but it's okay if v8 registers one.
v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/true);
return;
}
if (base::debug::SetStackDumpFirstChanceCallback(
v8::TryHandleWebAssemblyTrapPosix)) {
// Crashpad and Breakpad are disabled, but the in-process stack dump
// handlers are enabled, so set the callback on the stack dump handlers.
v8::V8::EnableWebAssemblyTrapHandler(/*use_v8_signal_handler=*/false);
return;
}
// As the registration of the callback failed, we don't enable trap
// handlers.
#endif // defined(ENABLE_WEB_ASSEMBLY_TRAP_HANDLER_LINUX)
#endif
}
node::Environment* ElectronRendererClient::GetEnvironment(

View File

@@ -11,6 +11,7 @@
#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/strings/utf_string_conversions.h"
#include "electron/fuses.h"
#include "electron/mas.h"
#include "net/base/network_change_notifier.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
@@ -22,6 +23,7 @@
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/node_bindings.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_util.h"
#include "shell/services/node/parent_port.h"
#if !IS_MAS_BUILD()
@@ -130,6 +132,15 @@ void NodeService::Initialize(
v8::Isolate* const isolate = js_env_->isolate();
v8::HandleScope scope{isolate};
// Enable trap handlers before user script execution.
#if ((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) && \
defined(ARCH_CPU_X86_64)) || \
((BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC)) && defined(ARCH_CPU_ARM64))
if (electron::fuses::IsWasmTrapHandlersEnabled()) {
electron::SetUpWebAssemblyTrapHandler();
}
#endif
node_bindings_->Initialize(isolate, isolate->GetCurrentContext());
network_change_notifier_ = net::NetworkChangeNotifier::CreateIfNeeded(

221
spec/mas-spec.ts Normal file
View File

@@ -0,0 +1,221 @@
import * as cp from 'node:child_process';
import * as path from 'node:path';
import { ifdescribe } from './lib/spec-helpers';
ifdescribe(process.platform === 'darwin' && process.mas)('Mac App Store build', () => {
describe('private API usage', () => {
// Get paths to all Electron binaries
const getElectronBinaries = () => {
const contentsPath = path.dirname(path.dirname(process.execPath));
return {
mainProcess: process.execPath,
framework: path.join(contentsPath, 'Frameworks', 'Electron Framework.framework', 'Electron Framework'),
helpers: {
main: path.join(contentsPath, 'Frameworks', 'Electron Helper.app', 'Contents', 'MacOS', 'Electron Helper'),
gpu: path.join(contentsPath, 'Frameworks', 'Electron Helper (GPU).app', 'Contents', 'MacOS', 'Electron Helper (GPU)'),
plugin: path.join(contentsPath, 'Frameworks', 'Electron Helper (Plugin).app', 'Contents', 'MacOS', 'Electron Helper (Plugin)'),
renderer: path.join(contentsPath, 'Frameworks', 'Electron Helper (Renderer).app', 'Contents', 'MacOS', 'Electron Helper (Renderer)')
}
};
};
const checkBinaryForPrivateAPIs = (binaryPath: string, binaryName: string) => {
// Use nm without -U to get all symbols (both defined and undefined)
const nmResult = cp.spawnSync('nm', ['-g', binaryPath], {
encoding: 'utf-8',
maxBuffer: 50 * 1024 * 1024
});
if (nmResult.error) {
throw new Error(`Failed to run nm on ${binaryName}: ${nmResult.error.message}`);
}
const symbols = nmResult.stdout;
// List of known private APIs that should not be present in MAS builds
// These are from the mas_avoid_private_macos_api_usage.patch
const privateAPIs = [
'abort_report_np',
'pthread_fchdir_np',
'pthread_chdir_np',
'SetApplicationIsDaemon',
'_LSSetApplicationLaunchServicesServerConnectionStatus',
'CGSSetWindowCaptureExcludeShape',
'CGRegionCreateWithRect',
'CTFontCopyVariationAxesInternal',
'AudioDeviceDuck',
'CGSMainConnectionID',
'IOBluetoothPreferenceSetControllerPowerState',
'CGSSetDenyWindowServerConnections',
'CGFontRenderingGetFontSmoothingDisabled',
'CTFontDescriptorIsSystemUIFont',
'sandbox_init_with_parameters',
'sandbox_create_params',
'sandbox_set_param',
'sandbox_free_params',
'sandbox_compile_string',
'sandbox_apply',
'sandbox_free_profile',
'sandbox_extension_issue_file',
'sandbox_extension_consume',
'sandbox_extension_release',
'_CSCheckFixDisable',
'responsibility_get_pid_responsible_for_pid',
'_NSAppendToKillRing',
'_NSPrependToKillRing',
'_NSYankFromKillRing',
'__NSNewKillRingSequence',
'__NSInitializeKillRing',
'_NSSetKillRingToYankedState'
];
const foundPrivateAPIs: string[] = [];
for (const api of privateAPIs) {
// Check if the symbol appears in the nm output
// Look for ' U ' (undefined) or ' T ' (defined in text section) followed by the API
// nm output format is like: " U _symbol_name"
const regex = new RegExp(`\\s+[UT]\\s+(_${api})\\b`);
const match = symbols.match(regex);
if (match) {
// Keep the full symbol name including the underscore
foundPrivateAPIs.push(match[1]);
}
}
return foundPrivateAPIs;
};
it('should not use private macOS APIs in main process', function () {
this.timeout(60000);
const binaries = getElectronBinaries();
const foundPrivateAPIs = checkBinaryForPrivateAPIs(binaries.mainProcess, 'Electron main process');
if (foundPrivateAPIs.length > 0) {
throw new Error(
`Found private macOS APIs in main process:\n${foundPrivateAPIs.join('\n')}\n\n` +
'These APIs are not allowed in Mac App Store builds and will cause rejection.'
);
}
// Also check for private framework linkage
const otoolResult = cp.spawnSync('otool', ['-L', binaries.mainProcess], {
encoding: 'utf-8'
});
if (otoolResult.error) {
throw new Error(`Failed to run otool: ${otoolResult.error.message}`);
}
const frameworks = otoolResult.stdout;
if (frameworks.includes('PrivateFrameworks')) {
throw new Error(
'Found linkage to PrivateFrameworks which is not allowed in Mac App Store builds:\n' +
frameworks
);
}
});
it('should not use private macOS APIs in Electron Framework', function () {
this.timeout(60000);
// Check the Electron Framework binary (mentioned in issue #49616)
const binaries = getElectronBinaries();
const foundAPIs = checkBinaryForPrivateAPIs(binaries.framework, 'Electron Framework');
if (foundAPIs.length > 0) {
throw new Error(
`Found private macOS APIs in Electron Framework:\n${foundAPIs.join('\n')}\n\n` +
'These APIs are not allowed in Mac App Store builds and will cause rejection.\n' +
'See patches/chromium/mas_avoid_private_macos_api_usage.patch.patch'
);
}
});
it('should not use private macOS APIs in helper processes', function () {
this.timeout(60000);
const binaries = getElectronBinaries();
const allFoundAPIs: Record<string, string[]> = {};
for (const [helperName, helperPath] of Object.entries(binaries.helpers)) {
const displayName = `Electron Helper${helperName !== 'main' ? ` (${helperName.charAt(0).toUpperCase() + helperName.slice(1)})` : ''}`;
const foundAPIs = checkBinaryForPrivateAPIs(helperPath, displayName);
if (foundAPIs.length > 0) {
allFoundAPIs[displayName] = foundAPIs;
}
}
if (Object.keys(allFoundAPIs).length > 0) {
const errorLines = Object.entries(allFoundAPIs).map(([helper, apis]) =>
`${helper}:\n ${apis.join('\n ')}`
);
throw new Error(
`Found private macOS APIs in helper processes:\n\n${errorLines.join('\n\n')}\n\n` +
'These APIs are not allowed in Mac App Store builds and will cause rejection.'
);
}
});
it('should not reference private Objective-C classes', function () {
this.timeout(60000);
// Check for private Objective-C classes (appear as _OBJC_CLASS_$_ClassName)
const privateClasses = [
'NSAccessibilityRemoteUIElement',
'CAContext'
];
const binaries = getElectronBinaries();
const binariesToCheck = [
{ path: binaries.mainProcess, name: 'Electron main process' },
{ path: binaries.framework, name: 'Electron Framework' },
{ path: binaries.helpers.main, name: 'Electron Helper' },
{ path: binaries.helpers.renderer, name: 'Electron Helper (Renderer)' }
];
const foundClasses: Record<string, string[]> = {};
for (const binary of binariesToCheck) {
const nmResult = cp.spawnSync('nm', ['-g', binary.path], {
encoding: 'utf-8',
maxBuffer: 50 * 1024 * 1024
});
if (nmResult.error) {
throw new Error(`Failed to run nm on ${binary.name}: ${nmResult.error.message}`);
}
const symbols = nmResult.stdout;
const foundInBinary: string[] = [];
for (const className of privateClasses) {
// Look for _OBJC_CLASS_$_ClassName pattern
if (symbols.includes(`_OBJC_CLASS_$_${className}`)) {
foundInBinary.push(className);
}
}
if (foundInBinary.length > 0) {
foundClasses[binary.name] = foundInBinary;
}
}
if (Object.keys(foundClasses).length > 0) {
const errorLines = Object.entries(foundClasses).map(([binary, classes]) =>
`${binary}:\n ${classes.join('\n ')}`
);
throw new Error(
`Found references to private Objective-C classes:\n\n${errorLines.join('\n\n')}\n\n` +
'These are not allowed in Mac App Store builds and will cause rejection.'
);
}
});
});
});

463
yarn.lock
View File

@@ -638,7 +638,7 @@ __metadata:
ts-node: "npm:6.2.0"
typescript: "npm:^5.8.3"
url: "npm:^0.11.4"
webpack: "npm:^5.95.0"
webpack: "npm:^5.104.1"
webpack-cli: "npm:^6.0.1"
wrapper-webpack-plugin: "npm:^2.2.0"
yaml: "npm:^2.8.1"
@@ -1206,7 +1206,7 @@ __metadata:
languageName: node
linkType: hard
"@jridgewell/trace-mapping@npm:^0.3.20, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25":
"@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25":
version: 0.3.25
resolution: "@jridgewell/trace-mapping@npm:0.3.25"
dependencies:
@@ -1978,6 +1978,26 @@ __metadata:
languageName: node
linkType: hard
"@types/eslint-scope@npm:^3.7.7":
version: 3.7.7
resolution: "@types/eslint-scope@npm:3.7.7"
dependencies:
"@types/eslint": "npm:*"
"@types/estree": "npm:*"
checksum: 10c0/a0ecbdf2f03912679440550817ff77ef39a30fa8bfdacaf6372b88b1f931828aec392f52283240f0d648cf3055c5ddc564544a626bcf245f3d09fcb099ebe3cc
languageName: node
linkType: hard
"@types/eslint@npm:*":
version: 9.6.1
resolution: "@types/eslint@npm:9.6.1"
dependencies:
"@types/estree": "npm:*"
"@types/json-schema": "npm:*"
checksum: 10c0/69ba24fee600d1e4c5abe0df086c1a4d798abf13792d8cfab912d76817fe1a894359a1518557d21237fbaf6eda93c5ab9309143dee4c59ef54336d1b3570420e
languageName: node
linkType: hard
"@types/estree-jsx@npm:^1.0.0":
version: 1.0.5
resolution: "@types/estree-jsx@npm:1.0.5"
@@ -1987,20 +2007,13 @@ __metadata:
languageName: node
linkType: hard
"@types/estree@npm:*":
"@types/estree@npm:*, @types/estree@npm:^1.0.8":
version: 1.0.8
resolution: "@types/estree@npm:1.0.8"
checksum: 10c0/39d34d1afaa338ab9763f37ad6066e3f349444f9052b9676a7cc0252ef9485a41c6d81c9c4e0d26e9077993354edf25efc853f3224dd4b447175ef62bdcc86a5
languageName: node
linkType: hard
"@types/estree@npm:^1.0.5":
version: 1.0.5
resolution: "@types/estree@npm:1.0.5"
checksum: 10c0/b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d
languageName: node
linkType: hard
"@types/express-serve-static-core@npm:^4.17.33":
version: 4.19.7
resolution: "@types/express-serve-static-core@npm:4.19.7"
@@ -2079,6 +2092,13 @@ __metadata:
languageName: node
linkType: hard
"@types/json-schema@npm:*, @types/json-schema@npm:^7.0.15, @types/json-schema@npm:^7.0.9":
version: 7.0.15
resolution: "@types/json-schema@npm:7.0.15"
checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db
languageName: node
linkType: hard
"@types/json-schema@npm:^7.0.8":
version: 7.0.11
resolution: "@types/json-schema@npm:7.0.11"
@@ -2593,154 +2613,154 @@ __metadata:
languageName: node
linkType: hard
"@webassemblyjs/ast@npm:1.12.1, @webassemblyjs/ast@npm:^1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/ast@npm:1.12.1"
"@webassemblyjs/ast@npm:1.14.1, @webassemblyjs/ast@npm:^1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/ast@npm:1.14.1"
dependencies:
"@webassemblyjs/helper-numbers": "npm:1.11.6"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6"
checksum: 10c0/ba7f2b96c6e67e249df6156d02c69eb5f1bd18d5005303cdc42accb053bebbbde673826e54db0437c9748e97abd218366a1d13fa46859b23cde611b6b409998c
"@webassemblyjs/helper-numbers": "npm:1.13.2"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.13.2"
checksum: 10c0/67a59be8ed50ddd33fbb2e09daa5193ac215bf7f40a9371be9a0d9797a114d0d1196316d2f3943efdb923a3d809175e1563a3cb80c814fb8edccd1e77494972b
languageName: node
linkType: hard
"@webassemblyjs/floating-point-hex-parser@npm:1.11.6":
version: 1.11.6
resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.11.6"
checksum: 10c0/37fe26f89e18e4ca0e7d89cfe3b9f17cfa327d7daf906ae01400416dbb2e33c8a125b4dc55ad7ff405e5fcfb6cf0d764074c9bc532b9a31a71e762be57d2ea0a
"@webassemblyjs/floating-point-hex-parser@npm:1.13.2":
version: 1.13.2
resolution: "@webassemblyjs/floating-point-hex-parser@npm:1.13.2"
checksum: 10c0/0e88bdb8b50507d9938be64df0867f00396b55eba9df7d3546eb5dc0ca64d62e06f8d881ec4a6153f2127d0f4c11d102b6e7d17aec2f26bb5ff95a5e60652412
languageName: node
linkType: hard
"@webassemblyjs/helper-api-error@npm:1.11.6":
version: 1.11.6
resolution: "@webassemblyjs/helper-api-error@npm:1.11.6"
checksum: 10c0/a681ed51863e4ff18cf38d223429f414894e5f7496856854d9a886eeddcee32d7c9f66290f2919c9bb6d2fc2b2fae3f989b6a1e02a81e829359738ea0c4d371a
"@webassemblyjs/helper-api-error@npm:1.13.2":
version: 1.13.2
resolution: "@webassemblyjs/helper-api-error@npm:1.13.2"
checksum: 10c0/31be497f996ed30aae4c08cac3cce50c8dcd5b29660383c0155fce1753804fc55d47fcba74e10141c7dd2899033164e117b3bcfcda23a6b043e4ded4f1003dfb
languageName: node
linkType: hard
"@webassemblyjs/helper-buffer@npm:1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/helper-buffer@npm:1.12.1"
checksum: 10c0/0270724afb4601237410f7fd845ab58ccda1d5456a8783aadfb16eaaf3f2c9610c28e4a5bcb6ad880cde5183c82f7f116d5ccfc2310502439d33f14b6888b48a
"@webassemblyjs/helper-buffer@npm:1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/helper-buffer@npm:1.14.1"
checksum: 10c0/0d54105dc373c0fe6287f1091e41e3a02e36cdc05e8cf8533cdc16c59ff05a646355415893449d3768cda588af451c274f13263300a251dc11a575bc4c9bd210
languageName: node
linkType: hard
"@webassemblyjs/helper-numbers@npm:1.11.6":
version: 1.11.6
resolution: "@webassemblyjs/helper-numbers@npm:1.11.6"
"@webassemblyjs/helper-numbers@npm:1.13.2":
version: 1.13.2
resolution: "@webassemblyjs/helper-numbers@npm:1.13.2"
dependencies:
"@webassemblyjs/floating-point-hex-parser": "npm:1.11.6"
"@webassemblyjs/helper-api-error": "npm:1.11.6"
"@webassemblyjs/floating-point-hex-parser": "npm:1.13.2"
"@webassemblyjs/helper-api-error": "npm:1.13.2"
"@xtuc/long": "npm:4.2.2"
checksum: 10c0/c7d5afc0ff3bd748339b466d8d2f27b908208bf3ff26b2e8e72c39814479d486e0dca6f3d4d776fd9027c1efe05b5c0716c57a23041eb34473892b2731c33af3
checksum: 10c0/9c46852f31b234a8fb5a5a9d3f027bc542392a0d4de32f1a9c0075d5e8684aa073cb5929b56df565500b3f9cc0a2ab983b650314295b9bf208d1a1651bfc825a
languageName: node
linkType: hard
"@webassemblyjs/helper-wasm-bytecode@npm:1.11.6":
version: 1.11.6
resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.11.6"
checksum: 10c0/79d2bebdd11383d142745efa32781249745213af8e022651847382685ca76709f83e1d97adc5f0d3c2b8546bf02864f8b43a531fdf5ca0748cb9e4e0ef2acaa5
"@webassemblyjs/helper-wasm-bytecode@npm:1.13.2":
version: 1.13.2
resolution: "@webassemblyjs/helper-wasm-bytecode@npm:1.13.2"
checksum: 10c0/c4355d14f369b30cf3cbdd3acfafc7d0488e086be6d578e3c9780bd1b512932352246be96e034e2a7fcfba4f540ec813352f312bfcbbfe5bcfbf694f82ccc682
languageName: node
linkType: hard
"@webassemblyjs/helper-wasm-section@npm:1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/helper-wasm-section@npm:1.12.1"
"@webassemblyjs/helper-wasm-section@npm:1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/helper-wasm-section@npm:1.14.1"
dependencies:
"@webassemblyjs/ast": "npm:1.12.1"
"@webassemblyjs/helper-buffer": "npm:1.12.1"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6"
"@webassemblyjs/wasm-gen": "npm:1.12.1"
checksum: 10c0/0546350724d285ae3c26e6fc444be4c3b5fb824f3be0ec8ceb474179dc3f4430336dd2e36a44b3e3a1a6815960e5eec98cd9b3a8ec66dc53d86daedd3296a6a2
"@webassemblyjs/ast": "npm:1.14.1"
"@webassemblyjs/helper-buffer": "npm:1.14.1"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.13.2"
"@webassemblyjs/wasm-gen": "npm:1.14.1"
checksum: 10c0/1f9b33731c3c6dbac3a9c483269562fa00d1b6a4e7133217f40e83e975e636fd0f8736e53abd9a47b06b66082ecc976c7384391ab0a68e12d509ea4e4b948d64
languageName: node
linkType: hard
"@webassemblyjs/ieee754@npm:1.11.6":
version: 1.11.6
resolution: "@webassemblyjs/ieee754@npm:1.11.6"
"@webassemblyjs/ieee754@npm:1.13.2":
version: 1.13.2
resolution: "@webassemblyjs/ieee754@npm:1.13.2"
dependencies:
"@xtuc/ieee754": "npm:^1.2.0"
checksum: 10c0/59de0365da450322c958deadade5ec2d300c70f75e17ae55de3c9ce564deff5b429e757d107c7ec69bd0ba169c6b6cc2ff66293ab7264a7053c829b50ffa732f
checksum: 10c0/2e732ca78c6fbae3c9b112f4915d85caecdab285c0b337954b180460290ccd0fb00d2b1dc4bb69df3504abead5191e0d28d0d17dfd6c9d2f30acac8c4961c8a7
languageName: node
linkType: hard
"@webassemblyjs/leb128@npm:1.11.6":
version: 1.11.6
resolution: "@webassemblyjs/leb128@npm:1.11.6"
"@webassemblyjs/leb128@npm:1.13.2":
version: 1.13.2
resolution: "@webassemblyjs/leb128@npm:1.13.2"
dependencies:
"@xtuc/long": "npm:4.2.2"
checksum: 10c0/cb344fc04f1968209804de4da018679c5d4708a03b472a33e0fa75657bb024978f570d3ccf9263b7f341f77ecaa75d0e051b9cd4b7bb17a339032cfd1c37f96e
checksum: 10c0/dad5ef9e383c8ab523ce432dfd80098384bf01c45f70eb179d594f85ce5db2f80fa8c9cba03adafd85684e6d6310f0d3969a882538975989919329ac4c984659
languageName: node
linkType: hard
"@webassemblyjs/utf8@npm:1.11.6":
version: 1.11.6
resolution: "@webassemblyjs/utf8@npm:1.11.6"
checksum: 10c0/14d6c24751a89ad9d801180b0d770f30a853c39f035a15fbc96266d6ac46355227abd27a3fd2eeaa97b4294ced2440a6b012750ae17bafe1a7633029a87b6bee
"@webassemblyjs/utf8@npm:1.13.2":
version: 1.13.2
resolution: "@webassemblyjs/utf8@npm:1.13.2"
checksum: 10c0/d3fac9130b0e3e5a1a7f2886124a278e9323827c87a2b971e6d0da22a2ba1278ac9f66a4f2e363ecd9fac8da42e6941b22df061a119e5c0335f81006de9ee799
languageName: node
linkType: hard
"@webassemblyjs/wasm-edit@npm:^1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/wasm-edit@npm:1.12.1"
"@webassemblyjs/wasm-edit@npm:^1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/wasm-edit@npm:1.14.1"
dependencies:
"@webassemblyjs/ast": "npm:1.12.1"
"@webassemblyjs/helper-buffer": "npm:1.12.1"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6"
"@webassemblyjs/helper-wasm-section": "npm:1.12.1"
"@webassemblyjs/wasm-gen": "npm:1.12.1"
"@webassemblyjs/wasm-opt": "npm:1.12.1"
"@webassemblyjs/wasm-parser": "npm:1.12.1"
"@webassemblyjs/wast-printer": "npm:1.12.1"
checksum: 10c0/972f5e6c522890743999e0ed45260aae728098801c6128856b310dd21f1ee63435fc7b518e30e0ba1cdafd0d1e38275829c1e4451c3536a1d9e726e07a5bba0b
"@webassemblyjs/ast": "npm:1.14.1"
"@webassemblyjs/helper-buffer": "npm:1.14.1"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.13.2"
"@webassemblyjs/helper-wasm-section": "npm:1.14.1"
"@webassemblyjs/wasm-gen": "npm:1.14.1"
"@webassemblyjs/wasm-opt": "npm:1.14.1"
"@webassemblyjs/wasm-parser": "npm:1.14.1"
"@webassemblyjs/wast-printer": "npm:1.14.1"
checksum: 10c0/5ac4781086a2ca4b320bdbfd965a209655fe8a208ca38d89197148f8597e587c9a2c94fb6bd6f1a7dbd4527c49c6844fcdc2af981f8d793a97bf63a016aa86d2
languageName: node
linkType: hard
"@webassemblyjs/wasm-gen@npm:1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/wasm-gen@npm:1.12.1"
"@webassemblyjs/wasm-gen@npm:1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/wasm-gen@npm:1.14.1"
dependencies:
"@webassemblyjs/ast": "npm:1.12.1"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6"
"@webassemblyjs/ieee754": "npm:1.11.6"
"@webassemblyjs/leb128": "npm:1.11.6"
"@webassemblyjs/utf8": "npm:1.11.6"
checksum: 10c0/1e257288177af9fa34c69cab94f4d9036ebed611f77f3897c988874e75182eeeec759c79b89a7a49dd24624fc2d3d48d5580b62b67c4a1c9bfbdcd266b281c16
"@webassemblyjs/ast": "npm:1.14.1"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.13.2"
"@webassemblyjs/ieee754": "npm:1.13.2"
"@webassemblyjs/leb128": "npm:1.13.2"
"@webassemblyjs/utf8": "npm:1.13.2"
checksum: 10c0/d678810d7f3f8fecb2e2bdadfb9afad2ec1d2bc79f59e4711ab49c81cec578371e22732d4966f59067abe5fba8e9c54923b57060a729d28d408e608beef67b10
languageName: node
linkType: hard
"@webassemblyjs/wasm-opt@npm:1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/wasm-opt@npm:1.12.1"
"@webassemblyjs/wasm-opt@npm:1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/wasm-opt@npm:1.14.1"
dependencies:
"@webassemblyjs/ast": "npm:1.12.1"
"@webassemblyjs/helper-buffer": "npm:1.12.1"
"@webassemblyjs/wasm-gen": "npm:1.12.1"
"@webassemblyjs/wasm-parser": "npm:1.12.1"
checksum: 10c0/992a45e1f1871033c36987459436ab4e6430642ca49328e6e32a13de9106fe69ae6c0ac27d7050efd76851e502d11cd1ac0e06b55655dfa889ad82f11a2712fb
"@webassemblyjs/ast": "npm:1.14.1"
"@webassemblyjs/helper-buffer": "npm:1.14.1"
"@webassemblyjs/wasm-gen": "npm:1.14.1"
"@webassemblyjs/wasm-parser": "npm:1.14.1"
checksum: 10c0/515bfb15277ee99ba6b11d2232ddbf22aed32aad6d0956fe8a0a0a004a1b5a3a277a71d9a3a38365d0538ac40d1b7b7243b1a244ad6cd6dece1c1bb2eb5de7ee
languageName: node
linkType: hard
"@webassemblyjs/wasm-parser@npm:1.12.1, @webassemblyjs/wasm-parser@npm:^1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/wasm-parser@npm:1.12.1"
"@webassemblyjs/wasm-parser@npm:1.14.1, @webassemblyjs/wasm-parser@npm:^1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/wasm-parser@npm:1.14.1"
dependencies:
"@webassemblyjs/ast": "npm:1.12.1"
"@webassemblyjs/helper-api-error": "npm:1.11.6"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.11.6"
"@webassemblyjs/ieee754": "npm:1.11.6"
"@webassemblyjs/leb128": "npm:1.11.6"
"@webassemblyjs/utf8": "npm:1.11.6"
checksum: 10c0/e85cec1acad07e5eb65b92d37c8e6ca09c6ca50d7ca58803a1532b452c7321050a0328c49810c337cc2dfd100c5326a54d5ebd1aa5c339ebe6ef10c250323a0e
"@webassemblyjs/ast": "npm:1.14.1"
"@webassemblyjs/helper-api-error": "npm:1.13.2"
"@webassemblyjs/helper-wasm-bytecode": "npm:1.13.2"
"@webassemblyjs/ieee754": "npm:1.13.2"
"@webassemblyjs/leb128": "npm:1.13.2"
"@webassemblyjs/utf8": "npm:1.13.2"
checksum: 10c0/95427b9e5addbd0f647939bd28e3e06b8deefdbdadcf892385b5edc70091bf9b92fa5faac3fce8333554437c5d85835afef8c8a7d9d27ab6ba01ffab954db8c6
languageName: node
linkType: hard
"@webassemblyjs/wast-printer@npm:1.12.1":
version: 1.12.1
resolution: "@webassemblyjs/wast-printer@npm:1.12.1"
"@webassemblyjs/wast-printer@npm:1.14.1":
version: 1.14.1
resolution: "@webassemblyjs/wast-printer@npm:1.14.1"
dependencies:
"@webassemblyjs/ast": "npm:1.12.1"
"@webassemblyjs/ast": "npm:1.14.1"
"@xtuc/long": "npm:4.2.2"
checksum: 10c0/39bf746eb7a79aa69953f194943bbc43bebae98bd7cadd4d8bc8c0df470ca6bf9d2b789effaa180e900fab4e2691983c1f7d41571458bd2a26267f2f0c73705a
checksum: 10c0/8d7768608996a052545251e896eac079c98e0401842af8dd4de78fba8d90bd505efb6c537e909cd6dae96e09db3fa2e765a6f26492553a675da56e2db51f9d24
languageName: node
linkType: hard
@@ -2848,12 +2868,12 @@ __metadata:
languageName: node
linkType: hard
"acorn-import-attributes@npm:^1.9.5":
version: 1.9.5
resolution: "acorn-import-attributes@npm:1.9.5"
"acorn-import-phases@npm:^1.0.3":
version: 1.0.4
resolution: "acorn-import-phases@npm:1.0.4"
peerDependencies:
acorn: ^8
checksum: 10c0/5926eaaead2326d5a86f322ff1b617b0f698aa61dc719a5baa0e9d955c9885cc71febac3fb5bacff71bbf2c4f9c12db2056883c68c53eb962c048b952e1e013d
acorn: ^8.14.0
checksum: 10c0/338eb46fc1aed5544f628344cb9af189450b401d152ceadbf1f5746901a5d923016cd0e7740d5606062d374fdf6941c29bb515d2bd133c4f4242d5d4cd73a3c7
languageName: node
linkType: hard
@@ -2866,7 +2886,16 @@ __metadata:
languageName: node
linkType: hard
"acorn@npm:^8.7.1, acorn@npm:^8.8.2, acorn@npm:^8.9.0":
"acorn@npm:^8.15.0":
version: 8.15.0
resolution: "acorn@npm:8.15.0"
bin:
acorn: bin/acorn
checksum: 10c0/dec73ff59b7d6628a01eebaece7f2bdb8bb62b9b5926dcad0f8931f2b8b79c2be21f6c68ac095592adb5adb15831a3635d9343e6a91d028bbe85d564875ec3ec
languageName: node
linkType: hard
"acorn@npm:^8.9.0":
version: 8.12.1
resolution: "acorn@npm:8.12.1"
bin:
@@ -2923,6 +2952,17 @@ __metadata:
languageName: node
linkType: hard
"ajv-keywords@npm:^5.1.0":
version: 5.1.0
resolution: "ajv-keywords@npm:5.1.0"
dependencies:
fast-deep-equal: "npm:^3.1.3"
peerDependencies:
ajv: ^8.8.2
checksum: 10c0/18bec51f0171b83123ba1d8883c126e60c6f420cef885250898bf77a8d3e65e3bfb9e8564f497e30bdbe762a83e0d144a36931328616a973ee669dc74d4a9590
languageName: node
linkType: hard
"ajv@npm:^6.12.4, ajv@npm:^6.12.5":
version: 6.12.6
resolution: "ajv@npm:6.12.6"
@@ -2935,7 +2975,7 @@ __metadata:
languageName: node
linkType: hard
"ajv@npm:^8.0.0, ajv@npm:^8.12.0, ajv@npm:^8.16.0":
"ajv@npm:^8.0.0, ajv@npm:^8.12.0, ajv@npm:^8.16.0, ajv@npm:^8.9.0":
version: 8.17.1
resolution: "ajv@npm:8.17.1"
dependencies:
@@ -3397,6 +3437,15 @@ __metadata:
languageName: node
linkType: hard
"baseline-browser-mapping@npm:^2.9.0":
version: 2.9.19
resolution: "baseline-browser-mapping@npm:2.9.19"
bin:
baseline-browser-mapping: dist/cli.js
checksum: 10c0/569928db78bcd081953d7db79e4243a59a579a34b4ae1806b9b42d3b7f84e5bc40e6e82ae4fa06e7bef8291bf747b33b3f9ef5d3c6e1e420cb129d9295536129
languageName: node
linkType: hard
"basic-auth@npm:^2.0.1":
version: 2.0.1
resolution: "basic-auth@npm:2.0.1"
@@ -3553,17 +3602,18 @@ __metadata:
languageName: node
linkType: hard
"browserslist@npm:^4.21.10":
version: 4.23.3
resolution: "browserslist@npm:4.23.3"
"browserslist@npm:^4.28.1":
version: 4.28.1
resolution: "browserslist@npm:4.28.1"
dependencies:
caniuse-lite: "npm:^1.0.30001646"
electron-to-chromium: "npm:^1.5.4"
node-releases: "npm:^2.0.18"
update-browserslist-db: "npm:^1.1.0"
baseline-browser-mapping: "npm:^2.9.0"
caniuse-lite: "npm:^1.0.30001759"
electron-to-chromium: "npm:^1.5.263"
node-releases: "npm:^2.0.27"
update-browserslist-db: "npm:^1.2.0"
bin:
browserslist: cli.js
checksum: 10c0/3063bfdf812815346447f4796c8f04601bf5d62003374305fd323c2a463e42776475bcc5309264e39bcf9a8605851e53560695991a623be988138b3ff8c66642
checksum: 10c0/545a5fa9d7234e3777a7177ec1e9134bb2ba60a69e6b95683f6982b1473aad347c77c1264ccf2ac5dea609a9731fbfbda6b85782bdca70f80f86e28a402504bd
languageName: node
linkType: hard
@@ -3787,10 +3837,10 @@ __metadata:
languageName: node
linkType: hard
"caniuse-lite@npm:^1.0.30001646":
version: 1.0.30001659
resolution: "caniuse-lite@npm:1.0.30001659"
checksum: 10c0/11dc1c0795505d5c629cdf02361d7d60249646a49ed2868997144c3d9c6b0c3e18d87f6ea2b48b6deed593c483271003cebca7dd805fbda96607a9b83899eeaa
"caniuse-lite@npm:^1.0.30001759":
version: 1.0.30001768
resolution: "caniuse-lite@npm:1.0.30001768"
checksum: 10c0/16808cb39f9563098deab6d45bcd0642a79fc5ace8dbcea8106b008b179820353e3ec089ed7e54f1f3c8bb84f2c2835b451f308212d8f36c2b7942f879e91955
languageName: node
linkType: hard
@@ -4956,10 +5006,10 @@ __metadata:
languageName: unknown
linkType: soft
"electron-to-chromium@npm:^1.5.4":
version: 1.5.18
resolution: "electron-to-chromium@npm:1.5.18"
checksum: 10c0/2c553c4e7618e887398af0fb7ddd8055beb69d37a810ad73fcea0f3e9027f1fc879ef280151fb6bae8e5b961f5597452eafc1ae5a0adca5bd49211545a34afe7
"electron-to-chromium@npm:^1.5.263":
version: 1.5.286
resolution: "electron-to-chromium@npm:1.5.286"
checksum: 10c0/5384510f9682d7e46f98fa48b874c3901d9639de96e9e387afce1fe010fbac31376df0534524edc15f66e9902bfacee54037a5e598004e9c6a617884e379926d
languageName: node
linkType: hard
@@ -5034,13 +5084,13 @@ __metadata:
languageName: node
linkType: hard
"enhanced-resolve@npm:^5.17.1":
version: 5.17.1
resolution: "enhanced-resolve@npm:5.17.1"
"enhanced-resolve@npm:^5.19.0":
version: 5.19.0
resolution: "enhanced-resolve@npm:5.19.0"
dependencies:
graceful-fs: "npm:^4.2.4"
tapable: "npm:^2.2.0"
checksum: 10c0/81a0515675eca17efdba2cf5bad87abc91a528fc1191aad50e275e74f045b41506167d420099022da7181c8d787170ea41e4a11a0b10b7a16f6237daecb15370
tapable: "npm:^2.3.0"
checksum: 10c0/966b1dffb82d5f6a4d6a86e904e812104a999066aa29f9223040aaa751e7c453b462a3f5ef91f8bd4408131ff6f7f90651dd1c804bdcb7944e2099a9c2e45ee2
languageName: node
linkType: hard
@@ -5305,10 +5355,10 @@ __metadata:
languageName: node
linkType: hard
"es-module-lexer@npm:^1.2.1":
version: 1.5.4
resolution: "es-module-lexer@npm:1.5.4"
checksum: 10c0/300a469488c2f22081df1e4c8398c78db92358496e639b0df7f89ac6455462aaf5d8893939087c1a1cbcbf20eed4610c70e0bcb8f3e4b0d80a5d2611c539408c
"es-module-lexer@npm:^2.0.0":
version: 2.0.0
resolution: "es-module-lexer@npm:2.0.0"
checksum: 10c0/ae78dbbd43035a4b972c46cfb6877e374ea290adfc62bc2f5a083fea242c0b2baaab25c5886af86be55f092f4a326741cb94334cd3c478c383fdc8a9ec5ff817
languageName: node
linkType: hard
@@ -5420,7 +5470,7 @@ __metadata:
languageName: node
linkType: hard
"escalade@npm:^3.1.1, escalade@npm:^3.1.2":
"escalade@npm:^3.1.1, escalade@npm:^3.2.0":
version: 3.2.0
resolution: "escalade@npm:3.2.0"
checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65
@@ -8609,10 +8659,10 @@ __metadata:
languageName: node
linkType: hard
"loader-runner@npm:^4.2.0":
version: 4.3.0
resolution: "loader-runner@npm:4.3.0"
checksum: 10c0/a44d78aae0907a72f73966fe8b82d1439c8c485238bd5a864b1b9a2a3257832effa858790241e6b37876b5446a78889adf2fcc8dd897ce54c089ecc0a0ce0bf0
"loader-runner@npm:^4.3.1":
version: 4.3.1
resolution: "loader-runner@npm:4.3.1"
checksum: 10c0/a523b6329f114e0a98317158e30a7dfce044b731521be5399464010472a93a15ece44757d1eaed1d8845019869c5390218bc1c7c3110f4eeaef5157394486eac
languageName: node
linkType: hard
@@ -10064,10 +10114,10 @@ __metadata:
languageName: node
linkType: hard
"node-releases@npm:^2.0.18":
version: 2.0.18
resolution: "node-releases@npm:2.0.18"
checksum: 10c0/786ac9db9d7226339e1dc84bbb42007cb054a346bd9257e6aa154d294f01bc6a6cddb1348fa099f079be6580acbb470e3c048effd5f719325abd0179e566fd27
"node-releases@npm:^2.0.27":
version: 2.0.27
resolution: "node-releases@npm:2.0.27"
checksum: 10c0/f1e6583b7833ea81880627748d28a3a7ff5703d5409328c216ae57befbced10ce2c991bea86434e8ec39003bd017f70481e2e5f8c1f7e0a7663241f81d6e00e2
languageName: node
linkType: hard
@@ -10906,20 +10956,13 @@ __metadata:
languageName: node
linkType: hard
"picocolors@npm:^1.0.0":
"picocolors@npm:^1.0.0, picocolors@npm:^1.1.1":
version: 1.1.1
resolution: "picocolors@npm:1.1.1"
checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58
languageName: node
linkType: hard
"picocolors@npm:^1.0.1":
version: 1.1.0
resolution: "picocolors@npm:1.1.0"
checksum: 10c0/86946f6032148801ef09c051c6fb13b5cf942eaf147e30ea79edb91dd32d700934edebe782a1078ff859fb2b816792e97ef4dab03d7f0b804f6b01a0df35e023
languageName: node
linkType: hard
"picomatch@npm:^2.0.4":
version: 2.0.7
resolution: "picomatch@npm:2.0.7"
@@ -12543,7 +12586,7 @@ __metadata:
languageName: node
linkType: hard
"schema-utils@npm:^3.0.0, schema-utils@npm:^3.1.1, schema-utils@npm:^3.2.0":
"schema-utils@npm:^3.0.0":
version: 3.3.0
resolution: "schema-utils@npm:3.3.0"
dependencies:
@@ -12554,6 +12597,18 @@ __metadata:
languageName: node
linkType: hard
"schema-utils@npm:^4.3.0, schema-utils@npm:^4.3.3":
version: 4.3.3
resolution: "schema-utils@npm:4.3.3"
dependencies:
"@types/json-schema": "npm:^7.0.9"
ajv: "npm:^8.9.0"
ajv-formats: "npm:^2.1.1"
ajv-keywords: "npm:^5.1.0"
checksum: 10c0/1c8d2c480a026d7c02ab2ecbe5919133a096d6a721a3f201fa50663e4f30f6d6ba020dfddd93cb828b66b922e76b342e103edd19a62c95c8f60e9079cc403202
languageName: node
linkType: hard
"semver-compare@npm:^1.0.0":
version: 1.0.0
resolution: "semver-compare@npm:1.0.0"
@@ -12659,7 +12714,7 @@ __metadata:
languageName: node
linkType: hard
"serialize-javascript@npm:^6.0.1, serialize-javascript@npm:^6.0.2":
"serialize-javascript@npm:^6.0.2":
version: 6.0.2
resolution: "serialize-javascript@npm:6.0.2"
dependencies:
@@ -13564,10 +13619,10 @@ __metadata:
languageName: node
linkType: hard
"tapable@npm:^2.1.1, tapable@npm:^2.2.0":
version: 2.2.1
resolution: "tapable@npm:2.2.1"
checksum: 10c0/bc40e6efe1e554d075469cedaba69a30eeb373552aaf41caeaaa45bf56ffacc2674261b106245bd566b35d8f3329b52d838e851ee0a852120acae26e622925c9
"tapable@npm:^2.3.0":
version: 2.3.0
resolution: "tapable@npm:2.3.0"
checksum: 10c0/cb9d67cc2c6a74dedc812ef3085d9d681edd2c1fa18e4aef57a3c0605fdbe44e6b8ea00bd9ef21bc74dd45314e39d31227aa031ebf2f5e38164df514136f2681
languageName: node
linkType: hard
@@ -13618,15 +13673,15 @@ __metadata:
languageName: node
linkType: hard
"terser-webpack-plugin@npm:^5.3.10":
version: 5.3.10
resolution: "terser-webpack-plugin@npm:5.3.10"
"terser-webpack-plugin@npm:^5.3.16":
version: 5.3.16
resolution: "terser-webpack-plugin@npm:5.3.16"
dependencies:
"@jridgewell/trace-mapping": "npm:^0.3.20"
"@jridgewell/trace-mapping": "npm:^0.3.25"
jest-worker: "npm:^27.4.5"
schema-utils: "npm:^3.1.1"
serialize-javascript: "npm:^6.0.1"
terser: "npm:^5.26.0"
schema-utils: "npm:^4.3.0"
serialize-javascript: "npm:^6.0.2"
terser: "npm:^5.31.1"
peerDependencies:
webpack: ^5.1.0
peerDependenciesMeta:
@@ -13636,21 +13691,21 @@ __metadata:
optional: true
uglify-js:
optional: true
checksum: 10c0/66d1ed3174542560911cf96f4716aeea8d60e7caab212291705d50072b6ba844c7391442541b13c848684044042bea9ec87512b8506528c12854943da05faf91
checksum: 10c0/39e37c5b3015c1a5354a3633f77235677bfa06eac2608ce26d258b1d1a74070a99910319a6f2f2c437eb61dc321f66434febe01d78e73fa96b4d4393b813f4cf
languageName: node
linkType: hard
"terser@npm:^5.26.0":
version: 5.32.0
resolution: "terser@npm:5.32.0"
"terser@npm:^5.31.1":
version: 5.46.0
resolution: "terser@npm:5.46.0"
dependencies:
"@jridgewell/source-map": "npm:^0.3.3"
acorn: "npm:^8.8.2"
acorn: "npm:^8.15.0"
commander: "npm:^2.20.0"
source-map-support: "npm:~0.5.20"
bin:
terser: bin/terser
checksum: 10c0/94daae4881258eb7d09abd46378e23d11ee46caa507b2fb26c5595c7e490914be734e0de38c50041dc38fae5fca24de11badf042dfbbfc1d336ed117335c420a
checksum: 10c0/93ad468f13187c4f66b609bbfc00a6aee752007779ca3157f2c1ee063697815748d6010fd449a16c30be33213748431d5f54cc0224ba6a3fbbf5acd3582a4356
languageName: node
linkType: hard
@@ -14395,17 +14450,17 @@ __metadata:
languageName: node
linkType: hard
"update-browserslist-db@npm:^1.1.0":
version: 1.1.0
resolution: "update-browserslist-db@npm:1.1.0"
"update-browserslist-db@npm:^1.2.0":
version: 1.2.3
resolution: "update-browserslist-db@npm:1.2.3"
dependencies:
escalade: "npm:^3.1.2"
picocolors: "npm:^1.0.1"
escalade: "npm:^3.2.0"
picocolors: "npm:^1.1.1"
peerDependencies:
browserslist: ">= 4.21.0"
bin:
update-browserslist-db: cli.js
checksum: 10c0/a7452de47785842736fb71547651c5bbe5b4dc1e3722ccf48a704b7b34e4dcf633991eaa8e4a6a517ffb738b3252eede3773bef673ef9021baa26b056d63a5b9
checksum: 10c0/13a00355ea822388f68af57410ce3255941d5fb9b7c49342c4709a07c9f230bbef7f7499ae0ca7e0de532e79a82cc0c4edbd125f1a323a1845bf914efddf8bec
languageName: node
linkType: hard
@@ -14633,13 +14688,13 @@ __metadata:
languageName: node
linkType: hard
"watchpack@npm:^2.4.1":
version: 2.4.2
resolution: "watchpack@npm:2.4.2"
"watchpack@npm:^2.5.1":
version: 2.5.1
resolution: "watchpack@npm:2.5.1"
dependencies:
glob-to-regexp: "npm:^0.4.1"
graceful-fs: "npm:^4.1.2"
checksum: 10c0/ec60a5f0e9efaeca0102fd9126346b3b2d523e01c34030d3fddf5813a7125765121ebdc2552981136dcd2c852deb1af0b39340f2fcc235f292db5399d0283577
checksum: 10c0/dffbb483d1f61be90dc570630a1eb308581e2227d507d783b1d94a57ac7b705ecd9a1a4b73d73c15eab596d39874e5276a3d9cb88bbb698bafc3f8d08c34cf17
languageName: node
linkType: hard
@@ -14707,46 +14762,48 @@ __metadata:
languageName: node
linkType: hard
"webpack-sources@npm:^3.2.3":
version: 3.2.3
resolution: "webpack-sources@npm:3.2.3"
checksum: 10c0/2ef63d77c4fad39de4a6db17323d75eb92897b32674e97d76f0a1e87c003882fc038571266ad0ef581ac734cbe20952912aaa26155f1905e96ce251adbb1eb4e
"webpack-sources@npm:^3.3.3":
version: 3.3.3
resolution: "webpack-sources@npm:3.3.3"
checksum: 10c0/ab732f6933b513ba4d505130418995ddef6df988421fccf3289e53583c6a39e205c4a0739cee98950964552d3006604912679c736031337fb4a9d78d8576ed40
languageName: node
linkType: hard
"webpack@npm:^5.95.0":
version: 5.95.0
resolution: "webpack@npm:5.95.0"
"webpack@npm:^5.104.1":
version: 5.105.0
resolution: "webpack@npm:5.105.0"
dependencies:
"@types/estree": "npm:^1.0.5"
"@webassemblyjs/ast": "npm:^1.12.1"
"@webassemblyjs/wasm-edit": "npm:^1.12.1"
"@webassemblyjs/wasm-parser": "npm:^1.12.1"
acorn: "npm:^8.7.1"
acorn-import-attributes: "npm:^1.9.5"
browserslist: "npm:^4.21.10"
"@types/eslint-scope": "npm:^3.7.7"
"@types/estree": "npm:^1.0.8"
"@types/json-schema": "npm:^7.0.15"
"@webassemblyjs/ast": "npm:^1.14.1"
"@webassemblyjs/wasm-edit": "npm:^1.14.1"
"@webassemblyjs/wasm-parser": "npm:^1.14.1"
acorn: "npm:^8.15.0"
acorn-import-phases: "npm:^1.0.3"
browserslist: "npm:^4.28.1"
chrome-trace-event: "npm:^1.0.2"
enhanced-resolve: "npm:^5.17.1"
es-module-lexer: "npm:^1.2.1"
enhanced-resolve: "npm:^5.19.0"
es-module-lexer: "npm:^2.0.0"
eslint-scope: "npm:5.1.1"
events: "npm:^3.2.0"
glob-to-regexp: "npm:^0.4.1"
graceful-fs: "npm:^4.2.11"
json-parse-even-better-errors: "npm:^2.3.1"
loader-runner: "npm:^4.2.0"
loader-runner: "npm:^4.3.1"
mime-types: "npm:^2.1.27"
neo-async: "npm:^2.6.2"
schema-utils: "npm:^3.2.0"
tapable: "npm:^2.1.1"
terser-webpack-plugin: "npm:^5.3.10"
watchpack: "npm:^2.4.1"
webpack-sources: "npm:^3.2.3"
schema-utils: "npm:^4.3.3"
tapable: "npm:^2.3.0"
terser-webpack-plugin: "npm:^5.3.16"
watchpack: "npm:^2.5.1"
webpack-sources: "npm:^3.3.3"
peerDependenciesMeta:
webpack-cli:
optional: true
bin:
webpack: bin/webpack.js
checksum: 10c0/b9e6d0f8ebcbf0632494ac0b90fe4acb8f4a9b83f7ace4a67a15545a36fe58599c912ab58e625e1bf58ab3b0916c75fe99da6196d412ee0cab0b5065edd84238
checksum: 10c0/4aea6b976485b5364e122f301c08f48efa84ddb2c0cb5d09f27445d1f2da0b9875cd889e41b58cac3ff05618a9c965be716df52586d151b5f52a7bbed7662174
languageName: node
linkType: hard