summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/Function/has-instance.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/non262/Function/has-instance.js')
-rw-r--r--js/src/tests/non262/Function/has-instance.js101
1 files changed, 101 insertions, 0 deletions
diff --git a/js/src/tests/non262/Function/has-instance.js b/js/src/tests/non262/Function/has-instance.js
new file mode 100644
index 0000000000..f0c7bf28e1
--- /dev/null
+++ b/js/src/tests/non262/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);