On Aug 28, 2013, at 5:09 AM, André Bargull wrote:
> This test case [1] from SpiderMonkey failed when I applied the latest spec
> changes to my ES6 test implementation. Based on the bug report at [2], this
> might be another web-compatibility issue - but is that really the case? Any
> input appreciated!
>
> Thanks,
> André
>
>
> [1]
> https://github.com/mozilla/mozilla-central/blob/master/js/src/jit-test/tests/basic/bug683140.js
> [2] https://bugzilla.mozilla.org/show_bug.cgi?id=683140
Very interesting. Here is one of the test cases André is talking about.
var g = newGlobal("new-compartment"); //or any non-standard mechanism to get a
handle on another realm's global object
g.a = g.Array(10);
print(g.a instanceof Array);
g.a = Array.prototype.slice(g.a);
print(g.a instanceof Array);
--
Output ES<6: false, true
Output ES6: false, false
Also note that if the instanceof tests above were replaced with
Array.isArray(g.a) you would get all trues in both ES5 and ES6. instanceof is
not a reliable test for array-ness when objects flow between realms..
The problem is that in ES<6 slice always returned a new Array instance using
the Array of the realm associated with the invoked slice function. In ES6
slice returns an object that is determine based upon the actual this value
passed to slice. In the default case like above, this will be the a new Array
instance using the Array of the realm associated with the this value.
The reason for this change is to enable slice to behave rationally for Array
subclasses. For example:
class SubArray extends Array {
get isSubArray() {return true}
}
let sa = new SubArray(10);
let sal = sa.slice(1);
print(sa.isSubArray); //true for Es6 slice, undefined for ES5
slice
print(sal instanceof SubArray); //true for ES6 slice spec. false for ES5 slice
spec.
print(sal instanceof Array); //true for ES6. true for ES5
The way that the result object creation works in the ES6 spec. is approximately:
slice(start, end) {
...
let result = new this.constructor(); //create an instance of the same
"class" as the this value
...
}
Continuing to allow slice (and most other Array.prototype methods) to work as
expected with subclasses and still preserving ES5 cross-realm instanceof
compatability for these cases is at best hackish. Something like:
slice(start, end) {
...
let resultConstructor = this.constructor;
if (realm(resultConstructor) !== thisFunctionsRealm) {
if (isIntrinsicArrayConstrutorForAnyRealm(resultConstructor)
then resultConstructor = thisFunctionsReam.intrinsics("Array");
}
let result = new resultConstructor();
...
}
I guess I could put mechanism to support this into the spec...
However, do we actually understand what the real world use case that tripped
over this in FF? It'seasy to write a test case that detects this difference
but that sort of instanceof test doesn't seem to make much sense for production
code.
Allen _______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss