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