mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
12 Commits
roller/chr
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efb3fd98c6 | ||
|
|
9ca9311b73 | ||
|
|
8b05717661 | ||
|
|
be45b5f8e7 | ||
|
|
87597a99de | ||
|
|
3ed52a3ded | ||
|
|
dfdf04976e | ||
|
|
f4ba25a3da | ||
|
|
05061544ab | ||
|
|
10566c2d5f | ||
|
|
931c257de7 | ||
|
|
459a88f788 |
2
.github/actions/build-electron/action.yml
vendored
2
.github/actions/build-electron/action.yml
vendored
@@ -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..."
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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'
|
||||
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -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_
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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**.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 --"
|
||||
],
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
287
script/lint-roller-chromium-changes.mjs
Normal file
287
script/lint-roller-chromium-changes.mjs
Normal 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);
|
||||
});
|
||||
}
|
||||
@@ -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 = [];
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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_; }
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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 {
|
||||
|
||||
/**
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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
221
spec/mas-spec.ts
Normal 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
463
yarn.lock
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user