Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
ad3c1ab
Remove redundant m_renderRange.start() null checks in RenderHighlight…
Ahmad-S792 Jun 30, 2026
144aa0d
[GPUP] WebGPU BindGroup Validation-Cache Key Collision Leads to GPU O…
mwyrzykowski Jun 30, 2026
b690833
Uninitialized-heap disclosure in convertImagePixelsFromFloat16ToFloat…
zakariaridouh Jun 30, 2026
c3ca56b
[JSC] DFGArgumentsEliminationPhase removeViaKill should reset node sc…
ast-hugger Jun 30, 2026
3ccfb3e
[Tools][WPE][browserperfdash-benchmark] browser-binary-size plan plug…
clopez Jun 30, 2026
d8576e6
Reject requestStorageAccess() without gesture should not synthesize u…
charliewolfe Jun 30, 2026
82a21e0
MockSampleBox should not have negative timeScales and duration
jernoble Jun 30, 2026
3c46119
[cleanup] Rename RenderBox::setWidth()/setHeight() to setBorderBoxWid…
alanbaradlay Jun 30, 2026
bdf08cf
[cleanup] Use RenderBox::borderBoxSize() in size-only callers of bord…
alanbaradlay Jun 30, 2026
e1084c3
Use-after-free under WebsiteDataStore::beginAppBoundDomainCheck()
cdumez Jun 30, 2026
8c0e20b
WebGL: Uninitialized FastMalloc heap disclosure in RemoteGraphicsCont…
kkinnunen-apple Jun 30, 2026
bb98ffd
FilterImage may return uninitialized PixelBuffer
shallawa Jun 30, 2026
bd5f1e5
YarrJIT negativeOffsetIndexedAddress discards adjusted base register
asworkjsc Jun 30, 2026
0d6fe16
[JSC] Spread operator doesn't account for cellButterflyOnlyAtomString…
heimskr Jun 30, 2026
16b1bde
[CoreIPC] [NP] Heap UAF in WebCore::IDBServer::MemoryIndexCursor reve…
zakariaridouh Jun 30, 2026
8d4c709
ANGLE: Metal: Inconsistent implementation of various DrawElements var…
kkinnunen-apple Jun 30, 2026
543f99d
[WebGPU] signed-negation overflow on baseVertex==INT32_MIN in RenderP…
tadeuzagallo Jun 30, 2026
20d1bae
[JSC] Unconditionally keep OMGOSREntryCallee alive while updating its…
vigneshrao-apple Jun 30, 2026
e2b88c2
Reject IndexedDB transactions during version change operation
atar13 Jun 30, 2026
aad3188
[WebGPU] Stale WeakPtr comparison in BindGroupLayout::errorValidating…
tadeuzagallo Jun 30, 2026
e147963
use-after-free in WebCodecsAudioData::memoryCost() via concurrent GC …
sheeparegreat Jun 30, 2026
d9783c3
[WebKit Process Model] Use-after-free in WebExtensionContext::storage…
cdumez Jun 30, 2026
7a9d149
[JSC] TypedArray.from() Out-of-Bounds Read via Resizable ArrayBuffer …
heimskr Jun 30, 2026
4691d48
Fix animateMotion-spline-invalid-keyTimes.html
rwlbuis Jun 30, 2026
2620d0d
[JSC] Insert barrier for MultiPutByOffset when it can reallocate storage
syg Jun 30, 2026
ff4c717
REGRESSION(316095@main): error: initializer 'init(_:)' is not availab…
JonWBedard Jun 30, 2026
ebcf150
[LBSE] Rebaseline iOS specific results after 315674@main
nikolaszimmermann Jun 30, 2026
5dd6865
[JSC] Add ArrayStorage + GetByVal specific operation
Constellation Jun 30, 2026
9d4788b
Need a process-specific `WebBackForwardListItem::allItems()` instead …
beidson Jun 30, 2026
ef2bac7
Combining marks on SVG <textPath> render as dotted circles
karlcow Jun 30, 2026
5c93ade
[macOS] Scroll pocket color may be lost in fullscreen after refresh
lilyspiniolas Jun 30, 2026
a828526
[MSE] Loosen gap tolerance during playback and seek
jyavenard Jun 30, 2026
b590f91
[cleanup] Use RenderBox::borderBoxSize() in size-only callers of fram…
alanbaradlay Jun 30, 2026
9b4ffe1
Add findIfCached / insert to TinyLRUCache
justinmichaud Jun 30, 2026
5044a54
Validate several ITP and storage access IPC messages
charliewolfe Jun 30, 2026
6ea1f0a
[WebCore][bindings] Empty JSValue returned to script from callPromise…
cdumez Jun 30, 2026
a93904b
Use-after-free in SVGGeometryElement::getPointAtLength — raw renderer…
shallawa Jun 30, 2026
736ce62
[JSC] Disallow defining private names on WasmGC objects
syg Jun 30, 2026
d3cffdd
Uninitialized result of FEGaussianBlur if the input isAlphaImage
shallawa Jun 30, 2026
8e5b854
Sort TestWebKitAPI pbxproj file after 316044@main
aprotyas Jun 30, 2026
ce030f7
WebGL: GraphicsContextGLANGLE PACK_* state is modifiable through pixe…
kkinnunen-apple Jun 30, 2026
8bdea30
Marked-text highlight pseudo-element fill color is taken from the str…
Ahmad-S792 Jun 30, 2026
0012e61
Add size limit to Yarr generated code
asworkjsc Jun 30, 2026
3ab3db0
DOM XSS in committers-autocomplete.js
lingcherd Jun 30, 2026
0f85710
GetPixelBuffer should zeroFill the destination if any error happens
shallawa Jun 30, 2026
0053494
Lowercase CSP directive names eagerly
roberto-apple Jun 30, 2026
e23afe6
[Site Isolation] Per-frame back/forward walk regresses iframe to stal…
basuke Jun 30, 2026
e081edf
[Scripts] --print-expectations fails when no tests match
TheBoyRoy05 Jun 30, 2026
8d85f54
Re-enable MTE hard-mode
Achierius Jun 30, 2026
140ce5b
[JSC] Missing codeBlock->m_lock in repatchGetBySlowPathCall
heimskr Jun 30, 2026
7deaf9d
Prepare to replace WKJSScriptingBuffer with NSData
achristensen07 Jun 30, 2026
a18c0a8
Unvalidated replacementPath in NetworkConnectionToWebProcess::registe…
RupinMittal Jun 30, 2026
6aa96bc
Missing allowsFirstPartyForCookies check in loadPing() IPC may lead t…
RupinMittal Jun 30, 2026
2020284
[iOS] Remove support for AVMediaSource from MediaDeviceRoute
aestes Jun 30, 2026
6c94926
[css-mixins-1] Implement argument parsing in terms of first-valid()
anttijk Jun 30, 2026
f9eddca
Stored XSS on bugs.webkit.org in Commits extension; fix guidance (esc…
lingcherd Jun 30, 2026
4b7a49a
Web Inspector: Support ES2022 Private Methods
dcrousso Jun 30, 2026
508bfb2
Migrate CoreIPC defines from WebKitAdditions
sheeparegreat Jun 30, 2026
88e4fef
Reduce use of `.get()` for smart pointers in WebModelPlayer
ruthvikkonda Jun 30, 2026
ae0d90b
Fix some failures in imported/w3c/web-platform-tests/svg/styling
rwlbuis Jun 30, 2026
2f91fd7
[WebCore] Take graphLock() in BiquadFilterNode::setType() to avoid race
atar13 Jun 30, 2026
4454093
Cherry-pick 343f135c4791. rdar://175672573
xeenon Jun 30, 2026
9bb8fdf
PrettyPatch should HTML-escape image URLs when rendering binary image…
lingcherd Jun 30, 2026
d7eb859
Add system version prefix mapping for macOS 26
samuelengida Jun 30, 2026
d6fb60c
[WebCore] Capture WeakPtr to this (MediaMetadata) in ArtworkImageLoad…
atar13 Jun 30, 2026
bf0c7c6
REGRESSION(312893@main): ASSERT(m_decodedSize >= decodedSize) in Bitm…
shallawa Jun 30, 2026
ba3be26
[WebCore] use-after-free in Style::TreeResolver — XMLDocumentParser::…
anttijk Jun 30, 2026
b12f122
Compromised web content processes can use percent-encoded path separa…
aprotyas Jun 30, 2026
a2de66f
[JSC][FTL] compileArrayIndexOfOrArrayIncludes (UntypedUse + Array::Co…
heimskr Jun 30, 2026
54b8e49
Heap UaF in GPU Process via MediaStreamTrack.clone() + ImageCapture.t…
youennf Jun 30, 2026
336c35e
[JSC] Stale structure bit in SlowPutArrayStorage
heimskr Jun 30, 2026
e540a45
[ Gardening ] Mark expectations for layout-tests that have been filed
Smackteo Jun 30, 2026
c5fabb4
Remove shouldRestrictHTTPResponseAccess from NetworkResourceLoadParam…
basuke Jun 30, 2026
b48b4d4
[WebCore] Use-after-free in InternalAudioEncoderCocoa on ASBD change …
eric-carlson Jun 30, 2026
d75a9fd
[JSC] Do not cache property absence on dictionaries
syg Jun 30, 2026
a0291f1
[css-mixins-1] Serialize types
anttijk Jun 30, 2026
019c43f
[SharedWorker] Add MESSAGE_CHECK to establishSharedWorkerContextConne…
basuke Jun 30, 2026
95a70d5
Custom property names in declaration blocks should be serialized escaped
anttijk Jun 30, 2026
c312747
[WebKit Networking] continueWillSendRequest m_redirectionForCurrentNa…
cdumez Jun 30, 2026
cfced00
[CI] Update measure-build-time swift patch
emw-apple Jun 30, 2026
7a5ee54
UAF due to cross-thread destruction of worker DeferredPromise in WebL…
cdumez Jun 30, 2026
428365d
RenderFlexibleBox::LineState constructor copies FlexLayoutItems inste…
Ahmad-S792 Jun 30, 2026
600eab6
[LBSE] Add LBSE specific result for svg/repaint/svg-outline-repaint-o…
nikolaszimmermann Jun 30, 2026
d81bcc3
Prepare for removal of _WKJSHandle
achristensen07 Jun 30, 2026
f652829
Merge remote-tracking branch 'upstream/main' into bun/upgrade-to-d81b…
robobun Jun 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Configurations/Version.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ SHORT_VERSION_STRING = $(SHORT_VERSION_STRING_$(CONFIGURATION))
SYSTEM_VERSION_MAJOR_SHORT_MACOS = $(SYSTEM_VERSION_MAJOR_SHORT_MACOS_$(TARGET_MAC_OS_X_VERSION_MAJOR))
SYSTEM_VERSION_MAJOR_SHORT_MACOS_150000 = 15
SYSTEM_VERSION_MAJOR_SHORT_MACOS_160000 = 16
SYSTEM_VERSION_MAJOR_SHORT_MACOS_260000 = 26
SYSTEM_VERSION_MAJOR_SHORT_MACOS_270000 = 27
SYSTEM_VERSION_MAJOR_SHORT_MACOS_280000 = 28
SYSTEM_VERSION_MAJOR_SHORT_MACOS_290000 = 29
Expand All @@ -44,6 +45,7 @@ SYSTEM_VERSION_MAJOR_SHORT_MACOS_300000 = 30
SYSTEM_VERSION_PREFIX = $(SYSTEM_VERSION_PREFIX_$(PLATFORM_NAME)_$(SYSTEM_VERSION_MAJOR_SHORT_MACOS))
SYSTEM_VERSION_PREFIX_macosx_15 = 20
SYSTEM_VERSION_PREFIX_macosx_16 = 21
SYSTEM_VERSION_PREFIX_macosx_26 = 21
SYSTEM_VERSION_PREFIX_macosx_27 = 22
SYSTEM_VERSION_PREFIX_macosx_28 = 23
SYSTEM_VERSION_PREFIX_macosx_29 = 24
Expand Down
32 changes: 32 additions & 0 deletions JSTests/microbenchmarks/get-by-val-array-storage-sparse-hole.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py
// Hole/miss-dominated reads of a large sparse array (ArrayStorage mode with a sparse map). Every read
// hits an in-bounds hole that is absent from the sparse map, so the int-indexed GetByVal slow path
// (operationGetByValArrayStorageInt) must resolve it to undefined via the (sane) prototype chain.
function get(array, i)
{
return array[i];
}
noInline(get);

var maxIndex = 200000;
var step = 16;

var array = [];
for (var i = maxIndex - step; i >= 0; i -= step)
array[i] = i + 1;

var expectedPass = 0;
for (var i = 1; i < maxIndex; i += step) // i = 1, 17, 33, ... are all holes (never written).
++expectedPass;

var iterations = 400;
var holes = 0;
for (var iter = 0; iter < iterations; ++iter) {
for (var i = 1; i < maxIndex; i += step) {
if (get(array, i) === void 0)
++holes;
}
}

if (holes !== expectedPass * iterations)
throw "Error: bad hole count: " + holes;
31 changes: 31 additions & 0 deletions JSTests/microbenchmarks/get-by-val-array-storage-sparse.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//@ skip if $model == "Apple Watch Series 3" # added by mark-jsc-stress-test.py
// Hit-dominated reads of a large sparse array (ArrayStorage mode with a sparse map). Every read
// resolves through the int-indexed GetByVal slow path (operationGetByValArrayStorageInt) and finds
// its value in the sparse map.
function get(array, i)
{
return array[i];
}
noInline(get);

var maxIndex = 200000;
var step = 16; // 1/16 density (< 1/8) keeps the array in ArrayStorage with a sparse map.

var array = [];
// Descending writes: the first one is far beyond length, forcing ArrayStorage + sparse map.
for (var i = maxIndex - step; i >= 0; i -= step)
array[i] = i + 1;

var expectedPass = 0;
for (var i = 0; i < maxIndex; i += step)
expectedPass += i + 1;

var iterations = 800;
var sum = 0;
for (var iter = 0; iter < iterations; ++iter) {
for (var i = 0; i < maxIndex; i += step)
sum += get(array, i);
}

if (sum !== expectedPass * iterations)
throw "Error: bad sum: " + sum;
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//@ skip if $buildType == "debug"
//@ runDefault("--useConcurrentJIT=false", "--jitPolicyScale=0", "--maximumFunctionForCallInlineCandidateBytecodeCostForFTL=500")

let g = 0;
function restY(c, ...r) { g = c ? 1 : 2; return r; }
function h(c, ...r) { return r; }
function h2(...r) { return r; }
function sink() {
let out = [];
for (let i = 0; i < arguments.length; i++) out.push(arguments[i]);
return out;
}
noInline(sink);

function restX(c, ...rx) {
let arr = [...rx, ...restY(c, ...rx)];
let dummy = [0, 0, 0, 0, 0, 0, 0, h(50, 9.9, 8.8)];
return [sink.apply(null, arr), dummy];
}
for (let i = 0; i < 1000000; i++) restX(i & 1, 0.1, 0.2);

function makeSrc(k) {
return `
(function() {
function victim${k}(c1) {
let q = restX(c1, 0.1, 0.2);
let z = h2(7.7, 6.6);
return [q, z];
}
noInline(victim${k});
for (let i = 0; i < 1000000; i++) {
victim${k}(i & 1);
}
})()
`;
}

for (let k = 0; k < 30; k++) eval(makeSrc(k));
15 changes: 15 additions & 0 deletions JSTests/stress/array-indexof-ensure-still-alive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
//@ runDefault("--useFTLJIT=1", "--jitPolicyScale=0.1", "--useConcurrentJIT=0", "--useConcurrentGC=0", "--sweepSynchronously=1", "--collectContinuously=1")

function opt(s, needle) {
return [s + "A", s + "B", s + "C", s + "D", s + "E", s + "F", s + "G", s + "H"].indexOf(needle);
}
noInline(opt);

let big = "Q".repeat(1024 * 1024);
let needleStr = "Z".repeat(big.length + 1);

for (let i = 0; i < 2000; i++)
opt(big, (i & 1) ? needleStr : 1234);

for (let i = 0; i < 10000; i++)
opt(big, needleStr);
87 changes: 87 additions & 0 deletions JSTests/stress/dfg-ensure-absence-cached-dictionary-then.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
function createObject1() {
const tmp = {
toJSON: 1,
a: 1,
};

Object.create(tmp);

return tmp;
}

function createObject2() {
const tmp = {
b: 1,
toJSON: {}
};

Object.create(tmp);

return tmp;
}

function opt(container1, object2, array, thenable, flags) {
const promise = new Promise(() => {});

container1.x;
thenable.x;

const object1 = Object.getPrototypeOf(container1);

let tmp = object1;
object1.a;

if (flags & 1) {
tmp = object2;
tmp.b;

0[0];
}

+tmp.toJSON;
+tmp.toJSON;

array[0];
Promise.resolve(+tmp.toJSON === 1 ? thenable : promise);

array[0] = 2.3023e-320;
}

function main() {
noDFG(main);

const object1 = createObject1();
const object2 = createObject2();

createObject1().z = 1;

const container1 = Object.create(object1);

const thenable = {
x: 1
};

for (let i = 0; i < 100; i++) {
thenable['a' + i] = 1;
}

const array = {
0: 1.1
};

JSON.stringify(container1);

for (let i = 0; i < 200; i++) {
opt(container1, object2, array, thenable, i);
}

thenable.__defineGetter__('then', () => {
array[0] = {};
});

opt(container1, object2, array, thenable, 0);

array[0].x;
}

main();
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
//@ runDefault("--useConcurrentJIT=false", "--jitPolicyScale=0.1", "--useConcurrentGC=false", "--verifyGC=true", "--gcMaxHeapSize=500000")

var g_value = {};

function makeObj() { return {}; }

function foo(cond) {
let a = makeObj();
a.p1 = 1;
a.p2 = 1;
a.p3 = 1;
a.p4 = 1;
a.p5 = 1;
if (cond)
a.y = 1;
else
a.z = 1;
a.x = g_value;
return a;
}
noInline(foo);

for (let i = 0; i < testLoopCount; ++i) {
g_value = {};
foo(i & 1);
}

var holder = new Array(100000).fill(null);
fullGC();

for (let i = 0; i < testLoopCount * 10; ++i)
holder[i % 100000] = foo(i & 1);
25 changes: 25 additions & 0 deletions JSTests/stress/regexp-many-non-greedy-paren-groups.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Test that regular expressions with many sequential non-greedy quantified
// parenthesized groups produce correct results at various sizes.

function testLargeNonGreedyParens(n) {
let s = '(?:a){0,2}?'.repeat(n);

let r = new RegExp(s);

let result = 'aaa'.match(r);
if (result === null)
throw new Error("Expected match for n=" + n);
if (result.index !== 0)
throw new Error("Expected index 0 for n=" + n + ", got " + result.index);

let replaced = 'a'.replace(r, 'x');
if (typeof replaced !== 'string')
throw new Error("replace failed for n=" + n);
}

testLargeNonGreedyParens(10);
testLargeNonGreedyParens(100);
testLargeNonGreedyParens(1000);
testLargeNonGreedyParens(2000);
testLargeNonGreedyParens(4000);
testLargeNonGreedyParens(8193);
25 changes: 25 additions & 0 deletions JSTests/stress/regress-174630697.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const icCount = 100;
const structCount = 16;

let body = "var x = 0;\n";
for (let i = 0; i < icCount; i++)
body += "x += o.p;\n";
body += "return x;\n";

let objs = [];
for (let i = 0; i < structCount; i++) {
let o = {};
o["k" + i] = i;
o.p = 1;
objs.push(o);
}

let f = new Function("o", body);

for (let j = 0; j < 130; j++)
f(objs[j % structCount]);

for (let j = 0; j < 100000; j++)
f(objs[j % structCount]);

f(42);
34 changes: 34 additions & 0 deletions JSTests/stress/slowputarraystorage-stale-structure-bit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
Object.defineProperty(Object.prototype, 0, { get() {}, configurable: true });
delete Object.prototype[0];
let target = [1, 2, 3];
Object.defineProperty(target, "length", { writable: false });

let proxyGet = new Proxy(target, {
get: (t, k) => k === "length" ? 999 : t[k]
});

try {
let lengthLie = proxyGet.length;
if (lengthLie === 999) {
throw "\"get\" trap successfully returned a lying value (999) for a non-configurable, non-writable property!";
}
} catch (e) {
if (!(e instanceof TypeError)) {
throw "Expected TypeError for \"get\" trap invariant violation, got: " + e;
}
Comment on lines +10 to +18

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fail when the invariant check does not throw.

Both blocks currently pass if the engine skips the proxy trap path and returns the ordinary target result instead of throwing. That makes this regression test too weak for the stale-structure bug it is trying to pin down.

Suggested fix
 try {
-    let lengthLie = proxyGet.length;
-    if (lengthLie === 999) {
-        throw "\"get\" trap successfully returned a lying value (999) for a non-configurable, non-writable property!";
-    }
+    proxyGet.length;
+    throw "Expected TypeError for \"get\" trap invariant violation, but no exception was thrown";
 } catch (e) {
     if (!(e instanceof TypeError)) {
         throw "Expected TypeError for \"get\" trap invariant violation, got: " + e;
     }
 }
@@
 try {
-    let setSuccess = Reflect.set(proxySet, "length", 999);
-    if (setSuccess === true && target.length !== 999) {
-        throw "Reflect.set returned true claiming success on a non-configurable, non-writable property!";
-    }
+    Reflect.set(proxySet, "length", 999);
+    throw "Expected TypeError for \"set\" trap invariant violation, but no exception was thrown";
 } catch (e) {
     if (!(e instanceof TypeError)) {
         throw "Expected TypeError for \"set\" trap invariant violation, got: " + e;
     }
 }

Also applies to: 25-33

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@JSTests/stress/slowputarraystorage-stale-structure-bit.js` around lines 10 -
18, The proxy invariant test around proxyGet.length is too weak because it still
passes when no TypeError is thrown and the ordinary target value is returned.
Update the try/catch blocks to explicitly fail when the invariant violation does
not throw, using the existing proxyGet.length check and the TypeError validation
so the stale-structure regression only passes when the engine actually raises
the expected error.

}

let proxySet = new Proxy(target, {
set: (t, k, v) => true
});

try {
let setSuccess = Reflect.set(proxySet, "length", 999);
if (setSuccess === true && target.length !== 999) {
throw "Reflect.set returned true claiming success on a non-configurable, non-writable property!";
}
} catch (e) {
if (!(e instanceof TypeError)) {
throw "Expected TypeError for \"set\" trap invariant violation, got: " + e;
}
}
6 changes: 6 additions & 0 deletions JSTests/stress/spread-with-OnlyAtomStringsStructure.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//@ runDefault("--forceEagerCompilation=1", "--validateAbstractInterpreterState=1")

const array = [""];

for (let index = 0; index < testLoopCount; index++)
(() => {})(...array);
47 changes: 47 additions & 0 deletions JSTests/stress/typedarray-from-oob.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
function testResize(ctor, bytesPerElement, initialBytes, shrinkBytes, resizeAt) {
const newCount = shrinkBytes / bytesPerElement;
const resizableArrayBuffer = new ArrayBuffer(initialBytes, { maxByteLength: initialBytes * 4 });
const source = new ctor(resizableArrayBuffer);
source[Symbol.iterator] = null;

let callbacks = 0;
ctor.from(source, (val, index) => {
if (index === resizeAt)
resizableArrayBuffer.resize(shrinkBytes);
callbacks++;
return val;
});

const expected = Math.max(resizeAt + 1, newCount);
if (callbacks > expected)
throw new Error(ctor.name + ": " + callbacks + " callbacks (expected <= " + expected + ")");
}

function testDetach(detachAt) {
const arrayBuffer = new ArrayBuffer(256);
const source = new Int32Array(arrayBuffer);
source[Symbol.iterator] = null;

let callbacks = 0;
try {
Int32Array.from(source, (val, index) => {
if (index === detachAt)
arrayBuffer.transfer();
callbacks++;
return val;
});
} catch (e) {
return;
}
Comment on lines +26 to +35

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Don't swallow unexpected exceptions in the detach regression.

This catch makes the test pass even when Int32Array.from() fails before the buffer is actually detached, so unrelated breakage can silently slip through.

Suggested fix
     let callbacks = 0;
+    let didDetach = false;
     try {
         Int32Array.from(source, (val, index) => {
-            if (index === detachAt)
+            if (index === detachAt) {
                 arrayBuffer.transfer();
+                didDetach = true;
+            }
             callbacks++;
             return val;
         });
     } catch (e) {
-        return;
+        if (didDetach)
+            return;
+        throw e;
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try {
Int32Array.from(source, (val, index) => {
if (index === detachAt)
arrayBuffer.transfer();
callbacks++;
return val;
});
} catch (e) {
return;
}
let callbacks = 0;
let didDetach = false;
try {
Int32Array.from(source, (val, index) => {
if (index === detachAt) {
arrayBuffer.transfer();
didDetach = true;
}
callbacks++;
return val;
});
} catch (e) {
if (didDetach)
return;
throw e;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@JSTests/stress/typedarray-from-oob.js` around lines 26 - 35, The try/catch
around Int32Array.from in typedarray-from-oob.js is swallowing all failures,
which can hide unrelated regressions before the buffer is actually detached.
Narrow the handling so only the expected detach-related exception path is
accepted, and let any other exception escape or fail the test explicitly; keep
the test logic around the Int32Array.from callback, arrayBuffer.transfer, and
callbacks count intact while making unexpected errors visible.


if (callbacks > detachAt + 1)
throw new Error("detach: " + callbacks + " callbacks (expected <= " + (detachAt + 1) + ")");
}

testResize(Int32Array, 4, 4096, 16, 4);
testResize(Int32Array, 4, 4096, 8, 8);
testResize(Float64Array, 8, 8192, 32, 8);
testResize(Uint8Array, 1, 1024, 4, 8);
testResize(Int32Array, 4, 4096, 8, 0);
testDetach(4);
testDetach(0);
Loading
Loading