mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
187 Commits
| 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 |
@@ -248,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
|
||||
@@ -333,27 +337,46 @@ step-setup-env-for-build: &step-setup-env-for-build
|
||||
# To find `gn` executable.
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
|
||||
step-setup-rbe-for-build: &step-setup-rbe-for-build
|
||||
step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
run:
|
||||
name: Setup RBE
|
||||
name: Setup Goma
|
||||
command: |
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=300' >> $BASH_ENV
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
echo 'export NUMBER_OF_NINJA_PROCESSES=200' >> $BASH_ENV
|
||||
echo 'ulimit -n 10000' >> $BASH_ENV
|
||||
echo 'sudo launchctl limit maxfiles 65536 200000' >> $BASH_ENV
|
||||
fi
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ]; then
|
||||
echo $RAW_GOMA_AUTH > ~/.goma_oauth2_config
|
||||
fi
|
||||
git clone https://github.com/electron/build-tools.git
|
||||
cd build-tools
|
||||
npx yarn --ignore-engines
|
||||
npm install
|
||||
mkdir third_party
|
||||
# Pull down credential helper and print status
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
HELPER=$(node -p "require('./src/utils/reclient.js').helperPath({})")
|
||||
$HELPER login
|
||||
echo 'export RBE_service='`node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"` >> $BASH_ENV
|
||||
echo 'export RBE_experimental_credentials_helper='`node -e "console.log(require('./src/utils/reclient.js').helperPath({}))"` >> $BASH_ENV
|
||||
echo 'export RBE_experimental_credentials_helper_args="print"' >> $BASH_ENV
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
export GOMA_FALLBACK_ON_AUTH_FAILURE=true
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ] && [ "`third_party/goma/goma_auth.py info`" != "Login as Fermi Planck" ]; then
|
||||
echo "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token."
|
||||
exit 1
|
||||
fi
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
cd ..
|
||||
touch "${TMPDIR:=/tmp}"/.goma-ready
|
||||
background: true
|
||||
|
||||
step-wait-for-goma: &step-wait-for-goma
|
||||
run:
|
||||
name: Wait for Goma
|
||||
command: |
|
||||
until [ -f "${TMPDIR:=/tmp}"/.goma-ready ]
|
||||
do
|
||||
sleep 5
|
||||
done
|
||||
echo "Goma ready"
|
||||
no_output_timeout: 5m
|
||||
|
||||
step-restore-brew-cache: &step-restore-brew-cache
|
||||
restore_cache:
|
||||
@@ -527,13 +550,6 @@ step-fix-sync: &step-fix-sync
|
||||
sed -i '' "s/Updating depot_tools... //g" gn_ensure_file
|
||||
cipd ensure --root src/buildtools/mac -ensure-file gn_ensure_file
|
||||
|
||||
# Fix reclient (wrong binary)
|
||||
echo 'infra/rbe/client/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/buildtools/reclient:infra/rbe/client/${platform}'` > gn_ensure_file
|
||||
# Remove extra output from calling gclient getdep which always calls update_depot_tools
|
||||
sed -i '' "s/Updating depot_tools... //g" gn_ensure_file
|
||||
cipd ensure --root src/buildtools/reclient -ensure-file gn_ensure_file
|
||||
python3 src/buildtools/reclient_cfgs/configure_reclient_cfgs.py --rbe_instance "projects/rbe-chrome-untrusted/instances/default_instance" --reproxy_cfg_template reproxy.cfg.template --rewrapper_cfg_project "" --skip_remoteexec_cfg_fetch
|
||||
|
||||
# Fix dsymutil (wrong binary)
|
||||
if [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
export DSYM_SHA_FILE=src/tools/clang/dsymutil/bin/dsymutil.arm64.sha1
|
||||
@@ -586,7 +602,7 @@ step-gn-gen-default: &step-gn-gen-default
|
||||
name: Default GN gen
|
||||
command: |
|
||||
cd src
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") use_remoteexec=true $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
gn gen out/Default --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
|
||||
step-gn-check: &step-gn-check
|
||||
run:
|
||||
@@ -622,16 +638,16 @@ step-electron-chromedriver-build: &step-electron-chromedriver-build
|
||||
command: |
|
||||
cd src
|
||||
if [ "`uname`" != "Darwin" ] && ([ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]); then
|
||||
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") use_remoteexec=true is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
gn gen out/chromedriver --args="import(\"$GN_CONFIG\") import(\"$GN_GOMA_FILE\") is_component_ffmpeg=false proprietary_codecs=false $GN_EXTRA_ARGS $GN_BUILDFLAG_ARGS"
|
||||
export CHROMEDRIVER_DIR="out/chromedriver"
|
||||
else
|
||||
export CHROMEDRIVER_DIR="out/Default"
|
||||
fi
|
||||
autoninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver -j $NUMBER_OF_NINJA_PROCESSES
|
||||
if [ "`uname`" == "Linux" ]; then
|
||||
electron/script/strip-binaries.py --target-cpu="$TARGET_ARCH" --file $PWD/$CHROMEDRIVER_DIR/chromedriver
|
||||
fi
|
||||
autoninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver_zip
|
||||
ninja -C $CHROMEDRIVER_DIR electron:electron_chromedriver_zip
|
||||
if [ "`uname`" != "Darwin" ] && ([ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]); then
|
||||
cp out/chromedriver/chromedriver.zip out/Default
|
||||
fi
|
||||
@@ -641,7 +657,7 @@ step-nodejs-headers-build: &step-nodejs-headers-build
|
||||
name: Build Node.js headers
|
||||
command: |
|
||||
cd src
|
||||
autoninja -C out/Default electron:node_headers
|
||||
ninja -C out/Default electron:node_headers
|
||||
|
||||
step-electron-publish: &step-electron-publish
|
||||
run:
|
||||
@@ -695,14 +711,14 @@ step-ffmpeg-gn-gen: &step-ffmpeg-gn-gen
|
||||
name: ffmpeg GN gen
|
||||
command: |
|
||||
cd src
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true $GN_EXTRA_ARGS"
|
||||
gn gen out/ffmpeg --args="import(\"//electron/build/args/ffmpeg.gn\") import(\"$GN_GOMA_FILE\") $GN_EXTRA_ARGS"
|
||||
|
||||
step-ffmpeg-build: &step-ffmpeg-build
|
||||
run:
|
||||
name: Non proprietary ffmpeg build
|
||||
command: |
|
||||
cd src
|
||||
autoninja -C out/ffmpeg electron:electron_ffmpeg_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/ffmpeg electron:electron_ffmpeg_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
|
||||
step-verify-mksnapshot: &step-verify-mksnapshot
|
||||
run:
|
||||
@@ -734,13 +750,26 @@ step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
|
||||
sh -e /etc/init.d/xvfb start
|
||||
fi
|
||||
|
||||
step-show-goma-stats: &step-show-goma-stats
|
||||
run:
|
||||
shell: /bin/bash
|
||||
name: Check goma stats after build
|
||||
command: |
|
||||
set +e
|
||||
set +o pipefail
|
||||
python3 $GOMA_DIR/goma_ctl.py stat
|
||||
python3 $GOMA_DIR/diagnose_goma_log.py
|
||||
true
|
||||
when: always
|
||||
background: true
|
||||
|
||||
step-mksnapshot-build: &step-mksnapshot-build
|
||||
run:
|
||||
name: mksnapshot build
|
||||
no_output_timeout: 30m
|
||||
command: |
|
||||
cd src
|
||||
autoninja -C out/Default electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
SEDOPTION="-i"
|
||||
@@ -763,7 +792,7 @@ step-mksnapshot-build: &step-mksnapshot-build
|
||||
fi
|
||||
fi
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
autoninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args gen/v8/embedded.S)
|
||||
fi
|
||||
|
||||
@@ -773,7 +802,7 @@ step-hunspell-build: &step-hunspell-build
|
||||
command: |
|
||||
cd src
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
autoninja -C out/Default electron:hunspell_dictionaries_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:hunspell_dictionaries_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
fi
|
||||
|
||||
step-maybe-generate-libcxx: &step-maybe-generate-libcxx
|
||||
@@ -782,9 +811,9 @@ step-maybe-generate-libcxx: &step-maybe-generate-libcxx
|
||||
command: |
|
||||
cd src
|
||||
if [ "`uname`" == "Linux" ]; then
|
||||
autoninja -C out/Default electron:libcxx_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:libcxxabi_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
autoninja -C out/Default electron:libcxx_objects_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:libcxx_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:libcxxabi_headers_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:libcxx_objects_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
fi
|
||||
|
||||
step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
|
||||
@@ -794,7 +823,7 @@ step-maybe-generate-breakpad-symbols: &step-maybe-generate-breakpad-symbols
|
||||
command: |
|
||||
if [ "$GENERATE_SYMBOLS" == "true" ]; then
|
||||
cd src
|
||||
autoninja -C out/Default electron:electron_symbols
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
fi
|
||||
|
||||
step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
@@ -803,8 +832,8 @@ step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
autoninja -C out/Default electron:licenses
|
||||
autoninja -C out/Default electron:electron_version_file
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version_file
|
||||
electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-zip-symbols-and-clean: &step-maybe-zip-symbols-and-clean
|
||||
@@ -813,8 +842,8 @@ step-maybe-zip-symbols-and-clean: &step-maybe-zip-symbols-and-clean
|
||||
command: |
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
autoninja -C out/Default electron:licenses
|
||||
autoninja -C out/Default electron:electron_version_file
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version_file
|
||||
DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
|
||||
@@ -1161,10 +1190,11 @@ commands:
|
||||
could-be-aks:
|
||||
type: boolean
|
||||
steps:
|
||||
- *step-setup-rbe-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- checkout-from-cache:
|
||||
could-be-aks: << parameters.could-be-aks >>
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
build_and_save_artifacts:
|
||||
@@ -1183,7 +1213,9 @@ 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
|
||||
|
||||
# mksnapshot
|
||||
- *step-mksnapshot-build
|
||||
@@ -1313,7 +1345,7 @@ commands:
|
||||
command: |
|
||||
cd src
|
||||
if [ "$SKIP_DIST_ZIP" != "1" ]; then
|
||||
autoninja -C out/Default electron:electron_dist_zip << parameters.additional-targets >> -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default electron:electron_dist_zip << parameters.additional-targets >> -j $NUMBER_OF_NINJA_PROCESSES
|
||||
if [ "$CHECK_DIST_MANIFEST" == "1" ]; then
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
target_os=mac
|
||||
@@ -1414,7 +1446,7 @@ commands:
|
||||
- when:
|
||||
condition: << parameters.build >>
|
||||
steps:
|
||||
- *step-setup-rbe-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- when:
|
||||
condition: << parameters.checkout-and-assume-cache >>
|
||||
steps:
|
||||
@@ -1533,6 +1565,7 @@ commands:
|
||||
steps:
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-get-more-space-on-mac
|
||||
- *step-fix-sync
|
||||
- *step-delete-git-directories
|
||||
@@ -1718,12 +1751,14 @@ commands:
|
||||
- *step-fix-sync
|
||||
- *step-setup-env-for-build
|
||||
- *step-fix-known-hosts-linux
|
||||
- *step-setup-rbe-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
|
||||
# Electron app
|
||||
- ninja_build_electron:
|
||||
build-type: << parameters.build-type >>
|
||||
- *step-show-goma-stats
|
||||
- *step-maybe-generate-breakpad-symbols
|
||||
- *step-maybe-electron-dist-strip
|
||||
- step-electron-dist-build
|
||||
@@ -2130,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
|
||||
@@ -2296,6 +2331,7 @@ jobs:
|
||||
executor:
|
||||
name: macos
|
||||
size: macos.m1.medium.gen1
|
||||
version: 14.0.0
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
@@ -2322,6 +2358,7 @@ jobs:
|
||||
executor:
|
||||
name: macos
|
||||
size: macos.m1.medium.gen1
|
||||
version: 14.0.0
|
||||
environment:
|
||||
<<: *env-mac-large
|
||||
<<: *env-stack-dumping
|
||||
|
||||
35
.github/workflows/branch-created.yml
vendored
35
.github/workflows/branch-created.yml
vendored
@@ -8,7 +8,7 @@ permissions: {}
|
||||
jobs:
|
||||
release-branch-created:
|
||||
name: Release Branch Created
|
||||
if: ${{ github.event.ref_type == 'branch' && endsWith(github.event.ref, '-x-y') && !startsWith(github.event.ref, 'roller') }}
|
||||
if: ${{ github.event.ref_type == 'branch' && endsWith(github.event.ref, '-x-y') }}
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
@@ -72,44 +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
|
||||
id: create-release-board
|
||||
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: Dump Release Project Board Contents
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
run: gh project item-list ${{ steps.create-release-board.outputs.number }} --owner electron --format json | jq
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
|
||||
- name: Find Previous Release Project Board
|
||||
if: ${{ steps.check-major-version.outputs.MAJOR }}
|
||||
uses: dsanders11/project-actions/find-project@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 }}
|
||||
|
||||
19
.github/workflows/pull-request-labeled.yml
vendored
19
.github/workflows/pull-request-labeled.yml
vendored
@@ -1,26 +1,13 @@
|
||||
name: Pull Request Labeled
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
|
||||
permissions: {}
|
||||
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 ✅'
|
||||
|
||||
37
BUILD.gn
37
BUILD.gn
@@ -29,7 +29,6 @@ import("filenames.gni")
|
||||
import("filenames.hunspell.gni")
|
||||
import("filenames.libcxx.gni")
|
||||
import("filenames.libcxxabi.gni")
|
||||
import("js2c_toolchain.gni")
|
||||
|
||||
if (is_mac) {
|
||||
import("//build/config/mac/rules.gni")
|
||||
@@ -238,7 +237,6 @@ action("electron_js2c") {
|
||||
":electron_sandboxed_renderer_bundle",
|
||||
":electron_utility_bundle",
|
||||
":electron_worker_bundle",
|
||||
"//third_party/electron_node:node_js2c($electron_js2c_toolchain)",
|
||||
]
|
||||
|
||||
sources = [
|
||||
@@ -251,17 +249,13 @@ action("electron_js2c") {
|
||||
"$target_gen_dir/js2c/worker_init.js",
|
||||
]
|
||||
|
||||
inputs = sources
|
||||
inputs = sources + [ "//third_party/electron_node/tools/js2c.py" ]
|
||||
outputs = [ "$root_gen_dir/electron_natives.cc" ]
|
||||
|
||||
script = "build/js2c.py"
|
||||
out_dir =
|
||||
get_label_info(":anything($electron_js2c_toolchain)", "root_out_dir")
|
||||
args = [
|
||||
rebase_path("$out_dir/node_js2c"),
|
||||
rebase_path("$root_gen_dir"),
|
||||
] + rebase_path(outputs, root_gen_dir) +
|
||||
rebase_path(sources, root_gen_dir)
|
||||
args = [ rebase_path("//third_party/electron_node") ] +
|
||||
rebase_path(outputs, root_build_dir) +
|
||||
rebase_path(sources, root_build_dir)
|
||||
}
|
||||
|
||||
action("generate_config_gypi") {
|
||||
@@ -492,7 +486,6 @@ source_set("electron_lib") {
|
||||
"//third_party/webrtc_overrides:webrtc_component",
|
||||
"//third_party/widevine/cdm:headers",
|
||||
"//third_party/zlib/google:zip",
|
||||
"//ui/base:ozone_buildflags",
|
||||
"//ui/base/idle",
|
||||
"//ui/compositor",
|
||||
"//ui/events:dom_keycode_converter",
|
||||
@@ -704,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",
|
||||
]
|
||||
@@ -723,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",
|
||||
@@ -1339,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 =
|
||||
|
||||
11
DEPS
11
DEPS
@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'122.0.6261.139',
|
||||
'120.0.6099.291',
|
||||
'node_version':
|
||||
'v20.9.0',
|
||||
'v18.18.2',
|
||||
'nan_version':
|
||||
'e14bdcd1f72d62bca1d541b66da43130384ec213',
|
||||
'squirrel.mac_version':
|
||||
@@ -13,8 +13,6 @@ vars = {
|
||||
'74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76',
|
||||
'mantle_version':
|
||||
'78d3966b3c331292ea29ec38661b25df0a245948',
|
||||
'engflow_reclient_configs_version':
|
||||
'955335c30a752e9ef7bff375baab5e0819b6c00d',
|
||||
|
||||
'pyyaml_version': '3.12',
|
||||
|
||||
@@ -25,7 +23,6 @@ vars = {
|
||||
'squirrel_git': 'https://github.com/Squirrel',
|
||||
'reactiveobjc_git': 'https://github.com/ReactiveCocoa',
|
||||
'mantle_git': 'https://github.com/Mantle',
|
||||
'engflow_git': 'https://github.com/EngFlow',
|
||||
|
||||
# The path of the sysroots.json file.
|
||||
'sysroots_json_path': 'electron/script/sysroots.json',
|
||||
@@ -105,10 +102,6 @@ deps = {
|
||||
'src/third_party/squirrel.mac/vendor/Mantle': {
|
||||
'url': Var("mantle_git") + '/Mantle.git@' + Var("mantle_version"),
|
||||
'condition': 'process_deps',
|
||||
},
|
||||
'src/third_party/engflow-reclient-configs': {
|
||||
'url': Var("engflow_git") + '/reclient-configs.git@' + Var("engflow_reclient_configs_version"),
|
||||
'condition': 'process_deps'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
10
README.md
10
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
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ environment:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -37,6 +37,7 @@ environment:
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_27370823e7: 28622d16b1
|
||||
@@ -93,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"
|
||||
@@ -100,22 +106,31 @@ for:
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npx yarn --ignore-engines
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
- ps: $env:RECLIENT_HELPER = node -p "require('./src/utils/reclient.js').helperPath({})"
|
||||
- ps: >-
|
||||
& $env:RECLIENT_HELPER login
|
||||
- ps: >-
|
||||
$env:RBE_service = node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper = $env:RECLIENT_HELPER
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper_args = "print"
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..\..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python3 $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
@@ -137,36 +152,37 @@ for:
|
||||
- cd src
|
||||
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") use_remoteexec=true %GN_EXTRA_ARGS% "
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED ELECTRON_RBE_JWT (autoninja -j 300 -C out/Default electron:electron_app) else (autoninja -C out/Default electron:electron_app)
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true %GN_EXTRA_ARGS%"
|
||||
- autoninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- autoninja -C out/Default electron:electron_dist_zip
|
||||
- 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: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') -And -not $_.Contains('The gn arg use_goma=true') } | Set-Content out/Default/mksnapshot_args
|
||||
- autoninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- autoninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- autoninja -C out/Default electron:electron_chromedriver_zip
|
||||
- autoninja -C out/Default electron:node_headers
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default electron:node_headers
|
||||
- python3 %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- ps: >-
|
||||
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
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
autoninja -C out/Default electron:electron_symbols
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
@@ -189,16 +205,13 @@ for:
|
||||
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"
|
||||
}
|
||||
@@ -230,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)
|
||||
@@ -269,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
|
||||
@@ -293,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
|
||||
|
||||
69
appveyor.yml
69
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
|
||||
@@ -37,6 +37,7 @@ environment:
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: "@marshallofsound/mocha-appveyor-reporter, tap"
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 1
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN_BASE_URL: "https://dev-cdn.electronjs.org/windows-toolchains/_"
|
||||
GYP_MSVS_HASH_27370823e7: 28622d16b1
|
||||
@@ -91,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"
|
||||
@@ -98,22 +104,31 @@ for:
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npx yarn --ignore-engines
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/reclient.js').downloadAndPrepare({})"
|
||||
- ps: $env:RECLIENT_HELPER = node -p "require('./src/utils/reclient.js').helperPath({})"
|
||||
- ps: >-
|
||||
& $env:RECLIENT_HELPER login
|
||||
- ps: >-
|
||||
$env:RBE_service = node -e "console.log(require('./src/utils/reclient.js').serviceAddress)"
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper = $env:RECLIENT_HELPER
|
||||
- ps: >-
|
||||
$env:RBE_experimental_credentials_helper_args = "print"
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..\..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python3 $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
@@ -135,26 +150,28 @@ for:
|
||||
- cd src
|
||||
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") use_remoteexec=true %GN_EXTRA_ARGS% "
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED ELECTRON_RBE_JWT (autoninja -j 300 -C out/Default electron:electron_app) else (autoninja -C out/Default electron:electron_app)
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") use_remoteexec=true %GN_EXTRA_ARGS%"
|
||||
- autoninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- autoninja -C out/Default electron:electron_dist_zip
|
||||
- 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: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') -And -not $_.Contains('The gn arg use_goma=true') } | Set-Content out/Default/mksnapshot_args
|
||||
- autoninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- autoninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- autoninja -C out/Default electron:electron_chromedriver_zip
|
||||
- autoninja -C out/Default electron:node_headers
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default electron:node_headers
|
||||
- python3 %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- ps: >-
|
||||
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
|
||||
@@ -163,7 +180,7 @@ for:
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
autoninja -C out/Default electron:electron_symbols
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
@@ -186,7 +203,7 @@ for:
|
||||
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"
|
||||
@@ -224,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)
|
||||
@@ -260,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
|
||||
@@ -299,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"
|
||||
|
||||
@@ -2,7 +2,7 @@ is_electron_build = true
|
||||
root_extra_deps = [ "//electron" ]
|
||||
|
||||
# Registry of NMVs --> https://github.com/nodejs/node/blob/main/doc/abi_version_registry.json
|
||||
node_module_version = 121
|
||||
node_module_version = 119
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_embedder_string = "-electron.0"
|
||||
@@ -64,6 +64,3 @@ enable_dangling_raw_ptr_checks = false
|
||||
# This flag speeds up the performance of fork/execve on linux systems.
|
||||
# Ref: https://chromium-review.googlesource.com/c/v8/v8/+/4602858
|
||||
v8_enable_private_mapping_fork_optimization = true
|
||||
|
||||
# Expose public V8 symbols for native modules.
|
||||
v8_expose_public_symbols = true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
|
||||
import collections
|
||||
import os
|
||||
|
||||
@@ -32,13 +32,6 @@ extern const volatile char kFuseWire[];
|
||||
|
||||
TEMPLATE_CC = """
|
||||
#include "electron/fuses.h"
|
||||
#include "base/dcheck_is_on.h"
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
#include "base/command_line.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
namespace electron::fuses {
|
||||
|
||||
@@ -73,20 +66,9 @@ for fuse in fuses:
|
||||
getters_h += "FUSE_EXPORT bool Is{name}Enabled();\n".replace("{name}", name)
|
||||
getters_cc += """
|
||||
bool Is{name}Enabled() {
|
||||
#if DCHECK_IS_ON()
|
||||
// RunAsNode is checked so early that base::CommandLine isn't yet
|
||||
// initialized, so guard here to avoid a CHECK.
|
||||
if (base::CommandLine::InitializedForCurrentProcess()) {
|
||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||
if (command_line->HasSwitch("{switch_name}")) {
|
||||
std::string switch_value = command_line->GetSwitchValueASCII("{switch_name}");
|
||||
return switch_value == "1";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return kFuseWire[{index}] == '1';
|
||||
}
|
||||
""".replace("{name}", name).replace("{switch_name}", f"set-fuse-{fuse.lower()}").replace("{index}", str(index))
|
||||
""".replace("{name}", name).replace("{index}", str(index))
|
||||
|
||||
def c_hex(n):
|
||||
s = hex(n)[2:]
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
32
build/js2c.py
Normal file → Executable file
32
build/js2c.py
Normal file → Executable file
@@ -4,14 +4,32 @@ import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
def main():
|
||||
js2c = sys.argv[1]
|
||||
root = sys.argv[2]
|
||||
natives = sys.argv[3]
|
||||
js_source_files = sys.argv[4:]
|
||||
TEMPLATE = """
|
||||
#include "node_native_module.h"
|
||||
#include "node_internals.h"
|
||||
|
||||
namespace node::native_module {{
|
||||
|
||||
{definitions}
|
||||
|
||||
void NativeModuleLoader::LoadEmbedderJavaScriptSource() {{
|
||||
{initializers}
|
||||
}}
|
||||
|
||||
}} // namespace node::native_module
|
||||
"""
|
||||
|
||||
def main():
|
||||
node_path = os.path.abspath(sys.argv[1])
|
||||
natives = os.path.abspath(sys.argv[2])
|
||||
js_source_files = sys.argv[3:]
|
||||
|
||||
js2c = os.path.join(node_path, 'tools', 'js2c.py')
|
||||
subprocess.check_call(
|
||||
[js2c, natives] + js_source_files + ['--only-js', "--root", root])
|
||||
[sys.executable, js2c] +
|
||||
js_source_files +
|
||||
['--only-js', '--target', natives])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main())
|
||||
sys.exit(main())
|
||||
|
||||
@@ -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,11 +1,10 @@
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
def main(argv):
|
||||
os.chdir(argv[1])
|
||||
p = subprocess.Popen(argv[2:])
|
||||
return p.wait()
|
||||
cwd = argv[1]
|
||||
os.chdir(cwd)
|
||||
os.execv(sys.executable, [sys.executable] + argv[2:])
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.exit(main(sys.argv))
|
||||
main(sys.argv)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -31,8 +31,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/devtools/devtools_file_system_indexer.cc",
|
||||
"//chrome/browser/devtools/devtools_file_system_indexer.h",
|
||||
"//chrome/browser/devtools/devtools_settings.h",
|
||||
"//chrome/browser/devtools/visual_logging.cc",
|
||||
"//chrome/browser/devtools/visual_logging.h",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener.h",
|
||||
"//chrome/browser/icon_loader.cc",
|
||||
@@ -59,14 +57,8 @@ static_library("chrome") {
|
||||
"//chrome/browser/net/proxy_service_factory.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_bounds_cache.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_bounds_cache.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker_observer.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_occlusion_tracker_observer.h",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.cc",
|
||||
"//chrome/browser/picture_in_picture/picture_in_picture_window_manager.h",
|
||||
"//chrome/browser/picture_in_picture/scoped_picture_in_picture_occlusion_observation.cc",
|
||||
"//chrome/browser/picture_in_picture/scoped_picture_in_picture_occlusion_observation.h",
|
||||
"//chrome/browser/platform_util.cc",
|
||||
"//chrome/browser/platform_util.h",
|
||||
"//chrome/browser/predictors/preconnect_manager.cc",
|
||||
@@ -242,8 +234,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_mac.mm",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.h",
|
||||
"//chrome/browser/media/webrtc/system_media_capture_permissions_stats_mac.mm",
|
||||
"//chrome/browser/media/webrtc/thumbnail_capturer_mac.h",
|
||||
"//chrome/browser/media/webrtc/thumbnail_capturer_mac.mm",
|
||||
"//chrome/browser/media/webrtc/window_icon_util_mac.mm",
|
||||
"//chrome/browser/platform_util_mac.mm",
|
||||
"//chrome/browser/process_singleton_mac.mm",
|
||||
@@ -345,8 +335,6 @@ static_library("chrome") {
|
||||
"//chrome/browser/pdf/pdf_extension_util.h",
|
||||
"//chrome/browser/pdf/pdf_frame_util.cc",
|
||||
"//chrome/browser/pdf/pdf_frame_util.h",
|
||||
"//chrome/browser/pdf/pdf_viewer_stream_manager.cc",
|
||||
"//chrome/browser/pdf/pdf_viewer_stream_manager.h",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.cc",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.h",
|
||||
]
|
||||
@@ -454,8 +442,6 @@ source_set("chrome_spellchecker") {
|
||||
"//chrome/browser/profiles/profile_selections.h",
|
||||
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.cc",
|
||||
"//chrome/browser/spellchecker/spell_check_host_chrome_impl.h",
|
||||
"//chrome/browser/spellchecker/spell_check_initialization_host_impl.cc",
|
||||
"//chrome/browser/spellchecker/spell_check_initialization_host_impl.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.cc",
|
||||
"//chrome/browser/spellchecker/spellcheck_custom_dictionary.h",
|
||||
"//chrome/browser/spellchecker/spellcheck_factory.cc",
|
||||
|
||||
@@ -32,7 +32,7 @@ In most cases, you should do everything in the `ready` event handler.
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `launchInfo` Record\<string, any\> | [NotificationResponse](structures/notification-response.md) _macOS_
|
||||
* `launchInfo` Record<string, any> | [NotificationResponse](structures/notification-response.md) _macOS_
|
||||
|
||||
Emitted once, when Electron has finished initializing. On macOS, `launchInfo`
|
||||
holds the `userInfo` of the [`NSUserNotification`](https://developer.apple.com/documentation/foundation/nsusernotification)
|
||||
@@ -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:
|
||||
@@ -970,7 +999,7 @@ app.setJumpList([
|
||||
|
||||
### `app.requestSingleInstanceLock([additionalData])`
|
||||
|
||||
* `additionalData` Record\<any, any\> (optional) - A JSON object containing additional data to send to the first instance.
|
||||
* `additionalData` Record<any, any> (optional) - A JSON object containing additional data to send to the first instance.
|
||||
|
||||
Returns `boolean`
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -103,7 +103,7 @@ The `autoUpdater` object has the following methods:
|
||||
|
||||
* `options` Object
|
||||
* `url` string
|
||||
* `headers` Record\<string, string\> (optional) _macOS_ - HTTP request headers.
|
||||
* `headers` Record<string, string> (optional) _macOS_ - HTTP request headers.
|
||||
* `serverType` string (optional) _macOS_ - Can be `json` or `default`, see the [Squirrel.Mac][squirrel-mac]
|
||||
README for more information.
|
||||
|
||||
|
||||
@@ -775,7 +775,7 @@ Closes the currently open [Quick Look][quick-look] panel.
|
||||
|
||||
#### `win.setBounds(bounds[, animate])`
|
||||
|
||||
* `bounds` Partial\<[Rectangle](structures/rectangle.md)\>
|
||||
* `bounds` Partial<[Rectangle](structures/rectangle.md)>
|
||||
* `animate` boolean (optional) _macOS_
|
||||
|
||||
Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values.
|
||||
@@ -1211,7 +1211,7 @@ win.loadURL('http://localhost:8000/post', {
|
||||
|
||||
* `filePath` string
|
||||
* `options` Object (optional)
|
||||
* `query` Record\<string, string\> (optional) - Passed to `url.format()`.
|
||||
* `query` Record<string, string> (optional) - Passed to `url.format()`.
|
||||
* `search` string (optional) - Passed to `url.format()`.
|
||||
* `hash` string (optional) - Passed to `url.format()`.
|
||||
|
||||
|
||||
@@ -17,6 +17,8 @@ following properties:
|
||||
method.
|
||||
* `url` string (optional) - The request URL. Must be provided in the absolute
|
||||
form with the protocol scheme specified as http or https.
|
||||
* `headers` Record<string, string | string[]> (optional) - Headers to be sent
|
||||
with the request.
|
||||
* `session` Session (optional) - The [`Session`](session.md) instance with
|
||||
which the request is associated.
|
||||
* `partition` string (optional) - The name of the [`partition`](session.md)
|
||||
@@ -158,7 +160,7 @@ Returns:
|
||||
* `statusCode` Integer
|
||||
* `method` string
|
||||
* `redirectUrl` string
|
||||
* `responseHeaders` Record\<string, string[]\>
|
||||
* `responseHeaders` Record<string, string[]>
|
||||
|
||||
Emitted when the server returns a redirect response (e.g. 301 Moved
|
||||
Permanently). Calling [`request.followRedirect`](#requestfollowredirect) will
|
||||
|
||||
@@ -59,14 +59,14 @@ The `crashReporter` module has the following methods:
|
||||
number of crashes uploaded to 1/hour. Default is `false`.
|
||||
* `compress` boolean (optional) - If true, crash reports will be compressed
|
||||
and uploaded with `Content-Encoding: gzip`. Default is `true`.
|
||||
* `extra` Record\<string, string\> (optional) - Extra string key/value
|
||||
* `extra` Record<string, string> (optional) - Extra string key/value
|
||||
annotations that will be sent along with crash reports that are generated
|
||||
in the main process. Only string values are supported. Crashes generated in
|
||||
child processes will not contain these extra
|
||||
parameters to crash reports generated from child processes, call
|
||||
[`addExtraParameter`](#crashreporteraddextraparameterkey-value) from the
|
||||
child process.
|
||||
* `globalExtra` Record\<string, string\> (optional) - Extra string key/value
|
||||
* `globalExtra` Record<string, string> (optional) - Extra string key/value
|
||||
annotations that will be sent along with any crash reports generated in any
|
||||
process. These annotations cannot be changed once the crash reporter has
|
||||
been started. If a key is present in both the global extra parameters and
|
||||
@@ -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
|
||||
|
||||
@@ -72,7 +72,7 @@ Removes listeners of the specified `channel`.
|
||||
### `ipcMain.handle(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `listener` Function<Promise\<any> | any>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
* `...args` any[]
|
||||
|
||||
@@ -109,7 +109,7 @@ provided to the renderer process. Please refer to
|
||||
### `ipcMain.handleOnce(channel, listener)`
|
||||
|
||||
* `channel` string
|
||||
* `listener` Function\<Promise\<any\> | any\>
|
||||
* `listener` Function<Promise\<any> | any>
|
||||
* `event` [IpcMainInvokeEvent][ipc-main-invoke-event]
|
||||
* `...args` any[]
|
||||
|
||||
|
||||
@@ -4,41 +4,36 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
|
||||
The `nativeImage` module provides a unified interface for manipulating
|
||||
system images. These can be handy if you want to provide multiple scaled
|
||||
versions of the same icon or take advantage of macOS [template images][template-image].
|
||||
In Electron, for the APIs that take images, you can pass either file paths or
|
||||
`NativeImage` instances. An empty image will be used when `null` is passed.
|
||||
|
||||
Electron APIs that take image files accept either file paths or
|
||||
`NativeImage` instances. An empty and transparent image will be used when `null` is passed.
|
||||
For example, when creating a tray or setting a window's icon, you can pass an
|
||||
image file path as a `string`:
|
||||
|
||||
For example, when creating a [Tray](../api/tray.md) or setting a [BrowserWindow](../api/browser-window.md)'s
|
||||
icon, you can either pass an image file path as a string:
|
||||
|
||||
```js title='Main Process'
|
||||
```js
|
||||
const { BrowserWindow, Tray } = require('electron')
|
||||
|
||||
const tray = new Tray('/Users/somebody/images/icon.png')
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
const win = new BrowserWindow({ icon: '/Users/somebody/images/window.png' })
|
||||
console.log(appIcon, win)
|
||||
```
|
||||
|
||||
or generate a `NativeImage` instance from the same file:
|
||||
Or read the image from the clipboard, which returns a `NativeImage`:
|
||||
|
||||
```js title='Main Process'
|
||||
const { BrowserWindow, nativeImage, Tray } = require('electron')
|
||||
|
||||
const trayIcon = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
const appIcon = nativeImage.createFromPath('/Users/somebody/images/window.png')
|
||||
const tray = new Tray(trayIcon)
|
||||
const win = new BrowserWindow({ icon: appIcon })
|
||||
```js
|
||||
const { clipboard, Tray } = require('electron')
|
||||
const image = clipboard.readImage()
|
||||
const appIcon = new Tray(image)
|
||||
console.log(appIcon)
|
||||
```
|
||||
|
||||
## Supported Formats
|
||||
|
||||
Currently, `PNG` and `JPEG` image formats are supported across all platforms.
|
||||
`PNG` is recommended because of its support for transparency and lossless compression.
|
||||
Currently `PNG` and `JPEG` image formats are supported. `PNG` is recommended
|
||||
because of its support for transparency and lossless compression.
|
||||
|
||||
On Windows, you can also load `ICO` icons from file paths. For best visual
|
||||
quality, we recommend including at least the following sizes:
|
||||
quality, it is recommended to include at least the following sizes in the:
|
||||
|
||||
* Small icon
|
||||
* 16x16 (100% DPI scale)
|
||||
@@ -52,9 +47,9 @@ quality, we recommend including at least the following sizes:
|
||||
* 64x64 (200% DPI scale)
|
||||
* 256x256
|
||||
|
||||
Check the _Icon Scaling_ section in the Windows [App Icon Construction][icons] reference.
|
||||
Check the _Size requirements_ section in [this article][icons].
|
||||
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/apps/design/style/iconography/app-icon-construction#icon-scaling
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-icons
|
||||
|
||||
:::note
|
||||
|
||||
@@ -65,17 +60,16 @@ image encoding and decoding.
|
||||
|
||||
## High Resolution Image
|
||||
|
||||
On platforms that support high pixel density displays (such as Apple Retina),
|
||||
you can append `@2x` after image's base filename to mark it as a 2x scale
|
||||
high resolution image.
|
||||
On platforms that have high-DPI support such as Apple Retina displays, you can
|
||||
append `@2x` after image's base filename to mark it as a high resolution image.
|
||||
|
||||
For example, if `icon.png` is a normal image that has standard resolution, then
|
||||
`icon@2x.png` will be treated as a high resolution image that has double
|
||||
Dots per Inch (DPI) density.
|
||||
`icon@2x.png` will be treated as a high resolution image that has double DPI
|
||||
density.
|
||||
|
||||
If you want to support displays with different DPI densities at the same time,
|
||||
you can put images with different sizes in the same folder and use the filename
|
||||
without DPI suffixes within Electron. For example:
|
||||
without DPI suffixes. For example:
|
||||
|
||||
```plaintext
|
||||
images/
|
||||
@@ -84,9 +78,10 @@ images/
|
||||
└── icon@3x.png
|
||||
```
|
||||
|
||||
```js title='Main Process'
|
||||
```js
|
||||
const { Tray } = require('electron')
|
||||
const appTray = new Tray('/Users/somebody/images/icon.png')
|
||||
const appIcon = new Tray('/Users/somebody/images/icon.png')
|
||||
console.log(appIcon)
|
||||
```
|
||||
|
||||
The following suffixes for DPI are also supported:
|
||||
@@ -103,23 +98,27 @@ The following suffixes for DPI are also supported:
|
||||
* `@4x`
|
||||
* `@5x`
|
||||
|
||||
## Template Image _macOS_
|
||||
## Template Image
|
||||
|
||||
On macOS, [template images][template-image] consist of black and an alpha channel.
|
||||
Template images consist of black and an alpha channel.
|
||||
Template images are not intended to be used as standalone images and are usually
|
||||
mixed with other content to create the desired final appearance.
|
||||
|
||||
The most common case is to use template images for a menu bar (Tray) icon, so it can
|
||||
The most common case is to use template images for a menu bar icon, so it can
|
||||
adapt to both light and dark menu bars.
|
||||
|
||||
To mark an image as a template image, its base filename should end with the word
|
||||
`Template` (e.g. `xxxTemplate.png`). You can also specify template images at
|
||||
different DPI densities (e.g. `xxxTemplate@2x.png`).
|
||||
**Note:** Template image is only supported on macOS.
|
||||
|
||||
To mark an image as a template image, its filename should end with the word
|
||||
`Template`. For example:
|
||||
|
||||
* `xxxTemplate.png`
|
||||
* `xxxTemplate@2x.png`
|
||||
|
||||
## Methods
|
||||
|
||||
The `nativeImage` module has the following methods, all of which return
|
||||
an instance of the [`NativeImage`](#class-nativeimage) class:
|
||||
an instance of the `NativeImage` class:
|
||||
|
||||
### `nativeImage.createEmpty()`
|
||||
|
||||
@@ -138,7 +137,7 @@ Note: The Windows implementation will ignore `size.height` and scale the height
|
||||
|
||||
### `nativeImage.createFromPath(path)`
|
||||
|
||||
* `path` string - path to a file that we intend to construct an image out of.
|
||||
* `path` string
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
@@ -147,7 +146,7 @@ returns an empty image if the `path` does not exist, cannot be read, or is not
|
||||
a valid image.
|
||||
|
||||
```js
|
||||
const { nativeImage } = require('electron')
|
||||
const nativeImage = require('electron').nativeImage
|
||||
|
||||
const image = nativeImage.createFromPath('/Users/somebody/images/icon.png')
|
||||
console.log(image)
|
||||
@@ -184,7 +183,7 @@ Creates a new `NativeImage` instance from `buffer`. Tries to decode as PNG or JP
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
Creates a new `NativeImage` instance from `dataUrl`, a base 64 encoded [Data URL][data-url] string.
|
||||
Creates a new `NativeImage` instance from `dataURL`.
|
||||
|
||||
### `nativeImage.createFromNamedImage(imageName[, hslShift])` _macOS_
|
||||
|
||||
@@ -193,14 +192,14 @@ Creates a new `NativeImage` instance from `dataUrl`, a base 64 encoded [Data URL
|
||||
|
||||
Returns `NativeImage`
|
||||
|
||||
Creates a new `NativeImage` instance from the `NSImage` that maps to the
|
||||
given image name. See Apple's [`NSImageName`](https://developer.apple.com/documentation/appkit/nsimagename#2901388)
|
||||
documentation for a list of possible values.
|
||||
Creates a new `NativeImage` instance from the NSImage that maps to the
|
||||
given image name. See [`System Icons`](https://developer.apple.com/design/human-interface-guidelines/macos/icons-and-images/system-icons/)
|
||||
for a list of possible values.
|
||||
|
||||
The `hslShift` is applied to the image with the following rules:
|
||||
|
||||
* `hsl_shift[0]` (hue): The absolute hue value for the image - 0 and 1 map
|
||||
to 0 and 360 on the hue color wheel (red).
|
||||
to 0 and 360 on the hue color wheel (red).
|
||||
* `hsl_shift[1]` (saturation): A saturation shift for the image, with the
|
||||
following key values:
|
||||
0 = remove all color.
|
||||
@@ -217,9 +216,7 @@ This means that `[-1, 0, 1]` will make the image completely white and
|
||||
|
||||
In some cases, the `NSImageName` doesn't match its string representation; one example of this is `NSFolderImageName`, whose string representation would actually be `NSFolder`. Therefore, you'll need to determine the correct string representation for your image before passing it in. This can be done with the following:
|
||||
|
||||
```sh
|
||||
echo -e '#import <Cocoa/Cocoa.h>\nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME); }' | clang -otest -x objective-c -framework Cocoa - && ./test
|
||||
```
|
||||
`echo -e '#import <Cocoa/Cocoa.h>\nint main() { NSLog(@"%@", SYSTEM_IMAGE_NAME); }' | clang -otest -x objective-c -framework Cocoa - && ./test`
|
||||
|
||||
where `SYSTEM_IMAGE_NAME` should be replaced with any value from [this list](https://developer.apple.com/documentation/appkit/nsimagename?language=objc).
|
||||
|
||||
@@ -260,7 +257,7 @@ data.
|
||||
* `options` Object (optional)
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `string` - The [Data URL][data-url] of the image.
|
||||
Returns `string` - The data URL of the image.
|
||||
|
||||
#### `image.getBitmap([options])`
|
||||
|
||||
@@ -276,7 +273,7 @@ current event loop tick; otherwise the data might be changed or destroyed.
|
||||
#### `image.getNativeHandle()` _macOS_
|
||||
|
||||
Returns `Buffer` - A [Buffer][buffer] that stores C pointer to underlying native handle of
|
||||
the image. On macOS, a pointer to `NSImage` instance is returned.
|
||||
the image. On macOS, a pointer to `NSImage` instance would be returned.
|
||||
|
||||
Notice that the returned pointer is a weak pointer to the underlying native
|
||||
image instead of a copy, so you _must_ ensure that the associated
|
||||
@@ -298,11 +295,11 @@ If `scaleFactor` is passed, this will return the size corresponding to the image
|
||||
|
||||
* `option` boolean
|
||||
|
||||
Marks the image as a macOS [template image][template-image].
|
||||
Marks the image as a template image.
|
||||
|
||||
#### `image.isTemplateImage()`
|
||||
|
||||
Returns `boolean` - Whether the image is a macOS [template image][template-image].
|
||||
Returns `boolean` - Whether the image is a template image.
|
||||
|
||||
#### `image.crop(rect)`
|
||||
|
||||
@@ -331,13 +328,13 @@ will be preserved in the resized image.
|
||||
|
||||
* `scaleFactor` Number (optional) - Defaults to 1.0.
|
||||
|
||||
Returns `Number` - The image's aspect ratio (width divided by height).
|
||||
Returns `Number` - The image's aspect ratio.
|
||||
|
||||
If `scaleFactor` is passed, this will return the aspect ratio corresponding to the image representation most closely matching the passed value.
|
||||
|
||||
#### `image.getScaleFactors()`
|
||||
|
||||
Returns `Number[]` - An array of all scale factors corresponding to representations for a given `NativeImage`.
|
||||
Returns `Number[]` - An array of all scale factors corresponding to representations for a given nativeImage.
|
||||
|
||||
#### `image.addRepresentation(options)`
|
||||
|
||||
@@ -352,17 +349,15 @@ Returns `Number[]` - An array of all scale factors corresponding to representati
|
||||
encoded PNG or JPEG image.
|
||||
|
||||
Add an image representation for a specific scale factor. This can be used
|
||||
to programmatically add different scale factor representations to an image. This
|
||||
to explicitly add different scale factor representations to an image. This
|
||||
can be called on empty images.
|
||||
|
||||
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
|
||||
|
||||
### Instance Properties
|
||||
|
||||
#### `nativeImage.isMacTemplateImage` _macOS_
|
||||
|
||||
A `boolean` property that determines whether the image is considered a [template image][template-image].
|
||||
A `boolean` property that determines whether the image is considered a [template image](https://developer.apple.com/documentation/appkit/nsimage/1520017-template).
|
||||
|
||||
Please note that this property only has an effect on macOS.
|
||||
|
||||
[buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer
|
||||
[data-url]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URLs
|
||||
[template-image]: https://developer.apple.com/documentation/appkit/nsimage/1520017-template
|
||||
|
||||
@@ -111,7 +111,7 @@ expect streaming responses.
|
||||
|
||||
* `scheme` string - scheme to handle, for example `https` or `my-app`. This is
|
||||
the bit before the `:` in a URL.
|
||||
* `handler` Function\<[GlobalResponse](https://nodejs.org/api/globals.html#response) | Promise\<GlobalResponse\>\>
|
||||
* `handler` Function<[GlobalResponse](https://nodejs.org/api/globals.html#response) | Promise<GlobalResponse>>
|
||||
* `request` [GlobalRequest](https://nodejs.org/api/globals.html#request)
|
||||
|
||||
Register a protocol handler for `scheme`. Requests made to URLs with this
|
||||
@@ -123,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([
|
||||
@@ -146,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,
|
||||
|
||||
@@ -27,7 +27,7 @@ The `pushNotification` module emits the following events:
|
||||
Returns:
|
||||
|
||||
* `event` Event
|
||||
* `userInfo` Record\<String, any\>
|
||||
* `userInfo` Record<String, any>
|
||||
|
||||
Emitted when the app receives a remote notification while running.
|
||||
See: https://developer.apple.com/documentation/appkit/nsapplicationdelegate/1428430-application?language=objc
|
||||
|
||||
@@ -813,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
|
||||
@@ -861,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.
|
||||
@@ -1215,7 +1219,7 @@ Returns `Promise<Buffer>` - resolves with blob data.
|
||||
|
||||
* `url` string
|
||||
* `options` Object (optional)
|
||||
* `headers` Record\<string, string\> (optional) - HTTP request headers.
|
||||
* `headers` Record<string, string> (optional) - HTTP request headers.
|
||||
|
||||
Initiates a download of the resource at `url`.
|
||||
The API will generate a [DownloadItem](download-item.md) that can be accessed
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# FilePathWithHeaders Object
|
||||
|
||||
* `path` string - The path to the file to send.
|
||||
* `headers` Record\<string, string\> (optional) - Additional headers to be sent.
|
||||
* `headers` Record<string, string> (optional) - Additional headers to be sent.
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
* `actionIdentifier` string - The identifier string of the action that the user selected.
|
||||
* `date` number - The delivery date of the notification.
|
||||
* `identifier` string - The unique identifier for this notification request.
|
||||
* `userInfo` Record\<string, any\> - A dictionary of custom information associated with the notification.
|
||||
* `userInfo` Record<string, any> - A dictionary of custom information associated with the notification.
|
||||
* `userText` string (optional) - The text entered or chosen by the user.
|
||||
|
||||
@@ -4,4 +4,4 @@
|
||||
* `referrer` string
|
||||
* `method` string
|
||||
* `uploadData` [UploadData[]](upload-data.md) (optional)
|
||||
* `headers` Record\<string, string\>
|
||||
* `headers` Record<string, string>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
`"text/html"`. Setting `mimeType` would implicitly set the `content-type`
|
||||
header in response, but if `content-type` is already set in `headers`, the
|
||||
`mimeType` would be ignored.
|
||||
* `headers` Record\<string, string | string[]\> (optional) - An object containing the response headers. The
|
||||
* `headers` Record<string, string | string[]> (optional) - An object containing the response headers. The
|
||||
keys must be string, and values must be either string or Array of string.
|
||||
* `data` (Buffer | string | ReadableStream) (optional) - The response body. When
|
||||
returning stream as response, this is a Node.js readable stream representing
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
include in the trace. If not specified, trace all processes.
|
||||
* `histogram_names` string[] (optional) - a list of [histogram][] names to report
|
||||
with the trace.
|
||||
* `memory_dump_config` Record\<string, any\> (optional) - if the
|
||||
* `memory_dump_config` Record<string, any> (optional) - if the
|
||||
`disabled-by-default-memory-infra` category is enabled, this contains
|
||||
optional additional configuration for data collection. See the [Chromium
|
||||
memory-infra docs][memory-infra docs] for more information.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -36,7 +36,7 @@ Returns `boolean` - Whether the Swipe between pages setting is on.
|
||||
### `systemPreferences.postNotification(event, userInfo[, deliverImmediately])` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `userInfo` Record\<string, any\>
|
||||
* `userInfo` Record<string, any>
|
||||
* `deliverImmediately` boolean (optional) - `true` to post notifications immediately even when the subscribing app is inactive.
|
||||
|
||||
Posts `event` as native notifications of macOS. The `userInfo` is an Object
|
||||
@@ -45,7 +45,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
### `systemPreferences.postLocalNotification(event, userInfo)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `userInfo` Record\<string, any\>
|
||||
* `userInfo` Record<string, any>
|
||||
|
||||
Posts `event` as native notifications of macOS. The `userInfo` is an Object
|
||||
that contains the user information dictionary sent along with the notification.
|
||||
@@ -53,7 +53,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
### `systemPreferences.postWorkspaceNotification(event, userInfo)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `userInfo` Record\<string, any\>
|
||||
* `userInfo` Record<string, any>
|
||||
|
||||
Posts `event` as native notifications of macOS. The `userInfo` is an Object
|
||||
that contains the user information dictionary sent along with the notification.
|
||||
@@ -63,7 +63,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record\<string, unknown\>
|
||||
* `userInfo` Record<string, unknown>
|
||||
* `object` string
|
||||
|
||||
Returns `number` - The ID of this subscription
|
||||
@@ -92,7 +92,7 @@ If `event` is null, the `NSDistributedNotificationCenter` doesn’t use it as cr
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record\<string, unknown\>
|
||||
* `userInfo` Record<string, unknown>
|
||||
* `object` string
|
||||
|
||||
Returns `number` - The ID of this subscription
|
||||
@@ -107,7 +107,7 @@ If `event` is null, the `NSNotificationCenter` doesn’t use it as criteria for
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record\<string, unknown\>
|
||||
* `userInfo` Record<string, unknown>
|
||||
* `object` string
|
||||
|
||||
Returns `number` - The ID of this subscription
|
||||
@@ -137,7 +137,7 @@ Same as `unsubscribeNotification`, but removes the subscriber from `NSWorkspace.
|
||||
|
||||
### `systemPreferences.registerDefaults(defaults)` _macOS_
|
||||
|
||||
* `defaults` Record\<string, string | boolean | number\> - a dictionary of (`key: value`) user defaults
|
||||
* `defaults` Record<string, string | boolean | number> - a dictionary of (`key: value`) user defaults
|
||||
|
||||
Add the specified defaults to your application's `NSUserDefaults`.
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ app.whenReady().then(() => {
|
||||
|
||||
**MacOS**
|
||||
|
||||
* Icons passed to the Tray constructor should be [Template Images](native-image.md#template-image-macos).
|
||||
* Icons passed to the Tray constructor should be [Template Images](native-image.md#template-image).
|
||||
* To make sure your icon isn't grainy on retina monitors, be sure your `@2x` image is 144dpi.
|
||||
* If you are bundling your application (e.g., with webpack for development), be sure that the file names are not being mangled or hashed. The filename needs to end in Template, and the `@2x` image needs to have the same filename as the standard image, or MacOS will not magically invert your image's colors or use the high density image.
|
||||
* 16x16 (72dpi) and 32x32@2x (144dpi) work well for most icons.
|
||||
|
||||
@@ -21,11 +21,12 @@ Process: [Main](../glossary.md#main-process)<br />
|
||||
of the child process. Default is `inherit`.
|
||||
String value can be one of `pipe`, `ignore`, `inherit`, for more details on these values you can refer to
|
||||
[stdio][] documentation from Node.js. Currently this option only supports configuring `stdout` and
|
||||
`stderr` to either `pipe`, `inherit` or `ignore`. Configuring `stdin` to any property other than `ignore` is not supported and will result in an error.
|
||||
`stderr` to either `pipe`, `inherit` or `ignore`. Configuring `stdin` is not supported; `stdin` will
|
||||
always be ignored.
|
||||
For example, the supported values will be processed as following:
|
||||
* `pipe`: equivalent to \['ignore', 'pipe', 'pipe']
|
||||
* `pipe`: equivalent to \['ignore', 'pipe', 'pipe'] (the default)
|
||||
* `ignore`: equivalent to \['ignore', 'ignore', 'ignore']
|
||||
* `inherit`: equivalent to \['ignore', 'inherit', 'inherit'] (the default)
|
||||
* `inherit`: equivalent to \['ignore', 'inherit', 'inherit']
|
||||
* `serviceName` string (optional) - Name of the process that will appear in `name` property of
|
||||
[`ProcessMetric`](structures/process-metric.md) returned by [`app.getAppMetrics`](app.md#appgetappmetrics)
|
||||
and [`child-process-gone` event of `app`](app.md#event-child-process-gone).
|
||||
|
||||
@@ -237,7 +237,7 @@ See [`window.open()`](window-open.md) for more details and how to use this in co
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `details` Event<>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - This event does not fire for same document navigations using window.history api and reference fragment navigations.
|
||||
This property is always set to `false` for this event.
|
||||
@@ -270,7 +270,7 @@ Calling `event.preventDefault()` will prevent the navigation.
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `details` Event<>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - This event does not fire for same document navigations using window.history api and reference fragment navigations.
|
||||
This property is always set to `false` for this event.
|
||||
@@ -300,7 +300,7 @@ Calling `event.preventDefault()` will prevent the navigation.
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `details` Event<>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - Whether the navigation happened without changing
|
||||
document. Examples of same document navigations are reference fragment
|
||||
@@ -324,7 +324,7 @@ Emitted when any frame (including main) starts navigating.
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `details` Event<>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - Whether the navigation happened without changing
|
||||
document. Examples of same document navigations are reference fragment
|
||||
@@ -355,7 +355,7 @@ redirect).
|
||||
|
||||
Returns:
|
||||
|
||||
* `details` Event\<\>
|
||||
* `details` Event<>
|
||||
* `url` string - The URL the frame is navigating to.
|
||||
* `isSameDocument` boolean - Whether the navigation happened without changing
|
||||
document. Examples of same document navigations are reference fragment
|
||||
@@ -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:
|
||||
@@ -674,7 +688,7 @@ Emitted when media is paused or done playing.
|
||||
|
||||
Returns:
|
||||
|
||||
* `event` Event\<\>
|
||||
* `event` Event<>
|
||||
* `audible` boolean - True if one or more frames or child `webContents` are emitting audio.
|
||||
|
||||
Emitted when media becomes audible or inaudible.
|
||||
@@ -894,7 +908,7 @@ Returns:
|
||||
* `webPreferences` [WebPreferences](structures/web-preferences.md) - The web preferences that will be used by the guest
|
||||
page. This object can be modified to adjust the preferences for the guest
|
||||
page.
|
||||
* `params` Record\<string, string\> - The other `<webview>` parameters such as the `src` URL.
|
||||
* `params` Record<string, string> - The other `<webview>` parameters such as the `src` URL.
|
||||
This object can be modified to adjust the parameters of the guest page.
|
||||
|
||||
Emitted when a `<webview>`'s web contents is being attached to this web
|
||||
@@ -1014,7 +1028,7 @@ win.webContents.loadURL('https://github.com', options)
|
||||
|
||||
* `filePath` string
|
||||
* `options` Object (optional)
|
||||
* `query` Record\<string, string\> (optional) - Passed to `url.format()`.
|
||||
* `query` Record<string, string> (optional) - Passed to `url.format()`.
|
||||
* `search` string (optional) - Passed to `url.format()`.
|
||||
* `hash` string (optional) - Passed to `url.format()`.
|
||||
|
||||
@@ -1045,7 +1059,7 @@ win.loadFile('src/index.html')
|
||||
|
||||
* `url` string
|
||||
* `options` Object (optional)
|
||||
* `headers` Record\<string, string\> (optional) - HTTP request headers.
|
||||
* `headers` Record<string, string> (optional) - HTTP request headers.
|
||||
|
||||
Initiates a download of the resource at `url` without navigating. The
|
||||
`will-download` event of `session` will be triggered.
|
||||
@@ -1282,7 +1296,7 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
|
||||
#### `contents.setWindowOpenHandler(handler)`
|
||||
|
||||
* `handler` Function\<{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}\>
|
||||
* `handler` Function<{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}>
|
||||
* `details` Object
|
||||
* `url` string - The _resolved_ version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
|
||||
* `frameName` string - Name of the window provided in `window.open()`
|
||||
@@ -1560,7 +1574,7 @@ Returns `Promise<PrinterInfo[]>` - Resolves with a [`PrinterInfo[]`](structures/
|
||||
* `from` number - Index of the first page to print (0-based).
|
||||
* `to` number - Index of the last page to print (inclusive) (0-based).
|
||||
* `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
|
||||
* `dpi` Record\<string, number\> (optional)
|
||||
* `dpi` Record<string, number> (optional)
|
||||
* `horizontal` number (optional) - The horizontal dpi.
|
||||
* `vertical` number (optional) - The vertical dpi.
|
||||
* `header` string (optional) - string to be printed as page header.
|
||||
@@ -1614,7 +1628,6 @@ win.webContents.print(options, (success, errorType) => {
|
||||
* `footerTemplate` string (optional) - HTML template for the print footer. Should use the same format as the `headerTemplate`.
|
||||
* `preferCSSPageSize` boolean (optional) - Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size.
|
||||
* `generateTaggedPDF` boolean (optional) _Experimental_ - Whether or not to generate a tagged (accessible) PDF. Defaults to false. As this property is experimental, the generated PDF may not adhere fully to PDF/UA and WCAG standards.
|
||||
* `generateDocumentOutline` boolean (optional) _Experimental_ - Whether or not to generate a PDF document outline from content headers. Defaults to false.
|
||||
|
||||
Returns `Promise<Buffer>` - Resolves with the generated PDF data.
|
||||
|
||||
@@ -1625,26 +1638,24 @@ The `landscape` will be ignored if `@page` CSS at-rule is used in the web page.
|
||||
An example of `webContents.printToPDF`:
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const { BrowserWindow } = require('electron')
|
||||
const fs = require('node:fs')
|
||||
const path = require('node:path')
|
||||
const os = require('node:os')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow()
|
||||
win.loadURL('https://github.com')
|
||||
const win = new BrowserWindow()
|
||||
win.loadURL('https://github.com')
|
||||
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
// Use default printing options
|
||||
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
|
||||
win.webContents.printToPDF({}).then(data => {
|
||||
fs.writeFile(pdfPath, data, (error) => {
|
||||
if (error) throw error
|
||||
console.log(`Wrote PDF successfully to ${pdfPath}`)
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(`Failed to write PDF to ${pdfPath}: `, error)
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
// Use default printing options
|
||||
const pdfPath = path.join(os.homedir(), 'Desktop', 'temp.pdf')
|
||||
win.webContents.printToPDF({}).then(data => {
|
||||
fs.writeFile(pdfPath, data, (error) => {
|
||||
if (error) throw error
|
||||
console.log(`Wrote PDF successfully to ${pdfPath}`)
|
||||
})
|
||||
}).catch(error => {
|
||||
console.log(`Failed to write PDF to ${pdfPath}: `, error)
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
@@ -99,11 +99,11 @@ Some examples of valid `urls`:
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `uploadData` [UploadData[]](structures/upload-data.md) (optional)
|
||||
* `requestHeaders` Record\<string, string\>
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `callback` Function
|
||||
* `beforeSendResponse` Object
|
||||
* `cancel` boolean (optional)
|
||||
* `requestHeaders` Record\<string, string | string[]\> (optional) - When provided, request will be made
|
||||
* `requestHeaders` Record<string, string | string[]> (optional) - When provided, request will be made
|
||||
with these headers.
|
||||
|
||||
The `listener` will be called with `listener(details, callback)` before sending
|
||||
@@ -126,7 +126,7 @@ The `callback` has to be called with a `response` object.
|
||||
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `requestHeaders` Record\<string, string\>
|
||||
* `requestHeaders` Record<string, string>
|
||||
|
||||
The `listener` will be called with `listener(details)` just before a request is
|
||||
going to be sent to the server, modifications of previous `onBeforeSendHeaders`
|
||||
@@ -148,11 +148,11 @@ response are visible by the time this listener is fired.
|
||||
* `timestamp` Double
|
||||
* `statusLine` string
|
||||
* `statusCode` Integer
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `callback` Function
|
||||
* `headersReceivedResponse` Object
|
||||
* `cancel` boolean (optional)
|
||||
* `responseHeaders` Record\<string, string | string[]\> (optional) - When provided, the server is assumed
|
||||
* `responseHeaders` Record<string, string | string[]> (optional) - When provided, the server is assumed
|
||||
to have responded with these headers.
|
||||
* `statusLine` string (optional) - Should be provided when overriding
|
||||
`responseHeaders` to change header status otherwise original response
|
||||
@@ -177,7 +177,7 @@ The `callback` has to be called with a `response` object.
|
||||
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `fromCache` boolean - Indicates whether the response was fetched from disk
|
||||
cache.
|
||||
* `statusCode` Integer
|
||||
@@ -207,7 +207,7 @@ and response headers are available.
|
||||
* `ip` string (optional) - The server IP address that the request was
|
||||
actually sent to.
|
||||
* `fromCache` boolean
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
|
||||
The `listener` will be called with `listener(details)` when a server initiated
|
||||
redirect is about to occur.
|
||||
@@ -226,7 +226,7 @@ redirect is about to occur.
|
||||
* `resourceType` string - Can be `mainFrame`, `subFrame`, `stylesheet`, `script`, `image`, `font`, `object`, `xhr`, `ping`, `cspReport`, `media`, `webSocket` or `other`.
|
||||
* `referrer` string
|
||||
* `timestamp` Double
|
||||
* `responseHeaders` Record\<string, string[]\> (optional)
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `fromCache` boolean
|
||||
* `statusCode` Integer
|
||||
* `statusLine` string
|
||||
|
||||
@@ -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])
|
||||
```
|
||||
@@ -284,7 +284,7 @@ e.g. the `http://` or `file://`.
|
||||
|
||||
* `url` string
|
||||
* `options` Object (optional)
|
||||
* `headers` Record\<string, string\> (optional) - HTTP request headers.
|
||||
* `headers` Record<string, string> (optional) - HTTP request headers.
|
||||
|
||||
Initiates a download of the resource at `url` without navigating.
|
||||
|
||||
@@ -577,7 +577,7 @@ Stops any `findInPage` request for the `webview` with the provided `action`.
|
||||
* `from` number - Index of the first page to print (0-based).
|
||||
* `to` number - Index of the last page to print (inclusive) (0-based).
|
||||
* `duplexMode` string (optional) - Set the duplex mode of the printed web page. Can be `simplex`, `shortEdge`, or `longEdge`.
|
||||
* `dpi` Record\<string, number\> (optional)
|
||||
* `dpi` Record<string, number> (optional)
|
||||
* `horizontal` number (optional) - The horizontal dpi.
|
||||
* `vertical` number (optional) - The vertical dpi.
|
||||
* `header` string (optional) - string to be printed as page header.
|
||||
@@ -608,7 +608,6 @@ Prints `webview`'s web page. Same as `webContents.print([options])`.
|
||||
* `footerTemplate` string (optional) - HTML template for the print footer. Should use the same format as the `headerTemplate`.
|
||||
* `preferCSSPageSize` boolean (optional) - Whether or not to prefer page size as defined by css. Defaults to false, in which case the content will be scaled to fit the paper size.
|
||||
* `generateTaggedPDF` boolean (optional) _Experimental_ - Whether or not to generate a tagged (accessible) PDF. Defaults to false. As this property is experimental, the generated PDF may not adhere fully to PDF/UA and WCAG standards.
|
||||
* `generateDocumentOutline` boolean (optional) _Experimental_ - Whether or not to generate a PDF document outline from content headers. Defaults to false.
|
||||
|
||||
Returns `Promise<Uint8Array>` - Resolves with the generated PDF data.
|
||||
|
||||
@@ -987,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,76 +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 (30.0)
|
||||
|
||||
### Behavior Changed: cross-origin iframes now use Permission Policy to access features
|
||||
|
||||
Cross-origin iframes must now specify features available to a given `iframe` via the `allow`
|
||||
attribute in order to access them.
|
||||
|
||||
See [documentation](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#allow) for
|
||||
more information.
|
||||
|
||||
### Removed: The `--disable-color-correct-rendering` switch
|
||||
|
||||
This switch was never formally documented but it's removal is being noted here regardless. Chromium itself now has better support for color spaces so this flag should not be needed.
|
||||
|
||||
## Planned Breaking API Changes (29.0)
|
||||
|
||||
### Behavior Changed: `ipcRenderer` can no longer be sent over the `contextBridge`
|
||||
|
||||
Attempting to send the entire `ipcRenderer` module as an object over the `contextBridge` will now result in
|
||||
an empty object on the receiving side of the bridge. This change was made to remove / mitigate
|
||||
a security footgun. You should not directly expose ipcRenderer or its 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`
|
||||
@@ -1664,7 +1594,7 @@ folder
|
||||
└── file3
|
||||
```
|
||||
|
||||
In Electron <=6, this would return a `FileList` with a `File` object for:
|
||||
In Electron <=6, this would return a `FileList` with a `File` object for:
|
||||
|
||||
```console
|
||||
path/to/folder
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 4.2 MiB After Width: | Height: | Size: 59 KiB |
@@ -5,25 +5,34 @@ slug: code-signing
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
Code signing is a security technology to certify that an app was created by you.
|
||||
You should sign your application so it does not trigger any operating system
|
||||
security warnings.
|
||||
Code signing is a security technology that you use to certify that an app was
|
||||
created by you. You should sign your application so it does not trigger any
|
||||
operating system security checks.
|
||||
|
||||

|
||||
On macOS, the system can detect any change to the app, whether the change is
|
||||
introduced accidentally or by malicious code.
|
||||
|
||||
Both Windows and macOS prevent users from running unsigned applications. It is
|
||||
possible to distribute applications without codesigning them - but in order to
|
||||
run them, users need to go through multiple advanced and manual steps to run
|
||||
them.
|
||||
On Windows, the system assigns a trust level to your code signing certificate
|
||||
which if you don't have, or if your trust level is low, will cause security
|
||||
dialogs to appear when users start using your application. Trust level builds
|
||||
over time so it's better to start code signing as early as possible.
|
||||
|
||||
While it is possible to distribute unsigned apps, it is not recommended. Both
|
||||
Windows and macOS will, by default, prevent either the download or the execution
|
||||
of unsigned applications. Starting with macOS Catalina (version 10.15), users
|
||||
have to go through multiple manual steps to open unsigned applications.
|
||||
|
||||

|
||||
|
||||
As you can see, users get two options: Move the app straight to the trash or
|
||||
cancel running it. You don't want your users to see that dialog.
|
||||
|
||||
If you are building an Electron app that you intend to package and distribute,
|
||||
it should be code signed. The Electron ecosystem tooling makes codesigning your
|
||||
apps straightforward - this documentation explains how sign your apps on both
|
||||
Windows and macOS.
|
||||
it should be code signed.
|
||||
|
||||
## Signing & notarizing macOS builds
|
||||
|
||||
Preparing macOS applications for release requires two steps: First, the
|
||||
Properly preparing macOS applications for release requires two steps. First, the
|
||||
app needs to be code signed. Then, the app needs to be uploaded to Apple for a
|
||||
process called **notarization**, where automated systems will further verify that
|
||||
your app isn't doing anything to endanger its users.
|
||||
@@ -56,9 +65,7 @@ are likely using [`@electron/packager`][], which includes [`@electron/osx-sign`]
|
||||
[`@electron/notarize`][].
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that both signs
|
||||
and notarizes your application](https://electron.github.io/packager/main/modules.html).
|
||||
If the example below does not meet your needs, please see [`@electron/osx-sign`][] and
|
||||
[`@electron/notarize`][] for the many possible configuration options.
|
||||
and notarizes your application](https://electron.github.io/packager/main/interfaces/electronpackager.options.html).
|
||||
|
||||
```js @ts-nocheck
|
||||
const packager = require('@electron/packager')
|
||||
@@ -79,81 +86,35 @@ See the [Mac App Store Guide][].
|
||||
|
||||
## Signing Windows builds
|
||||
|
||||
Before you can code sign your application, you need to acquire a code signing
|
||||
certificate. Unlike Apple, Microsoft allows developers to purchase those
|
||||
certificates on the open market. They are usually sold by the same companies
|
||||
also offering HTTPS certificates. Prices vary, so it may be worth your time to
|
||||
shop around. Popular resellers include:
|
||||
Before signing Windows builds, you must do the following:
|
||||
|
||||
- [Certum EV code signing certificate](https://shop.certum.eu/data-safety/code-signing-certificates/certum-ev-code-sigining.html)
|
||||
- [DigiCert EV code signing certificate](https://www.digicert.com/signing/code-signing-certificates)
|
||||
- [Entrust EV code signing certificate](https://www.entrustdatacard.com/products/digital-signing-certificates/code-signing-certificates)
|
||||
- [GlobalSign EV code signing certificate](https://www.globalsign.com/en/code-signing-certificate/ev-code-signing-certificates)
|
||||
- [IdenTrust EV code signing certificate](https://www.identrust.com/digital-certificates/trustid-ev-code-signing)
|
||||
- [Sectigo (formerly Comodo) EV code signing certificate](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
- [SSL.com EV code signing certificate](https://www.ssl.com/certificates/ev-code-signing/)
|
||||
1. Get a Windows Authenticode code signing certificate (requires an annual fee)
|
||||
2. Install Visual Studio to get the signing utility (the free [Community
|
||||
Edition](https://visualstudio.microsoft.com/vs/community/) is enough)
|
||||
|
||||
It is important to call out that since June 2023, Microsoft requires software to
|
||||
be signed with an "extended validation" certificate, also called an "EV code signing
|
||||
certificate". In the past, developers could sign software with a simpler and cheaper
|
||||
certificate called "authenticode code signing certificate" or "software-based OV certificate".
|
||||
These simpler certificates no longer provide benefits: Windows will treat your app as
|
||||
completely unsigned and display the equivalent warning dialogs.
|
||||
You can get a code signing certificate from a lot of resellers. Prices vary, so
|
||||
it may be worth your time to shop around. Popular resellers include:
|
||||
|
||||
The new EV certificates are required to be stored on a hardware storage module
|
||||
compliant with FIPS 140 Level 2, Common Criteria EAL 4+ or equivalent. In other words,
|
||||
the certificate cannot be simply downloaded onto a CI infrastructure. In practice,
|
||||
those storage modules look like fancy USB thumb drives.
|
||||
- [digicert](https://www.digicert.com/dc/code-signing/microsoft-authenticode.htm)
|
||||
- [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
- Amongst others, please shop around to find one that suits your needs! 😄
|
||||
|
||||
Many certificate providers now offer "cloud-based signing" - the entire signing hardware
|
||||
is in their data center and you can use it to remotely sign code. This approach is
|
||||
popular with Electron maintainers since it makes signing your applications in CI (like
|
||||
GitHub Actions, CircleCI, etc) relatively easy.
|
||||
|
||||
At the time of writing, Electron's own apps use [DigiCert KeyLocker](https://docs.digicert.com/en/digicert-keylocker.html), but any provider that provides a command line tool for
|
||||
signing files will be compatible with Electron's tooling.
|
||||
|
||||
All tools in the Electron ecosystem use [`@electron/windows-sign`][] and typically
|
||||
expose configuration options through a `windowsSign` property. You can either use it
|
||||
to sign files directly - or use the same `windowsSign` configuration across Electron
|
||||
Forge, [`@electron/packager`][], [`electron-winstaller`][], and [`electron-wix-msi`][].
|
||||
:::caution Keep your certificate password private
|
||||
Your certificate password should be a **secret**. Do not share it publicly or
|
||||
commit it to your source code.
|
||||
:::
|
||||
|
||||
### Using Electron Forge
|
||||
|
||||
Electron Forge is the recommended way to sign your app as well as your `Squirrel.Windows`
|
||||
and `WiX MSI` installers. Detailed instructions on how to configure your application can
|
||||
be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-windows).
|
||||
|
||||
### Using Electron Packager
|
||||
|
||||
If you're not using an integrated build pipeline like Forge, you
|
||||
are likely using [`@electron/packager`][], which includes [`@electron/windows-sign`][].
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that signs
|
||||
your application](https://electron.github.io/packager/main/modules.html). If the
|
||||
example below does not meet your needs, please see [`@electron/windows-sign`][]
|
||||
for the many possible configuration options.
|
||||
|
||||
```js @ts-nocheck
|
||||
const packager = require('@electron/packager')
|
||||
|
||||
packager({
|
||||
dir: '/path/to/my/app',
|
||||
windowsSign: {
|
||||
signWithParams: '--my=custom --parameters',
|
||||
// If signtool.exe does not work for you, customize!
|
||||
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
|
||||
}
|
||||
})
|
||||
```
|
||||
Electron Forge is the recommended way to sign your `Squirrel.Windows` and `WiX MSI` installers. Detailed instructions on how to configure your application can be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-macos).
|
||||
|
||||
### Using electron-winstaller (Squirrel.Windows)
|
||||
|
||||
[`electron-winstaller`][] is a package that can generate Squirrel.Windows installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's
|
||||
[Squirrel.Windows Maker][maker-squirrel]. Just like `@electron/packager`, it uses
|
||||
[`@electron/windows-sign`][] under the hood and supports the same `windowsSign`
|
||||
options.
|
||||
[Squirrel.Windows Maker][maker-squirrel]. If you're not using Electron Forge and want to use
|
||||
`electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration
|
||||
options when creating your installer.
|
||||
|
||||
```js {10-11} @ts-nocheck
|
||||
const electronInstaller = require('electron-winstaller')
|
||||
@@ -165,11 +126,8 @@ try {
|
||||
outputDirectory: '/tmp/build/installer64',
|
||||
authors: 'My App Inc.',
|
||||
exe: 'myapp.exe',
|
||||
windowsSign: {
|
||||
signWithParams: '--my=custom --parameters',
|
||||
// If signtool.exe does not work for you, customize!
|
||||
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
|
||||
}
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret'
|
||||
})
|
||||
console.log('It worked!')
|
||||
} catch (e) {
|
||||
@@ -183,8 +141,10 @@ For full configuration options, check out the [`electron-winstaller`][] reposito
|
||||
|
||||
[`electron-wix-msi`][] is a package that can generate MSI installers for your
|
||||
Electron app. This is the tool used under the hood by Electron Forge's [MSI Maker][maker-msi].
|
||||
Just like `@electron/packager`, it uses [`@electron/windows-sign`][] under the hood
|
||||
and supports the same `windowsSign` options.
|
||||
|
||||
If you're not using Electron Forge and want to use `electron-wix-msi` directly, use the
|
||||
`certificateFile` and `certificatePassword` configuration options
|
||||
or pass in parameters directly to [SignTool.exe][] with the `signWithParams` option.
|
||||
|
||||
```js {12-13} @ts-nocheck
|
||||
import { MSICreator } from 'electron-wix-msi'
|
||||
@@ -198,11 +158,8 @@ const msiCreator = new MSICreator({
|
||||
manufacturer: 'Kitten Technologies',
|
||||
version: '1.1.2',
|
||||
outputDirectory: '/path/to/output/folder',
|
||||
windowsSign: {
|
||||
signWithParams: '--my=custom --parameters',
|
||||
// If signtool.exe does not work for you, customize!
|
||||
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
|
||||
}
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: 'this-is-a-secret'
|
||||
})
|
||||
|
||||
// Step 2: Create a .wxs template file
|
||||
@@ -235,7 +192,6 @@ See the [Windows Store Guide][].
|
||||
[`@electron/osx-sign`]: https://github.com/electron/osx-sign
|
||||
[`@electron/packager`]: https://github.com/electron/packager
|
||||
[`@electron/notarize`]: https://github.com/electron/notarize
|
||||
[`@electron/windows-sign`]: https://github.com/electron/windows-sign
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[`electron-wix-msi`]: https://github.com/electron-userland/electron-wix-msi
|
||||
[xcode]: https://developer.apple.com/xcode
|
||||
@@ -244,3 +200,4 @@ See the [Windows Store Guide][].
|
||||
[windows store guide]: ./windows-store-guide.md
|
||||
[maker-squirrel]: https://www.electronforge.io/config/makers/squirrel.windows
|
||||
[maker-msi]: https://www.electronforge.io/config/makers/wix-msi
|
||||
[signtool.exe]: https://learn.microsoft.com/en-us/dotnet/framework/tools/signtool-exe
|
||||
|
||||
@@ -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]`
|
||||
|
||||
@@ -33,7 +33,7 @@ clicked.
|
||||
## WebHID API
|
||||
|
||||
The [WebHID API](https://web.dev/hid/) can be used to access HID devices such
|
||||
as keyboards and gamepads. Electron provides several APIs for working with
|
||||
as keyboards and gamepads. Electron provides several APIs for working with
|
||||
the WebHID API:
|
||||
|
||||
* The [`select-hid-device` event on the Session](../api/session.md#event-select-hid-device)
|
||||
|
||||
@@ -12,7 +12,7 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
| 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-20 | M116 | v18.16 | 🚫 |
|
||||
| 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 | 🚫 |
|
||||
|
||||
@@ -15,7 +15,7 @@ Fuses are the solution to this problem, at a high level they are "magic bits" in
|
||||
**Default:** Enabled
|
||||
**@electron/fuses:** `FuseV1Options.RunAsNode`
|
||||
|
||||
The runAsNode fuse toggles whether the `ELECTRON_RUN_AS_NODE` environment variable is respected or not. Please note that if this fuse is disabled then `process.fork` in the main process will not function as expected as it depends on this environment variable to function. Instead, we recommend that you use [Utility Processes](../api/utility-process.md), which work for many use cases where you need a standalone Node.js process (like a Sqlite server process or similar scenarios).
|
||||
The runAsNode fuse toggles whether the `ELECTRON_RUN_AS_NODE` environment variable is respected or not. Please note that if this fuse is disabled then `process.fork` in the main process will not function as expected as it depends on this environment variable to function.
|
||||
|
||||
### `cookieEncryption`
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -107,7 +107,7 @@ if (!inAppPurchase.canMakePayments()) {
|
||||
inAppPurchase.getProducts(PRODUCT_IDS).then(products => {
|
||||
// Check the parameters.
|
||||
if (!Array.isArray(products) || products.length <= 0) {
|
||||
console.log('Unable to retrieve the product information.')
|
||||
console.log('Unable to retrieve the product informations.')
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -24,7 +24,7 @@ careful to understand that the term "performance" means different things for
|
||||
a Node.js backend than it does for an application running on a client.
|
||||
|
||||
This list is provided for your convenience – and is, much like our
|
||||
[security checklist][security] – not meant to be exhaustive. It is probably possible
|
||||
[security checklist][security] – not meant to exhaustive. It is probably possible
|
||||
to build a slow Electron app that follows all the steps outlined below. Electron
|
||||
is a powerful development platform that enables you, the developer, to do more
|
||||
or less whatever you want. All that freedom means that performance is largely
|
||||
@@ -83,7 +83,7 @@ is not in fact the leanest or smallest one available.
|
||||
|
||||
The reasoning behind this recommendation is best illustrated with a real-world
|
||||
example. During the early days of Electron, reliable detection of network
|
||||
connectivity was a problem, resulting in many apps using a module that exposed a
|
||||
connectivity was a problem, resulting many apps to use a module that exposed a
|
||||
simple `isOnline()` method.
|
||||
|
||||
That module detected your network connectivity by attempting to reach out to a
|
||||
|
||||
@@ -83,7 +83,7 @@ terminated as well.
|
||||
|
||||
The main process also controls your application's lifecycle through Electron's
|
||||
[`app`][app] module. This module provides a large set of events and methods
|
||||
that you can use to add custom application behavior (for instance, programmatically
|
||||
that you can use to add custom application behaviour (for instance, programmatically
|
||||
quitting your application, modifying the application dock, or showing an About panel).
|
||||
|
||||
As a practical example, the app shown in the [quick start guide][quick-start-lifecycle]
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -17,7 +17,7 @@ further configuration. If you want to disable the sandbox for a process, see the
|
||||
[Disabling the sandbox for a single process](#disabling-the-sandbox-for-a-single-process)
|
||||
section.
|
||||
|
||||
## Sandbox behavior in Electron
|
||||
## Sandbox behaviour in Electron
|
||||
|
||||
Sandboxed processes in Electron behave _mostly_ in the same way as Chromium's do, but
|
||||
Electron has a few additional concepts to consider because it interfaces with Node.js.
|
||||
@@ -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)
|
||||
|
||||
@@ -114,8 +114,6 @@ You should at least follow these steps to improve the security of your applicati
|
||||
15. [Do not use `shell.openExternal` with untrusted content](#15-do-not-use-shellopenexternal-with-untrusted-content)
|
||||
16. [Use a current version of Electron](#16-use-a-current-version-of-electron)
|
||||
17. [Validate the `sender` of all IPC messages](#17-validate-the-sender-of-all-ipc-messages)
|
||||
18. [Avoid usage of the `file://` protocol and prefer usage of custom protocols](#18-avoid-usage-of-the-file-protocol-and-prefer-usage-of-custom-protocols)
|
||||
19. [Check which fuses you can change](#19-check-which-fuses-you-can-change)
|
||||
|
||||
To automate the detection of misconfigurations and insecure patterns, it is
|
||||
possible to use
|
||||
@@ -761,49 +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.
|
||||
|
||||
### 19. Check which fuses you can change
|
||||
|
||||
Electron ships with a number of options that can be useful but a large portion of
|
||||
applications probably don't need. In order to avoid having to build your own version of
|
||||
Electron, these can be turned off or on using [Fuses](./fuses.md).
|
||||
|
||||
#### Why?
|
||||
|
||||
Some fuses, like `runAsNode` and `nodeCliInspect`, allow the application to behave differently
|
||||
when run from the command line using specific environment variables or CLI arguments. These
|
||||
can be used to execute commands on the device through your application.
|
||||
|
||||
This can let external scripts run commands that they potentially would not be allowed to, but
|
||||
that your application might have the rights for.
|
||||
|
||||
#### How?
|
||||
|
||||
We've made a module, [`@electron/fuses`](https://npmjs.com/package/@electron/fuses), to make
|
||||
flipping these fuses easy. Check out the README of that module for more details on usage and
|
||||
potential error cases, and refer to
|
||||
[How do I flip the fuses?](./fuses.md#how-do-i-flip-the-fuses) in our documentation.
|
||||
|
||||
[breaking-changes]: ../breaking-changes.md
|
||||
[browser-window]: ../api/browser-window.md
|
||||
[browser-view]: ../api/browser-view.md
|
||||
|
||||
@@ -203,7 +203,7 @@ loading the HTML file so that the handler is guaranteed to be ready before
|
||||
you send out the `invoke` call from the renderer.
|
||||
|
||||
```js {1,15} title="main.js"
|
||||
const { app, BrowserWindow, ipcMain } = require('electron/main')
|
||||
const { app, BrowserWindow, ipcMain } = require('electron')
|
||||
const path = require('node:path')
|
||||
|
||||
const createWindow = () => {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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",
|
||||
@@ -153,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",
|
||||
@@ -282,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",
|
||||
@@ -319,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",
|
||||
|
||||
@@ -371,6 +371,8 @@ filenames = {
|
||||
"shell/browser/electron_download_manager_delegate.h",
|
||||
"shell/browser/electron_gpu_client.cc",
|
||||
"shell/browser/electron_gpu_client.h",
|
||||
"shell/browser/electron_javascript_dialog_manager.cc",
|
||||
"shell/browser/electron_javascript_dialog_manager.h",
|
||||
"shell/browser/electron_navigation_throttle.cc",
|
||||
"shell/browser/electron_navigation_throttle.h",
|
||||
"shell/browser/electron_permission_manager.cc",
|
||||
@@ -385,7 +387,6 @@ filenames = {
|
||||
"shell/browser/extended_web_contents_observer.h",
|
||||
"shell/browser/feature_list.cc",
|
||||
"shell/browser/feature_list.h",
|
||||
"shell/browser/feature_list_mac.mm",
|
||||
"shell/browser/file_select_helper.cc",
|
||||
"shell/browser/file_select_helper.h",
|
||||
"shell/browser/file_select_helper_mac.mm",
|
||||
@@ -683,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",
|
||||
@@ -736,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",
|
||||
|
||||
@@ -23,8 +23,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__algorithm/find_first_of.h",
|
||||
"//third_party/libc++/src/include/__algorithm/find_if.h",
|
||||
"//third_party/libc++/src/include/__algorithm/find_if_not.h",
|
||||
"//third_party/libc++/src/include/__algorithm/find_segment_if.h",
|
||||
"//third_party/libc++/src/include/__algorithm/fold.h",
|
||||
"//third_party/libc++/src/include/__algorithm/for_each.h",
|
||||
"//third_party/libc++/src/include/__algorithm/for_each_n.h",
|
||||
"//third_party/libc++/src/include/__algorithm/for_each_segment.h",
|
||||
@@ -90,7 +88,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__algorithm/pstl_backends/cpu_backends/transform_reduce.h",
|
||||
"//third_party/libc++/src/include/__algorithm/pstl_copy.h",
|
||||
"//third_party/libc++/src/include/__algorithm/pstl_count.h",
|
||||
"//third_party/libc++/src/include/__algorithm/pstl_equal.h",
|
||||
"//third_party/libc++/src/include/__algorithm/pstl_fill.h",
|
||||
"//third_party/libc++/src/include/__algorithm/pstl_find.h",
|
||||
"//third_party/libc++/src/include/__algorithm/pstl_for_each.h",
|
||||
@@ -110,7 +107,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_any_of.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_binary_search.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_clamp.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_contains.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_copy.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_copy_backward.h",
|
||||
"//third_party/libc++/src/include/__algorithm/ranges_copy_if.h",
|
||||
@@ -822,6 +818,7 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__type_traits/negation.h",
|
||||
"//third_party/libc++/src/include/__type_traits/noexcept_move_assign_container.h",
|
||||
"//third_party/libc++/src/include/__type_traits/operation_traits.h",
|
||||
"//third_party/libc++/src/include/__type_traits/predicate_traits.h",
|
||||
"//third_party/libc++/src/include/__type_traits/promote.h",
|
||||
"//third_party/libc++/src/include/__type_traits/rank.h",
|
||||
"//third_party/libc++/src/include/__type_traits/remove_all_extents.h",
|
||||
@@ -842,7 +839,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__type_traits/void_t.h",
|
||||
"//third_party/libc++/src/include/__undef_macros",
|
||||
"//third_party/libc++/src/include/__utility/as_const.h",
|
||||
"//third_party/libc++/src/include/__utility/as_lvalue.h",
|
||||
"//third_party/libc++/src/include/__utility/auto_cast.h",
|
||||
"//third_party/libc++/src/include/__utility/cmp.h",
|
||||
"//third_party/libc++/src/include/__utility/convert_to_integral.h",
|
||||
@@ -856,7 +852,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/__utility/integer_sequence.h",
|
||||
"//third_party/libc++/src/include/__utility/is_pointer_in_range.h",
|
||||
"//third_party/libc++/src/include/__utility/move.h",
|
||||
"//third_party/libc++/src/include/__utility/no_destroy.h",
|
||||
"//third_party/libc++/src/include/__utility/pair.h",
|
||||
"//third_party/libc++/src/include/__utility/piecewise_construct.h",
|
||||
"//third_party/libc++/src/include/__utility/priority_tag.h",
|
||||
@@ -916,8 +911,10 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/expected",
|
||||
"//third_party/libc++/src/include/experimental/__config",
|
||||
"//third_party/libc++/src/include/experimental/__memory",
|
||||
"//third_party/libc++/src/include/experimental/__simd/abi_tag.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/aligned_tag.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/declaration.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/internal_declaration.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/reference.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/scalar.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/simd.h",
|
||||
@@ -925,12 +922,22 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/experimental/__simd/traits.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/utility.h",
|
||||
"//third_party/libc++/src/include/experimental/__simd/vec_ext.h",
|
||||
"//third_party/libc++/src/include/experimental/deque",
|
||||
"//third_party/libc++/src/include/experimental/forward_list",
|
||||
"//third_party/libc++/src/include/experimental/iterator",
|
||||
"//third_party/libc++/src/include/experimental/memory",
|
||||
"//third_party/libc++/src/include/experimental/list",
|
||||
"//third_party/libc++/src/include/experimental/map",
|
||||
"//third_party/libc++/src/include/experimental/memory_resource",
|
||||
"//third_party/libc++/src/include/experimental/propagate_const",
|
||||
"//third_party/libc++/src/include/experimental/regex",
|
||||
"//third_party/libc++/src/include/experimental/set",
|
||||
"//third_party/libc++/src/include/experimental/simd",
|
||||
"//third_party/libc++/src/include/experimental/string",
|
||||
"//third_party/libc++/src/include/experimental/type_traits",
|
||||
"//third_party/libc++/src/include/experimental/unordered_map",
|
||||
"//third_party/libc++/src/include/experimental/unordered_set",
|
||||
"//third_party/libc++/src/include/experimental/utility",
|
||||
"//third_party/libc++/src/include/experimental/vector",
|
||||
"//third_party/libc++/src/include/ext/__hash",
|
||||
"//third_party/libc++/src/include/ext/hash_map",
|
||||
"//third_party/libc++/src/include/ext/hash_set",
|
||||
@@ -995,7 +1002,6 @@ libcxx_headers = [
|
||||
"//third_party/libc++/src/include/string.h",
|
||||
"//third_party/libc++/src/include/string_view",
|
||||
"//third_party/libc++/src/include/strstream",
|
||||
"//third_party/libc++/src/include/syncstream",
|
||||
"//third_party/libc++/src/include/system_error",
|
||||
"//third_party/libc++/src/include/tgmath.h",
|
||||
"//third_party/libc++/src/include/thread",
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
# Copyright (c) 2023 Microsoft, GmbH
|
||||
# Use of this source code is governed by the MIT license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
declare_args() {
|
||||
electron_js2c_toolchain = ""
|
||||
}
|
||||
|
||||
if (electron_js2c_toolchain == "") {
|
||||
if (current_os == host_os && current_cpu == host_cpu) {
|
||||
# This is not a cross-compile, so build the snapshot with the current
|
||||
# toolchain.
|
||||
electron_js2c_toolchain = current_toolchain
|
||||
} else if (current_os == host_os && current_cpu == "x86" &&
|
||||
host_cpu == "x64") {
|
||||
# This is an x64 -> x86 cross-compile, but x64 hosts can usually run x86
|
||||
# binaries built for the same OS, so build the snapshot with the current
|
||||
# toolchain here, too.
|
||||
electron_js2c_toolchain = current_toolchain
|
||||
} else if (current_os == host_os && host_cpu == "arm64" &&
|
||||
current_cpu == "arm") {
|
||||
# Trying to compile 32-bit arm on arm64. Good luck!
|
||||
electron_js2c_toolchain = current_toolchain
|
||||
} else if (host_cpu == current_cpu) {
|
||||
# Cross-build from same ISA on one OS to another. For example:
|
||||
# * targeting win/x64 on a linux/x64 host
|
||||
# * targeting win/arm64 on a mac/arm64 host
|
||||
electron_js2c_toolchain = host_toolchain
|
||||
} else if (host_cpu == "arm64" && current_cpu == "x64") {
|
||||
# Cross-build from arm64 to intel (likely on an Apple Silicon mac).
|
||||
electron_js2c_toolchain =
|
||||
"//build/toolchain/${host_os}:clang_arm64_v8_$current_cpu"
|
||||
} else if (host_cpu == "x64") {
|
||||
# This is a cross-compile from an x64 host to either a non-Intel target
|
||||
# cpu or to 32-bit x86 on a different target OS.
|
||||
|
||||
assert(current_cpu != "x64", "handled by host_cpu == current_cpu branch")
|
||||
if (current_cpu == "x86") {
|
||||
_cpus = current_cpu
|
||||
} else if (current_cpu == "arm64") {
|
||||
if (is_win) {
|
||||
# set _cpus to blank for Windows ARM64 so host_toolchain could be
|
||||
# selected as snapshot toolchain later.
|
||||
_cpus = ""
|
||||
} else {
|
||||
_cpus = "x64_v8_${current_cpu}"
|
||||
}
|
||||
} else if (current_cpu == "arm") {
|
||||
_cpus = "x86_v8_${current_cpu}"
|
||||
} else {
|
||||
# This branch should not be reached; leave _cpus blank so the assert
|
||||
# below will fail.
|
||||
_cpus = ""
|
||||
}
|
||||
|
||||
if (_cpus != "") {
|
||||
electron_js2c_toolchain = "//build/toolchain/${host_os}:clang_${_cpus}"
|
||||
} else if (is_win && current_cpu == "arm64") {
|
||||
# cross compile Windows arm64 with host toolchain.
|
||||
electron_js2c_toolchain = host_toolchain
|
||||
}
|
||||
} else if (host_cpu == "arm64" && current_cpu == "arm64" &&
|
||||
host_os == "mac") {
|
||||
# cross compile iOS arm64 with host_toolchain
|
||||
electron_js2c_toolchain = host_toolchain
|
||||
}
|
||||
}
|
||||
|
||||
assert(electron_js2c_toolchain != "",
|
||||
"Do not know how to build js2c for $current_toolchain " +
|
||||
"on $host_os $host_cpu")
|
||||
@@ -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,69 +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) => {
|
||||
spawnedProcess = undefined;
|
||||
spawnedArgs = [];
|
||||
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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -29,21 +29,6 @@ function makeStreamFromPipe (pipe: any): ReadableStream {
|
||||
});
|
||||
}
|
||||
|
||||
function makeStreamFromFileInfo ({
|
||||
filePath,
|
||||
offset = 0,
|
||||
length = -1
|
||||
}: {
|
||||
filePath: string;
|
||||
offset?: number;
|
||||
length?: number;
|
||||
}): ReadableStream {
|
||||
return Readable.toWeb(createReadStream(filePath, {
|
||||
start: offset,
|
||||
end: length >= 0 ? offset + length : undefined
|
||||
}));
|
||||
}
|
||||
|
||||
function convertToRequestBody (uploadData: ProtocolRequest['uploadData']): RequestInit['body'] {
|
||||
if (!uploadData) return null;
|
||||
// Optimization: skip creating a stream if the request is just a single buffer.
|
||||
@@ -52,42 +37,30 @@ function convertToRequestBody (uploadData: ProtocolRequest['uploadData']): Reque
|
||||
const chunks = [...uploadData] as any[]; // TODO: types are wrong
|
||||
let current: ReadableStreamDefaultReader | null = null;
|
||||
return new ReadableStream({
|
||||
async pull (controller) {
|
||||
pull (controller) {
|
||||
if (current) {
|
||||
const { done, value } = await current.read();
|
||||
// (done => value === undefined) as per WHATWG spec
|
||||
if (done) {
|
||||
current = null;
|
||||
return this.pull!(controller);
|
||||
} else {
|
||||
current.read().then(({ done, value }) => {
|
||||
controller.enqueue(value);
|
||||
}
|
||||
if (done) current = null;
|
||||
}, (err) => {
|
||||
controller.error(err);
|
||||
});
|
||||
} else {
|
||||
if (!chunks.length) { return controller.close(); }
|
||||
const chunk = chunks.shift()!;
|
||||
if (chunk.type === 'rawData') {
|
||||
controller.enqueue(chunk.bytes);
|
||||
} else if (chunk.type === 'file') {
|
||||
current = makeStreamFromFileInfo(chunk).getReader();
|
||||
return this.pull!(controller);
|
||||
if (chunk.type === 'rawData') { controller.enqueue(chunk.bytes); } else if (chunk.type === 'file') {
|
||||
current = Readable.toWeb(createReadStream(chunk.filePath, { start: chunk.offset ?? 0, end: chunk.length >= 0 ? chunk.offset + chunk.length : undefined })).getReader();
|
||||
this.pull!(controller);
|
||||
} else if (chunk.type === 'stream') {
|
||||
current = makeStreamFromPipe(chunk.body).getReader();
|
||||
return this.pull!(controller);
|
||||
} else if (chunk.type === 'blob') {
|
||||
// Note that even though `getBlobData()` is a `Session` API, it doesn't
|
||||
// actually use the `Session` context. Its implementation solely relies
|
||||
// on global variables which allows us to implement this feature without
|
||||
// knowledge of the `Session` associated with the current request by
|
||||
// always pulling `Blob` data out of the default `Session`.
|
||||
controller.enqueue(await session.defaultSession.getBlobData(chunk.blobUUID));
|
||||
} else {
|
||||
throw new Error(`Unknown upload data chunk type: ${chunk.type}`);
|
||||
this.pull!(controller);
|
||||
}
|
||||
}
|
||||
}
|
||||
}) as RequestInit['body'];
|
||||
}
|
||||
|
||||
// TODO(codebytere): Use Object.hasOwn() once we update to ECMAScript 2022.
|
||||
function validateResponse (res: Response) {
|
||||
if (!res || typeof res !== 'object') return false;
|
||||
|
||||
@@ -112,12 +85,8 @@ Protocol.prototype.handle = function (this: Electron.Protocol, scheme: string, h
|
||||
const success = register.call(this, scheme, async (preq: ProtocolRequest, cb: any) => {
|
||||
try {
|
||||
const body = convertToRequestBody(preq.uploadData);
|
||||
const headers = new Headers(preq.headers);
|
||||
if (headers.get('origin') === 'null') {
|
||||
headers.delete('origin');
|
||||
}
|
||||
const req = new Request(preq.url, {
|
||||
headers,
|
||||
headers: preq.headers,
|
||||
method: preq.method,
|
||||
referrer: preq.referrer,
|
||||
body,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { app, ipcMain, session, webFrameMain, dialog } from 'electron/main';
|
||||
import type { BrowserWindowConstructorOptions, LoadURLOptions, MessageBoxOptions, WebFrameMain } from 'electron/main';
|
||||
import { app, ipcMain, session, webFrameMain } from 'electron/main';
|
||||
import type { BrowserWindowConstructorOptions, LoadURLOptions } from 'electron/main';
|
||||
|
||||
import * as url from 'url';
|
||||
import * as path from 'path';
|
||||
@@ -245,7 +245,6 @@ 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'),
|
||||
generateDocumentOutline: checkType(options.generateDocumentOutline ?? false, 'boolean', 'generateDocumentOutline'),
|
||||
...pageSize
|
||||
};
|
||||
|
||||
@@ -582,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);
|
||||
|
||||
@@ -738,56 +741,6 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
const originCounts = new Map<string, number>();
|
||||
const openDialogs = new Set<AbortController>();
|
||||
this.on('-run-dialog' as any, async (info: {frame: WebFrameMain, dialogType: 'prompt' | 'confirm' | 'alert', messageText: string, defaultPromptText: string}, callback: (success: boolean, user_input: string) => void) => {
|
||||
const originUrl = new URL(info.frame.url);
|
||||
const origin = originUrl.protocol === 'file:' ? originUrl.href : originUrl.origin;
|
||||
if ((originCounts.get(origin) ?? 0) < 0) return callback(false, '');
|
||||
|
||||
const prefs = this.getLastWebPreferences();
|
||||
if (!prefs || prefs.disableDialogs) return callback(false, '');
|
||||
|
||||
// We don't support prompt() for some reason :)
|
||||
if (info.dialogType === 'prompt') return callback(false, '');
|
||||
|
||||
originCounts.set(origin, (originCounts.get(origin) ?? 0) + 1);
|
||||
|
||||
// TODO: translate?
|
||||
const checkbox = originCounts.get(origin)! > 1 && prefs.safeDialogs ? prefs.safeDialogsMessage || 'Prevent this app from creating additional dialogs' : '';
|
||||
const parent = this.getOwnerBrowserWindow();
|
||||
const abortController = new AbortController();
|
||||
const options: MessageBoxOptions = {
|
||||
message: info.messageText,
|
||||
checkboxLabel: checkbox,
|
||||
signal: abortController.signal,
|
||||
...(info.dialogType === 'confirm') ? {
|
||||
buttons: ['OK', 'Cancel'],
|
||||
defaultId: 0,
|
||||
cancelId: 1
|
||||
} : {
|
||||
buttons: ['OK'],
|
||||
defaultId: -1, // No default button
|
||||
cancelId: 0
|
||||
}
|
||||
};
|
||||
openDialogs.add(abortController);
|
||||
const promise = parent && !prefs.offscreen ? dialog.showMessageBox(parent, options) : dialog.showMessageBox(options);
|
||||
try {
|
||||
const result = await promise;
|
||||
if (abortController.signal.aborted) return;
|
||||
if (result.checkboxChecked) originCounts.set(origin, -1);
|
||||
return callback(result.response === 0, '');
|
||||
} finally {
|
||||
openDialogs.delete(abortController);
|
||||
}
|
||||
});
|
||||
|
||||
this.on('-cancel-dialogs' as any, () => {
|
||||
for (const controller of openDialogs) { controller.abort(); }
|
||||
openDialogs.clear();
|
||||
});
|
||||
|
||||
app.emit('web-contents-created', { sender: this, preventDefault () {}, get defaultPrevented () { return false; } }, this);
|
||||
|
||||
// Properties
|
||||
|
||||
@@ -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: [],
|
||||
|
||||
@@ -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;
|
||||
@@ -65,7 +65,7 @@ require('@electron/internal/renderer/common-init');
|
||||
|
||||
if (nodeIntegration) {
|
||||
// Export node bindings to global.
|
||||
const { makeRequireFunction } = __non_webpack_require__('internal/modules/helpers');
|
||||
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers');
|
||||
global.module = new Module('electron/js2c/renderer_init');
|
||||
global.require = makeRequireFunction(global.module);
|
||||
|
||||
|
||||
@@ -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')
|
||||
}
|
||||
];
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -13,7 +13,7 @@ require('@electron/internal/common/init');
|
||||
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Export node bindings to global.
|
||||
const { makeRequireFunction } = __non_webpack_require__('internal/modules/helpers');
|
||||
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers');
|
||||
global.module = new Module('electron/js2c/worker_init');
|
||||
global.require = makeRequireFunction(global.module);
|
||||
|
||||
|
||||
@@ -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 => {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/get": "^2.0.0",
|
||||
"@types/node": "^20.9.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"extract-zip": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"@types/klaw": "^3.0.1",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"@types/node": "^20.9.0",
|
||||
"@types/node": "^18.11.18",
|
||||
"@types/semver": "^7.3.3",
|
||||
"@types/send": "^0.14.5",
|
||||
"@types/split": "^1.0.0",
|
||||
|
||||
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)
|
||||
{
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user