ReviewOS

zig-utils/zig-js

Objects: update own data after accessor deletion and inherited creation

#1080
Closed chris opened this 9 days ago ·
9 days ago

Related: #1079, #491, #532

Executed on parent a6a984e7 while checking ordinary property semantics for #1079:

const object = {};
Object.defineProperty(object, 'value', {
  configurable: true,
  get() { return 1; },
  set(value) { delete object.value; Object.setPrototypeOf(object, { value: 50 }); }
});
object.value = 1;
object.value = 54;
object.value = 59;
JSON.stringify([
  object.value,
  Object.getOwnPropertyDescriptor(object, 'value').value,
  Object.getPrototypeOf(object).value
]);

Node returns [59,59,50]. Both parent tree-walker and required-VM execution return [54,54,50]. The final ordinary assignment therefore fails to update the own data property created through the inherited writable data descriptor after accessor deletion.

Acceptance:

  • Diagnose and fix the actual named-property storage/descriptor update path; do not special-case this program or weaken #1079's live-property witness.
  • Pin the Node-confirmed result in both execution modes, including shared/no-GIL execution, descriptor visibility, and repeated writes after accessor deletion/prototype edits.
  • Focused normal/ReleaseSafe/unsuppressed TSan and relevant before/after property/assignment corpus comparisons pass without new failures.
  • Land as one small logical fix, with measured scope and evidence linked here.
9 days ago

The cause is retained attribute metadata after deleting an accessor-only property. The newly created own data key inherited the deleted accessor's writable:false / enumerable:false flags, so the following ordinary assignment was blocked.

The fix removes those attributes under the existing property lock when ordinary deletion removes the whole descriptor. Representation conversions and surviving data slots retain their attributes.

The minimal probe now returns [59,59,50] in both tree-walker and required-VM execution, matching Node. Language-level regression checks pass 3/3 in normal, ReleaseSafe, and unsuppressed TSan, covering both execution modes in isolated/shared contexts plus four actual no-GIL workers. Low-level deletion/recreation and conversion-preservation checks pass 1/1 in each mode. Existing accessor-deletion OOM and fused-property checks also pass.

Exact parent/after Object, assignment, and delete corpus comparisons are running. #1079's kernel removal is saved separately so this semantic fix can land as its own commit.

9 days ago

Landed in bc37401b.

Ordinary accessor-only deletion now removes its attribute sidecar under the existing property lock. Representation conversions and surviving data slots retain their attributes. The recreated key receives ordinary writable/enumerable/configurable data semantics, so repeated writes succeed.

Validation:

  • The executed probe changes [54,54,50] → [59,59,50] in both tree-walker and required-VM execution, matching Node.
  • Language regressions 3/3 in normal, ReleaseSafe, and unsuppressed TSan cover strict assignments, reflection, key creation order, both execution modes in isolated/shared contexts, and four actual no-GIL workers.
  • Low-level deletion/recreation and conversion-preservation checks 1/1 in each mode. Existing accessor-deletion OOM check 1/1 and fused-property check 2/2 pass.
  • Exact parent/after Object 3,411, assignment 485, and delete 69 comparisons: 3,965 total, 0 failures before → after, 0 flips, and 0 tree/required-VM differences on both binaries. The binary hashes are checked to be distinct.

These are scoped local checks; full integration gates run in CI. #1079 remains separate and can now resume its live-property witness without weakening the Node-confirmed expectation.

Sign in to comment on this issue.