Skip to content

Interop: a params overload is chosen by the array's element type, and a failing element declines instead of throwing (#3764) - #3782

Merged
lahma merged 1 commit into
sebastienros:4.xfrom
lahma:backport/3746-params-array-overload
Sep 3, 2026
Merged

lahma merged 1 commit into
sebastienros:4.xfrom
lahma:backport/3746-params-array-overload

Conversation

@lahma

@lahma lahma commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Backports #3764 (main) to the 4.x maintenance branch. Both defects were confirmed present on 4.x by running the ported tests against unfixed code first.

The two defects

A. A JavaScript array short-circuited overload scoring above the converter probe. A params call bundles its trailing arguments into one JsArray before overload resolution runs, so InteropHelper.CalculateMethodParameterScore rated three candidates differing only in their element type — CDecimal[], CInteger[], CLong[] — with one rule, "is an array, wants an array", that answered a flat 2 for every one of them. The element type was never consulted, the converter probe below that rule (the #3407 fix, which 4.x already has) was never reached, and declaration order decided. Where the first-declared candidate happened to be convertible it answered silently and wrongly; where it was not, the conversion's InvalidCastException left through the embedder's Evaluate — invisible to a script catch and to a host catch (JavaScriptException) alike.

B. The composite branches of DefaultTypeConverter.TryConvert converted their parts through the public, throwing Convert. A List<T> or Collection<T> item, a T[] element, a target dictionary's value and a member of a POCO built from a dictionary all ignored the propagateException flag their own frame had been called with, so a method documented as returning false threw. That is not something the candidate loop in MethodInfoFunction.Call can move on from: it tries candidates in score order and declines its way to the next, and an exception ends the call rather than the candidate.

They are fixed together, because fixing A by asking the converter per element throws until B is fixed.

  • TryConvertPart routes all five composite sites through the flag their frame was given. It mirrors Convert — the virtual TryConvert first, so a subclass override still answers for the parts — so behaviour under propagateException: true is unchanged.
  • CalculateParameterTypeScore is the type-level core of the parameter score, so an element with no ParameterInfo of its own can be scored by the same rules. An array parameter now scores its base 2 plus its worst element, up to eight of them, and returns -1 on the first element that cannot bind at all. Element types any JsValue is assignable to — object, JsValue — are carved out and keep the flat base, or params object[] and params JsValue[] would rank below the scalar overload beside them.

Deliberately out of scope, exactly as on main: MethodDescriptor.Call's TypeReference constructor lane keeps its throwing Convert and gets no retry loop (correct selection is what repairs it), and an empty JS array against several params T[] overloads stays ambiguous and keeps today's answer.

Failing first

Both files were ported and run against unfixed 4.x before Jint/ was touched. Identical counts on both legs (net472, which exercises Jint's net462-compiled asset, and net10.0):

Suite Unfixed 4.x After
Jint.Tests.PublicInterface/HostArrayElementOverloadTests 8 failed / 3 passed of 11 11 passed
Jint.Tests/Runtime/CompositeConversionDeclineTests 5 failed / 6 passed of 11 11 passed

The three that passed unfixed in the first file are exactly the ones meant to: the empty-array pin (AnEmptyArrayKeepsTodaysAnswer, deliberately unchanged behaviour) and the two carve-out guards (params object[], params JsValue[]). The six that passed unfixed in the second are the five Convert-still-throws cases and the convertible-composite control — the half that pins what must not change.

The two representative unfixed failures:

  • math.Add(a, b) with two CIntegers → System.InvalidCastException: Invalid cast from '…' to '…+CDecimal' out of Evaluate, through MethodInfoFunction.TryCallDefaultTypeConverter.TryConvertConvert.
  • converter.TryConvert(new object[] { new Widget() }, typeof(Gadget[]), …) threw instead of returning false.

Divergences from main actually found

  1. parameterValue.IsSpecArray() on main is parameterValue.IsArray() on 4.x — confirmed. JsProxy overrides it on 4.x too, so the Proxy carve-out (is not ArrayInstance keeps the base score, no traps run during scoring) still holds and the comment was reworded from "spec array" to "array".
  2. engine._typeConverter on main is engine.TypeConverter on 4.x — confirmed, but it did not affect this change: the only site reading it is the existing Interop: a plain type mismatch scores 100 instead of being discarded, so 'text' + an overloaded CLR value throws #3407 probe, which the port leaves untouched.
  3. ClrTypeConverter on main is ITypeConverter on 4.x — confirmed as the base type of DefaultTypeConverter. It did not affect TryConvertPart, whose doc comment references only Convert, TryConvert and Options.InteropOptions.ExceptionHandler, all of which exist on 4.x with the same names.
  4. The fifth site does differ structurally, as expected: 4.x has the POCO-member copy inline in a foreach (var member in type.GetMembers()) loop with a MemberType != Property && != Field filter, not main's extracted static void CopyDictionaryEntryToMember(…) local function over separate GetProperties()/GetFields() passes. main's refactor was not imported; TryConvertPart is called inline and the loop return falses on a decline.
  5. 4.x's catch in the Convert.ChangeType fallback has no Throw.MustPropagateHostException(e) call — confirmed, and left alone.
  6. ArrayInstance.GetLength() (internal override uint) and TryGetValue(uint, out JsValue) (public bool) exist on 4.x with the same signatures — no adaptation needed.

Two more that turned up during the port:

  1. The constructor-resolution message differs. 4.x throws Could not resolve a constructor for type {type} for given arguments; main reworded it to Could not resolve a constructor for the specified arguments.. AConstructorArgumentNoOverloadAcceptsIsACatchableResolutionFailure asserts 4.x's wording (with a * wildcard for the type name). The behaviour being pinned — a catchable JavaScriptException / script-visible TypeError instead of a raw InvalidCastException — is identical, and that test is red on unfixed 4.x either way.
  2. The tests are xUnit v3 on 4.x, and the folder layout differs. [Test][Fact] throughout (no [TestCase] in either file). Invoking(…) and the AwesomeAssertions global usings are already present on 4.x in both projects, so the assertion style is unchanged. main created Jint.Tests/Runtime/Interop/ for CompositeConversionDeclineTests.cs; 4.x has no such folder and keeps DefaultTypeConverterTests.cs directly in Jint.Tests/Runtime/, so the ported file sits there with namespace Jint.Tests.Runtime.

No AGENTS.md change. 4.x has no Jint/Runtime/Interop/AGENTS.md — the co-located split is main-only, and 4.x's single root AGENTS.md carries no "Overload scoring's last rule" bullet (and no mention of #3407) to extend. No docs/v5-migration.md row either; that file is main-only.

Verification

All in Release, no --no-build, TreatWarningsAsErrors on, both TFMs where the project multi-targets:

Suite Result
Jint.Tests 7017 passed / 0 failed / 4 skipped (net472) · 7102 / 0 / 4 (net10.0)
Jint.Tests.PublicInterface 1828 / 0 / 9 (net472) · 1836 / 0 / 9 (net10.0)
Jint.Tests.CommonScripts 28 / 0 / 0 on both
Jint.Tests.Test262 102,499 passed / 0 failed / 185 skipped of 102,684

test262 matches the branch control exactly, with neither of the two known load flakes (intl402/supportedLocalesOf-unicode-extensions-ignored.js, staging/sm/Array/toSpliced-dense.js) firing this run. Full solution build: 0 errors, and the only warning is the pre-existing MSB3277 reference conflict in Jint.Tests.CommonScripts on net472, untouched by this change.

🤖 Generated with Claude Code

https://claude.ai/code/session_01LfyCDDqtkhyWVEFHKWhZfu

… a failing element declines instead of throwing

Backport of sebastienros#3764 to 4.x.

A `params` call bundles its trailing arguments into one `JsArray` before overload
resolution runs, so `InteropHelper.CalculateMethodParameterScore` rated three
candidates differing only in their element type - `CDecimal[]`, `CInteger[]`,
`CLong[]` - with one rule, "is an array, wants an array", that answered a flat 2
for every one of them. The element type was never consulted, the converter probe
below that rule (the sebastienros#3407 fix) was never reached, and declaration order decided.
Where the first-declared candidate happened to be convertible it answered
silently and wrongly; where it was not, the conversion's `InvalidCastException`
left through the embedder's `Evaluate`.

It escaped because of the second defect. The composite branches of
`DefaultTypeConverter.TryConvert` - a `List<T>` or `Collection<T>` item, a `T[]`
element, a target dictionary's value, a member of a POCO built from a dictionary
- converted their parts through the public, throwing `Convert`, ignoring the
`propagateException` flag their own frame had been called with. So a method
documented as returning false threw, which is not something the candidate loop in
`MethodInfoFunction.Call` can move on from: it tries candidates in score order and
declines its way to the next, and an exception ends the call rather than the
candidate.

Both are fixed together, because fixing the first by asking the converter per
element throws until the second is fixed.

- `TryConvertPart` routes all five composite sites through the flag their frame
  was given. It mirrors `Convert` - the virtual `TryConvert` first, so a subclass
  override still answers for the parts - so behaviour under
  `propagateException: true` is unchanged.
- `CalculateParameterTypeScore` is the type-level core of the parameter score, so
  an element with no `ParameterInfo` of its own can be scored by the same rules.
  An array parameter now scores its base 2 plus its *worst* element, up to eight
  of them, and returns -1 on the first element that cannot bind at all. Element
  types any `JsValue` is assignable to - `object`, `JsValue` - are carved out and
  keep the flat base, or `params object[]` and `params JsValue[]` would rank
  below the scalar overload beside them.

Deliberately out of scope: `MethodDescriptor.Call`'s `TypeReference` constructor
lane keeps its throwing `Convert` and gets no retry loop - correct selection is
what repairs it, exactly as sebastienros#3407 repaired that lane - and an empty JS array
against several `params T[]` overloads stays ambiguous and keeps today's answer.

Pinned in `Jint.Tests.PublicInterface/HostArrayElementOverloadTests.cs` and
`Jint.Tests/Runtime/CompositeConversionDeclineTests.cs`, which fail 8/11 and
5/11 respectively on unfixed 4.x, on both net472 and net10.0.

Closes sebastienros#3754 on 4.x

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LfyCDDqtkhyWVEFHKWhZfu
@lahma
lahma merged commit 7e5b870 into sebastienros:4.x Sep 3, 2026
5 checks passed
@lahma
lahma deleted the backport/3746-params-array-overload branch September 3, 2026 21:14
PatrickSt1991 pushed a commit to Apps2Samsung/Apps2Samsung that referenced this pull request Sep 14, 2026
Updated [Avalonia](https://github.com/AvaloniaUI/Avalonia/) from 11.3.20
to 11.3.22.

<details>
<summary>Release notes</summary>

_Sourced from [Avalonia's
releases](https://github.com/AvaloniaUI/Avalonia//releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/AvaloniaUI/Avalonia//commits).
</details>

Updated [Avalonia.Desktop](https://github.com/AvaloniaUI/Avalonia/) from
11.3.20 to 11.3.22.

<details>
<summary>Release notes</summary>

_Sourced from [Avalonia.Desktop's
releases](https://github.com/AvaloniaUI/Avalonia//releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/AvaloniaUI/Avalonia//commits).
</details>

Updated [Avalonia.Diagnostics](https://github.com/AvaloniaUI/Avalonia/)
from 11.3.20 to 11.3.22.

<details>
<summary>Release notes</summary>

_Sourced from [Avalonia.Diagnostics's
releases](https://github.com/AvaloniaUI/Avalonia//releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/AvaloniaUI/Avalonia//commits).
</details>

Updated [Avalonia.Fonts.Inter](https://github.com/AvaloniaUI/Avalonia/)
from 11.3.20 to 11.3.22.

<details>
<summary>Release notes</summary>

_Sourced from [Avalonia.Fonts.Inter's
releases](https://github.com/AvaloniaUI/Avalonia//releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/AvaloniaUI/Avalonia//commits).
</details>

Updated
[Avalonia.Themes.Fluent](https://github.com/AvaloniaUI/Avalonia/) from
11.3.20 to 11.3.22.

<details>
<summary>Release notes</summary>

_Sourced from [Avalonia.Themes.Fluent's
releases](https://github.com/AvaloniaUI/Avalonia//releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/AvaloniaUI/Avalonia//commits).
</details>

Updated [Jint](https://github.com/sebastienros/jint) from 4.16.1 to
4.16.2.

<details>
<summary>Release notes</summary>

_Sourced from [Jint's
releases](https://github.com/sebastienros/jint/releases)._

## 4.16.2

Jint 4.16.2 is a maintenance release from the `4.x` branch:
**correctness and conformance fixes backported from `main`, and nothing
that changes an existing API or an existing default.** If you are on
4.16.1 it is a drop-in update — every public signature is the one 4.16.0
shipped, on all five target frameworks, and the per-framework snapshots
in `Jint.Tests.PublicInterface/Verify/` are unchanged. `main` remains
5.0.0 development; what is coming there is recorded as it lands in
[`docs/v5-migration.md`](https://github.com/sebastienros/jint/blob/main/docs/v5-migration.md).

### Highlights

**Failures that used to end the process, or never end.** A native error
raised while a call's arguments are being evaluated is propagated
instead of leaving an empty value behind, which on 4.16.1 could recurse
until the process died — `decodeURIComponent` on a malformed sequence
was enough (#​4009). Native recursion and the forwarding paths through
bound functions and proxies are guarded so a deep native chain raises a
catchable error (#​4007). A module graph too deep to link raises an
error the host can catch instead of overflowing the stack (#​3548).
Temporal and Intl parsing cannot throw an uncatchable
`RegexMatchTimeoutException` because the machine was busy (#​3543), a
Temporal difference past a calendar's range raises `RangeError` instead
of spinning forever (#​3555), and the process-wide Intl culture cache
and Temporal zone cache are read-only and bounded, with a rejected zone
no longer remembered — closing a script-driven unbounded growth
(#​3546).

**Generators and built-ins, step by step.** A `yield*` delegation
reached again by a loop both re-delegates and keeps its place:
`countdown(3)` in a loop no longer hangs, and a delegating generator no
longer returns the memoized first result (#​3545). `Array.prototype.map`
and `slice` hand a `@@​species` constructor the length `ToLength`
produced, and a non-callable `map` argument is a `TypeError` (#​3547). A
trailing NUL pads neither a numeric string nor an array index (#​3552).
A removed property slot is a tombstone rather than a free slot to reuse,
so enumeration order survives a delete-and-readd (#​3318), and
`LengthOfArrayLike` no longer clamps through a `uint` overload (#​3328).

**Interop that answers for the right engine.** Two engines in one
process no longer decide each other's conversions and operators
(#​3559), a host type converter's answer stays with the engine whose
converter gave it (#​3563), and a value the host registers on a
`ShadowRealm` — and the members its wrapper builds eagerly — belong to
that realm (#​3557). Realm construction state is restored after nesting
or a failure (#​4008). Overload selection is by the arguments in hand:
an operator overload is chosen that way (#​3611), a `params` overload is
chosen by the array's element type with a failing element declining
rather than throwing (#​3782), an overload the argument cannot bind to
is not a match, and a host operator that throws reports what it threw
(#​3554). An index on a wrapped host collection is one property however
it is spelled, and a member filter that hides the indexer hides it
(#​3562); a read-only host collection refuses a write with a JavaScript
`TypeError` rather than the CLR's `NotSupportedException` (#​3556).

**Internationalization and Temporal.** The Persian calendar extends into
proleptic years on its 33-year cycle, so the ends of Temporal's range
land in the right Persian year (#​4006); a calendar that counts
Gregorian months writes their names (#​3612); and a `-u-` extension
carrying more than one key is read whole (#​3613).

**Errors.** Only a string-valued `stack` counts as a pre-existing stack
when a `JavaScriptException` is built, so an accessor or non-string
`stack` on a thrown object no longer breaks error reporting (#​3677,
reported by @​jeske).

Every change was verified failing-first against the unfixed branch on
both .NET Framework and .NET 10, and the release was gated on a paired
SunSpider and Dromaeo comparison against 4.16.1 on an idle machine: no
row regressed outside run-to-run noise, most run 1–4 % faster.

## What's Changed
* Backport: a removed property slot is a tombstone, not a free slot to
reuse (#​3273) by @​lahma in
sebastienros/jint#3318
* Backport: LengthOfArrayLike, delete the uint overload rather than
clamp it (#​3248) by @​lahma in
sebastienros/jint#3328
* Temporal and Intl parsing cannot fail because the machine was busy
(#​3486) by @​lahma in sebastienros/jint#3543
* Backport: the process-wide Intl culture cache and Temporal zone cache
are read-only and bounded, and a rejected zone is not remembered by
@​lahma in sebastienros/jint#3546
* Array: map and slice hand a @@​species constructor the length ToLength
produced (#​3510) by @​lahma in
sebastienros/jint#3547
* Generators: a yield* delegation both re-delegates and keeps its place
(backport of #​3506 and #​3518) by @​lahma in
sebastienros/jint#3545
* A module graph too deep to link raises an error the host can catch,
instead of ending the process (#​3415) by @​lahma in
sebastienros/jint#3548
* String to number: a trailing NUL pads neither a number string nor an
array index (backport of #​3544) by @​lahma in
sebastienros/jint#3552
* Interop: a host operator reports what it threw, and an overload the
argument cannot bind to is not a match by @​lahma in
sebastienros/jint#3554
* Temporal: a difference past a calendar's range raises RangeError
instead of spinning (#​3452) by @​lahma in
sebastienros/jint#3555
* Interop: a read-only host collection refuses script with a JavaScript
error, not the CLR's own (backport of #​3385) by @​lahma in
sebastienros/jint#3556
* ShadowRealm: a value the host registers, and the members its wrapper
builds eagerly, belong to that realm by @​lahma in
sebastienros/jint#3557
* Interop: two engines in one process do not decide each other's
conversions and operators (backport of #​3521 and #​3526) by @​lahma in
sebastienros/jint#3559
* Interop: an index on a wrapped host collection is one property, and a
filter that hides the indexer hides it by @​lahma in
sebastienros/jint#3562
* Interop: a host type converter's answer stays with the engine whose
converter gave it by @​lahma in
sebastienros/jint#3563
* Interop: an operator overload is chosen by the arguments in hand
(backport of #​3578) by @​lahma in
sebastienros/jint#3611
* Intl: a calendar counting Gregorian months writes their names
(backport of #​3589) by @​lahma in
sebastienros/jint#3612
* Intl: a `-u-` extension carrying more than one key is read whole
(backport of #​3594) by @​lahma in
sebastienros/jint#3613
* JavaScriptException: only a string "stack" counts as a pre-existing
stack (#​3607 backport) by @​lahma in
sebastienros/jint#3677
* Interop: a params overload is chosen by the array's element type, and
a failing element declines instead of throwing (#​3764) by @​lahma in
sebastienros/jint#3782
* Backport #​3751 to 4.x: Temporal: the persian calendar extends into
proleptic years on the 33-year cycle by @​lahma in
sebastienros/jint#4006
* Backport #​3922 to 4.x: Restore realm construction state after nesting
or failure by @​lahma in sebastienros/jint#4008
* Backport #​3845 to 4.x: Propagate native errors during call argument
evaluation by @​lahma in sebastienros/jint#4009
* Backport #​3877 to 4.x: Guard native recursion and forwarding paths by
@​lahma in sebastienros/jint#4007


**Full Changelog**:
sebastienros/jint@v4.16.1...v4.16.2


Commits viewable in [compare
view](sebastienros/jint@v4.16.1...v4.16.2).
</details>

Updated [Microsoft.AspNetCore](https://github.com/dotnet/aspnetcore)
from 2.3.12 to 2.3.13.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.AspNetCore's
releases](https://github.com/dotnet/aspnetcore/releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/dotnet/aspnetcore/commits).
</details>

Updated
[Microsoft.AspNetCore.Server.Kestrel.Core](https://github.com/dotnet/aspnetcore)
from 2.3.12 to 2.3.13.

<details>
<summary>Release notes</summary>

_Sourced from [Microsoft.AspNetCore.Server.Kestrel.Core's
releases](https://github.com/dotnet/aspnetcore/releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/dotnet/aspnetcore/commits).
</details>

Updated
[System.Security.Cryptography.Xml](https://github.com/dotnet/dotnet)
from 10.0.11 to 10.0.12.

<details>
<summary>Release notes</summary>

_Sourced from [System.Security.Cryptography.Xml's
releases](https://github.com/dotnet/dotnet/releases)._

No release notes found for this version range.

Commits viewable in [compare
view](https://github.com/dotnet/dotnet/commits).
</details>

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 <dependency name> major version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's major version (unless you unignore this specific
dependency's major version or upgrade to it yourself)
- `@dependabot ignore <dependency name> minor version` will close this
group update PR and stop Dependabot creating any more for the specific
dependency's minor version (unless you unignore this specific
dependency's minor version or upgrade to it yourself)
- `@dependabot ignore <dependency name>` will close this group update PR
and stop Dependabot creating any more for the specific dependency
(unless you unignore this specific dependency or upgrade to it yourself)
- `@dependabot unignore <dependency name>` will remove all of the ignore
conditions of the specified dependency
- `@dependabot unignore <dependency name> <ignore condition>` will
remove the ignore condition of the specified dependency and ignore
conditions


</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
legrab added a commit to legrab/pocok that referenced this pull request Sep 15, 2026
Updated [Jint](https://github.com/sebastienros/jint) from 4.16.1 to
4.16.2.

<details>
<summary>Release notes</summary>

_Sourced from [Jint's
releases](https://github.com/sebastienros/jint/releases)._

## 4.16.2

Jint 4.16.2 is a maintenance release from the `4.x` branch:
**correctness and conformance fixes backported from `main`, and nothing
that changes an existing API or an existing default.** If you are on
4.16.1 it is a drop-in update — every public signature is the one 4.16.0
shipped, on all five target frameworks, and the per-framework snapshots
in `Jint.Tests.PublicInterface/Verify/` are unchanged. `main` remains
5.0.0 development; what is coming there is recorded as it lands in
[`docs/v5-migration.md`](https://github.com/sebastienros/jint/blob/main/docs/v5-migration.md).

### Highlights

**Failures that used to end the process, or never end.** A native error
raised while a call's arguments are being evaluated is propagated
instead of leaving an empty value behind, which on 4.16.1 could recurse
until the process died — `decodeURIComponent` on a malformed sequence
was enough (#​4009). Native recursion and the forwarding paths through
bound functions and proxies are guarded so a deep native chain raises a
catchable error (#​4007). A module graph too deep to link raises an
error the host can catch instead of overflowing the stack (#​3548).
Temporal and Intl parsing cannot throw an uncatchable
`RegexMatchTimeoutException` because the machine was busy (#​3543), a
Temporal difference past a calendar's range raises `RangeError` instead
of spinning forever (#​3555), and the process-wide Intl culture cache
and Temporal zone cache are read-only and bounded, with a rejected zone
no longer remembered — closing a script-driven unbounded growth
(#​3546).

**Generators and built-ins, step by step.** A `yield*` delegation
reached again by a loop both re-delegates and keeps its place:
`countdown(3)` in a loop no longer hangs, and a delegating generator no
longer returns the memoized first result (#​3545). `Array.prototype.map`
and `slice` hand a `@@​species` constructor the length `ToLength`
produced, and a non-callable `map` argument is a `TypeError` (#​3547). A
trailing NUL pads neither a numeric string nor an array index (#​3552).
A removed property slot is a tombstone rather than a free slot to reuse,
so enumeration order survives a delete-and-readd (#​3318), and
`LengthOfArrayLike` no longer clamps through a `uint` overload (#​3328).

**Interop that answers for the right engine.** Two engines in one
process no longer decide each other's conversions and operators
(#​3559), a host type converter's answer stays with the engine whose
converter gave it (#​3563), and a value the host registers on a
`ShadowRealm` — and the members its wrapper builds eagerly — belong to
that realm (#​3557). Realm construction state is restored after nesting
or a failure (#​4008). Overload selection is by the arguments in hand:
an operator overload is chosen that way (#​3611), a `params` overload is
chosen by the array's element type with a failing element declining
rather than throwing (#​3782), an overload the argument cannot bind to
is not a match, and a host operator that throws reports what it threw
(#​3554). An index on a wrapped host collection is one property however
it is spelled, and a member filter that hides the indexer hides it
(#​3562); a read-only host collection refuses a write with a JavaScript
`TypeError` rather than the CLR's `NotSupportedException` (#​3556).

**Internationalization and Temporal.** The Persian calendar extends into
proleptic years on its 33-year cycle, so the ends of Temporal's range
land in the right Persian year (#​4006); a calendar that counts
Gregorian months writes their names (#​3612); and a `-u-` extension
carrying more than one key is read whole (#​3613).

**Errors.** Only a string-valued `stack` counts as a pre-existing stack
when a `JavaScriptException` is built, so an accessor or non-string
`stack` on a thrown object no longer breaks error reporting (#​3677,
reported by @​jeske).

Every change was verified failing-first against the unfixed branch on
both .NET Framework and .NET 10, and the release was gated on a paired
SunSpider and Dromaeo comparison against 4.16.1 on an idle machine: no
row regressed outside run-to-run noise, most run 1–4 % faster.

## What's Changed
* Backport: a removed property slot is a tombstone, not a free slot to
reuse (#​3273) by @​lahma in
sebastienros/jint#3318
* Backport: LengthOfArrayLike, delete the uint overload rather than
clamp it (#​3248) by @​lahma in
sebastienros/jint#3328
* Temporal and Intl parsing cannot fail because the machine was busy
(#​3486) by @​lahma in sebastienros/jint#3543
* Backport: the process-wide Intl culture cache and Temporal zone cache
are read-only and bounded, and a rejected zone is not remembered by
@​lahma in sebastienros/jint#3546
* Array: map and slice hand a @@​species constructor the length ToLength
produced (#​3510) by @​lahma in
sebastienros/jint#3547
* Generators: a yield* delegation both re-delegates and keeps its place
(backport of #​3506 and #​3518) by @​lahma in
sebastienros/jint#3545
* A module graph too deep to link raises an error the host can catch,
instead of ending the process (#​3415) by @​lahma in
sebastienros/jint#3548
* String to number: a trailing NUL pads neither a number string nor an
array index (backport of #​3544) by @​lahma in
sebastienros/jint#3552
* Interop: a host operator reports what it threw, and an overload the
argument cannot bind to is not a match by @​lahma in
sebastienros/jint#3554
* Temporal: a difference past a calendar's range raises RangeError
instead of spinning (#​3452) by @​lahma in
sebastienros/jint#3555
* Interop: a read-only host collection refuses script with a JavaScript
error, not the CLR's own (backport of #​3385) by @​lahma in
sebastienros/jint#3556
* ShadowRealm: a value the host registers, and the members its wrapper
builds eagerly, belong to that realm by @​lahma in
sebastienros/jint#3557
* Interop: two engines in one process do not decide each other's
conversions and operators (backport of #​3521 and #​3526) by @​lahma in
sebastienros/jint#3559
* Interop: an index on a wrapped host collection is one property, and a
filter that hides the indexer hides it by @​lahma in
sebastienros/jint#3562
* Interop: a host type converter's answer stays with the engine whose
converter gave it by @​lahma in
sebastienros/jint#3563
* Interop: an operator overload is chosen by the arguments in hand
(backport of #​3578) by @​lahma in
sebastienros/jint#3611
* Intl: a calendar counting Gregorian months writes their names
(backport of #​3589) by @​lahma in
sebastienros/jint#3612
* Intl: a `-u-` extension carrying more than one key is read whole
(backport of #​3594) by @​lahma in
sebastienros/jint#3613
* JavaScriptException: only a string "stack" counts as a pre-existing
stack (#​3607 backport) by @​lahma in
sebastienros/jint#3677
* Interop: a params overload is chosen by the array's element type, and
a failing element declines instead of throwing (#​3764) by @​lahma in
sebastienros/jint#3782
* Backport #​3751 to 4.x: Temporal: the persian calendar extends into
proleptic years on the 33-year cycle by @​lahma in
sebastienros/jint#4006
* Backport #​3922 to 4.x: Restore realm construction state after nesting
or failure by @​lahma in sebastienros/jint#4008
* Backport #​3845 to 4.x: Propagate native errors during call argument
evaluation by @​lahma in sebastienros/jint#4009
* Backport #​3877 to 4.x: Guard native recursion and forwarding paths by
@​lahma in sebastienros/jint#4007


**Full Changelog**:
sebastienros/jint@v4.16.1...v4.16.2


Commits viewable in [compare
view](sebastienros/jint@v4.16.1...v4.16.2).
</details>

[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=Jint&package-manager=nuget&previous-version=4.16.1&new-version=4.16.2)](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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant