Using a Typed Array (or most any exotic object) as as a prototype is weird. But their specification
of [[Get]] and [[Set]] does not correctly deal with the case where the _Rceiver_ argument is not the same object as the exotic array. In this case, a [[Put]] can actually mutate the prototype type object. Consider:
let o = new Int8Array(1)
Object.setPrototypeOf(Array.prototype, o);
const a = []; //a inherits indirectly from o
a[0] = 4; //according to current spec. this will set o[0] to 4.
The problem is that 9.4.5.5 does not check if _O_ is different from _Receiver_ and calls IntegerIndexElementSet to mutate _O_ rather than _Receiver_ (which would also be wrong, but for other reasons.
The fix is to change step 2 to:
if SameValue(_O_,_Reciever_) and Type(_P_) is String, then
The same change should also be made to 9.4.5.4
With this code:
let o = new Int8Array(1)
Object.setPrototypeOf(Array.prototype, o);
const a = []; //a inherits indirectly from o
a[0] = 4; //according to current spec. this will set o[0] to 4.
print(a[0], o[0]);
I get these results from eshost file.js:
#### Chakra
4 0
#### JavaScriptCore
4 0
#### SpiderMonkey
4 0
#### V8
4 0
#### V8 --harmony
4 0
This suggests that engines are already doing the correct thing, so it's just a bug in the spec.
That means reverting #347, so we'd again get what was originally specified in ES6.
Does that imply that engines implemented it after #347 landed but with the prior behavior?
I guess SpiderMonkey follows what the current spec (including #347) has for 9.4.5.4 [[Get]], but SpiderMonkey's implementation for 9.4.5.5 [[Set]] doesn't seem to comply to the current spec.
LookupOwnPropertyInline returns done = true when a TypedArray object is encountered, so we always stop in NativeGetPropertyInline even for out-of-bounds accesses. But for [[Set]], an out-of-bounds access results in adding a new property in NativeSetProperty and also in SetExistingProperty for in-bounds, but wrong receiver.
So basically the primary reason for any differences in SpiderMonkey's implementation, is that we inspect the [[ArrayLength]] internal slot of the TypedArrray object earlier than specified in the spec.
OK, so I guess the real questions here imo are in this order:
I think I tried to implement the spec behavior for [[Set]] and it's not web compatible: https://bugzilla.mozilla.org/show_bug.cgi?id=1502889
aha, and that points to #1339.
Looks like we may need to revert all or part of #347?
I've totally forgotten about the web-compatibility issue encountered in Firefox.
Looks like we may need to revert all or part of #347?
I guess the [[Get]] part is still okay, but [[Set]] will need to be changed.
And then we need to decide if consistency between [[Get]] and [[Set]] () or between [[Get]] and [[HasProperty]] (*) is more important, because we can't get both.
() That means consistent receiver checks.
(*) Per the example in #347
What about just adding a branch for into 2 (if SameValue(O,Receiver)) so we don't fall to 3, but still don't set the value onto the prototype?