mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
25 Commits
v35.0.0-be
...
dsanders11
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d35285eaf | ||
|
|
863faea542 | ||
|
|
5aabb6bec5 | ||
|
|
5e05dff949 | ||
|
|
3ea623364b | ||
|
|
cf67dc8898 | ||
|
|
d7b568a1c0 | ||
|
|
fe9031eb23 | ||
|
|
f5eba67f0d | ||
|
|
e1762e6e44 | ||
|
|
9d32b6ddfc | ||
|
|
7a413ff2ad | ||
|
|
0090d171fd | ||
|
|
980b68e9cc | ||
|
|
44a630e634 | ||
|
|
81d12fa452 | ||
|
|
83666ddc36 | ||
|
|
fa5de40f86 | ||
|
|
7d05fb2a1b | ||
|
|
51a249f380 | ||
|
|
90754e5fd2 | ||
|
|
0e5fe3fa60 | ||
|
|
6953f5505f | ||
|
|
45f90cd5dd | ||
|
|
8294f44c74 |
2
.github/workflows/archaeologist-dig.yml
vendored
2
.github/workflows/archaeologist-dig.yml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
sha-file: .dig-old
|
||||
filename: electron.old.d.ts
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b #v4.5.0
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 #v4.6.0
|
||||
with:
|
||||
name: artifacts
|
||||
path: electron/artifacts
|
||||
|
||||
6
.github/workflows/branch-created.yml
vendored
6
.github/workflows/branch-created.yml
vendored
@@ -94,7 +94,7 @@ jobs:
|
||||
}))
|
||||
- name: Create Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/copy-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/copy-project@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
id: create-release-board
|
||||
with:
|
||||
drafts: true
|
||||
@@ -114,14 +114,14 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Find Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/find-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/find-project@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
id: find-prev-release-board
|
||||
with:
|
||||
title: ${{ steps.generate-project-metadata.outputs.prev-prev-major }}-x-y
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Close Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/close-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/close-project@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
project-number: ${{ steps.find-prev-release-board.outputs.number }}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
6
.github/workflows/issue-labeled.yml
vendored
6
.github/workflows/issue-labeled.yml
vendored
@@ -20,12 +20,13 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: ✅ Triaged
|
||||
fail-if-item-not-found: false
|
||||
issue-labeled-blocked:
|
||||
name: blocked/* label added
|
||||
if: startsWith(github.event.label.name, 'blocked/')
|
||||
@@ -38,12 +39,13 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: 🛑 Blocked
|
||||
fail-if-item-not-found: false
|
||||
issue-labeled-blocked-need-repro:
|
||||
name: blocked/need-repro label added
|
||||
if: github.event.label.name == 'blocked/need-repro'
|
||||
|
||||
2
.github/workflows/issue-opened.yml
vendored
2
.github/workflows/issue-opened.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Add to Issue Triage
|
||||
uses: dsanders11/project-actions/add-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/add-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
field: Reporter
|
||||
field-value: ${{ github.event.issue.user.login }}
|
||||
|
||||
5
.github/workflows/issue-transferred.yml
vendored
5
.github/workflows/issue-transferred.yml
vendored
@@ -10,6 +10,7 @@ jobs:
|
||||
issue-transferred:
|
||||
name: Issue Transferred
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ !github.event.changes.new_repository.private }}
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
@@ -18,7 +19,9 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Remove from issue triage
|
||||
uses: dsanders11/project-actions/delete-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/delete-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
item: ${{ github.event.changes.new_issue.html_url }}
|
||||
fail-if-item-not-found: false
|
||||
|
||||
3
.github/workflows/issue-unlabeled.yml
vendored
3
.github/workflows/issue-unlabeled.yml
vendored
@@ -30,9 +30,10 @@ jobs:
|
||||
org: electron
|
||||
- name: Set status
|
||||
if: ${{ steps.check-for-blocked-labels.outputs.NOT_BLOCKED }}
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: 📥 Was Blocked
|
||||
fail-if-item-not-found: false
|
||||
|
||||
@@ -239,7 +239,7 @@ jobs:
|
||||
if: always() && !cancelled()
|
||||
- name: Upload Test Artifacts
|
||||
if: always() && !cancelled()
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08
|
||||
with:
|
||||
name: test_artifacts_${{ env.ARTIFACT_KEY }}_${{ matrix.shard }}
|
||||
path: src/electron/spec/artifacts
|
||||
|
||||
2
.github/workflows/pull-request-labeled.yml
vendored
2
.github/workflows/pull-request-labeled.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
creds: ${{ secrets.RELEASE_BOARD_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 94
|
||||
|
||||
4
.github/workflows/scorecards.yml
vendored
4
.github/workflows/scorecards.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.0
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
@@ -50,6 +50,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
|
||||
uses: github/codeql-action/upload-sarif@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
2
.github/workflows/stable-prep-items.yml
vendored
2
.github/workflows/stable-prep-items.yml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
PROJECT_NUMBER=$(gh project list --owner electron --format json | jq -r '.projects | map(select(.title | test("^[0-9]+-x-y$"))) | max_by(.number) | .number')
|
||||
echo "PROJECT_NUMBER=$PROJECT_NUMBER" >> "$GITHUB_OUTPUT"
|
||||
- name: Update Completed Stable Prep Items
|
||||
uses: dsanders11/project-actions/completed-by@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
uses: dsanders11/project-actions/completed-by@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
with:
|
||||
field: Prep Status
|
||||
field-value: ✅ Complete
|
||||
|
||||
2
.github/workflows/update_appveyor_image.yml
vendored
2
.github/workflows/update_appveyor_image.yml
vendored
@@ -44,7 +44,7 @@ jobs:
|
||||
fi
|
||||
- name: (Optionally) Update Appveyor Image
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
uses: mikefarah/yq@4839dbbf80445070a31c7a9c1055da527db2d5ee # v4.44.6
|
||||
uses: mikefarah/yq@8bf425b4d1344db7cd469a8d10a390876e0c77fd # v4.45.1
|
||||
with:
|
||||
cmd: |
|
||||
yq '.image = "${{ env.APPVEYOR_IMAGE_VERSION }}"' "appveyor.yml" > "appveyor2.yml"
|
||||
|
||||
2
DEPS
2
DEPS
@@ -4,7 +4,7 @@ vars = {
|
||||
'chromium_version':
|
||||
'133.0.6920.0',
|
||||
'node_version':
|
||||
'v22.9.0',
|
||||
'v22.11.0',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -21,7 +21,6 @@ an issue:
|
||||
### Getting started
|
||||
|
||||
* [Introduction](tutorial/introduction.md)
|
||||
* [Quick Start](tutorial/quick-start.md)
|
||||
* [Process Model](tutorial/process-model.md)
|
||||
|
||||
### Learning the basics
|
||||
|
||||
@@ -12,9 +12,17 @@ shortcuts.
|
||||
not have the keyboard focus. This module cannot be used before the `ready`
|
||||
event of the app module is emitted.
|
||||
|
||||
Please also note that it is also possible to use Chromium's
|
||||
`GlobalShortcutsPortal` implementation, which allows apps to bind global
|
||||
shortcuts when running within a Wayland session.
|
||||
|
||||
```js
|
||||
const { app, globalShortcut } = require('electron')
|
||||
|
||||
// Enable usage of Portal's globalShortcuts. This is essential for cases when
|
||||
// the app runs in a Wayland session.
|
||||
app.commandLine.appendSwitch('enable-features', 'GlobalShortcutsPortal')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
// Register a 'CommandOrControl+X' shortcut listener.
|
||||
const ret = globalShortcut.register('CommandOrControl+X', () => {
|
||||
|
||||
@@ -14,7 +14,7 @@ To configure a local keyboard shortcut, you need to specify an [`accelerator`][]
|
||||
property when creating a [MenuItem][] within the [Menu][] module.
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` to be:
|
||||
[tutorial starter code][tutorial-starter-code], update the `main.js` to be:
|
||||
|
||||
```fiddle docs/fiddles/features/keyboard-shortcuts/local
|
||||
const { app, BrowserWindow, Menu, MenuItem } = require('electron/main')
|
||||
@@ -75,7 +75,7 @@ module to detect keyboard events even when the application does not have
|
||||
keyboard focus.
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` to be:
|
||||
[tutorial starter code][tutorial-starter-code], update the `main.js` to be:
|
||||
|
||||
```fiddle docs/fiddles/features/keyboard-shortcuts/global
|
||||
const { app, BrowserWindow, globalShortcut } = require('electron/main')
|
||||
@@ -144,7 +144,7 @@ is emitted before dispatching `keydown` and `keyup` events in the page. It can
|
||||
be used to catch and handle custom shortcuts that are not visible in the menu.
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
[tutorial starter code][tutorial-starter-code], update the `main.js` file with the
|
||||
following lines:
|
||||
|
||||
```fiddle docs/fiddles/features/keyboard-shortcuts/interception-from-main
|
||||
@@ -207,3 +207,4 @@ Mousetrap.bind('up up down down left right left right b a enter', () => {
|
||||
[mousetrap]: https://github.com/ccampbell/mousetrap
|
||||
[dom-events]: https://developer.mozilla.org/en-US/docs/Web/Events
|
||||
[addEventListener-api]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
|
||||
[tutorial-starter-code]: tutorial-2-first-app.md#final-starter-code
|
||||
|
||||
@@ -86,7 +86,7 @@ The main process also controls your application's lifecycle through Electron's
|
||||
that you can use to add custom application behavior (for instance, programmatically
|
||||
quitting your application, modifying the application dock, or showing an About panel).
|
||||
|
||||
As a practical example, the app shown in the [quick start guide][quick-start-lifecycle]
|
||||
As a practical example, the app shown in the [tutorial starter code][tutorial-lifecycle]
|
||||
uses `app` APIs to create a more native application window experience.
|
||||
|
||||
```js title='main.js'
|
||||
@@ -97,7 +97,7 @@ app.on('window-all-closed', () => {
|
||||
```
|
||||
|
||||
[app]: ../api/app.md
|
||||
[quick-start-lifecycle]: ../tutorial/quick-start.md#manage-your-windows-lifecycle
|
||||
[tutorial-lifecycle]: ../tutorial/tutorial-2-first-app.md#quit-the-app-when-all-windows-are-closed-windows--linux
|
||||
|
||||
### Native APIs
|
||||
|
||||
|
||||
@@ -1,513 +0,0 @@
|
||||
# Quick Start
|
||||
|
||||
This guide will step you through the process of creating a barebones Hello World app in
|
||||
Electron, similar to [`electron/electron-quick-start`][quick-start].
|
||||
|
||||
By the end of this tutorial, your app will open a browser window that displays a web page
|
||||
with information about which Chromium, Node.js, and Electron versions are running.
|
||||
|
||||
[quick-start]: https://github.com/electron/electron-quick-start
|
||||
|
||||
## Prerequisites
|
||||
|
||||
To use Electron, you need to install [Node.js][node-download]. We recommend that you
|
||||
use the latest `LTS` version available.
|
||||
|
||||
> Please install Node.js using pre-built installers for your platform.
|
||||
> You may encounter incompatibility issues with different development tools otherwise.
|
||||
|
||||
To check that Node.js was installed correctly, type the following commands in your
|
||||
terminal client:
|
||||
|
||||
```sh
|
||||
node -v
|
||||
npm -v
|
||||
```
|
||||
|
||||
The commands should print the versions of Node.js and npm accordingly.
|
||||
|
||||
**Note:** Since Electron embeds Node.js into its binary, the version of Node.js running
|
||||
your code is unrelated to the version running on your system.
|
||||
|
||||
[node-download]: https://nodejs.org/en/download/
|
||||
|
||||
## Create your application
|
||||
|
||||
### Scaffold the project
|
||||
|
||||
Electron apps follow the same general structure as other Node.js projects.
|
||||
Start by creating a folder and initializing an npm package.
|
||||
|
||||
```sh npm2yarn
|
||||
mkdir my-electron-app && cd my-electron-app
|
||||
npm init
|
||||
```
|
||||
|
||||
The interactive `init` command will prompt you to set some fields in your config.
|
||||
There are a few rules to follow for the purposes of this tutorial:
|
||||
|
||||
* `entry point` should be `main.js`.
|
||||
* `author` and `description` can be any value, but are necessary for
|
||||
[app packaging](#package-and-distribute-your-application).
|
||||
|
||||
Your `package.json` file should look something like this:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-electron-app",
|
||||
"version": "1.0.0",
|
||||
"description": "Hello World!",
|
||||
"main": "main.js",
|
||||
"author": "Jane Doe",
|
||||
"license": "MIT"
|
||||
}
|
||||
```
|
||||
|
||||
Then, install the `electron` package into your app's `devDependencies`.
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev electron
|
||||
```
|
||||
|
||||
> Note: If you're encountering any issues with installing Electron, please
|
||||
> refer to the [Advanced Installation][advanced-installation] guide.
|
||||
|
||||
Finally, you want to be able to execute Electron. In the [`scripts`][package-scripts]
|
||||
field of your `package.json` config, add a `start` command like so:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"start": "electron ."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This `start` command will let you open your app in development mode.
|
||||
|
||||
```sh npm2yarn
|
||||
npm start
|
||||
```
|
||||
|
||||
> Note: This script tells Electron to run on your project's root folder. At this stage,
|
||||
> your app will immediately throw an error telling you that it cannot find an app to run.
|
||||
|
||||
[advanced-installation]: ./installation.md
|
||||
[package-scripts]: https://docs.npmjs.com/cli/v7/using-npm/scripts
|
||||
|
||||
### Run the main process
|
||||
|
||||
The entry point of any Electron application is its `main` script. This script controls the
|
||||
**main process**, which runs in a full Node.js environment and is responsible for
|
||||
controlling your app's lifecycle, displaying native interfaces, performing privileged
|
||||
operations, and managing renderer processes (more on that later).
|
||||
|
||||
During execution, Electron will look for this script in the [`main`][package-json-main]
|
||||
field of the app's `package.json` config, which you should have configured during the
|
||||
[app scaffolding](#scaffold-the-project) step.
|
||||
|
||||
To initialize the `main` script, create an empty file named `main.js` in the root folder
|
||||
of your project.
|
||||
|
||||
> Note: If you run the `start` script again at this point, your app will no longer throw
|
||||
> any errors! However, it won't do anything yet because we haven't added any code into
|
||||
> `main.js`.
|
||||
|
||||
[package-json-main]: https://docs.npmjs.com/cli/v7/configuring-npm/package-json#main
|
||||
|
||||
### Create a web page
|
||||
|
||||
Before we can create a window for our application, we need to create the content that
|
||||
will be loaded into it. In Electron, each window displays web contents that can be loaded
|
||||
from either a local HTML file or a remote URL.
|
||||
|
||||
For this tutorial, you will be doing the former. Create an `index.html` file in the root
|
||||
folder of your project:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
We are using Node.js <span id="node-version"></span>,
|
||||
Chromium <span id="chrome-version"></span>,
|
||||
and Electron <span id="electron-version"></span>.
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
> Note: Looking at this HTML document, you can observe that the version numbers are
|
||||
> missing from the body text. We'll manually insert them later using JavaScript.
|
||||
|
||||
### Opening your web page in a browser window
|
||||
|
||||
Now that you have a web page, load it into an application window. To do so, you'll
|
||||
need two Electron modules:
|
||||
|
||||
* The [`app`][app] module, which controls your application's event lifecycle.
|
||||
* The [`BrowserWindow`][browser-window] module, which creates and manages application
|
||||
windows.
|
||||
|
||||
Because the main process runs Node.js, you can import these as [CommonJS][commonjs]
|
||||
modules at the top of your `main.js` file:
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
```
|
||||
|
||||
Then, add a `createWindow()` function that loads `index.html` into a new `BrowserWindow`
|
||||
instance.
|
||||
|
||||
```js
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
```
|
||||
|
||||
Next, call this `createWindow()` function to open your window.
|
||||
|
||||
In Electron, browser windows can only be created after the `app` module's
|
||||
[`ready`][app-ready] event is fired. You can wait for this event by using the
|
||||
[`app.whenReady()`][app-when-ready] API. Call `createWindow()` after `whenReady()`
|
||||
resolves its Promise.
|
||||
|
||||
```js @ts-type={createWindow:()=>void}
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
```
|
||||
|
||||
> Note: At this point, your Electron application should successfully
|
||||
> open a window that displays your web page!
|
||||
|
||||
[app]: ../api/app.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[commonjs]: https://nodejs.org/docs/latest/api/modules.html#modules_modules_commonjs_modules
|
||||
[app-ready]: ../api/app.md#event-ready
|
||||
[app-when-ready]: ../api/app.md#appwhenready
|
||||
|
||||
### Manage your window's lifecycle
|
||||
|
||||
Although you can now open a browser window, you'll need some additional boilerplate code
|
||||
to make it feel more native to each platform. Application windows behave differently on
|
||||
each OS, and Electron puts the responsibility on developers to implement these
|
||||
conventions in their app.
|
||||
|
||||
In general, you can use the `process` global's [`platform`][node-platform] attribute
|
||||
to run code specifically for certain operating systems.
|
||||
|
||||
#### Quit the app when all windows are closed (Windows & Linux)
|
||||
|
||||
On Windows and Linux, exiting all windows generally quits an application entirely.
|
||||
|
||||
To implement this, listen for the `app` module's [`'window-all-closed'`][window-all-closed]
|
||||
event, and call [`app.quit()`][app-quit] if the user is not on macOS (`darwin`).
|
||||
|
||||
```js
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
```
|
||||
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
[window-all-closed]: ../api/app.md#event-window-all-closed
|
||||
[app-quit]: ../api/app.md#appquit
|
||||
|
||||
#### Open a window if none are open (macOS)
|
||||
|
||||
Whereas Linux and Windows apps quit when they have no windows open, macOS apps generally
|
||||
continue running even without any windows open, and activating the app when no windows
|
||||
are available should open a new one.
|
||||
|
||||
To implement this feature, listen for the `app` module's [`activate`][activate]
|
||||
event, and call your existing `createWindow()` method if no browser windows are open.
|
||||
|
||||
Because windows cannot be created before the `ready` event, you should only listen for
|
||||
`activate` events after your app is initialized. Do this by attaching your event listener
|
||||
from within your existing `whenReady()` callback.
|
||||
|
||||
[activate]: ../api/app.md#event-activate-macos
|
||||
|
||||
```js @ts-type={createWindow:()=>void}
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
> Note: At this point, your window controls should be fully functional!
|
||||
|
||||
### Access Node.js from the renderer with a preload script
|
||||
|
||||
Now, the last thing to do is print out the version numbers for Electron and its
|
||||
dependencies onto your web page.
|
||||
|
||||
Accessing this information is trivial to do in the main process through Node's
|
||||
global `process` object. However, you can't just edit the DOM from the main
|
||||
process because it has no access to the renderer's `document` context.
|
||||
They're in entirely different processes!
|
||||
|
||||
> Note: If you need a more in-depth look at Electron processes, see the
|
||||
> [Process Model][] document.
|
||||
|
||||
This is where attaching a **preload** script to your renderer comes in handy.
|
||||
A preload script runs before the renderer process is loaded, and has access to both
|
||||
renderer globals (e.g. `window` and `document`) and a Node.js environment.
|
||||
|
||||
Create a new script named `preload.js` as such:
|
||||
|
||||
```js
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const replaceText = (selector, text) => {
|
||||
const element = document.getElementById(selector)
|
||||
if (element) element.innerText = text
|
||||
}
|
||||
|
||||
for (const dependency of ['chrome', 'node', 'electron']) {
|
||||
replaceText(`${dependency}-version`, process.versions[dependency])
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
The above code accesses the Node.js `process.versions` object and runs a basic `replaceText`
|
||||
helper function to insert the version numbers into the HTML document.
|
||||
|
||||
To attach this script to your renderer process, pass in the path to your preload script
|
||||
to the `webPreferences.preload` option in your existing `BrowserWindow` constructor.
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
// include the Node.js 'path' module at the top of your file
|
||||
const path = require('node:path')
|
||||
|
||||
// modify your existing createWindow() function
|
||||
const createWindow = () => {
|
||||
const win = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
win.loadFile('index.html')
|
||||
}
|
||||
// ...
|
||||
```
|
||||
|
||||
There are two Node.js concepts that are used here:
|
||||
|
||||
* The [`__dirname`][dirname] string points to the path of the currently executing script
|
||||
(in this case, your project's root folder).
|
||||
* The [`path.join`][path-join] API joins multiple path segments together, creating a
|
||||
combined path string that works across all platforms.
|
||||
|
||||
We use a path relative to the currently executing JavaScript file so that your relative
|
||||
path will work in both development and packaged mode.
|
||||
|
||||
[Process Model]: ./process-model.md
|
||||
[dirname]: https://nodejs.org/api/modules.html#modules_dirname
|
||||
[path-join]: https://nodejs.org/api/path.html#path_path_join_paths
|
||||
|
||||
### Bonus: Add functionality to your web contents
|
||||
|
||||
At this point, you might be wondering how to add more functionality to your application.
|
||||
|
||||
For any interactions with your web contents, you want to add scripts to your
|
||||
renderer process. Because the renderer runs in a normal web environment, you can add a
|
||||
`<script>` tag right before your `index.html` file's closing `</body>` tag to include
|
||||
any arbitrary scripts you want:
|
||||
|
||||
```html
|
||||
<script src="./renderer.js"></script>
|
||||
```
|
||||
|
||||
The code contained in `renderer.js` can then use the same JavaScript APIs and tooling
|
||||
you use for typical front-end development, such as using [`webpack`][webpack] to bundle
|
||||
and minify your code or [React][react] to manage your user interfaces.
|
||||
|
||||
[webpack]: https://webpack.js.org
|
||||
[react]: https://reactjs.org
|
||||
|
||||
### Recap
|
||||
|
||||
After following the above steps, you should have a fully functional
|
||||
Electron application that looks like this:
|
||||
|
||||

|
||||
|
||||
<!--TODO(erickzhao): Remove the individual code blocks for static website -->
|
||||
The full code is available below:
|
||||
|
||||
```js
|
||||
// main.js
|
||||
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
const createWindow = () => {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', () => {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
```
|
||||
|
||||
```js
|
||||
// preload.js
|
||||
|
||||
// All the Node.js APIs are available in the preload process.
|
||||
// It has the same sandbox as a Chrome extension.
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const replaceText = (selector, text) => {
|
||||
const element = document.getElementById(selector)
|
||||
if (element) element.innerText = text
|
||||
}
|
||||
|
||||
for (const dependency of ['chrome', 'node', 'electron']) {
|
||||
replaceText(`${dependency}-version`, process.versions[dependency])
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!--index.html-->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Hello World!</h1>
|
||||
We are using Node.js <span id="node-version"></span>,
|
||||
Chromium <span id="chrome-version"></span>,
|
||||
and Electron <span id="electron-version"></span>.
|
||||
|
||||
<!-- You can also require other files to run in this process -->
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
```fiddle docs/fiddles/quick-start
|
||||
```
|
||||
|
||||
To summarize all the steps we've done:
|
||||
|
||||
* We bootstrapped a Node.js application and added Electron as a dependency.
|
||||
* We created a `main.js` script that runs our main process, which controls our app
|
||||
and runs in a Node.js environment. In this script, we used Electron's `app` and
|
||||
`BrowserWindow` modules to create a browser window that displays web content
|
||||
in a separate process (the renderer).
|
||||
* In order to access certain Node.js functionality in the renderer, we attached
|
||||
a preload script to our `BrowserWindow` constructor.
|
||||
|
||||
## Package and distribute your application
|
||||
|
||||
The fastest way to distribute your newly created app is using
|
||||
[Electron Forge](https://www.electronforge.io).
|
||||
|
||||
:::info
|
||||
|
||||
To build an RPM package for Linux, you will need to [install its required system dependencies](https://www.electronforge.io/config/makers/rpm).
|
||||
|
||||
:::
|
||||
|
||||
1. Add a description to your `package.json` file, otherwise rpmbuild will fail. Blank description are not valid.
|
||||
2. Add Electron Forge as a development dependency of your app, and use its `import` command to set up
|
||||
Forge's scaffolding:
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @electron-forge/cli
|
||||
npx electron-forge import
|
||||
|
||||
✔ Checking your system
|
||||
✔ Initializing Git Repository
|
||||
✔ Writing modified package.json file
|
||||
✔ Installing dependencies
|
||||
✔ Writing modified package.json file
|
||||
✔ Fixing .gitignore
|
||||
|
||||
We have ATTEMPTED to convert your app to be in a format that electron-forge understands.
|
||||
|
||||
Thanks for using "electron-forge"!!!
|
||||
```
|
||||
|
||||
3. Create a distributable using Forge's `make` command:
|
||||
|
||||
```sh npm2yarn
|
||||
npm run make
|
||||
|
||||
> my-electron-app@1.0.0 make /my-electron-app
|
||||
> electron-forge make
|
||||
|
||||
✔ Checking your system
|
||||
✔ Resolving Forge Config
|
||||
We need to package your application before we can make it
|
||||
✔ Preparing to Package Application for arch: x64
|
||||
✔ Preparing native dependencies
|
||||
✔ Packaging Application
|
||||
Making for the following targets: zip
|
||||
✔ Making for target: zip - On platform: darwin - For arch: x64
|
||||
```
|
||||
|
||||
Electron Forge creates the `out` folder where your package will be located:
|
||||
|
||||
```plain
|
||||
// Example for macOS
|
||||
out/
|
||||
├── out/make/zip/darwin/x64/my-electron-app-darwin-x64-1.0.0.zip
|
||||
├── ...
|
||||
└── out/my-electron-app-darwin-x64/my-electron-app.app/Contents/MacOS/my-electron-app
|
||||
```
|
||||
@@ -1,17 +0,0 @@
|
||||
# Window Customization
|
||||
|
||||
The [`BrowserWindow`][] module is the foundation of your Electron application, and
|
||||
it exposes many APIs that let you customize the look and behavior of your app’s windows.
|
||||
This section covers how to implement various use cases for window customization on macOS,
|
||||
Windows, and Linux.
|
||||
|
||||
:::info
|
||||
`BrowserWindow` is a subclass of the [`BaseWindow`][] module. Both modules allow
|
||||
you to create and manage application windows in Electron, with the main difference
|
||||
being that `BrowserWindow` supports a single, full size web view while `BaseWindow`
|
||||
supports composing many web views. `BaseWindow` can be used interchangeably with `BrowserWindow`
|
||||
in the examples of the documents in this section.
|
||||
:::
|
||||
|
||||
[`BaseWindow`]: ../api/base-window.md
|
||||
[`BrowserWindow`]: ../api/browser-window.md
|
||||
21
docs/tutorial/window-customization.mdx
Normal file
21
docs/tutorial/window-customization.mdx
Normal file
@@ -0,0 +1,21 @@
|
||||
import DocCardList from '@theme/DocCardList';
|
||||
|
||||
# Window Customization
|
||||
|
||||
The [`BrowserWindow`][] module is the foundation of your Electron application, and
|
||||
it exposes many APIs that let you customize the look and behavior of your app’s windows.
|
||||
This section covers how to implement various use cases for window customization on macOS,
|
||||
Windows, and Linux.
|
||||
|
||||
> [!NOTE]
|
||||
> `BrowserWindow` is a subclass of the [`BaseWindow`][] module. Both modules allow
|
||||
> you to create and manage application windows in Electron, with the main difference
|
||||
> being that `BrowserWindow` supports a single, full size web view while `BaseWindow`
|
||||
> supports composing many web views. `BaseWindow` can be used interchangeably with `BrowserWindow`
|
||||
> in the examples of the documents in this section.
|
||||
|
||||
<!-- markdownlint-disable-next-line MD033 -->
|
||||
<DocCardList />
|
||||
|
||||
[`BaseWindow`]: ../api/base-window.md
|
||||
[`BrowserWindow`]: ../api/browser-window.md
|
||||
@@ -8,7 +8,7 @@ If your app doesn't use any native modules, then it's really easy to create an A
|
||||
|
||||
1. Make sure that your app's `node_modules` directory is empty.
|
||||
2. Using a _Command Prompt_, run `set npm_config_arch=arm64` before running `npm install`/`yarn install` as usual.
|
||||
3. [If you have Electron installed as a development dependency](quick-start.md#prerequisites), npm will download and unpack the arm64 version. You can then package and distribute your app as normal.
|
||||
3. [If you have Electron installed as a development dependency](tutorial-2-first-app.md#initializing-your-npm-project), npm will download and unpack the arm64 version. You can then package and distribute your app as normal.
|
||||
|
||||
## General considerations
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ To set user tasks for your application, you can use
|
||||
##### Set user tasks
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
[tutorial starter code][tutorial-starter-code], update the `main.js` file with the
|
||||
following lines:
|
||||
|
||||
```js
|
||||
@@ -121,7 +121,7 @@ To set thumbnail toolbar in your application, you need to use
|
||||
##### Set thumbnail toolbar
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
[tutorial starter code][tutorial-starter-code], update the `main.js` file with the
|
||||
following lines:
|
||||
|
||||
```js
|
||||
@@ -185,7 +185,7 @@ To set the overlay icon for a window, you need to use the
|
||||
#### Example
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
[tutorial starter code][tutorial-starter-code], update the `main.js` file with the
|
||||
following lines:
|
||||
|
||||
```js
|
||||
@@ -214,7 +214,7 @@ To flash the BrowserWindow taskbar button, you need to use the
|
||||
#### Example
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the
|
||||
[tutorial starter code][tutorial-starter-code], update the `main.js` file with the
|
||||
following lines:
|
||||
|
||||
```js
|
||||
@@ -231,10 +231,10 @@ In the above example, it is called when the window comes into focus,
|
||||
but you might use a timeout or some other event to disable it.
|
||||
|
||||
[msdn-flash-frame]: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-flashwindow#remarks
|
||||
|
||||
[setthumbarbuttons]: ../api/browser-window.md#winsetthumbarbuttonsbuttons-windows
|
||||
[setusertaskstasks]: ../api/app.md#appsetusertaskstasks-windows
|
||||
[setoverlayicon]: ../api/browser-window.md#winsetoverlayiconoverlay-description-windows
|
||||
[flashframe]: ../api/browser-window.md#winflashframeflag
|
||||
[recent-documents]: ./recent-documents.md
|
||||
[progress-bar]: ./progress-bar.md
|
||||
[tutorial-starter-code]: ../tutorial/tutorial-2-first-app.md#final-starter-code
|
||||
|
||||
103
docs/why-electron.md
Normal file
103
docs/why-electron.md
Normal file
@@ -0,0 +1,103 @@
|
||||
# Why Electron
|
||||
|
||||
Electron is a framework enabling developers to build cross-platform desktop applications for macOS, Windows, and Linux by combining web technologies (HTML, JavaScript, CSS) with Node.js and native code. It is open-source, MIT-licensed, and free for both commercial and personal use. In this document, we’ll explain why companies and developers choose Electron.
|
||||
|
||||
We can split up the benefits of Electron in two questions: First, why should you use web technologies to build your application? Then, why should you choose Electron as the framework to do so?
|
||||
|
||||
If you’re already using web technologies for your application, you can skip straight to the `Why Electron?` section below.
|
||||
|
||||
## Why choose web technologies
|
||||
|
||||
Web technologies include HTML, CSS, JavaScript, and WebAssembly. They’re the storefront of the modern Internet. Those technologies have emerged as the best choice for building user interfaces — both for consumer applications as well as mission-critical business applications. This is true both for applications that need to run in a browser as well as desktop applications that are not accessible from a browser. Our bold claim here is that this isn’t just true for cross-platform applications that need to run on multiple operating systems but true overall.
|
||||
|
||||
As an example, NASA’s actual [Mission Control](https://github.com/nasa/openmct) is written with web technologies. The [Bloomberg Terminal](https://en.wikipedia.org/wiki/Bloomberg_Terminal), the computer system found at every financial institution, is written with web technologies and runs inside Chromium. It costs $25,000 per user, per year. The McDonald’s ordering kiosk, powering the world’s biggest food retailer, is entirely built with Chromium. The [SpaceX’s Dragon 2 space capsule](https://old.reddit.com/r/spacex/comments/gxb7j1/we_are_the_spacex_software_team_ask_us_anything/ft62781/?context=3) uses Chromium to display its interface. You get the point: web technologies are a great tech stack to build user interfaces.
|
||||
|
||||
Here are the reasons we, the Electron maintainers, are betting on the web.
|
||||
|
||||
### Versatility
|
||||
|
||||
Modern versions of HTML and CSS enable your developers and designers to fully express themselves. The web’s showcase includes Google Earth, Netflix, Spotify, Gmail, Facebook, Airbnb, or GitHub. Whatever interface your application needs, you will be able to express it with HTML, CSS, and JavaScript.
|
||||
|
||||
If you want to focus on building a great product without figuring out how you can realize your designer’s vision in a specific UI framework, the web is a safe bet.
|
||||
|
||||
### Reliability
|
||||
|
||||
Web technologies are the most-used foundation for user interfaces on the planet. The have been hardened accordingly. Modern computers have been optimized from the CPU to the operating system to be good at running web technologies. The manufacturers of your user’s devices—be that an Android phone or the latest MacBook—will ensure that they can visit websites, play videos on YouTube, or display emails. In turn, they’ll also ensure that your app has a stable foundation, even if you have just one user.
|
||||
|
||||
If you want to focus on building a great product without debugging a weird quirk that nobody has found before, the web is a safe bet.
|
||||
|
||||
### Interoperability
|
||||
|
||||
Whatever provider or customer data you need to interact with, they will have probably thought of an integration path with the web. Depending on your technology choice, embedding a YouTube video either takes 30 seconds or requires you to hire a team devoted to streaming and hardware-accelerated video decoding. In the case of YouTube, using anything other than the provided players is actually against their terms and conditions, so you’ll likely embed a browser frame before you implement your own video streaming decoder.
|
||||
|
||||
There will be virtually no platform where your app cannot run if you build it with web technologies. Virtually all devices with a display—be that an ATM, a car infotainment system, a smart TV, a fridge, or a Nintendo Switch—come with means to display web technologies. The web is safe bet if you want to be cross-platform.
|
||||
|
||||
### Ubiquity
|
||||
|
||||
It’s easy to find developers with experience building with web technologies. If you’re a developer, it’ll be easy to find answers to your questions on Google, Stack Overflow, GitHub, or a coding AI of your choice. Whatever problem you need to solve, it’s likely that somebody has solved it well before—and that you can find the answer to the puzzle online.
|
||||
|
||||
If you want to focus on building a great product with ample access to resources and materials, the web is a safe bet.
|
||||
|
||||
## Why choose Electron
|
||||
|
||||
Electron combines Chromium, Node.js, and the ability to write custom native code into one framework for building powerful desktop applications. There are three main reasons to use Electron:
|
||||
|
||||
### Enterprise-grade
|
||||
|
||||
Electron is reliable, secure, stable, and mature. It is the premier choice for companies building their flagship product. We have a list of some of those companies on our homepage, but just among chat apps, Slack, Discord, and Skype are built with Electron. Among AI applications, both OpenAI’s ChatGPT and Anthropic’s Claude use Electron. Visual Studio Code, Loom, Canva, Notion, Docker, and countless other leading developers of software bet on Electron.
|
||||
|
||||
We did make it a priority to make Electron easy to work with and a delight for developers. That’s likely the main reason why Electron became as popular as it is today — but what keeps Electron alive and thriving is the maintainer’s focus on making Electron as stable, secure, performant, and capable of mission-critical use cases for end users as possible. We’re building an Electron that is ready to be used in scenarios where unfixable bugs, unpatched security holes, and outages of any kind are worst-case scenarios.
|
||||
|
||||
### Mature
|
||||
|
||||
Our current estimation is that most desktop computers on the planet run at least one Electron app. Electron has grown by prioritizing talent in its maintainer group, fostering excellent and sustainable engineering practices in managing the ongoing maintenance, and proactively inviting companies betting on Electron to directly contribute to the project. We’re an impact project with the OpenJS foundation, which is itself a part of the Linux foundation. We share resources and expertise with other foundation projects like Node.js, ESLint, Webpack - or the Linux Kernel or Kubernetes.
|
||||
|
||||
What does all of that mean for you, a developer, in practice?
|
||||
|
||||
- **Reliable release schedule**: Electron will release a new major version in lockstep with every second major Chromium release, usually on the same day as Chromium. A lot of work, both in the form of building processes and tools, but also in terms of raw invested hours every week, has to go into making that happen.
|
||||
- **No dictators**: Sometimes, betting on a technology also requires you to bet on a single person or company. In turn, it requires you to trust that the person or company never has a breakdown, starts fighting you directly, or does anything else drastic that’ll force you rethink your entire tech stack. Electron is maintained by a diverse set of companies (Microsoft, Slack/Salesforce, Notion, and more) and will continue to welcome more companies interested in ensuring their “seat at the decision-making table”.
|
||||
|
||||
### Stability, security, performance
|
||||
|
||||
Electron delivers the best experience on all target platforms (macOS, Windows, Linux) by bundling the latest version of Chromium, V8, and Node.js directly with the application binary. When it comes to running and rendering web content with upmost stability, security, and performance, we currently believe that stack to be “best in class”.
|
||||
|
||||
#### Why bundle anything at all
|
||||
|
||||
You might wonder why we bundle Chromium’s web stack with our apps when most modern operating systems already ship a browser and some form of web view. Bundling doesn’t just increase the amount of work for Electron maintainers dramatically, it also increases the total disk size of Electron apps (most apps are >100MB). Many Electron maintainers once developed applications that did make use of embedded web views — and have since accepted the increased disk size and maintainer work as a worthy trade-off.
|
||||
|
||||
When using an operating system's built-in web view, you're limited by the browser version included in the oldest operating system version you need to support. We have found the following problems with this approach:
|
||||
|
||||
- **Stability**: The modern web technology stack is complex, and as a result, you’ll sooner or later encounter bugs. If you use the operating system’s web view, your only recourse will be to ask your customers to upgrade their operating system. If no upgrade is available for that machine (because of no ability to upgrade to the latest macOS or Windows 11), you’ll have to ask them to buy a new computer. If you’re unlucky, you’re now losing a major customer because they will not upgrade their entire fleet of thousands of machines just because one team wanted to try your startup’s app. You have _no recourse_ in this situation. Even the risk of that happening is unacceptable to the companies that employ the Electron maintainers.
|
||||
- **Security:** Similar to how you can fix stability bugs by releasing an app update, you can also release security fixes to your application without asking your customer to upgrade their operating system. Even if operating system providers prioritize updates to their built-in browser, we have not seen them reliably update the built-in web views with similar urgency. Bundling a web renderer gives you, the developer, control.
|
||||
- **Performance:** For simple HTML documents, a built-in web view will sometimes use fewer resources than an app with a bundled framework. For bigger apps, it is our experience that we can deliver better performance with the latest version of Chromium than we can with built-in web views. You might think that the built-in view can share a lot of resources with other apps and the operating system— but for security reasons, apps have to run in their own sandboxes, isolated from each other. At that point, the question is whether the OS’ web view is more performant than Chromium. Across many apps, our experience is that bundling Chromium and Node.js enables us to build better and more performant experiences.
|
||||
|
||||
#### Why bundle Chromium and Node.js
|
||||
|
||||
Electron aims to enable the apps it supports to deliver the best possible user experience, followed by the best possible developer experience. Chromium is currently the best cross-platform rendering stack available. Node.js uses Chromium’s JavaScript engine V8, allowing us to combine the powers of both.
|
||||
|
||||
- **Native code when you want it**: Thanks to Node.js’ mature native addon system, you can always write native code. There is no system API out of reach for you. Whatever macOS, Windows, or Linux feature you’ll want to integrate with —as long as you can do it in C, C++, Objective-C, Rust, or another native language, you’ll be able to do it in Electron. Again, this gives you, the developer, maximum control. With Electron, you can use web technologies without choosing _only_ web technologies.
|
||||
|
||||
### Developer experience
|
||||
|
||||
To summarize, we aim to build an Electron that is mature, enterprise-grade, and ready for mission-critical applications. We prioritize reliability, stability, security, and performance. That said, you might also choose Electron for its developer experience:
|
||||
|
||||
- **Powerful ecosystem**: Anything you find on npm will run inside Electron. Any resource available to you about how to work with Node.js also applies to Electron. In addition, Electron itself has a [thriving ecosystem](https://www.npmjs.com/search?q=electron) — including plenty of choices for installers, updaters, deeper operating system-integration, and more.
|
||||
- **Plenty of built-in capabilities:** Over the last ten years, Electron’s core has gained plenty of native capabilities that you might need to build your application. Written in C++ and Objective-C, Electron has [dozens of easy-to-use APIs for deeper operating-system integration](https://www.electronjs.org/docs/latest/api/app) — like advanced window customization for transparent or oddly shaped widgets, receiving push notifications from the Apple Push Notification Network, or handling a custom URL protocol for your app.
|
||||
- **Open source**: The entire stack is open source and open to your inspection. This ensures your freedom to add any feature or fix any bug you might encounter in the future.
|
||||
- **Native code when you need it:** It bears repeating that Electron allows you to mix and match web technologies and C++, C, Objective-C, Rust, and other native languages. Whether it be SQLite, a whole LLM, or just the ability to call one specific native API, Electron will make it easy.
|
||||
|
||||
---
|
||||
|
||||
## Why choose something else
|
||||
|
||||
As outlined above, the web is an amazing platform for building interfaces. That doesn’t mean that we, the maintainers, would build _everything_ with HTML and CSS. Here are some notable exceptions:
|
||||
|
||||
**Resource-Constrained Environments and IoT:** In scenarios with very limited memory or processing power (say, one megabyte of memory and 100MHz of processing power on a low-powered ARM Cortex-M), you will likely need to use a low-level language to directly talk to the display to output basic text and images. Even on slightly higher-powered single-chip devices you might want to consider an embedded UI framework. A classic example is a smart watch.
|
||||
|
||||
**Small Disk Footprint**: Zipped Electron apps are usually around 80 to 100 Megabytes. If a smaller disk footprint is a hard requirement, you’ll have to use something else.
|
||||
|
||||
**Operating System UI Frameworks and Libraries**: By allowing you to write native code, Electron can do anything a native application can do, including the use of the operating system’s UI components, like WinUI, SwiftUI, or AppKit. In practice, most Electron apps make rare use of that ability. If you want the majority of your app to be built with operating system-provided interface components, you’ll likely be better off building fully native apps for each operating system you’d like to target. It’s not that it’s impossible with Electron, it’ll just likely be an overall easier development process.
|
||||
|
||||
**Games and Real-Time Graphics:** If you're building a high-performance game or application requiring complex real-time 3D graphics, native frameworks like Unity, Unreal Engine, or DirectX/OpenGL will provide better performance and more direct access to graphics hardware. Web fans might point out caveats, like the fact that even Unreal Engine ships with Chromium — or that WebGPU and WebGL are developing rapidly and many game engines, including the ones listed here, can now output their games in a format that runs in a browser. That said, if you asked us to build the next AAA game, we’d likely use something else than just web technologies.
|
||||
|
||||
**Embedding Lightweight Websites**: Electron apps typically are mostly web apps with native code sprinkled in where useful. Processing-heavy Electron applications tend to write the UI in HTML/CSS and build the backend in Rust, C++, or another native language. If you’re planning to build a primarily native application that also wants to display a little website in a specific view, you might be better off using the OS-provided web view or something like [ultralight](https://ultralig.ht/).
|
||||
@@ -159,12 +159,8 @@ filenames = {
|
||||
"shell/browser/osr/osr_web_contents_view_mac.mm",
|
||||
"shell/browser/relauncher_mac.cc",
|
||||
"shell/browser/ui/certificate_trust_mac.mm",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.h",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.mm",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.h",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.mm",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.h",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.mm",
|
||||
"shell/browser/ui/cocoa/electron_native_widget_mac.h",
|
||||
@@ -191,8 +187,6 @@ filenames = {
|
||||
"shell/browser/ui/cocoa/window_buttons_proxy.mm",
|
||||
"shell/browser/ui/drag_util_mac.mm",
|
||||
"shell/browser/ui/file_dialog_mac.mm",
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.h",
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.mm",
|
||||
"shell/browser/ui/message_box_mac.mm",
|
||||
"shell/browser/ui/tray_icon_cocoa.h",
|
||||
"shell/browser/ui/tray_icon_cocoa.mm",
|
||||
@@ -224,8 +218,6 @@ filenames = {
|
||||
"shell/browser/ui/views/electron_views_delegate.h",
|
||||
"shell/browser/ui/views/frameless_view.cc",
|
||||
"shell/browser/ui/views/frameless_view.h",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.cc",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.h",
|
||||
"shell/browser/ui/views/menu_bar.cc",
|
||||
"shell/browser/ui/views/menu_bar.h",
|
||||
"shell/browser/ui/views/menu_delegate.cc",
|
||||
|
||||
@@ -871,9 +871,9 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
const binding = internalBinding('fs');
|
||||
|
||||
const { internalModuleStat } = binding;
|
||||
internalBinding('fs').internalModuleStat = (pathArgument: string) => {
|
||||
internalBinding('fs').internalModuleStat = (receiver: unknown, pathArgument: string) => {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return internalModuleStat(pathArgument);
|
||||
if (!pathInfo.isAsar) return internalModuleStat(receiver, pathArgument);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
|
||||
// -ENOENT
|
||||
@@ -908,7 +908,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
if (withFileTypes) {
|
||||
initialItem = [
|
||||
[...initialItem], initialItem.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(originalPath, p));
|
||||
return internalBinding('fs').internalModuleStat(binding, path.join(originalPath, p));
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -941,7 +941,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
|
||||
readdirResult = [
|
||||
[...files], files.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(direntPath, p));
|
||||
return internalBinding('fs').internalModuleStat(binding, path.join(direntPath, p));
|
||||
})
|
||||
];
|
||||
} else {
|
||||
@@ -962,7 +962,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
const { 0: pathArg, 1: readDir } = queue.pop();
|
||||
for (const ent of readDir) {
|
||||
const direntPath = path.join(pathArg, ent);
|
||||
const stat = internalBinding('fs').internalModuleStat(direntPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(binding, direntPath);
|
||||
result.push(path.relative(originalPath, direntPath));
|
||||
|
||||
if (stat === 1) {
|
||||
@@ -1014,7 +1014,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
if (withFileTypes) {
|
||||
readdirResult = [
|
||||
[...readdirResult], readdirResult.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(pathArg, p));
|
||||
return internalBinding('fs').internalModuleStat(binding, path.join(pathArg, p));
|
||||
})
|
||||
];
|
||||
}
|
||||
@@ -1054,7 +1054,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
for (let i = 0; i < readdirResult.length; i++) {
|
||||
const resultPath = path.join(pathArg, readdirResult[i]);
|
||||
const relativeResultPath = path.relative(basePath, resultPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(resultPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(binding, resultPath);
|
||||
|
||||
readdirResults.push(relativeResultPath);
|
||||
if (stat === 1) pathsQueue.push(resultPath);
|
||||
|
||||
@@ -133,7 +133,10 @@ osr_shared_texture_remove_keyed_mutex_on_win_dxgi.patch
|
||||
feat_allow_usage_of_sccontentsharingpicker_on_supported_platforms.patch
|
||||
chore_partial_revert_of.patch
|
||||
fix_software_compositing_infinite_loop.patch
|
||||
fix_add_method_which_disables_headless_mode_on_native_widget.patch
|
||||
fix_put_nsvisualeffectview_before_viewscompositorsuperview.patch
|
||||
refactor_unfilter_unresponsive_events.patch
|
||||
build_disable_thin_lto_mac.patch
|
||||
build_add_public_config_simdutf_config.patch
|
||||
revert_code_health_clean_up_stale_macwebcontentsocclusion.patch
|
||||
check_for_unit_to_activate_before_notifying_about_success.patch
|
||||
|
||||
@@ -0,0 +1,497 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Maksim Sisov <msisov@igalia.com>
|
||||
Date: Tue, 7 Jan 2025 23:46:56 -0800
|
||||
Subject: Check for unit to activate before notifying about success
|
||||
|
||||
Portal's globalShortcuts interface relies on the unit name to
|
||||
properly assign a client for the bound commands. However, in
|
||||
some scenarious, there is a race between the service to be
|
||||
created, changed its name and activated. As a result, shortcuts
|
||||
might be bound before the name is changed. As a result, shortcuts
|
||||
might not correctly work and the client will not receive any
|
||||
signals.
|
||||
|
||||
This is mostly not an issue for Chromium as it creates the
|
||||
global shortcuts portal linux object way earlier than it gets
|
||||
commands from the command service. But downstream project, which
|
||||
try to bind shortcuts at the same time as that instance is created,
|
||||
may experience this issue. As a result, they might not have
|
||||
shortcuts working correctly after system reboot or app restart as
|
||||
there is a race between those operations.
|
||||
|
||||
Bug: None
|
||||
Change-Id: I8346d65e051d9587850c76ca0b8807669c161667
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6110782
|
||||
Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
|
||||
Commit-Queue: Maksim Sisov <msisov@igalia.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1403434}
|
||||
|
||||
diff --git a/components/dbus/xdg/systemd.cc b/components/dbus/xdg/systemd.cc
|
||||
index 362a16447bf578923cb8a84674c277ae6c98228f..3cd9a55d540c07a4c53f5a62bec5cbea37c11838 100644
|
||||
--- a/components/dbus/xdg/systemd.cc
|
||||
+++ b/components/dbus/xdg/systemd.cc
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
#include "components/dbus/xdg/systemd.h"
|
||||
|
||||
+#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/environment.h"
|
||||
+#include "base/functional/bind.h"
|
||||
+#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/sequence_checker.h"
|
||||
@@ -17,7 +20,9 @@
|
||||
#include "components/dbus/utils/name_has_owner.h"
|
||||
#include "dbus/bus.h"
|
||||
#include "dbus/message.h"
|
||||
+#include "dbus/object_path.h"
|
||||
#include "dbus/object_proxy.h"
|
||||
+#include "dbus/property.h"
|
||||
#include "third_party/abseil-cpp/absl/types/variant.h"
|
||||
|
||||
namespace dbus_xdg {
|
||||
@@ -37,6 +42,10 @@ constexpr char kServiceNameSystemd[] = "org.freedesktop.systemd1";
|
||||
constexpr char kObjectPathSystemd[] = "/org/freedesktop/systemd1";
|
||||
constexpr char kInterfaceSystemdManager[] = "org.freedesktop.systemd1.Manager";
|
||||
constexpr char kMethodStartTransientUnit[] = "StartTransientUnit";
|
||||
+constexpr char kMethodGetUnit[] = "GetUnit";
|
||||
+
|
||||
+constexpr char kInterfaceSystemdUnit[] = "org.freedesktop.systemd1.Unit";
|
||||
+constexpr char kActiveStateProp[] = "ActiveState";
|
||||
|
||||
constexpr char kUnitNameFormat[] = "app-$1$2-$3.scope";
|
||||
|
||||
@@ -67,6 +76,81 @@ const char* GetAppNameSuffix(const std::string& channel) {
|
||||
return "";
|
||||
}
|
||||
|
||||
+// Declare this helper for SystemdUnitActiveStateWatcher to be used.
|
||||
+void SetStateAndRunCallbacks(SystemdUnitStatus result);
|
||||
+
|
||||
+// Watches the object to become active and fires callbacks via
|
||||
+// SetStateAndRunCallbacks. The callbacks are fired whenever a response with the
|
||||
+// state being "active" or "failed" (or similar) comes.
|
||||
+//
|
||||
+// PS firing callbacks results in destroying this object. So any references
|
||||
+// to this become invalid.
|
||||
+class SystemdUnitActiveStateWatcher : public dbus::PropertySet {
|
||||
+ public:
|
||||
+ SystemdUnitActiveStateWatcher(scoped_refptr<dbus::Bus> bus,
|
||||
+ dbus::ObjectProxy* object_proxy)
|
||||
+ : dbus::PropertySet(object_proxy,
|
||||
+ kInterfaceSystemdUnit,
|
||||
+ base::BindRepeating(
|
||||
+ &SystemdUnitActiveStateWatcher::OnPropertyChanged,
|
||||
+ base::Unretained(this))),
|
||||
+ bus_(bus) {
|
||||
+ RegisterProperty(kActiveStateProp, &active_state_);
|
||||
+ ConnectSignals();
|
||||
+ GetAll();
|
||||
+ }
|
||||
+
|
||||
+ ~SystemdUnitActiveStateWatcher() override {
|
||||
+ bus_->RemoveObjectProxy(kServiceNameSystemd, object_proxy()->object_path(),
|
||||
+ base::DoNothing());
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ void OnPropertyChanged(const std::string& property_name) {
|
||||
+ DCHECK(active_state_.is_valid());
|
||||
+ const std::string state_value = active_state_.value();
|
||||
+ if (callbacks_called_ || state_value == "activating" ||
|
||||
+ state_value == "reloading") {
|
||||
+ // Ignore if callbacks have already been fired or continue waiting until
|
||||
+ // the state changes to something else.
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // There are other states as failed, inactive, and deactivating. Treat all
|
||||
+ // of them as failed.
|
||||
+ callbacks_called_ = true;
|
||||
+ SetStateAndRunCallbacks(state_value == "active"
|
||||
+ ? SystemdUnitStatus::kUnitStarted
|
||||
+ : SystemdUnitStatus::kFailedToStart);
|
||||
+ MaybeDeleteSelf();
|
||||
+ }
|
||||
+
|
||||
+ void OnGetAll(dbus::Response* response) override {
|
||||
+ dbus::PropertySet::OnGetAll(response);
|
||||
+ keep_alive_ = false;
|
||||
+ MaybeDeleteSelf();
|
||||
+ }
|
||||
+
|
||||
+ void MaybeDeleteSelf() {
|
||||
+ if (!keep_alive_ && callbacks_called_) {
|
||||
+ delete this;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Registered property that this listens updates to.
|
||||
+ dbus::Property<std::string> active_state_;
|
||||
+
|
||||
+ // Indicates whether callbacks for the unit's state have been called.
|
||||
+ bool callbacks_called_ = false;
|
||||
+
|
||||
+ // Control variable that helps to defer the destruction of |this| as deleting
|
||||
+ // self when the state changes to active during |OnGetAll| will result in a
|
||||
+ // segfault.
|
||||
+ bool keep_alive_ = true;
|
||||
+
|
||||
+ scoped_refptr<dbus::Bus> bus_;
|
||||
+};
|
||||
+
|
||||
// Global state for cached result or pending callbacks.
|
||||
StatusOrCallbacks& GetUnitNameState() {
|
||||
static base::NoDestructor<StatusOrCallbacks> state(
|
||||
@@ -83,10 +167,52 @@ void SetStateAndRunCallbacks(SystemdUnitStatus result) {
|
||||
}
|
||||
}
|
||||
|
||||
-void OnStartTransientUnitResponse(dbus::Response* response) {
|
||||
+void OnGetPathResponse(scoped_refptr<dbus::Bus> bus, dbus::Response* response) {
|
||||
+ dbus::MessageReader reader(response);
|
||||
+ dbus::ObjectPath obj_path;
|
||||
+ if (!response || !reader.PopObjectPath(&obj_path) || !obj_path.IsValid()) {
|
||||
+ // We didn't get a valid response. Treat this as failed service.
|
||||
+ SetStateAndRunCallbacks(SystemdUnitStatus::kFailedToStart);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ dbus::ObjectProxy* unit_proxy =
|
||||
+ bus->GetObjectProxy(kServiceNameSystemd, obj_path);
|
||||
+ // Create the active state property watcher. It will destroy itself once
|
||||
+ // it gets notified about the state change.
|
||||
+ std::unique_ptr<SystemdUnitActiveStateWatcher> active_state_watcher =
|
||||
+ std::make_unique<SystemdUnitActiveStateWatcher>(bus, unit_proxy);
|
||||
+ active_state_watcher.release();
|
||||
+}
|
||||
+
|
||||
+void WaitUnitActivateAndRunCallbacks(scoped_refptr<dbus::Bus> bus,
|
||||
+ std::string unit_name) {
|
||||
+ // Get the path of the unit, which looks similar to
|
||||
+ // /org/freedesktop/systemd1/unit/app_2dorg_2echromium_2eChromium_2d3182191_2escope
|
||||
+ // and then wait for it activation.
|
||||
+ dbus::ObjectProxy* systemd = bus->GetObjectProxy(
|
||||
+ kServiceNameSystemd, dbus::ObjectPath(kObjectPathSystemd));
|
||||
+
|
||||
+ dbus::MethodCall method_call(kInterfaceSystemdManager, kMethodGetUnit);
|
||||
+ dbus::MessageWriter writer(&method_call);
|
||||
+ writer.AppendString(unit_name);
|
||||
+
|
||||
+ systemd->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
|
||||
+ base::BindOnce(&OnGetPathResponse, std::move(bus)));
|
||||
+}
|
||||
+
|
||||
+void OnStartTransientUnitResponse(scoped_refptr<dbus::Bus> bus,
|
||||
+ std::string unit_name,
|
||||
+ dbus::Response* response) {
|
||||
SystemdUnitStatus result = response ? SystemdUnitStatus::kUnitStarted
|
||||
: SystemdUnitStatus::kFailedToStart;
|
||||
- SetStateAndRunCallbacks(result);
|
||||
+ // If the start of the unit failed, immediately notify the client. Otherwise,
|
||||
+ // wait for its activation.
|
||||
+ if (result == SystemdUnitStatus::kFailedToStart) {
|
||||
+ SetStateAndRunCallbacks(result);
|
||||
+ } else {
|
||||
+ WaitUnitActivateAndRunCallbacks(std::move(bus), unit_name);
|
||||
+ }
|
||||
}
|
||||
|
||||
void OnNameHasOwnerResponse(scoped_refptr<dbus::Bus> bus,
|
||||
@@ -128,8 +254,9 @@ void OnNameHasOwnerResponse(scoped_refptr<dbus::Bus> bus,
|
||||
properties.Write(&writer);
|
||||
// No auxiliary units.
|
||||
Dict<VarDict>().Write(&writer);
|
||||
- systemd->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
|
||||
- base::BindOnce(&OnStartTransientUnitResponse));
|
||||
+ systemd->CallMethod(
|
||||
+ &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
|
||||
+ base::BindOnce(&OnStartTransientUnitResponse, std::move(bus), unit_name));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
diff --git a/components/dbus/xdg/systemd_unittest.cc b/components/dbus/xdg/systemd_unittest.cc
|
||||
index 2e3baecabc4b479000c78d4f6bd30cb1f6e61d2e..67278d7033664d52fbbda02749a2aaa43352f402 100644
|
||||
--- a/components/dbus/xdg/systemd_unittest.cc
|
||||
+++ b/components/dbus/xdg/systemd_unittest.cc
|
||||
@@ -16,7 +16,9 @@
|
||||
#include "dbus/message.h"
|
||||
#include "dbus/mock_bus.h"
|
||||
#include "dbus/mock_object_proxy.h"
|
||||
+#include "dbus/object_path.h"
|
||||
#include "dbus/object_proxy.h"
|
||||
+#include "dbus/property.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@@ -32,6 +34,27 @@ constexpr char kServiceNameSystemd[] = "org.freedesktop.systemd1";
|
||||
constexpr char kObjectPathSystemd[] = "/org/freedesktop/systemd1";
|
||||
constexpr char kInterfaceSystemdManager[] = "org.freedesktop.systemd1.Manager";
|
||||
constexpr char kMethodStartTransientUnit[] = "StartTransientUnit";
|
||||
+constexpr char kMethodGetUnit[] = "GetUnit";
|
||||
+
|
||||
+constexpr char kFakeUnitPath[] = "/fake/unit/path";
|
||||
+constexpr char kActiveState[] = "ActiveState";
|
||||
+constexpr char kStateActive[] = "active";
|
||||
+constexpr char kStateInactive[] = "inactive";
|
||||
+
|
||||
+std::unique_ptr<dbus::Response> CreateActiveStateGetAllResponse(
|
||||
+ const std::string& state) {
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ dbus::MessageWriter writer(response.get());
|
||||
+ dbus::MessageWriter array_writer(nullptr);
|
||||
+ dbus::MessageWriter dict_entry_writer(nullptr);
|
||||
+ writer.OpenArray("{sv}", &array_writer);
|
||||
+ array_writer.OpenDictEntry(&dict_entry_writer);
|
||||
+ dict_entry_writer.AppendString(kActiveState);
|
||||
+ dict_entry_writer.AppendVariantOfString(state);
|
||||
+ array_writer.CloseContainer(&dict_entry_writer);
|
||||
+ writer.CloseContainer(&array_writer);
|
||||
+ return response;
|
||||
+}
|
||||
|
||||
class SetSystemdScopeUnitNameForXdgPortalTest : public ::testing::Test {
|
||||
public:
|
||||
@@ -124,17 +147,48 @@ TEST_F(SetSystemdScopeUnitNameForXdgPortalTest, StartTransientUnitSuccess) {
|
||||
|
||||
EXPECT_CALL(*bus, GetObjectProxy(kServiceNameSystemd,
|
||||
dbus::ObjectPath(kObjectPathSystemd)))
|
||||
- .WillOnce(Return(mock_systemd_proxy.get()));
|
||||
+ .Times(2)
|
||||
+ .WillRepeatedly(Return(mock_systemd_proxy.get()));
|
||||
+
|
||||
+ auto mock_dbus_unit_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
|
||||
+ bus.get(), kServiceNameSystemd, dbus::ObjectPath(kFakeUnitPath));
|
||||
+ EXPECT_CALL(*bus, GetObjectProxy(kServiceNameSystemd,
|
||||
+ dbus::ObjectPath(kFakeUnitPath)))
|
||||
+ .WillOnce(Return(mock_dbus_unit_proxy.get()));
|
||||
|
||||
EXPECT_CALL(*mock_systemd_proxy, DoCallMethod(_, _, _))
|
||||
.WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ // Expect kMethodStartTransientUnit first.
|
||||
EXPECT_EQ(method_call->GetInterface(), kInterfaceSystemdManager);
|
||||
EXPECT_EQ(method_call->GetMember(), kMethodStartTransientUnit);
|
||||
|
||||
// Simulate a successful response
|
||||
auto response = dbus::Response::CreateEmpty();
|
||||
std::move(*callback).Run(response.get());
|
||||
+ }))
|
||||
+ .WillOnce(Invoke([obj_path = kFakeUnitPath](
|
||||
+ dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ // Then expect kMethodGetUnit. A valid path must be provided.
|
||||
+ EXPECT_EQ(method_call->GetInterface(), kInterfaceSystemdManager);
|
||||
+ EXPECT_EQ(method_call->GetMember(), kMethodGetUnit);
|
||||
+
|
||||
+ // Simulate a successful response and provide a fake path to the object.
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ dbus::MessageWriter writer(response.get());
|
||||
+ writer.AppendObjectPath(dbus::ObjectPath(obj_path));
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }));
|
||||
+
|
||||
+ EXPECT_CALL(*mock_dbus_unit_proxy, DoCallMethod(_, _, _))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ EXPECT_EQ(method_call->GetInterface(), dbus::kPropertiesInterface);
|
||||
+ EXPECT_EQ(method_call->GetMember(), dbus::kPropertiesGetAll);
|
||||
+ // Simulate a successful response with "active" state.
|
||||
+ auto response = CreateActiveStateGetAllResponse(kStateActive);
|
||||
+ std::move(*callback).Run(response.get());
|
||||
}));
|
||||
|
||||
std::optional<SystemdUnitStatus> status;
|
||||
@@ -189,6 +243,142 @@ TEST_F(SetSystemdScopeUnitNameForXdgPortalTest, StartTransientUnitFailure) {
|
||||
EXPECT_EQ(status, SystemdUnitStatus::kFailedToStart);
|
||||
}
|
||||
|
||||
+TEST_F(SetSystemdScopeUnitNameForXdgPortalTest,
|
||||
+ StartTransientUnitInvalidUnitPath) {
|
||||
+ scoped_refptr<dbus::MockBus> bus =
|
||||
+ base::MakeRefCounted<dbus::MockBus>(dbus::Bus::Options());
|
||||
+
|
||||
+ auto mock_dbus_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
|
||||
+ bus.get(), DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS));
|
||||
+
|
||||
+ EXPECT_CALL(
|
||||
+ *bus, GetObjectProxy(DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS)))
|
||||
+ .WillRepeatedly(Return(mock_dbus_proxy.get()));
|
||||
+
|
||||
+ EXPECT_CALL(*mock_dbus_proxy, DoCallMethod(_, _, _))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ dbus::MessageWriter writer(response.get());
|
||||
+ writer.AppendBool(true);
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }));
|
||||
+
|
||||
+ auto mock_systemd_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
|
||||
+ bus.get(), kServiceNameSystemd, dbus::ObjectPath(kObjectPathSystemd));
|
||||
+
|
||||
+ EXPECT_CALL(*bus, GetObjectProxy(kServiceNameSystemd,
|
||||
+ dbus::ObjectPath(kObjectPathSystemd)))
|
||||
+ .Times(2)
|
||||
+ .WillRepeatedly(Return(mock_systemd_proxy.get()));
|
||||
+
|
||||
+ EXPECT_CALL(*mock_systemd_proxy, DoCallMethod(_, _, _))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ EXPECT_EQ(method_call->GetInterface(), kInterfaceSystemdManager);
|
||||
+ EXPECT_EQ(method_call->GetMember(), kMethodStartTransientUnit);
|
||||
+
|
||||
+ // Simulate a successful response
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ EXPECT_EQ(method_call->GetInterface(), kInterfaceSystemdManager);
|
||||
+ EXPECT_EQ(method_call->GetMember(), kMethodGetUnit);
|
||||
+
|
||||
+ // Simulate a failure response.
|
||||
+ std::move(*callback).Run(nullptr);
|
||||
+ }));
|
||||
+
|
||||
+ std::optional<SystemdUnitStatus> status;
|
||||
+
|
||||
+ SetSystemdScopeUnitNameForXdgPortal(
|
||||
+ bus.get(), base::BindLambdaForTesting(
|
||||
+ [&](SystemdUnitStatus result) { status = result; }));
|
||||
+
|
||||
+ EXPECT_EQ(status, SystemdUnitStatus::kFailedToStart);
|
||||
+}
|
||||
+
|
||||
+TEST_F(SetSystemdScopeUnitNameForXdgPortalTest,
|
||||
+ StartTransientUnitFailToActivate) {
|
||||
+ scoped_refptr<dbus::MockBus> bus =
|
||||
+ base::MakeRefCounted<dbus::MockBus>(dbus::Bus::Options());
|
||||
+
|
||||
+ auto mock_dbus_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
|
||||
+ bus.get(), DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS));
|
||||
+
|
||||
+ EXPECT_CALL(
|
||||
+ *bus, GetObjectProxy(DBUS_SERVICE_DBUS, dbus::ObjectPath(DBUS_PATH_DBUS)))
|
||||
+ .WillRepeatedly(Return(mock_dbus_proxy.get()));
|
||||
+
|
||||
+ EXPECT_CALL(*mock_dbus_proxy, DoCallMethod(_, _, _))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ dbus::MessageWriter writer(response.get());
|
||||
+ writer.AppendBool(true);
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }));
|
||||
+
|
||||
+ auto mock_systemd_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
|
||||
+ bus.get(), kServiceNameSystemd, dbus::ObjectPath(kObjectPathSystemd));
|
||||
+
|
||||
+ EXPECT_CALL(*bus, GetObjectProxy(kServiceNameSystemd,
|
||||
+ dbus::ObjectPath(kObjectPathSystemd)))
|
||||
+ .Times(2)
|
||||
+ .WillRepeatedly(Return(mock_systemd_proxy.get()));
|
||||
+
|
||||
+ auto mock_dbus_unit_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
|
||||
+ bus.get(), kServiceNameSystemd, dbus::ObjectPath(kFakeUnitPath));
|
||||
+ EXPECT_CALL(*bus, GetObjectProxy(kServiceNameSystemd,
|
||||
+ dbus::ObjectPath(kFakeUnitPath)))
|
||||
+ .WillOnce(Return(mock_dbus_unit_proxy.get()));
|
||||
+
|
||||
+ EXPECT_CALL(*mock_systemd_proxy, DoCallMethod(_, _, _))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ EXPECT_EQ(method_call->GetInterface(), kInterfaceSystemdManager);
|
||||
+ EXPECT_EQ(method_call->GetMember(), kMethodStartTransientUnit);
|
||||
+
|
||||
+ // Simulate a successful response
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }))
|
||||
+ .WillOnce(Invoke([obj_path = kFakeUnitPath](
|
||||
+ dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ EXPECT_EQ(method_call->GetInterface(), kInterfaceSystemdManager);
|
||||
+ EXPECT_EQ(method_call->GetMember(), kMethodGetUnit);
|
||||
+
|
||||
+ // Simulate a successful response
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ dbus::MessageWriter writer(response.get());
|
||||
+ writer.AppendObjectPath(dbus::ObjectPath(obj_path));
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }));
|
||||
+
|
||||
+ EXPECT_CALL(*mock_dbus_unit_proxy, DoCallMethod(_, _, _))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ // Then expect kMethodGetUnit. A valid path must be provided.
|
||||
+ EXPECT_EQ(method_call->GetInterface(), dbus::kPropertiesInterface);
|
||||
+ EXPECT_EQ(method_call->GetMember(), dbus::kPropertiesGetAll);
|
||||
+
|
||||
+ // Simulate a successful response, but with inactive state.
|
||||
+ auto response = CreateActiveStateGetAllResponse(kStateInactive);
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }));
|
||||
+
|
||||
+ std::optional<SystemdUnitStatus> status;
|
||||
+
|
||||
+ SetSystemdScopeUnitNameForXdgPortal(
|
||||
+ bus.get(), base::BindLambdaForTesting(
|
||||
+ [&](SystemdUnitStatus result) { status = result; }));
|
||||
+
|
||||
+ EXPECT_EQ(status, SystemdUnitStatus::kFailedToStart);
|
||||
+}
|
||||
+
|
||||
TEST_F(SetSystemdScopeUnitNameForXdgPortalTest, UnitNameConstruction) {
|
||||
scoped_refptr<dbus::MockBus> bus =
|
||||
base::MakeRefCounted<dbus::MockBus>(dbus::Bus::Options());
|
||||
@@ -220,7 +410,14 @@ TEST_F(SetSystemdScopeUnitNameForXdgPortalTest, UnitNameConstruction) {
|
||||
|
||||
EXPECT_CALL(*bus, GetObjectProxy(kServiceNameSystemd,
|
||||
dbus::ObjectPath(kObjectPathSystemd)))
|
||||
- .WillOnce(Return(mock_systemd_proxy.get()));
|
||||
+ .Times(2)
|
||||
+ .WillRepeatedly(Return(mock_systemd_proxy.get()));
|
||||
+
|
||||
+ auto mock_dbus_unit_proxy = base::MakeRefCounted<dbus::MockObjectProxy>(
|
||||
+ bus.get(), kServiceNameSystemd, dbus::ObjectPath(kFakeUnitPath));
|
||||
+ EXPECT_CALL(*bus, GetObjectProxy(kServiceNameSystemd,
|
||||
+ dbus::ObjectPath(kFakeUnitPath)))
|
||||
+ .WillOnce(Return(mock_dbus_unit_proxy.get()));
|
||||
|
||||
EXPECT_CALL(*mock_systemd_proxy, DoCallMethod(_, _, _))
|
||||
.WillOnce(Invoke([&](dbus::MethodCall* method_call, int timeout_ms,
|
||||
@@ -256,6 +453,30 @@ TEST_F(SetSystemdScopeUnitNameForXdgPortalTest, UnitNameConstruction) {
|
||||
|
||||
auto response = dbus::Response::CreateEmpty();
|
||||
std::move(*callback).Run(response.get());
|
||||
+ }))
|
||||
+ .WillOnce(Invoke([obj_path = kFakeUnitPath](
|
||||
+ dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ EXPECT_EQ(method_call->GetInterface(), kInterfaceSystemdManager);
|
||||
+ EXPECT_EQ(method_call->GetMember(), kMethodGetUnit);
|
||||
+
|
||||
+ // Simulate a successful response
|
||||
+ auto response = dbus::Response::CreateEmpty();
|
||||
+ dbus::MessageWriter writer(response.get());
|
||||
+ writer.AppendObjectPath(dbus::ObjectPath(obj_path));
|
||||
+ std::move(*callback).Run(response.get());
|
||||
+ }));
|
||||
+
|
||||
+ EXPECT_CALL(*mock_dbus_unit_proxy, DoCallMethod(_, _, _))
|
||||
+ .WillOnce(Invoke([](dbus::MethodCall* method_call, int timeout_ms,
|
||||
+ dbus::ObjectProxy::ResponseCallback* callback) {
|
||||
+ // Then expect kMethodGetUnit. A valid path must be provided.
|
||||
+ EXPECT_EQ(method_call->GetInterface(), dbus::kPropertiesInterface);
|
||||
+ EXPECT_EQ(method_call->GetMember(), dbus::kPropertiesGetAll);
|
||||
+
|
||||
+ // Simulate a successful response
|
||||
+ auto response = CreateActiveStateGetAllResponse(kStateActive);
|
||||
+ std::move(*callback).Run(response.get());
|
||||
}));
|
||||
|
||||
std::optional<SystemdUnitStatus> status;
|
||||
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cezary Kulakowski <cezary@openfin.co>
|
||||
Date: Mon, 22 Jul 2024 16:23:13 +0200
|
||||
Subject: fix: add method which disables headless mode on native widget
|
||||
|
||||
We need this method as we create window in headless mode and we
|
||||
switch it back to normal mode only after inital paint is done in
|
||||
order to get some events like WebContents.beginFrameSubscription.
|
||||
If we don't set `is_headless_` to false then some child windows
|
||||
e.g. autofill popups will be created in headless mode leading to
|
||||
ui problems (like dissapearing popup during typing in html's
|
||||
input list.
|
||||
|
||||
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
|
||||
index 30d0ea6633cb0f7f9aab37951a38be9b0482a12a..734e91e6d50c8d3afd20b39167c6254e934e7c1e 100644
|
||||
--- a/ui/views/widget/widget.h
|
||||
+++ b/ui/views/widget/widget.h
|
||||
@@ -1144,6 +1144,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
|
||||
// True if widget was created in headless mode.
|
||||
bool is_headless() const { return is_headless_; }
|
||||
|
||||
+ void DisableHeadlessMode() { is_headless_ = false; }
|
||||
+
|
||||
// True if the window size will follow the content preferred size.
|
||||
bool is_autosized() const { return is_autosized_; }
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Micha=C5=82=20Pichli=C5=84ski?=
|
||||
<michal.pichlinski@openfin.co>
|
||||
Date: Tue, 29 Oct 2024 21:16:29 +0100
|
||||
Subject: fix: Put NSVisualEffectView before ViewsCompositorSuperview
|
||||
|
||||
Upstreamed at https://chromium-review.googlesource.com/c/chromium/src/+/6030552
|
||||
|
||||
Otherwise when using `vibrancy` in `BrowserWindow` NSVisualEffectView
|
||||
will hide content displayed by the compositor.
|
||||
|
||||
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
|
||||
index 07c3997e6565cf77362ee73959c4d21da4fefe96..3353a7847df90b58eec34ea4d6ff8fb19617f5cc 100644
|
||||
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
|
||||
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
|
||||
@@ -223,8 +223,19 @@ NSComparisonResult SubviewSorter(__kindof NSView* lhs,
|
||||
void* rank_as_void) {
|
||||
DCHECK_NE(lhs, rhs);
|
||||
|
||||
- if ([lhs isKindOfClass:[ViewsCompositorSuperview class]])
|
||||
+
|
||||
+ // Put NSVisualEffectView before ViewsCompositorSuperview otherwise when using
|
||||
+ // `vibrancy` in `BrowserWindow` NSVisualEffectView will hide content
|
||||
+ // displayed by the compositor.
|
||||
+ if ([lhs isKindOfClass:[NSVisualEffectView class]]) {
|
||||
return NSOrderedAscending;
|
||||
+ }
|
||||
+ if ([lhs isKindOfClass:[ViewsCompositorSuperview class]]) {
|
||||
+ if ([rhs isKindOfClass:[NSVisualEffectView class]]) {
|
||||
+ return NSOrderedDescending;
|
||||
+ }
|
||||
+ return NSOrderedAscending;
|
||||
+ }
|
||||
|
||||
const RankMap* rank = static_cast<const RankMap*>(rank_as_void);
|
||||
auto left_rank = rank->find(lhs);
|
||||
@@ -604,6 +604,19 @@ index 402be34ab888cdf834d0fb65de0832e9a8021ced..82ddc92a35d824926c30279e660cc4e8
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS)
|
||||
diff --git a/chrome/browser/printing/printer_query_oop.cc b/chrome/browser/printing/printer_query_oop.cc
|
||||
index e271d17b3261c47f3dbeaf9be0b3c4229ee27181..ed19764250d9125915f0f948896acd7eae7911a6 100644
|
||||
--- a/chrome/browser/printing/printer_query_oop.cc
|
||||
+++ b/chrome/browser/printing/printer_query_oop.cc
|
||||
@@ -127,7 +127,7 @@ void PrinterQueryOop::OnDidAskUserForSettings(
|
||||
std::unique_ptr<PrintSettings> new_settings,
|
||||
mojom::ResultCode result) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
- if (result == mojom::ResultCode::kSuccess) {
|
||||
+ if (result == mojom::ResultCode::kSuccess && query_with_ui_client_id_) {
|
||||
// Want the same PrintBackend service as the query so that we use the same
|
||||
// device context.
|
||||
print_document_client_id_ =
|
||||
diff --git a/components/printing/browser/print_manager.cc b/components/printing/browser/print_manager.cc
|
||||
index 21c81377d32ae8d4185598a7eba88ed1d2063ef0..0767f4e9369e926b1cea99178c1a1975941f1765 100644
|
||||
--- a/components/printing/browser/print_manager.cc
|
||||
@@ -653,7 +666,7 @@ index 6809c4576c71bc1e1a6ad4e0a37707272a9a10f4..3aad10424a6a31dab2ca393d00149ec6
|
||||
PrintingFailed(int32 cookie, PrintFailureReason reason);
|
||||
|
||||
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
|
||||
index 18a8d64167b66d0de67c0c89779af90814b827c6..33079deee8720a447e2b4e1f3601542b59e1cf16 100644
|
||||
index 18a8d64167b66d0de67c0c89779af90814b827c6..52b95469f0392fbb108bef3f6d5ea0f8a81410fd 100644
|
||||
--- a/components/printing/renderer/print_render_frame_helper.cc
|
||||
+++ b/components/printing/renderer/print_render_frame_helper.cc
|
||||
@@ -52,6 +52,7 @@
|
||||
@@ -771,7 +784,7 @@ index 18a8d64167b66d0de67c0c89779af90814b827c6..33079deee8720a447e2b4e1f3601542b
|
||||
// Check if `this` is still valid.
|
||||
if (!self)
|
||||
return;
|
||||
@@ -2359,29 +2374,37 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
@@ -2359,29 +2374,43 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
}
|
||||
|
||||
bool PrintRenderFrameHelper::InitPrintSettings(blink::WebLocalFrame* frame,
|
||||
@@ -803,10 +816,18 @@ index 18a8d64167b66d0de67c0c89779af90814b827c6..33079deee8720a447e2b4e1f3601542b
|
||||
|
||||
bool center_on_paper = !IsPrintingPdfFrame(frame, node);
|
||||
- settings.params->print_scaling_option =
|
||||
+ settings->params->print_scaling_option =
|
||||
center_on_paper ? mojom::PrintScalingOption::kCenterShrinkToFitPaper
|
||||
: mojom::PrintScalingOption::kSourceSize;
|
||||
- center_on_paper ? mojom::PrintScalingOption::kCenterShrinkToFitPaper
|
||||
- : mojom::PrintScalingOption::kSourceSize;
|
||||
- RecordDebugEvent(settings.params->printed_doc_type ==
|
||||
+ bool silent = new_settings.FindBool("silent").value_or(false);
|
||||
+ if (silent) {
|
||||
+ settings->params->print_scaling_option = mojom::PrintScalingOption::kFitToPrintableArea;
|
||||
+ } else {
|
||||
+ settings->params->print_scaling_option =
|
||||
+ center_on_paper ? mojom::PrintScalingOption::kCenterShrinkToFitPaper
|
||||
+ : mojom::PrintScalingOption::kSourceSize;
|
||||
+ }
|
||||
+
|
||||
+ RecordDebugEvent(settings->params->printed_doc_type ==
|
||||
mojom::SkiaDocumentType::kMSKP
|
||||
? DebugEvent::kSetPrintSettings5
|
||||
|
||||
@@ -10,6 +10,17 @@ however those files were cherry-picked from main branch and do not
|
||||
really in 20/21. We have to wait until 22 is released to be able to
|
||||
build with upstream GN files.
|
||||
|
||||
diff --git a/deps/simdjson/unofficial.gni b/deps/simdjson/unofficial.gni
|
||||
index d6909b95886f4de3f0b953c2a2992f69066b7434..972955f9144aafcd3a3fe278b7aaad401cadddda 100644
|
||||
--- a/deps/simdjson/unofficial.gni
|
||||
+++ b/deps/simdjson/unofficial.gni
|
||||
@@ -18,5 +18,6 @@ template("simdjson_gn_build") {
|
||||
forward_variables_from(invoker, "*")
|
||||
public_configs = [ ":simdjson_config" ]
|
||||
sources = gypi_values.simdjson_sources
|
||||
+ cflags_c = [ "-Wdeprecated-literal-operator" ]
|
||||
}
|
||||
}
|
||||
diff --git a/deps/sqlite/unofficial.gni b/deps/sqlite/unofficial.gni
|
||||
index ebb3ffcd6d42b4c16b6865a91ccf4428cffe864b..00225afa1fb4205f1e02d9f185aeb97d642b3fd9 100644
|
||||
--- a/deps/sqlite/unofficial.gni
|
||||
@@ -31,7 +42,7 @@ index ebb3ffcd6d42b4c16b6865a91ccf4428cffe864b..00225afa1fb4205f1e02d9f185aeb97d
|
||||
"-Wno-unused-but-set-variable",
|
||||
"-Wno-unused-function",
|
||||
diff --git a/node.gni b/node.gni
|
||||
index 9dca810decebd75aab427e306b3cc37c80fb55c9..32709b860ccb12d8d1e75342a65dda0b86129b21 100644
|
||||
index 9dca810decebd75aab427e306b3cc37c80fb55c9..852f64fa9cfb50fe6e9ce7aa46be336d3196d5b8 100644
|
||||
--- a/node.gni
|
||||
+++ b/node.gni
|
||||
@@ -5,10 +5,10 @@
|
||||
@@ -56,20 +67,29 @@ index 9dca810decebd75aab427e306b3cc37c80fb55c9..32709b860ccb12d8d1e75342a65dda0b
|
||||
|
||||
# Custom build tag.
|
||||
node_tag = ""
|
||||
@@ -58,7 +58,7 @@ declare_args() {
|
||||
@@ -58,7 +58,16 @@ declare_args() {
|
||||
# TODO(zcbenz): There are few broken things for now:
|
||||
# 1. cross-os compilation is not supported.
|
||||
# 2. node_mksnapshot crashes when cross-compiling for x64 from arm64.
|
||||
- node_use_node_snapshot = (host_os == target_os) && !(host_cpu == "arm64" && target_cpu == "x64")
|
||||
+ node_use_node_snapshot = false
|
||||
+
|
||||
+ # Build with Amaro (TypeScript utils).
|
||||
+ node_use_amaro = true
|
||||
+
|
||||
+ # Allows downstream packagers (eg. Linux distributions) to build against system shared libraries.
|
||||
+ use_system_cares = false
|
||||
+ use_system_nghttp2 = false
|
||||
+ use_system_llhttp = false
|
||||
+ use_system_histogram = false
|
||||
}
|
||||
|
||||
assert(!node_enable_inspector || node_use_openssl,
|
||||
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
|
||||
index 2bc7155f7c075e5a22ece7159a64a1c9ba3d8ac9..48d29a0d05538cd1d992f3f086d826e78d0d8882 100644
|
||||
index 1bec44f6f29b0b652e92d2bb336fdb74b85eee30..599b59873dbb17ae5e7463403859e088ffb86cda 100644
|
||||
--- a/src/node_builtins.cc
|
||||
+++ b/src/node_builtins.cc
|
||||
@@ -775,6 +775,7 @@ void BuiltinLoader::RegisterExternalReferences(
|
||||
@@ -778,6 +778,7 @@ void BuiltinLoader::RegisterExternalReferences(
|
||||
registry->Register(GetNatives);
|
||||
|
||||
RegisterExternalReferencesForInternalizedBuiltinCode(registry);
|
||||
@@ -91,7 +111,7 @@ index 1cb85b9058d06555382e565dc32192a9fa48ed9f..cec9be01abd107e8612f70daf19b4834
|
||||
// Handles compilation and caching of built-in JavaScript modules and
|
||||
// bootstrap scripts, whose source are bundled into the binary as static data.
|
||||
diff --git a/tools/generate_config_gypi.py b/tools/generate_config_gypi.py
|
||||
index 45b3ac5006140fb55aad0e6b78084b753a947a76..8667857107e4f2481fd98032d4333b086fb7b479 100755
|
||||
index 45b3ac5006140fb55aad0e6b78084b753a947a76..35cce2ea8fd85f21582962115ac455918d4c4553 100755
|
||||
--- a/tools/generate_config_gypi.py
|
||||
+++ b/tools/generate_config_gypi.py
|
||||
@@ -21,7 +21,7 @@ import getnapibuildversion
|
||||
@@ -103,6 +123,14 @@ index 45b3ac5006140fb55aad0e6b78084b753a947a76..8667857107e4f2481fd98032d4333b08
|
||||
else:
|
||||
GN = 'gn'
|
||||
|
||||
@@ -65,6 +65,7 @@ def translate_config(out_dir, config, v8_config):
|
||||
eval(config['node_builtin_shareable_builtins']),
|
||||
'node_module_version': int(config['node_module_version']),
|
||||
'node_use_openssl': config['node_use_openssl'],
|
||||
+ 'node_use_amaro': config['node_use_amaro'],
|
||||
'node_use_node_code_cache': config['node_use_node_code_cache'],
|
||||
'node_use_node_snapshot': config['node_use_node_snapshot'],
|
||||
'v8_enable_inspector': # this is actually a node misnomer
|
||||
diff --git a/tools/install.py b/tools/install.py
|
||||
index bf54249b66c0d4e179deaae5a9fd55568e694fe0..31b94d2e4b532d3b8202b512e2d2f41d29a2a546 100755
|
||||
--- a/tools/install.py
|
||||
@@ -118,10 +146,10 @@ index bf54249b66c0d4e179deaae5a9fd55568e694fe0..31b94d2e4b532d3b8202b512e2d2f41d
|
||||
diff --git a/tools/js2c.cc b/tools/js2c.cc
|
||||
old mode 100644
|
||||
new mode 100755
|
||||
index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd786f64bb
|
||||
index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2e9dfb0f0
|
||||
--- a/tools/js2c.cc
|
||||
+++ b/tools/js2c.cc
|
||||
@@ -30,6 +30,7 @@ namespace js2c {
|
||||
@@ -28,6 +28,7 @@ namespace js2c {
|
||||
int Main(int argc, char* argv[]);
|
||||
|
||||
static bool is_verbose = false;
|
||||
@@ -129,7 +157,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
|
||||
void Debug(const char* format, ...) {
|
||||
va_list arguments;
|
||||
@@ -196,6 +197,7 @@ const char* kTemplate = R"(
|
||||
@@ -175,6 +176,7 @@ const char* kTemplate = R"(
|
||||
#include "node_builtins.h"
|
||||
#include "node_external_reference.h"
|
||||
#include "node_internals.h"
|
||||
@@ -137,7 +165,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
|
||||
namespace node {
|
||||
|
||||
@@ -211,7 +213,11 @@ const ThreadsafeCopyOnWrite<BuiltinSourceMap> global_source_map {
|
||||
@@ -190,7 +192,11 @@ const ThreadsafeCopyOnWrite<BuiltinSourceMap> global_source_map {
|
||||
} // anonymous namespace
|
||||
|
||||
void BuiltinLoader::LoadJavaScriptSource() {
|
||||
@@ -150,7 +178,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
}
|
||||
|
||||
void RegisterExternalReferencesForInternalizedBuiltinCode(
|
||||
@@ -228,6 +234,45 @@ UnionBytes BuiltinLoader::GetConfig() {
|
||||
@@ -207,6 +213,45 @@ UnionBytes BuiltinLoader::GetConfig() {
|
||||
} // namespace node
|
||||
)";
|
||||
|
||||
@@ -196,7 +224,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
Fragment Format(const Fragments& definitions,
|
||||
const Fragments& initializers,
|
||||
const Fragments& registrations) {
|
||||
@@ -237,13 +282,12 @@ Fragment Format(const Fragments& definitions,
|
||||
@@ -216,13 +261,12 @@ Fragment Format(const Fragments& definitions,
|
||||
size_t init_size = init_buf.size();
|
||||
std::vector<char> reg_buf = Join(registrations, "\n");
|
||||
size_t reg_size = reg_buf.size();
|
||||
@@ -213,7 +241,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
static_cast<int>(def_buf.size()),
|
||||
def_buf.data(),
|
||||
static_cast<int>(init_buf.size()),
|
||||
@@ -834,12 +878,15 @@ int JS2C(const FileList& js_files,
|
||||
@@ -846,12 +890,15 @@ int JS2C(const FileList& js_files,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +257,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
Fragment out = Format(definitions, initializers, registrations);
|
||||
return WriteIfChanged(out, dest);
|
||||
}
|
||||
@@ -865,6 +912,8 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -877,6 +924,8 @@ int Main(int argc, char* argv[]) {
|
||||
std::string arg(argv[i]);
|
||||
if (arg == "--verbose") {
|
||||
is_verbose = true;
|
||||
@@ -238,7 +266,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
} else if (arg == "--root") {
|
||||
if (i == argc - 1) {
|
||||
fprintf(stderr, "--root must be followed by a path\n");
|
||||
@@ -913,6 +962,14 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -925,6 +974,14 @@ int Main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,7 +281,7 @@ index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd
|
||||
// Should have exactly 3 types: `.js`, `.mjs` and `.gypi`.
|
||||
assert(file_map.size() == 3);
|
||||
auto gypi_it = file_map.find(".gypi");
|
||||
@@ -939,6 +996,7 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -951,6 +1008,7 @@ int Main(int argc, char* argv[]) {
|
||||
std::sort(mjs_it->second.begin(), mjs_it->second.end());
|
||||
|
||||
return JS2C(js_it->second, mjs_it->second, gypi_it->second[0], output);
|
||||
@@ -274,10 +302,22 @@ index 65d0e1be42f0a85418491ebb548278cf431aa6a0..d4a31342f1c6107b029394c6e1d00a1d
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1fa351a9d9 100644
|
||||
index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6dbbe7ac7 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -139,6 +139,7 @@ template("node_gn_build") {
|
||||
@@ -22,6 +22,11 @@ template("node_gn_build") {
|
||||
} else {
|
||||
defines += [ "HAVE_OPENSSL=0" ]
|
||||
}
|
||||
+ if (node_use_amaro) {
|
||||
+ defines += [ "HAVE_AMARO=1" ]
|
||||
+ } else {
|
||||
+ defines += [ "HAVE_AMARO=0" ]
|
||||
+ }
|
||||
if (node_use_v8_platform) {
|
||||
defines += [ "NODE_USE_V8_PLATFORM=1" ]
|
||||
} else {
|
||||
@@ -139,6 +144,7 @@ template("node_gn_build") {
|
||||
public_deps = [
|
||||
"deps/ada",
|
||||
"deps/uv",
|
||||
@@ -285,7 +325,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1f
|
||||
"deps/simdjson",
|
||||
"$node_v8_path",
|
||||
]
|
||||
@@ -150,7 +151,6 @@ template("node_gn_build") {
|
||||
@@ -150,7 +156,6 @@ template("node_gn_build") {
|
||||
"deps/llhttp",
|
||||
"deps/nbytes",
|
||||
"deps/nghttp2",
|
||||
@@ -293,7 +333,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1f
|
||||
"deps/postject",
|
||||
"deps/simdutf",
|
||||
"deps/sqlite",
|
||||
@@ -159,7 +159,11 @@ template("node_gn_build") {
|
||||
@@ -159,7 +164,11 @@ template("node_gn_build") {
|
||||
"$node_v8_path:v8_libplatform",
|
||||
]
|
||||
|
||||
@@ -305,7 +345,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1f
|
||||
"$target_gen_dir/node_javascript.cc",
|
||||
] + gypi_values.node_sources
|
||||
|
||||
@@ -178,8 +182,10 @@ template("node_gn_build") {
|
||||
@@ -178,8 +187,10 @@ template("node_gn_build") {
|
||||
deps += [ "//third_party/icu" ]
|
||||
}
|
||||
if (node_use_openssl) {
|
||||
@@ -318,7 +358,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1f
|
||||
sources += gypi_values.node_crypto_sources
|
||||
}
|
||||
if (node_enable_inspector) {
|
||||
@@ -276,6 +282,7 @@ template("node_gn_build") {
|
||||
@@ -276,6 +287,7 @@ template("node_gn_build") {
|
||||
}
|
||||
|
||||
executable("node_js2c") {
|
||||
@@ -326,7 +366,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1f
|
||||
deps = [
|
||||
"deps/simdutf",
|
||||
"deps/uv",
|
||||
@@ -286,26 +293,75 @@ template("node_gn_build") {
|
||||
@@ -286,26 +298,75 @@ template("node_gn_build") {
|
||||
"src/embedded_data.cc",
|
||||
"src/embedded_data.h",
|
||||
]
|
||||
@@ -412,7 +452,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1f
|
||||
outputs = [ "$target_gen_dir/node_javascript.cc" ]
|
||||
|
||||
# Get the path to node_js2c executable of the host toolchain.
|
||||
@@ -319,11 +375,11 @@ template("node_gn_build") {
|
||||
@@ -319,11 +380,11 @@ template("node_gn_build") {
|
||||
get_label_info(":node_js2c($host_toolchain)", "name") +
|
||||
host_executable_suffix
|
||||
|
||||
|
||||
@@ -13,28 +13,11 @@ We don't need to do this for zlib, as the existing gn workflow uses the same
|
||||
|
||||
Upstreamed at https://github.com/nodejs/node/pull/55903
|
||||
|
||||
diff --git a/node.gni b/node.gni
|
||||
index 18d58591e3d0f1f3512db00033c3410a65702864..99ec540ec41ddf5682eed7618ba87d6935b3b982 100644
|
||||
--- a/node.gni
|
||||
+++ b/node.gni
|
||||
@@ -61,6 +61,12 @@ declare_args() {
|
||||
# 1. cross-os compilation is not supported.
|
||||
# 2. node_mksnapshot crashes when cross-compiling for x64 from arm64.
|
||||
node_use_node_snapshot = false
|
||||
+
|
||||
+ # Allows downstream packagers (eg. Linux distributions) to build against system shared libraries.
|
||||
+ use_system_cares = false
|
||||
+ use_system_nghttp2 = false
|
||||
+ use_system_llhttp = false
|
||||
+ use_system_histogram = false
|
||||
}
|
||||
|
||||
assert(!node_enable_inspector || node_use_openssl,
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index 3d8b7957e791ce2fa2a8d0937a87b6010087803d..c23922a301a721662ff34bf6e54fd26b41f25ccc 100644
|
||||
index ddfbb97276b29df114ab455a2eed3b186b3af5d2..87bfc313dd1408e597e929ba93c8c0f52ae39ced 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -147,7 +147,6 @@ template("node_gn_build") {
|
||||
@@ -152,7 +152,6 @@ template("node_gn_build") {
|
||||
":run_node_js2c",
|
||||
"deps/cares",
|
||||
"deps/histogram",
|
||||
@@ -42,7 +25,7 @@ index 3d8b7957e791ce2fa2a8d0937a87b6010087803d..c23922a301a721662ff34bf6e54fd26b
|
||||
"deps/nbytes",
|
||||
"deps/nghttp2",
|
||||
"deps/postject",
|
||||
@@ -178,7 +177,17 @@ template("node_gn_build") {
|
||||
@@ -183,7 +182,17 @@ template("node_gn_build") {
|
||||
configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
|
||||
configs += [ "//build/config/gcc:symbol_visibility_default" ]
|
||||
}
|
||||
@@ -61,7 +44,7 @@ index 3d8b7957e791ce2fa2a8d0937a87b6010087803d..c23922a301a721662ff34bf6e54fd26b
|
||||
if (v8_enable_i18n_support) {
|
||||
deps += [ "//third_party/icu" ]
|
||||
}
|
||||
@@ -205,6 +214,19 @@ template("node_gn_build") {
|
||||
@@ -210,6 +219,19 @@ template("node_gn_build") {
|
||||
sources += node_inspector.node_inspector_sources +
|
||||
node_inspector.node_inspector_generated_sources
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ V8 requires C++20 support as of https://chromium-review.googlesource.com/c/v8/v8
|
||||
This can be removed when Electron upgrades to a version of Node.js containing the required V8 version.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 74616453e2e047acbb9e25f2f93ebeab06011669..bce15fc4a8b3f2fa0b5a588e6a2b28d2b8b6ac45 100644
|
||||
index 34aaf439936c874bd4c8b7d4ffd69477abb40193..69d10c17ef3c5b0ce6173d1754a975df589d9b61 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -518,7 +518,7 @@
|
||||
|
||||
@@ -264,27 +264,25 @@ index 18e4f43efaae3a60b924e697918867e604513194..7cbaf01235750138c680c8ec2ed5d206
|
||||
uint32_t current_chunk_seq_ = 1;
|
||||
uint32_t id_;
|
||||
diff --git a/src/tracing/node_trace_writer.cc b/src/tracing/node_trace_writer.cc
|
||||
index 8f053efe93324b9acbb4e85f7b974b4f7712e200..e331ed5567caa39ade90ce28cea69f1d10533812 100644
|
||||
index 8f053efe93324b9acbb4e85f7b974b4f7712e200..1801594e727ec7a2ef3b89603975f507078b88a1 100644
|
||||
--- a/src/tracing/node_trace_writer.cc
|
||||
+++ b/src/tracing/node_trace_writer.cc
|
||||
@@ -95,7 +95,7 @@ void NodeTraceWriter::OpenNewFileForStreaming() {
|
||||
fd_ = -1;
|
||||
@@ -96,6 +96,7 @@ void NodeTraceWriter::OpenNewFileForStreaming() {
|
||||
}
|
||||
}
|
||||
-
|
||||
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
void NodeTraceWriter::AppendTraceEvent(TraceObject* trace_event) {
|
||||
Mutex::ScopedLock scoped_lock(stream_mutex_);
|
||||
// If this is the first trace event, open a new file for streaming.
|
||||
@@ -112,7 +112,7 @@ void NodeTraceWriter::AppendTraceEvent(TraceObject* trace_event) {
|
||||
@@ -112,6 +113,7 @@ void NodeTraceWriter::AppendTraceEvent(TraceObject* trace_event) {
|
||||
++total_traces_;
|
||||
json_trace_writer_->AppendTraceEvent(trace_event);
|
||||
}
|
||||
-
|
||||
+#endif
|
||||
|
||||
void NodeTraceWriter::FlushPrivate() {
|
||||
std::string str;
|
||||
int highest_request_id;
|
||||
diff --git a/src/tracing/node_trace_writer.h b/src/tracing/node_trace_writer.h
|
||||
index cd965d77b7859ff2edcf781a934594b5a9b6d251..fe1714ba77fddef693d37eeb8c7a196ddfd15c26 100644
|
||||
--- a/src/tracing/node_trace_writer.h
|
||||
@@ -300,7 +298,7 @@ index cd965d77b7859ff2edcf781a934594b5a9b6d251..fe1714ba77fddef693d37eeb8c7a196d
|
||||
|
||||
static const int kTracesPerFile = 1 << 19;
|
||||
diff --git a/src/tracing/trace_event.h b/src/tracing/trace_event.h
|
||||
index be0f55a409a71bf9c1763c36fdc252857228742e..827b5330b2f8c545338a46c548f8abf4aab7f50c 100644
|
||||
index a662a081dc3bf356bf93e4063fcb043e4d8df07b..c89cdfe2b2681fbf9946200a03d7d1f7bad21226 100644
|
||||
--- a/src/tracing/trace_event.h
|
||||
+++ b/src/tracing/trace_event.h
|
||||
@@ -69,8 +69,16 @@ enum CategoryGroupEnabledFlags {
|
||||
@@ -336,21 +334,23 @@ index be0f55a409a71bf9c1763c36fdc252857228742e..827b5330b2f8c545338a46c548f8abf4
|
||||
|
||||
// Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method
|
||||
// on the convertable value will be called at flush time.
|
||||
@@ -319,10 +332,13 @@ class TraceEventHelper {
|
||||
@@ -319,12 +332,15 @@ class TraceEventHelper {
|
||||
static void SetAgent(Agent* agent);
|
||||
|
||||
static inline const uint8_t* GetCategoryGroupEnabled(const char* group) {
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
v8::TracingController* controller = GetTracingController();
|
||||
static const uint8_t disabled = 0;
|
||||
if (UNLIKELY(controller == nullptr)) return &disabled;
|
||||
if (controller == nullptr) [[unlikely]] {
|
||||
return &disabled;
|
||||
}
|
||||
return controller->GetCategoryGroupEnabled(group);
|
||||
+#endif
|
||||
+ return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -460,6 +476,7 @@ static inline uint64_t AddTraceEventImpl(
|
||||
@@ -462,6 +478,7 @@ static inline uint64_t AddTraceEventImpl(
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values, unsigned int flags) {
|
||||
@@ -358,14 +358,7 @@ index be0f55a409a71bf9c1763c36fdc252857228742e..827b5330b2f8c545338a46c548f8abf4
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2];
|
||||
if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
|
||||
arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -469,13 +486,14 @@ static inline uint64_t AddTraceEventImpl(
|
||||
arg_convertibles[1].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
static_cast<intptr_t>(arg_values[1])));
|
||||
}
|
||||
- // DCHECK(num_args, 2);
|
||||
v8::TracingController* controller =
|
||||
node::tracing::TraceEventHelper::GetTracingController();
|
||||
if (controller == nullptr) return 0;
|
||||
@@ -478,6 +495,8 @@ static inline uint64_t AddTraceEventImpl(
|
||||
return controller->AddTraceEvent(phase, category_group_enabled, name, scope, id,
|
||||
bind_id, num_args, arg_names, arg_types,
|
||||
arg_values, arg_convertibles, flags);
|
||||
@@ -374,25 +367,18 @@ index be0f55a409a71bf9c1763c36fdc252857228742e..827b5330b2f8c545338a46c548f8abf4
|
||||
}
|
||||
|
||||
static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
@@ -483,6 +501,7 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
@@ -485,6 +504,7 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
const char* scope, uint64_t id, uint64_t bind_id, int32_t num_args,
|
||||
const char** arg_names, const uint8_t* arg_types,
|
||||
const uint64_t* arg_values, unsigned int flags, int64_t timestamp) {
|
||||
+#ifndef V8_USE_PERFETTO
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertables[2];
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2];
|
||||
if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
|
||||
arg_convertables[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -492,19 +511,21 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
arg_convertables[1].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
static_cast<intptr_t>(arg_values[1])));
|
||||
}
|
||||
- // DCHECK_LE(num_args, 2);
|
||||
v8::TracingController* controller =
|
||||
node::tracing::TraceEventHelper::GetTracingController();
|
||||
if (controller == nullptr) return 0;
|
||||
arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -501,12 +521,15 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
return controller->AddTraceEventWithTimestamp(
|
||||
phase, category_group_enabled, name, scope, id, bind_id, num_args,
|
||||
arg_names, arg_types, arg_values, arg_convertables, flags, timestamp);
|
||||
arg_names, arg_types, arg_values, arg_convertibles, flags, timestamp);
|
||||
+#endif
|
||||
+ return 0;
|
||||
}
|
||||
@@ -405,7 +391,7 @@ index be0f55a409a71bf9c1763c36fdc252857228742e..827b5330b2f8c545338a46c548f8abf4
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertibles[2];
|
||||
if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
|
||||
arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -520,6 +541,7 @@ static V8_INLINE void AddMetadataEventImpl(
|
||||
@@ -522,6 +545,7 @@ static V8_INLINE void AddMetadataEventImpl(
|
||||
return agent->GetTracingController()->AddMetadataEvent(
|
||||
category_group_enabled, name, num_args, arg_names, arg_types, arg_values,
|
||||
arg_convertibles, flags);
|
||||
|
||||
@@ -7,7 +7,7 @@ Subject: build: ensure native module compilation fails if not using a new
|
||||
This should not be upstreamed, it is a quality-of-life patch for downstream module builders.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 229cb96c1385c597138719f2b01f78bd54ad44ab..74616453e2e047acbb9e25f2f93ebeab06011669 100644
|
||||
index cfb1fd6b53715dd2a39ab58b6a3bee0d8aef12bc..34aaf439936c874bd4c8b7d4ffd69477abb40193 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -86,6 +86,8 @@
|
||||
@@ -40,7 +40,7 @@ index 229cb96c1385c597138719f2b01f78bd54ad44ab..74616453e2e047acbb9e25f2f93ebeab
|
||||
# list in v8/BUILD.gn.
|
||||
['v8_enable_v8_checks == 1', {
|
||||
diff --git a/configure.py b/configure.py
|
||||
index d03db1970fd7a1629a7a7719a5ff267402ab4a66..ce055fb5dfc84c75c486b99f01fea6b9531ff54b 100755
|
||||
index c4653f37f5a69b7cdbd6e4c32e0717ab40a00994..88db584318a4b0f95539baf1d0895d6039fb25ca 100755
|
||||
--- a/configure.py
|
||||
+++ b/configure.py
|
||||
@@ -1634,6 +1634,7 @@ def configure_library(lib, output, pkgname=None):
|
||||
|
||||
@@ -34,7 +34,7 @@ index f5ecc15159f457cd0b8069c0427b7c758c916c4e..c9ce67391f321989b0af48159b4da3ab
|
||||
let kResistStopPropagation;
|
||||
|
||||
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
|
||||
index 48d29a0d05538cd1d992f3f086d826e78d0d8882..8987234c2d08449242b5fd037ed314b725bc42a5 100644
|
||||
index 599b59873dbb17ae5e7463403859e088ffb86cda..d23cb087de5cb3cd02ef0542fd2f34207f967ad2 100644
|
||||
--- a/src/node_builtins.cc
|
||||
+++ b/src/node_builtins.cc
|
||||
@@ -34,6 +34,7 @@ using v8::Value;
|
||||
|
||||
@@ -11,7 +11,7 @@ node-gyp will use the result of `process.config` that reflects the environment
|
||||
in which the binary got built.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index bce15fc4a8b3f2fa0b5a588e6a2b28d2b8b6ac45..289ab5d282e93c795eafb5fb992c3bbc4790a687 100644
|
||||
index 69d10c17ef3c5b0ce6173d1754a975df589d9b61..2e3a04e90a6bb32b3437780502cf45a7acad75c0 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -125,6 +125,7 @@
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: build: use third_party/simdutf
|
||||
use the Chromium version of simdutf to avoid duplicate symbols
|
||||
|
||||
diff --git a/node.gni b/node.gni
|
||||
index 99ec540ec41ddf5682eed7618ba87d6935b3b982..274e627fe27b318218f10e982ca5a0773a9075a5 100644
|
||||
index 461bff93e151c454cd0a9575daa01d3f7c0ec9c3..a1eab549b8686c24399f5206f9b611bcbce3d470 100644
|
||||
--- a/node.gni
|
||||
+++ b/node.gni
|
||||
@@ -12,6 +12,8 @@ declare_args() {
|
||||
@@ -19,10 +19,10 @@ index 99ec540ec41ddf5682eed7618ba87d6935b3b982..274e627fe27b318218f10e982ca5a077
|
||||
node_module_version = exec_script("$node_path/tools/getmoduleversion.py", [], "value")
|
||||
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index c23922a301a721662ff34bf6e54fd26b41f25ccc..988dd1d73e72ccd3a6eb10b326b8dc7fcd8e257b 100644
|
||||
index 87bfc313dd1408e597e929ba93c8c0f52ae39ced..4ef97ab65bdfacca4d6dbbc603da0218214b039d 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -150,7 +150,7 @@ template("node_gn_build") {
|
||||
@@ -155,7 +155,7 @@ template("node_gn_build") {
|
||||
"deps/nbytes",
|
||||
"deps/nghttp2",
|
||||
"deps/postject",
|
||||
@@ -31,7 +31,7 @@ index c23922a301a721662ff34bf6e54fd26b41f25ccc..988dd1d73e72ccd3a6eb10b326b8dc7f
|
||||
"deps/sqlite",
|
||||
"deps/uvwasi",
|
||||
"//third_party/zlib",
|
||||
@@ -305,7 +305,7 @@ template("node_gn_build") {
|
||||
@@ -310,7 +310,7 @@ template("node_gn_build") {
|
||||
executable("node_js2c") {
|
||||
defines = []
|
||||
deps = [
|
||||
@@ -40,7 +40,7 @@ index c23922a301a721662ff34bf6e54fd26b41f25ccc..988dd1d73e72ccd3a6eb10b326b8dc7f
|
||||
"deps/uv",
|
||||
]
|
||||
sources = [
|
||||
@@ -412,7 +412,7 @@ template("node_gn_build") {
|
||||
@@ -417,7 +417,7 @@ template("node_gn_build") {
|
||||
"deps/googletest",
|
||||
"deps/googletest:gtest_main",
|
||||
"deps/nbytes",
|
||||
|
||||
@@ -8,7 +8,7 @@ they use themselves as the entry point. We should try to upstream some form
|
||||
of this.
|
||||
|
||||
diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js
|
||||
index d49941881e6cfd8647a6d44a57e0daaf1c874702..f696fb263b356a76b87cd4b6c4b1a0fd60a84afd 100644
|
||||
index ad8d41a06bde1ca22d0245fa49143e080365b5e1..69d7743767d025453e43d99b32235700d8122c9a 100644
|
||||
--- a/lib/internal/modules/cjs/loader.js
|
||||
+++ b/lib/internal/modules/cjs/loader.js
|
||||
@@ -1518,6 +1518,13 @@ Module.prototype._compile = function(content, filename, format) {
|
||||
@@ -26,10 +26,10 @@ index d49941881e6cfd8647a6d44a57e0daaf1c874702..f696fb263b356a76b87cd4b6c4b1a0fd
|
||||
try {
|
||||
resolvedArgv = Module._resolveFilename(process.argv[1], null, false);
|
||||
diff --git a/lib/internal/process/pre_execution.js b/lib/internal/process/pre_execution.js
|
||||
index cb96fd1bc4fcdce750ce241ee5f47f2ae39cfdc6..c46b270109697f7cc1683f8f9f463575e5040216 100644
|
||||
index 848ff7f142fc700dd3b4b7a6b14d3c537e0fd280..be3018296dd3c63a930328fa9cb1d902cc779b89 100644
|
||||
--- a/lib/internal/process/pre_execution.js
|
||||
+++ b/lib/internal/process/pre_execution.js
|
||||
@@ -243,12 +243,14 @@ function patchProcessObject(expandArgv1) {
|
||||
@@ -245,12 +245,14 @@ function patchProcessObject(expandArgv1) {
|
||||
if (expandArgv1 && process.argv[1] &&
|
||||
!StringPrototypeStartsWith(process.argv[1], '-')) {
|
||||
// Expand process.argv[1] into a full path.
|
||||
|
||||
@@ -11,7 +11,7 @@ its own blended handler between Node and Blink.
|
||||
Not upstreamable.
|
||||
|
||||
diff --git a/lib/internal/modules/esm/utils.js b/lib/internal/modules/esm/utils.js
|
||||
index d393d4336a0c1e681e4f6b4e5c7cf2bcc5fc287e..807cb5172e0c2178b6c20e81f8175141d3a0284f 100644
|
||||
index 2799af0f8dd4923ef5ccd372922ea39a66f93470..3012ea1da2db6b22dc6c6a1cac12ec4c5b44487a 100644
|
||||
--- a/lib/internal/modules/esm/utils.js
|
||||
+++ b/lib/internal/modules/esm/utils.js
|
||||
@@ -30,7 +30,7 @@ const {
|
||||
@@ -23,7 +23,7 @@ index d393d4336a0c1e681e4f6b4e5c7cf2bcc5fc287e..807cb5172e0c2178b6c20e81f8175141
|
||||
const {
|
||||
loadPreloadModules,
|
||||
initializeFrozenIntrinsics,
|
||||
@@ -273,12 +273,13 @@ let _forceDefaultLoader = false;
|
||||
@@ -276,12 +276,13 @@ let _forceDefaultLoader = false;
|
||||
* @param {boolean} [forceDefaultLoader=false] - A boolean indicating disabling custom loaders.
|
||||
*/
|
||||
function initializeESM(forceDefaultLoader = false) {
|
||||
@@ -40,7 +40,7 @@ index d393d4336a0c1e681e4f6b4e5c7cf2bcc5fc287e..807cb5172e0c2178b6c20e81f8175141
|
||||
|
||||
/**
|
||||
diff --git a/src/module_wrap.cc b/src/module_wrap.cc
|
||||
index 48b61e8b7600701c4992a98ff802614ce915faee..4e9835e502a8d078a448aa4253f37de0f49f4854 100644
|
||||
index e2252639cf45184b72ebe669f7603bd5e6d92b9a..05353281c0a773d5cf5585cb1698126e17f677a0 100644
|
||||
--- a/src/module_wrap.cc
|
||||
+++ b/src/module_wrap.cc
|
||||
@@ -813,7 +813,7 @@ MaybeLocal<Module> ModuleWrap::ResolveModuleCallback(
|
||||
|
||||
@@ -18,10 +18,10 @@ Reviewed-By: Michaël Zasso <targos@protonmail.com>
|
||||
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
|
||||
|
||||
diff --git a/doc/api/cli.md b/doc/api/cli.md
|
||||
index 0cfed4a4a91a3d3fb5aee6c9a4db3405ba836565..61d980a12fcf7c799e726e1462c65ce478a8ed0c 100644
|
||||
index 62d3d37a061f787babe44649143d45010ce90011..1f614cabf0f31d7adff9dd7a039ca591d805d3bd 100644
|
||||
--- a/doc/api/cli.md
|
||||
+++ b/doc/api/cli.md
|
||||
@@ -3151,7 +3151,6 @@ V8 options that are allowed are:
|
||||
@@ -3177,7 +3177,6 @@ V8 options that are allowed are:
|
||||
* `--disallow-code-generation-from-strings`
|
||||
* `--enable-etw-stack-walking`
|
||||
* `--expose-gc`
|
||||
@@ -30,10 +30,10 @@ index 0cfed4a4a91a3d3fb5aee6c9a4db3405ba836565..61d980a12fcf7c799e726e1462c65ce4
|
||||
* `--jitless`
|
||||
* `--max-old-space-size`
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 4b3f7751db2871c8ce76b197a84a2417097030ea..21e53e1053fe2e4194d91b27a726d3a1306b1683 100644
|
||||
index 6f9a8d3e0884bc6e356413f2f39522a7109c86b5..ccf740bfd631aca608244b6b3998177ca5f47f75 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -922,11 +922,6 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
|
||||
@@ -929,11 +929,6 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
|
||||
"disallow eval and friends",
|
||||
V8Option{},
|
||||
kAllowedInEnvvar);
|
||||
@@ -46,10 +46,10 @@ index 4b3f7751db2871c8ce76b197a84a2417097030ea..21e53e1053fe2e4194d91b27a726d3a1
|
||||
"disable runtime allocation of executable memory",
|
||||
V8Option{},
|
||||
diff --git a/test/parallel/test-cli-node-options.js b/test/parallel/test-cli-node-options.js
|
||||
index e898a81af09ca6852ddc866310e5b8e0dc82971b..22d5a342df5d55f065383a6ebe1aebe59dc0f8d2 100644
|
||||
index 03ffe7aa03f48156f04bb527316221ec10e7e0df..69bf136559c1a8a18a7bfc444a439d161f622635 100644
|
||||
--- a/test/parallel/test-cli-node-options.js
|
||||
+++ b/test/parallel/test-cli-node-options.js
|
||||
@@ -70,7 +70,6 @@ if (common.hasCrypto) {
|
||||
@@ -72,7 +72,6 @@ if (common.hasCrypto) {
|
||||
expect('--abort_on-uncaught_exception', 'B\n');
|
||||
expect('--disallow-code-generation-from-strings', 'B\n');
|
||||
expect('--expose-gc', 'B\n');
|
||||
|
||||
@@ -8,7 +8,7 @@ to child processes spawned with `ELECTRON_RUN_AS_NODE` which is used
|
||||
by the crashpad client to connect with the handler process.
|
||||
|
||||
diff --git a/lib/child_process.js b/lib/child_process.js
|
||||
index 580a441a803bdd0b57871c0cdd8af576f11609b1..755712d24219de7ffe491957d941df7c8cf7baad 100644
|
||||
index 51fc6fe995d3cf8c70ad7bc3cecf1cc00f190b08..012ad108f44b73346d19d927afc78b57c18b7718 100644
|
||||
--- a/lib/child_process.js
|
||||
+++ b/lib/child_process.js
|
||||
@@ -61,6 +61,7 @@ let debug = require('internal/util/debuglog').debuglog(
|
||||
@@ -27,7 +27,7 @@ index 580a441a803bdd0b57871c0cdd8af576f11609b1..755712d24219de7ffe491957d941df7c
|
||||
args = [...execArgv, modulePath, ...args];
|
||||
|
||||
if (typeof options.stdio === 'string') {
|
||||
@@ -617,6 +617,22 @@ function normalizeSpawnArguments(file, args, options) {
|
||||
@@ -615,6 +615,22 @@ function normalizeSpawnArguments(file, args, options) {
|
||||
'options.windowsVerbatimArguments');
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ index 580a441a803bdd0b57871c0cdd8af576f11609b1..755712d24219de7ffe491957d941df7c
|
||||
if (options.shell) {
|
||||
validateArgumentNullCheck(options.shell, 'options.shell');
|
||||
const command = ArrayPrototypeJoin([file, ...args], ' ');
|
||||
@@ -650,7 +666,6 @@ function normalizeSpawnArguments(file, args, options) {
|
||||
@@ -648,7 +664,6 @@ function normalizeSpawnArguments(file, args, options) {
|
||||
ArrayPrototypeUnshift(args, file);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ common.gypi is a file that's included in the node header bundle, despite
|
||||
the fact that we do not build node with gyp.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index a97e77860e151f5126515d65ef99b34aa7301f76..229cb96c1385c597138719f2b01f78bd54ad44ab 100644
|
||||
index de83a566724a36fff8b0c4ca9ba7e151a8c39f54..cfb1fd6b53715dd2a39ab58b6a3bee0d8aef12bc 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -88,6 +88,23 @@
|
||||
|
||||
@@ -44,10 +44,10 @@ index 59b5a16f1309a5e4055bccfdb7a529045ad30402..bfdaf6211466a01b64b7942f7b16c480
|
||||
let filename = call.getFileName();
|
||||
const line = call.getLineNumber() - 1;
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index f59abcb21d64b910d8d42eb23c03109f62558813..1b6613d1de8c89c8271066a652afd1024988362d 100644
|
||||
index 89ce587cac4506c4218a9316fe0b68070a7a8504..b74fb837fc1cfee839c8b5b8c0b9a6f805881206 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -244,6 +244,9 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
@@ -247,6 +247,9 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
auto* prepare_stack_trace_cb = s.prepare_stack_trace_callback ?
|
||||
s.prepare_stack_trace_callback : PrepareStackTraceCallback;
|
||||
isolate->SetPrepareStackTraceCallback(prepare_stack_trace_cb);
|
||||
@@ -58,10 +58,10 @@ index f59abcb21d64b910d8d42eb23c03109f62558813..1b6613d1de8c89c8271066a652afd102
|
||||
}
|
||||
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 29630fcccc3bd9d24ad6aec64bef2fedfc3c4031..4b3f7751db2871c8ce76b197a84a2417097030ea 100644
|
||||
index 3c42f9b87c11a0f88800d6709515c1c9e2972fc0..6f9a8d3e0884bc6e356413f2f39522a7109c86b5 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -1464,14 +1464,16 @@ void GetEmbedderOptions(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1476,14 +1476,16 @@ void GetEmbedderOptions(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
Isolate* isolate = args.GetIsolate();
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ before it's acceptable to upstream, as this patch comments out a couple
|
||||
of tests that upstream probably cares about.
|
||||
|
||||
diff --git a/test/common/index.js b/test/common/index.js
|
||||
index 172cdb6b049824539a9850789e0e7c5baf613367..c29abc18191aec78ad8eb810093a9a4ef9e854e4 100644
|
||||
index b95e812c5a9fab59f742e1557e9f218155638af4..6d2566c43f16493cbb2a0f9469ed386c41686782 100644
|
||||
--- a/test/common/index.js
|
||||
+++ b/test/common/index.js
|
||||
@@ -65,6 +65,8 @@ const opensslVersionNumber = (major = 0, minor = 0, patch = 0) => {
|
||||
@@ -23,7 +23,7 @@ index 172cdb6b049824539a9850789e0e7c5baf613367..c29abc18191aec78ad8eb810093a9a4e
|
||||
let OPENSSL_VERSION_NUMBER;
|
||||
const hasOpenSSL = (major = 0, minor = 0, patch = 0) => {
|
||||
if (!hasCrypto) return false;
|
||||
@@ -996,6 +998,7 @@ const common = {
|
||||
@@ -1008,6 +1010,7 @@ const common = {
|
||||
mustNotMutateObjectDeep,
|
||||
mustSucceed,
|
||||
nodeProcessAborted,
|
||||
@@ -395,7 +395,7 @@ index 338a19b0e88ad6f08d2f6b6a5d38b9980996ce11..a4ee215575d072450ba66c558ddca88b
|
||||
};
|
||||
assert.throws(() => crypto.scrypt('pass', 'salt', 1, options, () => {}),
|
||||
diff --git a/test/parallel/test-crypto-sign-verify.js b/test/parallel/test-crypto-sign-verify.js
|
||||
index 9dd586a1a1f9a00d9bb0af5b0532e81e7b96a5ce..a37e6d50914345829c8260a97949cee7d17ab676 100644
|
||||
index 8a263ec3350f5540591ac02e70fa2f552b9ac477..dcc4c2ec816d28f1b27df1c358cfce66f1a3a03b 100644
|
||||
--- a/test/parallel/test-crypto-sign-verify.js
|
||||
+++ b/test/parallel/test-crypto-sign-verify.js
|
||||
@@ -29,7 +29,7 @@ const keySize = 2048;
|
||||
@@ -471,10 +471,21 @@ index 008ab129f0e019c659eecf5a76b7eb412c947fe3..6688f5d916f50e1e4fcfff1619c8634a
|
||||
|
||||
cipher.end('Papaya!'); // Should not cause an unhandled exception.
|
||||
diff --git a/test/parallel/test-crypto-x509.js b/test/parallel/test-crypto-x509.js
|
||||
index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f639056b21ee3b 100644
|
||||
index 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9900fb816 100644
|
||||
--- a/test/parallel/test-crypto-x509.js
|
||||
+++ b/test/parallel/test-crypto-x509.js
|
||||
@@ -111,7 +111,7 @@ const der = Buffer.from(
|
||||
@@ -96,8 +96,10 @@ const der = Buffer.from(
|
||||
assert.strictEqual(x509.infoAccess, infoAccessCheck);
|
||||
assert.strictEqual(x509.validFrom, 'Sep 3 21:40:37 2022 GMT');
|
||||
assert.strictEqual(x509.validTo, 'Jun 17 21:40:37 2296 GMT');
|
||||
+ if (!common.openSSLIsBoringSSL) {
|
||||
assert.deepStrictEqual(x509.validFromDate, new Date('2022-09-03T21:40:37Z'));
|
||||
assert.deepStrictEqual(x509.validToDate, new Date('2296-06-17T21:40:37Z'));
|
||||
+ }
|
||||
assert.strictEqual(
|
||||
x509.fingerprint,
|
||||
'8B:89:16:C4:99:87:D2:13:1A:64:94:36:38:A5:32:01:F0:95:3B:53');
|
||||
@@ -113,7 +115,7 @@ const der = Buffer.from(
|
||||
'5A:42:63:E0:21:2F:D6:70:63:07:96:6F:27:A7:78:12:08:02:7A:8B'
|
||||
);
|
||||
assert.strictEqual(x509.keyUsage, undefined);
|
||||
@@ -483,7 +494,7 @@ index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f63905
|
||||
|
||||
assert.deepStrictEqual(x509.raw, der);
|
||||
|
||||
@@ -253,6 +253,16 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -255,6 +257,16 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
});
|
||||
mc.port2.postMessage(x509);
|
||||
|
||||
@@ -500,7 +511,7 @@ index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f63905
|
||||
// Verify that legacy encoding works
|
||||
const legacyObjectCheck = {
|
||||
subject: Object.assign({ __proto__: null }, {
|
||||
@@ -277,15 +287,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -279,15 +291,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
'OCSP - URI': ['http://ocsp.nodejs.org/'],
|
||||
'CA Issuers - URI': ['http://ca.nodejs.org/ca.cert']
|
||||
}),
|
||||
@@ -517,7 +528,7 @@ index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f63905
|
||||
bits: 2048,
|
||||
exponent: '0x10001',
|
||||
valid_from: 'Sep 3 21:40:37 2022 GMT',
|
||||
@@ -298,7 +300,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -300,7 +304,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
'51:62:18:39:E2:E2:77:F5:86:11:E8:C0:CA:54:43:7C:76:83:19:05:D0:03:' +
|
||||
'24:21:B8:EB:14:61:FB:24:16:EB:BD:51:1A:17:91:04:30:03:EB:68:5F:DC:' +
|
||||
'86:E1:D1:7C:FB:AF:78:ED:63:5F:29:9C:32:AF:A1:8E:22:96:D1:02',
|
||||
@@ -526,7 +537,7 @@ index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f63905
|
||||
};
|
||||
|
||||
const legacyObject = x509.toLegacyObject();
|
||||
@@ -307,7 +309,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -309,7 +313,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
assert.deepStrictEqual(legacyObject.subject, legacyObjectCheck.subject);
|
||||
assert.deepStrictEqual(legacyObject.issuer, legacyObjectCheck.issuer);
|
||||
assert.deepStrictEqual(legacyObject.infoAccess, legacyObjectCheck.infoAccess);
|
||||
@@ -535,7 +546,7 @@ index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f63905
|
||||
assert.strictEqual(legacyObject.bits, legacyObjectCheck.bits);
|
||||
assert.strictEqual(legacyObject.exponent, legacyObjectCheck.exponent);
|
||||
assert.strictEqual(legacyObject.valid_from, legacyObjectCheck.valid_from);
|
||||
@@ -316,11 +318,12 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -318,11 +322,12 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
assert.strictEqual(
|
||||
legacyObject.fingerprint256,
|
||||
legacyObjectCheck.fingerprint256);
|
||||
@@ -546,17 +557,40 @@ index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f63905
|
||||
+ legacyObjectCheck.serialNumberPattern);
|
||||
}
|
||||
|
||||
+/*
|
||||
+if (!common.openSSLIsBoringSSL) {
|
||||
{
|
||||
// This X.509 Certificate can be parsed by OpenSSL because it contains a
|
||||
// structurally sound TBSCertificate structure. However, the SPKI field of the
|
||||
@@ -359,3 +362,4 @@ UcXd/5qu2GhokrKU2cPttU+XAN2Om6a0
|
||||
@@ -361,6 +366,7 @@ UcXd/5qu2GhokrKU2cPttU+XAN2Om6a0
|
||||
|
||||
assert.strictEqual(cert.checkIssued(cert), false);
|
||||
}
|
||||
+*/
|
||||
+}
|
||||
|
||||
{
|
||||
// Test date parsing of `validFromDate` and `validToDate` fields, according to RFC 5280.
|
||||
@@ -398,8 +404,10 @@ UidvpWWipVLZgK+oDks+bKTobcoXGW9oXobiIYqslXPy
|
||||
-----END CERTIFICATE-----`.trim();
|
||||
const c1 = new X509Certificate(certPemUTCTime);
|
||||
|
||||
+ if (!common.openSSLIsBoringSSL) {
|
||||
assert.deepStrictEqual(c1.validFromDate, new Date('1949-12-25T23:59:58Z'));
|
||||
assert.deepStrictEqual(c1.validToDate, new Date('1950-01-01T23:59:58Z'));
|
||||
+ }
|
||||
|
||||
// The GeneralizedTime format is used for dates in 2050 or later.
|
||||
const certPemGeneralizedTime = `-----BEGIN CERTIFICATE-----
|
||||
@@ -433,6 +441,8 @@ CWwQO8JZjJqFtqtuzy2n+gLCvqePgG/gmSqHOPm2ZbLW
|
||||
-----END CERTIFICATE-----`.trim();
|
||||
const c2 = new X509Certificate(certPemGeneralizedTime);
|
||||
|
||||
+ if (!common.openSSLIsBoringSSL) {
|
||||
assert.deepStrictEqual(c2.validFromDate, new Date('2049-12-26T00:00:01Z'));
|
||||
assert.deepStrictEqual(c2.validToDate, new Date('2050-01-02T00:00:01Z'));
|
||||
+ }
|
||||
}
|
||||
diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js
|
||||
index 4271121881379b6c6892e89e520345f77e4181df..6c87a1ac687aa37d4ba245d1b6fc746a5f1eeffc 100644
|
||||
index 4271121881379b6c6892e89e520345f77e4181df..7a17285deee18ffbccf1d01d9d1b7b87e561bffa 100644
|
||||
--- a/test/parallel/test-crypto.js
|
||||
+++ b/test/parallel/test-crypto.js
|
||||
@@ -61,7 +61,7 @@ assert.throws(() => {
|
||||
@@ -595,23 +629,14 @@ index 4271121881379b6c6892e89e520345f77e4181df..6c87a1ac687aa37d4ba245d1b6fc746a
|
||||
validateList(crypto.getHashes());
|
||||
// Make sure all of the hashes are supported by OpenSSL
|
||||
for (const algo of crypto.getHashes())
|
||||
@@ -195,7 +193,7 @@ assert.throws(
|
||||
return true;
|
||||
@@ -196,6 +194,7 @@ assert.throws(
|
||||
}
|
||||
);
|
||||
-
|
||||
+/*
|
||||
|
||||
+if (!common.openSSLIsBoringSSL) {
|
||||
assert.throws(() => {
|
||||
const priv = [
|
||||
'-----BEGIN RSA PRIVATE KEY-----',
|
||||
@@ -208,6 +206,7 @@ assert.throws(() => {
|
||||
].join('\n');
|
||||
crypto.createSign('SHA256').update('test').sign(priv);
|
||||
}, (err) => {
|
||||
+ console.log(err)
|
||||
if (!common.hasOpenSSL3)
|
||||
assert.ok(!('opensslErrorStack' in err));
|
||||
assert.throws(() => { throw err; }, common.hasOpenSSL3 ? {
|
||||
@@ -216,10 +215,10 @@ assert.throws(() => {
|
||||
library: 'rsa routines',
|
||||
} : {
|
||||
@@ -632,7 +657,7 @@ index 4271121881379b6c6892e89e520345f77e4181df..6c87a1ac687aa37d4ba245d1b6fc746a
|
||||
});
|
||||
}
|
||||
-
|
||||
+*/
|
||||
+}
|
||||
// Make sure memory isn't released before being returned
|
||||
console.log(crypto.randomBytes(16));
|
||||
|
||||
@@ -725,7 +750,7 @@ index b06f2fa2c53ea72f9a66f0d002dd9281d0259a0f..864fffeebfad75d95416fd47efdea7f2
|
||||
|
||||
const server = https.createServer(opts, (req, res) => {
|
||||
diff --git a/test/parallel/test-webcrypto-derivebits.js b/test/parallel/test-webcrypto-derivebits.js
|
||||
index eb09bc24f0cb8244b05987e3a7c1d203360d3a38..011990db171faa708c5211f6ab9ae1ac0e0ab90e 100644
|
||||
index eb09bc24f0cb8244b05987e3a7c1d203360d3a38..8c251ff2371fb59bf679160574e1c5dc1b4b2665 100644
|
||||
--- a/test/parallel/test-webcrypto-derivebits.js
|
||||
+++ b/test/parallel/test-webcrypto-derivebits.js
|
||||
@@ -101,8 +101,9 @@ const { subtle } = globalThis.crypto;
|
||||
@@ -739,11 +764,6 @@ index eb09bc24f0cb8244b05987e3a7c1d203360d3a38..011990db171faa708c5211f6ab9ae1ac
|
||||
async function test(name) {
|
||||
const [alice, bob] = await Promise.all([
|
||||
subtle.generateKey({ name }, true, ['deriveBits']),
|
||||
@@ -126,3 +127,4 @@ const { subtle } = globalThis.crypto;
|
||||
test('X25519').then(common.mustCall());
|
||||
test('X448').then(common.mustCall());
|
||||
}
|
||||
+
|
||||
diff --git a/test/parallel/test-webcrypto-derivekey.js b/test/parallel/test-webcrypto-derivekey.js
|
||||
index 558d37d90d5796b30101d1b512c9df3e7661d0db..f42bf8f4be0b439dd7e7c8d0f6f8a41e01588870 100644
|
||||
--- a/test/parallel/test-webcrypto-derivekey.js
|
||||
|
||||
@@ -19,10 +19,10 @@ index 463e76cb1abc0c2fdddba4db2ca2e00f7c591e12..d7bc3c35c77b5bf9ec122b38248d0cf1
|
||||
context = { __proto__: context, source };
|
||||
}
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index 06b31af80ebbfbf35ec787a94f345775eb512ebf..deca5aa4b8829ba9921440fcb5c285a10e40c8f0 100644
|
||||
index 45a0abc6423a4e53e070f3c117fac2a3554b188d..abd89e9cccba1060f8e76580d5bb338e65a710ea 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -354,6 +354,9 @@ function cjsPreparseModuleExports(filename, source) {
|
||||
@@ -287,6 +287,9 @@ function cjsPreparseModuleExports(filename, source) {
|
||||
if (module && module[kModuleExportNames] !== undefined) {
|
||||
return { module, exportNames: module[kModuleExportNames] };
|
||||
}
|
||||
@@ -33,7 +33,7 @@ index 06b31af80ebbfbf35ec787a94f345775eb512ebf..deca5aa4b8829ba9921440fcb5c285a1
|
||||
if (!loaded) {
|
||||
module = new CJSModule(filename);
|
||||
diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js
|
||||
index 1e1a1ea46fc6c1b43cad4038ab0d9cdf21d6ba3d..95e2fa5479ea31559fdb5a2e03515f243b231b75 100644
|
||||
index ab4783a7982b9feb8fa85b62e3e3b181f93309bd..34f91026451d7347ae278712d083e4fe281e50f3 100644
|
||||
--- a/lib/internal/modules/run_main.js
|
||||
+++ b/lib/internal/modules/run_main.js
|
||||
@@ -2,6 +2,7 @@
|
||||
@@ -58,7 +58,7 @@ index 1e1a1ea46fc6c1b43cad4038ab0d9cdf21d6ba3d..95e2fa5479ea31559fdb5a2e03515f24
|
||||
const defaultType = getOptionValue('--experimental-default-type');
|
||||
/** @type {string} */
|
||||
let mainPath;
|
||||
@@ -63,6 +71,13 @@ function resolveMainPath(main) {
|
||||
@@ -62,6 +70,13 @@ function resolveMainPath(main) {
|
||||
* @param {string} mainPath - Absolute path to the main entry point
|
||||
*/
|
||||
function shouldUseESMLoader(mainPath) {
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: fix: expose the built-in electron module via the ESM loader
|
||||
This allows usage of `import { app } from 'electron'` and `import('electron')` natively in the browser + non-sandboxed renderer
|
||||
|
||||
diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js
|
||||
index a89446df710a941390c15171fea63c551776fc93..912f03bfa96c3aa12bfa6e709746642452568bb7 100644
|
||||
index 26d0bace6cdd3905f1248c5ad3fa794eb272252d..4ec1f4f6951be40f5fcb4c1cb3d1205e69434f23 100644
|
||||
--- a/lib/internal/modules/esm/get_format.js
|
||||
+++ b/lib/internal/modules/esm/get_format.js
|
||||
@@ -26,6 +26,7 @@ const protocolHandlers = {
|
||||
@@ -46,7 +46,7 @@ index 8b157f0f461c7b92c567fffe4d99357dbc09aee7..605e812d515fc467001e4ab88fc15b4a
|
||||
}
|
||||
}
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 1fbbb6773c9479128408fa1f27cf19f1a7786ba6..f05c6f99c0037193c5802024be46a967d6cf47a0 100644
|
||||
index 35925ef0817273948b7a2128c6ddc12c91bc3cfd..ee2cc03892c01141b71571989b18eec387d3c766 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -772,6 +772,8 @@ function parsePackageName(specifier, base) {
|
||||
@@ -71,10 +71,10 @@ index 1fbbb6773c9479128408fa1f27cf19f1a7786ba6..f05c6f99c0037193c5802024be46a967
|
||||
parsePackageName(specifier, base);
|
||||
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index 8f88214f558c52ef26000fb0e1ef4d391327e84e..d182eedf5e96039e0029d36e51f40b75c6fb2a39 100644
|
||||
index 9b89c3e1d52a0f724dab451844d32df67f1eab9f..25ee090bbb4884d3e5f2530cc7153f9215754fae 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -246,7 +246,7 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
@@ -182,7 +182,7 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
|
||||
const { exportNames, module } = cjsPreparseModuleExports(filename, source);
|
||||
cjsCache.set(url, module);
|
||||
@@ -83,7 +83,7 @@ index 8f88214f558c52ef26000fb0e1ef4d391327e84e..d182eedf5e96039e0029d36e51f40b75
|
||||
[...exportNames] : ['default', ...exportNames];
|
||||
|
||||
if (isMain) {
|
||||
@@ -268,8 +268,8 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
@@ -204,8 +204,8 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
({ exports } = module);
|
||||
}
|
||||
for (const exportName of exportNames) {
|
||||
@@ -94,7 +94,7 @@ index 8f88214f558c52ef26000fb0e1ef4d391327e84e..d182eedf5e96039e0029d36e51f40b75
|
||||
continue;
|
||||
}
|
||||
// We might trigger a getter -> dont fail.
|
||||
@@ -304,6 +304,10 @@ translators.set('require-commonjs', (url, source, isMain) => {
|
||||
@@ -239,6 +239,10 @@ translators.set('require-commonjs', (url, source, isMain) => {
|
||||
return createCJSModuleWrap(url, source);
|
||||
});
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ Subject: fix: expose tracing::Agent and use tracing::TracingController instead
|
||||
This API is used by Electron to create Node's tracing controller.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 77c20a4b6b9db414444974f68c5def8788386d2b..5fc1b6f2446d7c786024eb60800e2edab613dcd1 100644
|
||||
index ad323fc800a33c010b0504a4aa55c107498dee26..e044f10284f31f1862b18be752a04b3bd5d53401 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -564,6 +564,10 @@ MultiIsolatePlatform* GetMultiIsolatePlatform(IsolateData* env) {
|
||||
@@ -567,6 +567,10 @@ MultiIsolatePlatform* GetMultiIsolatePlatform(IsolateData* env) {
|
||||
return env->platform();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ Upstreams:
|
||||
- https://github.com/nodejs/node/pull/39136
|
||||
|
||||
diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc
|
||||
index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a44bd88f8e 100644
|
||||
index 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824ca574106 100644
|
||||
--- a/deps/ncrypto/ncrypto.cc
|
||||
+++ b/deps/ncrypto/ncrypto.cc
|
||||
@@ -6,13 +6,11 @@
|
||||
@@ -35,7 +35,7 @@ index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a4
|
||||
|
||||
namespace ncrypto {
|
||||
namespace {
|
||||
@@ -665,7 +663,7 @@ bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
@@ -694,7 +692,7 @@ bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
|
||||
bool ok = true;
|
||||
|
||||
@@ -44,7 +44,7 @@ index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a4
|
||||
GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
|
||||
|
||||
if (i != 0)
|
||||
@@ -691,7 +689,7 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
@@ -720,7 +718,7 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
|
||||
bool ok = true;
|
||||
|
||||
@@ -53,7 +53,25 @@ index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a4
|
||||
ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(descs, i);
|
||||
|
||||
if (i != 0)
|
||||
@@ -1002,7 +1000,11 @@ BIOPointer BIOPointer::NewMem() {
|
||||
@@ -857,13 +855,17 @@ BIOPointer X509View::getValidTo() const {
|
||||
|
||||
int64_t X509View::getValidToTime() const {
|
||||
struct tm tp;
|
||||
+#ifndef OPENSSL_IS_BORINGSSL
|
||||
ASN1_TIME_to_tm(X509_get0_notAfter(cert_), &tp);
|
||||
+#endif
|
||||
return PortableTimeGM(&tp);
|
||||
}
|
||||
|
||||
int64_t X509View::getValidFromTime() const {
|
||||
struct tm tp;
|
||||
+#ifndef OPENSSL_IS_BORINGSSL
|
||||
ASN1_TIME_to_tm(X509_get0_notBefore(cert_), &tp);
|
||||
+#endif
|
||||
return PortableTimeGM(&tp);
|
||||
}
|
||||
|
||||
@@ -1043,7 +1045,11 @@ BIOPointer BIOPointer::NewMem() {
|
||||
}
|
||||
|
||||
BIOPointer BIOPointer::NewSecMem() {
|
||||
@@ -65,7 +83,7 @@ index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a4
|
||||
}
|
||||
|
||||
BIOPointer BIOPointer::New(const BIO_METHOD* method) {
|
||||
@@ -1057,8 +1059,10 @@ BignumPointer DHPointer::FindGroup(const std::string_view name,
|
||||
@@ -1098,8 +1104,10 @@ BignumPointer DHPointer::FindGroup(const std::string_view name,
|
||||
FindGroupOption option) {
|
||||
#define V(n, p) if (EqualNoCase(name, n)) return BignumPointer(p(nullptr));
|
||||
if (option != FindGroupOption::NO_SMALL_PRIMES) {
|
||||
@@ -76,7 +94,7 @@ index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a4
|
||||
V("modp5", BN_get_rfc3526_prime_1536);
|
||||
}
|
||||
V("modp14", BN_get_rfc3526_prime_2048);
|
||||
@@ -1130,11 +1134,13 @@ DHPointer::CheckPublicKeyResult DHPointer::checkPublicKey(const BignumPointer& p
|
||||
@@ -1171,11 +1179,13 @@ DHPointer::CheckPublicKeyResult DHPointer::checkPublicKey(const BignumPointer& p
|
||||
int codes = 0;
|
||||
if (DH_check_pub_key(dh_.get(), pub_key.get(), &codes) != 1)
|
||||
return DHPointer::CheckPublicKeyResult::CHECK_FAILED;
|
||||
@@ -92,10 +110,10 @@ index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a4
|
||||
}
|
||||
return CheckPublicKeyResult::NONE;
|
||||
diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h
|
||||
index 60bfce3ea8999e8e145aaf8cd14f0fdf21ed9c54..55aae783bb57273d1b49927f65b6c0830d09d115 100644
|
||||
index 20b69dc67b13fd4f0bd44f7adf6a0d928a2c10c4..2320f92c50543fb9b426bce1c6d182bddf7658de 100644
|
||||
--- a/deps/ncrypto/ncrypto.h
|
||||
+++ b/deps/ncrypto/ncrypto.h
|
||||
@@ -400,17 +400,21 @@ public:
|
||||
@@ -493,17 +493,21 @@ public:
|
||||
UNABLE_TO_CHECK_GENERATOR = DH_UNABLE_TO_CHECK_GENERATOR,
|
||||
NOT_SUITABLE_GENERATOR = DH_NOT_SUITABLE_GENERATOR,
|
||||
Q_NOT_PRIME = DH_CHECK_Q_NOT_PRIME,
|
||||
@@ -131,7 +149,7 @@ index ea024af73e215b3cad5f08796ac405f419530c86..41061b524eea74330b8d2452635a38c4
|
||||
}
|
||||
}
|
||||
diff --git a/node.gni b/node.gni
|
||||
index 32709b860ccb12d8d1e75342a65dda0b86129b21..18d58591e3d0f1f3512db00033c3410a65702864 100644
|
||||
index 852f64fa9cfb50fe6e9ce7aa46be336d3196d5b8..461bff93e151c454cd0a9575daa01d3f7c0ec9c3 100644
|
||||
--- a/node.gni
|
||||
+++ b/node.gni
|
||||
@@ -10,6 +10,8 @@ declare_args() {
|
||||
@@ -144,10 +162,10 @@ index 32709b860ccb12d8d1e75342a65dda0b86129b21..18d58591e3d0f1f3512db00033c3410a
|
||||
node_module_version = exec_script("$node_path/tools/getmoduleversion.py", [], "value")
|
||||
|
||||
diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc
|
||||
index fe35a8e0f6bbb7ab515a0343a7ed046c44e86474..43a7abbf237d8d809953e302b83755a3283a1bf4 100644
|
||||
index a81ab8e95f2fc23e1e315fb9c69364934377a0c1..dbe12ba2413ef29ff06a7e8abde50000eaf277e2 100644
|
||||
--- a/src/crypto/crypto_cipher.cc
|
||||
+++ b/src/crypto/crypto_cipher.cc
|
||||
@@ -1078,7 +1078,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1080,7 +1080,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) {
|
||||
return ThrowCryptoError(env, ERR_get_error());
|
||||
}
|
||||
@@ -156,7 +174,7 @@ index fe35a8e0f6bbb7ab515a0343a7ed046c44e86474..43a7abbf237d8d809953e302b83755a3
|
||||
int rsa_pkcs1_implicit_rejection =
|
||||
EVP_PKEY_CTX_ctrl_str(ctx.get(), "rsa_pkcs1_implicit_rejection", "1");
|
||||
// From the doc -2 means that the option is not supported.
|
||||
@@ -1094,6 +1094,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1096,6 +1096,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
"RSA_PKCS1_PADDING is no longer supported for private decryption,"
|
||||
" this can be reverted with --security-revert=CVE-2024-PEND");
|
||||
}
|
||||
@@ -165,7 +183,7 @@ index fe35a8e0f6bbb7ab515a0343a7ed046c44e86474..43a7abbf237d8d809953e302b83755a3
|
||||
|
||||
const EVP_MD* digest = nullptr;
|
||||
diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc
|
||||
index 6a967702b22df0eb8aa10e853fd232794955860d..31058cccc6ffeed6b09aaecda320ee2f15849ec8 100644
|
||||
index 43a126f863779d3f364f92bd237039474b489845..77a3caee93049f65faef37e93b871c467ebca7e5 100644
|
||||
--- a/src/crypto/crypto_common.cc
|
||||
+++ b/src/crypto/crypto_common.cc
|
||||
@@ -134,7 +134,7 @@ const char* GetClientHelloALPN(const SSLPointer& ssl) {
|
||||
@@ -254,7 +272,7 @@ index 6a967702b22df0eb8aa10e853fd232794955860d..31058cccc6ffeed6b09aaecda320ee2f
|
||||
crypto::EVPKeyPointer key(raw_key);
|
||||
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index c924a54639e8c22d765dc240dffacfffb200ca0c..287afcc792a0a2b7e19126ee9a48ebe21cc8844e 100644
|
||||
index aa5fc61f19e435b4833f3f49df10fa1edf2142c7..0a338b018a4ec20cb5bce250faf60d3f3bf192d4 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -94,7 +94,7 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
|
||||
@@ -290,7 +308,7 @@ index c924a54639e8c22d765dc240dffacfffb200ca0c..287afcc792a0a2b7e19126ee9a48ebe2
|
||||
|
||||
X509_STORE_add_cert(sc->GetCertStoreOwnedByThisSecureContext(), ca);
|
||||
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
|
||||
index e5664dfa2bc7e11922fa965f28acdf21470d1147..33ffbbb85d05f5356183e3aa1ca23707c5629b5d 100644
|
||||
index d760a0d3ea1d12184a558f5e87cb22043d26a0f5..f973941b3b9ea954f35f2ea135f8ee3d77b98958 100644
|
||||
--- a/src/crypto/crypto_dh.cc
|
||||
+++ b/src/crypto/crypto_dh.cc
|
||||
@@ -7,7 +7,9 @@
|
||||
@@ -375,7 +393,7 @@ index e5664dfa2bc7e11922fa965f28acdf21470d1147..33ffbbb85d05f5356183e3aa1ca23707
|
||||
break;
|
||||
}
|
||||
@@ -398,9 +398,11 @@ EVPKeyCtxPointer DhKeyGenTraits::Setup(DhKeyPairGenConfig* params) {
|
||||
key_params = EVPKeyPointer(EVP_PKEY_new());
|
||||
key_params = EVPKeyPointer::New();
|
||||
CHECK(key_params);
|
||||
CHECK_EQ(EVP_PKEY_assign_DH(key_params.get(), dh.release()), 1);
|
||||
- } else if (int* prime_size = std::get_if<int>(¶ms->params.prime)) {
|
||||
@@ -398,7 +416,7 @@ index e5664dfa2bc7e11922fa965f28acdf21470d1147..33ffbbb85d05f5356183e3aa1ca23707
|
||||
UNREACHABLE();
|
||||
}
|
||||
diff --git a/src/crypto/crypto_dsa.cc b/src/crypto/crypto_dsa.cc
|
||||
index 5d081863cf2dcdcf8c2d09db6060eeb5e78c452f..67523ec1c406e345945e1dde663c784c43a1c624 100644
|
||||
index b557de774117e442d7f429e92d63a6e1faa236fd..0aca233ced39269b09c383e5b32d85cf36260a1e 100644
|
||||
--- a/src/crypto/crypto_dsa.cc
|
||||
+++ b/src/crypto/crypto_dsa.cc
|
||||
@@ -40,7 +40,7 @@ namespace crypto {
|
||||
@@ -422,10 +440,10 @@ index 5d081863cf2dcdcf8c2d09db6060eeb5e78c452f..67523ec1c406e345945e1dde663c784c
|
||||
return EVPKeyCtxPointer();
|
||||
|
||||
diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc
|
||||
index 8488fc57faaf722174032c5a927d150c76120d60..c51efc92d4818ee7701b4725585fb7e1d2d644ad 100644
|
||||
index 6af8d089ca6bcd73aff314638443610b9cc4bf7e..c84cbd5b4708e0c403ab0a1e1ddf5fc72eb3d148 100644
|
||||
--- a/src/crypto/crypto_keys.cc
|
||||
+++ b/src/crypto/crypto_keys.cc
|
||||
@@ -1204,6 +1204,7 @@ void KeyObjectHandle::GetAsymmetricKeyType(
|
||||
@@ -1059,6 +1059,7 @@ void KeyObjectHandle::GetAsymmetricKeyType(
|
||||
}
|
||||
|
||||
bool KeyObjectHandle::CheckEcKeyData() const {
|
||||
@@ -433,7 +451,7 @@ index 8488fc57faaf722174032c5a927d150c76120d60..c51efc92d4818ee7701b4725585fb7e1
|
||||
MarkPopErrorOnReturn mark_pop_error_on_return;
|
||||
|
||||
const auto& key = data_.GetAsymmetricKey();
|
||||
@@ -1220,6 +1221,9 @@ bool KeyObjectHandle::CheckEcKeyData() const {
|
||||
@@ -1075,6 +1076,9 @@ bool KeyObjectHandle::CheckEcKeyData() const {
|
||||
#else
|
||||
return EVP_PKEY_public_check(ctx.get()) == 1;
|
||||
#endif
|
||||
@@ -457,27 +475,25 @@ index b59e394d9a7e2c19fdf1f2b0177753ff488da0fa..91218f49da5392c6f769495ee7f9275a
|
||||
THROW_ERR_CRYPTO_OPERATION_FAILED(env, "could not generate prime");
|
||||
return Nothing<void>();
|
||||
diff --git a/src/crypto/crypto_rsa.cc b/src/crypto/crypto_rsa.cc
|
||||
index 02e8e24b4054afd4c3ca797c19a78927319a0d9e..d2a931a3f8f9490fe17ef8a82d0204ee2cca409d 100644
|
||||
index 6d360554b31d53a597d61fcbd660f703a903ca21..86fafe98222d4c18f062032d80104f3ef00dbc01 100644
|
||||
--- a/src/crypto/crypto_rsa.cc
|
||||
+++ b/src/crypto/crypto_rsa.cc
|
||||
@@ -608,10 +608,11 @@ Maybe<void> GetRsaKeyDetail(Environment* env,
|
||||
@@ -608,10 +608,13 @@ Maybe<void> GetRsaKeyDetail(Environment* env,
|
||||
}
|
||||
|
||||
if (params->saltLength != nullptr) {
|
||||
- if (ASN1_INTEGER_get_int64(&salt_length, params->saltLength) != 1) {
|
||||
- ThrowCryptoError(env, ERR_get_error(), "ASN1_INTEGER_get_in64 error");
|
||||
- return Nothing<void>();
|
||||
- }
|
||||
+#ifndef OPENSSL_IS_BORINGSSL
|
||||
+ // TODO(codebytere): Upstream a shim to BoringSSL?
|
||||
+ // if (ASN1_INTEGER_get_int64(&salt_length, params->saltLength) != 1) {
|
||||
+ // ThrowCryptoError(env, ERR_get_error(), "ASN1_INTEGER_get_in64 error");
|
||||
+ // return Nothing<void>();
|
||||
+ // }
|
||||
if (ASN1_INTEGER_get_int64(&salt_length, params->saltLength) != 1) {
|
||||
ThrowCryptoError(env, ERR_get_error(), "ASN1_INTEGER_get_in64 error");
|
||||
return Nothing<void>();
|
||||
}
|
||||
+#endif
|
||||
}
|
||||
|
||||
if (target
|
||||
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
|
||||
index 793c196f8ce538c66b20611d00e12392ff9e878b..ee81048caab4ccfe26ea9e677782c9c955d162a9 100644
|
||||
index 12ee0cde0897024bccb0face49053544a0bcfcd7..8a6a36a3c31532ed585c287ba8cee14026d315b4 100644
|
||||
--- a/src/crypto/crypto_util.cc
|
||||
+++ b/src/crypto/crypto_util.cc
|
||||
@@ -495,24 +495,15 @@ Maybe<void> Decorate(Environment* env,
|
||||
@@ -538,7 +554,7 @@ index 793c196f8ce538c66b20611d00e12392ff9e878b..ee81048caab4ccfe26ea9e677782c9c9
|
||||
} // namespace
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index fc8dbd615255851cad90e1d8ffe225f5e0c6a718..49ca9c0042ccf22ad1fffa54f05fd443cbc681ba 100644
|
||||
index 55124cd38e75ab67c092f6bf5c909a50e7232045..3ef093e612b23d5e1e7cacf56055e5f9818bcb02 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -50,7 +50,7 @@
|
||||
@@ -550,7 +566,7 @@ index fc8dbd615255851cad90e1d8ffe225f5e0c6a718..49ca9c0042ccf22ad1fffa54f05fd443
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
@@ -1073,7 +1073,7 @@ class Environment final : public MemoryRetainer {
|
||||
@@ -1060,7 +1060,7 @@ class Environment final : public MemoryRetainer {
|
||||
kExitInfoFieldCount
|
||||
};
|
||||
|
||||
@@ -573,7 +589,7 @@ index c59e65ad1fe3fac23f1fc25ca77e6133d1ccaccd..f2f07434e076e2977755ef7dac7d489a
|
||||
#if NODE_OPENSSL_HAS_QUIC
|
||||
#include <openssl/quic.h>
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index cfc599ec9a6197231c3469d318f02c620cdb03a8..29630fcccc3bd9d24ad6aec64bef2fedfc3c4031 100644
|
||||
index d3b59690e917afcf725cbfb1232d6ed9f298ee3a..3c42f9b87c11a0f88800d6709515c1c9e2972fc0 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -6,7 +6,7 @@
|
||||
@@ -586,7 +602,7 @@ index cfc599ec9a6197231c3469d318f02c620cdb03a8..29630fcccc3bd9d24ad6aec64bef2fed
|
||||
#endif
|
||||
|
||||
diff --git a/src/node_options.h b/src/node_options.h
|
||||
index 9e656a2815045aa5da7eb267708c03058be9f362..600e0850f01e01024414d42b25605f256200540a 100644
|
||||
index fc7f898a6b9b6072c15d77710c20ed1ba580966b..f39dcad0a28ae483e6d0e5df3816693119ac823e 100644
|
||||
--- a/src/node_options.h
|
||||
+++ b/src/node_options.h
|
||||
@@ -11,7 +11,7 @@
|
||||
@@ -599,10 +615,10 @@ index 9e656a2815045aa5da7eb267708c03058be9f362..600e0850f01e01024414d42b25605f25
|
||||
#endif
|
||||
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index de6ff5548ca5282199b7d85c11941c1fa351a9d9..3d8b7957e791ce2fa2a8d0937a87b6010087803d 100644
|
||||
index f6793b8bf22d6ac911a1977edaa881b6dbbe7ac7..ddfbb97276b29df114ab455a2eed3b186b3af5d2 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -145,7 +145,6 @@ template("node_gn_build") {
|
||||
@@ -150,7 +150,6 @@ template("node_gn_build") {
|
||||
]
|
||||
deps = [
|
||||
":run_node_js2c",
|
||||
@@ -610,7 +626,7 @@ index de6ff5548ca5282199b7d85c11941c1fa351a9d9..3d8b7957e791ce2fa2a8d0937a87b601
|
||||
"deps/cares",
|
||||
"deps/histogram",
|
||||
"deps/llhttp",
|
||||
@@ -156,6 +155,8 @@ template("node_gn_build") {
|
||||
@@ -161,6 +160,8 @@ template("node_gn_build") {
|
||||
"deps/sqlite",
|
||||
"deps/uvwasi",
|
||||
"//third_party/zlib",
|
||||
@@ -619,7 +635,7 @@ index de6ff5548ca5282199b7d85c11941c1fa351a9d9..3d8b7957e791ce2fa2a8d0937a87b601
|
||||
"$node_v8_path:v8_libplatform",
|
||||
]
|
||||
|
||||
@@ -182,10 +183,8 @@ template("node_gn_build") {
|
||||
@@ -187,10 +188,8 @@ template("node_gn_build") {
|
||||
deps += [ "//third_party/icu" ]
|
||||
}
|
||||
if (node_use_openssl) {
|
||||
|
||||
@@ -38,11 +38,11 @@ index 605e812d515fc467001e4ab88fc15b4af3fd4aa2..463e76cb1abc0c2fdddba4db2ca2e00f
|
||||
const result = dataURLProcessor(url);
|
||||
if (result === 'failure') {
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index f05c6f99c0037193c5802024be46a967d6cf47a0..f3dad958b2ec275992554477b9344214c8c1e2c8 100644
|
||||
index ee2cc03892c01141b71571989b18eec387d3c766..c13475102a75d65329908f44def06a60f4a2c4f1 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -24,7 +24,7 @@ const {
|
||||
} = primordials;
|
||||
@@ -25,7 +25,7 @@ const {
|
||||
const assert = require('internal/assert');
|
||||
const internalFS = require('internal/fs/utils');
|
||||
const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
-const { realpathSync } = require('fs');
|
||||
@@ -60,10 +60,10 @@ index f05c6f99c0037193c5802024be46a967d6cf47a0..f3dad958b2ec275992554477b9344214
|
||||
});
|
||||
const { search, hash } = resolved;
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index d182eedf5e96039e0029d36e51f40b75c6fb2a39..06b31af80ebbfbf35ec787a94f345775eb512ebf 100644
|
||||
index 25ee090bbb4884d3e5f2530cc7153f9215754fae..45a0abc6423a4e53e070f3c117fac2a3554b188d 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -34,7 +34,7 @@ const {
|
||||
@@ -24,7 +24,7 @@ const {
|
||||
|
||||
const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
const assert = require('internal/assert');
|
||||
@@ -71,8 +71,8 @@ index d182eedf5e96039e0029d36e51f40b75c6fb2a39..06b31af80ebbfbf35ec787a94f345775
|
||||
+const fs = require('fs');
|
||||
const { dirname, extname, isAbsolute } = require('path');
|
||||
const {
|
||||
loadBuiltinModule,
|
||||
@@ -335,7 +335,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
assertBufferSource,
|
||||
@@ -269,7 +269,7 @@ translators.set('commonjs', function commonjsStrategy(url, source, isMain) {
|
||||
|
||||
try {
|
||||
// We still need to read the FS to detect the exports.
|
||||
@@ -81,7 +81,7 @@ index d182eedf5e96039e0029d36e51f40b75c6fb2a39..06b31af80ebbfbf35ec787a94f345775
|
||||
} catch {
|
||||
// Continue regardless of error.
|
||||
}
|
||||
@@ -403,7 +403,7 @@ function cjsPreparseModuleExports(filename, source) {
|
||||
@@ -336,7 +336,7 @@ function cjsPreparseModuleExports(filename, source) {
|
||||
isAbsolute(resolved)) {
|
||||
// TODO: this should be calling the `load` hook chain to get the source
|
||||
// (and fallback to reading the FS only if the source is nullish).
|
||||
|
||||
@@ -48,7 +48,7 @@ index 867a1c4aca54b9d41490d23a5eb55088b7e941cc..09f4c65a18efea262b1f854f993c6f18
|
||||
|
||||
static v8::CFunction fast_equal(v8::CFunction::Make(FastTimingSafeEqual));
|
||||
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
|
||||
index 2302e8d94da3250e7fb4ee0c5e6a51d3d6941fbc..ed72476e16036d972de54d39cf4bd37bbbed5c5f 100644
|
||||
index cd51d9acf9540d506ec35812b9d2c530fce24912..07068344262f7b73a83073d4da75bffe8b747a61 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -44,6 +44,14 @@
|
||||
@@ -74,7 +74,7 @@ index 2302e8d94da3250e7fb4ee0c5e6a51d3d6941fbc..ed72476e16036d972de54d39cf4bd37b
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Global;
|
||||
using v8::HandleScope;
|
||||
@@ -581,19 +588,24 @@ void SlowCopy(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -582,19 +589,24 @@ void SlowCopy(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
// Assume caller has properly validated args.
|
||||
uint32_t FastCopy(Local<Value> receiver,
|
||||
@@ -107,7 +107,7 @@ index 2302e8d94da3250e7fb4ee0c5e6a51d3d6941fbc..ed72476e16036d972de54d39cf4bd37b
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
@@ -857,19 +869,17 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
|
||||
@@ -858,19 +870,17 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
|
||||
}
|
||||
|
||||
int32_t FastCompare(v8::Local<v8::Value>,
|
||||
@@ -135,7 +135,7 @@ index 2302e8d94da3250e7fb4ee0c5e6a51d3d6941fbc..ed72476e16036d972de54d39cf4bd37b
|
||||
}
|
||||
|
||||
static v8::CFunction fast_compare(v8::CFunction::Make(FastCompare));
|
||||
@@ -1140,14 +1150,13 @@ void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1141,14 +1151,13 @@ void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
int32_t FastIndexOfNumber(v8::Local<v8::Value>,
|
||||
@@ -153,7 +153,7 @@ index 2302e8d94da3250e7fb4ee0c5e6a51d3d6941fbc..ed72476e16036d972de54d39cf4bd37b
|
||||
}
|
||||
|
||||
static v8::CFunction fast_index_of_number(
|
||||
@@ -1552,21 +1561,31 @@ void SlowWriteString(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1501,21 +1510,31 @@ void SlowWriteString(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
template <encoding encoding>
|
||||
uint32_t FastWriteString(Local<Value> receiver,
|
||||
@@ -194,10 +194,10 @@ index 2302e8d94da3250e7fb4ee0c5e6a51d3d6941fbc..ed72476e16036d972de54d39cf4bd37b
|
||||
|
||||
static v8::CFunction fast_write_string_ascii(
|
||||
diff --git a/src/node_external_reference.h b/src/node_external_reference.h
|
||||
index 38a4ff7e6c2c9997f004c7c1f94cb5a9ffc2ffe0..48e73168f994d79ae3564b813acb5546ca8f2526 100644
|
||||
index 8d49a119c218323674e29a522ecf71bd22cdaf1b..d39693f2f45f39e45960453112b0f6460a1b3a4d 100644
|
||||
--- a/src/node_external_reference.h
|
||||
+++ b/src/node_external_reference.h
|
||||
@@ -34,16 +34,16 @@ using CFunctionCallbackWithStrings =
|
||||
@@ -40,16 +40,16 @@ using CFunctionCallbackWithStrings =
|
||||
const v8::FastOneByteString& base);
|
||||
using CFunctionCallbackWithTwoUint8Arrays =
|
||||
int32_t (*)(v8::Local<v8::Value>,
|
||||
@@ -219,7 +219,7 @@ index 38a4ff7e6c2c9997f004c7c1f94cb5a9ffc2ffe0..48e73168f994d79ae3564b813acb5546
|
||||
uint32_t,
|
||||
int64_t,
|
||||
bool);
|
||||
@@ -58,18 +58,20 @@ using CFunctionWithBool = void (*)(v8::Local<v8::Value>, bool);
|
||||
@@ -68,18 +68,20 @@ using CFunctionWithBool = void (*)(v8::Local<v8::Value>,
|
||||
|
||||
using CFunctionWriteString =
|
||||
uint32_t (*)(v8::Local<v8::Value> receiver,
|
||||
@@ -246,19 +246,18 @@ index 38a4ff7e6c2c9997f004c7c1f94cb5a9ffc2ffe0..48e73168f994d79ae3564b813acb5546
|
||||
// This class manages the external references from the V8 heap
|
||||
// to the C++ addresses in Node.js.
|
||||
diff --git a/src/util.h b/src/util.h
|
||||
index a6da8720c499df54ab4608eb03cff905759c2232..43ef977363e565a6f9422c9454e25b8fe0b327d5 100644
|
||||
index b1f316eebc7199a3737f05a5f9a1dd7fc289490c..23a0a486244ce38277ef11df5806da1266b901ac 100644
|
||||
--- a/src/util.h
|
||||
+++ b/src/util.h
|
||||
@@ -57,6 +57,8 @@
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
namespace node {
|
||||
|
||||
+static constexpr size_t kMaxSizeInHeap = 64; \
|
||||
+
|
||||
constexpr char kPathSeparator = std::filesystem::path::preferred_separator;
|
||||
+static constexpr size_t kMaxSizeInHeap = 64;
|
||||
|
||||
#ifdef _WIN32
|
||||
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
|
||||
#define PATH_MAX_BYTES (MAX_PATH * 4)
|
||||
@@ -573,6 +575,16 @@ class BufferValue : public MaybeStackBuffer<char> {
|
||||
@@ -576,6 +577,16 @@ class BufferValue : public MaybeStackBuffer<char> {
|
||||
static_cast<char*>(name->Buffer()->Data()) + name##_offset; \
|
||||
if (name##_length > 0) CHECK_NE(name##_data, nullptr);
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ This patch can be removed when we upgrade to a V8 version that
|
||||
contains the above CL.
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index ccc1085a84b214d241687fa9ebd45b55b2cc60d8..1df8e1f00a0e2ffa63bfd4369240b837ab6a9c50 100644
|
||||
index 1a2a43bdd37441400323a800c147fcb89f0d549a..ae0b40b40e601e86d22e223a764c20106ae29d70 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -804,7 +804,7 @@ static ExitCode ProcessGlobalArgsInternal(std::vector<std::string>* args,
|
||||
|
||||
@@ -15,10 +15,10 @@ to recognize asar files.
|
||||
This reverts commit 9cf2e1f55b8446a7cde23699d00a3be73aa0c8f1.
|
||||
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index f3dad958b2ec275992554477b9344214c8c1e2c8..a086217046fd5ed7cfb09cfd2ed62f3987eb1f31 100644
|
||||
index c13475102a75d65329908f44def06a60f4a2c4f1..e9fe83a675cb5bf681934e0f1c30a3cab447ba57 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -27,14 +27,13 @@ const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
@@ -28,14 +28,13 @@ const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
const fs = require('fs');
|
||||
const { getOptionValue } = require('internal/options');
|
||||
// Do not eagerly grab .manifest, it may be in TDZ
|
||||
@@ -35,56 +35,36 @@ index f3dad958b2ec275992554477b9344214c8c1e2c8..a086217046fd5ed7cfb09cfd2ed62f39
|
||||
const {
|
||||
ERR_INPUT_TYPE_NOT_ALLOWED,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
@@ -154,34 +153,13 @@ function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
|
||||
@@ -183,6 +182,15 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
kResolvedByPackageAndNode: 9,
|
||||
};
|
||||
|
||||
const realpathCache = new SafeMap();
|
||||
|
||||
-const legacyMainResolveExtensions = [
|
||||
- '',
|
||||
- '.js',
|
||||
- '.json',
|
||||
- '.node',
|
||||
- '/index.js',
|
||||
- '/index.json',
|
||||
- '/index.node',
|
||||
- './index.js',
|
||||
- './index.json',
|
||||
- './index.node',
|
||||
-];
|
||||
-
|
||||
-const legacyMainResolveExtensionsIndexes = {
|
||||
- // 0-6: when packageConfig.main is defined
|
||||
- kResolvedByMain: 0,
|
||||
- kResolvedByMainJs: 1,
|
||||
- kResolvedByMainJson: 2,
|
||||
- kResolvedByMainNode: 3,
|
||||
- kResolvedByMainIndexJs: 4,
|
||||
- kResolvedByMainIndexJson: 5,
|
||||
- kResolvedByMainIndexNode: 6,
|
||||
- // 7-9: when packageConfig.main is NOT defined,
|
||||
- // or when the previous case didn't found the file
|
||||
- kResolvedByPackageAndJs: 7,
|
||||
- kResolvedByPackageAndJson: 8,
|
||||
- kResolvedByPackageAndNode: 9,
|
||||
-};
|
||||
+/**
|
||||
+ * @param {string | URL} url
|
||||
+ * @returns {boolean}
|
||||
+ */
|
||||
+function fileExists(url) {
|
||||
+ return internalFsBinding.internalModuleStat(toNamespacedPath(toPathIfFileURL(url))) === 0;
|
||||
+ const namespaced = toNamespacedPath(toPathIfFileURL(url));
|
||||
+ return internalFsBinding.internalModuleStat(internalFsBinding, namespaced) === 0;
|
||||
+}
|
||||
|
||||
+
|
||||
/**
|
||||
* Legacy CommonJS main resolution:
|
||||
@@ -196,22 +174,44 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
* @returns {URL}
|
||||
*/
|
||||
function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
- const packageJsonUrlString = packageJSONUrl.href;
|
||||
* 1. let M = pkg_url + (json main field)
|
||||
@@ -199,18 +207,45 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
assert(isURL(packageJSONUrl));
|
||||
const pkgPath = fileURLToPath(new URL('.', packageJSONUrl));
|
||||
|
||||
- const baseStringified = isURL(base) ? base.href : base;
|
||||
-
|
||||
- if (typeof packageJsonUrlString !== 'string') {
|
||||
- throw new ERR_INVALID_ARG_TYPE('packageJSONUrl', ['URL'], packageJSONUrl);
|
||||
- const resolvedOption = FSLegacyMainResolve(pkgPath, packageConfig.main, baseStringified);
|
||||
-
|
||||
- const maybeMain = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ?
|
||||
- packageConfig.main || './' : '';
|
||||
- const resolvedPath = resolve(pkgPath, maybeMain + legacyMainResolveExtensions[resolvedOption]);
|
||||
- const resolvedUrl = pathToFileURL(resolvedPath);
|
||||
-
|
||||
- emitLegacyIndexDeprecation(resolvedUrl, resolvedPath, pkgPath, base, packageConfig.main);
|
||||
+ let guess;
|
||||
+ if (packageConfig.main !== undefined) {
|
||||
+ // Note: fs check redundances will be handled by Descriptor cache here.
|
||||
@@ -105,277 +85,39 @@ index f3dad958b2ec275992554477b9344214c8c1e2c8..a086217046fd5ed7cfb09cfd2ed62f39
|
||||
+ packageJSONUrl)));
|
||||
+ else guess = undefined;
|
||||
+ if (guess) {
|
||||
+ emitLegacyIndexDeprecation(guess, packageJSONUrl, base,
|
||||
+ packageConfig.main);
|
||||
+ emitLegacyIndexDeprecation(guess, fileURLToPath(guess), pkgPath,
|
||||
+ base, packageConfig.main);
|
||||
+ return guess;
|
||||
+ }
|
||||
+ // Fallthrough.
|
||||
}
|
||||
-
|
||||
- const baseStringified = isURL(base) ? base.href : base;
|
||||
-
|
||||
- const resolvedOption = FSLegacyMainResolve(packageJsonUrlString, packageConfig.main, baseStringified);
|
||||
-
|
||||
- const baseUrl = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ? `./${packageConfig.main}` : '';
|
||||
- const resolvedUrl = new URL(baseUrl + legacyMainResolveExtensions[resolvedOption], packageJSONUrl);
|
||||
-
|
||||
- emitLegacyIndexDeprecation(resolvedUrl, packageJSONUrl, base, packageConfig.main);
|
||||
-
|
||||
+ }
|
||||
|
||||
- return resolvedUrl;
|
||||
+ // Fallthrough.
|
||||
+ if (fileExists(guess = new URL('./index.js', packageJSONUrl)));
|
||||
+ // So fs.
|
||||
+ else if (fileExists(guess = new URL('./index.json', packageJSONUrl)));
|
||||
+ else if (fileExists(guess = new URL('./index.node', packageJSONUrl)));
|
||||
+ else guess = undefined;
|
||||
+ if (guess) {
|
||||
+ emitLegacyIndexDeprecation(guess, packageJSONUrl, base, packageConfig.main);
|
||||
+ emitLegacyIndexDeprecation(guess, fileURLToPath(guess), pkgPath,
|
||||
+ base, packageConfig.main);
|
||||
+ return guess;
|
||||
+ }
|
||||
+ // Not found.
|
||||
+ throw new ERR_MODULE_NOT_FOUND(
|
||||
+ fileURLToPath(new URL('.', packageJSONUrl)), fileURLToPath(base));
|
||||
+ throw new ERR_MODULE_NOT_FOUND(pkgPath, fileURLToPath(base), null);
|
||||
}
|
||||
|
||||
const encodedSepRegEx = /%2F|%5C/i;
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 0bb70eb0fcd42ddf4d5e585065cf1ad8e74faab3..b565beae625d970ba92ab667a145d8897d4e8a6e 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -19,14 +19,12 @@
|
||||
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
||||
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
#include "node_file.h" // NOLINT(build/include_inline)
|
||||
-#include "ada.h"
|
||||
#include "aliased_buffer-inl.h"
|
||||
#include "memory_tracker-inl.h"
|
||||
#include "node_buffer.h"
|
||||
#include "node_errors.h"
|
||||
#include "node_external_reference.h"
|
||||
#include "node_file-inl.h"
|
||||
-#include "node_metadata.h"
|
||||
#include "node_process-inl.h"
|
||||
#include "node_stat_watcher.h"
|
||||
#include "node_url.h"
|
||||
@@ -3208,146 +3206,6 @@ constexpr std::array<std::string_view, 10> legacy_main_extensions = {
|
||||
|
||||
} // namespace
|
||||
|
||||
-void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
- CHECK_GE(args.Length(), 1);
|
||||
- CHECK(args[0]->IsString());
|
||||
-
|
||||
- Environment* env = Environment::GetCurrent(args);
|
||||
- auto isolate = env->isolate();
|
||||
-
|
||||
- Utf8Value utf8_package_json_url(isolate, args[0]);
|
||||
- auto package_json_url =
|
||||
- ada::parse<ada::url_aggregator>(utf8_package_json_url.ToStringView());
|
||||
-
|
||||
- if (!package_json_url) {
|
||||
- THROW_ERR_INVALID_URL(isolate, "Invalid URL");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- std::string package_initial_file = "";
|
||||
-
|
||||
- ada::result<ada::url_aggregator> file_path_url;
|
||||
- std::optional<std::string> initial_file_path;
|
||||
- std::string file_path;
|
||||
-
|
||||
- if (args.Length() >= 2 && args[1]->IsString()) {
|
||||
- auto package_config_main = Utf8Value(isolate, args[1]).ToString();
|
||||
-
|
||||
- file_path_url = ada::parse<ada::url_aggregator>(
|
||||
- std::string("./") + package_config_main, &package_json_url.value());
|
||||
-
|
||||
- if (!file_path_url) {
|
||||
- THROW_ERR_INVALID_URL(isolate, "Invalid URL");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- initial_file_path = node::url::FileURLToPath(env, *file_path_url);
|
||||
- if (!initial_file_path.has_value()) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- FromNamespacedPath(&initial_file_path.value());
|
||||
-
|
||||
- package_initial_file = *initial_file_path;
|
||||
-
|
||||
- for (int i = 0; i < legacy_main_extensions_with_main_end; i++) {
|
||||
- file_path = *initial_file_path + std::string(legacy_main_extensions[i]);
|
||||
- // TODO(anonrig): Remove this when ToNamespacedPath supports std::string
|
||||
- Local<Value> local_file_path =
|
||||
- Buffer::Copy(env->isolate(), file_path.c_str(), file_path.size())
|
||||
- .ToLocalChecked();
|
||||
- BufferValue buff_file_path(isolate, local_file_path);
|
||||
- ToNamespacedPath(env, &buff_file_path);
|
||||
-
|
||||
- switch (FilePathIsFile(env, buff_file_path.ToString())) {
|
||||
- case BindingData::FilePathIsFileReturnType::kIsFile:
|
||||
- return args.GetReturnValue().Set(i);
|
||||
- case BindingData::FilePathIsFileReturnType::kIsNotFile:
|
||||
- continue;
|
||||
- case BindingData::FilePathIsFileReturnType::
|
||||
- kThrowInsufficientPermissions:
|
||||
- // the default behavior when do not have permission is to return
|
||||
- // and exit the execution of the method as soon as possible
|
||||
- // the internal function will throw the exception
|
||||
- return;
|
||||
- default:
|
||||
- UNREACHABLE();
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- file_path_url =
|
||||
- ada::parse<ada::url_aggregator>("./index", &package_json_url.value());
|
||||
-
|
||||
- if (!file_path_url) {
|
||||
- THROW_ERR_INVALID_URL(isolate, "Invalid URL");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- initial_file_path = node::url::FileURLToPath(env, *file_path_url);
|
||||
- if (!initial_file_path.has_value()) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- FromNamespacedPath(&initial_file_path.value());
|
||||
-
|
||||
- for (int i = legacy_main_extensions_with_main_end;
|
||||
- i < legacy_main_extensions_package_fallback_end;
|
||||
- i++) {
|
||||
- file_path = *initial_file_path + std::string(legacy_main_extensions[i]);
|
||||
- // TODO(anonrig): Remove this when ToNamespacedPath supports std::string
|
||||
- Local<Value> local_file_path =
|
||||
- Buffer::Copy(env->isolate(), file_path.c_str(), file_path.size())
|
||||
- .ToLocalChecked();
|
||||
- BufferValue buff_file_path(isolate, local_file_path);
|
||||
- ToNamespacedPath(env, &buff_file_path);
|
||||
-
|
||||
- switch (FilePathIsFile(env, buff_file_path.ToString())) {
|
||||
- case BindingData::FilePathIsFileReturnType::kIsFile:
|
||||
- return args.GetReturnValue().Set(i);
|
||||
- case BindingData::FilePathIsFileReturnType::kIsNotFile:
|
||||
- continue;
|
||||
- case BindingData::FilePathIsFileReturnType::kThrowInsufficientPermissions:
|
||||
- // the default behavior when do not have permission is to return
|
||||
- // and exit the execution of the method as soon as possible
|
||||
- // the internal function will throw the exception
|
||||
- return;
|
||||
- default:
|
||||
- UNREACHABLE();
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- if (package_initial_file == "")
|
||||
- package_initial_file = *initial_file_path + ".js";
|
||||
-
|
||||
- std::optional<std::string> module_base;
|
||||
-
|
||||
- if (args.Length() >= 3 && args[2]->IsString()) {
|
||||
- Utf8Value utf8_base_path(isolate, args[2]);
|
||||
- auto base_url =
|
||||
- ada::parse<ada::url_aggregator>(utf8_base_path.ToStringView());
|
||||
-
|
||||
- if (!base_url) {
|
||||
- THROW_ERR_INVALID_URL(isolate, "Invalid URL");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- module_base = node::url::FileURLToPath(env, *base_url);
|
||||
- if (!module_base.has_value()) {
|
||||
- return;
|
||||
- }
|
||||
- } else {
|
||||
- THROW_ERR_INVALID_ARG_TYPE(
|
||||
- isolate,
|
||||
- "The \"base\" argument must be of type string or an instance of URL.");
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- THROW_ERR_MODULE_NOT_FOUND(isolate,
|
||||
- "Cannot find package '%s' imported from %s",
|
||||
- package_initial_file,
|
||||
- *module_base);
|
||||
-}
|
||||
|
||||
void BindingData::MemoryInfo(MemoryTracker* tracker) const {
|
||||
tracker->TrackField("stats_field_array", stats_field_array);
|
||||
@@ -3448,19 +3306,6 @@ InternalFieldInfoBase* BindingData::Serialize(int index) {
|
||||
return info;
|
||||
}
|
||||
|
||||
-void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
|
||||
- Local<ObjectTemplate> target) {
|
||||
- Isolate* isolate = isolate_data->isolate();
|
||||
-
|
||||
- SetMethod(
|
||||
- isolate, target, "legacyMainResolve", BindingData::LegacyMainResolve);
|
||||
-}
|
||||
-
|
||||
-void BindingData::RegisterExternalReferences(
|
||||
- ExternalReferenceRegistry* registry) {
|
||||
- registry->Register(BindingData::LegacyMainResolve);
|
||||
-}
|
||||
-
|
||||
static void CreatePerIsolateProperties(IsolateData* isolate_data,
|
||||
Local<ObjectTemplate> target) {
|
||||
Isolate* isolate = isolate_data->isolate();
|
||||
@@ -3520,7 +3365,6 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
|
||||
SetMethod(isolate, target, "cpSyncCheckPaths", CpSyncCheckPaths);
|
||||
|
||||
StatWatcher::CreatePerIsolateProperties(isolate_data, target);
|
||||
- BindingData::CreatePerIsolateProperties(isolate_data, target);
|
||||
|
||||
target->Set(
|
||||
FIXED_ONE_BYTE_STRING(isolate, "kFsStatsFieldsNumber"),
|
||||
@@ -3593,7 +3437,6 @@ BindingData* FSReqBase::binding_data() {
|
||||
void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
|
||||
registry->Register(Access);
|
||||
StatWatcher::RegisterExternalReferences(registry);
|
||||
- BindingData::RegisterExternalReferences(registry);
|
||||
|
||||
registry->Register(GetFormatOfExtensionlessFile);
|
||||
registry->Register(Close);
|
||||
diff --git a/src/node_file.h b/src/node_file.h
|
||||
index bdad1ae25f4892cbbfd8cc30c4d8b4a6f600edbc..5a3c462853aa784d9ef61ff4f63010848c48b92c 100644
|
||||
--- a/src/node_file.h
|
||||
+++ b/src/node_file.h
|
||||
@@ -86,13 +86,6 @@ class BindingData : public SnapshotableObject {
|
||||
SERIALIZABLE_OBJECT_METHODS()
|
||||
SET_BINDING_ID(fs_binding_data)
|
||||
|
||||
- static void LegacyMainResolve(
|
||||
- const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
-
|
||||
- static void CreatePerIsolateProperties(IsolateData* isolate_data,
|
||||
- v8::Local<v8::ObjectTemplate> ctor);
|
||||
- static void RegisterExternalReferences(ExternalReferenceRegistry* registry);
|
||||
-
|
||||
void MemoryInfo(MemoryTracker* tracker) const override;
|
||||
SET_SELF_SIZE(BindingData)
|
||||
SET_MEMORY_INFO_NAME(BindingData)
|
||||
diff --git a/test/es-module/test-cjs-legacyMainResolve.js b/test/es-module/test-cjs-legacyMainResolve.js
|
||||
index 0bfeb567a22b1f9d9116b749d6cb3a8fda6bcc6a..17f137c595a9fef5f051fafc4682f206034c214c 100644
|
||||
index edb567bce403f2d4df482c2549c6f7cec78c3588..4567ddc3715ac0d11facb0b567c5f5763699f4c9 100644
|
||||
--- a/test/es-module/test-cjs-legacyMainResolve.js
|
||||
+++ b/test/es-module/test-cjs-legacyMainResolve.js
|
||||
@@ -82,7 +82,7 @@ describe('legacyMainResolve', () => {
|
||||
{},
|
||||
''
|
||||
),
|
||||
- { message: /instance of URL/, code: 'ERR_INVALID_ARG_TYPE' },
|
||||
+ { message: 'Invalid URL', code: 'ERR_INVALID_URL' },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -129,7 +129,7 @@ describe('legacyMainResolve', () => {
|
||||
);
|
||||
assert.throws(
|
||||
() => legacyMainResolve(packageJsonUrl, { main: null }, packageJsonUrl),
|
||||
- { message: /index\.js/, code: 'ERR_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_INTERNAL_ASSERTION' },
|
||||
+ { code: 'ERR_MODULE_NOT_FOUND' },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -384,7 +126,7 @@ index 0bfeb567a22b1f9d9116b749d6cb3a8fda6bcc6a..17f137c595a9fef5f051fafc4682f206
|
||||
assert.throws(
|
||||
() => legacyMainResolve(packageJsonUrl, { main: null }, packageJsonUrl),
|
||||
- { message: /index\.js/, code: 'ERR_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_INTERNAL_ASSERTION' },
|
||||
+ { code: 'ERR_MODULE_NOT_FOUND' },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -393,11 +135,11 @@ index 0bfeb567a22b1f9d9116b749d6cb3a8fda6bcc6a..17f137c595a9fef5f051fafc4682f206
|
||||
assert.throws(
|
||||
() => legacyMainResolve(packageJsonUrl, { main: './index.node' }, packageJsonUrl),
|
||||
- { message: /index\.node/, code: 'ERR_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_INTERNAL_ASSERTION' },
|
||||
+ { code: 'ERR_MODULE_NOT_FOUND' },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -163,7 +163,7 @@ describe('legacyMainResolve', () => {
|
||||
@@ -163,11 +163,11 @@ describe('legacyMainResolve', () => {
|
||||
);
|
||||
assert.throws(
|
||||
() => legacyMainResolve(packageJsonUrl, { main: null }, undefined),
|
||||
@@ -405,4 +147,9 @@ index 0bfeb567a22b1f9d9116b749d6cb3a8fda6bcc6a..17f137c595a9fef5f051fafc4682f206
|
||||
+ { message: 'The "path" argument must be of type string or an instance of URL. Received undefined', code: 'ERR_INVALID_ARG_TYPE' },
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
- it('should interpret main as a path, not a URL', () => {
|
||||
+ it.skip('should interpret main as a path, not a URL', () => {
|
||||
const packageJsonUrl = fixtures.fileURL('/es-modules/legacy-main-resolver/package.json');
|
||||
assert.deepStrictEqual(
|
||||
legacyMainResolve(packageJsonUrl, { main: '../folder%25with percentage#/' }, packageJsonUrl),
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: Pass all globals through "require"
|
||||
(cherry picked from commit 7d015419cb7a0ecfe6728431a4ed2056cd411d62)
|
||||
|
||||
diff --git a/lib/internal/modules/cjs/loader.js b/lib/internal/modules/cjs/loader.js
|
||||
index 451b7c2195e7ad3ab0bde95259e054dc431d7de9..d49941881e6cfd8647a6d44a57e0daaf1c874702 100644
|
||||
index b0210e4d96348c77da9eabbe8f3d292337cd6ae4..ad8d41a06bde1ca22d0245fa49143e080365b5e1 100644
|
||||
--- a/lib/internal/modules/cjs/loader.js
|
||||
+++ b/lib/internal/modules/cjs/loader.js
|
||||
@@ -182,6 +182,13 @@ const {
|
||||
@@ -183,6 +183,13 @@ const {
|
||||
CHAR_FORWARD_SLASH,
|
||||
} = require('internal/constants');
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ We use this to allow node's 'fs' module to read from ASAR files as if they were
|
||||
a real filesystem.
|
||||
|
||||
diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js
|
||||
index f7a62364b6107ab0bad33ea2f745703c746991dc..bab2aaf3db66452216035db594dc3ebdc3606c8b 100644
|
||||
index 11d585bc5b3e47b36877ca8306b72f571acb7d09..65d42428c70a3242f7076f1c1a4cec027a9c9829 100644
|
||||
--- a/lib/internal/bootstrap/node.js
|
||||
+++ b/lib/internal/bootstrap/node.js
|
||||
@@ -134,6 +134,10 @@ process.domain = null;
|
||||
|
||||
@@ -15,7 +15,7 @@ In a future release of simdjson, we will provide a more convenient function that
|
||||
avoids such ugly workaround.
|
||||
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index 3bedd2dfecb49c3f69ea59b70d72b8b6fc605132..2b0e4905dd557e73542cf052ba81327b1e1e471f 100644
|
||||
index dfd115a9eccc6b58d63a72ac450a1497354482dd..16a9f923148835daa95d3578e5941b284ff71434 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -100,11 +100,23 @@ const BindingData::PackageConfig* BindingData::GetPackageJSON(
|
||||
|
||||
@@ -16,7 +16,7 @@ patch:
|
||||
(cherry picked from commit 30329d06235a9f9733b1d4da479b403462d1b326)
|
||||
|
||||
diff --git a/src/env-inl.h b/src/env-inl.h
|
||||
index 28a15aa741ddd40c664aae641797e7cc2813442f..08fe98e10b7716c694bbc882299fe0ed9e282d73 100644
|
||||
index 3b041dd28ba32f028ecbb7d87b82f9ddee406b4f..5436c1a0f21e261f2eb2fdbb7f679d4f92a14ffd 100644
|
||||
--- a/src/env-inl.h
|
||||
+++ b/src/env-inl.h
|
||||
@@ -62,31 +62,6 @@ inline uv_loop_t* IsolateData::event_loop() const {
|
||||
@@ -52,7 +52,7 @@ index 28a15aa741ddd40c664aae641797e7cc2813442f..08fe98e10b7716c694bbc882299fe0ed
|
||||
return &(wrapper_data_->cppgc_id);
|
||||
}
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index 665b064091d4cc42a4dc9ee5b0ea9e2f190338ca..4c8cb75945d82544ce2237d94cd1406d15efe424 100644
|
||||
index 130524cad713e8aa685feaa8c384fe4db9452500..21bc5b8a3326e759ce12b865e49029cf8ffe9995 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -23,6 +23,7 @@
|
||||
@@ -63,7 +63,7 @@ index 665b064091d4cc42a4dc9ee5b0ea9e2f190338ca..4c8cb75945d82544ce2237d94cd1406d
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
@@ -71,7 +72,6 @@ using v8::TryCatch;
|
||||
@@ -70,7 +71,6 @@ using v8::TryCatch;
|
||||
using v8::Uint32;
|
||||
using v8::Undefined;
|
||||
using v8::Value;
|
||||
@@ -146,7 +146,7 @@ index 665b064091d4cc42a4dc9ee5b0ea9e2f190338ca..4c8cb75945d82544ce2237d94cd1406d
|
||||
|
||||
void IsolateData::MemoryInfo(MemoryTracker* tracker) const {
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 49ca9c0042ccf22ad1fffa54f05fd443cbc681ba..945535d0dc40f1a32f7e3ecf7d50361e591ba6c8 100644
|
||||
index 3ef093e612b23d5e1e7cacf56055e5f9818bcb02..9dfc1364c7206377b6d0d088b456c357c23a9151 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -175,10 +175,6 @@ class NODE_EXTERN_PRIVATE IsolateData : public MemoryRetainer {
|
||||
|
||||
@@ -26,10 +26,10 @@ index 3d8ccc77b5952a999c5fe48792259d32b402c460..867a1c4aca54b9d41490d23a5eb55088
|
||||
}
|
||||
|
||||
diff --git a/src/histogram.cc b/src/histogram.cc
|
||||
index 4dbdea9be5721486d71a9dda77311b4919d450a3..4aacaa2a5d12533a039b4b96cb7f1fd79063d50f 100644
|
||||
index c62a5b8952400ff0dd8818c31a3e07622b63725c..36f61f57e951e1abfeb2fedb831b55c61363bcbc 100644
|
||||
--- a/src/histogram.cc
|
||||
+++ b/src/histogram.cc
|
||||
@@ -193,7 +193,8 @@ void HistogramBase::FastRecord(Local<Value> receiver,
|
||||
@@ -195,7 +195,8 @@ void HistogramBase::FastRecord(Local<Value> unused,
|
||||
const int64_t value,
|
||||
FastApiCallbackOptions& options) {
|
||||
if (value < 1) {
|
||||
@@ -40,14 +40,13 @@ index 4dbdea9be5721486d71a9dda77311b4919d450a3..4aacaa2a5d12533a039b4b96cb7f1fd7
|
||||
}
|
||||
HistogramBase* histogram;
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index b565beae625d970ba92ab667a145d8897d4e8a6e..31c2fe82299d6905855c4efffeea4a4d161a88d5 100644
|
||||
index 6b98a13099990918dc619c47124c8538bbee5e2d..307492bf3dfce7b4a476c448bec666b8116dc431 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -1049,23 +1049,10 @@ static int32_t FastInternalModuleStat(
|
||||
const FastOneByteString& input,
|
||||
@@ -1060,22 +1060,10 @@ static int32_t FastInternalModuleStat(
|
||||
// NOLINTNEXTLINE(runtime/references) This is V8 api.
|
||||
FastApiCallbackOptions& options) {
|
||||
- // This needs a HandleScope which needs an isolate.
|
||||
// This needs a HandleScope which needs an isolate.
|
||||
- Isolate* isolate = Isolate::TryGetCurrent();
|
||||
- if (!isolate) {
|
||||
- options.fallback = true;
|
||||
@@ -60,24 +59,24 @@ index b565beae625d970ba92ab667a145d8897d4e8a6e..31c2fe82299d6905855c4efffeea4a4d
|
||||
+ HandleScope scope(env->isolate());
|
||||
|
||||
auto path = std::filesystem::path(input.data, input.data + input.length);
|
||||
- if (UNLIKELY(!env->permission()->is_granted(
|
||||
- env, permission::PermissionScope::kFileSystemRead, path.string()))) {
|
||||
- if (!env->permission()->is_granted(
|
||||
- env, permission::PermissionScope::kFileSystemRead, path.string()))
|
||||
- [[unlikely]] {
|
||||
- options.fallback = true;
|
||||
- return -1;
|
||||
- }
|
||||
-
|
||||
|
||||
switch (std::filesystem::status(path).type()) {
|
||||
case std::filesystem::file_type::directory:
|
||||
return 1;
|
||||
diff --git a/src/node_wasi.cc b/src/node_wasi.cc
|
||||
index ad1da44a01f437c97e06a3857eebd2edcebc83da..7123278e1a0942b61a76e9b1e7464eb8b5064079 100644
|
||||
index 468c2e59903fefe58d9c178d3afac3ef5b09f611..23a376e52e08a8af49dd47c47488552e01287426 100644
|
||||
--- a/src/node_wasi.cc
|
||||
+++ b/src/node_wasi.cc
|
||||
@@ -248,17 +248,18 @@ R WASI::WasiFunction<FT, F, R, Args...>::FastCallback(
|
||||
WASI* wasi = reinterpret_cast<WASI*>(BaseObject::FromJSObject(receiver));
|
||||
if (UNLIKELY(wasi == nullptr)) return EinvalError<R>();
|
||||
@@ -251,17 +251,19 @@ R WASI::WasiFunction<FT, F, R, Args...>::FastCallback(
|
||||
return EinvalError<R>();
|
||||
}
|
||||
|
||||
- if (UNLIKELY(options.wasm_memory == nullptr || wasi->memory_.IsEmpty())) {
|
||||
- if (options.wasm_memory == nullptr || wasi->memory_.IsEmpty()) [[unlikely]] {
|
||||
- // fallback to slow path which to throw an error about missing memory.
|
||||
- options.fallback = true;
|
||||
+ v8::Isolate* isolate = receiver->GetIsolate();
|
||||
@@ -87,15 +86,16 @@ index ad1da44a01f437c97e06a3857eebd2edcebc83da..7123278e1a0942b61a76e9b1e7464eb8
|
||||
return EinvalError<R>();
|
||||
}
|
||||
- uint8_t* memory = nullptr;
|
||||
- CHECK(LIKELY(options.wasm_memory->getStorageIfAligned(&memory)));
|
||||
+ Local<ArrayBuffer> ab = wasi->memory_.Get(isolate)->Buffer();
|
||||
+ size_t mem_size = ab->ByteLength();
|
||||
+ char* mem_data = static_cast<char*>(ab->Data());
|
||||
+ CHECK_NOT_NULL(mem_data);
|
||||
- CHECK(options.wasm_memory->getStorageIfAligned(&memory));
|
||||
|
||||
- return F(*wasi,
|
||||
- {reinterpret_cast<char*>(memory), options.wasm_memory->length()},
|
||||
- args...);
|
||||
+ Local<ArrayBuffer> ab = wasi->memory_.Get(isolate)->Buffer();
|
||||
+ size_t mem_size = ab->ByteLength();
|
||||
+ char* mem_data = static_cast<char*>(ab->Data());
|
||||
+ CHECK_NOT_NULL(mem_data);
|
||||
+
|
||||
+ return F(*wasi, {mem_data, mem_size}, args...);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ This refactors several allocators to allocate within the V8 memory cage,
|
||||
allowing them to be compatible with the V8_SANDBOXED_POINTERS feature.
|
||||
|
||||
diff --git a/src/api/environment.cc b/src/api/environment.cc
|
||||
index 5fc1b6f2446d7c786024eb60800e2edab613dcd1..f59abcb21d64b910d8d42eb23c03109f62558813 100644
|
||||
index e044f10284f31f1862b18be752a04b3bd5d53401..89ce587cac4506c4218a9316fe0b68070a7a8504 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -101,6 +101,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
@@ -102,6 +102,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ index 5fc1b6f2446d7c786024eb60800e2edab613dcd1..f59abcb21d64b910d8d42eb23c03109f
|
||||
void* ret;
|
||||
if (zero_fill_field_ || per_process::cli_options->zero_fill_all_buffers)
|
||||
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
|
||||
index 33ffbbb85d05f5356183e3aa1ca23707c5629b5d..008d212ebe25b0022020379aa08963c12828940c 100644
|
||||
index f973941b3b9ea954f35f2ea135f8ee3d77b98958..743c63ff7e3f526829919a8f2de7ebd625a93fbc 100644
|
||||
--- a/src/crypto/crypto_dh.cc
|
||||
+++ b/src/crypto/crypto_dh.cc
|
||||
@@ -51,6 +51,25 @@ void DiffieHellman::MemoryInfo(MemoryTracker* tracker) const {
|
||||
@@ -64,7 +64,7 @@ index 33ffbbb85d05f5356183e3aa1ca23707c5629b5d..008d212ebe25b0022020379aa08963c1
|
||||
auto ab = ArrayBuffer::New(env->isolate(), std::move(backing));
|
||||
return Buffer::New(env, ab, 0, ab->ByteLength()).FromMaybe(Local<Value>());
|
||||
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
|
||||
index ee81048caab4ccfe26ea9e677782c9c955d162a9..643c9d31dc2737faa2ec51684ffceb35a1014a58 100644
|
||||
index 8a6a36a3c31532ed585c287ba8cee14026d315b4..3d449b5853f359d63e1b88671a857bf9152ff6af 100644
|
||||
--- a/src/crypto/crypto_util.cc
|
||||
+++ b/src/crypto/crypto_util.cc
|
||||
@@ -326,10 +326,35 @@ ByteSource& ByteSource::operator=(ByteSource&& other) noexcept {
|
||||
@@ -156,10 +156,10 @@ index 922e77091d72172ed6cfc5e8477901e3608396c5..16a236c69caed6d60248c7973531a95a
|
||||
v8::Local<v8::ArrayBuffer> ToArrayBuffer(Environment* env);
|
||||
|
||||
diff --git a/src/crypto/crypto_x509.cc b/src/crypto/crypto_x509.cc
|
||||
index af2f953f0388dbce326b0c519de3883552f8f009..7fb34057a486914dd886ec4d3d23be90cccb4fea 100644
|
||||
index 9b9bb7be9a8daca98a2635bf13cb6d1d561ea5fb..81afe2b5f7398f0c20b340648ca75022470be544 100644
|
||||
--- a/src/crypto/crypto_x509.cc
|
||||
+++ b/src/crypto/crypto_x509.cc
|
||||
@@ -174,6 +174,19 @@ MaybeLocal<Value> ToV8Value(Local<Context> context, const BIOPointer& bio) {
|
||||
@@ -175,6 +175,19 @@ MaybeLocal<Value> ToV8Value(Local<Context> context, const BIOPointer& bio) {
|
||||
MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
|
||||
if (bio == nullptr || !*bio) return {};
|
||||
BUF_MEM* mem = *bio;
|
||||
@@ -179,7 +179,7 @@ index af2f953f0388dbce326b0c519de3883552f8f009..7fb34057a486914dd886ec4d3d23be90
|
||||
auto backing = ArrayBuffer::NewBackingStore(
|
||||
mem->data,
|
||||
mem->length,
|
||||
@@ -181,6 +194,8 @@ MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
|
||||
@@ -182,6 +195,8 @@ MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
|
||||
BIOPointer free_me(static_cast<BIO*>(data));
|
||||
},
|
||||
bio->release());
|
||||
@@ -229,10 +229,10 @@ index 43bb68351bf0a68285e464601013bbdbd5d5df5f..4126bbff080548c91154a6dcc437359c
|
||||
|
||||
constexpr const char* EncodingName(const enum encoding encoding) {
|
||||
diff --git a/src/node_internals.h b/src/node_internals.h
|
||||
index fe2d25decd883085e4c3f368ab4acc01a7f66f6e..bcd5c87afcff9c56429443363c63fc8079521451 100644
|
||||
index 85b666e11f5654afe2a2f192e629221f2133b165..bd8d65247ad3ba4878f1288ab2b66e3598982b09 100644
|
||||
--- a/src/node_internals.h
|
||||
+++ b/src/node_internals.h
|
||||
@@ -117,7 +117,9 @@ v8::Maybe<bool> InitializePrimordials(v8::Local<v8::Context> context);
|
||||
@@ -117,7 +117,9 @@ v8::Maybe<void> InitializePrimordials(v8::Local<v8::Context> context);
|
||||
|
||||
class NodeArrayBufferAllocator : public ArrayBufferAllocator {
|
||||
public:
|
||||
@@ -369,3 +369,18 @@ index 9787b14352753c5e0f8dc2b90093680e7cd10f1a..31af9e62396368af1b81f8841a705fd3
|
||||
auto ab = ArrayBuffer::New(isolate, std::move(bs));
|
||||
v8::Local<Uint8Array> u8 = v8::Uint8Array::New(ab, 0, 1);
|
||||
|
||||
diff --git a/test/parallel/test-buffer-tostring-range.js b/test/parallel/test-buffer-tostring-range.js
|
||||
index 73fec107a36c3db4af6f492137d0ca174f2d0547..a1153ec381f7b12a1640b611073f6997e1ec5696 100644
|
||||
--- a/test/parallel/test-buffer-tostring-range.js
|
||||
+++ b/test/parallel/test-buffer-tostring-range.js
|
||||
@@ -102,8 +102,8 @@ assert.throws(() => {
|
||||
// Must not throw when start and end are within kMaxLength
|
||||
// Cannot test on 32bit machine as we are testing the case
|
||||
// when start and end are above the threshold
|
||||
-if (!common.openSSLIsBoringSSL) {
|
||||
+/*
|
||||
const threshold = 0xFFFFFFFF;
|
||||
const largeBuffer = Buffer.alloc(threshold + 20);
|
||||
largeBuffer.toString('utf8', threshold, threshold + 20);
|
||||
-}
|
||||
+*/
|
||||
|
||||
@@ -7,7 +7,7 @@ Instead of disabling the tests, flag them as flaky so they still run
|
||||
but don't cause CI failures on flakes.
|
||||
|
||||
diff --git a/test/parallel/parallel.status b/test/parallel/parallel.status
|
||||
index 24e1a74886bad536dc08df75fbdb0508e4e1420a..7f3be73474557788050a9110b0e29e602b7d6397 100644
|
||||
index 6b5b0ed739bc8600d46c2f65993b86a4092c680c..40beb6a5ec2e129181ce74afce4021bf88286989 100644
|
||||
--- a/test/parallel/parallel.status
|
||||
+++ b/test/parallel/parallel.status
|
||||
@@ -5,6 +5,16 @@ prefix parallel
|
||||
@@ -28,7 +28,7 @@ index 24e1a74886bad536dc08df75fbdb0508e4e1420a..7f3be73474557788050a9110b0e29e60
|
||||
test-net-write-fully-async-hex-string: PASS, FLAKY
|
||||
# https://github.com/nodejs/node/issues/52273
|
||||
diff --git a/test/sequential/sequential.status b/test/sequential/sequential.status
|
||||
index a539649d5537376a6a2ac9a7a46051b8648f0cb1..a03c86b752772be7ae36fab31faeccf3b0ccff64 100644
|
||||
index 073b29cce8dbca4c8d92ad666f9244ad511296db..338d20263f29a630febb96567f3cb708623bd09a 100644
|
||||
--- a/test/sequential/sequential.status
|
||||
+++ b/test/sequential/sequential.status
|
||||
@@ -7,6 +7,18 @@ prefix sequential
|
||||
|
||||
@@ -64,6 +64,8 @@
|
||||
"parallel/test-snapshot-namespaced-builtin",
|
||||
"parallel/test-snapshot-net",
|
||||
"parallel/test-snapshot-reproducible",
|
||||
"parallel/test-snapshot-stack-trace-limit",
|
||||
"parallel/test-snapshot-stack-trace-limit-mutation",
|
||||
"parallel/test-snapshot-typescript",
|
||||
"parallel/test-snapshot-umd",
|
||||
"parallel/test-snapshot-warning",
|
||||
|
||||
@@ -369,9 +369,6 @@ def main():
|
||||
patch_file.close()
|
||||
os.unlink(patch_file.name)
|
||||
else:
|
||||
print(
|
||||
'To patch these files, run:',
|
||||
f"$ git apply {patch_file.name}", sep='\n')
|
||||
filename=patch_file.name
|
||||
print(f"\nTo patch these files, run:\n$ git apply {filename}\n")
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include "base/files/file_util.h"
|
||||
@@ -20,6 +21,7 @@
|
||||
#include "shell/common/node_includes.h"
|
||||
|
||||
using content::TracingController;
|
||||
using namespace std::literals;
|
||||
|
||||
namespace gin {
|
||||
|
||||
@@ -69,9 +71,9 @@ void StopTracing(gin_helper::Promise<base::FilePath> promise,
|
||||
std::optional<base::FilePath> file_path) {
|
||||
auto resolve_or_reject = base::BindOnce(
|
||||
[](gin_helper::Promise<base::FilePath> promise,
|
||||
const base::FilePath& path, std::optional<std::string> error) {
|
||||
if (error) {
|
||||
promise.RejectWithErrorMessage(error.value());
|
||||
const base::FilePath& path, const std::string_view error) {
|
||||
if (!std::empty(error)) {
|
||||
promise.RejectWithErrorMessage(error);
|
||||
} else {
|
||||
promise.Resolve(path);
|
||||
}
|
||||
@@ -81,21 +83,17 @@ void StopTracing(gin_helper::Promise<base::FilePath> promise,
|
||||
auto* instance = TracingController::GetInstance();
|
||||
if (!instance->IsTracing()) {
|
||||
std::move(resolve_or_reject)
|
||||
.Run(std::make_optional(
|
||||
"Failed to stop tracing - no trace in progress"));
|
||||
.Run("Failed to stop tracing - no trace in progress"sv);
|
||||
} else if (file_path) {
|
||||
auto split_callback = base::SplitOnceCallback(std::move(resolve_or_reject));
|
||||
auto endpoint = TracingController::CreateFileEndpoint(
|
||||
*file_path,
|
||||
base::BindOnce(std::move(split_callback.first), std::nullopt));
|
||||
*file_path, base::BindOnce(std::move(split_callback.first), ""sv));
|
||||
if (!instance->StopTracing(endpoint)) {
|
||||
std::move(split_callback.second)
|
||||
.Run(std::make_optional("Failed to stop tracing"));
|
||||
std::move(split_callback.second).Run("Failed to stop tracing"sv);
|
||||
}
|
||||
} else {
|
||||
std::move(resolve_or_reject)
|
||||
.Run(std::make_optional(
|
||||
"Failed to create temporary file for trace data"));
|
||||
.Run("Failed to create temporary file for trace data"sv);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,15 @@
|
||||
|
||||
#include "shell/browser/api/electron_api_global_shortcut.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/containers/contains.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "base/uuid.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "electron/shell/browser/electron_browser_context.h"
|
||||
#include "electron/shell/common/electron_constants.h"
|
||||
#include "extensions/common/command.h"
|
||||
#include "gin/dictionary.h"
|
||||
#include "gin/handle.h"
|
||||
@@ -62,7 +68,12 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||
|
||||
void GlobalShortcut::ExecuteCommand(const extensions::ExtensionId& extension_id,
|
||||
const std::string& command_id) {
|
||||
// Ignore extension commands
|
||||
if (!base::Contains(command_callback_map_, command_id)) {
|
||||
// This should never occur, because if it does, GlobalShortcutListener
|
||||
// notifies us with wrong command.
|
||||
NOTREACHED();
|
||||
}
|
||||
command_callback_map_[command_id].Run();
|
||||
}
|
||||
|
||||
bool GlobalShortcut::RegisterAll(
|
||||
@@ -103,13 +114,56 @@ bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
|
||||
this)) {
|
||||
auto* instance = GlobalShortcutListener::GetInstance();
|
||||
if (!instance) {
|
||||
return false;
|
||||
}
|
||||
|
||||
accelerator_callback_map_[accelerator] = callback;
|
||||
return true;
|
||||
if (instance->IsRegistrationHandledExternally()) {
|
||||
auto* context = ElectronBrowserContext::From("", false);
|
||||
PrefService* prefs = context->prefs();
|
||||
|
||||
// Need a unique profile id. Set one if not generated yet, otherwise re-use
|
||||
// the same so that the session for the globalShortcuts is able to get
|
||||
// already registered shortcuts from the previous session. This will be used
|
||||
// by GlobalShortcutListenerLinux as a session key.
|
||||
std::string profile_id = prefs->GetString(kElectronGlobalShortcutsUuid);
|
||||
if (profile_id.empty()) {
|
||||
profile_id = base::Uuid::GenerateRandomV4().AsLowercaseString();
|
||||
prefs->SetString(kElectronGlobalShortcutsUuid, profile_id);
|
||||
}
|
||||
|
||||
// There is no way to get command id for the accelerator as it's extensions'
|
||||
// thing. Instead, we can convert it to string in a following example form
|
||||
// - std::string("Alt+Shift+K"). That must be sufficient enough for us to
|
||||
// map this accelerator with registered commands.
|
||||
const std::string command_str =
|
||||
extensions::Command::AcceleratorToString(accelerator);
|
||||
ui::CommandMap commands;
|
||||
extensions::Command command(
|
||||
command_str, base::UTF8ToUTF16("Electron shortcut " + command_str),
|
||||
/*accelerator=*/std::string(), /*global=*/true);
|
||||
command.set_accelerator(accelerator);
|
||||
commands[command_str] = command;
|
||||
|
||||
// In order to distinguish the shortcuts, we must register multiple commands
|
||||
// as different extensions. Otherwise, each shortcut will be an alternative
|
||||
// for the very first registered and we'll not be able to distinguish them.
|
||||
// For example, if Alt+Shift+K is registered first, registering and pressing
|
||||
// Alt+Shift+M will trigger global shortcuts, but the command id that is
|
||||
// received by GlobalShortcut will correspond to Alt+Shift+K as our command
|
||||
// id is basically a stringified accelerator.
|
||||
const std::string fake_extension_id = command_str + "+" + profile_id;
|
||||
instance->OnCommandsChanged(fake_extension_id, profile_id, commands, this);
|
||||
command_callback_map_[command_str] = callback;
|
||||
return true;
|
||||
} else {
|
||||
if (instance->RegisterAccelerator(accelerator, this)) {
|
||||
accelerator_callback_map_[accelerator] = callback;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||
@@ -127,8 +181,10 @@ void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||
}
|
||||
#endif
|
||||
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
|
||||
this);
|
||||
if (GlobalShortcutListener::GetInstance()) {
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
|
||||
this);
|
||||
}
|
||||
}
|
||||
|
||||
void GlobalShortcut::UnregisterSome(
|
||||
@@ -139,7 +195,12 @@ void GlobalShortcut::UnregisterSome(
|
||||
}
|
||||
|
||||
bool GlobalShortcut::IsRegistered(const ui::Accelerator& accelerator) {
|
||||
return base::Contains(accelerator_callback_map_, accelerator);
|
||||
if (base::Contains(accelerator_callback_map_, accelerator)) {
|
||||
return true;
|
||||
}
|
||||
const std::string command_str =
|
||||
extensions::Command::AcceleratorToString(accelerator);
|
||||
return base::Contains(command_callback_map_, command_str);
|
||||
}
|
||||
|
||||
void GlobalShortcut::UnregisterAll() {
|
||||
@@ -149,7 +210,9 @@ void GlobalShortcut::UnregisterAll() {
|
||||
return;
|
||||
}
|
||||
accelerator_callback_map_.clear();
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
|
||||
if (GlobalShortcutListener::GetInstance()) {
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -44,6 +44,7 @@ class GlobalShortcut final
|
||||
private:
|
||||
typedef std::map<ui::Accelerator, base::RepeatingClosure>
|
||||
AcceleratorCallbackMap;
|
||||
typedef std::map<std::string, base::RepeatingClosure> CommandCallbackMap;
|
||||
|
||||
bool RegisterAll(const std::vector<ui::Accelerator>& accelerators,
|
||||
const base::RepeatingClosure& callback);
|
||||
@@ -60,6 +61,7 @@ class GlobalShortcut final
|
||||
const std::string& command_id) override;
|
||||
|
||||
AcceleratorCallbackMap accelerator_callback_map_;
|
||||
CommandCallbackMap command_callback_map_;
|
||||
};
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
@@ -27,29 +27,14 @@
|
||||
#include "ui/views/view_class_properties.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
#include "shell/browser/ui/cocoa/delayed_native_view_host.h"
|
||||
#endif
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
WebContentsView::WebContentsView(v8::Isolate* isolate,
|
||||
gin::Handle<WebContents> web_contents)
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
: View(new DelayedNativeViewHost(web_contents->inspectable_web_contents()
|
||||
->GetView()
|
||||
->GetNativeView())),
|
||||
#else
|
||||
: View(web_contents->inspectable_web_contents()->GetView()->GetView()),
|
||||
#endif
|
||||
: View(web_contents->inspectable_web_contents()->GetView()),
|
||||
web_contents_(isolate, web_contents.ToV8()),
|
||||
api_web_contents_(web_contents.get()) {
|
||||
#if !BUILDFLAG(IS_MAC)
|
||||
// On macOS the View is a newly-created |DelayedNativeViewHost| and it is our
|
||||
// responsibility to delete it. On other platforms the View is created and
|
||||
// managed by InspectableWebContents.
|
||||
set_delete_view(false);
|
||||
#endif
|
||||
view()->SetProperty(
|
||||
views::kFlexBehaviorKey,
|
||||
views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
|
||||
|
||||
@@ -405,9 +405,9 @@ void ElectronBrowserClient::OverrideWebkitPrefs(
|
||||
prefs->javascript_enabled = true;
|
||||
prefs->web_security_enabled = true;
|
||||
prefs->plugins_enabled = true;
|
||||
prefs->dom_paste_enabled = true;
|
||||
prefs->dom_paste_enabled = false;
|
||||
prefs->javascript_can_access_clipboard = false;
|
||||
prefs->allow_scripts_to_close_windows = true;
|
||||
prefs->javascript_can_access_clipboard = true;
|
||||
prefs->local_storage_enabled = true;
|
||||
prefs->databases_enabled = true;
|
||||
prefs->allow_universal_access_from_file_urls =
|
||||
|
||||
@@ -458,6 +458,10 @@ void ElectronBrowserContext::InitPrefs() {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unique uuid for global shortcuts.
|
||||
registry->RegisterStringPref(electron::kElectronGlobalShortcutsUuid,
|
||||
std::string());
|
||||
}
|
||||
|
||||
void ElectronBrowserContext::SetUserAgent(const std::string& user_agent) {
|
||||
|
||||
@@ -490,14 +490,8 @@ std::unique_ptr<UserScript> ParseUserScript(
|
||||
ConvertRegisteredContentScriptToSerializedUserScript(
|
||||
std::move(content_script));
|
||||
|
||||
std::unique_ptr<UserScript> user_script =
|
||||
script_serialization::ParseSerializedUserScript(
|
||||
serialized_script, extension, allowed_in_incognito, error);
|
||||
if (!user_script) {
|
||||
return nullptr; // Parsing failed.
|
||||
}
|
||||
|
||||
return user_script;
|
||||
return script_serialization::ParseSerializedUserScript(
|
||||
serialized_script, extension, allowed_in_incognito, error);
|
||||
}
|
||||
|
||||
// Converts a UserScript object to a api::scripting::RegisteredContentScript
|
||||
|
||||
@@ -651,7 +651,16 @@ bool TabsUpdateFunction::UpdateURL(const std::string& url_string,
|
||||
// will stay in the omnibox - see https://crbug.com/1085779.
|
||||
load_params.transition_type = ui::PAGE_TRANSITION_FROM_API;
|
||||
|
||||
web_contents_->GetController().LoadURLWithParams(load_params);
|
||||
base::WeakPtr<content::NavigationHandle> navigation_handle =
|
||||
web_contents_->GetController().LoadURLWithParams(load_params);
|
||||
// Navigation can fail for any number of reasons at the content layer.
|
||||
// Unfortunately, we can't provide a detailed error message here, because
|
||||
// there are too many possible triggers. At least notify the extension that
|
||||
// the update failed.
|
||||
if (!navigation_handle) {
|
||||
*error = "Navigation rejected.";
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK_EQ(url,
|
||||
web_contents_->GetController().GetPendingEntry()->GetVirtualURL());
|
||||
|
||||
@@ -461,7 +461,7 @@ FileSystemAccessPermissionContext::GetReadPermissionGrant(
|
||||
// but that is exactly what we want.
|
||||
auto& origin_state = active_permissions_map_[origin];
|
||||
auto*& existing_grant = origin_state.read_grants[path_info.path];
|
||||
scoped_refptr<PermissionGrantImpl> new_grant;
|
||||
scoped_refptr<PermissionGrantImpl> grant;
|
||||
|
||||
if (existing_grant && existing_grant->handle_type() != handle_type) {
|
||||
// |path| changed from being a directory to being a file or vice versa,
|
||||
@@ -471,18 +471,21 @@ FileSystemAccessPermissionContext::GetReadPermissionGrant(
|
||||
existing_grant = nullptr;
|
||||
}
|
||||
|
||||
if (!existing_grant) {
|
||||
new_grant = base::MakeRefCounted<PermissionGrantImpl>(
|
||||
bool creating_new_grant = !existing_grant;
|
||||
if (creating_new_grant) {
|
||||
grant = base::MakeRefCounted<PermissionGrantImpl>(
|
||||
weak_factory_.GetWeakPtr(), origin, path_info, handle_type,
|
||||
GrantType::kRead, user_action);
|
||||
existing_grant = new_grant.get();
|
||||
existing_grant = grant.get();
|
||||
} else {
|
||||
grant = existing_grant;
|
||||
}
|
||||
|
||||
// If a parent directory is already readable this new grant should also be
|
||||
// readable.
|
||||
if (new_grant &&
|
||||
if (creating_new_grant &&
|
||||
AncestorHasActivePermission(origin, path_info.path, GrantType::kRead)) {
|
||||
existing_grant->SetStatus(PermissionStatus::GRANTED);
|
||||
grant->SetStatus(PermissionStatus::GRANTED);
|
||||
} else {
|
||||
switch (user_action) {
|
||||
case UserAction::kOpen:
|
||||
@@ -494,7 +497,7 @@ FileSystemAccessPermissionContext::GetReadPermissionGrant(
|
||||
[[fallthrough]];
|
||||
case UserAction::kDragAndDrop:
|
||||
// Drag&drop grants read access for all handles.
|
||||
existing_grant->SetStatus(PermissionStatus::GRANTED);
|
||||
grant->SetStatus(PermissionStatus::GRANTED);
|
||||
break;
|
||||
case UserAction::kLoadFromStorage:
|
||||
case UserAction::kNone:
|
||||
@@ -502,7 +505,7 @@ FileSystemAccessPermissionContext::GetReadPermissionGrant(
|
||||
}
|
||||
}
|
||||
|
||||
return existing_grant;
|
||||
return grant;
|
||||
}
|
||||
|
||||
scoped_refptr<content::FileSystemAccessPermissionGrant>
|
||||
@@ -516,7 +519,7 @@ FileSystemAccessPermissionContext::GetWritePermissionGrant(
|
||||
// but that is exactly what we want.
|
||||
auto& origin_state = active_permissions_map_[origin];
|
||||
auto*& existing_grant = origin_state.write_grants[path_info.path];
|
||||
scoped_refptr<PermissionGrantImpl> new_grant;
|
||||
scoped_refptr<PermissionGrantImpl> grant;
|
||||
|
||||
if (existing_grant && existing_grant->handle_type() != handle_type) {
|
||||
// |path| changed from being a directory to being a file or vice versa,
|
||||
@@ -526,23 +529,26 @@ FileSystemAccessPermissionContext::GetWritePermissionGrant(
|
||||
existing_grant = nullptr;
|
||||
}
|
||||
|
||||
if (!existing_grant) {
|
||||
new_grant = base::MakeRefCounted<PermissionGrantImpl>(
|
||||
bool creating_new_grant = !existing_grant;
|
||||
if (creating_new_grant) {
|
||||
grant = base::MakeRefCounted<PermissionGrantImpl>(
|
||||
weak_factory_.GetWeakPtr(), origin, path_info, handle_type,
|
||||
GrantType::kWrite, user_action);
|
||||
existing_grant = new_grant.get();
|
||||
existing_grant = grant.get();
|
||||
} else {
|
||||
grant = existing_grant;
|
||||
}
|
||||
|
||||
// If a parent directory is already writable this new grant should also be
|
||||
// writable.
|
||||
if (new_grant &&
|
||||
if (creating_new_grant &&
|
||||
AncestorHasActivePermission(origin, path_info.path, GrantType::kWrite)) {
|
||||
existing_grant->SetStatus(PermissionStatus::GRANTED);
|
||||
grant->SetStatus(PermissionStatus::GRANTED);
|
||||
} else {
|
||||
switch (user_action) {
|
||||
case UserAction::kSave:
|
||||
// Only automatically grant write access for save dialogs.
|
||||
existing_grant->SetStatus(PermissionStatus::GRANTED);
|
||||
grant->SetStatus(PermissionStatus::GRANTED);
|
||||
break;
|
||||
case UserAction::kOpen:
|
||||
case UserAction::kDragAndDrop:
|
||||
@@ -552,7 +558,7 @@ FileSystemAccessPermissionContext::GetWritePermissionGrant(
|
||||
}
|
||||
}
|
||||
|
||||
return existing_grant;
|
||||
return grant;
|
||||
}
|
||||
|
||||
bool FileSystemAccessPermissionContext::IsFileTypeDangerous(
|
||||
@@ -588,7 +594,7 @@ void FileSystemAccessPermissionContext::ConfirmSensitiveEntryAccess(
|
||||
content::GlobalRenderFrameHostId frame_id,
|
||||
base::OnceCallback<void(SensitiveEntryResult)> callback) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
callback_ = std::move(callback);
|
||||
callback_map_.try_emplace(path_info.path, std::move(callback));
|
||||
|
||||
auto after_blocklist_check_callback = base::BindOnce(
|
||||
&FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist,
|
||||
@@ -632,16 +638,18 @@ void FileSystemAccessPermissionContext::PerformAfterWriteChecks(
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::RunRestrictedPathCallback(
|
||||
const base::FilePath& file_path,
|
||||
SensitiveEntryResult result) {
|
||||
if (callback_)
|
||||
std::move(callback_).Run(result);
|
||||
if (auto val = callback_map_.extract(file_path))
|
||||
std::move(val.mapped()).Run(result);
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::OnRestrictedPathResult(
|
||||
const base::FilePath& file_path,
|
||||
gin::Arguments* args) {
|
||||
SensitiveEntryResult result = SensitiveEntryResult::kAbort;
|
||||
args->GetNext(&result);
|
||||
RunRestrictedPathCallback(result);
|
||||
RunRestrictedPathCallback(file_path, result);
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
|
||||
@@ -654,8 +662,9 @@ void FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
||||
if (user_action == UserAction::kNone) {
|
||||
RunRestrictedPathCallback(should_block ? SensitiveEntryResult::kAbort
|
||||
: SensitiveEntryResult::kAllowed);
|
||||
auto result = should_block ? SensitiveEntryResult::kAbort
|
||||
: SensitiveEntryResult::kAllowed;
|
||||
RunRestrictedPathCallback(path_info.path, result);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -674,11 +683,11 @@ void FileSystemAccessPermissionContext::DidCheckPathAgainstBlocklist(
|
||||
"file-system-access-restricted", details,
|
||||
base::BindRepeating(
|
||||
&FileSystemAccessPermissionContext::OnRestrictedPathResult,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
weak_factory_.GetWeakPtr(), path_info.path));
|
||||
return;
|
||||
}
|
||||
|
||||
RunRestrictedPathCallback(SensitiveEntryResult::kAllowed);
|
||||
RunRestrictedPathCallback(path_info.path, SensitiveEntryResult::kAllowed);
|
||||
}
|
||||
|
||||
void FileSystemAccessPermissionContext::MaybeEvictEntries(
|
||||
@@ -866,12 +875,22 @@ void FileSystemAccessPermissionContext::RevokeActiveGrants(
|
||||
auto origin_it = active_permissions_map_.find(origin);
|
||||
if (origin_it != active_permissions_map_.end()) {
|
||||
OriginState& origin_state = origin_it->second;
|
||||
for (auto& grant : origin_state.read_grants) {
|
||||
for (auto grant_iter = origin_state.read_grants.begin(),
|
||||
grant_end = origin_state.read_grants.end();
|
||||
grant_iter != grant_end;) {
|
||||
// The grant may be removed from `read_grants`, so increase the iterator
|
||||
// before continuing.
|
||||
auto& grant = *(grant_iter++);
|
||||
if (file_path.empty() || grant.first == file_path) {
|
||||
grant.second->SetStatus(PermissionStatus::ASK);
|
||||
}
|
||||
}
|
||||
for (auto& grant : origin_state.write_grants) {
|
||||
for (auto grant_iter = origin_state.write_grants.begin(),
|
||||
grant_end = origin_state.write_grants.end();
|
||||
grant_iter != grant_end;) {
|
||||
// The grant may be removed from `write_grants`, so increase the iterator
|
||||
// before continuing.
|
||||
auto& grant = *(grant_iter++);
|
||||
if (file_path.empty() || grant.first == file_path) {
|
||||
grant.second->SetStatus(PermissionStatus::ASK);
|
||||
}
|
||||
|
||||
@@ -144,9 +144,11 @@ class FileSystemAccessPermissionContext
|
||||
content::GlobalRenderFrameHostId frame_id,
|
||||
bool should_block);
|
||||
|
||||
void RunRestrictedPathCallback(SensitiveEntryResult result);
|
||||
void RunRestrictedPathCallback(const base::FilePath& file_path,
|
||||
SensitiveEntryResult result);
|
||||
|
||||
void OnRestrictedPathResult(gin::Arguments* args);
|
||||
void OnRestrictedPathResult(const base::FilePath& file_path,
|
||||
gin::Arguments* args);
|
||||
|
||||
void MaybeEvictEntries(base::Value::Dict& dict);
|
||||
|
||||
@@ -170,7 +172,8 @@ class FileSystemAccessPermissionContext
|
||||
|
||||
std::map<url::Origin, base::Value::Dict> id_pathinfo_map_;
|
||||
|
||||
base::OnceCallback<void(SensitiveEntryResult)> callback_;
|
||||
std::map<base::FilePath, base::OnceCallback<void(SensitiveEntryResult)>>
|
||||
callback_map_;
|
||||
|
||||
base::WeakPtrFactory<FileSystemAccessPermissionContext> weak_factory_{this};
|
||||
};
|
||||
|
||||
@@ -169,9 +169,6 @@ class NativeWindowMac : public NativeWindow,
|
||||
void NotifyWindowDidFailToEnterFullScreen();
|
||||
void NotifyWindowWillLeaveFullScreen();
|
||||
|
||||
// views::WidgetDelegate:
|
||||
views::View* GetContentsView() override;
|
||||
|
||||
// Cleanup observers when window is getting closed. Note that the destructor
|
||||
// can be called much later after window gets closed, so we should not do
|
||||
// cleanup in destructor.
|
||||
@@ -223,6 +220,7 @@ class NativeWindowMac : public NativeWindow,
|
||||
|
||||
protected:
|
||||
// views::WidgetDelegate:
|
||||
views::View* GetContentsView() override;
|
||||
bool CanMaximize() const override;
|
||||
std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView(
|
||||
views::Widget* widget) override;
|
||||
|
||||
@@ -194,6 +194,8 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||
params.bounds = bounds;
|
||||
params.delegate = this;
|
||||
params.type = views::Widget::InitParams::TYPE_WINDOW;
|
||||
// Allow painting before shown, to be later disabled in ElectronNSWindow.
|
||||
params.headless_mode = true;
|
||||
params.native_widget =
|
||||
new ElectronNativeWidgetMac(this, windowType, styleMask, widget());
|
||||
widget()->Init(std::move(params));
|
||||
@@ -1674,6 +1676,7 @@ void NativeWindowMac::Cleanup() {
|
||||
DCHECK(!IsClosed());
|
||||
ui::NativeTheme::GetInstanceForNativeUi()->RemoveObserver(this);
|
||||
display::Screen::GetScreen()->RemoveObserver(this);
|
||||
[window_ cleanup];
|
||||
}
|
||||
|
||||
class NativeAppWindowFrameViewMac : public views::NativeFrameViewMac {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "content/public/browser/desktop_media_id.h"
|
||||
#include "content/public/common/color_parser.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
#include "shell/browser/ui/views/root_view.h"
|
||||
#include "shell/browser/web_contents_preferences.h"
|
||||
#include "shell/browser/web_view_manager.h"
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_
|
||||
|
||||
#include "ui/views/controls/native/native_view_host.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
// Automatically attach the native view after the NativeViewHost is attached to
|
||||
// a widget. (Attaching it directly would cause crash.)
|
||||
class DelayedNativeViewHost : public views::NativeViewHost {
|
||||
public:
|
||||
explicit DelayedNativeViewHost(gfx::NativeView native_view);
|
||||
~DelayedNativeViewHost() override;
|
||||
|
||||
// disable copy
|
||||
DelayedNativeViewHost(const DelayedNativeViewHost&) = delete;
|
||||
DelayedNativeViewHost& operator=(const DelayedNativeViewHost&) = delete;
|
||||
|
||||
// views::View:
|
||||
void ViewHierarchyChanged(
|
||||
const views::ViewHierarchyChangedDetails& details) override;
|
||||
|
||||
private:
|
||||
gfx::NativeView native_view_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_COCOA_DELAYED_NATIVE_VIEW_HOST_H_
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright (c) 2018 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/ui/cocoa/delayed_native_view_host.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
DelayedNativeViewHost::DelayedNativeViewHost(gfx::NativeView native_view)
|
||||
: native_view_(native_view) {}
|
||||
|
||||
DelayedNativeViewHost::~DelayedNativeViewHost() = default;
|
||||
|
||||
void DelayedNativeViewHost::ViewHierarchyChanged(
|
||||
const views::ViewHierarchyChangedDetails& details) {
|
||||
if (!details.is_add && native_view())
|
||||
Detach();
|
||||
NativeViewHost::ViewHierarchyChanged(details);
|
||||
if (details.is_add && GetWidget() && !native_view())
|
||||
Attach(native_view_);
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
@@ -1,54 +0,0 @@
|
||||
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-CHROMIUM file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
#include "base/apple/owned_objc.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h"
|
||||
#include "ui/base/cocoa/base_view.h"
|
||||
|
||||
namespace electron {
|
||||
class InspectableWebContentsViewMac;
|
||||
}
|
||||
|
||||
using electron::InspectableWebContentsViewMac;
|
||||
|
||||
@interface NSView (WebContentsView)
|
||||
- (void)setMouseDownCanMoveWindow:(BOOL)can_move;
|
||||
@end
|
||||
|
||||
@interface ElectronInspectableWebContentsView : BaseView <NSWindowDelegate> {
|
||||
@private
|
||||
raw_ptr<electron::InspectableWebContentsViewMac> inspectableWebContentsView_;
|
||||
|
||||
NSView* __strong fake_view_;
|
||||
NSWindow* __strong devtools_window_;
|
||||
BOOL devtools_visible_;
|
||||
BOOL devtools_docked_;
|
||||
BOOL devtools_is_first_responder_;
|
||||
BOOL attached_to_window_;
|
||||
|
||||
DevToolsContentsResizingStrategy strategy_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithInspectableWebContentsViewMac:
|
||||
(InspectableWebContentsViewMac*)view;
|
||||
- (void)notifyDevToolsFocused;
|
||||
- (void)setCornerRadii:(CGFloat)cornerRadius;
|
||||
- (void)setDevToolsVisible:(BOOL)visible activate:(BOOL)activate;
|
||||
- (BOOL)isDevToolsVisible;
|
||||
- (BOOL)isDevToolsFocused;
|
||||
- (void)setIsDocked:(BOOL)docked activate:(BOOL)activate;
|
||||
- (void)setContentsResizingStrategy:
|
||||
(const DevToolsContentsResizingStrategy&)strategy;
|
||||
- (void)setTitle:(NSString*)title;
|
||||
- (NSString*)getTitle;
|
||||
|
||||
@end
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_INSPECTABLE_WEB_CONTENTS_VIEW_H_
|
||||
@@ -1,337 +0,0 @@
|
||||
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-CHROMIUM file.
|
||||
|
||||
#include "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h"
|
||||
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/ui/cocoa/event_dispatching_window.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_mac.h"
|
||||
#include "ui/base/cocoa/base_view.h"
|
||||
#include "ui/gfx/mac/scoped_cocoa_disable_screen_updates.h"
|
||||
|
||||
@implementation ElectronInspectableWebContentsView
|
||||
|
||||
- (instancetype)initWithInspectableWebContentsViewMac:
|
||||
(InspectableWebContentsViewMac*)view {
|
||||
self = [super init];
|
||||
if (!self)
|
||||
return nil;
|
||||
|
||||
inspectableWebContentsView_ = view;
|
||||
devtools_visible_ = NO;
|
||||
devtools_docked_ = NO;
|
||||
devtools_is_first_responder_ = NO;
|
||||
attached_to_window_ = NO;
|
||||
|
||||
if (inspectableWebContentsView_->inspectable_web_contents()->is_guest()) {
|
||||
fake_view_ = [[NSView alloc] init];
|
||||
[fake_view_ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[self addSubview:fake_view_];
|
||||
} else {
|
||||
auto* contents = inspectableWebContentsView_->inspectable_web_contents()
|
||||
->GetWebContents();
|
||||
auto* contentsView = contents->GetNativeView().GetNativeNSView();
|
||||
[contentsView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
|
||||
[self addSubview:contentsView];
|
||||
}
|
||||
|
||||
// See https://code.google.com/p/chromium/issues/detail?id=348490.
|
||||
[self setWantsLayer:YES];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
- (void)resizeSubviewsWithOldSize:(NSSize)oldBoundsSize {
|
||||
[self adjustSubviews];
|
||||
}
|
||||
|
||||
- (void)viewDidMoveToWindow {
|
||||
if (attached_to_window_ && !self.window) {
|
||||
attached_to_window_ = NO;
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
} else if (!attached_to_window_ && self.window) {
|
||||
attached_to_window_ = YES;
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(viewDidBecomeFirstResponder:)
|
||||
name:kViewDidBecomeFirstResponder
|
||||
object:nil];
|
||||
[[NSNotificationCenter defaultCenter]
|
||||
addObserver:self
|
||||
selector:@selector(parentWindowBecameMain:)
|
||||
name:NSWindowDidBecomeMainNotification
|
||||
object:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)showDevTools:(id)sender {
|
||||
inspectableWebContentsView_->inspectable_web_contents()->ShowDevTools(true);
|
||||
}
|
||||
|
||||
- (void)notifyDevToolsFocused {
|
||||
if (inspectableWebContentsView_->GetDelegate())
|
||||
inspectableWebContentsView_->GetDelegate()->DevToolsFocused();
|
||||
}
|
||||
|
||||
- (void)setCornerRadii:(CGFloat)cornerRadius {
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
DCHECK(inspectable_web_contents);
|
||||
auto* webContents = inspectable_web_contents->GetWebContents();
|
||||
if (!webContents)
|
||||
return;
|
||||
auto* webContentsView = webContents->GetNativeView().GetNativeNSView();
|
||||
webContentsView.wantsLayer = YES;
|
||||
webContentsView.layer.cornerRadius = cornerRadius;
|
||||
}
|
||||
|
||||
- (void)notifyDevToolsResized {
|
||||
// When devtools is opened, resizing devtools would not trigger
|
||||
// UpdateDraggableRegions for WebContents, so we have to notify the window
|
||||
// to do an update of draggable regions.
|
||||
if (inspectableWebContentsView_->GetDelegate())
|
||||
inspectableWebContentsView_->GetDelegate()->DevToolsResized();
|
||||
}
|
||||
|
||||
- (void)setDevToolsVisible:(BOOL)visible activate:(BOOL)activate {
|
||||
if (visible == devtools_visible_)
|
||||
return;
|
||||
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto* devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView();
|
||||
|
||||
devtools_visible_ = visible;
|
||||
if (devtools_docked_) {
|
||||
if (visible) {
|
||||
// Place the devToolsView under contentsView, notice that we didn't set
|
||||
// sizes for them until the setContentsResizingStrategy message.
|
||||
[self addSubview:devToolsView positioned:NSWindowBelow relativeTo:nil];
|
||||
[self adjustSubviews];
|
||||
|
||||
// Focus on web view.
|
||||
devToolsWebContents->RestoreFocus();
|
||||
} else {
|
||||
gfx::ScopedCocoaDisableScreenUpdates disabler;
|
||||
[devToolsView removeFromSuperview];
|
||||
[self adjustSubviews];
|
||||
[self notifyDevToolsResized];
|
||||
}
|
||||
} else {
|
||||
if (visible) {
|
||||
if (activate) {
|
||||
[devtools_window_ makeKeyAndOrderFront:nil];
|
||||
} else {
|
||||
[devtools_window_ orderBack:nil];
|
||||
}
|
||||
} else {
|
||||
[devtools_window_ setDelegate:nil];
|
||||
[devtools_window_ close];
|
||||
devtools_window_ = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isDevToolsVisible {
|
||||
return devtools_visible_;
|
||||
}
|
||||
|
||||
- (BOOL)isDevToolsFocused {
|
||||
if (devtools_docked_) {
|
||||
return [[self window] isKeyWindow] && devtools_is_first_responder_;
|
||||
} else {
|
||||
return [devtools_window_ isKeyWindow];
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove NSWindowStyleMaskTexturedBackground.
|
||||
// https://github.com/electron/electron/issues/43125
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
- (void)setIsDocked:(BOOL)docked activate:(BOOL)activate {
|
||||
// Revert to no-devtools state.
|
||||
[self setDevToolsVisible:NO activate:NO];
|
||||
|
||||
// Switch to new state.
|
||||
devtools_docked_ = docked;
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
auto devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView();
|
||||
if (!docked) {
|
||||
auto styleMask = NSWindowStyleMaskTitled | NSWindowStyleMaskClosable |
|
||||
NSWindowStyleMaskMiniaturizable |
|
||||
NSWindowStyleMaskResizable |
|
||||
NSWindowStyleMaskTexturedBackground |
|
||||
NSWindowStyleMaskUnifiedTitleAndToolbar;
|
||||
devtools_window_ = [[EventDispatchingWindow alloc]
|
||||
initWithContentRect:NSMakeRect(0, 0, 800, 600)
|
||||
styleMask:styleMask
|
||||
backing:NSBackingStoreBuffered
|
||||
defer:YES];
|
||||
[devtools_window_ setDelegate:self];
|
||||
[devtools_window_ setFrameAutosaveName:@"electron.devtools"];
|
||||
[devtools_window_ setTitle:@"Developer Tools"];
|
||||
[devtools_window_ setReleasedWhenClosed:NO];
|
||||
[devtools_window_ setAutorecalculatesContentBorderThickness:NO
|
||||
forEdge:NSMaxYEdge];
|
||||
[devtools_window_ setContentBorderThickness:24 forEdge:NSMaxYEdge];
|
||||
|
||||
NSView* contentView = [devtools_window_ contentView];
|
||||
devToolsView.frame = contentView.bounds;
|
||||
devToolsView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
[contentView addSubview:devToolsView];
|
||||
[devToolsView setMouseDownCanMoveWindow:NO];
|
||||
} else {
|
||||
[devToolsView setMouseDownCanMoveWindow:YES];
|
||||
}
|
||||
[self setDevToolsVisible:YES activate:activate];
|
||||
}
|
||||
|
||||
// -Wdeprecated-declarations
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
- (void)setContentsResizingStrategy:
|
||||
(const DevToolsContentsResizingStrategy&)strategy {
|
||||
strategy_.CopyFrom(strategy);
|
||||
[self adjustSubviews];
|
||||
}
|
||||
|
||||
- (void)adjustSubviews {
|
||||
if (![[self subviews] count])
|
||||
return;
|
||||
|
||||
if (![self isDevToolsVisible] || devtools_window_) {
|
||||
DCHECK_EQ(1u, [[self subviews] count]);
|
||||
NSView* contents = [[self subviews] objectAtIndex:0];
|
||||
[contents setFrame:[self bounds]];
|
||||
return;
|
||||
}
|
||||
|
||||
NSView* devToolsView = [[self subviews] objectAtIndex:0];
|
||||
NSView* contentsView = [[self subviews] objectAtIndex:1];
|
||||
|
||||
DCHECK_EQ(2u, [[self subviews] count]);
|
||||
|
||||
gfx::Rect new_devtools_bounds;
|
||||
gfx::Rect new_contents_bounds;
|
||||
ApplyDevToolsContentsResizingStrategy(
|
||||
strategy_, gfx::Size(NSSizeToCGSize([self bounds].size)),
|
||||
&new_devtools_bounds, &new_contents_bounds);
|
||||
[devToolsView setFrame:[self flipRectToNSRect:new_devtools_bounds]];
|
||||
[contentsView setFrame:[self flipRectToNSRect:new_contents_bounds]];
|
||||
|
||||
// Move mask to the devtools area to exclude it from dragging.
|
||||
NSRect cf = contentsView.frame;
|
||||
NSRect sb = [self bounds];
|
||||
NSRect devtools_frame;
|
||||
if (cf.size.height < sb.size.height) { // bottom docked
|
||||
devtools_frame.origin.x = 0;
|
||||
devtools_frame.origin.y = 0;
|
||||
devtools_frame.size.width = sb.size.width;
|
||||
devtools_frame.size.height = sb.size.height - cf.size.height;
|
||||
} else { // left or right docked
|
||||
if (cf.origin.x > 0) // left docked
|
||||
devtools_frame.origin.x = 0;
|
||||
else // right docked.
|
||||
devtools_frame.origin.x = cf.size.width;
|
||||
devtools_frame.origin.y = 0;
|
||||
devtools_frame.size.width = sb.size.width - cf.size.width;
|
||||
devtools_frame.size.height = sb.size.height;
|
||||
}
|
||||
|
||||
[self notifyDevToolsResized];
|
||||
}
|
||||
|
||||
- (void)setTitle:(NSString*)title {
|
||||
[devtools_window_ setTitle:title];
|
||||
}
|
||||
|
||||
- (NSString*)getTitle {
|
||||
return [devtools_window_ title];
|
||||
}
|
||||
|
||||
- (void)viewDidBecomeFirstResponder:(NSNotification*)notification {
|
||||
auto* inspectable_web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents();
|
||||
DCHECK(inspectable_web_contents);
|
||||
auto* webContents = inspectable_web_contents->GetWebContents();
|
||||
if (!webContents)
|
||||
return;
|
||||
auto* webContentsView = webContents->GetNativeView().GetNativeNSView();
|
||||
|
||||
NSView* view = [notification object];
|
||||
if ([[webContentsView subviews] containsObject:view]) {
|
||||
devtools_is_first_responder_ = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
auto* devToolsWebContents =
|
||||
inspectable_web_contents->GetDevToolsWebContents();
|
||||
if (!devToolsWebContents)
|
||||
return;
|
||||
auto devToolsView = devToolsWebContents->GetNativeView().GetNativeNSView();
|
||||
|
||||
if ([[devToolsView subviews] containsObject:view]) {
|
||||
devtools_is_first_responder_ = YES;
|
||||
[self notifyDevToolsFocused];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)parentWindowBecameMain:(NSNotification*)notification {
|
||||
NSWindow* parentWindow = [notification object];
|
||||
if ([self window] == parentWindow && devtools_docked_ &&
|
||||
devtools_is_first_responder_)
|
||||
[self notifyDevToolsFocused];
|
||||
}
|
||||
|
||||
#pragma mark - NSWindowDelegate
|
||||
|
||||
- (void)windowWillClose:(NSNotification*)notification {
|
||||
inspectableWebContentsView_->inspectable_web_contents()->CloseDevTools();
|
||||
}
|
||||
|
||||
- (void)windowDidBecomeMain:(NSNotification*)notification {
|
||||
content::WebContents* web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents()
|
||||
->GetDevToolsWebContents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
web_contents->RestoreFocus();
|
||||
|
||||
content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
|
||||
if (rwhv)
|
||||
rwhv->SetActive(true);
|
||||
|
||||
[self notifyDevToolsFocused];
|
||||
}
|
||||
|
||||
- (void)windowDidResignMain:(NSNotification*)notification {
|
||||
content::WebContents* web_contents =
|
||||
inspectableWebContentsView_->inspectable_web_contents()
|
||||
->GetDevToolsWebContents();
|
||||
if (!web_contents)
|
||||
return;
|
||||
|
||||
web_contents->StoreFocus();
|
||||
|
||||
content::RenderWidgetHostView* rwhv = web_contents->GetRenderWidgetHostView();
|
||||
if (rwhv)
|
||||
rwhv->SetActive(false);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -29,6 +29,8 @@ class ScopedDisableResize {
|
||||
|
||||
} // namespace electron
|
||||
|
||||
class ElectronNativeWindowObserver;
|
||||
|
||||
@interface ElectronNSWindow : NativeWidgetMacNSWindow {
|
||||
@private
|
||||
raw_ptr<electron::NativeWindowMac> shell_;
|
||||
@@ -41,6 +43,7 @@ class ScopedDisableResize {
|
||||
@property(nonatomic, retain) NSImage* cornerMask;
|
||||
- (id)initWithShell:(electron::NativeWindowMac*)shell
|
||||
styleMask:(NSUInteger)styleMask;
|
||||
- (void)cleanup;
|
||||
- (electron::NativeWindowMac*)shell;
|
||||
- (id)accessibilityFocusedUIElement;
|
||||
- (NSRect)originalContentRectForFrameRect:(NSRect)frameRect;
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include "electron/mas.h"
|
||||
#include "shell/browser/api/electron_api_web_contents.h"
|
||||
#include "shell/browser/native_window_mac.h"
|
||||
#include "shell/browser/ui/cocoa/delayed_native_view_host.h"
|
||||
#include "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h"
|
||||
#include "shell/browser/ui/cocoa/electron_preview_item.h"
|
||||
#include "shell/browser/ui/cocoa/electron_touch_bar.h"
|
||||
#include "shell/browser/ui/cocoa/root_view_mac.h"
|
||||
@@ -113,6 +111,7 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
|
||||
method_getImplementation(new_swipe_with_event));
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
@implementation ElectronNSWindow
|
||||
@@ -168,6 +167,10 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)cleanup {
|
||||
shell_ = nullptr;
|
||||
}
|
||||
|
||||
- (electron::NativeWindowMac*)shell {
|
||||
return shell_;
|
||||
}
|
||||
@@ -255,6 +258,17 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) {
|
||||
[super setFrame:windowFrame display:displayViews];
|
||||
}
|
||||
|
||||
- (void)orderWindow:(NSWindowOrderingMode)place relativeTo:(NSInteger)otherWin {
|
||||
if (shell_) {
|
||||
// We initialize the window in headless mode to allow painting before it is
|
||||
// shown, but we don't want the headless behavior of allowing the window to
|
||||
// be placed unconstrained.
|
||||
self.isHeadless = false;
|
||||
shell_->widget()->DisableHeadlessMode();
|
||||
}
|
||||
[super orderWindow:place relativeTo:otherWin];
|
||||
}
|
||||
|
||||
- (id)accessibilityAttributeValue:(NSString*)attribute {
|
||||
if ([attribute isEqual:NSAccessibilityEnabledAttribute])
|
||||
return [NSNumber numberWithBool:YES];
|
||||
|
||||
@@ -365,6 +365,19 @@ using FullScreenTransitionState =
|
||||
shell_->GetNativeWindow());
|
||||
auto* bridged_view = bridge_host->GetInProcessNSWindowBridge();
|
||||
bridged_view->OnWindowWillClose();
|
||||
|
||||
// Native widget and its compositor have been destroyed upon close. We need
|
||||
// to detach contents view in order to prevent reusing its layer without
|
||||
// compositor in the `WebContentsViewMac::CreateViewForWidget`, leading to
|
||||
// `DCHECK` failure in `BrowserCompositorMac::SetParentUiLayer`.
|
||||
auto* contents_view =
|
||||
static_cast<views::WidgetDelegate*>(shell_)->GetContentsView();
|
||||
if (contents_view) {
|
||||
auto* parent = contents_view->parent();
|
||||
if (parent) {
|
||||
parent->RemoveChildView(contents_view);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)windowShouldClose:(id)window {
|
||||
|
||||
@@ -297,11 +297,6 @@ class InspectableWebContents::NetworkResourceLoader
|
||||
base::TimeDelta retry_delay_;
|
||||
};
|
||||
|
||||
// Implemented separately on each platform.
|
||||
InspectableWebContentsView* CreateInspectableContentsView(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
|
||||
// static
|
||||
// static
|
||||
void InspectableWebContents::RegisterPrefs(PrefRegistrySimple* registry) {
|
||||
registry->RegisterDictionaryPref(kDevToolsBoundsPref,
|
||||
@@ -317,7 +312,7 @@ InspectableWebContents::InspectableWebContents(
|
||||
: pref_service_(pref_service),
|
||||
web_contents_(std::move(web_contents)),
|
||||
is_guest_(is_guest),
|
||||
view_(CreateInspectableContentsView(this)) {
|
||||
view_(new InspectableWebContentsView(this)) {
|
||||
const base::Value* bounds_dict =
|
||||
&pref_service_->GetValue(kDevToolsBoundsPref);
|
||||
if (bounds_dict->is_dict()) {
|
||||
|
||||
@@ -5,12 +5,250 @@
|
||||
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "shell/browser/ui/drag_util.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
|
||||
#include "ui/base/models/image_model.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
#include "ui/views/controls/webview/webview.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
#include "ui/views/widget/widget_delegate.h"
|
||||
#include "ui/views/window/client_view.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
class DevToolsWindowDelegate : public views::ClientView,
|
||||
public views::WidgetDelegate {
|
||||
public:
|
||||
DevToolsWindowDelegate(InspectableWebContentsView* shell,
|
||||
views::View* view,
|
||||
views::Widget* widget)
|
||||
: views::ClientView(widget, view),
|
||||
shell_(shell),
|
||||
view_(view),
|
||||
widget_(widget) {
|
||||
SetOwnedByWidget(true);
|
||||
set_owned_by_client();
|
||||
|
||||
if (shell->GetDelegate())
|
||||
icon_ = shell->GetDelegate()->GetDevToolsWindowIcon();
|
||||
}
|
||||
~DevToolsWindowDelegate() override = default;
|
||||
|
||||
// disable copy
|
||||
DevToolsWindowDelegate(const DevToolsWindowDelegate&) = delete;
|
||||
DevToolsWindowDelegate& operator=(const DevToolsWindowDelegate&) = delete;
|
||||
|
||||
// views::WidgetDelegate:
|
||||
views::View* GetInitiallyFocusedView() override { return view_; }
|
||||
std::u16string GetWindowTitle() const override { return shell_->GetTitle(); }
|
||||
ui::ImageModel GetWindowAppIcon() override { return GetWindowIcon(); }
|
||||
ui::ImageModel GetWindowIcon() override { return icon_; }
|
||||
views::Widget* GetWidget() override { return widget_; }
|
||||
const views::Widget* GetWidget() const override { return widget_; }
|
||||
views::View* GetContentsView() override { return view_; }
|
||||
views::ClientView* CreateClientView(views::Widget* widget) override {
|
||||
return this;
|
||||
}
|
||||
|
||||
// views::ClientView:
|
||||
views::CloseRequestResult OnWindowCloseRequested() override {
|
||||
shell_->inspectable_web_contents()->CloseDevTools();
|
||||
return views::CloseRequestResult::kCannotClose;
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<InspectableWebContentsView> shell_;
|
||||
raw_ptr<views::View> view_;
|
||||
raw_ptr<views::Widget> widget_;
|
||||
ui::ImageModel icon_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
InspectableWebContentsView::InspectableWebContentsView(
|
||||
InspectableWebContents* inspectable_web_contents)
|
||||
: inspectable_web_contents_(inspectable_web_contents) {}
|
||||
: inspectable_web_contents_(inspectable_web_contents),
|
||||
devtools_web_view_(new views::WebView(nullptr)),
|
||||
title_(u"Developer Tools") {
|
||||
if (!inspectable_web_contents_->is_guest() &&
|
||||
inspectable_web_contents_->GetWebContents()->GetNativeView()) {
|
||||
auto* contents_web_view = new views::WebView(nullptr);
|
||||
contents_web_view->SetWebContents(
|
||||
inspectable_web_contents_->GetWebContents());
|
||||
contents_web_view_ = contents_web_view;
|
||||
} else {
|
||||
no_contents_view_ = new views::Label(u"No content under offscreen mode");
|
||||
}
|
||||
|
||||
InspectableWebContentsView::~InspectableWebContentsView() = default;
|
||||
devtools_web_view_->SetVisible(false);
|
||||
AddChildView(devtools_web_view_.get());
|
||||
AddChildView(GetContentsView());
|
||||
}
|
||||
|
||||
InspectableWebContentsView::~InspectableWebContentsView() {
|
||||
if (devtools_window_)
|
||||
inspectable_web_contents()->SaveDevToolsBounds(
|
||||
devtools_window_->GetWindowBoundsInScreen());
|
||||
}
|
||||
|
||||
void InspectableWebContentsView::SetCornerRadii(
|
||||
const gfx::RoundedCornersF& corner_radii) {
|
||||
// WebView won't exist for offscreen rendering.
|
||||
if (contents_web_view_) {
|
||||
contents_web_view_->holder()->SetCornerRadii(corner_radii);
|
||||
}
|
||||
}
|
||||
|
||||
void InspectableWebContentsView::ShowDevTools(bool activate) {
|
||||
if (devtools_visible_)
|
||||
return;
|
||||
|
||||
devtools_visible_ = true;
|
||||
if (devtools_window_) {
|
||||
devtools_window_web_view_->SetWebContents(
|
||||
inspectable_web_contents_->GetDevToolsWebContents());
|
||||
devtools_window_->SetBounds(inspectable_web_contents()->dev_tools_bounds());
|
||||
if (activate) {
|
||||
devtools_window_->Show();
|
||||
} else {
|
||||
devtools_window_->ShowInactive();
|
||||
}
|
||||
|
||||
// Update draggable regions to account for the new dock position.
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
} else {
|
||||
devtools_web_view_->SetVisible(true);
|
||||
devtools_web_view_->SetWebContents(
|
||||
inspectable_web_contents_->GetDevToolsWebContents());
|
||||
devtools_web_view_->RequestFocus();
|
||||
DeprecatedLayoutImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
void InspectableWebContentsView::CloseDevTools() {
|
||||
if (!devtools_visible_)
|
||||
return;
|
||||
|
||||
devtools_visible_ = false;
|
||||
if (devtools_window_) {
|
||||
auto save_bounds = devtools_window_->IsMinimized()
|
||||
? devtools_window_->GetRestoredBounds()
|
||||
: devtools_window_->GetWindowBoundsInScreen();
|
||||
inspectable_web_contents()->SaveDevToolsBounds(save_bounds);
|
||||
|
||||
devtools_window_.reset();
|
||||
devtools_window_web_view_ = nullptr;
|
||||
devtools_window_delegate_ = nullptr;
|
||||
} else {
|
||||
devtools_web_view_->SetVisible(false);
|
||||
devtools_web_view_->SetWebContents(nullptr);
|
||||
DeprecatedLayoutImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
bool InspectableWebContentsView::IsDevToolsViewShowing() {
|
||||
return devtools_visible_;
|
||||
}
|
||||
|
||||
bool InspectableWebContentsView::IsDevToolsViewFocused() {
|
||||
if (devtools_window_web_view_)
|
||||
return devtools_window_web_view_->HasFocus();
|
||||
else if (devtools_web_view_)
|
||||
return devtools_web_view_->HasFocus();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void InspectableWebContentsView::SetIsDocked(bool docked, bool activate) {
|
||||
CloseDevTools();
|
||||
|
||||
if (!docked) {
|
||||
devtools_window_ = std::make_unique<views::Widget>();
|
||||
devtools_window_web_view_ = new views::WebView(nullptr);
|
||||
devtools_window_delegate_ = new DevToolsWindowDelegate(
|
||||
this, devtools_window_web_view_, devtools_window_.get());
|
||||
|
||||
views::Widget::InitParams params(
|
||||
views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET,
|
||||
views::Widget::InitParams::TYPE_WINDOW);
|
||||
params.delegate = devtools_window_delegate_;
|
||||
params.bounds = inspectable_web_contents()->dev_tools_bounds();
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
params.wm_role_name = "devtools";
|
||||
if (GetDelegate())
|
||||
GetDelegate()->GetDevToolsWindowWMClass(¶ms.wm_class_name,
|
||||
¶ms.wm_class_class);
|
||||
#endif
|
||||
|
||||
devtools_window_->Init(std::move(params));
|
||||
devtools_window_->UpdateWindowIcon();
|
||||
devtools_window_->widget_delegate()->SetHasWindowSizeControls(true);
|
||||
}
|
||||
|
||||
ShowDevTools(activate);
|
||||
}
|
||||
|
||||
void InspectableWebContentsView::SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy) {
|
||||
strategy_.CopyFrom(strategy);
|
||||
DeprecatedLayoutImmediately();
|
||||
}
|
||||
|
||||
void InspectableWebContentsView::SetTitle(const std::u16string& title) {
|
||||
if (devtools_window_) {
|
||||
title_ = title;
|
||||
devtools_window_->UpdateWindowTitle();
|
||||
}
|
||||
}
|
||||
|
||||
const std::u16string InspectableWebContentsView::GetTitle() {
|
||||
return title_;
|
||||
}
|
||||
|
||||
void InspectableWebContentsView::Layout(PassKey) {
|
||||
if (!devtools_web_view_->GetVisible()) {
|
||||
GetContentsView()->SetBoundsRect(GetContentsBounds());
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
LayoutSuperclass<View>(this);
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::Size container_size(width(), height());
|
||||
gfx::Rect new_devtools_bounds;
|
||||
gfx::Rect new_contents_bounds;
|
||||
ApplyDevToolsContentsResizingStrategy(
|
||||
strategy_, container_size, &new_devtools_bounds, &new_contents_bounds);
|
||||
|
||||
// DevTools cares about the specific position, so we have to compensate RTL
|
||||
// layout here.
|
||||
new_devtools_bounds.set_x(GetMirroredXForRect(new_devtools_bounds));
|
||||
new_contents_bounds.set_x(GetMirroredXForRect(new_contents_bounds));
|
||||
|
||||
devtools_web_view_->SetBoundsRect(new_devtools_bounds);
|
||||
GetContentsView()->SetBoundsRect(new_contents_bounds);
|
||||
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
LayoutSuperclass<View>(this);
|
||||
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
}
|
||||
|
||||
views::View* InspectableWebContentsView::GetContentsView() const {
|
||||
DCHECK(contents_web_view_ || no_contents_view_);
|
||||
|
||||
return contents_web_view_ ? contents_web_view_ : no_contents_view_;
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -9,13 +9,9 @@
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "build/build_config.h"
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
|
||||
#include "ui/views/view.h"
|
||||
#else
|
||||
#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h"
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
#endif
|
||||
#include "ui/views/view.h"
|
||||
|
||||
class DevToolsContentsResizingStrategy;
|
||||
|
||||
@@ -23,23 +19,22 @@ namespace gfx {
|
||||
class RoundedCornersF;
|
||||
} // namespace gfx
|
||||
|
||||
#if defined(TOOLKIT_VIEWS)
|
||||
namespace views {
|
||||
class View;
|
||||
class WebView;
|
||||
class Widget;
|
||||
class WidgetDelegate;
|
||||
} // namespace views
|
||||
#endif
|
||||
|
||||
namespace electron {
|
||||
|
||||
class InspectableWebContents;
|
||||
class InspectableWebContentsViewDelegate;
|
||||
|
||||
class InspectableWebContentsView {
|
||||
class InspectableWebContentsView : public views::View {
|
||||
public:
|
||||
explicit InspectableWebContentsView(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
virtual ~InspectableWebContentsView();
|
||||
~InspectableWebContentsView() override;
|
||||
|
||||
InspectableWebContents* inspectable_web_contents() {
|
||||
return inspectable_web_contents_;
|
||||
@@ -51,32 +46,40 @@ class InspectableWebContentsView {
|
||||
}
|
||||
InspectableWebContentsViewDelegate* GetDelegate() const { return delegate_; }
|
||||
|
||||
#if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
|
||||
// Returns the container control, which has devtools view attached.
|
||||
virtual views::View* GetView() = 0;
|
||||
#else
|
||||
virtual gfx::NativeView GetNativeView() const = 0;
|
||||
#endif
|
||||
void SetCornerRadii(const gfx::RoundedCornersF& corner_radii);
|
||||
|
||||
virtual void ShowDevTools(bool activate) = 0;
|
||||
virtual void SetCornerRadii(const gfx::RoundedCornersF& corner_radii) = 0;
|
||||
// Hide the DevTools view.
|
||||
virtual void CloseDevTools() = 0;
|
||||
virtual bool IsDevToolsViewShowing() = 0;
|
||||
virtual bool IsDevToolsViewFocused() = 0;
|
||||
virtual void SetIsDocked(bool docked, bool activate) = 0;
|
||||
virtual void SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy) = 0;
|
||||
virtual void SetTitle(const std::u16string& title) = 0;
|
||||
virtual const std::u16string GetTitle() = 0;
|
||||
void ShowDevTools(bool activate);
|
||||
void CloseDevTools();
|
||||
bool IsDevToolsViewShowing();
|
||||
bool IsDevToolsViewFocused();
|
||||
void SetIsDocked(bool docked, bool activate);
|
||||
void SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy);
|
||||
void SetTitle(const std::u16string& title);
|
||||
const std::u16string GetTitle();
|
||||
|
||||
// views::View:
|
||||
void Layout(PassKey) override;
|
||||
|
||||
private:
|
||||
views::View* GetContentsView() const;
|
||||
|
||||
protected:
|
||||
// Owns us.
|
||||
raw_ptr<InspectableWebContents> inspectable_web_contents_;
|
||||
|
||||
private:
|
||||
raw_ptr<InspectableWebContentsViewDelegate> delegate_ =
|
||||
nullptr; // weak references.
|
||||
|
||||
std::unique_ptr<views::Widget> devtools_window_;
|
||||
raw_ptr<views::WebView> devtools_window_web_view_ = nullptr;
|
||||
raw_ptr<views::WebView> contents_web_view_ = nullptr;
|
||||
raw_ptr<views::View> no_contents_view_ = nullptr;
|
||||
raw_ptr<views::WebView> devtools_web_view_ = nullptr;
|
||||
|
||||
DevToolsContentsResizingStrategy strategy_;
|
||||
bool devtools_visible_ = false;
|
||||
raw_ptr<views::WidgetDelegate> devtools_window_delegate_ = nullptr;
|
||||
std::u16string title_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-CHROMIUM file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_
|
||||
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
|
||||
@class ElectronInspectableWebContentsView;
|
||||
|
||||
namespace electron {
|
||||
|
||||
class InspectableWebContentsViewMac : public InspectableWebContentsView {
|
||||
public:
|
||||
explicit InspectableWebContentsViewMac(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
InspectableWebContentsViewMac(const InspectableWebContentsViewMac&) = delete;
|
||||
InspectableWebContentsViewMac& operator=(
|
||||
const InspectableWebContentsViewMac&) = delete;
|
||||
~InspectableWebContentsViewMac() override;
|
||||
|
||||
gfx::NativeView GetNativeView() const override;
|
||||
void SetCornerRadii(const gfx::RoundedCornersF& corner_radii) override;
|
||||
void ShowDevTools(bool activate) override;
|
||||
void CloseDevTools() override;
|
||||
bool IsDevToolsViewShowing() override;
|
||||
bool IsDevToolsViewFocused() override;
|
||||
void SetIsDocked(bool docked, bool activate) override;
|
||||
void SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy) override;
|
||||
void SetTitle(const std::u16string& title) override;
|
||||
const std::u16string GetTitle() override;
|
||||
|
||||
private:
|
||||
ElectronInspectableWebContentsView* __strong view_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_INSPECTABLE_WEB_CONTENTS_VIEW_MAC_H_
|
||||
@@ -1,75 +0,0 @@
|
||||
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
||||
// Copyright (c) 2013 Adam Roben <adam@roben.org>. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-CHROMIUM file.
|
||||
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_mac.h"
|
||||
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#import "shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
|
||||
#include "ui/gfx/geometry/rounded_corners_f.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
InspectableWebContentsView* CreateInspectableContentsView(
|
||||
InspectableWebContents* inspectable_web_contents) {
|
||||
return new InspectableWebContentsViewMac(inspectable_web_contents);
|
||||
}
|
||||
|
||||
InspectableWebContentsViewMac::InspectableWebContentsViewMac(
|
||||
InspectableWebContents* inspectable_web_contents)
|
||||
: InspectableWebContentsView(inspectable_web_contents),
|
||||
view_([[ElectronInspectableWebContentsView alloc]
|
||||
initWithInspectableWebContentsViewMac:this]) {}
|
||||
|
||||
InspectableWebContentsViewMac::~InspectableWebContentsViewMac() {
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:view_];
|
||||
CloseDevTools();
|
||||
}
|
||||
|
||||
gfx::NativeView InspectableWebContentsViewMac::GetNativeView() const {
|
||||
return view_;
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewMac::SetCornerRadii(
|
||||
const gfx::RoundedCornersF& corner_radii) {
|
||||
// We can assume all four values are identical.
|
||||
[view_ setCornerRadii:corner_radii.upper_left()];
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewMac::ShowDevTools(bool activate) {
|
||||
[view_ setDevToolsVisible:YES activate:activate];
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewMac::CloseDevTools() {
|
||||
[view_ setDevToolsVisible:NO activate:NO];
|
||||
}
|
||||
|
||||
bool InspectableWebContentsViewMac::IsDevToolsViewShowing() {
|
||||
return [view_ isDevToolsVisible];
|
||||
}
|
||||
|
||||
bool InspectableWebContentsViewMac::IsDevToolsViewFocused() {
|
||||
return [view_ isDevToolsFocused];
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewMac::SetIsDocked(bool docked, bool activate) {
|
||||
[view_ setIsDocked:docked activate:activate];
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewMac::SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy) {
|
||||
[view_ setContentsResizingStrategy:strategy];
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewMac::SetTitle(const std::u16string& title) {
|
||||
[view_ setTitle:base::SysUTF16ToNSString(title)];
|
||||
}
|
||||
|
||||
const std::u16string InspectableWebContentsViewMac::GetTitle() {
|
||||
return base::SysNSStringToUTF16([view_ getTitle]);
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
@@ -5,6 +5,8 @@
|
||||
#include "shell/browser/ui/views/frameless_view.h"
|
||||
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
#include "ui/aura/window.h"
|
||||
#include "ui/base/hit_test.h"
|
||||
#include "ui/base/metadata/metadata_impl_macros.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
|
||||
@@ -1,257 +0,0 @@
|
||||
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-CHROMIUM file.
|
||||
|
||||
#include "shell/browser/ui/views/inspectable_web_contents_view_views.h"
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "shell/browser/ui/drag_util.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
|
||||
#include "ui/base/models/image_model.h"
|
||||
#include "ui/gfx/geometry/rounded_corners_f.h"
|
||||
#include "ui/views/controls/label.h"
|
||||
#include "ui/views/controls/webview/webview.h"
|
||||
#include "ui/views/widget/widget.h"
|
||||
#include "ui/views/widget/widget_delegate.h"
|
||||
#include "ui/views/window/client_view.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
class DevToolsWindowDelegate : public views::ClientView,
|
||||
public views::WidgetDelegate {
|
||||
public:
|
||||
DevToolsWindowDelegate(InspectableWebContentsViewViews* shell,
|
||||
views::View* view,
|
||||
views::Widget* widget)
|
||||
: views::ClientView(widget, view),
|
||||
shell_(shell),
|
||||
view_(view),
|
||||
widget_(widget) {
|
||||
SetOwnedByWidget(true);
|
||||
set_owned_by_client();
|
||||
|
||||
if (shell->GetDelegate())
|
||||
icon_ = shell->GetDelegate()->GetDevToolsWindowIcon();
|
||||
}
|
||||
~DevToolsWindowDelegate() override = default;
|
||||
|
||||
// disable copy
|
||||
DevToolsWindowDelegate(const DevToolsWindowDelegate&) = delete;
|
||||
DevToolsWindowDelegate& operator=(const DevToolsWindowDelegate&) = delete;
|
||||
|
||||
// views::WidgetDelegate:
|
||||
views::View* GetInitiallyFocusedView() override { return view_; }
|
||||
std::u16string GetWindowTitle() const override { return shell_->GetTitle(); }
|
||||
ui::ImageModel GetWindowAppIcon() override { return GetWindowIcon(); }
|
||||
ui::ImageModel GetWindowIcon() override { return icon_; }
|
||||
views::Widget* GetWidget() override { return widget_; }
|
||||
const views::Widget* GetWidget() const override { return widget_; }
|
||||
views::View* GetContentsView() override { return view_; }
|
||||
views::ClientView* CreateClientView(views::Widget* widget) override {
|
||||
return this;
|
||||
}
|
||||
|
||||
// views::ClientView:
|
||||
views::CloseRequestResult OnWindowCloseRequested() override {
|
||||
shell_->inspectable_web_contents()->CloseDevTools();
|
||||
return views::CloseRequestResult::kCannotClose;
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<InspectableWebContentsViewViews> shell_;
|
||||
raw_ptr<views::View> view_;
|
||||
raw_ptr<views::Widget> widget_;
|
||||
ui::ImageModel icon_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
InspectableWebContentsView* CreateInspectableContentsView(
|
||||
InspectableWebContents* inspectable_web_contents) {
|
||||
return new InspectableWebContentsViewViews(inspectable_web_contents);
|
||||
}
|
||||
|
||||
InspectableWebContentsViewViews::InspectableWebContentsViewViews(
|
||||
InspectableWebContents* inspectable_web_contents)
|
||||
: InspectableWebContentsView(inspectable_web_contents),
|
||||
devtools_web_view_(new views::WebView(nullptr)),
|
||||
title_(u"Developer Tools") {
|
||||
if (!inspectable_web_contents_->is_guest() &&
|
||||
inspectable_web_contents_->GetWebContents()->GetNativeView()) {
|
||||
auto* contents_web_view = new views::WebView(nullptr);
|
||||
contents_web_view->SetWebContents(
|
||||
inspectable_web_contents_->GetWebContents());
|
||||
contents_view_ = contents_web_view_ = contents_web_view;
|
||||
} else {
|
||||
contents_view_ = new views::Label(u"No content under offscreen mode");
|
||||
}
|
||||
|
||||
devtools_web_view_->SetVisible(false);
|
||||
AddChildView(devtools_web_view_.get());
|
||||
AddChildView(contents_view_.get());
|
||||
}
|
||||
|
||||
InspectableWebContentsViewViews::~InspectableWebContentsViewViews() {
|
||||
if (devtools_window_)
|
||||
inspectable_web_contents()->SaveDevToolsBounds(
|
||||
devtools_window_->GetWindowBoundsInScreen());
|
||||
}
|
||||
|
||||
views::View* InspectableWebContentsViewViews::GetView() {
|
||||
return this;
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewViews::SetCornerRadii(
|
||||
const gfx::RoundedCornersF& corner_radii) {
|
||||
// WebView won't exist for offscreen rendering.
|
||||
if (contents_web_view_) {
|
||||
contents_web_view_->holder()->SetCornerRadii(
|
||||
gfx::RoundedCornersF(corner_radii));
|
||||
}
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewViews::ShowDevTools(bool activate) {
|
||||
if (devtools_visible_)
|
||||
return;
|
||||
|
||||
devtools_visible_ = true;
|
||||
if (devtools_window_) {
|
||||
devtools_window_web_view_->SetWebContents(
|
||||
inspectable_web_contents_->GetDevToolsWebContents());
|
||||
devtools_window_->SetBounds(inspectable_web_contents()->dev_tools_bounds());
|
||||
if (activate) {
|
||||
devtools_window_->Show();
|
||||
} else {
|
||||
devtools_window_->ShowInactive();
|
||||
}
|
||||
|
||||
// Update draggable regions to account for the new dock position.
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
} else {
|
||||
devtools_web_view_->SetVisible(true);
|
||||
devtools_web_view_->SetWebContents(
|
||||
inspectable_web_contents_->GetDevToolsWebContents());
|
||||
devtools_web_view_->RequestFocus();
|
||||
DeprecatedLayoutImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewViews::CloseDevTools() {
|
||||
if (!devtools_visible_)
|
||||
return;
|
||||
|
||||
devtools_visible_ = false;
|
||||
if (devtools_window_) {
|
||||
auto save_bounds = devtools_window_->IsMinimized()
|
||||
? devtools_window_->GetRestoredBounds()
|
||||
: devtools_window_->GetWindowBoundsInScreen();
|
||||
inspectable_web_contents()->SaveDevToolsBounds(save_bounds);
|
||||
|
||||
devtools_window_.reset();
|
||||
devtools_window_web_view_ = nullptr;
|
||||
devtools_window_delegate_ = nullptr;
|
||||
} else {
|
||||
devtools_web_view_->SetVisible(false);
|
||||
devtools_web_view_->SetWebContents(nullptr);
|
||||
DeprecatedLayoutImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
bool InspectableWebContentsViewViews::IsDevToolsViewShowing() {
|
||||
return devtools_visible_;
|
||||
}
|
||||
|
||||
bool InspectableWebContentsViewViews::IsDevToolsViewFocused() {
|
||||
if (devtools_window_web_view_)
|
||||
return devtools_window_web_view_->HasFocus();
|
||||
else if (devtools_web_view_)
|
||||
return devtools_web_view_->HasFocus();
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewViews::SetIsDocked(bool docked, bool activate) {
|
||||
CloseDevTools();
|
||||
|
||||
if (!docked) {
|
||||
devtools_window_ = std::make_unique<views::Widget>();
|
||||
devtools_window_web_view_ = new views::WebView(nullptr);
|
||||
devtools_window_delegate_ = new DevToolsWindowDelegate(
|
||||
this, devtools_window_web_view_, devtools_window_.get());
|
||||
|
||||
views::Widget::InitParams params{
|
||||
views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET};
|
||||
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
|
||||
params.delegate = devtools_window_delegate_;
|
||||
params.bounds = inspectable_web_contents()->dev_tools_bounds();
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
params.wm_role_name = "devtools";
|
||||
if (GetDelegate())
|
||||
GetDelegate()->GetDevToolsWindowWMClass(¶ms.wm_class_name,
|
||||
¶ms.wm_class_class);
|
||||
#endif
|
||||
|
||||
devtools_window_->Init(std::move(params));
|
||||
devtools_window_->UpdateWindowIcon();
|
||||
devtools_window_->widget_delegate()->SetHasWindowSizeControls(true);
|
||||
}
|
||||
|
||||
ShowDevTools(activate);
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewViews::SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy) {
|
||||
strategy_.CopyFrom(strategy);
|
||||
DeprecatedLayoutImmediately();
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewViews::SetTitle(const std::u16string& title) {
|
||||
if (devtools_window_) {
|
||||
title_ = title;
|
||||
devtools_window_->UpdateWindowTitle();
|
||||
}
|
||||
}
|
||||
|
||||
const std::u16string InspectableWebContentsViewViews::GetTitle() {
|
||||
return title_;
|
||||
}
|
||||
|
||||
void InspectableWebContentsViewViews::Layout(PassKey) {
|
||||
if (!devtools_web_view_->GetVisible()) {
|
||||
contents_view_->SetBoundsRect(GetContentsBounds());
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
LayoutSuperclass<View>(this);
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::Size container_size(width(), height());
|
||||
gfx::Rect new_devtools_bounds;
|
||||
gfx::Rect new_contents_bounds;
|
||||
ApplyDevToolsContentsResizingStrategy(
|
||||
strategy_, container_size, &new_devtools_bounds, &new_contents_bounds);
|
||||
|
||||
// DevTools cares about the specific position, so we have to compensate RTL
|
||||
// layout here.
|
||||
new_devtools_bounds.set_x(GetMirroredXForRect(new_devtools_bounds));
|
||||
new_contents_bounds.set_x(GetMirroredXForRect(new_contents_bounds));
|
||||
|
||||
devtools_web_view_->SetBoundsRect(new_devtools_bounds);
|
||||
contents_view_->SetBoundsRect(new_contents_bounds);
|
||||
|
||||
// Propagate layout call to all children, for example browser views.
|
||||
LayoutSuperclass<View>(this);
|
||||
|
||||
if (GetDelegate())
|
||||
GetDelegate()->DevToolsResized();
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
@@ -1,63 +0,0 @@
|
||||
// Copyright (c) 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-CHROMIUM file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_VIEWS_INSPECTABLE_WEB_CONTENTS_VIEW_VIEWS_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_VIEWS_INSPECTABLE_WEB_CONTENTS_VIEW_VIEWS_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "chrome/browser/devtools/devtools_contents_resizing_strategy.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view.h"
|
||||
#include "third_party/skia/include/core/SkRegion.h"
|
||||
#include "ui/views/view.h"
|
||||
|
||||
namespace views {
|
||||
class WebView;
|
||||
class Widget;
|
||||
class WidgetDelegate;
|
||||
} // namespace views
|
||||
|
||||
namespace electron {
|
||||
|
||||
class InspectableWebContentsViewViews : public InspectableWebContentsView,
|
||||
public views::View {
|
||||
public:
|
||||
explicit InspectableWebContentsViewViews(
|
||||
InspectableWebContents* inspectable_web_contents);
|
||||
~InspectableWebContentsViewViews() override;
|
||||
|
||||
// InspectableWebContentsView:
|
||||
views::View* GetView() override;
|
||||
void ShowDevTools(bool activate) override;
|
||||
void SetCornerRadii(const gfx::RoundedCornersF& corner_radii) override;
|
||||
void CloseDevTools() override;
|
||||
bool IsDevToolsViewShowing() override;
|
||||
bool IsDevToolsViewFocused() override;
|
||||
void SetIsDocked(bool docked, bool activate) override;
|
||||
void SetContentsResizingStrategy(
|
||||
const DevToolsContentsResizingStrategy& strategy) override;
|
||||
void SetTitle(const std::u16string& title) override;
|
||||
const std::u16string GetTitle() override;
|
||||
|
||||
// views::View:
|
||||
void Layout(PassKey) override;
|
||||
|
||||
private:
|
||||
std::unique_ptr<views::Widget> devtools_window_;
|
||||
raw_ptr<views::WebView> devtools_window_web_view_ = nullptr;
|
||||
raw_ptr<views::WebView> contents_web_view_ = nullptr;
|
||||
raw_ptr<views::View> contents_view_ = nullptr;
|
||||
raw_ptr<views::WebView> devtools_web_view_ = nullptr;
|
||||
|
||||
DevToolsContentsResizingStrategy strategy_;
|
||||
bool devtools_visible_ = false;
|
||||
raw_ptr<views::WidgetDelegate> devtools_window_delegate_ = nullptr;
|
||||
std::u16string title_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_VIEWS_INSPECTABLE_WEB_CONTENTS_VIEW_VIEWS_H_
|
||||
@@ -23,6 +23,13 @@ inline constexpr std::string_view kDeviceSerialNumberKey = "serialNumber";
|
||||
|
||||
inline constexpr base::cstring_view kRunAsNode = "ELECTRON_RUN_AS_NODE";
|
||||
|
||||
// Per-profile UUID to distinguish global shortcut sessions for
|
||||
// org.freedesktop.portal.GlobalShortcuts. This is a counterpart to
|
||||
// extensions::pref_names::kGlobalShortcutsUuid, which may be not defined
|
||||
// if extensions are disabled.
|
||||
inline constexpr char kElectronGlobalShortcutsUuid[] =
|
||||
"electron.global_shortcuts.uuid";
|
||||
|
||||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
|
||||
inline constexpr std::string_view kPDFExtensionPluginName =
|
||||
"Chromium PDF Viewer";
|
||||
|
||||
@@ -31,6 +31,11 @@
|
||||
#include "components/services/print_compositor/public/mojom/print_compositor.mojom.h" // nogncheck
|
||||
#endif // BUILDFLAG(ENABLE_PRINTING)
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING)
|
||||
#include "chrome/services/printing/print_backend_service_impl.h"
|
||||
#include "chrome/services/printing/public/mojom/print_backend_service.mojom.h"
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING)
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINTING) && BUILDFLAG(IS_WIN)
|
||||
#include "chrome/services/printing/pdf_to_emf_converter_factory.h"
|
||||
#endif
|
||||
@@ -72,6 +77,21 @@ auto RunPrintCompositor(
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING)
|
||||
auto RunPrintingSandboxedPrintBackendHost(
|
||||
mojo::PendingReceiver<printing::mojom::SandboxedPrintBackendHost>
|
||||
receiver) {
|
||||
return std::make_unique<printing::SandboxedPrintBackendHostImpl>(
|
||||
std::move(receiver));
|
||||
}
|
||||
auto RunPrintingUnsandboxedPrintBackendHost(
|
||||
mojo::PendingReceiver<printing::mojom::UnsandboxedPrintBackendHost>
|
||||
receiver) {
|
||||
return std::make_unique<printing::UnsandboxedPrintBackendHostImpl>(
|
||||
std::move(receiver));
|
||||
}
|
||||
#endif // BUILDFLAG(ENABLE_OOP_PRINTING)
|
||||
|
||||
auto RunProxyResolver(
|
||||
mojo::PendingReceiver<proxy_resolver::mojom::ProxyResolverFactory>
|
||||
receiver) {
|
||||
@@ -122,6 +142,11 @@ void ElectronContentUtilityClient::RegisterMainThreadServices(
|
||||
services.Add(RunPrintCompositor);
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_OOP_PRINTING)
|
||||
services.Add(RunPrintingSandboxedPrintBackendHost);
|
||||
services.Add(RunPrintingUnsandboxedPrintBackendHost);
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(ENABLE_PRINT_PREVIEW) || \
|
||||
(BUILDFLAG(ENABLE_PRINTING) && BUILDFLAG(IS_WIN))
|
||||
services.Add(RunPrintingService);
|
||||
|
||||
@@ -1272,6 +1272,7 @@ describe('BrowserWindow module', () => {
|
||||
// We first need to resign app focus for this test to work
|
||||
const isInactive = once(app, 'did-resign-active');
|
||||
childProcess.execSync('osascript -e \'tell application "Finder" to activate\'');
|
||||
defer(() => childProcess.execSync('osascript -e \'tell application "Finder" to quit\''));
|
||||
await isInactive;
|
||||
|
||||
// Create new window
|
||||
|
||||
@@ -99,7 +99,8 @@ ifdescribe(!(['arm', 'arm64'].includes(process.arch)) || (process.platform !== '
|
||||
this.timeout(5e3);
|
||||
}
|
||||
|
||||
it('does not crash on empty string', async () => {
|
||||
// FIXME(samuelmaddock): this test regularly flakes
|
||||
it.skip('does not crash on empty string', async () => {
|
||||
const options = {
|
||||
categoryFilter: '*',
|
||||
traceOptions: 'record-until-full,enable-sampling'
|
||||
|
||||
Reference in New Issue
Block a user