Ask an exotic global prototype for a bare identifier through [[Get]] - #2946
Merged
Merged
Conversation
GlobalEnvironment's identifier lane resolved the global's direct prototype with TryGetOwnPropertyValue, whose base body is [[GetOwnProperty]]. For a Proxy that fires the getOwnPropertyDescriptor trap and never get, so a name the handler only produces from its get trap resolved to nothing - while HasBinding, a real [[HasProperty]] chain walk, had already said the binding exists. A host object that synthesises a value in Get has the same shape and was answered the same way. Reading the identical name two levels down worked, because the deeper levels were already spec-shaped [[HasProperty]] + [[Get]]. The direct prototype now takes that same pair whenever it carries InternalTypes.ExoticGet - the flag behind PropertyAccessSemantics.Exotic, which the exotic built-ins state outright and which the engine derives for a host type that overrides Get. Everything else keeps the shortcut and the reason it exists: a host prototype answering from its own state without building a descriptor it would only throw away. The ordinary path gains one test on a field it already loads. test262's staging/sm/Proxy/global-receiver.js is the specification for this and now passes (gets 1, sets 1, both receivers the global). It is not in our generated suite - the harness generates annexB, built-ins, intl402 and language only - so it is pinned from the embedder's side instead, together with the host-object shape the flag covers and the ordinary prototypes that must keep the short path. The write lane needed nothing: SetFromMutableBinding already routed an inherited name through [[HasProperty]] + [[Set]] with the global as receiver. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lahma
added a commit
that referenced
this pull request
Aug 15, 2026
* Run test262's staging/ directory too We generate annexB, built-ins, intl402 and language and have never generated staging/, and the reason was never a decision: Test262Harness.Console's settings file had no way to name the set. Test262StreamOptions.SubDirectories existed, EnumerateTestFiles already recursed and TestSuiteGenerator already iterated the option -- but TestSuiteGeneratorOptions had no matching property and the console's configureOptions lambda set only the loggers, so the stream kept the built-in default whatever the settings file said. lahma/test262-harness-dotnet#173 binds the three together; this bumps to the 1.1.2 that carries it and opts in. It is worth having because staging/ carries coverage that exists nowhere else in the tree we already pin. Both defects fixed in 4.16.0 have their only upstream test there: - staging/sm/Proxy/global-receiver.js asserts the receiver a Proxy sees when it is the global's prototype -- the [[Get]] defect fixed in #2946. - staging/sm/global/parseInt-01.js asserts parseInt("-0x10", 16) === -16 and that parseInt("-0", 10) is -0 -- both fixed in #2945. All 55 files under built-ins/parseInt/ use unsigned hex, so neither was reachable for us. Both pass. The SpiderMonkey ports include their helpers as "sm/non262-Set-shell.js" from harness/sm/, but Test262Stream.GetHarnessFiles() enumerates only the top level of harness/, so TestHarness now walks the tree itself and keys State.Sources on the path relative to harness/. A top-level file's relative path is its file name, so every existing include resolves byte-identically -- which the run proves: all 99,901 pre-existing cases still pass. 99,901 -> 102,664 generated cases; 2m48s -> 3m00s. 131 of the 1,483 new files are excluded, grouped under a banner with a prose reason each: the ones that hang or exhaust memory, and the conformance gaps the SpiderMonkey suite reaches that the stable directories do not (cross-realm error identity, legacy Function.caller, Annex B block-scoped function hoisting, Set-method operation order, Math and Number precision, function source text, ...). Four pre-existing language/ tests join the _slowTestFiles list: they eval() a regexp literal per code unit and the extra parallel load pushes them past the 30-second wall clock, though the whole group still runs in 6 seconds on its own. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Re-run CI now that Test262Harness.Console 1.1.2 is published The previous run failed only on 'Version 1.1.2 of package test262harness.console is not found in NuGet feeds' - the tool was tagged but had not propagated yet. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
GlobalEnvironment.TryGetFromGlobalPrototyperesolved the direct prototype withTryGetOwnPropertyValue— that is[[GetOwnProperty]], so aProxyinstalled as the global's prototype saw itsgetOwnPropertyDescriptortrap and never itsget. Levels two and deeper were already spec-shaped (HasProperty+Get(name, global)), so the defect was exactly one level deep — and it madeHasBindingand the value read contradict each other:Pre-existing, but aggravated by #2928: before it,
typeofalso answered"undefined", so the engine was at least self-consistent. Now it reports the binding exists and the read throws.test262 covers this and we do not run it.
test/staging/sm/Proxy/global-receiver.jsasserts the global is the receiver handed to a Proxy'sgetandsettraps when the Proxy is the global's prototype. Run by hand through the REPL: before,ReferenceError: bareword is not definedat the first assertion; after,PASS gets=1 sets=1. The harness emits onlyannexB,built-ins,intl402andlanguage, sostaging/never reaches the suite. It is now pinned in-repo asExoticGlobalPrototypeTests.Test262StagingGlobalReceiver.The gate is
InternalTypes.ExoticGet— the bit behindPropertyAccessSemantics.Exotic— not ais JsProxytype test, so a host object that overridesGetgets the same answer, and one that overridesGetbut declaresOrdinarykeeps the shortcut, which is exactly what that declaration promises. Level 1 and levels 2+ now share one body.The shortcut is kept for ordinary prototypes because it is load-bearing: it lets a host prototype answer without building a descriptor it would throw away. An ordinary prototype now additionally executes a load of
prototype._type, anANDwith a constant and a not-taken branch — a same-cache-line load feeding a predictable branch, on a method that is alreadyNoInliningand is reached only after the global's own lookup and its shape lookup have both missed. No new call, no new allocation, no change in virtual dispatch count.8 new tests, 4 red on
mainon both net10.0 and net472. The 4 that passed cold were the set-trap and level-2 cases, isolating the defect. Verification leg green.🤖 Generated with Claude Code