From 652e35bd3297e2c2093573ddca78e2544f5008f0 Mon Sep 17 00:00:00 2001
From: Mike Pennisi <mike@mikepennisi.com>
Date: Mon, 13 Jul 2015 16:24:12 -0400
Subject: [PATCH] Add tests for well-known Symbol, @@hasInstance

Assert the behavior of the built-in method on the FunctionPrototype and
the usage of the Symbol by the `instanceof` operator.
---
 .../prototype/Symbol.hasInstance/length.js    | 26 ++++++++++
 .../prototype/Symbol.hasInstance/name.js      | 19 +++++++
 .../prototype/Symbol.hasInstance/prop-desc.js | 17 +++++++
 .../this-val-bound-target.js                  | 23 +++++++++
 .../this-val-not-callable.js                  | 17 +++++++
 .../this-val-poisoned-prototype.js            | 29 +++++++++++
 .../this-val-prototype-non-obj.js             | 49 +++++++++++++++++++
 .../value-get-prototype-of-err.js             | 36 ++++++++++++++
 .../Symbol.hasInstance/value-negative.js      | 27 ++++++++++
 .../Symbol.hasInstance/value-non-obj.js       | 23 +++++++++
 .../Symbol.hasInstance/value-positive.js      | 27 ++++++++++
 .../built-ins/Symbol/hasInstance/prop-desc.js | 16 ++++++
 .../instanceof/symbol-hasinstance-get-err.js  | 24 +++++++++
 .../symbol-hasinstance-invocation.js          | 32 ++++++++++++
 .../symbol-hasinstance-not-callable.js        | 24 +++++++++
 .../symbol-hasinstance-to-boolean.js          | 44 +++++++++++++++++
 16 files changed, 433 insertions(+)
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/length.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/name.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/prop-desc.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/this-val-bound-target.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/this-val-not-callable.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/this-val-poisoned-prototype.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/this-val-prototype-non-obj.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/value-get-prototype-of-err.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/value-negative.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/value-non-obj.js
 create mode 100644 test/built-ins/Function/prototype/Symbol.hasInstance/value-positive.js
 create mode 100644 test/built-ins/Symbol/hasInstance/prop-desc.js
 create mode 100644 test/language/expressions/instanceof/symbol-hasinstance-get-err.js
 create mode 100644 test/language/expressions/instanceof/symbol-hasinstance-invocation.js
 create mode 100644 test/language/expressions/instanceof/symbol-hasinstance-not-callable.js
 create mode 100644 test/language/expressions/instanceof/symbol-hasinstance-to-boolean.js

diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/length.js b/test/built-ins/Function/prototype/Symbol.hasInstance/length.js
new file mode 100644
index 0000000000..1bf262c3b6
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/length.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: Function.prototye[Symbol.hasInstance] `length` property
+info: >
+    ES6 Section 17:
+    Every built-in Function object, including constructors, has a length
+    property whose value is an integer. Unless otherwise specified, this value
+    is equal to the largest number of named arguments shown in the subclause
+    headings for the function description, including optional parameters.
+
+    [...]
+
+    Unless otherwise specified, the length property of a built-in Function
+    object has the attributes { [[Writable]]: false, [[Enumerable]]: false,
+    [[Configurable]]: true }.
+features: [Symbol.hasInstance]
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(Function.prototype[Symbol.hasInstance].length, 1);
+
+verifyNotEnumerable(Function.prototype[Symbol.hasInstance], 'length');
+verifyNotWritable(Function.prototype[Symbol.hasInstance], 'length');
+verifyConfigurable(Function.prototype[Symbol.hasInstance], 'length');
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/name.js b/test/built-ins/Function/prototype/Symbol.hasInstance/name.js
new file mode 100644
index 0000000000..3a809af577
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/name.js
@@ -0,0 +1,19 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: >
+    The value of the name property of this function is "[Symbol.hasInstance]".
+
+    17 ECMAScript Standard Built-in Objects
+features: [Symbol.hasInstance]
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(
+  Function.prototype[Symbol.hasInstance].name, '[Symbol.hasInstance]'
+);
+
+verifyNotEnumerable(Function.prototype[Symbol.hasInstance], 'name');
+verifyNotWritable(Function.prototype[Symbol.hasInstance], 'name');
+verifyConfigurable(Function.prototype[Symbol.hasInstance], 'name');
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/prop-desc.js b/test/built-ins/Function/prototype/Symbol.hasInstance/prop-desc.js
new file mode 100644
index 0000000000..0359878b77
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/prop-desc.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: Function.prototype[Symbol.hasInstance] property descriptor
+info: >
+    This property has the attributes { [[Writable]]: false, [[Enumerable]]:
+    false, [[Configurable]]: false }.
+features: [Symbol.hasInstance]
+includes: [propertyHelper.js]
+---*/
+
+assert.sameValue(typeof Function.prototype[Symbol.hasInstance], 'function');
+
+verifyNotEnumerable(Function.prototype, Symbol.hasInstance);
+verifyNotWritable(Function.prototype, Symbol.hasInstance);
+verifyNotConfigurable(Function.prototype, Symbol.hasInstance);
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-bound-target.js b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-bound-target.js
new file mode 100644
index 0000000000..40e7d03330
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-bound-target.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: Invoked on a bound function
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    1. If IsCallable(C) is false, return false.
+    2. If C has a [[BoundTargetFunction]] internal slot, then
+       a. Let BC be the value of C’s [[BoundTargetFunction]] internal slot.
+       b. Return InstanceofOperator(O,BC) (see 12.9.4).
+features: [Symbol.hasInstance]
+---*/
+
+var BC = function() {};
+var bc = new BC();
+var bound = BC.bind();
+
+assert.sameValue(bound[Symbol.hasInstance](bc), true);
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-not-callable.js b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-not-callable.js
new file mode 100644
index 0000000000..d712ef4c48
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-not-callable.js
@@ -0,0 +1,17 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: Non-callable `this` value
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    1. If IsCallable(C) is false, return false.
+features: [Symbol.hasInstance]
+---*/
+
+assert.sameValue(Function.prototype[Symbol.hasInstance].call(), false);
+assert.sameValue(Function.prototype[Symbol.hasInstance].call({}), false);
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-poisoned-prototype.js b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-poisoned-prototype.js
new file mode 100644
index 0000000000..18777c7622
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-poisoned-prototype.js
@@ -0,0 +1,29 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: Error thrown when accessing `prototype` property of `this` value
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    [...]
+    4. Let P be Get(C, "prototype").
+    5. ReturnIfAbrupt(P).
+features: [Symbol.hasInstance]
+---*/
+
+// Create a callable object without a `prototype` property
+var f = Object.getOwnPropertyDescriptor({ get f() {} }, 'f').get;
+
+Object.defineProperty(f, 'prototype', {
+  get: function() {
+    throw new Test262Error();
+  }
+});
+
+assert.throws(Test262Error, function() {
+  f[Symbol.hasInstance]({});
+});
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-prototype-non-obj.js b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-prototype-non-obj.js
new file mode 100644
index 0000000000..a6462b2243
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/this-val-prototype-non-obj.js
@@ -0,0 +1,49 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: Error thrown when accessing `prototype` property of `this` value
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    [...]
+    4. Let P be Get(C, "prototype").
+    5. ReturnIfAbrupt(P).
+    6. If Type(P) is not Object, throw a TypeError exception.
+features: [Symbol, Symbol.hasInstance]
+---*/
+
+var f = function() {};
+
+f.prototype = undefined;
+assert.throws(TypeError, function() {
+  f[Symbol.hasInstance]({});
+});
+
+f.prototype = null;
+assert.throws(TypeError, function() {
+  f[Symbol.hasInstance]({});
+});
+
+f.prototype = true;
+assert.throws(TypeError, function() {
+  f[Symbol.hasInstance]({});
+});
+
+f.prototype = 'string';
+assert.throws(TypeError, function() {
+  f[Symbol.hasInstance]({});
+});
+
+f.prototype = Symbol();
+assert.throws(TypeError, function() {
+  f[Symbol.hasInstance]({});
+});
+
+f.prototype = 86;
+assert.throws(TypeError, function() {
+  f[Symbol.hasInstance]({});
+});
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/value-get-prototype-of-err.js b/test/built-ins/Function/prototype/Symbol.hasInstance/value-get-prototype-of-err.js
new file mode 100644
index 0000000000..18eb41d32d
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/value-get-prototype-of-err.js
@@ -0,0 +1,36 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: >
+    Error thrown when invoking argument's [[GetPrototypeOf]] internal method
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    [...]
+    7. Repeat
+       a. Let O be O.[[GetPrototypeOf]]().
+       b. ReturnIfAbrupt(O).
+       c. If O is null, return false.
+       d. If SameValue(P, O) is true, return true.
+features: [Proxy, Symbol.hasInstance]
+---*/
+
+var o = new Proxy({}, {
+  getPrototypeOf: function() {
+    throw new Test262Error();
+  }
+});
+var o2 = Object.create(o);
+var f = function() {};
+
+assert.throws(Test262Error, function() {
+  f[Symbol.hasInstance](o);
+});
+
+assert.throws(Test262Error, function() {
+  f[Symbol.hasInstance](o2);
+});
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/value-negative.js b/test/built-ins/Function/prototype/Symbol.hasInstance/value-negative.js
new file mode 100644
index 0000000000..1df674524e
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/value-negative.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: >
+    Constructor is not defined in the argument's prototype chain
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    [...]
+    7. Repeat
+       a. Let O be O.[[GetPrototypeOf]]().
+       b. ReturnIfAbrupt(O).
+       c. If O is null, return false.
+       d. If SameValue(P, O) is true, return true.
+features: [Symbol.hasInstance]
+---*/
+
+var f = function() {};
+var o = Object.create(null);
+var o2 = Object.create(o);
+
+assert.sameValue(f[Symbol.hasInstance](o), false);
+assert.sameValue(f[Symbol.hasInstance](o2), false);
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/value-non-obj.js b/test/built-ins/Function/prototype/Symbol.hasInstance/value-non-obj.js
new file mode 100644
index 0000000000..f77b7db226
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/value-non-obj.js
@@ -0,0 +1,23 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: Non-object argument
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    [...]
+    3. If Type(O) is not Object, return false.
+features: [Symbol, Symbol.hasInstance]
+---*/
+
+assert.sameValue(function() {}[Symbol.hasInstance](), false);
+assert.sameValue(function() {}[Symbol.hasInstance](undefined), false);
+assert.sameValue(function() {}[Symbol.hasInstance](null), false);
+assert.sameValue(function() {}[Symbol.hasInstance](true), false);
+assert.sameValue(function() {}[Symbol.hasInstance]('string'), false);
+assert.sameValue(function() {}[Symbol.hasInstance](Symbol()), false);
+assert.sameValue(function() {}[Symbol.hasInstance](86), false);
diff --git a/test/built-ins/Function/prototype/Symbol.hasInstance/value-positive.js b/test/built-ins/Function/prototype/Symbol.hasInstance/value-positive.js
new file mode 100644
index 0000000000..c3aebc6dd4
--- /dev/null
+++ b/test/built-ins/Function/prototype/Symbol.hasInstance/value-positive.js
@@ -0,0 +1,27 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.2.3.6
+description: >
+    Constructor is defined in the argument's prototype chain
+info: >
+    1. Let F be the this value.
+    2. Return OrdinaryHasInstance(F, V).
+
+    7.3.19 OrdinaryHasInstance (C, O)
+
+    [...]
+    7. Repeat
+       a. Let O be O.[[GetPrototypeOf]]().
+       b. ReturnIfAbrupt(O).
+       c. If O is null, return false.
+       d. If SameValue(P, O) is true, return true.
+features: [Symbol.hasInstance]
+---*/
+
+var f = function() {};
+var o = new f();
+var o2 = Object.create(o);
+
+assert.sameValue(f[Symbol.hasInstance](o), true);
+assert.sameValue(f[Symbol.hasInstance](o2), true);
diff --git a/test/built-ins/Symbol/hasInstance/prop-desc.js b/test/built-ins/Symbol/hasInstance/prop-desc.js
new file mode 100644
index 0000000000..26c089eb24
--- /dev/null
+++ b/test/built-ins/Symbol/hasInstance/prop-desc.js
@@ -0,0 +1,16 @@
+// Copyright (C) 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+es6id: 19.4.2.2
+description: Property descriptor
+info: >
+    This property has the attributes { [[Writable]]: false, [[Enumerable]]:
+    false, [[Configurable]]: false }.
+includes: [propertyHelper.js]
+features: [Symbol.hasInstance]
+---*/
+
+assert.sameValue(typeof Symbol.hasInstance, 'symbol');
+verifyNotEnumerable(Symbol, 'hasInstance');
+verifyNotWritable(Symbol, 'hasInstance');
+verifyNotConfigurable(Symbol, 'hasInstance');
diff --git a/test/language/expressions/instanceof/symbol-hasinstance-get-err.js b/test/language/expressions/instanceof/symbol-hasinstance-get-err.js
new file mode 100644
index 0000000000..b55caeb997
--- /dev/null
+++ b/test/language/expressions/instanceof/symbol-hasinstance-get-err.js
@@ -0,0 +1,24 @@
+// Copyright (C) Copyright 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 12.9.4
+description: Error thrown when accessing constructor's @@hasInstance property
+info: >
+    1. If Type(C) is not Object, throw a TypeError exception.
+    2. Let instOfHandler be GetMethod(C,@@hasInstance).
+    3. ReturnIfAbrupt(instOfHandler).
+features: [Symbol.hasInstance]
+---*/
+
+var F = {};
+
+Object.defineProperty(F, Symbol.hasInstance, {
+  get: function() {
+    throw new Test262Error();
+  }
+});
+
+assert.throws(Test262Error, function() {
+  0 instanceof F;
+});
diff --git a/test/language/expressions/instanceof/symbol-hasinstance-invocation.js b/test/language/expressions/instanceof/symbol-hasinstance-invocation.js
new file mode 100644
index 0000000000..d213e38822
--- /dev/null
+++ b/test/language/expressions/instanceof/symbol-hasinstance-invocation.js
@@ -0,0 +1,32 @@
+// Copyright (C) Copyright 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 12.9.4
+description: >
+    Arguments and 'this' value when invoking constructor's @@hasInstance property
+info: >
+    1. If Type(C) is not Object, throw a TypeError exception.
+    2. Let instOfHandler be GetMethod(C,@@hasInstance).
+    3. ReturnIfAbrupt(instOfHandler).
+    4. If instOfHandler is not undefined, then
+       a. Return ToBoolean(Call(instOfHandler, C, «O»)).
+features: [Symbol.hasInstance]
+---*/
+
+var F = {};
+var callCount = 0;
+var thisValue, args;
+
+F[Symbol.hasInstance] = function() {
+  thisValue = this;
+  args = arguments;
+  callCount += 1;
+};
+
+0 instanceof F;
+
+assert.sameValue(callCount, 1);
+assert.sameValue(thisValue, F);
+assert.sameValue(args.length, 1);
+assert.sameValue(args[0], 0);
diff --git a/test/language/expressions/instanceof/symbol-hasinstance-not-callable.js b/test/language/expressions/instanceof/symbol-hasinstance-not-callable.js
new file mode 100644
index 0000000000..e163ad45a4
--- /dev/null
+++ b/test/language/expressions/instanceof/symbol-hasinstance-not-callable.js
@@ -0,0 +1,24 @@
+// Copyright (C) Copyright 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 12.9.4
+description: >
+    Error thrown when constructor's @@hasInstance property is defined but not callable
+info: >
+    1. If Type(C) is not Object, throw a TypeError exception.
+    2. Let instOfHandler be GetMethod(C,@@hasInstance).
+    3. ReturnIfAbrupt(instOfHandler).
+    4. If instOfHandler is not undefined, then
+       a. Return ToBoolean(Call(instOfHandler, C, «O»)).
+    5. If IsCallable(C) is false, throw a TypeError exception.
+features: [Symbol.hasInstance]
+---*/
+
+var F = {};
+
+F[Symbol.hasInstance] = null;
+
+assert.throws(TypeError, function() {
+  0 instanceof F;
+});
diff --git a/test/language/expressions/instanceof/symbol-hasinstance-to-boolean.js b/test/language/expressions/instanceof/symbol-hasinstance-to-boolean.js
new file mode 100644
index 0000000000..76240b81b1
--- /dev/null
+++ b/test/language/expressions/instanceof/symbol-hasinstance-to-boolean.js
@@ -0,0 +1,44 @@
+// Copyright (C) Copyright 2015 the V8 project authors. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/*---
+es6id: 12.9.4
+description: >
+    Type coercion of value returned by constructor's @@hasInstance property
+info: >
+    1. If Type(C) is not Object, throw a TypeError exception.
+    2. Let instOfHandler be GetMethod(C,@@hasInstance).
+    3. ReturnIfAbrupt(instOfHandler).
+    4. If instOfHandler is not undefined, then
+       a. Return ToBoolean(Call(instOfHandler, C, «O»)).
+features: [Symbol, Symbol.hasInstance]
+---*/
+
+var F = {};
+
+F[Symbol.hasInstance] = function() { return undefined; };
+assert.sameValue(0 instanceof F, false);
+
+F[Symbol.hasInstance] = function() { return null; };
+assert.sameValue(0 instanceof F, false);
+
+F[Symbol.hasInstance] = function() { return true; };
+assert.sameValue(0 instanceof F, true);
+
+F[Symbol.hasInstance] = function() { return NaN; };
+assert.sameValue(0 instanceof F, false);
+
+F[Symbol.hasInstance] = function() { return 1; };
+assert.sameValue(0 instanceof F, true);
+
+F[Symbol.hasInstance] = function() { return ''; };
+assert.sameValue(0 instanceof F, false);
+
+F[Symbol.hasInstance] = function() { return 'string'; };
+assert.sameValue(0 instanceof F, true);
+
+F[Symbol.hasInstance] = function() { return Symbol(); };
+assert.sameValue(0 instanceof F, true);
+
+F[Symbol.hasInstance] = function() { return {}; };
+assert.sameValue(0 instanceof F, true);
-- 
GitLab