Skip to content

Fix readonly array descriptors not throwing TypeError in strict mode#2542

Merged
lahma merged 1 commit into
mainfrom
copilot/fix-readonly-descriptors-issue
Jun 23, 2026
Merged

Fix readonly array descriptors not throwing TypeError in strict mode#2542
lahma merged 1 commit into
mainfrom
copilot/fix-readonly-descriptors-issue

Conversation

Copilot AI commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Summary

Fix TryWriteExistingDense bypassing writability checks on frozen/locked array elements.

Details

When array elements were made non-writable via FastSetProperty + PreventExtensions, the SimpleAssignmentExpression.SetValue fast path called TryWriteExistingDense which only checked slot occupancy—never descriptor writability. This silently overwrote (or appeared to overwrite) read-only elements without throwing in strict mode.

Fixes:

  • ArrayInstance.TryWriteExistingDense: bail out when _sparse has a non-writable descriptor for the index, forcing fallback to the full PutValue path that enforces strict-mode TypeError.
  • ArrayLikeWrapper.Set: handle numeric index writes directly with CanWrite/Extensible guards (consistent with how ObjectWrapper.Set handles string-keyed properties), preventing the SetSlow fallback from incorrectly returning true.

Repro from the issue:

var engine = new Engine(x => x.Strict());
// ... wrap dictionary with object[1] property, lock descriptors, PreventExtensions ...
engine.Evaluate("context.property[0] = {};"); // should throw, was silent

Linked issue

Closes #2541

Test plan

  • Added or updated unit tests in Jint.Tests
  • Ran dotnet test --configuration Release locally
  • For ECMAScript spec changes: ran Jint.Tests.Test262 and confirmed no regressions (99,260 pass)
  • For interop changes: covered in Jint.Tests/Runtime/Interop
  • For perf changes: included before/after numbers from Jint.Benchmark

Breaking change?

No. Restores pre-4.10.0 behavior where writing to non-writable array elements throws in strict mode.

Copilot AI changed the title [WIP] Fix readonly descriptors not throwing JavaScriptException Fix readonly array descriptors not throwing TypeError in strict mode Jun 18, 2026
Copilot finished work on behalf of lahma June 18, 2026 15:26
Copilot AI requested a review from lahma June 18, 2026 15:26
…#2541)

Assigning to a non-writable element of a frozen native array — or a frozen /
read-only interop list wrapper — silently failed instead of throwing a TypeError
in strict mode (a regression from 4.9.3 where the dense-write fast paths bypassed
the writability check).

- ArrayInstance.TryWriteExistingDense: bail to the full Set/PutValue path when a
  materialized _sparse element descriptor is non-writable and the array is
  non-extensible, so strict-mode assignment throws. Gating on !Extensible keeps the
  common dense-write fast path free of a dictionary probe (an extensible array's
  fallback ArrayInstance.Set writes through regardless, so the check would be wasted
  there) and avoids a per-write probe on arrays previously enumerated via
  Object.keys / for-in (which materialize _sparse alongside _dense).

- ArrayLikeWrapper.Set: refuse in-range element writes to read-only / non-extensible
  (frozen) wrappers, which base.SetSlow would otherwise silently accept by
  materializing a throwaway descriptor. Writable writes, growth, and runtime
  read-only collections (e.g. ReadOnlyCollection<T>) defer to base.Set unchanged.

Adds native-array and interop-wrapper regression tests covering strict-mode throw,
non-strict silent no-op, non-mutation, and a runtime read-only collection.

Closes #2541

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lahma
lahma force-pushed the copilot/fix-readonly-descriptors-issue branch from 9880420 to 21fafaf Compare June 23, 2026 13:04
@lahma
lahma marked this pull request as ready for review June 23, 2026 13:04
@lahma
lahma enabled auto-merge (squash) June 23, 2026 13:07
@lahma
lahma merged commit a207e92 into main Jun 23, 2026
4 checks passed
@lahma
lahma deleted the copilot/fix-readonly-descriptors-issue branch June 23, 2026 13:17
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.

Readonly descriptors don't throw JavaScriptException

2 participants