Add opt-in ClrArrayConversion.LiveView interop mode for CLR arrays#2721
Merged
Conversation
Options.Interop.ClrArrayConversion selects how CLR arrays cross into script: Copy (default, per-conversion JsArray snapshot, behavior unchanged) or LiveView, which exposes single-rank T[] as a fixed-size ArrayWrapper<T> live view routed through the same WrapObjectHandler and identity-cache machinery as other wrapped CLR objects. - element reads/writes go straight to the underlying array in both directions; script writes are coerced to the element type - resize attempts (push/pop/shift/unshift/splice, length writes, out-of-bounds index writes) throw a JS TypeError instead of leaking CLR exceptions; delete mirrors integer-indexed exotic semantics (false in range, true out of range) so pop/shift cannot zero slots - Array.isArray stays false; iteration, spread, attached Array.prototype methods and JSON.stringify-as-array work like other array-like wrappers - multi-rank (T[,]) and non-zero-based (T[*]) arrays keep Copy-mode behavior under both modes Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
lahma
enabled auto-merge (squash)
July 21, 2026 12:46
This was referenced Jul 21, 2026
lahma
added a commit
to lahma/jint
that referenced
this pull request
Jul 21, 2026
Flip the default of Options.Interop.ArrayConversion from Copy to LiveView so single-rank CLR arrays (T[]) cross into script as live, fixed-size wrapper views instead of per-read deep-copied JsArray snapshots -- aligning T[] with wrapped List<T> and cutting ~2.9x time / ~75% allocation on array-member traversal. Copy stays available to preserve the pre-4.14 behavior. Also rename the option (added in the unreleased sebastienros#2721) from ClrArrayConversion to ArrayConversion, enum ArrayConversionMode: Interop already implies CLR, and Copy/LiveView are exclusive modes (like StepMode), not a combinable ...Type flags enum. Migrate the tests that specifically exercised Copy-snapshot semantics (array identity cache, sebastienros#2541 element writability) and four extension-method tests to pin Copy explicitly: a CLR method returning T[] now yields a wrapper that AsArray() rejects, and the LINQ .join() case additionally resolves the Enumerable.Join extension method on the wrapper's IEnumerable<T> target instead of falling back to native Array.prototype.join (PreferJsPrototypeMethods mitigates). Refresh the interop churn benchmark comments/config for the new default. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
lahma
added a commit
that referenced
this pull request
Jul 21, 2026
Flip the default of Options.Interop.ArrayConversion from Copy to LiveView so single-rank CLR arrays (T[]) cross into script as live, fixed-size wrapper views instead of per-read deep-copied JsArray snapshots -- aligning T[] with wrapped List<T> and cutting ~2.9x time / ~75% allocation on array-member traversal. Copy stays available to preserve the pre-4.14 behavior. Also rename the option (added in the unreleased #2721) from ClrArrayConversion to ArrayConversion, enum ArrayConversionMode: Interop already implies CLR, and Copy/LiveView are exclusive modes (like StepMode), not a combinable ...Type flags enum. Migrate the tests that specifically exercised Copy-snapshot semantics (array identity cache, #2541 element writability) and four extension-method tests to pin Copy explicitly: a CLR method returning T[] now yields a wrapper that AsArray() rejects, and the LINQ .join() case additionally resolves the Enumerable.Join extension method on the wrapper's IEnumerable<T> target instead of falling back to native Array.prototype.join (PreferJsPrototypeMethods mitigates). Refresh the interop churn benchmark comments/config for the new default. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This was referenced Jul 22, 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.
Part of the V8-gap performance campaign (#1775 follow-up); completes the array-interop story started in #2716.
Change
New
Options.Interop.ClrArrayConversionenum:Copy(default — exact current behavior, locked by tests) andLiveView. UnderLiveView, a single-rankT[]crossing into script becomes a live, fixed-sizeArrayWrapper<T>view — aligned with how wrappedList<T>already behaves — instead of a per-read deep-copiedJsArraysnapshot:push, growth, length write) throws a JSTypeError— never a leaking CLRNotSupportedException.Array.isArrayisfalse(matches the other wrappers; documented);for..of, spread andArray.prototypemethods work via the attached array prototype;JSON.stringifystill serializes as an array.T[,]) and non-zero-based arrays keep their existing behavior in both modes._typeMappersmemoization.Numbers (default BDN job,
InteropWrapperChurnBenchmark.ArrayMemberTraversal: 100 reads of anint[100]member per op)LiveView needs no identity flag for its 2.5× / −75% alloc win (live semantics, fresh wrapper per crossing); combined with an identity flag, array reads hit the wrapper cache like any other host object. Memory-probe verified: zero retained growth after full GC over 200k iterations.
Gates
Rebased on current main (includes #2716–#2720): Jint.Tests 3689/3626 (net10/net472, includes 31 new LiveView tests), PublicInterface 114/114 both TFMs (API-approval snapshot updated for the new enum/property), Test262 99,431 passed / 0 failed.
InteropTests.NonWritableArrayElement_*andShouldConvertArrayToArrayInstancepass unchanged under defaultCopy.A follow-up proposal issue for flipping the default to
LiveViewin the next major (aligningT[]withList<T>semantics) will be filed once this merges.🤖 Generated with Claude Code