Source code

Revision control

Copy as Markdown

Other Tools

// It is possible to override Function.prototype[@@hasInstance].
let passed = false;
let obj = { foo: true };
let C = function(){};
Object.defineProperty(C, Symbol.hasInstance, {
value: function(inst) { passed = inst.foo; return false; }
});
assertEq(obj instanceof C, false);
assertEq(passed, true);
{
let obj = {
[Symbol.hasInstance](v) { return true; },
};
let whatevs = {};
assertEq(whatevs instanceof obj, true);
}
{
function zzzz() {};
let xxxx = new zzzz();
assertEq(xxxx instanceof zzzz, true);
assertEq(zzzz[Symbol.hasInstance](xxxx), true);
}
// Non-callable objects should return false.
const nonCallables = [
1,
undefined,
null,
"nope",
]
for (let nonCallable of nonCallables) {
assertEq(nonCallable instanceof Function, false);
assertEq(nonCallable instanceof Object, false);
}
// Non-callables should throw when used on the right hand side
// of `instanceof`.
assertThrowsInstanceOf(() => {
function foo() {};
let obj = {};
foo instanceof obj;
}, TypeError);
// Non-callables do not throw for overridden methods
let o = {[Symbol.hasInstance](v) { return true; }}
assertEq(1 instanceof o, true);
// Non-callables return false instead of an exception when
// Function.prototype[Symbol.hasInstance] is called directly.
for (let nonCallable of nonCallables) {
assertEq(Function.prototype[Symbol.hasInstance].call(nonCallable, Object), false);
}
// It should be possible to call the Symbol.hasInstance method directly.
assertEq(Function.prototype[Symbol.hasInstance].call(Function, () => 1), true);
assertEq(Function.prototype[Symbol.hasInstance].call(Function, Object), true);
assertEq(Function.prototype[Symbol.hasInstance].call(Function, null), false);
assertEq(Function.prototype[Symbol.hasInstance].call(Function, Array), true);
assertEq(Function.prototype[Symbol.hasInstance].call(Object, Array), true);
assertEq(Function.prototype[Symbol.hasInstance].call(Array, Function), false);
assertEq(Function.prototype[Symbol.hasInstance].call(({}), Function), false);
assertEq(Function.prototype[Symbol.hasInstance].call(), false)
assertEq(Function.prototype[Symbol.hasInstance].call(({})), false)
// Ensure that bound functions are unwrapped properly
let bindme = {x: function() {}};
let instance = new bindme.x();
let xOuter = bindme.x;
let bound = xOuter.bind(bindme);
let doubleBound = bound.bind(bindme);
let tripleBound = bound.bind(doubleBound);
assertEq(Function.prototype[Symbol.hasInstance].call(bound, instance), true);
assertEq(Function.prototype[Symbol.hasInstance].call(doubleBound, instance), true);
assertEq(Function.prototype[Symbol.hasInstance].call(tripleBound, instance), true);
// Function.prototype[Symbol.hasInstance] is not configurable
let desc = Object.getOwnPropertyDescriptor(Function.prototype, Symbol.hasInstance);
assertEq(desc.configurable, false);
// Attempting to use a non-callable @@hasInstance triggers a type error
assertThrowsInstanceOf(() => {
var fun = function() {}
var p = new Proxy(fun, {
get(target, key) {
return /not-callable/;
}
});
fun instanceof p;
}, TypeError);
if (typeof reportCompare === "function")
reportCompare(true, true);