mirror of
https://github.com/electron/electron.git
synced 2026-04-10 03:01:51 -04:00
Compare commits
187 Commits
v29.0.0-ni
...
28-x-y
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
92e4123de7 | ||
|
|
db688056d8 | ||
|
|
cd25fbfd73 | ||
|
|
65d35309db | ||
|
|
1e054f3ef9 | ||
|
|
c89546bc92 | ||
|
|
19d3d66f46 | ||
|
|
196b6e66b8 | ||
|
|
b5262e4700 | ||
|
|
70cdc2e551 | ||
|
|
b5eba900b5 | ||
|
|
b3defc12dc | ||
|
|
dc8a39ce37 | ||
|
|
4e0650fe3b | ||
|
|
1768c3bc99 | ||
|
|
ad92d24273 | ||
|
|
8c3daf4e9b | ||
|
|
260c036662 | ||
|
|
6115b5f3b0 | ||
|
|
3b78798c2d | ||
|
|
966a50628b | ||
|
|
9ec710e99c | ||
|
|
e9060c2793 | ||
|
|
03bfd50875 | ||
|
|
484b75568f | ||
|
|
2e95cf50bb | ||
|
|
c29526b721 | ||
|
|
f4b7aa5401 | ||
|
|
76172fd27e | ||
|
|
c145388dd2 | ||
|
|
faa3dc7654 | ||
|
|
3f0dd063cb | ||
|
|
c2184ad4ff | ||
|
|
31cd9d1f61 | ||
|
|
ca6bd89a69 | ||
|
|
82b648e491 | ||
|
|
085363db07 | ||
|
|
565988c96f | ||
|
|
2977fc4025 | ||
|
|
1ded991603 | ||
|
|
dc19cd2c9d | ||
|
|
945f1c7262 | ||
|
|
70255b1db1 | ||
|
|
c96d7db592 | ||
|
|
6780e671f9 | ||
|
|
e5799c1dc2 | ||
|
|
6544cec686 | ||
|
|
8618d5d220 | ||
|
|
15d87d48b2 | ||
|
|
59436b032b | ||
|
|
e93a028c91 | ||
|
|
80de0b6acd | ||
|
|
28485340b0 | ||
|
|
de85def21b | ||
|
|
c9ff1d38e4 | ||
|
|
3649df1043 | ||
|
|
89817d6a02 | ||
|
|
8177a16f9a | ||
|
|
abd7850ee4 | ||
|
|
b0c3534ecb | ||
|
|
16adf2a263 | ||
|
|
b96b40223a | ||
|
|
a4f6d8a1f7 | ||
|
|
2ed1041e66 | ||
|
|
d6221eaf2d | ||
|
|
ace362c4c4 | ||
|
|
f163b0ad64 | ||
|
|
6fa5495a70 | ||
|
|
2df0c05a3a | ||
|
|
d5d40d50ab | ||
|
|
b9acd8afbd | ||
|
|
865a72fe34 | ||
|
|
59f50c75fc | ||
|
|
52251f2154 | ||
|
|
750df6ad9a | ||
|
|
e21a6bf385 | ||
|
|
8f005ee01c | ||
|
|
38b64d334f | ||
|
|
9283a9d19b | ||
|
|
116dcfb827 | ||
|
|
87bf58d04a | ||
|
|
08f30e2623 | ||
|
|
35670486f7 | ||
|
|
33057eb8d4 | ||
|
|
b12e04eda0 | ||
|
|
0c9581609c | ||
|
|
b0121d9eb1 | ||
|
|
b70b76e97f | ||
|
|
42728caaa3 | ||
|
|
d60d4c6b2d | ||
|
|
cdf99a215a | ||
|
|
af42e8e9c7 | ||
|
|
52113e0d1c | ||
|
|
8f72f9bcb5 | ||
|
|
6e44c8f7d0 | ||
|
|
0f8ebfba1e | ||
|
|
4583072a98 | ||
|
|
8f902599e4 | ||
|
|
dcc19bb8d6 | ||
|
|
71d6776e00 | ||
|
|
37d4f807a6 | ||
|
|
efad0a8018 | ||
|
|
dae05a44a0 | ||
|
|
e887328b23 | ||
|
|
337684f3cb | ||
|
|
0862529a86 | ||
|
|
4120b8f72a | ||
|
|
73111dae51 | ||
|
|
73197a85e2 | ||
|
|
741774177f | ||
|
|
9b2ddea855 | ||
|
|
aa8d667bef | ||
|
|
7989f02a43 | ||
|
|
0b8f962010 | ||
|
|
957d8748b2 | ||
|
|
14c6651e35 | ||
|
|
c9f886c03d | ||
|
|
0aa33cc3df | ||
|
|
5d5ebc9da2 | ||
|
|
66e4c3089b | ||
|
|
4a617aa666 | ||
|
|
271f2b576a | ||
|
|
515803e601 | ||
|
|
34d115a430 | ||
|
|
e809537ac0 | ||
|
|
589c827cb9 | ||
|
|
fe49f1c79a | ||
|
|
5bc8e761d6 | ||
|
|
0756fe6f30 | ||
|
|
a0c85cf57e | ||
|
|
e45e20acd5 | ||
|
|
1af25902a6 | ||
|
|
9ad4024e82 | ||
|
|
9e323e3104 | ||
|
|
9e1c116ff6 | ||
|
|
581fafb2e9 | ||
|
|
630d75981c | ||
|
|
f939be0638 | ||
|
|
d01469e486 | ||
|
|
0594081f26 | ||
|
|
131c5e7986 | ||
|
|
a3986f84db | ||
|
|
33b39fb63d | ||
|
|
9a4b32d517 | ||
|
|
8eb6b35fc0 | ||
|
|
b92b4c8fcf | ||
|
|
bc07c3be54 | ||
|
|
1f0fa3471a | ||
|
|
460b8dc453 | ||
|
|
db995982cd | ||
|
|
30fe3b5667 | ||
|
|
0b847b0d9f | ||
|
|
a77f2e0cee | ||
|
|
f739cb110a | ||
|
|
b2235fefc3 | ||
|
|
5c70bd768a | ||
|
|
3934f72496 | ||
|
|
8d5a15316f | ||
|
|
6916e19ce1 | ||
|
|
5997b47d21 | ||
|
|
3f0af4d435 | ||
|
|
45fbdcca6a | ||
|
|
09c151a701 | ||
|
|
5dad69ce8f | ||
|
|
d0d2a64739 | ||
|
|
2c200c9b8d | ||
|
|
bb0dd34e63 | ||
|
|
8148ba5398 | ||
|
|
f6d7aba69c | ||
|
|
22687c18c4 | ||
|
|
d1bf107bee | ||
|
|
eff2ea682d | ||
|
|
0310156be6 | ||
|
|
714e6ea49c | ||
|
|
3cf8652027 | ||
|
|
f622bd9927 | ||
|
|
9ddd08ba89 | ||
|
|
a98d66dd23 | ||
|
|
1e51ee974d | ||
|
|
6732f63ac0 | ||
|
|
641249f384 | ||
|
|
f6b135e1ac | ||
|
|
a5f01f0328 | ||
|
|
d65b8761f8 | ||
|
|
f8d4c45f8e | ||
|
|
6625666e40 | ||
|
|
e3e7bf3786 |
@@ -75,17 +75,15 @@ executors:
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# Electron Runners
|
||||
apple-silicon:
|
||||
resource_class: electronjs/macos-arm64
|
||||
machine: true
|
||||
|
||||
linux-arm:
|
||||
resource_class: electronjs/linux-arm
|
||||
machine: true
|
||||
resource_class: electronjs/aks-linux-arm-test
|
||||
docker:
|
||||
- image: ghcr.io/electron/test:arm32v7-8e0f85b708fa58e28e4824954d6fd55adfda5e9e
|
||||
|
||||
linux-arm64:
|
||||
resource_class: electronjs/linux-arm64
|
||||
machine: true
|
||||
resource_class: electronjs/aks-linux-arm-test
|
||||
docker:
|
||||
- image: ghcr.io/electron/test:arm64v8-76d5d29e247972da3855a01c2d8cf72c5998233a
|
||||
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
@@ -250,6 +248,10 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
name: Get depot tools
|
||||
command: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
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
|
||||
@@ -1211,7 +1213,7 @@ commands:
|
||||
build-type: << parameters.build-type >>
|
||||
- *step-maybe-electron-dist-strip
|
||||
- step-electron-dist-build:
|
||||
additional-targets: electron:node_headers third_party/electron_node:overlapped-checker electron:hunspell_dictionaries_zip
|
||||
additional-targets: shell_browser_ui_unittests electron:node_headers third_party/electron_node:overlapped-checker electron:hunspell_dictionaries_zip
|
||||
|
||||
- *step-show-goma-stats
|
||||
|
||||
@@ -1657,17 +1659,15 @@ commands:
|
||||
export LLVM_SYMBOLIZER_PATH=$PWD/third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer
|
||||
export MOCHA_TIMEOUT=180000
|
||||
echo "Piping output to ASAN_SYMBOLIZE ($ASAN_SYMBOLIZE)"
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings 2>&1)) | $ASAN_SYMBOLIZE
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | xargs -I@ -P4 bash -c "echo $(pwd)/@" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings 2>&1)) | $ASAN_SYMBOLIZE
|
||||
else
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
export ELECTRON_SKIP_NATIVE_MODULE_TESTS=true
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging)
|
||||
else
|
||||
if [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
npm_config_arch=x64 node electron/node_modules/dugite/script/download-git.js
|
||||
fi
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings))
|
||||
fi
|
||||
if [ "$TARGET_ARCH" == "ia32" ]; then
|
||||
npm_config_arch=x64 node electron/node_modules/dugite/script/download-git.js
|
||||
fi
|
||||
(cd electron && (circleci tests glob "spec/*-spec.ts" | xargs -I@ -P4 bash -c "echo $(pwd)/@" | circleci tests run --command="xargs node script/yarn test --runners=main --trace-uncaught --enable-logging --files" --split-by=timings))
|
||||
fi
|
||||
- store_test_results:
|
||||
path: src/junit
|
||||
@@ -2165,7 +2165,7 @@ jobs:
|
||||
<<: *env-ninja-status
|
||||
<<: *env-macos-build
|
||||
<<: *env-apple-silicon
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac --custom-var=host_cpu=arm64'
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: true
|
||||
@@ -2297,6 +2297,7 @@ jobs:
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
parallelism: 3
|
||||
steps:
|
||||
- electron-tests:
|
||||
artifact-key: linux-arm
|
||||
@@ -2308,6 +2309,7 @@ jobs:
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
parallelism: 3
|
||||
steps:
|
||||
- electron-tests:
|
||||
artifact-key: linux-arm64
|
||||
@@ -2325,8 +2327,11 @@ jobs:
|
||||
- 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
|
||||
version: 14.0.0
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
@@ -2350,7 +2355,10 @@ jobs:
|
||||
artifact-key: mas-x64
|
||||
|
||||
mas-testing-arm64-tests:
|
||||
executor: apple-silicon
|
||||
executor:
|
||||
name: macos
|
||||
size: macos.m1.medium.gen1
|
||||
version: 14.0.0
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
|
||||
27
.github/workflows/branch-created.yml
vendored
27
.github/workflows/branch-created.yml
vendored
@@ -72,38 +72,21 @@ jobs:
|
||||
with:
|
||||
script: |
|
||||
const major = ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
const nextMajor = major + 1
|
||||
const prevMajor = major - 1
|
||||
|
||||
core.setOutput("major", major)
|
||||
core.setOutput("next-major", nextMajor)
|
||||
core.setOutput("prev-major", prevMajor)
|
||||
core.setOutput("prev-prev-major", prevMajor - 1)
|
||||
core.setOutput("template-view", JSON.stringify({
|
||||
major,
|
||||
"next-major": nextMajor,
|
||||
"prev-major": prevMajor,
|
||||
"next-major": major + 1,
|
||||
"prev-major": major - 1,
|
||||
}))
|
||||
core.setOutput("title", `${major}-x-y`)
|
||||
- name: Create Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/copy-project@3a81985616963f32fae17d1d1b406c631f3201a1 # v1.1.0
|
||||
uses: dsanders11/project-actions/copy-project@a24415515fa60a22f71f9d9d00e36ca82660cde9 # v1.0.1
|
||||
with:
|
||||
drafts: true
|
||||
project-number: 64
|
||||
# TODO - Set to public once GitHub fixes their GraphQL bug
|
||||
# public: true
|
||||
link-to-repository: electron/electron
|
||||
template-view: ${{ steps.generate-project-metadata.outputs.template-view }}
|
||||
title: ${{ steps.generate-project-metadata.outputs.major }}-x-y
|
||||
title: ${{ steps.generate-project-metadata.outputs.title}}
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Find Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/find-project@3a81985616963f32fae17d1d1b406c631f3201a1 # v1.1.0
|
||||
id: find-prev-release-board
|
||||
with:
|
||||
title: ${{ steps.generate-project-metadata.outputs.prev-prev-major }}-x-y
|
||||
- name: Close Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/close-project@3a81985616963f32fae17d1d1b406c631f3201a1 # v1.1.0
|
||||
with:
|
||||
project-number: ${{ steps.find-prev-release-board.outputs.number }}
|
||||
|
||||
14
.github/workflows/pull-request-labeled.yml
vendored
14
.github/workflows/pull-request-labeled.yml
vendored
@@ -8,20 +8,6 @@ permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
pull-request-labeled-backport-requested:
|
||||
name: backport/requested label added
|
||||
if: github.event.label.name == 'backport/requested 🗳'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger Slack workflow
|
||||
uses: slackapi/slack-github-action@e28cf165c92ffef168d23c5c9000cffc8a25e117 # v1.24.0
|
||||
with:
|
||||
payload: |
|
||||
{
|
||||
"url": "${{ github.event.pull_request.html_url }}"
|
||||
}
|
||||
env:
|
||||
SLACK_WEBHOOK_URL: ${{ secrets.BACKPORT_REQUESTED_SLACK_WEBHOOK_URL }}
|
||||
pull-request-labeled-deprecation-review-complete:
|
||||
name: deprecation-review/complete label added
|
||||
if: github.event.label.name == 'deprecation-review/complete ✅'
|
||||
|
||||
44
BUILD.gn
44
BUILD.gn
@@ -165,15 +165,6 @@ npm_action("build_electron_definitions") {
|
||||
outputs = [ "$target_gen_dir/tsc/typings/electron.d.ts" ]
|
||||
}
|
||||
|
||||
webpack_build("electron_asar_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
inputs = auto_filenames.asar_bundle_deps
|
||||
|
||||
config_file = "//electron/build/webpack/webpack.config.asar.js"
|
||||
out_file = "$target_gen_dir/js2c/asar_bundle.js"
|
||||
}
|
||||
|
||||
webpack_build("electron_browser_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
@@ -219,6 +210,15 @@ webpack_build("electron_isolated_renderer_bundle") {
|
||||
out_file = "$target_gen_dir/js2c/isolated_bundle.js"
|
||||
}
|
||||
|
||||
webpack_build("electron_node_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
inputs = auto_filenames.node_bundle_deps
|
||||
|
||||
config_file = "//electron/build/webpack/webpack.config.node.js"
|
||||
out_file = "$target_gen_dir/js2c/node_init.js"
|
||||
}
|
||||
|
||||
webpack_build("electron_utility_bundle") {
|
||||
deps = [ ":build_electron_definitions" ]
|
||||
|
||||
@@ -230,9 +230,9 @@ webpack_build("electron_utility_bundle") {
|
||||
|
||||
action("electron_js2c") {
|
||||
deps = [
|
||||
":electron_asar_bundle",
|
||||
":electron_browser_bundle",
|
||||
":electron_isolated_renderer_bundle",
|
||||
":electron_node_bundle",
|
||||
":electron_renderer_bundle",
|
||||
":electron_sandboxed_renderer_bundle",
|
||||
":electron_utility_bundle",
|
||||
@@ -240,9 +240,9 @@ action("electron_js2c") {
|
||||
]
|
||||
|
||||
sources = [
|
||||
"$target_gen_dir/js2c/asar_bundle.js",
|
||||
"$target_gen_dir/js2c/browser_init.js",
|
||||
"$target_gen_dir/js2c/isolated_bundle.js",
|
||||
"$target_gen_dir/js2c/node_init.js",
|
||||
"$target_gen_dir/js2c/renderer_init.js",
|
||||
"$target_gen_dir/js2c/sandbox_bundle.js",
|
||||
"$target_gen_dir/js2c/utility_init.js",
|
||||
@@ -697,6 +697,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",
|
||||
]
|
||||
@@ -716,7 +718,6 @@ source_set("electron_lib") {
|
||||
"shell/common/extensions/api",
|
||||
"shell/common/extensions/api:extensions_features",
|
||||
"//chrome/browser/resources:component_extension_resources",
|
||||
"//components/guest_view/common:mojom",
|
||||
"//components/update_client:update_client",
|
||||
"//components/zoom",
|
||||
"//extensions/browser",
|
||||
@@ -1332,6 +1333,25 @@ if (is_mac) {
|
||||
}
|
||||
}
|
||||
|
||||
test("shell_browser_ui_unittests") {
|
||||
sources = [
|
||||
"//electron/shell/browser/ui/accelerator_util_unittests.cc",
|
||||
"//electron/shell/browser/ui/run_all_unittests.cc",
|
||||
]
|
||||
|
||||
configs += [ ":electron_lib_config" ]
|
||||
|
||||
deps = [
|
||||
":electron_lib",
|
||||
"//base",
|
||||
"//base/test:test_support",
|
||||
"//testing/gmock",
|
||||
"//testing/gtest",
|
||||
"//ui/base",
|
||||
"//ui/strings",
|
||||
]
|
||||
}
|
||||
|
||||
template("dist_zip") {
|
||||
_runtime_deps_target = "${target_name}__deps"
|
||||
_runtime_deps_file =
|
||||
|
||||
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'121.0.6116.0',
|
||||
'120.0.6099.291',
|
||||
'node_version':
|
||||
'v18.18.2',
|
||||
'nan_version':
|
||||
|
||||
12
README.md
12
README.md
@@ -9,8 +9,8 @@ View these docs in other languages on our [Crowdin](https://crowdin.com/project/
|
||||
|
||||
The Electron framework lets you write cross-platform desktop applications
|
||||
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
|
||||
[Chromium](https://www.chromium.org) and is used by the [Visual Studio
|
||||
Code](https://github.com/Microsoft/vscode/) and many other [apps](https://electronjs.org/apps).
|
||||
[Chromium](https://www.chromium.org) and is used by the [Atom
|
||||
editor](https://github.com/atom/atom) and many other [apps](https://electronjs.org/apps).
|
||||
|
||||
Follow [@electronjs](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
@@ -41,9 +41,9 @@ Each Electron release provides binaries for macOS, Windows, and Linux.
|
||||
* macOS (Catalina and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
|
||||
* Windows (Windows 10 and up): Electron provides `ia32` (`x86`), `x64` (`amd64`), and `arm64` binaries for Windows. Windows on ARM support was added in Electron 5.0.8. Support for Windows 7, 8 and 8.1 was [removed in Electron 23, in line with Chromium's Windows deprecation policy](https://www.electronjs.org/blog/windows-7-to-8-1-deprecation-notice).
|
||||
* Linux: The prebuilt binaries of Electron are built on Ubuntu 20.04. They have also been verified to work on:
|
||||
* Ubuntu 18.04 and newer
|
||||
* Fedora 32 and newer
|
||||
* Debian 10 and newer
|
||||
* Ubuntu 14.04 and newer
|
||||
* Fedora 24 and newer
|
||||
* Debian 8 and newer
|
||||
|
||||
## Quick start & Electron Fiddle
|
||||
|
||||
@@ -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-121.0.6116.0
|
||||
image: e-120.0.6099.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -94,6 +94,11 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
@@ -156,6 +161,7 @@ for:
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
@@ -172,7 +178,6 @@ for:
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- 7z a nan.zip third_party\nan
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
@@ -188,23 +193,25 @@ for:
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
$manifest_file = "electron/script/zip_manifests/dist_zip.win.$env:TARGET_ARCH.manifest"
|
||||
python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip $manifest_file
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Zip contains files not listed in the manifest $manifest_file"
|
||||
}
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only $env:APPVEYOR_PROJECT_NAME"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip','nan.zip'
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif (
|
||||
$artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} elseif (
|
||||
$artifact_name -eq 'nan.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
@@ -236,10 +243,10 @@ for:
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist nan.zip (appveyor-retry appveyor PushArtifact nan.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
@@ -275,12 +282,12 @@ for:
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','electron.lib', 'nan.zip')
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','electron.lib')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build Arm on X64 Windows") {
|
||||
$jobId = $job.jobId
|
||||
foreach($artifact_name in $artifacts_to_download) {
|
||||
if ($artifact_name -eq 'electron.lib') {
|
||||
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
|
||||
$outfile = "src\out\Default\$artifact_name"
|
||||
} else {
|
||||
$outfile = $artifact_name
|
||||
@@ -299,7 +306,6 @@ for:
|
||||
}
|
||||
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
|
||||
- ps: 7z x -y -osrc node_headers.zip
|
||||
- ps: 7z x -y -osrc nan.zip
|
||||
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
|
||||
23
appveyor.yml
23
appveyor.yml
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-121.0.6116.0
|
||||
image: e-120.0.6099.0
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -92,6 +92,11 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
git checkout f76550541c751f956ef9287f2695a6c8a74bf709
|
||||
cd ..
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
@@ -154,6 +159,7 @@ for:
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
@@ -185,14 +191,19 @@ for:
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- ps: |
|
||||
$manifest_file = "electron/script/zip_manifests/dist_zip.win.$env:TARGET_ARCH.manifest"
|
||||
python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip $manifest_file
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "Zip contains files not listed in the manifest $manifest_file"
|
||||
}
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
|
||||
Write-warning "Skipping artifact validation for doc-only $env:APPVEYOR_PROJECT_NAME"
|
||||
} else {
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
|
||||
foreach($artifact_name in $artifacts_to_validate) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
@@ -230,6 +241,7 @@ for:
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
@@ -266,12 +278,12 @@ for:
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
|
||||
$artifacts_to_download = @('dist.zip','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build") {
|
||||
$jobId = $job.jobId
|
||||
foreach($artifact_name in $artifacts_to_download) {
|
||||
if ($artifact_name -eq 'electron.lib') {
|
||||
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
|
||||
$outfile = "src\out\Default\$artifact_name"
|
||||
} else {
|
||||
$outfile = $artifact_name
|
||||
@@ -305,6 +317,7 @@ for:
|
||||
$env:npm_config_arch = "ia32"
|
||||
}
|
||||
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log
|
||||
- echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log
|
||||
- cd ..
|
||||
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
- echo "About to verify mksnapshot"
|
||||
|
||||
@@ -24,6 +24,10 @@ enable_printing = true
|
||||
angle_enable_vulkan_validation_layers = false
|
||||
dawn_enable_vulkan_validation_layers = false
|
||||
|
||||
# Removes dxc dll's that are only used experimentally.
|
||||
# See https://bugs.chromium.org/p/chromium/issues/detail?id=1474897
|
||||
dawn_use_built_dxc = false
|
||||
|
||||
# These are disabled because they cause the zip manifest to differ between
|
||||
# testing and release builds.
|
||||
# See https://chromium-review.googlesource.com/c/chromium/src/+/2774898.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
|
||||
import collections
|
||||
import os
|
||||
|
||||
@@ -8,6 +8,5 @@
|
||||
"node_cli_inspect": "1",
|
||||
"embedded_asar_integrity_validation": "0",
|
||||
"only_load_app_from_asar": "0",
|
||||
"load_browser_process_specific_v8_snapshot": "0",
|
||||
"grant_file_protocol_extra_privileges": "1"
|
||||
"load_browser_process_specific_v8_snapshot": "0"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import contextlib
|
||||
import sys
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'asar',
|
||||
alwaysHasNode: true,
|
||||
targetDeletesNodeGlobals: true
|
||||
});
|
||||
4
build/webpack/webpack.config.node.js
Normal file
4
build/webpack/webpack.config.node.js
Normal file
@@ -0,0 +1,4 @@
|
||||
module.exports = require('./webpack.config.base')({
|
||||
target: 'node',
|
||||
alwaysHasNode: true
|
||||
});
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -15,4 +15,15 @@ buildflag_header("buildflags") {
|
||||
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
|
||||
"OVERRIDE_LOCATION_PROVIDER=$enable_fake_location_provider",
|
||||
]
|
||||
|
||||
if (electron_vendor_version != "") {
|
||||
result = string_split(electron_vendor_version, ":")
|
||||
flags += [
|
||||
"HAS_VENDOR_VERSION=true",
|
||||
"VENDOR_VERSION_NAME=\"${result[0]}\"",
|
||||
"VENDOR_VERSION_VALUE=\"${result[1]}\"",
|
||||
]
|
||||
} else {
|
||||
flags += [ "HAS_VENDOR_VERSION=false" ]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,4 +23,10 @@ declare_args() {
|
||||
# Packagers and vendor builders should set this in gn args to avoid running
|
||||
# the script that reads git tag.
|
||||
override_electron_version = ""
|
||||
|
||||
# Define an extra item that will show in process.versions, the value must
|
||||
# be in the format of "key:value".
|
||||
# Packagers and vendor builders can set this in gn args to attach extra info
|
||||
# about the build in the binary.
|
||||
electron_vendor_version = ""
|
||||
}
|
||||
|
||||
@@ -256,6 +256,8 @@ static_library("chrome") {
|
||||
sources += [
|
||||
"//chrome/browser/bad_message.cc",
|
||||
"//chrome/browser/bad_message.h",
|
||||
"//chrome/browser/printing/prefs_util.cc",
|
||||
"//chrome/browser/printing/prefs_util.h",
|
||||
"//chrome/browser/printing/print_job.cc",
|
||||
"//chrome/browser/printing/print_job.h",
|
||||
"//chrome/browser/printing/print_job_manager.cc",
|
||||
|
||||
@@ -377,6 +377,35 @@ page.
|
||||
|
||||
Emitted whenever there is a GPU info update.
|
||||
|
||||
### Event: 'gpu-process-crashed' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `killed` boolean
|
||||
|
||||
Emitted when the GPU process crashes or is killed.
|
||||
|
||||
**Deprecated:** This event is superceded by the `child-process-gone` event
|
||||
which contains more information about why the child process disappeared. It
|
||||
isn't always because it crashed. The `killed` boolean can be replaced by
|
||||
checking `reason === 'killed'` when you switch to that event.
|
||||
|
||||
### Event: 'renderer-process-crashed' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `webContents` [WebContents](web-contents.md)
|
||||
* `killed` boolean
|
||||
|
||||
Emitted when the renderer process of `webContents` crashes or is killed.
|
||||
|
||||
**Deprecated:** This event is superceded by the `render-process-gone` event
|
||||
which contains more information about why the render process disappeared. It
|
||||
isn't always because it crashed. The `killed` boolean can be replaced by
|
||||
checking `reason === 'killed'` when you switch to that event.
|
||||
|
||||
### Event: 'render-process-gone'
|
||||
|
||||
Returns:
|
||||
@@ -1249,10 +1278,10 @@ Returns `boolean` - Whether the current desktop environment is Unity launcher.
|
||||
### `app.getLoginItemSettings([options])` _macOS_ _Windows_
|
||||
|
||||
* `options` Object (optional)
|
||||
* `type` string (optional) _macOS_ - Can be one of `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
|
||||
* `serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
|
||||
* `path` string (optional) _Windows_ - The executable path to compare against. Defaults to `process.execPath`.
|
||||
* `args` string[] (optional) _Windows_ - The command-line arguments to compare against. Defaults to an empty array.
|
||||
* `path` string (optional) _Windows_ - The executable path to compare against.
|
||||
Defaults to `process.execPath`.
|
||||
* `args` string[] (optional) _Windows_ - The command-line arguments to compare
|
||||
against. Defaults to an empty array.
|
||||
|
||||
If you provided `path` and `args` options to `app.setLoginItemSettings`, then you
|
||||
need to pass the same arguments here for `openAtLogin` to be set correctly.
|
||||
@@ -1260,11 +1289,17 @@ need to pass the same arguments here for `openAtLogin` to be set correctly.
|
||||
Returns `Object`:
|
||||
|
||||
* `openAtLogin` boolean - `true` if the app is set to open at login.
|
||||
* `openAsHidden` boolean _macOS_ _Deprecated_ - `true` if the app is set to open as hidden at login. This does not work on macOS 13 and up.
|
||||
* `wasOpenedAtLogin` boolean _macOS_ _Deprecated_ - `true` if the app was opened at login automatically. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
|
||||
* `wasOpenedAsHidden` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
|
||||
* `restoreState` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
|
||||
* `status` string _macOS_ - can be one of `not-registered`, `enabled`, `requires-approval`, or `not-found`.
|
||||
* `openAsHidden` boolean _macOS_ - `true` if the app is set to open as hidden at login.
|
||||
This setting is not available on [MAS builds][mas-builds].
|
||||
* `wasOpenedAtLogin` boolean _macOS_ - `true` if the app was opened at login
|
||||
automatically. This setting is not available on [MAS builds][mas-builds].
|
||||
* `wasOpenedAsHidden` boolean _macOS_ - `true` if the app was opened as a hidden login
|
||||
item. This indicates that the app should not open any windows at startup.
|
||||
This setting is not available on [MAS builds][mas-builds].
|
||||
* `restoreState` boolean _macOS_ - `true` if the app was opened as a login item that
|
||||
should restore the state from the previous session. This indicates that the
|
||||
app should restore the windows that were open the last time the app was
|
||||
closed. This setting is not available on [MAS builds][mas-builds].
|
||||
* `executableWillLaunchAtLogin` boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
|
||||
* `launchItems` Object[] _Windows_
|
||||
* `name` string _Windows_ - name value of a registry entry.
|
||||
@@ -1278,14 +1313,10 @@ Returns `Object`:
|
||||
* `settings` Object
|
||||
* `openAtLogin` boolean (optional) - `true` to open the app at login, `false` to remove
|
||||
the app as a login item. Defaults to `false`.
|
||||
* `openAsHidden` boolean (optional) _macOS_ _Deprecated_ - `true` to open the app as hidden. Defaults to `false`. The user can edit this setting from the System Preferences so `app.getLoginItemSettings().wasOpenedAsHidden` should be checked when the app is opened to know the current value. This setting is not available on [MAS build
|
||||
s][mas-builds] or on macOS 13 and up.
|
||||
* `type` string (optional) _macOS_ - The type of service to add as a login item. Defaults to `mainAppService`. Only available on macOS 13 and up.
|
||||
* `mainAppService` - The primary application.
|
||||
* `agentService` - The property list name for a launch agent. The property list name must correspond to a property list in the app’s `Contents/Library/LaunchAgents` directory.
|
||||
* `daemonService` string (optional) _macOS_ - The property list name for a launch agent. The property list name must correspond to a property list in the app’s `Contents/Library/LaunchDaemons` directory.
|
||||
* `loginItemService` string (optional) _macOS_ - The property list name for a login item service. The property list name must correspond to a property list in the app’s `Contents/Library/LoginItems` directory.
|
||||
* `serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
|
||||
* `openAsHidden` boolean (optional) _macOS_ - `true` to open the app as hidden. Defaults to
|
||||
`false`. The user can edit this setting from the System Preferences so
|
||||
`app.getLoginItemSettings().wasOpenedAsHidden` should be checked when the app
|
||||
is opened to know the current value. This setting is not available on [MAS builds][mas-builds].
|
||||
* `path` string (optional) _Windows_ - The executable to launch at login.
|
||||
Defaults to `process.execPath`.
|
||||
* `args` string[] (optional) _Windows_ - The command-line arguments to pass to
|
||||
@@ -1294,7 +1325,6 @@ s][mas-builds] or on macOS 13 and up.
|
||||
* `enabled` boolean (optional) _Windows_ - `true` will change the startup approved registry key and `enable / disable` the App in Task Manager and Windows Settings.
|
||||
Defaults to `true`.
|
||||
* `name` string (optional) _Windows_ - value name to write into registry. Defaults to the app's AppUserModelId().
|
||||
|
||||
Set the app's login item settings.
|
||||
|
||||
To work with Electron's `autoUpdater` on Windows, which uses [Squirrel][Squirrel-Windows],
|
||||
@@ -1319,8 +1349,6 @@ app.setLoginItemSettings({
|
||||
})
|
||||
```
|
||||
|
||||
For more information about setting different services as login items on macOS 13 and up, see [`SMAppService`](https://developer.apple.com/documentation/servicemanagement/smappservice?language=objc).
|
||||
|
||||
### `app.isAccessibilitySupportEnabled()` _macOS_ _Windows_
|
||||
|
||||
Returns `boolean` - `true` if Chrome's accessibility support is enabled,
|
||||
@@ -1468,6 +1496,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_
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Make HTTP/HTTPS requests.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)<br />
|
||||
Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-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._
|
||||
|
||||
`ClientRequest` implements the [Writable Stream](https://nodejs.org/api/stream.html#stream_writable_streams)
|
||||
@@ -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)
|
||||
|
||||
@@ -100,7 +100,7 @@ longer than the maximum length will be truncated.
|
||||
|
||||
### `crashReporter.getLastCrashReport()`
|
||||
|
||||
Returns [`CrashReport | null`](structures/crash-report.md) - The date and ID of the
|
||||
Returns [`CrashReport`](structures/crash-report.md) - The date and ID of the
|
||||
last crash report. Only crash reports that have been uploaded will be returned;
|
||||
even if a crash report is present on disk it will not be returned until it is
|
||||
uploaded. In the case that there are no uploaded reports, `null` is returned.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
> 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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Handle responses to HTTP/HTTPS requests.
|
||||
|
||||
Process: [Main](../glossary.md#main-process)<br />
|
||||
Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-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._
|
||||
|
||||
`IncomingMessage` implements the [Readable Stream](https://nodejs.org/api/stream.html#stream_readable_streams)
|
||||
|
||||
@@ -51,6 +51,13 @@ Check the _Size requirements_ section in [this article][icons].
|
||||
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-icons
|
||||
|
||||
:::note
|
||||
|
||||
EXIF metadata is currently not supported and will not be taken into account during
|
||||
image encoding and decoding.
|
||||
|
||||
:::
|
||||
|
||||
## High Resolution Image
|
||||
|
||||
On platforms that have high-DPI support such as Apple Retina displays, you can
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Issue HTTP/HTTPS requests using Chromium's native networking library
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
Process: [Main](../glossary.md#main-process), [Utility](../glossary.md#utility-process)
|
||||
|
||||
The `net` module is a client-side API for issuing HTTP(S) requests. It is
|
||||
similar to the [HTTP](https://nodejs.org/api/http.html) and
|
||||
@@ -119,6 +119,9 @@ protocol.handle('https', (req) => {
|
||||
})
|
||||
```
|
||||
|
||||
Note: in the [utility process](../glossary.md#utility-process) custom protocols
|
||||
are not supported.
|
||||
|
||||
### `net.isOnline()`
|
||||
|
||||
Returns `boolean` - Whether there is currently internet connection.
|
||||
|
||||
@@ -61,8 +61,9 @@ The `protocol` module has the following methods:
|
||||
module gets emitted and can be called only once.
|
||||
|
||||
Registers the `scheme` as standard, secure, bypasses content security policy for
|
||||
resources, allows registering ServiceWorker, supports fetch API, and streaming
|
||||
video/audio. Specify a privilege with the value of `true` to enable the capability.
|
||||
resources, allows registering ServiceWorker, supports fetch API, streaming
|
||||
video/audio, and V8 code cache. Specify a privilege with the value of `true` to
|
||||
enable the capability.
|
||||
|
||||
An example of registering a privileged scheme, that bypasses Content Security
|
||||
Policy:
|
||||
@@ -122,7 +123,7 @@ Example:
|
||||
|
||||
```js
|
||||
const { app, net, protocol } = require('electron')
|
||||
const path = require('node:path')
|
||||
const { join } = require('node:path')
|
||||
const { pathToFileURL } = require('url')
|
||||
|
||||
protocol.registerSchemesAsPrivileged([
|
||||
@@ -145,19 +146,9 @@ app.whenReady().then(() => {
|
||||
headers: { 'content-type': 'text/html' }
|
||||
})
|
||||
}
|
||||
// NB, this checks for paths that escape the bundle, e.g.
|
||||
// NB, this does not check for paths that escape the bundle, e.g.
|
||||
// app://bundle/../../secret_file.txt
|
||||
const pathToServe = path.resolve(__dirname, pathname)
|
||||
const relativePath = path.relative(__dirname, pathToServe)
|
||||
const isSafe = relativePath && !relativePath.startsWith('..') && !path.isAbsolute(relativePath)
|
||||
if (!isSafe) {
|
||||
return new Response('bad', {
|
||||
status: 400,
|
||||
headers: { 'content-type': 'text/html' }
|
||||
})
|
||||
}
|
||||
|
||||
return net.fetch(pathToFileURL(pathToServe).toString())
|
||||
return net.fetch(pathToFileURL(join(__dirname, pathname)).toString())
|
||||
} else if (host === 'api') {
|
||||
return net.fetch('https://api.my-server.com/' + pathname, {
|
||||
method: req.method,
|
||||
|
||||
@@ -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.
|
||||
@@ -903,6 +813,8 @@ 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.
|
||||
* `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.
|
||||
* `callback` Function
|
||||
@@ -951,6 +863,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.
|
||||
@@ -1356,6 +1270,10 @@ registered.
|
||||
Sets the directory to store the generated JS [code cache](https://v8.dev/blog/code-caching-for-devs) for this session. The directory is not required to be created by the user before this call, the runtime will create if it does not exist otherwise will use the existing directory. If directory cannot be created, then code cache will not be used and all operations related to code cache will fail silently inside the runtime. By default, the directory will be `Code Cache` under the
|
||||
respective user data folder.
|
||||
|
||||
Note that by default code cache is only enabled for http(s) URLs, to enable code
|
||||
cache for custom protocols, `codeCache: true` and `standard: true` must be
|
||||
specified when registering the protocol.
|
||||
|
||||
#### `ses.clearCodeCaches(options)`
|
||||
|
||||
* `options` Object
|
||||
|
||||
@@ -9,3 +9,5 @@
|
||||
* `supportFetchAPI` boolean (optional) - Default false.
|
||||
* `corsEnabled` boolean (optional) - Default false.
|
||||
* `stream` boolean (optional) - Default false.
|
||||
* `codeCache` boolean (optional) - Enable V8 code cache for the scheme, only
|
||||
works when `standard` is also set to true. Default false.
|
||||
|
||||
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".
|
||||
@@ -9,4 +9,4 @@
|
||||
* `array` Array\<unknown>
|
||||
* `dictionary` Record\<string, unknown>
|
||||
|
||||
This type is a helper alias, no object will ever exist of this type.
|
||||
This type is a helper alias, no object will never exist of this type.
|
||||
|
||||
@@ -460,6 +460,20 @@ win.webContents.on('will-prevent-unload', (event) => {
|
||||
|
||||
**Note:** This will be emitted for `BrowserViews` but will _not_ be respected - this is because we have chosen not to tie the `BrowserView` lifecycle to its owning BrowserWindow should one exist per the [specification](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event).
|
||||
|
||||
#### Event: 'crashed' _Deprecated_
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `killed` boolean
|
||||
|
||||
Emitted when the renderer process crashes or is killed.
|
||||
|
||||
**Deprecated:** This event is superceded by the `render-process-gone` event
|
||||
which contains more information about why the render process disappeared. It
|
||||
isn't always because it crashed. The `killed` boolean can be replaced by
|
||||
checking `reason === 'killed'` when you switch to that event.
|
||||
|
||||
#### Event: 'render-process-gone'
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# webUtils
|
||||
|
||||
> A utility layer to interact with Web API objects (Files, Blobs, etc.)
|
||||
|
||||
Process: [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
## Methods
|
||||
|
||||
The `webUtils` module has the following methods:
|
||||
|
||||
### `webUtils.getPathForFile(file)`
|
||||
|
||||
* `file` File - A web [File](https://developer.mozilla.org/en-US/docs/Web/API/File) object.
|
||||
|
||||
Returns `string` - The file system path that this `File` object points to. In the case where the object passed in is not a `File` object an exception is thrown. In the case where the File object passed in was constructed in JS and is not backed by a file on disk an empty string is returned.
|
||||
|
||||
This method superceded the previous augmentation to the `File` object with the `path` property. An example is included below.
|
||||
|
||||
```js
|
||||
// Before
|
||||
const oldPath = document.querySelector('input').files[0].path
|
||||
|
||||
// After
|
||||
const { webUtils } = require('electron')
|
||||
const newPath = webUtils.getPathForFile(document.querySelector('input').files[0])
|
||||
```
|
||||
@@ -986,6 +986,14 @@ ipcRenderer.on('ping', () => {
|
||||
})
|
||||
```
|
||||
|
||||
### Event: 'crashed' _Deprecated_
|
||||
|
||||
Fired when the renderer process crashes or is killed.
|
||||
|
||||
**Deprecated:** This event is superceded by the `render-process-gone` event
|
||||
which contains more information about why the render process disappeared. It
|
||||
isn't always because it crashed.
|
||||
|
||||
### Event: 'render-process-gone'
|
||||
|
||||
Returns:
|
||||
|
||||
@@ -12,62 +12,6 @@ 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 (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
|
||||
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:
|
||||
|
||||
```js
|
||||
contextBridge.exposeInMainWorld('app', {
|
||||
onEvent: (cb) => ipcRenderer.on('foo', (e, ...args) => cb(args))
|
||||
})
|
||||
```
|
||||
|
||||
### Removed: `renderer-process-crashed` event on `app`
|
||||
|
||||
The `renderer-process-crashed` event on `app` has been removed.
|
||||
Use the new `render-process-gone` event instead.
|
||||
|
||||
```js
|
||||
// Removed
|
||||
app.on('renderer-process-crashed', (event, webContents, killed) => { /* ... */ })
|
||||
|
||||
// Replace with
|
||||
app.on('render-process-gone', (event, webContents, details) => { /* ... */ })
|
||||
```
|
||||
|
||||
### Removed: `crashed` event on `WebContents` and `<webview>`
|
||||
|
||||
The `crashed` events on `WebContents` and `<webview>` have been removed.
|
||||
Use the new `render-process-gone` event instead.
|
||||
|
||||
```js
|
||||
// Removed
|
||||
win.webContents.on('crashed', (event, killed) => { /* ... */ })
|
||||
webview.addEventListener('crashed', (event) => { /* ... */ })
|
||||
|
||||
// Replace with
|
||||
win.webContents.on('render-process-gone', (event, details) => { /* ... */ })
|
||||
webview.addEventListener('render-process-gone', (event) => { /* ... */ })
|
||||
```
|
||||
|
||||
### Removed: `gpu-process-crashed` event on `app`
|
||||
|
||||
The `gpu-process-crashed` event on `app` has been removed.
|
||||
Use the new `child-process-gone` event instead.
|
||||
|
||||
```js
|
||||
// Removed
|
||||
app.on('gpu-process-crashed', (event, killed) => { /* ... */ })
|
||||
|
||||
// Replace with
|
||||
app.on('child-process-gone', (event, details) => { /* ... */ })
|
||||
```
|
||||
|
||||
## Planned Breaking API Changes (28.0)
|
||||
|
||||
### Behavior Changed: `WebContents.backgroundThrottling` set to false affects all `WebContents` in the host `BrowserWindow`
|
||||
@@ -211,6 +155,18 @@ systemPreferences.on('high-contrast-color-scheme-changed', () => { /* ... */ })
|
||||
nativeTheme.on('updated', () => { /* ... */ })
|
||||
```
|
||||
|
||||
### Removed: Some `window.setVibrancy` options on macOS
|
||||
|
||||
The following vibrancy options have been removed:
|
||||
|
||||
* 'light'
|
||||
* 'medium-light'
|
||||
* 'dark'
|
||||
* 'ultra-dark'
|
||||
* 'appearance-based'
|
||||
|
||||
These were previously deprecated and have been removed by Apple in 10.15.
|
||||
|
||||
### Removed: `webContents.getPrinters`
|
||||
|
||||
The `webContents.getPrinters` method has been removed. Use
|
||||
|
||||
@@ -196,32 +196,19 @@ support via Electron's support for the [Chrome DevTools Protocol][] (CDP).
|
||||
|
||||
### Install dependencies
|
||||
|
||||
You can install Playwright through your preferred Node.js package manager. The Playwright team
|
||||
recommends using the `PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD` environment variable to avoid
|
||||
unnecessary browser downloads when testing an Electron app.
|
||||
|
||||
```sh npm2yarn
|
||||
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1 npm install --save-dev playwright
|
||||
```
|
||||
|
||||
Playwright also comes with its own test runner, Playwright Test, which is built for end-to-end
|
||||
testing. You can also install it as a dev dependency in your project:
|
||||
You can install Playwright through your preferred Node.js package manager. It comes with its
|
||||
own [test runner][playwright-intro], which is built for end-to-end testing:
|
||||
|
||||
```sh npm2yarn
|
||||
npm install --save-dev @playwright/test
|
||||
```
|
||||
|
||||
:::caution Dependencies
|
||||
This tutorial was written `playwright@1.16.3` and `@playwright/test@1.16.3`. Check out
|
||||
This tutorial was written with `@playwright/test@1.41.1`. Check out
|
||||
[Playwright's releases][playwright-releases] page to learn about
|
||||
changes that might affect the code below.
|
||||
:::
|
||||
|
||||
:::info Using third-party test runners
|
||||
If you're interested in using an alternative test runner (e.g. Jest or Mocha), check out
|
||||
Playwright's [Third-Party Test Runner][playwright-test-runners] guide.
|
||||
:::
|
||||
|
||||
### Write your tests
|
||||
|
||||
Playwright launches your app in development mode through the `_electron.launch` API.
|
||||
@@ -229,8 +216,7 @@ To point this API to your Electron app, you can pass the path to your main proce
|
||||
entry point (here, it is `main.js`).
|
||||
|
||||
```js {5} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('launch app', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -242,9 +228,8 @@ test('launch app', async () => {
|
||||
After that, you will access to an instance of Playwright's `ElectronApp` class. This
|
||||
is a powerful class that has access to main process modules for example:
|
||||
|
||||
```js {6-11} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
```js {5-10} @ts-nocheck
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('get isPackaged', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -263,8 +248,7 @@ It can also create individual [Page][playwright-page] objects from Electron Brow
|
||||
For example, to grab the first BrowserWindow and save a screenshot:
|
||||
|
||||
```js {6-7} @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test } = require('@playwright/test')
|
||||
const { test, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('save screenshot', async () => {
|
||||
const electronApp = await electron.launch({ args: ['main.js'] })
|
||||
@@ -275,12 +259,11 @@ test('save screenshot', async () => {
|
||||
})
|
||||
```
|
||||
|
||||
Putting all this together using the PlayWright Test runner, let's create a `example.spec.js`
|
||||
Putting all this together using the Playwright test-runner, let's create a `example.spec.js`
|
||||
test file with a single test and assertion:
|
||||
|
||||
```js title='example.spec.js' @ts-nocheck
|
||||
const { _electron: electron } = require('playwright')
|
||||
const { test, expect } = require('@playwright/test')
|
||||
const { test, expect, _electron: electron } = require('@playwright/test')
|
||||
|
||||
test('example test', async () => {
|
||||
const electronApp = await electron.launch({ args: ['.'] })
|
||||
@@ -316,6 +299,7 @@ Running 1 test using 1 worker
|
||||
:::info
|
||||
Playwright Test will automatically run any files matching the `.*(test|spec)\.(js|ts|mjs)` regex.
|
||||
You can customize this match in the [Playwright Test configuration options][playwright-test-config].
|
||||
It also works with TypeScript out of the box.
|
||||
:::
|
||||
|
||||
:::tip Further reading
|
||||
@@ -473,10 +457,10 @@ test.after.always('cleanup', async t => {
|
||||
|
||||
[chrome-driver]: https://sites.google.com/chromium.org/driver/
|
||||
[Puppeteer]: https://github.com/puppeteer/puppeteer
|
||||
[playwright-intro]: https://playwright.dev/docs/intro
|
||||
[playwright-electron]: https://playwright.dev/docs/api/class-electron/
|
||||
[playwright-electronapplication]: https://playwright.dev/docs/api/class-electronapplication
|
||||
[playwright-page]: https://playwright.dev/docs/api/class-page
|
||||
[playwright-releases]: https://github.com/microsoft/playwright/releases
|
||||
[playwright-releases]: https://playwright.dev/docs/release-notes
|
||||
[playwright-test-config]: https://playwright.dev/docs/api/class-testconfig#test-config-test-match
|
||||
[playwright-test-runners]: https://playwright.dev/docs/test-runners/
|
||||
[Chrome DevTools Protocol]: https://chromedevtools.github.io/devtools-protocol/
|
||||
|
||||
@@ -82,9 +82,9 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
||||
})
|
||||
```
|
||||
|
||||
You can create a `interface.d.ts` declaration file and globally augment the `Window` interface:
|
||||
You can create a `renderer.d.ts` declaration file and globally augment the `Window` interface:
|
||||
|
||||
```ts title='interface.d.ts' @ts-noisolate
|
||||
```ts title='renderer.d.ts' @ts-noisolate
|
||||
export interface IElectronAPI {
|
||||
loadPreferences: () => Promise<void>,
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ process:
|
||||
|
||||
Electron will listen for V8 inspector protocol messages on the specified `port`,
|
||||
an external debugger will need to connect on this port. The default `port` is
|
||||
`5858`.
|
||||
`9229`.
|
||||
|
||||
```shell
|
||||
electron --inspect=5858 your/app
|
||||
electron --inspect=9229 your/app
|
||||
```
|
||||
|
||||
### `--inspect-brk=[port]`
|
||||
|
||||
@@ -9,10 +9,11 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
|
||||
| 28.0.0 | 2023-Oct-11 | 2023-Nov-6 | 2023-Dec-5 | TBD | M120 | TBD | ✅ |
|
||||
| 29.0.0 | 2023-Dec-07 | 2024-Jan-24 | 2024-Feb-20 | 2024-Aug-20 | M122 | v18.19 | ✅ |
|
||||
| 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-27 | M116 | v18.16 | ✅ |
|
||||
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2024-Jan-02 | M114 | v18.15 | ✅ |
|
||||
| 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 | 🚫 |
|
||||
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | 2023-Oct-10 | M108 | v16.17 | 🚫 |
|
||||
@@ -37,6 +38,19 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | 2019-Jul-30 | M66 | v10.2 | 🚫 |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | 2019-Apr-23 | M61 | v8.9 | 🚫 |
|
||||
|
||||
:::info Official support dates may change
|
||||
|
||||
Electron's official support policy is the latest 3 stable releases. Our stable
|
||||
release and end-of-life dates are determined by Chromium, and may be subject to
|
||||
change. While we try to keep our planned release and end-of-life dates frequently
|
||||
updated here, future dates may change if affected by upstream scheduling changes,
|
||||
and may not always be accurately reflected.
|
||||
|
||||
See [Chromium's public release schedule](https://chromiumdash.appspot.com/schedule) for
|
||||
definitive information about Chromium's scheduled release dates.
|
||||
|
||||
:::
|
||||
|
||||
**Notes:**
|
||||
|
||||
* The `-alpha.1`, `-beta.1`, and `stable` dates are our solid release dates.
|
||||
@@ -48,20 +62,10 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
* Since Electron 5, Electron has been publicizing its release dates ([see blog post](https://www.electronjs.org/blog/electron-5-0-timeline)).
|
||||
* Since Electron 6, Electron major versions have been targeting every other Chromium major version. Each Electron stable should happen on the same day as Chrome stable ([see blog post](https://www.electronjs.org/blog/12-week-cadence)).
|
||||
* Since Electron 16, Electron has been releasing major versions on an 8-week cadence in accordance to Chrome's change to a 4-week release cadence ([see blog post](https://www.electronjs.org/blog/8-week-cadence)).
|
||||
* Electron temporarily extended support for Electron 22 until October 10, 2023, to support an extended end-of-life for Windows 7/8/8.1
|
||||
|
||||
## Version support policy
|
||||
|
||||
:::info
|
||||
|
||||
The Electron team will temporarily support Electron 22 until October 10, 2023.
|
||||
This extended support is intended to help Electron developers who still need
|
||||
support for Windows 7/8/8.1, which ended support in Electron 23. The October
|
||||
support date follows the extended support dates from both Chromium and Microsoft.
|
||||
On October 11, the Electron team will drop support back to the latest three
|
||||
stable major versions.
|
||||
|
||||
:::
|
||||
|
||||
The latest three _stable_ major versions are supported by the Electron team.
|
||||
For example, if the latest release is 6.1.x, then the 5.0.x as well
|
||||
as the 4.2.x series are supported. We only support the latest minor release
|
||||
|
||||
@@ -61,19 +61,6 @@ The onlyLoadAppFromAsar fuse changes the search system that Electron uses to loc
|
||||
|
||||
The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is used for the browser process. By default Electron's processes will all use the same V8 snapshot file. When this fuse is enabled the browser process uses the file called `browser_v8_context_snapshot.bin` for its V8 snapshot. The other processes will use the V8 snapshot file that they normally do.
|
||||
|
||||
### `grantFileProtocolExtraPrivileges`
|
||||
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.GrantFileProtocolExtraPrivileges`
|
||||
|
||||
The grantFileProtocolExtraPrivileges fuse changes whether pages loaded from the `file://` protocol are given privileges beyond what they would receive in a traditional web browser. This behavior was core to Electron apps in original versions of Electron but is no longer required as apps should be [serving local files from custom protocols](./security.md#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols) now instead. If you aren't serving pages from `file://` you should disable this fuse.
|
||||
|
||||
The extra privileges granted to the `file://` protocol by this fuse are incompletely documented below:
|
||||
|
||||
* `file://` protocol pages can use `fetch` to load other assets over `file://`
|
||||
* `file://` protocol pages can use service workers
|
||||
* `file://` protocol pages have universal access granted to child frames also running on `file://` protocols regardless of sandbox settings
|
||||
|
||||
## How do I flip the fuses?
|
||||
|
||||
### The easy way
|
||||
|
||||
@@ -91,9 +91,9 @@ The above configuration will download from URLs such as
|
||||
`https://npmmirror.com/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.
|
||||
|
||||
If your mirror serves artifacts with different checksums to the official
|
||||
Electron release you may have to set `electron_use_remote_checksums=1` directly,
|
||||
or configure it in a `.npmrc` file, to force Electron to use the remote `SHASUMS256.txt`
|
||||
file to verify the checksum instead of the embedded checksums.
|
||||
Electron release you may have to set `electron_use_remote_checksums=1` to
|
||||
force Electron to use the remote `SHASUMS256.txt` file to verify the checksum
|
||||
instead of the embedded checksums.
|
||||
|
||||
#### Cache
|
||||
|
||||
|
||||
@@ -280,8 +280,8 @@ selected file path in the `#filePath` element.
|
||||
### Note: legacy approaches
|
||||
|
||||
The `ipcRenderer.invoke` API was added in Electron 7 as a developer-friendly way to tackle two-way
|
||||
IPC from the renderer process. However, a couple of alternative approaches to this IPC pattern
|
||||
exist.
|
||||
IPC from the renderer process. However, there exist a couple alternative approaches to this IPC
|
||||
pattern.
|
||||
|
||||
:::warning Avoid legacy approaches if possible
|
||||
We recommend using `ipcRenderer.invoke` whenever possible. The following two-way renderer-to-main
|
||||
|
||||
@@ -155,7 +155,7 @@ need two Electron modules:
|
||||
windows.
|
||||
|
||||
Because the main process runs Node.js, you can import these as [CommonJS][commonjs]
|
||||
modules at the top of your `main.js` file:
|
||||
modules at the top of your file:
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
@@ -46,7 +46,7 @@ scripts attached to sandboxed renderers will still have a polyfilled subset of N
|
||||
APIs available. A `require` function similar to Node's `require` module is exposed,
|
||||
but can only import a subset of Electron and Node's built-in modules:
|
||||
|
||||
* `electron` (following renderer process modules: `contextBridge`, `crashReporter`, `ipcRenderer`, `nativeImage`, `webFrame`, `webUtils`)
|
||||
* `electron` (following renderer process modules: `contextBridge`, `crashReporter`, `ipcRenderer`, `nativeImage`, `webFrame`)
|
||||
* [`events`](https://nodejs.org/api/events.html)
|
||||
* [`timers`](https://nodejs.org/api/timers.html)
|
||||
* [`url`](https://nodejs.org/api/url.html)
|
||||
|
||||
@@ -759,27 +759,6 @@ function validateSender (frame) {
|
||||
}
|
||||
```
|
||||
|
||||
### 18. Avoid usage of the `file://` protocol and prefer usage of custom protocols
|
||||
|
||||
You should serve local pages from a custom protocol instead of the `file://` protocol.
|
||||
|
||||
#### Why?
|
||||
|
||||
The `file://` protocol gets more privileges in Electron than in a web browser and even in
|
||||
browsers it is treated differently to http/https URLs. Using a custom protocol allows you
|
||||
to be more aligned with classic web url behavior while retaining even more control about
|
||||
what can be loaded and when.
|
||||
|
||||
Pages running on `file://` have unilateral access to every file on your machine meaning
|
||||
that XSS issues can be used to load arbitrary files from the users machine. Using a custom
|
||||
protocol prevents issues like this as you can limit the protocol to only serving a specific
|
||||
set of files.
|
||||
|
||||
#### How?
|
||||
|
||||
Follow the [`protocol.handle`](../api/protocol.md#protocolhandlescheme-handler) examples to
|
||||
learn how to serve files / content from a custom protocol.
|
||||
|
||||
[breaking-changes]: ../breaking-changes.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[browser-view]: ../api/browser-view.md
|
||||
|
||||
@@ -243,11 +243,11 @@ const { app, BrowserWindow } = require('electron/main')
|
||||
For more information, see the [Process Model docs](../tutorial/process-model.md#process-specific-module-aliases-typescript).
|
||||
</details>
|
||||
|
||||
:::warning ES Modules in Electron
|
||||
:::info ES Modules in Electron
|
||||
|
||||
[ECMAScript modules](https://nodejs.org/api/esm.html) (i.e. using `import` to load a module)
|
||||
are currently not directly supported in Electron. You can find more information about the
|
||||
state of ESM in Electron in [electron/electron#21457](https://github.com/electron/electron/issues/21457).
|
||||
are supported in Electron as of Electron 28. You can find more information about the
|
||||
state of ESM in Electron and how to use them in our app in [our ESM guide](../tutorial/esm.md).
|
||||
|
||||
:::
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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" ]
|
||||
|
||||
@@ -67,7 +67,6 @@ auto_filenames = {
|
||||
"docs/api/web-frame-main.md",
|
||||
"docs/api/web-frame.md",
|
||||
"docs/api/web-request.md",
|
||||
"docs/api/web-utils.md",
|
||||
"docs/api/webview-tag.md",
|
||||
"docs/api/window-open.md",
|
||||
"docs/api/structures/bluetooth-device.md",
|
||||
@@ -114,6 +113,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",
|
||||
@@ -152,7 +152,6 @@ auto_filenames = {
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/api/web-utils.ts",
|
||||
"lib/renderer/common-init.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
@@ -215,7 +214,6 @@ auto_filenames = {
|
||||
"lib/browser/api/message-channel.ts",
|
||||
"lib/browser/api/module-list.ts",
|
||||
"lib/browser/api/native-theme.ts",
|
||||
"lib/browser/api/net-client-request.ts",
|
||||
"lib/browser/api/net-fetch.ts",
|
||||
"lib/browser/api/net-log.ts",
|
||||
"lib/browser/api/net.ts",
|
||||
@@ -251,12 +249,12 @@ auto_filenames = {
|
||||
"lib/browser/web-view-events.ts",
|
||||
"lib/common/api/module-list.ts",
|
||||
"lib/common/api/native-image.ts",
|
||||
"lib/common/api/net-client-request.ts",
|
||||
"lib/common/api/shell.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/deprecate.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"package.json",
|
||||
@@ -273,7 +271,6 @@ auto_filenames = {
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-provider.ts",
|
||||
"lib/renderer/api/clipboard.ts",
|
||||
@@ -283,7 +280,6 @@ auto_filenames = {
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/api/web-utils.ts",
|
||||
"lib/renderer/common-init.ts",
|
||||
"lib/renderer/init.ts",
|
||||
"lib/renderer/inspector.ts",
|
||||
@@ -312,7 +308,6 @@ auto_filenames = {
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/webpack-provider.ts",
|
||||
"lib/renderer/api/clipboard.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
@@ -321,7 +316,6 @@ auto_filenames = {
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
"lib/renderer/api/module-list.ts",
|
||||
"lib/renderer/api/web-frame.ts",
|
||||
"lib/renderer/api/web-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal-utils.ts",
|
||||
"lib/renderer/ipc-renderer-internal.ts",
|
||||
"lib/worker/init.ts",
|
||||
@@ -332,10 +326,9 @@ auto_filenames = {
|
||||
"typings/internal-electron.d.ts",
|
||||
]
|
||||
|
||||
asar_bundle_deps = [
|
||||
"lib/asar/fs-wrapper.ts",
|
||||
"lib/asar/init.ts",
|
||||
"lib/common/webpack-provider.ts",
|
||||
node_bundle_deps = [
|
||||
"lib/node/asar-fs-wrapper.ts",
|
||||
"lib/node/init.ts",
|
||||
"package.json",
|
||||
"tsconfig.electron.json",
|
||||
"tsconfig.json",
|
||||
@@ -344,12 +337,15 @@ auto_filenames = {
|
||||
]
|
||||
|
||||
utility_bundle_deps = [
|
||||
"lib/browser/api/net-fetch.ts",
|
||||
"lib/browser/message-port-main.ts",
|
||||
"lib/common/api/net-client-request.ts",
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/init.ts",
|
||||
"lib/common/reset-search-paths.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/utility/api/exports/electron.ts",
|
||||
"lib/utility/api/module-list.ts",
|
||||
"lib/utility/api/net.ts",
|
||||
"lib/utility/init.ts",
|
||||
"lib/utility/parent-port.ts",
|
||||
"package.json",
|
||||
|
||||
@@ -199,6 +199,8 @@ filenames = {
|
||||
"shell/common/language_util_mac.mm",
|
||||
"shell/common/mac/main_application_bundle.h",
|
||||
"shell/common/mac/main_application_bundle.mm",
|
||||
"shell/common/mac/codesign_util.cc",
|
||||
"shell/common/mac/codesign_util.h",
|
||||
"shell/common/node_bindings_mac.cc",
|
||||
"shell/common/node_bindings_mac.h",
|
||||
"shell/common/platform_util_mac.mm",
|
||||
@@ -281,7 +283,6 @@ filenames = {
|
||||
"shell/browser/api/electron_api_menu.h",
|
||||
"shell/browser/api/electron_api_native_theme.cc",
|
||||
"shell/browser/api/electron_api_native_theme.h",
|
||||
"shell/browser/api/electron_api_net.cc",
|
||||
"shell/browser/api/electron_api_net_log.cc",
|
||||
"shell/browser/api/electron_api_net_log.h",
|
||||
"shell/browser/api/electron_api_notification.cc",
|
||||
@@ -307,8 +308,6 @@ filenames = {
|
||||
"shell/browser/api/electron_api_system_preferences.h",
|
||||
"shell/browser/api/electron_api_tray.cc",
|
||||
"shell/browser/api/electron_api_tray.h",
|
||||
"shell/browser/api/electron_api_url_loader.cc",
|
||||
"shell/browser/api/electron_api_url_loader.h",
|
||||
"shell/browser/api/electron_api_utility_process.cc",
|
||||
"shell/browser/api/electron_api_utility_process.h",
|
||||
"shell/browser/api/electron_api_view.cc",
|
||||
@@ -548,8 +547,11 @@ filenames = {
|
||||
"shell/common/api/electron_api_key_weak_map.h",
|
||||
"shell/common/api/electron_api_native_image.cc",
|
||||
"shell/common/api/electron_api_native_image.h",
|
||||
"shell/common/api/electron_api_net.cc",
|
||||
"shell/common/api/electron_api_shell.cc",
|
||||
"shell/common/api/electron_api_testing.cc",
|
||||
"shell/common/api/electron_api_url_loader.cc",
|
||||
"shell/common/api/electron_api_url_loader.h",
|
||||
"shell/common/api/electron_api_v8_util.cc",
|
||||
"shell/common/api/electron_bindings.cc",
|
||||
"shell/common/api/electron_bindings.h",
|
||||
@@ -682,8 +684,6 @@ filenames = {
|
||||
"shell/renderer/api/electron_api_spell_check_client.cc",
|
||||
"shell/renderer/api/electron_api_spell_check_client.h",
|
||||
"shell/renderer/api/electron_api_web_frame.cc",
|
||||
"shell/renderer/api/electron_api_web_utils.cc",
|
||||
"shell/renderer/api/electron_api_web_utils.h",
|
||||
"shell/renderer/browser_exposed_renderer_interfaces.cc",
|
||||
"shell/renderer/browser_exposed_renderer_interfaces.h",
|
||||
"shell/renderer/content_settings_observer.cc",
|
||||
@@ -735,6 +735,8 @@ filenames = {
|
||||
"shell/browser/extensions/electron_extension_host_delegate.h",
|
||||
"shell/browser/extensions/electron_extension_loader.cc",
|
||||
"shell/browser/extensions/electron_extension_loader.h",
|
||||
"shell/browser/extensions/electron_extension_message_filter.cc",
|
||||
"shell/browser/extensions/electron_extension_message_filter.h",
|
||||
"shell/browser/extensions/electron_extension_system_factory.cc",
|
||||
"shell/browser/extensions/electron_extension_system_factory.h",
|
||||
"shell/browser/extensions/electron_extension_system.cc",
|
||||
|
||||
@@ -927,7 +927,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/experimental/iterator",
|
||||
"//third_party/libc++/src/include/experimental/list",
|
||||
"//third_party/libc++/src/include/experimental/map",
|
||||
"//third_party/libc++/src/include/experimental/memory",
|
||||
"//third_party/libc++/src/include/experimental/memory_resource",
|
||||
"//third_party/libc++/src/include/experimental/propagate_const",
|
||||
"//third_party/libc++/src/include/experimental/regex",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
import { wrapFsWithAsar } from './fs-wrapper';
|
||||
|
||||
wrapFsWithAsar(require('fs'));
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as fs from 'fs';
|
||||
|
||||
import { Menu } from 'electron/main';
|
||||
import * as deprecate from '@electron/internal/common/deprecate';
|
||||
|
||||
const bindings = process._linkedBinding('electron_browser_app');
|
||||
const commandLine = process._linkedBinding('electron_common_command_line');
|
||||
@@ -111,3 +112,13 @@ for (const name of events) {
|
||||
webContents.emit(name, event, ...args);
|
||||
});
|
||||
}
|
||||
|
||||
// Deprecation.
|
||||
deprecate.event(app, 'gpu-process-crashed', 'child-process-gone', () => {
|
||||
// the old event is still emitted by App::OnGpuProcessCrashed()
|
||||
return undefined;
|
||||
});
|
||||
|
||||
deprecate.event(app, 'renderer-process-crashed', 'render-process-gone', (event: Electron.Event, webContents: Electron.WebContents, details: Electron.RenderProcessGoneDetails) => {
|
||||
return [event, webContents, details.reason === 'killed'];
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@ import { app } from 'electron/main';
|
||||
import { EventEmitter } from 'events';
|
||||
import * as squirrelUpdate from '@electron/internal/browser/api/auto-updater/squirrel-update-win';
|
||||
|
||||
class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
||||
class AutoUpdater extends EventEmitter {
|
||||
updateAvailable: boolean = false;
|
||||
updateURL: string | null = null;
|
||||
|
||||
@@ -15,7 +15,7 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
||||
}
|
||||
|
||||
getFeedURL () {
|
||||
return this.updateURL ?? '';
|
||||
return this.updateURL;
|
||||
}
|
||||
|
||||
setFeedURL (options: { url: string } | string) {
|
||||
@@ -34,7 +34,7 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
||||
this.updateURL = updateURL;
|
||||
}
|
||||
|
||||
async checkForUpdates () {
|
||||
checkForUpdates () {
|
||||
const url = this.updateURL;
|
||||
if (!url) {
|
||||
return this.emitError(new Error('Update URL is not set'));
|
||||
@@ -43,24 +43,27 @@ class AutoUpdater extends EventEmitter implements Electron.AutoUpdater {
|
||||
return this.emitError(new Error('Can not find Squirrel'));
|
||||
}
|
||||
this.emit('checking-for-update');
|
||||
try {
|
||||
const update = await squirrelUpdate.checkForUpdate(url);
|
||||
squirrelUpdate.checkForUpdate(url, (error, update) => {
|
||||
if (error != null) {
|
||||
return this.emitError(error);
|
||||
}
|
||||
if (update == null) {
|
||||
return this.emit('update-not-available');
|
||||
}
|
||||
this.updateAvailable = true;
|
||||
this.emit('update-available');
|
||||
|
||||
await squirrelUpdate.update(url);
|
||||
const { releaseNotes, version } = update;
|
||||
// Date is not available on Windows, so fake it.
|
||||
const date = new Date();
|
||||
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
|
||||
this.quitAndInstall();
|
||||
squirrelUpdate.update(url, (error) => {
|
||||
if (error != null) {
|
||||
return this.emitError(error);
|
||||
}
|
||||
const { releaseNotes, version } = update;
|
||||
// Date is not available on Windows, so fake it.
|
||||
const date = new Date();
|
||||
this.emit('update-downloaded', {}, releaseNotes, version, date, this.updateURL, () => {
|
||||
this.quitAndInstall();
|
||||
});
|
||||
});
|
||||
} catch (error) {
|
||||
this.emitError(error as Error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Private: Emit both error object and message, this is to keep compatibility
|
||||
|
||||
@@ -15,67 +15,91 @@ const isSameArgs = (args: string[]) => args.length === spawnedArgs.length && arg
|
||||
|
||||
// Spawn a command and invoke the callback when it completes with an error
|
||||
// and the output from standard out.
|
||||
const spawnUpdate = async function (args: string[], options: { detached: boolean }): Promise<string> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const spawnUpdate = function (args: string[], detached: boolean, callback: Function) {
|
||||
let error: Error, errorEmitted: boolean, stderr: string, stdout: string;
|
||||
|
||||
try {
|
||||
// Ensure we don't spawn multiple squirrel processes
|
||||
// Process spawned, same args: Attach events to already running process
|
||||
// Process spawned, different args: Return with error
|
||||
// No process spawned: Spawn new process
|
||||
if (spawnedProcess && !isSameArgs(args)) {
|
||||
throw new Error(`AutoUpdater process with arguments ${args} is already running`);
|
||||
return callback(`AutoUpdater process with arguments ${args} is already running`);
|
||||
} else if (!spawnedProcess) {
|
||||
spawnedProcess = spawn(updateExe, args, {
|
||||
detached: options.detached,
|
||||
detached: detached,
|
||||
windowsHide: true
|
||||
});
|
||||
spawnedArgs = args || [];
|
||||
}
|
||||
} catch (error1) {
|
||||
error = error1 as Error;
|
||||
|
||||
let stdout = '';
|
||||
let stderr = '';
|
||||
|
||||
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
|
||||
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
|
||||
|
||||
spawnedProcess.on('error', (error) => {
|
||||
reject(error);
|
||||
// Shouldn't happen, but still guard it.
|
||||
process.nextTick(function () {
|
||||
return callback(error);
|
||||
});
|
||||
return;
|
||||
}
|
||||
stdout = '';
|
||||
stderr = '';
|
||||
|
||||
spawnedProcess.on('exit', function (code, signal) {
|
||||
spawnedProcess = undefined;
|
||||
spawnedArgs = [];
|
||||
spawnedProcess.stdout.on('data', (data) => { stdout += data; });
|
||||
spawnedProcess.stderr.on('data', (data) => { stderr += data; });
|
||||
|
||||
if (code !== 0) {
|
||||
// Process terminated with error.
|
||||
reject(new Error(`Command failed: ${signal ?? code}\n${stderr}`));
|
||||
} else {
|
||||
// Success.
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
errorEmitted = false;
|
||||
spawnedProcess.on('error', (error) => {
|
||||
errorEmitted = true;
|
||||
spawnedProcess = undefined;
|
||||
spawnedArgs = [];
|
||||
callback(error);
|
||||
});
|
||||
|
||||
return spawnedProcess.on('exit', function (code, signal) {
|
||||
spawnedProcess = undefined;
|
||||
spawnedArgs = [];
|
||||
|
||||
// We may have already emitted an error.
|
||||
if (errorEmitted) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Process terminated with error.
|
||||
if (code !== 0) {
|
||||
return callback(`Command failed: ${signal ?? code}\n${stderr}`);
|
||||
}
|
||||
|
||||
// Success.
|
||||
callback(null, stdout);
|
||||
});
|
||||
};
|
||||
|
||||
// Start an instance of the installed app.
|
||||
export function processStart () {
|
||||
spawnUpdate(['--processStartAndWait', exeName], { detached: true });
|
||||
return spawnUpdate(['--processStartAndWait', exeName], true, function () {});
|
||||
}
|
||||
|
||||
// Download the releases specified by the URL and write new results to stdout.
|
||||
export async function checkForUpdate (updateURL: string): Promise<any> {
|
||||
const stdout = await spawnUpdate(['--checkForUpdate', updateURL], { detached: false });
|
||||
try {
|
||||
// Last line of output is the JSON details about the releases
|
||||
const json = stdout.trim().split('\n').pop();
|
||||
return JSON.parse(json!)?.releasesToApply?.pop?.();
|
||||
} catch {
|
||||
throw new Error(`Invalid result:\n${stdout}`);
|
||||
}
|
||||
export function checkForUpdate (updateURL: string, callback: (error: Error | null, update?: any) => void) {
|
||||
return spawnUpdate(['--checkForUpdate', updateURL], false, function (error: Error, stdout: string) {
|
||||
let ref, ref1, update;
|
||||
if (error != null) {
|
||||
return callback(error);
|
||||
}
|
||||
try {
|
||||
// Last line of output is the JSON details about the releases
|
||||
const json = stdout.trim().split('\n').pop();
|
||||
update = (ref = JSON.parse(json!)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : undefined : undefined : undefined;
|
||||
} catch {
|
||||
return callback(new Error(`Invalid result:\n${stdout}`));
|
||||
}
|
||||
return callback(null, update);
|
||||
});
|
||||
}
|
||||
|
||||
// Update the application to the latest remote version specified by URL.
|
||||
export async function update (updateURL: string): Promise<void> {
|
||||
await spawnUpdate(['--update', updateURL], { detached: false });
|
||||
export function update (updateURL: string, callback: (error: Error) => void) {
|
||||
return spawnUpdate(['--update', updateURL], false, callback);
|
||||
}
|
||||
|
||||
// Is the Update.exe installed with the current application?
|
||||
|
||||
@@ -11,7 +11,7 @@ BrowserWindow.prototype._init = function (this: BWT) {
|
||||
// Avoid recursive require.
|
||||
const { app } = require('electron');
|
||||
|
||||
// Set ID at construction time so it's accessible after
|
||||
// Set ID at constructon time so it's accessible after
|
||||
// underlying window destruction.
|
||||
const id = this.id;
|
||||
Object.defineProperty(this, 'id', {
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as deprecate from '@electron/internal/common/deprecate';
|
||||
|
||||
const binding = process._linkedBinding('electron_browser_crash_reporter');
|
||||
|
||||
class CrashReporter implements Electron.CrashReporter {
|
||||
class CrashReporter {
|
||||
start (options: Electron.CrashReporterStartOptions) {
|
||||
const {
|
||||
productName = app.name,
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
import { EventEmitter } from 'events';
|
||||
const { createPair } = process._linkedBinding('electron_browser_message_port');
|
||||
|
||||
export default class MessageChannelMain extends EventEmitter implements Electron.MessageChannelMain {
|
||||
export default class MessageChannelMain {
|
||||
port1: MessagePortMain;
|
||||
port2: MessagePortMain;
|
||||
constructor () {
|
||||
super();
|
||||
const { port1, port2 } = createPair();
|
||||
this.port1 = new MessagePortMain(port1);
|
||||
this.port2 = new MessagePortMain(port2);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { net, IncomingMessage, Session as SessionT } from 'electron/main';
|
||||
import { ClientRequestConstructorOptions, ClientRequest, IncomingMessage, Session as SessionT } from 'electron/main';
|
||||
import { Readable, Writable, isReadable } from 'stream';
|
||||
import { allowAnyProtocol } from '@electron/internal/browser/api/net-client-request';
|
||||
import { allowAnyProtocol } from '@electron/internal/common/api/net-client-request';
|
||||
|
||||
function createDeferredPromise<T, E extends Error = Error> (): { promise: Promise<T>; resolve: (x: T) => void; reject: (e: E) => void; } {
|
||||
let res: (x: T) => void;
|
||||
@@ -13,7 +13,8 @@ function createDeferredPromise<T, E extends Error = Error> (): { promise: Promis
|
||||
return { promise, resolve: res!, reject: rej! };
|
||||
}
|
||||
|
||||
export function fetchWithSession (input: RequestInfo, init: (RequestInit & {bypassCustomProtocolHandlers?: boolean}) | undefined, session: SessionT): Promise<Response> {
|
||||
export function fetchWithSession (input: RequestInfo, init: (RequestInit & {bypassCustomProtocolHandlers?: boolean}) | undefined, session: SessionT | undefined,
|
||||
request: (options: ClientRequestConstructorOptions | string) => ClientRequest) {
|
||||
const p = createDeferredPromise<Response>();
|
||||
let req: Request;
|
||||
try {
|
||||
@@ -73,7 +74,7 @@ export function fetchWithSession (input: RequestInfo, init: (RequestInit & {bypa
|
||||
// We can't set credentials to same-origin unless there's an origin set.
|
||||
const credentials = req.credentials === 'same-origin' && !origin ? 'include' : req.credentials;
|
||||
|
||||
const r = net.request(allowAnyProtocol({
|
||||
const r = request(allowAnyProtocol({
|
||||
session,
|
||||
method: req.method,
|
||||
url: req.url,
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { IncomingMessage, session } from 'electron/main';
|
||||
import { app, IncomingMessage, session } from 'electron/main';
|
||||
import type { ClientRequestConstructorOptions } from 'electron/main';
|
||||
import { ClientRequest } from '@electron/internal/browser/api/net-client-request';
|
||||
import { ClientRequest } from '@electron/internal/common/api/net-client-request';
|
||||
|
||||
const { isOnline } = process._linkedBinding('electron_browser_net');
|
||||
const { isOnline } = process._linkedBinding('electron_common_net');
|
||||
|
||||
export function request (options: ClientRequestConstructorOptions | string, callback?: (message: IncomingMessage) => void) {
|
||||
if (!app.isReady()) {
|
||||
throw new Error('net module can only be used after app is ready');
|
||||
}
|
||||
return new ClientRequest(options, callback);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ const {
|
||||
isOnBatteryPower
|
||||
} = process._linkedBinding('electron_browser_power_monitor');
|
||||
|
||||
class PowerMonitor extends EventEmitter implements Electron.PowerMonitor {
|
||||
class PowerMonitor extends EventEmitter {
|
||||
constructor () {
|
||||
super();
|
||||
// Don't start the event source until both a) the app is ready and b)
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { fetchWithSession } from '@electron/internal/browser/api/net-fetch';
|
||||
import { net } from 'electron/main';
|
||||
const { fromPartition, fromPath, Session } = process._linkedBinding('electron_browser_session');
|
||||
|
||||
Session.prototype.fetch = function (input: RequestInfo, init?: RequestInit) {
|
||||
return fetchWithSession(input, init, this);
|
||||
return fetchWithSession(input, init, this, net.request);
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import { BrowserWindow, Menu, SharingItem, PopupOptions } from 'electron/main';
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
class ShareMenu extends EventEmitter implements Electron.ShareMenu {
|
||||
class ShareMenu {
|
||||
private menu: Menu;
|
||||
|
||||
constructor (sharingItem: SharingItem) {
|
||||
super();
|
||||
this.menu = new (Menu as any)({ sharingItem });
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Socket } from 'net';
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
const { _fork } = process._linkedBinding('electron_browser_utility_process');
|
||||
|
||||
class ForkUtilityProcess extends EventEmitter implements Electron.UtilityProcess {
|
||||
class ForkUtilityProcess extends EventEmitter {
|
||||
#handle: ElectronInternal.UtilityProcessWrapper | null;
|
||||
#stdout: Duplex | null = null;
|
||||
#stderr: Duplex | null = null;
|
||||
|
||||
@@ -220,6 +220,16 @@ function parsePageSize (pageSize: string | ElectronInternal.PageSize) {
|
||||
let pendingPromise: Promise<any> | undefined;
|
||||
WebContents.prototype.printToPDF = async function (options) {
|
||||
const margins = checkType(options.margins ?? {}, 'object', 'margins');
|
||||
const pageSize = parsePageSize(options.pageSize ?? 'letter');
|
||||
|
||||
const { top, bottom, left, right } = margins;
|
||||
const validHeight = [top, bottom].every(u => u === undefined || u <= pageSize.paperHeight);
|
||||
const validWidth = [left, right].every(u => u === undefined || u <= pageSize.paperWidth);
|
||||
|
||||
if (!validHeight || !validWidth) {
|
||||
throw new Error('margins must be less than or equal to pageSize');
|
||||
}
|
||||
|
||||
const printSettings = {
|
||||
requestID: getNextId(),
|
||||
landscape: checkType(options.landscape ?? false, 'boolean', 'landscape'),
|
||||
@@ -235,7 +245,7 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
pageRanges: checkType(options.pageRanges ?? '', 'string', 'pageRanges'),
|
||||
preferCSSPageSize: checkType(options.preferCSSPageSize ?? false, 'boolean', 'preferCSSPageSize'),
|
||||
generateTaggedPDF: checkType(options.generateTaggedPDF ?? false, 'boolean', 'generateTaggedPDF'),
|
||||
...parsePageSize(options.pageSize ?? 'letter')
|
||||
...pageSize
|
||||
};
|
||||
|
||||
if (this._printToPDF) {
|
||||
@@ -252,13 +262,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) {
|
||||
@@ -272,7 +280,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,
|
||||
@@ -284,7 +292,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,
|
||||
@@ -297,9 +305,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.');
|
||||
@@ -573,6 +581,10 @@ WebContents.prototype._init = function () {
|
||||
ipcMain.emit(channel, event, message);
|
||||
});
|
||||
|
||||
deprecate.event(this, 'crashed', 'render-process-gone', (event: Electron.Event, details: Electron.RenderProcessGoneDetails) => {
|
||||
return [event, details.reason === 'killed'];
|
||||
});
|
||||
|
||||
this.on('render-process-gone', (event, details) => {
|
||||
app.emit('render-process-gone', event, this, details);
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ interface GuestInstance {
|
||||
}
|
||||
|
||||
const webViewManager = process._linkedBinding('electron_browser_web_view_manager');
|
||||
const netBinding = process._linkedBinding('electron_browser_net');
|
||||
const netBinding = process._linkedBinding('electron_common_net');
|
||||
|
||||
const supportedWebViewEvents = Object.keys(webViewEvents);
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
import type * as defaultMenuModule from '@electron/internal/browser/default-menu';
|
||||
import type * as url from 'url';
|
||||
import type * as v8 from 'v8';
|
||||
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
@@ -10,9 +12,6 @@ const Module = require('module') as NodeJS.ModuleInternal;
|
||||
// we need to restore it here.
|
||||
process.argv.splice(1, 1);
|
||||
|
||||
// Clear search paths.
|
||||
require('../common/reset-search-paths');
|
||||
|
||||
// Import common settings.
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
@@ -135,7 +134,7 @@ if (packageJson.desktopName != null) {
|
||||
// Set v8 flags, deliberately lazy load so that apps that do not use this
|
||||
// feature do not pay the price
|
||||
if (packageJson.v8Flags != null) {
|
||||
require('v8').setFlagsFromString(packageJson.v8Flags);
|
||||
(require('v8') as typeof v8).setFlagsFromString(packageJson.v8Flags);
|
||||
}
|
||||
|
||||
app.setAppPath(packagePath);
|
||||
@@ -198,7 +197,7 @@ 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 main = require('url').pathToFileURL(path.join(packagePath, mainStartupScript));
|
||||
const main = (require('url') as typeof url).pathToFileURL(path.join(packagePath, mainStartupScript));
|
||||
loadESM(async (esmLoader: any) => {
|
||||
try {
|
||||
await esmLoader.import(main.toString(), undefined, Object.create(null));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { IpcMainInvokeEvent } from 'electron/main';
|
||||
|
||||
export class IpcMainImpl extends EventEmitter implements Electron.IpcMain {
|
||||
export class IpcMainImpl extends EventEmitter {
|
||||
private _invokeHandlers: Map<string, (e: IpcMainInvokeEvent, ...args: any[]) => void> = new Map();
|
||||
|
||||
constructor () {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
export class MessagePortMain extends EventEmitter implements Electron.MessagePortMain {
|
||||
export class MessagePortMain extends EventEmitter {
|
||||
_internalPort: any;
|
||||
constructor (internalPort: any) {
|
||||
super();
|
||||
|
||||
@@ -21,6 +21,7 @@ export const webViewEvents: Record<string, readonly string[]> = {
|
||||
'did-navigate-in-page': ['url', 'isMainFrame', 'frameProcessId', 'frameRoutingId'],
|
||||
'-focus-change': ['focus'],
|
||||
close: [],
|
||||
crashed: [],
|
||||
'render-process-gone': ['details'],
|
||||
'plugin-crashed': ['name', 'version'],
|
||||
destroyed: [],
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import * as url from 'url';
|
||||
import { Readable, Writable } from 'stream';
|
||||
import { app } from 'electron/main';
|
||||
import type { ClientRequestConstructorOptions, UploadProgress } from 'electron/main';
|
||||
import type {
|
||||
ClientRequestConstructorOptions,
|
||||
UploadProgress
|
||||
} from 'electron/common';
|
||||
|
||||
const {
|
||||
isValidHeaderName,
|
||||
isValidHeaderValue,
|
||||
createURLLoader
|
||||
} = process._linkedBinding('electron_browser_net');
|
||||
const { Session } = process._linkedBinding('electron_browser_session');
|
||||
} = process._linkedBinding('electron_common_net');
|
||||
|
||||
const kHttpProtocols = new Set(['http:', 'https:']);
|
||||
|
||||
@@ -283,14 +284,17 @@ function parseOptions (optionsIn: ClientRequestConstructorOptions | string): Nod
|
||||
const key = name.toLowerCase();
|
||||
urlLoaderOptions.headers[key] = { name, value };
|
||||
}
|
||||
if (options.session) {
|
||||
if (!(options.session instanceof Session)) { throw new TypeError('`session` should be an instance of the Session class'); }
|
||||
urlLoaderOptions.session = options.session;
|
||||
} else if (options.partition) {
|
||||
if (typeof options.partition === 'string') {
|
||||
urlLoaderOptions.partition = options.partition;
|
||||
} else {
|
||||
throw new TypeError('`partition` should be a string');
|
||||
if (process.type !== 'utility') {
|
||||
const { Session } = process._linkedBinding('electron_browser_session');
|
||||
if (options.session) {
|
||||
if (!(options.session instanceof Session)) { throw new TypeError('`session` should be an instance of the Session class'); }
|
||||
urlLoaderOptions.session = options.session;
|
||||
} else if (options.partition) {
|
||||
if (typeof options.partition === 'string') {
|
||||
urlLoaderOptions.partition = options.partition;
|
||||
} else {
|
||||
throw new TypeError('`partition` should be a string');
|
||||
}
|
||||
}
|
||||
}
|
||||
return urlLoaderOptions;
|
||||
@@ -312,10 +316,6 @@ export class ClientRequest extends Writable implements Electron.ClientRequest {
|
||||
constructor (options: ClientRequestConstructorOptions | string, callback?: (message: IncomingMessage) => void) {
|
||||
super({ autoDestroy: true });
|
||||
|
||||
if (!app.isReady()) {
|
||||
throw new Error('net module can only be used after app is ready');
|
||||
}
|
||||
|
||||
if (callback) {
|
||||
this.once('response', callback);
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as util from 'util';
|
||||
import type * as stream from 'stream';
|
||||
|
||||
const timers = require('timers');
|
||||
import timers = require('timers');
|
||||
|
||||
type AnyFn = (...args: any[]) => any
|
||||
|
||||
@@ -62,7 +63,7 @@ if (process.type === 'browser' ||
|
||||
|
||||
if (process.platform === 'win32') {
|
||||
// Always returns EOF for stdin stream.
|
||||
const { Readable } = require('stream');
|
||||
const { Readable } = require('stream') as typeof stream;
|
||||
const stdin = new Readable();
|
||||
stdin.push(null);
|
||||
Object.defineProperty(process, 'stdin', {
|
||||
@@ -73,3 +74,43 @@ if (process.platform === 'win32') {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
// Make a fake Electron module that we will insert into the module cache
|
||||
const makeElectronModule = (name: string) => {
|
||||
const electronModule = new Module('electron', null);
|
||||
electronModule.id = 'electron';
|
||||
electronModule.loaded = true;
|
||||
electronModule.filename = name;
|
||||
Object.defineProperty(electronModule, 'exports', {
|
||||
get: () => require('electron')
|
||||
});
|
||||
Module._cache[name] = electronModule;
|
||||
};
|
||||
|
||||
makeElectronModule('electron');
|
||||
makeElectronModule('electron/common');
|
||||
if (process.type === 'browser') {
|
||||
makeElectronModule('electron/main');
|
||||
}
|
||||
if (process.type === 'renderer') {
|
||||
makeElectronModule('electron/renderer');
|
||||
}
|
||||
|
||||
const originalResolveFilename = Module._resolveFilename;
|
||||
|
||||
// 'electron/main', 'electron/renderer' and 'electron/common' are module aliases
|
||||
// of the 'electron' module for TypeScript purposes, i.e., the types for
|
||||
// 'electron/main' consist of only main process modules, etc. It is intentional
|
||||
// that these can be `require()`-ed from both the main process as well as the
|
||||
// renderer process regardless of the names, they're superficial for TypeScript
|
||||
// only.
|
||||
const electronModuleNames = new Set(['electron', 'electron/main', 'electron/renderer', 'electron/common']);
|
||||
Module._resolveFilename = function (request, parent, isMain, options) {
|
||||
if (electronModuleNames.has(request)) {
|
||||
return 'electron';
|
||||
} else {
|
||||
return originalResolveFilename(request, parent, isMain, options);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,69 +0,0 @@
|
||||
import * as path from 'path';
|
||||
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
// We do not want to allow use of the VM module in the renderer process as
|
||||
// it conflicts with Blink's V8::Context internal logic.
|
||||
if (process.type === 'renderer') {
|
||||
const _load = Module._load;
|
||||
Module._load = function (request: string) {
|
||||
if (request === 'vm') {
|
||||
console.warn('The vm module of Node.js is deprecated in the renderer process and will be removed.');
|
||||
}
|
||||
return _load.apply(this, arguments as any);
|
||||
};
|
||||
}
|
||||
|
||||
// Prevent Node from adding paths outside this app to search paths.
|
||||
const resourcesPathWithTrailingSlash = process.resourcesPath + path.sep;
|
||||
const originalNodeModulePaths = Module._nodeModulePaths;
|
||||
Module._nodeModulePaths = function (from: string) {
|
||||
const paths: string[] = originalNodeModulePaths(from);
|
||||
const fromPath = path.resolve(from) + path.sep;
|
||||
// If "from" is outside the app then we do nothing.
|
||||
if (fromPath.startsWith(resourcesPathWithTrailingSlash)) {
|
||||
return paths.filter(function (candidate) {
|
||||
return candidate.startsWith(resourcesPathWithTrailingSlash);
|
||||
});
|
||||
} else {
|
||||
return paths;
|
||||
}
|
||||
};
|
||||
|
||||
// Make a fake Electron module that we will insert into the module cache
|
||||
const makeElectronModule = (name: string) => {
|
||||
const electronModule = new Module('electron', null);
|
||||
electronModule.id = 'electron';
|
||||
electronModule.loaded = true;
|
||||
electronModule.filename = name;
|
||||
Object.defineProperty(electronModule, 'exports', {
|
||||
get: () => require('electron')
|
||||
});
|
||||
Module._cache[name] = electronModule;
|
||||
};
|
||||
|
||||
makeElectronModule('electron');
|
||||
makeElectronModule('electron/common');
|
||||
if (process.type === 'browser') {
|
||||
makeElectronModule('electron/main');
|
||||
}
|
||||
if (process.type === 'renderer') {
|
||||
makeElectronModule('electron/renderer');
|
||||
}
|
||||
|
||||
const originalResolveFilename = Module._resolveFilename;
|
||||
|
||||
// 'electron/main', 'electron/renderer' and 'electron/common' are module aliases
|
||||
// of the 'electron' module for TypeScript purposes, i.e., the types for
|
||||
// 'electron/main' consist of only main process modules, etc. It is intentional
|
||||
// that these can be `require()`-ed from both the main process as well as the
|
||||
// renderer process regardless of the names, they're superficial for TypeScript
|
||||
// only.
|
||||
const electronModuleNames = new Set(['electron', 'electron/main', 'electron/renderer', 'electron/common']);
|
||||
Module._resolveFilename = function (request, parent, isMain, options) {
|
||||
if (electronModuleNames.has(request)) {
|
||||
return 'electron';
|
||||
} else {
|
||||
return originalResolveFilename(request, parent, isMain, options);
|
||||
}
|
||||
};
|
||||
@@ -2,7 +2,9 @@ import { Buffer } from 'buffer';
|
||||
import { constants } from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as util from 'util';
|
||||
|
||||
import type * as Crypto from 'crypto';
|
||||
import type * as os from 'os';
|
||||
|
||||
const asar = process._linkedBinding('electron_common_asar');
|
||||
|
||||
@@ -255,7 +257,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
if (!process.env.ELECTRON_LOG_ASAR_READS) return;
|
||||
if (!logFDs.has(asarPath)) {
|
||||
const logFilename = `${path.basename(asarPath, '.asar')}-access-log.txt`;
|
||||
const logPath = path.join(require('os').tmpdir(), logFilename);
|
||||
const logPath = path.join((require('os') as typeof os).tmpdir(), logFilename);
|
||||
logFDs.set(asarPath, fs.openSync(logPath, 'a'));
|
||||
}
|
||||
fs.writeSync(logFDs.get(asarPath), `${offset}: ${filePath}\n`);
|
||||
49
lib/node/init.ts
Normal file
49
lib/node/init.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
// Initialize ASAR support in fs module.
|
||||
import { wrapFsWithAsar } from './asar-fs-wrapper';
|
||||
wrapFsWithAsar(require('fs'));
|
||||
|
||||
// Hook child_process.fork.
|
||||
import cp = require('child_process'); // eslint-disable-line import/first
|
||||
const originalFork = cp.fork;
|
||||
cp.fork = (modulePath, args?, options?: cp.ForkOptions) => {
|
||||
// Parse optional args.
|
||||
if (args == null) {
|
||||
args = [];
|
||||
} else if (typeof args === 'object' && !Array.isArray(args)) {
|
||||
options = args as cp.ForkOptions;
|
||||
args = [];
|
||||
}
|
||||
// Fallback to original fork to report arg type errors.
|
||||
if (typeof modulePath !== 'string' || !Array.isArray(args) ||
|
||||
(typeof options !== 'object' && typeof options !== 'undefined')) {
|
||||
return originalFork(modulePath, args, options);
|
||||
}
|
||||
// When forking a child script, we setup a special environment to make
|
||||
// the electron binary run like upstream Node.js.
|
||||
options = options ?? {};
|
||||
options.env = Object.create(options.env || process.env);
|
||||
options.env!.ELECTRON_RUN_AS_NODE = '1';
|
||||
// On mac the child script runs in helper executable.
|
||||
if (!options.execPath && process.platform === 'darwin') {
|
||||
options.execPath = process.helperExecPath;
|
||||
}
|
||||
return originalFork(modulePath, args, options);
|
||||
};
|
||||
|
||||
// Prevent Node from adding paths outside this app to search paths.
|
||||
import path = require('path'); // eslint-disable-line import/first
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
const resourcesPathWithTrailingSlash = process.resourcesPath + path.sep;
|
||||
const originalNodeModulePaths = Module._nodeModulePaths;
|
||||
Module._nodeModulePaths = function (from) {
|
||||
const paths: string[] = originalNodeModulePaths(from);
|
||||
const fromPath = path.resolve(from) + path.sep;
|
||||
// If "from" is outside the app then we do nothing.
|
||||
if (fromPath.startsWith(resourcesPathWithTrailingSlash)) {
|
||||
return paths.filter(function (candidate) {
|
||||
return candidate.startsWith(resourcesPathWithTrailingSlash);
|
||||
});
|
||||
} else {
|
||||
return paths;
|
||||
}
|
||||
};
|
||||
@@ -3,30 +3,30 @@ import { EventEmitter } from 'events';
|
||||
const { ipc } = process._linkedBinding('electron_renderer_ipc');
|
||||
|
||||
const internal = false;
|
||||
class IpcRenderer extends EventEmitter implements Electron.IpcRenderer {
|
||||
send (channel: string, ...args: any[]) {
|
||||
return ipc.send(internal, channel, args);
|
||||
}
|
||||
|
||||
sendSync (channel: string, ...args: any[]) {
|
||||
return ipc.sendSync(internal, channel, args);
|
||||
}
|
||||
const ipcRenderer = new EventEmitter() as Electron.IpcRenderer;
|
||||
ipcRenderer.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
|
||||
sendToHost (channel: string, ...args: any[]) {
|
||||
return ipc.sendToHost(channel, args);
|
||||
}
|
||||
ipcRenderer.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args);
|
||||
};
|
||||
|
||||
async invoke (channel: string, ...args: any[]) {
|
||||
const { error, result } = await ipc.invoke(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
ipcRenderer.sendToHost = function (channel, ...args) {
|
||||
return ipc.sendToHost(channel, args);
|
||||
};
|
||||
|
||||
postMessage (channel: string, message: any, transferables: any) {
|
||||
return ipc.postMessage(channel, message, transferables);
|
||||
ipcRenderer.invoke = async function (channel, ...args) {
|
||||
const { error, result } = await ipc.invoke(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default new IpcRenderer();
|
||||
ipcRenderer.postMessage = function (channel: string, message: any, transferables: any) {
|
||||
return ipc.postMessage(channel, message, transferables);
|
||||
};
|
||||
|
||||
export default ipcRenderer;
|
||||
|
||||
@@ -4,6 +4,5 @@ export const rendererModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'contextBridge', loader: () => require('./context-bridge') },
|
||||
{ name: 'crashReporter', loader: () => require('./crash-reporter') },
|
||||
{ name: 'ipcRenderer', loader: () => require('./ipc-renderer') },
|
||||
{ name: 'webFrame', loader: () => require('./web-frame') },
|
||||
{ name: 'webUtils', loader: () => require('./web-utils') }
|
||||
{ name: 'webFrame', loader: () => require('./web-frame') }
|
||||
];
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
const binding = process._linkedBinding('electron_renderer_web_utils');
|
||||
|
||||
export const getPathForFile = binding.getPathForFile;
|
||||
@@ -7,6 +7,16 @@ import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-re
|
||||
|
||||
const Module = require('module') as NodeJS.ModuleInternal;
|
||||
|
||||
// We do not want to allow use of the VM module in the renderer process as
|
||||
// it conflicts with Blink's V8::Context internal logic.
|
||||
const originalModuleLoad = Module._load;
|
||||
Module._load = function (request: string) {
|
||||
if (request === 'vm') {
|
||||
console.warn('The vm module of Node.js is deprecated in the renderer process and will be removed.');
|
||||
}
|
||||
return originalModuleLoad.apply(this, arguments as any);
|
||||
};
|
||||
|
||||
// Make sure globals like "process" and "global" are always available in preload
|
||||
// scripts even after they are deleted in "loaded" script.
|
||||
//
|
||||
@@ -33,9 +43,6 @@ Module.wrapper = [
|
||||
// init.js, we need to restore it here.
|
||||
process.argv.splice(1, 1);
|
||||
|
||||
// Clear search paths.
|
||||
require('../common/reset-search-paths');
|
||||
|
||||
// Import common settings.
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
|
||||
@@ -4,22 +4,20 @@ const { ipc } = process._linkedBinding('electron_renderer_ipc');
|
||||
|
||||
const internal = true;
|
||||
|
||||
class IpcRendererInternal extends EventEmitter implements ElectronInternal.IpcRendererInternal {
|
||||
send (channel: string, ...args: any[]) {
|
||||
return ipc.send(internal, channel, args);
|
||||
export const ipcRendererInternal = new EventEmitter() as any as ElectronInternal.IpcRendererInternal;
|
||||
|
||||
ipcRendererInternal.send = function (channel, ...args) {
|
||||
return ipc.send(internal, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.sendSync = function (channel, ...args) {
|
||||
return ipc.sendSync(internal, channel, args);
|
||||
};
|
||||
|
||||
ipcRendererInternal.invoke = async function<T> (channel: string, ...args: any[]) {
|
||||
const { error, result } = await ipc.invoke<T>(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
|
||||
sendSync (channel: string, ...args: any[]) {
|
||||
return ipc.sendSync(internal, channel, args);
|
||||
}
|
||||
|
||||
async invoke<T> (channel: string, ...args: any[]) {
|
||||
const { error, result } = await ipc.invoke<T>(internal, channel, args);
|
||||
if (error) {
|
||||
throw new Error(`Error invoking remote method '${channel}': ${error}`);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
export const ipcRendererInternal = new IpcRendererInternal();
|
||||
return result;
|
||||
};
|
||||
|
||||
@@ -18,9 +18,5 @@ export const moduleList: ElectronInternal.ModuleEntry[] = [
|
||||
{
|
||||
name: 'webFrame',
|
||||
loader: () => require('@electron/internal/renderer/api/web-frame')
|
||||
},
|
||||
{
|
||||
name: 'webUtils',
|
||||
loader: () => require('@electron/internal/renderer/api/web-utils')
|
||||
}
|
||||
];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import * as events from 'events';
|
||||
import { setImmediate, clearImmediate } from 'timers';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
@@ -126,7 +127,6 @@ function runPreloadScript (preloadSrc: string) {
|
||||
|
||||
// eval in window scope
|
||||
const preloadFn = binding.createPreloadScript(preloadWrapperSrc);
|
||||
const { setImmediate, clearImmediate } = require('timers');
|
||||
const exports = {};
|
||||
|
||||
preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate, clearImmediate, exports, { exports });
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
// Utility side modules, please sort alphabetically.
|
||||
export const utilityNodeModuleList: ElectronInternal.ModuleEntry[] = [];
|
||||
export const utilityNodeModuleList: ElectronInternal.ModuleEntry[] = [
|
||||
{ name: 'net', loader: () => require('./net') }
|
||||
];
|
||||
|
||||
22
lib/utility/api/net.ts
Normal file
22
lib/utility/api/net.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { IncomingMessage } from 'electron/utility';
|
||||
import type { ClientRequestConstructorOptions } from 'electron/utility';
|
||||
import { ClientRequest } from '@electron/internal/common/api/net-client-request';
|
||||
import { fetchWithSession } from '@electron/internal/browser/api/net-fetch';
|
||||
|
||||
const { isOnline, resolveHost } = process._linkedBinding('electron_common_net');
|
||||
|
||||
export function request (options: ClientRequestConstructorOptions | string, callback?: (message: IncomingMessage) => void) {
|
||||
return new ClientRequest(options, callback);
|
||||
}
|
||||
|
||||
export function fetch (input: RequestInfo, init?: RequestInit): Promise<Response> {
|
||||
return fetchWithSession(input, init, undefined, request);
|
||||
}
|
||||
|
||||
exports.resolveHost = resolveHost;
|
||||
|
||||
exports.isOnline = isOnline;
|
||||
|
||||
Object.defineProperty(exports, 'online', {
|
||||
get: () => isOnline()
|
||||
});
|
||||
@@ -1,3 +1,4 @@
|
||||
import { EventEmitter } from 'events';
|
||||
import { pathToFileURL } from 'url';
|
||||
|
||||
import { ParentPort } from '@electron/internal/utility/parent-port';
|
||||
@@ -9,12 +10,11 @@ const entryScript: string = v8Util.getHiddenValue(process, '_serviceStartupScrip
|
||||
// we need to restore it here.
|
||||
process.argv.splice(1, 1, entryScript);
|
||||
|
||||
// Clear search paths.
|
||||
require('../common/reset-search-paths');
|
||||
|
||||
// Import common settings.
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
process._linkedBinding('electron_browser_event_emitter').setEventEmitterPrototype(EventEmitter.prototype);
|
||||
|
||||
const parentPort: ParentPort = new ParentPort();
|
||||
Object.defineProperty(process, 'parentPort', {
|
||||
enumerable: true,
|
||||
|
||||
@@ -2,7 +2,7 @@ import { EventEmitter } from 'events';
|
||||
import { MessagePortMain } from '@electron/internal/browser/message-port-main';
|
||||
const { createParentPort } = process._linkedBinding('electron_utility_parent_port');
|
||||
|
||||
export class ParentPort extends EventEmitter implements Electron.ParentPort {
|
||||
export class ParentPort extends EventEmitter {
|
||||
#port: ParentPort;
|
||||
constructor () {
|
||||
super();
|
||||
|
||||
@@ -6,9 +6,6 @@ const Module = require('module') as NodeJS.ModuleInternal;
|
||||
// init.js, we need to restore it here.
|
||||
process.argv.splice(1, 1);
|
||||
|
||||
// Clear search paths.
|
||||
require('../common/reset-search-paths');
|
||||
|
||||
// Import common settings.
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ downloadArtifact({
|
||||
artifactName: 'electron',
|
||||
force: process.env.force_no_cache === 'true',
|
||||
cacheRoot: process.env.electron_config_cache,
|
||||
checksums: process.env.electron_use_remote_checksums ?? process.env.npm_config_electron_use_remote_checksums ? undefined : require('./checksums.json'),
|
||||
checksums: process.env.electron_use_remote_checksums ? undefined : require('./checksums.json'),
|
||||
platform,
|
||||
arch
|
||||
}).then(extractFile).catch(err => {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
"@electron/fiddle-core": "^1.0.4",
|
||||
"@electron/github-app-auth": "^2.0.0",
|
||||
"@electron/lint-roller": "^1.9.0",
|
||||
"@electron/typescript-definitions": "^8.15.1",
|
||||
"@electron/typescript-definitions": "^8.15.2",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
"@types/basic-auth": "^1.1.3",
|
||||
|
||||
5
patches/DirectXShaderCompiler/.patches
Normal file
5
patches/DirectXShaderCompiler/.patches
Normal file
@@ -0,0 +1,5 @@
|
||||
fix_hlmatrixlowerpass_leaving_call_to_dangling_functionval.patch
|
||||
cherry-pick-a65e511a14b4.patch
|
||||
cherry-pick-bc18aec94c82.patch
|
||||
cherry-pick-bd7aa9779873.patch
|
||||
cherry-pick-2a434fd0af6b.patch
|
||||
419
patches/DirectXShaderCompiler/cherry-pick-2a434fd0af6b.patch
Normal file
419
patches/DirectXShaderCompiler/cherry-pick-2a434fd0af6b.patch
Normal file
@@ -0,0 +1,419 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Maiorano <amaiorano@google.com>
|
||||
Date: Wed, 8 May 2024 13:38:38 -0400
|
||||
Subject: Fix invalid IR from scalarrepl-param-hlsl in ReplaceConstantWithInst
|
||||
(#6556)
|
||||
|
||||
ReplaceConstantWithInst(C, V) replaces uses of C in the current function
|
||||
with V. If such a use C is an instruction I, the it replaces uses of C
|
||||
in I with V. However, this function did not make sure to only perform
|
||||
this replacement if V dominates I. As a result, it may end up replacing
|
||||
uses of C in instructions before the definition of V.
|
||||
|
||||
The fix is to lazily compute the dominator tree in
|
||||
ReplaceConstantWithInst so that we can guard the replacement with that
|
||||
dominance check.
|
||||
|
||||
Bug: chromium:333414294
|
||||
Change-Id: I2a8bf64094298b49a1887cc7c1334e91a745c396
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5525429
|
||||
Reviewed-by: James Price <jrprice@google.com>
|
||||
Reviewed-by: dan sinclair <dsinclair@google.com>
|
||||
|
||||
diff --git a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
index bd429ae98b0e11bbb2b95c68392b82eb222f64a4..1ef9a002a46f3acd14be6e1cb456efcbd398b416 100644
|
||||
--- a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
+++ b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
@@ -3271,15 +3271,34 @@ bool SROA_Helper::DoScalarReplacement(GlobalVariable *GV,
|
||||
return true;
|
||||
}
|
||||
|
||||
-static void ReplaceConstantWithInst(Constant *C, Value *V,
|
||||
+// Replaces uses of constant C in the current function
|
||||
+// with V, when those uses are dominated by V.
|
||||
+// Returns true if it was completely replaced.
|
||||
+static bool ReplaceConstantWithInst(Constant *C, Value *V,
|
||||
IRBuilder<> &Builder) {
|
||||
+ bool bReplacedAll = true;
|
||||
Function *F = Builder.GetInsertBlock()->getParent();
|
||||
+ Instruction *VInst = dyn_cast<Instruction>(V);
|
||||
+ // Lazily calculate dominance
|
||||
+ DominatorTree DT;
|
||||
+ bool Calculated = false;
|
||||
+ auto Dominates = [&](llvm::Instruction *Def, llvm::Instruction *User) {
|
||||
+ if (!Calculated) {
|
||||
+ DT.recalculate(*F);
|
||||
+ Calculated = true;
|
||||
+ }
|
||||
+ return DT.dominates(Def, User);
|
||||
+ };
|
||||
+
|
||||
for (auto it = C->user_begin(); it != C->user_end();) {
|
||||
User *U = *(it++);
|
||||
if (Instruction *I = dyn_cast<Instruction>(U)) {
|
||||
if (I->getParent()->getParent() != F)
|
||||
continue;
|
||||
- I->replaceUsesOfWith(C, V);
|
||||
+ if (VInst && Dominates(VInst, I))
|
||||
+ I->replaceUsesOfWith(C, V);
|
||||
+ else
|
||||
+ bReplacedAll = false;
|
||||
} else {
|
||||
// Skip unused ConstantExpr.
|
||||
if (U->user_empty())
|
||||
@@ -3288,10 +3307,12 @@ static void ReplaceConstantWithInst(Constant *C, Value *V,
|
||||
Instruction *Inst = CE->getAsInstruction();
|
||||
Builder.Insert(Inst);
|
||||
Inst->replaceUsesOfWith(C, V);
|
||||
- ReplaceConstantWithInst(CE, Inst, Builder);
|
||||
+ if (!ReplaceConstantWithInst(CE, Inst, Builder))
|
||||
+ bReplacedAll = false;
|
||||
}
|
||||
}
|
||||
C->removeDeadConstantUsers();
|
||||
+ return bReplacedAll;
|
||||
}
|
||||
|
||||
static void ReplaceUnboundedArrayUses(Value *V, Value *Src) {
|
||||
@@ -3531,7 +3552,8 @@ static bool ReplaceMemcpy(Value *V, Value *Src, MemCpyInst *MC,
|
||||
} else {
|
||||
// Replace Constant with a non-Constant.
|
||||
IRBuilder<> Builder(MC);
|
||||
- ReplaceConstantWithInst(C, Src, Builder);
|
||||
+ if (!ReplaceConstantWithInst(C, Src, Builder))
|
||||
+ return false;
|
||||
}
|
||||
} else {
|
||||
// Try convert special pattern for cbuffer which copy array of float4 to
|
||||
@@ -3539,7 +3561,8 @@ static bool ReplaceMemcpy(Value *V, Value *Src, MemCpyInst *MC,
|
||||
if (!tryToReplaceCBVec4ArrayToScalarArray(V, TyV, Src, TySrc, MC, DL)) {
|
||||
IRBuilder<> Builder(MC);
|
||||
Src = Builder.CreateBitCast(Src, V->getType());
|
||||
- ReplaceConstantWithInst(C, Src, Builder);
|
||||
+ if (!ReplaceConstantWithInst(C, Src, Builder))
|
||||
+ return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -5443,9 +5466,9 @@ void SROA_Parameter_HLSL::flattenArgument(
|
||||
if (Ty->isPointerTy())
|
||||
Ty = Ty->getPointerElementType();
|
||||
unsigned size = DL.getTypeAllocSize(Ty);
|
||||
-#if 0 // HLSL Change
|
||||
+#if 0 // HLSL Change
|
||||
DIExpression *DDIExp = DIB.createBitPieceExpression(debugOffset, size);
|
||||
-#else // HLSL Change
|
||||
+#else // HLSL Change
|
||||
Type *argTy = Arg->getType();
|
||||
if (argTy->isPointerTy())
|
||||
argTy = argTy->getPointerElementType();
|
||||
diff --git a/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.hlsl b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.hlsl
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0f30050e69decaf7da3f2ae645611c1a49a4a719
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.hlsl
|
||||
@@ -0,0 +1,45 @@
|
||||
+// RUN: not %dxc -T ps_6_2 %s 2>&1 | FileCheck %s
|
||||
+
|
||||
+// Validate that copying from static array to local, then back to static
|
||||
+// array does not crash the compiler. This was resulting in an invalid
|
||||
+// ReplaceConstantWithInst from ScalarReplAggregatesHLSL, which would
|
||||
+// result in referenced deleted instruction in a later pass.
|
||||
+
|
||||
+// CHECK: error: Loop must have break.
|
||||
+
|
||||
+static int arr1[10] = (int[10])0;
|
||||
+static int arr2[10] = (int[10])0;
|
||||
+static float result = 0;
|
||||
+ByteAddressBuffer buff : register(t0);
|
||||
+
|
||||
+void foo() {
|
||||
+ int i = 0;
|
||||
+ if (buff.Load(0u)) {
|
||||
+ return;
|
||||
+ }
|
||||
+ arr2[i] = arr1[i];
|
||||
+ result = float(arr1[0]);
|
||||
+}
|
||||
+
|
||||
+struct tint_symbol {
|
||||
+ float4 value : SV_Target0;
|
||||
+};
|
||||
+
|
||||
+float main_inner() {
|
||||
+ foo();
|
||||
+ bool cond = false;
|
||||
+ while (true) {
|
||||
+ if (cond) { break; }
|
||||
+ }
|
||||
+ int arr1_copy[10] = arr1; // constant to local
|
||||
+ arr1 = arr1_copy; // local to constant
|
||||
+ foo();
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+tint_symbol main() {
|
||||
+ float inner_result = main_inner();
|
||||
+ tint_symbol wrapper_result = (tint_symbol)0;
|
||||
+ wrapper_result.value.x = inner_result;
|
||||
+ return wrapper_result;
|
||||
+}
|
||||
diff --git a/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.ll b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.ll
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6ca08ab3a9c500cacb715f63ee407c7add4fc51c
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/DXC/Passes/ScalarReplHLSL/scalarrepl-param-hlsl-const-to-local-and-back.ll
|
||||
@@ -0,0 +1,253 @@
|
||||
+; RUN: %dxopt %s -hlsl-passes-resume -scalarrepl-param-hlsl -S | FileCheck %s
|
||||
+
|
||||
+; The first memcpy, from arr1 to arr1_copy.i, should be replaced by a series of 10 loads and stores,
|
||||
+; while the second memcpy, from arr1_copy.i back to arr1, should be removed:
|
||||
+; %19 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !33 ; line:25 col:23
|
||||
+; call void @llvm.memcpy.p0i8.p0i8.i64(i8* %19, i8* bitcast ([10 x i32]* @arr1 to i8*), i64 40, i32 1, i1 false) #0, !dbg !33 ; line:25 col:23
|
||||
+; %20 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !34 ; line:26 col:10
|
||||
+; call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([10 x i32]* @arr1 to i8*), i8* %20, i64 40, i32 1, i1 false) #0, !dbg !34 ; line:26 col:10
|
||||
+; store i32 0, i32* %i.i.1.i, align 4, !dbg !35, !tbaa !12 ; line:7 col:7
|
||||
+
|
||||
+; CHECK: [[DEST0:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 0
|
||||
+; CHECK-NEXT: [[SRC0:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 0)
|
||||
+; CHECK-NEXT: store i32 [[SRC0:%[a-z0-9\.]+]], i32* [[DEST0:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST1:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 1
|
||||
+; CHECK-NEXT: [[SRC1:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 1)
|
||||
+; CHECK-NEXT: store i32 [[SRC1:%[a-z0-9\.]+]], i32* [[DEST1:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST2:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 2
|
||||
+; CHECK-NEXT: [[SRC2:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 2)
|
||||
+; CHECK-NEXT: store i32 [[SRC2:%[a-z0-9\.]+]], i32* [[DEST2:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST3:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 3
|
||||
+; CHECK-NEXT: [[SRC3:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 3)
|
||||
+; CHECK-NEXT: store i32 [[SRC3:%[a-z0-9\.]+]], i32* [[DEST3:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST4:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 4
|
||||
+; CHECK-NEXT: [[SRC4:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 4)
|
||||
+; CHECK-NEXT: store i32 [[SRC4:%[a-z0-9\.]+]], i32* [[DEST4:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST5:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 5
|
||||
+; CHECK-NEXT: [[SRC5:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 5)
|
||||
+; CHECK-NEXT: store i32 [[SRC5:%[a-z0-9\.]+]], i32* [[DEST5:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST6:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 6
|
||||
+; CHECK-NEXT: [[SRC6:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 6)
|
||||
+; CHECK-NEXT: store i32 [[SRC6:%[a-z0-9\.]+]], i32* [[DEST6:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST7:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 7
|
||||
+; CHECK-NEXT: [[SRC7:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 7)
|
||||
+; CHECK-NEXT: store i32 [[SRC7:%[a-z0-9\.]+]], i32* [[DEST7:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST8:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 8
|
||||
+; CHECK-NEXT: [[SRC8:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 8)
|
||||
+; CHECK-NEXT: store i32 [[SRC8:%[a-z0-9\.]+]], i32* [[DEST8:%[a-z0-9\.]+]]
|
||||
+; CHECK-NEXT: [[DEST9:%[a-z0-9\.]+]] = getelementptr inbounds [10 x i32], [10 x i32]* %arr1_copy.i, i32 0, i32 9
|
||||
+; CHECK-NEXT: [[SRC9:%[a-z0-9\.]+]] = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 9)
|
||||
+; CHECK-NEXT: store i32 [[SRC9:%[a-z0-9\.]+]], i32* [[DEST9:%[a-z0-9\.]+]]
|
||||
+
|
||||
+;
|
||||
+; Buffer Definitions:
|
||||
+;
|
||||
+; cbuffer $Globals
|
||||
+; {
|
||||
+;
|
||||
+; [0 x i8] (type annotation not present)
|
||||
+;
|
||||
+; }
|
||||
+;
|
||||
+;
|
||||
+; Resource Bindings:
|
||||
+;
|
||||
+; Name Type Format Dim ID HLSL Bind Count
|
||||
+; ------------------------------ ---------- ------- ----------- ------- -------------- ------
|
||||
+; $Globals cbuffer NA NA CB0 cb4294967295 1
|
||||
+; buff texture byte r/o T0 t0 1
|
||||
+;
|
||||
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
|
||||
+target triple = "dxil-ms-dx"
|
||||
+
|
||||
+%struct.ByteAddressBuffer = type { i32 }
|
||||
+%ConstantBuffer = type opaque
|
||||
+%struct.tint_symbol = type { <4 x float> }
|
||||
+%dx.types.Handle = type { i8* }
|
||||
+%dx.types.ResourceProperties = type { i32, i32 }
|
||||
+
|
||||
+@"\01?buff@@3UByteAddressBuffer@@A" = external global %struct.ByteAddressBuffer, align 4
|
||||
+@arr1 = internal global [10 x i32] zeroinitializer, align 4
|
||||
+@arr2 = internal global [10 x i32] zeroinitializer, align 4
|
||||
+@"$Globals" = external constant %ConstantBuffer
|
||||
+
|
||||
+; Function Attrs: nounwind
|
||||
+define void @main(%struct.tint_symbol* noalias sret %agg.result) #0 {
|
||||
+ %1 = alloca float
|
||||
+ store float 0.000000e+00, float* %1
|
||||
+ %i.i.1.i = alloca i32, align 4
|
||||
+ %i.i.i = alloca i32, align 4
|
||||
+ %cond.i = alloca i32, align 4
|
||||
+ %arr1_copy.i = alloca [10 x i32], align 4
|
||||
+ %inner_result = alloca float, align 4
|
||||
+ %wrapper_result = alloca %struct.tint_symbol, align 4
|
||||
+ store i32 0, i32* %i.i.i, align 4, !dbg !23, !tbaa !31 ; line:7 col:7
|
||||
+ %2 = load %struct.ByteAddressBuffer, %struct.ByteAddressBuffer* @"\01?buff@@3UByteAddressBuffer@@A", !dbg !35 ; line:8 col:7
|
||||
+ %3 = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.ByteAddressBuffer)"(i32 0, %struct.ByteAddressBuffer %2) #0, !dbg !35 ; line:8 col:7
|
||||
+ %4 = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer)"(i32 14, %dx.types.Handle %3, %dx.types.ResourceProperties { i32 11, i32 0 }, %struct.ByteAddressBuffer undef) #0, !dbg !35 ; line:8 col:7
|
||||
+ %5 = call i32 @"dx.hl.op.ro.i32 (i32, %dx.types.Handle, i32)"(i32 231, %dx.types.Handle %4, i32 0) #0, !dbg !35 ; line:8 col:7
|
||||
+ %6 = icmp ne i32 %5, 0, !dbg !35 ; line:8 col:7
|
||||
+ br i1 %6, label %"\01?foo@@YAXXZ.exit.i", label %7, !dbg !35 ; line:8 col:7
|
||||
+
|
||||
+; <label>:7 ; preds = %0
|
||||
+ %8 = load i32, i32* %i.i.i, align 4, !dbg !36, !tbaa !31 ; line:11 col:18
|
||||
+ %9 = getelementptr inbounds [10 x i32], [10 x i32]* @arr1, i32 0, i32 %8, !dbg !37 ; line:11 col:13
|
||||
+ %10 = load i32, i32* %9, align 4, !dbg !37, !tbaa !31 ; line:11 col:13
|
||||
+ %11 = load i32, i32* %i.i.i, align 4, !dbg !38, !tbaa !31 ; line:11 col:8
|
||||
+ %12 = getelementptr inbounds [10 x i32], [10 x i32]* @arr2, i32 0, i32 %11, !dbg !39 ; line:11 col:3
|
||||
+ store i32 %10, i32* %12, align 4, !dbg !40, !tbaa !31 ; line:11 col:11
|
||||
+ %13 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 0), align 4, !dbg !41, !tbaa !31 ; line:12 col:18
|
||||
+ %14 = sitofp i32 %13 to float, !dbg !41 ; line:12 col:18
|
||||
+ store float %14, float* %1, align 4, !dbg !42, !tbaa !43 ; line:12 col:10
|
||||
+ br label %"\01?foo@@YAXXZ.exit.i", !dbg !45 ; line:13 col:1
|
||||
+
|
||||
+"\01?foo@@YAXXZ.exit.i": ; preds = %7, %0
|
||||
+ store i32 0, i32* %cond.i, align 4, !dbg !46, !tbaa !47 ; line:21 col:8
|
||||
+ br label %15, !dbg !49 ; line:22 col:3
|
||||
+
|
||||
+; <label>:15 ; preds = %15, %"\01?foo@@YAXXZ.exit.i"
|
||||
+ %16 = load i32, i32* %cond.i, align 4, !dbg !50, !tbaa !47, !range !51 ; line:23 col:9
|
||||
+ %17 = icmp ne i32 %16, 0, !dbg !50 ; line:23 col:9
|
||||
+ br i1 %17, label %18, label %15, !dbg !50 ; line:23 col:9
|
||||
+
|
||||
+; <label>:18 ; preds = %15
|
||||
+ %19 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !52 ; line:25 col:23
|
||||
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %19, i8* bitcast ([10 x i32]* @arr1 to i8*), i64 40, i32 1, i1 false) #0, !dbg !52 ; line:25 col:23
|
||||
+ %20 = bitcast [10 x i32]* %arr1_copy.i to i8*, !dbg !53 ; line:26 col:10
|
||||
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* bitcast ([10 x i32]* @arr1 to i8*), i8* %20, i64 40, i32 1, i1 false) #0, !dbg !53 ; line:26 col:10
|
||||
+ store i32 0, i32* %i.i.1.i, align 4, !dbg !54, !tbaa !31 ; line:7 col:7
|
||||
+ %21 = load %struct.ByteAddressBuffer, %struct.ByteAddressBuffer* @"\01?buff@@3UByteAddressBuffer@@A", !dbg !56 ; line:8 col:7
|
||||
+ %22 = call %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.ByteAddressBuffer)"(i32 0, %struct.ByteAddressBuffer %21) #0, !dbg !56 ; line:8 col:7
|
||||
+ %23 = call %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer)"(i32 14, %dx.types.Handle %22, %dx.types.ResourceProperties { i32 11, i32 0 }, %struct.ByteAddressBuffer undef) #0, !dbg !56 ; line:8 col:7
|
||||
+ %24 = call i32 @"dx.hl.op.ro.i32 (i32, %dx.types.Handle, i32)"(i32 231, %dx.types.Handle %23, i32 0) #0, !dbg !56 ; line:8 col:7
|
||||
+ %25 = icmp ne i32 %24, 0, !dbg !56 ; line:8 col:7
|
||||
+ br i1 %25, label %"\01?main_inner@@YAMXZ.exit", label %26, !dbg !56 ; line:8 col:7
|
||||
+
|
||||
+; <label>:26 ; preds = %18
|
||||
+ %27 = load i32, i32* %i.i.1.i, align 4, !dbg !57, !tbaa !31 ; line:11 col:18
|
||||
+ %28 = getelementptr inbounds [10 x i32], [10 x i32]* @arr1, i32 0, i32 %27, !dbg !58 ; line:11 col:13
|
||||
+ %29 = load i32, i32* %28, align 4, !dbg !58, !tbaa !31 ; line:11 col:13
|
||||
+ %30 = load i32, i32* %i.i.1.i, align 4, !dbg !59, !tbaa !31 ; line:11 col:8
|
||||
+ %31 = getelementptr inbounds [10 x i32], [10 x i32]* @arr2, i32 0, i32 %30, !dbg !60 ; line:11 col:3
|
||||
+ store i32 %29, i32* %31, align 4, !dbg !61, !tbaa !31 ; line:11 col:11
|
||||
+ %32 = load i32, i32* getelementptr inbounds ([10 x i32], [10 x i32]* @arr1, i32 0, i32 0), align 4, !dbg !62, !tbaa !31 ; line:12 col:18
|
||||
+ %33 = sitofp i32 %32 to float, !dbg !62 ; line:12 col:18
|
||||
+ store float %33, float* %1, align 4, !dbg !63, !tbaa !43 ; line:12 col:10
|
||||
+ br label %"\01?main_inner@@YAMXZ.exit", !dbg !64 ; line:13 col:1
|
||||
+
|
||||
+"\01?main_inner@@YAMXZ.exit": ; preds = %18, %26
|
||||
+ %34 = load float, float* %1, align 4, !dbg !65, !tbaa !43 ; line:28 col:10
|
||||
+ store float %34, float* %inner_result, align 4, !dbg !66, !tbaa !43 ; line:32 col:9
|
||||
+ %35 = getelementptr inbounds %struct.tint_symbol, %struct.tint_symbol* %wrapper_result, i32 0, i32 0, !dbg !67 ; line:33 col:45
|
||||
+ store <4 x float> zeroinitializer, <4 x float>* %35, !dbg !67 ; line:33 col:45
|
||||
+ %36 = load float, float* %inner_result, align 4, !dbg !68, !tbaa !43 ; line:34 col:28
|
||||
+ %37 = getelementptr inbounds %struct.tint_symbol, %struct.tint_symbol* %wrapper_result, i32 0, i32 0, !dbg !69 ; line:34 col:18
|
||||
+ %38 = load <4 x float>, <4 x float>* %37, align 4, !dbg !70 ; line:34 col:26
|
||||
+ %39 = getelementptr <4 x float>, <4 x float>* %37, i32 0, i32 0, !dbg !70 ; line:34 col:26
|
||||
+ store float %36, float* %39, !dbg !70 ; line:34 col:26
|
||||
+ %40 = bitcast %struct.tint_symbol* %agg.result to i8*, !dbg !71 ; line:35 col:10
|
||||
+ %41 = bitcast %struct.tint_symbol* %wrapper_result to i8*, !dbg !71 ; line:35 col:10
|
||||
+ call void @llvm.memcpy.p0i8.p0i8.i64(i8* %40, i8* %41, i64 16, i32 1, i1 false), !dbg !71 ; line:35 col:10
|
||||
+ ret void, !dbg !72 ; line:35 col:3
|
||||
+}
|
||||
+
|
||||
+; Function Attrs: nounwind
|
||||
+declare void @llvm.memcpy.p0i8.p0i8.i64(i8* nocapture, i8* nocapture readonly, i64, i32, i1) #0
|
||||
+
|
||||
+; Function Attrs: nounwind readonly
|
||||
+declare i32 @"dx.hl.op.ro.i32 (i32, %dx.types.Handle, i32)"(i32, %dx.types.Handle, i32) #1
|
||||
+
|
||||
+; Function Attrs: nounwind readnone
|
||||
+declare %dx.types.Handle @"dx.hl.createhandle..%dx.types.Handle (i32, %struct.ByteAddressBuffer)"(i32, %struct.ByteAddressBuffer) #2
|
||||
+
|
||||
+; Function Attrs: nounwind readnone
|
||||
+declare %dx.types.Handle @"dx.hl.annotatehandle..%dx.types.Handle (i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer)"(i32, %dx.types.Handle, %dx.types.ResourceProperties, %struct.ByteAddressBuffer) #2
|
||||
+
|
||||
+attributes #0 = { nounwind }
|
||||
+attributes #1 = { nounwind readonly }
|
||||
+attributes #2 = { nounwind readnone }
|
||||
+
|
||||
+!llvm.module.flags = !{!0}
|
||||
+!pauseresume = !{!1}
|
||||
+!llvm.ident = !{!2}
|
||||
+!dx.version = !{!3}
|
||||
+!dx.valver = !{!4}
|
||||
+!dx.shaderModel = !{!5}
|
||||
+!dx.typeAnnotations = !{!6, !9}
|
||||
+!dx.entryPoints = !{!14}
|
||||
+!dx.fnprops = !{!20}
|
||||
+!dx.options = !{!21, !22}
|
||||
+
|
||||
+!0 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
+!1 = !{!"hlsl-hlemit", !"hlsl-hlensure"}
|
||||
+!2 = !{!"dxc(private) 1.8.0.4547 (14ec4b49d)"}
|
||||
+!3 = !{i32 1, i32 2}
|
||||
+!4 = !{i32 1, i32 8}
|
||||
+!5 = !{!"ps", i32 6, i32 2}
|
||||
+!6 = !{i32 0, %struct.tint_symbol undef, !7}
|
||||
+!7 = !{i32 16, !8}
|
||||
+!8 = !{i32 6, !"value", i32 3, i32 0, i32 4, !"SV_Target0", i32 7, i32 9}
|
||||
+!9 = !{i32 1, void (%struct.tint_symbol*)* @main, !10}
|
||||
+!10 = !{!11, !13}
|
||||
+!11 = !{i32 0, !12, !12}
|
||||
+!12 = !{}
|
||||
+!13 = !{i32 1, !12, !12}
|
||||
+!14 = !{void (%struct.tint_symbol*)* @main, !"main", null, !15, null}
|
||||
+!15 = !{!16, null, !18, null}
|
||||
+!16 = !{!17}
|
||||
+!17 = !{i32 0, %struct.ByteAddressBuffer* @"\01?buff@@3UByteAddressBuffer@@A", !"buff", i32 0, i32 0, i32 1, i32 11, i32 0, null}
|
||||
+!18 = !{!19}
|
||||
+!19 = !{i32 0, %ConstantBuffer* @"$Globals", !"$Globals", i32 0, i32 -1, i32 1, i32 0, null}
|
||||
+!20 = !{void (%struct.tint_symbol*)* @main, i32 0, i1 false}
|
||||
+!21 = !{i32 144}
|
||||
+!22 = !{i32 -1}
|
||||
+!23 = !DILocation(line: 7, column: 7, scope: !24, inlinedAt: !27)
|
||||
+!24 = !DISubprogram(name: "foo", scope: !25, file: !25, line: 6, type: !26, isLocal: false, isDefinition: true, scopeLine: 6, flags: DIFlagPrototyped, isOptimized: false)
|
||||
+!25 = !DIFile(filename: "333414294_simplifed.hlsl", directory: "")
|
||||
+!26 = !DISubroutineType(types: !12)
|
||||
+!27 = distinct !DILocation(line: 20, column: 3, scope: !28, inlinedAt: !29)
|
||||
+!28 = !DISubprogram(name: "main_inner", scope: !25, file: !25, line: 19, type: !26, isLocal: false, isDefinition: true, scopeLine: 19, flags: DIFlagPrototyped, isOptimized: false)
|
||||
+!29 = distinct !DILocation(line: 32, column: 24, scope: !30)
|
||||
+!30 = !DISubprogram(name: "main", scope: !25, file: !25, line: 31, type: !26, isLocal: false, isDefinition: true, scopeLine: 31, flags: DIFlagPrototyped, isOptimized: false, function: void (%struct.tint_symbol*)* @main)
|
||||
+!31 = !{!32, !32, i64 0}
|
||||
+!32 = !{!"int", !33, i64 0}
|
||||
+!33 = !{!"omnipotent char", !34, i64 0}
|
||||
+!34 = !{!"Simple C/C++ TBAA"}
|
||||
+!35 = !DILocation(line: 8, column: 7, scope: !24, inlinedAt: !27)
|
||||
+!36 = !DILocation(line: 11, column: 18, scope: !24, inlinedAt: !27)
|
||||
+!37 = !DILocation(line: 11, column: 13, scope: !24, inlinedAt: !27)
|
||||
+!38 = !DILocation(line: 11, column: 8, scope: !24, inlinedAt: !27)
|
||||
+!39 = !DILocation(line: 11, column: 3, scope: !24, inlinedAt: !27)
|
||||
+!40 = !DILocation(line: 11, column: 11, scope: !24, inlinedAt: !27)
|
||||
+!41 = !DILocation(line: 12, column: 18, scope: !24, inlinedAt: !27)
|
||||
+!42 = !DILocation(line: 12, column: 10, scope: !24, inlinedAt: !27)
|
||||
+!43 = !{!44, !44, i64 0}
|
||||
+!44 = !{!"float", !33, i64 0}
|
||||
+!45 = !DILocation(line: 13, column: 1, scope: !24, inlinedAt: !27)
|
||||
+!46 = !DILocation(line: 21, column: 8, scope: !28, inlinedAt: !29)
|
||||
+!47 = !{!48, !48, i64 0}
|
||||
+!48 = !{!"bool", !33, i64 0}
|
||||
+!49 = !DILocation(line: 22, column: 3, scope: !28, inlinedAt: !29)
|
||||
+!50 = !DILocation(line: 23, column: 9, scope: !28, inlinedAt: !29)
|
||||
+!51 = !{i32 0, i32 2}
|
||||
+!52 = !DILocation(line: 25, column: 23, scope: !28, inlinedAt: !29)
|
||||
+!53 = !DILocation(line: 26, column: 10, scope: !28, inlinedAt: !29)
|
||||
+!54 = !DILocation(line: 7, column: 7, scope: !24, inlinedAt: !55)
|
||||
+!55 = distinct !DILocation(line: 27, column: 3, scope: !28, inlinedAt: !29)
|
||||
+!56 = !DILocation(line: 8, column: 7, scope: !24, inlinedAt: !55)
|
||||
+!57 = !DILocation(line: 11, column: 18, scope: !24, inlinedAt: !55)
|
||||
+!58 = !DILocation(line: 11, column: 13, scope: !24, inlinedAt: !55)
|
||||
+!59 = !DILocation(line: 11, column: 8, scope: !24, inlinedAt: !55)
|
||||
+!60 = !DILocation(line: 11, column: 3, scope: !24, inlinedAt: !55)
|
||||
+!61 = !DILocation(line: 11, column: 11, scope: !24, inlinedAt: !55)
|
||||
+!62 = !DILocation(line: 12, column: 18, scope: !24, inlinedAt: !55)
|
||||
+!63 = !DILocation(line: 12, column: 10, scope: !24, inlinedAt: !55)
|
||||
+!64 = !DILocation(line: 13, column: 1, scope: !24, inlinedAt: !55)
|
||||
+!65 = !DILocation(line: 28, column: 10, scope: !28, inlinedAt: !29)
|
||||
+!66 = !DILocation(line: 32, column: 9, scope: !30)
|
||||
+!67 = !DILocation(line: 33, column: 45, scope: !30)
|
||||
+!68 = !DILocation(line: 34, column: 28, scope: !30)
|
||||
+!69 = !DILocation(line: 34, column: 18, scope: !30)
|
||||
+!70 = !DILocation(line: 34, column: 26, scope: !30)
|
||||
+!71 = !DILocation(line: 35, column: 10, scope: !30)
|
||||
+!72 = !DILocation(line: 35, column: 3, scope: !30)
|
||||
66
patches/DirectXShaderCompiler/cherry-pick-a65e511a14b4.patch
Normal file
66
patches/DirectXShaderCompiler/cherry-pick-a65e511a14b4.patch
Normal file
@@ -0,0 +1,66 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Maiorano <amaiorano@google.com>
|
||||
Date: Wed, 3 Apr 2024 15:58:51 -0400
|
||||
Subject: Fix ASAN use-after-free on unreferenced self-assignment of struct
|
||||
instance (#6466)
|
||||
|
||||
When deleting an unused memcpy, ScalarReplAggregatesHLSL was attempting
|
||||
to delete both the target and the source of the memcpy without first
|
||||
checking if they were both same, resulting in a double-delete.
|
||||
|
||||
Bug: chromium:331123811
|
||||
Change-Id: Idaef95a06b10a7fb6f0ca2e662972a44ec662fbc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5419225
|
||||
Reviewed-by: David Neto <dneto@google.com>
|
||||
Reviewed-by: dan sinclair <dsinclair@chromium.org>
|
||||
Reviewed-by: Ben Clayton <bclayton@chromium.org>
|
||||
|
||||
diff --git a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
index ae726fbcb67de79ed75992e6d31acfdc21f516c0..bd429ae98b0e11bbb2b95c68392b82eb222f64a4 100644
|
||||
--- a/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
+++ b/lib/Transforms/Scalar/ScalarReplAggregatesHLSL.cpp
|
||||
@@ -1003,9 +1003,11 @@ void DeleteMemcpy(MemCpyInst *MI) {
|
||||
if (op0->user_empty())
|
||||
op0->eraseFromParent();
|
||||
}
|
||||
- if (Instruction *op1 = dyn_cast<Instruction>(Op1)) {
|
||||
- if (op1->user_empty())
|
||||
- op1->eraseFromParent();
|
||||
+ if (Op0 != Op1) {
|
||||
+ if (Instruction *op1 = dyn_cast<Instruction>(Op1)) {
|
||||
+ if (op1->user_empty())
|
||||
+ op1->eraseFromParent();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/tools/clang/test/DXC/unreferenced_struct_selft_assignment_crash.hlsl b/tools/clang/test/DXC/unreferenced_struct_selft_assignment_crash.hlsl
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..81adf71867c9868992372e12dc1ba81aebb48344
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/DXC/unreferenced_struct_selft_assignment_crash.hlsl
|
||||
@@ -0,0 +1,24 @@
|
||||
+// RUN: %dxc -T cs_6_0 %s | FileCheck %s
|
||||
+
|
||||
+// Validate that self-assignment of a static struct instance that is not
|
||||
+// referenced does not crash the compiler. This was resulting in an ASAN
|
||||
+// use-after-free in ScalarReplAggregatesHLSL because DeleteMemcpy would
|
||||
+// attempt to delete both source and target, even if both were the same.
|
||||
+// CHECK: define void @main() {
|
||||
+// CHECK-NEXT: ret void
|
||||
+// CHECK-NEXT: }
|
||||
+
|
||||
+struct MyStruct {
|
||||
+ int m0;
|
||||
+};
|
||||
+
|
||||
+static MyStruct s;
|
||||
+
|
||||
+void foo() {
|
||||
+ s = s;
|
||||
+}
|
||||
+
|
||||
+[numthreads(1, 1, 1)]
|
||||
+void main() {
|
||||
+ foo();
|
||||
+}
|
||||
57
patches/DirectXShaderCompiler/cherry-pick-bc18aec94c82.patch
Normal file
57
patches/DirectXShaderCompiler/cherry-pick-bc18aec94c82.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Maiorano <amaiorano@google.com>
|
||||
Date: Thu, 18 Apr 2024 13:07:04 -0400
|
||||
Subject: Replace dynamic_cast with virtual call (#6515)
|
||||
|
||||
Make TextDiagnosticPrinter::setPrefix a virtual function in base class
|
||||
DiagnosticConsumer. This allows us to avoid using dynamic_cast in
|
||||
BackendConsumer::DxilDiagHandler, required for codebases that do not
|
||||
enable RTTI. This is also the only place in the codebase that uses RTTI
|
||||
(AFAICT).
|
||||
|
||||
Bug: chromium:333420620
|
||||
Change-Id: Ida73077f24fdb4b705b5d868b04ac6cfecb30327
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5464347
|
||||
Reviewed-by: dan sinclair <dsinclair@chromium.org>
|
||||
Reviewed-by: David Neto <dneto@google.com>
|
||||
|
||||
diff --git a/tools/clang/include/clang/Basic/Diagnostic.h b/tools/clang/include/clang/Basic/Diagnostic.h
|
||||
index dc9f781c093c0bc8f6da773d514ac6d1503f842d..0b98dffb94185e242320409d43b74dae2c2a908d 100644
|
||||
--- a/tools/clang/include/clang/Basic/Diagnostic.h
|
||||
+++ b/tools/clang/include/clang/Basic/Diagnostic.h
|
||||
@@ -1395,6 +1395,8 @@ public:
|
||||
/// warnings and errors.
|
||||
virtual void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
|
||||
const Diagnostic &Info);
|
||||
+
|
||||
+ virtual void setPrefix(std::string Value) {} // HLSL Change
|
||||
};
|
||||
|
||||
/// \brief A diagnostic client that ignores all diagnostics.
|
||||
diff --git a/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h b/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
|
||||
index 04a570559fe06a0670ef8a7e6e94c40aa37e55a9..936031e09673a09c6e1164c515efce02ac51b910 100644
|
||||
--- a/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
|
||||
+++ b/tools/clang/include/clang/Frontend/TextDiagnosticPrinter.h
|
||||
@@ -45,7 +45,8 @@ public:
|
||||
/// setPrefix - Set the diagnostic printer prefix string, which will be
|
||||
/// printed at the start of any diagnostics. If empty, no prefix string is
|
||||
/// used.
|
||||
- void setPrefix(std::string Value) { Prefix = Value; }
|
||||
+ // HLSL Change: add override
|
||||
+ void setPrefix(std::string Value) override { Prefix = Value; }
|
||||
|
||||
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override;
|
||||
void EndSourceFile() override;
|
||||
diff --git a/tools/clang/lib/CodeGen/CodeGenAction.cpp b/tools/clang/lib/CodeGen/CodeGenAction.cpp
|
||||
index 4fa721e812296356e31fc1bf6ea35ce295c2592c..68ebaadf5a8960c8def189248412136fe9543422 100644
|
||||
--- a/tools/clang/lib/CodeGen/CodeGenAction.cpp
|
||||
+++ b/tools/clang/lib/CodeGen/CodeGenAction.cpp
|
||||
@@ -557,7 +557,7 @@ BackendConsumer::DxilDiagHandler(const llvm::DiagnosticInfoDxil &D) {
|
||||
|
||||
// If no location information is available, add function name
|
||||
if (Loc.isInvalid()) {
|
||||
- auto *DiagClient = dynamic_cast<TextDiagnosticPrinter*>(Diags.getClient());
|
||||
+ auto *DiagClient = Diags.getClient();
|
||||
auto *func = D.getFunction();
|
||||
if (DiagClient && func)
|
||||
DiagClient->setPrefix("Function: " + func->getName().str());
|
||||
161
patches/DirectXShaderCompiler/cherry-pick-bd7aa9779873.patch
Normal file
161
patches/DirectXShaderCompiler/cherry-pick-bd7aa9779873.patch
Normal file
@@ -0,0 +1,161 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Maiorano <amaiorano@google.com>
|
||||
Date: Thu, 25 Apr 2024 16:49:11 -0400
|
||||
Subject: Fixed crash in loop unroll caused by bug in structurize loop exits
|
||||
(#6548)
|
||||
|
||||
Fixed a bug in `hlsl::RemoveUnstructuredLoopExits` where when a new
|
||||
exiting block is created from splitting, it was added to the current
|
||||
loop being processed, when it could also part of an inner loop. Not
|
||||
adding the new block to inner loops that it's part of makes the inner
|
||||
loops malformed, and causes crash.
|
||||
|
||||
This fix adds the new block to the inner most loop that it should be
|
||||
part of. Also adds the `StructurizeLoopExits` option to `loop-unroll`
|
||||
pass, which was missing before.
|
||||
|
||||
Bug: chromium:333508731
|
||||
Change-Id: I7efc21bc61aeb81b4906a600c35272af232710ea
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5490380
|
||||
Reviewed-by: James Price <jrprice@google.com>
|
||||
Reviewed-by: Ben Clayton <bclayton@chromium.org>
|
||||
|
||||
diff --git a/lib/Transforms/Scalar/DxilRemoveUnstructuredLoopExits.cpp b/lib/Transforms/Scalar/DxilRemoveUnstructuredLoopExits.cpp
|
||||
index b6a07d6b27a23ee3831e84cee82299d6d405a288..ef6718f0f22ee33e3f16f9801a64c1a6fb6c653a 100644
|
||||
--- a/lib/Transforms/Scalar/DxilRemoveUnstructuredLoopExits.cpp
|
||||
+++ b/lib/Transforms/Scalar/DxilRemoveUnstructuredLoopExits.cpp
|
||||
@@ -447,7 +447,12 @@ static bool RemoveUnstructuredLoopExitsIteration(BasicBlock *exiting_block,
|
||||
new_exiting_block->splitBasicBlock(new_exiting_block->getFirstNonPHI());
|
||||
new_exiting_block->setName("dx.struct_exit.new_exiting");
|
||||
new_not_exiting_block->setName(old_name);
|
||||
- L->addBasicBlockToLoop(new_not_exiting_block, *LI);
|
||||
+ // Query for new_exiting_block's own loop to add new_not_exiting_block to.
|
||||
+ // It's possible that new_exiting_block is part of another inner loop
|
||||
+ // separate from L. If added directly to L, the inner loop(s) will not
|
||||
+ // contain new_not_exiting_block, making them malformed.
|
||||
+ Loop *inner_loop_of_exiting_block = LI->getLoopFor(new_exiting_block);
|
||||
+ inner_loop_of_exiting_block->addBasicBlockToLoop(new_not_exiting_block, *LI);
|
||||
|
||||
// Branch to latch_exit
|
||||
new_exiting_block->getTerminator()->eraseFromParent();
|
||||
diff --git a/lib/Transforms/Scalar/LoopUnrollPass.cpp b/lib/Transforms/Scalar/LoopUnrollPass.cpp
|
||||
index dd520f7e57d25311be7f3773849a00efaabe6717..b17a5a4a0bc368f16020c4153370ea2c92e5c26c 100644
|
||||
--- a/lib/Transforms/Scalar/LoopUnrollPass.cpp
|
||||
+++ b/lib/Transforms/Scalar/LoopUnrollPass.cpp
|
||||
@@ -155,6 +155,18 @@ namespace {
|
||||
bool UserAllowPartial;
|
||||
bool UserRuntime;
|
||||
|
||||
+ // HLSL Change - begin
|
||||
+ // Function overrides that resolve options when used for DxOpt
|
||||
+ void applyOptions(PassOptions O) override {
|
||||
+ GetPassOptionBool(O, "StructurizeLoopExits", &StructurizeLoopExits,
|
||||
+ false);
|
||||
+ }
|
||||
+ void dumpConfig(raw_ostream &OS) override {
|
||||
+ LoopPass::dumpConfig(OS);
|
||||
+ OS << ",StructurizeLoopExits=" << StructurizeLoopExits;
|
||||
+ }
|
||||
+ // HLSL Change - end
|
||||
+
|
||||
bool runOnLoop(Loop *L, LPPassManager &LPM) override;
|
||||
|
||||
/// This transformation requires natural loop information & requires that
|
||||
diff --git a/tools/clang/test/DXC/loop_structurize_exit_inner_latch_regression.ll b/tools/clang/test/DXC/loop_structurize_exit_inner_latch_regression.ll
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..743135541cd8faec287164ba3b321a59432832b6
|
||||
--- /dev/null
|
||||
+++ b/tools/clang/test/DXC/loop_structurize_exit_inner_latch_regression.ll
|
||||
@@ -0,0 +1,75 @@
|
||||
+; RUN: %dxopt %s -S -loop-unroll,StructurizeLoopExits=1 | FileCheck %s
|
||||
+; RUN: %dxopt %s -S -dxil-loop-unroll,StructurizeLoopExits=1 | FileCheck %s
|
||||
+
|
||||
+; CHECK: mul nsw i32
|
||||
+; CHECK: mul nsw i32
|
||||
+; CHECK-NOT: mul nsw i32
|
||||
+
|
||||
+; This is a regression test for a crash in loop unroll. When there are multiple
|
||||
+; exits, the compiler will run hlsl::RemoveUnstructuredLoopExits to try to
|
||||
+; avoid unstructured code.
|
||||
+;
|
||||
+; In this test, the compiler will try to unroll the middle loop. The exit edge
|
||||
+; from %land.lhs.true to %if.then will be removed, and %if.end will be split at
|
||||
+; the beginning, and branch to %if.end instead.
|
||||
+;
|
||||
+; Since the new split block at %if.end becomes the new latch of the inner-most
|
||||
+; loop, it needs to be added to the Loop analysis structure of the inner loop.
|
||||
+; However, it was only added to the current middle loop that is being unrolled.
|
||||
+
|
||||
+target datalayout = "e-m:e-p:32:32-i1:32-i8:32-i16:32-i32:32-i64:64-f16:32-f32:32-f64:64-n8:16:32:64"
|
||||
+target triple = "dxil-ms-dx"
|
||||
+
|
||||
+; Function Attrs: nounwind
|
||||
+define void @main(i32 *%arg0, i32 *%arg1, i32 *%arg2) #0 {
|
||||
+entry:
|
||||
+ br label %while.body.3.preheader.lr.ph
|
||||
+
|
||||
+while.body.3.preheader.lr.ph.loopexit: ; preds = %for.inc
|
||||
+ br label %while.body.3.preheader.lr.ph
|
||||
+
|
||||
+while.body.3.preheader.lr.ph: ; preds = %while.body.3.preheader.lr.ph.loopexit, %entry
|
||||
+ br label %while.body.3.preheader
|
||||
+
|
||||
+while.body.3.preheader: ; preds = %while.body.3.preheader.lr.ph, %for.inc
|
||||
+ %i.0 = phi i32 [ 0, %while.body.3.preheader.lr.ph ], [ %inc, %for.inc ]
|
||||
+ br label %while.body.3
|
||||
+
|
||||
+while.body.3: ; preds = %while.body.3.preheader, %if.end
|
||||
+ %load_arg0 = load i32, i32* %arg0
|
||||
+ %cmp4 = icmp sgt i32 %load_arg0, 0
|
||||
+ br i1 %cmp4, label %land.lhs.true, label %if.end
|
||||
+
|
||||
+land.lhs.true: ; preds = %while.body.3
|
||||
+ %load_arg1 = load i32, i32* %arg1
|
||||
+ %load_arg2 = load i32, i32* %arg2
|
||||
+ %mul = mul nsw i32 %load_arg2, %load_arg1
|
||||
+ %cmp7 = icmp eq i32 %mul, 10
|
||||
+ br i1 %cmp7, label %if.then, label %if.end
|
||||
+
|
||||
+if.then: ; preds = %land.lhs.true
|
||||
+ ret void
|
||||
+
|
||||
+if.end: ; preds = %land.lhs.true, %while.body.3
|
||||
+ %cmp10 = icmp sle i32 %i.0, 4
|
||||
+ br i1 %cmp10, label %for.inc, label %while.body.3
|
||||
+
|
||||
+for.inc: ; preds = %if.end
|
||||
+ %inc = add nsw i32 %i.0, 1
|
||||
+ %cmp = icmp slt i32 %inc, 2
|
||||
+ br i1 %cmp, label %while.body.3.preheader, label %while.body.3.preheader.lr.ph.loopexit, !llvm.loop !3
|
||||
+}
|
||||
+
|
||||
+attributes #0 = { nounwind }
|
||||
+attributes #1 = { nounwind readnone }
|
||||
+attributes #2 = { nounwind readonly }
|
||||
+
|
||||
+!llvm.module.flags = !{!0}
|
||||
+!pauseresume = !{!1}
|
||||
+!llvm.ident = !{!2}
|
||||
+
|
||||
+!0 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
+!1 = !{!"hlsl-dxilemit", !"hlsl-dxilload"}
|
||||
+!2 = !{!"dxc(private) 1.8.0.14563 (main, 07ce88034-dirty)"}
|
||||
+!3 = distinct !{!3, !4}
|
||||
+!4 = !{!"llvm.loop.unroll.full"}
|
||||
diff --git a/utils/hct/hctdb.py b/utils/hct/hctdb.py
|
||||
index 578b8ec99586b8a2a060355f3758d89522f67623..bcd2a3b9053e62bfeddbfb11f89403adfbde604e 100644
|
||||
--- a/utils/hct/hctdb.py
|
||||
+++ b/utils/hct/hctdb.py
|
||||
@@ -5908,6 +5908,12 @@ class db_dxil(object):
|
||||
"t": "unsigned",
|
||||
"d": "Unrolled size limit for loops with an unroll(full) or unroll_count pragma.",
|
||||
},
|
||||
+ {
|
||||
+ "n": "StructurizeLoopExits",
|
||||
+ "t": "bool",
|
||||
+ "c": 1,
|
||||
+ "d": "Whether the unroller should try to structurize loop exits first.",
|
||||
+ },
|
||||
],
|
||||
)
|
||||
add_pass("mldst-motion", "MergedLoadStoreMotion", "MergedLoadStoreMotion", [])
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Maiorano <amaiorano@google.com>
|
||||
Date: Wed, 20 Mar 2024 17:15:40 -0400
|
||||
Subject: Fix HLMatrixLowerPass leaving call to dangling FunctionVal
|
||||
|
||||
When lowering an hl.cast, when the operand was an undef matrix, the pass would insert a call to a mat2vec stub, but since the undef value is not
|
||||
an alloca, it never gets handled, and the call to the temporary stub
|
||||
remains. Since the stub FunctionVal gets deleted, when the instruction
|
||||
is accessed in a future pass, it reads a dangling pointer.
|
||||
|
||||
The fix is to handle undef similarly to how constant 0 is handled, and
|
||||
to return an undef vector from lowerHLCast.
|
||||
|
||||
Bug: chromium:328958020
|
||||
Change-Id: Id31e3aa326d9cb9f03ea97139f14dc5292cd6f7b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/external/github.com/microsoft/DirectXShaderCompiler/+/5383595
|
||||
Reviewed-by: Ben Clayton <bclayton@chromium.org>
|
||||
Reviewed-by: David Neto <dneto@google.com>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
|
||||
diff --git a/lib/HLSL/HLMatrixLowerPass.cpp b/lib/HLSL/HLMatrixLowerPass.cpp
|
||||
index ca8a8a33fdb475542b3705f3f7a8b8af2554a21f..d5959eb9335465f67d8e7ef7d7ab4eb720274226 100644
|
||||
--- a/lib/HLSL/HLMatrixLowerPass.cpp
|
||||
+++ b/lib/HLSL/HLMatrixLowerPass.cpp
|
||||
@@ -421,6 +421,11 @@ Value *HLMatrixLowerPass::getLoweredByValOperand(Value *Val,
|
||||
if (isa<ConstantAggregateZero>(Val))
|
||||
return ConstantAggregateZero::get(LoweredTy);
|
||||
|
||||
+ // Lower undef mat as undef vec
|
||||
+ if (isa<UndefValue>(Val)) {
|
||||
+ return UndefValue::get(LoweredTy);
|
||||
+ }
|
||||
+
|
||||
// Return a mat-to-vec translation stub
|
||||
FunctionType *TranslationStubTy =
|
||||
FunctionType::get(LoweredTy, {Ty}, /* isVarArg */ false);
|
||||
4
patches/angle/.patches
Normal file
4
patches/angle/.patches
Normal file
@@ -0,0 +1,4 @@
|
||||
m123_vulkan_fix_access_to_inactive_attributes.patch
|
||||
cherry-pick-f6672dbbe223.patch
|
||||
cherry-pick-ba3b4e239620.patch
|
||||
cherry-pick-c67f290ef0f0.patch
|
||||
249
patches/angle/cherry-pick-ba3b4e239620.patch
Normal file
249
patches/angle/cherry-pick-ba3b4e239620.patch
Normal file
@@ -0,0 +1,249 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 8 Apr 2024 10:14:45 -0400
|
||||
Subject: M123: SPIR-V: Fix const constructors with single scalar
|
||||
|
||||
These constructors may be generated because of
|
||||
RemoveArrayLengthTraverser.
|
||||
|
||||
Bug: chromium:332546345
|
||||
Change-Id: I2b2bf3728ef5bae148abc2a8518f8f3f42850025
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5462388
|
||||
(cherry picked from commit 0b776d32f69a932acb61963d9daad9e13f610944)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5473406
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Daniel Gagnon <dgagnon@google.com>
|
||||
|
||||
diff --git a/src/compiler/translator/Compiler.cpp b/src/compiler/translator/Compiler.cpp
|
||||
index b76923563fd186087dc34be142934b84874da853..9a7e46f644fb8bb01561c5c1a6e332249b31276c 100644
|
||||
--- a/src/compiler/translator/Compiler.cpp
|
||||
+++ b/src/compiler/translator/Compiler.cpp
|
||||
@@ -1035,6 +1035,11 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
|
||||
{
|
||||
return false;
|
||||
}
|
||||
+ // Fold the expressions again, because |RemoveArrayLengthMethod| can introduce new constants.
|
||||
+ if (!FoldExpressions(this, root, &mDiagnostics))
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
if (!RemoveUnreferencedVariables(this, root, &mSymbolTable))
|
||||
{
|
||||
diff --git a/src/compiler/translator/spirv/OutputSPIRV.cpp b/src/compiler/translator/spirv/OutputSPIRV.cpp
|
||||
index caa8f956716abf53aaeb58a5f654f5a4f04c4d6a..67b1fdd4784660483a408f1ee27ce48b05ffcb0a 100644
|
||||
--- a/src/compiler/translator/spirv/OutputSPIRV.cpp
|
||||
+++ b/src/compiler/translator/spirv/OutputSPIRV.cpp
|
||||
@@ -1335,6 +1335,8 @@ spirv::IdRef OutputSPIRVTraverser::createComplexConstant(const TType &type,
|
||||
|
||||
if (type.isMatrix() && !type.isArray())
|
||||
{
|
||||
+ ASSERT(parameters.size() == type.getRows() * type.getCols());
|
||||
+
|
||||
// Matrices are constructed from their columns.
|
||||
spirv::IdRefList columnIds;
|
||||
|
||||
diff --git a/src/tests/gl_tests/GLSLTest.cpp b/src/tests/gl_tests/GLSLTest.cpp
|
||||
index c9d954ed1f7a4bfd4d5b5d5916d3def07aaa2637..8c13f9ef1dafb63d5ed8aa557a152404585608be 100644
|
||||
--- a/src/tests/gl_tests/GLSLTest.cpp
|
||||
+++ b/src/tests/gl_tests/GLSLTest.cpp
|
||||
@@ -8486,6 +8486,198 @@ void main()
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
}
|
||||
|
||||
+// Test that array length inside vector constructor works.
|
||||
+TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructor)
|
||||
+{
|
||||
+ const char kVS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+flat out uvec4 v;
|
||||
+
|
||||
+int[1] f0()
|
||||
+{
|
||||
+ return int[1](1);
|
||||
+}
|
||||
+void main()
|
||||
+{
|
||||
+ v = uvec4(vec4(f0().length()));
|
||||
+
|
||||
+ gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.zw = vec2(0, 1);
|
||||
+})";
|
||||
+
|
||||
+ const char kFS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+flat in uvec4 v;
|
||||
+out vec4 color;
|
||||
+
|
||||
+bool isEq(uint a, float b) { return abs(float(a) - b) < 0.01; }
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ if (isEq(v[0], 1.) &&
|
||||
+ isEq(v[1], 1.) &&
|
||||
+ isEq(v[2], 1.) &&
|
||||
+ isEq(v[3], 1.))
|
||||
+ {
|
||||
+ color = vec4(0, 1, 0, 1);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ color = vec4(1, 0, 0, 1);
|
||||
+ }
|
||||
+})";
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glUseProgram(program);
|
||||
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Test that array length inside vector constructor works in complex expression.
|
||||
+TEST_P(GLSLTest_ES3, ArrayLengthInVectorConstructorComplex)
|
||||
+{
|
||||
+ const char kVS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+out vec4 v;
|
||||
+
|
||||
+int[1] f0()
|
||||
+{
|
||||
+ return int[1](1);
|
||||
+}
|
||||
+void main()
|
||||
+{
|
||||
+ v = vec4(float(uint(f0().length()) + 1u) / 4.);
|
||||
+
|
||||
+ gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.zw = vec2(0, 1);
|
||||
+})";
|
||||
+
|
||||
+ const char kFS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+in vec4 v;
|
||||
+out vec4 color;
|
||||
+
|
||||
+bool isEq(float a, float b) { return abs(float(a) - b) < 0.01; }
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ if (isEq(v[0], 0.5) &&
|
||||
+ isEq(v[1], 0.5) &&
|
||||
+ isEq(v[2], 0.5) &&
|
||||
+ isEq(v[3], 0.5))
|
||||
+ {
|
||||
+ color = vec4(0, 1, 0, 1);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ color = vec4(1, 0, 0, 1);
|
||||
+ }
|
||||
+})";
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glUseProgram(program);
|
||||
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Test that array length inside matrix constructor works.
|
||||
+TEST_P(GLSLTest_ES3, ArrayLengthInMatrixConstructor)
|
||||
+{
|
||||
+ const char kVS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+out mat2x2 v;
|
||||
+
|
||||
+int[1] f0()
|
||||
+{
|
||||
+ return int[1](1);
|
||||
+}
|
||||
+void main()
|
||||
+{
|
||||
+ v = mat2x2(f0().length());
|
||||
+
|
||||
+ gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.zw = vec2(0, 1);
|
||||
+})";
|
||||
+
|
||||
+ const char kFS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+in mat2x2 v;
|
||||
+out vec4 color;
|
||||
+
|
||||
+bool isEq(float a, float b) { return abs(a - b) < 0.01; }
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ if (isEq(v[0][0], 1.) &&
|
||||
+ isEq(v[0][1], 0.) &&
|
||||
+ isEq(v[1][0], 0.) &&
|
||||
+ isEq(v[1][1], 1.))
|
||||
+ {
|
||||
+ color = vec4(0, 1, 0, 1);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ color = vec4(1, 0, 0, 1);
|
||||
+ }
|
||||
+})";
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glUseProgram(program);
|
||||
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Test that array length inside vector constructor inside matrix constructor works.
|
||||
+TEST_P(GLSLTest_ES3, ArrayLengthInVectorInMatrixConstructor)
|
||||
+{
|
||||
+ const char kVS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+out mat2x2 v;
|
||||
+
|
||||
+int[1] f0()
|
||||
+{
|
||||
+ return int[1](1);
|
||||
+}
|
||||
+void main()
|
||||
+{
|
||||
+ v = mat2x2(vec2(f0().length()), f0().length(), 0);
|
||||
+
|
||||
+ gl_Position.x = ((gl_VertexID & 1) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.y = ((gl_VertexID & 2) == 0 ? -1.0 : 1.0);
|
||||
+ gl_Position.zw = vec2(0, 1);
|
||||
+})";
|
||||
+
|
||||
+ const char kFS[] = R"(#version 300 es
|
||||
+precision highp float;
|
||||
+in mat2x2 v;
|
||||
+out vec4 color;
|
||||
+
|
||||
+bool isEq(float a, float b) { return abs(a - b) < 0.01; }
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ if (isEq(v[0][0], 1.) &&
|
||||
+ isEq(v[0][1], 1.) &&
|
||||
+ isEq(v[1][0], 1.) &&
|
||||
+ isEq(v[1][1], 0.))
|
||||
+ {
|
||||
+ color = vec4(0, 1, 0, 1);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ color = vec4(1, 0, 0, 1);
|
||||
+ }
|
||||
+})";
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glUseProgram(program);
|
||||
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Test that statements inside switch() get translated to correct HLSL.
|
||||
TEST_P(GLSLTest_ES3, DifferentStatementsInsideSwitch)
|
||||
{
|
||||
32
patches/angle/cherry-pick-c67f290ef0f0.patch
Normal file
32
patches/angle/cherry-pick-c67f290ef0f0.patch
Normal file
@@ -0,0 +1,32 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Mon, 29 Apr 2024 15:27:36 -0400
|
||||
Subject: M124: GL: Sync unpack state for glCompressedTexSubImage3D
|
||||
|
||||
Unpack state is supposed to be ignored for compressed tex image calls
|
||||
but some drivers use it anyways and read incorrect data.
|
||||
|
||||
Texture3DTestES3.PixelUnpackStateTexSubImage covers this case.
|
||||
|
||||
Bug: chromium:337766133
|
||||
Change-Id: Ic11a056113b1850bd5b4d6840527164a12849a22
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5498735
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 1bb1ee061fe0bce322fb93b447a72e72c993a1f2)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5518811
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Reviewed-by: Srinivas Sista <srinivassista@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/gl/TextureGL.cpp b/src/libANGLE/renderer/gl/TextureGL.cpp
|
||||
index 10874b7f04c1cb353c1ab2fabc28b0d5effca673..8921dae4740ef4921a7c72efda8a1d9219bcbd28 100644
|
||||
--- a/src/libANGLE/renderer/gl/TextureGL.cpp
|
||||
+++ b/src/libANGLE/renderer/gl/TextureGL.cpp
|
||||
@@ -664,6 +664,7 @@ angle::Result TextureGL::setCompressedSubImage(const gl::Context *context,
|
||||
nativegl::GetCompressedSubTexImageFormat(functions, features, format);
|
||||
|
||||
stateManager->bindTexture(getType(), mTextureID);
|
||||
+ ANGLE_TRY(stateManager->setPixelUnpackState(context, unpack));
|
||||
if (nativegl::UseTexImage2D(getType()))
|
||||
{
|
||||
ASSERT(area.z == 0 && area.depth == 1);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user