mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
477fe8566e | ||
|
|
a9837ed476 | ||
|
|
1f7269f482 | ||
|
|
2813b89824 | ||
|
|
a4560db9f0 | ||
|
|
adfc062313 | ||
|
|
8dc34b4b25 | ||
|
|
6cc5ad763d | ||
|
|
4c5637c687 | ||
|
|
0d71ed0f29 | ||
|
|
fc63000ee7 | ||
|
|
8d41dbe65f | ||
|
|
f3b90cc91c | ||
|
|
a78a8cd30c | ||
|
|
2511f78120 | ||
|
|
f711af1080 | ||
|
|
616026ce1c | ||
|
|
ada2c4e072 | ||
|
|
1a76e35971 | ||
|
|
3d475716f4 | ||
|
|
c7a033dd06 | ||
|
|
2ff6e7e042 | ||
|
|
3302c4dbd8 | ||
|
|
76ce7a7ca0 | ||
|
|
4237bcbc4c | ||
|
|
c81c505fea | ||
|
|
638dd2221a | ||
|
|
8ec629e871 | ||
|
|
ba487e914d | ||
|
|
4cd269a752 | ||
|
|
201be32e0f | ||
|
|
11f60f3520 | ||
|
|
530c16aab5 | ||
|
|
e0a61a58ef |
8
.github/actions/build-electron/action.yml
vendored
8
.github/actions/build-electron/action.yml
vendored
@@ -95,7 +95,7 @@ runs:
|
||||
# Upload build stats to Datadog
|
||||
if ($env:DD_API_KEY) {
|
||||
try {
|
||||
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats
|
||||
npx node electron\script\build-stats.mjs out\Default\siso.exe.INFO --upload-stats ; $LASTEXITCODE = 0
|
||||
} catch {
|
||||
Write-Host "Build stats upload failed, continuing..."
|
||||
}
|
||||
@@ -216,6 +216,7 @@ runs:
|
||||
- name: Publish Electron Dist ${{ inputs.step-suffix }}
|
||||
if: ${{ inputs.is-release == 'true' }}
|
||||
shell: bash
|
||||
id: github-upload
|
||||
run: |
|
||||
rm -rf src/out/Default/obj
|
||||
cd src/electron
|
||||
@@ -226,6 +227,11 @@ runs:
|
||||
echo 'Uploading Electron release distribution to GitHub releases'
|
||||
script/release/uploaders/upload.py --verbose
|
||||
fi
|
||||
- name: Generate artifact attestation
|
||||
if: ${{ inputs.is-release == 'true' }}
|
||||
uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3.2.0
|
||||
with:
|
||||
subject-path: ${{ steps.github-upload.outputs.UPLOADED_PATHS }}
|
||||
- name: Generate siso report
|
||||
if: ${{ inputs.target-platform != 'win' && !cancelled() }}
|
||||
shell: bash
|
||||
|
||||
@@ -15,7 +15,7 @@ runs:
|
||||
git config --global core.preloadindex true
|
||||
git config --global core.longpaths true
|
||||
fi
|
||||
export BUILD_TOOLS_SHA=4430e4a505e0f4fa2a41b707a10a36f780bbdd26
|
||||
export BUILD_TOOLS_SHA=a0cc95a1884a631559bcca0c948465b725d9295a
|
||||
npm i -g @electron/build-tools
|
||||
# Update depot_tools to ensure python
|
||||
e d update_depot_tools
|
||||
|
||||
122
.github/copilot-instructions.md
vendored
Normal file
122
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
# Copilot Instructions for Electron
|
||||
|
||||
## Build System
|
||||
|
||||
Electron uses `@electron/build-tools` (`e` CLI). Install with `npm i -g @electron/build-tools`.
|
||||
|
||||
```bash
|
||||
e sync # Fetch sources and apply patches
|
||||
e build # Build Electron (GN + Ninja)
|
||||
e build -k 999 # Build, continuing through errors
|
||||
e start # Run built Electron
|
||||
e start --version # Verify Electron launches
|
||||
e test # Run full test suite
|
||||
e debug # Run in debugger (lldb on macOS, gdb on Linux)
|
||||
```
|
||||
|
||||
### Linting
|
||||
|
||||
```bash
|
||||
npm run lint # Run all linters (JS, C++, Python, GN, docs)
|
||||
npm run lint:js # JavaScript/TypeScript only
|
||||
npm run lint:clang-format # C++ formatting only
|
||||
npm run lint:cpp # C++ linting only
|
||||
npm run lint:docs # Documentation only
|
||||
```
|
||||
|
||||
### Running a Single Test
|
||||
|
||||
```bash
|
||||
npm run test -- -g "pattern" # Run tests matching a regex pattern
|
||||
# Example: npm run test -- -g "ipc"
|
||||
```
|
||||
|
||||
### Running a Single Node.js Test
|
||||
|
||||
```bash
|
||||
node script/node-spec-runner.js parallel/test-crypto-keygen
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
Electron embeds Chromium (rendering) and Node.js (backend) to enable desktop apps with web technologies. The parent directory (`../`) is the Chromium source tree.
|
||||
|
||||
### Process Model
|
||||
|
||||
Electron has two primary process types, mirroring Chromium:
|
||||
|
||||
- **Main process** (`shell/browser/` + `lib/browser/`): Controls app lifecycle, creates windows, system APIs
|
||||
- **Renderer process** (`shell/renderer/` + `lib/renderer/`): Runs web content in BrowserWindows
|
||||
|
||||
### Native ↔ JavaScript Bridge
|
||||
|
||||
Each API is implemented as a C++/JS pair:
|
||||
|
||||
- C++ side: `shell/browser/api/electron_api_{name}.cc/.h` — uses `gin::Wrappable` and `ObjectTemplateBuilder`
|
||||
- JS side: `lib/browser/api/{name}.ts` — exports the module, registered in `lib/browser/api/module-list.ts`
|
||||
- Binding: `NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{name}, Initialize)` in C++ and registered in `shell/common/node_bindings.cc`
|
||||
- Type declaration: `typings/internal-ambient.d.ts` maps `process._linkedBinding('electron_browser_{name}')`
|
||||
|
||||
### Patches System
|
||||
|
||||
Electron patches upstream dependencies (Chromium, Node.js, V8, etc.) rather than forking them. Patches live in `patches/` organized by target, with `patches/config.json` mapping directories to repos.
|
||||
|
||||
```text
|
||||
patches/{target}/*.patch → [e sync] → target repo commits
|
||||
← [e patches] ←
|
||||
```
|
||||
|
||||
Key rules:
|
||||
|
||||
- Fix existing patches rather than creating new ones
|
||||
- Preserve original authorship in TODO comments — never change `TODO(name)` assignees
|
||||
- Each patch commit message must explain why the patch exists
|
||||
- After modifying patches, run `e patches {target}` to export
|
||||
|
||||
When working on the `roller/chromium/main` branch for Chromium upgrades, use `e sync --3` for 3-way merge conflict resolution.
|
||||
|
||||
## Conventions
|
||||
|
||||
### File Naming
|
||||
|
||||
- JS/TS files: kebab-case (`file-name.ts`)
|
||||
- C++ files: snake_case with `electron_api_` prefix (`electron_api_safe_storage.cc`)
|
||||
- Test files: `api-{module-name}-spec.ts` in `spec/`
|
||||
- Source file lists are maintained in `filenames.gni` (with platform-specific sections)
|
||||
|
||||
### JavaScript/TypeScript
|
||||
|
||||
- Semicolons required (`"semi": ["error", "always"]`)
|
||||
- `const` and `let` only (no `var`)
|
||||
- Arrow functions preferred
|
||||
- Import order enforced: `@electron/internal` → `@electron` → `electron` → external → builtin → relative
|
||||
- API naming: `PascalCase` for classes (`BrowserWindow`), `camelCase` for module APIs (`globalShortcut`)
|
||||
- Prefer getters/setters over jQuery-style `.text([text])` patterns
|
||||
|
||||
### C++
|
||||
|
||||
- Follows Chromium coding style, enforced by `clang-format` and `clang-tidy`
|
||||
- Uses Chromium abstractions (`base::`, `content::`, etc.)
|
||||
- Header guards: `#ifndef ELECTRON_SHELL_BROWSER_API_ELECTRON_API_{NAME}_H_`
|
||||
- Platform-specific files: `_mac.mm`, `_win.cc`, `_linux.cc`
|
||||
|
||||
### Testing
|
||||
|
||||
- Framework: Mocha + Chai + Sinon
|
||||
- Test helpers in `spec/lib/` (e.g., `spec-helpers.ts`, `window-helpers.ts`)
|
||||
- Use `defer()` from spec-helpers for cleanup, `closeAllWindows()` for window teardown
|
||||
- Tests import from `electron/main` or `electron/renderer`
|
||||
|
||||
### Documentation
|
||||
|
||||
- API docs in `docs/api/` as Markdown, parsed by `@electron/docs-parser` to generate `electron.d.ts`
|
||||
- API history tracked via YAML blocks in HTML comments within doc files
|
||||
- Docs must pass `npm run lint:docs`
|
||||
|
||||
### Build Configuration
|
||||
|
||||
- `BUILD.gn`: Main GN build config
|
||||
- `buildflags/buildflags.gni`: Feature flags (PDF viewer, extensions, spellchecker)
|
||||
- `build/args/`: Build argument profiles (`testing.gn`, `release.gn`, `all.gn`)
|
||||
- `DEPS`: Dependency versions and checkout paths
|
||||
- `chromium_src/`: Chromium source file overrides (compiled instead of originals)
|
||||
16
.github/problem-matchers/markdownlint.json
vendored
Normal file
16
.github/problem-matchers/markdownlint.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "markdownlint",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^(.+):(\\d+):(\\d+)\\s+(.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
15
.github/workflows/linux-publish.yml
vendored
15
.github/workflows/linux-publish.yml
vendored
@@ -43,9 +43,12 @@ jobs:
|
||||
uses: ./src/electron/.github/actions/checkout
|
||||
|
||||
publish-x64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -60,9 +63,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -77,9 +83,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-linux
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
20
.github/workflows/macos-publish.yml
vendored
20
.github/workflows/macos-publish.yml
vendored
@@ -47,9 +47,12 @@ jobs:
|
||||
target-platform: macos
|
||||
|
||||
publish-x64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -64,9 +67,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-x64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -81,9 +87,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64-darwin:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -98,9 +107,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64-mas:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-macos
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
12
.github/workflows/pipeline-electron-lint.yml
vendored
12
.github/workflows/pipeline-electron-lint.yml
vendored
@@ -65,9 +65,11 @@ jobs:
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/buildtools/DEPS?format=TEXT" | base64 -d > src/buildtools/DEPS
|
||||
|
||||
gclient sync --spec="solutions=[{'name':'src/buildtools','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':True},'managed':False}]"
|
||||
- name: Add ESLint problem matcher
|
||||
- name: Add problem matchers
|
||||
shell: bash
|
||||
run: echo "::add-matcher::src/electron/.github/problem-matchers/eslint-stylish.json"
|
||||
run: |
|
||||
echo "::add-matcher::src/electron/.github/problem-matchers/eslint-stylish.json"
|
||||
echo "::add-matcher::src/electron/.github/problem-matchers/markdownlint.json"
|
||||
- name: Run Lint
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -85,4 +87,8 @@ jobs:
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn.js tsc -p tsconfig.script.json
|
||||
|
||||
- name: Check GHA Workflows
|
||||
shell: bash
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/copy-pipeline-segment-publish.js --check
|
||||
|
||||
237
.github/workflows/pipeline-segment-electron-publish.yml
vendored
Normal file
237
.github/workflows/pipeline-segment-electron-publish.yml
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
# AUTOGENERATED FILE - DO NOT EDIT MANUALLY
|
||||
# ONLY EDIT .github/workflows/pipeline-segment-electron-build.yml
|
||||
|
||||
name: Pipeline Segment - Electron Build
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
environment:
|
||||
description: using the production or testing environment
|
||||
required: false
|
||||
type: string
|
||||
target-platform:
|
||||
type: string
|
||||
description: Platform to run on, can be macos, win or linux
|
||||
required: true
|
||||
target-arch:
|
||||
type: string
|
||||
description: Arch to build for, can be x64, arm64, ia32 or arm
|
||||
required: true
|
||||
target-variant:
|
||||
type: string
|
||||
description: Variant to build for, no effect on non-macOS target platforms. Can
|
||||
be darwin, mas or all.
|
||||
default: all
|
||||
build-runs-on:
|
||||
type: string
|
||||
description: What host to run the build
|
||||
required: true
|
||||
build-container:
|
||||
type: string
|
||||
description: JSON container information for aks runs-on
|
||||
required: false
|
||||
default: '{"image":null}'
|
||||
is-release:
|
||||
description: Whether this build job is a release job
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
gn-build-type:
|
||||
description: The gn build type - testing or release
|
||||
required: true
|
||||
type: string
|
||||
default: testing
|
||||
generate-symbols:
|
||||
description: Whether or not to generate symbols
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
upload-to-storage:
|
||||
description: Whether or not to upload build artifacts to external storage
|
||||
required: true
|
||||
type: string
|
||||
default: "0"
|
||||
is-asan:
|
||||
description: Building the Address Sanitizer (ASan) Linux build
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
enable-ssh:
|
||||
description: Enable SSH debugging
|
||||
required: false
|
||||
type: boolean
|
||||
default: false
|
||||
permissions: {}
|
||||
concurrency:
|
||||
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:
|
||||
CHROMIUM_GIT_COOKIE: ${{ secrets.CHROMIUM_GIT_COOKIE }}
|
||||
CHROMIUM_GIT_COOKIE_WINDOWS_STRING: ${{ secrets.CHROMIUM_GIT_COOKIE_WINDOWS_STRING }}
|
||||
DD_API_KEY: ${{ secrets.DD_API_KEY }}
|
||||
ELECTRON_ARTIFACTS_BLOB_STORAGE: ${{ secrets.ELECTRON_ARTIFACTS_BLOB_STORAGE }}
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
SUDOWOODO_EXCHANGE_URL: ${{ secrets.SUDOWOODO_EXCHANGE_URL }}
|
||||
SUDOWOODO_EXCHANGE_TOKEN: ${{ secrets.SUDOWOODO_EXCHANGE_TOKEN }}
|
||||
GCLIENT_EXTRA_ARGS: ${{ inputs.target-platform == 'macos' &&
|
||||
'--custom-var=checkout_mac=True --custom-var=host_os=mac' ||
|
||||
inputs.target-platform == 'win' && '--custom-var=checkout_win=True' ||
|
||||
'--custom-var=checkout_arm=True --custom-var=checkout_arm64=True' }}
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ACTIONS_STEP_DEBUG: ${{ secrets.ACTIONS_STEP_DEBUG }}
|
||||
jobs:
|
||||
build:
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
runs-on: ${{ inputs.build-runs-on }}
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
container: ${{ fromJSON(inputs.build-container) }}
|
||||
environment: ${{ inputs.environment }}
|
||||
env:
|
||||
TARGET_ARCH: ${{ inputs.target-arch }}
|
||||
TARGET_PLATFORM: ${{ inputs.target-platform }}
|
||||
steps:
|
||||
- name: Create src dir
|
||||
run: |
|
||||
mkdir src
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Setup SSH Debugging
|
||||
if: ${{ inputs.target-platform == 'macos' && (inputs.enable-ssh ||
|
||||
env.ACTIONS_STEP_DEBUG == 'true') }}
|
||||
uses: ./src/electron/.github/actions/ssh-debug
|
||||
with:
|
||||
tunnel: "true"
|
||||
env:
|
||||
CLOUDFLARE_TUNNEL_CERT: ${{ secrets.CLOUDFLARE_TUNNEL_CERT }}
|
||||
CLOUDFLARE_TUNNEL_HOSTNAME: ${{ vars.CLOUDFLARE_TUNNEL_HOSTNAME }}
|
||||
CLOUDFLARE_USER_CA_CERT: ${{ secrets.CLOUDFLARE_USER_CA_CERT }}
|
||||
AUTHORIZED_USERS: ${{ secrets.SSH_DEBUG_AUTHORIZED_USERS }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Free up space (macOS)
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/free-space-macos
|
||||
- name: Check disk space after freeing up space
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: df -h
|
||||
- name: Setup Node.js/npm
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903
|
||||
with:
|
||||
node-version: 20.19.x
|
||||
cache: yarn
|
||||
cache-dependency-path: src/electron/yarn.lock
|
||||
- name: Install Dependencies
|
||||
uses: ./src/electron/.github/actions/install-dependencies
|
||||
- name: Install AZCopy
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
run: brew install azcopy
|
||||
- name: Set GN_EXTRA_ARGS for Linux
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
run: >
|
||||
if [ "${{ inputs.target-arch }}" = "arm" ]; then
|
||||
if [ "${{ inputs.is-release }}" = true ]; then
|
||||
GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false symbol_level=1'
|
||||
else
|
||||
GN_EXTRA_ARGS='target_cpu="arm" build_tflite_with_xnnpack=false'
|
||||
fi
|
||||
elif [ "${{ inputs.target-arch }}" = "arm64" ]; then
|
||||
GN_EXTRA_ARGS='target_cpu="arm64" fatal_linker_warnings=false enable_linux_installer=false'
|
||||
elif [ "${{ inputs.is-asan }}" = true ]; then
|
||||
GN_EXTRA_ARGS='is_asan=true'
|
||||
fi
|
||||
|
||||
echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV
|
||||
- name: Set Chromium Git Cookie
|
||||
uses: ./src/electron/.github/actions/set-chromium-cookie
|
||||
- name: Install Build Tools
|
||||
uses: ./src/electron/.github/actions/install-build-tools
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js
|
||||
DEPSHASH=v1-src-cache-$(cat src/electron/.depshash)
|
||||
echo "DEPSHASH=$DEPSHASH" >> $GITHUB_ENV
|
||||
echo "CACHE_PATH=$DEPSHASH.tar" >> $GITHUB_ENV
|
||||
- name: Restore src cache via AZCopy
|
||||
if: ${{ inputs.target-platform != 'linux' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-azcopy
|
||||
with:
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
- name: Restore src cache via AKS
|
||||
if: ${{ inputs.target-platform == 'linux' }}
|
||||
uses: ./src/electron/.github/actions/restore-cache-aks
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
|
||||
with:
|
||||
path: src/electron
|
||||
fetch-depth: 0
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- name: Fix Sync
|
||||
if: ${{ inputs.target-platform != 'linux' }}
|
||||
uses: ./src/electron/.github/actions/fix-sync
|
||||
with:
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
env:
|
||||
ELECTRON_DEPOT_TOOLS_DISABLE_LOG: true
|
||||
- name: Init Build Tools
|
||||
run: >
|
||||
e init -f --root=$(pwd) --out=Default ${{ inputs.gn-build-type }}
|
||||
--import ${{ inputs.gn-build-type }} --target-cpu ${{
|
||||
inputs.target-arch }} --remote-build siso
|
||||
- name: Run Electron Only Hooks
|
||||
run: |
|
||||
e d gclient runhooks --spec="solutions=[{'name':'src/electron','url':None,'deps_file':'DEPS','custom_vars':{'process_deps':False},'managed':False}]"
|
||||
- name: Regenerate DEPS Hash
|
||||
run: >
|
||||
(cd src/electron && git checkout .) && node
|
||||
src/electron/script/generate-deps-hash.js
|
||||
|
||||
echo "DEPSHASH=$(cat src/electron/.depshash)" >> $GITHUB_ENV
|
||||
- name: Add CHROMIUM_BUILDTOOLS_PATH to env
|
||||
run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV
|
||||
- name: Free up space (macOS)
|
||||
if: ${{ inputs.target-platform == 'macos' }}
|
||||
uses: ./src/electron/.github/actions/free-space-macos
|
||||
- name: Build Electron
|
||||
if: ${{ inputs.target-platform != 'macos' || (inputs.target-variant == 'all' ||
|
||||
inputs.target-variant == 'darwin') }}
|
||||
uses: ./src/electron/.github/actions/build-electron
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
artifact-platform: ${{ inputs.target-platform == 'macos' && 'darwin' ||
|
||||
inputs.target-platform }}
|
||||
is-release: ${{ inputs.is-release }}
|
||||
generate-symbols: ${{ inputs.generate-symbols }}
|
||||
upload-to-storage: ${{ inputs.upload-to-storage }}
|
||||
is-asan: ${{ inputs.is-asan }}
|
||||
- name: Set GN_EXTRA_ARGS for MAS Build
|
||||
if: ${{ inputs.target-platform == 'macos' && (inputs.target-variant == 'all' ||
|
||||
inputs.target-variant == 'mas') }}
|
||||
run: |
|
||||
echo "MAS_BUILD=true" >> $GITHUB_ENV
|
||||
GN_EXTRA_ARGS='is_mas_build=true'
|
||||
echo "GN_EXTRA_ARGS=$GN_EXTRA_ARGS" >> $GITHUB_ENV
|
||||
- name: Build Electron (MAS)
|
||||
if: ${{ inputs.target-platform == 'macos' && (inputs.target-variant == 'all' ||
|
||||
inputs.target-variant == 'mas') }}
|
||||
uses: ./src/electron/.github/actions/build-electron
|
||||
with:
|
||||
target-arch: ${{ inputs.target-arch }}
|
||||
target-platform: ${{ inputs.target-platform }}
|
||||
artifact-platform: mas
|
||||
is-release: ${{ inputs.is-release }}
|
||||
generate-symbols: ${{ inputs.generate-symbols }}
|
||||
upload-to-storage: ${{ inputs.upload-to-storage }}
|
||||
step-suffix: (mas)
|
||||
2
.github/workflows/update-website-docs.yml
vendored
2
.github/workflows/update-website-docs.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
echo "isLatestRelease=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Trigger website docs update
|
||||
if: ${{ steps.check-if-latest-release.outputs.isLatestRelease }}
|
||||
if: ${{ steps.check-if-latest-release.outputs.isLatestRelease == 'true' }}
|
||||
env:
|
||||
GH_REPO: electron/website
|
||||
GH_TOKEN: ${{ fromJSON(steps.secret-service.outputs.secrets).WEBSITE_DOCS_UPDATER_APP_TOKEN }}
|
||||
|
||||
15
.github/workflows/windows-publish.yml
vendored
15
.github/workflows/windows-publish.yml
vendored
@@ -51,9 +51,12 @@ jobs:
|
||||
target-platform: win
|
||||
|
||||
publish-x64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -67,9 +70,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-arm64-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
@@ -83,9 +89,12 @@ jobs:
|
||||
secrets: inherit
|
||||
|
||||
publish-x86-win:
|
||||
uses: ./.github/workflows/pipeline-segment-electron-build.yml
|
||||
uses: ./.github/workflows/pipeline-segment-electron-publish.yml
|
||||
permissions:
|
||||
artifact-metadata: write
|
||||
attestations: write
|
||||
contents: read
|
||||
id-token: write
|
||||
needs: checkout-windows
|
||||
with:
|
||||
environment: production-release
|
||||
|
||||
4
DEPS
4
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'144.0.7559.134',
|
||||
'144.0.7559.220',
|
||||
'node_version':
|
||||
'v24.13.0',
|
||||
'v24.13.1',
|
||||
'nan_version':
|
||||
'675cefebca42410733da8a454c8d9391fcebfbc2',
|
||||
'squirrel.mac_version':
|
||||
|
||||
@@ -250,7 +250,9 @@ Returns:
|
||||
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
|
||||
### Event: 'browser-window-blur'
|
||||
|
||||
@@ -1121,6 +1123,19 @@ Updates the current activity if its type matches `type`, merging the entries fro
|
||||
|
||||
Changes the [Application User Model ID][app-user-model-id] to `id`.
|
||||
|
||||
### `app.setToastActivatorCLSID(id)` _Windows_
|
||||
|
||||
* `id` string
|
||||
|
||||
Changes the [Toast Activator CLSID][toast-activator-clsid] to `id`. If one is not set via this method, it will be randomly generated for the app.
|
||||
|
||||
* The value must be a valid GUID/CLSID in one of the following forms:
|
||||
* Canonical brace-wrapped: `{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}` (preferred)
|
||||
* Canonical without braces: `XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX` (braces will be added automatically)
|
||||
* Hex digits are case-insensitive.
|
||||
|
||||
This method should be called early (before showing notifications) so the value is baked into the registration/shortcut. Supplying an empty string or an unparsable value throws and leaves the existing (or generated) CLSID unchanged. If this method is never called, a random CLSID is generated once per run and exposed via `app.toastActivatorCLSID`.
|
||||
|
||||
### `app.setActivationPolicy(policy)` _macOS_
|
||||
|
||||
* `policy` string - Can be 'regular', 'accessory', or 'prohibited'.
|
||||
@@ -1703,8 +1718,13 @@ platforms) that allows you to perform actions on your app icon in the user's doc
|
||||
|
||||
A `boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments.
|
||||
|
||||
### `app.toastActivatorCLSID` _Windows_ _Readonly_
|
||||
|
||||
A `string` property that returns the app's [Toast Activator CLSID][toast-activator-clsid].
|
||||
|
||||
[tasks]:https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#tasks
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[toast-activator-clsid]: https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/packager
|
||||
[CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115
|
||||
|
||||
@@ -351,7 +351,11 @@ Emitted when the window has closed a sheet.
|
||||
|
||||
#### Event: 'new-window-for-tab' _macOS_
|
||||
|
||||
Emitted when the native new tab button is clicked.
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
|
||||
#### Event: 'system-context-menu' _Windows_ _Linux_
|
||||
|
||||
|
||||
@@ -431,7 +431,11 @@ Emitted when the window has closed a sheet.
|
||||
|
||||
#### Event: 'new-window-for-tab' _macOS_
|
||||
|
||||
Emitted when the native new tab button is clicked.
|
||||
Emitted when the user clicks the native macOS new tab button. The new
|
||||
tab button is only visible if the current `BrowserWindow` has a
|
||||
`tabbingIdentifier`.
|
||||
|
||||
You must create a window in this handler in order for macOS tabbing to work as expected.
|
||||
|
||||
#### Event: 'system-context-menu' _Windows_ _Linux_
|
||||
|
||||
|
||||
@@ -366,6 +366,13 @@ Keep in mind that standalone switches can sometimes be split into individual fea
|
||||
|
||||
Finally, you'll need to ensure that the version of Chromium in Electron matches the version of the browser you're using to cross-reference the switches.
|
||||
|
||||
### Chromium features relevant to Electron apps
|
||||
|
||||
* `AlwaysLogLOAFURL`: enables script attribution for
|
||||
[`long-animation-frame`](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/Long_animation_frame_timing)
|
||||
`PerformanceObserver` events for non-http(s), non-data, non-blob URLs (such as `file:` or custom
|
||||
protocol URLs).
|
||||
|
||||
[app]: app.md
|
||||
[append-switch]: command-line.md#commandlineappendswitchswitch-value
|
||||
[debugging-main-process]: ../tutorial/debugging-main-process.md
|
||||
|
||||
@@ -94,18 +94,45 @@ The `desktopCapturer` module has the following methods:
|
||||
Returns `Promise<DesktopCapturerSource[]>` - Resolves with an array of [`DesktopCapturerSource`](structures/desktop-capturer-source.md) objects, each `DesktopCapturerSource` represents a screen or an individual window that can be captured.
|
||||
|
||||
> [!NOTE]
|
||||
> Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher,
|
||||
> which can detected by [`systemPreferences.getMediaAccessStatus`][].
|
||||
|
||||
> * Capturing audio requires `NSAudioCaptureUsageDescription` Info.plist key on macOS 14.2 Sonoma and higher - [read more](#macos-versions-142-or-higher).
|
||||
> * Capturing the screen contents requires user consent on macOS 10.15 Catalina or higher, which can detected by [`systemPreferences.getMediaAccessStatus`][].
|
||||
|
||||
[`navigator.mediaDevices.getUserMedia`]: https://developer.mozilla.org/en/docs/Web/API/MediaDevices/getUserMedia
|
||||
[`systemPreferences.getMediaAccessStatus`]: system-preferences.md#systempreferencesgetmediaaccessstatusmediatype-windows-macos
|
||||
|
||||
## Caveats
|
||||
|
||||
### Linux
|
||||
|
||||
`desktopCapturer.getSources(options)` only returns a single source on Linux when using Pipewire.
|
||||
|
||||
PipeWire supports a single capture for both screens and windows. If you request the window and screen type, the selected source will be returned as a window capture.
|
||||
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this.
|
||||
---
|
||||
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like Soundflower and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.
|
||||
### MacOS versions 14.2 or higher
|
||||
|
||||
`NSAudioCaptureUsageDescription` Info.plist key must be added in-order for audio to be captured by `desktopCapturer`. If instead you are running electron from another program like a terminal or IDE then that parent program must contain the Info.plist key.
|
||||
|
||||
This is in order to facillitate use of Apple's new [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by Chromium.
|
||||
|
||||
> [!WARNING]
|
||||
> Failure of `desktopCapturer` to start an audio stream due to `NSAudioCaptureUsageDescription` permission not present will still create a dead audio stream however no warnings or errors are displayed.
|
||||
|
||||
As of electron `v39.0.0-beta.4` Chromium [made Apple's new `CoreAudio Tap API` the default](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e) for desktop audio capture. There is no fallback to the older `Screen & System Audio Recording` permissions system even if [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps) stream creation fails.
|
||||
|
||||
If you need to continue using `Screen & System Audio Recording` permissions for `desktopCapturer` on macOS versions 14.2 and later, you can apply a chromium feature flag to force use of that older permissions system:
|
||||
|
||||
```js
|
||||
// main.js (right beneath your require/import statments)
|
||||
app.commandLine.appendSwitch('disable-features', 'MacCatapLoopbackAudioForScreenShare')
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### MacOS versions 12.7.6 or lower
|
||||
|
||||
`navigator.mediaDevices.getUserMedia` does not work on macOS versions 12.7.6 and prior for audio capture due to a fundamental limitation whereby apps that want to access the system's audio require a [signed kernel extension](https://developer.apple.com/library/archive/documentation/Security/Conceptual/System_Integrity_Protection_Guide/KernelExtensions/KernelExtensions.html). Chromium, and by extension Electron, does not provide this. Only in macOS 13 and onwards does Apple provide APIs to capture desktop audio without the need for a signed kernel extension.
|
||||
|
||||
It is possible to circumvent this limitation by capturing system audio with another macOS app like [BlackHole](https://existential.audio/blackhole/) or [Soundflower](https://rogueamoeba.com/freebies/soundflower/) and passing it through a virtual audio input device. This virtual device can then be queried with `navigator.mediaDevices.getUserMedia`.
|
||||
|
||||
@@ -67,6 +67,22 @@ Emitted when the notification is shown to the user. Note that this event can be
|
||||
multiple times as a notification can be shown multiple times through the
|
||||
`show()` method.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('show', () => console.log('Notification shown!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'click'
|
||||
|
||||
Returns:
|
||||
@@ -75,6 +91,22 @@ Returns:
|
||||
|
||||
Emitted when the notification is clicked by the user.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('click', () => console.log('Notification clicked!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'close'
|
||||
|
||||
Returns:
|
||||
@@ -88,21 +120,85 @@ is closed.
|
||||
|
||||
On Windows, the `close` event can be emitted in one of three ways: programmatic dismissal with `notification.close()`, by the user closing the notification, or via system timeout. If a notification is in the Action Center after the initial `close` event is emitted, a call to `notification.close()` will remove the notification from the action center but the `close` event will not be emitted again.
|
||||
|
||||
#### Event: 'reply' _macOS_
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.on('close', () => console.log('Notification closed!'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'reply' _macOS_ _Windows_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `reply` string - The string the user entered into the inline reply field.
|
||||
* `details` Event\<\>
|
||||
* `reply` string - The string the user entered into the inline reply field.
|
||||
* `reply` string _Deprecated_
|
||||
|
||||
Emitted when the user clicks the "Reply" button on a notification with `hasReply: true`.
|
||||
|
||||
#### Event: 'action' _macOS_
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Send a Message',
|
||||
body: 'Body Text',
|
||||
hasReply: true,
|
||||
replyPlaceholder: 'Message text...'
|
||||
})
|
||||
|
||||
n.on('reply', (e, reply) => console.log(`User replied: ${reply}`))
|
||||
n.on('click', () => console.log('Notification clicked'))
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'action' _macOS_ _Windows_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `index` number - The index of the action that was activated.
|
||||
* `details` Event\<\>
|
||||
* `actionIndex` number - The index of the action that was activated.
|
||||
* `selectionIndex` number _Windows_ - The index of the selected item, if one was chosen. -1 if none was chosen.
|
||||
* `actionIndex` number _Deprecated_
|
||||
* `selectionIndex` number _Windows_ _Deprecated_
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const items = ['One', 'Two', 'Three']
|
||||
const n = new Notification({
|
||||
title: 'Choose an Action!',
|
||||
actions: [
|
||||
{ type: 'button', text: 'Action 1' },
|
||||
{ type: 'button', text: 'Action 2' },
|
||||
{ type: 'selection', text: 'Apply', items }
|
||||
]
|
||||
})
|
||||
|
||||
n.on('click', () => console.log('Notification clicked'))
|
||||
n.on('action', (e) => {
|
||||
console.log(`User triggered action at index: ${e.actionIndex}`)
|
||||
if (e.selectionIndex > -1) {
|
||||
console.log(`User chose selection item '${items[e.selectionIndex]}'`)
|
||||
}
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### Event: 'failed' _Windows_
|
||||
|
||||
@@ -113,6 +209,22 @@ Returns:
|
||||
|
||||
Emitted when an error is encountered while creating and showing the native notification.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Bad Action'
|
||||
})
|
||||
|
||||
n.on('failed', (e, err) => {
|
||||
console.log('Notification failed: ', err)
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Methods
|
||||
|
||||
Objects created with the `new Notification()` constructor have the following instance methods:
|
||||
@@ -126,12 +238,42 @@ call this method before the OS will display it.
|
||||
If the notification has been shown before, this method will dismiss the previously
|
||||
shown notification and create a new one with identical properties.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
#### `notification.close()`
|
||||
|
||||
Dismisses the notification.
|
||||
|
||||
On Windows, calling `notification.close()` while the notification is visible on screen will dismiss the notification and remove it from the Action Center. If `notification.close()` is called after the notification is no longer visible on screen, calling `notification.close()` will try remove it from the Action Center.
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const n = new Notification({
|
||||
title: 'Title!',
|
||||
subtitle: 'Subtitle!',
|
||||
body: 'Body!'
|
||||
})
|
||||
|
||||
n.show()
|
||||
|
||||
setTimeout(() => n.close(), 5000)
|
||||
})
|
||||
```
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `notification.title`
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# sharedTexture
|
||||
|
||||
> Import shared textures into Electron and converts platform specific handles into [`VideoFrame`](https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame). Supports all Web rendering systems, and can be transferred across Electron processes. Read [here](https://github.com/electron/electron/blob/main/shell/common/api/shared_texture/README.md) for more information.
|
||||
> Import shared textures into Electron and converts platform specific handles into [`VideoFrame`](https://developer.mozilla.org/en-US/docs/Web/API/VideoFrame). Supports all Web rendering systems, and can be transferred across Electron processes. Read [here](../../shell/common/api/shared_texture/README.md) for more information.
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
# NotificationAction Object
|
||||
|
||||
* `type` string - The type of action, can be `button`.
|
||||
* `type` string - The type of action, can be `button` or `selection`. `selection` is only supported on Windows.
|
||||
* `text` string (optional) - The label for the given action.
|
||||
* `items` string[] (optional) _Windows_ - The list of items for the `selection` action `type`.
|
||||
|
||||
## Platform / Action Support
|
||||
|
||||
| Action Type | Platform Support | Usage of `text` | Default `text` | Limitations |
|
||||
|-------------|------------------|-----------------|----------------|-------------|
|
||||
| `button` | macOS | Used as the label for the button | "Show" (or a localized string by system default if first of such `button`, otherwise empty) | Only the first one is used. If multiple are provided, those beyond the first will be listed as additional actions (displayed when mouse active over the action button). Any such action also is incompatible with `hasReply` and will be ignored if `hasReply` is `true`. |
|
||||
| `button` | macOS, Windows | Used as the label for the button | "Show" on macOS (localized) if first `button`, otherwise empty; Windows uses provided `text` | macOS: Only the first one is used as primary; others shown as additional actions (hover). Incompatible with `hasReply` (beyond first ignored). |
|
||||
| `selection` | Windows | Used as the label for the submit button for the selection menu | "Select" | Requires an `items` array property specifying option labels. Emits the `action` event with `(index, selectedIndex)` where `selectedIndex` is the chosen option (>= 0). Ignored on platforms that do not support selection actions. |
|
||||
|
||||
### Button support on macOS
|
||||
|
||||
@@ -18,3 +20,34 @@ following criteria.
|
||||
* App has its `NSUserNotificationAlertStyle` set to `alert` in the `Info.plist`.
|
||||
|
||||
If either of these requirements are not met the button won't appear.
|
||||
|
||||
### Selection support on Windows
|
||||
|
||||
To add a selection (combo box) style action, include an action with `type: 'selection'`, a `text` label for the submit button, and an `items` array of strings:
|
||||
|
||||
```js
|
||||
const { Notification, app } = require('electron')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const items = ['One', 'Two', 'Three']
|
||||
const n = new Notification({
|
||||
title: 'Choose an option',
|
||||
actions: [{
|
||||
type: 'selection',
|
||||
text: 'Apply',
|
||||
items
|
||||
}]
|
||||
})
|
||||
|
||||
n.on('action', (e) => {
|
||||
console.log(`User triggered action at index: ${e.actionIndex}`)
|
||||
if (e.selectionIndex > 0) {
|
||||
console.log(`User chose selection item '${items[e.selectionIndex]}'`)
|
||||
}
|
||||
})
|
||||
|
||||
n.show()
|
||||
})
|
||||
```
|
||||
|
||||
When the user activates the selection action, the notification's `action` event will be emitted with two parameters: `actionIndex` (the action's index in the `actions` array) and `selectedIndex` (the zero-based index of the chosen item, or `-1` if unavailable). On non-Windows platforms selection actions are ignored.
|
||||
|
||||
@@ -156,6 +156,8 @@
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `transparent` boolean (optional) - Whether to enable background transparency for the guest page. Default is `true`. **Note:** The guest page's text and background colors are derived from the [color scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme) of its root element. When transparency is enabled, the text color will still change accordingly but the background will remain transparent.
|
||||
* `enableDeprecatedPaste` boolean (optional) _Deprecated_ - Whether to enable the `paste` [execCommand](https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand). Default is `false`.
|
||||
* `focusOnNavigation` boolean (optional) - Whether to focus the WebContents
|
||||
when navigating. Default is `true`.
|
||||
|
||||
[chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment
|
||||
[runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
|
||||
@@ -933,7 +933,7 @@ copying data between CPU and GPU memory, with Chromium's hardware acceleration s
|
||||
Only a limited number of textures can exist at the same time, so it's important that you call `texture.release()` as soon as you're done with the texture.
|
||||
By managing the texture lifecycle by yourself, you can safely pass the `texture.textureInfo` to other processes through IPC.
|
||||
|
||||
More details can be found in the [offscreen rendering tutorial](../tutorial/offscreen-rendering.md). To learn about how to handle the texture in native code, refer to [offscreen rendering's code documentation.](https://github.com/electron/electron/blob/main/shell/browser/osr/README.md).
|
||||
More details can be found in the [offscreen rendering tutorial](../tutorial/offscreen-rendering.md). To learn about how to handle the texture in native code, refer to [offscreen rendering's code documentation.](../../shell/browser/osr/README.md).
|
||||
|
||||
```js
|
||||
const { BrowserWindow } = require('electron')
|
||||
|
||||
@@ -50,6 +50,22 @@ webContents.setWindowOpenHandler((details) => {
|
||||
})
|
||||
```
|
||||
|
||||
### Behavior Changed: `NSAudioCaptureUsageDescription` should be included in your app's Info.plist file to use `desktopCapturer` (🍏 macOS ≥14.2)
|
||||
|
||||
Per [Chromium update](https://source.chromium.org/chromium/chromium/src/+/ad17e8f8b93d5f34891b06085d373a668918255e) which enables Apple's newer [CoreAudio Tap API](https://developer.apple.com/documentation/CoreAudio/capturing-system-audio-with-core-audio-taps#Configure-the-sample-code-project) by default, you now must have `NSAudioCaptureUsageDescription` defined in your `Info.plist` to use `desktopCapturer`.
|
||||
|
||||
Electron's `desktopCapturer` will create a dead audio stream if the new permission is absent however no errors or warnings will occur. This is partially a side-effect of Chromium not falling back to the older `Screen & System Audio Recording` permissions system if the new system fails.
|
||||
|
||||
To restore previous behavior:
|
||||
|
||||
```js
|
||||
// main.js (right beneath your require/import statments)
|
||||
app.commandLine.appendSwitch(
|
||||
'disable-features',
|
||||
'MacCatapLoopbackAudioForScreenShare'
|
||||
)
|
||||
```
|
||||
|
||||
### Behavior Changed: shared texture OSR `paint` event data structure
|
||||
|
||||
When using shared texture offscreen rendering feature, the `paint` event now emits a more structured object.
|
||||
|
||||
@@ -41,7 +41,7 @@ e init --root=~/electron --bootstrap testing
|
||||
```
|
||||
|
||||
The `--bootstrap` flag also runs `e sync` (synchronizes source code branches from
|
||||
[`DEPS`](https://github.com/electron/electron/blob/main/DEPS) using
|
||||
[`DEPS`](../../DEPS) using
|
||||
[`gclient`](https://chromium.googlesource.com/chromium/tools/depot_tools.git/+/HEAD/README.gclient.md))
|
||||
and `e build` (compiles the Electron binary into the `${root}/src/out` folder).
|
||||
|
||||
@@ -63,7 +63,7 @@ Some quick tips on building once your checkout is set up:
|
||||
* **Updating your checkout:** Run git commands such as `git checkout <branch>` and `git pull` from `${root}/src/electron`.
|
||||
Whenever you update your commit `HEAD`, make sure to `e sync` before `e build` to sync dependencies
|
||||
such as Chromium and Node.js. This is especially relevant because the Chromium version in
|
||||
[`DEPS`](https://github.com/electron/electron/blob/main/DEPS) changes frequently.
|
||||
[`DEPS`](../../DEPS) changes frequently.
|
||||
* **Rebuilding:** When making changes to code in `${root}/src/electron/` in a local branch, you only need to re-run `e build`.
|
||||
* **Adding patches:** When contributing changes in `${root}/src/` outside of `${root}/src/electron/`, you need to do so
|
||||
via Electron's [patch system](./patches.md). The `e patches` command can export all relevant patches to
|
||||
@@ -98,7 +98,7 @@ Project configurations can be found in the `.gn` and `.gni` files in the `electr
|
||||
|
||||
The following `gn` files contain the main rules for building Electron:
|
||||
|
||||
* [`BUILD.gn`](https://github.com/electron/electron/blob/main/BUILD.gn) defines how Electron itself
|
||||
* [`BUILD.gn`](../../BUILD.gn) defines how Electron itself
|
||||
is built and includes the default configurations for linking with Chromium.
|
||||
* [`build/args/{testing,release,all}.gn`](https://github.com/electron/electron/tree/main/build/args)
|
||||
contain the default build arguments for building Electron.
|
||||
|
||||
@@ -6,7 +6,7 @@ This is not a comprehensive end-all guide to creating an Electron Browser API, r
|
||||
|
||||
## Add your files to Electron's project configuration
|
||||
|
||||
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](https://github.com/electron/electron/blob/main/filenames.gni).
|
||||
Electron uses [GN](https://gn.googlesource.com/gn) as a meta build system to generate files for its compiler, [Ninja](https://ninja-build.org/). This means that in order to tell Electron to compile your code, we have to add your API's code and header file names into [`filenames.gni`](../../filenames.gni).
|
||||
|
||||
You will need to append your API file names alphabetically into the appropriate files like so:
|
||||
|
||||
@@ -127,7 +127,7 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
## Link your Electron API with Node
|
||||
|
||||
In the [`typings/internal-ambient.d.ts`](https://github.com/electron/electron/blob/main/typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
|
||||
In the [`typings/internal-ambient.d.ts`](../../typings/internal-ambient.d.ts) file, we need to append a new property onto the `Process` interface like so:
|
||||
|
||||
```ts title='typings/internal-ambient.d.ts' @ts-nocheck
|
||||
interface Process {
|
||||
@@ -141,7 +141,7 @@ At the very bottom of your `api_name.cc` file:
|
||||
NODE_LINKED_BINDING_CONTEXT_AWARE(electron_browser_{api_name},Initialize)
|
||||
```
|
||||
|
||||
In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
|
||||
In your [`shell/common/node_bindings.cc`](../../shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
|
||||
|
||||
```cpp title='shell/common/node_bindings.cc'
|
||||
#define ELECTRON_BROWSER_MODULES(V) \
|
||||
@@ -159,7 +159,7 @@ We will need to create a new TypeScript file in the path that follows:
|
||||
|
||||
`"lib/browser/api/{electron_browser_{api_name}}.ts"`
|
||||
|
||||
An example of the contents of this file can be found [here](https://github.com/electron/electron/blob/main/lib/browser/api/native-theme.ts).
|
||||
An example of the contents of this file can be found [here](../../lib/browser/api/native-theme.ts).
|
||||
|
||||
### Expose your module to TypeScript
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ $ git push origin my-branch
|
||||
### Step 9: Opening the Pull Request
|
||||
|
||||
From within GitHub, opening a new pull request will present you with a template
|
||||
that should be filled out. It can be found [here](https://github.com/electron/electron/blob/main/.github/PULL_REQUEST_TEMPLATE.md).
|
||||
that should be filled out. It can be found [here](../../.github/PULL_REQUEST_TEMPLATE.md).
|
||||
|
||||
If you do not adequately complete this template, your PR may be delayed in being merged as maintainers
|
||||
seek more information or clarify ambiguities.
|
||||
@@ -218,8 +218,7 @@ seem unfamiliar, refer to this
|
||||
|
||||
#### Approval and Request Changes Workflow
|
||||
|
||||
All pull requests require approval from a
|
||||
[Code Owner](https://github.com/electron/electron/blob/main/.github/CODEOWNERS)
|
||||
All pull requests require approval from a [Code Owner](../../.github/CODEOWNERS)
|
||||
of the area you modified in order to land. Whenever a maintainer reviews a pull
|
||||
request they may request changes. These may be small, such as fixing a typo, or
|
||||
may involve substantive changes. Such requests are intended to be helpful, but
|
||||
|
||||
@@ -10,7 +10,7 @@ to understand the source code better.
|
||||
## Project structure
|
||||
|
||||
Electron is a complex project containing multiple upstream dependencies, which are tracked in source
|
||||
control via the [`DEPS`](https://github.com/electron/electron/blob/main/DEPS) file. When
|
||||
control via the [`DEPS`](../../DEPS) file. When
|
||||
[initializing a local Electron checkout](./build-instructions-gn.md), Electron's source code is just one
|
||||
of many nested folders within the project root.
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ hide_title: false
|
||||
---
|
||||
|
||||
After creating an [application distribution](application-distribution.md), the
|
||||
app's source code are usually bundled into an [ASAR archive](https://github.com/electron/asar),
|
||||
app's source code is usually bundled into an [ASAR archive](https://github.com/electron/asar),
|
||||
which is a simple extensive archive format designed for Electron apps. By bundling the app
|
||||
we can mitigate issues around long path names on Windows, speed up `require` and conceal your source
|
||||
code from cursory inspection.
|
||||
@@ -134,7 +134,7 @@ underlying system calls, Electron will extract the needed file into a
|
||||
temporary file and pass the path of the temporary file to the APIs to make them
|
||||
work. This adds a little overhead for those APIs.
|
||||
|
||||
APIs that requires extra unpacking are:
|
||||
APIs that require extra unpacking are:
|
||||
|
||||
* `child_process.execFile`
|
||||
* `child_process.execFileSync`
|
||||
|
||||
@@ -15,6 +15,14 @@ Currently, ASAR integrity checking is supported on:
|
||||
* macOS as of `electron>=16.0.0`
|
||||
* Windows as of `electron>=30.0.0`
|
||||
|
||||
> [!NOTE]
|
||||
> ASAR integrity is fully supported in Mac App Store (MAS) builds and is recommended
|
||||
> as a best practice. While MAS-installed applications have their `Resources/` folder
|
||||
> protected by the system (owned by root), ASAR integrity still provides an additional
|
||||
> layer of security. It is especially important if you use Electron's MAS build but
|
||||
> distribute your app through channels other than the Mac App Store (such as direct
|
||||
> download), since those installations won't have the system-level read-only protections.
|
||||
|
||||
In order to enable ASAR integrity checking, you also need to ensure that your `app.asar` file
|
||||
was generated by a version of the `@electron/asar` npm package that supports ASAR integrity.
|
||||
|
||||
@@ -24,7 +32,7 @@ All versions of `@electron/asar` support ASAR integrity.
|
||||
## How it works
|
||||
|
||||
Each ASAR archive contains a JSON string header. The header format includes an `integrity` object
|
||||
that contain a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
|
||||
that contains a hex encoded hash of the entire archive as well as an array of hex encoded hashes for each
|
||||
block of `blockSize` bytes.
|
||||
|
||||
```json
|
||||
|
||||
@@ -203,7 +203,7 @@ test('launch app', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
After that, you will access to an instance of Playwright's `ElectronApp` class. This
|
||||
After that, you will have access to an instance of Playwright's `ElectronApp` class. This
|
||||
is a powerful class that has access to main process modules for example:
|
||||
|
||||
```js {5-10} @ts-nocheck
|
||||
@@ -237,7 +237,7 @@ test('save screenshot', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
Putting all this together using the Playwright test-runner, let's create a `example.spec.js`
|
||||
Putting all this together using the Playwright test-runner, let's create an `example.spec.js`
|
||||
test file with a single test and assertion:
|
||||
|
||||
```js title='example.spec.js' @ts-nocheck
|
||||
@@ -377,7 +377,7 @@ class TestDriver {
|
||||
module.exports = { TestDriver }
|
||||
```
|
||||
|
||||
In your app code, can then write a simple handler to receive RPC calls:
|
||||
In your app code, you can then write a simple handler to receive RPC calls:
|
||||
|
||||
```js title='main.js'
|
||||
const METHODS = {
|
||||
|
||||
@@ -17,7 +17,7 @@ run them, users need to go through multiple advanced and manual steps.
|
||||
|
||||
If you are building an Electron app that you intend to package and distribute,
|
||||
it should be code signed. The Electron ecosystem tooling makes codesigning your
|
||||
apps straightforward - this documentation explains how sign your apps on both
|
||||
apps straightforward - this documentation explains how to sign your apps on both
|
||||
Windows and macOS.
|
||||
|
||||
## Signing & notarizing macOS builds
|
||||
|
||||
@@ -110,7 +110,7 @@ const win = new BrowserWindow({
|
||||
#### Show and hide the traffic lights programmatically _macOS_
|
||||
|
||||
You can also show and hide the traffic lights programmatically from the main process.
|
||||
The `win.setWindowButtonVisibility` forces traffic lights to be show or hidden depending
|
||||
The `win.setWindowButtonVisibility` forces traffic lights to be shown or hidden depending
|
||||
on the value of its boolean parameter.
|
||||
|
||||
```js title='main.js'
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
By default, windows are dragged using the title bar provided by the OS chrome. Apps
|
||||
that remove the default title bar need to use the `app-region` CSS property to define
|
||||
specific areas that can be used to drag the window. Setting `app-region: drag` marks
|
||||
a rectagular area as draggable.
|
||||
a rectangular area as draggable.
|
||||
|
||||
It is important to note that draggable areas ignore all pointer events. For example,
|
||||
a button element that overlaps a draggable region will not emit mouse clicks or mouse
|
||||
enter/exit events within that overlapping area. Setting `app-region: no-drag` reenables
|
||||
pointer events by excluding a rectagular area from a draggable region.
|
||||
pointer events by excluding a rectangular area from a draggable region.
|
||||
|
||||
To make the whole window draggable, you can add `app-region: drag` as
|
||||
`body`'s style:
|
||||
|
||||
@@ -29,7 +29,7 @@ be updated accordingly.
|
||||
In macOS 10.14 Mojave, Apple introduced a new [system-wide dark mode][system-wide-dark-mode]
|
||||
for all macOS computers. If your Electron app has a dark mode, you can make it
|
||||
follow the system-wide dark mode setting using
|
||||
[the `nativeTheme` api](../api/native-theme.md).
|
||||
[the `nativeTheme` API](../api/native-theme.md).
|
||||
|
||||
In macOS 10.15 Catalina, Apple introduced a new "automatic" dark mode option
|
||||
for all macOS computers. In order for the `nativeTheme.shouldUseDarkColors` and
|
||||
|
||||
@@ -197,4 +197,4 @@ Somewhere in the Electron binary, there will be a sequence of bytes that look li
|
||||
|
||||
To flip a fuse, you find its position in the fuse wire and change it to "0" or "1" depending on the state you'd like.
|
||||
|
||||
You can view the current schema [here](https://github.com/electron/electron/blob/main/build/fuses/fuses.json5).
|
||||
You can view the current schema [here](../../build/fuses/fuses.json5).
|
||||
|
||||
@@ -171,7 +171,7 @@ sections.
|
||||
|
||||
In the main process, we'll be creating a `handleFileOpen()` function that calls
|
||||
`dialog.showOpenDialog` and returns the value of the file path selected by the user. This function
|
||||
is used as a callback whenever an `ipcRender.invoke` message is sent through the `dialog:openFile`
|
||||
is used as a callback whenever an `ipcRenderer.invoke` message is sent through the `dialog:openFile`
|
||||
channel from the renderer process. The return value is then returned as a Promise to the original
|
||||
`invoke` call.
|
||||
|
||||
@@ -446,7 +446,7 @@ After loading the preload script, your renderer process should have access to th
|
||||
We don't directly expose the whole `ipcRenderer.on` API for [security reasons][]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
Also don't just pass the callback to `ipcRenderer.on` as this will leak `ipcRenderer` via `event.sender`.
|
||||
Use a custom handler that invoke the `callback` only with the desired arguments.
|
||||
Use a custom handler that invokes the `callback` only with the desired arguments.
|
||||
:::
|
||||
|
||||
:::info
|
||||
|
||||
@@ -10,7 +10,7 @@ hide_title: false
|
||||
## Accelerators
|
||||
|
||||
Accelerators are strings that can be used to represent keyboard shortcuts throughout your Electron.
|
||||
These strings can contain multiple modifiers keys and a single key code joined by the `+` character.
|
||||
These strings can contain multiple modifier keys and a single key code joined by the `+` character.
|
||||
|
||||
> [!NOTE]
|
||||
> Accelerators are **case-insensitive**.
|
||||
|
||||
@@ -62,9 +62,9 @@ const createWindow = () => {
|
||||
}
|
||||
```
|
||||
|
||||
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
|
||||
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
|
||||
|
||||
This code will be different in Windows and Linux compared to MacOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
|
||||
This code will be different in Windows and Linux compared to macOS. This is due to both platforms emitting the `second-instance` event rather than the `open-url` event and Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
|
||||
|
||||
#### Windows and Linux code:
|
||||
|
||||
@@ -91,7 +91,7 @@ if (!gotTheLock) {
|
||||
}
|
||||
```
|
||||
|
||||
#### MacOS code:
|
||||
#### macOS code:
|
||||
|
||||
```js @ts-type={createWindow:()=>void}
|
||||
// This method will be called when Electron has finished
|
||||
|
||||
@@ -65,7 +65,7 @@ The full list of certificate types can be found
|
||||
Apps signed with "Apple Development" and "Apple Distribution" certificates can
|
||||
only run under [App Sandbox][app-sandboxing], so they must use the MAS build of
|
||||
Electron. However, the "Developer ID Application" certificate does not have this
|
||||
restrictions, so apps signed with it can use either the normal build or the MAS
|
||||
restriction, so apps signed with it can use either the normal build or the MAS
|
||||
build of Electron.
|
||||
|
||||
#### Legacy certificate names
|
||||
@@ -208,7 +208,7 @@ signAsync({
|
||||
After signing the app with the "Apple Distribution" certificate, you can
|
||||
continue to submit it to Mac App Store.
|
||||
|
||||
However, this guide do not ensure your app will be approved by Apple; you
|
||||
However, this guide does not ensure your app will be approved by Apple; you
|
||||
still need to read Apple's [Submitting Your App][submitting-your-app] guide on
|
||||
how to meet the Mac App Store requirements.
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ Electron application, and this property only exists on macOS.
|
||||
One of the main uses for your app's Dock icon is to expose additional app menus. The Dock menu is
|
||||
triggered by right-clicking or <kbd>Ctrl</kbd>-clicking the app icon. By default, the app's Dock menu
|
||||
will come with system-provided window management utilities, including the ability to show all windows,
|
||||
hide the app, and switch betweeen different open windows.
|
||||
hide the app, and switch between different open windows.
|
||||
|
||||
To set an app-defined custom Dock menu, pass any [Menu](../api/menu.md) instance into the
|
||||
[`dock.setMenu`](../api/dock.md#docksetmenumenu-macos) API.
|
||||
|
||||
@@ -200,7 +200,7 @@ macOS has a number of platform-specific menu roles available. Many of these map
|
||||
|
||||
* `recentDocuments` - The submenu is an "Open Recent" menu.
|
||||
* `clearRecentDocuments` - Map to the [`clearRecentDocuments`](https://developer.apple.com/documentation/appkit/nsdocumentcontroller/clearrecentdocuments(_:)) action.
|
||||
* `shareMenu` - The submenu is [share menu][ShareMenu]. The `sharingItem` property must also be set to indicate the item to share.
|
||||
* `shareMenu` - The submenu is [share menu](../api/share-menu.md). The `sharingItem` property must also be set to indicate the item to share.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> When specifying a `role` on macOS, `label` and `accelerator` are the only
|
||||
|
||||
@@ -1339,7 +1339,7 @@ For developers wanting to learn more, you can refer to the [official N-API docum
|
||||
|
||||
### Putting `cpp_addon.cc` together
|
||||
|
||||
We've now finished the bridge part our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
|
||||
We've now finished the bridge part of our addon - that is, the code that's most concerned with being the bridge between your JavaScript and C++ code (and by contrast, less so actually interacting with the operating system or GTK). After adding all the sections above, your `src/cpp_addon.cc` should look like this:
|
||||
|
||||
```cpp title='src/cpp_addon.cc'
|
||||
#include <napi.h>
|
||||
|
||||
@@ -4,13 +4,13 @@ This tutorial builds on the [general introduction to Native Code and Electron](.
|
||||
|
||||
Specifically, we'll be integrating with two commonly used native Windows libraries:
|
||||
|
||||
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are advanced and alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
|
||||
* `comctl32.lib`, which contains common controls and user interface components. It provides various UI elements like buttons, scrollbars, toolbars, status bars, progress bars, and tree views. As far as GUI development on Windows goes, this library is very low-level and basic - more modern frameworks like WinUI or WPF are more advanced alternatives but require a lot more C++ and Windows version considerations than are useful for this tutorial. This way, we can avoid the many perils of building native interfaces for multiple Windows versions!
|
||||
* `shcore.lib`, a library that provides high-DPI awareness functionality and other Shell-related features around managing displays and UI elements.
|
||||
|
||||
This tutorial will be most useful to those who already have some familiarity with native C++ GUI development on Windows. You should have experience with basic window classes and procedures, like `WNDCLASSEXW` and `WindowProc` functions. You should also be familiar with the Windows message loop, which is the heart of any native application - our code will be using `GetMessage`, `TranslateMessage`, and `DispatchMessage` to handle messages. Lastly, we'll be using (but not explaining) standard Win32 controls like `WC_EDITW` or `WC_BUTTONW`.
|
||||
|
||||
> [!NOTE]
|
||||
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particular for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
|
||||
> If you're not familiar with C++ GUI development on Windows, we recommend Microsoft's excellent documentation and guides, particularly for beginners. "[Get Started with Win32 and C++](https://learn.microsoft.com/en-us/windows/win32/learnwin32/learn-to-program-for-windows)" is a great introduction.
|
||||
|
||||
## Requirements
|
||||
|
||||
@@ -1333,7 +1333,7 @@ npm run build
|
||||
|
||||
## Conclusion
|
||||
|
||||
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of things we've done here are:
|
||||
You've now built a complete native Node.js addon for Windows using C++ and the Win32 API. Some of the things we've done here are:
|
||||
|
||||
1. Creating a native Windows GUI from C++
|
||||
2. Implementing a Todo list application with Add, Edit, and Delete functionality
|
||||
|
||||
@@ -1167,7 +1167,7 @@ The approach demonstrated here allows you to:
|
||||
* Setting up bidirectional communication using callbacks and events
|
||||
* Configuring a custom build process to compile Swift code
|
||||
|
||||
For more information on developing with Swift and Swift, refer to Apple's developer documentation:
|
||||
For more information on developing with Swift and SwiftUI, refer to Apple's developer documentation:
|
||||
|
||||
* [Swift Programming Language](https://developer.apple.com/swift/)
|
||||
* [SwiftUI Framework](https://developer.apple.com/documentation/swiftui)
|
||||
|
||||
@@ -36,8 +36,8 @@ setting.
|
||||
This is an advanced feature requiring a native node module to work with your own code.
|
||||
The frames are directly copied in GPU textures, thus this mode is very fast because
|
||||
there's no CPU-GPU memory copies overhead, and you can directly import the shared
|
||||
texture to your own rendering program. You can read more details at
|
||||
[here](https://github.com/electron/electron/blob/main/shell/browser/osr/README.md).
|
||||
texture to your own rendering program. You can read more details
|
||||
[here](../../shell/common/api/shared_texture/README.md).
|
||||
|
||||
2. Use CPU shared memory bitmap
|
||||
|
||||
|
||||
@@ -294,7 +294,7 @@ particularly useful if users complain about your app sometimes "stuttering".
|
||||
|
||||
Generally speaking, all advice for building performant web apps for modern
|
||||
browsers apply to Electron's renderers, too. The two primary tools at your
|
||||
disposal are currently `requestIdleCallback()` for small operations and
|
||||
disposal are currently `requestIdleCallback()` for small operations and
|
||||
`Web Workers` for long-running operations.
|
||||
|
||||
_`requestIdleCallback()`_ allows developers to queue up a function to be
|
||||
@@ -360,7 +360,7 @@ turning into a desktop application. As web developers, we are used to loading
|
||||
resources from a variety of content delivery networks. Now that you are
|
||||
shipping a proper desktop application, attempt to "cut the cord" where possible
|
||||
and avoid letting your users wait for resources that never change and could
|
||||
easily be included in your app.
|
||||
easily be included in your app.
|
||||
|
||||
A typical example is Google Fonts. Many developers make use of Google's
|
||||
impressive collection of free fonts, which comes with a content delivery
|
||||
|
||||
@@ -113,7 +113,7 @@ For a full list of Electron's main process modules, check out our API documentat
|
||||
|
||||
Each Electron app spawns a separate renderer process for each open `BrowserWindow`
|
||||
(and each web embed). As its name implies, a renderer is responsible for
|
||||
_rendering_ web content. For all intents and purposes, code ran in renderer processes
|
||||
_rendering_ web content. For all intents and purposes, code run in renderer processes
|
||||
should behave according to web standards (insofar as Chromium does, at least).
|
||||
|
||||
Therefore, all user interfaces and app functionality within a single browser
|
||||
|
||||
@@ -9,7 +9,7 @@ toc_max_heading_level: 3
|
||||
|
||||
:::info Reporting security issues
|
||||
For information on how to properly disclose an Electron vulnerability,
|
||||
see [SECURITY.md](https://github.com/electron/electron/blob/main/SECURITY.md).
|
||||
see [SECURITY.md](../../SECURITY.md).
|
||||
|
||||
For upstream Chromium vulnerabilities: Electron keeps up to date with alternating
|
||||
Chromium releases. For more information, see the
|
||||
@@ -771,7 +771,7 @@ ipcMain.handle('get-secrets', (e) => {
|
||||
})
|
||||
|
||||
function validateSender (frame) {
|
||||
// Value the host of the URL using an actual URL parser and an allowlist
|
||||
// Validate the host of the URL using an actual URL parser and an allowlist
|
||||
if ((new URL(frame.url)).host === 'electronjs.org') return true
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
* For information on supported releases, see the [Electron Releases](./electron-timelines.md) doc.
|
||||
* For community support on Electron, see the [Community page](https://www.electronjs.org/community).
|
||||
* For platform support info, see the [README](https://github.com/electron/electron/blob/main/README.md).
|
||||
* For platform support info, see the [README](../../README.md).
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
Being based on Chromium, Electron requires a display driver to function.
|
||||
If Chromium can't find a display driver, Electron will fail to launch -
|
||||
and therefore not executing any of your tests, regardless of how you are running
|
||||
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar Systems
|
||||
and therefore not execute any of your tests, regardless of how you are running
|
||||
them. Testing Electron-based apps on Travis, CircleCI, Jenkins or similar systems
|
||||
requires therefore a little bit of configuration. In essence, we need to use
|
||||
a virtual display driver.
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ following JSON format:
|
||||
"updateTo": {
|
||||
"version": "1.2.1",
|
||||
"pub_date": "2023-09-18T12:29:53+01:00",
|
||||
"notes": "Theses are some release notes innit",
|
||||
"notes": "These are some release notes innit",
|
||||
"name": "1.2.1",
|
||||
"url": "https://mycompany.example.com/myapp/releases/myrelease"
|
||||
}
|
||||
@@ -54,7 +54,7 @@ following JSON format:
|
||||
"updateTo": {
|
||||
"version": "1.2.3",
|
||||
"pub_date": "2024-09-18T12:29:53+01:00",
|
||||
"notes": "Theses are some more release notes innit",
|
||||
"notes": "These are some more release notes innit",
|
||||
"name": "1.2.3",
|
||||
"url": "https://mycompany.example.com/myapp/releases/myrelease3"
|
||||
}
|
||||
@@ -307,7 +307,7 @@ app update. All other properties in the object are optional.
|
||||
{
|
||||
"url": "https://your-static.storage/your-app-1.2.3-darwin.zip",
|
||||
"name": "1.2.3",
|
||||
"notes": "Theses are some release notes innit",
|
||||
"notes": "These are some release notes innit",
|
||||
"pub_date": "2024-09-18T12:29:53+01:00"
|
||||
}
|
||||
```
|
||||
|
||||
@@ -149,7 +149,7 @@ for an example delay-load hook if you're implementing your own.
|
||||
native Node modules with prebuilt binaries for multiple versions of Node
|
||||
and Electron.
|
||||
|
||||
If the `prebuild`-powered module provide binaries for the usage in Electron,
|
||||
If the `prebuild`-powered module provides binaries for the usage in Electron,
|
||||
make sure to omit `--build-from-source` and the `npm_config_build_from_source`
|
||||
environment variable in order to take full advantage of the prebuilt binaries.
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ To test your app, use a Windows on Arm device running Windows 10 (version 1903 o
|
||||
|
||||
### Node.js/node-gyp
|
||||
|
||||
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
|
||||
[Node.js v12.9.0 or later is recommended.](https://nodejs.org/en/) If updating to a new version of Node is undesirable, you can instead [update npm's copy of node-gyp manually](https://github.com/nodejs/node-gyp/wiki/Updating-npm's-bundled-node-gyp) to version 5.0.2 or later, which contains the required changes to compile native modules for Arm.
|
||||
|
||||
### Visual Studio 2017
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ system.
|
||||
|
||||
Before running the CLI for the first time, you will have to setup the "Windows Desktop App
|
||||
Converter". This will take a few minutes, but don't worry - you only have to do
|
||||
this once. Download and Desktop App Converter from [here][app-converter].
|
||||
this once. Download the Desktop App Converter from [here][app-converter].
|
||||
You will receive two files: `DesktopAppConverter.zip` and `BaseImage-14316.wim`.
|
||||
|
||||
1. Unzip `DesktopAppConverter.zip`. From an elevated PowerShell (opened with
|
||||
|
||||
@@ -79,6 +79,8 @@ filenames = {
|
||||
"shell/browser/notifications/win/notification_presenter_win.h",
|
||||
"shell/browser/notifications/win/windows_toast_notification.cc",
|
||||
"shell/browser/notifications/win/windows_toast_notification.h",
|
||||
"shell/browser/notifications/win/windows_toast_activator.cc",
|
||||
"shell/browser/notifications/win/windows_toast_activator.h",
|
||||
"shell/browser/relauncher_win.cc",
|
||||
"shell/browser/ui/certificate_trust_win.cc",
|
||||
"shell/browser/ui/file_dialog_win.cc",
|
||||
|
||||
@@ -57,7 +57,8 @@
|
||||
"url": "^0.11.4",
|
||||
"webpack": "^5.95.0",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"wrapper-webpack-plugin": "^2.2.0"
|
||||
"wrapper-webpack-plugin": "^2.2.0",
|
||||
"yaml": "^2.8.1"
|
||||
},
|
||||
"private": true,
|
||||
"scripts": {
|
||||
@@ -73,7 +74,7 @@
|
||||
"lint:gn": "node ./script/lint.js --gn",
|
||||
"lint:docs": "remark docs -qf && npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:ts-check-js-in-markdown && npm run lint:docs-fiddles && npm run lint:docs-relative-links && npm run lint:markdown && npm run lint:api-history",
|
||||
"lint:docs-fiddles": "standard \"docs/fiddles/**/*.js\"",
|
||||
"lint:docs-relative-links": "lint-roller-markdown-links --root docs \"**/*.md\"",
|
||||
"lint:docs-relative-links": "lint-roller-markdown-links --resource-root . --root docs \"**/*.md\"",
|
||||
"lint:markdown": "node ./script/lint.js --md",
|
||||
"lint:ts-check-js-in-markdown": "lint-roller-markdown-ts-check --root docs \"**/*.md\" --ignore \"breaking-changes.md\"",
|
||||
"lint:js-in-markdown": "lint-roller-markdown-standard --root docs \"**/*.md\"",
|
||||
@@ -132,6 +133,10 @@
|
||||
"DEPS": [
|
||||
"node script/gen-hunspell-filenames.js",
|
||||
"node script/gen-libc++-filenames.js"
|
||||
],
|
||||
".github/workflows/pipeline-segment-electron-build.yml": [
|
||||
"node script/copy-pipeline-segment-publish.js",
|
||||
"git add .github/workflows/pipeline-segment-electron-publish.yml"
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
|
||||
@@ -145,3 +145,6 @@ viz_create_isbufferqueuesupportedandenabled.patch
|
||||
viz_fix_visual_artifacts_while_resizing_window_with_dcomp.patch
|
||||
fix_os_crypt_async_cookie_encryption.patch
|
||||
graphite_handle_out_of_order_recording_errors.patch
|
||||
move_wayland_pointer_lock_overrides_to_common_code.patch
|
||||
loaf_add_feature_to_enable_sourceurl_for_all_protocols.patch
|
||||
fix_update_dbus_signal_signature_for_xdg_globalshortcuts_portal.patch
|
||||
|
||||
@@ -4,7 +4,7 @@ Date: Wed, 28 Jun 2023 21:11:40 +0900
|
||||
Subject: fix: harden blink::ScriptState::MaybeFrom
|
||||
|
||||
NOTE: since https://chromium-review.googlesource.com/c/chromium/src/+/6973697
|
||||
the patch is only needed for 32-bit builds.
|
||||
the patch is only needed for 32-bit builds or builds where the V8 sandbox is disabled.
|
||||
|
||||
This is needed as side effect of https://chromium-review.googlesource.com/c/chromium/src/+/4609446
|
||||
which now gets blink::ExecutionContext from blink::ScriptState
|
||||
@@ -56,18 +56,18 @@ index cecf528475cb832ed1876381878eade582bc83d6..71308b2d963c2d083328aad6be356dc5
|
||||
|
||||
enum EmbedderDataTag : uint16_t {
|
||||
diff --git a/third_party/blink/renderer/platform/bindings/script_state.cc b/third_party/blink/renderer/platform/bindings/script_state.cc
|
||||
index 8b6522c9299bef5ab766795b64a1ba30bc382a12..a714aeb8a62886bedb3820b33b49b1ebdb9c7cc0 100644
|
||||
index 8b6522c9299bef5ab766795b64a1ba30bc382a12..4615dc04a3814a096898a36c7bbeb30f960a8b4d 100644
|
||||
--- a/third_party/blink/renderer/platform/bindings/script_state.cc
|
||||
+++ b/third_party/blink/renderer/platform/bindings/script_state.cc
|
||||
@@ -14,6 +14,12 @@ namespace blink {
|
||||
|
||||
ScriptState::CreateCallback ScriptState::s_create_callback_ = nullptr;
|
||||
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+int const ScriptState::kScriptStateTag = 0x6e6f64;
|
||||
+void* const ScriptState::kScriptStateTagPtr = const_cast<void*>(
|
||||
+ static_cast<const void*>(&ScriptState::kScriptStateTag));
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
+
|
||||
// static
|
||||
void ScriptState::SetCreateCallback(CreateCallback create_callback) {
|
||||
@@ -76,10 +76,10 @@ index 8b6522c9299bef5ab766795b64a1ba30bc382a12..a714aeb8a62886bedb3820b33b49b1eb
|
||||
context_.SetWeak(this, &OnV8ContextCollectedCallback);
|
||||
context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this,
|
||||
gin::kBlinkScriptState);
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ context->SetAlignedPointerInEmbedderData(
|
||||
+ kV8ContextPerContextDataTagIndex, ScriptState::kScriptStateTagPtr, v8::kEmbedderDataTypeTagDefault);
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
RendererResourceCoordinator::Get()->OnScriptStateCreated(this,
|
||||
execution_context);
|
||||
}
|
||||
@@ -87,15 +87,15 @@ index 8b6522c9299bef5ab766795b64a1ba30bc382a12..a714aeb8a62886bedb3820b33b49b1eb
|
||||
// Cut the reference from V8 context to ScriptState.
|
||||
GetContext()->SetAlignedPointerInEmbedderData(
|
||||
kV8ContextPerContextDataIndex, nullptr, gin::kBlinkScriptState);
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ GetContext()->SetAlignedPointerInEmbedderData(
|
||||
+ kV8ContextPerContextDataTagIndex, nullptr, v8::kEmbedderDataTypeTagDefault);
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
reference_from_v8_context_.Clear();
|
||||
|
||||
// Cut the reference from ScriptState to V8 context.
|
||||
diff --git a/third_party/blink/renderer/platform/bindings/script_state.h b/third_party/blink/renderer/platform/bindings/script_state.h
|
||||
index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f964e5c28 100644
|
||||
index 5ccdf26cead17031d510589b74288cbe79692779..54ede003ebe0a46e624c9d67f7272b8898bbc83e 100644
|
||||
--- a/third_party/blink/renderer/platform/bindings/script_state.h
|
||||
+++ b/third_party/blink/renderer/platform/bindings/script_state.h
|
||||
@@ -6,6 +6,7 @@
|
||||
@@ -110,7 +110,7 @@ index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f
|
||||
kV8ContextPerContextDataIndex) {
|
||||
return nullptr;
|
||||
}
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ if (context->GetNumberOfEmbedderDataFields() <=
|
||||
+ kV8ContextPerContextDataTagIndex ||
|
||||
+ context->GetAlignedPointerFromEmbedderData(
|
||||
@@ -119,7 +119,7 @@ index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f
|
||||
+ ScriptState::kScriptStateTagPtr) {
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
ScriptState* script_state =
|
||||
static_cast<ScriptState*>(context->GetAlignedPointerFromEmbedderData(
|
||||
isolate, kV8ContextPerContextDataIndex, gin::kBlinkScriptState));
|
||||
@@ -127,13 +127,13 @@ index 5ccdf26cead17031d510589b74288cbe79692779..bf3023d5305c05c5d92953b5bf5f655f
|
||||
static_cast<int>(gin::kPerContextDataStartIndex) +
|
||||
static_cast<int>(gin::kEmbedderBlink);
|
||||
|
||||
+#if defined(ARCH_CPU_32_BITS)
|
||||
+#if !defined(V8_ENABLE_SANDBOX)
|
||||
+ static void* const kScriptStateTagPtr;
|
||||
+ static int const kScriptStateTag;
|
||||
+ static constexpr int kV8ContextPerContextDataTagIndex =
|
||||
+ static_cast<int>(gin::kPerContextDataStartIndex) +
|
||||
+ static_cast<int>(gin::kEmbedderBlinkTag);
|
||||
+#endif // defined(ARCH_CPU_32_BITS)
|
||||
+#endif // !defined(V8_ENABLE_SANDBOX)
|
||||
+
|
||||
// For accessing information about the last script compilation via
|
||||
// internals.idl.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 16 Feb 2026 22:33:57 +0100
|
||||
Subject: fix: update DBus signal signature for XDG GlobalShortcuts portal
|
||||
|
||||
Refs https://chromium-review.googlesource.com/c/chromium/src/+/7143562
|
||||
|
||||
The Activated signal from the XDG GlobalShortcuts portal has signature "osta{sv}",
|
||||
but ConnectToSignal was declared with "ost". The strict ReadMessage parser
|
||||
fails on the extra trailing options vardict. Fix by updating the signature
|
||||
to match the spec.
|
||||
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc
|
||||
index 505e59edad7acb41f272f1e323cfd90744e4701b..ead80cfac902a7630cf502b03cb7d2ee048944ac 100644
|
||||
--- a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc
|
||||
+++ b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.cc
|
||||
@@ -78,7 +78,7 @@ void GlobalAcceleratorListenerLinux::OnServiceStarted(bool service_started) {
|
||||
global_shortcuts_proxy_ = bus_->GetObjectProxy(
|
||||
kPortalServiceName, dbus::ObjectPath(kPortalObjectPath));
|
||||
|
||||
- dbus_utils::ConnectToSignal<"ost">(
|
||||
+ dbus_utils::ConnectToSignal<"osta{sv}">(
|
||||
global_shortcuts_proxy_, kGlobalShortcutsInterface, kSignalActivated,
|
||||
base::BindRepeating(&GlobalAcceleratorListenerLinux::OnActivatedSignal,
|
||||
weak_ptr_factory_.GetWeakPtr()),
|
||||
@@ -299,13 +299,14 @@ void GlobalAcceleratorListenerLinux::OnBindShortcuts(
|
||||
}
|
||||
|
||||
void GlobalAcceleratorListenerLinux::OnActivatedSignal(
|
||||
- dbus_utils::ConnectToSignalResultSig<"ost"> result) {
|
||||
+ dbus_utils::ConnectToSignalResultSig<"osta{sv}"> result) {
|
||||
if (!result.has_value()) {
|
||||
LOG(ERROR) << "Failed to parse Activated signal.";
|
||||
return;
|
||||
}
|
||||
|
||||
- auto [session_handle, shortcut_id, timestamp] = std::move(result.value());
|
||||
+ auto [session_handle, shortcut_id, timestamp, options] =
|
||||
+ std::move(result.value());
|
||||
|
||||
// Only process the signal if it comes from our current session.
|
||||
if (!session_proxy_ || session_proxy_->object_path() != session_handle) {
|
||||
diff --git a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h
|
||||
index 3838de75a0a3791f774e2ddedec0f6c7f2f30157..91a205e6c526aa02b46b1590fa427e8875a67280 100644
|
||||
--- a/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h
|
||||
+++ b/ui/base/accelerators/global_accelerator_listener/global_accelerator_listener_linux.h
|
||||
@@ -97,7 +97,8 @@ class GlobalAcceleratorListenerLinux : public GlobalAcceleratorListener {
|
||||
base::expected<dbus_xdg::Dictionary, dbus_xdg::ResponseError> results);
|
||||
|
||||
// Callbacks for DBus signals.
|
||||
- void OnActivatedSignal(dbus_utils::ConnectToSignalResultSig<"ost"> result);
|
||||
+ void OnActivatedSignal(
|
||||
+ dbus_utils::ConnectToSignalResultSig<"osta{sv}"> result);
|
||||
|
||||
void OnSignalConnected(const std::string& interface_name,
|
||||
const std::string& signal_name,
|
||||
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Niklas Wenzel <dev@nikwen.de>
|
||||
Date: Wed, 4 Feb 2026 06:02:40 -0800
|
||||
Subject: LoAF: Add feature to enable sourceURL for all protocols
|
||||
|
||||
Backports https://crrev.com/c/7510894 (minus the test changes).
|
||||
|
||||
Can be removed when that CL is included via a Chromium roll.
|
||||
|
||||
Change-Id: Id5e58a151b13cc0ac054f4ec237b038255d683fd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7510894
|
||||
Commit-Queue: Noam Rosenthal <nrosenthal@google.com>
|
||||
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
|
||||
Reviewed-by: Noam Rosenthal <nrosenthal@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1579397}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
|
||||
index 0d621b6b397a2f8c33732a7bc1a68830539438be..f0749e9a9db7c5cd6b9d12440800241a14640cdd 100644
|
||||
--- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.cc
|
||||
@@ -520,8 +520,15 @@ void AnimationFrameTimingMonitor::Trace(Visitor* visitor) const {
|
||||
visitor->Trace(frame_handling_input_);
|
||||
}
|
||||
|
||||
+BASE_FEATURE(kAlwaysLogLOAFURL, base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
+
|
||||
namespace {
|
||||
+
|
||||
bool ShouldAllowScriptURL(const String& url) {
|
||||
+ if (base::FeatureList::IsEnabled(kAlwaysLogLOAFURL)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
KURL kurl(url);
|
||||
return kurl.ProtocolIsData() || kurl.ProtocolIsInHTTPFamily() ||
|
||||
kurl.ProtocolIs("blob") || kurl.IsEmpty();
|
||||
diff --git a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
|
||||
index f2fe39be2db525d89fcd9787c2ae9285babab26d..c395cf39d404f6c4f6f6e23c9fb8dfe92151a7d2 100644
|
||||
--- a/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
|
||||
+++ b/third_party/blink/renderer/core/frame/animation_frame_timing_monitor.h
|
||||
@@ -22,6 +22,11 @@ class TimeTicks;
|
||||
|
||||
namespace blink {
|
||||
|
||||
+// When enabled, long-animation-frame events will always include the sourceURL,
|
||||
+// regardless of protocol. This is useful during development when using `file:`
|
||||
+// URLs or custom protocols defined by embedders.
|
||||
+CORE_EXPORT BASE_DECLARE_FEATURE(kAlwaysLogLOAFURL);
|
||||
+
|
||||
class LocalFrame;
|
||||
|
||||
// Monitors long-animation-frame timing (LoAF).
|
||||
@@ -1,13 +1,13 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Thu, 7 Apr 2022 20:30:16 +0900
|
||||
Subject: Make gtk::GetLibGdkPixbuf public
|
||||
Subject: Make gtk::GetLibGdkPixbuf and gtk::GetLibGdk public
|
||||
|
||||
Allows embedders to get a handle to the gdk_pixbuf
|
||||
library already loaded in the process.
|
||||
Allows embedders to get handles to the gdk_pixbuf
|
||||
and gdk libraries already loaded in the process.
|
||||
|
||||
diff --git a/ui/gtk/gtk_compat.cc b/ui/gtk/gtk_compat.cc
|
||||
index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..c06af1c03487fafe76fde3bfa157a7d265e2f3a0 100644
|
||||
index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..86524a419606bea3e7d090415fda8f2d8ce24df2 100644
|
||||
--- a/ui/gtk/gtk_compat.cc
|
||||
+++ b/ui/gtk/gtk_compat.cc
|
||||
@@ -78,11 +78,6 @@ void* GetLibGio() {
|
||||
@@ -22,7 +22,7 @@ index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..c06af1c03487fafe76fde3bfa157a7d2
|
||||
void* GetLibGdk3() {
|
||||
static void* libgdk3 = DlOpen("libgdk-3.so.0");
|
||||
return libgdk3;
|
||||
@@ -175,6 +170,11 @@ gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
|
||||
@@ -175,6 +170,15 @@ gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
|
||||
|
||||
} // namespace
|
||||
|
||||
@@ -30,20 +30,27 @@ index e05b4f2eb1b22d5a647cb020bae4e4052a2e735c..c06af1c03487fafe76fde3bfa157a7d2
|
||||
+ static void* libgdk_pixbuf = DlOpen("libgdk_pixbuf-2.0.so.0");
|
||||
+ return libgdk_pixbuf;
|
||||
+}
|
||||
+
|
||||
+void* GetLibGdk() {
|
||||
+ return GtkCheckVersion(4) ? GetLibGtk4() : GetLibGdk3();
|
||||
+}
|
||||
+
|
||||
bool LoadGtk(ui::LinuxUiBackend backend) {
|
||||
static bool loaded = LoadGtkImpl(backend);
|
||||
return loaded;
|
||||
diff --git a/ui/gtk/gtk_compat.h b/ui/gtk/gtk_compat.h
|
||||
index 841e2e8fcdbe2da4aac487badd4d352476e461a2..e458df649546fa3bee10e24f0edac147186cc152 100644
|
||||
index 841e2e8fcdbe2da4aac487badd4d352476e461a2..043c3ab4dde02ca71798034e8cb2b3f2d2677af7 100644
|
||||
--- a/ui/gtk/gtk_compat.h
|
||||
+++ b/ui/gtk/gtk_compat.h
|
||||
@@ -42,6 +42,9 @@ using SkColor = uint32_t;
|
||||
@@ -42,6 +42,12 @@ using SkColor = uint32_t;
|
||||
|
||||
namespace gtk {
|
||||
|
||||
+// Get handle to the currently loaded gdk_pixbuf library in the process.
|
||||
+void* GetLibGdkPixbuf();
|
||||
+
|
||||
+// Get handle to the currently loaded gdk library in the process.
|
||||
+void* GetLibGdk();
|
||||
+
|
||||
// Loads libgtk and related libraries and returns true on success.
|
||||
bool LoadGtk(ui::LinuxUiBackend backend);
|
||||
|
||||
@@ -516,7 +516,7 @@ index 020050de162705651b4eb8378880cd4eb017d46c..2d3554861a570271d6f9b9a2c8b1de53
|
||||
// The NSWindow used by BridgedNativeWidget. Provides hooks into AppKit that
|
||||
// can only be accomplished by overriding methods.
|
||||
diff --git a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6b192912c 100644
|
||||
index a474e70cf3c10405b6f94f129f5a7312bb81fd73..adaff0f3d676eeaef93ac9a4a3b55fc0e572d33b 100644
|
||||
--- a/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
+++ b/components/remote_cocoa/app_shim/native_widget_mac_nswindow.mm
|
||||
@@ -21,6 +21,7 @@
|
||||
@@ -553,7 +553,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
@end
|
||||
|
||||
struct NSEdgeAndCornerThicknesses {
|
||||
@@ -158,13 +163,17 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
|
||||
@@ -158,13 +163,30 @@ - (void)cr_mouseDownOnFrameView:(NSEvent*)event;
|
||||
@implementation NSView (CRFrameViewAdditions)
|
||||
// If a mouseDown: falls through to the frame view, turn it into a window drag.
|
||||
- (void)cr_mouseDownOnFrameView:(NSEvent*)event {
|
||||
@@ -561,6 +561,19 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
if ([self.window _resizeDirectionForMouseLocation:event.locationInWindow] !=
|
||||
-1)
|
||||
return;
|
||||
+#else
|
||||
+ // For MAS builds, approximate the resize direction check.
|
||||
+ if (self.window.styleMask & NSWindowStyleMaskResizable) {
|
||||
+ constexpr CGFloat kResizeThreshold = 5.0;
|
||||
+ NSPoint location = event.locationInWindow;
|
||||
+ NSRect frame = self.window.frame;
|
||||
+ CGFloat width = NSWidth(frame);
|
||||
+ CGFloat height = NSHeight(frame);
|
||||
+ if (location.x < kResizeThreshold || location.x > width - kResizeThreshold ||
|
||||
+ location.y < kResizeThreshold || location.y > height - kResizeThreshold) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
+#endif
|
||||
[self.window performWindowDragWithEvent:event];
|
||||
}
|
||||
@@ -571,7 +584,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
@implementation NativeWidgetMacNSWindowTitledFrame
|
||||
- (void)mouseDown:(NSEvent*)event {
|
||||
if (self.window.isMovable)
|
||||
@@ -192,6 +201,8 @@ - (BOOL)usesCustomDrawing {
|
||||
@@ -192,6 +214,8 @@ - (BOOL)usesCustomDrawing {
|
||||
}
|
||||
@end
|
||||
|
||||
@@ -580,7 +593,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
@implementation NativeWidgetMacNSWindow {
|
||||
@private
|
||||
CommandDispatcher* __strong _commandDispatcher;
|
||||
@@ -241,6 +252,7 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
|
||||
@@ -241,6 +265,7 @@ - (instancetype)initWithContentRect:(NSRect)contentRect
|
||||
// bubbles and the find bar, but these should not be movable.
|
||||
// Instead, let's push this up to the parent window which should be
|
||||
// the browser.
|
||||
@@ -588,7 +601,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
- (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
if (self.parentWindow) {
|
||||
[self.parentWindow _zoomToScreenEdge:edge];
|
||||
@@ -248,6 +260,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
@@ -248,6 +273,7 @@ - (void)_zoomToScreenEdge:(NSUInteger)edge {
|
||||
[super _zoomToScreenEdge:edge];
|
||||
}
|
||||
}
|
||||
@@ -596,7 +609,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
|
||||
// This override helps diagnose lifetime issues in crash stacktraces by
|
||||
// inserting a symbol on NativeWidgetMacNSWindow and should be kept even if it
|
||||
@@ -393,6 +406,8 @@ - (NSAccessibilityRole)accessibilityRole {
|
||||
@@ -393,6 +419,8 @@ - (NSAccessibilityRole)accessibilityRole {
|
||||
|
||||
// NSWindow overrides.
|
||||
|
||||
@@ -605,7 +618,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
if (windowStyle & NSWindowStyleMaskTitled) {
|
||||
if (Class customFrame = [NativeWidgetMacNSWindowTitledFrame class])
|
||||
@@ -404,6 +419,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
@@ -404,6 +432,8 @@ + (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle {
|
||||
return [super frameViewClassForStyleMask:windowStyle];
|
||||
}
|
||||
|
||||
@@ -614,7 +627,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
- (BOOL)_isTitleHidden {
|
||||
bool shouldShowWindowTitle = YES;
|
||||
if (_bridge)
|
||||
@@ -428,12 +445,14 @@ - (BOOL)_usesCustomDrawing {
|
||||
@@ -428,12 +458,14 @@ - (BOOL)_usesCustomDrawing {
|
||||
// if it were valid to set that style for windows, setting the window style
|
||||
// recalculates and re-caches a bunch of stuff, so a surgical override is the
|
||||
// cleanest approach.
|
||||
@@ -629,7 +642,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
|
||||
+ (void)_getExteriorResizeEdgeThicknesses:
|
||||
(NSEdgeAndCornerThicknesses*)outThicknesses
|
||||
@@ -687,9 +706,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
|
||||
@@ -687,9 +719,11 @@ - (id)archiver:(NSKeyedArchiver*)archiver willEncodeObject:(id)object {
|
||||
}
|
||||
|
||||
- (void)saveRestorableState {
|
||||
@@ -641,7 +654,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
|
||||
// Certain conditions, such as in the Speedometer 3 benchmark, can trigger a
|
||||
// rapid succession of calls to saveRestorableState. If there's no pending
|
||||
@@ -756,6 +777,7 @@ - (void)reallySaveRestorableState {
|
||||
@@ -756,6 +790,7 @@ - (void)reallySaveRestorableState {
|
||||
// affects its restorable state changes.
|
||||
- (void)invalidateRestorableState {
|
||||
[super invalidateRestorableState];
|
||||
@@ -649,7 +662,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
if ([self _isConsideredOpenForPersistentState]) {
|
||||
if (_willUpdateRestorableState)
|
||||
return;
|
||||
@@ -768,6 +790,7 @@ - (void)invalidateRestorableState {
|
||||
@@ -768,6 +803,7 @@ - (void)invalidateRestorableState {
|
||||
_willUpdateRestorableState = NO;
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
}
|
||||
@@ -657,7 +670,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
}
|
||||
|
||||
// On newer SDKs, _canMiniaturize respects NSWindowStyleMaskMiniaturizable in
|
||||
@@ -932,6 +955,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
@@ -932,6 +968,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
// Since _removeFromGroups: is not documented it could go away in newer
|
||||
// versions of macOS. If the selector does not exist, DumpWithoutCrashing() so
|
||||
// we hear about the change.
|
||||
@@ -665,7 +678,7 @@ index a474e70cf3c10405b6f94f129f5a7312bb81fd73..00f6719bd80c8fdf31f910af3b93b5c6
|
||||
if (![NSWindow instancesRespondToSelector:@selector(_removeFromGroups:)]) {
|
||||
base::debug::DumpWithoutCrashing();
|
||||
return;
|
||||
@@ -949,6 +973,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
@@ -949,6 +986,7 @@ - (void)maybeRemoveTreeFromOrderingGroups {
|
||||
[currentWindow _removeFromGroups:child];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?V=C3=A4in=C3=B6=20M=C3=A4kel=C3=A4?=
|
||||
<vaino.o.makela@gmail.com>
|
||||
Date: Mon, 5 Jan 2026 11:27:05 -0800
|
||||
Subject: Move Wayland pointer lock overrides to common code
|
||||
|
||||
Since the Wayland-specific pointer lock implementation overrides were
|
||||
placed in Chrome-specific code, they could not be used by other projects
|
||||
depending on Chromium source like Electron, making pointer lock not work
|
||||
on Wayland for them without special care. Moving the function
|
||||
implementations to the more generic DesktopWindowTreeHostLinux class
|
||||
allows Electron to benefit from this code without having to override the
|
||||
functions itself.
|
||||
|
||||
Change-Id: Ideb7dca9fd3dfb491df8f68296ba2d21069901cd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7362747
|
||||
Reviewed-by: Thomas Anderson <thomasanderson@chromium.org>
|
||||
Reviewed-by: Kramer Ge <fangzhoug@chromium.org>
|
||||
Commit-Queue: Kramer Ge <fangzhoug@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1564501}
|
||||
|
||||
diff --git a/AUTHORS b/AUTHORS
|
||||
index 2384448120f5e5ac6b0315625e897d961bfc19b8..7eb8f26120a23539b0780eb3f7e1d6a7ac52b102 100644
|
||||
--- a/AUTHORS
|
||||
+++ b/AUTHORS
|
||||
@@ -1604,6 +1604,7 @@ Vitaliy Kharin <kvserr@gmail.com>
|
||||
Vivek Galatage <vivek.vg@samsung.com>
|
||||
Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
Volker Sorge <volker.sorge@gmail.com>
|
||||
+Väinö Mäkelä <vaino.o.makela@gmail.com>
|
||||
Waihung Fu <fufranci@amazon.com>
|
||||
wafuwafu13 <mariobaske@i.softbank.jp>
|
||||
Wojciech Bielawski <wojciech.bielawski@gmail.com>
|
||||
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
|
||||
index 87d1f5c0f8f9e286a58e809ae9cfc2b84dd97ed2..e2afae41f0b2fce9eb0428119b66ff09f4811932 100644
|
||||
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
|
||||
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.cc
|
||||
@@ -126,35 +126,6 @@ void BrowserDesktopWindowTreeHostLinux::FrameTypeChanged() {
|
||||
UpdateFrameHints();
|
||||
}
|
||||
|
||||
-bool BrowserDesktopWindowTreeHostLinux::SupportsMouseLock() {
|
||||
- auto* wayland_extension = ui::GetWaylandToplevelExtension(*platform_window());
|
||||
- if (!wayland_extension) {
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- return wayland_extension->SupportsPointerLock();
|
||||
-}
|
||||
-
|
||||
-void BrowserDesktopWindowTreeHostLinux::LockMouse(aura::Window* window) {
|
||||
- DesktopWindowTreeHostLinux::LockMouse(window);
|
||||
-
|
||||
- if (SupportsMouseLock()) {
|
||||
- auto* wayland_extension =
|
||||
- ui::GetWaylandToplevelExtension(*platform_window());
|
||||
- wayland_extension->LockPointer(true /*enabled*/);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-void BrowserDesktopWindowTreeHostLinux::UnlockMouse(aura::Window* window) {
|
||||
- DesktopWindowTreeHostLinux::UnlockMouse(window);
|
||||
-
|
||||
- if (SupportsMouseLock()) {
|
||||
- auto* wayland_extension =
|
||||
- ui::GetWaylandToplevelExtension(*platform_window());
|
||||
- wayland_extension->LockPointer(false /*enabled*/);
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void BrowserDesktopWindowTreeHostLinux::TabDraggingKindChanged(
|
||||
TabDragKind tab_drag_kind) {
|
||||
CHECK(browser_widget_);
|
||||
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h
|
||||
index 01ef9a93657f9401191adb4b8bd17528da790127..12ca597be51480e45acf4490cf6e533c23c30556 100644
|
||||
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h
|
||||
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_linux.h
|
||||
@@ -80,9 +80,6 @@ class BrowserDesktopWindowTreeHostLinux
|
||||
void CloseNow() override;
|
||||
void Show(ui::mojom::WindowShowState show_state,
|
||||
const gfx::Rect& restore_bounds) override;
|
||||
- bool SupportsMouseLock() override;
|
||||
- void LockMouse(aura::Window* window) override;
|
||||
- void UnlockMouse(aura::Window* window) override;
|
||||
void ClientDestroyedWidget() override;
|
||||
|
||||
// ui::X11ExtensionDelegate:
|
||||
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
|
||||
index dfc327588c74d43893820a97056780ece2b22de5..1c5c18a8fb57376f53f8659c99384b4919b10db8 100644
|
||||
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
|
||||
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.cc
|
||||
@@ -348,6 +348,35 @@ DesktopWindowTreeHostLinux::GetKeyboardLayoutMap() {
|
||||
return WindowTreeHostPlatform::GetKeyboardLayoutMap();
|
||||
}
|
||||
|
||||
+bool DesktopWindowTreeHostLinux::SupportsMouseLock() {
|
||||
+ auto* wayland_extension = ui::GetWaylandToplevelExtension(*platform_window());
|
||||
+ if (!wayland_extension) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return wayland_extension->SupportsPointerLock();
|
||||
+}
|
||||
+
|
||||
+void DesktopWindowTreeHostLinux::LockMouse(aura::Window* window) {
|
||||
+ DesktopWindowTreeHostPlatform::LockMouse(window);
|
||||
+
|
||||
+ if (SupportsMouseLock()) {
|
||||
+ auto* wayland_extension =
|
||||
+ ui::GetWaylandToplevelExtension(*platform_window());
|
||||
+ wayland_extension->LockPointer(true /*enabled*/);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void DesktopWindowTreeHostLinux::UnlockMouse(aura::Window* window) {
|
||||
+ DesktopWindowTreeHostPlatform::UnlockMouse(window);
|
||||
+
|
||||
+ if (SupportsMouseLock()) {
|
||||
+ auto* wayland_extension =
|
||||
+ ui::GetWaylandToplevelExtension(*platform_window());
|
||||
+ wayland_extension->LockPointer(false /*enabled*/);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void DesktopWindowTreeHostLinux::OnCompleteSwapWithNewSize(
|
||||
const gfx::Size& size) {
|
||||
if (GetX11Extension()) {
|
||||
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
|
||||
index 5c57268b37e2acdb30b09dd525a0eefc11f39112..c773bbe351260d958de222cd4e7942d757a53c25 100644
|
||||
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
|
||||
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_linux.h
|
||||
@@ -93,6 +93,11 @@ class VIEWS_EXPORT DesktopWindowTreeHostLinux
|
||||
// DesktopWindowTreeHostPlatform:
|
||||
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
|
||||
|
||||
+ // WindowTreeHost:
|
||||
+ bool SupportsMouseLock() override;
|
||||
+ void LockMouse(aura::Window* window) override;
|
||||
+ void UnlockMouse(aura::Window* window) override;
|
||||
+
|
||||
// Called back by compositor_observer_ if the latter is set.
|
||||
virtual void OnCompleteSwapWithNewSize(const gfx::Size& size);
|
||||
|
||||
@@ -28,7 +28,6 @@ fix_adjust_wpt_and_webidl_tests_for_enabled_float16array.patch
|
||||
refactor_attach_cppgc_heap_on_v8_isolate_creation.patch
|
||||
fix_cppgc_initializing_twice.patch
|
||||
fix_expose_readfilesync_override_for_modules.patch
|
||||
fix_array_out-of-bounds_read_in_boyer-moore_search.patch
|
||||
test_accomodate_v8_thenable_stack_trace_change_in_snapshot.patch
|
||||
chore_exclude_electron_node_folder_from_exit-time-destructors.patch
|
||||
api_remove_deprecated_getisolate.patch
|
||||
@@ -40,6 +39,5 @@ api_delete_deprecated_fields_on_v8_isolate.patch
|
||||
api_promote_deprecation_of_v8_context_and_v8_object_api_methods.patch
|
||||
fix_ensure_traverseparent_bails_on_resource_path_exit.patch
|
||||
reland_temporal_unflag_temporal.patch
|
||||
src_handle_der_decoding_errors_from_system_certificates.patch
|
||||
build_restore_macos_deployment_target_to_12_0.patch
|
||||
test_make_buffer_sizes_32bit-aware_in.patch
|
||||
fix_generate_config_gypi_needs_to_generate_valid_json.patch
|
||||
|
||||
@@ -44,7 +44,7 @@ index 37d83e41b618a07aca98118260abe9618f11256d..26d5c1bd3c8191fce1d22b969996b6bf
|
||||
|
||||
template <typename T>
|
||||
diff --git a/src/env-inl.h b/src/env-inl.h
|
||||
index 97c43afb487b58c0c77bd59b4a6b6d7a13690053..23a4d7b651935a4029249fb2f1dd3ed46ea3b26f 100644
|
||||
index 74bbb9fb83246a90bc425e259150f0868020ac9e..a4b3a1c0907c9d50baf6c8cd473cb4c7369d0a5c 100644
|
||||
--- a/src/env-inl.h
|
||||
+++ b/src/env-inl.h
|
||||
@@ -189,7 +189,8 @@ inline Environment* Environment::GetCurrent(v8::Local<v8::Context> context) {
|
||||
@@ -104,10 +104,10 @@ index cb13d84388bcc6806d3b038a51e1cc2d1feccda1..687b2cf3e63b2a3306e2cbac67e3e216
|
||||
MakeWeak();
|
||||
}
|
||||
diff --git a/src/node_realm-inl.h b/src/node_realm-inl.h
|
||||
index f162d1506c990a5fe578be6f1324427e3f9023f4..b57bb0b42e98b954c0c8662c667e589d6c68a5d3 100644
|
||||
index 0af487a9abc9ee1783367ac86b0016ab89e02006..c01cef477aaba52f9894943acede7fb22ed17dcb 100644
|
||||
--- a/src/node_realm-inl.h
|
||||
+++ b/src/node_realm-inl.h
|
||||
@@ -21,7 +21,8 @@ inline Realm* Realm::GetCurrent(v8::Local<v8::Context> context) {
|
||||
@@ -22,7 +22,8 @@ inline Realm* Realm::GetCurrent(v8::Local<v8::Context> context) {
|
||||
return nullptr;
|
||||
}
|
||||
return static_cast<Realm*>(
|
||||
|
||||
@@ -85,10 +85,10 @@ index cc60ddddb037e0279615bbe24821eb20fd8da677..37d83e41b618a07aca98118260abe961
|
||||
|
||||
return handle;
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index f3631d538a38dc3a93a47707ea8dab0462fa2140..12ad6e6ddbda2cc679e733f7a9c6b9e4cf9623dd 100644
|
||||
index 2e3f31e1765024373c3fc2acd33fc3bfb352a906..ca62d3001bf51193d78caac0cccd93c188a8410c 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -1022,7 +1022,7 @@ bool ArrayOfStringsToX509s(Local<Context> context,
|
||||
@@ -1045,7 +1045,7 @@ bool ArrayOfStringsToX509s(Local<Context> context,
|
||||
Local<Array> cert_array,
|
||||
std::vector<X509*>* certs) {
|
||||
ClearErrorOnReturn clear_error_on_return;
|
||||
@@ -120,10 +120,10 @@ index 4c5427596d1c90d3a413cdd9ff4f1151e657073d..70135a6be65e41fcb3564ddf6d1e8083
|
||||
NewStringType::kNormal,
|
||||
mem->length)
|
||||
diff --git a/src/encoding_binding.cc b/src/encoding_binding.cc
|
||||
index 266f640fb1c6503a424e77cc41fc15bc658bb6a5..877ae8a18f6b8f2c7e3474dfba060d99db88e6b9 100644
|
||||
index a913e34c73db3fb62aedcf28bee1bf1c4d59de7a..9de38eb9907269e99fdf0907aa35862572a2c643 100644
|
||||
--- a/src/encoding_binding.cc
|
||||
+++ b/src/encoding_binding.cc
|
||||
@@ -76,7 +76,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
@@ -75,7 +75,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
int index,
|
||||
InternalFieldInfoBase* info) {
|
||||
DCHECK_IS_SNAPSHOT_SLOT(index);
|
||||
@@ -388,10 +388,10 @@ index d278a32c9934c15bc721da164efccca7bc7e7111..ab862bf93a411e6ae6da7c9f9706cee2
|
||||
BlobBindingData* binding = realm->AddBindingData<BlobBindingData>(holder);
|
||||
CHECK_NOT_NULL(binding);
|
||||
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
|
||||
index e69eb280050cae0c0f394b2f956eef947e628904..9bb4576fcf4f07550e7d6f4ff2310cedc8093c5f 100644
|
||||
index 703ac1be06249736073f797058d170576a0db1bf..f0607ec9fd1983386166d0f4782adac99ace943e 100644
|
||||
--- a/src/node_builtins.cc
|
||||
+++ b/src/node_builtins.cc
|
||||
@@ -274,7 +274,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
|
||||
@@ -275,7 +275,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompileInternal(
|
||||
const char* id,
|
||||
LocalVector<String>* parameters,
|
||||
Realm* optional_realm) {
|
||||
@@ -400,7 +400,7 @@ index e69eb280050cae0c0f394b2f956eef947e628904..9bb4576fcf4f07550e7d6f4ff2310ced
|
||||
EscapableHandleScope scope(isolate);
|
||||
|
||||
Local<String> source;
|
||||
@@ -396,7 +396,7 @@ void BuiltinLoader::SaveCodeCache(const char* id, Local<Function> fun) {
|
||||
@@ -397,7 +397,7 @@ void BuiltinLoader::SaveCodeCache(const char* id, Local<Function> fun) {
|
||||
MaybeLocal<Function> BuiltinLoader::LookupAndCompile(Local<Context> context,
|
||||
const char* id,
|
||||
Realm* optional_realm) {
|
||||
@@ -409,7 +409,7 @@ index e69eb280050cae0c0f394b2f956eef947e628904..9bb4576fcf4f07550e7d6f4ff2310ced
|
||||
LocalVector<String> parameters(isolate);
|
||||
// Detects parameters of the scripts based on module ids.
|
||||
// internal/bootstrap/realm: process, getLinkedBinding,
|
||||
@@ -450,7 +450,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompile(Local<Context> context,
|
||||
@@ -451,7 +451,7 @@ MaybeLocal<Function> BuiltinLoader::LookupAndCompile(Local<Context> context,
|
||||
MaybeLocal<Value> BuiltinLoader::CompileAndCall(Local<Context> context,
|
||||
const char* id,
|
||||
Realm* realm) {
|
||||
@@ -418,7 +418,7 @@ index e69eb280050cae0c0f394b2f956eef947e628904..9bb4576fcf4f07550e7d6f4ff2310ced
|
||||
// Detects parameters of the scripts based on module ids.
|
||||
// internal/bootstrap/realm: process, getLinkedBinding,
|
||||
// getInternalBinding, primordials
|
||||
@@ -506,7 +506,7 @@ MaybeLocal<Value> BuiltinLoader::CompileAndCall(Local<Context> context,
|
||||
@@ -507,7 +507,7 @@ MaybeLocal<Value> BuiltinLoader::CompileAndCall(Local<Context> context,
|
||||
if (!maybe_fn.ToLocal(&fn)) {
|
||||
return MaybeLocal<Value>();
|
||||
}
|
||||
@@ -427,7 +427,7 @@ index e69eb280050cae0c0f394b2f956eef947e628904..9bb4576fcf4f07550e7d6f4ff2310ced
|
||||
return fn->Call(context, undefined, argc, argv);
|
||||
}
|
||||
|
||||
@@ -544,14 +544,14 @@ bool BuiltinLoader::CompileAllBuiltinsAndCopyCodeCache(
|
||||
@@ -545,14 +545,14 @@ bool BuiltinLoader::CompileAllBuiltinsAndCopyCodeCache(
|
||||
to_eager_compile_.emplace(id);
|
||||
}
|
||||
|
||||
@@ -533,10 +533,10 @@ index 55a0c986c5b6989ee9ce277bb6a9778abb2ad2ee..809d88f21e5572807e38132d40ee7587
|
||||
READONLY_PROPERTY(target, "exitCodes", exit_codes);
|
||||
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 7dfb7a486040e0188eb53ee7a65f91a99e713a3a..c364f2a4f6dd6ec066b00f364108383154be12ec 100644
|
||||
index ba6ffc2b6565dea500bc8dd4818c8fcb7648694a..e834325a763f7ea8f53210145b5edd134d6b67e6 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -3834,7 +3834,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
@@ -3843,7 +3843,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
int index,
|
||||
InternalFieldInfoBase* info) {
|
||||
DCHECK_IS_SNAPSHOT_SLOT(index);
|
||||
@@ -586,7 +586,7 @@ index 57e068ae249d618c2658638f9f3b03e1fedb6524..8c51ae4e0a435971c6d0288af8781087
|
||||
data_.Reset();
|
||||
return ret;
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index d3907c3d063c7757cdd7ef99ed09bea1eb58a3fd..df9925404e77ec61900f89a5241c86a599e548c5 100644
|
||||
index cecdda74847801fd5821bc0afdf0dfc9f131c44a..04ebecc5d924f6c2fddd9992462d1ff692e1cee5 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -70,7 +70,7 @@ void BindingData::Deserialize(v8::Local<v8::Context> context,
|
||||
@@ -598,7 +598,7 @@ index d3907c3d063c7757cdd7ef99ed09bea1eb58a3fd..df9925404e77ec61900f89a5241c86a5
|
||||
Realm* realm = Realm::GetCurrent(context);
|
||||
BindingData* binding = realm->AddBindingData<BindingData>(holder);
|
||||
CHECK_NOT_NULL(binding);
|
||||
@@ -709,7 +709,7 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
@@ -750,7 +750,7 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
Realm* realm = Realm::GetCurrent(context);
|
||||
realm->AddBindingData<BindingData>(target);
|
||||
|
||||
@@ -608,10 +608,10 @@ index d3907c3d063c7757cdd7ef99ed09bea1eb58a3fd..df9925404e77ec61900f89a5241c86a5
|
||||
|
||||
#define V(status) \
|
||||
diff --git a/src/node_process_methods.cc b/src/node_process_methods.cc
|
||||
index e453bacc3e5247493a3582c24174bfe6e590825d..fe4aad63bc877be105830a80aa6be10ce3f8fda4 100644
|
||||
index 4a258e5f140994536386492059d64c9cf94ea0a6..67278974199db46fed85b443e7cdd30accd7687f 100644
|
||||
--- a/src/node_process_methods.cc
|
||||
+++ b/src/node_process_methods.cc
|
||||
@@ -737,7 +737,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
@@ -745,7 +745,7 @@ void BindingData::Deserialize(Local<Context> context,
|
||||
int index,
|
||||
InternalFieldInfoBase* info) {
|
||||
DCHECK_IS_SNAPSHOT_SLOT(index);
|
||||
@@ -621,7 +621,7 @@ index e453bacc3e5247493a3582c24174bfe6e590825d..fe4aad63bc877be105830a80aa6be10c
|
||||
// Recreate the buffer in the constructor.
|
||||
InternalFieldInfo* casted_info = static_cast<InternalFieldInfo*>(info);
|
||||
diff --git a/src/node_realm.cc b/src/node_realm.cc
|
||||
index 2a5fe9fe501d1fd9356eeb7d044a872fa5a55f38..39f6f142044c42904d234da20a266315346c135a 100644
|
||||
index 6d2e4eb641a8ffaacf4aebd3522008a285387a30..47bd7d9f19077ac7a558c73db5f51bdf8da291e7 100644
|
||||
--- a/src/node_realm.cc
|
||||
+++ b/src/node_realm.cc
|
||||
@@ -22,7 +22,7 @@ using v8::String;
|
||||
@@ -660,7 +660,7 @@ index c2e24b4645e7903e08c80aead1c18c7bcff1bd89..e34d24d51d5c090b560d06f727043f20
|
||||
// Recreate the buffer in the constructor.
|
||||
InternalFieldInfo* casted_info = static_cast<InternalFieldInfo*>(info);
|
||||
diff --git a/src/node_sqlite.cc b/src/node_sqlite.cc
|
||||
index 955b76cbc71d0cd3a1cc01c3c0dea0536a792dc0..0b111ce1fb1d59cad019ba13bbfc513f157d3f06 100644
|
||||
index 6bfc54dd81446545ebbb0faedb55a5383b81de49..2e52fb801684feb22800d4809daab006fc7cae9c 100644
|
||||
--- a/src/node_sqlite.cc
|
||||
+++ b/src/node_sqlite.cc
|
||||
@@ -2061,7 +2061,7 @@ bool StatementSync::BindParams(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -736,7 +736,7 @@ index 370221d3cddc201180260ecb3a222bc831c91093..f5aff2f65fe6b9f48cf970ab3e7c57cf
|
||||
THROW_ERR_WASI_NOT_STARTED(isolate);
|
||||
return EinvalError<R>();
|
||||
diff --git a/src/node_webstorage.cc b/src/node_webstorage.cc
|
||||
index cc90af827a3fbd14fb4cbfbfd39cc661f22cf6e1..5819d9bca845e0eed6d4d93564469d8f3c36200b 100644
|
||||
index 5c7d268d38ff55ce4db07463b1ea0bcb2f4e63ea..bd83654012442195866e57173b6e5d4d25fecf0f 100644
|
||||
--- a/src/node_webstorage.cc
|
||||
+++ b/src/node_webstorage.cc
|
||||
@@ -57,7 +57,7 @@ using v8::Value;
|
||||
@@ -748,7 +748,7 @@ index cc90af827a3fbd14fb4cbfbfd39cc661f22cf6e1..5819d9bca845e0eed6d4d93564469d8f
|
||||
auto dom_exception_str = FIXED_ONE_BYTE_STRING(isolate, "DOMException");
|
||||
auto err_name = FIXED_ONE_BYTE_STRING(isolate, "QuotaExceededError");
|
||||
auto err_message =
|
||||
@@ -433,7 +433,7 @@ Maybe<void> Storage::Store(Local<Name> key, Local<Value> value) {
|
||||
@@ -437,7 +437,7 @@ Maybe<void> Storage::Store(Local<Name> key, Local<Value> value) {
|
||||
}
|
||||
|
||||
static MaybeLocal<String> Uint32ToName(Local<Context> context, uint32_t index) {
|
||||
@@ -758,10 +758,10 @@ index cc90af827a3fbd14fb4cbfbfd39cc661f22cf6e1..5819d9bca845e0eed6d4d93564469d8f
|
||||
|
||||
static void Clear(const FunctionCallbackInfo<Value>& info) {
|
||||
diff --git a/src/node_worker.cc b/src/node_worker.cc
|
||||
index 62c53368d1173edb7eb42e3337049c46fd7cdda9..7d08d8af7f6d99f7bd41cb7eb91063c630b3f87b 100644
|
||||
index e7d26b4c8cbb08a175084ceac51395860dc60598..fa4ec53ee556a23c8fd018caa1eee51bc5e004fe 100644
|
||||
--- a/src/node_worker.cc
|
||||
+++ b/src/node_worker.cc
|
||||
@@ -1466,8 +1466,6 @@ void GetEnvMessagePort(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1465,8 +1465,6 @@ void GetEnvMessagePort(const FunctionCallbackInfo<Value>& args) {
|
||||
Local<Object> port = env->message_port();
|
||||
CHECK_IMPLIES(!env->is_main_thread(), !port.IsEmpty());
|
||||
if (!port.IsEmpty()) {
|
||||
|
||||
@@ -11,7 +11,7 @@ really in 20/21. We have to wait until 22 is released to be able to
|
||||
build with upstream GN files.
|
||||
|
||||
diff --git a/configure.py b/configure.py
|
||||
index 750ddc8ace6cad894e738f6e1d983b5906acc10f..e063f9131d4d547d231811dafea03c8c52b611e6 100755
|
||||
index f31d460038db2fa2fa4c47d62be3100da959978f..209f23b04663113e4f6b3c3242c0544cfed9a950 100755
|
||||
--- a/configure.py
|
||||
+++ b/configure.py
|
||||
@@ -1736,7 +1736,7 @@ def configure_v8(o, configs):
|
||||
@@ -68,10 +68,10 @@ index d4438f7fd61598afac2c1e3184721a759d22b10c..e2407027ab05e59b2f0f1c213b98ea46
|
||||
|
||||
assert(!node_enable_inspector || node_use_openssl,
|
||||
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
|
||||
index 581b9886ded52f294b7cc6b080b2269b7617c85e..e43e2559aaf48add88aad342b1c96fd34f26c87f 100644
|
||||
index 7b34b14856a5193c723987f69d6040bdb6aa7c34..90fdf52d79954bf2cd86fd1d2d6da8199683d344 100644
|
||||
--- a/src/node_builtins.cc
|
||||
+++ b/src/node_builtins.cc
|
||||
@@ -774,6 +774,7 @@ void BuiltinLoader::RegisterExternalReferences(
|
||||
@@ -775,6 +775,7 @@ void BuiltinLoader::RegisterExternalReferences(
|
||||
registry->Register(GetNatives);
|
||||
|
||||
RegisterExternalReferencesForInternalizedBuiltinCode(registry);
|
||||
@@ -95,7 +95,7 @@ index 7a7b84337feb67960819472e43192dbdc151e299..bcdd50f635757f41287c87df1db9cd3b
|
||||
diff --git a/tools/js2c.cc b/tools/js2c.cc
|
||||
old mode 100644
|
||||
new mode 100755
|
||||
index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2e9dfb0f0
|
||||
index 9c2f70de4e00834ff448e573743898072dc14c5d..71a12c606f4da7165cc41a295a278b2e504af1b6
|
||||
--- a/tools/js2c.cc
|
||||
+++ b/tools/js2c.cc
|
||||
@@ -28,6 +28,7 @@ namespace js2c {
|
||||
@@ -190,7 +190,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,
|
||||
@@ -836,12 +880,15 @@ int JS2C(const FileList& js_files,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ index 21992cbe894a880e3223c379326b62db22f2f12d..1296a5457422099035ba34f2b02624f2
|
||||
Fragment out = Format(definitions, initializers, registrations);
|
||||
return WriteIfChanged(out, dest);
|
||||
}
|
||||
@@ -877,6 +924,8 @@ int Main(int argc, char* argv[]) {
|
||||
@@ -867,6 +914,8 @@ int Main(int argc, char* argv[]) {
|
||||
std::string arg(argv[i]);
|
||||
if (arg == "--verbose") {
|
||||
is_verbose = true;
|
||||
@@ -215,7 +215,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[]) {
|
||||
@@ -915,6 +964,14 @@ int Main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,7 +230,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[]) {
|
||||
@@ -941,6 +998,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);
|
||||
|
||||
@@ -64,7 +64,7 @@ index e664663348adc7bb31f7c9ec78481bbeb71401d9..62b659beb766b8256b214447af376f43
|
||||
|
||||
function ipToInt(ip) {
|
||||
diff --git a/node.gyp b/node.gyp
|
||||
index c3917f805464669c709bef83b9982ef95d0fbaa1..56e11cde31897260bf41db3f32f5c6d6fbd6d5bf 100644
|
||||
index c035d1d7cdac1d18cca0ef5cefbc5ce4c1fd1b86..a48e4e5d1fb7621b12b9abeaaf78214515a23efc 100644
|
||||
--- a/node.gyp
|
||||
+++ b/node.gyp
|
||||
@@ -176,7 +176,6 @@
|
||||
|
||||
@@ -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 8280cff0d93d42a95875b78de84221aa1bcae092..76a03b9a5458f4afc0ab5768c8a2e90633749fe9 100644
|
||||
index cf3ceaf19972ee107deff63b4dba16c12191c615..6159350823fd9f0090e2b98e8797e829fd481750 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -89,6 +89,8 @@
|
||||
@@ -42,7 +42,7 @@ index 8280cff0d93d42a95875b78de84221aa1bcae092..76a03b9a5458f4afc0ab5768c8a2e906
|
||||
# list in v8/BUILD.gn.
|
||||
['v8_enable_v8_checks == 1', {
|
||||
diff --git a/configure.py b/configure.py
|
||||
index e063f9131d4d547d231811dafea03c8c52b611e6..a5c764d9e7fb0ffa219202015ec67ed6d3e14c04 100755
|
||||
index 209f23b04663113e4f6b3c3242c0544cfed9a950..88164b99ae3d37f47e5e9a9ba96d7b450d6ba4ab 100755
|
||||
--- a/configure.py
|
||||
+++ b/configure.py
|
||||
@@ -1717,6 +1717,7 @@ def configure_library(lib, output, pkgname=None):
|
||||
|
||||
@@ -34,7 +34,7 @@ index 605dee28cace56f2366fec9d7f18894559044ae4..15dcabb3b1682438eb6d5a681363b7ea
|
||||
let kResistStopPropagation;
|
||||
|
||||
diff --git a/src/node_builtins.cc b/src/node_builtins.cc
|
||||
index e43e2559aaf48add88aad342b1c96fd34f26c87f..e69eb280050cae0c0f394b2f956eef947e628904 100644
|
||||
index 90fdf52d79954bf2cd86fd1d2d6da8199683d344..703ac1be06249736073f797058d170576a0db1bf 100644
|
||||
--- a/src/node_builtins.cc
|
||||
+++ b/src/node_builtins.cc
|
||||
@@ -39,6 +39,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 76a03b9a5458f4afc0ab5768c8a2e90633749fe9..bdadbdaa607b2f668749fc484271de8d126bbd17 100644
|
||||
index 6159350823fd9f0090e2b98e8797e829fd481750..5f47ec9bb405f6c1574304ac68807929604cd402 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -128,6 +128,7 @@
|
||||
|
||||
@@ -10,7 +10,7 @@ M151, and so we should allow for building until then.
|
||||
This patch can be removed at the M151 branch point.
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index bdadbdaa607b2f668749fc484271de8d126bbd17..8df2802191b7fe6ae14edbd85cb3a5d16eb5a76a 100644
|
||||
index 5f47ec9bb405f6c1574304ac68807929604cd402..914f28b41d05b1485874885570ae5adaabd8e1b2 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -677,7 +677,7 @@
|
||||
|
||||
@@ -14,10 +14,10 @@ and
|
||||
This patch can be removed once this is fixed upstream in simdjson.
|
||||
|
||||
diff --git a/deps/simdjson/simdjson.h b/deps/simdjson/simdjson.h
|
||||
index 35ff2626f26735495e308381782e5f1d9b8a629e..b4aa4bce33d62c579beee745712d24d9ebd5e0c2 100644
|
||||
index 1d6560e80fab0458b22f0ac2437056bce4873e8f..c3dbe2b6fc08c36a07ced5e29a814f7bcd85b748 100644
|
||||
--- a/deps/simdjson/simdjson.h
|
||||
+++ b/deps/simdjson/simdjson.h
|
||||
@@ -4179,12 +4179,17 @@ inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string
|
||||
@@ -4215,12 +4215,17 @@ inline std::ostream& operator<<(std::ostream& out, simdjson_result<padded_string
|
||||
|
||||
} // namespace simdjson
|
||||
|
||||
@@ -35,7 +35,7 @@ index 35ff2626f26735495e308381782e5f1d9b8a629e..b4aa4bce33d62c579beee745712d24d9
|
||||
namespace simdjson {
|
||||
namespace internal {
|
||||
|
||||
@@ -4636,6 +4641,9 @@ inline simdjson_result<padded_string> padded_string::load(std::string_view filen
|
||||
@@ -4729,6 +4734,9 @@ inline simdjson_result<padded_string> padded_string::load(std::wstring_view file
|
||||
|
||||
} // namespace simdjson
|
||||
|
||||
@@ -45,8 +45,8 @@ index 35ff2626f26735495e308381782e5f1d9b8a629e..b4aa4bce33d62c579beee745712d24d9
|
||||
inline simdjson::padded_string operator ""_padded(const char *str, size_t len) {
|
||||
return simdjson::padded_string(str, len);
|
||||
}
|
||||
@@ -4644,6 +4652,8 @@ inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len
|
||||
return simdjson::padded_string(reinterpret_cast<const char8_t *>(str), len);
|
||||
@@ -4737,6 +4745,8 @@ inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len
|
||||
return simdjson::padded_string(reinterpret_cast<const char *>(str), len);
|
||||
}
|
||||
#endif
|
||||
+#pragma clang diagnostic pop
|
||||
@@ -54,7 +54,7 @@ index 35ff2626f26735495e308381782e5f1d9b8a629e..b4aa4bce33d62c579beee745712d24d9
|
||||
#endif // SIMDJSON_PADDED_STRING_INL_H
|
||||
/* end file simdjson/padded_string-inl.h */
|
||||
/* skipped duplicate #include "simdjson/padded_string_view.h" */
|
||||
@@ -43674,12 +43684,16 @@ simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::
|
||||
@@ -44745,12 +44755,16 @@ simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::
|
||||
return parser_instance;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ index 35ff2626f26735495e308381782e5f1d9b8a629e..b4aa4bce33d62c579beee745712d24d9
|
||||
|
||||
} // namespace ondemand
|
||||
} // namespace arm64
|
||||
@@ -57923,12 +57937,16 @@ simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::
|
||||
@@ -59221,12 +59235,16 @@ simdjson_inline simdjson_warn_unused std::unique_ptr<ondemand::parser>& parser::
|
||||
return parser_instance;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ modules to sandboxed renderers.
|
||||
TODO(codebytere): remove and replace with a public facing API.
|
||||
|
||||
diff --git a/src/node_binding.cc b/src/node_binding.cc
|
||||
index 5bd07e5253ae64b02ae1874226ab70c1972cf9e0..768d81a63a42d9016a42b7cdce7b6be86c59afdf 100644
|
||||
index 3b284583d6ccc9b2d0273d678335b9ab0a6fa81c..fbbdc26b8d1428084709ab113f102c42424842b0 100644
|
||||
--- a/src/node_binding.cc
|
||||
+++ b/src/node_binding.cc
|
||||
@@ -655,6 +655,10 @@ void GetInternalBinding(const FunctionCallbackInfo<Value>& args) {
|
||||
|
||||
@@ -18,7 +18,7 @@ Stage 3.
|
||||
Upstreamed in https://github.com/nodejs/node/pull/60364
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index d77735f4f5686e914811c0576975b57e6c631398..d8e1c809df6e96ed561c73c0e8de0cf9736e4aaa 100644
|
||||
index ae082f2d0498e0e694e427da71078ca19086e275..f9630a5cd9bed1535a7839517313a2d47d403b1f 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -782,7 +782,7 @@ static ExitCode ProcessGlobalArgsInternal(std::vector<std::string>* args,
|
||||
|
||||
@@ -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 db1625378697d9e6d7685d57acbdc212e8f25ec0..8280cff0d93d42a95875b78de84221aa1bcae092 100644
|
||||
index 5adfd888711ae46a3ba157853359145c4409169b..cf3ceaf19972ee107deff63b4dba16c12191c615 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -91,6 +91,23 @@
|
||||
|
||||
@@ -9,10 +9,10 @@ conflict with Blink's in renderer and worker processes.
|
||||
We should try to upstream some version of this.
|
||||
|
||||
diff --git a/doc/api/cli.md b/doc/api/cli.md
|
||||
index 667603438cc41701820d6aaa734d21ac35bcc8d1..6611face009797f9d540be4478df80d05888893a 100644
|
||||
index d94226df8d90d791c3c5fdb7cab7357b0e2555b0..7512ec43ea10d9b0e167125040bc8136f7ad568a 100644
|
||||
--- a/doc/api/cli.md
|
||||
+++ b/doc/api/cli.md
|
||||
@@ -1798,6 +1798,14 @@ changes:
|
||||
@@ -1814,6 +1814,14 @@ changes:
|
||||
|
||||
Disable using [syntax detection][] to determine module type.
|
||||
|
||||
@@ -27,7 +27,7 @@ index 667603438cc41701820d6aaa734d21ac35bcc8d1..6611face009797f9d540be4478df80d0
|
||||
### `--no-experimental-global-navigator`
|
||||
|
||||
<!-- YAML
|
||||
@@ -3476,6 +3484,7 @@ one is included in the list below.
|
||||
@@ -3493,6 +3501,7 @@ one is included in the list below.
|
||||
* `--no-addons`
|
||||
* `--no-async-context-frame`
|
||||
* `--no-deprecation`
|
||||
@@ -79,7 +79,7 @@ index 9a99ff6d44320c0e28f4a787d24ea98ae1c96196..8f5810267d1ba430bae02be141f087f2
|
||||
function setupWebsocket() {
|
||||
if (getOptionValue('--no-experimental-websocket')) {
|
||||
diff --git a/src/node_options.cc b/src/node_options.cc
|
||||
index 342bffb00fd355f7f1c5d0d83133bd5561be91e1..41f268195c281689339e98ceb98e8034ecd28b63 100644
|
||||
index f6f81f50c8bd91a72ca96093dc64c183bd58039b..aa18dab6e4171d8a7f0af4b7db1b8c2c07191859 100644
|
||||
--- a/src/node_options.cc
|
||||
+++ b/src/node_options.cc
|
||||
@@ -545,7 +545,11 @@ EnvironmentOptionsParser::EnvironmentOptionsParser() {
|
||||
|
||||
@@ -11,7 +11,7 @@ We can fix this by allowing the C++ implementation of legacyMainResolve to use
|
||||
a fileExists function that does take Asar into account.
|
||||
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 72cc9444ca93ef7a1526e23314693aeaf5f173b0..79684dd7e8d1629b19be01ebf97e43e503dec581 100644
|
||||
index 8dc8bbfe8d73e2d11edc261d6fe9f37aaa81e4cd..9c965f21918b8170ca2c2d6efee067b52537698e 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');
|
||||
@@ -31,7 +31,7 @@ index 72cc9444ca93ef7a1526e23314693aeaf5f173b0..79684dd7e8d1629b19be01ebf97e43e5
|
||||
const {
|
||||
ERR_INPUT_TYPE_NOT_ALLOWED,
|
||||
ERR_INVALID_ARG_TYPE,
|
||||
@@ -183,6 +182,11 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
@@ -184,6 +183,11 @@ const legacyMainResolveExtensionsIndexes = {
|
||||
kResolvedByPackageAndNode: 9,
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ index 72cc9444ca93ef7a1526e23314693aeaf5f173b0..79684dd7e8d1629b19be01ebf97e43e5
|
||||
/**
|
||||
* Legacy CommonJS main resolution:
|
||||
* 1. let M = pkg_url + (json main field)
|
||||
@@ -201,7 +205,7 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
@@ -202,7 +206,7 @@ function legacyMainResolve(packageJSONUrl, packageConfig, base) {
|
||||
|
||||
const baseStringified = isURL(base) ? base.href : base;
|
||||
|
||||
@@ -53,10 +53,10 @@ index 72cc9444ca93ef7a1526e23314693aeaf5f173b0..79684dd7e8d1629b19be01ebf97e43e5
|
||||
const maybeMain = resolvedOption <= legacyMainResolveExtensionsIndexes.kResolvedByMainIndexNode ?
|
||||
packageConfig.main || './' : '';
|
||||
diff --git a/src/node_file.cc b/src/node_file.cc
|
||||
index 88fdca1eb85a49468e787d50f1cee6b8561841d6..7dfb7a486040e0188eb53ee7a65f91a99e713a3a 100644
|
||||
index 58476306172433db98a3e3a1ab31d13bf42014f1..ba6ffc2b6565dea500bc8dd4818c8fcb7648694a 100644
|
||||
--- a/src/node_file.cc
|
||||
+++ b/src/node_file.cc
|
||||
@@ -3583,13 +3583,25 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3592,13 +3592,25 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile(
|
||||
@@ -83,7 +83,7 @@ index 88fdca1eb85a49468e787d50f1cee6b8561841d6..7dfb7a486040e0188eb53ee7a65f91a9
|
||||
uv_fs_t req;
|
||||
|
||||
int rc = uv_fs_stat(env->event_loop(), &req, file_path.c_str(), nullptr);
|
||||
@@ -3647,6 +3659,11 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3656,6 +3668,11 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
std::optional<std::string> initial_file_path;
|
||||
std::string file_path;
|
||||
|
||||
@@ -95,7 +95,7 @@ index 88fdca1eb85a49468e787d50f1cee6b8561841d6..7dfb7a486040e0188eb53ee7a65f91a9
|
||||
if (args.Length() >= 2 && args[1]->IsString()) {
|
||||
auto package_config_main = Utf8Value(isolate, args[1]).ToString();
|
||||
|
||||
@@ -3667,7 +3684,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3676,7 +3693,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
BufferValue buff_file_path(isolate, local_file_path);
|
||||
ToNamespacedPath(env, &buff_file_path);
|
||||
|
||||
@@ -104,7 +104,7 @@ index 88fdca1eb85a49468e787d50f1cee6b8561841d6..7dfb7a486040e0188eb53ee7a65f91a9
|
||||
case BindingData::FilePathIsFileReturnType::kIsFile:
|
||||
return args.GetReturnValue().Set(i);
|
||||
case BindingData::FilePathIsFileReturnType::kIsNotFile:
|
||||
@@ -3704,7 +3721,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -3713,7 +3730,7 @@ void BindingData::LegacyMainResolve(const FunctionCallbackInfo<Value>& args) {
|
||||
BufferValue buff_file_path(isolate, local_file_path);
|
||||
ToNamespacedPath(env, &buff_file_path);
|
||||
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Thu, 10 Jul 2025 08:36:12 +0000
|
||||
Subject: fix: array out-of-bounds read in Boyer-Moore search
|
||||
|
||||
Refs https://chromium-review.googlesource.com/c/chromium/src/+/6703757
|
||||
|
||||
The above CL enabled array bounds sanitization, which triggered a crash in a Node.js
|
||||
test which exposed an issue in Node.js implementation of Boyer-Moore string search.
|
||||
|
||||
Some Boyer-Moore search impl functions were using "biased pointer" arithmetic to
|
||||
create array pointers that point outside the actual array bounds.
|
||||
|
||||
When start_ is large this creates pointers far outside the valid memory range.
|
||||
While this worked by accident in practice, it's undefined behavior that the CL
|
||||
correctly prohibits.
|
||||
|
||||
diff --git a/deps/nbytes/include/nbytes.h b/deps/nbytes/include/nbytes.h
|
||||
index b012729c6cca8e42c94fd9b6a9c72301b4370de4..bb2e2e5fd2781f9e3db7f0b0699e1b0513e6782d 100644
|
||||
--- a/deps/nbytes/include/nbytes.h
|
||||
+++ b/deps/nbytes/include/nbytes.h
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
+#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
@@ -548,7 +549,11 @@ size_t StringSearch<Char>::BoyerMooreSearch(Vector subject,
|
||||
size_t start = start_;
|
||||
|
||||
int *bad_char_occurrence = bad_char_shift_table_;
|
||||
- int *good_suffix_shift = good_suffix_shift_table_ - start_;
|
||||
+
|
||||
+ auto good_suffix_get = [&](size_t idx) -> int {
|
||||
+ if (idx < start || idx - start > kBMMaxShift) return 0;
|
||||
+ return good_suffix_shift_table_[idx - start];
|
||||
+ };
|
||||
|
||||
Char last_char = pattern_[pattern_length - 1];
|
||||
size_t index = start_index;
|
||||
@@ -575,7 +580,7 @@ size_t StringSearch<Char>::BoyerMooreSearch(Vector subject,
|
||||
index +=
|
||||
pattern_length - 1 - CharOccurrence(bad_char_occurrence, last_char);
|
||||
} else {
|
||||
- int gs_shift = good_suffix_shift[j + 1];
|
||||
+ int gs_shift = good_suffix_get(j + 1);
|
||||
int bc_occ = CharOccurrence(bad_char_occurrence, c);
|
||||
int shift = j - bc_occ;
|
||||
if (gs_shift > shift) {
|
||||
@@ -596,17 +601,22 @@ void StringSearch<Char>::PopulateBoyerMooreTable() {
|
||||
const size_t start = start_;
|
||||
const size_t length = pattern_length - start;
|
||||
|
||||
- // Biased tables so that we can use pattern indices as table indices,
|
||||
- // even if we only cover the part of the pattern from offset start.
|
||||
- int *shift_table = good_suffix_shift_table_ - start_;
|
||||
- int *suffix_table = suffix_table_ - start_;
|
||||
+ auto shift_get = [&](size_t idx) -> int& {
|
||||
+ if (idx < start) abort();
|
||||
+ return good_suffix_shift_table_[idx - start];
|
||||
+ };
|
||||
+
|
||||
+ auto suffix_get = [&](size_t idx) -> int& {
|
||||
+ if (idx < start) abort();
|
||||
+ return suffix_table_[idx - start];
|
||||
+ };
|
||||
|
||||
// Initialize table.
|
||||
for (size_t i = start; i < pattern_length; i++) {
|
||||
- shift_table[i] = length;
|
||||
+ shift_get(i) = length;
|
||||
}
|
||||
- shift_table[pattern_length] = 1;
|
||||
- suffix_table[pattern_length] = pattern_length + 1;
|
||||
+ shift_get(pattern_length) = 1;
|
||||
+ suffix_get(pattern_length) = pattern_length + 1;
|
||||
|
||||
if (pattern_length <= start) {
|
||||
return;
|
||||
@@ -620,22 +630,22 @@ void StringSearch<Char>::PopulateBoyerMooreTable() {
|
||||
while (i > start) {
|
||||
Char c = pattern_[i - 1];
|
||||
while (suffix <= pattern_length && c != pattern_[suffix - 1]) {
|
||||
- if (static_cast<size_t>(shift_table[suffix]) == length) {
|
||||
- shift_table[suffix] = suffix - i;
|
||||
+ if (static_cast<size_t>(shift_get(suffix)) == length) {
|
||||
+ shift_get(suffix) = suffix - i;
|
||||
}
|
||||
- suffix = suffix_table[suffix];
|
||||
+ suffix = suffix_get(suffix);
|
||||
}
|
||||
- suffix_table[--i] = --suffix;
|
||||
+ suffix_get(--i) = --suffix;
|
||||
if (suffix == pattern_length) {
|
||||
// No suffix to extend, so we check against last_char only.
|
||||
while ((i > start) && (pattern_[i - 1] != last_char)) {
|
||||
- if (static_cast<size_t>(shift_table[pattern_length]) == length) {
|
||||
- shift_table[pattern_length] = pattern_length - i;
|
||||
+ if (static_cast<size_t>(shift_get(pattern_length)) == length) {
|
||||
+ shift_get(pattern_length) = pattern_length - i;
|
||||
}
|
||||
- suffix_table[--i] = pattern_length;
|
||||
+ suffix_get(--i) = pattern_length;
|
||||
}
|
||||
if (i > start) {
|
||||
- suffix_table[--i] = --suffix;
|
||||
+ suffix_get(--i) = --suffix;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -643,11 +653,11 @@ void StringSearch<Char>::PopulateBoyerMooreTable() {
|
||||
// Build shift table using suffixes.
|
||||
if (suffix < pattern_length) {
|
||||
for (size_t i = start; i <= pattern_length; i++) {
|
||||
- if (static_cast<size_t>(shift_table[i]) == length) {
|
||||
- shift_table[i] = suffix - start;
|
||||
+ if (static_cast<size_t>(shift_get(i)) == length) {
|
||||
+ shift_get(i) = suffix - start;
|
||||
}
|
||||
if (i == suffix) {
|
||||
- suffix = suffix_table[suffix];
|
||||
+ suffix = suffix_get(suffix);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,10 @@ only allocate the native SecureContext on success.
|
||||
|
||||
This should be upstreamed to Node.js.
|
||||
|
||||
diff --git a/lib/_tls_common.js b/lib/_tls_common.js
|
||||
diff --git a/lib/internal/tls/common.js b/lib/internal/tls/common.js
|
||||
index 66331d2d9999e93e59cbce9e153affb942b79946..0f7fd0747ea779f76a9e64ed37d195bd735ea2a8 100644
|
||||
--- a/lib/_tls_common.js
|
||||
+++ b/lib/_tls_common.js
|
||||
--- a/lib/internal/tls/common.js
|
||||
+++ b/lib/internal/tls/common.js
|
||||
@@ -82,10 +82,11 @@ function SecureContext(secureProtocol, secureOptions, minVersion, maxVersion) {
|
||||
throw new ERR_TLS_PROTOCOL_VERSION_CONFLICT(maxVersion, secureProtocol);
|
||||
}
|
||||
@@ -39,10 +39,10 @@ index 66331d2d9999e93e59cbce9e153affb942b79946..0f7fd0747ea779f76a9e64ed37d195bd
|
||||
if (secureOptions) {
|
||||
validateInteger(secureOptions, 'secureOptions');
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index 12ad6e6ddbda2cc679e733f7a9c6b9e4cf9623dd..fc6d295a401d5283ba19dd5c95b748c83b7055a9 100644
|
||||
index ca62d3001bf51193d78caac0cccd93c188a8410c..d6af2460c3745901415d4e785cf210da8a730a8d 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -1354,10 +1354,8 @@ SecureContext::SecureContext(Environment* env, Local<Object> wrap)
|
||||
@@ -1377,10 +1377,8 @@ SecureContext::SecureContext(Environment* env, Local<Object> wrap)
|
||||
}
|
||||
|
||||
inline void SecureContext::Reset() {
|
||||
|
||||
@@ -12,7 +12,7 @@ This can be removed/refactored once Node.js upgrades to a version of V8
|
||||
containing the above CL.
|
||||
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 31439d0cc1199d0e0c94c9d616d957610279e01b..d77735f4f5686e914811c0576975b57e6c631398 100644
|
||||
index 8791119956ff93d65163d2ef424a8d821ebbdfad..ae082f2d0498e0e694e427da71078ca19086e275 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -1248,7 +1248,7 @@ InitializeOncePerProcessInternal(const std::vector<std::string>& args,
|
||||
|
||||
@@ -273,7 +273,7 @@ index a66f0a94efd7c952c1d2320fbc7a39fe3a88a8a1..dc5846db0e3dcf8f7cb5f7efcdbc81c1
|
||||
for (const [file, length] of keys) {
|
||||
const privKey = fixtures.readKey(file);
|
||||
diff --git a/test/parallel/test-crypto.js b/test/parallel/test-crypto.js
|
||||
index 84111740cd9ef6425b747e24e984e66e46b0b2ef..b1621d310536fae3fdec91a6a9d275ec8fc99a98 100644
|
||||
index d21a6bd3d98d6db26cc82896e62da2869cf22842..115a2046b4d4b2688eaf033b58514c903af7a4b5 100644
|
||||
--- a/test/parallel/test-crypto.js
|
||||
+++ b/test/parallel/test-crypto.js
|
||||
@@ -62,7 +62,7 @@ assert.throws(() => {
|
||||
|
||||
@@ -8,10 +8,10 @@ resource path. This commit ensures that the TraverseParent function
|
||||
bails out if the parent path is outside of the resource path.
|
||||
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index df9925404e77ec61900f89a5241c86a599e548c5..b5425122b54d91673e184ccfe88dd3a0ca2ff634 100644
|
||||
index 04ebecc5d924f6c2fddd9992462d1ff692e1cee5..5d9a9da3a068a68c13c5c0cacfe07eec3dad8bc3 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -333,8 +333,41 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
@@ -345,8 +345,41 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
Realm* realm, const std::filesystem::path& check_path) {
|
||||
std::filesystem::path current_path = check_path;
|
||||
auto env = realm->env();
|
||||
@@ -53,7 +53,7 @@ index df9925404e77ec61900f89a5241c86a599e548c5..b5425122b54d91673e184ccfe88dd3a0
|
||||
do {
|
||||
current_path = current_path.parent_path();
|
||||
|
||||
@@ -354,6 +387,12 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
@@ -366,6 +399,12 @@ const BindingData::PackageConfig* BindingData::TraverseParent(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ index bb874fec74c73b5de0ef6d1e2a872ebceefb11ce..6fafe2a8029c535fa98276e2d73f04ee
|
||||
V(performance_entry_callback, v8::Function) \
|
||||
V(prepare_stack_trace_callback, v8::Function) \
|
||||
diff --git a/src/node_modules.cc b/src/node_modules.cc
|
||||
index fa0aa90cf4d6a9fae3cde0b0bb743b88b47c07bb..d3907c3d063c7757cdd7ef99ed09bea1eb58a3fd 100644
|
||||
index 95a7b8c32693c32ca9f57e01aff9ef06b84f78b2..cecdda74847801fd5821bc0afdf0dfc9f131c44a 100644
|
||||
--- a/src/node_modules.cc
|
||||
+++ b/src/node_modules.cc
|
||||
@@ -23,12 +23,14 @@ namespace modules {
|
||||
@@ -46,7 +46,7 @@ index fa0aa90cf4d6a9fae3cde0b0bb743b88b47c07bb..d3907c3d063c7757cdd7ef99ed09bea1
|
||||
auto binding_data = realm->GetBindingData<BindingData>();
|
||||
|
||||
auto cache_entry = binding_data->package_configs_.find(path.data());
|
||||
@@ -103,8 +106,48 @@ const BindingData::PackageConfig* BindingData::GetPackageJSON(
|
||||
@@ -111,8 +114,48 @@ const BindingData::PackageConfig* BindingData::GetPackageJSON(
|
||||
|
||||
PackageConfig package_config{};
|
||||
package_config.file_path = path;
|
||||
@@ -93,11 +93,11 @@ index fa0aa90cf4d6a9fae3cde0b0bb743b88b47c07bb..d3907c3d063c7757cdd7ef99ed09bea1
|
||||
+ }
|
||||
+ }
|
||||
+ if (read_err < 0) {
|
||||
return nullptr;
|
||||
}
|
||||
simdjson::ondemand::document document;
|
||||
@@ -242,6 +285,12 @@ const BindingData::PackageConfig* BindingData::GetPackageJSON(
|
||||
return &cached.first->second;
|
||||
// Add `nullopt` to the package config cache so that we don't
|
||||
// need to open and attempt to read this path again
|
||||
binding_data->package_configs_.insert({std::string(path), std::nullopt});
|
||||
@@ -254,6 +297,12 @@ const BindingData::PackageConfig* BindingData::GetPackageJSON(
|
||||
return &*cached.first->second;
|
||||
}
|
||||
|
||||
+void BindingData::OverrideReadFileSync(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -109,7 +109,7 @@ index fa0aa90cf4d6a9fae3cde0b0bb743b88b47c07bb..d3907c3d063c7757cdd7ef99ed09bea1
|
||||
void BindingData::ReadPackageJSON(const FunctionCallbackInfo<Value>& args) {
|
||||
CHECK_GE(args.Length(), 1); // path, [is_esm, base, specifier]
|
||||
CHECK(args[0]->IsString()); // path
|
||||
@@ -635,6 +684,8 @@ void SaveCompileCacheEntry(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -672,6 +721,8 @@ void SaveCompileCacheEntry(const FunctionCallbackInfo<Value>& args) {
|
||||
void BindingData::CreatePerIsolateProperties(IsolateData* isolate_data,
|
||||
Local<ObjectTemplate> target) {
|
||||
Isolate* isolate = isolate_data->isolate();
|
||||
@@ -118,7 +118,7 @@ index fa0aa90cf4d6a9fae3cde0b0bb743b88b47c07bb..d3907c3d063c7757cdd7ef99ed09bea1
|
||||
SetMethod(isolate, target, "readPackageJSON", ReadPackageJSON);
|
||||
SetMethod(isolate,
|
||||
target,
|
||||
@@ -694,6 +745,8 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
@@ -735,6 +786,8 @@ void BindingData::CreatePerContextProperties(Local<Object> target,
|
||||
|
||||
void BindingData::RegisterExternalReferences(
|
||||
ExternalReferenceRegistry* registry) {
|
||||
@@ -126,9 +126,9 @@ index fa0aa90cf4d6a9fae3cde0b0bb743b88b47c07bb..d3907c3d063c7757cdd7ef99ed09bea1
|
||||
+
|
||||
registry->Register(ReadPackageJSON);
|
||||
registry->Register(GetNearestParentPackageJSONType);
|
||||
registry->Register(GetPackageScopeConfig<false>);
|
||||
registry->Register(GetNearestParentPackageJSON);
|
||||
diff --git a/src/node_modules.h b/src/node_modules.h
|
||||
index e4ba6b75bc86d14deada835903ba68a4cb0eccc5..ae77f9ec81b358bd356993617cd07671d382e8ca 100644
|
||||
index d610306a3a3111327f111def823b07c3da04192f..5bb7245816822282977e62ce3b0e6c0b9c6ac32b 100644
|
||||
--- a/src/node_modules.h
|
||||
+++ b/src/node_modules.h
|
||||
@@ -54,6 +54,8 @@ class BindingData : public SnapshotableObject {
|
||||
@@ -138,5 +138,5 @@ index e4ba6b75bc86d14deada835903ba68a4cb0eccc5..ae77f9ec81b358bd356993617cd07671
|
||||
+ static void OverrideReadFileSync(
|
||||
+ const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void ReadPackageJSON(const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
static void GetNearestParentPackageJSONType(
|
||||
static void GetNearestParentPackageJSON(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args);
|
||||
|
||||
@@ -64,7 +64,7 @@ index c284163fba86ec820af1996571fbd3d092d41d34..5f1921d15bc1d3a68c35990f85e36a0e
|
||||
}
|
||||
}
|
||||
diff --git a/lib/internal/modules/esm/loader.js b/lib/internal/modules/esm/loader.js
|
||||
index abfe88c272dcc4aa1e95948bf754f55e1df74ddf..7a29cd391fdf050ebda50c5b2f263d27001ced74 100644
|
||||
index 22c1e9f1ae652b033903f56f394352806ddff754..961da666a233541203b5416909fd1ff0326e63e1 100644
|
||||
--- a/lib/internal/modules/esm/loader.js
|
||||
+++ b/lib/internal/modules/esm/loader.js
|
||||
@@ -437,7 +437,7 @@ class ModuleLoader {
|
||||
@@ -77,10 +77,10 @@ index abfe88c272dcc4aa1e95948bf754f55e1df74ddf..7a29cd391fdf050ebda50c5b2f263d27
|
||||
if (cjsModule?.[kIsExecuting]) {
|
||||
const parentFilename = urlToFilename(parentURL);
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index c27ee4c6612c6a7ea0b6355f03563e8724fd0e40..5f03cf14e948d449d303b22ab6710b5508fb83b2 100644
|
||||
index c1d774b9c5c4049f7ecda4e3a1faaa59dad01764..4fd58b1cea557ec122bd860e1ebc15bd04c44f78 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -751,6 +751,9 @@ function packageImportsResolve(name, base, conditions) {
|
||||
@@ -752,6 +752,9 @@ function packageImportsResolve(name, base, conditions) {
|
||||
throw importNotDefined(name, packageJSONUrl, base);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ index c27ee4c6612c6a7ea0b6355f03563e8724fd0e40..5f03cf14e948d449d303b22ab6710b55
|
||||
|
||||
/**
|
||||
* Resolves a package specifier to a URL.
|
||||
@@ -765,6 +768,11 @@ function packageResolve(specifier, base, conditions) {
|
||||
@@ -766,6 +769,11 @@ function packageResolve(specifier, base, conditions) {
|
||||
return new URL('node:' + specifier);
|
||||
}
|
||||
|
||||
@@ -129,10 +129,10 @@ index 1716328c7a98996a8933dbaa00a1c6c3156fb2ff..30f887663bbbd9913eff35f0e6e5b829
|
||||
// This translator function must be sync, as `require` is sync.
|
||||
translators.set('require-commonjs-typescript', (url, translateContext, parentURL) => {
|
||||
diff --git a/lib/internal/url.js b/lib/internal/url.js
|
||||
index a1473fdac8aba3be541df3b6688a05c0dfbe403f..0a87d997856ea227f8f21393909ffc4634043f24 100644
|
||||
index 813208f39e6622a43ae27ba0cc5d11d1e0de55c1..1c1e6075ebabbdbc29d811fcb9f911ee29b28f9e 100644
|
||||
--- a/lib/internal/url.js
|
||||
+++ b/lib/internal/url.js
|
||||
@@ -1609,6 +1609,8 @@ function fileURLToPath(path, options = kEmptyObject) {
|
||||
@@ -1604,6 +1604,8 @@ function fileURLToPath(path, options = kEmptyObject) {
|
||||
path = new URL(path);
|
||||
else if (!isURL(path))
|
||||
throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Tue, 10 Feb 2026 16:48:47 +0100
|
||||
Subject: fix: generate_config_gypi needs to generate valid JSON
|
||||
|
||||
Node.js added new process.config.variables entries, which the GN generator
|
||||
emitted with Python repr (single quotes). This made the JSON parse blow
|
||||
up. Fix this by switching to json.dumps.
|
||||
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/tools/generate_config_gypi.py b/tools/generate_config_gypi.py
|
||||
index abd11e1dbda8d400cb900343c6e8d2d6e84fe944..436767e633e1f492fa858645e25ce9b904a5fccb 100755
|
||||
--- a/tools/generate_config_gypi.py
|
||||
+++ b/tools/generate_config_gypi.py
|
||||
@@ -58,7 +58,7 @@ def translate_config(out_dir, config, v8_config):
|
||||
'llvm_version': 13,
|
||||
'napi_build_version': config['napi_build_version'],
|
||||
'node_builtin_shareable_builtins':
|
||||
- eval(config['node_builtin_shareable_builtins']),
|
||||
+ json.loads(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'],
|
||||
@@ -102,7 +102,8 @@ def main():
|
||||
|
||||
# Write output.
|
||||
with open(args.target, 'w') as f:
|
||||
- f.write(repr(translate_config(args.out_dir, config, v8_config)))
|
||||
+ f.write(json.dumps(translate_config(args.out_dir, config, v8_config),
|
||||
+ sort_keys=True))
|
||||
|
||||
# Write depfile. Force regenerating config.gypi when GN configs change.
|
||||
if args.dep_file:
|
||||
@@ -107,7 +107,7 @@ index e2407027ab05e59b2f0f1c213b98ea469db7a91b..c64761b730e61edcdc0e46a48699f2fd
|
||||
# The location of simdutf - use the one from node's deps by default.
|
||||
node_simdutf_path = "//third_party/simdutf"
|
||||
diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc
|
||||
index 5ed2f8b35a1e2f8348a0f3891f37944f49371256..bd453ae633b2833cc3c6e3e415b43792dc5bf2e5 100644
|
||||
index ed509e5c9fe79c5d545180fef0fea9ab6f1ba39b..9446314c95e57ea408568d107a9f6e76886650cb 100644
|
||||
--- a/src/crypto/crypto_cipher.cc
|
||||
+++ b/src/crypto/crypto_cipher.cc
|
||||
@@ -447,6 +447,7 @@ bool CipherBase::InitAuthenticated(const char* cipher_type,
|
||||
@@ -151,7 +151,7 @@ index d005bf0ffb93445fa6611a1beb1b465764271ede..01770687bd191c61af02e76d7de24bba
|
||||
X509View ca(sk_X509_value(peer_certs.get(), i));
|
||||
if (!cert->view().isIssuedBy(ca)) continue;
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index 03c0c6f42d84efaeba0cc3b997cd29f77648b00d..f3631d538a38dc3a93a47707ea8dab0462fa2140 100644
|
||||
index 4e968477ebcc08fb0ccd6abd4d66240309cf76e8..2e3f31e1765024373c3fc2acd33fc3bfb352a906 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -143,7 +143,7 @@ int SSL_CTX_use_certificate_chain(SSL_CTX* ctx,
|
||||
@@ -163,7 +163,7 @@ index 03c0c6f42d84efaeba0cc3b997cd29f77648b00d..f3631d538a38dc3a93a47707ea8dab04
|
||||
X509* ca = sk_X509_value(extra_certs, i);
|
||||
|
||||
// NOTE: Increments reference count on `ca`
|
||||
@@ -1832,11 +1832,12 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -1855,11 +1855,12 @@ void SecureContext::SetDHParam(const FunctionCallbackInfo<Value>& args) {
|
||||
// If the user specified "auto" for dhparams, the JavaScript layer will pass
|
||||
// true to this function instead of the original string. Any other string
|
||||
// value will be interpreted as custom DH parameters below.
|
||||
@@ -177,7 +177,7 @@ index 03c0c6f42d84efaeba0cc3b997cd29f77648b00d..f3631d538a38dc3a93a47707ea8dab04
|
||||
DHPointer dh;
|
||||
{
|
||||
BIOPointer bio(LoadBIO(env, args[0]));
|
||||
@@ -2062,7 +2063,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
|
||||
@@ -2085,7 +2086,7 @@ void SecureContext::LoadPKCS12(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
// Add CA certs too
|
||||
@@ -276,7 +276,7 @@ index 205e248e0f20f019e189a6c69d3c011a616b3939..12b0d804c6f1d4998b85160b0aac8eb7
|
||||
|
||||
#define V(name) case ERR_LIB_##name: lib = #name "_"; break;
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index ed2253f1fc3cf8d59e73e4f2478dfb0d4227aacd..84a650885a79bc5c49efdc26f62ec8db48de775c 100644
|
||||
index 3ab33341806ad6c0b06b982a30a57b7b5399e38f..754ddf7b331465c56081db05d6fd2a45fe50596a 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -52,7 +52,7 @@
|
||||
@@ -311,7 +311,7 @@ index d9c533f100d25aeab1fe8589932a8ddead431258..2acab8786a8a752b17961445edeb872c
|
||||
#if NODE_OPENSSL_HAS_QUIC
|
||||
#include <openssl/quic.h>
|
||||
diff --git a/src/node_options.h b/src/node_options.h
|
||||
index 1f15c6cc6a9ae192b1b394c437393e744b5b1153..638e49ccf48d9b9c60189af9255ce7cef9184723 100644
|
||||
index 887ead81d4b8bd55351091c06ed641c6a87b8419..6d4df44ccc06c3278948879a2430ab6f459cbec4 100644
|
||||
--- a/src/node_options.h
|
||||
+++ b/src/node_options.h
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
@@ -28,7 +28,7 @@ index 5f1921d15bc1d3a68c35990f85e36a0e8a5b3ec4..99c6ce57c04768d125dd0a1c6bd62bca
|
||||
const result = dataURLProcessor(url);
|
||||
if (result === 'failure') {
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 5f03cf14e948d449d303b22ab6710b5508fb83b2..72cc9444ca93ef7a1526e23314693aeaf5f173b0 100644
|
||||
index 4fd58b1cea557ec122bd860e1ebc15bd04c44f78..8dc8bbfe8d73e2d11edc261d6fe9f37aaa81e4cd 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -25,7 +25,7 @@ const {
|
||||
@@ -40,7 +40,7 @@ index 5f03cf14e948d449d303b22ab6710b5508fb83b2..72cc9444ca93ef7a1526e23314693aea
|
||||
const { getOptionValue } = require('internal/options');
|
||||
// Do not eagerly grab .manifest, it may be in TDZ
|
||||
const { sep, posix: { relative: relativePosixPath }, resolve } = require('path');
|
||||
@@ -276,7 +276,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
|
||||
@@ -277,7 +277,7 @@ function finalizeResolution(resolved, base, preserveSymlinks) {
|
||||
}
|
||||
|
||||
if (!preserveSymlinks) {
|
||||
|
||||
@@ -6,7 +6,7 @@ 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 414e450ee3a8110b8249dd831fef1ab885cc6fa1..c6ff40d814a49536808a2fd79ee6918c3ac118c9 100644
|
||||
index 2b199e82fee3a9d56521b9c5cc04a20cdfd6f045..e28755a20176c2806769430910b28a0e61d7691e 100644
|
||||
--- a/lib/internal/modules/cjs/loader.js
|
||||
+++ b/lib/internal/modules/cjs/loader.js
|
||||
@@ -209,6 +209,13 @@ const {
|
||||
@@ -23,7 +23,7 @@ index 414e450ee3a8110b8249dd831fef1ab885cc6fa1..c6ff40d814a49536808a2fd79ee6918c
|
||||
const {
|
||||
isProxy,
|
||||
} = require('internal/util/types');
|
||||
@@ -1756,10 +1763,12 @@ Module.prototype._compile = function(content, filename, format) {
|
||||
@@ -1799,10 +1806,12 @@ Module.prototype._compile = function(content, filename, format) {
|
||||
if (this[kIsMainSymbol] && getOptionValue('--inspect-brk')) {
|
||||
const { callAndPauseOnStart } = internalBinding('inspector');
|
||||
result = callAndPauseOnStart(compiledWrapper, thisValue, exports,
|
||||
|
||||
@@ -143,7 +143,7 @@ index dd6ecd1f9d82f6661b2480c0195e33515633429f..334d5cb7df7a763e0929468392dad834
|
||||
isolate_ =
|
||||
NewIsolate(isolate_params_.get(), event_loop, platform, snapshot_data);
|
||||
diff --git a/src/node_worker.cc b/src/node_worker.cc
|
||||
index 7bae29747d8cd8e83973d105099f9111fc185fe1..62c53368d1173edb7eb42e3337049c46fd7cdda9 100644
|
||||
index fcfd5fecdebd2724441eb83b498b38b11eedad25..e7d26b4c8cbb08a175084ceac51395860dc60598 100644
|
||||
--- a/src/node_worker.cc
|
||||
+++ b/src/node_worker.cc
|
||||
@@ -181,6 +181,9 @@ class WorkerThreadData {
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joyee Cheung <joyeec9h3@gmail.com>
|
||||
Date: Thu, 20 Nov 2025 13:50:28 +0900
|
||||
Subject: src: handle DER decoding errors from system certificates
|
||||
|
||||
When decoding certificates from the system store, it's not actually
|
||||
guaranteed to succeed. In case the system returns a certificate
|
||||
that cannot be decoded (might be related to SSL implementation issues),
|
||||
skip them.
|
||||
|
||||
diff --git a/src/crypto/crypto_context.cc b/src/crypto/crypto_context.cc
|
||||
index fc6d295a401d5283ba19dd5c95b748c83b7055a9..b971ea5b6842549563c0c54168d17ecf6e72bb73 100644
|
||||
--- a/src/crypto/crypto_context.cc
|
||||
+++ b/src/crypto/crypto_context.cc
|
||||
@@ -507,7 +507,11 @@ void ReadMacOSKeychainCertificates(
|
||||
CFRelease(search);
|
||||
|
||||
if (ortn) {
|
||||
- fprintf(stderr, "ERROR: SecItemCopyMatching failed %d\n", ortn);
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Cannot read certificates from system because "
|
||||
+ "SecItemCopyMatching failed %d\n",
|
||||
+ ortn);
|
||||
+ return;
|
||||
}
|
||||
|
||||
CFIndex count = CFArrayGetCount(curr_anchors);
|
||||
@@ -518,7 +522,9 @@ void ReadMacOSKeychainCertificates(
|
||||
|
||||
CFDataRef der_data = SecCertificateCopyData(cert_ref);
|
||||
if (!der_data) {
|
||||
- fprintf(stderr, "ERROR: SecCertificateCopyData failed\n");
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Skipping read of a system certificate "
|
||||
+ "because SecCertificateCopyData failed\n");
|
||||
continue;
|
||||
}
|
||||
auto data_buffer_pointer = CFDataGetBytePtr(der_data);
|
||||
@@ -526,9 +532,19 @@ void ReadMacOSKeychainCertificates(
|
||||
X509* cert =
|
||||
d2i_X509(nullptr, &data_buffer_pointer, CFDataGetLength(der_data));
|
||||
CFRelease(der_data);
|
||||
+
|
||||
+ if (cert == nullptr) {
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Skipping read of a system certificate "
|
||||
+ "because decoding failed\n");
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
bool is_valid = IsCertificateTrustedForPolicy(cert, cert_ref);
|
||||
if (is_valid) {
|
||||
system_root_certificates_X509->emplace_back(cert);
|
||||
+ } else {
|
||||
+ X509_free(cert);
|
||||
}
|
||||
}
|
||||
CFRelease(curr_anchors);
|
||||
@@ -638,7 +654,14 @@ void GatherCertsForLocation(std::vector<X509*>* vector,
|
||||
reinterpret_cast<const unsigned char*>(cert_from_store->pbCertEncoded);
|
||||
const size_t cert_size = cert_from_store->cbCertEncoded;
|
||||
|
||||
- vector->emplace_back(d2i_X509(nullptr, &cert_data, cert_size));
|
||||
+ X509* x509 = d2i_X509(nullptr, &cert_data, cert_size);
|
||||
+ if (x509 == nullptr) {
|
||||
+ per_process::Debug(DebugCategory::CRYPTO,
|
||||
+ "Skipping read of a system certificate "
|
||||
+ "because decoding failed\n");
|
||||
+ } else {
|
||||
+ vector->emplace_back(x509);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,7 +121,7 @@ index b30297eac08ad9587642b723f91d7e3b954294d4..4c5427596d1c90d3a413cdd9ff4f1151
|
||||
auto backing = ArrayBuffer::NewBackingStore(
|
||||
mem->data,
|
||||
diff --git a/src/node_buffer.cc b/src/node_buffer.cc
|
||||
index 49df0b4284748effb27b05ecd69f05699dd8be75..77da37881bb351249c45e405289193c10d083e0c 100644
|
||||
index ddee7b7e40c3ee4054b2b15b75154607aa6431ed..decc3c8c966c2322f22d6bdd871514bb53882a29 100644
|
||||
--- a/src/node_buffer.cc
|
||||
+++ b/src/node_buffer.cc
|
||||
@@ -1420,7 +1420,7 @@ inline size_t CheckNumberToSize(Local<Value> number) {
|
||||
@@ -309,3 +309,17 @@ index ef659f1c39f7ee958879bf395377bc99911fc346..225b1465b7c97d972a38968faf6d6850
|
||||
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-concat.js b/test/parallel/test-buffer-concat.js
|
||||
index 9f0eadd2f10163c3c30657c84eb0ba55db17364d..7c1a6f71ca24dd2e54f9f5987aae2014b44bfba6 100644
|
||||
--- a/test/parallel/test-buffer-concat.js
|
||||
+++ b/test/parallel/test-buffer-concat.js
|
||||
@@ -84,8 +84,7 @@ assert.throws(() => {
|
||||
Buffer.concat([Buffer.from('hello')], -2);
|
||||
}, {
|
||||
code: 'ERR_OUT_OF_RANGE',
|
||||
- message: 'The value of "length" is out of range. It must be >= 0 && <= 9007199254740991. ' +
|
||||
- 'Received -2'
|
||||
+ message: /The value of "length" is out of range\. It must be >= 0 && <= (?:34359738367|9007199254740991)\. Received -2/
|
||||
});
|
||||
|
||||
// eslint-disable-next-line node-core/crypto-check
|
||||
|
||||
@@ -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 8ac30c589926a46356f44076a21f8c18057378e1..8531599f1c1474640bf804737244129c5860b0bd 100644
|
||||
index 8bf4ae46f2d1d204d05adb6e951a613902f8bae2..2438ed04e3477c3bc74d02717129bf830a40c5f4 100644
|
||||
--- a/test/parallel/parallel.status
|
||||
+++ b/test/parallel/parallel.status
|
||||
@@ -5,6 +5,16 @@ prefix parallel
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Ren=C3=A9?= <contact.9a5d6388@renegade334.me.uk>
|
||||
Date: Sat, 20 Dec 2025 22:20:21 +0000
|
||||
Subject: test: make buffer sizes 32bit-aware in
|
||||
test-internal-util-construct-sab
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/61026
|
||||
Fixes: https://github.com/nodejs/node/issues/61025
|
||||
Refs: https://github.com/nodejs/node/pull/60497
|
||||
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
|
||||
|
||||
diff --git a/test/parallel/test-internal-util-construct-sab.js b/test/parallel/test-internal-util-construct-sab.js
|
||||
index 5ff9b09f8e7d36a91825a38e861b8c2615c62500..403b59809e47d2e1d3503a059826f66334a2f035 100644
|
||||
--- a/test/parallel/test-internal-util-construct-sab.js
|
||||
+++ b/test/parallel/test-internal-util-construct-sab.js
|
||||
@@ -3,16 +3,20 @@
|
||||
|
||||
require('../common');
|
||||
const assert = require('assert');
|
||||
+const { kMaxLength } = require('buffer');
|
||||
const { isSharedArrayBuffer } = require('util/types');
|
||||
const { constructSharedArrayBuffer } = require('internal/util');
|
||||
|
||||
// We're testing that we can construct a SAB even when the global is not exposed.
|
||||
assert.strictEqual(typeof SharedArrayBuffer, 'undefined');
|
||||
|
||||
-for (const length of [undefined, 0, 1, 2 ** 32]) {
|
||||
+for (const length of [undefined, 0, 1, 2 ** 16]) {
|
||||
assert(isSharedArrayBuffer(constructSharedArrayBuffer(length)));
|
||||
}
|
||||
|
||||
-for (const length of [-1, Number.MAX_SAFE_INTEGER + 1, 2 ** 64]) {
|
||||
+// Specifically test the following cases:
|
||||
+// - out-of-range allocation requests should not crash the process
|
||||
+// - no int64 overflow
|
||||
+for (const length of [-1, kMaxLength + 1, 2 ** 64]) {
|
||||
assert.throws(() => constructSharedArrayBuffer(length), RangeError);
|
||||
}
|
||||
32
script/copy-pipeline-segment-publish.js
Normal file
32
script/copy-pipeline-segment-publish.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const yaml = require('yaml');
|
||||
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
|
||||
const PREFIX = '# AUTOGENERATED FILE - DO NOT EDIT MANUALLY\n# ONLY EDIT .github/workflows/pipeline-segment-electron-build.yml\n\n';
|
||||
|
||||
const base = path.resolve(__dirname, '../.github/workflows/pipeline-segment-electron-build.yml');
|
||||
const target = path.resolve(__dirname, '../.github/workflows/pipeline-segment-electron-publish.yml');
|
||||
|
||||
const baseContents = fs.readFileSync(base, 'utf-8');
|
||||
|
||||
const parsedBase = yaml.parse(baseContents);
|
||||
parsedBase.jobs.build.permissions = {
|
||||
'artifact-metadata': 'write',
|
||||
attestations: 'write',
|
||||
contents: 'read',
|
||||
'id-token': 'write'
|
||||
};
|
||||
|
||||
if (process.argv.includes('--check')) {
|
||||
if (fs.readFileSync(target, 'utf-8') !== PREFIX + yaml.stringify(parsedBase)) {
|
||||
console.error(`${target} is out of date`);
|
||||
console.error('Please run "copy-pipeline-segment-publish.js" to update it');
|
||||
process.exit(1);
|
||||
}
|
||||
} else {
|
||||
fs.writeFileSync(
|
||||
target,
|
||||
PREFIX + yaml.stringify(parsedBase)
|
||||
);
|
||||
}
|
||||
@@ -107,7 +107,8 @@
|
||||
"parallel/test-tls-multi-key",
|
||||
"parallel/test-tls-multi-pfx",
|
||||
"parallel/test-tls-no-cert-required",
|
||||
"parallel/test-tls-no-sslv23.js",
|
||||
"parallel/test-tls-no-sslv23",
|
||||
"parallel/test-tls-off-thread-cert-loading",
|
||||
"parallel/test-tls-options-boolean-check",
|
||||
"parallel/test-tls-passphrase",
|
||||
"parallel/test-tls-peer-certificate",
|
||||
|
||||
@@ -369,6 +369,14 @@ def upload_io_to_github(release, filename, filepath, version):
|
||||
sys.stdout.buffer.write(c)
|
||||
sys.stdout.flush()
|
||||
|
||||
if "GITHUB_OUTPUT" in os.environ:
|
||||
output_path = os.environ["GITHUB_OUTPUT"]
|
||||
with open(output_path, "r+", encoding='utf-8') as github_output:
|
||||
if len(github_output.readlines()) > 0:
|
||||
github_output.write(",")
|
||||
else:
|
||||
github_output.write('UPLOADED_PATHS=')
|
||||
github_output.write(filepath)
|
||||
|
||||
def upload_sha256_checksum(version, file_path, key_prefix=None):
|
||||
checksum_path = f'{file_path}.sha256sum'
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "shell/browser/notifications/win/windows_toast_activator.h"
|
||||
#include "shell/browser/ui/win/jump_list.h"
|
||||
#endif
|
||||
|
||||
@@ -1840,6 +1841,10 @@ gin::ObjectTemplateBuilder App::GetObjectTemplateBuilder(v8::Isolate* isolate) {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
.SetMethod("setAppUserModelId",
|
||||
base::BindRepeating(&Browser::SetAppUserModelID, browser))
|
||||
.SetMethod("setToastActivatorCLSID",
|
||||
base::BindRepeating(&App::SetToastActivatorCLSID,
|
||||
base::Unretained(this)))
|
||||
.SetProperty("toastActivatorCLSID", &App::GetToastActivatorCLSID)
|
||||
#endif
|
||||
.SetMethod(
|
||||
"isDefaultProtocolClient",
|
||||
@@ -1967,6 +1972,34 @@ gin::ObjectTemplateBuilder App::GetObjectTemplateBuilder(v8::Isolate* isolate) {
|
||||
.SetMethod("resolveProxy", &App::ResolveProxy);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
void App::SetToastActivatorCLSID(gin_helper::ErrorThrower thrower,
|
||||
const std::string& id) {
|
||||
std::wstring wide = base::UTF8ToWide(id);
|
||||
CLSID parsed;
|
||||
if (FAILED(::CLSIDFromString(wide.c_str(), &parsed))) {
|
||||
if (!wide.empty() && wide.front() != L'{') {
|
||||
std::wstring with_braces = L"{" + wide + L"}";
|
||||
if (FAILED(::CLSIDFromString(with_braces.c_str(), &parsed))) {
|
||||
thrower.ThrowError("Invalid CLSID format");
|
||||
return;
|
||||
}
|
||||
wide = std::move(with_braces);
|
||||
} else {
|
||||
thrower.ThrowError("Invalid CLSID format");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SetAppToastActivatorCLSID(wide);
|
||||
}
|
||||
|
||||
v8::Local<v8::Value> App::GetToastActivatorCLSID(v8::Isolate* isolate) {
|
||||
return gin::ConvertToV8(isolate,
|
||||
base::WideToUTF8(GetAppToastActivatorCLSID()));
|
||||
}
|
||||
#endif
|
||||
|
||||
const char* App::GetHumanReadableName() const {
|
||||
return "Electron / App";
|
||||
}
|
||||
|
||||
@@ -265,6 +265,12 @@ class App final : public gin::Wrappable<App>,
|
||||
|
||||
// Set or remove a custom Jump List for the application.
|
||||
JumpListResult SetJumpList(v8::Isolate* isolate, v8::Local<v8::Value> val);
|
||||
|
||||
// Set the toast activator CLSID.
|
||||
void SetToastActivatorCLSID(gin_helper::ErrorThrower thrower,
|
||||
const std::string& id);
|
||||
// Get the toast activator CLSID.
|
||||
v8::Local<v8::Value> GetToastActivatorCLSID(v8::Isolate* isolate);
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
std::unique_ptr<ProcessSingleton> process_singleton_;
|
||||
|
||||
@@ -31,6 +31,9 @@ struct Converter<electron::NotificationAction> {
|
||||
return false;
|
||||
}
|
||||
dict.Get("text", &(out->text));
|
||||
std::vector<std::u16string> items;
|
||||
if (dict.Get("items", &items))
|
||||
out->items = std::move(items);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -39,6 +42,9 @@ struct Converter<electron::NotificationAction> {
|
||||
auto dict = gin::Dictionary::CreateEmpty(isolate);
|
||||
dict.Set("text", val.text);
|
||||
dict.Set("type", val.type);
|
||||
if (!val.items.empty()) {
|
||||
dict.Set("items", val.items);
|
||||
}
|
||||
return ConvertToV8(isolate, dict);
|
||||
}
|
||||
};
|
||||
@@ -138,8 +144,20 @@ void Notification::SetToastXml(const std::u16string& new_toast_xml) {
|
||||
toast_xml_ = new_toast_xml;
|
||||
}
|
||||
|
||||
void Notification::NotificationAction(int index) {
|
||||
Emit("action", index);
|
||||
void Notification::NotificationAction(int action_index, int selection_index) {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
gin_helper::internal::Event* event =
|
||||
gin_helper::internal::Event::New(isolate);
|
||||
v8::Local<v8::Object> event_object =
|
||||
event->GetWrapper(isolate).ToLocalChecked();
|
||||
|
||||
gin_helper::Dictionary dict(isolate, event_object);
|
||||
dict.Set("selectionIndex", selection_index);
|
||||
dict.Set("actionIndex", action_index);
|
||||
|
||||
EmitWithoutEvent("action", event_object, action_index, selection_index);
|
||||
}
|
||||
|
||||
void Notification::NotificationClick() {
|
||||
@@ -147,7 +165,18 @@ void Notification::NotificationClick() {
|
||||
}
|
||||
|
||||
void Notification::NotificationReplied(const std::string& reply) {
|
||||
Emit("reply", reply);
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
v8::HandleScope handle_scope(isolate);
|
||||
|
||||
gin_helper::internal::Event* event =
|
||||
gin_helper::internal::Event::New(isolate);
|
||||
v8::Local<v8::Object> event_object =
|
||||
event->GetWrapper(isolate).ToLocalChecked();
|
||||
|
||||
gin_helper::Dictionary dict(isolate, event_object);
|
||||
dict.Set("reply", reply);
|
||||
|
||||
EmitWithoutEvent("reply", event_object, reply);
|
||||
}
|
||||
|
||||
void Notification::NotificationDisplayed() {
|
||||
|
||||
@@ -45,7 +45,7 @@ class Notification final : public gin_helper::DeprecatedWrappable<Notification>,
|
||||
static const char* GetClassName() { return "Notification"; }
|
||||
|
||||
// NotificationDelegate:
|
||||
void NotificationAction(int index) override;
|
||||
void NotificationAction(int action_index, int selection_index) override;
|
||||
void NotificationClick() override;
|
||||
void NotificationReplied(const std::string& reply) override;
|
||||
void NotificationDisplayed() override;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user