Repository navigation
Conversation
…ut `configurable` Three tests beside "what a file defines without `configurable` is undone too". They pass once the WebKit that Bun builds against deletes such a key in VM::DeletePropertyMode::IgnoreConfigurable.
A compiled run refuses an index key on a built-in prototype (TS100014), so the first two files of that test fail under --aot. The warm-up loop of the compiled-code test stops at 1000 rounds.
Collaborator
Author
|
Updated 3:54 PM PT - Nov 11th, 2026
❌ @robobun, your commit 5b8328a has 1 failures in
🧪 To try this PR locally: bunx bun-pr 48630That installs a local version of the PR into your bun-48630 --bun |
Collaborator
Author
|
Status Reproduced on a debug build of main: The fix is oven-sh/WebKit#1039. This PR holds the tests and waits for that change in Bun's WebKit. |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Needs oven-sh/WebKit#1039 in Bun's WebKit. The new tests fail until then.
Problem
bun test --isolate=modules, an index key that a test file defines on a built-in withoutconfigurable: truestays for the later files:[][7]readsfake. OnArray.prototypethe file's other changes stay too.restoreProperties()(src/js/internal/test/globals.ts:122) deletes the key throughjsFunctionDeleteOwnProperty(src/jsc/bindings/TestEnvironment.cpp:139), in JavaScriptCore'sIgnoreConfigurablemode.JSObject::deletePropertyByIndex()does not read that mode and returns false.Fix
test/cli/test/isolation.test.tsand changes no Bun source.test/aot/runner-suites.known.txt: a compiled run refuses an index key on a built-in prototype (TS100014).Background
--isolate=modules(bun test: Vitest compatibility #44833, in no release) keeps one global object for all test files. Between files,globals.tsputs the built-ins back from a snapshot and deletes each key that a file added.IgnoreConfigurableis JavaScriptCore's delete mode that also removes a property that is not configurable. For an index key it did nothing.TestEnvironment.cpp: from Bun, only a drop of all optimized code invalidates. In JavaScriptCore only code that depends on the object goes.Notes
Repro.
bun test --isolate=modules ./a.test.js ./b.test.js ./c.test.jsfake fake 1 8undefined 2 undefined 0Map.prototypefake 2 undefinedundefined 2 undefinedObject.prototype[0]:({})[0],[][0],"0" in {}trap trap trueundefined undefined falseObject.defineProperty(globalThis, "7", { value: "fake" }):globalThis[7],"7" in globalThisfake trueundefined falseWith
configurable: true, with the name key"seven", and with--isolate, main already prints the right column.Why
Array.prototypekeeps everything. The key makesArray.prototype.length8. The restore then setslengthback to 0, which throws while the element is there, andrestoreGlobals()catches the error for the whole object (globals.ts:187). With the element deleted first,lengthgoes back and the rest follows. Index keys come first inReflect.ownKeys().The three tests.
an index key that a file defines without configurable is undone too: file a defines a read-only key onArray.prototype(and replacesat, addszz),globalThis,Map.prototypeandString.prototype, a writable key onMath, and getters onDateandObject.prototype[0]. File b prints the clean state and defines all of them again with other values, which throws while a key of file a is there. File c prints the clean state.a preload defines an index key without configurable for every file: the preload runs again for each file and defines a getter onMath[7]. On main the second run throwsTypeError: Attempting to change the getter of an unconfigurable property.compiled code doesn't keep an index key that a file defined without configurable: a shared module hasfunction read() { return Math[7]; }. The second file defines the key and callsread()until the DFG has compiled it. The third file must readundefined, then defines the key with another value and must read that. With the key removed from the object and the code kept, it printsread b b. The first file only loads the module: code that is compiled while a function has one copy is dropped when the next file makes its copy.Results (debug ASAN build, main 447ff87, WebKit 264cf6db built from source with and without oven-sh/WebKit#1039)
read b b.bun test --isolate=modulesblock ofisolation.test.tswith the change: 19 of 20 pass.no other builtin module patches a global class when it loadsfails because its inner test takes 15 to 19 s against its limit of 5 s on this debug build. That test defines no index key.--aot(the preload oftest/aot/harness/children-under-aot.ts): the preload test and the compiled-code test pass. The first test fails, as the new line inrunner-suites.known.txtsays: the build warnsTS100014: this assignment throws if it runs: built-in objects are read-only in a compiled executablefor the keys onArray.prototype,Map.prototype,String.prototypeandObject.prototype.mock-fn.test.js(848 pass),spyMatchers.test.ts(150 pass, 3 todo) andcapture-stack-trace.test.js(76 pass): the same counts with and without the change. They are the tests of the other users ofIgnoreConfigurable.What it costs at run time. Nothing in Bun: 0 native lines, 0 host functions. The numbers for JavaScriptCore are in oven-sh/WebKit#1039. In short: a
deleteof an element runs the same instructions but for two cases (a configurable sparse element: 2 more, a refused delete: 27 more), and a restore that force-deletes a key makes one Structure and drops the optimized code that depends on that object (3 of 31 warmed functions forMath, 0 of 31 forObject.prototypeandglobalThis). In 60 test files that define no such key, the new function is never called.When this can merge. After oven-sh/WebKit#1039 is merged and
WEBKIT_VERSION(scripts/build/deps/webkit.ts) is at or past that commit. WebKit's main is past what Bun's main builds against, so this PR does not move the pin.Still carried over after this (none is new)
varor function declaration of a classic script:JSSymbolTableObject::deleteProperty()refuses it in every mode.Array.prototypekeeps itslength.haveABadTime). Only speed.Seen on the way, not part of this. On a debug ASAN build,
bun test --aotsometimes dies while it compiles the files of the first test (4 of 14 runs):SEGVinWTF::removeIteratorunderJSC::AOT::Typed::LinkFlow::findWhatSomeLaneWasGiven(aot/facts/AOTLinkFlow.cpp:2980). TheHashMapiterator of that function is destroyed after its lock is released. Only builds with hash table iterator checks have that list.