Run test262's staging/ directory too - #3016
Merged
Merged
Conversation
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 sebastienros#2946. - staging/sm/global/parseInt-01.js asserts parseInt("-0x10", 16) === -16 and that parseInt("-0", 10) is -0 -- both fixed in sebastienros#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>
This was referenced Aug 14, 2026
lahma
marked this pull request as ready for review
August 15, 2026 07:27
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>
lahma
added a commit
to lahma/jint
that referenced
this pull request
Aug 15, 2026
sebastienros#3016 landed the staging/ directory while this branch was still open, so it had to park the file this issue was found through. The fix is here, so the exclusion goes: 102,324 passed / 0 failed with it removed, and the file itself passes in both strict and sloppy mode. It is the upstream coverage for exactly this defect - a substitution whose result exceeds the maximum string length - and it is the reason the issue could be written with a reproduction at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lahma
added a commit
that referenced
this pull request
Aug 15, 2026
…ent (#3015) * Give JavaScript strings a maximum length instead of a wrapped array rent ValueStringBuilder.Grow computed its required size (_pos + additionalCapacityBeyondPos) as an unchecked int. Past 2^31 characters that wraps negative, the (uint) -> Math.Max -> (int) round-trip carries the wrapped value through, and ArrayPool<char>.Shared.Rent(-2147483648) throws an ArgumentOutOfRangeException that escapes Evaluate past every catch in the script. The ClrLimits.MaxArrayLength cap in the same expression bounds only the doubling term, never the required size. Adopt V8's limit, (1 << 29) - 24 = 536,870,888 characters, as JsString.MaxLength and guard the paths that build a string from JavaScript with a catchable RangeError: Invalid string length. repeat and padStart/padEnd move from the CLR array ceiling to it; GetSubstitution, the @@replace accumulator, replace, replaceAll, join, toLocaleString, String.raw, String.prototype.concat, '+'/'+=' and template literals gain one they never had. Grow itself stays realm-free - it also backs the JSON serializer, URI encoding and the Intl/Temporal formatters - and only stops lying about the size. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Measure the receiver's length from inside Append, not at the call site The length guard read jsString.Length before calling Append. JsString.Length is virtual and ConcatenatedString overrides it with a two-branch null coalesce, so every `s += t` paid a dispatch it had never paid before - the pre-fix path called Append(rprim) and let the override do the coercion internally, reading no length at all. It showed up in the gate. Against ff980b7, three string rows regressed in both of two pairs: Dromaeo ObjectString [Modern=True&Prepared=True] +7.50/+1.80, SunSpider string-base64 +2.22/+1.25 and string-fasta +1.31/+2.64. SunSpider's string-base64 and string-fasta are that loop and almost nothing else. Both Append overrides already hold the field that answers the question - the base calls ToString() anyway, and ConcatenatedString reads _stringBuilder or _value on the very next line - so moving the check inside costs an add and a compare, no dispatch. The realm becomes a parameter, which is two field loads in place of a virtual call. StringPrototype.Concat drops its own pre-check for the same reason. Re-measured over five pairs: string-fasta -0.64% median, string-base64 +0.34%, 3d-raytrace -0.72%, ObjectString back to noise. No string row regresses. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Run staging/sm/String/replace-math.js now that it passes #3016 landed the staging/ directory while this branch was still open, so it had to park the file this issue was found through. The fix is here, so the exclusion goes: 102,324 passed / 0 failed with it removed, and the file itself passes in both strict and sloppy mode. It is the upstream coverage for exactly this defect - a substitution whose result exceeds the maximum string length - and it is the reason the issue could be written with a reproduction at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lahma
added a commit
to lahma/jint
that referenced
this pull request
Aug 15, 2026
…lready fixed comment saying the fix for sebastienros#3010 removes the entry. That fix merged first (sebastienros#3014, 2026-08-14), sebastienros#3016 merged after it, and nothing went back to delete the now-stale exclusion - so a test that passes has been skipped ever since. It asserts the absence of 28 members the Temporal proposal removed, five of which sebastienros#3014 dropped and the rest of which Jint never had. Both modes pass: Passed Temporal("staging/Temporal/removed-methods.js",False) Passed Temporal("staging/Temporal/removed-methods.js",True) Full suite with the entry gone: 102,324 passed, 0 failed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
lahma
added a commit
that referenced
this pull request
Aug 15, 2026
…#3023) comment saying the fix for #3010 removes the entry. That fix merged first (#3014, 2026-08-14), #3016 merged after it, and nothing went back to delete the now-stale exclusion - so a test that passes has been skipped ever since. It asserts the absence of 28 members the Temporal proposal removed, five of which #3014 dropped and the rest of which Jint never had. Both modes pass: Passed Temporal("staging/Temporal/removed-methods.js",False) Passed Temporal("staging/Temporal/removed-methods.js",True) Full suite with the entry gone: 102,324 passed, 0 failed. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Aug 23, 2026
legrab
added a commit
to legrab/pocok
that referenced
this pull request
Aug 25, 2026
Updated [Jint](https://github.com/sebastienros/jint) from 4.16.0 to 4.16.1. <details> <summary>Release notes</summary> _Sourced from [Jint's releases](https://github.com/sebastienros/jint/releases)._ ## 4.16.1 Jint 4.16.1 is the **first release from the new `4.x` maintenance branch**, and it marks the point where the two lines separate: `main` is now **5.0.0 development**, and `4.x` is where the 4.16.x line continues. **What that means for you.** If you are on 4.16.0, this is a drop-in update — it is correctness and conformance work only, **no API change and no changed default**. Every public signature is the same one 4.16.0 shipped, on all five target frameworks. If you want the 4.x line, take it from `4.x` and expect fixes rather than features. If you want to follow where the engine is going, watch `main` — v5 brings breaking API changes, an opt-in WHATWG web API surface, Web Workers, Node compatibility and a raised .NET Framework floor, and every one of them is recorded as it lands in [`docs/v5-migration.md`](https://github.com/sebastienros/jint/blob/main/docs/v5-migration.md). From this release onward the 4.x public surface is snapshotted per target framework in `Jint.Tests.PublicInterface/Verify/`, so "did the API move?" is a diff rather than a judgement call — on this branch a diff there is a bug, and comparing those files against `main`'s is the v4→v5 delta. ### Highlights **Conformance, from a suite that now runs more of test262.** The `staging/` directory is generated and executed for the first time (#3016), which is roughly 2,800 additional cases — largely SpiderMonkey's own suite contributed upstream, covering behaviour the stable directories never reach. Much of the work below is what it found. **Built-ins do what the spec says, step by step.** The array built-ins perform the internal methods they name rather than equivalents (#3066); `Array.from` honours `IsConstructor` and a typed array's `length` write throws (#3043); an array truncation walks downwards and the generics report the writes they fail (#3072); argument validation and evaluation order are corrected in five built-ins (#3069); `Map` and `Set` get the `[[SetData]]` tombstone their traversals are specified over (#3073); `Date.prototype.setTime` stores the clipped time value (#3042); and `Array.prototype.values`/`keys`/`entries` no longer gate on an array-like receiver (#3236). **Iterators and control flow.** A throw from the iterator step no longer closes the iterator (#3047); the `done` flag is consulted before stepping again (#3048); a rejected `return()` propagates out of an abandoned `for await` loop (#3113); an optional-chain short circuit is distinguished from a genuine `undefined` (#3040); a computed property key is evaluated even when spelled as a literal (#3039) and survives an `await` or `yield` intact (#3144, #3150); and destructuring the rest of an exhausted array yields an empty array rather than 2³² elements (#3263). **Numeric and string accuracy.** `Math.acosh`, `asinh`, `atanh`, `cbrt`, `expm1` and `log1p` are ported from fdlibm for correctly-rounded results across every target framework (#3050); `toFixed` formats from the double's exact value and reads `this` from `[[NumberData]]` (#3071); `String.prototype` case conversion derives from Jint's own Unicode tables rather than the host's culture data (#3068); and the regex engine is chosen per subject, with `RegExp.prototype.replace` no longer rewriting `lastIndex` (#3070). **Bounds that hold.** JavaScript strings have a maximum length instead of a wrapped array rent (#3015); a JSON document too long to become a string is refused while it is being built (#3028); a frame displaced by a proper tail call keeps counting while its trampoline runs, so `MaxRecursionDepth` cannot be evaded by leaving and re-entering the trampoline (#3022); and an `Atomics` waiter is released when nothing can ever notify it again (#3029). **Error messages no longer run user JavaScript** (#3041) — rendering a message for a value with a script-supplied `toString` used to invoke it, from inside the failure path. **Internationalization.** The five Temporal members the proposal removed are dropped (#3014), and `u`-extension options are canonicalized with every date format the spec allows (#3018). Two fixes in this release come from **@svenrog** — a sloppy function answering its own `arguments` (#3061) and the outer link on a parked `Function`-constructor environment (#3063). ## What's Changed * Drop the five Temporal members the proposal removed by @lahma in sebastienros/jint#3014 * Canonicalize u-extension options and format every date the spec allows by @lahma in sebastienros/jint#3018 * Mark a global created by an unresolvable assignment, and stop a waitAsync timeout outliving its engine by @lahma in sebastienros/jint#3019 * Run test262's staging/ directory too by @lahma in sebastienros/jint#3016 * Give JavaScript strings a maximum length instead of a wrapped array rent by @lahma in sebastienros/jint#3015 * Let a for-of frame decline the unwind it can only rethrow by @lahma in sebastienros/jint#3017 * Keep counting a frame a tail call replaced while its trampoline runs by @lahma in sebastienros/jint#3022 * Unpark staging/Temporal/removed-methods.js, which #3014 already fixed by @lahma in sebastienros/jint#3023 * Drop the Islamic date conversions no calendar path reaches by @lahma in sebastienros/jint#3027 * Let an Atomics waiter go when nothing can ever notify it again by @lahma in sebastienros/jint#3029 * Refuse a JSON document too long to be a string while it is being built by @lahma in sebastienros/jint#3028 * Bump the microsoft group with 3 updates by @dependabot[bot] in sebastienros/jint#3033 * Bump the analyzers group with 1 update by @dependabot[bot] in sebastienros/jint#3031 * Add initial threat model for untrusted scripts by @sebastienros in sebastienros/jint#3030 * Stop ClassBenchmark rebuilding its engine per iteration by @lahma in sebastienros/jint#3053 * createRealm installs a full $262 on the new realm and returns it by @lahma in sebastienros/jint#3044 * Give the benchmark suite a measurement environment by @lahma in sebastienros/jint#3055 * Evaluate a computed property key even when it is spelled as a literal by @lahma in sebastienros/jint#3039 * Stop error messages from running user JavaScript by @lahma in sebastienros/jint#3041 * Array.from honours IsConstructor, and a typed array's length write throws by @lahma in sebastienros/jint#3043 * Consult the iterator's done flag before stepping it again by @lahma in sebastienros/jint#3048 * Date.prototype.setTime must store the clipped time value by @lahma in sebastienros/jint#3042 * Answer a sloppy function's own arguments instead of throwing by @svenrog in sebastienros/jint#3061 * Keep the outer link on a parked Function-constructor environment by @svenrog in sebastienros/jint#3063 * A throw from the iterator step must not close the iterator by @lahma in sebastienros/jint#3047 ... (truncated) Commits viewable in [compare view](sebastienros/jint@v4.16.0...v4.16.1). </details> [](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself) </details>
This was referenced Aug 26, 2026
This was referenced Aug 30, 2026
This was referenced Sep 6, 2026
This was referenced Sep 13, 2026
This was referenced Sep 20, 2026
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.
Why staging/ was missing, and the one-line reason
We generate
annexB,built-ins,intl402andlanguage.staging/has never been generated, andExcludedDirectoriesis empty — so nobody ever decided to leave it out. The exclusion was structural:Test262Harness.Console's settings file simply had no way to name the set.Three of the four pieces were already in the tool:
Test262StreamOptions.SubDirectoriesexisted, defaulting to those four.Test262Stream.EnumerateTestFilesalready recursed (SearchOption.AllDirectories), so a deeper tree needs nothing new.TestSuiteGenerator.Generatealready iteratedstream.Options.SubDirectories.What was missing was the binding:
TestSuiteGeneratorOptions— which is whatTest262Harness.settings.jsondeserializes into — had noSubDirectoriesproperty, andGenerateCommand'sconfigureOptionslambda set onlyLogInfo/LogError, so the stream kept its built-in default whatever the settings file said. lahma/test262-harness-dotnet#173 adds the property and assigns it; this PR bumps to the 1.1.2 that carries it and opts in with one array entry.What it buys: both defects fixed in 4.16.0 have their only upstream test there
staging/sm/Proxy/global-receiver.js— installs aProxyas the global object's[[Prototype]]and asserts theget/settraps receive the global itself as the receiver. That is the defect fixed in Ask an exotic global prototype for a bare identifier through [[Get]] #2946.staging/sm/global/parseInt-01.js— assertsparseInt("-0x10", 16) === -16(line 117) and thatparseInt("-0", 10)is-0(line 60). Both were fixed in Strip the sign before testing parseInt's argument for a hex prefix #2945, and neither assertion is reachable anywhere else in the suite: all 55 files underbuilt-ins/parseInt/use unsigned hex.Both pass, in both modes:
Cost
dotnet testdurationstaging/is 1,483 non-fixture files — 1,409 of them undersm/(SpiderMonkey's own suite, contributed upstream), the restexplicit-resource-management(53),built-ins(8),top-level-await(4),source-phase-imports(4),decorators(3),set-methods(3),Temporal(2),Uint8Array(1), plus 4 at the top level. 131 are excluded, 1,352 pass — a 91% pass rate for a directory that has never been run.The harness-file change
Test262Stream.GetHarnessFiles()enumerates only the top level ofharness/, and anincludes:entry is looked up by the exact string the test's frontmatter wrote. The SpiderMonkey ports writeincludes: [sm/non262-Set-shell.js, ...], and those 11 helpers live inharness/sm/. SoTestHarness.csnow enumerates the whole tree offState.Test262Stream.Options.FileSystemand keysState.Sourceson the path relative toharness/.A top-level file's relative path is just its file name, so every pre-existing include resolves byte-identically — and the run proves that rather than merely asserting it: all 99,901 pre-existing cases still pass, including the 32 top-level harness scripts every one of them loads.
Exclusions
All 131 are under
staging/, grouped under a// === STAGING EXCLUSIONS ===banner with a prose reason per group, matching the file's existingintl402convention. Every entry is commented with what removes it.Blocked on a sibling PR (2) — see merge order below
staging/Temporal/removed-methods.jsstaging/sm/String/replace-math.jsreplaceresult must raiseRangeError; today the length overflows toint.MinValueand surfaces asArgumentOutOfRangeExceptionout of the BCL — removed by the fix for #3011Hangs, or exhausts the machine (20)
A test that hangs or OOMs is worse than one that fails, so these are excluded rather than left red.
staging/sm/extensions/recursion.jsis the sharpest: it recurses without bound, and since Jint's defaultMaxRecursionDepthis-1the CLR stack overflows and takes the entire test host with it, every other test in the process included.staging/sm/extensions/recursion.js,staging/sm/Array/to-length.js({length: Infinity}array generics), the eightstaging/sm/Date/dst-offset-caching-*-of-8.js(which additionally drive multi-GB allocation),staging/sm/generators/delegating-yield-9.js,staging/sm/regress/regress-610026.js,staging/sm/regress/regress-619003-1.js— and, found by running the suite,staging/sm/Function/has-instance-jitted.js,staging/sm/JSON/parse-mega-huge-array.js,staging/sm/RegExp/unicode-braced.js,staging/sm/RegExp/unicode-class-braced.js,staging/sm/RegExp/unicode-ignoreCase.js,staging/sm/expressions/nullish-coalescing.js,staging/sm/regress/regress-1507322-deep-weakmap.js. Each burns the whole 30-second budget, twice over (both modes), and together they starved the run badly enough to time out unrelated tests elsewhere in the suite.Conformance gaps the stable directories never reach (109)
$262.createRealm()works, but an error raised while running another realm's function is constructed from the current realm's intrinsics, soe instanceof otherGlobal.TypeErroris false. The created realm's global also carries no$262of its own, sootherGlobal.$262.detachArrayBufferis undefinedFunction.prototype.caller/arguments.callee.callernullat the top of the stack, poisoned on strict functions, transparent throughevalframes — is not reproducedthisor indextoSourceextension, which Jint does not implement at all — that half is removed by the test moving, not by Jint changingGetSetRecordreadssize, thenhas, thenkeys, and coercessizeexactly once; Jint's order and coercion count differIteratorCloseArray.from, theMap/Setconstructors,for-ofand array destructuringlastIndexand case-insensitive matchingSymbol.match/Symbol.replace/matchAlllastIndexbookkeeping (including-0and the per-iterationToLengthrecomputation), and matching across the Latin-1 boundarysuper()inside an arrow inside a direct eval in a derived constructor, a duplicate destructuring binding, a strict-mode legacy octal literal,yieldas an identifier, a field initializer's TDZacosh/asinh/atanh/cbrt/expm1/log1pdelegate to the BCL, which differs in the last few ULPs and flushes1e-300to zeroTimeClipdoes not reject every out-of-range value, andSymbol.toPrimitivethrows a non-objectFunction.prototype.toStringdoes not return the original source for class expressions and some method forms, and NamedEvaluation does not reach every position the spec names[[DefineOwnProperty]]and generics orderinglengthpast a non-configurable sparse element stops at the wrong index,sort/unshiftobserve the wrong element sequence, and the strict-mode generics do not report a failed writeNumberconversion and formattingtoFixed/toPrecisionlose the exact mathematical value for extreme magnitudes and subnormals, andToPrimitiveon aNumberwrapper consults the wrong methoddefinePropertyinvariant check of Jint's own that fires where it should notArray.fromapplied to an arbitrary constructorArrayCreatebranch, andCreateDataPropertyOrThrowon a read-only element or a non-extensible targetargumentsimport sourceof a JavaScript module is refused outright and theAbstractModuleSourceprototype chain differsIterator.from'snext()result validation, theMapconstructor's per-entry type check,Symbol.keyForover a cross-realm registry, and a module namespace re-exported under a string nameOne pre-existing fragility this exposed
Four
language/literals/regexp/S7.8.5_*_T2.jstests join the existing_slowTestFileslist inTest262Test.cs. They loop0x0000..0xFFFFcallingeval()on a fresh regexp literal per code unit, so every iteration is a parse. The wholeLiterals_regexpgroup still runs in 6 seconds on its own; these four only exceed the 30-second wall clock once staging adds ~2,800 cases to the parallel run. That is CPU starvation, not the engine getting slower — which is exactly what that list's comment already anticipates for thedecodeURIbyte-range tests sitting next to them.Merge order
This PR must merge after both of:
staging/Temporal/removed-methods.jsis redString.prototype.replacelength overflow) — otherwisestaging/sm/String/replace-math.jsis redBoth are excluded here with the issue number named in the comment, so whichever lands first, the follow-up is a two-line deletion. And the whole thing stays a draft until
Test262Harness.Console1.1.2 is on nuget.org (lahma/test262-harness-dotnet#173).Closes #3008
🤖 Generated with Claude Code