diff options
Diffstat (limited to 'js/src/tests/ecma_6/Function/has-instance.js')
-rw-r--r-- | js/src/tests/ecma_6/Function/has-instance.js | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Function/has-instance.js b/js/src/tests/ecma_6/Function/has-instance.js new file mode 100644 index 000000000..f0c7bf28e --- /dev/null +++ b/js/src/tests/ecma_6/Function/has-instance.js @@ -0,0 +1,101 @@ +// 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 +// Bug 1280892 +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); |