mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
178 Commits
v30.1.2
...
v32.0.0-ni
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
752efddf89 | ||
|
|
23a5d8b64a | ||
|
|
2e778a98b9 | ||
|
|
b8381b7d93 | ||
|
|
af9a59cc40 | ||
|
|
c67744a127 | ||
|
|
0b62abf244 | ||
|
|
19dc276878 | ||
|
|
a54afabe04 | ||
|
|
125bd6aa2b | ||
|
|
7f8fabbe7b | ||
|
|
435003566d | ||
|
|
d7099b0ad4 | ||
|
|
f2af35182c | ||
|
|
d0cb298f95 | ||
|
|
1ef5406c8c | ||
|
|
4e70213037 | ||
|
|
45cc31fd2f | ||
|
|
03e259dc25 | ||
|
|
e4d89ba2b4 | ||
|
|
44ebc1b1c2 | ||
|
|
4c27b0c282 | ||
|
|
e19754d7fd | ||
|
|
c56e1dffb0 | ||
|
|
653d0f009e | ||
|
|
10fd0ba655 | ||
|
|
88f28a302f | ||
|
|
8d4467bdc4 | ||
|
|
188196e78c | ||
|
|
c765d57265 | ||
|
|
3ea3b0e8e1 | ||
|
|
96dda274e9 | ||
|
|
9b0409f7c9 | ||
|
|
0725f5c5cf | ||
|
|
c00eb5d491 | ||
|
|
3bd807b03e | ||
|
|
e2acdffe58 | ||
|
|
865b0499bb | ||
|
|
6675f3ae65 | ||
|
|
731bc7a334 | ||
|
|
793276ac87 | ||
|
|
0128a072d6 | ||
|
|
a059dd7b69 | ||
|
|
53a4484372 | ||
|
|
8cfc4b9d50 | ||
|
|
c3c4173377 | ||
|
|
d5c8f2d6d9 | ||
|
|
5b60698dea | ||
|
|
05631ec445 | ||
|
|
36310b8729 | ||
|
|
f5fb44eaf8 | ||
|
|
441dbda833 | ||
|
|
ef097b77ad | ||
|
|
5310b79ffb | ||
|
|
b95d0f7623 | ||
|
|
b41da150ca | ||
|
|
b684a98267 | ||
|
|
7621e7cff7 | ||
|
|
d8f8560b1c | ||
|
|
1cf194faae | ||
|
|
a0fee8f47a | ||
|
|
4e8c28fdf0 | ||
|
|
46adb0a3a9 | ||
|
|
a8db7fe2ef | ||
|
|
0346e0a8bf | ||
|
|
39bf441b3b | ||
|
|
46ef7ef8fb | ||
|
|
07a68c2bf8 | ||
|
|
ed9fec7da4 | ||
|
|
c4aeb17245 | ||
|
|
67ba30402b | ||
|
|
b683754c16 | ||
|
|
0222686e9a | ||
|
|
bf754a3cae | ||
|
|
7120c58297 | ||
|
|
b118c70f77 | ||
|
|
cdafe09ffb | ||
|
|
b428315c6d | ||
|
|
c670e38b4b | ||
|
|
6aa9a003c8 | ||
|
|
2a6ad42113 | ||
|
|
d80c5f8377 | ||
|
|
755f7d5ed0 | ||
|
|
734395bea9 | ||
|
|
75dae2e004 | ||
|
|
b446ce7f22 | ||
|
|
05fba85aa3 | ||
|
|
db11090e58 | ||
|
|
df22e62bf4 | ||
|
|
f8c832d80d | ||
|
|
344aba0838 | ||
|
|
41ba963392 | ||
|
|
43a9f70d19 | ||
|
|
0a7df0ef3d | ||
|
|
38ef9a7690 | ||
|
|
ba3b647fd7 | ||
|
|
76f7bbb0a8 | ||
|
|
22c149812c | ||
|
|
42164d7081 | ||
|
|
3eb94b72ba | ||
|
|
752f2eb124 | ||
|
|
beafbfd511 | ||
|
|
d54645e554 | ||
|
|
0bf53a3876 | ||
|
|
62d4b21819 | ||
|
|
61457c9498 | ||
|
|
c6102b9278 | ||
|
|
72c2b9e862 | ||
|
|
08241669bc | ||
|
|
6e36153799 | ||
|
|
4f76fff978 | ||
|
|
c82ec0c72b | ||
|
|
c57ce31e84 | ||
|
|
32b44aa5c8 | ||
|
|
7032c0d03c | ||
|
|
b9c4b27781 | ||
|
|
8c427253b3 | ||
|
|
ed28ead8ac | ||
|
|
90a7e5acae | ||
|
|
707b9a58cc | ||
|
|
a32705fd30 | ||
|
|
00e3445f8a | ||
|
|
1036d824fe | ||
|
|
587b66acc1 | ||
|
|
040acaaf30 | ||
|
|
dd3fd78e63 | ||
|
|
61ddb1aa07 | ||
|
|
00da7279cb | ||
|
|
7609156ae1 | ||
|
|
66dec24e32 | ||
|
|
433d6c33d8 | ||
|
|
b02918883f | ||
|
|
1cd7419718 | ||
|
|
daecbb90fe | ||
|
|
193e162ec6 | ||
|
|
3759e59bbd | ||
|
|
41b2102d10 | ||
|
|
1bfd3e0631 | ||
|
|
122a2fd177 | ||
|
|
1840d7b7ee | ||
|
|
6cb84ddbfb | ||
|
|
02020fbb63 | ||
|
|
26752d3a06 | ||
|
|
80f34ecd2c | ||
|
|
2f133f5e28 | ||
|
|
150c2bcef9 | ||
|
|
1252f92431 | ||
|
|
c0f9d0eeed | ||
|
|
4ec4efd3e5 | ||
|
|
fb1b5ca4ce | ||
|
|
f826506218 | ||
|
|
62331f5ac1 | ||
|
|
a7d664e3a3 | ||
|
|
62a897b75b | ||
|
|
cc7e80c4e3 | ||
|
|
9f673c859d | ||
|
|
e67ab9a93d | ||
|
|
814ba71dc1 | ||
|
|
cc9e21c260 | ||
|
|
9565b7de74 | ||
|
|
d5912fd05a | ||
|
|
a0dad83ded | ||
|
|
04df5ce492 | ||
|
|
13e601e35c | ||
|
|
a6133e85d1 | ||
|
|
267c0796dd | ||
|
|
b468b5e6e8 | ||
|
|
d89ad1106f | ||
|
|
3885011220 | ||
|
|
3394ee71f0 | ||
|
|
12d7a8ff66 | ||
|
|
e95673b052 | ||
|
|
26131b23b8 | ||
|
|
136762b45f | ||
|
|
d73a937375 | ||
|
|
ddd93529d5 | ||
|
|
e72f4f7f26 | ||
|
|
f350cce64f |
8
.autofix.markdownlint-cli2.jsonc
Normal file
8
.autofix.markdownlint-cli2.jsonc
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"config": {
|
||||
"default": false,
|
||||
"no-trailing-spaces": {
|
||||
"br_spaces": 0
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -56,7 +56,7 @@ executors:
|
||||
# 2xlarge should not be used directly, use the pipeline param instead
|
||||
enum: ["medium", "electronjs/aks-linux-medium", "xlarge", "electronjs/aks-linux-large", "2xlarge"]
|
||||
docker:
|
||||
- image: ghcr.io/electron/build:e6bebd08a51a0d78ec23e5b3fd7e7c0846412328
|
||||
- image: ghcr.io/electron/build:9a43c14f5c19be0359843299f79e736521373adc
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
macos:
|
||||
@@ -75,10 +75,6 @@ executors:
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# Electron Runners
|
||||
apple-silicon:
|
||||
resource_class: electronjs/macos-arm64
|
||||
machine: true
|
||||
|
||||
linux-arm:
|
||||
resource_class: electronjs/aks-linux-arm-test
|
||||
docker:
|
||||
@@ -1642,6 +1638,8 @@ commands:
|
||||
fi
|
||||
- store_test_results:
|
||||
path: src/junit
|
||||
- store_artifacts:
|
||||
path: src/electron/spec/artifacts
|
||||
|
||||
- *step-verify-mksnapshot
|
||||
- *step-verify-chromedriver
|
||||
@@ -2293,11 +2291,14 @@ jobs:
|
||||
<<: *env-stack-dumping
|
||||
parallelism: 2
|
||||
steps:
|
||||
- run: nvm install lts/iron && nvm alias default lts/iron
|
||||
- electron-tests:
|
||||
artifact-key: darwin-x64
|
||||
|
||||
darwin-testing-arm64-tests:
|
||||
executor: apple-silicon
|
||||
darwin-testing-arm64-tests:
|
||||
executor:
|
||||
name: macos
|
||||
size: macos.m1.medium.gen1
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
@@ -2317,11 +2318,14 @@ jobs:
|
||||
<<: *env-stack-dumping
|
||||
parallelism: 2
|
||||
steps:
|
||||
- run: nvm install lts/iron && nvm alias default lts/iron
|
||||
- electron-tests:
|
||||
artifact-key: mas-x64
|
||||
|
||||
mas-testing-arm64-tests:
|
||||
executor: apple-silicon
|
||||
executor:
|
||||
name: macos
|
||||
size: macos.m1.medium.gen1
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
|
||||
@@ -4,12 +4,8 @@
|
||||
"onCreateCommand": ".devcontainer/on-create-command.sh",
|
||||
"updateContentCommand": ".devcontainer/update-content-command.sh",
|
||||
"workspaceFolder": "/workspaces/gclient/src/electron",
|
||||
"forwardPorts": [8088, 6080, 5901],
|
||||
"forwardPorts": [6080, 5901],
|
||||
"portsAttributes": {
|
||||
"8088": {
|
||||
"label": "Goma Control Panel",
|
||||
"onAutoForward": "silent"
|
||||
},
|
||||
"6080": {
|
||||
"label": "VNC web client (noVNC)",
|
||||
"onAutoForward": "silent"
|
||||
@@ -31,7 +27,8 @@
|
||||
]
|
||||
},
|
||||
"vscode": {
|
||||
"extensions": ["joeleinbinder.mojom-language",
|
||||
"extensions": [
|
||||
"joeleinbinder.mojom-language",
|
||||
"rafaelmaiolla.diff",
|
||||
"surajbarkale.ninja",
|
||||
"ms-vscode.cpptools",
|
||||
|
||||
@@ -2,7 +2,7 @@ version: '3'
|
||||
|
||||
services:
|
||||
buildtools:
|
||||
image: ghcr.io/electron/devcontainer:3d8d44d0f15b05bef6149e448f9cc522111847e9
|
||||
image: ghcr.io/electron/devcontainer:9a43c14f5c19be0359843299f79e736521373adc
|
||||
|
||||
volumes:
|
||||
- ..:/workspaces/gclient/src/electron:cached
|
||||
|
||||
@@ -39,7 +39,6 @@ if [ ! -f $buildtools/configs/evm.testing.json ]; then
|
||||
write_config() {
|
||||
echo "
|
||||
{
|
||||
\"goma\": \"$1\",
|
||||
\"root\": \"/workspaces/gclient\",
|
||||
\"remotes\": {
|
||||
\"electron\": {
|
||||
@@ -49,7 +48,7 @@ if [ ! -f $buildtools/configs/evm.testing.json ]; then
|
||||
\"gen\": {
|
||||
\"args\": [
|
||||
\"import(\\\"//electron/build/args/testing.gn\\\")\",
|
||||
\"import(\\\"/home/builduser/.electron_build_tools/third_party/goma.gn\\\")\"
|
||||
\"use_remoteexec = true\"
|
||||
],
|
||||
\"out\": \"Testing\"
|
||||
},
|
||||
@@ -57,26 +56,18 @@ if [ ! -f $buildtools/configs/evm.testing.json ]; then
|
||||
\"CHROMIUM_BUILDTOOLS_PATH\": \"/workspaces/gclient/src/buildtools\",
|
||||
\"GIT_CACHE_PATH\": \"/workspaces/gclient/.git-cache\"
|
||||
},
|
||||
\"\$schema\": \"file:///home/builduser/.electron_build_tools/evm-config.schema.json\"
|
||||
\"\$schema\": \"file:///home/builduser/.electron_build_tools/evm-config.schema.json\",
|
||||
\"configValidationLevel\": \"strict\",
|
||||
\"reclient\": \"$1\",
|
||||
\"goma\": \"none\",
|
||||
\"preserveXcode\": 5
|
||||
}
|
||||
" >$buildtools/configs/evm.testing.json
|
||||
}
|
||||
|
||||
# Start out as cache only
|
||||
write_config cache-only
|
||||
write_config remote_exec
|
||||
|
||||
e use testing
|
||||
|
||||
# Attempt to auth to the goma service via codespaces tokens
|
||||
# if it works we can use the goma cluster
|
||||
export NOTGOMA_CODESPACES_TOKEN=$GITHUB_TOKEN
|
||||
if e d goma_auth login; then
|
||||
echo "$GITHUB_USER has GOMA access - switching to cluster mode"
|
||||
write_config cluster
|
||||
fi
|
||||
e use testing
|
||||
else
|
||||
echo "build-tools testing config already exists"
|
||||
|
||||
# Re-auth with the goma cluster regardless.
|
||||
NOTGOMA_CODESPACES_TOKEN=$GITHUB_TOKEN e d goma_auth login || true
|
||||
fi
|
||||
|
||||
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
@@ -11,6 +11,9 @@ DEPS @electron/wg-upgrades
|
||||
/docs/breaking-changes.md @electron/wg-releases
|
||||
/npm/ @electron/wg-releases
|
||||
/script/release @electron/wg-releases
|
||||
appveyor.yml @electron/wg-releases
|
||||
appveyor-bake.yml @electron/wg-releases
|
||||
appveyor-woa.yml @electron/wg-releases
|
||||
|
||||
# Security WG
|
||||
/lib/browser/devtools.ts @electron/wg-security
|
||||
|
||||
9
.github/dependabot.yml
vendored
Normal file
9
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
# Keep GitHub Actions up to date with GitHub's Dependabot...
|
||||
# https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
|
||||
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: github-actions
|
||||
directory: /
|
||||
schedule:
|
||||
interval: weekly
|
||||
26
.github/workflows/config/evm.mas.json
vendored
Normal file
26
.github/workflows/config/evm.mas.json
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"root": "/Users/runner/work/electron/electron/",
|
||||
"remotes": {
|
||||
"electron": {
|
||||
"origin": "https://github.com/electron/electron.git"
|
||||
}
|
||||
},
|
||||
"gen": {
|
||||
"args": [
|
||||
"import(\"//electron/build/args/testing.gn\")",
|
||||
"use_remoteexec = true",
|
||||
"target_cpu = \"arm64\"",
|
||||
"is_mas_build = true"
|
||||
],
|
||||
"out": "Default"
|
||||
},
|
||||
"env": {
|
||||
"CHROMIUM_BUILDTOOLS_PATH": "/Users/runner/work/electron/electron/src/buildtools",
|
||||
"GIT_CACHE_PATH": "/Users/runner/work/electron/electron/.git-cache"
|
||||
},
|
||||
"$schema": "file:///home/builduser/.electron_build_tools/evm-config.schema.json",
|
||||
"configValidationLevel": "strict",
|
||||
"reclient": "remote_exec",
|
||||
"goma": "none",
|
||||
"preserveXcode": 5
|
||||
}
|
||||
14
.github/workflows/config/gclient.diff
vendored
Normal file
14
.github/workflows/config/gclient.diff
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
diff --git a/gclient.py b/gclient.py
|
||||
index 59e2b4c5197928bdba1ef69bdbe637d7dfe471c1..b4bae5e48c83c84bd867187afaf40eed16e69851 100755
|
||||
--- a/gclient.py
|
||||
+++ b/gclient.py
|
||||
@@ -739,7 +739,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
||||
|
||||
if dep_type == 'cipd':
|
||||
cipd_root = self.GetCipdRoot()
|
||||
- for package in dep_value.get('packages', []):
|
||||
+ packages = dep_value.get('packages', [])
|
||||
+ for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
|
||||
deps_to_add.append(
|
||||
CipdDependency(parent=self,
|
||||
name=name,
|
||||
20
.github/workflows/issue-labeled.yml
vendored
20
.github/workflows/issue-labeled.yml
vendored
@@ -8,6 +8,24 @@ permissions: # added using https://github.com/step-security/secure-workflows
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
issue-labeled-with-status:
|
||||
name: status/{confirmed,reviewed} label added
|
||||
if: github.event.label.name == 'status/confirmed' || github.event.label.name == 'status/reviewed'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
id: generate-token
|
||||
with:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- name: Set status
|
||||
uses: dsanders11/project-actions/edit-item@82e99438bd44a14ad18d92d036dbc25cbfb9a8c4 # v1.2.0
|
||||
with:
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
project-number: 90
|
||||
field: Status
|
||||
field-value: ✅ Triaged
|
||||
issue-labeled-blocked:
|
||||
name: blocked/* label added
|
||||
if: startsWith(github.event.label.name, 'blocked/')
|
||||
@@ -52,7 +70,7 @@ jobs:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
- name: Create comment
|
||||
if: ${{ steps.check-for-comment.outputs.SHOULD_COMMENT }}
|
||||
uses: actions-cool/issues-helper@275328970dbc3bfc3bc43f5fe741bf3638300c0a # v3.3.3
|
||||
uses: actions-cool/issues-helper@a610082f8ac0cf03e357eb8dd0d5e2ba075e017e # v3.6.0
|
||||
with:
|
||||
actions: 'create-comment'
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
64
.github/workflows/issue-opened.yml
vendored
64
.github/workflows/issue-opened.yml
vendored
@@ -25,3 +25,67 @@ jobs:
|
||||
field-value: ${{ github.event.issue.user.login }}
|
||||
project-number: 90
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
set-labels:
|
||||
if: ${{ contains(github.event.issue.labels.*.name, 'bug :beetle:') }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
id: generate-token
|
||||
with:
|
||||
creds: ${{ secrets.ISSUE_TRIAGE_GH_APP_CREDS }}
|
||||
org: electron
|
||||
- run: npm install mdast-util-from-markdown@2.0.0 unist-util-select@5.1.0 semver@7.6.0
|
||||
- name: Add labels
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
env:
|
||||
ISSUE_BODY: ${{ github.event.issue.body }}
|
||||
with:
|
||||
github-token: ${{ steps.generate-token.outputs.token }}
|
||||
script: |
|
||||
const { fromMarkdown } = await import('${{ github.workspace }}/node_modules/mdast-util-from-markdown/index.js');
|
||||
const { select } = await import('${{ github.workspace }}/node_modules/unist-util-select/index.js');
|
||||
const semver = await import('${{ github.workspace }}/node_modules/semver/index.js');
|
||||
|
||||
const [ owner, repo ] = '${{ github.repository }}'.split('/');
|
||||
const issue_number = ${{ github.event.issue.number }};
|
||||
|
||||
const tree = fromMarkdown(process.env.ISSUE_BODY);
|
||||
|
||||
const labels = [];
|
||||
|
||||
const electronVersion = select('heading:has(> text[value="Electron Version"]) + paragraph > text', tree)?.value.trim();
|
||||
if (electronVersion !== undefined) {
|
||||
const major = semver.parse(electronVersion)?.major;
|
||||
if (major) {
|
||||
const versionLabel = `${major}-x-y`;
|
||||
let labelExists = false;
|
||||
|
||||
try {
|
||||
await github.rest.issues.getLabel({
|
||||
owner,
|
||||
repo,
|
||||
name: versionLabel,
|
||||
});
|
||||
labelExists = true;
|
||||
} catch {}
|
||||
|
||||
if (labelExists) {
|
||||
labels.push(versionLabel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const gistUrl = select('heading:has(> text[value="Testcase Gist URL"]) + paragraph > text', tree)?.value.trim();
|
||||
if (gistUrl !== undefined && gistUrl.startsWith('https://gist.github.com/')) {
|
||||
labels.push('has-repro-gist');
|
||||
}
|
||||
|
||||
if (labels.length) {
|
||||
await github.rest.issues.addLabels({
|
||||
owner,
|
||||
repo,
|
||||
issue_number,
|
||||
labels,
|
||||
});
|
||||
}
|
||||
|
||||
590
.github/workflows/macos-build.yml
vendored
Normal file
590
.github/workflows/macos-build.yml
vendored
Normal file
@@ -0,0 +1,590 @@
|
||||
name: Build MacOS
|
||||
|
||||
# TODO: change to 'pull_request' and 'push'
|
||||
# when we are ready to enable this for PRs.
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac --custom-var=host_cpu=arm64'
|
||||
IS_RELEASE: false
|
||||
# GENERATE_SYMBOLS: true only on release builds
|
||||
GENERATE_SYMBOLS: false
|
||||
AZURE_STORAGE_ACCOUNT: ${{ secrets.AZURE_STORAGE_ACCOUNT }}
|
||||
AZURE_STORAGE_KEY: ${{ secrets.AZURE_STORAGE_KEY }}
|
||||
AZURE_STORAGE_CONTAINER_NAME: ${{ secrets.AZURE_STORAGE_CONTAINER_NAME }}
|
||||
ELECTRON_RBE_JWT: ${{ secrets.ELECTRON_RBE_JWT }}
|
||||
# TODO: this should be set to the correct GN_CONFIG for the build type.
|
||||
GN_CONFIG: //electron/build/args/testing.gn
|
||||
# Disable pre-compiled headers to reduce out size - only useful for rebuilds
|
||||
GN_BUILDFLAG_ARGS: 'enable_precompiled_headers = false'
|
||||
|
||||
jobs:
|
||||
checkout:
|
||||
runs-on: LargeLinuxRunner
|
||||
steps:
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: src/electron
|
||||
- name: Install Azure CLI
|
||||
run: ./script/azure_cli_deb_install.sh
|
||||
- name: Set GIT_CACHE_PATH to make gclient to use the cache
|
||||
run: |
|
||||
echo "GIT_CACHE_PATH=$(pwd)/git-cache" >> $GITHUB_ENV
|
||||
- name: Setup Node.js/npm
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20.11.x
|
||||
cache: yarn
|
||||
cache-dependency-path: src/electron/yarn.lock
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn install
|
||||
- name: Get Depot Tools
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
# remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems
|
||||
sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
else
|
||||
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
# Remove swift-format dep from cipd on macOS until we send a patch upstream.
|
||||
cd depot_tools
|
||||
git apply --3way ../src/electron/.github/workflows/config/gclient.diff
|
||||
fi
|
||||
# Ensure depot_tools does not update.
|
||||
test -d depot_tools && cd depot_tools
|
||||
touch .disable_auto_update
|
||||
- name: Add Depot Tools to PATH
|
||||
run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js && cat src/electron/.depshash-target
|
||||
echo "DEPSHASH=v1-src-cache-$(shasum src/electron/.depshash | cut -f1 -d' ')" >> $GITHUB_ENV
|
||||
- name: Check If Cache Exists
|
||||
id: check-cache
|
||||
run: |
|
||||
exists_json=$(az storage blob exists \
|
||||
--account-name $AZURE_STORAGE_ACCOUNT \
|
||||
--account-key $AZURE_STORAGE_KEY \
|
||||
--container-name $AZURE_STORAGE_CONTAINER_NAME \
|
||||
--name $DEPSHASH)
|
||||
|
||||
cache_exists=$(echo $exists_json | jq -r '.exists')
|
||||
echo "cache_exists=$cache_exists" >> $GITHUB_OUTPUT
|
||||
|
||||
if (test "$cache_exists" = "true"); then
|
||||
echo "Cache Exists for $DEPSHASH"
|
||||
else
|
||||
echo "Cache Does Not Exist for $DEPSHASH"
|
||||
fi
|
||||
- name: Gclient Sync
|
||||
# If there is no existing src cache, we need to do a full gclient sync.
|
||||
# TODO(codebytere): Add stale patch handling for non-release builds.
|
||||
if: steps.check-cache.outputs.cache_exists == 'false'
|
||||
run: |
|
||||
gclient config \
|
||||
--name "src/electron" \
|
||||
--unmanaged \
|
||||
${GCLIENT_EXTRA_ARGS} \
|
||||
"$GITHUB_SERVER_URL/$GITHUB_REPOSITORY"
|
||||
|
||||
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags -vvvvv
|
||||
if [ "$IS_RELEASE" != "true" ]; then
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python3 src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
cd src/electron
|
||||
git update-index --refresh || true
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
# There are changes to the patches. Make a git commit with the updated patches
|
||||
git add patches
|
||||
GIT_COMMITTER_NAME="PatchUp" GIT_COMMITTER_EMAIL="73610968+patchup[bot]@users.noreply.github.com" git commit -m "chore: update patches" --author="PatchUp <73610968+patchup[bot]@users.noreply.github.com>"
|
||||
# Export it
|
||||
mkdir -p ../../patches
|
||||
git format-patch -1 --stdout --keep-subject --no-stat --full-index > ../../patches/update-patches.patch
|
||||
if (node ./script/push-patch.js 2> /dev/null > /dev/null); then
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "Changes to the patches when applying, we have auto-pushed the diff to the current branch"
|
||||
echo "A new CI job will kick off shortly"
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
else
|
||||
echo
|
||||
echo "======================================================================"
|
||||
echo "There were changes to the patches when applying."
|
||||
echo "Check the CI artifacts for a patch you can apply to fix it."
|
||||
echo "======================================================================"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# delete all .git directories under src/ except for
|
||||
# third_party/angle/ and third_party/dawn/ because of build time generation of files
|
||||
# gen/angle/commit.h depends on third_party/angle/.git/HEAD
|
||||
# https://chromium-review.googlesource.com/c/angle/angle/+/2074924
|
||||
# and dawn/common/Version_autogen.h depends on third_party/dawn/.git/HEAD
|
||||
# https://dawn-review.googlesource.com/c/dawn/+/83901
|
||||
# TODO: maybe better to always leave out */.git/HEAD file for all targets ?
|
||||
- name: Delete .git directories under src to free space
|
||||
if: steps.check-cache.outputs.cache_exists == 'false'
|
||||
run: |
|
||||
cd src
|
||||
( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" -not -path "./electron/*" ) | xargs rm -rf
|
||||
- name: Minimize Cache Size for Upload
|
||||
if: steps.check-cache.outputs.cache_exists == 'false'
|
||||
run: |
|
||||
rm -rf src/android_webview
|
||||
rm -rf src/ios/chrome
|
||||
rm -rf src/third_party/blink/web_tests
|
||||
rm -rf src/third_party/blink/perf_tests
|
||||
rm -rf src/chrome/test/data/xr/webvr_info
|
||||
rm -rf src/third_party/angle/third_party/VK-GL-CTS/src
|
||||
rm -rf src/third_party/swift-toolchain
|
||||
rm -rf src/third_party/swiftshader/tests/regres/testlists
|
||||
rm -rf src/electron
|
||||
- name: Compress Src Directory
|
||||
if: steps.check-cache.outputs.cache_exists == 'false'
|
||||
run: |
|
||||
echo "Uncompressed src size: $(du -sh src | cut -f1 -d' ')"
|
||||
tar -cvf $DEPSHASH.tar src
|
||||
echo "Compressed src to $(du -sh $DEPSHASH.tar | cut -f1 -d' ')"
|
||||
- name: Upload Compressed Src Cache to Azure
|
||||
if: steps.check-cache.outputs.cache_exists == 'false'
|
||||
run: |
|
||||
az storage blob upload \
|
||||
--account-name $AZURE_STORAGE_ACCOUNT \
|
||||
--account-key $AZURE_STORAGE_KEY \
|
||||
--container-name $AZURE_STORAGE_CONTAINER_NAME \
|
||||
--file $DEPSHASH.tar \
|
||||
--name $DEPSHASH \
|
||||
--debug
|
||||
build:
|
||||
runs-on: macos-13-xlarge
|
||||
needs: checkout
|
||||
steps:
|
||||
- name: Load Build Tools
|
||||
run: |
|
||||
export BUILD_TOOLS_SHA=2bb63e2e7877491b52f972532b52adc979a6ec2f
|
||||
npm i -g @electron/build-tools
|
||||
e init --root=$(pwd) --out=Default testing
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: src/electron
|
||||
- name: Install Azure CLI
|
||||
run: |
|
||||
brew update && brew install azure-cli
|
||||
- name: Setup Node.js/npm
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20.11.x
|
||||
cache: yarn
|
||||
cache-dependency-path: src/electron/yarn.lock
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn install
|
||||
- name: Get Depot Tools
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
# remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems
|
||||
sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
else
|
||||
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
# Remove swift-format dep from cipd on macOS until we send a patch upstream.
|
||||
cd depot_tools
|
||||
git apply --3way ../src/electron/.github/workflows/config/gclient.diff
|
||||
fi
|
||||
# Ensure depot_tools does not update.
|
||||
test -d depot_tools && cd depot_tools
|
||||
touch .disable_auto_update
|
||||
- name: Add Depot Tools to PATH
|
||||
run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH
|
||||
- name: Generate DEPS Hash
|
||||
run: |
|
||||
node src/electron/script/generate-deps-hash.js && cat src/electron/.depshash-target
|
||||
echo "DEPSHASH=v1-src-cache-$(shasum src/electron/.depshash | cut -f1 -d' ')" >> $GITHUB_ENV
|
||||
- name: Download Src Cache
|
||||
# The cache will always exist here as a result of the checkout job
|
||||
# Either it was uploaded to Azure in the checkout job for this commit
|
||||
# or it was uploaded in the checkout job for a previous commit.
|
||||
run: |
|
||||
az storage blob download \
|
||||
--account-name $AZURE_STORAGE_ACCOUNT \
|
||||
--account-key $AZURE_STORAGE_KEY \
|
||||
--container-name $AZURE_STORAGE_CONTAINER_NAME \
|
||||
--name $DEPSHASH \
|
||||
--file $DEPSHASH.tar \
|
||||
- name: Unzip and Ensure Src Cache
|
||||
run: |
|
||||
echo "Downloaded cache is $(du -sh $DEPSHASH.tar | cut -f1)"
|
||||
mkdir temp-cache
|
||||
tar -xvf $DEPSHASH.tar -C temp-cache
|
||||
echo "Unzipped cache is $(du -sh temp-cache/src | cut -f1)"
|
||||
|
||||
if [ -d "temp-cache/src" ]; then
|
||||
echo "Relocating Cache"
|
||||
rm -rf src
|
||||
mv temp-cache/src src
|
||||
|
||||
echo "Deleting zip file"
|
||||
rm -rf $DEPSHASH.tar
|
||||
fi
|
||||
|
||||
if [ ! -d "src/third_party/blink" ]; then
|
||||
echo "Cache was not correctly restored - exiting"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Wiping Electron Directory"
|
||||
rm -rf src/electron
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: src/electron
|
||||
- name: Run Electron Only Hooks
|
||||
run: |
|
||||
echo "Running Electron Only Hooks"
|
||||
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 && cat src/electron/.depshash-target
|
||||
echo "DEPSHASH=$(shasum src/electron/.depshash | cut -f1 -d' ')" >> $GITHUB_ENV
|
||||
- name: Add CHROMIUM_BUILDTOOLS_PATH to env
|
||||
run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV
|
||||
- name: Fix Sync
|
||||
# This step is required to correct for differences between "gclient sync"
|
||||
# on Linux and the expected state on macOS. This requires:
|
||||
# 1. Fixing Clang Install (wrong binary)
|
||||
# 2. Fixing esbuild (wrong binary)
|
||||
# 3. Fixing rustc (wrong binary)
|
||||
# 4. Fixing gn (wrong binary)
|
||||
# 5. Fix reclient (wrong binary)
|
||||
# 6. Fixing dsymutil (wrong binary)
|
||||
# 7. Ensuring we are using the correct ninja and adding it to PATH
|
||||
# 8. Fixing angle (wrong remote)
|
||||
run : |
|
||||
SEDOPTION="-i ''"
|
||||
rm -rf src/third_party/llvm-build
|
||||
python3 src/tools/clang/scripts/update.py
|
||||
|
||||
echo 'infra/3pp/tools/esbuild/${platform}' `gclient getdep --deps-file=src/third_party/devtools-frontend/src/DEPS -r 'third_party/esbuild:infra/3pp/tools/esbuild/${platform}'` > esbuild_ensure_file
|
||||
# Remove extra output from calling gclient getdep which always calls update_depot_tools
|
||||
sed -i '' "s/Updating depot_tools... //g" esbuild_ensure_file
|
||||
cipd ensure --root src/third_party/devtools-frontend/src/third_party/esbuild -ensure-file esbuild_ensure_file
|
||||
|
||||
rm -rf src/third_party/rust-toolchain
|
||||
python3 src/tools/rust/update_rust.py
|
||||
|
||||
# Prevent calling gclient getdep which always calls update_depot_tools
|
||||
echo 'gn/gn/mac-${arch}' `gclient getdep --deps-file=src/DEPS -r 'src/buildtools/mac:gn/gn/mac-${arch}'` > gn_ensure_file
|
||||
sed -i '' "s/Updating depot_tools... //g" gn_ensure_file
|
||||
cipd ensure --root src/buildtools/mac -ensure-file gn_ensure_file
|
||||
|
||||
# Prevent calling gclient getdep which always calls update_depot_tools
|
||||
echo 'infra/rbe/client/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/buildtools/reclient:infra/rbe/client/${platform}'` > gn_ensure_file
|
||||
sed -i '' "s/Updating depot_tools... //g" gn_ensure_file
|
||||
cipd ensure --root src/buildtools/reclient -ensure-file gn_ensure_file
|
||||
python3 src/buildtools/reclient_cfgs/configure_reclient_cfgs.py --rbe_instance "projects/rbe-chrome-untrusted/instances/default_instance" --reproxy_cfg_template reproxy.cfg.template --rewrapper_cfg_project "" --skip_remoteexec_cfg_fetch
|
||||
|
||||
DSYM_SHA_FILE=src/tools/clang/dsymutil/bin/dsymutil.arm64.sha1
|
||||
python3 src/third_party/depot_tools/download_from_google_storage.py --no_resume --no_auth --bucket chromium-browser-clang -s $DSYM_SHA_FILE -o src/tools/clang/dsymutil/bin/dsymutil
|
||||
|
||||
echo 'infra/3pp/tools/ninja/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/third_party/ninja:infra/3pp/tools/ninja/${platform}'` > ninja_ensure_file
|
||||
sed $SEDOPTION "s/Updating depot_tools... //g" ninja_ensure_file
|
||||
cipd ensure --root src/third_party/ninja -ensure-file ninja_ensure_file
|
||||
|
||||
echo "$(pwd)/src/third_party/ninja" >> $GITHUB_PATH
|
||||
|
||||
cd src/third_party/angle
|
||||
rm -f .git/objects/info/alternates
|
||||
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
|
||||
cp .git/config .git/config.backup
|
||||
git remote remove origin
|
||||
mv .git/config.backup .git/config
|
||||
git fetch
|
||||
- name: Install build-tools & Setup RBE
|
||||
run: |
|
||||
echo "NUMBER_OF_NINJA_PROCESSES=200" >> $GITHUB_ENV
|
||||
cd ~/.electron_build_tools
|
||||
npx yarn --ignore-engines
|
||||
# Pull down credential helper and print status
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
HELPER=$(node -p "require('./src/utils/reclient.js').helperPath({})")
|
||||
$HELPER login
|
||||
echo 'RBE_service='`node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"` >> $GITHUB_ENV
|
||||
echo 'RBE_experimental_credentials_helper='`node -e "console.log(require('./src/utils/reclient.js').helperPath({}))"` >> $GITHUB_ENV
|
||||
echo 'RBE_experimental_credentials_helper_args=print' >> $GITHUB_ENV
|
||||
- name: Build Electron (darwin)
|
||||
run: |
|
||||
cd src/electron
|
||||
# TODO(codebytere): remove this once we figure out why .git/packed-refs is initially missing
|
||||
git pack-refs
|
||||
cd ..
|
||||
|
||||
ulimit -n 10000
|
||||
sudo launchctl limit maxfiles 65536 200000
|
||||
NINJA_SUMMARIZE_BUILD=1 e build -j $NUMBER_OF_NINJA_PROCESSES
|
||||
cp out/Default/.ninja_log out/electron_ninja_log
|
||||
node electron/script/check-symlinks.js
|
||||
- name: Build Electron dist.zip (darwin)
|
||||
run: |
|
||||
cd src
|
||||
e build electron:electron_dist_zip $ADDITIONAL_TARGETS -j $NUMBER_OF_NINJA_PROCESSES
|
||||
if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
|
||||
target_os=mac
|
||||
target_cpu=arm64
|
||||
electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.$target_cpu.manifest
|
||||
fi
|
||||
- name: Build Mksnapshot (darwin)
|
||||
run: |
|
||||
cd src
|
||||
e build electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
SEDOPTION="-i ''"
|
||||
sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/The gn arg use_goma=true .*/d' out/Default/mksnapshot_args
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
e build electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
|
||||
fi
|
||||
- name: Build Chromedriver (darwin)
|
||||
run: |
|
||||
cd src
|
||||
e build electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
|
||||
e build electron:electron_chromedriver_zip
|
||||
- name: Build Node Headers (darwin)
|
||||
run: |
|
||||
cd src
|
||||
e build electron:node_headers
|
||||
- name: Generate & Zip Symbols (darwin)
|
||||
run: |
|
||||
if [ "$GENERATE_SYMBOLS" == "true" ]; then
|
||||
e build electron:electron_symbols
|
||||
fi
|
||||
cd src
|
||||
export BUILD_PATH="$(pwd)/out/Default"
|
||||
e build electron:licenses
|
||||
e build electron:electron_version_file
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
# TODO(vertedinde): handle creating ffmpeg and hunspell for release builds
|
||||
# The current generated_artifacts_<< artifact.key >> name was taken from CircleCI
|
||||
# tp ensure we don't break anything, but we may be able to improve that.
|
||||
- name: Move all Generated Artifacts to Upload Folder
|
||||
run: ./src/electron/script/actions/move-artifacts.sh
|
||||
- name: Upload Generated Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: generated_artifacts_darwin
|
||||
path: ./generated_artifacts_darwin
|
||||
- name: Persist Build Artifacts
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
src/out/Default/gen/node_headers
|
||||
src/out/Default/overlapped-checker
|
||||
src/electron
|
||||
src/third_party/electron_node
|
||||
src/third_party/nan
|
||||
src/cross-arch-snapshots
|
||||
src/third_party/llvm-build
|
||||
src/build/linux
|
||||
src/buildtools/mac
|
||||
src/buildtools/third_party/libc++
|
||||
src/buildtools/third_party/libc++abi
|
||||
src/third_party/libc++
|
||||
src/third_party/libc++abi
|
||||
src/out/Default/obj/buildtools/third_party
|
||||
src/v8/tools/builtins-pgo
|
||||
key: ${{ runner.os }}-build-artifacts-darwin-${{ github.sha }}
|
||||
- name: Create MAS Config
|
||||
run: |
|
||||
mv src/electron/.github/workflows/config/evm.mas.json $HOME/.electron_build_tools/configs/evm.mas.json
|
||||
echo "MAS_BUILD=true" >> $GITHUB_ENV
|
||||
e use mas
|
||||
- name: Build Electron (mas)
|
||||
run: |
|
||||
rm -rf "src/out/Default/Electron Framework.framework"
|
||||
rm -rf src/out/Default/Electron*.app
|
||||
|
||||
cd src/electron
|
||||
# TODO(codebytere): remove this once we figure out why .git/packed-refs is initially missing
|
||||
git pack-refs
|
||||
cd ..
|
||||
|
||||
ulimit -n 10000
|
||||
sudo launchctl limit maxfiles 65536 200000
|
||||
NINJA_SUMMARIZE_BUILD=1 e build -j $NUMBER_OF_NINJA_PROCESSES
|
||||
cp out/Default/.ninja_log out/electron_ninja_log
|
||||
node electron/script/check-symlinks.js
|
||||
- name: Build Electron dist.zip (mas)
|
||||
run: |
|
||||
cd src
|
||||
e build electron:electron_dist_zip $ADDITIONAL_TARGETS -j $NUMBER_OF_NINJA_PROCESSES
|
||||
if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
|
||||
target_os=mac_mas
|
||||
target_cpu=arm64
|
||||
electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.$target_os.$target_cpu.manifest
|
||||
fi
|
||||
- name: Build Mksnapshot (mas)
|
||||
run: |
|
||||
cd src
|
||||
e build electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
SEDOPTION="-i ''"
|
||||
sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/The gn arg use_goma=true .*/d' out/Default/mksnapshot_args
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
e build electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
|
||||
fi
|
||||
- name: Build Chromedriver (mas)
|
||||
run: |
|
||||
cd src
|
||||
e build electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
|
||||
e build electron:electron_chromedriver_zip
|
||||
- name: Build Node Headers
|
||||
run: |
|
||||
cd src
|
||||
e build electron:node_headers
|
||||
- name: Generate & Zip Symbols (mas)
|
||||
run: |
|
||||
if [ "$GENERATE_SYMBOLS" == "true" ]; then
|
||||
e build electron:electron_symbols
|
||||
fi
|
||||
cd src
|
||||
export BUILD_PATH="$(pwd)/out/Default"
|
||||
e build electron:licenses
|
||||
e build electron:electron_version_file
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
- name: Move all Generated Artifacts to Upload Folder (mas)
|
||||
run: ./src/electron/script/actions/move-artifacts.sh
|
||||
- name: Upload Generated Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: generated_artifacts_mas
|
||||
path: ./generated_artifacts_mas
|
||||
- name: Persist Build Artifacts
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: |
|
||||
src/out/Default/gen/node_headers
|
||||
src/out/Default/overlapped-checker
|
||||
src/electron
|
||||
src/third_party/electron_node
|
||||
src/third_party/nan
|
||||
src/cross-arch-snapshots
|
||||
src/third_party/llvm-build
|
||||
src/build/linux
|
||||
src/buildtools/mac
|
||||
src/buildtools/third_party/libc++
|
||||
src/buildtools/third_party/libc++abi
|
||||
src/third_party/libc++
|
||||
src/third_party/libc++abi
|
||||
src/out/Default/obj/buildtools/third_party
|
||||
src/v8/tools/builtins-pgo
|
||||
key: ${{ runner.os }}-build-artifacts-mas-${{ github.sha }}
|
||||
test:
|
||||
runs-on: macos-13-xlarge
|
||||
needs: build
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
build-type: [darwin, mas]
|
||||
env:
|
||||
BUILD_TYPE: ${{ matrix.build-type }}
|
||||
steps:
|
||||
- name: Load Build Tools
|
||||
run: |
|
||||
yarn add git://github.com/electron/build-tools.git#2bb63e2e7877491b52f972532b52adc979a6ec2f
|
||||
e init --root=$(pwd) --out=Default testing
|
||||
- name: Checkout Electron
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: src/electron
|
||||
- name: Setup Node.js/npm
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 20.11.x
|
||||
cache: yarn
|
||||
cache-dependency-path: src/electron/yarn.lock
|
||||
- name: Install Dependencies
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn install
|
||||
- name: Get Depot Tools
|
||||
timeout-minutes: 5
|
||||
run: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
# remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems
|
||||
sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
else
|
||||
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
# Remove swift-format dep from cipd on macOS until we send a patch upstream.
|
||||
cd depot_tools
|
||||
git apply --3way ../src/electron/.github/workflows/config/gclient.diff
|
||||
fi
|
||||
# Ensure depot_tools does not update.
|
||||
test -d depot_tools && cd depot_tools
|
||||
touch .disable_auto_update
|
||||
- name: Add Depot Tools to PATH
|
||||
run: echo "$(pwd)/depot_tools" >> $GITHUB_PATH
|
||||
- name: Download Generated Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: generated_artifacts_${{ matrix.build-type }}
|
||||
path: ./generated_artifacts_${{ matrix.build-type }}
|
||||
- name: Restore Persisted Build Artifacts
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: |
|
||||
src/out/Default/gen/node_headers
|
||||
src/out/Default/overlapped-checker
|
||||
src/electron
|
||||
src/third_party/electron_node
|
||||
src/third_party/nan
|
||||
src/cross-arch-snapshots
|
||||
src/third_party/llvm-build
|
||||
src/build/linux
|
||||
src/buildtools/mac
|
||||
src/buildtools/third_party/libc++
|
||||
src/buildtools/third_party/libc++abi
|
||||
src/third_party/libc++
|
||||
src/third_party/libc++abi
|
||||
src/out/Default/obj/buildtools/third_party
|
||||
src/v8/tools/builtins-pgo
|
||||
key: ${{ runner.os }}-build-artifacts-${{ matrix.build-type }}-${{ github.sha }}
|
||||
- name: Restore Generated Artifacts
|
||||
run: ./src/electron/script/actions/restore-artifacts.sh
|
||||
- name: Unzip Dist, Mksnapshot & Chromedriver
|
||||
run: |
|
||||
cd src/out/Default
|
||||
unzip -:o dist.zip
|
||||
unzip -:o chromedriver.zip
|
||||
unzip -:o mksnapshot.zip
|
||||
- name: Run Electron Tests
|
||||
env:
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
|
||||
ELECTRON_DISABLE_SECURITY_WARNINGS: 1
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
run: |
|
||||
cd src/electron
|
||||
node script/yarn test --runners=main --trace-uncaught --enable-logging
|
||||
2
.github/workflows/pull-request-labeled.yml
vendored
2
.github/workflows/pull-request-labeled.yml
vendored
@@ -13,7 +13,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@6c661ce58804a1a20f6dc5fbee7f0381b469e001 # v1.25.0
|
||||
uses: slackapi/slack-github-action@70cd7be8e40a46e8b0eced40b0de447bdb42f68e # v1.26.0
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
|
||||
4
.github/workflows/scorecards.yml
vendored
4
.github/workflows/scorecards.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
||||
|
||||
# This is a pre-submit / pre-release.
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
|
||||
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
@@ -50,6 +50,6 @@ jobs:
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard.
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0
|
||||
uses: github/codeql-action/upload-sarif@b7cec7526559c32f1616476ff32d17ba4c59b2d6 # v3.25.5
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
|
||||
2
.github/workflows/semantic.yml
vendored
2
.github/workflows/semantic.yml
vendored
@@ -19,7 +19,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: semantic-pull-request
|
||||
uses: amannn/action-semantic-pull-request@e9fabac35e210fea40ca5b14c0da95a099eff26f # v5.4.0
|
||||
uses: amannn/action-semantic-pull-request@cfb60706e18bc85e8aec535e3c577abe8f70378e # v5.5.2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
|
||||
43
.github/workflows/update_appveyor_image.yml
vendored
43
.github/workflows/update_appveyor_image.yml
vendored
@@ -6,22 +6,23 @@ on:
|
||||
schedule:
|
||||
- cron: '0 8 * * 1-5' # runs 8:00 every business day (see https://crontab.guru)
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
bake-appveyor-image:
|
||||
name: Bake AppVeyor Image
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write # to create a new PR with updated Appveyor images
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Generate GitHub App token
|
||||
uses: electron/github-app-auth-action@384fd19694fe7b6dcc9a684746c6976ad78228ae # v1.1.1
|
||||
id: generate-token
|
||||
with:
|
||||
creds: ${{ secrets.APPVEYOR_UPDATER_GH_APP_CREDS }}
|
||||
- name: Checkout
|
||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Yarn install
|
||||
run: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
@@ -38,7 +39,7 @@ jobs:
|
||||
fi
|
||||
- name: (Optionally) Update Appveyor Image
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
uses: mikefarah/yq@bb66c9c872a7a4cf3d6846c2ff6d182c66ec3f77 # v4.40.7
|
||||
uses: mikefarah/yq@557dcb87b8efe786f89a12c09e9046b4753ab72e # v4.44.1
|
||||
with:
|
||||
cmd: |
|
||||
yq '.image = "${{ env.APPVEYOR_IMAGE_VERSION }}"' "appveyor.yml" > "appveyor2.yml"
|
||||
@@ -49,26 +50,24 @@ jobs:
|
||||
diff -w -B appveyor.yml appveyor2.yml > appveyor.diff || true
|
||||
patch -f appveyor.yml < appveyor.diff
|
||||
rm appveyor2.yml appveyor.diff
|
||||
git add appveyor.yml
|
||||
- name: (Optionally) Generate Commit Diff for WOA
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
run: |
|
||||
diff -w -B appveyor-woa.yml appveyor-woa2.yml > appveyor-woa.diff || true
|
||||
patch -f appveyor-woa.yml < appveyor-woa.diff
|
||||
rm appveyor-woa2.yml appveyor-woa.diff
|
||||
- name: (Optionally) Commit and Pull Request
|
||||
git add appveyor-woa.yml
|
||||
- name: (Optionally) Commit to Branch
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 # v6.0.0
|
||||
uses: dsanders11/github-app-commit-action@48d2ff8c1a855eb15d16afa97ae12616456d7cbc # v1.4.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'build: update appveyor image to latest version'
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
signoff: false
|
||||
branch: bump-appveyor-image
|
||||
delete-branch: true
|
||||
reviewers: electron/wg-releases
|
||||
title: 'build: update appveyor image to latest version'
|
||||
labels: semver/none,no-backport
|
||||
body: |
|
||||
This PR updates appveyor.yml to the latest baked image, ${{ env.APPVEYOR_IMAGE_VERSION }}.
|
||||
Notes: none
|
||||
message: 'build: update appveyor image to latest version'
|
||||
ref: bump-appveyor-image
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
- name: (Optionally) Create Pull Request
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
run: |
|
||||
printf "This PR updates appveyor.yml to the latest baked image, ${{ env.APPVEYOR_IMAGE_VERSION }}.\n\nNotes: none" | gh pr create --head bump-appveyor-image --label no-backport --label semver/none --title 'build: update appveyor image to latest version' --body-file=-
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
13
.lint-roller.json
Normal file
13
.lint-roller.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"markdown-ts-check": {
|
||||
"defaultImports": [
|
||||
"import * as childProcess from 'node:child_process'",
|
||||
"import * as fs from 'node:fs'",
|
||||
"import * as path from 'node:path'",
|
||||
"import { app, autoUpdater, contextBridge, crashReporter, dialog, BrowserWindow, ipcMain, ipcRenderer, Menu, MessageChannelMain, nativeImage, net, protocol, session, systemPreferences, Tray, utilityProcess, webFrame, webFrameMain } from 'electron'"
|
||||
],
|
||||
"typings": [
|
||||
"../electron.d.ts"
|
||||
]
|
||||
}
|
||||
}
|
||||
27
.markdownlint-cli2.jsonc
Normal file
27
.markdownlint-cli2.jsonc
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"config": {
|
||||
"extends": "@electron/lint-roller/configs/markdownlint.json",
|
||||
"link-image-style": {
|
||||
"autolink": false,
|
||||
"shortcut": false
|
||||
},
|
||||
"no-angle-brackets": true,
|
||||
"no-curly-braces": true,
|
||||
"no-inline-html": {
|
||||
"allowed_elements": [
|
||||
"br",
|
||||
"details",
|
||||
"img",
|
||||
"li",
|
||||
"summary",
|
||||
"ul",
|
||||
"unknown",
|
||||
"Tabs",
|
||||
"TabItem"
|
||||
]
|
||||
}
|
||||
},
|
||||
"customRules": [
|
||||
"@electron/lint-roller/markdownlint-rules/"
|
||||
]
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"default": false,
|
||||
"no-trailing-spaces": {
|
||||
"br_spaces": 0
|
||||
}
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": "@electron/lint-roller/configs/markdownlint.json"
|
||||
}
|
||||
33
BUILD.gn
33
BUILD.gn
@@ -81,18 +81,11 @@ if (is_linux) {
|
||||
]
|
||||
}
|
||||
|
||||
# Generates electron_gtk_stubs.h header which contains
|
||||
# stubs for extracting function ptrs from the gtk library.
|
||||
# Function signatures for which stubs are required should be
|
||||
# declared in electron_gtk.sigs, currently this file contains
|
||||
# signatures for the functions used with native file chooser
|
||||
# implementation. In future, this file can be extended to contain
|
||||
# gtk4 stubs to switch gtk version in runtime.
|
||||
# Generates headers which contain stubs for extracting function ptrs
|
||||
# from the gtk library. Function signatures for which stubs are
|
||||
# required should be declared in the sig files.
|
||||
generate_stubs("electron_gtk_stubs") {
|
||||
sigs = [
|
||||
"shell/browser/ui/electron_gdk_pixbuf.sigs",
|
||||
"shell/browser/ui/electron_gtk.sigs",
|
||||
]
|
||||
sigs = [ "shell/browser/ui/electron_gdk_pixbuf.sigs" ]
|
||||
extra_header = "shell/browser/ui/electron_gtk.fragment"
|
||||
output_name = "electron_gtk_stubs"
|
||||
public_deps = [ "//ui/gtk:gtk_config" ]
|
||||
@@ -475,6 +468,7 @@ source_set("electron_lib") {
|
||||
"//net:extras",
|
||||
"//net:net_resources",
|
||||
"//printing/buildflags",
|
||||
"//services/device/public/cpp/bluetooth:bluetooth",
|
||||
"//services/device/public/cpp/geolocation",
|
||||
"//services/device/public/cpp/hid",
|
||||
"//services/device/public/mojom",
|
||||
@@ -502,6 +496,7 @@ source_set("electron_lib") {
|
||||
"//ui/native_theme",
|
||||
"//ui/shell_dialogs",
|
||||
"//ui/views",
|
||||
"//ui/views/controls/webview",
|
||||
"//v8",
|
||||
"//v8:v8_libplatform",
|
||||
]
|
||||
@@ -637,7 +632,6 @@ source_set("electron_lib") {
|
||||
"//ui/gtk:gtk_config",
|
||||
"//ui/linux:linux_ui",
|
||||
"//ui/linux:linux_ui_factory",
|
||||
"//ui/views/controls/webview",
|
||||
"//ui/wm",
|
||||
]
|
||||
if (ozone_platform_x11) {
|
||||
@@ -664,9 +658,9 @@ source_set("electron_lib") {
|
||||
libs += [ "dwmapi.lib" ]
|
||||
sources += [ "shell/common/asar/archive_win.cc" ]
|
||||
deps += [
|
||||
"//components/app_launch_prefetch",
|
||||
"//components/crash/core/app:crash_export_thunks",
|
||||
"//ui/native_theme:native_theme_browser",
|
||||
"//ui/views/controls/webview",
|
||||
"//ui/wm",
|
||||
"//ui/wm/public",
|
||||
]
|
||||
@@ -700,6 +694,8 @@ source_set("electron_lib") {
|
||||
sources += [
|
||||
"shell/browser/printing/print_view_manager_electron.cc",
|
||||
"shell/browser/printing/print_view_manager_electron.h",
|
||||
"shell/browser/printing/printing_utils.cc",
|
||||
"shell/browser/printing/printing_utils.h",
|
||||
"shell/renderer/printing/print_render_frame_helper_delegate.cc",
|
||||
"shell/renderer/printing/print_render_frame_helper_delegate.h",
|
||||
]
|
||||
@@ -744,7 +740,8 @@ source_set("electron_lib") {
|
||||
"//chrome/browser/resources/pdf:resources",
|
||||
"//components/pdf/browser",
|
||||
"//components/pdf/browser:interceptors",
|
||||
"//components/pdf/common",
|
||||
"//components/pdf/common:constants",
|
||||
"//components/pdf/common:util",
|
||||
"//components/pdf/renderer",
|
||||
"//pdf",
|
||||
]
|
||||
@@ -856,7 +853,7 @@ if (is_mac) {
|
||||
if (is_asan) {
|
||||
# crashpad_handler requires the ASan runtime at its @executable_path.
|
||||
sources += [ "$root_out_dir/libclang_rt.asan_osx_dynamic.dylib" ]
|
||||
public_deps += [ "//build/config/sanitizers:copy_asan_runtime" ]
|
||||
public_deps += [ "//build/config/sanitizers:copy_sanitizer_runtime" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1464,8 +1461,10 @@ dist_zip("hunspell_dictionaries_zip") {
|
||||
}
|
||||
|
||||
copy("libcxx_headers") {
|
||||
sources = libcxx_headers + libcxx_licenses +
|
||||
[ "//buildtools/third_party/libc++/__config_site" ]
|
||||
sources = libcxx_headers + libcxx_licenses + [
|
||||
"//buildtools/third_party/libc++/__assertion_handler",
|
||||
"//buildtools/third_party/libc++/__config_site",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/electron_libcxx_include/{{source_root_relative_dir}}/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
|
||||
52
DEPS
52
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'123.0.6296.0',
|
||||
'126.0.6445.0',
|
||||
'node_version':
|
||||
'v20.11.1',
|
||||
'v20.13.1',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
@@ -161,6 +161,54 @@ hooks = [
|
||||
'import os, subprocess; os.chdir(os.path.join("src", "electron")); subprocess.check_call(["python3", "script/lib/npx.py", "yarn@' + (Var("yarn_version")) + '", "install", "--frozen-lockfile"]);',
|
||||
],
|
||||
},
|
||||
{
|
||||
'name': 'sysroot_arm',
|
||||
'pattern': '.',
|
||||
'condition': 'checkout_linux and checkout_arm',
|
||||
'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py',
|
||||
'--sysroots-json-path=' + Var('sysroots_json_path'),
|
||||
'--arch=arm'],
|
||||
},
|
||||
{
|
||||
'name': 'sysroot_arm64',
|
||||
'pattern': '.',
|
||||
'condition': 'checkout_linux and checkout_arm64',
|
||||
'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py',
|
||||
'--sysroots-json-path=' + Var('sysroots_json_path'),
|
||||
'--arch=arm64'],
|
||||
},
|
||||
{
|
||||
'name': 'sysroot_x86',
|
||||
'pattern': '.',
|
||||
'condition': 'checkout_linux and (checkout_x86 or checkout_x64)',
|
||||
'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py',
|
||||
'--sysroots-json-path=' + Var('sysroots_json_path'),
|
||||
'--arch=x86'],
|
||||
},
|
||||
{
|
||||
'name': 'sysroot_mips',
|
||||
'pattern': '.',
|
||||
'condition': 'checkout_linux and checkout_mips',
|
||||
'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py',
|
||||
'--sysroots-json-path=' + Var('sysroots_json_path'),
|
||||
'--arch=mips'],
|
||||
},
|
||||
{
|
||||
'name': 'sysroot_mips64',
|
||||
'pattern': '.',
|
||||
'condition': 'checkout_linux and checkout_mips64',
|
||||
'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py',
|
||||
'--sysroots-json-path=' + Var('sysroots_json_path'),
|
||||
'--arch=mips64el'],
|
||||
},
|
||||
{
|
||||
'name': 'sysroot_x64',
|
||||
'pattern': '.',
|
||||
'condition': 'checkout_linux and checkout_x64',
|
||||
'action': ['python3', 'src/build/linux/sysroot_scripts/install-sysroot.py',
|
||||
'--sysroots-json-path=' + Var('sysroots_json_path'),
|
||||
'--arch=x64'],
|
||||
},
|
||||
]
|
||||
|
||||
recursedeps = [
|
||||
|
||||
@@ -112,4 +112,4 @@ and more can be found on the [Community page](https://www.electronjs.org/communi
|
||||
|
||||
[MIT](https://github.com/electron/electron/blob/main/LICENSE)
|
||||
|
||||
When using Electron logos, make sure to follow [OpenJS Foundation Trademark Policy](https://openjsf.org/wp-content/uploads/sites/84/2021/01/OpenJS-Foundation-Trademark-Policy-2021-01-12.docx.pdf).
|
||||
When using Electron logos, make sure to follow [OpenJS Foundation Trademark Policy](https://trademark-policy.openjsf.org/).
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-123.0.6296.0
|
||||
image: e-126.0.6445.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -39,7 +39,7 @@ environment:
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_27370823e7: 28622d16b1
|
||||
GYP_MSVS_HASH_7393122652: 3ba76c5c20
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
matrix:
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-123.0.6296.0
|
||||
image: e-126.0.6445.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -39,7 +39,7 @@ environment:
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_27370823e7: 28622d16b1
|
||||
GYP_MSVS_HASH_7393122652: 3ba76c5c20
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
matrix:
|
||||
|
||||
@@ -50,16 +50,13 @@ is_cfi = false
|
||||
# TODO: fix this once sysroots have been updated.
|
||||
use_qt = false
|
||||
|
||||
# https://chromium-review.googlesource.com/c/chromium/src/+/4365718
|
||||
# TODO(codebytere): fix perfetto incompatibility with Node.js.
|
||||
use_perfetto_client_library = false
|
||||
|
||||
# Disables the builtins PGO for V8
|
||||
v8_builtins_profiling_log_file = ""
|
||||
|
||||
# https://chromium.googlesource.com/chromium/src/+/main/docs/dangling_ptr.md
|
||||
# TODO(vertedinde): hunt down dangling pointers on Linux
|
||||
enable_dangling_raw_ptr_checks = false
|
||||
enable_dangling_raw_ptr_feature_flag = false
|
||||
|
||||
# This flag speeds up the performance of fork/execve on linux systems.
|
||||
# Ref: https://chromium-review.googlesource.com/c/v8/v8/+/4602858
|
||||
@@ -67,3 +64,12 @@ v8_enable_private_mapping_fork_optimization = true
|
||||
|
||||
# Expose public V8 symbols for native modules.
|
||||
v8_expose_public_symbols = true
|
||||
|
||||
# Disables unsafe-buffers-usage plugin due to incompatibilities with our reclient implementation
|
||||
# Ref: https://chromium-review.googlesource.com/c/chromium/src/+/5426599
|
||||
# Ref: https://github.com/electron/electron/commit/8e20f16ea35eeaeb149ae63bad3703d782665f6a
|
||||
clang_unsafe_buffers_paths = ""
|
||||
|
||||
# Disable snapshotting a page when printing for its content to be analyzed for
|
||||
# sensitive content by enterprise users.
|
||||
enterprise_content_analysis = false
|
||||
|
||||
@@ -33,6 +33,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/devtools/visual_logging.h",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.h",
|
||||
"//chrome/browser/file_system_access/file_system_access_features.cc",
|
||||
"//chrome/browser/file_system_access/file_system_access_features.h",
|
||||
"//chrome/browser/icon_loader.cc",
|
||||
"//chrome/browser/icon_loader.h",
|
||||
"//chrome/browser/icon_manager.cc",
|
||||
@@ -92,6 +94,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_manager.cc",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_manager.h",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_permission_manager.cc",
|
||||
"//chrome/browser/ui/exclusive_access/exclusive_access_permission_manager.h",
|
||||
"//chrome/browser/ui/exclusive_access/fullscreen_controller.cc",
|
||||
"//chrome/browser/ui/exclusive_access/fullscreen_controller.h",
|
||||
"//chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.cc",
|
||||
@@ -181,6 +185,8 @@ static_library("chrome") {
|
||||
"//chrome/browser:resource_prefetch_predictor_proto",
|
||||
"//chrome/browser/resource_coordinator:mojo_bindings",
|
||||
"//chrome/browser/web_applications/mojom:mojom_web_apps_enum",
|
||||
"//components/enterprise/buildflags",
|
||||
"//components/safe_browsing/core/browser/db:safebrowsing_proto",
|
||||
"//components/vector_icons:vector_icons",
|
||||
"//ui/snapshot",
|
||||
"//ui/views/controls/webview",
|
||||
@@ -231,6 +237,7 @@ static_library("chrome") {
|
||||
"//chrome/services/util_win:lib",
|
||||
"//components/webapps/common:mojo_bindings",
|
||||
]
|
||||
deps += [ "//components/segmentation_platform/public/proto" ]
|
||||
}
|
||||
|
||||
if (is_mac) {
|
||||
@@ -268,6 +275,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/bad_message.h",
|
||||
"//chrome/browser/printing/prefs_util.cc",
|
||||
"//chrome/browser/printing/prefs_util.h",
|
||||
"//chrome/browser/printing/print_compositor_util.cc",
|
||||
"//chrome/browser/printing/print_compositor_util.h",
|
||||
"//chrome/browser/printing/print_job.cc",
|
||||
"//chrome/browser/printing/print_job.h",
|
||||
"//chrome/browser/printing/print_job_manager.cc",
|
||||
@@ -294,6 +303,8 @@ static_library("chrome") {
|
||||
|
||||
if (enable_oop_printing) {
|
||||
sources += [
|
||||
"//chrome/browser/printing/oop_features.cc",
|
||||
"//chrome/browser/printing/oop_features.h",
|
||||
"//chrome/browser/printing/print_backend_service_manager.cc",
|
||||
"//chrome/browser/printing/print_backend_service_manager.h",
|
||||
]
|
||||
@@ -320,6 +331,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/printing/pdf_to_emf_converter.h",
|
||||
"//chrome/browser/printing/printer_xml_parser_impl.cc",
|
||||
"//chrome/browser/printing/printer_xml_parser_impl.h",
|
||||
"//chrome/browser/printing/xps_features.cc",
|
||||
"//chrome/browser/printing/xps_features.h",
|
||||
]
|
||||
deps += [ "//printing:printing_base" ]
|
||||
}
|
||||
@@ -343,8 +356,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/pdf/chrome_pdf_stream_delegate.h",
|
||||
"//chrome/browser/pdf/pdf_extension_util.cc",
|
||||
"//chrome/browser/pdf/pdf_extension_util.h",
|
||||
"//chrome/browser/pdf/pdf_frame_util.cc",
|
||||
"//chrome/browser/pdf/pdf_frame_util.h",
|
||||
"//chrome/browser/pdf/pdf_viewer_stream_manager.cc",
|
||||
"//chrome/browser/pdf/pdf_viewer_stream_manager.h",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.cc",
|
||||
|
||||
@@ -98,7 +98,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
|
||||
### Custom DOM Elements:
|
||||
|
||||
* [`File` Object](api/file-object.md)
|
||||
* [`<webview>` Tag](api/webview-tag.md)
|
||||
* [`window.open` Function](api/window-open.md)
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ In most cases, you should do everything in the `ready` event handler.
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `launchInfo` Record<string, any> | [NotificationResponse](structures/notification-response.md) _macOS_
|
||||
* `launchInfo` Record\<string, any\> | [NotificationResponse](structures/notification-response.md) _macOS_
|
||||
|
||||
Emitted once, when Electron has finished initializing. On macOS, `launchInfo`
|
||||
holds the `userInfo` of the [`NSUserNotification`](https://developer.apple.com/documentation/foundation/nsusernotification)
|
||||
@@ -41,6 +41,10 @@ that was used to open the application, if it was launched from Notification Cent
|
||||
You can also call `app.isReady()` to check if this event has already fired and `app.whenReady()`
|
||||
to get a Promise that is fulfilled when Electron is initialized.
|
||||
|
||||
**Note**: The `ready` event is only fired after the main process has finished running the first
|
||||
tick of the event loop. If an Electron API needs to be called before the `ready` event, ensure
|
||||
that it is called synchronously in the top-level context of the main process.
|
||||
|
||||
### Event: 'window-all-closed'
|
||||
|
||||
Emitted when all windows have been closed.
|
||||
@@ -970,7 +974,7 @@ app.setJumpList([
|
||||
|
||||
### `app.requestSingleInstanceLock([additionalData])`
|
||||
|
||||
* `additionalData` Record<any, any> (optional) - A JSON object containing additional data to send to the first instance.
|
||||
* `additionalData` Record\<any, any\> (optional) - A JSON object containing additional data to send to the first instance.
|
||||
|
||||
Returns `boolean`
|
||||
|
||||
@@ -1468,6 +1472,24 @@ details.
|
||||
|
||||
**Note:** Enable `Secure Keyboard Entry` only when it is needed and disable it when it is no longer needed.
|
||||
|
||||
### `app.setProxy(config)`
|
||||
|
||||
* `config` [ProxyConfig](structures/proxy-config.md)
|
||||
|
||||
Returns `Promise<void>` - Resolves when the proxy setting process is complete.
|
||||
|
||||
Sets the proxy settings for networks requests made without an associated [Session](session.md).
|
||||
Currently this will affect requests made with [Net](net.md) in the [utility process](../glossary.md#utility-process)
|
||||
and internal requests made by the runtime (ex: geolocation queries).
|
||||
|
||||
This method can only be called after app is ready.
|
||||
|
||||
#### `app.resolveProxy(url)`
|
||||
|
||||
* `url` URL
|
||||
|
||||
Returns `Promise<string>` - Resolves with the proxy information for `url` that will be used when attempting to make requests using [Net](net.md) in the [utility process](../glossary.md#utility-process).
|
||||
|
||||
## Properties
|
||||
|
||||
### `app.accessibilitySupportEnabled` _macOS_ _Windows_
|
||||
|
||||
@@ -103,7 +103,7 @@ The `autoUpdater` object has the following methods:
|
||||
|
||||
* `options` Object
|
||||
* `url` string
|
||||
* `headers` Record<string, string> (optional) _macOS_ - HTTP request headers.
|
||||
* `headers` Record\<string, string\> (optional) _macOS_ - HTTP request headers.
|
||||
* `serverType` string (optional) _macOS_ - Can be `json` or `default`, see the [Squirrel.Mac][squirrel-mac]
|
||||
README for more information.
|
||||
|
||||
|
||||
@@ -600,7 +600,7 @@ Perhaps there are 15 pixels of controls on the left edge, 25 pixels of controls
|
||||
on the right edge and 50 pixels of controls below the player. In order to
|
||||
maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within
|
||||
the player itself we would call this function with arguments of 16/9 and
|
||||
{ width: 40, height: 50 }. The second argument doesn't care where the extra width and height
|
||||
\{ width: 40, height: 50 \}. The second argument doesn't care where the extra width and height
|
||||
are within the content view--only that they exist. Sum any extra width and
|
||||
height areas you have within the overall content view.
|
||||
|
||||
@@ -656,7 +656,7 @@ Closes the currently open [Quick Look][quick-look] panel.
|
||||
|
||||
#### `win.setBounds(bounds[, animate])`
|
||||
|
||||
* `bounds` Partial<[Rectangle](structures/rectangle.md)>
|
||||
* `bounds` Partial\<[Rectangle](structures/rectangle.md)\>
|
||||
* `animate` boolean (optional) _macOS_
|
||||
|
||||
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.
|
||||
|
||||
@@ -723,7 +723,7 @@ Perhaps there are 15 pixels of controls on the left edge, 25 pixels of controls
|
||||
on the right edge and 50 pixels of controls below the player. In order to
|
||||
maintain a 16:9 aspect ratio (standard aspect ratio for HD @1920x1080) within
|
||||
the player itself we would call this function with arguments of 16/9 and
|
||||
{ width: 40, height: 50 }. The second argument doesn't care where the extra width and height
|
||||
\{ width: 40, height: 50 \}. The second argument doesn't care where the extra width and height
|
||||
are within the content view--only that they exist. Sum any extra width and
|
||||
height areas you have within the overall content view.
|
||||
|
||||
@@ -779,7 +779,7 @@ Closes the currently open [Quick Look][quick-look] panel.
|
||||
|
||||
#### `win.setBounds(bounds[, animate])`
|
||||
|
||||
* `bounds` Partial<[Rectangle](structures/rectangle.md)>
|
||||
* `bounds` Partial\<[Rectangle](structures/rectangle.md)\>
|
||||
* `animate` boolean (optional) _macOS_
|
||||
|
||||
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.
|
||||
@@ -1215,7 +1215,7 @@ win.loadURL('http://localhost:8000/post', {
|
||||
|
||||
* `filePath` string
|
||||
* `options` Object (optional)
|
||||
* `query` Record<string, string> (optional) - Passed to `url.format()`.
|
||||
* `query` Record\<string, string\> (optional) - Passed to `url.format()`.
|
||||
* `search` string (optional) - Passed to `url.format()`.
|
||||
* `hash` string (optional) - Passed to `url.format()`.
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ following properties:
|
||||
method.
|
||||
* `url` string (optional) - The request URL. Must be provided in the absolute
|
||||
form with the protocol scheme specified as http or https.
|
||||
* `headers` Record\<string, string | string[]\> (optional) - Headers to be sent
|
||||
with the request.
|
||||
* `session` Session (optional) - The [`Session`](session.md) instance with
|
||||
which the request is associated.
|
||||
* `partition` string (optional) - The name of the [`partition`](session.md)
|
||||
@@ -158,7 +160,7 @@ Returns:
|
||||
* `statusCode` Integer
|
||||
* `method` string
|
||||
* `redirectUrl` string
|
||||
* `responseHeaders` Record<string, string[]>
|
||||
* `responseHeaders` Record\<string, string[]\>
|
||||
|
||||
Emitted when the server returns a redirect response (e.g. 301 Moved
|
||||
Permanently). Calling [`request.followRedirect`](#requestfollowredirect) will
|
||||
|
||||
@@ -129,7 +129,7 @@ has been included below for completeness:
|
||||
| `Object` | Complex | ✅ | ✅ | Keys must be supported using only "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
|
||||
| `Array` | Complex | ✅ | ✅ | Same limitations as the `Object` type |
|
||||
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context, and any custom properties on the Error object [will be lost](https://github.com/electron/electron/issues/25596) |
|
||||
| `Promise` | Complex | ✅ | ✅ | N/A
|
||||
| `Promise` | Complex | ✅ | ✅ | N/A |
|
||||
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
|
||||
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
|
||||
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |
|
||||
|
||||
@@ -59,14 +59,14 @@ The `crashReporter` module has the following methods:
|
||||
number of crashes uploaded to 1/hour. Default is `false`.
|
||||
* `compress` boolean (optional) - If true, crash reports will be compressed
|
||||
and uploaded with `Content-Encoding: gzip`. Default is `true`.
|
||||
* `extra` Record<string, string> (optional) - Extra string key/value
|
||||
* `extra` Record\<string, string\> (optional) - Extra string key/value
|
||||
annotations that will be sent along with crash reports that are generated
|
||||
in the main process. Only string values are supported. Crashes generated in
|
||||
child processes will not contain these extra
|
||||
parameters to crash reports generated from child processes, call
|
||||
[`addExtraParameter`](#crashreporteraddextraparameterkey-value) from the
|
||||
child process.
|
||||
* `globalExtra` Record<string, string> (optional) - Extra string key/value
|
||||
* `globalExtra` Record\<string, string\> (optional) - Extra string key/value
|
||||
annotations that will be sent along with any crash reports generated in any
|
||||
process. These annotations cannot be changed once the crash reporter has
|
||||
been started. If a key is present in both the global extra parameters and
|
||||
|
||||
@@ -174,7 +174,7 @@ dialog.showOpenDialog(mainWindow, {
|
||||
* `dontAddToRecent` _Windows_ - Do not add the item being saved to the recent documents list.
|
||||
* `securityScopedBookmarks` boolean (optional) _macOS_ _mas_ - Create a [security scoped bookmark](https://developer.apple.com/library/content/documentation/Security/Conceptual/AppSandboxDesignGuide/AppSandboxInDepth/AppSandboxInDepth.html#//apple_ref/doc/uid/TP40011183-CH3-SW16) when packaged for the Mac App Store. If this option is enabled and the file doesn't already exist a blank file will be created at the chosen path.
|
||||
|
||||
Returns `string | undefined`, the path of the file chosen by the user; if the dialog is cancelled it returns `undefined`.
|
||||
Returns `string`, the path of the file chosen by the user; if the dialog is cancelled it returns an empty string.
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
|
||||
|
||||
@@ -207,7 +207,7 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
Returns `Promise<Object>` - Resolve with an object containing the following:
|
||||
|
||||
* `canceled` boolean - whether or not the dialog was canceled.
|
||||
* `filePath` string (optional) - If the dialog is canceled, this will be `undefined`.
|
||||
* `filePath` string - If the dialog is canceled, this will be an empty string.
|
||||
* `bookmark` string (optional) _macOS_ _mas_ - Base64 encoded string which contains the security scoped bookmark data for the saved file. `securityScopedBookmarks` must be enabled for this to be present. (For return values, see [table here](#bookmarks-array).)
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
|
||||
|
||||
@@ -51,6 +51,18 @@ Unsupported options are:
|
||||
--http-parser
|
||||
```
|
||||
|
||||
If the [`nodeOptions` fuse](../tutorial/fuses.md#nodeoptions) is disabled, `NODE_OPTIONS` will be ignored.
|
||||
|
||||
### `NODE_EXTRA_CA_CERTS`
|
||||
|
||||
See [Node.js cli documentation](https://github.com/nodejs/node/blob/main/doc/api/cli.md#node_extra_ca_certsfile) for details.
|
||||
|
||||
```sh
|
||||
export NODE_EXTRA_CA_CERTS=/path/to/cert.pem
|
||||
```
|
||||
|
||||
If the [`nodeOptions` fuse](../tutorial/fuses.md#nodeoptions) is disabled, `NODE_EXTRA_CA_CERTS` will be ignored.
|
||||
|
||||
### `GOOGLE_API_KEY`
|
||||
|
||||
Geolocation support in Electron requires the use of Google Cloud Platform's
|
||||
@@ -92,6 +104,8 @@ you would when running the normal Node.js executable, with the exception of the
|
||||
These flags are disabled owing to the fact that Electron uses BoringSSL instead of OpenSSL when building Node.js'
|
||||
`crypto` module, and so will not work as designed.
|
||||
|
||||
If the [`runAsNode` fuse](../tutorial/fuses.md#L13) is disabled, `ELECTRON_RUN_AS_NODE` will be ignored.
|
||||
|
||||
### `ELECTRON_NO_ATTACH_CONSOLE` _Windows_
|
||||
|
||||
Don't attach to the current console session.
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
# `File` Object
|
||||
|
||||
> Use the HTML5 `File` API to work natively with files on the filesystem.
|
||||
|
||||
> **Warning**
|
||||
> The `path` property that Electron adds to the `File` interface is deprecated
|
||||
> and **will** be removed in a future Electron release. We recommend you
|
||||
> use `webUtils.getPathForFile` instead.
|
||||
|
||||
The DOM's File interface provides abstraction around native files in order to
|
||||
let users work on native files directly with the HTML5 file API. Electron has
|
||||
added a `path` attribute to the `File` interface which exposes the file's real
|
||||
path on filesystem.
|
||||
|
||||
Example of getting a real path from a dragged-onto-the-app file:
|
||||
|
||||
```html
|
||||
<div id="holder">
|
||||
Drag your file here
|
||||
</div>
|
||||
|
||||
<script>
|
||||
document.addEventListener('drop', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
for (const f of e.dataTransfer.files) {
|
||||
console.log('File(s) you dragged here: ', f.path)
|
||||
}
|
||||
});
|
||||
document.addEventListener('dragover', (e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
});
|
||||
</script>
|
||||
```
|
||||
@@ -72,7 +72,7 @@ Removes listeners of the specified `channel`.
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function<Promise\<any> | any>
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
* `...args` any[]
|
||||
|
||||
@@ -109,7 +109,7 @@ provided to the renderer process. Please refer to
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function<Promise\<any> | any>
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
* `...args` any[]
|
||||
|
||||
|
||||
@@ -38,18 +38,18 @@ See [`Menu`](menu.md) for examples.
|
||||
`Menu.buildFromTemplate`.
|
||||
* `id` string (optional) - Unique within a single menu. If defined then it can be used
|
||||
as a reference to this item by the position attribute.
|
||||
* `before` string[] (optional) - Inserts this item before the item with the specified label. If
|
||||
* `before` string[] (optional) - Inserts this item before the item with the specified id. If
|
||||
the referenced item doesn't exist the item will be inserted at the end of the menu. Also implies
|
||||
that the menu item in question should be placed in the same “group” as the item.
|
||||
* `after` string[] (optional) - Inserts this item after the item with the specified label. If the
|
||||
* `after` string[] (optional) - Inserts this item after the item with the specified id. If the
|
||||
referenced item doesn't exist the item will be inserted at the end of
|
||||
the menu.
|
||||
* `beforeGroupContaining` string[] (optional) - Provides a means for a single context menu to declare
|
||||
the placement of their containing group before the containing group of the item
|
||||
with the specified label.
|
||||
with the specified id.
|
||||
* `afterGroupContaining` string[] (optional) - Provides a means for a single context menu to declare
|
||||
the placement of their containing group after the containing group of the item
|
||||
with the specified label.
|
||||
with the specified id.
|
||||
|
||||
**Note:** `acceleratorWorksWhenHidden` is specified as being macOS-only because accelerators always work when items are hidden on Windows and Linux. The option is exposed to users to give them the option to turn it off, as this is possible in native macOS development.
|
||||
|
||||
|
||||
@@ -336,16 +336,16 @@ browser windows.
|
||||
|
||||
You can make use of `before`, `after`, `beforeGroupContaining`, `afterGroupContaining` and `id` to control how the item will be placed when building a menu with `Menu.buildFromTemplate`.
|
||||
|
||||
* `before` - Inserts this item before the item with the specified label. If the
|
||||
* `before` - Inserts this item before the item with the specified id. If the
|
||||
referenced item doesn't exist the item will be inserted at the end of
|
||||
the menu. Also implies that the menu item in question should be placed in the same “group” as the item.
|
||||
* `after` - Inserts this item after the item with the specified label. If the
|
||||
* `after` - Inserts this item after the item with the specified id. If the
|
||||
referenced item doesn't exist the item will be inserted at the end of
|
||||
the menu. Also implies that the menu item in question should be placed in the same “group” as the item.
|
||||
* `beforeGroupContaining` - Provides a means for a single context menu to declare
|
||||
the placement of their containing group before the containing group of the item with the specified label.
|
||||
the placement of their containing group before the containing group of the item with the specified id.
|
||||
* `afterGroupContaining` - Provides a means for a single context menu to declare
|
||||
the placement of their containing group after the containing group of the item with the specified label.
|
||||
the placement of their containing group after the containing group of the item with the specified id.
|
||||
|
||||
By default, items will be inserted in the order they exist in the template unless one of the specified positioning keywords is used.
|
||||
|
||||
|
||||
@@ -4,36 +4,41 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
In Electron, for the APIs that take images, you can pass either file paths or
|
||||
`NativeImage` instances. An empty image will be used when `null` is passed.
|
||||
The `nativeImage` module provides a unified interface for manipulating
|
||||
system images. These can be handy if you want to provide multiple scaled
|
||||
versions of the same icon or take advantage of macOS [template images][template-image].
|
||||
|
||||
For example, when creating a tray or setting a window's icon, you can pass an
|
||||
image file path as a `string`:
|
||||
Electron APIs that take image files accept either file paths or
|
||||
`NativeImage` instances. An empty and transparent image will be used when `null` is passed.
|
||||
|
||||
```js
|
||||
For example, when creating a [Tray](../api/tray.md) or setting a [BrowserWindow](../api/browser-window.md)'s
|
||||
icon, you can either pass an image file path as a string:
|
||||
|
||||
```js title='Main Process'
|
||||
const { BrowserWindow, Tray } = require('electron')
|
||||
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
const tray = new Tray('/Users/somebody/images/icon.png')
|
||||
const win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
|
||||
console.log(appIcon, win)
|
||||
```
|
||||
|
||||
Or read the image from the clipboard, which returns a `NativeImage`:
|
||||
or generate a `NativeImage` instance from the same file:
|
||||
|
||||
```js
|
||||
const { clipboard, Tray } = require('electron')
|
||||
const image = clipboard.readImage()
|
||||
const appIcon = new Tray(image)
|
||||
console.log(appIcon)
|
||||
```js title='Main Process'
|
||||
const { BrowserWindow, nativeImage, Tray } = require('electron')
|
||||
|
||||
const trayIcon = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
const appIcon = nativeImage.createFromPath('/Users/somebody/images/window.png')
|
||||
const tray = new Tray(trayIcon)
|
||||
const win = new BrowserWindow({ icon: appIcon })
|
||||
```
|
||||
|
||||
## Supported Formats
|
||||
|
||||
Currently `PNG` and `JPEG` image formats are supported. `PNG` is recommended
|
||||
because of its support for transparency and lossless compression.
|
||||
Currently, `PNG` and `JPEG` image formats are supported across all platforms.
|
||||
`PNG` is recommended because of its support for transparency and lossless compression.
|
||||
|
||||
On Windows, you can also load `ICO` icons from file paths. For best visual
|
||||
quality, it is recommended to include at least the following sizes in the:
|
||||
quality, we recommend including at least the following sizes:
|
||||
|
||||
* Small icon
|
||||
* 16x16 (100% DPI scale)
|
||||
@@ -47,9 +52,9 @@ quality, it is recommended to include at least the following sizes in the:
|
||||
* 64x64 (200% DPI scale)
|
||||
* 256x256
|
||||
|
||||
Check the _Size requirements_ section in [this article][icons].
|
||||
Check the _Icon Scaling_ section in the Windows [App Icon Construction][icons] reference.
|
||||
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-icons
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/apps/design/style/iconography/app-icon-construction#icon-scaling
|
||||
|
||||
:::note
|
||||
|
||||
@@ -60,16 +65,17 @@ image encoding and decoding.
|
||||
|
||||
## High Resolution Image
|
||||
|
||||
On platforms that have high-DPI support such as Apple Retina displays, you can
|
||||
append `@2x` after image's base filename to mark it as a high resolution image.
|
||||
On platforms that support high pixel density displays (such as Apple Retina),
|
||||
you can append `@2x` after image's base filename to mark it as a 2x scale
|
||||
high resolution image.
|
||||
|
||||
For example, if `icon.png` is a normal image that has standard resolution, then
|
||||
`icon@2x.png` will be treated as a high resolution image that has double DPI
|
||||
density.
|
||||
`icon@2x.png` will be treated as a high resolution image that has double
|
||||
Dots per Inch (DPI) density.
|
||||
|
||||
If you want to support displays with different DPI densities at the same time,
|
||||
you can put images with different sizes in the same folder and use the filename
|
||||
without DPI suffixes. For example:
|
||||
without DPI suffixes within Electron. For example:
|
||||
|
||||
```plaintext
|
||||
images/
|
||||
@@ -78,10 +84,9 @@ images/
|
||||
└── icon@3x.png
|
||||
```
|
||||
|
||||
```js
|
||||
```js title='Main Process'
|
||||
const { Tray } = require('electron')
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
console.log(appIcon)
|
||||
const appTray = new Tray('/Users/somebody/images/icon.png')
|
||||
```
|
||||
|
||||
The following suffixes for DPI are also supported:
|
||||
@@ -98,27 +103,23 @@ The following suffixes for DPI are also supported:
|
||||
* `@4x`
|
||||
* `@5x`
|
||||
|
||||
## Template Image
|
||||
## Template Image _macOS_
|
||||
|
||||
Template images consist of black and an alpha channel.
|
||||
On macOS, [template images][template-image] consist of black and an alpha channel.
|
||||
Template images are not intended to be used as standalone images and are usually
|
||||
mixed with other content to create the desired final appearance.
|
||||
|
||||
The most common case is to use template images for a menu bar icon, so it can
|
||||
The most common case is to use template images for a menu bar (Tray) icon, so it can
|
||||
adapt to both light and dark menu bars.
|
||||
|
||||
**Note:** Template image is only supported on macOS.
|
||||
|
||||
To mark an image as a template image, its filename should end with the word
|
||||
`Template`. For example:
|
||||
|
||||
* `xxxTemplate.png`
|
||||
* `xxxTemplate@2x.png`
|
||||
To mark an image as a template image, its base filename should end with the word
|
||||
`Template` (e.g. `xxxTemplate.png`). You can also specify template images at
|
||||
different DPI densities (e.g. `xxxTemplate@2x.png`).
|
||||
|
||||
## Methods
|
||||
|
||||
The `nativeImage` module has the following methods, all of which return
|
||||
an instance of the `NativeImage` class:
|
||||
an instance of the [`NativeImage`](#class-nativeimage) class:
|
||||
|
||||
### `nativeImage.createEmpty()`
|
||||
|
||||
@@ -137,7 +138,7 @@ Note: The Windows implementation will ignore `size.height` and scale the height
|
||||
|
||||
### `nativeImage.createFromPath(path)`
|
||||
|
||||
* `path` string
|
||||
* `path` string - path to a file that we intend to construct an image out of.
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
@@ -146,7 +147,7 @@ returns an empty image if the `path` does not exist, cannot be read, or is not
|
||||
a valid image.
|
||||
|
||||
```js
|
||||
const nativeImage = require('electron').nativeImage
|
||||
const { nativeImage } = require('electron')
|
||||
|
||||
const image = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
console.log(image)
|
||||
@@ -183,7 +184,7 @@ Creates a new `NativeImage` instance from `buffer`. Tries to decode as PNG or JP
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
Creates a new `NativeImage` instance from `dataURL`.
|
||||
Creates a new `NativeImage` instance from `dataUrl`, a base 64 encoded [Data URL][data-url] string.
|
||||
|
||||
### `nativeImage.createFromNamedImage(imageName[, hslShift])` _macOS_
|
||||
|
||||
@@ -192,14 +193,14 @@ Creates a new `NativeImage` instance from `dataURL`.
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
Creates a new `NativeImage` instance from the NSImage that maps to the
|
||||
given image name. See [`System Icons`](https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/system-icons/)
|
||||
for a list of possible values.
|
||||
Creates a new `NativeImage` instance from the `NSImage` that maps to the
|
||||
given image name. See Apple's [`NSImageName`](https://developer.apple.com/documentation/appkit/nsimagename#2901388)
|
||||
documentation for a list of possible values.
|
||||
|
||||
The `hslShift` is applied to the image with the following rules:
|
||||
|
||||
* `hsl_shift[0]` (hue): The absolute hue value for the image - 0 and 1 map
|
||||
to 0 and 360 on the hue color wheel (red).
|
||||
to 0 and 360 on the hue color wheel (red).
|
||||
* `hsl_shift[1]` (saturation): A saturation shift for the image, with the
|
||||
following key values:
|
||||
0 = remove all color.
|
||||
@@ -216,7 +217,9 @@ This means that `[-1, 0, 1]` will make the image completely white and
|
||||
|
||||
In some cases, the `NSImageName` doesn't match its string representation; one example of this is `NSFolderImageName`, whose string representation would actually be `NSFolder`. Therefore, you'll need to determine the correct string representation for your image before passing it in. This can be done with the following:
|
||||
|
||||
`echo -e '#import <Cocoa/Cocoa.h>\nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME); }' | clang -otest -x objective-c -framework Cocoa - && ./test`
|
||||
```sh
|
||||
echo -e '#import <Cocoa/Cocoa.h>\nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME); }' | clang -otest -x objective-c -framework Cocoa - && ./test
|
||||
```
|
||||
|
||||
where `SYSTEM_IMAGE_NAME` should be replaced with any value from [this list](https://developer.apple.com/documentation/appkit/nsimagename?language=objc).
|
||||
|
||||
@@ -257,7 +260,7 @@ data.
|
||||
* `options` Object (optional)
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `string` - The data URL of the image.
|
||||
Returns `string` - The [Data URL][data-url] of the image.
|
||||
|
||||
#### `image.getBitmap([options])`
|
||||
|
||||
@@ -273,7 +276,7 @@ current event loop tick; otherwise the data might be changed or destroyed.
|
||||
#### `image.getNativeHandle()` _macOS_
|
||||
|
||||
Returns `Buffer` - A [Buffer][buffer] that stores C pointer to underlying native handle of
|
||||
the image. On macOS, a pointer to `NSImage` instance would be returned.
|
||||
the image. On macOS, a pointer to `NSImage` instance is returned.
|
||||
|
||||
Notice that the returned pointer is a weak pointer to the underlying native
|
||||
image instead of a copy, so you _must_ ensure that the associated
|
||||
@@ -295,11 +298,11 @@ If `scaleFactor` is passed, this will return the size corresponding to the image
|
||||
|
||||
* `option` boolean
|
||||
|
||||
Marks the image as a template image.
|
||||
Marks the image as a macOS [template image][template-image].
|
||||
|
||||
#### `image.isTemplateImage()`
|
||||
|
||||
Returns `boolean` - Whether the image is a template image.
|
||||
Returns `boolean` - Whether the image is a macOS [template image][template-image].
|
||||
|
||||
#### `image.crop(rect)`
|
||||
|
||||
@@ -328,13 +331,13 @@ will be preserved in the resized image.
|
||||
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `Number` - The image's aspect ratio.
|
||||
Returns `Number` - The image's aspect ratio (width divided by height).
|
||||
|
||||
If `scaleFactor` is passed, this will return the aspect ratio corresponding to the image representation most closely matching the passed value.
|
||||
|
||||
#### `image.getScaleFactors()`
|
||||
|
||||
Returns `Number[]` - An array of all scale factors corresponding to representations for a given nativeImage.
|
||||
Returns `Number[]` - An array of all scale factors corresponding to representations for a given `NativeImage`.
|
||||
|
||||
#### `image.addRepresentation(options)`
|
||||
|
||||
@@ -349,15 +352,17 @@ Returns `Number[]` - An array of all scale factors corresponding to representati
|
||||
encoded PNG or JPEG image.
|
||||
|
||||
Add an image representation for a specific scale factor. This can be used
|
||||
to explicitly add different scale factor representations to an image. This
|
||||
to programmatically add different scale factor representations to an image. This
|
||||
can be called on empty images.
|
||||
|
||||
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `nativeImage.isMacTemplateImage` _macOS_
|
||||
|
||||
A `boolean` property that determines whether the image is considered a [template image](https://developer.apple.com/documentation/appkit/nsimage/1520017-template).
|
||||
A `boolean` property that determines whether the image is considered a [template image][template-image].
|
||||
|
||||
Please note that this property only has an effect on macOS.
|
||||
|
||||
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
|
||||
[data-url]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
|
||||
[template-image]: https://developer.apple.com/documentation/appkit/nsimage/1520017-template
|
||||
|
||||
29
docs/api/navigation-history.md
Normal file
29
docs/api/navigation-history.md
Normal file
@@ -0,0 +1,29 @@
|
||||
## Class: NavigationHistory
|
||||
|
||||
> Manage a list of navigation entries, representing the user's browsing history within the application.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)<br />
|
||||
_This class is not exported from the `'electron'` module. It is only available as a return value of other methods in the Electron API._
|
||||
|
||||
Each navigation entry corresponds to a specific page. The indexing system follows a sequential order, where the first available navigation entry is at index 0, representing the earliest visited page, and the latest navigation entry is at index N, representing the most recent page. Maintaining this ordered list of navigation entries enables seamless navigation both backward and forward through the user's browsing history.
|
||||
|
||||
### Instance Methods
|
||||
|
||||
#### `navigationHistory.getActiveIndex()`
|
||||
|
||||
Returns `Integer` - The index of the current page, from which we would go back/forward or reload.
|
||||
|
||||
#### `navigationHistory.getEntryAtIndex(index)`
|
||||
|
||||
* `index` Integer
|
||||
|
||||
Returns `Object`:
|
||||
|
||||
* `url` string - The URL of the navigation entry at the given index.
|
||||
* `title` string - The page title of the navigation entry at the given index.
|
||||
|
||||
If index is out of bounds (greater than history length or less than 0), null will be returned.
|
||||
|
||||
#### `navigationHistory.length()`
|
||||
|
||||
Returns `Integer` - History length.
|
||||
@@ -66,7 +66,7 @@ requests according to the specified protocol scheme in the `options` object.
|
||||
### `net.fetch(input[, init])`
|
||||
|
||||
* `input` string | [GlobalRequest](https://nodejs.org/api/globals.html#request)
|
||||
* `init` [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options) & { bypassCustomProtocolHandlers?: boolean } (optional)
|
||||
* `init` [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options) & \{ bypassCustomProtocolHandlers?: boolean \} (optional)
|
||||
|
||||
Returns `Promise<GlobalResponse>` - see [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response).
|
||||
|
||||
|
||||
@@ -21,7 +21,6 @@ In sandboxed renderers the `process` object contains only a subset of the APIs:
|
||||
* `getSystemMemoryInfo()`
|
||||
* `getSystemVersion()`
|
||||
* `getCPUUsage()`
|
||||
* `getIOCounters()`
|
||||
* `uptime()`
|
||||
* `argv`
|
||||
* `execPath`
|
||||
@@ -162,10 +161,6 @@ The time is represented as number of milliseconds since epoch. It returns null i
|
||||
|
||||
Returns [`CPUUsage`](structures/cpu-usage.md)
|
||||
|
||||
### `process.getIOCounters()` _Windows_ _Linux_
|
||||
|
||||
Returns [`IOCounters`](structures/io-counters.md)
|
||||
|
||||
### `process.getHeapStatistics()`
|
||||
|
||||
Returns `Object`:
|
||||
|
||||
@@ -9,10 +9,14 @@ An example of implementing a protocol that has the same effect as the
|
||||
|
||||
```js
|
||||
const { app, protocol, net } = require('electron')
|
||||
const path = require('node:path')
|
||||
const url = require('node:url')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
protocol.handle('atom', (request) =>
|
||||
net.fetch('file://' + request.url.slice('atom://'.length)))
|
||||
protocol.handle('atom', (request) => {
|
||||
const filePath = request.url.slice('atom://'.length)
|
||||
return net.fetch(url.pathToFileURL(path.join(__dirname, filePath)).toString())
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@@ -42,7 +46,7 @@ app.whenReady().then(() => {
|
||||
|
||||
ses.protocol.handle('atom', (request) => {
|
||||
const filePath = request.url.slice('atom://'.length)
|
||||
return net.fetch(url.pathToFileURL(path.join(__dirname, filePath)).toString())
|
||||
return net.fetch(url.pathToFileURL(path.resolve(__dirname, filePath)).toString())
|
||||
})
|
||||
|
||||
const mainWindow = new BrowserWindow({ webPreferences: { partition } })
|
||||
@@ -111,7 +115,7 @@ expect streaming responses.
|
||||
|
||||
* `scheme` string - scheme to handle, for example `https` or `my-app`. This is
|
||||
the bit before the `:` in a URL.
|
||||
* `handler` Function<[GlobalResponse](https://nodejs.org/api/globals.html#response) | Promise<GlobalResponse>>
|
||||
* `handler` Function\<[GlobalResponse](https://nodejs.org/api/globals.html#response) | Promise\<GlobalResponse\>\>
|
||||
* `request` [GlobalRequest](https://nodejs.org/api/globals.html#request)
|
||||
|
||||
Register a protocol handler for `scheme`. Requests made to URLs with this
|
||||
|
||||
@@ -27,7 +27,7 @@ The `pushNotification` module emits the following events:
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `userInfo` Record<String, any>
|
||||
* `userInfo` Record\<String, any\>
|
||||
|
||||
Emitted when the app receives a remote notification while running.
|
||||
See: https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428430-application?language=objc
|
||||
|
||||
@@ -589,105 +589,15 @@ Writes any unwritten DOMStorage data to disk.
|
||||
|
||||
#### `ses.setProxy(config)`
|
||||
|
||||
* `config` Object
|
||||
* `mode` string (optional) - The proxy mode. Should be one of `direct`,
|
||||
`auto_detect`, `pac_script`, `fixed_servers` or `system`. If it's
|
||||
unspecified, it will be automatically determined based on other specified
|
||||
options.
|
||||
* `direct`
|
||||
In direct mode all connections are created directly, without any proxy involved.
|
||||
* `auto_detect`
|
||||
In auto_detect mode the proxy configuration is determined by a PAC script that can
|
||||
be downloaded at http://wpad/wpad.dat.
|
||||
* `pac_script`
|
||||
In pac_script mode the proxy configuration is determined by a PAC script that is
|
||||
retrieved from the URL specified in the `pacScript`. This is the default mode
|
||||
if `pacScript` is specified.
|
||||
* `fixed_servers`
|
||||
In fixed_servers mode the proxy configuration is specified in `proxyRules`.
|
||||
This is the default mode if `proxyRules` is specified.
|
||||
* `system`
|
||||
In system mode the proxy configuration is taken from the operating system.
|
||||
Note that the system mode is different from setting no proxy configuration.
|
||||
In the latter case, Electron falls back to the system settings
|
||||
only if no command-line options influence the proxy configuration.
|
||||
* `pacScript` string (optional) - The URL associated with the PAC file.
|
||||
* `proxyRules` string (optional) - Rules indicating which proxies to use.
|
||||
* `proxyBypassRules` string (optional) - Rules indicating which URLs should
|
||||
bypass the proxy settings.
|
||||
* `config` [ProxyConfig](structures/proxy-config.md)
|
||||
|
||||
Returns `Promise<void>` - Resolves when the proxy setting process is complete.
|
||||
|
||||
Sets the proxy settings.
|
||||
|
||||
When `mode` is unspecified, `pacScript` and `proxyRules` are provided together, the `proxyRules`
|
||||
option is ignored and `pacScript` configuration is applied.
|
||||
|
||||
You may need `ses.closeAllConnections` to close currently in flight connections to prevent
|
||||
pooled sockets using previous proxy from being reused by future requests.
|
||||
|
||||
The `proxyRules` has to follow the rules below:
|
||||
|
||||
```sh
|
||||
proxyRules = schemeProxies[";"<schemeProxies>]
|
||||
schemeProxies = [<urlScheme>"="]<proxyURIList>
|
||||
urlScheme = "http" | "https" | "ftp" | "socks"
|
||||
proxyURIList = <proxyURL>[","<proxyURIList>]
|
||||
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
* `http=foopy:80;ftp=foopy2` - Use HTTP proxy `foopy:80` for `http://` URLs, and
|
||||
HTTP proxy `foopy2:80` for `ftp://` URLs.
|
||||
* `foopy:80` - Use HTTP proxy `foopy:80` for all URLs.
|
||||
* `foopy:80,bar,direct://` - Use HTTP proxy `foopy:80` for all URLs, failing
|
||||
over to `bar` if `foopy:80` is unavailable, and after that using no proxy.
|
||||
* `socks4://foopy` - Use SOCKS v4 proxy `foopy:1080` for all URLs.
|
||||
* `http=foopy,socks5://bar.com` - Use HTTP proxy `foopy` for http URLs, and fail
|
||||
over to the SOCKS5 proxy `bar.com` if `foopy` is unavailable.
|
||||
* `http=foopy,direct://` - Use HTTP proxy `foopy` for http URLs, and use no
|
||||
proxy if `foopy` is unavailable.
|
||||
* `http=foopy;socks=foopy2` - Use HTTP proxy `foopy` for http URLs, and use
|
||||
`socks4://foopy2` for all other URLs.
|
||||
|
||||
The `proxyBypassRules` is a comma separated list of rules described below:
|
||||
|
||||
* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`
|
||||
|
||||
Match all hostnames that match the pattern HOSTNAME_PATTERN.
|
||||
|
||||
Examples:
|
||||
"foobar.com", "\*foobar.com", "\*.foobar.com", "\*foobar.com:99",
|
||||
"https://x.\*.y.com:99"
|
||||
|
||||
* `"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]`
|
||||
|
||||
Match a particular domain suffix.
|
||||
|
||||
Examples:
|
||||
".google.com", ".com", "http://.google.com"
|
||||
|
||||
* `[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]`
|
||||
|
||||
Match URLs which are IP address literals.
|
||||
|
||||
Examples:
|
||||
"127.0.1", "\[0:0::1]", "\[::1]", "http://\[::1]:99"
|
||||
|
||||
* `IP_LITERAL "/" PREFIX_LENGTH_IN_BITS`
|
||||
|
||||
Match any URL that is to an IP literal that falls between the
|
||||
given range. IP range is specified using CIDR notation.
|
||||
|
||||
Examples:
|
||||
"192.168.1.1/16", "fefe:13::abc/33".
|
||||
|
||||
* `<local>`
|
||||
|
||||
Match local addresses. The meaning of `<local>` is whether the
|
||||
host matches one of: "127.0.0.1", "::1", "localhost".
|
||||
|
||||
#### `ses.resolveHost(host, [options])`
|
||||
|
||||
* `host` string - Hostname to resolve.
|
||||
@@ -785,7 +695,7 @@ Returns `Promise<void>` - Resolves when all connections are closed.
|
||||
#### `ses.fetch(input[, init])`
|
||||
|
||||
* `input` string | [GlobalRequest](https://nodejs.org/api/globals.html#request)
|
||||
* `init` [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options) & { bypassCustomProtocolHandlers?: boolean } (optional)
|
||||
* `init` [RequestInit](https://developer.mozilla.org/en-US/docs/Web/API/fetch#options) & \{ bypassCustomProtocolHandlers?: boolean \} (optional)
|
||||
|
||||
Returns `Promise<GlobalResponse>` - see [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response).
|
||||
|
||||
@@ -903,17 +813,15 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `pointerLock` - Request to directly interpret mouse movements as an input method via the [Pointer Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API). These requests always appear to originate from the main frame.
|
||||
* `keyboardLock` - Request capture of keypresses for any or all of the keys on the physical keyboard via the [Keyboard Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Keyboard/lock). These requests always appear to originate from the main frame.
|
||||
* `openExternal` - Request to open links in external applications.
|
||||
* `speaker-selection` - Request to enumerate and select audio output devices via the [speaker-selection permissions policy](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy/speaker-selection).
|
||||
* `storage-access` - Allows content loaded in a third-party context to request access to third-party cookies using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
|
||||
* `top-level-storage-access` - Allow top-level sites to request third-party cookie access on behalf of embedded content originating from another site in the same related website set using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
|
||||
* `window-management` - Request access to enumerate screens using the [`getScreenDetails`](https://developer.chrome.com/en/articles/multi-screen-window-placement/) API.
|
||||
* `unknown` - An unrecognized permission request.
|
||||
* `fileSystem` - Request access to read, write, and file management capabilities using the [File System API](https://developer.mozilla.org/en-US/docs/Web/API/File_System_API).
|
||||
* `callback` Function
|
||||
* `permissionGranted` boolean - Allow or deny the permission.
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
* `externalURL` string (optional) - The url of the `openExternal` request.
|
||||
* `securityOrigin` string (optional) - The security origin of the `media` request.
|
||||
* `mediaTypes` string[] (optional) - The types of media access being requested, elements can be `video`
|
||||
or `audio`
|
||||
* `requestingUrl` string - The last URL the requesting frame loaded
|
||||
* `isMainFrame` boolean - Whether the frame making the request is the main frame
|
||||
* `details` [PermissionRequest](structures/permission-request.md) | [FilesystemPermissionRequest](structures/filesystem-permission-request.md) | [MediaAccessPermissionRequest](structures/media-access-permission-request.md) | [OpenExternalPermissionRequest](structures/open-external-permission-request.md) - Additional information about the permission being requested.
|
||||
|
||||
Sets the handler which can be used to respond to permission requests for the `session`.
|
||||
Calling `callback(true)` will allow the permission and `callback(false)` will reject it.
|
||||
@@ -951,6 +859,8 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
|
||||
* `openExternal` - Open links in external applications.
|
||||
* `pointerLock` - Directly interpret mouse movements as an input method via the [Pointer Lock API](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API). These requests always appear to originate from the main frame.
|
||||
* `serial` - Read from and write to serial devices with the [Web Serial API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API).
|
||||
* `storage-access` - Allows content loaded in a third-party context to request access to third-party cookies using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
|
||||
* `top-level-storage-access` - Allow top-level sites to request third-party cookie access on behalf of embedded content originating from another site in the same related website set using the [Storage Access API](https://developer.mozilla.org/en-US/docs/Web/API/Storage_Access_API).
|
||||
* `usb` - Expose non-standard Universal Serial Bus (USB) compatible devices services to the web with the [WebUSB API](https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API).
|
||||
* `requestingOrigin` string - The origin URL of the permission check
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
@@ -1305,7 +1215,7 @@ Returns `Promise<Buffer>` - resolves with blob data.
|
||||
|
||||
* `url` string
|
||||
* `options` Object (optional)
|
||||
* `headers` Record<string, string> (optional) - HTTP request headers.
|
||||
* `headers` Record\<string, string\> (optional) - HTTP request headers.
|
||||
|
||||
Initiates a download of the resource at `url`.
|
||||
The API will generate a [DownloadItem](download-item.md) that can be accessed
|
||||
@@ -1513,6 +1423,37 @@ is emitted.
|
||||
Returns `string | null` - The absolute file system path where data for this
|
||||
session is persisted on disk. For in memory sessions this returns `null`.
|
||||
|
||||
#### `ses.clearData([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `dataTypes` String[] (optional) - The types of data to clear. By default, this will clear all types of data.
|
||||
* `backgroundFetch` - Background Fetch
|
||||
* `cache` - Cache
|
||||
* `cookies` - Cookies
|
||||
* `downloads` - Downloads
|
||||
* `fileSystems` - File Systems
|
||||
* `indexedDB` - IndexedDB
|
||||
* `localStorage` - Local Storage
|
||||
* `serviceWorkers` - Service Workers
|
||||
* `webSQL` - WebSQL
|
||||
* `origins` String[] (optional) - Clear data for only these origins. Cannot be used with `excludeOrigins`.
|
||||
* `excludeOrigins` String[] (optional) - Clear data for all origins except these ones. Cannot be used with `origins`.
|
||||
* `avoidClosingConnections` boolean (optional) - Skips deleting cookies that would close current network connections. (Default: `false`)
|
||||
* `originMatchingMode` String (optional) - The behavior for matching data to origins.
|
||||
* `third-parties-included` (default) - Storage is matched on origin in first-party contexts and top-level-site in third-party contexts.
|
||||
* `origin-in-all-contexts` - Storage is matched on origin only in all contexts.
|
||||
|
||||
Returns `Promise<void>` - resolves when all data has been cleared.
|
||||
|
||||
Clears various different types of data.
|
||||
|
||||
This method clears more types of data and is more thourough than the
|
||||
`clearStorageData` method.
|
||||
|
||||
**Note:** Cookies are stored at a broader scope than origins. When removing cookies and filtering by `origins` (or `excludeOrigins`), the cookies will be removed at the [registrable domain](https://url.spec.whatwg.org/#host-registrable-domain) level. For example, clearing cookies for the origin `https://really.specific.origin.example.com/` will end up clearing all cookies for `example.com`. Clearing cookies for the origin `https://my.website.example.co.uk/` will end up clearing all cookies for `example.co.uk`.
|
||||
|
||||
For more information, refer to Chromium's [`BrowsingDataRemover` interface](https://source.chromium.org/chromium/chromium/src/+/main:content/public/browser/browsing_data_remover.h).
|
||||
|
||||
### Instance Properties
|
||||
|
||||
The following properties are available on instances of `Session`:
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# FilePathWithHeaders Object
|
||||
|
||||
* `path` string - The path to the file to send.
|
||||
* `headers` Record<string, string> (optional) - Additional headers to be sent.
|
||||
* `headers` Record\<string, string\> (optional) - Additional headers to be sent.
|
||||
|
||||
5
docs/api/structures/filesystem-permission-request.md
Normal file
5
docs/api/structures/filesystem-permission-request.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# FilesystemPermissionRequest Object extends `PermissionRequest`
|
||||
|
||||
* `filePath` string (optional) - The path of the `fileSystem` request.
|
||||
* `isDirectory` boolean (optional) - Whether the `fileSystem` request is a directory.
|
||||
* `fileAccessType` string (optional) - The access type of the `fileSystem` request. Can be `writable` or `readable`.
|
||||
@@ -1,8 +0,0 @@
|
||||
# IOCounters Object
|
||||
|
||||
* `readOperationCount` number - The number of I/O read operations.
|
||||
* `writeOperationCount` number - The number of I/O write operations.
|
||||
* `otherOperationCount` number - Then number of I/O other operations.
|
||||
* `readTransferCount` number - The number of I/O read transfers.
|
||||
* `writeTransferCount` number - The number of I/O write transfers.
|
||||
* `otherTransferCount` number - Then number of I/O other transfers.
|
||||
5
docs/api/structures/media-access-permission-request.md
Normal file
5
docs/api/structures/media-access-permission-request.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# MediaAccessPermissionRequest Object extends `PermissionRequest`
|
||||
|
||||
* `securityOrigin` string (optional) - The security origin of the request.
|
||||
* `mediaTypes` string[] (optional) - The types of media access being requested - elements can be `video`
|
||||
or `audio`.
|
||||
@@ -3,5 +3,5 @@
|
||||
* `actionIdentifier` string - The identifier string of the action that the user selected.
|
||||
* `date` number - The delivery date of the notification.
|
||||
* `identifier` string - The unique identifier for this notification request.
|
||||
* `userInfo` Record<string, any> - A dictionary of custom information associated with the notification.
|
||||
* `userInfo` Record\<string, any\> - A dictionary of custom information associated with the notification.
|
||||
* `userText` string (optional) - The text entered or chosen by the user.
|
||||
|
||||
3
docs/api/structures/open-external-permission-request.md
Normal file
3
docs/api/structures/open-external-permission-request.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# OpenExternalPermissionRequest Object extends `PermissionRequest`
|
||||
|
||||
* `externalURL` string (optional) - The url of the `openExternal` request.
|
||||
4
docs/api/structures/permission-request.md
Normal file
4
docs/api/structures/permission-request.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# PermissionRequest Object
|
||||
|
||||
* `requestingUrl` string - The last URL the requesting frame loaded.
|
||||
* `isMainFrame` boolean - Whether the frame making the request is the main frame.
|
||||
@@ -4,4 +4,4 @@
|
||||
* `referrer` string
|
||||
* `method` string
|
||||
* `uploadData` [UploadData[]](upload-data.md) (optional)
|
||||
* `headers` Record<string, string>
|
||||
* `headers` Record\<string, string\>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
`"text/html"`. Setting `mimeType` would implicitly set the `content-type`
|
||||
header in response, but if `content-type` is already set in `headers`, the
|
||||
`mimeType` would be ignored.
|
||||
* `headers` Record<string, string | string[]> (optional) - An object containing the response headers. The
|
||||
* `headers` Record\<string, string | string[]\> (optional) - An object containing the response headers. The
|
||||
keys must be string, and values must be either string or Array of string.
|
||||
* `data` (Buffer | string | ReadableStream) (optional) - The response body. When
|
||||
returning stream as response, this is a Node.js readable stream representing
|
||||
|
||||
86
docs/api/structures/proxy-config.md
Normal file
86
docs/api/structures/proxy-config.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# ProxyConfig Object
|
||||
|
||||
* `mode` string (optional) - The proxy mode. Should be one of `direct`,
|
||||
`auto_detect`, `pac_script`, `fixed_servers` or `system`.
|
||||
Defaults to `pac_script` proxy mode if `pacScript` option is specified
|
||||
otherwise defaults to `fixed_servers`.
|
||||
* `direct` - In direct mode all connections are created directly, without any proxy involved.
|
||||
* `auto_detect` - In auto_detect mode the proxy configuration is determined by a PAC script that can
|
||||
be downloaded at http://wpad/wpad.dat.
|
||||
* `pac_script` - In pac_script mode the proxy configuration is determined by a PAC script that is
|
||||
retrieved from the URL specified in the `pacScript`. This is the default mode if `pacScript` is specified.
|
||||
* `fixed_servers` - In fixed_servers mode the proxy configuration is specified in `proxyRules`.
|
||||
This is the default mode if `proxyRules` is specified.
|
||||
* `system` - In system mode the proxy configuration is taken from the operating system.
|
||||
Note that the system mode is different from setting no proxy configuration.
|
||||
In the latter case, Electron falls back to the system settings only if no
|
||||
command-line options influence the proxy configuration.
|
||||
* `pacScript` string (optional) - The URL associated with the PAC file.
|
||||
* `proxyRules` string (optional) - Rules indicating which proxies to use.
|
||||
* `proxyBypassRules` string (optional) - Rules indicating which URLs should
|
||||
bypass the proxy settings.
|
||||
|
||||
When `mode` is unspecified, `pacScript` and `proxyRules` are provided together, the `proxyRules`
|
||||
option is ignored and `pacScript` configuration is applied.
|
||||
|
||||
The `proxyRules` has to follow the rules below:
|
||||
|
||||
```sh
|
||||
proxyRules = schemeProxies[";"<schemeProxies>]
|
||||
schemeProxies = [<urlScheme>"="]<proxyURIList>
|
||||
urlScheme = "http" | "https" | "ftp" | "socks"
|
||||
proxyURIList = <proxyURL>[","<proxyURIList>]
|
||||
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
|
||||
```
|
||||
|
||||
For example:
|
||||
|
||||
* `http=foopy:80;ftp=foopy2` - Use HTTP proxy `foopy:80` for `http://` URLs, and
|
||||
HTTP proxy `foopy2:80` for `ftp://` URLs.
|
||||
* `foopy:80` - Use HTTP proxy `foopy:80` for all URLs.
|
||||
* `foopy:80,bar,direct://` - Use HTTP proxy `foopy:80` for all URLs, failing
|
||||
over to `bar` if `foopy:80` is unavailable, and after that using no proxy.
|
||||
* `socks4://foopy` - Use SOCKS v4 proxy `foopy:1080` for all URLs.
|
||||
* `http=foopy,socks5://bar.com` - Use HTTP proxy `foopy` for http URLs, and fail
|
||||
over to the SOCKS5 proxy `bar.com` if `foopy` is unavailable.
|
||||
* `http=foopy,direct://` - Use HTTP proxy `foopy` for http URLs, and use no
|
||||
proxy if `foopy` is unavailable.
|
||||
* `http=foopy;socks=foopy2` - Use HTTP proxy `foopy` for http URLs, and use
|
||||
`socks4://foopy2` for all other URLs.
|
||||
|
||||
The `proxyBypassRules` is a comma separated list of rules described below:
|
||||
|
||||
* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`
|
||||
|
||||
Match all hostnames that match the pattern HOSTNAME_PATTERN.
|
||||
|
||||
Examples:
|
||||
"foobar.com", "\*foobar.com", "\*.foobar.com", "\*foobar.com:99",
|
||||
"https://x.\*.y.com:99"
|
||||
|
||||
* `"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]`
|
||||
|
||||
Match a particular domain suffix.
|
||||
|
||||
Examples:
|
||||
".google.com", ".com", "http://.google.com"
|
||||
|
||||
* `[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]`
|
||||
|
||||
Match URLs which are IP address literals.
|
||||
|
||||
Examples:
|
||||
"127.0.1", "\[0:0::1]", "\[::1]", "http://\[::1]:99"
|
||||
|
||||
* `IP_LITERAL "/" PREFIX_LENGTH_IN_BITS`
|
||||
|
||||
Match any URL that is to an IP literal that falls between the
|
||||
given range. IP range is specified using CIDR notation.
|
||||
|
||||
Examples:
|
||||
"192.168.1.1/16", "fefe:13::abc/33".
|
||||
|
||||
* `<local>`
|
||||
|
||||
Match local addresses. The meaning of `<local>` is whether the
|
||||
host matches one of: "127.0.0.1", "::1", "localhost".
|
||||
@@ -19,7 +19,7 @@
|
||||
include in the trace. If not specified, trace all processes.
|
||||
* `histogram_names` string[] (optional) - a list of [histogram][] names to report
|
||||
with the trace.
|
||||
* `memory_dump_config` Record<string, any> (optional) - if the
|
||||
* `memory_dump_config` Record\<string, any\> (optional) - if the
|
||||
`disabled-by-default-memory-infra` category is enabled, this contains
|
||||
optional additional configuration for data collection. See the [Chromium
|
||||
memory-infra docs][memory-infra docs] for more information.
|
||||
|
||||
7
docs/api/structures/window-open-handler-response.md
Normal file
7
docs/api/structures/window-open-handler-response.md
Normal file
@@ -0,0 +1,7 @@
|
||||
# WindowOpenHandlerResponse Object
|
||||
|
||||
* `action` string - Can be `allow` or `deny`. Controls whether new window should be created.
|
||||
* `overrideBrowserWindowOptions` BrowserWindowConstructorOptions (optional) - Allows customization of the created window.
|
||||
* `outlivesOpener` boolean (optional) - By default, child windows are closed when their opener is closed. This can be
|
||||
changed by specifying `outlivesOpener: true`, in which case the opened window will not be closed when its opener is closed.
|
||||
* `createWindow` (options: BrowserWindowConstructorOptions) => WebContents (optional) - If specified, will be called instead of `new BrowserWindow` to create the new child window and event [`did-create-window`](../web-contents.md#event-did-create-window) will not be emitted. Constructed child window should use passed `options` object. This can be used for example to have the new window open as a BrowserView instead of in a separate window.
|
||||
@@ -36,7 +36,7 @@ Returns `boolean` - Whether the Swipe between pages setting is on.
|
||||
### `systemPreferences.postNotification(event, userInfo[, deliverImmediately])` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `userInfo` Record<string, any>
|
||||
* `userInfo` Record\<string, any\>
|
||||
* `deliverImmediately` boolean (optional) - `true` to post notifications immediately even when the subscribing app is inactive.
|
||||
|
||||
Posts `event` as native notifications of macOS. The `userInfo` is an Object
|
||||
@@ -45,7 +45,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
### `systemPreferences.postLocalNotification(event, userInfo)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `userInfo` Record<string, any>
|
||||
* `userInfo` Record\<string, any\>
|
||||
|
||||
Posts `event` as native notifications of macOS. The `userInfo` is an Object
|
||||
that contains the user information dictionary sent along with the notification.
|
||||
@@ -53,7 +53,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
### `systemPreferences.postWorkspaceNotification(event, userInfo)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `userInfo` Record<string, any>
|
||||
* `userInfo` Record\<string, any\>
|
||||
|
||||
Posts `event` as native notifications of macOS. The `userInfo` is an Object
|
||||
that contains the user information dictionary sent along with the notification.
|
||||
@@ -63,7 +63,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
* `userInfo` Record\<string, unknown\>
|
||||
* `object` string
|
||||
|
||||
Returns `number` - The ID of this subscription
|
||||
@@ -92,7 +92,7 @@ If `event` is null, the `NSDistributedNotificationCenter` doesn’t use it as cr
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
* `userInfo` Record\<string, unknown\>
|
||||
* `object` string
|
||||
|
||||
Returns `number` - The ID of this subscription
|
||||
@@ -107,7 +107,7 @@ If `event` is null, the `NSNotificationCenter` doesn’t use it as criteria for
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
* `userInfo` Record\<string, unknown\>
|
||||
* `object` string
|
||||
|
||||
Returns `number` - The ID of this subscription
|
||||
@@ -137,7 +137,7 @@ Same as `unsubscribeNotification`, but removes the subscriber from `NSWorkspace.
|
||||
|
||||
### `systemPreferences.registerDefaults(defaults)` _macOS_
|
||||
|
||||
* `defaults` Record<string, string | boolean | number> - a dictionary of (`key: value`) user defaults
|
||||
* `defaults` Record\<string, string | boolean | number\> - a dictionary of (`key: value`) user defaults
|
||||
|
||||
Add the specified defaults to your application's `NSUserDefaults`.
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ app.whenReady().then(() => {
|
||||
|
||||
**MacOS**
|
||||
|
||||
* Icons passed to the Tray constructor should be [Template Images](native-image.md#template-image).
|
||||
* Icons passed to the Tray constructor should be [Template Images](native-image.md#template-image-macos).
|
||||
* To make sure your icon isn't grainy on retina monitors, be sure your `@2x` image is 144dpi.
|
||||
* If you are bundling your application (e.g., with webpack for development), be sure that the file names are not being mangled or hashed. The filename needs to end in Template, and the `@2x` image needs to have the same filename as the standard image, or MacOS will not magically invert your image's colors or use the high density image.
|
||||
* 16x16 (72dpi) and 32x32@2x (144dpi) work well for most icons.
|
||||
|
||||
@@ -48,6 +48,9 @@ Objects created with `new View` have the following instance methods:
|
||||
* `index` Integer (optional) - Index at which to insert the child view.
|
||||
Defaults to adding the child at the end of the child list.
|
||||
|
||||
If the same View is added to a parent which already contains it, it will be reordered such that
|
||||
it becomes the topmost view.
|
||||
|
||||
#### `view.removeChildView(view)`
|
||||
|
||||
* `view` View - Child view to remove.
|
||||
|
||||
@@ -237,7 +237,7 @@ See [`window.open()`](window-open.md) for more details and how to use this in co
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event<>
|
||||
* `details` Event\<\>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - This event does not fire for same document navigations using window.history api and reference fragment navigations.
|
||||
This property is always set to `false` for this event.
|
||||
@@ -270,7 +270,7 @@ Calling `event.preventDefault()` will prevent the navigation.
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event<>
|
||||
* `details` Event\<\>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - This event does not fire for same document navigations using window.history api and reference fragment navigations.
|
||||
This property is always set to `false` for this event.
|
||||
@@ -300,7 +300,7 @@ Calling `event.preventDefault()` will prevent the navigation.
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event<>
|
||||
* `details` Event\<\>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - Whether the navigation happened without changing
|
||||
document. Examples of same document navigations are reference fragment
|
||||
@@ -324,7 +324,7 @@ Emitted when any frame (including main) starts navigating.
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event<>
|
||||
* `details` Event\<\>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - Whether the navigation happened without changing
|
||||
document. Examples of same document navigations are reference fragment
|
||||
@@ -355,7 +355,7 @@ redirect).
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event<>
|
||||
* `details` Event\<\>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - Whether the navigation happened without changing
|
||||
document. Examples of same document navigations are reference fragment
|
||||
@@ -582,6 +582,15 @@ Returns:
|
||||
|
||||
Emitted when a link is clicked in DevTools or 'Open in new tab' is selected for a link in its context menu.
|
||||
|
||||
#### Event: 'devtools-search-query'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `query` string - text to query for.
|
||||
|
||||
Emitted when 'Search' is selected for text in its context menu.
|
||||
|
||||
#### Event: 'devtools-opened'
|
||||
|
||||
Emitted when DevTools is opened.
|
||||
@@ -674,7 +683,7 @@ Emitted when media is paused or done playing.
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event<>
|
||||
* `event` Event\<\>
|
||||
* `audible` boolean - True if one or more frames or child `webContents` are emitting audio.
|
||||
|
||||
Emitted when media becomes audible or inaudible.
|
||||
@@ -778,9 +787,6 @@ Returns:
|
||||
`input-text`, `input-time`, `input-url`, `input-week`, `output`, `reset-button`,
|
||||
`select-list`, `select-list`, `select-multiple`, `select-one`, `submit-button`,
|
||||
and `text-area`,
|
||||
* `inputFieldType` string _Deprecated_ - If the context menu was invoked on an
|
||||
input field, the type of that field. Possible values include `none`,
|
||||
`plainText`, `password`, `other`.
|
||||
* `spellcheckEnabled` boolean - If the context is editable, whether or not spellchecking is enabled.
|
||||
* `menuSourceType` string - Input source that invoked the context menu.
|
||||
Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`, `longPress`, `longTap`, `touchHandle`, `stylus`, `adjustSelection`, or `adjustSelectionReset`.
|
||||
@@ -894,7 +900,7 @@ Returns:
|
||||
* `webPreferences` [WebPreferences](structures/web-preferences.md) - The web preferences that will be used by the guest
|
||||
page. This object can be modified to adjust the preferences for the guest
|
||||
page.
|
||||
* `params` Record<string, string> - The other `<webview>` parameters such as the `src` URL.
|
||||
* `params` Record\<string, string\> - The other `<webview>` parameters such as the `src` URL.
|
||||
This object can be modified to adjust the parameters of the guest page.
|
||||
|
||||
Emitted when a `<webview>`'s web contents is being attached to this web
|
||||
@@ -1014,7 +1020,7 @@ win.webContents.loadURL('https://github.com', options)
|
||||
|
||||
* `filePath` string
|
||||
* `options` Object (optional)
|
||||
* `query` Record<string, string> (optional) - Passed to `url.format()`.
|
||||
* `query` Record\<string, string\> (optional) - Passed to `url.format()`.
|
||||
* `search` string (optional) - Passed to `url.format()`.
|
||||
* `hash` string (optional) - Passed to `url.format()`.
|
||||
|
||||
@@ -1045,7 +1051,7 @@ win.loadFile('src/index.html')
|
||||
|
||||
* `url` string
|
||||
* `options` Object (optional)
|
||||
* `headers` Record<string, string> (optional) - HTTP request headers.
|
||||
* `headers` Record\<string, string\> (optional) - HTTP request headers.
|
||||
|
||||
Initiates a download of the resource at `url` without navigating. The
|
||||
`will-download` event of `session` will be triggered.
|
||||
@@ -1282,7 +1288,7 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
|
||||
#### `contents.setWindowOpenHandler(handler)`
|
||||
|
||||
* `handler` Function<{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}>
|
||||
* `handler` Function\<[WindowOpenHandlerResponse](structures/window-open-handler-response.md)\>
|
||||
* `details` Object
|
||||
* `url` string - The _resolved_ version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
|
||||
* `frameName` string - Name of the window provided in `window.open()`
|
||||
@@ -1297,11 +1303,8 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
be set. If no post data is to be sent, the value will be `null`. Only defined
|
||||
when the window is being created by a form that set `target=_blank`.
|
||||
|
||||
Returns `{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new
|
||||
window. `allow` will allow the new window to be created. Specifying `overrideBrowserWindowOptions` allows customization of the created window.
|
||||
By default, child windows are closed when their opener is closed. This can be
|
||||
changed by specifying `outlivesOpener: true`, in which case the opened window
|
||||
will not be closed when its opener is closed.
|
||||
Returns `WindowOpenHandlerResponse` - When set to `{ action: 'deny' }` cancels the creation of the new
|
||||
window. `{ action: 'allow' }` will allow the new window to be created.
|
||||
Returning an unrecognized value such as a null, undefined, or an object
|
||||
without a recognized 'action' value will result in a console error and have
|
||||
the same effect as returning `{action: 'deny'}`.
|
||||
@@ -1312,6 +1315,26 @@ submitting a form with `<form target="_blank">`. See
|
||||
[`window.open()`](window-open.md) for more details and how to use this in
|
||||
conjunction with `did-create-window`.
|
||||
|
||||
An example showing how to customize the process of new `BrowserWindow` creation to be `BrowserView` attached to main window instead:
|
||||
|
||||
```js
|
||||
const { BrowserView, BrowserWindow } = require('electron')
|
||||
|
||||
const mainWindow = new BrowserWindow()
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
return {
|
||||
action: 'allow',
|
||||
createWindow: (options) => {
|
||||
const browserView = new BrowserView(options)
|
||||
mainWindow.addBrowserView(browserView)
|
||||
browserView.setBounds({ x: 0, y: 0, width: 640, height: 480 })
|
||||
return browserView.webContents
|
||||
}
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
#### `contents.setAudioMuted(muted)`
|
||||
|
||||
* `muted` boolean
|
||||
@@ -1560,7 +1583,7 @@ Returns `Promise<PrinterInfo[]>` - Resolves with a [`PrinterInfo[]`](structures/
|
||||
* `from` number - Index of the first page to print (0-based).
|
||||
* `to` number - Index of the last page to print (inclusive) (0-based).
|
||||
* `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
|
||||
* `dpi` Record<string, number> (optional)
|
||||
* `dpi` Record\<string, number\> (optional)
|
||||
* `horizontal` number (optional) - The horizontal dpi.
|
||||
* `vertical` number (optional) - The vertical dpi.
|
||||
* `header` string (optional) - string to be printed as page header.
|
||||
@@ -2200,6 +2223,10 @@ A `Integer` representing the unique ID of this WebContents. Each ID is unique am
|
||||
|
||||
A [`Session`](session.md) used by this webContents.
|
||||
|
||||
#### `contents.navigationHistory` _Readonly_
|
||||
|
||||
A [`NavigationHistory`](navigation-history.md) used by this webContents.
|
||||
|
||||
#### `contents.hostWebContents` _Readonly_
|
||||
|
||||
A [`WebContents`](web-contents.md) instance that might own this `WebContents`.
|
||||
|
||||
@@ -99,11 +99,11 @@ Some examples of valid `urls`:
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md) (optional)
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `requestHeaders` Record\<string, string\>
|
||||
* `callback` Function
|
||||
* `beforeSendResponse` Object
|
||||
* `cancel` boolean (optional)
|
||||
* `requestHeaders` Record<string, string | string[]> (optional) - When provided, request will be made
|
||||
* `requestHeaders` Record\<string, string | string[]\> (optional) - When provided, request will be made
|
||||
with these headers.
|
||||
|
||||
The `listener` will be called with `listener(details, callback)` before sending
|
||||
@@ -126,7 +126,7 @@ The `callback` has to be called with a `response` object.
|
||||
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `requestHeaders` Record\<string, string\>
|
||||
|
||||
The `listener` will be called with `listener(details)` just before a request is
|
||||
going to be sent to the server, modifications of previous `onBeforeSendHeaders`
|
||||
@@ -148,11 +148,11 @@ response are visible by the time this listener is fired.
|
||||
* `timestamp` Double
|
||||
* `statusLine` string
|
||||
* `statusCode` Integer
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
* `callback` Function
|
||||
* `headersReceivedResponse` Object
|
||||
* `cancel` boolean (optional)
|
||||
* `responseHeaders` Record<string, string | string[]> (optional) - When provided, the server is assumed
|
||||
* `responseHeaders` Record\<string, string | string[]\> (optional) - When provided, the server is assumed
|
||||
to have responded with these headers.
|
||||
* `statusLine` string (optional) - Should be provided when overriding
|
||||
`responseHeaders` to change header status otherwise original response
|
||||
@@ -177,7 +177,7 @@ The `callback` has to be called with a `response` object.
|
||||
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
* `fromCache` boolean - Indicates whether the response was fetched from disk
|
||||
cache.
|
||||
* `statusCode` Integer
|
||||
@@ -207,7 +207,7 @@ and response headers are available.
|
||||
* `ip` string (optional) - The server IP address that the request was
|
||||
actually sent to.
|
||||
* `fromCache` boolean
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
|
||||
The `listener` will be called with `listener(details)` when a server initiated
|
||||
redirect is about to occur.
|
||||
@@ -226,7 +226,7 @@ redirect is about to occur.
|
||||
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
* `fromCache` boolean
|
||||
* `statusCode` Integer
|
||||
* `statusLine` string
|
||||
|
||||
@@ -287,7 +287,7 @@ e.g. the `http://` or `file://`.
|
||||
|
||||
* `url` string
|
||||
* `options` Object (optional)
|
||||
* `headers` Record<string, string> (optional) - HTTP request headers.
|
||||
* `headers` Record\<string, string\> (optional) - HTTP request headers.
|
||||
|
||||
Initiates a download of the resource at `url` without navigating.
|
||||
|
||||
@@ -580,7 +580,7 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
|
||||
* `from` number - Index of the first page to print (0-based).
|
||||
* `to` number - Index of the last page to print (inclusive) (0-based).
|
||||
* `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
|
||||
* `dpi` Record<string, number> (optional)
|
||||
* `dpi` Record\<string, number\> (optional)
|
||||
* `horizontal` number (optional) - The horizontal dpi.
|
||||
* `vertical` number (optional) - The vertical dpi.
|
||||
* `header` string (optional) - string to be printed as page header.
|
||||
@@ -1048,6 +1048,15 @@ Returns:
|
||||
|
||||
Emitted when a link is clicked in DevTools or 'Open in new tab' is selected for a link in its context menu.
|
||||
|
||||
#### Event: 'devtools-search-query'
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `query` string - text to query for.
|
||||
|
||||
Emitted when 'Search' is selected for text in its context menu.
|
||||
|
||||
### Event: 'devtools-opened'
|
||||
|
||||
Emitted when DevTools is opened.
|
||||
@@ -1111,9 +1120,6 @@ Returns:
|
||||
`input-text`, `input-time`, `input-url`, `input-week`, `output`, `reset-button`,
|
||||
`select-list`, `select-list`, `select-multiple`, `select-one`, `submit-button`,
|
||||
and `text-area`,
|
||||
* `inputFieldType` string _Deprecated_ - If the context menu was invoked on an
|
||||
input field, the type of that field. Possible values include `none`,
|
||||
`plainText`, `password`, `other`.
|
||||
* `spellcheckEnabled` boolean - If the context is editable, whether or not spellchecking is enabled.
|
||||
* `menuSourceType` string - Input source that invoked the context menu.
|
||||
Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`, `longPress`, `longTap`, `touchHandle`, `stylus`, `adjustSelection`, or `adjustSelectionReset`.
|
||||
|
||||
@@ -12,6 +12,57 @@ This document uses the following convention to categorize breaking changes:
|
||||
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
|
||||
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
|
||||
|
||||
## Planned Breaking API Changes (32.0)
|
||||
|
||||
### Removed: `File.path`
|
||||
|
||||
The nonstandard `path` property of the Web `File` object was added in an early version of Electron as a convenience method for working with native files when doing everything in the renderer was more common. However, it represents a deviation from the standard and poses a minor security risk as well, so beginning in Electron 32.0 it has been removed in favor of the [`webUtils.getPathForFile`](api/web-utils.md#webutilsgetpathforfilefile) method.
|
||||
|
||||
```js
|
||||
// Before (renderer)
|
||||
|
||||
const file = document.querySelector('input[type=file]')
|
||||
alert(`Uploaded file path was: ${file.path}`)
|
||||
```
|
||||
|
||||
```js
|
||||
// After (renderer)
|
||||
|
||||
const file = document.querySelector('input[type=file]')
|
||||
electron.showFilePath(file)
|
||||
|
||||
// (preload)
|
||||
const { contextBridge, webUtils } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electron', {
|
||||
showFilePath (file) {
|
||||
// It's best not to expose the full file path to the web content if
|
||||
// possible.
|
||||
const path = webUtils.getPathForFile(file)
|
||||
alert(`Uploaded file path was: ${path}`)
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (31.0)
|
||||
|
||||
### Removed: `WebSQL` support
|
||||
|
||||
Chromium has removed support for WebSQL upstream, transitioning it to Android only. See
|
||||
[Chromium's intent to remove discussion](https://groups.google.com/a/chromium.org/g/blink-dev/c/fWYb6evVA-w/m/wGI863zaAAAJ)
|
||||
for more information.
|
||||
|
||||
### Behavior Changed: `nativeImage.toDataURL` will preseve PNG colorspace
|
||||
|
||||
PNG decoder implementation has been changed to preserve colorspace data, the
|
||||
encoded data returned from this function now matches it.
|
||||
|
||||
See [crbug.com/332584706](https://issues.chromium.org/issues/332584706) for more information.
|
||||
|
||||
### Behavior Changed: `window.flashFrame(bool)` will flash dock icon continuously on macOS
|
||||
|
||||
This brings the behavior to parity with Windows and Linux. Prior behavior: The first `flashFrame(true)` bounces the dock icon only once (using the [NSInformationalRequest](https://developer.apple.com/documentation/appkit/nsrequestuserattentiontype/nsinformationalrequest) level) and `flashFrame(false)` does nothing. New behavior: Flash continuously until `flashFrame(false)` is called. This uses the [NSCriticalRequest](https://developer.apple.com/documentation/appkit/nsrequestuserattentiontype/nscriticalrequest) level instead. To explicitly use `NSInformationalRequest` to cause a single dock icon bounce, it is still possible to use [`dock.bounce('informational')`](https://www.electronjs.org/docs/latest/api/dock#dockbouncetype-macos).
|
||||
|
||||
## Planned Breaking API Changes (30.0)
|
||||
|
||||
### Behavior Changed: cross-origin iframes now use Permission Policy to access features
|
||||
@@ -38,14 +89,24 @@ The autoresizing behavior is now standardized across all platforms.
|
||||
If your app uses `BrowserView.setAutoResize` to do anything more complex than making a BrowserView fill the entire window, it's likely you already had custom logic in place to handle this difference in behavior on macOS.
|
||||
If so, that logic will no longer be needed in Electron 30 as autoresizing behavior is consistent.
|
||||
|
||||
### Removed: `params.inputFormType` property on `context-menu` on `WebContents`
|
||||
|
||||
The `inputFormType` property of the params object in the `context-menu`
|
||||
event from `WebContents` has been removed. Use the new `formControlType`
|
||||
property instead.
|
||||
|
||||
### Removed: `process.getIOCounters()`
|
||||
|
||||
Chromium has removed access to this information.
|
||||
|
||||
## Planned Breaking API Changes (29.0)
|
||||
|
||||
### Behavior Changed: `ipcRenderer` can no longer be sent over the `contextBridge`
|
||||
|
||||
Attempting to send `ipcRenderer` as an object over the `contextBridge` will now result in
|
||||
Attempting to send the entire `ipcRenderer` module as an object over the `contextBridge` will now result in
|
||||
an empty object on the receiving side of the bridge. This change was made to remove / mitigate
|
||||
a security footgun, you should not directly expose ipcRenderer or it's methods over the bridge.
|
||||
Instead provide a safe wrapper like below:
|
||||
a security footgun. You should not directly expose ipcRenderer or its methods over the bridge.
|
||||
Instead, provide a safe wrapper like below:
|
||||
|
||||
```js
|
||||
contextBridge.exposeInMainWorld('app', {
|
||||
@@ -1676,7 +1737,7 @@ folder
|
||||
└── file3
|
||||
```
|
||||
|
||||
In Electron <=6, this would return a `FileList` with a `File` object for:
|
||||
In Electron <=6, this would return a `FileList` with a `File` object for:
|
||||
|
||||
```console
|
||||
path/to/folder
|
||||
|
||||
@@ -110,22 +110,51 @@ $ export CHROMIUM_BUILDTOOLS_PATH=`pwd`/buildtools
|
||||
On Windows:
|
||||
|
||||
```sh
|
||||
# cmd
|
||||
$ cd src
|
||||
$ set CHROMIUM_BUILDTOOLS_PATH=%cd%\buildtools
|
||||
|
||||
# PowerShell
|
||||
$ cd src
|
||||
$ $env:CHROMIUM_BUILDTOOLS_PATH = "$(Get-Location)\buildtools"
|
||||
```
|
||||
|
||||
**To generate Testing build config of Electron:**
|
||||
|
||||
On Linux & MacOS
|
||||
|
||||
```sh
|
||||
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"
|
||||
```
|
||||
|
||||
On Windows:
|
||||
|
||||
```sh
|
||||
# cmd
|
||||
$ gn gen out/Testing --args="import(\"//electron/build/args/testing.gn\")"
|
||||
|
||||
# PowerShell
|
||||
gn gen out/Testing --args="import(\`"//electron/build/args/testing.gn\`")"
|
||||
```
|
||||
|
||||
**To generate Release build config of Electron:**
|
||||
|
||||
On Linux & MacOS
|
||||
|
||||
```sh
|
||||
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\")"
|
||||
```
|
||||
|
||||
On Windows:
|
||||
|
||||
```sh
|
||||
# cmd
|
||||
$ gn gen out/Release --args="import(\"//electron/build/args/release.gn\")"
|
||||
|
||||
# PowerShell
|
||||
$ gn gen out/Release --args="import(\`"//electron/build/args/release.gn\`")"
|
||||
```
|
||||
|
||||
**Note:** This will generate a `out/Testing` or `out/Release` build directory under `src/` with the testing or release build depending upon the configuration passed above. You can replace `Testing|Release` with another names, but it should be a subdirectory of `out`.
|
||||
|
||||
Also you shouldn't have to run `gn gen` again—if you want to change the build arguments, you can run `gn args out/Testing` to bring up an editor. To see the list of available build configuration options, run `gn args out/Testing --list`.
|
||||
@@ -300,3 +329,7 @@ Error: Cannot find module '/Users/<user>/.electron_build_tools/src/e'
|
||||
```
|
||||
|
||||
We recommend installing Node through [nvm](https://github.com/nvm-sh/nvm). This allows for easier Node version management, and is often a fix for missing `e` modules.
|
||||
|
||||
### RBE authentication randomly fails with "Token not valid"
|
||||
|
||||
This could be caused by the local clock time on the machine being off by a small amount. Use [time.is](https://time.is/) to check.
|
||||
|
||||
@@ -41,7 +41,7 @@ etc.
|
||||
|
||||
* Write [remark](https://github.com/remarkjs/remark) markdown style.
|
||||
|
||||
You can run `npm run lint-docs` to ensure that your documentation changes are
|
||||
You can run `npm run lint:docs` to ensure that your documentation changes are
|
||||
formatted correctly.
|
||||
|
||||
## JavaScript
|
||||
|
||||
@@ -15,7 +15,7 @@ calls, and other compiler optimizations. The only workaround is to build an
|
||||
unoptimized local build.
|
||||
|
||||
The official symbol server URL for Electron is
|
||||
<https://symbols.electronjs.org>.
|
||||
[https://symbols.electronjs.org](https://symbols.electronjs.org).
|
||||
You cannot visit this URL directly, you must add it to the symbol path of your
|
||||
debugging tool. In the examples below, a local cache directory is used to avoid
|
||||
repeatedly fetching the PDB from the server. Replace `c:\code\symbols` with an
|
||||
|
||||
@@ -14,6 +14,5 @@
|
||||
<button id="reset-to-system">Reset to System Theme</button>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 2.3 MiB |
@@ -5,40 +5,50 @@ slug: asar-integrity
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
## Platform Support
|
||||
ASAR integrity is an experimental feature that validates the contents of your app's
|
||||
[ASAR archives](./asar-archives.md) at runtime.
|
||||
|
||||
Currently ASAR integrity checking is only supported on macOS.
|
||||
## Version support
|
||||
|
||||
## Requirements
|
||||
Currently, ASAR integrity checking is supported on:
|
||||
|
||||
### Electron Forge / Electron Packager
|
||||
* macOS as of `electron>=16.0.0`
|
||||
* Windows as of `electron>=30.0.0`
|
||||
|
||||
If you are using `>= @electron/packager`, `>= electron-packager@15.4.0` or `>= @electron-forge/core@6.0.0-beta.61` then all these requirements are met for you automatically and you can skip to [Toggling the Fuse](#toggling-the-fuse).
|
||||
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.
|
||||
|
||||
### Other build systems
|
||||
Support was introduced in `asar@3.1.0`. Note that this package has since migrated over to `@electron/asar`.
|
||||
All versions of `@electron/asar` support ASAR integrity.
|
||||
|
||||
In order to enable ASAR integrity checking you need to ensure that your `app.asar` file was generated by a version of the `asar` npm package that supports asar integrity. Support was introduced in version `3.1.0`.
|
||||
## How it works
|
||||
|
||||
Your must then populate a valid `ElectronAsarIntegrity` dictionary block in your packaged apps `Info.plist`. An example is included below.
|
||||
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
|
||||
block of `blockSize` bytes.
|
||||
|
||||
```plist
|
||||
<key>ElectronAsarIntegrity</key>
|
||||
<dict>
|
||||
<key>Resources/app.asar</key>
|
||||
<dict>
|
||||
<key>algorithm</key>
|
||||
<string>SHA256</string>
|
||||
<key>hash</key>
|
||||
<string>9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac</string>
|
||||
</dict>
|
||||
</dict>
|
||||
```json
|
||||
{
|
||||
"algorithm": "SHA256",
|
||||
"hash": "...",
|
||||
"blockSize": 1024,
|
||||
"blocks": ["...", "..."]
|
||||
}
|
||||
```
|
||||
|
||||
Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of the ASAR header using the given algorithm. The `asar` package exposes a `getRawHeader` method whose result can then be hashed to generate this value.
|
||||
Separately, you need to define a hex encoded hash of the entire ASAR header when packaging your Electron app.
|
||||
|
||||
## Toggling the Fuse
|
||||
When ASAR integrity is enabled, your Electron app will verify the header hash of the ASAR archive on runtime.
|
||||
If no hash is present or if there is a mismatch in the hashes, the app will forcefully terminate.
|
||||
|
||||
ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path.
|
||||
## Enabling ASAR integrity in the binary
|
||||
|
||||
ASAR integrity checking is currently disabled by default in Electron and can
|
||||
be enabled on build time by toggling the `EnableEmbeddedAsarIntegrityValidation`
|
||||
[Electron fuse](fuses.md).
|
||||
|
||||
When enabling this fuse, you typically also want to enable the `onlyLoadAppFromAsar` fuse.
|
||||
Otherwise, the validity checking can be bypassed via the Electron app code search path.
|
||||
|
||||
```js @ts-nocheck
|
||||
const { flipFuses, FuseVersion, FuseV1Options } = require('@electron/fuses')
|
||||
@@ -53,3 +63,71 @@ flipFuses(
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
:::tip Fuses in Electron Forge
|
||||
|
||||
With Electron Forge, you can configure your app's fuses with
|
||||
[@electron-forge/plugin-fuses](https://www.electronforge.io/config/plugins/fuses)
|
||||
in your Forge configuration file.
|
||||
|
||||
:::
|
||||
|
||||
## Providing the header hash
|
||||
|
||||
ASAR integrity validates the contents of the ASAR archive against the header hash that you provide
|
||||
on package time. The process of providing this packaged hash is different for macOS and Windows.
|
||||
|
||||
### Using Electron tooling
|
||||
|
||||
Electron Forge and Electron Packager do this setup automatically for you with no additional
|
||||
configuration. The minimum required versions for ASAR integrity are:
|
||||
|
||||
* `@electron/packager@18.3.1`
|
||||
* `@electron/forge@7.4.0`
|
||||
|
||||
### Using other build systems
|
||||
|
||||
#### macOS
|
||||
|
||||
When packaging for macOS, you must populate a valid `ElectronAsarIntegrity` dictionary block
|
||||
in your packaged app's `Info.plist`. An example is included below.
|
||||
|
||||
```xml title='Info.plist'
|
||||
<key>ElectronAsarIntegrity</key>
|
||||
<dict>
|
||||
<key>Resources/app.asar</key>
|
||||
<dict>
|
||||
<key>algorithm</key>
|
||||
<string>SHA256</string>
|
||||
<key>hash</key>
|
||||
<string>9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac</string>
|
||||
</dict>
|
||||
</dict>
|
||||
```
|
||||
|
||||
Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of the ASAR header using the given algorithm.
|
||||
The `@electron/asar` package exposes a `getRawHeader` method whose result can then be hashed to generate this value
|
||||
(e.g. using the [`node:crypto`](https://nodejs.org/api/crypto.html) module).
|
||||
|
||||
### Windows
|
||||
|
||||
When packaging for Windows, you must populate a valid [resource](https://learn.microsoft.com/en-us/windows/win32/menurc/resources)
|
||||
entry of type `Integrity` and name `ElectronAsar`. The value of this resource should be a JSON encoded dictionary
|
||||
in the form included below:
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"file": "resources\\app.asar",
|
||||
"alg": "sha256",
|
||||
"value": "9d1f61ea03c4bb62b4416387a521101b81151da0cfbe18c9f8c8b818c5cebfac"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
::: info
|
||||
|
||||
For an implementation example, see [`src/resedit.ts`](https://github.com/electron/packager/blob/main/src/resedit.ts)
|
||||
in the Electron Packager code.
|
||||
|
||||
:::
|
||||
|
||||
@@ -5,34 +5,25 @@ slug: code-signing
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
Code signing is a security technology that you use to certify that an app was
|
||||
created by you. You should sign your application so it does not trigger any
|
||||
operating system security checks.
|
||||
Code signing is a security technology to certify that an app was created by you.
|
||||
You should sign your application so it does not trigger any operating system
|
||||
security warnings.
|
||||
|
||||
On macOS, the system can detect any change to the app, whether the change is
|
||||
introduced accidentally or by malicious code.
|
||||

|
||||
|
||||
On Windows, the system assigns a trust level to your code signing certificate
|
||||
which if you don't have, or if your trust level is low, will cause security
|
||||
dialogs to appear when users start using your application. Trust level builds
|
||||
over time so it's better to start code signing as early as possible.
|
||||
|
||||
While it is possible to distribute unsigned apps, it is not recommended. Both
|
||||
Windows and macOS will, by default, prevent either the download or the execution
|
||||
of unsigned applications. Starting with macOS Catalina (version 10.15), users
|
||||
have to go through multiple manual steps to open unsigned applications.
|
||||
|
||||

|
||||
|
||||
As you can see, users get two options: Move the app straight to the trash or
|
||||
cancel running it. You don't want your users to see that dialog.
|
||||
Both Windows and macOS prevent users from running unsigned applications. It is
|
||||
possible to distribute applications without codesigning them - but in order to
|
||||
run them, users need to go through multiple advanced and manual steps to run
|
||||
them.
|
||||
|
||||
If you are building an Electron app that you intend to package and distribute,
|
||||
it should be code signed.
|
||||
it should be code signed. The Electron ecosystem tooling makes codesigning your
|
||||
apps straightforward - this documentation explains how sign your apps on both
|
||||
Windows and macOS.
|
||||
|
||||
## Signing & notarizing macOS builds
|
||||
|
||||
Properly preparing macOS applications for release requires two steps. First, the
|
||||
Preparing macOS applications for release requires two steps: First, the
|
||||
app needs to be code signed. Then, the app needs to be uploaded to Apple for a
|
||||
process called **notarization**, where automated systems will further verify that
|
||||
your app isn't doing anything to endanger its users.
|
||||
@@ -65,7 +56,9 @@ are likely using [`@electron/packager`][], which includes [`@electron/osx-sign`]
|
||||
[`@electron/notarize`][].
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that both signs
|
||||
and notarizes your application](https://electron.github.io/packager/main/interfaces/electronpackager.options.html).
|
||||
and notarizes your application](https://electron.github.io/packager/main/modules.html).
|
||||
If the example below does not meet your needs, please see [`@electron/osx-sign`][] and
|
||||
[`@electron/notarize`][] for the many possible configuration options.
|
||||
|
||||
```js @ts-nocheck
|
||||
const packager = require('@electron/packager')
|
||||
@@ -86,35 +79,81 @@ See the [Mac App Store Guide][].
|
||||
|
||||
## Signing Windows builds
|
||||
|
||||
Before signing Windows builds, you must do the following:
|
||||
Before you can code sign your application, you need to acquire a code signing
|
||||
certificate. Unlike Apple, Microsoft allows developers to purchase those
|
||||
certificates on the open market. They are usually sold by the same companies
|
||||
also offering HTTPS certificates. Prices vary, so it may be worth your time to
|
||||
shop around. Popular resellers include:
|
||||
|
||||
1. Get a Windows Authenticode code signing certificate (requires an annual fee)
|
||||
2. Install Visual Studio to get the signing utility (the free [Community
|
||||
Edition](https://visualstudio.microsoft.com/vs/community/) is enough)
|
||||
- [Certum EV code signing certificate](https://shop.certum.eu/data-safety/code-signing-certificates/certum-ev-code-sigining.html)
|
||||
- [DigiCert EV code signing certificate](https://www.digicert.com/signing/code-signing-certificates)
|
||||
- [Entrust EV code signing certificate](https://www.entrustdatacard.com/products/digital-signing-certificates/code-signing-certificates)
|
||||
- [GlobalSign EV code signing certificate](https://www.globalsign.com/en/code-signing-certificate/ev-code-signing-certificates)
|
||||
- [IdenTrust EV code signing certificate](https://www.identrust.com/digital-certificates/trustid-ev-code-signing)
|
||||
- [Sectigo (formerly Comodo) EV code signing certificate](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
- [SSL.com EV code signing certificate](https://www.ssl.com/certificates/ev-code-signing/)
|
||||
|
||||
You can get a code signing certificate from a lot of resellers. Prices vary, so
|
||||
it may be worth your time to shop around. Popular resellers include:
|
||||
It is important to call out that since June 2023, Microsoft requires software to
|
||||
be signed with an "extended validation" certificate, also called an "EV code signing
|
||||
certificate". In the past, developers could sign software with a simpler and cheaper
|
||||
certificate called "authenticode code signing certificate" or "software-based OV certificate".
|
||||
These simpler certificates no longer provide benefits: Windows will treat your app as
|
||||
completely unsigned and display the equivalent warning dialogs.
|
||||
|
||||
- [digicert](https://www.digicert.com/dc/code-signing/microsoft-authenticode.htm)
|
||||
- [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
- Amongst others, please shop around to find one that suits your needs! 😄
|
||||
The new EV certificates are required to be stored on a hardware storage module
|
||||
compliant with FIPS 140 Level 2, Common Criteria EAL 4+ or equivalent. In other words,
|
||||
the certificate cannot be simply downloaded onto a CI infrastructure. In practice,
|
||||
those storage modules look like fancy USB thumb drives.
|
||||
|
||||
:::caution Keep your certificate password private
|
||||
Your certificate password should be a **secret**. Do not share it publicly or
|
||||
commit it to your source code.
|
||||
:::
|
||||
Many certificate providers now offer "cloud-based signing" - the entire signing hardware
|
||||
is in their data center and you can use it to remotely sign code. This approach is
|
||||
popular with Electron maintainers since it makes signing your applications in CI (like
|
||||
GitHub Actions, CircleCI, etc) relatively easy.
|
||||
|
||||
At the time of writing, Electron's own apps use [DigiCert KeyLocker](https://docs.digicert.com/en/digicert-keylocker.html), but any provider that provides a command line tool for
|
||||
signing files will be compatible with Electron's tooling.
|
||||
|
||||
All tools in the Electron ecosystem use [`@electron/windows-sign`][] and typically
|
||||
expose configuration options through a `windowsSign` property. You can either use it
|
||||
to sign files directly - or use the same `windowsSign` configuration across Electron
|
||||
Forge, [`@electron/packager`][], [`electron-winstaller`][], and [`electron-wix-msi`][].
|
||||
|
||||
### Using Electron Forge
|
||||
|
||||
Electron Forge is the recommended way to sign your `Squirrel.Windows` and `WiX MSI` installers. Detailed instructions on how to configure your application can be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-macos).
|
||||
Electron Forge is the recommended way to sign your app as well as your `Squirrel.Windows`
|
||||
and `WiX MSI` installers. Detailed instructions on how to configure your application can
|
||||
be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-windows).
|
||||
|
||||
### Using Electron Packager
|
||||
|
||||
If you're not using an integrated build pipeline like Forge, you
|
||||
are likely using [`@electron/packager`][], which includes [`@electron/windows-sign`][].
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that signs
|
||||
your application](https://electron.github.io/packager/main/modules.html). If the
|
||||
example below does not meet your needs, please see [`@electron/windows-sign`][]
|
||||
for the many possible configuration options.
|
||||
|
||||
```js @ts-nocheck
|
||||
const packager = require('@electron/packager')
|
||||
|
||||
packager({
|
||||
dir: '/path/to/my/app',
|
||||
windowsSign: {
|
||||
signWithParams: '--my=custom --parameters',
|
||||
// If signtool.exe does not work for you, customize!
|
||||
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Using electron-winstaller (Squirrel.Windows)
|
||||
|
||||
[`electron-winstaller`][] is a package that can generate Squirrel.Windows installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's
|
||||
[Squirrel.Windows Maker][maker-squirrel]. If you're not using Electron Forge and want to use
|
||||
`electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration
|
||||
options when creating your installer.
|
||||
[Squirrel.Windows Maker][maker-squirrel]. Just like `@electron/packager`, it uses
|
||||
[`@electron/windows-sign`][] under the hood and supports the same `windowsSign`
|
||||
options.
|
||||
|
||||
```js {10-11} @ts-nocheck
|
||||
const electronInstaller = require('electron-winstaller')
|
||||
@@ -126,8 +165,11 @@ try {
|
||||
outputDirectory: '/tmp/build/installer64',
|
||||
authors: 'My App Inc.',
|
||||
exe: 'myapp.exe',
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret'
|
||||
windowsSign: {
|
||||
signWithParams: '--my=custom --parameters',
|
||||
// If signtool.exe does not work for you, customize!
|
||||
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
|
||||
}
|
||||
})
|
||||
console.log('It worked!')
|
||||
} catch (e) {
|
||||
@@ -141,10 +183,8 @@ For full configuration options, check out the [`electron-winstaller`][] reposito
|
||||
|
||||
[`electron-wix-msi`][] is a package that can generate MSI installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's [MSI Maker][maker-msi].
|
||||
|
||||
If you're not using Electron Forge and want to use `electron-wix-msi` directly, use the
|
||||
`certificateFile` and `certificatePassword` configuration options
|
||||
or pass in parameters directly to [SignTool.exe][] with the `signWithParams` option.
|
||||
Just like `@electron/packager`, it uses [`@electron/windows-sign`][] under the hood
|
||||
and supports the same `windowsSign` options.
|
||||
|
||||
```js {12-13} @ts-nocheck
|
||||
import { MSICreator } from 'electron-wix-msi'
|
||||
@@ -158,8 +198,11 @@ const msiCreator = new MSICreator({
|
||||
manufacturer: 'Kitten Technologies',
|
||||
version: '1.1.2',
|
||||
outputDirectory: '/path/to/output/folder',
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret'
|
||||
windowsSign: {
|
||||
signWithParams: '--my=custom --parameters',
|
||||
// If signtool.exe does not work for you, customize!
|
||||
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
|
||||
}
|
||||
})
|
||||
|
||||
// Step 2: Create a .wxs template file
|
||||
@@ -192,6 +235,7 @@ See the [Windows Store Guide][].
|
||||
[`@electron/osx-sign`]: https://github.com/electron/osx-sign
|
||||
[`@electron/packager`]: https://github.com/electron/packager
|
||||
[`@electron/notarize`]: https://github.com/electron/notarize
|
||||
[`@electron/windows-sign`]: https://github.com/electron/windows-sign
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[`electron-wix-msi`]: https://github.com/electron-userland/electron-wix-msi
|
||||
[xcode]: https://developer.apple.com/xcode
|
||||
@@ -200,4 +244,3 @@ See the [Windows Store Guide][].
|
||||
[windows store guide]: ./windows-store-guide.md
|
||||
[maker-squirrel]: https://www.electronforge.io/config/makers/squirrel.windows
|
||||
[maker-msi]: https://www.electronforge.io/config/makers/wix-msi
|
||||
[signtool.exe]: https://learn.microsoft.com/en-us/dotnet/framework/tools/signtool-exe
|
||||
|
||||
@@ -75,7 +75,6 @@ Starting with the `index.html` file:
|
||||
<button id="reset-to-system">Reset to System Theme</button>
|
||||
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
@@ -9,11 +9,12 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
|
||||
| 30.0.0 | 2024-Feb-22 | 2024-Mar-20 | 2024-Apr-16 | 2024-Oct-15 | M124 | v20.9+ | ✅ |
|
||||
| 31.0.0 | 2024-Apr-18 | 2024-May-15 | 2024-Jun-11 | 2025-Jan-07 | M126 | TBD | ✅ |
|
||||
| 30.0.0 | 2024-Feb-22 | 2024-Mar-20 | 2024-Apr-16 | 2024-Oct-15 | M124 | v20.11 | ✅ |
|
||||
| 29.0.0 | 2023-Dec-07 | 2024-Jan-24 | 2024-Feb-20 | 2024-Aug-20 | M122 | v20.9 | ✅ |
|
||||
| 28.0.0 | 2023-Oct-11 | 2023-Nov-06 | 2023-Dec-05 | 2024-Jun-11 | M120 | v18.18 | ✅ |
|
||||
| 27.0.0 | 2023-Aug-17 | 2023-Sep-13 | 2023-Oct-10 | 2024-Apr-16 | M118 | v18.17 | ✅ |
|
||||
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | 2024-Feb-20 | M116 | v18.16 | ✅ |
|
||||
| 27.0.0 | 2023-Aug-17 | 2023-Sep-13 | 2023-Oct-10 | 2024-Apr-16 | M118 | v18.17 | 🚫 |
|
||||
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-15 | 2024-Feb-20 | M116 | v18.16 | 🚫 |
|
||||
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2023-Dec-05 | M114 | v18.15 | 🚫 |
|
||||
| 24.0.0 | 2023-Feb-09 | 2023-Mar-07 | 2023-Apr-04 | 2023-Oct-10 | M112 | v18.14 | 🚫 |
|
||||
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-15 | M110 | v18.12 | 🚫 |
|
||||
|
||||
@@ -59,7 +59,7 @@ need to be called **before** the app's `ready` event is emitted.
|
||||
With top-level `await` available in Node.js ESM, make sure to `await` every Promise that you need to
|
||||
execute before the `ready` event. Otherwise, your app may be `ready` before your code executes.
|
||||
|
||||
This is particularly important to keep in mind for dynamic ESM import statmements (static imports are unaffected).
|
||||
This is particularly important to keep in mind for dynamic ESM import statements (static imports are unaffected).
|
||||
For example, if `index.mjs` calls `import('./set-up-paths.mjs')` at the top level, the app will
|
||||
likely already be `ready` by the time that dynamic import resolves.
|
||||
|
||||
@@ -78,7 +78,8 @@ JavaScript transpilers (e.g. Babel, TypeScript) have historically supported ES M
|
||||
syntax before Node.js supported ESM imports by turning these calls to CommonJS
|
||||
`require` calls.
|
||||
|
||||
<details><summary>Example: @babel/plugin-transform-modules-commonjs</summary>
|
||||
<details>
|
||||
<summary>Example: @babel/plugin-transform-modules-commonjs</summary>
|
||||
|
||||
The `@babel/plugin-transform-modules-commonjs` plugin will transform
|
||||
ESM imports down to `require` calls. The exact syntax will depend on the
|
||||
|
||||
@@ -29,7 +29,7 @@ The cookieEncryption fuse toggles whether the cookie store on disk is encrypted
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.EnableNodeOptionsEnvironmentVariable`
|
||||
|
||||
The nodeOptions fuse toggles whether the [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#node_optionsoptions) environment variable is respected or not. This environment variable can be used to pass all kinds of custom options to the Node.js runtime and isn't typically used by apps in production. Most apps can safely disable this fuse.
|
||||
The nodeOptions fuse toggles whether the [`NODE_OPTIONS`](https://nodejs.org/api/cli.html#node_optionsoptions) and [`NODE_EXTRA_CA_CERTS`](https://github.com/nodejs/node/blob/main/doc/api/cli.md#node_extra_ca_certsfile) environment variables are respected. The `NODE_OPTIONS` environment variable can be used to pass all kinds of custom options to the Node.js runtime and isn't typically used by apps in production. Most apps can safely disable this fuse.
|
||||
|
||||
### `nodeCliInspect`
|
||||
|
||||
|
||||
@@ -82,4 +82,5 @@ app.on('window-all-closed', () => {
|
||||
|
||||
After launching the Electron application, navigate to your application's
|
||||
working folder, where you'll find the rendered image.
|
||||
|
||||
[disablehardwareacceleration]: ../api/app.md#appdisablehardwareacceleration
|
||||
|
||||
@@ -112,4 +112,5 @@ For macOS, the progress bar will also be indicated for your application
|
||||
when using [Mission Control](https://support.apple.com/en-us/HT204100):
|
||||
|
||||

|
||||
|
||||
[setprogressbar]: ../api/browser-window.md#winsetprogressbarprogress-options
|
||||
|
||||
@@ -121,7 +121,7 @@ need to install Node.js themselves as a prerequisite to running your app.
|
||||
|
||||
To check which version of Node.js is running in your app, you can access the global
|
||||
[`process.versions`][] variable in the main process or preload script. You can also reference
|
||||
<https://releases.electronjs.org/releases.json>.
|
||||
[https://releases.electronjs.org/releases.json](https://releases.electronjs.org/releases.json).
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -222,7 +222,8 @@ with CommonJS module syntax:
|
||||
- [app][app], which controls your application's event lifecycle.
|
||||
- [BrowserWindow][browser-window], which creates and manages app windows.
|
||||
|
||||
<details><summary>Module capitalization conventions</summary>
|
||||
<details>
|
||||
<summary>Module capitalization conventions</summary>
|
||||
|
||||
You might have noticed the capitalization difference between the **a**pp
|
||||
and **B**rowser**W**indow modules. Electron follows typical JavaScript conventions here,
|
||||
@@ -231,10 +232,11 @@ Notification) whereas camelCase modules are not instantiable (e.g. app, ipcRende
|
||||
|
||||
</details>
|
||||
|
||||
<details><summary>Typed import aliases</summary>
|
||||
<details>
|
||||
<summary>Typed import aliases</summary>
|
||||
|
||||
For better type checking when writing TypeScript code, you can choose to import
|
||||
main process modules from <code>electron/main</code>.
|
||||
main process modules from `electron/main`.
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron/main')
|
||||
|
||||
@@ -152,7 +152,7 @@ command that can handle the version bumping and tagging for you.
|
||||
#### Bonus: Publishing in GitHub Actions
|
||||
|
||||
Publishing locally can be painful, especially because you can only create distributables
|
||||
for your host operating system (i.e. you can't publish a Window `.exe` file from macOS).
|
||||
for your host operating system (i.e. you can't publish a Windows `.exe` file from macOS).
|
||||
|
||||
A solution for this would be to publish your app via automation workflows
|
||||
such as [GitHub Actions][], which can run tasks in the
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
If you want to embed (third-party) web content in an Electron `BrowserWindow`,
|
||||
there are three options available to you: `<iframe>` tags, `<webview>` tags,
|
||||
and `BrowserViews`. Each one offers slightly different functionality and is
|
||||
and `WebContentsView`. Each one offers slightly different functionality and is
|
||||
useful in different situations. To help you choose between these, this guide
|
||||
explains the differences and capabilities of each option.
|
||||
|
||||
|
||||
@@ -77,6 +77,7 @@ template("electron_extra_paks") {
|
||||
"//content:content_resources",
|
||||
"//content/browser/resources/gpu:resources",
|
||||
"//content/browser/resources/media:resources",
|
||||
"//content/browser/resources/process:resources",
|
||||
"//content/browser/tracing:resources",
|
||||
"//content/browser/webrtc/resources",
|
||||
"//electron:resources",
|
||||
@@ -96,6 +97,7 @@ template("electron_extra_paks") {
|
||||
# New paks should be added here by default.
|
||||
sources += [
|
||||
"$root_gen_dir/content/browser/devtools/devtools_resources.pak",
|
||||
"$root_gen_dir/content/process_resources.pak",
|
||||
"$root_gen_dir/ui/resources/webui_resources.pak",
|
||||
]
|
||||
deps += [ "//content/browser/devtools:devtools_resources" ]
|
||||
|
||||
@@ -22,7 +22,6 @@ auto_filenames = {
|
||||
"docs/api/download-item.md",
|
||||
"docs/api/environment-variables.md",
|
||||
"docs/api/extensions.md",
|
||||
"docs/api/file-object.md",
|
||||
"docs/api/global-shortcut.md",
|
||||
"docs/api/in-app-purchase.md",
|
||||
"docs/api/incoming-message.md",
|
||||
@@ -34,6 +33,7 @@ auto_filenames = {
|
||||
"docs/api/message-port-main.md",
|
||||
"docs/api/native-image.md",
|
||||
"docs/api/native-theme.md",
|
||||
"docs/api/navigation-history.md",
|
||||
"docs/api/net-log.md",
|
||||
"docs/api/net.md",
|
||||
"docs/api/notification.md",
|
||||
@@ -88,10 +88,10 @@ auto_filenames = {
|
||||
"docs/api/structures/extension.md",
|
||||
"docs/api/structures/file-filter.md",
|
||||
"docs/api/structures/file-path-with-headers.md",
|
||||
"docs/api/structures/filesystem-permission-request.md",
|
||||
"docs/api/structures/gpu-feature-status.md",
|
||||
"docs/api/structures/hid-device.md",
|
||||
"docs/api/structures/input-event.md",
|
||||
"docs/api/structures/io-counters.md",
|
||||
"docs/api/structures/ipc-main-event.md",
|
||||
"docs/api/structures/ipc-main-invoke-event.md",
|
||||
"docs/api/structures/ipc-renderer-event.md",
|
||||
@@ -99,6 +99,7 @@ auto_filenames = {
|
||||
"docs/api/structures/jump-list-item.md",
|
||||
"docs/api/structures/keyboard-event.md",
|
||||
"docs/api/structures/keyboard-input-event.md",
|
||||
"docs/api/structures/media-access-permission-request.md",
|
||||
"docs/api/structures/memory-info.md",
|
||||
"docs/api/structures/memory-usage-details.md",
|
||||
"docs/api/structures/mime-typed-buffer.md",
|
||||
@@ -106,7 +107,9 @@ auto_filenames = {
|
||||
"docs/api/structures/mouse-wheel-input-event.md",
|
||||
"docs/api/structures/notification-action.md",
|
||||
"docs/api/structures/notification-response.md",
|
||||
"docs/api/structures/open-external-permission-request.md",
|
||||
"docs/api/structures/payment-discount.md",
|
||||
"docs/api/structures/permission-request.md",
|
||||
"docs/api/structures/point.md",
|
||||
"docs/api/structures/post-body.md",
|
||||
"docs/api/structures/printer-info.md",
|
||||
@@ -118,6 +121,7 @@ auto_filenames = {
|
||||
"docs/api/structures/protocol-request.md",
|
||||
"docs/api/structures/protocol-response-upload-data.md",
|
||||
"docs/api/structures/protocol-response.md",
|
||||
"docs/api/structures/proxy-config.md",
|
||||
"docs/api/structures/rectangle.md",
|
||||
"docs/api/structures/referrer.md",
|
||||
"docs/api/structures/render-process-gone-details.md",
|
||||
@@ -144,6 +148,7 @@ auto_filenames = {
|
||||
"docs/api/structures/web-preferences.md",
|
||||
"docs/api/structures/web-request-filter.md",
|
||||
"docs/api/structures/web-source.md",
|
||||
"docs/api/structures/window-open-handler-response.md",
|
||||
]
|
||||
|
||||
sandbox_bundle_deps = [
|
||||
|
||||
@@ -34,7 +34,7 @@ filenames = {
|
||||
"shell/browser/notifications/linux/notification_presenter_linux.h",
|
||||
"shell/browser/relauncher_linux.cc",
|
||||
"shell/browser/ui/electron_desktop_window_tree_host_linux.cc",
|
||||
"shell/browser/ui/file_dialog_gtk.cc",
|
||||
"shell/browser/ui/file_dialog_linux.cc",
|
||||
"shell/browser/ui/gtk/menu_gtk.cc",
|
||||
"shell/browser/ui/gtk/menu_gtk.h",
|
||||
"shell/browser/ui/gtk/menu_util.cc",
|
||||
@@ -155,12 +155,8 @@ filenames = {
|
||||
"shell/browser/osr/osr_web_contents_view_mac.mm",
|
||||
"shell/browser/relauncher_mac.cc",
|
||||
"shell/browser/ui/certificate_trust_mac.mm",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.h",
|
||||
"shell/browser/ui/cocoa/delayed_native_view_host.mm",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.h",
|
||||
"shell/browser/ui/cocoa/electron_bundle_mover.mm",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.h",
|
||||
"shell/browser/ui/cocoa/electron_inspectable_web_contents_view.mm",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.h",
|
||||
"shell/browser/ui/cocoa/electron_menu_controller.mm",
|
||||
"shell/browser/ui/cocoa/electron_native_widget_mac.h",
|
||||
@@ -187,8 +183,6 @@ filenames = {
|
||||
"shell/browser/ui/cocoa/window_buttons_proxy.mm",
|
||||
"shell/browser/ui/drag_util_mac.mm",
|
||||
"shell/browser/ui/file_dialog_mac.mm",
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.h",
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.mm",
|
||||
"shell/browser/ui/message_box_mac.mm",
|
||||
"shell/browser/ui/tray_icon_cocoa.h",
|
||||
"shell/browser/ui/tray_icon_cocoa.mm",
|
||||
@@ -204,6 +198,7 @@ filenames = {
|
||||
"shell/common/node_bindings_mac.cc",
|
||||
"shell/common/node_bindings_mac.h",
|
||||
"shell/common/platform_util_mac.mm",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_mac.mm",
|
||||
]
|
||||
|
||||
lib_sources_views = [
|
||||
@@ -218,8 +213,6 @@ filenames = {
|
||||
"shell/browser/ui/views/electron_views_delegate.h",
|
||||
"shell/browser/ui/views/frameless_view.cc",
|
||||
"shell/browser/ui/views/frameless_view.h",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.cc",
|
||||
"shell/browser/ui/views/inspectable_web_contents_view_views.h",
|
||||
"shell/browser/ui/views/menu_bar.cc",
|
||||
"shell/browser/ui/views/menu_bar.h",
|
||||
"shell/browser/ui/views/menu_delegate.cc",
|
||||
@@ -383,9 +376,14 @@ filenames = {
|
||||
"shell/browser/extended_web_contents_observer.h",
|
||||
"shell/browser/feature_list.cc",
|
||||
"shell/browser/feature_list.h",
|
||||
"shell/browser/feature_list_mac.mm",
|
||||
"shell/browser/file_select_helper.cc",
|
||||
"shell/browser/file_select_helper.h",
|
||||
"shell/browser/file_select_helper_mac.mm",
|
||||
"shell/browser/file_system_access/file_system_access_permission_context.cc",
|
||||
"shell/browser/file_system_access/file_system_access_permission_context.h",
|
||||
"shell/browser/file_system_access/file_system_access_permission_context_factory.cc",
|
||||
"shell/browser/file_system_access/file_system_access_permission_context_factory.h",
|
||||
"shell/browser/font_defaults.cc",
|
||||
"shell/browser/font_defaults.h",
|
||||
"shell/browser/hid/electron_hid_delegate.cc",
|
||||
@@ -589,6 +587,8 @@ filenames = {
|
||||
"shell/common/gin_converters/hid_device_info_converter.h",
|
||||
"shell/common/gin_converters/image_converter.cc",
|
||||
"shell/common/gin_converters/image_converter.h",
|
||||
"shell/common/gin_converters/login_item_settings_converter.cc",
|
||||
"shell/common/gin_converters/login_item_settings_converter.h",
|
||||
"shell/common/gin_converters/media_converter.cc",
|
||||
"shell/common/gin_converters/media_converter.h",
|
||||
"shell/common/gin_converters/message_box_converter.cc",
|
||||
@@ -757,8 +757,8 @@ filenames = {
|
||||
"shell/common/extensions/electron_extensions_client.h",
|
||||
"shell/common/gin_converters/extension_converter.cc",
|
||||
"shell/common/gin_converters/extension_converter.h",
|
||||
"shell/renderer/extensions/electron_extensions_dispatcher_delegate.cc",
|
||||
"shell/renderer/extensions/electron_extensions_dispatcher_delegate.h",
|
||||
"shell/renderer/extensions/electron_extensions_renderer_api_provider.cc",
|
||||
"shell/renderer/extensions/electron_extensions_renderer_api_provider.h",
|
||||
"shell/renderer/extensions/electron_extensions_renderer_client.cc",
|
||||
"shell/renderer/extensions/electron_extensions_renderer_client.h",
|
||||
]
|
||||
|
||||
@@ -111,6 +111,7 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_binary_search.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_clamp.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_contains.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_contains_subrange.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_copy.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_copy_backward.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_copy_if.h",
|
||||
@@ -217,6 +218,7 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__algorithm/shift_right.h",
|
||||
"//third_party/libc++/src/include/__algorithm/shuffle.h",
|
||||
"//third_party/libc++/src/include/__algorithm/sift_down.h",
|
||||
"//third_party/libc++/src/include/__algorithm/simd_utils.h",
|
||||
"//third_party/libc++/src/include/__algorithm/sort.h",
|
||||
"//third_party/libc++/src/include/__algorithm/sort_heap.h",
|
||||
"//third_party/libc++/src/include/__algorithm/stable_partition.h",
|
||||
@@ -291,6 +293,8 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__chrono/steady_clock.h",
|
||||
"//third_party/libc++/src/include/__chrono/system_clock.h",
|
||||
"//third_party/libc++/src/include/__chrono/time_point.h",
|
||||
"//third_party/libc++/src/include/__chrono/time_zone.h",
|
||||
"//third_party/libc++/src/include/__chrono/time_zone_link.h",
|
||||
"//third_party/libc++/src/include/__chrono/tzdb.h",
|
||||
"//third_party/libc++/src/include/__chrono/tzdb_list.h",
|
||||
"//third_party/libc++/src/include/__chrono/weekday.h",
|
||||
@@ -379,7 +383,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__format/format_context.h",
|
||||
"//third_party/libc++/src/include/__format/format_error.h",
|
||||
"//third_party/libc++/src/include/__format/format_functions.h",
|
||||
"//third_party/libc++/src/include/__format/format_fwd.h",
|
||||
"//third_party/libc++/src/include/__format/format_parse_context.h",
|
||||
"//third_party/libc++/src/include/__format/format_string.h",
|
||||
"//third_party/libc++/src/include/__format/format_to_n_result.h",
|
||||
@@ -428,22 +431,28 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__functional/weak_result_type.h",
|
||||
"//third_party/libc++/src/include/__fwd/array.h",
|
||||
"//third_party/libc++/src/include/__fwd/bit_reference.h",
|
||||
"//third_party/libc++/src/include/__fwd/complex.h",
|
||||
"//third_party/libc++/src/include/__fwd/deque.h",
|
||||
"//third_party/libc++/src/include/__fwd/format.h",
|
||||
"//third_party/libc++/src/include/__fwd/fstream.h",
|
||||
"//third_party/libc++/src/include/__fwd/get.h",
|
||||
"//third_party/libc++/src/include/__fwd/hash.h",
|
||||
"//third_party/libc++/src/include/__fwd/functional.h",
|
||||
"//third_party/libc++/src/include/__fwd/ios.h",
|
||||
"//third_party/libc++/src/include/__fwd/istream.h",
|
||||
"//third_party/libc++/src/include/__fwd/mdspan.h",
|
||||
"//third_party/libc++/src/include/__fwd/memory.h",
|
||||
"//third_party/libc++/src/include/__fwd/memory_resource.h",
|
||||
"//third_party/libc++/src/include/__fwd/ostream.h",
|
||||
"//third_party/libc++/src/include/__fwd/pair.h",
|
||||
"//third_party/libc++/src/include/__fwd/queue.h",
|
||||
"//third_party/libc++/src/include/__fwd/span.h",
|
||||
"//third_party/libc++/src/include/__fwd/sstream.h",
|
||||
"//third_party/libc++/src/include/__fwd/stack.h",
|
||||
"//third_party/libc++/src/include/__fwd/streambuf.h",
|
||||
"//third_party/libc++/src/include/__fwd/string.h",
|
||||
"//third_party/libc++/src/include/__fwd/string_view.h",
|
||||
"//third_party/libc++/src/include/__fwd/subrange.h",
|
||||
"//third_party/libc++/src/include/__fwd/tuple.h",
|
||||
"//third_party/libc++/src/include/__fwd/vector.h",
|
||||
"//third_party/libc++/src/include/__hash_table",
|
||||
"//third_party/libc++/src/include/__ios/fpos.h",
|
||||
"//third_party/libc++/src/include/__iterator/access.h",
|
||||
@@ -700,6 +709,7 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__thread/thread.h",
|
||||
"//third_party/libc++/src/include/__thread/timed_backoff_policy.h",
|
||||
"//third_party/libc++/src/include/__tree",
|
||||
"//third_party/libc++/src/include/__tuple/find_index.h",
|
||||
"//third_party/libc++/src/include/__tuple/make_tuple_types.h",
|
||||
"//third_party/libc++/src/include/__tuple/pair_like.h",
|
||||
"//third_party/libc++/src/include/__tuple/sfinae_helpers.h",
|
||||
@@ -753,10 +763,7 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__type_traits/is_constant_evaluated.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_convertible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_copy_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_copy_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_core_convertible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_default_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_destructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_empty.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_enum.h",
|
||||
@@ -772,17 +779,10 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__type_traits/is_member_function_pointer.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_member_object_pointer.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_member_pointer.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_move_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_move_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_convertible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_copy_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_copy_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_default_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_destructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_move_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_nothrow_move_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_null_pointer.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_object.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_pod.h",
|
||||
@@ -803,14 +803,9 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivial.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_copy_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_copy_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_copyable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_default_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_destructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_lexicographically_comparable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_move_assignable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_move_constructible.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_trivially_relocatable.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_unbounded_array.h",
|
||||
"//third_party/libc++/src/include/__type_traits/is_union.h",
|
||||
@@ -967,7 +962,7 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/mdspan",
|
||||
"//third_party/libc++/src/include/memory",
|
||||
"//third_party/libc++/src/include/memory_resource",
|
||||
"//third_party/libc++/src/include/module.modulemap.in",
|
||||
"//third_party/libc++/src/include/module.modulemap",
|
||||
"//third_party/libc++/src/include/mutex",
|
||||
"//third_party/libc++/src/include/new",
|
||||
"//third_party/libc++/src/include/numbers",
|
||||
|
||||
@@ -34,13 +34,17 @@ export default class BrowserView {
|
||||
}
|
||||
|
||||
setAutoResize (options: AutoResizeOptions) {
|
||||
if (options == null || typeof options !== 'object') { throw new Error('Invalid auto resize options'); }
|
||||
if (options == null || typeof options !== 'object') {
|
||||
throw new Error('Invalid auto resize options');
|
||||
}
|
||||
|
||||
this.#autoResizeFlags = {
|
||||
width: !!options.width,
|
||||
height: !!options.height,
|
||||
horizontal: !!options.horizontal,
|
||||
vertical: !!options.vertical
|
||||
};
|
||||
|
||||
this.#autoHorizontalProportion = null;
|
||||
this.#autoVerticalProportion = null;
|
||||
}
|
||||
@@ -71,7 +75,10 @@ export default class BrowserView {
|
||||
#autoHorizontalProportion: {width: number, left: number} | null = null;
|
||||
#autoVerticalProportion: {height: number, top: number} | null = null;
|
||||
#autoResize () {
|
||||
if (!this.ownerWindow) throw new Error('Electron bug: #autoResize called without owner window');
|
||||
if (!this.ownerWindow) {
|
||||
throw new Error('Electron bug: #autoResize called without owner window');
|
||||
};
|
||||
|
||||
if (this.#autoResizeFlags.horizontal && this.#autoHorizontalProportion == null) {
|
||||
const viewBounds = this.#webContentsView.getBounds();
|
||||
this.#autoHorizontalProportion = {
|
||||
@@ -79,6 +86,7 @@ export default class BrowserView {
|
||||
left: this.#lastWindowSize.width / viewBounds.x
|
||||
};
|
||||
}
|
||||
|
||||
if (this.#autoResizeFlags.vertical && this.#autoVerticalProportion == null) {
|
||||
const viewBounds = this.#webContentsView.getBounds();
|
||||
this.#autoVerticalProportion = {
|
||||
@@ -86,6 +94,7 @@ export default class BrowserView {
|
||||
top: this.#lastWindowSize.height / viewBounds.y
|
||||
};
|
||||
}
|
||||
|
||||
const newBounds = this.ownerWindow.getBounds();
|
||||
let widthDelta = newBounds.width - this.#lastWindowSize.width;
|
||||
let heightDelta = newBounds.height - this.#lastWindowSize.height;
|
||||
@@ -105,10 +114,12 @@ export default class BrowserView {
|
||||
newViewBounds.width = newBounds.width / this.#autoHorizontalProportion.width;
|
||||
newViewBounds.x = newBounds.width / this.#autoHorizontalProportion.left;
|
||||
}
|
||||
|
||||
if (this.#autoVerticalProportion) {
|
||||
newViewBounds.height = newBounds.height / this.#autoVerticalProportion.height;
|
||||
newViewBounds.y = newBounds.y / this.#autoVerticalProportion.top;
|
||||
}
|
||||
|
||||
if (this.#autoHorizontalProportion || this.#autoVerticalProportion) {
|
||||
this.#webContentsView.setBounds(newViewBounds);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,29 @@ BrowserWindow.prototype._init = function (this: BWT) {
|
||||
app.emit('browser-window-focus', event, this);
|
||||
});
|
||||
|
||||
let unresponsiveEvent: NodeJS.Timeout | null = null;
|
||||
const emitUnresponsiveEvent = () => {
|
||||
unresponsiveEvent = null;
|
||||
if (!this.isDestroyed() && this.isEnabled()) { this.emit('unresponsive'); }
|
||||
};
|
||||
this.webContents.on('unresponsive', () => {
|
||||
if (!unresponsiveEvent) { unresponsiveEvent = setTimeout(emitUnresponsiveEvent, 50); }
|
||||
});
|
||||
this.webContents.on('responsive', () => {
|
||||
if (unresponsiveEvent) {
|
||||
clearTimeout(unresponsiveEvent);
|
||||
unresponsiveEvent = null;
|
||||
}
|
||||
this.emit('responsive');
|
||||
});
|
||||
this.on('close', () => {
|
||||
if (!unresponsiveEvent) { unresponsiveEvent = setTimeout(emitUnresponsiveEvent, 5000); }
|
||||
});
|
||||
this.webContents.on('destroyed', () => {
|
||||
if (unresponsiveEvent) clearTimeout(unresponsiveEvent);
|
||||
unresponsiveEvent = null;
|
||||
});
|
||||
|
||||
// Subscribe to visibilityState changes and pass to renderer process.
|
||||
let isVisible = this.isVisible() && !this.isMinimized();
|
||||
const visibilityChanged = () => {
|
||||
|
||||
@@ -18,7 +18,7 @@ function makeStreamFromPipe (pipe: any): ReadableStream {
|
||||
try {
|
||||
const rv = await pipe.read(buf);
|
||||
if (rv > 0) {
|
||||
controller.enqueue(buf.subarray(0, rv));
|
||||
controller.enqueue(buf.slice(0, rv));
|
||||
} else {
|
||||
controller.close();
|
||||
}
|
||||
|
||||
@@ -263,13 +263,11 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
|
||||
// TODO(codebytere): deduplicate argument sanitization by moving rest of
|
||||
// print param logic into new file shared between printToPDF and print
|
||||
WebContents.prototype.print = function (options: ElectronInternal.WebContentsPrintOptions, callback) {
|
||||
if (typeof options !== 'object') {
|
||||
WebContents.prototype.print = function (options: ElectronInternal.WebContentsPrintOptions = {}, callback) {
|
||||
if (typeof options !== 'object' || options == null) {
|
||||
throw new TypeError('webContents.print(): Invalid print settings specified.');
|
||||
}
|
||||
|
||||
const printSettings: Record<string, any> = { ...options };
|
||||
|
||||
const pageSize = options.pageSize ?? 'A4';
|
||||
if (typeof pageSize === 'object') {
|
||||
if (!pageSize.height || !pageSize.width) {
|
||||
@@ -283,7 +281,7 @@ WebContents.prototype.print = function (options: ElectronInternal.WebContentsPri
|
||||
throw new RangeError('height and width properties must be minimum 352 microns.');
|
||||
}
|
||||
|
||||
printSettings.mediaSize = {
|
||||
options.mediaSize = {
|
||||
name: 'CUSTOM',
|
||||
custom_display_name: 'Custom',
|
||||
height_microns: height,
|
||||
@@ -295,7 +293,7 @@ WebContents.prototype.print = function (options: ElectronInternal.WebContentsPri
|
||||
};
|
||||
} else if (typeof pageSize === 'string' && PDFPageSizes[pageSize]) {
|
||||
const mediaSize = PDFPageSizes[pageSize];
|
||||
printSettings.mediaSize = {
|
||||
options.mediaSize = {
|
||||
...mediaSize,
|
||||
imageable_area_left_microns: 0,
|
||||
imageable_area_bottom_microns: 0,
|
||||
@@ -308,9 +306,9 @@ WebContents.prototype.print = function (options: ElectronInternal.WebContentsPri
|
||||
|
||||
if (this._print) {
|
||||
if (callback) {
|
||||
this._print(printSettings, callback);
|
||||
this._print(options, callback);
|
||||
} else {
|
||||
this._print(printSettings);
|
||||
this._print(options);
|
||||
}
|
||||
} else {
|
||||
console.error('Error: Printing feature is disabled.');
|
||||
@@ -435,14 +433,15 @@ WebContents.prototype.loadURL = function (url, options) {
|
||||
return p;
|
||||
};
|
||||
|
||||
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => ({action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions, outlivesOpener?: boolean})) {
|
||||
WebContents.prototype.setWindowOpenHandler = function (handler: (details: Electron.HandlerDetails) => Electron.WindowOpenHandlerResponse) {
|
||||
this._windowOpenHandler = handler;
|
||||
};
|
||||
|
||||
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, outlivesOpener: boolean} {
|
||||
WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event, details: Electron.HandlerDetails): {browserWindowConstructorOptions: BrowserWindowConstructorOptions | null, outlivesOpener: boolean, createWindow?: Electron.CreateWindowFunction} {
|
||||
const defaultResponse = {
|
||||
browserWindowConstructorOptions: null,
|
||||
outlivesOpener: false
|
||||
outlivesOpener: false,
|
||||
createWindow: undefined
|
||||
};
|
||||
if (!this._windowOpenHandler) {
|
||||
return defaultResponse;
|
||||
@@ -468,7 +467,8 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event,
|
||||
} else if (response.action === 'allow') {
|
||||
return {
|
||||
browserWindowConstructorOptions: typeof response.overrideBrowserWindowOptions === 'object' ? response.overrideBrowserWindowOptions : null,
|
||||
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false
|
||||
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false,
|
||||
createWindow: typeof response.createWindow === 'function' ? response.createWindow : undefined
|
||||
};
|
||||
} else {
|
||||
event.preventDefault();
|
||||
@@ -533,6 +533,18 @@ WebContents.prototype._init = function () {
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
// Add navigationHistory property which handles session history,
|
||||
// maintaining a list of navigation entries for backward and forward navigation.
|
||||
Object.defineProperty(this, 'navigationHistory', {
|
||||
value: {
|
||||
getActiveIndex: this._getActiveIndex.bind(this),
|
||||
length: this._historyLength.bind(this),
|
||||
getEntryAtIndex: this._getNavigationEntryAtIndex.bind(this)
|
||||
},
|
||||
writable: false,
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
// Dispatch IPC messages to the ipc module.
|
||||
this.on('-ipc-message' as any, function (this: Electron.WebContents, event: Electron.IpcMainEvent, internal: boolean, channel: string, args: any[]) {
|
||||
addSenderToEvent(event, this);
|
||||
@@ -655,13 +667,16 @@ WebContents.prototype._init = function () {
|
||||
postData,
|
||||
overrideBrowserWindowOptions: options || {},
|
||||
windowOpenArgs: details,
|
||||
outlivesOpener: result.outlivesOpener
|
||||
outlivesOpener: result.outlivesOpener,
|
||||
createWindow: result.createWindow
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let windowOpenOverriddenOptions: BrowserWindowConstructorOptions | null = null;
|
||||
let windowOpenOutlivesOpenerOption: boolean = false;
|
||||
let createWindow: Electron.CreateWindowFunction | undefined;
|
||||
|
||||
this.on('-will-add-new-contents' as any, (event: Electron.Event, url: string, frameName: string, rawFeatures: string, disposition: Electron.HandlerDetails['disposition'], referrer: Electron.Referrer, postData: PostData) => {
|
||||
const postBody = postData ? {
|
||||
data: postData,
|
||||
@@ -686,6 +701,7 @@ WebContents.prototype._init = function () {
|
||||
|
||||
windowOpenOutlivesOpenerOption = result.outlivesOpener;
|
||||
windowOpenOverriddenOptions = result.browserWindowConstructorOptions;
|
||||
createWindow = result.createWindow;
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
@@ -715,6 +731,9 @@ WebContents.prototype._init = function () {
|
||||
referrer: Electron.Referrer, rawFeatures: string, postData: PostData) => {
|
||||
const overriddenOptions = windowOpenOverriddenOptions || undefined;
|
||||
const outlivesOpener = windowOpenOutlivesOpenerOption;
|
||||
const windowOpenFunction = createWindow;
|
||||
|
||||
createWindow = undefined;
|
||||
windowOpenOverriddenOptions = null;
|
||||
// false is the default
|
||||
windowOpenOutlivesOpenerOption = false;
|
||||
@@ -737,7 +756,8 @@ WebContents.prototype._init = function () {
|
||||
frameName,
|
||||
features: rawFeatures
|
||||
},
|
||||
outlivesOpener
|
||||
outlivesOpener,
|
||||
createWindow: windowOpenFunction
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -16,16 +16,16 @@ export type WindowOpenArgs = {
|
||||
features: string,
|
||||
}
|
||||
|
||||
const frameNamesToWindow = new Map<string, BrowserWindow>();
|
||||
const registerFrameNameToGuestWindow = (name: string, win: BrowserWindow) => frameNamesToWindow.set(name, win);
|
||||
const frameNamesToWindow = new Map<string, WebContents>();
|
||||
const registerFrameNameToGuestWindow = (name: string, webContents: WebContents) => frameNamesToWindow.set(name, webContents);
|
||||
const unregisterFrameName = (name: string) => frameNamesToWindow.delete(name);
|
||||
const getGuestWindowByFrameName = (name: string) => frameNamesToWindow.get(name);
|
||||
const getGuestWebContentsByFrameName = (name: string) => frameNamesToWindow.get(name);
|
||||
|
||||
/**
|
||||
* `openGuestWindow` is called to create and setup event handling for the new
|
||||
* window.
|
||||
*/
|
||||
export function openGuestWindow ({ embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener }: {
|
||||
export function openGuestWindow ({ embedder, guest, referrer, disposition, postData, overrideBrowserWindowOptions, windowOpenArgs, outlivesOpener, createWindow }: {
|
||||
embedder: WebContents,
|
||||
guest?: WebContents,
|
||||
referrer: Referrer,
|
||||
@@ -34,7 +34,8 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
|
||||
overrideBrowserWindowOptions?: BrowserWindowConstructorOptions,
|
||||
windowOpenArgs: WindowOpenArgs,
|
||||
outlivesOpener: boolean,
|
||||
}): BrowserWindow | undefined {
|
||||
createWindow?: Electron.CreateWindowFunction
|
||||
}): void {
|
||||
const { url, frameName, features } = windowOpenArgs;
|
||||
const { options: parsedOptions } = parseFeatures(features);
|
||||
const browserWindowOptions = {
|
||||
@@ -48,17 +49,42 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
|
||||
// To spec, subsequent window.open calls with the same frame name (`target` in
|
||||
// spec parlance) will reuse the previous window.
|
||||
// https://html.spec.whatwg.org/multipage/window-object.html#apis-for-creating-and-navigating-browsing-contexts-by-name
|
||||
const existingWindow = getGuestWindowByFrameName(frameName);
|
||||
if (existingWindow) {
|
||||
if (existingWindow.isDestroyed() || existingWindow.webContents.isDestroyed()) {
|
||||
const existingWebContents = getGuestWebContentsByFrameName(frameName);
|
||||
if (existingWebContents) {
|
||||
if (existingWebContents.isDestroyed()) {
|
||||
// FIXME(t57ser): The webContents is destroyed for some reason, unregister the frame name
|
||||
unregisterFrameName(frameName);
|
||||
} else {
|
||||
existingWindow.loadURL(url);
|
||||
return existingWindow;
|
||||
existingWebContents.loadURL(url);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (createWindow) {
|
||||
const webContents = createWindow({
|
||||
webContents: guest,
|
||||
...browserWindowOptions
|
||||
});
|
||||
|
||||
if (guest != null) {
|
||||
if (webContents !== guest) {
|
||||
throw new Error('Invalid webContents. Created window should be connected to webContents passed with options object.');
|
||||
}
|
||||
|
||||
webContents.loadURL(url, {
|
||||
httpReferrer: referrer,
|
||||
...(postData && {
|
||||
postData,
|
||||
extraHeaders: formatPostDataHeaders(postData as Electron.UploadRawData[])
|
||||
})
|
||||
});
|
||||
|
||||
handleWindowLifecycleEvents({ embedder, frameName, guest, outlivesOpener });
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const window = new BrowserWindow({
|
||||
webContents: guest,
|
||||
...browserWindowOptions
|
||||
@@ -77,11 +103,9 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
|
||||
});
|
||||
}
|
||||
|
||||
handleWindowLifecycleEvents({ embedder, frameName, guest: window, outlivesOpener });
|
||||
handleWindowLifecycleEvents({ embedder, frameName, guest: window.webContents, outlivesOpener });
|
||||
|
||||
embedder.emit('did-create-window', window, { url, frameName, options: browserWindowOptions, disposition, referrer, postData });
|
||||
|
||||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,12 +116,12 @@ export function openGuestWindow ({ embedder, guest, referrer, disposition, postD
|
||||
*/
|
||||
const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outlivesOpener }: {
|
||||
embedder: WebContents,
|
||||
guest: BrowserWindow,
|
||||
guest: WebContents,
|
||||
frameName: string,
|
||||
outlivesOpener: boolean
|
||||
}) {
|
||||
const closedByEmbedder = function () {
|
||||
guest.removeListener('closed', closedByUser);
|
||||
guest.removeListener('destroyed', closedByUser);
|
||||
guest.destroy();
|
||||
};
|
||||
|
||||
@@ -110,11 +134,11 @@ const handleWindowLifecycleEvents = function ({ embedder, guest, frameName, outl
|
||||
if (!outlivesOpener) {
|
||||
embedder.once('current-render-view-deleted' as any, closedByEmbedder);
|
||||
}
|
||||
guest.once('closed', closedByUser);
|
||||
guest.once('destroyed', closedByUser);
|
||||
|
||||
if (frameName) {
|
||||
registerFrameNameToGuestWindow(frameName, guest);
|
||||
guest.once('closed', function () {
|
||||
guest.once('destroyed', function () {
|
||||
unregisterFrameName(frameName);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -200,11 +200,11 @@ delete process.appCodeLoaded;
|
||||
if (packagePath) {
|
||||
// Finally load app's main.js and transfer control to C++.
|
||||
if ((packageJson.type === 'module' && !mainStartupScript.endsWith('.cjs')) || mainStartupScript.endsWith('.mjs')) {
|
||||
const { loadESM } = __non_webpack_require__('internal/process/esm_loader');
|
||||
const { runEntryPointWithESMLoader } = __non_webpack_require__('internal/modules/run_main');
|
||||
const main = (require('url') as typeof url).pathToFileURL(path.join(packagePath, mainStartupScript));
|
||||
loadESM(async (esmLoader: any) => {
|
||||
runEntryPointWithESMLoader(async (cascadedLoader: any) => {
|
||||
try {
|
||||
await esmLoader.import(main.toString(), undefined, Object.create(null));
|
||||
await cascadedLoader.import(main.toString(), undefined, Object.create(null));
|
||||
appCodeLoaded!();
|
||||
} catch (err) {
|
||||
appCodeLoaded!();
|
||||
|
||||
@@ -209,6 +209,22 @@ type ExtraURLLoaderOptions = {
|
||||
headers: Record<string, { name: string, value: string | string[] }>;
|
||||
allowNonHttpProtocols: boolean;
|
||||
}
|
||||
|
||||
function validateHeader (name: any, value: any): void {
|
||||
if (typeof name !== 'string') {
|
||||
throw new TypeError('`name` should be a string in setHeader(name, value)');
|
||||
}
|
||||
if (value == null) {
|
||||
throw new Error('`value` required in setHeader("' + name + '", value)');
|
||||
}
|
||||
if (!isValidHeaderName(name)) {
|
||||
throw new Error(`Invalid header name: '${name}'`);
|
||||
}
|
||||
if (!isValidHeaderValue(value.toString())) {
|
||||
throw new Error(`Invalid value for header '${name}': '${value}'`);
|
||||
}
|
||||
}
|
||||
|
||||
function parseOptions (optionsIn: ClientRequestConstructorOptions | string): NodeJS.CreateURLLoaderOptions & ExtraURLLoaderOptions {
|
||||
// eslint-disable-next-line node/no-deprecated-api
|
||||
const options: any = typeof optionsIn === 'string' ? url.parse(optionsIn) : { ...optionsIn };
|
||||
@@ -275,12 +291,7 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
|
||||
};
|
||||
const headers: Record<string, string | string[]> = options.headers || {};
|
||||
for (const [name, value] of Object.entries(headers)) {
|
||||
if (!isValidHeaderName(name)) {
|
||||
throw new Error(`Invalid header name: '${name}'`);
|
||||
}
|
||||
if (!isValidHeaderValue(value.toString())) {
|
||||
throw new Error(`Invalid value for header '${name}': '${value}'`);
|
||||
}
|
||||
validateHeader(name, value);
|
||||
const key = name.toLowerCase();
|
||||
urlLoaderOptions.headers[key] = { name, value };
|
||||
}
|
||||
@@ -351,21 +362,10 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
|
||||
}
|
||||
|
||||
setHeader (name: string, value: string) {
|
||||
if (typeof name !== 'string') {
|
||||
throw new TypeError('`name` should be a string in setHeader(name, value)');
|
||||
}
|
||||
if (value == null) {
|
||||
throw new Error('`value` required in setHeader("' + name + '", value)');
|
||||
}
|
||||
if (this._started || this._firstWrite) {
|
||||
throw new Error('Can\'t set headers after they are sent');
|
||||
}
|
||||
if (!isValidHeaderName(name)) {
|
||||
throw new Error(`Invalid header name: '${name}'`);
|
||||
}
|
||||
if (!isValidHeaderValue(value.toString())) {
|
||||
throw new Error(`Invalid value for header '${name}': '${value}'`);
|
||||
}
|
||||
validateHeader(name, value);
|
||||
|
||||
const key = name.toLowerCase();
|
||||
this._urlLoaderOptions.headers[key] = { name, value };
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Buffer } from 'buffer';
|
||||
import { constants } from 'fs';
|
||||
import { Dirent, constants } from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
|
||||
@@ -46,7 +46,17 @@ process._getOrCreateArchive = getOrCreateArchive;
|
||||
|
||||
const asarRe = /\.asar/i;
|
||||
|
||||
const { getValidatedPath } = __non_webpack_require__('internal/fs/utils');
|
||||
const {
|
||||
getValidatedPath,
|
||||
getOptions,
|
||||
getDirent
|
||||
} = __non_webpack_require__('internal/fs/utils');
|
||||
|
||||
const {
|
||||
validateBoolean,
|
||||
validateFunction
|
||||
} = __non_webpack_require__('internal/validators');
|
||||
|
||||
// In the renderer node internals use the node global URL but we do not set that to be
|
||||
// the global URL instance. We need to do instanceof checks against the internal URL impl
|
||||
const { URL: NodeURL } = __non_webpack_require__('internal/url');
|
||||
@@ -78,6 +88,23 @@ const gid = process.getgid?.() ?? 0;
|
||||
|
||||
const fakeTime = new Date();
|
||||
|
||||
function getDirents (p: string, { 0: names, 1: types }: any[][]): Dirent[] {
|
||||
for (let i = 0; i < names.length; i++) {
|
||||
let type = types[i];
|
||||
const info = splitPath(path.join(p, names[i]));
|
||||
if (info.isAsar) {
|
||||
const archive = getOrCreateArchive(info.asarPath);
|
||||
if (!archive) continue;
|
||||
const stats = archive.stat(info.filePath);
|
||||
if (!stats) continue;
|
||||
type = stats.type;
|
||||
}
|
||||
names[i] = getDirent(p, names[i], type);
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
enum AsarFileType {
|
||||
kFile = (constants as any).UV_DIRENT_FILE,
|
||||
kDirectory = (constants as any).UV_DIRENT_DIR,
|
||||
@@ -467,7 +494,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
};
|
||||
|
||||
const { access } = fs;
|
||||
fs.access = function (pathArgument: string, mode: any, callback: any) {
|
||||
fs.access = function (pathArgument: string, mode: number, callback: any) {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return access.apply(this, arguments);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
@@ -512,7 +539,16 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
nextTick(callback);
|
||||
};
|
||||
|
||||
fs.promises.access = util.promisify(fs.access);
|
||||
const { access: accessPromise } = fs.promises;
|
||||
fs.promises.access = function (pathArgument: string, mode: number) {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) {
|
||||
return accessPromise.apply(this, arguments);
|
||||
}
|
||||
|
||||
const p = util.promisify(fs.access);
|
||||
return p(pathArgument, mode);
|
||||
};
|
||||
|
||||
const { accessSync } = fs;
|
||||
fs.accessSync = function (pathArgument: string, mode: any) {
|
||||
@@ -662,13 +698,27 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
return (encoding) ? buffer.toString(encoding) : buffer;
|
||||
};
|
||||
|
||||
type ReaddirOptions = { encoding: BufferEncoding | null; withFileTypes?: false, recursive?: false } | undefined | null;
|
||||
type ReaddirCallback = (err: NodeJS.ErrnoException | null, files: string[]) => void;
|
||||
|
||||
const { readdir } = fs;
|
||||
fs.readdir = function (pathArgument: string, options?: { encoding?: string | null; withFileTypes?: boolean } | null, callback?: Function) {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = undefined;
|
||||
fs.readdir = function (pathArgument: string, options: ReaddirOptions, callback: ReaddirCallback) {
|
||||
callback = typeof options === 'function' ? options : callback;
|
||||
validateFunction(callback, 'callback');
|
||||
|
||||
options = getOptions(options);
|
||||
pathArgument = getValidatedPath(pathArgument);
|
||||
|
||||
if (options?.recursive != null) {
|
||||
validateBoolean(options?.recursive, 'options.recursive');
|
||||
}
|
||||
|
||||
if (options?.recursive) {
|
||||
nextTick(callback!, [null, readdirSyncRecursive(pathArgument, options)]);
|
||||
return;
|
||||
}
|
||||
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return readdir.apply(this, arguments);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
|
||||
@@ -705,12 +755,62 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
nextTick(callback!, [null, files]);
|
||||
};
|
||||
|
||||
fs.promises.readdir = util.promisify(fs.readdir);
|
||||
const { readdir: readdirPromise } = require('fs').promises;
|
||||
fs.promises.readdir = async function (pathArgument: string, options: ReaddirOptions) {
|
||||
options = getOptions(options);
|
||||
pathArgument = getValidatedPath(pathArgument);
|
||||
|
||||
type ReaddirSyncOptions = { encoding: BufferEncoding | null; withFileTypes?: false };
|
||||
if (options?.recursive != null) {
|
||||
validateBoolean(options?.recursive, 'options.recursive');
|
||||
}
|
||||
|
||||
if (options?.recursive) {
|
||||
return readdirRecursive(pathArgument, options);
|
||||
}
|
||||
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return readdirPromise(pathArgument, options);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
|
||||
const archive = getOrCreateArchive(asarPath);
|
||||
if (!archive) {
|
||||
return Promise.reject(createError(AsarError.INVALID_ARCHIVE, { asarPath }));
|
||||
}
|
||||
|
||||
const files = archive.readdir(filePath);
|
||||
if (!files) {
|
||||
return Promise.reject(createError(AsarError.NOT_FOUND, { asarPath, filePath }));
|
||||
}
|
||||
|
||||
if (options?.withFileTypes) {
|
||||
const dirents = [];
|
||||
for (const file of files) {
|
||||
const childPath = path.join(filePath, file);
|
||||
const stats = archive.stat(childPath);
|
||||
if (!stats) {
|
||||
throw createError(AsarError.NOT_FOUND, { asarPath, filePath: childPath });
|
||||
}
|
||||
dirents.push(new fs.Dirent(file, stats.type));
|
||||
}
|
||||
return Promise.resolve(dirents);
|
||||
}
|
||||
|
||||
return Promise.resolve(files);
|
||||
};
|
||||
|
||||
const { readdirSync } = fs;
|
||||
fs.readdirSync = function (pathArgument: string, options: ReaddirSyncOptions | BufferEncoding | null) {
|
||||
fs.readdirSync = function (pathArgument: string, options: ReaddirOptions) {
|
||||
options = getOptions(options);
|
||||
pathArgument = getValidatedPath(pathArgument);
|
||||
|
||||
if (options?.recursive != null) {
|
||||
validateBoolean(options?.recursive, 'options.recursive');
|
||||
}
|
||||
|
||||
if (options?.recursive) {
|
||||
return readdirSyncRecursive(pathArgument, options);
|
||||
}
|
||||
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return readdirSync.apply(this, arguments);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
@@ -725,7 +825,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
throw createError(AsarError.NOT_FOUND, { asarPath, filePath });
|
||||
}
|
||||
|
||||
if (options && (options as ReaddirSyncOptions).withFileTypes) {
|
||||
if (options?.withFileTypes) {
|
||||
const dirents = [];
|
||||
for (const file of files) {
|
||||
const childPath = path.join(filePath, file);
|
||||
@@ -741,7 +841,8 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
return files;
|
||||
};
|
||||
|
||||
const { internalModuleReadJSON } = internalBinding('fs');
|
||||
const binding = internalBinding('fs');
|
||||
const { internalModuleReadJSON, kUsePromises } = binding;
|
||||
internalBinding('fs').internalModuleReadJSON = (pathArgument: string) => {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (!pathInfo.isAsar) return internalModuleReadJSON(pathArgument);
|
||||
@@ -787,6 +888,187 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
return (stats.type === AsarFileType.kDirectory) ? 1 : 0;
|
||||
};
|
||||
|
||||
async function readdirRecursive (originalPath: string, options: ReaddirOptions) {
|
||||
const result: any[] = [];
|
||||
|
||||
const pathInfo = splitPath(originalPath);
|
||||
let queue: [string, string[]][] = [];
|
||||
const withFileTypes = Boolean(options?.withFileTypes);
|
||||
|
||||
let initialItem = [];
|
||||
if (pathInfo.isAsar) {
|
||||
const archive = getOrCreateArchive(pathInfo.asarPath);
|
||||
if (!archive) return result;
|
||||
const files = archive.readdir(pathInfo.filePath);
|
||||
if (!files) return result;
|
||||
|
||||
// If we're in an asar dir, we need to ensure the result is in the same format as the
|
||||
// native call to readdir withFileTypes i.e. an array of arrays.
|
||||
initialItem = files;
|
||||
if (withFileTypes) {
|
||||
initialItem = [
|
||||
[...initialItem], initialItem.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(originalPath, p));
|
||||
})
|
||||
];
|
||||
}
|
||||
} else {
|
||||
initialItem = await binding.readdir(
|
||||
path.toNamespacedPath(originalPath),
|
||||
options!.encoding,
|
||||
withFileTypes,
|
||||
kUsePromises
|
||||
);
|
||||
}
|
||||
|
||||
queue = [[originalPath, initialItem]];
|
||||
|
||||
if (withFileTypes) {
|
||||
while (queue.length > 0) {
|
||||
// @ts-expect-error this is a valid array destructure assignment.
|
||||
const { 0: pathArg, 1: readDir } = queue.pop();
|
||||
for (const dirent of getDirents(pathArg, readDir)) {
|
||||
result.push(dirent);
|
||||
if (dirent.isDirectory()) {
|
||||
const direntPath = path.join(pathArg, dirent.name);
|
||||
const info = splitPath(direntPath);
|
||||
let readdirResult;
|
||||
if (info.isAsar) {
|
||||
const archive = getOrCreateArchive(info.asarPath);
|
||||
if (!archive) continue;
|
||||
const files = archive.readdir(info.filePath);
|
||||
if (!files) continue;
|
||||
|
||||
readdirResult = [
|
||||
[...files], files.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(direntPath, p));
|
||||
})
|
||||
];
|
||||
} else {
|
||||
readdirResult = await binding.readdir(
|
||||
direntPath,
|
||||
options!.encoding,
|
||||
true,
|
||||
kUsePromises
|
||||
);
|
||||
}
|
||||
queue.push([direntPath, readdirResult]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (queue.length > 0) {
|
||||
// @ts-expect-error this is a valid array destructure assignment.
|
||||
const { 0: pathArg, 1: readDir } = queue.pop();
|
||||
for (const ent of readDir) {
|
||||
const direntPath = path.join(pathArg, ent);
|
||||
const stat = internalBinding('fs').internalModuleStat(direntPath);
|
||||
result.push(path.relative(originalPath, direntPath));
|
||||
|
||||
if (stat === 1) {
|
||||
const subPathInfo = splitPath(direntPath);
|
||||
let item = [];
|
||||
if (subPathInfo.isAsar) {
|
||||
const archive = getOrCreateArchive(subPathInfo.asarPath);
|
||||
if (!archive) return;
|
||||
const files = archive.readdir(subPathInfo.filePath);
|
||||
if (!files) return result;
|
||||
item = files;
|
||||
} else {
|
||||
item = await binding.readdir(
|
||||
path.toNamespacedPath(direntPath),
|
||||
options!.encoding,
|
||||
false,
|
||||
kUsePromises
|
||||
);
|
||||
}
|
||||
queue.push([direntPath, item]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function readdirSyncRecursive (basePath: string, options: ReaddirOptions) {
|
||||
const withFileTypes = Boolean(options!.withFileTypes);
|
||||
const encoding = options!.encoding;
|
||||
|
||||
const readdirResults: string[] = [];
|
||||
const pathsQueue = [basePath];
|
||||
|
||||
function read (pathArg: string) {
|
||||
let readdirResult;
|
||||
|
||||
const pathInfo = splitPath(pathArg);
|
||||
if (pathInfo.isAsar) {
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
const archive = getOrCreateArchive(asarPath);
|
||||
if (!archive) return;
|
||||
|
||||
readdirResult = archive.readdir(filePath);
|
||||
if (!readdirResult) return;
|
||||
// If we're in an asar dir, we need to ensure the result is in the same format as the
|
||||
// native call to readdir withFileTypes i.e. an array of arrays.
|
||||
if (withFileTypes) {
|
||||
readdirResult = [
|
||||
[...readdirResult], readdirResult.map((p: string) => {
|
||||
return internalBinding('fs').internalModuleStat(path.join(pathArg, p));
|
||||
})
|
||||
];
|
||||
}
|
||||
} else {
|
||||
readdirResult = binding.readdir(
|
||||
path.toNamespacedPath(pathArg),
|
||||
encoding,
|
||||
withFileTypes
|
||||
);
|
||||
}
|
||||
|
||||
if (readdirResult === undefined) return;
|
||||
|
||||
if (withFileTypes) {
|
||||
const length = readdirResult[0].length;
|
||||
for (let i = 0; i < length; i++) {
|
||||
const resultPath = path.join(pathArg, readdirResult[0][i]);
|
||||
const info = splitPath(resultPath);
|
||||
|
||||
let type = readdirResult[1][i];
|
||||
if (info.isAsar) {
|
||||
const archive = getOrCreateArchive(info.asarPath);
|
||||
if (!archive) return;
|
||||
const stats = archive.stat(info.filePath);
|
||||
if (!stats) continue;
|
||||
type = stats.type;
|
||||
}
|
||||
|
||||
const dirent = getDirent(pathArg, readdirResult[0][i], type);
|
||||
|
||||
readdirResults.push(dirent);
|
||||
if (dirent.isDirectory()) {
|
||||
pathsQueue.push(path.join(dirent.path, dirent.name));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < readdirResult.length; i++) {
|
||||
const resultPath = path.join(pathArg, readdirResult[i]);
|
||||
const relativeResultPath = path.relative(basePath, resultPath);
|
||||
const stat = internalBinding('fs').internalModuleStat(resultPath);
|
||||
|
||||
readdirResults.push(relativeResultPath);
|
||||
if (stat === 1) pathsQueue.push(resultPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < pathsQueue.length; i++) {
|
||||
read(pathsQueue[i]);
|
||||
}
|
||||
|
||||
return readdirResults;
|
||||
}
|
||||
|
||||
// Calling mkdir for directory inside asar archive should throw ENOTDIR
|
||||
// error, but on Windows it throws ENOENT.
|
||||
if (process.platform === 'win32') {
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
import { wrapFsWithAsar } from './asar-fs-wrapper';
|
||||
wrapFsWithAsar(require('fs'));
|
||||
|
||||
// See ElectronRendererClient::DidCreateScriptContext.
|
||||
if ((globalThis as any).blinkFetch) {
|
||||
globalThis.fetch = (globalThis as any).blinkFetch;
|
||||
}
|
||||
|
||||
// Hook child_process.fork.
|
||||
import cp = require('child_process'); // eslint-disable-line import/first
|
||||
const originalFork = cp.fork;
|
||||
|
||||
@@ -150,12 +150,12 @@ if (cjsPreloads.length) {
|
||||
}
|
||||
}
|
||||
if (esmPreloads.length) {
|
||||
const { loadESM } = __non_webpack_require__('internal/process/esm_loader');
|
||||
const { runEntryPointWithESMLoader } = __non_webpack_require__('internal/modules/run_main');
|
||||
|
||||
loadESM(async (esmLoader: any) => {
|
||||
runEntryPointWithESMLoader(async (cascadedLoader: any) => {
|
||||
// Load the preload scripts.
|
||||
for (const preloadScript of esmPreloads) {
|
||||
await esmLoader.import(pathToFileURL(preloadScript).toString(), undefined, Object.create(null)).catch((err: Error) => {
|
||||
await cascadedLoader.import(pathToFileURL(preloadScript).toString(), undefined, Object.create(null)).catch((err: Error) => {
|
||||
console.error(`Unable to load preload script: ${preloadScript}`);
|
||||
console.error(err);
|
||||
|
||||
|
||||
@@ -36,11 +36,12 @@ parentPort.on('removeListener', (name: string) => {
|
||||
});
|
||||
|
||||
// Finally load entry script.
|
||||
const { loadESM } = __non_webpack_require__('internal/process/esm_loader');
|
||||
const { runEntryPointWithESMLoader } = __non_webpack_require__('internal/modules/run_main');
|
||||
const mainEntry = pathToFileURL(entryScript);
|
||||
loadESM(async (esmLoader: any) => {
|
||||
|
||||
runEntryPointWithESMLoader(async (cascadedLoader: any) => {
|
||||
try {
|
||||
await esmLoader.import(mainEntry.toString(), undefined, Object.create(null));
|
||||
await cascadedLoader.import(mainEntry.toString(), undefined, Object.create(null));
|
||||
} catch (err) {
|
||||
// @ts-ignore internalBinding is a secret internal global that we shouldn't
|
||||
// really be using, so we ignore the type error instead of declaring it in types
|
||||
|
||||
13
package.json
13
package.json
@@ -9,7 +9,7 @@
|
||||
"@electron/docs-parser": "^1.2.0",
|
||||
"@electron/fiddle-core": "^1.0.4",
|
||||
"@electron/github-app-auth": "^2.0.0",
|
||||
"@electron/lint-roller": "^1.9.0",
|
||||
"@electron/lint-roller": "^2.1.0",
|
||||
"@electron/typescript-definitions": "^8.15.2",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
@@ -49,7 +49,7 @@
|
||||
"eslint-plugin-standard": "^4.0.1",
|
||||
"eslint-plugin-unicorn": "^46.0.1",
|
||||
"events": "^3.2.0",
|
||||
"express": "^4.16.4",
|
||||
"express": "^4.19.2",
|
||||
"folder-hash": "^2.1.1",
|
||||
"fs-extra": "^9.0.1",
|
||||
"got": "^11.8.5",
|
||||
@@ -57,6 +57,7 @@
|
||||
"klaw": "^3.0.0",
|
||||
"lint": "^1.1.2",
|
||||
"lint-staged": "^10.2.11",
|
||||
"markdownlint-cli2": "^0.13.0",
|
||||
"minimist": "^1.2.6",
|
||||
"null-loader": "^4.0.0",
|
||||
"pre-flight": "^1.1.0",
|
||||
@@ -91,10 +92,10 @@
|
||||
"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",
|
||||
"lint:docs-fiddles": "standard \"docs/fiddles/**/*.js\"",
|
||||
"lint:docs-relative-links": "electron-lint-markdown-links --root docs \"**/*.md\"",
|
||||
"lint:docs-relative-links": "lint-roller-markdown-links --root docs \"**/*.md\"",
|
||||
"lint:markdown": "node ./script/lint.js --md",
|
||||
"lint:ts-check-js-in-markdown": "electron-lint-markdown-ts-check --root docs \"**/*.md\" --ignore \"breaking-changes.md\"",
|
||||
"lint:js-in-markdown": "electron-lint-markdown-standard --root docs \"**/*.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\"",
|
||||
"create-api-json": "node script/create-api-json.js",
|
||||
"create-typescript-definitions": "npm run create-api-json && electron-typescript-definitions --api=electron-api.json && node spec/ts-smoke/runner.js",
|
||||
"gn-typescript-definitions": "npm run create-typescript-definitions && shx cp electron.d.ts",
|
||||
@@ -139,7 +140,7 @@
|
||||
],
|
||||
"docs/api/**/*.md": [
|
||||
"ts-node script/gen-filenames.ts",
|
||||
"electron-markdownlint --config .markdownlint.autofix.json --fix",
|
||||
"markdownlint-cli2 --config .autofix.markdownlint-cli2.jsonc --fix",
|
||||
"git add filenames.auto.gni"
|
||||
],
|
||||
"{*.patch,.patches}": [
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user