Parent: #459 Related: #889, #892
Problem
RequireObjectCoercible failures on a read already match JavaScriptCore's leading clause. The write and delete paths do not — they use two different messages that JSC never emits:
| source | zig-js | JavaScriptCore |
|---|---|---|
var v = null; v.x = 1 | Cannot access property of null or undefined | null is not an object (evaluating 'v.x = 1') |
var x = {}; x.y.z = 2 | Cannot access property of null or undefined | undefined is not an object (evaluating 'x.y.z = 2') |
var z = {}; delete z.a.b | Cannot convert undefined or null to object | undefined is not an object (evaluating 'delete z.a.b') |
For comparison, these reads are already exact:
var p = null; p.x -> null is not an object (leading clause matches)
var o = {}; o.m.o -> undefined is not an object (leading clause matches)
var t = {}; t.z[u] -> undefined is not an object (leading clause matches)So the same operation reports one of three different strings depending on whether the member expression is being read, assigned, or deleted. Only the read wording is right.
This is a leading clause mismatch, which is the half that matters for substring matching
in ported test suites — distinct from the missing (evaluating '...') suffix that #892
covers for all three.
Required implementation
- Route the assignment and delete RequireObjectCoercible failures through the same
notAnObjectMessage(base)the read path uses, so all three saynull is not an object/undefined is not an object. - Check both tiers: the tree-walker's member-assignment and
delete_exprpaths insrc/interpreter.zig, and the corresponding store/delete opcodes insrc/vm.zig. Message-text divergence between tiers is invisible to test262, which asserts none of it. - Verify against the oracle rather than by eye:
~/Code/Home/lang/zig-out/bin/home-tool runis a real JSC backend. Drive the probe from inside a function — indirectevalin a script shares global scope with the harness, so single-letter case variables silently clobber the driver's loop counter and truncate the run. - Note JSC names the whole assignment/delete expression in the suffix (
'v.x = 1','delete z.a.b'), not just the member — relevant when #892 adds the suffix.