mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
27 Commits
fix/captur
...
v35.0.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc6164fe27 | ||
|
|
59e4794ff5 | ||
|
|
fa03b92f7e | ||
|
|
9d696ceffe | ||
|
|
e9b3e4cc91 | ||
|
|
895bc51272 | ||
|
|
ef1ad85082 | ||
|
|
e99328a45e | ||
|
|
04f5fe6a1c | ||
|
|
08b6bb1712 | ||
|
|
813efbcdf7 | ||
|
|
d34fa2e301 | ||
|
|
724744af16 | ||
|
|
91bb748eaa | ||
|
|
d77c2d75ed | ||
|
|
f4c3eb4391 | ||
|
|
9aca9e9fb6 | ||
|
|
e0fa647601 | ||
|
|
6b0fd02c0a | ||
|
|
1017ac821f | ||
|
|
91b53b633a | ||
|
|
8da9572592 | ||
|
|
291bbff5d8 | ||
|
|
d704a3fc5b | ||
|
|
fb70b81ee6 | ||
|
|
97fa059e1f | ||
|
|
8a64cdc0b1 |
@@ -16,5 +16,5 @@ runs:
|
||||
e auto-update disable
|
||||
if [ "$(expr substr $(uname -s) 1 10)" == "MSYS_NT-10" ]; then
|
||||
e d cipd.bat --version
|
||||
cp "C:\Python37\python.exe" "C:\Python37\python3.exe"
|
||||
cp "C:\Python311\python.exe" "C:\Python311\python3.exe"
|
||||
fi
|
||||
|
||||
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@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 #v4.6.0
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b #v4.5.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@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/copy-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/find-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/close-project@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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,13 +20,12 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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/')
|
||||
@@ -39,13 +38,12 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/add-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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,7 +10,6 @@ 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
|
||||
@@ -19,9 +18,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Remove from issue triage
|
||||
uses: dsanders11/project-actions/delete-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/delete-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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,10 +30,9 @@ jobs:
|
||||
org: electron
|
||||
- name: Set status
|
||||
if: ${{ steps.check-for-blocked-labels.outputs.NOT_BLOCKED }}
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: 📥 Was Blocked
|
||||
fail-if-item-not-found: false
|
||||
|
||||
@@ -56,8 +56,8 @@ on:
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: electron-build-and-test-and-nan-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-build-and-test-and-nan-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
@@ -56,8 +56,8 @@ on:
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: electron-build-and-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-build-and-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
4
.github/workflows/pipeline-electron-lint.yml
vendored
4
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -9,8 +9,8 @@ on:
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: electron-lint-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-lint-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
|
||||
@@ -61,8 +61,8 @@ on:
|
||||
|
||||
|
||||
concurrency:
|
||||
group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.target-variant }}-${{ inputs.is-asan }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-build-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.target-variant }}-${{ inputs.is-asan }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
env:
|
||||
ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }}
|
||||
|
||||
@@ -27,8 +27,8 @@ on:
|
||||
default: false
|
||||
|
||||
concurrency:
|
||||
group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ inputs.is-asan }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -239,7 +239,7 @@ jobs:
|
||||
if: always() && !cancelled()
|
||||
- name: Upload Test Artifacts
|
||||
if: always() && !cancelled()
|
||||
uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b
|
||||
with:
|
||||
name: test_artifacts_${{ env.ARTIFACT_KEY }}_${{ matrix.shard }}
|
||||
path: src/electron/spec/artifacts
|
||||
|
||||
@@ -27,8 +27,8 @@ on:
|
||||
default: testing
|
||||
|
||||
concurrency:
|
||||
group: electron-node-nan-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && !endsWith(github.ref, '-x-y') }}
|
||||
group: electron-node-nan-test-${{ inputs.target-platform }}-${{ inputs.target-arch }}-${{ github.ref_protected == true && github.run_id || github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_protected != true }}
|
||||
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
6
.github/workflows/pull-request-labeled.yml
vendored
6
.github/workflows/pull-request-labeled.yml
vendored
@@ -15,12 +15,12 @@ jobs:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@485a9d42d3a73031f12ec201c457e2162c45d02d # v2.0.0
|
||||
with:
|
||||
webhook: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
|
||||
webhook-type: webhook-trigger
|
||||
payload: |
|
||||
{
|
||||
"url": "${{ github.event.pull_request.html_url }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
|
||||
pull-request-labeled-deprecation-review-complete:
|
||||
name: deprecation-review/complete label added
|
||||
if: github.event.label.name == 'deprecation-review/complete ✅'
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
creds: ${{ secrets.RELEASE_BOARD_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/edit-item@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0
|
||||
uses: actions/upload-artifact@6f51ac03b9356f520e9adb1b1b7802705f340c2b # v4.5.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@b6a472f63d85b9c78a3ac5e89422239fc15e9b3c # v3.28.1
|
||||
uses: github/codeql-action/upload-sarif@48ab28a6f5dbc2a99bf1e0131198dd8f1df78169 # v3.28.0
|
||||
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@9c80cd31f58599941c64f74636bea95ba5d46090 # v1.5.1
|
||||
uses: dsanders11/project-actions/completed-by@438b25e007c2f4efec324497fadc6402e7cc61a6 # v1.4.0
|
||||
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@8bf425b4d1344db7cd469a8d10a390876e0c77fd # v4.45.1
|
||||
uses: mikefarah/yq@4839dbbf80445070a31c7a9c1055da527db2d5ee # v4.44.6
|
||||
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.11.0',
|
||||
'v22.9.0',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -127,6 +127,7 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* [pushNotifications](api/push-notifications.md)
|
||||
* [safeStorage](api/safe-storage.md)
|
||||
* [screen](api/screen.md)
|
||||
* [ServiceWorkerMain](api/service-worker-main.md)
|
||||
* [session](api/session.md)
|
||||
* [ShareMenu](api/share-menu.md)
|
||||
* [systemPreferences](api/system-preferences.md)
|
||||
|
||||
@@ -61,6 +61,20 @@ The `contextBridge` module has the following methods:
|
||||
* `apiKey` string - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
|
||||
* `api` any - Your API, more information on what this API can be and how it works is available below.
|
||||
|
||||
### `contextBridge.executeInMainWorld(executionScript)` _Experimental_
|
||||
|
||||
<!-- TODO(samuelmaddock): add generics to map the `args` types to the `func` params -->
|
||||
|
||||
* `executionScript` Object
|
||||
* `func` (...args: any[]) => any - A JavaScript function to execute. This function will be serialized which means
|
||||
that any bound parameters and execution context will be lost.
|
||||
* `args` any[] (optional) - An array of arguments to pass to the provided function. These
|
||||
arguments will be copied between worlds in accordance with
|
||||
[the table of supported types.](#parameter--error--return-type-support)
|
||||
|
||||
Returns `any` - A copy of the resulting value from executing the function in the main world.
|
||||
[Refer to the table](#parameter--error--return-type-support) on how values are copied between worlds.
|
||||
|
||||
## Usage
|
||||
|
||||
### API
|
||||
|
||||
@@ -12,17 +12,9 @@ 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', () => {
|
||||
|
||||
@@ -41,6 +41,16 @@ The `ipcRenderer` module has the following method to listen for events and send
|
||||
Listens to `channel`, when a new message arrives `listener` would be called with
|
||||
`listener(event, args...)`.
|
||||
|
||||
:::warning
|
||||
Do not expose the `event` argument to the renderer for security reasons! Wrap any
|
||||
callback that you receive from the renderer in another function like this:
|
||||
`ipcRenderer.on('my-channel', (event, ...args) => callback(...args))`.
|
||||
Not wrapping the callback in such a function would expose dangerous Electron APIs
|
||||
to the renderer process. See the
|
||||
[security guide](../tutorial/security.md#20-do-not-expose-electron-apis-to-untrusted-web-content)
|
||||
for more info.
|
||||
:::
|
||||
|
||||
### `ipcRenderer.off(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
|
||||
34
docs/api/service-worker-main.md
Normal file
34
docs/api/service-worker-main.md
Normal file
@@ -0,0 +1,34 @@
|
||||
# ServiceWorkerMain
|
||||
|
||||
> An instance of a Service Worker representing a version of a script for a given scope.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
## Class: ServiceWorkerMain
|
||||
|
||||
Process: [Main](../glossary.md#main-process)<br />
|
||||
_This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API._
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `serviceWorker.isDestroyed()` _Experimental_
|
||||
|
||||
Returns `boolean` - Whether the service worker has been destroyed.
|
||||
|
||||
#### `serviceWorker.startTask()` _Experimental_
|
||||
|
||||
Returns `Object`:
|
||||
|
||||
- `end` Function - Method to call when the task has ended. If never called, the service won't terminate while otherwise idle.
|
||||
|
||||
Initiate a task to keep the service worker alive until ended.
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `serviceWorker.scope` _Readonly_ _Experimental_
|
||||
|
||||
A `string` representing the scope URL of the service worker.
|
||||
|
||||
#### `serviceWorker.versionId` _Readonly_ _Experimental_
|
||||
|
||||
A `number` representing the ID of the specific version of the service worker script in its scope.
|
||||
@@ -56,6 +56,17 @@ Returns:
|
||||
|
||||
Emitted when a service worker has been registered. Can occur after a call to [`navigator.serviceWorker.register('/sw.js')`](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerContainer/register) successfully resolves or when a Chrome extension is loaded.
|
||||
|
||||
#### Event: 'running-status-changed' _Experimental_
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `versionId` number - ID of the updated service worker version
|
||||
* `runningStatus` string - Running status.
|
||||
Possible values include `starting`, `running`, `stopping`, or `stopped`.
|
||||
|
||||
Emitted when a service worker's running status has changed.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
The following methods are available on instances of `ServiceWorkers`:
|
||||
@@ -64,10 +75,56 @@ The following methods are available on instances of `ServiceWorkers`:
|
||||
|
||||
Returns `Record<number, ServiceWorkerInfo>` - A [ServiceWorkerInfo](structures/service-worker-info.md) object where the keys are the service worker version ID and the values are the information about that service worker.
|
||||
|
||||
#### `serviceWorkers.getFromVersionID(versionId)`
|
||||
#### `serviceWorkers.getInfoFromVersionID(versionId)`
|
||||
|
||||
* `versionId` number
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
|
||||
|
||||
If the service worker does not exist or is not running this method will throw an exception.
|
||||
|
||||
#### `serviceWorkers.getFromVersionID(versionId)` _Deprecated_
|
||||
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
Returns [`ServiceWorkerInfo`](structures/service-worker-info.md) - Information about this service worker
|
||||
|
||||
If the service worker does not exist or is not running this method will throw an exception.
|
||||
|
||||
**Deprecated:** Use the new `serviceWorkers.getInfoFromVersionID` API.
|
||||
|
||||
#### `serviceWorkers.getWorkerFromVersionID(versionId)` _Experimental_
|
||||
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
Returns [`ServiceWorkerMain | undefined`](service-worker-main.md) - Instance of the service worker associated with the given version ID. If there's no associated version, or its running status has changed to 'stopped', this will return `undefined`.
|
||||
|
||||
#### `serviceWorkers.startWorkerForScope(scope)` _Experimental_
|
||||
|
||||
* `scope` string - The scope of the service worker to start.
|
||||
|
||||
Returns `Promise<ServiceWorkerMain>` - Resolves with the service worker when it's started.
|
||||
|
||||
Starts the service worker or does nothing if already running.
|
||||
|
||||
<!-- TODO(samuelmaddock): extend example to send IPC after starting worker -->
|
||||
|
||||
```js
|
||||
const { app, session } = require('electron')
|
||||
const { serviceWorkers } = session.defaultSession
|
||||
|
||||
// Collect service workers scopes
|
||||
const workerScopes = Object.values(serviceWorkers.getAllRunning()).map((info) => info.scope)
|
||||
|
||||
app.on('browser-window-created', async (event, window) => {
|
||||
for (const scope of workerScopes) {
|
||||
try {
|
||||
// Ensure worker is started
|
||||
await serviceWorkers.startWorkerForScope(scope)
|
||||
} catch (error) {
|
||||
console.error(`Failed to start service worker for ${scope}`)
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
@@ -1330,18 +1330,43 @@ the initial state will be `interrupted`. The download will start only when the
|
||||
|
||||
Returns `Promise<void>` - resolves when the session’s HTTP authentication cache has been cleared.
|
||||
|
||||
#### `ses.setPreloads(preloads)`
|
||||
#### `ses.setPreloads(preloads)` _Deprecated_
|
||||
|
||||
* `preloads` string[] - An array of absolute path to preload scripts
|
||||
|
||||
Adds scripts that will be executed on ALL web contents that are associated with
|
||||
this session just before normal `preload` scripts run.
|
||||
|
||||
#### `ses.getPreloads()`
|
||||
**Deprecated:** Use the new `ses.registerPreloadScript` API.
|
||||
|
||||
#### `ses.getPreloads()` _Deprecated_
|
||||
|
||||
Returns `string[]` an array of paths to preload scripts that have been
|
||||
registered.
|
||||
|
||||
**Deprecated:** Use the new `ses.getPreloadScripts` API. This will only return preload script paths
|
||||
for `frame` context types.
|
||||
|
||||
#### `ses.registerPreloadScript(script)`
|
||||
|
||||
* `script` [PreloadScriptRegistration](structures/preload-script-registration.md) - Preload script
|
||||
|
||||
Registers preload script that will be executed in its associated context type in this session. For
|
||||
`frame` contexts, this will run prior to any preload defined in the web preferences of a
|
||||
WebContents.
|
||||
|
||||
Returns `string` - The ID of the registered preload script.
|
||||
|
||||
#### `ses.unregisterPreloadScript(id)`
|
||||
|
||||
* `id` string - Preload script ID
|
||||
|
||||
Unregisters script.
|
||||
|
||||
#### `ses.getPreloadScripts()`
|
||||
|
||||
Returns [`PreloadScript[]`](structures/preload-script.md): An array of paths to preload scripts that have been registered.
|
||||
|
||||
#### `ses.setCodeCachePath(path)`
|
||||
|
||||
* `path` String - Absolute path to store the v8 generated JS code cache from the renderer.
|
||||
|
||||
6
docs/api/structures/preload-script-registration.md
Normal file
6
docs/api/structures/preload-script-registration.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# PreloadScriptRegistration Object
|
||||
|
||||
* `type` string - Context type where the preload script will be executed.
|
||||
Possible values include `frame`.
|
||||
* `id` string (optional) - Unique ID of preload script. Defaults to a random UUID.
|
||||
* `filePath` string - Path of the script file. Must be an absolute path.
|
||||
6
docs/api/structures/preload-script.md
Normal file
6
docs/api/structures/preload-script.md
Normal file
@@ -0,0 +1,6 @@
|
||||
# PreloadScript Object
|
||||
|
||||
* `type` string - Context type where the preload script will be executed.
|
||||
Possible values include `frame`.
|
||||
* `id` string - Unique ID of preload script.
|
||||
* `filePath` string - Path of the script file. Must be an absolute path.
|
||||
@@ -3,3 +3,4 @@
|
||||
* `scriptUrl` string - The full URL to the script that this service worker runs
|
||||
* `scope` string - The base URL that this service worker is active for.
|
||||
* `renderProcessId` number - The virtual ID of the process that this service worker is running in. This is not an OS level PID. This aligns with the ID set used for `webContents.getProcessId()`.
|
||||
* `versionId` number - ID of the service worker version
|
||||
|
||||
@@ -14,6 +14,40 @@ This document uses the following convention to categorize breaking changes:
|
||||
|
||||
## Planned Breaking API Changes (35.0)
|
||||
|
||||
### Deprecated: `setPreloads`, `getPreloads` on `Session`
|
||||
|
||||
`registerPreloadScript`, `unregisterPreloadScript`, and `getPreloadScripts` are introduced as a
|
||||
replacement for the deprecated methods. These new APIs allow third-party libraries to register
|
||||
preload scripts without replacing existing scripts. Also, the new `type` option allows for
|
||||
additional preload targets beyond `frame`.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
session.setPreloads([path.join(__dirname, 'preload.js')])
|
||||
|
||||
// Replace with:
|
||||
session.registerPreloadScript({
|
||||
type: 'frame',
|
||||
id: 'app-preload',
|
||||
filePath: path.join(__dirname, 'preload.js')
|
||||
})
|
||||
```
|
||||
|
||||
### Deprecated: `getFromVersionID` on `session.serviceWorkers`
|
||||
|
||||
The `session.serviceWorkers.fromVersionID(versionId)` API has been deprecated
|
||||
in favor of `session.serviceWorkers.getInfoFromVersionID(versionId)`. This was
|
||||
changed to make it more clear which object is returned with the introduction
|
||||
of the `session.serviceWorkers.getWorkerFromVersionID(versionId)` API.
|
||||
|
||||
```js
|
||||
// Deprecated
|
||||
session.serviceWorkers.fromVersionID(versionId)
|
||||
|
||||
// Replace with
|
||||
session.serviceWorkers.getInfoFromVersionID(versionId)
|
||||
```
|
||||
|
||||
### Deprecated: `level`, `message`, `line`, and `sourceId` arguments in `console-message` event on `WebContents`
|
||||
|
||||
The `console-message` event on `WebContents` has been updated to provide details on the `Event`
|
||||
@@ -56,15 +90,15 @@ immediately upon being received. Otherwise, it's not guaranteed to point to the
|
||||
same webpage as when received. To avoid misaligned expectations, Electron will
|
||||
return `null` in the case of late access where the webpage has changed.
|
||||
|
||||
```ts
|
||||
```js
|
||||
ipcMain.on('unload-event', (event) => {
|
||||
event.senderFrame; // ✅ accessed immediately
|
||||
});
|
||||
event.senderFrame // ✅ accessed immediately
|
||||
})
|
||||
|
||||
ipcMain.on('unload-event', async (event) => {
|
||||
await crossOriginNavigationPromise;
|
||||
event.senderFrame; // ❌ returns `null` due to late access
|
||||
});
|
||||
await crossOriginNavigationPromise
|
||||
event.senderFrame // ❌ returns `null` due to late access
|
||||
})
|
||||
```
|
||||
|
||||
### Behavior Changed: custom protocol URL handling on Windows
|
||||
|
||||
@@ -22,12 +22,9 @@ In `preload.js` use the [`contextBridge`][] to inject a method `window.electron.
|
||||
|
||||
```js
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
startDrag: (fileName) => {
|
||||
ipcRenderer.send('ondragstart', path.join(process.cwd(), fileName))
|
||||
}
|
||||
startDrag: (fileName) => ipcRenderer.send('ondragstart', fileName)
|
||||
})
|
||||
```
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ You should at least follow these steps to improve the security of your applicati
|
||||
17. [Validate the `sender` of all IPC messages](#17-validate-the-sender-of-all-ipc-messages)
|
||||
18. [Avoid usage of the `file://` protocol and prefer usage of custom protocols](#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols)
|
||||
19. [Check which fuses you can change](#19-check-which-fuses-you-can-change)
|
||||
20. [Do not expose Electron APIs to untrusted web content](#20-do-not-expose-electron-apis-to-untrusted-web-content)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
@@ -229,7 +230,7 @@ API to remotely loaded content via the [contextBridge API](../api/context-bridge
|
||||
### 3. Enable Context Isolation
|
||||
|
||||
:::info
|
||||
This recommendation is the default behavior in Electron since 12.0.0.
|
||||
Context Isolation is the default behavior in Electron since 12.0.0.
|
||||
:::
|
||||
|
||||
Context isolation is an Electron feature that allows developers to run code
|
||||
@@ -804,6 +805,48 @@ flipping these fuses easy. Check out the README of that module for more details
|
||||
potential error cases, and refer to
|
||||
[How do I flip the fuses?](./fuses.md#how-do-i-flip-the-fuses) in our documentation.
|
||||
|
||||
### 20. Do not expose Electron APIs to untrusted web content
|
||||
|
||||
You should not directly expose Electron's APIs, especially IPC, to untrusted web content in your
|
||||
preload scripts.
|
||||
|
||||
### Why?
|
||||
|
||||
Exposing raw APIs like `ipcRenderer.on` is dangerous because it gives renderer processes direct
|
||||
access to the entire IPC event system, allowing them to listen for any IPC events, not just the ones
|
||||
intended for them.
|
||||
|
||||
To avoid that exposure, we also cannot pass callbacks directly through: The first
|
||||
argument to IPC event callbacks is an `IpcRendererEvent` object, which includes properties like `sender`
|
||||
that provide access to the underlying `ipcRenderer` instance. Even if you only listen for specific
|
||||
events, passing the callback directly means the renderer gets access to this event object.
|
||||
|
||||
In short, we want the untrusted web content to only have access to necessary information and APIs.
|
||||
|
||||
### How?
|
||||
|
||||
```js title='preload'.js'
|
||||
// Bad
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
on: ipcRenderer.on
|
||||
})
|
||||
|
||||
// Also bad
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
|
||||
})
|
||||
|
||||
// Good
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', (_event, value) => callback(value))
|
||||
})
|
||||
```
|
||||
|
||||
:::info
|
||||
For more information on what `contextIsolation` is and how to use it to secure your app,
|
||||
please see the [Context Isolation](context-isolation.md) document.
|
||||
:::
|
||||
|
||||
[breaking-changes]: ../breaking-changes.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[webview-tag]: ../api/webview-tag.md
|
||||
|
||||
@@ -45,6 +45,7 @@ auto_filenames = {
|
||||
"docs/api/push-notifications.md",
|
||||
"docs/api/safe-storage.md",
|
||||
"docs/api/screen.md",
|
||||
"docs/api/service-worker-main.md",
|
||||
"docs/api/service-workers.md",
|
||||
"docs/api/session.md",
|
||||
"docs/api/share-menu.md",
|
||||
@@ -114,6 +115,8 @@ auto_filenames = {
|
||||
"docs/api/structures/permission-request.md",
|
||||
"docs/api/structures/point.md",
|
||||
"docs/api/structures/post-body.md",
|
||||
"docs/api/structures/preload-script-registration.md",
|
||||
"docs/api/structures/preload-script.md",
|
||||
"docs/api/structures/printer-info.md",
|
||||
"docs/api/structures/process-memory-info.md",
|
||||
"docs/api/structures/process-metric.md",
|
||||
@@ -183,6 +186,8 @@ auto_filenames = {
|
||||
"lib/sandboxed_renderer/api/exports/electron.ts",
|
||||
"lib/sandboxed_renderer/api/module-list.ts",
|
||||
"lib/sandboxed_renderer/init.ts",
|
||||
"lib/sandboxed_renderer/pre-init.ts",
|
||||
"lib/sandboxed_renderer/preload.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
@@ -239,6 +244,7 @@ auto_filenames = {
|
||||
"lib/browser/api/push-notifications.ts",
|
||||
"lib/browser/api/safe-storage.ts",
|
||||
"lib/browser/api/screen.ts",
|
||||
"lib/browser/api/service-worker-main.ts",
|
||||
"lib/browser/api/session.ts",
|
||||
"lib/browser/api/share-menu.ts",
|
||||
"lib/browser/api/system-preferences.ts",
|
||||
|
||||
@@ -296,6 +296,8 @@ filenames = {
|
||||
"shell/browser/api/electron_api_screen.h",
|
||||
"shell/browser/api/electron_api_service_worker_context.cc",
|
||||
"shell/browser/api/electron_api_service_worker_context.h",
|
||||
"shell/browser/api/electron_api_service_worker_main.cc",
|
||||
"shell/browser/api/electron_api_service_worker_main.h",
|
||||
"shell/browser/api/electron_api_session.cc",
|
||||
"shell/browser/api/electron_api_session.h",
|
||||
"shell/browser/api/electron_api_system_preferences.cc",
|
||||
@@ -474,6 +476,7 @@ filenames = {
|
||||
"shell/browser/osr/osr_web_contents_view.h",
|
||||
"shell/browser/plugins/plugin_utils.cc",
|
||||
"shell/browser/plugins/plugin_utils.h",
|
||||
"shell/browser/preload_script.h",
|
||||
"shell/browser/protocol_registry.cc",
|
||||
"shell/browser/protocol_registry.h",
|
||||
"shell/browser/relauncher.cc",
|
||||
@@ -613,6 +616,8 @@ filenames = {
|
||||
"shell/common/gin_converters/osr_converter.cc",
|
||||
"shell/common/gin_converters/osr_converter.h",
|
||||
"shell/common/gin_converters/serial_port_info_converter.h",
|
||||
"shell/common/gin_converters/service_worker_converter.cc",
|
||||
"shell/common/gin_converters/service_worker_converter.h",
|
||||
"shell/common/gin_converters/std_converter.h",
|
||||
"shell/common/gin_converters/time_converter.cc",
|
||||
"shell/common/gin_converters/time_converter.h",
|
||||
|
||||
@@ -29,6 +29,7 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'protocol', loader: () => require('./protocol') },
|
||||
{ name: 'safeStorage', loader: () => require('./safe-storage') },
|
||||
{ name: 'screen', loader: () => require('./screen') },
|
||||
{ name: 'ServiceWorkerMain', loader: () => require('./service-worker-main') },
|
||||
{ name: 'session', loader: () => require('./session') },
|
||||
{ name: 'ShareMenu', loader: () => require('./share-menu') },
|
||||
{ name: 'systemPreferences', loader: () => require('./system-preferences') },
|
||||
|
||||
17
lib/browser/api/service-worker-main.ts
Normal file
17
lib/browser/api/service-worker-main.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
const { ServiceWorkerMain } = process._linkedBinding('electron_browser_service_worker_main');
|
||||
|
||||
ServiceWorkerMain.prototype.startTask = function () {
|
||||
// TODO(samuelmaddock): maybe make timeout configurable in the future
|
||||
const hasTimeout = false;
|
||||
const { id, ok } = this._startExternalRequest(hasTimeout);
|
||||
|
||||
if (!ok) {
|
||||
throw new Error('Unable to start service worker task.');
|
||||
}
|
||||
|
||||
return {
|
||||
end: () => this._finishExternalRequest(id)
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = ServiceWorkerMain;
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fetchWithSession } from '@electron/internal/browser/api/net-fetch';
|
||||
import * as deprecate from '@electron/internal/common/deprecate';
|
||||
|
||||
import { net } from 'electron/main';
|
||||
|
||||
@@ -36,6 +37,31 @@ Session.prototype.setDisplayMediaRequestHandler = function (handler, opts) {
|
||||
}, opts);
|
||||
};
|
||||
|
||||
const getPreloadsDeprecated = deprecate.warnOnce('session.getPreloads', 'session.getPreloadScripts');
|
||||
Session.prototype.getPreloads = function () {
|
||||
getPreloadsDeprecated();
|
||||
return this.getPreloadScripts()
|
||||
.filter((script) => script.type === 'frame')
|
||||
.map((script) => script.filePath);
|
||||
};
|
||||
|
||||
const setPreloadsDeprecated = deprecate.warnOnce('session.setPreloads', 'session.registerPreloadScript');
|
||||
Session.prototype.setPreloads = function (preloads) {
|
||||
setPreloadsDeprecated();
|
||||
this.getPreloadScripts()
|
||||
.filter((script) => script.type === 'frame')
|
||||
.forEach((script) => {
|
||||
this.unregisterPreloadScript(script.id);
|
||||
});
|
||||
preloads.map(filePath => ({
|
||||
type: 'frame',
|
||||
filePath,
|
||||
_deprecated: true
|
||||
}) as Electron.PreloadScriptRegistration).forEach(script => {
|
||||
this.registerPreloadScript(script);
|
||||
});
|
||||
};
|
||||
|
||||
export default {
|
||||
fromPartition,
|
||||
fromPath,
|
||||
|
||||
@@ -146,6 +146,9 @@ require('@electron/internal/browser/devtools');
|
||||
// Load protocol module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/protocol');
|
||||
|
||||
// Load service-worker-main module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/service-worker-main');
|
||||
|
||||
// Load web-contents module to ensure it is populated on app ready
|
||||
require('@electron/internal/browser/api/web-contents');
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import { clipboard } from 'electron/common';
|
||||
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
// Implements window.close()
|
||||
ipcMainInternal.on(IPC_MESSAGES.BROWSER_WINDOW_CLOSE, function (event) {
|
||||
@@ -43,22 +44,40 @@ ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, function (event, me
|
||||
return (clipboard as any)[method](...args);
|
||||
});
|
||||
|
||||
const getPreloadScript = async function (preloadPath: string) {
|
||||
let preloadSrc = null;
|
||||
let preloadError = null;
|
||||
const getPreloadScriptsFromEvent = (event: ElectronInternal.IpcMainInternalEvent) => {
|
||||
const session: Electron.Session = event.sender.session;
|
||||
const preloadScripts = session.getPreloadScripts();
|
||||
const framePreloads = preloadScripts.filter(script => script.type === 'frame');
|
||||
|
||||
const webPrefPreload = event.sender._getPreloadScript();
|
||||
if (webPrefPreload) framePreloads.push(webPrefPreload);
|
||||
|
||||
// TODO(samuelmaddock): Remove filter after Session.setPreloads is fully
|
||||
// deprecated. The new API will prevent relative paths from being registered.
|
||||
return framePreloads.filter(script => path.isAbsolute(script.filePath));
|
||||
};
|
||||
|
||||
const readPreloadScript = async function (script: Electron.PreloadScript): Promise<ElectronInternal.PreloadScript> {
|
||||
let contents;
|
||||
let error;
|
||||
try {
|
||||
preloadSrc = await fs.promises.readFile(preloadPath, 'utf8');
|
||||
} catch (error) {
|
||||
preloadError = error;
|
||||
contents = await fs.promises.readFile(script.filePath, 'utf8');
|
||||
} catch (err) {
|
||||
if (err instanceof Error) {
|
||||
error = err;
|
||||
}
|
||||
}
|
||||
return { preloadPath, preloadSrc, preloadError };
|
||||
return {
|
||||
...script,
|
||||
contents,
|
||||
error
|
||||
};
|
||||
};
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event) {
|
||||
const preloadPaths = event.sender._getPreloadPaths();
|
||||
|
||||
const preloadScripts = getPreloadScriptsFromEvent(event);
|
||||
return {
|
||||
preloadScripts: await Promise.all(preloadPaths.map(path => getPreloadScript(path))),
|
||||
preloadScripts: await Promise.all(preloadScripts.map(readPreloadScript)),
|
||||
process: {
|
||||
arch: process.arch,
|
||||
platform: process.platform,
|
||||
@@ -71,7 +90,8 @@ ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD, async function (event
|
||||
});
|
||||
|
||||
ipcMainUtils.handleSync(IPC_MESSAGES.BROWSER_NONSANDBOX_LOAD, function (event) {
|
||||
return { preloadPaths: event.sender._getPreloadPaths() };
|
||||
const preloadScripts = getPreloadScriptsFromEvent(event);
|
||||
return { preloadPaths: preloadScripts.map(script => script.filePath) };
|
||||
});
|
||||
|
||||
ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadPath: string, error: Error) {
|
||||
|
||||
@@ -871,9 +871,9 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
const binding = internalBinding('fs');
|
||||
|
||||
const { internalModuleStat } = binding;
|
||||
internalBinding('fs').internalModuleStat = (receiver: unknown, pathArgument: string) => {
|
||||
internalBinding('fs').internalModuleStat = (pathArgument: string) => {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return internalModuleStat(receiver, pathArgument);
|
||||
if (!pathInfo.isAsar) return internalModuleStat(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(binding, path.join(originalPath, p));
|
||||
return internalBinding('fs').internalModuleStat(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(binding, path.join(direntPath, p));
|
||||
return internalBinding('fs').internalModuleStat(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(binding, direntPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(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(binding, path.join(pathArg, p));
|
||||
return internalBinding('fs').internalModuleStat(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(binding, resultPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(resultPath);
|
||||
|
||||
readdirResults.push(relativeResultPath);
|
||||
if (stat === 1) pathsQueue.push(resultPath);
|
||||
|
||||
@@ -5,13 +5,17 @@ const checkContextIsolationEnabled = () => {
|
||||
};
|
||||
|
||||
const contextBridge: Electron.ContextBridge = {
|
||||
exposeInMainWorld: (key: string, api: any) => {
|
||||
exposeInMainWorld: (key, api) => {
|
||||
checkContextIsolationEnabled();
|
||||
return binding.exposeAPIInWorld(0, key, api);
|
||||
},
|
||||
exposeInIsolatedWorld: (worldId: number, key: string, api: any) => {
|
||||
exposeInIsolatedWorld: (worldId, key, api) => {
|
||||
checkContextIsolationEnabled();
|
||||
return binding.exposeAPIInWorld(worldId, key, api);
|
||||
},
|
||||
executeInMainWorld: (script) => {
|
||||
checkContextIsolationEnabled();
|
||||
return binding.executeInWorld(0, script);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -27,8 +31,7 @@ export const internalContextBridge = {
|
||||
},
|
||||
overrideGlobalPropertyFromIsolatedWorld: (keys: string[], getter: Function, setter?: Function) => {
|
||||
return binding._overrideGlobalPropertyFromIsolatedWorld(keys, getter, setter || null);
|
||||
},
|
||||
isInMainWorld: () => binding._isCalledFromMainWorld() as boolean
|
||||
}
|
||||
};
|
||||
|
||||
if (binding._isDebug) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import '@electron/internal/sandboxed_renderer/pre-init';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import type * as ipcRendererInternalModule from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { createPreloadProcessObject, executeSandboxedPreloadScripts } from '@electron/internal/sandboxed_renderer/preload';
|
||||
|
||||
import * as events from 'events';
|
||||
import { setImmediate, clearImmediate } from 'timers';
|
||||
@@ -11,35 +12,14 @@ declare const binding: {
|
||||
createPreloadScript: (src: string) => Function
|
||||
};
|
||||
|
||||
const { EventEmitter } = events;
|
||||
|
||||
process._linkedBinding = binding.get;
|
||||
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
// Expose Buffer shim as a hidden value. This is used by C++ code to
|
||||
// deserialize Buffer instances sent from browser process.
|
||||
v8Util.setHiddenValue(global, 'Buffer', Buffer);
|
||||
// The process object created by webpack is not an event emitter, fix it so
|
||||
// the API is more compatible with non-sandboxed renderers.
|
||||
for (const prop of Object.keys(EventEmitter.prototype) as (keyof typeof process)[]) {
|
||||
if (Object.hasOwn(process, prop)) {
|
||||
delete process[prop];
|
||||
}
|
||||
}
|
||||
Object.setPrototypeOf(process, EventEmitter.prototype);
|
||||
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal') as typeof ipcRendererInternalModule;
|
||||
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') as typeof ipcRendererUtilsModule;
|
||||
|
||||
const {
|
||||
preloadScripts,
|
||||
process: processProps
|
||||
} = ipcRendererUtils.invokeSync<{
|
||||
preloadScripts: {
|
||||
preloadPath: string;
|
||||
preloadSrc: string | null;
|
||||
preloadError: null | Error;
|
||||
}[];
|
||||
preloadScripts: ElectronInternal.PreloadScript[];
|
||||
process: NodeJS.Process;
|
||||
}>(IPC_MESSAGES.BROWSER_SANDBOX_LOAD);
|
||||
|
||||
@@ -60,8 +40,7 @@ const loadableModules = new Map<string, Function>([
|
||||
['node:url', () => require('url')]
|
||||
]);
|
||||
|
||||
// Pass different process object to the preload script.
|
||||
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
|
||||
const preloadProcess = createPreloadProcessObject();
|
||||
|
||||
// InvokeEmitProcessEvent in ElectronSandboxedRendererClient will look for this
|
||||
v8Util.setHiddenValue(global, 'emit-process-event', (event: string) => {
|
||||
@@ -72,77 +51,22 @@ v8Util.setHiddenValue(global, 'emit-process-event', (event: string) => {
|
||||
Object.assign(preloadProcess, binding.process);
|
||||
Object.assign(preloadProcess, processProps);
|
||||
|
||||
Object.assign(process, binding.process);
|
||||
Object.assign(process, processProps);
|
||||
|
||||
process.getProcessMemoryInfo = preloadProcess.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||
get () {
|
||||
return process.noDeprecation;
|
||||
},
|
||||
set (value) {
|
||||
process.noDeprecation = value;
|
||||
}
|
||||
});
|
||||
|
||||
// This is the `require` function that will be visible to the preload script
|
||||
function preloadRequire (module: string) {
|
||||
if (loadedModules.has(module)) {
|
||||
return loadedModules.get(module);
|
||||
}
|
||||
if (loadableModules.has(module)) {
|
||||
const loadedModule = loadableModules.get(module)!();
|
||||
loadedModules.set(module, loadedModule);
|
||||
return loadedModule;
|
||||
}
|
||||
throw new Error(`module not found: ${module}`);
|
||||
}
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
||||
// that tests can call it to get access to some test only bindings
|
||||
if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
preloadProcess._linkedBinding = process._linkedBinding;
|
||||
}
|
||||
|
||||
// Common renderer initialization
|
||||
require('@electron/internal/renderer/common-init');
|
||||
|
||||
// Wrap the script into a function executed in global scope. It won't have
|
||||
// access to the current scope, so we'll expose a few objects as arguments:
|
||||
//
|
||||
// - `require`: The `preloadRequire` function
|
||||
// - `process`: The `preloadProcess` object
|
||||
// - `Buffer`: Shim of `Buffer` implementation
|
||||
// - `global`: The window object, which is aliased to `global` by webpack.
|
||||
function runPreloadScript (preloadSrc: string) {
|
||||
const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate, clearImmediate, exports, module) {
|
||||
${preloadSrc}
|
||||
})`;
|
||||
|
||||
// eval in window scope
|
||||
const preloadFn = binding.createPreloadScript(preloadWrapperSrc);
|
||||
const exports = {};
|
||||
|
||||
preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate, clearImmediate, exports, { exports });
|
||||
}
|
||||
|
||||
for (const { preloadPath, preloadSrc, preloadError } of preloadScripts) {
|
||||
try {
|
||||
if (preloadSrc) {
|
||||
runPreloadScript(preloadSrc);
|
||||
} else if (preloadError) {
|
||||
throw preloadError;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Unable to load preload script: ${preloadPath}`);
|
||||
console.error(error);
|
||||
|
||||
ipcRendererInternal.send(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, preloadPath, error);
|
||||
executeSandboxedPreloadScripts({
|
||||
loadedModules,
|
||||
loadableModules,
|
||||
process: preloadProcess,
|
||||
createPreloadScript: binding.createPreloadScript,
|
||||
exposeGlobals: {
|
||||
Buffer,
|
||||
// FIXME(samuelmaddock): workaround webpack bug replacing this with just
|
||||
// `__webpack_require__.g,` which causes script error
|
||||
global: globalThis,
|
||||
setImmediate,
|
||||
clearImmediate
|
||||
}
|
||||
}
|
||||
}, preloadScripts);
|
||||
|
||||
30
lib/sandboxed_renderer/pre-init.ts
Normal file
30
lib/sandboxed_renderer/pre-init.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
// Pre-initialization code for sandboxed renderers.
|
||||
|
||||
import * as events from 'events';
|
||||
|
||||
declare const binding: {
|
||||
get: (name: string) => any;
|
||||
process: NodeJS.Process;
|
||||
};
|
||||
|
||||
// Expose internal binding getter.
|
||||
process._linkedBinding = binding.get;
|
||||
|
||||
const { EventEmitter } = events;
|
||||
const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
|
||||
// Include properties from script 'binding' parameter.
|
||||
Object.assign(process, binding.process);
|
||||
|
||||
// Expose Buffer shim as a hidden value. This is used by C++ code to
|
||||
// deserialize Buffer instances sent from browser process.
|
||||
v8Util.setHiddenValue(global, 'Buffer', Buffer);
|
||||
|
||||
// The process object created by webpack is not an event emitter, fix it so
|
||||
// the API is more compatible with non-sandboxed renderers.
|
||||
for (const prop of Object.keys(EventEmitter.prototype) as (keyof typeof process)[]) {
|
||||
if (Object.hasOwn(process, prop)) {
|
||||
delete process[prop];
|
||||
}
|
||||
}
|
||||
Object.setPrototypeOf(process, EventEmitter.prototype);
|
||||
101
lib/sandboxed_renderer/preload.ts
Normal file
101
lib/sandboxed_renderer/preload.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
interface PreloadContext {
|
||||
loadedModules: Map<string, any>;
|
||||
loadableModules: Map<string, any>;
|
||||
|
||||
/** Process object to pass into preloads. */
|
||||
process: NodeJS.Process;
|
||||
|
||||
createPreloadScript: (src: string) => Function
|
||||
|
||||
/** Globals to be exposed to preload context. */
|
||||
exposeGlobals: any;
|
||||
}
|
||||
|
||||
export function createPreloadProcessObject (): NodeJS.Process {
|
||||
const preloadProcess: NodeJS.Process = new EventEmitter() as any;
|
||||
|
||||
preloadProcess.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||
get () {
|
||||
return process.noDeprecation;
|
||||
},
|
||||
set (value) {
|
||||
process.noDeprecation = value;
|
||||
}
|
||||
});
|
||||
|
||||
const { hasSwitch } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Similar to nodes --expose-internals flag, this exposes _linkedBinding so
|
||||
// that tests can call it to get access to some test only bindings
|
||||
if (hasSwitch('unsafely-expose-electron-internals-for-testing')) {
|
||||
preloadProcess._linkedBinding = process._linkedBinding;
|
||||
}
|
||||
|
||||
return preloadProcess;
|
||||
}
|
||||
|
||||
// This is the `require` function that will be visible to the preload script
|
||||
function preloadRequire (context: PreloadContext, module: string) {
|
||||
if (context.loadedModules.has(module)) {
|
||||
return context.loadedModules.get(module);
|
||||
}
|
||||
if (context.loadableModules.has(module)) {
|
||||
const loadedModule = context.loadableModules.get(module)!();
|
||||
context.loadedModules.set(module, loadedModule);
|
||||
return loadedModule;
|
||||
}
|
||||
throw new Error(`module not found: ${module}`);
|
||||
}
|
||||
|
||||
// Wrap the script into a function executed in global scope. It won't have
|
||||
// access to the current scope, so we'll expose a few objects as arguments:
|
||||
//
|
||||
// - `require`: The `preloadRequire` function
|
||||
// - `process`: The `preloadProcess` object
|
||||
// - `Buffer`: Shim of `Buffer` implementation
|
||||
// - `global`: The window object, which is aliased to `global` by webpack.
|
||||
function runPreloadScript (context: PreloadContext, preloadSrc: string) {
|
||||
const globalVariables = [];
|
||||
const fnParameters = [];
|
||||
for (const [key, value] of Object.entries(context.exposeGlobals)) {
|
||||
globalVariables.push(key);
|
||||
fnParameters.push(value);
|
||||
}
|
||||
const preloadWrapperSrc = `(function(require, process, exports, module, ${globalVariables.join(', ')}) {
|
||||
${preloadSrc}
|
||||
})`;
|
||||
|
||||
// eval in window scope
|
||||
const preloadFn = context.createPreloadScript(preloadWrapperSrc);
|
||||
const exports = {};
|
||||
|
||||
preloadFn(preloadRequire.bind(null, context), context.process, exports, { exports }, ...fnParameters);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute preload scripts within a sandboxed process.
|
||||
*/
|
||||
export function executeSandboxedPreloadScripts (context: PreloadContext, preloadScripts: ElectronInternal.PreloadScript[]) {
|
||||
for (const { filePath, contents, error } of preloadScripts) {
|
||||
try {
|
||||
if (contents) {
|
||||
runPreloadScript(context, contents);
|
||||
} else if (error) {
|
||||
throw error;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Unable to load preload script: ${filePath}`);
|
||||
console.error(error);
|
||||
ipcRendererInternal.send(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, filePath, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,4 +139,4 @@ 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
|
||||
feat_add_signals_when_embedder_cleanup_callbacks_run_for.patch
|
||||
|
||||
@@ -1,497 +0,0 @@
|
||||
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,168 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Wed, 29 Jan 2025 17:01:03 +0900
|
||||
Subject: feat: add signals when embedder cleanup callbacks run for
|
||||
gin::wrappable
|
||||
|
||||
Current setup of finalization callbacks does not work well with
|
||||
gin_helper::CleanedUpAtExit for wrappables specifically on environment
|
||||
shutdown leading to UAF in the second pass.
|
||||
|
||||
Details at https://github.com/microsoft/vscode/issues/192119#issuecomment-2375851531
|
||||
|
||||
The signals exposed in this patch does the following 2 things,
|
||||
|
||||
1) Fix weak state of the wrapped object when the finializer callbacks
|
||||
have not yet been processed
|
||||
2) Avoid calling into the second pass when the embedder has already
|
||||
destroyed the wrapped object via CleanedUpAtExit.
|
||||
|
||||
This patch is more of a bandaid fix to improve the lifetime
|
||||
management with existing finalizer callbacks. We should be able to
|
||||
remove this patch once gin::Wrappable can be managed by V8 Oilpan
|
||||
|
||||
Refs https://issues.chromium.org/issues/40210365 which is blocked
|
||||
on https://issues.chromium.org/issues/42203693
|
||||
|
||||
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc
|
||||
index e5ee2c6b3cb787ff9f8272d4344a1e18c44971e2..22469cf0ab1025eefcf94e2cd351087e52182130 100644
|
||||
--- a/gin/isolate_holder.cc
|
||||
+++ b/gin/isolate_holder.cc
|
||||
@@ -34,6 +34,8 @@ v8::ArrayBuffer::Allocator* g_array_buffer_allocator = nullptr;
|
||||
const intptr_t* g_reference_table = nullptr;
|
||||
v8::FatalErrorCallback g_fatal_error_callback = nullptr;
|
||||
v8::OOMErrorCallback g_oom_error_callback = nullptr;
|
||||
+bool g_initialized_microtasks_runner = false;
|
||||
+bool g_destroyed_microtasks_runner = false;
|
||||
|
||||
std::unique_ptr<v8::Isolate::CreateParams> getModifiedIsolateParams(
|
||||
std::unique_ptr<v8::Isolate::CreateParams> params,
|
||||
@@ -194,10 +196,26 @@ IsolateHolder::getDefaultIsolateParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
+// static
|
||||
+bool IsolateHolder::DestroyedMicrotasksRunner() {
|
||||
+ return g_initialized_microtasks_runner &&
|
||||
+ g_destroyed_microtasks_runner;
|
||||
+}
|
||||
+
|
||||
void IsolateHolder::EnableIdleTasks(
|
||||
std::unique_ptr<V8IdleTaskRunner> idle_task_runner) {
|
||||
DCHECK(isolate_data_.get());
|
||||
isolate_data_->EnableIdleTasks(std::move(idle_task_runner));
|
||||
}
|
||||
|
||||
+void IsolateHolder::WillCreateMicrotasksRunner() {
|
||||
+ DCHECK(!g_initialized_microtasks_runner);
|
||||
+ g_initialized_microtasks_runner = true;
|
||||
+}
|
||||
+
|
||||
+void IsolateHolder::WillDestroyMicrotasksRunner() {
|
||||
+ DCHECK(g_initialized_microtasks_runner);
|
||||
+ g_destroyed_microtasks_runner = true;
|
||||
+}
|
||||
+
|
||||
} // namespace gin
|
||||
diff --git a/gin/public/isolate_holder.h b/gin/public/isolate_holder.h
|
||||
index c22b0a7f9af621573e888a518ccdc22293ce07ef..d3e5ced425df54f42534cec5cc0c5bbfb9d79c6c 100644
|
||||
--- a/gin/public/isolate_holder.h
|
||||
+++ b/gin/public/isolate_holder.h
|
||||
@@ -130,6 +130,8 @@ class GIN_EXPORT IsolateHolder {
|
||||
// Should only be called after v8::IsolateHolder::Initialize() is invoked.
|
||||
static std::unique_ptr<v8::Isolate::CreateParams> getDefaultIsolateParams();
|
||||
|
||||
+ static bool DestroyedMicrotasksRunner();
|
||||
+
|
||||
v8::Isolate* isolate() { return isolate_; }
|
||||
|
||||
// This method returns if v8::Locker is needed to access isolate.
|
||||
@@ -143,6 +145,9 @@ class GIN_EXPORT IsolateHolder {
|
||||
|
||||
void EnableIdleTasks(std::unique_ptr<V8IdleTaskRunner> idle_task_runner);
|
||||
|
||||
+ void WillCreateMicrotasksRunner();
|
||||
+ void WillDestroyMicrotasksRunner();
|
||||
+
|
||||
// This method returns V8IsolateMemoryDumpProvider of this isolate, used for
|
||||
// testing.
|
||||
V8IsolateMemoryDumpProvider* isolate_memory_dump_provider_for_testing()
|
||||
diff --git a/gin/wrappable.cc b/gin/wrappable.cc
|
||||
index 402355cb836cea14e9ee725a142a4bad44fd5bed..7e7f028dcfb87c7b80adebabac19ced8791f642e 100644
|
||||
--- a/gin/wrappable.cc
|
||||
+++ b/gin/wrappable.cc
|
||||
@@ -13,6 +13,9 @@ namespace gin {
|
||||
WrappableBase::WrappableBase() = default;
|
||||
|
||||
WrappableBase::~WrappableBase() {
|
||||
+ if (!wrapper_.IsEmpty()) {
|
||||
+ wrapper_.ClearWeak();
|
||||
+ }
|
||||
wrapper_.Reset();
|
||||
}
|
||||
|
||||
@@ -28,15 +31,24 @@ const char* WrappableBase::GetTypeName() {
|
||||
void WrappableBase::FirstWeakCallback(
|
||||
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
||||
WrappableBase* wrappable = data.GetParameter();
|
||||
- wrappable->dead_ = true;
|
||||
- wrappable->wrapper_.Reset();
|
||||
- data.SetSecondPassCallback(SecondWeakCallback);
|
||||
+ WrappableBase* wrappable_from_field =
|
||||
+ static_cast<WrappableBase*>(data.GetInternalField(1));
|
||||
+ if (wrappable && wrappable == wrappable_from_field) {
|
||||
+ wrappable->dead_ = true;
|
||||
+ wrappable->wrapper_.Reset();
|
||||
+ data.SetSecondPassCallback(SecondWeakCallback);
|
||||
+ }
|
||||
}
|
||||
|
||||
void WrappableBase::SecondWeakCallback(
|
||||
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
||||
+ if (IsolateHolder::DestroyedMicrotasksRunner()) {
|
||||
+ return;
|
||||
+ }
|
||||
WrappableBase* wrappable = data.GetParameter();
|
||||
- delete wrappable;
|
||||
+ if (wrappable) {
|
||||
+ delete wrappable;
|
||||
+ }
|
||||
}
|
||||
|
||||
v8::MaybeLocal<v8::Object> WrappableBase::GetWrapperImpl(v8::Isolate* isolate,
|
||||
@@ -71,10 +83,16 @@ v8::MaybeLocal<v8::Object> WrappableBase::GetWrapperImpl(v8::Isolate* isolate,
|
||||
void* values[] = {info, this};
|
||||
wrapper->SetAlignedPointerInInternalFields(2, indices, values);
|
||||
wrapper_.Reset(isolate, wrapper);
|
||||
- wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kParameter);
|
||||
+ wrapper_.SetWeak(this, FirstWeakCallback, v8::WeakCallbackType::kInternalFields);
|
||||
return v8::MaybeLocal<v8::Object>(wrapper);
|
||||
}
|
||||
|
||||
+void WrappableBase::ClearWeak() {
|
||||
+ if (!wrapper_.IsEmpty()) {
|
||||
+ wrapper_.ClearWeak();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
namespace internal {
|
||||
|
||||
void* FromV8Impl(v8::Isolate* isolate, v8::Local<v8::Value> val,
|
||||
diff --git a/gin/wrappable.h b/gin/wrappable.h
|
||||
index 4e7115685a5bf6997e78edcc1851e28bd00b1aa2..ca51fe33605e855438e88969e3d3cc734ef4523e 100644
|
||||
--- a/gin/wrappable.h
|
||||
+++ b/gin/wrappable.h
|
||||
@@ -80,6 +80,13 @@ class GIN_EXPORT WrappableBase {
|
||||
v8::MaybeLocal<v8::Object> GetWrapperImpl(v8::Isolate* isolate,
|
||||
WrapperInfo* wrapper_info);
|
||||
|
||||
+ // Make this wrappable strong again. This is useful when the wrappable is
|
||||
+ // destroyed outside the finalizer callbacks and we want to avoid scheduling
|
||||
+ // the weak callbacks if they haven't been scheduled yet.
|
||||
+ // NOTE!!! this does not prevent finalization callbacks from running if they
|
||||
+ // have already been processed.
|
||||
+ void ClearWeak();
|
||||
+
|
||||
private:
|
||||
static void FirstWeakCallback(
|
||||
const v8::WeakCallbackInfo<WrappableBase>& data);
|
||||
@@ -14,10 +14,25 @@ It also:
|
||||
This may be partially upstreamed to Chromium in the future.
|
||||
|
||||
diff --git a/ui/gtk/select_file_dialog_linux_gtk.cc b/ui/gtk/select_file_dialog_linux_gtk.cc
|
||||
index b83f0177a2adb0a19be49684f865941e6708f626..f313c766ddc2b79f082e70138dd566a846f0d923 100644
|
||||
index b83f0177a2adb0a19be49684f865941e6708f626..a8c7032cfc122b97665c41da9e1191e747b95a33 100644
|
||||
--- a/ui/gtk/select_file_dialog_linux_gtk.cc
|
||||
+++ b/ui/gtk/select_file_dialog_linux_gtk.cc
|
||||
@@ -407,9 +407,11 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateFileOpenHelper(
|
||||
@@ -259,8 +259,12 @@ void SelectFileDialogLinuxGtk::SelectFileImpl(
|
||||
case SELECT_EXISTING_FOLDER:
|
||||
dialog = CreateSelectFolderDialog(type, title_string, default_path,
|
||||
owning_window);
|
||||
- connect("response",
|
||||
- &SelectFileDialogLinuxGtk::OnSelectSingleFolderDialogResponse);
|
||||
+ if (allow_multiple_selection())
|
||||
+ connect("response",
|
||||
+ &SelectFileDialogLinuxGtk::OnSelectMultiFolderDialogResponse);
|
||||
+ else
|
||||
+ connect("response",
|
||||
+ &SelectFileDialogLinuxGtk::OnSelectSingleFolderDialogResponse);
|
||||
break;
|
||||
case SELECT_OPEN_FILE:
|
||||
dialog = CreateFileOpenDialog(title_string, default_path, owning_window);
|
||||
@@ -407,9 +411,11 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateFileOpenHelper(
|
||||
const std::string& title,
|
||||
const base::FilePath& default_path,
|
||||
gfx::NativeWindow parent) {
|
||||
@@ -30,7 +45,7 @@ index b83f0177a2adb0a19be49684f865941e6708f626..f313c766ddc2b79f082e70138dd566a8
|
||||
SetGtkTransientForAura(dialog, parent);
|
||||
AddFilters(GTK_FILE_CHOOSER(dialog));
|
||||
|
||||
@@ -425,6 +427,7 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateFileOpenHelper(
|
||||
@@ -425,6 +431,7 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateFileOpenHelper(
|
||||
GtkFileChooserSetCurrentFolder(GTK_FILE_CHOOSER(dialog),
|
||||
*last_opened_path());
|
||||
}
|
||||
@@ -38,7 +53,7 @@ index b83f0177a2adb0a19be49684f865941e6708f626..f313c766ddc2b79f082e70138dd566a8
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@@ -440,11 +443,15 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSelectFolderDialog(
|
||||
@@ -440,11 +447,15 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSelectFolderDialog(
|
||||
? l10n_util::GetStringUTF8(IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE)
|
||||
: l10n_util::GetStringUTF8(IDS_SELECT_FOLDER_DIALOG_TITLE);
|
||||
}
|
||||
@@ -59,7 +74,7 @@ index b83f0177a2adb0a19be49684f865941e6708f626..f313c766ddc2b79f082e70138dd566a8
|
||||
|
||||
GtkWidget* dialog = GtkFileChooserDialogNew(
|
||||
title_string.c_str(), nullptr, GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
|
||||
@@ -466,7 +473,8 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSelectFolderDialog(
|
||||
@@ -466,7 +477,8 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSelectFolderDialog(
|
||||
gtk_file_filter_add_mime_type(only_folders, "inode/directory");
|
||||
gtk_file_filter_add_mime_type(only_folders, "text/directory");
|
||||
gtk_file_chooser_add_filter(chooser, only_folders);
|
||||
@@ -69,7 +84,7 @@ index b83f0177a2adb0a19be49684f865941e6708f626..f313c766ddc2b79f082e70138dd566a8
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@@ -503,10 +511,11 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSaveAsDialog(
|
||||
@@ -503,10 +515,11 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSaveAsDialog(
|
||||
std::string title_string =
|
||||
!title.empty() ? title
|
||||
: l10n_util::GetStringUTF8(IDS_SAVE_AS_DIALOG_TITLE);
|
||||
@@ -83,7 +98,7 @@ index b83f0177a2adb0a19be49684f865941e6708f626..f313c766ddc2b79f082e70138dd566a8
|
||||
GTK_RESPONSE_ACCEPT);
|
||||
SetGtkTransientForAura(dialog, parent);
|
||||
|
||||
@@ -532,9 +541,10 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSaveAsDialog(
|
||||
@@ -532,9 +545,10 @@ GtkWidget* SelectFileDialogLinuxGtk::CreateSaveAsDialog(
|
||||
gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), FALSE);
|
||||
// Overwrite confirmation is always enabled in GTK4.
|
||||
if (!GtkCheckVersion(4)) {
|
||||
@@ -96,6 +111,65 @@ index b83f0177a2adb0a19be49684f865941e6708f626..f313c766ddc2b79f082e70138dd566a8
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@@ -589,15 +603,29 @@ void SelectFileDialogLinuxGtk::OnSelectSingleFolderDialogResponse(
|
||||
void SelectFileDialogLinuxGtk::OnSelectMultiFileDialogResponse(
|
||||
GtkWidget* dialog,
|
||||
int response_id) {
|
||||
+ SelectMultiFileHelper(dialog, response_id, false);
|
||||
+}
|
||||
+
|
||||
+void SelectFileDialogLinuxGtk::OnSelectMultiFolderDialogResponse(
|
||||
+ GtkWidget* dialog,
|
||||
+ int response_id) {
|
||||
+ SelectMultiFileHelper(dialog, response_id, true);
|
||||
+}
|
||||
+
|
||||
+void SelectFileDialogLinuxGtk::SelectMultiFileHelper(GtkWidget* dialog,
|
||||
+ int response_id,
|
||||
+ bool allow_folder) {
|
||||
if (IsCancelResponse(response_id)) {
|
||||
FileNotSelected(dialog);
|
||||
return;
|
||||
}
|
||||
|
||||
auto filenames = GtkFileChooserGetFilenames(dialog);
|
||||
- std::erase_if(filenames, [this](const base::FilePath& path) {
|
||||
- return CallDirectoryExistsOnUIThread(path);
|
||||
+ std::erase_if(filenames, [this, &allow_folder](const base::FilePath& path) {
|
||||
+ bool directory_exists = CallDirectoryExistsOnUIThread(path);
|
||||
+ return !allow_folder && directory_exists;
|
||||
});
|
||||
+
|
||||
if (filenames.empty()) {
|
||||
FileNotSelected(dialog);
|
||||
return;
|
||||
diff --git a/ui/gtk/select_file_dialog_linux_gtk.h b/ui/gtk/select_file_dialog_linux_gtk.h
|
||||
index 213eaa5ec6d657a659726cb38103e8bd671fe907..f497447c598198bf690758b1d1c5c6fe4112627f 100644
|
||||
--- a/ui/gtk/select_file_dialog_linux_gtk.h
|
||||
+++ b/ui/gtk/select_file_dialog_linux_gtk.h
|
||||
@@ -108,6 +108,12 @@ class SelectFileDialogLinuxGtk : public ui::SelectFileDialogLinux,
|
||||
gint response_id,
|
||||
bool allow_folder);
|
||||
|
||||
+ // Common function for OnSelectMultiFileDialogResponse and
|
||||
+ // OnSelectMultiFolderDialogResponse.
|
||||
+ void SelectMultiFileHelper(GtkWidget* dialog,
|
||||
+ gint response_id,
|
||||
+ bool allow_folder);
|
||||
+
|
||||
// Common function for CreateFileOpenDialog and CreateMultiFileOpenDialog.
|
||||
GtkWidget* CreateFileOpenHelper(const std::string& title,
|
||||
const base::FilePath& default_path,
|
||||
@@ -122,6 +128,9 @@ class SelectFileDialogLinuxGtk : public ui::SelectFileDialogLinux,
|
||||
// Callback for when the user responds to a Open Multiple Files dialog.
|
||||
void OnSelectMultiFileDialogResponse(GtkWidget* dialog, int response_id);
|
||||
|
||||
+ // Callback for when the user responds to a Select Multiple Folders dialog.
|
||||
+ void OnSelectMultiFolderDialogResponse(GtkWidget* dialog, int response_id);
|
||||
+
|
||||
// Callback for when the file chooser gets destroyed.
|
||||
void OnFileChooserDestroy(GtkWidget* dialog);
|
||||
|
||||
diff --git a/ui/shell_dialogs/select_file_dialog.h b/ui/shell_dialogs/select_file_dialog.h
|
||||
index eb3d997598631b220c3566748f23a5cdac3e4692..b4b2f7294ce6e9349a4a8a05f614e93359eca25a 100644
|
||||
--- a/ui/shell_dialogs/select_file_dialog.h
|
||||
@@ -186,18 +260,90 @@ index 61683d0eddb04c494ca5e650e7d556b44968ec49..5492456a9138b250e97a5479838bb443
|
||||
|
||||
} // namespace ui
|
||||
diff --git a/ui/shell_dialogs/select_file_dialog_linux_kde.cc b/ui/shell_dialogs/select_file_dialog_linux_kde.cc
|
||||
index 64a79ebe2e2d21d5a6b4a98042d1cdb7b6edad52..16f2ae01a8d33e6341ed52638e963c340455ebf8 100644
|
||||
index 64a79ebe2e2d21d5a6b4a98042d1cdb7b6edad52..748c2506781a237641b25b426876be14c8b7ba82 100644
|
||||
--- a/ui/shell_dialogs/select_file_dialog_linux_kde.cc
|
||||
+++ b/ui/shell_dialogs/select_file_dialog_linux_kde.cc
|
||||
@@ -468,7 +468,7 @@ void SelectFileDialogLinuxKde::CreateSelectFolderDialog(
|
||||
@@ -154,9 +154,20 @@ class SelectFileDialogLinuxKde : public SelectFileDialogLinux {
|
||||
void OnSelectMultiFileDialogResponse(
|
||||
gfx::AcceleratedWidget parent,
|
||||
std::unique_ptr<KDialogOutputParams> results);
|
||||
+
|
||||
+ // Common function for OnSelectSingleFolderDialogResponse and
|
||||
+ // OnSelectMultiFileDialogResponse.
|
||||
+ void SelectMultiFileDialogHelper(
|
||||
+ bool allow_folder,
|
||||
+ gfx::AcceleratedWidget parent,
|
||||
+ std::unique_ptr<KDialogOutputParams> results);
|
||||
+
|
||||
void OnSelectSingleFolderDialogResponse(
|
||||
gfx::AcceleratedWidget parent,
|
||||
std::unique_ptr<KDialogOutputParams> results);
|
||||
+ void OnSelectMultiFolderDialogResponse(
|
||||
+ gfx::AcceleratedWidget parent,
|
||||
+ std::unique_ptr<KDialogOutputParams> results);
|
||||
|
||||
// Should be either DESKTOP_ENVIRONMENT_KDE3, KDE4, KDE5, or KDE6.
|
||||
base::nix::DesktopEnvironment desktop_;
|
||||
@@ -461,6 +472,7 @@ void SelectFileDialogLinuxKde::CreateSelectFolderDialog(
|
||||
int title_message_id = (type == SELECT_UPLOAD_FOLDER)
|
||||
? IDS_SELECT_UPLOAD_FOLDER_DIALOG_TITLE
|
||||
: IDS_SELECT_FOLDER_DIALOG_TITLE;
|
||||
+ bool multiple_selection = allow_multiple_selection();
|
||||
pipe_task_runner_->PostTaskAndReplyWithResult(
|
||||
FROM_HERE,
|
||||
base::BindOnce(
|
||||
@@ -468,10 +480,12 @@ void SelectFileDialogLinuxKde::CreateSelectFolderDialog(
|
||||
KDialogParams(
|
||||
"--getexistingdirectory", GetTitle(title, title_message_id),
|
||||
default_path.empty() ? *last_opened_path() : default_path, parent,
|
||||
- false, false)),
|
||||
+ false, allow_multiple_selection())),
|
||||
+ false, multiple_selection)),
|
||||
base::BindOnce(
|
||||
&SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse, this,
|
||||
parent));
|
||||
- &SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse, this,
|
||||
- parent));
|
||||
+ multiple_selection
|
||||
+ ? &SelectFileDialogLinuxKde::OnSelectMultiFolderDialogResponse
|
||||
+ : &SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse,
|
||||
+ this, parent));
|
||||
}
|
||||
|
||||
void SelectFileDialogLinuxKde::CreateFileOpenDialog(
|
||||
@@ -561,7 +575,8 @@ void SelectFileDialogLinuxKde::OnSelectSingleFolderDialogResponse(
|
||||
SelectSingleFileHelper(true, std::move(results));
|
||||
}
|
||||
|
||||
-void SelectFileDialogLinuxKde::OnSelectMultiFileDialogResponse(
|
||||
+void SelectFileDialogLinuxKde::SelectMultiFileDialogHelper(
|
||||
+ bool allow_folder,
|
||||
gfx::AcceleratedWidget parent,
|
||||
std::unique_ptr<KDialogOutputParams> results) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
@@ -579,7 +594,7 @@ void SelectFileDialogLinuxKde::OnSelectMultiFileDialogResponse(
|
||||
base::SplitStringPiece(results->output, "\n", base::KEEP_WHITESPACE,
|
||||
base::SPLIT_WANT_NONEMPTY)) {
|
||||
base::FilePath path(line);
|
||||
- if (CallDirectoryExistsOnUIThread(path))
|
||||
+ if (!allow_folder && CallDirectoryExistsOnUIThread(path))
|
||||
continue;
|
||||
filenames_fp.push_back(path);
|
||||
}
|
||||
@@ -591,4 +606,16 @@ void SelectFileDialogLinuxKde::OnSelectMultiFileDialogResponse(
|
||||
MultiFilesSelected(filenames_fp);
|
||||
}
|
||||
|
||||
+void SelectFileDialogLinuxKde::OnSelectMultiFolderDialogResponse(
|
||||
+ gfx::AcceleratedWidget parent,
|
||||
+ std::unique_ptr<KDialogOutputParams> results) {
|
||||
+ SelectMultiFileDialogHelper(true, parent, std::move(results));
|
||||
+}
|
||||
+
|
||||
+void SelectFileDialogLinuxKde::OnSelectMultiFileDialogResponse(
|
||||
+ gfx::AcceleratedWidget parent,
|
||||
+ std::unique_ptr<KDialogOutputParams> results) {
|
||||
+ SelectMultiFileDialogHelper(false, parent, std::move(results));
|
||||
+}
|
||||
+
|
||||
} // namespace ui
|
||||
diff --git a/ui/shell_dialogs/select_file_dialog_linux_portal.cc b/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||
index 9780c80ffff7bdb715a9adcb656e5d33be974db6..cf6edf5c68a8e2f8ffda119b58c6283bc43199c0 100644
|
||||
--- a/ui/shell_dialogs/select_file_dialog_linux_portal.cc
|
||||
|
||||
@@ -10,17 +10,6 @@ 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
|
||||
@@ -42,7 +31,7 @@ index ebb3ffcd6d42b4c16b6865a91ccf4428cffe864b..00225afa1fb4205f1e02d9f185aeb97d
|
||||
"-Wno-unused-but-set-variable",
|
||||
"-Wno-unused-function",
|
||||
diff --git a/node.gni b/node.gni
|
||||
index 9dca810decebd75aab427e306b3cc37c80fb55c9..852f64fa9cfb50fe6e9ce7aa46be336d3196d5b8 100644
|
||||
index 9dca810decebd75aab427e306b3cc37c80fb55c9..32709b860ccb12d8d1e75342a65dda0b86129b21 100644
|
||||
--- a/node.gni
|
||||
+++ b/node.gni
|
||||
@@ -5,10 +5,10 @@
|
||||
@@ -67,29 +56,20 @@ index 9dca810decebd75aab427e306b3cc37c80fb55c9..852f64fa9cfb50fe6e9ce7aa46be336d
|
||||
|
||||
# Custom build tag.
|
||||
node_tag = ""
|
||||
@@ -58,7 +58,16 @@ declare_args() {
|
||||
@@ -58,7 +58,7 @@ 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 1bec44f6f29b0b652e92d2bb336fdb74b85eee30..599b59873dbb17ae5e7463403859e088ffb86cda 100644
|
||||
index 2bc7155f7c075e5a22ece7159a64a1c9ba3d8ac9..48d29a0d05538cd1d992f3f086d826e78d0d8882 100644
|
||||
--- a/src/node_builtins.cc
|
||||
+++ b/src/node_builtins.cc
|
||||
@@ -778,6 +778,7 @@ void BuiltinLoader::RegisterExternalReferences(
|
||||
@@ -775,6 +775,7 @@ void BuiltinLoader::RegisterExternalReferences(
|
||||
registry->Register(GetNatives);
|
||||
|
||||
RegisterExternalReferencesForInternalizedBuiltinCode(registry);
|
||||
@@ -111,7 +91,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..35cce2ea8fd85f21582962115ac455918d4c4553 100755
|
||||
index 45b3ac5006140fb55aad0e6b78084b753a947a76..8667857107e4f2481fd98032d4333b086fb7b479 100755
|
||||
--- a/tools/generate_config_gypi.py
|
||||
+++ b/tools/generate_config_gypi.py
|
||||
@@ -21,7 +21,7 @@ import getnapibuildversion
|
||||
@@ -123,14 +103,6 @@ index 45b3ac5006140fb55aad0e6b78084b753a947a76..35cce2ea8fd85f21582962115ac45591
|
||||
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
|
||||
@@ -146,10 +118,10 @@ index bf54249b66c0d4e179deaae5a9fd55568e694fe0..31b94d2e4b532d3b8202b512e2d2f41d
|
||||
diff --git a/tools/js2c.cc b/tools/js2c.cc
|
||||
old mode 100644
|
||||
new mode 100755
|
||||
index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2e9dfb0f0
|
||||
index a536b5dcd857275d3b02e361bd7d37a939f6b573..b2d5678d58a79774d5aeedc15ac5d5fd786f64bb
|
||||
--- a/tools/js2c.cc
|
||||
+++ b/tools/js2c.cc
|
||||
@@ -28,6 +28,7 @@ namespace js2c {
|
||||
@@ -30,6 +30,7 @@ namespace js2c {
|
||||
int Main(int argc, char* argv[]);
|
||||
|
||||
static bool is_verbose = false;
|
||||
@@ -157,7 +129,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
|
||||
void Debug(const char* format, ...) {
|
||||
va_list arguments;
|
||||
@@ -175,6 +176,7 @@ const char* kTemplate = R"(
|
||||
@@ -196,6 +197,7 @@ const char* kTemplate = R"(
|
||||
#include "node_builtins.h"
|
||||
#include "node_external_reference.h"
|
||||
#include "node_internals.h"
|
||||
@@ -165,7 +137,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
|
||||
namespace node {
|
||||
|
||||
@@ -190,7 +192,11 @@ const ThreadsafeCopyOnWrite<BuiltinSourceMap> global_source_map {
|
||||
@@ -211,7 +213,11 @@ const ThreadsafeCopyOnWrite<BuiltinSourceMap> global_source_map {
|
||||
} // anonymous namespace
|
||||
|
||||
void BuiltinLoader::LoadJavaScriptSource() {
|
||||
@@ -178,7 +150,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
}
|
||||
|
||||
void RegisterExternalReferencesForInternalizedBuiltinCode(
|
||||
@@ -207,6 +213,45 @@ UnionBytes BuiltinLoader::GetConfig() {
|
||||
@@ -228,6 +234,45 @@ UnionBytes BuiltinLoader::GetConfig() {
|
||||
} // namespace node
|
||||
)";
|
||||
|
||||
@@ -224,7 +196,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
Fragment Format(const Fragments& definitions,
|
||||
const Fragments& initializers,
|
||||
const Fragments& registrations) {
|
||||
@@ -216,13 +261,12 @@ Fragment Format(const Fragments& definitions,
|
||||
@@ -237,13 +282,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();
|
||||
@@ -241,7 +213,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
static_cast<int>(def_buf.size()),
|
||||
def_buf.data(),
|
||||
static_cast<int>(init_buf.size()),
|
||||
@@ -846,12 +890,15 @@ int JS2C(const FileList& js_files,
|
||||
@@ -834,12 +878,15 @@ int JS2C(const FileList& js_files,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,7 +229,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
Fragment out = Format(definitions, initializers, registrations);
|
||||
return WriteIfChanged(out, dest);
|
||||
}
|
||||
@@ -877,6 +924,8 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -865,6 +912,8 @@ int Main(int argc, char* argv[]) {
|
||||
std::string arg(argv[i]);
|
||||
if (arg == "--verbose") {
|
||||
is_verbose = true;
|
||||
@@ -266,7 +238,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
} else if (arg == "--root") {
|
||||
if (i == argc - 1) {
|
||||
fprintf(stderr, "--root must be followed by a path\n");
|
||||
@@ -925,6 +974,14 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -913,6 +962,14 @@ int Main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +253,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
// Should have exactly 3 types: `.js`, `.mjs` and `.gypi`.
|
||||
assert(file_map.size() == 3);
|
||||
auto gypi_it = file_map.find(".gypi");
|
||||
@@ -951,6 +1008,7 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -939,6 +996,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);
|
||||
@@ -302,22 +274,10 @@ index 65d0e1be42f0a85418491ebb548278cf431aa6a0..d4a31342f1c6107b029394c6e1d00a1d
|
||||
except Exception as e:
|
||||
print(str(e))
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6dbbe7ac7 100644
|
||||
index c3b311e4a7f5444b07d4d7028d4621806959804e..de6ff5548ca5282199b7d85c11941c1fa351a9d9 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -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") {
|
||||
@@ -139,6 +139,7 @@ template("node_gn_build") {
|
||||
public_deps = [
|
||||
"deps/ada",
|
||||
"deps/uv",
|
||||
@@ -325,7 +285,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6
|
||||
"deps/simdjson",
|
||||
"$node_v8_path",
|
||||
]
|
||||
@@ -150,7 +156,6 @@ template("node_gn_build") {
|
||||
@@ -150,7 +151,6 @@ template("node_gn_build") {
|
||||
"deps/llhttp",
|
||||
"deps/nbytes",
|
||||
"deps/nghttp2",
|
||||
@@ -333,7 +293,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6
|
||||
"deps/postject",
|
||||
"deps/simdutf",
|
||||
"deps/sqlite",
|
||||
@@ -159,7 +164,11 @@ template("node_gn_build") {
|
||||
@@ -159,7 +159,11 @@ template("node_gn_build") {
|
||||
"$node_v8_path:v8_libplatform",
|
||||
]
|
||||
|
||||
@@ -345,7 +305,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6
|
||||
"$target_gen_dir/node_javascript.cc",
|
||||
] + gypi_values.node_sources
|
||||
|
||||
@@ -178,8 +187,10 @@ template("node_gn_build") {
|
||||
@@ -178,8 +182,10 @@ template("node_gn_build") {
|
||||
deps += [ "//third_party/icu" ]
|
||||
}
|
||||
if (node_use_openssl) {
|
||||
@@ -358,7 +318,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6
|
||||
sources += gypi_values.node_crypto_sources
|
||||
}
|
||||
if (node_enable_inspector) {
|
||||
@@ -276,6 +287,7 @@ template("node_gn_build") {
|
||||
@@ -276,6 +282,7 @@ template("node_gn_build") {
|
||||
}
|
||||
|
||||
executable("node_js2c") {
|
||||
@@ -366,7 +326,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6
|
||||
deps = [
|
||||
"deps/simdutf",
|
||||
"deps/uv",
|
||||
@@ -286,26 +298,75 @@ template("node_gn_build") {
|
||||
@@ -286,26 +293,75 @@ template("node_gn_build") {
|
||||
"src/embedded_data.cc",
|
||||
"src/embedded_data.h",
|
||||
]
|
||||
@@ -452,7 +412,7 @@ index c3b311e4a7f5444b07d4d7028d4621806959804e..f6793b8bf22d6ac911a1977edaa881b6
|
||||
outputs = [ "$target_gen_dir/node_javascript.cc" ]
|
||||
|
||||
# Get the path to node_js2c executable of the host toolchain.
|
||||
@@ -319,11 +380,11 @@ template("node_gn_build") {
|
||||
@@ -319,11 +375,11 @@ template("node_gn_build") {
|
||||
get_label_info(":node_js2c($host_toolchain)", "name") +
|
||||
host_executable_suffix
|
||||
|
||||
|
||||
@@ -13,11 +13,28 @@ 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 ddfbb97276b29df114ab455a2eed3b186b3af5d2..87bfc313dd1408e597e929ba93c8c0f52ae39ced 100644
|
||||
index 3d8b7957e791ce2fa2a8d0937a87b6010087803d..c23922a301a721662ff34bf6e54fd26b41f25ccc 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -152,7 +152,6 @@ template("node_gn_build") {
|
||||
@@ -147,7 +147,6 @@ template("node_gn_build") {
|
||||
":run_node_js2c",
|
||||
"deps/cares",
|
||||
"deps/histogram",
|
||||
@@ -25,7 +42,7 @@ index ddfbb97276b29df114ab455a2eed3b186b3af5d2..87bfc313dd1408e597e929ba93c8c0f5
|
||||
"deps/nbytes",
|
||||
"deps/nghttp2",
|
||||
"deps/postject",
|
||||
@@ -183,7 +182,17 @@ template("node_gn_build") {
|
||||
@@ -178,7 +177,17 @@ template("node_gn_build") {
|
||||
configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
|
||||
configs += [ "//build/config/gcc:symbol_visibility_default" ]
|
||||
}
|
||||
@@ -44,7 +61,7 @@ index ddfbb97276b29df114ab455a2eed3b186b3af5d2..87bfc313dd1408e597e929ba93c8c0f5
|
||||
if (v8_enable_i18n_support) {
|
||||
deps += [ "//third_party/icu" ]
|
||||
}
|
||||
@@ -210,6 +219,19 @@ template("node_gn_build") {
|
||||
@@ -205,6 +214,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 34aaf439936c874bd4c8b7d4ffd69477abb40193..69d10c17ef3c5b0ce6173d1754a975df589d9b61 100644
|
||||
index 74616453e2e047acbb9e25f2f93ebeab06011669..bce15fc4a8b3f2fa0b5a588e6a2b28d2b8b6ac45 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -518,7 +518,7 @@
|
||||
|
||||
@@ -264,25 +264,27 @@ 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..1801594e727ec7a2ef3b89603975f507078b88a1 100644
|
||||
index 8f053efe93324b9acbb4e85f7b974b4f7712e200..e331ed5567caa39ade90ce28cea69f1d10533812 100644
|
||||
--- a/src/tracing/node_trace_writer.cc
|
||||
+++ b/src/tracing/node_trace_writer.cc
|
||||
@@ -96,6 +96,7 @@ void NodeTraceWriter::OpenNewFileForStreaming() {
|
||||
@@ -95,7 +95,7 @@ void NodeTraceWriter::OpenNewFileForStreaming() {
|
||||
fd_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
-
|
||||
+#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,6 +113,7 @@ void NodeTraceWriter::AppendTraceEvent(TraceObject* trace_event) {
|
||||
@@ -112,7 +112,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
|
||||
@@ -298,7 +300,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 a662a081dc3bf356bf93e4063fcb043e4d8df07b..c89cdfe2b2681fbf9946200a03d7d1f7bad21226 100644
|
||||
index be0f55a409a71bf9c1763c36fdc252857228742e..827b5330b2f8c545338a46c548f8abf4aab7f50c 100644
|
||||
--- a/src/tracing/trace_event.h
|
||||
+++ b/src/tracing/trace_event.h
|
||||
@@ -69,8 +69,16 @@ enum CategoryGroupEnabledFlags {
|
||||
@@ -334,23 +336,21 @@ index a662a081dc3bf356bf93e4063fcb043e4d8df07b..c89cdfe2b2681fbf9946200a03d7d1f7
|
||||
|
||||
// Adds a metadata event to the trace log. The |AppendValueAsTraceFormat| method
|
||||
// on the convertable value will be called at flush time.
|
||||
@@ -319,12 +332,15 @@ class TraceEventHelper {
|
||||
@@ -319,10 +332,13 @@ 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 (controller == nullptr) [[unlikely]] {
|
||||
return &disabled;
|
||||
}
|
||||
if (UNLIKELY(controller == nullptr)) return &disabled;
|
||||
return controller->GetCategoryGroupEnabled(group);
|
||||
+#endif
|
||||
+ return 0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -462,6 +478,7 @@ static inline uint64_t AddTraceEventImpl(
|
||||
@@ -460,6 +476,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,7 +358,14 @@ index a662a081dc3bf356bf93e4063fcb043e4d8df07b..c89cdfe2b2681fbf9946200a03d7d1f7
|
||||
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*>(
|
||||
@@ -478,6 +495,8 @@ static inline uint64_t AddTraceEventImpl(
|
||||
@@ -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;
|
||||
return controller->AddTraceEvent(phase, category_group_enabled, name, scope, id,
|
||||
bind_id, num_args, arg_names, arg_types,
|
||||
arg_values, arg_convertibles, flags);
|
||||
@@ -367,18 +374,25 @@ index a662a081dc3bf356bf93e4063fcb043e4d8df07b..c89cdfe2b2681fbf9946200a03d7d1f7
|
||||
}
|
||||
|
||||
static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
@@ -485,6 +504,7 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
@@ -483,6 +501,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_convertibles[2];
|
||||
std::unique_ptr<v8::ConvertableToTraceFormat> arg_convertables[2];
|
||||
if (num_args > 0 && arg_types[0] == TRACE_VALUE_TYPE_CONVERTABLE) {
|
||||
arg_convertibles[0].reset(reinterpret_cast<v8::ConvertableToTraceFormat*>(
|
||||
@@ -501,12 +521,15 @@ static V8_INLINE uint64_t AddTraceEventWithTimestampImpl(
|
||||
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;
|
||||
return controller->AddTraceEventWithTimestamp(
|
||||
phase, category_group_enabled, name, scope, id, bind_id, num_args,
|
||||
arg_names, arg_types, arg_values, arg_convertibles, flags, timestamp);
|
||||
arg_names, arg_types, arg_values, arg_convertables, flags, timestamp);
|
||||
+#endif
|
||||
+ return 0;
|
||||
}
|
||||
@@ -391,7 +405,7 @@ index a662a081dc3bf356bf93e4063fcb043e4d8df07b..c89cdfe2b2681fbf9946200a03d7d1f7
|
||||
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*>(
|
||||
@@ -522,6 +545,7 @@ static V8_INLINE void AddMetadataEventImpl(
|
||||
@@ -520,6 +541,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 cfb1fd6b53715dd2a39ab58b6a3bee0d8aef12bc..34aaf439936c874bd4c8b7d4ffd69477abb40193 100644
|
||||
index 229cb96c1385c597138719f2b01f78bd54ad44ab..74616453e2e047acbb9e25f2f93ebeab06011669 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -86,6 +86,8 @@
|
||||
@@ -40,7 +40,7 @@ index cfb1fd6b53715dd2a39ab58b6a3bee0d8aef12bc..34aaf439936c874bd4c8b7d4ffd69477
|
||||
# list in v8/BUILD.gn.
|
||||
['v8_enable_v8_checks == 1', {
|
||||
diff --git a/configure.py b/configure.py
|
||||
index c4653f37f5a69b7cdbd6e4c32e0717ab40a00994..88db584318a4b0f95539baf1d0895d6039fb25ca 100755
|
||||
index d03db1970fd7a1629a7a7719a5ff267402ab4a66..ce055fb5dfc84c75c486b99f01fea6b9531ff54b 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 599b59873dbb17ae5e7463403859e088ffb86cda..d23cb087de5cb3cd02ef0542fd2f34207f967ad2 100644
|
||||
index 48d29a0d05538cd1d992f3f086d826e78d0d8882..8987234c2d08449242b5fd037ed314b725bc42a5 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 69d10c17ef3c5b0ce6173d1754a975df589d9b61..2e3a04e90a6bb32b3437780502cf45a7acad75c0 100644
|
||||
index bce15fc4a8b3f2fa0b5a588e6a2b28d2b8b6ac45..289ab5d282e93c795eafb5fb992c3bbc4790a687 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 461bff93e151c454cd0a9575daa01d3f7c0ec9c3..a1eab549b8686c24399f5206f9b611bcbce3d470 100644
|
||||
index 99ec540ec41ddf5682eed7618ba87d6935b3b982..274e627fe27b318218f10e982ca5a0773a9075a5 100644
|
||||
--- a/node.gni
|
||||
+++ b/node.gni
|
||||
@@ -12,6 +12,8 @@ declare_args() {
|
||||
@@ -19,10 +19,10 @@ index 461bff93e151c454cd0a9575daa01d3f7c0ec9c3..a1eab549b8686c24399f5206f9b611bc
|
||||
node_module_version = exec_script("$node_path/tools/getmoduleversion.py", [], "value")
|
||||
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index 87bfc313dd1408e597e929ba93c8c0f52ae39ced..4ef97ab65bdfacca4d6dbbc603da0218214b039d 100644
|
||||
index c23922a301a721662ff34bf6e54fd26b41f25ccc..988dd1d73e72ccd3a6eb10b326b8dc7fcd8e257b 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -155,7 +155,7 @@ template("node_gn_build") {
|
||||
@@ -150,7 +150,7 @@ template("node_gn_build") {
|
||||
"deps/nbytes",
|
||||
"deps/nghttp2",
|
||||
"deps/postject",
|
||||
@@ -31,7 +31,7 @@ index 87bfc313dd1408e597e929ba93c8c0f52ae39ced..4ef97ab65bdfacca4d6dbbc603da0218
|
||||
"deps/sqlite",
|
||||
"deps/uvwasi",
|
||||
"//third_party/zlib",
|
||||
@@ -310,7 +310,7 @@ template("node_gn_build") {
|
||||
@@ -305,7 +305,7 @@ template("node_gn_build") {
|
||||
executable("node_js2c") {
|
||||
defines = []
|
||||
deps = [
|
||||
@@ -40,7 +40,7 @@ index 87bfc313dd1408e597e929ba93c8c0f52ae39ced..4ef97ab65bdfacca4d6dbbc603da0218
|
||||
"deps/uv",
|
||||
]
|
||||
sources = [
|
||||
@@ -417,7 +417,7 @@ template("node_gn_build") {
|
||||
@@ -412,7 +412,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 ad8d41a06bde1ca22d0245fa49143e080365b5e1..69d7743767d025453e43d99b32235700d8122c9a 100644
|
||||
index d49941881e6cfd8647a6d44a57e0daaf1c874702..f696fb263b356a76b87cd4b6c4b1a0fd60a84afd 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 ad8d41a06bde1ca22d0245fa49143e080365b5e1..69d7743767d025453e43d99b32235700
|
||||
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 848ff7f142fc700dd3b4b7a6b14d3c537e0fd280..be3018296dd3c63a930328fa9cb1d902cc779b89 100644
|
||||
index cb96fd1bc4fcdce750ce241ee5f47f2ae39cfdc6..c46b270109697f7cc1683f8f9f463575e5040216 100644
|
||||
--- a/lib/internal/process/pre_execution.js
|
||||
+++ b/lib/internal/process/pre_execution.js
|
||||
@@ -245,12 +245,14 @@ function patchProcessObject(expandArgv1) {
|
||||
@@ -243,12 +243,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 2799af0f8dd4923ef5ccd372922ea39a66f93470..3012ea1da2db6b22dc6c6a1cac12ec4c5b44487a 100644
|
||||
index d393d4336a0c1e681e4f6b4e5c7cf2bcc5fc287e..807cb5172e0c2178b6c20e81f8175141d3a0284f 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 2799af0f8dd4923ef5ccd372922ea39a66f93470..3012ea1da2db6b22dc6c6a1cac12ec4c
|
||||
const {
|
||||
loadPreloadModules,
|
||||
initializeFrozenIntrinsics,
|
||||
@@ -276,12 +276,13 @@ let _forceDefaultLoader = false;
|
||||
@@ -273,12 +273,13 @@ let _forceDefaultLoader = false;
|
||||
* @param {boolean} [forceDefaultLoader=false] - A boolean indicating disabling custom loaders.
|
||||
*/
|
||||
function initializeESM(forceDefaultLoader = false) {
|
||||
@@ -40,7 +40,7 @@ index 2799af0f8dd4923ef5ccd372922ea39a66f93470..3012ea1da2db6b22dc6c6a1cac12ec4c
|
||||
|
||||
/**
|
||||
diff --git a/src/module_wrap.cc b/src/module_wrap.cc
|
||||
index e2252639cf45184b72ebe669f7603bd5e6d92b9a..05353281c0a773d5cf5585cb1698126e17f677a0 100644
|
||||
index 48b61e8b7600701c4992a98ff802614ce915faee..4e9835e502a8d078a448aa4253f37de0f49f4854 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 62d3d37a061f787babe44649143d45010ce90011..1f614cabf0f31d7adff9dd7a039ca591d805d3bd 100644
|
||||
index 0cfed4a4a91a3d3fb5aee6c9a4db3405ba836565..61d980a12fcf7c799e726e1462c65ce478a8ed0c 100644
|
||||
--- a/doc/api/cli.md
|
||||
+++ b/doc/api/cli.md
|
||||
@@ -3177,7 +3177,6 @@ V8 options that are allowed are:
|
||||
@@ -3151,7 +3151,6 @@ V8 options that are allowed are:
|
||||
* `--disallow-code-generation-from-strings`
|
||||
* `--enable-etw-stack-walking`
|
||||
* `--expose-gc`
|
||||
@@ -30,10 +30,10 @@ index 62d3d37a061f787babe44649143d45010ce90011..1f614cabf0f31d7adff9dd7a039ca591
|
||||
* `--jitless`
|
||||
* `--max-old-space-size`
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 6f9a8d3e0884bc6e356413f2f39522a7109c86b5..ccf740bfd631aca608244b6b3998177ca5f47f75 100644
|
||||
index 4b3f7751db2871c8ce76b197a84a2417097030ea..21e53e1053fe2e4194d91b27a726d3a1306b1683 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -929,11 +929,6 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
|
||||
@@ -922,11 +922,6 @@ PerIsolateOptionsParser::PerIsolateOptionsParser(
|
||||
"disallow eval and friends",
|
||||
V8Option{},
|
||||
kAllowedInEnvvar);
|
||||
@@ -46,10 +46,10 @@ index 6f9a8d3e0884bc6e356413f2f39522a7109c86b5..ccf740bfd631aca608244b6b3998177c
|
||||
"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 03ffe7aa03f48156f04bb527316221ec10e7e0df..69bf136559c1a8a18a7bfc444a439d161f622635 100644
|
||||
index e898a81af09ca6852ddc866310e5b8e0dc82971b..22d5a342df5d55f065383a6ebe1aebe59dc0f8d2 100644
|
||||
--- a/test/parallel/test-cli-node-options.js
|
||||
+++ b/test/parallel/test-cli-node-options.js
|
||||
@@ -72,7 +72,6 @@ if (common.hasCrypto) {
|
||||
@@ -70,7 +70,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 51fc6fe995d3cf8c70ad7bc3cecf1cc00f190b08..012ad108f44b73346d19d927afc78b57c18b7718 100644
|
||||
index 580a441a803bdd0b57871c0cdd8af576f11609b1..755712d24219de7ffe491957d941df7c8cf7baad 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 51fc6fe995d3cf8c70ad7bc3cecf1cc00f190b08..012ad108f44b73346d19d927afc78b57
|
||||
args = [...execArgv, modulePath, ...args];
|
||||
|
||||
if (typeof options.stdio === 'string') {
|
||||
@@ -615,6 +615,22 @@ function normalizeSpawnArguments(file, args, options) {
|
||||
@@ -617,6 +617,22 @@ function normalizeSpawnArguments(file, args, options) {
|
||||
'options.windowsVerbatimArguments');
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ index 51fc6fe995d3cf8c70ad7bc3cecf1cc00f190b08..012ad108f44b73346d19d927afc78b57
|
||||
if (options.shell) {
|
||||
validateArgumentNullCheck(options.shell, 'options.shell');
|
||||
const command = ArrayPrototypeJoin([file, ...args], ' ');
|
||||
@@ -648,7 +664,6 @@ function normalizeSpawnArguments(file, args, options) {
|
||||
@@ -650,7 +666,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 de83a566724a36fff8b0c4ca9ba7e151a8c39f54..cfb1fd6b53715dd2a39ab58b6a3bee0d8aef12bc 100644
|
||||
index a97e77860e151f5126515d65ef99b34aa7301f76..229cb96c1385c597138719f2b01f78bd54ad44ab 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 89ce587cac4506c4218a9316fe0b68070a7a8504..b74fb837fc1cfee839c8b5b8c0b9a6f805881206 100644
|
||||
index f59abcb21d64b910d8d42eb23c03109f62558813..1b6613d1de8c89c8271066a652afd1024988362d 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -247,6 +247,9 @@ void SetIsolateErrorHandlers(v8::Isolate* isolate, const IsolateSettings& s) {
|
||||
@@ -244,6 +244,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 89ce587cac4506c4218a9316fe0b68070a7a8504..b74fb837fc1cfee839c8b5b8c0b9a6f8
|
||||
}
|
||||
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 3c42f9b87c11a0f88800d6709515c1c9e2972fc0..6f9a8d3e0884bc6e356413f2f39522a7109c86b5 100644
|
||||
index 29630fcccc3bd9d24ad6aec64bef2fedfc3c4031..4b3f7751db2871c8ce76b197a84a2417097030ea 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -1476,14 +1476,16 @@ void GetEmbedderOptions(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1464,14 +1464,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 b95e812c5a9fab59f742e1557e9f218155638af4..6d2566c43f16493cbb2a0f9469ed386c41686782 100644
|
||||
index 172cdb6b049824539a9850789e0e7c5baf613367..c29abc18191aec78ad8eb810093a9a4ef9e854e4 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 b95e812c5a9fab59f742e1557e9f218155638af4..6d2566c43f16493cbb2a0f9469ed386c
|
||||
let OPENSSL_VERSION_NUMBER;
|
||||
const hasOpenSSL = (major = 0, minor = 0, patch = 0) => {
|
||||
if (!hasCrypto) return false;
|
||||
@@ -1008,6 +1010,7 @@ const common = {
|
||||
@@ -996,6 +998,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 8a263ec3350f5540591ac02e70fa2f552b9ac477..dcc4c2ec816d28f1b27df1c358cfce66f1a3a03b 100644
|
||||
index 9dd586a1a1f9a00d9bb0af5b0532e81e7b96a5ce..a37e6d50914345829c8260a97949cee7d17ab676 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,21 +471,10 @@ 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 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9900fb816 100644
|
||||
index 89a7521544f7051edc1779138551bbad1972b3fb..91df6acc65d4003999f29f0fa5f639056b21ee3b 100644
|
||||
--- a/test/parallel/test-crypto-x509.js
|
||||
+++ b/test/parallel/test-crypto-x509.js
|
||||
@@ -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(
|
||||
@@ -111,7 +111,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);
|
||||
@@ -494,7 +483,7 @@ index 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9
|
||||
|
||||
assert.deepStrictEqual(x509.raw, der);
|
||||
|
||||
@@ -255,6 +257,16 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -253,6 +253,16 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
});
|
||||
mc.port2.postMessage(x509);
|
||||
|
||||
@@ -511,7 +500,7 @@ index 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9
|
||||
// Verify that legacy encoding works
|
||||
const legacyObjectCheck = {
|
||||
subject: Object.assign({ __proto__: null }, {
|
||||
@@ -279,15 +291,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -277,15 +287,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
'OCSP - URI': ['http://ocsp.nodejs.org/'],
|
||||
'CA Issuers - URI': ['http://ca.nodejs.org/ca.cert']
|
||||
}),
|
||||
@@ -528,7 +517,7 @@ index 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9
|
||||
bits: 2048,
|
||||
exponent: '0x10001',
|
||||
valid_from: 'Sep 3 21:40:37 2022 GMT',
|
||||
@@ -300,7 +304,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -298,7 +300,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',
|
||||
@@ -537,7 +526,7 @@ index 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9
|
||||
};
|
||||
|
||||
const legacyObject = x509.toLegacyObject();
|
||||
@@ -309,7 +313,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -307,7 +309,7 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
assert.deepStrictEqual(legacyObject.subject, legacyObjectCheck.subject);
|
||||
assert.deepStrictEqual(legacyObject.issuer, legacyObjectCheck.issuer);
|
||||
assert.deepStrictEqual(legacyObject.infoAccess, legacyObjectCheck.infoAccess);
|
||||
@@ -546,7 +535,7 @@ index 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9
|
||||
assert.strictEqual(legacyObject.bits, legacyObjectCheck.bits);
|
||||
assert.strictEqual(legacyObject.exponent, legacyObjectCheck.exponent);
|
||||
assert.strictEqual(legacyObject.valid_from, legacyObjectCheck.valid_from);
|
||||
@@ -318,11 +322,12 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
@@ -316,11 +318,12 @@ oans248kpal88CGqsN2so/wZKxVnpiXlPHMdiNL7hRSUqlHkUi07FrP2Htg8kjI=
|
||||
assert.strictEqual(
|
||||
legacyObject.fingerprint256,
|
||||
legacyObjectCheck.fingerprint256);
|
||||
@@ -557,40 +546,17 @@ index 15e1f53bb05faf60fa808eb5901591d1512edf3c..329f0d00c869cd19580acea18c904cf9
|
||||
+ 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
|
||||
@@ -361,6 +366,7 @@ UcXd/5qu2GhokrKU2cPttU+XAN2Om6a0
|
||||
@@ -359,3 +362,4 @@ 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..7a17285deee18ffbccf1d01d9d1b7b87e561bffa 100644
|
||||
index 4271121881379b6c6892e89e520345f77e4181df..6c87a1ac687aa37d4ba245d1b6fc746a5f1eeffc 100644
|
||||
--- a/test/parallel/test-crypto.js
|
||||
+++ b/test/parallel/test-crypto.js
|
||||
@@ -61,7 +61,7 @@ assert.throws(() => {
|
||||
@@ -629,14 +595,23 @@ index 4271121881379b6c6892e89e520345f77e4181df..7a17285deee18ffbccf1d01d9d1b7b87
|
||||
validateList(crypto.getHashes());
|
||||
// Make sure all of the hashes are supported by OpenSSL
|
||||
for (const algo of crypto.getHashes())
|
||||
@@ -196,6 +194,7 @@ assert.throws(
|
||||
@@ -195,7 +193,7 @@ assert.throws(
|
||||
return true;
|
||||
}
|
||||
);
|
||||
|
||||
+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',
|
||||
} : {
|
||||
@@ -657,7 +632,7 @@ index 4271121881379b6c6892e89e520345f77e4181df..7a17285deee18ffbccf1d01d9d1b7b87
|
||||
});
|
||||
}
|
||||
-
|
||||
+}
|
||||
+*/
|
||||
// Make sure memory isn't released before being returned
|
||||
console.log(crypto.randomBytes(16));
|
||||
|
||||
@@ -750,7 +725,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..8c251ff2371fb59bf679160574e1c5dc1b4b2665 100644
|
||||
index eb09bc24f0cb8244b05987e3a7c1d203360d3a38..011990db171faa708c5211f6ab9ae1ac0e0ab90e 100644
|
||||
--- a/test/parallel/test-webcrypto-derivebits.js
|
||||
+++ b/test/parallel/test-webcrypto-derivebits.js
|
||||
@@ -101,8 +101,9 @@ const { subtle } = globalThis.crypto;
|
||||
@@ -764,6 +739,11 @@ index eb09bc24f0cb8244b05987e3a7c1d203360d3a38..8c251ff2371fb59bf679160574e1c5dc
|
||||
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 45a0abc6423a4e53e070f3c117fac2a3554b188d..abd89e9cccba1060f8e76580d5bb338e65a710ea 100644
|
||||
index 06b31af80ebbfbf35ec787a94f345775eb512ebf..deca5aa4b8829ba9921440fcb5c285a10e40c8f0 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -287,6 +287,9 @@ function cjsPreparseModuleExports(filename, source) {
|
||||
@@ -354,6 +354,9 @@ function cjsPreparseModuleExports(filename, source) {
|
||||
if (module && module[kModuleExportNames] !== undefined) {
|
||||
return { module, exportNames: module[kModuleExportNames] };
|
||||
}
|
||||
@@ -33,7 +33,7 @@ index 45a0abc6423a4e53e070f3c117fac2a3554b188d..abd89e9cccba1060f8e76580d5bb338e
|
||||
if (!loaded) {
|
||||
module = new CJSModule(filename);
|
||||
diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js
|
||||
index ab4783a7982b9feb8fa85b62e3e3b181f93309bd..34f91026451d7347ae278712d083e4fe281e50f3 100644
|
||||
index 1e1a1ea46fc6c1b43cad4038ab0d9cdf21d6ba3d..95e2fa5479ea31559fdb5a2e03515f243b231b75 100644
|
||||
--- a/lib/internal/modules/run_main.js
|
||||
+++ b/lib/internal/modules/run_main.js
|
||||
@@ -2,6 +2,7 @@
|
||||
@@ -58,7 +58,7 @@ index ab4783a7982b9feb8fa85b62e3e3b181f93309bd..34f91026451d7347ae278712d083e4fe
|
||||
const defaultType = getOptionValue('--experimental-default-type');
|
||||
/** @type {string} */
|
||||
let mainPath;
|
||||
@@ -62,6 +70,13 @@ function resolveMainPath(main) {
|
||||
@@ -63,6 +71,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 26d0bace6cdd3905f1248c5ad3fa794eb272252d..4ec1f4f6951be40f5fcb4c1cb3d1205e69434f23 100644
|
||||
index a89446df710a941390c15171fea63c551776fc93..912f03bfa96c3aa12bfa6e709746642452568bb7 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 35925ef0817273948b7a2128c6ddc12c91bc3cfd..ee2cc03892c01141b71571989b18eec387d3c766 100644
|
||||
index 1fbbb6773c9479128408fa1f27cf19f1a7786ba6..f05c6f99c0037193c5802024be46a967d6cf47a0 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 35925ef0817273948b7a2128c6ddc12c91bc3cfd..ee2cc03892c01141b71571989b18eec3
|
||||
parsePackageName(specifier, base);
|
||||
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index 9b89c3e1d52a0f724dab451844d32df67f1eab9f..25ee090bbb4884d3e5f2530cc7153f9215754fae 100644
|
||||
index 8f88214f558c52ef26000fb0e1ef4d391327e84e..d182eedf5e96039e0029d36e51f40b75c6fb2a39 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -182,7 +182,7 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
@@ -246,7 +246,7 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
|
||||
const { exportNames, module } = cjsPreparseModuleExports(filename, source);
|
||||
cjsCache.set(url, module);
|
||||
@@ -83,7 +83,7 @@ index 9b89c3e1d52a0f724dab451844d32df67f1eab9f..25ee090bbb4884d3e5f2530cc7153f92
|
||||
[...exportNames] : ['default', ...exportNames];
|
||||
|
||||
if (isMain) {
|
||||
@@ -204,8 +204,8 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
@@ -268,8 +268,8 @@ function createCJSModuleWrap(url, source, isMain, loadCJS = loadCJSModule) {
|
||||
({ exports } = module);
|
||||
}
|
||||
for (const exportName of exportNames) {
|
||||
@@ -94,7 +94,7 @@ index 9b89c3e1d52a0f724dab451844d32df67f1eab9f..25ee090bbb4884d3e5f2530cc7153f92
|
||||
continue;
|
||||
}
|
||||
// We might trigger a getter -> dont fail.
|
||||
@@ -239,6 +239,10 @@ translators.set('require-commonjs', (url, source, isMain) => {
|
||||
@@ -304,6 +304,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 ad323fc800a33c010b0504a4aa55c107498dee26..e044f10284f31f1862b18be752a04b3bd5d53401 100644
|
||||
index 77c20a4b6b9db414444974f68c5def8788386d2b..5fc1b6f2446d7c786024eb60800e2edab613dcd1 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -567,6 +567,10 @@ MultiIsolatePlatform* GetMultiIsolatePlatform(IsolateData* env) {
|
||||
@@ -564,6 +564,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 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824ca574106 100644
|
||||
index eb3533bb4623b152605c3c590f37f086cce5f073..ded231aeaa15af22845704cfcc7d24a44bd88f8e 100644
|
||||
--- a/deps/ncrypto/ncrypto.cc
|
||||
+++ b/deps/ncrypto/ncrypto.cc
|
||||
@@ -6,13 +6,11 @@
|
||||
@@ -35,7 +35,7 @@ index 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824
|
||||
|
||||
namespace ncrypto {
|
||||
namespace {
|
||||
@@ -694,7 +692,7 @@ bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
@@ -665,7 +663,7 @@ bool SafeX509SubjectAltNamePrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
|
||||
bool ok = true;
|
||||
|
||||
@@ -44,7 +44,7 @@ index 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824
|
||||
GENERAL_NAME* gen = sk_GENERAL_NAME_value(names, i);
|
||||
|
||||
if (i != 0)
|
||||
@@ -720,7 +718,7 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
@@ -691,7 +689,7 @@ bool SafeX509InfoAccessPrint(const BIOPointer& out, X509_EXTENSION* ext) {
|
||||
|
||||
bool ok = true;
|
||||
|
||||
@@ -53,25 +53,7 @@ index 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824
|
||||
ACCESS_DESCRIPTION* desc = sk_ACCESS_DESCRIPTION_value(descs, i);
|
||||
|
||||
if (i != 0)
|
||||
@@ -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() {
|
||||
@@ -1002,7 +1000,11 @@ BIOPointer BIOPointer::NewMem() {
|
||||
}
|
||||
|
||||
BIOPointer BIOPointer::NewSecMem() {
|
||||
@@ -83,7 +65,7 @@ index 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824
|
||||
}
|
||||
|
||||
BIOPointer BIOPointer::New(const BIO_METHOD* method) {
|
||||
@@ -1098,8 +1104,10 @@ BignumPointer DHPointer::FindGroup(const std::string_view name,
|
||||
@@ -1057,8 +1059,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) {
|
||||
@@ -94,7 +76,7 @@ index 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824
|
||||
V("modp5", BN_get_rfc3526_prime_1536);
|
||||
}
|
||||
V("modp14", BN_get_rfc3526_prime_2048);
|
||||
@@ -1171,11 +1179,13 @@ DHPointer::CheckPublicKeyResult DHPointer::checkPublicKey(const BignumPointer& p
|
||||
@@ -1130,11 +1134,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;
|
||||
@@ -110,10 +92,10 @@ index 457bd2f6c5b18956d06c716fbfae429496fb352d..e954cb2e53f3d8c297d21ef9f698d824
|
||||
}
|
||||
return CheckPublicKeyResult::NONE;
|
||||
diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h
|
||||
index 20b69dc67b13fd4f0bd44f7adf6a0d928a2c10c4..2320f92c50543fb9b426bce1c6d182bddf7658de 100644
|
||||
index 60bfce3ea8999e8e145aaf8cd14f0fdf21ed9c54..55aae783bb57273d1b49927f65b6c0830d09d115 100644
|
||||
--- a/deps/ncrypto/ncrypto.h
|
||||
+++ b/deps/ncrypto/ncrypto.h
|
||||
@@ -493,17 +493,21 @@ public:
|
||||
@@ -400,17 +400,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,
|
||||
@@ -149,7 +131,7 @@ index ea024af73e215b3cad5f08796ac405f419530c86..41061b524eea74330b8d2452635a38c4
|
||||
}
|
||||
}
|
||||
diff --git a/node.gni b/node.gni
|
||||
index 852f64fa9cfb50fe6e9ce7aa46be336d3196d5b8..461bff93e151c454cd0a9575daa01d3f7c0ec9c3 100644
|
||||
index 32709b860ccb12d8d1e75342a65dda0b86129b21..18d58591e3d0f1f3512db00033c3410a65702864 100644
|
||||
--- a/node.gni
|
||||
+++ b/node.gni
|
||||
@@ -10,6 +10,8 @@ declare_args() {
|
||||
@@ -162,10 +144,10 @@ index 852f64fa9cfb50fe6e9ce7aa46be336d3196d5b8..461bff93e151c454cd0a9575daa01d3f
|
||||
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 a81ab8e95f2fc23e1e315fb9c69364934377a0c1..dbe12ba2413ef29ff06a7e8abde50000eaf277e2 100644
|
||||
index fe35a8e0f6bbb7ab515a0343a7ed046c44e86474..43a7abbf237d8d809953e302b83755a3283a1bf4 100644
|
||||
--- a/src/crypto/crypto_cipher.cc
|
||||
+++ b/src/crypto/crypto_cipher.cc
|
||||
@@ -1080,7 +1080,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1078,7 +1078,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) {
|
||||
return ThrowCryptoError(env, ERR_get_error());
|
||||
}
|
||||
@@ -174,7 +156,7 @@ index a81ab8e95f2fc23e1e315fb9c69364934377a0c1..dbe12ba2413ef29ff06a7e8abde50000
|
||||
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.
|
||||
@@ -1096,6 +1096,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1094,6 +1094,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");
|
||||
}
|
||||
@@ -183,7 +165,7 @@ index a81ab8e95f2fc23e1e315fb9c69364934377a0c1..dbe12ba2413ef29ff06a7e8abde50000
|
||||
|
||||
const EVP_MD* digest = nullptr;
|
||||
diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc
|
||||
index 43a126f863779d3f364f92bd237039474b489845..77a3caee93049f65faef37e93b871c467ebca7e5 100644
|
||||
index 6a967702b22df0eb8aa10e853fd232794955860d..31058cccc6ffeed6b09aaecda320ee2f15849ec8 100644
|
||||
--- a/src/crypto/crypto_common.cc
|
||||
+++ b/src/crypto/crypto_common.cc
|
||||
@@ -134,7 +134,7 @@ const char* GetClientHelloALPN(const SSLPointer& ssl) {
|
||||
@@ -272,7 +254,7 @@ index 43a126f863779d3f364f92bd237039474b489845..77a3caee93049f65faef37e93b871c46
|
||||
crypto::EVPKeyPointer key(raw_key);
|
||||
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index aa5fc61f19e435b4833f3f49df10fa1edf2142c7..0a338b018a4ec20cb5bce250faf60d3f3bf192d4 100644
|
||||
index c924a54639e8c22d765dc240dffacfffb200ca0c..287afcc792a0a2b7e19126ee9a48ebe21cc8844e 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,
|
||||
@@ -308,7 +290,7 @@ index aa5fc61f19e435b4833f3f49df10fa1edf2142c7..0a338b018a4ec20cb5bce250faf60d3f
|
||||
|
||||
X509_STORE_add_cert(sc->GetCertStoreOwnedByThisSecureContext(), ca);
|
||||
diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc
|
||||
index d760a0d3ea1d12184a558f5e87cb22043d26a0f5..f973941b3b9ea954f35f2ea135f8ee3d77b98958 100644
|
||||
index e5664dfa2bc7e11922fa965f28acdf21470d1147..33ffbbb85d05f5356183e3aa1ca23707c5629b5d 100644
|
||||
--- a/src/crypto/crypto_dh.cc
|
||||
+++ b/src/crypto/crypto_dh.cc
|
||||
@@ -7,7 +7,9 @@
|
||||
@@ -393,7 +375,7 @@ index d760a0d3ea1d12184a558f5e87cb22043d26a0f5..f973941b3b9ea954f35f2ea135f8ee3d
|
||||
break;
|
||||
}
|
||||
@@ -398,9 +398,11 @@ EVPKeyCtxPointer DhKeyGenTraits::Setup(DhKeyPairGenConfig* params) {
|
||||
key_params = EVPKeyPointer::New();
|
||||
key_params = EVPKeyPointer(EVP_PKEY_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)) {
|
||||
@@ -416,7 +398,7 @@ index d760a0d3ea1d12184a558f5e87cb22043d26a0f5..f973941b3b9ea954f35f2ea135f8ee3d
|
||||
UNREACHABLE();
|
||||
}
|
||||
diff --git a/src/crypto/crypto_dsa.cc b/src/crypto/crypto_dsa.cc
|
||||
index b557de774117e442d7f429e92d63a6e1faa236fd..0aca233ced39269b09c383e5b32d85cf36260a1e 100644
|
||||
index 5d081863cf2dcdcf8c2d09db6060eeb5e78c452f..67523ec1c406e345945e1dde663c784c43a1c624 100644
|
||||
--- a/src/crypto/crypto_dsa.cc
|
||||
+++ b/src/crypto/crypto_dsa.cc
|
||||
@@ -40,7 +40,7 @@ namespace crypto {
|
||||
@@ -440,10 +422,10 @@ index b557de774117e442d7f429e92d63a6e1faa236fd..0aca233ced39269b09c383e5b32d85cf
|
||||
return EVPKeyCtxPointer();
|
||||
|
||||
diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc
|
||||
index 6af8d089ca6bcd73aff314638443610b9cc4bf7e..c84cbd5b4708e0c403ab0a1e1ddf5fc72eb3d148 100644
|
||||
index 8488fc57faaf722174032c5a927d150c76120d60..c51efc92d4818ee7701b4725585fb7e1d2d644ad 100644
|
||||
--- a/src/crypto/crypto_keys.cc
|
||||
+++ b/src/crypto/crypto_keys.cc
|
||||
@@ -1059,6 +1059,7 @@ void KeyObjectHandle::GetAsymmetricKeyType(
|
||||
@@ -1204,6 +1204,7 @@ void KeyObjectHandle::GetAsymmetricKeyType(
|
||||
}
|
||||
|
||||
bool KeyObjectHandle::CheckEcKeyData() const {
|
||||
@@ -451,7 +433,7 @@ index 6af8d089ca6bcd73aff314638443610b9cc4bf7e..c84cbd5b4708e0c403ab0a1e1ddf5fc7
|
||||
MarkPopErrorOnReturn mark_pop_error_on_return;
|
||||
|
||||
const auto& key = data_.GetAsymmetricKey();
|
||||
@@ -1075,6 +1076,9 @@ bool KeyObjectHandle::CheckEcKeyData() const {
|
||||
@@ -1220,6 +1221,9 @@ bool KeyObjectHandle::CheckEcKeyData() const {
|
||||
#else
|
||||
return EVP_PKEY_public_check(ctx.get()) == 1;
|
||||
#endif
|
||||
@@ -475,25 +457,27 @@ 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 6d360554b31d53a597d61fcbd660f703a903ca21..86fafe98222d4c18f062032d80104f3ef00dbc01 100644
|
||||
index 02e8e24b4054afd4c3ca797c19a78927319a0d9e..d2a931a3f8f9490fe17ef8a82d0204ee2cca409d 100644
|
||||
--- a/src/crypto/crypto_rsa.cc
|
||||
+++ b/src/crypto/crypto_rsa.cc
|
||||
@@ -608,10 +608,13 @@ Maybe<void> GetRsaKeyDetail(Environment* env,
|
||||
@@ -608,10 +608,11 @@ Maybe<void> GetRsaKeyDetail(Environment* env,
|
||||
}
|
||||
|
||||
if (params->saltLength != nullptr) {
|
||||
+#ifndef OPENSSL_IS_BORINGSSL
|
||||
- if (ASN1_INTEGER_get_int64(&salt_length, params->saltLength) != 1) {
|
||||
- ThrowCryptoError(env, ERR_get_error(), "ASN1_INTEGER_get_in64 error");
|
||||
- return Nothing<void>();
|
||||
- }
|
||||
+ // 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>();
|
||||
}
|
||||
+#endif
|
||||
+ // if (ASN1_INTEGER_get_int64(&salt_length, params->saltLength) != 1) {
|
||||
+ // ThrowCryptoError(env, ERR_get_error(), "ASN1_INTEGER_get_in64 error");
|
||||
+ // return Nothing<void>();
|
||||
+ // }
|
||||
}
|
||||
|
||||
if (target
|
||||
diff --git a/src/crypto/crypto_util.cc b/src/crypto/crypto_util.cc
|
||||
index 12ee0cde0897024bccb0face49053544a0bcfcd7..8a6a36a3c31532ed585c287ba8cee14026d315b4 100644
|
||||
index 793c196f8ce538c66b20611d00e12392ff9e878b..ee81048caab4ccfe26ea9e677782c9c955d162a9 100644
|
||||
--- a/src/crypto/crypto_util.cc
|
||||
+++ b/src/crypto/crypto_util.cc
|
||||
@@ -495,24 +495,15 @@ Maybe<void> Decorate(Environment* env,
|
||||
@@ -554,7 +538,7 @@ index 12ee0cde0897024bccb0face49053544a0bcfcd7..8a6a36a3c31532ed585c287ba8cee140
|
||||
} // namespace
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 55124cd38e75ab67c092f6bf5c909a50e7232045..3ef093e612b23d5e1e7cacf56055e5f9818bcb02 100644
|
||||
index fc8dbd615255851cad90e1d8ffe225f5e0c6a718..49ca9c0042ccf22ad1fffa54f05fd443cbc681ba 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -50,7 +50,7 @@
|
||||
@@ -566,7 +550,7 @@ index 55124cd38e75ab67c092f6bf5c909a50e7232045..3ef093e612b23d5e1e7cacf56055e5f9
|
||||
#include <openssl/evp.h>
|
||||
#endif
|
||||
|
||||
@@ -1060,7 +1060,7 @@ class Environment final : public MemoryRetainer {
|
||||
@@ -1073,7 +1073,7 @@ class Environment final : public MemoryRetainer {
|
||||
kExitInfoFieldCount
|
||||
};
|
||||
|
||||
@@ -589,7 +573,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 d3b59690e917afcf725cbfb1232d6ed9f298ee3a..3c42f9b87c11a0f88800d6709515c1c9e2972fc0 100644
|
||||
index cfc599ec9a6197231c3469d318f02c620cdb03a8..29630fcccc3bd9d24ad6aec64bef2fedfc3c4031 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -6,7 +6,7 @@
|
||||
@@ -602,7 +586,7 @@ index d3b59690e917afcf725cbfb1232d6ed9f298ee3a..3c42f9b87c11a0f88800d6709515c1c9
|
||||
#endif
|
||||
|
||||
diff --git a/src/node_options.h b/src/node_options.h
|
||||
index fc7f898a6b9b6072c15d77710c20ed1ba580966b..f39dcad0a28ae483e6d0e5df3816693119ac823e 100644
|
||||
index 9e656a2815045aa5da7eb267708c03058be9f362..600e0850f01e01024414d42b25605f256200540a 100644
|
||||
--- a/src/node_options.h
|
||||
+++ b/src/node_options.h
|
||||
@@ -11,7 +11,7 @@
|
||||
@@ -615,10 +599,10 @@ index fc7f898a6b9b6072c15d77710c20ed1ba580966b..f39dcad0a28ae483e6d0e5df38166931
|
||||
#endif
|
||||
|
||||
diff --git a/unofficial.gni b/unofficial.gni
|
||||
index f6793b8bf22d6ac911a1977edaa881b6dbbe7ac7..ddfbb97276b29df114ab455a2eed3b186b3af5d2 100644
|
||||
index de6ff5548ca5282199b7d85c11941c1fa351a9d9..3d8b7957e791ce2fa2a8d0937a87b6010087803d 100644
|
||||
--- a/unofficial.gni
|
||||
+++ b/unofficial.gni
|
||||
@@ -150,7 +150,6 @@ template("node_gn_build") {
|
||||
@@ -145,7 +145,6 @@ template("node_gn_build") {
|
||||
]
|
||||
deps = [
|
||||
":run_node_js2c",
|
||||
@@ -626,7 +610,7 @@ index f6793b8bf22d6ac911a1977edaa881b6dbbe7ac7..ddfbb97276b29df114ab455a2eed3b18
|
||||
"deps/cares",
|
||||
"deps/histogram",
|
||||
"deps/llhttp",
|
||||
@@ -161,6 +160,8 @@ template("node_gn_build") {
|
||||
@@ -156,6 +155,8 @@ template("node_gn_build") {
|
||||
"deps/sqlite",
|
||||
"deps/uvwasi",
|
||||
"//third_party/zlib",
|
||||
@@ -635,7 +619,7 @@ index f6793b8bf22d6ac911a1977edaa881b6dbbe7ac7..ddfbb97276b29df114ab455a2eed3b18
|
||||
"$node_v8_path:v8_libplatform",
|
||||
]
|
||||
|
||||
@@ -187,10 +188,8 @@ template("node_gn_build") {
|
||||
@@ -182,10 +183,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 ee2cc03892c01141b71571989b18eec387d3c766..c13475102a75d65329908f44def06a60f4a2c4f1 100644
|
||||
index f05c6f99c0037193c5802024be46a967d6cf47a0..f3dad958b2ec275992554477b9344214c8c1e2c8 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -25,7 +25,7 @@ const {
|
||||
const assert = require('internal/assert');
|
||||
@@ -24,7 +24,7 @@ const {
|
||||
} = primordials;
|
||||
const internalFS = require('internal/fs/utils');
|
||||
const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
-const { realpathSync } = require('fs');
|
||||
@@ -60,10 +60,10 @@ index ee2cc03892c01141b71571989b18eec387d3c766..c13475102a75d65329908f44def06a60
|
||||
});
|
||||
const { search, hash } = resolved;
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index 25ee090bbb4884d3e5f2530cc7153f9215754fae..45a0abc6423a4e53e070f3c117fac2a3554b188d 100644
|
||||
index d182eedf5e96039e0029d36e51f40b75c6fb2a39..06b31af80ebbfbf35ec787a94f345775eb512ebf 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -24,7 +24,7 @@ const {
|
||||
@@ -34,7 +34,7 @@ const {
|
||||
|
||||
const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
const assert = require('internal/assert');
|
||||
@@ -71,8 +71,8 @@ index 25ee090bbb4884d3e5f2530cc7153f9215754fae..45a0abc6423a4e53e070f3c117fac2a3
|
||||
+const fs = require('fs');
|
||||
const { dirname, extname, isAbsolute } = require('path');
|
||||
const {
|
||||
assertBufferSource,
|
||||
@@ -269,7 +269,7 @@ translators.set('commonjs', function commonjsStrategy(url, source, isMain) {
|
||||
loadBuiltinModule,
|
||||
@@ -335,7 +335,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
|
||||
try {
|
||||
// We still need to read the FS to detect the exports.
|
||||
@@ -81,7 +81,7 @@ index 25ee090bbb4884d3e5f2530cc7153f9215754fae..45a0abc6423a4e53e070f3c117fac2a3
|
||||
} catch {
|
||||
// Continue regardless of error.
|
||||
}
|
||||
@@ -336,7 +336,7 @@ function cjsPreparseModuleExports(filename, source) {
|
||||
@@ -403,7 +403,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 cd51d9acf9540d506ec35812b9d2c530fce24912..07068344262f7b73a83073d4da75bffe8b747a61 100644
|
||||
index 2302e8d94da3250e7fb4ee0c5e6a51d3d6941fbc..ed72476e16036d972de54d39cf4bd37bbbed5c5f 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -44,6 +44,14 @@
|
||||
@@ -74,7 +74,7 @@ index cd51d9acf9540d506ec35812b9d2c530fce24912..07068344262f7b73a83073d4da75bffe
|
||||
using v8::FunctionCallbackInfo;
|
||||
using v8::Global;
|
||||
using v8::HandleScope;
|
||||
@@ -582,19 +589,24 @@ void SlowCopy(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -581,19 +588,24 @@ void SlowCopy(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
// Assume caller has properly validated args.
|
||||
uint32_t FastCopy(Local<Value> receiver,
|
||||
@@ -107,7 +107,7 @@ index cd51d9acf9540d506ec35812b9d2c530fce24912..07068344262f7b73a83073d4da75bffe
|
||||
return to_copy;
|
||||
}
|
||||
|
||||
@@ -858,19 +870,17 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
|
||||
@@ -857,19 +869,17 @@ void Compare(const FunctionCallbackInfo<Value> &args) {
|
||||
}
|
||||
|
||||
int32_t FastCompare(v8::Local<v8::Value>,
|
||||
@@ -135,7 +135,7 @@ index cd51d9acf9540d506ec35812b9d2c530fce24912..07068344262f7b73a83073d4da75bffe
|
||||
}
|
||||
|
||||
static v8::CFunction fast_compare(v8::CFunction::Make(FastCompare));
|
||||
@@ -1141,14 +1151,13 @@ void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1140,14 +1150,13 @@ void SlowIndexOfNumber(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
int32_t FastIndexOfNumber(v8::Local<v8::Value>,
|
||||
@@ -153,7 +153,7 @@ index cd51d9acf9540d506ec35812b9d2c530fce24912..07068344262f7b73a83073d4da75bffe
|
||||
}
|
||||
|
||||
static v8::CFunction fast_index_of_number(
|
||||
@@ -1501,21 +1510,31 @@ void SlowWriteString(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1552,21 +1561,31 @@ void SlowWriteString(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
template <encoding encoding>
|
||||
uint32_t FastWriteString(Local<Value> receiver,
|
||||
@@ -194,10 +194,10 @@ index cd51d9acf9540d506ec35812b9d2c530fce24912..07068344262f7b73a83073d4da75bffe
|
||||
|
||||
static v8::CFunction fast_write_string_ascii(
|
||||
diff --git a/src/node_external_reference.h b/src/node_external_reference.h
|
||||
index 8d49a119c218323674e29a522ecf71bd22cdaf1b..d39693f2f45f39e45960453112b0f6460a1b3a4d 100644
|
||||
index 38a4ff7e6c2c9997f004c7c1f94cb5a9ffc2ffe0..48e73168f994d79ae3564b813acb5546ca8f2526 100644
|
||||
--- a/src/node_external_reference.h
|
||||
+++ b/src/node_external_reference.h
|
||||
@@ -40,16 +40,16 @@ using CFunctionCallbackWithStrings =
|
||||
@@ -34,16 +34,16 @@ using CFunctionCallbackWithStrings =
|
||||
const v8::FastOneByteString& base);
|
||||
using CFunctionCallbackWithTwoUint8Arrays =
|
||||
int32_t (*)(v8::Local<v8::Value>,
|
||||
@@ -219,7 +219,7 @@ index 8d49a119c218323674e29a522ecf71bd22cdaf1b..d39693f2f45f39e45960453112b0f646
|
||||
uint32_t,
|
||||
int64_t,
|
||||
bool);
|
||||
@@ -68,18 +68,20 @@ using CFunctionWithBool = void (*)(v8::Local<v8::Value>,
|
||||
@@ -58,18 +58,20 @@ using CFunctionWithBool = void (*)(v8::Local<v8::Value>, bool);
|
||||
|
||||
using CFunctionWriteString =
|
||||
uint32_t (*)(v8::Local<v8::Value> receiver,
|
||||
@@ -246,18 +246,19 @@ index 8d49a119c218323674e29a522ecf71bd22cdaf1b..d39693f2f45f39e45960453112b0f646
|
||||
// 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 b1f316eebc7199a3737f05a5f9a1dd7fc289490c..23a0a486244ce38277ef11df5806da1266b901ac 100644
|
||||
index a6da8720c499df54ab4608eb03cff905759c2232..43ef977363e565a6f9422c9454e25b8fe0b327d5 100644
|
||||
--- a/src/util.h
|
||||
+++ b/src/util.h
|
||||
@@ -59,6 +59,7 @@
|
||||
@@ -57,6 +57,8 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
constexpr char kPathSeparator = std::filesystem::path::preferred_separator;
|
||||
+static constexpr size_t kMaxSizeInHeap = 64;
|
||||
|
||||
+static constexpr size_t kMaxSizeInHeap = 64; \
|
||||
+
|
||||
#ifdef _WIN32
|
||||
/* MAX_PATH is in characters, not bytes. Make sure we have enough headroom. */
|
||||
@@ -576,6 +577,16 @@ class BufferValue : public MaybeStackBuffer<char> {
|
||||
#define PATH_MAX_BYTES (MAX_PATH * 4)
|
||||
@@ -573,6 +575,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 1a2a43bdd37441400323a800c147fcb89f0d549a..ae0b40b40e601e86d22e223a764c20106ae29d70 100644
|
||||
index ccc1085a84b214d241687fa9ebd45b55b2cc60d8..1df8e1f00a0e2ffa63bfd4369240b837ab6a9c50 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 c13475102a75d65329908f44def06a60f4a2c4f1..e9fe83a675cb5bf681934e0f1c30a3cab447ba57 100644
|
||||
index f3dad958b2ec275992554477b9344214c8c1e2c8..a086217046fd5ed7cfb09cfd2ed62f3987eb1f31 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -28,14 +28,13 @@ const { BuiltinModule } = require('internal/bootstrap/realm');
|
||||
@@ -27,14 +27,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,36 +35,56 @@ index c13475102a75d65329908f44def06a60f4a2c4f1..e9fe83a675cb5bf681934e0f1c30a3ca
|
||||
const {
|
||||
ERR_INPUT_TYPE_NOT_ALLOWED,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
@@ -183,6 +182,15 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
kResolvedByPackageAndNode: 9,
|
||||
};
|
||||
@@ -154,34 +153,13 @@ function emitLegacyIndexDeprecation(url, packageJSONUrl, base, main) {
|
||||
|
||||
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) {
|
||||
+ const namespaced = toNamespacedPath(toPathIfFileURL(url));
|
||||
+ return internalFsBinding.internalModuleStat(internalFsBinding, namespaced) === 0;
|
||||
+ return internalFsBinding.internalModuleStat(toNamespacedPath(toPathIfFileURL(url))) === 0;
|
||||
+}
|
||||
+
|
||||
|
||||
/**
|
||||
* Legacy CommonJS main resolution:
|
||||
* 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;
|
||||
@@ -196,22 +174,44 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
* @returns {URL}
|
||||
*/
|
||||
function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
- const packageJsonUrlString = packageJSONUrl.href;
|
||||
-
|
||||
- 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);
|
||||
- if (typeof packageJsonUrlString !== 'string') {
|
||||
- throw new ERR_INVALID_ARG_TYPE('packageJSONUrl', ['URL'], packageJSONUrl);
|
||||
+ let guess;
|
||||
+ if (packageConfig.main !== undefined) {
|
||||
+ // Note: fs check redundances will be handled by Descriptor cache here.
|
||||
@@ -85,39 +105,277 @@ index c13475102a75d65329908f44def06a60f4a2c4f1..e9fe83a675cb5bf681934e0f1c30a3ca
|
||||
+ packageJSONUrl)));
|
||||
+ else guess = undefined;
|
||||
+ if (guess) {
|
||||
+ emitLegacyIndexDeprecation(guess, fileURLToPath(guess), pkgPath,
|
||||
+ base, packageConfig.main);
|
||||
+ emitLegacyIndexDeprecation(guess, packageJSONUrl, 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, fileURLToPath(guess), pkgPath,
|
||||
+ base, packageConfig.main);
|
||||
+ emitLegacyIndexDeprecation(guess, packageJSONUrl, base, packageConfig.main);
|
||||
+ return guess;
|
||||
+ }
|
||||
+ // Not found.
|
||||
+ throw new ERR_MODULE_NOT_FOUND(pkgPath, fileURLToPath(base), null);
|
||||
+ throw new ERR_MODULE_NOT_FOUND(
|
||||
+ fileURLToPath(new URL('.', packageJSONUrl)), fileURLToPath(base));
|
||||
}
|
||||
|
||||
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 edb567bce403f2d4df482c2549c6f7cec78c3588..4567ddc3715ac0d11facb0b567c5f5763699f4c9 100644
|
||||
index 0bfeb567a22b1f9d9116b749d6cb3a8fda6bcc6a..17f137c595a9fef5f051fafc4682f206034c214c 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_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_INTERNAL_ASSERTION' },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -126,7 +384,7 @@ index edb567bce403f2d4df482c2549c6f7cec78c3588..4567ddc3715ac0d11facb0b567c5f576
|
||||
assert.throws(
|
||||
() => legacyMainResolve(packageJsonUrl, { main: null }, packageJsonUrl),
|
||||
- { message: /index\.js/, code: 'ERR_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_INTERNAL_ASSERTION' },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -135,11 +393,11 @@ index edb567bce403f2d4df482c2549c6f7cec78c3588..4567ddc3715ac0d11facb0b567c5f576
|
||||
assert.throws(
|
||||
() => legacyMainResolve(packageJsonUrl, { main: './index.node' }, packageJsonUrl),
|
||||
- { message: /index\.node/, code: 'ERR_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_MODULE_NOT_FOUND' },
|
||||
+ { code: 'ERR_INTERNAL_ASSERTION' },
|
||||
);
|
||||
});
|
||||
|
||||
@@ -163,11 +163,11 @@ describe('legacyMainResolve', () => {
|
||||
@@ -163,7 +163,7 @@ describe('legacyMainResolve', () => {
|
||||
);
|
||||
assert.throws(
|
||||
() => legacyMainResolve(packageJsonUrl, { main: null }, undefined),
|
||||
@@ -147,9 +405,4 @@ index edb567bce403f2d4df482c2549c6f7cec78c3588..4567ddc3715ac0d11facb0b567c5f576
|
||||
+ { 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 b0210e4d96348c77da9eabbe8f3d292337cd6ae4..ad8d41a06bde1ca22d0245fa49143e080365b5e1 100644
|
||||
index 451b7c2195e7ad3ab0bde95259e054dc431d7de9..d49941881e6cfd8647a6d44a57e0daaf1c874702 100644
|
||||
--- a/lib/internal/modules/cjs/loader.js
|
||||
+++ b/lib/internal/modules/cjs/loader.js
|
||||
@@ -183,6 +183,13 @@ const {
|
||||
@@ -182,6 +182,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 11d585bc5b3e47b36877ca8306b72f571acb7d09..65d42428c70a3242f7076f1c1a4cec027a9c9829 100644
|
||||
index f7a62364b6107ab0bad33ea2f745703c746991dc..bab2aaf3db66452216035db594dc3ebdc3606c8b 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 dfd115a9eccc6b58d63a72ac450a1497354482dd..16a9f923148835daa95d3578e5941b284ff71434 100644
|
||||
index 3bedd2dfecb49c3f69ea59b70d72b8b6fc605132..2b0e4905dd557e73542cf052ba81327b1e1e471f 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 3b041dd28ba32f028ecbb7d87b82f9ddee406b4f..5436c1a0f21e261f2eb2fdbb7f679d4f92a14ffd 100644
|
||||
index 28a15aa741ddd40c664aae641797e7cc2813442f..08fe98e10b7716c694bbc882299fe0ed9e282d73 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 3b041dd28ba32f028ecbb7d87b82f9ddee406b4f..5436c1a0f21e261f2eb2fdbb7f679d4f
|
||||
return &(wrapper_data_->cppgc_id);
|
||||
}
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index 130524cad713e8aa685feaa8c384fe4db9452500..21bc5b8a3326e759ce12b865e49029cf8ffe9995 100644
|
||||
index 665b064091d4cc42a4dc9ee5b0ea9e2f190338ca..4c8cb75945d82544ce2237d94cd1406d15efe424 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -23,6 +23,7 @@
|
||||
@@ -63,7 +63,7 @@ index 130524cad713e8aa685feaa8c384fe4db9452500..21bc5b8a3326e759ce12b865e49029cf
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
@@ -70,7 +71,6 @@ using v8::TryCatch;
|
||||
@@ -71,7 +72,6 @@ using v8::TryCatch;
|
||||
using v8::Uint32;
|
||||
using v8::Undefined;
|
||||
using v8::Value;
|
||||
@@ -146,7 +146,7 @@ index 130524cad713e8aa685feaa8c384fe4db9452500..21bc5b8a3326e759ce12b865e49029cf
|
||||
|
||||
void IsolateData::MemoryInfo(MemoryTracker* tracker) const {
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 3ef093e612b23d5e1e7cacf56055e5f9818bcb02..9dfc1364c7206377b6d0d088b456c357c23a9151 100644
|
||||
index 49ca9c0042ccf22ad1fffa54f05fd443cbc681ba..945535d0dc40f1a32f7e3ecf7d50361e591ba6c8 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 c62a5b8952400ff0dd8818c31a3e07622b63725c..36f61f57e951e1abfeb2fedb831b55c61363bcbc 100644
|
||||
index 4dbdea9be5721486d71a9dda77311b4919d450a3..4aacaa2a5d12533a039b4b96cb7f1fd79063d50f 100644
|
||||
--- a/src/histogram.cc
|
||||
+++ b/src/histogram.cc
|
||||
@@ -195,7 +195,8 @@ void HistogramBase::FastRecord(Local<Value> unused,
|
||||
@@ -193,7 +193,8 @@ void HistogramBase::FastRecord(Local<Value> receiver,
|
||||
const int64_t value,
|
||||
FastApiCallbackOptions& options) {
|
||||
if (value < 1) {
|
||||
@@ -40,13 +40,14 @@ index c62a5b8952400ff0dd8818c31a3e07622b63725c..36f61f57e951e1abfeb2fedb831b55c6
|
||||
}
|
||||
HistogramBase* histogram;
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 6b98a13099990918dc619c47124c8538bbee5e2d..307492bf3dfce7b4a476c448bec666b8116dc431 100644
|
||||
index b565beae625d970ba92ab667a145d8897d4e8a6e..31c2fe82299d6905855c4efffeea4a4d161a88d5 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -1060,22 +1060,10 @@ static int32_t FastInternalModuleStat(
|
||||
@@ -1049,23 +1049,10 @@ static int32_t FastInternalModuleStat(
|
||||
const FastOneByteString& input,
|
||||
// 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;
|
||||
@@ -59,24 +60,24 @@ index 6b98a13099990918dc619c47124c8538bbee5e2d..307492bf3dfce7b4a476c448bec666b8
|
||||
+ HandleScope scope(env->isolate());
|
||||
|
||||
auto path = std::filesystem::path(input.data, input.data + input.length);
|
||||
- if (!env->permission()->is_granted(
|
||||
- env, permission::PermissionScope::kFileSystemRead, path.string()))
|
||||
- [[unlikely]] {
|
||||
- if (UNLIKELY(!env->permission()->is_granted(
|
||||
- env, permission::PermissionScope::kFileSystemRead, path.string()))) {
|
||||
- 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 468c2e59903fefe58d9c178d3afac3ef5b09f611..23a376e52e08a8af49dd47c47488552e01287426 100644
|
||||
index ad1da44a01f437c97e06a3857eebd2edcebc83da..7123278e1a0942b61a76e9b1e7464eb8b5064079 100644
|
||||
--- a/src/node_wasi.cc
|
||||
+++ b/src/node_wasi.cc
|
||||
@@ -251,17 +251,19 @@ R WASI::WasiFunction<FT, F, R, Args...>::FastCallback(
|
||||
return EinvalError<R>();
|
||||
}
|
||||
@@ -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>();
|
||||
|
||||
- if (options.wasm_memory == nullptr || wasi->memory_.IsEmpty()) [[unlikely]] {
|
||||
- if (UNLIKELY(options.wasm_memory == nullptr || wasi->memory_.IsEmpty())) {
|
||||
- // fallback to slow path which to throw an error about missing memory.
|
||||
- options.fallback = true;
|
||||
+ v8::Isolate* isolate = receiver->GetIsolate();
|
||||
@@ -86,16 +87,15 @@ index 468c2e59903fefe58d9c178d3afac3ef5b09f611..23a376e52e08a8af49dd47c47488552e
|
||||
return EinvalError<R>();
|
||||
}
|
||||
- uint8_t* memory = nullptr;
|
||||
- CHECK(options.wasm_memory->getStorageIfAligned(&memory));
|
||||
|
||||
- return F(*wasi,
|
||||
- {reinterpret_cast<char*>(memory), options.wasm_memory->length()},
|
||||
- args...);
|
||||
- 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);
|
||||
+
|
||||
|
||||
- return F(*wasi,
|
||||
- {reinterpret_cast<char*>(memory), options.wasm_memory->length()},
|
||||
- args...);
|
||||
+ 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 e044f10284f31f1862b18be752a04b3bd5d53401..89ce587cac4506c4218a9316fe0b68070a7a8504 100644
|
||||
index 5fc1b6f2446d7c786024eb60800e2edab613dcd1..f59abcb21d64b910d8d42eb23c03109f62558813 100644
|
||||
--- a/src/api/environment.cc
|
||||
+++ b/src/api/environment.cc
|
||||
@@ -102,6 +102,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
@@ -101,6 +101,14 @@ MaybeLocal<Value> PrepareStackTraceCallback(Local<Context> context,
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ index e044f10284f31f1862b18be752a04b3bd5d53401..89ce587cac4506c4218a9316fe0b6807
|
||||
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 f973941b3b9ea954f35f2ea135f8ee3d77b98958..743c63ff7e3f526829919a8f2de7ebd625a93fbc 100644
|
||||
index 33ffbbb85d05f5356183e3aa1ca23707c5629b5d..008d212ebe25b0022020379aa08963c12828940c 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 f973941b3b9ea954f35f2ea135f8ee3d77b98958..743c63ff7e3f526829919a8f2de7ebd6
|
||||
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 8a6a36a3c31532ed585c287ba8cee14026d315b4..3d449b5853f359d63e1b88671a857bf9152ff6af 100644
|
||||
index ee81048caab4ccfe26ea9e677782c9c955d162a9..643c9d31dc2737faa2ec51684ffceb35a1014a58 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 9b9bb7be9a8daca98a2635bf13cb6d1d561ea5fb..81afe2b5f7398f0c20b340648ca75022470be544 100644
|
||||
index af2f953f0388dbce326b0c519de3883552f8f009..7fb34057a486914dd886ec4d3d23be90cccb4fea 100644
|
||||
--- a/src/crypto/crypto_x509.cc
|
||||
+++ b/src/crypto/crypto_x509.cc
|
||||
@@ -175,6 +175,19 @@ MaybeLocal<Value> ToV8Value(Local<Context> context, const BIOPointer& bio) {
|
||||
@@ -174,6 +174,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 9b9bb7be9a8daca98a2635bf13cb6d1d561ea5fb..81afe2b5f7398f0c20b340648ca75022
|
||||
auto backing = ArrayBuffer::NewBackingStore(
|
||||
mem->data,
|
||||
mem->length,
|
||||
@@ -182,6 +195,8 @@ MaybeLocal<Value> ToBuffer(Environment* env, BIOPointer* bio) {
|
||||
@@ -181,6 +194,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 85b666e11f5654afe2a2f192e629221f2133b165..bd8d65247ad3ba4878f1288ab2b66e3598982b09 100644
|
||||
index fe2d25decd883085e4c3f368ab4acc01a7f66f6e..bcd5c87afcff9c56429443363c63fc8079521451 100644
|
||||
--- a/src/node_internals.h
|
||||
+++ b/src/node_internals.h
|
||||
@@ -117,7 +117,9 @@ v8::Maybe<void> InitializePrimordials(v8::Local<v8::Context> context);
|
||||
@@ -117,7 +117,9 @@ v8::Maybe<bool> InitializePrimordials(v8::Local<v8::Context> context);
|
||||
|
||||
class NodeArrayBufferAllocator : public ArrayBufferAllocator {
|
||||
public:
|
||||
@@ -369,18 +369,3 @@ 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 6b5b0ed739bc8600d46c2f65993b86a4092c680c..40beb6a5ec2e129181ce74afce4021bf88286989 100644
|
||||
index 24e1a74886bad536dc08df75fbdb0508e4e1420a..7f3be73474557788050a9110b0e29e602b7d6397 100644
|
||||
--- a/test/parallel/parallel.status
|
||||
+++ b/test/parallel/parallel.status
|
||||
@@ -5,6 +5,16 @@ prefix parallel
|
||||
@@ -28,7 +28,7 @@ index 6b5b0ed739bc8600d46c2f65993b86a4092c680c..40beb6a5ec2e129181ce74afce4021bf
|
||||
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 073b29cce8dbca4c8d92ad666f9244ad511296db..338d20263f29a630febb96567f3cb708623bd09a 100644
|
||||
index a539649d5537376a6a2ac9a7a46051b8648f0cb1..a03c86b752772be7ae36fab31faeccf3b0ccff64 100644
|
||||
--- a/test/sequential/sequential.status
|
||||
+++ b/test/sequential/sequential.status
|
||||
@@ -7,6 +7,18 @@ prefix sequential
|
||||
|
||||
@@ -64,8 +64,6 @@
|
||||
"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",
|
||||
|
||||
@@ -4,15 +4,9 @@
|
||||
|
||||
#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"
|
||||
@@ -68,12 +62,7 @@ void GlobalShortcut::OnKeyPressed(const ui::Accelerator& accelerator) {
|
||||
|
||||
void GlobalShortcut::ExecuteCommand(const extensions::ExtensionId& extension_id,
|
||||
const std::string& command_id) {
|
||||
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();
|
||||
// Ignore extension commands
|
||||
}
|
||||
|
||||
bool GlobalShortcut::RegisterAll(
|
||||
@@ -114,56 +103,13 @@ bool GlobalShortcut::Register(const ui::Accelerator& accelerator,
|
||||
}
|
||||
#endif
|
||||
|
||||
auto* instance = GlobalShortcutListener::GetInstance();
|
||||
if (!instance) {
|
||||
if (!GlobalShortcutListener::GetInstance()->RegisterAccelerator(accelerator,
|
||||
this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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;
|
||||
accelerator_callback_map_[accelerator] = callback;
|
||||
return true;
|
||||
}
|
||||
|
||||
void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||
@@ -181,10 +127,8 @@ void GlobalShortcut::Unregister(const ui::Accelerator& accelerator) {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (GlobalShortcutListener::GetInstance()) {
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
|
||||
this);
|
||||
}
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerator(accelerator,
|
||||
this);
|
||||
}
|
||||
|
||||
void GlobalShortcut::UnregisterSome(
|
||||
@@ -195,12 +139,7 @@ void GlobalShortcut::UnregisterSome(
|
||||
}
|
||||
|
||||
bool GlobalShortcut::IsRegistered(const ui::Accelerator& 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);
|
||||
return base::Contains(accelerator_callback_map_, accelerator);
|
||||
}
|
||||
|
||||
void GlobalShortcut::UnregisterAll() {
|
||||
@@ -210,9 +149,7 @@ void GlobalShortcut::UnregisterAll() {
|
||||
return;
|
||||
}
|
||||
accelerator_callback_map_.clear();
|
||||
if (GlobalShortcutListener::GetInstance()) {
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
|
||||
}
|
||||
GlobalShortcutListener::GetInstance()->UnregisterAccelerators(this);
|
||||
}
|
||||
|
||||
// static
|
||||
|
||||
@@ -44,7 +44,6 @@ 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);
|
||||
@@ -61,7 +60,6 @@ class GlobalShortcut final
|
||||
const std::string& command_id) override;
|
||||
|
||||
AcceleratorCallbackMap accelerator_callback_map_;
|
||||
CommandCallbackMap command_callback_map_;
|
||||
};
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
@@ -236,6 +236,10 @@ const char* Notification::GetTypeName() {
|
||||
return GetClassName();
|
||||
}
|
||||
|
||||
void Notification::WillBeDestroyed() {
|
||||
ClearWeak();
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -57,6 +57,9 @@ class Notification final : public gin::Wrappable<Notification>,
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
// gin_helper::CleanedUpAtExit
|
||||
void WillBeDestroyed() override;
|
||||
|
||||
// disable copy
|
||||
Notification(const Notification&) = delete;
|
||||
Notification& operator=(const Notification&) = delete;
|
||||
|
||||
@@ -13,11 +13,18 @@
|
||||
#include "gin/data_object_builder.h"
|
||||
#include "gin/handle.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "shell/browser/api/electron_api_service_worker_main.h"
|
||||
#include "shell/browser/electron_browser_context.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/service_worker_converter.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/promise.h"
|
||||
#include "shell/common/node_util.h"
|
||||
|
||||
using ServiceWorkerStatus =
|
||||
content::ServiceWorkerRunningInfo::ServiceWorkerVersionStatus;
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
@@ -72,8 +79,8 @@ gin::WrapperInfo ServiceWorkerContext::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
ServiceWorkerContext::ServiceWorkerContext(
|
||||
v8::Isolate* isolate,
|
||||
ElectronBrowserContext* browser_context) {
|
||||
service_worker_context_ =
|
||||
browser_context->GetDefaultStoragePartition()->GetServiceWorkerContext();
|
||||
storage_partition_ = browser_context->GetDefaultStoragePartition();
|
||||
service_worker_context_ = storage_partition_->GetServiceWorkerContext();
|
||||
service_worker_context_->AddObserver(this);
|
||||
}
|
||||
|
||||
@@ -81,6 +88,23 @@ ServiceWorkerContext::~ServiceWorkerContext() {
|
||||
service_worker_context_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnRunningStatusChanged(
|
||||
int64_t version_id,
|
||||
blink::EmbeddedWorkerStatus running_status) {
|
||||
ServiceWorkerMain* worker =
|
||||
ServiceWorkerMain::FromVersionID(version_id, storage_partition_);
|
||||
if (worker)
|
||||
worker->OnRunningStatusChanged(running_status);
|
||||
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
EmitWithoutEvent("running-status-changed",
|
||||
gin::DataObjectBuilder(isolate)
|
||||
.Set("versionId", version_id)
|
||||
.Set("runningStatus", running_status)
|
||||
.Build());
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnReportConsoleMessage(
|
||||
int64_t version_id,
|
||||
const GURL& scope,
|
||||
@@ -105,6 +129,32 @@ void ServiceWorkerContext::OnRegistrationCompleted(const GURL& scope) {
|
||||
gin::DataObjectBuilder(isolate).Set("scope", scope).Build());
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnVersionRedundant(int64_t version_id,
|
||||
const GURL& scope) {
|
||||
ServiceWorkerMain* worker =
|
||||
ServiceWorkerMain::FromVersionID(version_id, storage_partition_);
|
||||
if (worker)
|
||||
worker->OnVersionRedundant();
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnVersionStartingRunning(int64_t version_id) {
|
||||
OnRunningStatusChanged(version_id, blink::EmbeddedWorkerStatus::kStarting);
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnVersionStartedRunning(
|
||||
int64_t version_id,
|
||||
const content::ServiceWorkerRunningInfo& running_info) {
|
||||
OnRunningStatusChanged(version_id, blink::EmbeddedWorkerStatus::kRunning);
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnVersionStoppingRunning(int64_t version_id) {
|
||||
OnRunningStatusChanged(version_id, blink::EmbeddedWorkerStatus::kStopping);
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnVersionStoppedRunning(int64_t version_id) {
|
||||
OnRunningStatusChanged(version_id, blink::EmbeddedWorkerStatus::kStopped);
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::OnDestruct(content::ServiceWorkerContext* context) {
|
||||
if (context == service_worker_context_) {
|
||||
delete this;
|
||||
@@ -124,7 +174,7 @@ v8::Local<v8::Value> ServiceWorkerContext::GetAllRunningWorkerInfo(
|
||||
return builder.Build();
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> ServiceWorkerContext::GetWorkerInfoFromID(
|
||||
v8::Local<v8::Value> ServiceWorkerContext::GetInfoFromVersionID(
|
||||
gin_helper::ErrorThrower thrower,
|
||||
int64_t version_id) {
|
||||
const base::flat_map<int64_t, content::ServiceWorkerRunningInfo>& info_map =
|
||||
@@ -138,6 +188,87 @@ v8::Local<v8::Value> ServiceWorkerContext::GetWorkerInfoFromID(
|
||||
std::move(iter->second));
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> ServiceWorkerContext::GetFromVersionID(
|
||||
gin_helper::ErrorThrower thrower,
|
||||
int64_t version_id) {
|
||||
util::EmitWarning(thrower.isolate(),
|
||||
"The session.serviceWorkers.getFromVersionID API is "
|
||||
"deprecated, use "
|
||||
"session.serviceWorkers.getInfoFromVersionID instead.",
|
||||
"ServiceWorkersDeprecateGetFromVersionID");
|
||||
|
||||
return GetInfoFromVersionID(thrower, version_id);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> ServiceWorkerContext::GetWorkerFromVersionID(
|
||||
v8::Isolate* isolate,
|
||||
int64_t version_id) {
|
||||
return ServiceWorkerMain::From(isolate, service_worker_context_,
|
||||
storage_partition_, version_id)
|
||||
.ToV8();
|
||||
}
|
||||
|
||||
gin::Handle<ServiceWorkerMain>
|
||||
ServiceWorkerContext::GetWorkerFromVersionIDIfExists(v8::Isolate* isolate,
|
||||
int64_t version_id) {
|
||||
ServiceWorkerMain* worker =
|
||||
ServiceWorkerMain::FromVersionID(version_id, storage_partition_);
|
||||
if (!worker)
|
||||
return gin::Handle<ServiceWorkerMain>();
|
||||
return gin::CreateHandle(isolate, worker);
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> ServiceWorkerContext::StartWorkerForScope(
|
||||
v8::Isolate* isolate,
|
||||
GURL scope) {
|
||||
auto shared_promise =
|
||||
std::make_shared<gin_helper::Promise<v8::Local<v8::Value>>>(isolate);
|
||||
v8::Local<v8::Promise> handle = shared_promise->GetHandle();
|
||||
|
||||
blink::StorageKey storage_key =
|
||||
blink::StorageKey::CreateFirstParty(url::Origin::Create(scope));
|
||||
service_worker_context_->StartWorkerForScope(
|
||||
scope, storage_key,
|
||||
base::BindOnce(&ServiceWorkerContext::DidStartWorkerForScope,
|
||||
weak_ptr_factory_.GetWeakPtr(), shared_promise),
|
||||
base::BindOnce(&ServiceWorkerContext::DidFailToStartWorkerForScope,
|
||||
weak_ptr_factory_.GetWeakPtr(), shared_promise));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::DidStartWorkerForScope(
|
||||
std::shared_ptr<gin_helper::Promise<v8::Local<v8::Value>>> shared_promise,
|
||||
int64_t version_id,
|
||||
int process_id,
|
||||
int thread_id) {
|
||||
v8::Isolate* isolate = shared_promise->isolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
v8::Local<v8::Value> service_worker_main =
|
||||
GetWorkerFromVersionID(isolate, version_id);
|
||||
shared_promise->Resolve(service_worker_main);
|
||||
shared_promise.reset();
|
||||
}
|
||||
|
||||
void ServiceWorkerContext::DidFailToStartWorkerForScope(
|
||||
std::shared_ptr<gin_helper::Promise<v8::Local<v8::Value>>> shared_promise,
|
||||
content::StatusCodeResponse status) {
|
||||
shared_promise->RejectWithErrorMessage("Failed to start service worker.");
|
||||
shared_promise.reset();
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> ServiceWorkerContext::StopAllWorkers(
|
||||
v8::Isolate* isolate) {
|
||||
auto promise = gin_helper::Promise<void>(isolate);
|
||||
v8::Local<v8::Promise> handle = promise.GetHandle();
|
||||
|
||||
service_worker_context_->StopAllServiceWorkers(base::BindOnce(
|
||||
[](gin_helper::Promise<void> promise) { promise.Resolve(); },
|
||||
std::move(promise)));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<ServiceWorkerContext> ServiceWorkerContext::Create(
|
||||
v8::Isolate* isolate,
|
||||
@@ -153,8 +284,16 @@ gin::ObjectTemplateBuilder ServiceWorkerContext::GetObjectTemplateBuilder(
|
||||
ServiceWorkerContext>::GetObjectTemplateBuilder(isolate)
|
||||
.SetMethod("getAllRunning",
|
||||
&ServiceWorkerContext::GetAllRunningWorkerInfo)
|
||||
.SetMethod("getFromVersionID",
|
||||
&ServiceWorkerContext::GetWorkerInfoFromID);
|
||||
.SetMethod("getFromVersionID", &ServiceWorkerContext::GetFromVersionID)
|
||||
.SetMethod("getInfoFromVersionID",
|
||||
&ServiceWorkerContext::GetInfoFromVersionID)
|
||||
.SetMethod("getWorkerFromVersionID",
|
||||
&ServiceWorkerContext::GetWorkerFromVersionID)
|
||||
.SetMethod("_getWorkerFromVersionIDIfExists",
|
||||
&ServiceWorkerContext::GetWorkerFromVersionIDIfExists)
|
||||
.SetMethod("startWorkerForScope",
|
||||
&ServiceWorkerContext::StartWorkerForScope)
|
||||
.SetMethod("_stopAllWorkers", &ServiceWorkerContext::StopAllWorkers);
|
||||
}
|
||||
|
||||
const char* ServiceWorkerContext::GetTypeName() {
|
||||
|
||||
@@ -10,18 +10,30 @@
|
||||
#include "content/public/browser/service_worker_context_observer.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "third_party/blink/public/common/service_worker/embedded_worker_status.h"
|
||||
|
||||
namespace content {
|
||||
class StoragePartition;
|
||||
}
|
||||
|
||||
namespace gin {
|
||||
template <typename T>
|
||||
class Handle;
|
||||
} // namespace gin
|
||||
|
||||
namespace gin_helper {
|
||||
template <typename T>
|
||||
class Promise;
|
||||
} // namespace gin_helper
|
||||
|
||||
namespace electron {
|
||||
|
||||
class ElectronBrowserContext;
|
||||
|
||||
namespace api {
|
||||
|
||||
class ServiceWorkerMain;
|
||||
|
||||
class ServiceWorkerContext final
|
||||
: public gin::Wrappable<ServiceWorkerContext>,
|
||||
public gin_helper::EventEmitterMixin<ServiceWorkerContext>,
|
||||
@@ -32,14 +44,39 @@ class ServiceWorkerContext final
|
||||
ElectronBrowserContext* browser_context);
|
||||
|
||||
v8::Local<v8::Value> GetAllRunningWorkerInfo(v8::Isolate* isolate);
|
||||
v8::Local<v8::Value> GetWorkerInfoFromID(gin_helper::ErrorThrower thrower,
|
||||
int64_t version_id);
|
||||
v8::Local<v8::Value> GetInfoFromVersionID(gin_helper::ErrorThrower thrower,
|
||||
int64_t version_id);
|
||||
v8::Local<v8::Value> GetFromVersionID(gin_helper::ErrorThrower thrower,
|
||||
int64_t version_id);
|
||||
v8::Local<v8::Value> GetWorkerFromVersionID(v8::Isolate* isolate,
|
||||
int64_t version_id);
|
||||
gin::Handle<ServiceWorkerMain> GetWorkerFromVersionIDIfExists(
|
||||
v8::Isolate* isolate,
|
||||
int64_t version_id);
|
||||
v8::Local<v8::Promise> StartWorkerForScope(v8::Isolate* isolate, GURL scope);
|
||||
void DidStartWorkerForScope(
|
||||
std::shared_ptr<gin_helper::Promise<v8::Local<v8::Value>>> shared_promise,
|
||||
int64_t version_id,
|
||||
int process_id,
|
||||
int thread_id);
|
||||
void DidFailToStartWorkerForScope(
|
||||
std::shared_ptr<gin_helper::Promise<v8::Local<v8::Value>>> shared_promise,
|
||||
content::StatusCodeResponse status);
|
||||
void StopWorkersForScope(GURL scope);
|
||||
v8::Local<v8::Promise> StopAllWorkers(v8::Isolate* isolate);
|
||||
|
||||
// content::ServiceWorkerContextObserver
|
||||
void OnReportConsoleMessage(int64_t version_id,
|
||||
const GURL& scope,
|
||||
const content::ConsoleMessage& message) override;
|
||||
void OnRegistrationCompleted(const GURL& scope) override;
|
||||
void OnVersionStartingRunning(int64_t version_id) override;
|
||||
void OnVersionStartedRunning(
|
||||
int64_t version_id,
|
||||
const content::ServiceWorkerRunningInfo& running_info) override;
|
||||
void OnVersionStoppingRunning(int64_t version_id) override;
|
||||
void OnVersionStoppedRunning(int64_t version_id) override;
|
||||
void OnVersionRedundant(int64_t version_id, const GURL& scope) override;
|
||||
void OnDestruct(content::ServiceWorkerContext* context) override;
|
||||
|
||||
// gin::Wrappable
|
||||
@@ -58,8 +95,15 @@ class ServiceWorkerContext final
|
||||
~ServiceWorkerContext() override;
|
||||
|
||||
private:
|
||||
void OnRunningStatusChanged(int64_t version_id,
|
||||
blink::EmbeddedWorkerStatus running_status);
|
||||
|
||||
raw_ptr<content::ServiceWorkerContext> service_worker_context_;
|
||||
|
||||
// Service worker registration and versions are unique to a storage partition.
|
||||
// Keep a reference to the storage partition to be used for lookups.
|
||||
raw_ptr<content::StoragePartition> storage_partition_;
|
||||
|
||||
base::WeakPtrFactory<ServiceWorkerContext> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
|
||||
359
shell/browser/api/electron_api_service_worker_main.cc
Normal file
359
shell/browser/api/electron_api_service_worker_main.cc
Normal file
@@ -0,0 +1,359 @@
|
||||
// Copyright (c) 2025 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/api/electron_api_service_worker_main.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "content/browser/service_worker/service_worker_context_wrapper.h" // nogncheck
|
||||
#include "content/browser/service_worker/service_worker_version.h" // nogncheck
|
||||
#include "electron/shell/common/api/api.mojom.h"
|
||||
#include "gin/handle.h"
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "services/service_manager/public/cpp/interface_provider.h"
|
||||
#include "shell/browser/api/message_port.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/common/gin_converters/blink_converter.h"
|
||||
#include "shell/common/gin_converters/gurl_converter.h"
|
||||
#include "shell/common/gin_converters/value_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
#include "shell/common/gin_helper/error_thrower.h"
|
||||
#include "shell/common/gin_helper/object_template_builder.h"
|
||||
#include "shell/common/gin_helper/promise.h"
|
||||
#include "shell/common/node_includes.h"
|
||||
#include "shell/common/v8_util.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// Use private API to get the live version of the service worker. This will
|
||||
// exist while in starting, stopping, or stopped running status.
|
||||
content::ServiceWorkerVersion* GetLiveVersion(
|
||||
content::ServiceWorkerContext* service_worker_context,
|
||||
int64_t version_id) {
|
||||
auto* wrapper = static_cast<content::ServiceWorkerContextWrapper*>(
|
||||
service_worker_context);
|
||||
return wrapper->GetLiveVersion(version_id);
|
||||
}
|
||||
|
||||
// Get a public ServiceWorkerVersionBaseInfo object directly from the service
|
||||
// worker.
|
||||
std::optional<content::ServiceWorkerVersionBaseInfo> GetLiveVersionInfo(
|
||||
content::ServiceWorkerContext* service_worker_context,
|
||||
int64_t version_id) {
|
||||
auto* version = GetLiveVersion(service_worker_context, version_id);
|
||||
if (version) {
|
||||
return version->GetInfo();
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
// ServiceWorkerKey -> ServiceWorkerMain*
|
||||
typedef std::unordered_map<ServiceWorkerKey,
|
||||
ServiceWorkerMain*,
|
||||
ServiceWorkerKey::Hasher>
|
||||
VersionIdMap;
|
||||
|
||||
VersionIdMap& GetVersionIdMap() {
|
||||
static base::NoDestructor<VersionIdMap> instance;
|
||||
return *instance;
|
||||
}
|
||||
|
||||
ServiceWorkerMain* FromServiceWorkerKey(const ServiceWorkerKey& key) {
|
||||
VersionIdMap& version_map = GetVersionIdMap();
|
||||
auto iter = version_map.find(key);
|
||||
auto* service_worker = iter == version_map.end() ? nullptr : iter->second;
|
||||
return service_worker;
|
||||
}
|
||||
|
||||
// static
|
||||
ServiceWorkerMain* ServiceWorkerMain::FromVersionID(
|
||||
int64_t version_id,
|
||||
const content::StoragePartition* storage_partition) {
|
||||
ServiceWorkerKey key(version_id, storage_partition);
|
||||
return FromServiceWorkerKey(key);
|
||||
}
|
||||
|
||||
gin::WrapperInfo ServiceWorkerMain::kWrapperInfo = {gin::kEmbedderNativeGin};
|
||||
|
||||
ServiceWorkerMain::ServiceWorkerMain(content::ServiceWorkerContext* sw_context,
|
||||
int64_t version_id,
|
||||
const ServiceWorkerKey& key)
|
||||
: version_id_(version_id), key_(key), service_worker_context_(sw_context) {
|
||||
GetVersionIdMap().emplace(key_, this);
|
||||
InvalidateVersionInfo();
|
||||
}
|
||||
|
||||
ServiceWorkerMain::~ServiceWorkerMain() {
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void ServiceWorkerMain::Destroy() {
|
||||
version_destroyed_ = true;
|
||||
InvalidateVersionInfo();
|
||||
MaybeDisconnectRemote();
|
||||
GetVersionIdMap().erase(key_);
|
||||
Unpin();
|
||||
}
|
||||
|
||||
void ServiceWorkerMain::MaybeDisconnectRemote() {
|
||||
if (remote_.is_bound() &&
|
||||
(version_destroyed_ ||
|
||||
(!service_worker_context_->IsLiveStartingServiceWorker(version_id_) &&
|
||||
!service_worker_context_->IsLiveRunningServiceWorker(version_id_)))) {
|
||||
remote_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
mojom::ElectronRenderer* ServiceWorkerMain::GetRendererApi() {
|
||||
if (!remote_.is_bound()) {
|
||||
if (!service_worker_context_->IsLiveRunningServiceWorker(version_id_)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
service_worker_context_->GetRemoteAssociatedInterfaces(version_id_)
|
||||
.GetInterface(&remote_);
|
||||
}
|
||||
return remote_.get();
|
||||
}
|
||||
|
||||
void ServiceWorkerMain::Send(v8::Isolate* isolate,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
v8::Local<v8::Value> args) {
|
||||
blink::CloneableMessage message;
|
||||
if (!gin::ConvertFromV8(isolate, args, &message)) {
|
||||
isolate->ThrowException(v8::Exception::Error(
|
||||
gin::StringToV8(isolate, "Failed to serialize arguments")));
|
||||
return;
|
||||
}
|
||||
|
||||
auto* renderer_api_remote = GetRendererApi();
|
||||
if (!renderer_api_remote) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderer_api_remote->Message(internal, channel, std::move(message));
|
||||
}
|
||||
|
||||
void ServiceWorkerMain::InvalidateVersionInfo() {
|
||||
if (version_info_ != nullptr) {
|
||||
version_info_.reset();
|
||||
}
|
||||
|
||||
if (version_destroyed_)
|
||||
return;
|
||||
|
||||
auto version_info = GetLiveVersionInfo(service_worker_context_, version_id_);
|
||||
if (version_info) {
|
||||
version_info_ =
|
||||
std::make_unique<content::ServiceWorkerVersionBaseInfo>(*version_info);
|
||||
} else {
|
||||
// When ServiceWorkerContextCore::RemoveLiveVersion is called, it posts a
|
||||
// task to notify that the service worker has stopped. At this point, the
|
||||
// live version will no longer exist.
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceWorkerMain::OnRunningStatusChanged(
|
||||
blink::EmbeddedWorkerStatus running_status) {
|
||||
// Disconnect remote when content::ServiceWorkerHost has terminated.
|
||||
MaybeDisconnectRemote();
|
||||
|
||||
InvalidateVersionInfo();
|
||||
|
||||
// Redundant worker has been marked for deletion. Now that it's stopped, let's
|
||||
// destroy our wrapper.
|
||||
if (redundant_ && running_status == blink::EmbeddedWorkerStatus::kStopped) {
|
||||
Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void ServiceWorkerMain::OnVersionRedundant() {
|
||||
// Redundant service workers have been either unregistered or replaced. A new
|
||||
// ServiceWorkerMain will need to be created.
|
||||
// Set internal state to mark it for deletion once it has fully stopped.
|
||||
redundant_ = true;
|
||||
}
|
||||
|
||||
bool ServiceWorkerMain::IsDestroyed() const {
|
||||
return version_destroyed_;
|
||||
}
|
||||
|
||||
const blink::StorageKey ServiceWorkerMain::GetStorageKey() {
|
||||
GURL scope = version_info_ ? version_info()->scope : GURL::EmptyGURL();
|
||||
return blink::StorageKey::CreateFirstParty(url::Origin::Create(scope));
|
||||
}
|
||||
|
||||
gin_helper::Dictionary ServiceWorkerMain::StartExternalRequest(
|
||||
v8::Isolate* isolate,
|
||||
bool has_timeout) {
|
||||
auto details = gin_helper::Dictionary::CreateEmpty(isolate);
|
||||
|
||||
if (version_destroyed_) {
|
||||
isolate->ThrowException(v8::Exception::TypeError(
|
||||
gin::StringToV8(isolate, "ServiceWorkerMain is destroyed")));
|
||||
return details;
|
||||
}
|
||||
|
||||
auto request_uuid = base::Uuid::GenerateRandomV4();
|
||||
auto timeout_type =
|
||||
has_timeout
|
||||
? content::ServiceWorkerExternalRequestTimeoutType::kDefault
|
||||
: content::ServiceWorkerExternalRequestTimeoutType::kDoesNotTimeout;
|
||||
|
||||
content::ServiceWorkerExternalRequestResult start_result =
|
||||
service_worker_context_->StartingExternalRequest(
|
||||
version_id_, timeout_type, request_uuid);
|
||||
|
||||
details.Set("id", request_uuid.AsLowercaseString());
|
||||
details.Set("ok",
|
||||
start_result == content::ServiceWorkerExternalRequestResult::kOk);
|
||||
|
||||
return details;
|
||||
}
|
||||
|
||||
void ServiceWorkerMain::FinishExternalRequest(v8::Isolate* isolate,
|
||||
std::string uuid) {
|
||||
base::Uuid request_uuid = base::Uuid::ParseLowercase(uuid);
|
||||
if (!request_uuid.is_valid()) {
|
||||
isolate->ThrowException(v8::Exception::TypeError(
|
||||
gin::StringToV8(isolate, "Invalid external request UUID")));
|
||||
return;
|
||||
}
|
||||
|
||||
DCHECK(service_worker_context_);
|
||||
if (!service_worker_context_)
|
||||
return;
|
||||
|
||||
content::ServiceWorkerExternalRequestResult result =
|
||||
service_worker_context_->FinishedExternalRequest(version_id_,
|
||||
request_uuid);
|
||||
|
||||
std::string error;
|
||||
switch (result) {
|
||||
case content::ServiceWorkerExternalRequestResult::kOk:
|
||||
break;
|
||||
case content::ServiceWorkerExternalRequestResult::kBadRequestId:
|
||||
error = "Unknown external request UUID";
|
||||
break;
|
||||
case content::ServiceWorkerExternalRequestResult::kWorkerNotRunning:
|
||||
error = "Service worker is no longer running";
|
||||
break;
|
||||
case content::ServiceWorkerExternalRequestResult::kWorkerNotFound:
|
||||
error = "Service worker was not found";
|
||||
break;
|
||||
case content::ServiceWorkerExternalRequestResult::kNullContext:
|
||||
default:
|
||||
error = "Service worker context is unavailable and may be shutting down";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!error.empty()) {
|
||||
isolate->ThrowException(
|
||||
v8::Exception::TypeError(gin::StringToV8(isolate, error)));
|
||||
}
|
||||
}
|
||||
|
||||
size_t ServiceWorkerMain::CountExternalRequestsForTest() {
|
||||
if (version_destroyed_)
|
||||
return 0;
|
||||
auto& storage_key = GetStorageKey();
|
||||
return service_worker_context_->CountExternalRequestsForTest(storage_key);
|
||||
}
|
||||
|
||||
int64_t ServiceWorkerMain::VersionID() const {
|
||||
return version_id_;
|
||||
}
|
||||
|
||||
GURL ServiceWorkerMain::ScopeURL() const {
|
||||
if (version_destroyed_)
|
||||
return GURL::EmptyGURL();
|
||||
return version_info()->scope;
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<ServiceWorkerMain> ServiceWorkerMain::New(v8::Isolate* isolate) {
|
||||
return gin::Handle<ServiceWorkerMain>();
|
||||
}
|
||||
|
||||
// static
|
||||
gin::Handle<ServiceWorkerMain> ServiceWorkerMain::From(
|
||||
v8::Isolate* isolate,
|
||||
content::ServiceWorkerContext* sw_context,
|
||||
const content::StoragePartition* storage_partition,
|
||||
int64_t version_id) {
|
||||
ServiceWorkerKey service_worker_key(version_id, storage_partition);
|
||||
|
||||
auto* service_worker = FromServiceWorkerKey(service_worker_key);
|
||||
if (service_worker)
|
||||
return gin::CreateHandle(isolate, service_worker);
|
||||
|
||||
// Ensure ServiceWorkerVersion exists and is not redundant (pending deletion)
|
||||
auto* live_version = GetLiveVersion(sw_context, version_id);
|
||||
if (!live_version || live_version->is_redundant()) {
|
||||
return gin::Handle<ServiceWorkerMain>();
|
||||
}
|
||||
|
||||
auto handle = gin::CreateHandle(
|
||||
isolate,
|
||||
new ServiceWorkerMain(sw_context, version_id, service_worker_key));
|
||||
|
||||
// Prevent garbage collection of worker until it has been deleted internally.
|
||||
handle->Pin(isolate);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
// static
|
||||
void ServiceWorkerMain::FillObjectTemplate(
|
||||
v8::Isolate* isolate,
|
||||
v8::Local<v8::ObjectTemplate> templ) {
|
||||
gin_helper::ObjectTemplateBuilder(isolate, templ)
|
||||
.SetMethod("_send", &ServiceWorkerMain::Send)
|
||||
.SetMethod("isDestroyed", &ServiceWorkerMain::IsDestroyed)
|
||||
.SetMethod("_startExternalRequest",
|
||||
&ServiceWorkerMain::StartExternalRequest)
|
||||
.SetMethod("_finishExternalRequest",
|
||||
&ServiceWorkerMain::FinishExternalRequest)
|
||||
.SetMethod("_countExternalRequests",
|
||||
&ServiceWorkerMain::CountExternalRequestsForTest)
|
||||
.SetProperty("versionId", &ServiceWorkerMain::VersionID)
|
||||
.SetProperty("scope", &ServiceWorkerMain::ScopeURL)
|
||||
.Build();
|
||||
}
|
||||
|
||||
const char* ServiceWorkerMain::GetTypeName() {
|
||||
return GetClassName();
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
namespace {
|
||||
|
||||
using electron::api::ServiceWorkerMain;
|
||||
|
||||
void Initialize(v8::Local<v8::Object> exports,
|
||||
v8::Local<v8::Value> unused,
|
||||
v8::Local<v8::Context> context,
|
||||
void* priv) {
|
||||
v8::Isolate* isolate = context->GetIsolate();
|
||||
gin_helper::Dictionary dict(isolate, exports);
|
||||
dict.Set("ServiceWorkerMain", ServiceWorkerMain::GetConstructor(context));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_service_worker_main,
|
||||
Initialize)
|
||||
178
shell/browser/api/electron_api_service_worker_main.h
Normal file
178
shell/browser/api/electron_api_service_worker_main.h
Normal file
@@ -0,0 +1,178 @@
|
||||
// Copyright (c) 2025 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_SERVICE_WORKER_MAIN_H_
|
||||
#define ELECTRON_SHELL_BROWSER_API_ELECTRON_API_SERVICE_WORKER_MAIN_H_
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/process/process.h"
|
||||
#include "content/public/browser/global_routing_id.h"
|
||||
#include "content/public/browser/service_worker_context.h"
|
||||
#include "content/public/browser/service_worker_version_base_info.h"
|
||||
#include "gin/wrappable.h"
|
||||
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/associated_remote.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/common/api/api.mojom.h"
|
||||
#include "shell/common/gin_helper/constructible.h"
|
||||
#include "shell/common/gin_helper/pinnable.h"
|
||||
#include "third_party/blink/public/common/service_worker/embedded_worker_status.h"
|
||||
|
||||
class GURL;
|
||||
|
||||
namespace content {
|
||||
class StoragePartition;
|
||||
}
|
||||
|
||||
namespace gin {
|
||||
class Arguments;
|
||||
} // namespace gin
|
||||
|
||||
namespace gin_helper {
|
||||
class Dictionary;
|
||||
template <typename T>
|
||||
class Handle;
|
||||
template <typename T>
|
||||
class Promise;
|
||||
} // namespace gin_helper
|
||||
|
||||
namespace electron::api {
|
||||
|
||||
// Key to uniquely identify a ServiceWorkerMain by its Version ID within the
|
||||
// associated StoragePartition.
|
||||
struct ServiceWorkerKey {
|
||||
int64_t version_id;
|
||||
raw_ptr<const content::StoragePartition> storage_partition;
|
||||
|
||||
ServiceWorkerKey(int64_t id, const content::StoragePartition* partition)
|
||||
: version_id(id), storage_partition(partition) {}
|
||||
|
||||
bool operator<(const ServiceWorkerKey& other) const {
|
||||
return std::tie(version_id, storage_partition) <
|
||||
std::tie(other.version_id, other.storage_partition);
|
||||
}
|
||||
|
||||
bool operator==(const ServiceWorkerKey& other) const {
|
||||
return version_id == other.version_id &&
|
||||
storage_partition == other.storage_partition;
|
||||
}
|
||||
|
||||
struct Hasher {
|
||||
std::size_t operator()(const ServiceWorkerKey& key) const {
|
||||
return std::hash<const content::StoragePartition*>()(
|
||||
key.storage_partition) ^
|
||||
std::hash<int64_t>()(key.version_id);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// Creates a wrapper to align with the lifecycle of the non-public
|
||||
// content::ServiceWorkerVersion. Object instances are pinned for the lifetime
|
||||
// of the underlying SW such that registered IPC handlers continue to dispatch.
|
||||
//
|
||||
// Instances are uniquely identified by pairing their version ID and the
|
||||
// StoragePartition in which they're registered. In Electron, this is always
|
||||
// the default StoragePartition for the associated BrowserContext.
|
||||
class ServiceWorkerMain final
|
||||
: public gin::Wrappable<ServiceWorkerMain>,
|
||||
public gin_helper::EventEmitterMixin<ServiceWorkerMain>,
|
||||
public gin_helper::Pinnable<ServiceWorkerMain>,
|
||||
public gin_helper::Constructible<ServiceWorkerMain> {
|
||||
public:
|
||||
// Create a new ServiceWorkerMain and return the V8 wrapper of it.
|
||||
static gin::Handle<ServiceWorkerMain> New(v8::Isolate* isolate);
|
||||
|
||||
static gin::Handle<ServiceWorkerMain> From(
|
||||
v8::Isolate* isolate,
|
||||
content::ServiceWorkerContext* sw_context,
|
||||
const content::StoragePartition* storage_partition,
|
||||
int64_t version_id);
|
||||
static ServiceWorkerMain* FromVersionID(
|
||||
int64_t version_id,
|
||||
const content::StoragePartition* storage_partition);
|
||||
|
||||
// gin_helper::Constructible
|
||||
static void FillObjectTemplate(v8::Isolate*, v8::Local<v8::ObjectTemplate>);
|
||||
static const char* GetClassName() { return "ServiceWorkerMain"; }
|
||||
|
||||
// gin::Wrappable
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
// disable copy
|
||||
ServiceWorkerMain(const ServiceWorkerMain&) = delete;
|
||||
ServiceWorkerMain& operator=(const ServiceWorkerMain&) = delete;
|
||||
|
||||
void OnRunningStatusChanged(blink::EmbeddedWorkerStatus running_status);
|
||||
void OnVersionRedundant();
|
||||
|
||||
protected:
|
||||
explicit ServiceWorkerMain(content::ServiceWorkerContext* sw_context,
|
||||
int64_t version_id,
|
||||
const ServiceWorkerKey& key);
|
||||
~ServiceWorkerMain() override;
|
||||
|
||||
private:
|
||||
void Destroy();
|
||||
void MaybeDisconnectRemote();
|
||||
const blink::StorageKey GetStorageKey();
|
||||
|
||||
// Increments external requests for the service worker to keep it alive.
|
||||
gin_helper::Dictionary StartExternalRequest(v8::Isolate* isolate,
|
||||
bool has_timeout);
|
||||
void FinishExternalRequest(v8::Isolate* isolate, std::string uuid);
|
||||
size_t CountExternalRequestsForTest();
|
||||
|
||||
// Get or create a Mojo connection to the renderer process.
|
||||
mojom::ElectronRenderer* GetRendererApi();
|
||||
|
||||
// Send a message to the renderer process.
|
||||
void Send(v8::Isolate* isolate,
|
||||
bool internal,
|
||||
const std::string& channel,
|
||||
v8::Local<v8::Value> args);
|
||||
|
||||
void InvalidateVersionInfo();
|
||||
const content::ServiceWorkerVersionBaseInfo* version_info() const {
|
||||
return version_info_.get();
|
||||
}
|
||||
|
||||
bool IsDestroyed() const;
|
||||
|
||||
int64_t VersionID() const;
|
||||
GURL ScopeURL() const;
|
||||
|
||||
// Version ID unique only to the StoragePartition.
|
||||
int64_t version_id_;
|
||||
|
||||
// Unique identifier pairing the Version ID and StoragePartition.
|
||||
ServiceWorkerKey key_;
|
||||
|
||||
// Whether the Service Worker version has been destroyed.
|
||||
bool version_destroyed_ = false;
|
||||
|
||||
// Whether the Service Worker version's state is redundant.
|
||||
bool redundant_ = false;
|
||||
|
||||
// Store copy of version info so it's accessible when not running.
|
||||
std::unique_ptr<content::ServiceWorkerVersionBaseInfo> version_info_;
|
||||
|
||||
raw_ptr<content::ServiceWorkerContext> service_worker_context_;
|
||||
mojo::AssociatedRemote<mojom::ElectronRenderer> remote_;
|
||||
|
||||
std::unique_ptr<gin_helper::Promise<void>> start_worker_promise_;
|
||||
|
||||
base::WeakPtrFactory<ServiceWorkerMain> weak_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_API_ELECTRON_API_SERVICE_WORKER_MAIN_H_
|
||||
@@ -1065,16 +1065,72 @@ void Session::CreateInterruptedDownload(const gin_helper::Dictionary& options) {
|
||||
base::Time::FromSecondsSinceUnixEpoch(start_time)));
|
||||
}
|
||||
|
||||
void Session::SetPreloads(const std::vector<base::FilePath>& preloads) {
|
||||
std::string Session::RegisterPreloadScript(
|
||||
gin_helper::ErrorThrower thrower,
|
||||
const PreloadScript& new_preload_script) {
|
||||
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
|
||||
DCHECK(prefs);
|
||||
prefs->set_preloads(preloads);
|
||||
|
||||
auto& preload_scripts = prefs->preload_scripts();
|
||||
|
||||
auto it = std::find_if(preload_scripts.begin(), preload_scripts.end(),
|
||||
[&new_preload_script](const PreloadScript& script) {
|
||||
return script.id == new_preload_script.id;
|
||||
});
|
||||
|
||||
if (it != preload_scripts.end()) {
|
||||
thrower.ThrowError(base::StringPrintf(
|
||||
"Cannot register preload script with existing ID '%s'",
|
||||
new_preload_script.id.c_str()));
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!new_preload_script.file_path.IsAbsolute()) {
|
||||
// Deprecated preload scripts logged error without throwing.
|
||||
if (new_preload_script.deprecated) {
|
||||
LOG(ERROR) << "preload script must have absolute path: "
|
||||
<< new_preload_script.file_path;
|
||||
} else {
|
||||
thrower.ThrowError(
|
||||
base::StringPrintf("Preload script must have absolute path: %s",
|
||||
new_preload_script.file_path.value().c_str()));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
preload_scripts.push_back(new_preload_script);
|
||||
return new_preload_script.id;
|
||||
}
|
||||
|
||||
std::vector<base::FilePath> Session::GetPreloads() const {
|
||||
void Session::UnregisterPreloadScript(gin_helper::ErrorThrower thrower,
|
||||
const std::string& script_id) {
|
||||
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
|
||||
DCHECK(prefs);
|
||||
return prefs->preloads();
|
||||
|
||||
auto& preload_scripts = prefs->preload_scripts();
|
||||
|
||||
// Find the preload script by its ID
|
||||
auto it = std::find_if(preload_scripts.begin(), preload_scripts.end(),
|
||||
[&script_id](const PreloadScript& script) {
|
||||
return script.id == script_id;
|
||||
});
|
||||
|
||||
// If the script is found, erase it from the vector
|
||||
if (it != preload_scripts.end()) {
|
||||
preload_scripts.erase(it);
|
||||
return;
|
||||
}
|
||||
|
||||
// If the script is not found, throw an error
|
||||
thrower.ThrowError(base::StringPrintf(
|
||||
"Cannot unregister preload script with non-existing ID '%s'",
|
||||
script_id.c_str()));
|
||||
}
|
||||
|
||||
std::vector<PreloadScript> Session::GetPreloadScripts() const {
|
||||
auto* prefs = SessionPreferences::FromBrowserContext(browser_context());
|
||||
DCHECK(prefs);
|
||||
return prefs->preload_scripts();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1800,8 +1856,9 @@ void Session::FillObjectTemplate(v8::Isolate* isolate,
|
||||
.SetMethod("downloadURL", &Session::DownloadURL)
|
||||
.SetMethod("createInterruptedDownload",
|
||||
&Session::CreateInterruptedDownload)
|
||||
.SetMethod("setPreloads", &Session::SetPreloads)
|
||||
.SetMethod("getPreloads", &Session::GetPreloads)
|
||||
.SetMethod("registerPreloadScript", &Session::RegisterPreloadScript)
|
||||
.SetMethod("unregisterPreloadScript", &Session::UnregisterPreloadScript)
|
||||
.SetMethod("getPreloadScripts", &Session::GetPreloadScripts)
|
||||
.SetMethod("getSharedDictionaryUsageInfo",
|
||||
&Session::GetSharedDictionaryUsageInfo)
|
||||
.SetMethod("getSharedDictionaryInfo", &Session::GetSharedDictionaryInfo)
|
||||
@@ -1852,6 +1909,10 @@ const char* Session::GetTypeName() {
|
||||
return GetClassName();
|
||||
}
|
||||
|
||||
void Session::WillBeDestroyed() {
|
||||
ClearWeak();
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -57,6 +57,7 @@ class ProxyConfig;
|
||||
namespace electron {
|
||||
|
||||
class ElectronBrowserContext;
|
||||
struct PreloadScript;
|
||||
|
||||
namespace api {
|
||||
|
||||
@@ -102,6 +103,9 @@ class Session final : public gin::Wrappable<Session>,
|
||||
static const char* GetClassName() { return "Session"; }
|
||||
const char* GetTypeName() override;
|
||||
|
||||
// gin_helper::CleanedUpAtExit
|
||||
void WillBeDestroyed() override;
|
||||
|
||||
// Methods.
|
||||
v8::Local<v8::Promise> ResolveHost(
|
||||
std::string host,
|
||||
@@ -138,8 +142,11 @@ class Session final : public gin::Wrappable<Session>,
|
||||
const std::string& uuid);
|
||||
void DownloadURL(const GURL& url, gin::Arguments* args);
|
||||
void CreateInterruptedDownload(const gin_helper::Dictionary& options);
|
||||
void SetPreloads(const std::vector<base::FilePath>& preloads);
|
||||
std::vector<base::FilePath> GetPreloads() const;
|
||||
std::string RegisterPreloadScript(gin_helper::ErrorThrower thrower,
|
||||
const PreloadScript& new_preload_script);
|
||||
void UnregisterPreloadScript(gin_helper::ErrorThrower thrower,
|
||||
const std::string& script_id);
|
||||
std::vector<PreloadScript> GetPreloadScripts() const;
|
||||
v8::Local<v8::Promise> GetSharedDictionaryInfo(
|
||||
const gin_helper::Dictionary& options);
|
||||
v8::Local<v8::Promise> GetSharedDictionaryUsageInfo();
|
||||
|
||||
@@ -431,6 +431,10 @@ const char* Tray::GetTypeName() {
|
||||
return GetClassName();
|
||||
}
|
||||
|
||||
void Tray::WillBeDestroyed() {
|
||||
ClearWeak();
|
||||
}
|
||||
|
||||
} // namespace electron::api
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -58,6 +58,9 @@ class Tray final : public gin::Wrappable<Tray>,
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
// gin_helper::CleanedUpAtExit
|
||||
void WillBeDestroyed() override;
|
||||
|
||||
// disable copy
|
||||
Tray(const Tray&) = delete;
|
||||
Tray& operator=(const Tray&) = delete;
|
||||
|
||||
@@ -3757,16 +3757,15 @@ void WebContents::DoGetZoomLevel(
|
||||
std::move(callback).Run(GetZoomLevel());
|
||||
}
|
||||
|
||||
std::vector<base::FilePath> WebContents::GetPreloadPaths() const {
|
||||
auto result = SessionPreferences::GetValidPreloads(GetBrowserContext());
|
||||
|
||||
std::optional<PreloadScript> WebContents::GetPreloadScript() const {
|
||||
if (auto* web_preferences = WebContentsPreferences::From(web_contents())) {
|
||||
if (auto preload = web_preferences->GetPreloadPath()) {
|
||||
result.emplace_back(*preload);
|
||||
auto preload_script = PreloadScript{
|
||||
"", PreloadScript::ScriptType::kWebFrame, preload.value()};
|
||||
return preload_script;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> WebContents::GetLastWebPreferences(
|
||||
@@ -4520,7 +4519,7 @@ void WebContents::FillObjectTemplate(v8::Isolate* isolate,
|
||||
.SetMethod("setZoomFactor", &WebContents::SetZoomFactor)
|
||||
.SetMethod("getZoomFactor", &WebContents::GetZoomFactor)
|
||||
.SetMethod("getType", &WebContents::type)
|
||||
.SetMethod("_getPreloadPaths", &WebContents::GetPreloadPaths)
|
||||
.SetMethod("_getPreloadScript", &WebContents::GetPreloadScript)
|
||||
.SetMethod("getLastWebPreferences", &WebContents::GetLastWebPreferences)
|
||||
.SetMethod("getOwnerBrowserWindow", &WebContents::GetOwnerBrowserWindow)
|
||||
.SetMethod("inspectServiceWorker", &WebContents::InspectServiceWorker)
|
||||
@@ -4570,6 +4569,10 @@ const char* WebContents::GetTypeName() {
|
||||
return GetClassName();
|
||||
}
|
||||
|
||||
void WebContents::WillBeDestroyed() {
|
||||
ClearWeak();
|
||||
}
|
||||
|
||||
ElectronBrowserContext* WebContents::GetBrowserContext() const {
|
||||
return static_cast<ElectronBrowserContext*>(
|
||||
web_contents()->GetBrowserContext());
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "shell/browser/event_emitter_mixin.h"
|
||||
#include "shell/browser/extended_web_contents_observer.h"
|
||||
#include "shell/browser/osr/osr_paint_event.h"
|
||||
#include "shell/browser/preload_script.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_delegate.h"
|
||||
#include "shell/browser/ui/inspectable_web_contents_view_delegate.h"
|
||||
#include "shell/common/gin_helper/cleaned_up_at_exit.h"
|
||||
@@ -179,6 +180,9 @@ class WebContents final : public ExclusiveAccessContext,
|
||||
static gin::WrapperInfo kWrapperInfo;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
// gin_helper::CleanedUpAtExit
|
||||
void WillBeDestroyed() override;
|
||||
|
||||
void Destroy();
|
||||
void Close(std::optional<gin_helper::Dictionary> options);
|
||||
base::WeakPtr<WebContents> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
|
||||
@@ -341,8 +345,8 @@ class WebContents final : public ExclusiveAccessContext,
|
||||
const std::string& features,
|
||||
const scoped_refptr<network::ResourceRequestBody>& body);
|
||||
|
||||
// Returns the preload script path of current WebContents.
|
||||
std::vector<base::FilePath> GetPreloadPaths() const;
|
||||
// Returns the preload script of current WebContents.
|
||||
std::optional<PreloadScript> GetPreloadScript() const;
|
||||
|
||||
// Returns the web preferences of current WebContents.
|
||||
v8::Local<v8::Value> GetLastWebPreferences(v8::Isolate* isolate) const;
|
||||
|
||||
@@ -306,6 +306,10 @@ const char* MessagePort::GetTypeName() {
|
||||
return "MessagePort";
|
||||
}
|
||||
|
||||
void MessagePort::WillBeDestroyed() {
|
||||
ClearWeak();
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -61,6 +61,9 @@ class MessagePort final : public gin::Wrappable<MessagePort>,
|
||||
v8::Isolate* isolate) override;
|
||||
const char* GetTypeName() override;
|
||||
|
||||
// gin_helper::CleanedUpAtExit
|
||||
void WillBeDestroyed() override;
|
||||
|
||||
private:
|
||||
MessagePort();
|
||||
|
||||
|
||||
@@ -458,10 +458,6 @@ void ElectronBrowserContext::InitPrefs() {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Unique uuid for global shortcuts.
|
||||
registry->RegisterStringPref(electron::kElectronGlobalShortcutsUuid,
|
||||
std::string());
|
||||
}
|
||||
|
||||
void ElectronBrowserContext::SetUserAgent(const std::string& user_agent) {
|
||||
|
||||
@@ -132,11 +132,16 @@ v8::Isolate* JavascriptEnvironment::GetIsolate() {
|
||||
void JavascriptEnvironment::CreateMicrotasksRunner() {
|
||||
DCHECK(!microtasks_runner_);
|
||||
microtasks_runner_ = std::make_unique<MicrotasksRunner>(isolate());
|
||||
isolate_holder_.WillCreateMicrotasksRunner();
|
||||
base::CurrentThread::Get()->AddTaskObserver(microtasks_runner_.get());
|
||||
}
|
||||
|
||||
void JavascriptEnvironment::DestroyMicrotasksRunner() {
|
||||
DCHECK(microtasks_runner_);
|
||||
// Should be called before running gin_helper::CleanedUpAtExit::DoCleanup.
|
||||
// This helps to signal wrappable finalizer callbacks to not act on freed
|
||||
// parameters.
|
||||
isolate_holder_.WillDestroyMicrotasksRunner();
|
||||
{
|
||||
v8::HandleScope scope(isolate_);
|
||||
gin_helper::CleanedUpAtExit::DoCleanup();
|
||||
|
||||
104
shell/browser/preload_script.h
Normal file
104
shell/browser/preload_script.h
Normal file
@@ -0,0 +1,104 @@
|
||||
// Copyright (c) 2025 Salesforce, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_PRELOAD_SCRIPT_H_
|
||||
#define ELECTRON_SHELL_BROWSER_PRELOAD_SCRIPT_H_
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include "base/containers/fixed_flat_map.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/uuid.h"
|
||||
#include "gin/converter.h"
|
||||
#include "shell/common/gin_converters/file_path_converter.h"
|
||||
#include "shell/common/gin_helper/dictionary.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
struct PreloadScript {
|
||||
enum class ScriptType { kWebFrame, kServiceWorker };
|
||||
|
||||
std::string id;
|
||||
ScriptType script_type;
|
||||
base::FilePath file_path;
|
||||
|
||||
// If set, use the deprecated validation behavior of Session.setPreloads
|
||||
bool deprecated = false;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
namespace gin {
|
||||
|
||||
using electron::PreloadScript;
|
||||
|
||||
template <>
|
||||
struct Converter<PreloadScript::ScriptType> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const PreloadScript::ScriptType& in) {
|
||||
using Val = PreloadScript::ScriptType;
|
||||
static constexpr auto Lookup =
|
||||
base::MakeFixedFlatMap<Val, std::string_view>({
|
||||
{Val::kWebFrame, "frame"},
|
||||
{Val::kServiceWorker, "service-worker"},
|
||||
});
|
||||
return StringToV8(isolate, Lookup.at(in));
|
||||
}
|
||||
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
PreloadScript::ScriptType* out) {
|
||||
using Val = PreloadScript::ScriptType;
|
||||
static constexpr auto Lookup =
|
||||
base::MakeFixedFlatMap<std::string_view, Val>({
|
||||
{"frame", Val::kWebFrame},
|
||||
{"service-worker", Val::kServiceWorker},
|
||||
});
|
||||
return FromV8WithLookup(isolate, val, Lookup, out);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct Converter<PreloadScript> {
|
||||
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
|
||||
const PreloadScript& script) {
|
||||
gin::Dictionary dict(isolate, v8::Object::New(isolate));
|
||||
dict.Set("filePath", script.file_path.AsUTF8Unsafe());
|
||||
dict.Set("id", script.id);
|
||||
dict.Set("type", script.script_type);
|
||||
return ConvertToV8(isolate, dict).As<v8::Object>();
|
||||
}
|
||||
|
||||
static bool FromV8(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> val,
|
||||
PreloadScript* out) {
|
||||
gin_helper::Dictionary options;
|
||||
if (!ConvertFromV8(isolate, val, &options))
|
||||
return false;
|
||||
if (PreloadScript::ScriptType script_type;
|
||||
options.Get("type", &script_type)) {
|
||||
out->script_type = script_type;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (base::FilePath file_path; options.Get("filePath", &file_path)) {
|
||||
out->file_path = file_path;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (std::string id; options.Get("id", &id)) {
|
||||
out->id = id;
|
||||
} else {
|
||||
out->id = base::Uuid::GenerateRandomV4().AsLowercaseString();
|
||||
}
|
||||
if (bool deprecated; options.Get("_deprecated", &deprecated)) {
|
||||
out->deprecated = deprecated;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gin
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_PRELOAD_SCRIPT_H_
|
||||
@@ -64,5 +64,7 @@
|
||||
<string>${DEFAULT_APP_ASAR_HEADER_SHA}</string>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>NSPrefersDisplaySafeAreaCompatibilityMode</key>
|
||||
<false/>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -30,22 +30,4 @@ SessionPreferences* SessionPreferences::FromBrowserContext(
|
||||
return static_cast<SessionPreferences*>(context->GetUserData(&kLocatorKey));
|
||||
}
|
||||
|
||||
// static
|
||||
std::vector<base::FilePath> SessionPreferences::GetValidPreloads(
|
||||
content::BrowserContext* context) {
|
||||
std::vector<base::FilePath> result;
|
||||
|
||||
if (auto* self = FromBrowserContext(context)) {
|
||||
for (const auto& preload : self->preloads()) {
|
||||
if (preload.IsAbsolute()) {
|
||||
result.emplace_back(preload);
|
||||
} else {
|
||||
LOG(ERROR) << "preload script must have absolute path: " << preload;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/supports_user_data.h"
|
||||
#include "shell/browser/preload_script.h"
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
@@ -20,17 +21,12 @@ class SessionPreferences : public base::SupportsUserData::Data {
|
||||
public:
|
||||
static SessionPreferences* FromBrowserContext(
|
||||
content::BrowserContext* context);
|
||||
static std::vector<base::FilePath> GetValidPreloads(
|
||||
content::BrowserContext* context);
|
||||
|
||||
static void CreateForBrowserContext(content::BrowserContext* context);
|
||||
|
||||
~SessionPreferences() override;
|
||||
|
||||
void set_preloads(const std::vector<base::FilePath>& preloads) {
|
||||
preloads_ = preloads;
|
||||
}
|
||||
const std::vector<base::FilePath>& preloads() const { return preloads_; }
|
||||
std::vector<PreloadScript>& preload_scripts() { return preload_scripts_; }
|
||||
|
||||
private:
|
||||
SessionPreferences();
|
||||
@@ -38,7 +34,7 @@ class SessionPreferences : public base::SupportsUserData::Data {
|
||||
// The user data key.
|
||||
static int kLocatorKey;
|
||||
|
||||
std::vector<base::FilePath> preloads_;
|
||||
std::vector<PreloadScript> preload_scripts_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user