Compare commits

...

10 Commits

Author SHA1 Message Date
trop[bot]
00a492d282 chore: Respect HTTP(S) proxy env variable for Yarn (#50349)
Respect HTTP(S) proxy env variable for Yarn

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Filip Mösner <filip.mosner@seznam.cz>
2026-03-18 19:15:19 -04:00
trop[bot]
290a77b843 fix: correctly track BaseWindow::IsActive() on MacOS (#50338)
fix: correctly set IsActive() in BaseWindow on MacOS

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Kyle Cutler <kycutler@microsoft.com>
2026-03-18 19:12:31 -04:00
trop[bot]
87baa17e65 fix: ensure WebContents::WasShown runs when window is shown (#50341)
Avoids a freeze when failing to enter fullscreen on macOS.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Beutner <beutner.john@gmail.com>
2026-03-18 14:57:20 -04:00
trop[bot]
e6928c1319 fix: user resizable transparent windows on win32 (#50300)
test: revert win32 frameless and transparent resizable expectations

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Justin Mayfield <tooker@gmail.com>
2026-03-17 09:46:38 +01:00
trop[bot]
976a7bece5 fix: add ASAR support to additional copy methods (#50284)
* fix: add ASAR support for additional copy methods

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

* test: add tests for ASAR support for additional copy messages

Co-authored-by: Noah Gregory <noahmgregory@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Noah Gregory <noahmgregory@gmail.com>
2026-03-16 12:55:29 -04:00
trop[bot]
03244a56f1 ci: update actions/cache to 5.0.3 (#50237)
chore: update actions/cache to 5.0.3

Needed due to https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
2026-03-13 15:01:38 -04:00
Keeley Hammond
8e0f534873 chore: cherry-pick d5b0cb2acffe from v8 (#50232)
* chore: cherry-pick d5b0cb2acffe from v8

* chore: update patches

---------

Co-authored-by: Samuel Attard <sattard@anthropic.com>
2026-03-13 02:54:53 +00:00
Keeley Hammond
1573d6b28c chore: cherry-pick 7911bee5d90e from skia (#50230)
* chore: cherry-pick 7911bee5d90e from skia

* chore: update patch
2026-03-12 21:49:05 -04:00
John Kleinschmidt
1b3e1433dd ci: update actions/checkout to v6.0.2 (#50223)
* ci: update actions/checkout to v6.0.2

* ci: link node 24 for linux arm testing

(cherry picked from commit 7421434936)
2026-03-12 21:24:38 -04:00
John Kleinschmidt
e551cf8c00 ci: add timeout to test step (#50212)
ci: add timeout to test step (#50186)

Additionally, take a screenshot on timeout so that we can debug why there is a hang
2026-03-12 14:43:58 +01:00
29 changed files with 696 additions and 33 deletions

View File

@@ -43,7 +43,7 @@ runs:
curl --unix-socket /var/run/sas/sas.sock --fail "http://foo/$CACHE_FILE?platform=${{ inputs.target-platform }}&getAccountName=true" > sas-token
- name: Save SAS Key
if: ${{ inputs.generate-sas-token == 'true' }}
uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
uses: actions/cache/save@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
path: sas-token
key: sas-key-${{ inputs.target-platform }}-${{ github.run_number }}-${{ github.run_attempt }}

View File

@@ -7,7 +7,7 @@ runs:
shell: bash
id: yarn-cache-dir-path
run: echo "dir=$(node src/electron/script/yarn.js config get cacheFolder)" >> $GITHUB_OUTPUT
- uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}

View File

@@ -13,7 +13,7 @@ jobs:
contents: read
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.0.2
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
fetch-depth: 0
- name: Setup Node.js/npm

View File

@@ -23,7 +23,7 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -47,7 +47,7 @@ jobs:
TARGET_OS: 'win'
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -72,7 +72,7 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -57,7 +57,7 @@ jobs:
build-image-sha: ${{ steps.set-output.outputs.build-image-sha }}
docs-only: ${{ steps.set-output.outputs.docs-only }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 #v4.0.2
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd #v6.0.2
with:
ref: ${{ github.event.pull_request.head.sha }}
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
@@ -124,7 +124,7 @@ jobs:
build-image-sha: ${{ needs.setup.outputs.build-image-sha }}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -156,7 +156,7 @@ jobs:
build-image-sha: ${{ needs.setup.outputs.build-image-sha}}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -188,7 +188,7 @@ jobs:
build-image-sha: ${{ needs.setup.outputs.build-image-sha}}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -35,7 +35,7 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -36,7 +36,7 @@ jobs:
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_mac=True --custom-var=host_os=mac'
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -27,7 +27,7 @@ jobs:
container: ${{ fromJSON(inputs.container) }}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -43,7 +43,7 @@ jobs:
with:
target-platform: linux
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -27,7 +27,7 @@ jobs:
container: ${{ fromJSON(inputs.container) }}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -95,7 +95,7 @@ jobs:
run: |
mkdir src
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -163,7 +163,7 @@ jobs:
if: ${{ inputs.target-platform == 'linux' }}
uses: ./src/electron/.github/actions/restore-cache-aks
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -48,7 +48,7 @@ jobs:
container: ${{ fromJSON(inputs.check-container) }}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -115,7 +115,7 @@ jobs:
- name: Add CHROMIUM_BUILDTOOLS_PATH to env
run: echo "CHROMIUM_BUILDTOOLS_PATH=$(pwd)/src/buildtools" >> $GITHUB_ENV
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -102,7 +102,7 @@ jobs:
run: |
mkdir src
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -172,7 +172,7 @@ jobs:
if: ${{ inputs.target-platform == 'linux' }}
uses: ./src/electron/.github/actions/restore-cache-aks
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -69,6 +69,7 @@ jobs:
if: ${{ inputs.target-arch == 'arm' && inputs.target-platform == 'linux' }}
run: |
cp $(which node) /mnt/runner-externals/node20/bin/
cp $(which node) /mnt/runner-externals/node24/bin/
- name: Setup Node.js/npm
if: ${{ inputs.target-platform == 'win' }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
@@ -118,7 +119,7 @@ jobs:
if: ${{ inputs.target-platform == 'macos' }}
run: sudo xcode-select --switch /Applications/Xcode_16.4.app
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -208,6 +209,7 @@ jobs:
- name: Run Electron Tests
shell: bash
timeout-minutes: 40
env:
MOCHA_REPORTER: mocha-multi-reporters
MOCHA_MULTI_REPORTERS: mocha-junit-reporter, tap
@@ -258,6 +260,19 @@ jobs:
fi
fi
- name: Take screenshot on timeout or cancellation
if: ${{ inputs.target-platform != 'linux' && (cancelled() || failure()) }}
shell: bash
run: |
screenshot_dir="src/electron/spec/artifacts"
mkdir -p "$screenshot_dir"
screenshot_file="$screenshot_dir/screenshot-timeout-$(date +%Y%m%d%H%M%S).png"
if [ "${{ inputs.target-platform }}" = "macos" ]; then
screencapture -x "$screenshot_file" || true
elif [ "${{ inputs.target-platform }}" = "win" ]; then
powershell -command "Add-Type -AssemblyName System.Windows.Forms; \$screen = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds; \$bitmap = New-Object System.Drawing.Bitmap(\$screen.Width, \$screen.Height); \$graphics = [System.Drawing.Graphics]::FromImage(\$bitmap); \$graphics.CopyFromScreen(\$screen.Location, [System.Drawing.Point]::Empty, \$screen.Size); \$bitmap.Save('$screenshot_file')" || true
fi
- name: Upload Test results to Datadog
env:
DD_ENV: ci
@@ -273,7 +288,7 @@ jobs:
fi
if: always() && !cancelled()
- name: Upload Test Artifacts
if: always() && !cancelled()
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02
with:
name: test_artifacts_${{ env.ARTIFACT_KEY }}_${{ matrix.shard }}

View File

@@ -50,7 +50,7 @@ jobs:
container: ${{ fromJSON(inputs.test-container) }}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0
@@ -106,7 +106,7 @@ jobs:
container: ${{ fromJSON(inputs.test-container) }}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -22,7 +22,7 @@ jobs:
steps:
- name: "Checkout code"
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v4.2.2
with:
persist-credentials: false

View File

@@ -40,7 +40,7 @@ jobs:
build-image-sha: ${{ inputs.build-image-sha }}
steps:
- name: Checkout Electron
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
with:
path: src/electron
fetch-depth: 0

View File

@@ -9,4 +9,8 @@ npmMinimalAgeGate: 10080
npmPreapprovedPackages:
- "@electron/*"
httpProxy: "${HTTP_PROXY:-}"
httpsProxy: "${HTTPS_PROXY:-}"
yarnPath: .yarn/releases/yarn-4.12.0.cjs

View File

@@ -1232,6 +1232,8 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
// has filesystem caching.
overrideAPI(fs, 'copyFile');
overrideAPISync(fs, 'copyFileSync');
overrideAPI(fs, 'cp');
overrideAPISync(fs, 'cpSync');
overrideAPI(fs, 'open');
overrideAPISync(process, 'dlopen', 1);

View File

@@ -1,2 +1,3 @@
graphite_add_insertstatus_koutoforderrecording.patch
cherry-pick-03d405099043.patch
cherry-pick-7911bee5d90e.patch

View File

@@ -0,0 +1,544 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Greg Daniel <egdaniel@google.com>
Date: Wed, 11 Mar 2026 15:29:58 -0400
Subject: Make sure we are getting the correct atlas for glyph mask format.
Bug: b/491421267
Change-Id: I4eacd46599eca2df8c10a3fc894b9ce890fae1e2
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1184076
Commit-Queue: Greg Daniel <egdaniel@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
(cherry picked from commit 0cab3e4ee34b3bca6ba7df676639d73ffe4b2135)
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/1184917
diff --git a/bench/GlyphQuadFillBench.cpp b/bench/GlyphQuadFillBench.cpp
index d5de90c5afd20e85662443c2019521d71bef6fc4..edad3c19f1826e4aecdba74f5c1f04a4d3f9ebf6 100644
--- a/bench/GlyphQuadFillBench.cpp
+++ b/bench/GlyphQuadFillBench.cpp
@@ -68,7 +68,7 @@ class DirectMaskGlyphVertexFillBenchmark : public Benchmark {
const sktext::gpu::AtlasSubRun* subRun =
sktext::gpu::TextBlobTools::FirstSubRun(fBlob.get());
SkASSERT_RELEASE(subRun);
- subRun->testingOnly_packedGlyphIDToGlyph(&fCache);
+ subRun->testingOnly_packedGlyphIDToGlyph(&fCache, subRun->maskFormat());
fVertices.reset(new char[subRun->vertexStride(drawMatrix) * subRun->glyphCount() * 4]);
}
diff --git a/gn/tests.gni b/gn/tests.gni
index 6fc06d23db5357a05a8be5f3e6040be257a34fdf..d3cfbdafdefd766bb910c33007bd7e0bf85c5ff4 100644
--- a/gn/tests.gni
+++ b/gn/tests.gni
@@ -485,6 +485,12 @@ pathops_tests_sources = [
]
ganesh_tests_sources = [
+ "$_tests/AdvancedBlendTest.cpp",
+ "$_tests/ApplyGammaTest.cpp",
+ "$_tests/AtlasOobTest.cpp",
+ "$_tests/BackendAllocationTest.cpp",
+ "$_tests/BackendSurfaceMutableStateTest.cpp",
+ "$_tests/BlendTest.cpp",
"$_tests/BulkRectTest.cpp",
"$_tests/ClearTest.cpp",
"$_tests/DMSAATest.cpp",
diff --git a/src/gpu/ganesh/text/GrAtlasManager.cpp b/src/gpu/ganesh/text/GrAtlasManager.cpp
index 403bfe274e56293bfe2382b02525ae742ba541a7..1e7d9aa0ce14f19e09d79544730c6aa922ae37d6 100644
--- a/src/gpu/ganesh/text/GrAtlasManager.cpp
+++ b/src/gpu/ganesh/text/GrAtlasManager.cpp
@@ -178,8 +178,7 @@ GrDrawOpAtlas::ErrorCode GrAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph,
}
SkASSERT(glyph != nullptr);
- MaskFormat glyphFormat = Glyph::FormatFromSkGlyph(skGlyph.maskFormat());
- MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
+ MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyph->fGlyphEntryKey.fFormat);
int bytesPerPixel = MaskFormatBytesPerPixel(expectedMaskFormat);
int padding;
@@ -299,7 +298,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGanesh(
uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
- this->packedGlyphIDToGlyph(target->strikeCache());
+ this->packedGlyphIDToGlyph(target->strikeCache(), maskFormat);
if (fAtlasGeneration != currentAtlasGen) {
// Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
@@ -316,9 +315,10 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGanesh(
for (const Variant& variant : glyphs) {
Glyph* gpuGlyph = variant.glyph;
SkASSERT(gpuGlyph != nullptr);
-
+ SkASSERT(gpuGlyph->fGlyphEntryKey.fFormat == maskFormat);
if (!atlasManager->hasGlyph(maskFormat, gpuGlyph)) {
- const SkGlyph& skGlyph = *metricsAndImages.glyph(gpuGlyph->fPackedID);
+ const SkGlyph& skGlyph =
+ *metricsAndImages.glyph(gpuGlyph->fGlyphEntryKey.fPackedID);
auto code = atlasManager->addGlyphToAtlas(
skGlyph, gpuGlyph, srcPadding, target->resourceProvider(), uploadTarget);
if (code != GrDrawOpAtlas::ErrorCode::kSucceeded) {
diff --git a/src/gpu/graphite/Device.cpp b/src/gpu/graphite/Device.cpp
index 1bc1f0d51712df81118a67bb22f5d28a6ead8606..e2b8e40b80d44ccfff9bdbd14f657fbbbfe3a3d9 100644
--- a/src/gpu/graphite/Device.cpp
+++ b/src/gpu/graphite/Device.cpp
@@ -1325,6 +1325,7 @@ void Device::drawAtlasSubRun(const sktext::gpu::AtlasSubRun* subRun,
int padding) {
return glyphs->regenerateAtlasForGraphite(begin, end, maskFormat, padding, fRecorder);
};
+
for (int subRunCursor = 0; subRunCursor < subRunEnd;) {
// For the remainder of the run, add any atlas uploads to the Recorder's TextAtlasManager
auto[ok, glyphsRegenerated] = subRun->regenerateAtlas(subRunCursor, subRunEnd,
diff --git a/src/gpu/graphite/text/TextAtlasManager.cpp b/src/gpu/graphite/text/TextAtlasManager.cpp
index 6602a76c150bff077666fb91b990d3e45d528ce2..cbb51a66846922995912c3159afba879a2487313 100644
--- a/src/gpu/graphite/text/TextAtlasManager.cpp
+++ b/src/gpu/graphite/text/TextAtlasManager.cpp
@@ -207,8 +207,7 @@ DrawAtlas::ErrorCode TextAtlasManager::addGlyphToAtlas(const SkGlyph& skGlyph,
}
SkASSERT(glyph != nullptr);
- MaskFormat glyphFormat = Glyph::FormatFromSkGlyph(skGlyph.maskFormat());
- MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyphFormat);
+ MaskFormat expectedMaskFormat = this->resolveMaskFormat(glyph->fGlyphEntryKey.fFormat);
int bytesPerPixel = MaskFormatBytesPerPixel(expectedMaskFormat);
int padding;
@@ -359,7 +358,7 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGraphite(int begin,
uint64_t currentAtlasGen = atlasManager->atlasGeneration(maskFormat);
- this->packedGlyphIDToGlyph(recorder->priv().strikeCache());
+ this->packedGlyphIDToGlyph(recorder->priv().strikeCache(), maskFormat);
if (fAtlasGeneration != currentAtlasGen) {
// Calculate the texture coordinates for the vertexes during first use (fAtlasGeneration
@@ -375,9 +374,10 @@ std::tuple<bool, int> GlyphVector::regenerateAtlasForGraphite(int begin,
for (const Variant& variant : glyphs) {
Glyph* gpuGlyph = variant.glyph;
SkASSERT(gpuGlyph != nullptr);
-
+ SkASSERT(gpuGlyph->fGlyphEntryKey.fFormat == maskFormat);
if (!atlasManager->hasGlyph(maskFormat, gpuGlyph)) {
- const SkGlyph& skGlyph = *metricsAndImages.glyph(gpuGlyph->fPackedID);
+ const SkGlyph& skGlyph =
+ *metricsAndImages.glyph(gpuGlyph->fGlyphEntryKey.fPackedID);
auto code = atlasManager->addGlyphToAtlas(skGlyph, gpuGlyph, srcPadding);
if (code != DrawAtlas::ErrorCode::kSucceeded) {
success = code != DrawAtlas::ErrorCode::kError;
diff --git a/src/text/gpu/Glyph.h b/src/text/gpu/Glyph.h
index 2c6f828ca6f9941b1dc8d73d428370b11d1d52bd..7942006a563bcab925ea2129ab6f6beea438a4c8 100644
--- a/src/text/gpu/Glyph.h
+++ b/src/text/gpu/Glyph.h
@@ -14,6 +14,25 @@
namespace sktext::gpu {
+struct GlyphEntryKey {
+ explicit GlyphEntryKey(SkPackedGlyphID id, skgpu::MaskFormat format)
+ : fPackedID(id), fFormat(format) {}
+
+ const SkPackedGlyphID fPackedID;
+ skgpu::MaskFormat fFormat;
+
+ bool operator==(const GlyphEntryKey& that) const {
+ return fPackedID == that.fPackedID && fFormat == that.fFormat;
+ }
+ bool operator!=(const GlyphEntryKey& that) const {
+ return !(*this == that);
+ }
+
+ uint32_t hash() const {
+ return fPackedID.hash();
+ }
+};
+
class Glyph {
public:
static skgpu::MaskFormat FormatFromSkGlyph(SkMask::Format format) {
@@ -34,10 +53,11 @@ public:
SkUNREACHABLE;
}
- Glyph(SkPackedGlyphID packedGlyphID) : fPackedID(packedGlyphID) {}
+ explicit Glyph(SkPackedGlyphID packedGlyphID, skgpu::MaskFormat format)
+ : fGlyphEntryKey(packedGlyphID, format) {}
- const SkPackedGlyphID fPackedID;
- skgpu::AtlasLocator fAtlasLocator;
+ const GlyphEntryKey fGlyphEntryKey;
+ skgpu::AtlasLocator fAtlasLocator;
};
} // namespace sktext::gpu
diff --git a/src/text/gpu/GlyphVector.cpp b/src/text/gpu/GlyphVector.cpp
index 2a8e85f926aa547169f4b85372e9d3fb99816956..7bec7a0b77d8560d5ef978281edd7df6c45cb56f 100644
--- a/src/text/gpu/GlyphVector.cpp
+++ b/src/text/gpu/GlyphVector.cpp
@@ -99,14 +99,14 @@ SkSpan<const Glyph*> GlyphVector::glyphs() const {
// packedGlyphIDToGlyph must be run in single-threaded mode.
// If fSkStrike is not sk_sp<SkStrike> then the conversion to Glyph* has not happened.
-void GlyphVector::packedGlyphIDToGlyph(StrikeCache* cache) {
+void GlyphVector::packedGlyphIDToGlyph(StrikeCache* cache, MaskFormat maskFormat) {
if (fTextStrike == nullptr) {
SkStrike* strike = fStrikePromise.strike();
fTextStrike = cache->findOrCreateStrike(strike->strikeSpec());
// Get all the atlas locations for each glyph.
for (Variant& variant : fGlyphs) {
- variant.glyph = fTextStrike->getGlyph(variant.packedGlyphID);
+ variant.glyph = fTextStrike->getGlyph(variant.packedGlyphID, maskFormat);
}
// This must be pinned for the Atlas filling to work.
diff --git a/src/text/gpu/GlyphVector.h b/src/text/gpu/GlyphVector.h
index 42b92a93f70cc6d86d0a87dd07c2244e0da1281c..1eec6327d38fb4472b027faae68eecb9ad7509d7 100644
--- a/src/text/gpu/GlyphVector.h
+++ b/src/text/gpu/GlyphVector.h
@@ -68,7 +68,7 @@ public:
// the sub runs.
int unflattenSize() const { return GlyphVectorSize(fGlyphs.size()); }
- void packedGlyphIDToGlyph(StrikeCache* cache);
+ void packedGlyphIDToGlyph(StrikeCache* cache, skgpu::MaskFormat);
static size_t GlyphVectorSize(size_t count) {
return sizeof(Variant) * count;
diff --git a/src/text/gpu/StrikeCache.cpp b/src/text/gpu/StrikeCache.cpp
index add3127c92fdbfe56d6b56209a2235ce5a9f5acb..19df48329fd500f8682669ec96eb883b58243fdd 100644
--- a/src/text/gpu/StrikeCache.cpp
+++ b/src/text/gpu/StrikeCache.cpp
@@ -207,10 +207,11 @@ TextStrike::TextStrike(StrikeCache* strikeCache, const SkStrikeSpec& strikeSpec)
: fStrikeCache(strikeCache)
, fStrikeSpec{strikeSpec} {}
-Glyph* TextStrike::getGlyph(SkPackedGlyphID packedGlyphID) {
- Glyph* glyph = fCache.findOrNull(packedGlyphID);
+Glyph* TextStrike::getGlyph(SkPackedGlyphID packedGlyphID, skgpu::MaskFormat format) {
+ GlyphEntryKey localKey(packedGlyphID, format);
+ Glyph* glyph = fCache.findOrNull(localKey);
if (glyph == nullptr) {
- glyph = fAlloc.make<Glyph>(packedGlyphID);
+ glyph = fAlloc.make<Glyph>(packedGlyphID, format);
fCache.set(glyph);
fMemoryUsed += sizeof(Glyph);
if (!fRemoved) {
@@ -220,11 +221,11 @@ Glyph* TextStrike::getGlyph(SkPackedGlyphID packedGlyphID) {
return glyph;
}
-const SkPackedGlyphID& TextStrike::HashTraits::GetKey(const Glyph* glyph) {
- return glyph->fPackedID;
+const GlyphEntryKey& TextStrike::HashTraits::GetKey(const Glyph* glyph) {
+ return glyph->fGlyphEntryKey;
}
-uint32_t TextStrike::HashTraits::Hash(SkPackedGlyphID key) {
+uint32_t TextStrike::HashTraits::Hash(GlyphEntryKey key) {
return key.hash();
}
diff --git a/src/text/gpu/StrikeCache.h b/src/text/gpu/StrikeCache.h
index 007c45c6c6feecba3ff031ba3939ad2402e082b9..014afd5286602e3e049d8e48ae328273e599dc41 100644
--- a/src/text/gpu/StrikeCache.h
+++ b/src/text/gpu/StrikeCache.h
@@ -13,6 +13,7 @@
#include "src/core/SkDescriptor.h"
#include "src/core/SkStrikeSpec.h"
#include "src/core/SkTHash.h"
+#include "src/gpu/AtlasTypes.h"
#include <cstddef>
#include <cstdint>
@@ -32,6 +33,7 @@ struct SkPackedGlyphID;
namespace sktext::gpu {
class Glyph;
+struct GlyphEntryKey;
class StrikeCache;
// The TextStrike manages an SkArenaAlloc for Glyphs. The SkStrike is what actually creates
@@ -43,7 +45,7 @@ public:
TextStrike(StrikeCache* strikeCache,
const SkStrikeSpec& strikeSpec);
- Glyph* getGlyph(SkPackedGlyphID);
+ Glyph* getGlyph(SkPackedGlyphID, skgpu::MaskFormat format);
const SkStrikeSpec& strikeSpec() const { return fStrikeSpec; }
const SkDescriptor& getDescriptor() const { return fStrikeSpec.descriptor(); }
@@ -54,11 +56,11 @@ private:
const SkStrikeSpec fStrikeSpec;
struct HashTraits {
- static const SkPackedGlyphID& GetKey(const Glyph* glyph);
- static uint32_t Hash(SkPackedGlyphID key);
+ static const GlyphEntryKey& GetKey(const Glyph* glyph);
+ static uint32_t Hash(GlyphEntryKey key);
};
// Map SkPackedGlyphID -> Glyph*.
- skia_private::THashTable<Glyph*, SkPackedGlyphID, HashTraits> fCache;
+ skia_private::THashTable<Glyph*, GlyphEntryKey, HashTraits> fCache;
// Store for the glyph information.
SkArenaAlloc fAlloc{512};
diff --git a/src/text/gpu/SubRunContainer.cpp b/src/text/gpu/SubRunContainer.cpp
index 3a061a2012cd99de9ee4b3674f78ae99e0385d6c..a19460c82593c6713c047ab19e71caa27e375a6d 100644
--- a/src/text/gpu/SubRunContainer.cpp
+++ b/src/text/gpu/SubRunContainer.cpp
@@ -651,8 +651,9 @@ public:
int glyphSrcPadding() const override { return 0; }
- void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache) const override {
- fGlyphs.packedGlyphIDToGlyph(cache);
+ void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache,
+ skgpu::MaskFormat maskFormat) const override {
+ fGlyphs.packedGlyphIDToGlyph(cache, maskFormat);
}
std::tuple<bool, SkRect> deviceRectAndNeedsTransform(
@@ -755,8 +756,9 @@ public:
const AtlasSubRun* testingOnly_atlasSubRun() const override { return this; }
- void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache) const override {
- fGlyphs.packedGlyphIDToGlyph(cache);
+ void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache,
+ skgpu::MaskFormat maskFormat) const override {
+ fGlyphs.packedGlyphIDToGlyph(cache, maskFormat);
}
int glyphSrcPadding() const override { return 1; }
@@ -884,8 +886,9 @@ public:
const AtlasSubRun* testingOnly_atlasSubRun() const override { return this; }
- void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache) const override {
- fGlyphs.packedGlyphIDToGlyph(cache);
+ void testingOnly_packedGlyphIDToGlyph(StrikeCache *cache,
+ skgpu::MaskFormat maskFormat) const override {
+ fGlyphs.packedGlyphIDToGlyph(cache, maskFormat);
}
int glyphSrcPadding() const override { return SK_DistanceFieldInset; }
diff --git a/src/text/gpu/SubRunContainer.h b/src/text/gpu/SubRunContainer.h
index 2573dbb3964e9ab2cc0e276b60d4ab4f9804f0d9..4d1a3c8c2d55015d3d351d322ef039c45be2a398 100644
--- a/src/text/gpu/SubRunContainer.h
+++ b/src/text/gpu/SubRunContainer.h
@@ -167,7 +167,7 @@ public:
const VertexFiller& vertexFiller() const { return fVertexFiller; }
- virtual void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache) const = 0;
+ virtual void testingOnly_packedGlyphIDToGlyph(StrikeCache* cache, skgpu::MaskFormat) const = 0;
protected:
const VertexFiller fVertexFiller;
diff --git a/tests/AtlasOobTest.cpp b/tests/AtlasOobTest.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..4e6fb02ee6af6543df285d8112f1a2ced5bd9ac9
--- /dev/null
+++ b/tests/AtlasOobTest.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright 2026 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#include "include/core/SkCanvas.h"
+#include "include/core/SkGraphics.h"
+#include "include/core/SkSerialProcs.h"
+#include "include/core/SkSurface.h"
+#include "include/private/chromium/SkChromeRemoteGlyphCache.h"
+#include "include/private/chromium/Slug.h"
+#include "src/core/SkDescriptor.h"
+#include "src/core/SkReadBuffer.h"
+#include "src/core/SkTypeface_remote.h"
+#include "src/core/SkWriteBuffer.h"
+#include "src/gpu/AtlasTypes.h"
+#include "tests/CtsEnforcement.h"
+#include "tests/Test.h"
+#include "tools/ToolUtils.h"
+
+#if defined(SK_GANESH)
+#include "include/gpu/ganesh/GrDirectContext.h"
+#include "include/gpu/ganesh/SkSurfaceGanesh.h"
+#endif
+
+#if defined(SK_GRAPHITE)
+#include "include/gpu/graphite/Context.h"
+#include "include/gpu/graphite/Surface.h"
+#include "tools/graphite/GraphiteTestContext.h"
+#endif // defined(SK_GRAPHITE)
+
+#include <vector>
+#include <cstring>
+
+namespace {
+class FakeDiscardableManager : public SkStrikeClient::DiscardableHandleManager {
+public:
+ bool deleteHandle(SkDiscardableHandleId) override { return false; }
+ void notifyCacheMiss(SkStrikeClient::CacheMissType, int) override {}
+ void notifyReadFailure(const ReadFailureData&) override {}
+ void assertHandleValid(SkDiscardableHandleId) override {}
+};
+
+unsigned char kStrikeData[] = {
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x07, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65,
+ 0x00, 0x00, 0x00, 0x65, 0xd8, 0x50, 0xda, 0x99, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x63, 0x65, 0x72, 0x73, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x80, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x64, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0x67, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x66, 0x86, 0x07, 0xc2, 0x42,
+ 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x65, 0x72, 0x73, 0x38, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00
+};
+
+unsigned char kDrawSlugOp[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x00, 0x41,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3f,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+ 0x00, 0x00, 0x00, 0x41, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x86, 0x07, 0xc2, 0x42, 0x4c, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x63, 0x65, 0x72, 0x73,
+ 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x80, 0x41, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+} // namespace
+
+// TODO: We expect this test to correctly hit an SkUnreachable and then crash. That does not work
+// with our current testing framework because we have no to "expect" a crash. So for now we will
+// land this test with only the valid loop enabled, but to test this is working locally, you should
+// change the loop to have both iterations.
+static void run_atlas_oob_test(skiatest::Reporter* reporter, SkCanvas* canvas) {
+ auto discardableManager = sk_make_sp<FakeDiscardableManager>();
+ SkStrikeClient client(discardableManager, false);
+
+ // 1. Prepare Strike Data
+ if (!client.readStrikeData(kStrikeData, sizeof(kStrikeData))) {
+ REPORTER_ASSERT(reporter, false, "Failed to read initial strike data");
+ }
+
+ // 2. Prepare and Execute DrawSlug ops
+ SkPaint paint;
+ for (int idx = 0; idx < 1; ++idx) {
+// for (int idx = 0; idx < 2; ++idx) {
+ if (idx == 0) {
+ kDrawSlugOp[0x48] = (unsigned char)skgpu::MaskFormat::kARGB;
+ } else if (idx == 1) {
+ kDrawSlugOp[0x48] = (unsigned char)skgpu::MaskFormat::kA8;
+ }
+ kDrawSlugOp[0xd8] = SkMask::kARGB32_Format;
+ kDrawSlugOp[0xe0] = 0x99;
+
+ auto slug = client.deserializeSlugForTest(kDrawSlugOp, sizeof(kDrawSlugOp));
+ if (slug) {
+ slug->draw(canvas, paint);
+ }
+ }
+
+}
+
+#if defined(SK_GANESH)
+DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(Atlas_Oob_ganesh, reporter, ctxInfo, CtsEnforcement::kNextRelease) {
+ auto dContext = ctxInfo.directContext();
+ SkImageInfo info = SkImageInfo::MakeN32Premul(1024, 1024);
+ auto surface = SkSurfaces::RenderTarget(dContext, skgpu::Budgeted::kNo, info);
+ if (!surface) return;
+ auto canvas = surface->getCanvas();
+
+ run_atlas_oob_test(reporter, canvas);
+
+ dContext->flushAndSubmit();
+}
+#endif // defined(SK_GANESH)
+
+#if defined(SK_GRAPHITE)
+DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(Atlas_Oob_graphite, reporter, context, CtsEnforcement::kNextRelease) {
+ using namespace skgpu::graphite;
+ std::unique_ptr<Recorder> recorder = context->makeRecorder();
+ SkImageInfo info = SkImageInfo::MakeN32Premul(1024, 1024);
+ auto surface = SkSurfaces::RenderTarget(recorder.get(), info);
+ if (!surface) return;
+ auto canvas = surface->getCanvas();
+
+ run_atlas_oob_test(reporter, canvas);
+
+ std::unique_ptr<Recording> recording = recorder->snap();
+ InsertRecordingInfo recordingInfo;
+ recordingInfo.fRecording = recording.get();
+ context->insertRecording(recordingInfo);
+ context->submit();
+}
+#endif // defined(SK_GRAPHITE)

View File

@@ -3,3 +3,4 @@ turboshaft_avoid_introducing_too_many_variables.patch
runtime_setprototypeproperties_handling_of.patch
runtime_correcting_setprototypeproperties.patch
reduce_stack_memory_consumption_in_bytecodegenerator.patch
cherry-pick-d5b0cb2acffe.patch

View File

@@ -0,0 +1,50 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Darius Mercadier <dmercadier@chromium.org>
Date: Wed, 25 Feb 2026 12:56:18 +0100
Subject: [M144 Merge] [maglev] fix CanElideWriteBarrier Smi recording for phis
Recording a Tagged use is not enough for 2 reasons:
* Tagged uses are sometimes ignored, in particular for loop phis
where we distinguish in-loop and out-of-loop uses.
* This Tagged use could only prevent untagging of this specific phi,
but none of its inputs. So we could have a Smi phi as input to the
current phi which gets untagged and retagged to a non-Smi, all
while the current phi doesn't get untagged.
(cherry picked from commit a54bf5cd45e5b119e2afe6019428e81c3d626fb3)
Change-Id: I9b3a2ea339f2c9d81dbb74a44425ba55d8c73871
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7604255
Auto-Submit: Darius Mercadier <dmercadier@chromium.org>
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
Commit-Queue: Darius Mercadier <dmercadier@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#105444}
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/7659106
Auto-Submit: Srinivas Sista <srinivassista@chromium.org>
Reviewed-by: Rezvan Mahdavi Hezaveh <rezvan@chromium.org>
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
Reviewed-by: Deepti Gandluri <gdeepti@chromium.org>
Owners-Override: Srinivas Sista <srinivassista@chromium.org>
Cr-Commit-Position: refs/branch-heads/14.4@{#64}
Cr-Branched-From: 80acc26727d5a34e77dabeebe7c9213ec1bd4768-refs/heads/14.4.258@{#1}
Cr-Branched-From: ce7e597e90f6df3fa4b6df224bc613b80c635450-refs/heads/main@{#104020}
diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc
index 4664ca78b4413da6a3d9d6cafa705d33f5c02ee2..c682aec3ff109e42290c2e2ddec350f913e4e063 100644
--- a/src/maglev/maglev-graph-builder.cc
+++ b/src/maglev/maglev-graph-builder.cc
@@ -4496,7 +4496,11 @@ bool MaglevGraphBuilder::CanElideWriteBarrier(ValueNode* object,
ValueNode* value) {
if (value->Is<RootConstant>() || value->Is<ConsStringMap>()) return true;
if (!IsEmptyNodeType(GetType(value)) && CheckType(value, NodeType::kSmi)) {
- value->MaybeRecordUseReprHint(UseRepresentation::kTagged);
+ if constexpr (SmiValuesAre31Bits()) {
+ if (Phi* value_as_phi = value->TryCast<Phi>()) {
+ value_as_phi->SetUseRequires31BitValue();
+ }
+ }
return true;
}

View File

@@ -317,6 +317,12 @@ void BaseWindow::OnWindowSheetEnd() {
Emit("sheet-end");
}
void BaseWindow::OnWindowIsKeyChanged(bool is_key) {
#if BUILDFLAG(IS_MAC)
window()->SetActive(is_key);
#endif
}
void BaseWindow::OnWindowEnterHtmlFullScreen() {
Emit("enter-html-full-screen");
}

View File

@@ -83,6 +83,7 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
void OnWindowRotateGesture(float rotation) override;
void OnWindowSheetBegin() override;
void OnWindowSheetEnd() override;
void OnWindowIsKeyChanged(bool is_key) override;
void OnWindowEnterFullScreen() override;
void OnWindowLeaveFullScreen() override;
void OnWindowEnterHtmlFullScreen() override;

View File

@@ -280,16 +280,22 @@ v8::Local<v8::Value> BrowserWindow::GetWebContents(v8::Isolate* isolate) {
}
void BrowserWindow::OnWindowShow() {
if (!web_contents_shown_) {
web_contents()->WasShown();
web_contents_shown_ = true;
}
BaseWindow::OnWindowShow();
}
void BrowserWindow::OnWindowHide() {
web_contents()->WasOccluded();
web_contents_shown_ = false;
BaseWindow::OnWindowHide();
}
void BrowserWindow::Show() {
web_contents()->WasShown();
web_contents_shown_ = true;
BaseWindow::Show();
}
@@ -298,6 +304,7 @@ void BrowserWindow::ShowInactive() {
if (IsModal())
return;
web_contents()->WasShown();
web_contents_shown_ = true;
BaseWindow::ShowInactive();
}

View File

@@ -80,6 +80,7 @@ class BrowserWindow : public BaseWindow,
// Helpers.
v8::Global<v8::Value> web_contents_;
bool web_contents_shown_ = false;
v8::Global<v8::Value> web_contents_view_;
base::WeakPtr<api::WebContents> api_web_contents_;

View File

@@ -1000,17 +1000,13 @@ void NativeWindowViews::MoveTop() {
bool NativeWindowViews::CanResize() const {
#if BUILDFLAG(IS_WIN)
return resizable_ && thick_frame_;
return has_frame() ? resizable_ && thick_frame_ : resizable_;
#else
return resizable_;
#endif
}
bool NativeWindowViews::IsResizable() const {
#if BUILDFLAG(IS_WIN)
if (has_frame())
return ::GetWindowLong(GetAcceleratedWidget(), GWL_STYLE) & WS_THICKFRAME;
#endif
return CanResize();
}

View File

@@ -5501,7 +5501,7 @@ describe('BrowserWindow module', () => {
thickFrame: true,
transparent: true
});
expect(w.isResizable()).to.be.false('resizable');
expect(w.isResizable()).to.be.true('resizable');
w.maximize();
expect(w.isMaximized()).to.be.true('maximized');
const bounds = w.getBounds();

View File

@@ -407,6 +407,41 @@ describe('asar package', function () {
});
});
describe('fs.cpSync', function () {
itremote('copies a normal file', function () {
if (!fs.cpSync) return;
const p = path.join(asarDir, 'a.asar', 'file1');
const temp = require('temp').track();
const dest = temp.path();
fs.cpSync(p, dest);
expect(fs.readFileSync(p).equals(fs.readFileSync(dest))).to.be.true();
});
});
describe('fs.cp', function () {
itremote('copies a normal file', async function () {
if (!fs.cp) return;
const p = path.join(asarDir, 'a.asar', 'file1');
const temp = require('temp').track();
const dest = temp.path();
await new Promise<void>((resolve, reject) => {
fs.cp(p, dest, (err) => err ? reject(err) : resolve());
});
expect(fs.readFileSync(p).equals(fs.readFileSync(dest))).to.be.true();
});
});
describe('fs.promises.cp', function () {
itremote('copies a normal file', async function () {
if (!fs.promises.cp) return;
const p = path.join(asarDir, 'a.asar', 'file1');
const temp = require('temp').track();
const dest = temp.path();
await fs.promises.cp(p, dest);
expect(fs.readFileSync(p).equals(fs.readFileSync(dest))).to.be.true();
});
});
describe('fs.lstatSync', function () {
itremote('handles path with trailing slash correctly', function () {
const p = path.join(asarDir, 'a.asar', 'link2', 'link2', 'file1');