Clean up some existing constructor checks; eliminate duplicate checks

This commit is contained in:
Rick Waldron 2020-10-02 10:46:09 -04:00
parent c644ede430
commit 12ed905003
16 changed files with 265 additions and 111 deletions

View File

@ -0,0 +1,27 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-ecmascript-standard-built-in-objects
description: >
BigInt does not implement [[Construct]]
info: |
ECMAScript Function Objects
Built-in function objects that are not identified as constructors do not
implement the [[Construct]] internal method unless otherwise specified in
the description of a particular function.
includes: [isConstructor.js]
features: [BigInt, Reflect.construct, arrow-function]
---*/
assert.sameValue(
isConstructor(BigInt),
false,
'isConstructor(BigInt) must return false'
);
assert.throws(TypeError, () => {
new BigInt(1n);
}, '`new BigInt(1n)` throws TypeError');

View File

@ -6,16 +6,19 @@ description: >
Tests that Date.prototype.toJSON meets the requirements Tests that Date.prototype.toJSON meets the requirements
for built-in objects defined by the introduction of chapter 17 of for built-in objects defined by the introduction of chapter 17 of
the ECMAScript Language Specification. the ECMAScript Language Specification.
includes: [isConstructor.js]
features: [Reflect.construct] features: [Reflect.construct]
---*/ ---*/
var toJSON = Date.prototype.toJSON; assert(Object.isExtensible(Date.prototype.toJSON), 'Object.isExtensible(Date.prototype.toJSON) must return true');
assert.sameValue(typeof Date.prototype.toJSON, 'function', 'The value of `typeof Date.prototype.toJSON` is "function"');
assert(Object.isExtensible(toJSON)); assert.sameValue(
assert.sameValue(typeof toJSON, 'function'); Object.prototype.toString.call(Date.prototype.toJSON),
assert.sameValue(Object.prototype.toString.call(toJSON), '[object Function]'); '[object Function]',
assert.sameValue(Object.getPrototypeOf(toJSON), Function.prototype); 'Object.prototype.toString.call(Date.prototype.toJSON) must return "[object Function]"'
);
assert.sameValue(toJSON.hasOwnProperty('prototype'), false); assert.sameValue(
assert.sameValue(isConstructor(toJSON), false); Object.getPrototypeOf(Date.prototype.toJSON),
Function.prototype,
'Object.getPrototypeOf(Date.prototype.toJSON) must return the value of Function.prototype'
);
assert.sameValue(Date.prototype.toJSON.hasOwnProperty('prototype'), false, 'Date.prototype.toJSON.hasOwnProperty("prototype") must return false');

View File

@ -5,15 +5,24 @@ esid: sec-json.parse
description: > description: >
Requirements for built-in functions, defined in introduction of chapter 17, Requirements for built-in functions, defined in introduction of chapter 17,
are satisfied. are satisfied.
includes: [isConstructor.js]
features: [Reflect.construct] features: [Reflect.construct]
---*/ ---*/
var parse = JSON.parse; var parse = JSON.parse;
assert(Object.isExtensible(parse)); assert(Object.isExtensible(parse), 'Object.isExtensible(parse) must return true');
assert.sameValue(typeof parse, 'function'); assert.sameValue(typeof parse, 'function', 'The value of `typeof parse` is "function"');
assert.sameValue(Object.prototype.toString.call(parse), '[object Function]'); assert.sameValue(
assert.sameValue(Object.getPrototypeOf(parse), Function.prototype); Object.prototype.toString.call(parse),
'[object Function]',
assert.sameValue(parse.hasOwnProperty('prototype'), false); 'Object.prototype.toString.call("JSON.parse") must return "[object Function]"'
assert.sameValue(isConstructor(parse), false); );
assert.sameValue(
Object.getPrototypeOf(parse),
Function.prototype,
'Object.getPrototypeOf("JSON.parse") must return the value of Function.prototype'
);
assert.sameValue(
parse.hasOwnProperty('prototype'),
false,
'parse.hasOwnProperty("prototype") must return false'
);

View File

@ -6,12 +6,22 @@ description: >
Tests that JSON.stringify meets the requirements Tests that JSON.stringify meets the requirements
for built-in objects defined by the introduction of chapter 17 of for built-in objects defined by the introduction of chapter 17 of
the ECMAScript Language Specification. the ECMAScript Language Specification.
includes: [isConstructor.js]
features: [Reflect.construct] features: [Reflect.construct]
---*/ ---*/
assert(Object.isExtensible(JSON.stringify)); assert(Object.isExtensible(JSON.stringify), 'Object.isExtensible(JSON.stringify) must return true');
assert.sameValue(Object.prototype.toString.call(JSON.stringify), '[object Function]'); assert.sameValue(
assert.sameValue(Object.getPrototypeOf(JSON.stringify), Function.prototype); Object.prototype.toString.call(JSON.stringify),
assert.sameValue(JSON.stringify.hasOwnProperty('prototype'), false); '[object Function]',
assert.sameValue(isConstructor(JSON.stringify), false); 'Object.prototype.toString.call(JSON.stringify) must return "[object Function]"'
);
assert.sameValue(
Object.getPrototypeOf(JSON.stringify),
Function.prototype,
'Object.getPrototypeOf(JSON.stringify) must return the value of Function.prototype'
);
assert.sameValue(
JSON.stringify.hasOwnProperty('prototype'),
false,
'JSON.stringify.hasOwnProperty("prototype") must return false'
);

View File

@ -7,12 +7,25 @@ description: >
Tests that Object.prototype.isPrototypeOf meets the requirements Tests that Object.prototype.isPrototypeOf meets the requirements
for built-in objects defined by the introduction of chapter 17 of for built-in objects defined by the introduction of chapter 17 of
the ECMAScript Language Specification. the ECMAScript Language Specification.
includes: [isConstructor.js]
features: [Reflect.construct] features: [Reflect.construct]
---*/ ---*/
assert(Object.isExtensible(Object.prototype.isPrototypeOf)); assert(
assert.sameValue(Object.prototype.toString.call(Object.prototype.isPrototypeOf), "[object Function]"); Object.isExtensible(Object.prototype.isPrototypeOf),
assert.sameValue(Object.getPrototypeOf(Object.prototype.isPrototypeOf), Function.prototype); 'Object.isExtensible(Object.prototype.isPrototypeOf) must return true'
assert.sameValue(Object.prototype.isPrototypeOf.hasOwnProperty("prototype"), false); );
assert.sameValue(isConstructor(Object.prototype.isPrototypeOf), false); assert.sameValue(
Object.prototype.toString.call(Object.prototype.isPrototypeOf),
"[object Function]",
'Object.prototype.toString.call(Object.prototype.isPrototypeOf) must return "[object Function]"'
);
assert.sameValue(
Object.getPrototypeOf(Object.prototype.isPrototypeOf),
Function.prototype,
'Object.getPrototypeOf(Object.prototype.isPrototypeOf) must return the value of Function.prototype'
);
assert.sameValue(
Object.prototype.isPrototypeOf.hasOwnProperty("prototype"),
false,
'Object.prototype.isPrototypeOf.hasOwnProperty("prototype") must return false'
);

View File

@ -9,7 +9,7 @@ info: |
... ...
7. Let reject be ! CreateBuiltinFunction(stepsReject, « [[Promise]], [[AlreadyResolved]] »). 7. Let reject be ! CreateBuiltinFunction(stepsReject, « [[Promise]], [[AlreadyResolved]] »).
features: [Reflect.construct] features: [Reflect.construct, arrow-function]
includes: [isConstructor.js] includes: [isConstructor.js]
flags: [async] flags: [async]
---*/ ---*/
@ -20,9 +20,13 @@ Promise.resolve(1).then(function() {
var then = Promise.prototype.then; var then = Promise.prototype.then;
Promise.prototype.then = function(resolve, reject) { Promise.prototype.then = function(resolve, reject) {
assert(!isConstructor(reject)); assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false');
assert.sameValue(reject.length, 1); assert.throws(TypeError, () => {
assert.sameValue(reject.name, ''); new reject();
}, '`new reject()` throws TypeError');
assert.sameValue(reject.length, 1, 'The value of reject.length is 1');
assert.sameValue(reject.name, '', 'The value of reject.name is ""');
return then.call(this, resolve, reject); return then.call(this, resolve, reject);
}; };

View File

@ -9,7 +9,7 @@ info: |
... ...
3. Let resolve be ! CreateBuiltinFunction(stepsResolve, « [[Promise]], [[AlreadyResolved]] »). 3. Let resolve be ! CreateBuiltinFunction(stepsResolve, « [[Promise]], [[AlreadyResolved]] »).
features: [Reflect.construct] features: [Reflect.construct, arrow-function]
includes: [isConstructor.js] includes: [isConstructor.js]
flags: [async] flags: [async]
---*/ ---*/
@ -20,9 +20,13 @@ Promise.resolve(1).then(function() {
var then = Promise.prototype.then; var then = Promise.prototype.then;
Promise.prototype.then = function(resolve, reject) { Promise.prototype.then = function(resolve, reject) {
assert(!isConstructor(resolve)); assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false');
assert.sameValue(resolve.length, 1); assert.throws(TypeError, () => {
assert.sameValue(resolve.name, ''); new resolve();
}, '`new resolve()` throws TypeError');
assert.sameValue(resolve.length, 1, 'The value of resolve.length is 1');
assert.sameValue(resolve.name, '', 'The value of resolve.name is ""');
return then.call(this, resolve, reject); return then.call(this, resolve, reject);
}; };

View File

@ -10,7 +10,7 @@ info: |
implement the [[Construct]] internal method unless otherwise specified implement the [[Construct]] internal method unless otherwise specified
in the description of a particular function. in the description of a particular function.
includes: [isConstructor.js] includes: [isConstructor.js]
features: [Reflect.construct] features: [Reflect.construct, arrow-function]
---*/ ---*/
var executorFunction; var executorFunction;
@ -21,5 +21,14 @@ function NotPromise(executor) {
} }
Promise.resolve.call(NotPromise); Promise.resolve.call(NotPromise);
assert.sameValue(Object.prototype.hasOwnProperty.call(executorFunction, "prototype"), false); assert.sameValue(
assert.sameValue(isConstructor(executorFunction), false); Object.prototype.hasOwnProperty.call(executorFunction, "prototype"),
false,
'Object.prototype.hasOwnProperty.call(executorFunction, "prototype") must return false'
);
assert.sameValue(isConstructor(executorFunction), false, 'isConstructor(executorFunction) must return false');
assert.throws(TypeError, () => {
new executorFunction();
}, '`new executorFunction()` throws TypeError');

View File

@ -4,7 +4,7 @@
author: Jordan Harband author: Jordan Harband
description: Promise.prototype.finally invokes `then` method description: Promise.prototype.finally invokes `then` method
esid: sec-promise.prototype.finally esid: sec-promise.prototype.finally
features: [Promise.prototype.finally, Reflect.construct] features: [Promise.prototype.finally, Reflect.construct, arrow-function]
includes: [isConstructor.js] includes: [isConstructor.js]
---*/ ---*/
@ -13,16 +13,16 @@ var returnValue = {};
var callCount = 0; var callCount = 0;
var thisValue = null; var thisValue = null;
var argCount = null; var argCount = null;
var firstArg = null; var resolve = null;
var secondArg = null; var reject = null;
target.then = function(a, b) { target.then = function(a, b) {
callCount += 1; callCount += 1;
thisValue = this; thisValue = this;
argCount = arguments.length; argCount = arguments.length;
firstArg = a; resolve = a;
secondArg = b; reject = b;
return returnValue; return returnValue;
}; };
@ -30,31 +30,38 @@ target.then = function(a, b) {
var originalFinallyHandler = function() {}; var originalFinallyHandler = function() {};
var result = Promise.prototype.finally.call(target, originalFinallyHandler, 2, 3); var result = Promise.prototype.finally.call(target, originalFinallyHandler, 2, 3);
assert.sameValue(callCount, 1, 'Invokes `then` method exactly once'); assert.sameValue(callCount, 1, 'The value of `callCount` is 1');
assert.sameValue( assert.sameValue(
thisValue, thisValue,
target, target,
'Invokes `then` method with the instance as the `this` value' 'The value of `thisValue` is expected to equal the value of target'
); );
assert.sameValue(argCount, 2, 'Invokes `then` method with exactly two single arguments'); assert.sameValue(argCount, 2, 'The value of `argCount` is 2');
assert.sameValue( assert.sameValue(
typeof firstArg, typeof resolve,
'function', 'function',
'Invokes `then` method with a function as the first argument' 'The value of `typeof resolve` is "function"'
); );
assert.notSameValue(firstArg, originalFinallyHandler, 'Invokes `then` method with a different fulfillment handler'); assert.notSameValue(resolve, originalFinallyHandler, 'The value of `resolve` is expected to not equal the value of `originalFinallyHandler`');
assert.sameValue(firstArg.length, 1, 'fulfillment handler has a length of 1'); assert.sameValue(resolve.length, 1, 'The value of resolve.length is 1');
assert.sameValue(firstArg.name, '', 'fulfillment handler is anonymous'); assert.sameValue(resolve.name, '', 'The value of resolve.name is ""');
assert(!isConstructor(firstArg), 'fulfillment handler is not constructor'); assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false');
assert.throws(TypeError, () => {
new resolve();
}, '`new resolve()` throws TypeError');
assert.sameValue( assert.sameValue(
typeof secondArg, typeof reject,
'function', 'function',
'Invokes `then` method with a function as the second argument' 'The value of `typeof reject` is "function"'
); );
assert.notSameValue(secondArg, originalFinallyHandler, 'Invokes `then` method with a different rejection handler'); assert.notSameValue(reject, originalFinallyHandler, 'The value of `reject` is expected to not equal the value of `originalFinallyHandler`');
assert.sameValue(secondArg.length, 1, 'rejection handler has a length of 1'); assert.sameValue(reject.length, 1, 'The value of reject.length is 1');
assert.sameValue(secondArg.name, '', 'rejection handler is anonymous'); assert.sameValue(reject.name, '', 'The value of reject.name is ""');
assert(!isConstructor(secondArg), 'rejection handler is not constructor'); assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false');
assert.throws(TypeError, () => {
new reject();
}, '`new reject()` throws TypeError');
assert.sameValue(result, returnValue, 'Returns the result of the invocation of `then`'); assert.sameValue(result, returnValue, 'The value of `result` is expected to equal the value of returnValue');

View File

@ -12,7 +12,7 @@ info: |
9. Return ? Invoke(promise, "then", « thrower »). 9. Return ? Invoke(promise, "then", « thrower »).
The "length" property of a Catch Finally function is 1. The "length" property of a Catch Finally function is 1.
features: [Promise.prototype.finally, Reflect.construct] features: [Promise.prototype.finally, Reflect.construct, class, arrow-function]
includes: [isConstructor.js] includes: [isConstructor.js]
flags: [async] flags: [async]
---*/ ---*/
@ -40,11 +40,23 @@ var expected = [
var then = Promise.prototype.then; var then = Promise.prototype.then;
Promise.prototype.then = function(resolve, reject) { Promise.prototype.then = function(resolve, reject) {
assert(!isConstructor(resolve)); assert.sameValue(isConstructor(reject), false, 'isConstructor(reject) must return false');
assert.sameValue(resolve.length, expected[calls].length); assert.throws(TypeError, () => {
assert.sameValue(resolve.name, expected[calls].name); new reject();
}, '`new reject()` throws TypeError');
assert.sameValue(
resolve.length,
expected[calls].length,
'The value of resolve.length is expected to equal the value of expected[calls].length'
);
assert.sameValue(
resolve.name,
expected[calls].name,
'The value of resolve.name is expected to equal the value of expected[calls].name'
);
if (calls === 0) { if (calls === 0) {
assert.throws(MyError, resolve); assert.throws(MyError, resolve, '`resolve()` throws `MyError`');
} }
calls += 1; calls += 1;

View File

@ -12,7 +12,7 @@ info: |
9. Return ? Invoke(promise, "then", « valueThunk »). 9. Return ? Invoke(promise, "then", « valueThunk »).
The "length" property of a Then Finally function is 1. The "length" property of a Then Finally function is 1.
features: [Promise.prototype.finally, Reflect.construct] features: [Promise.prototype.finally, Reflect.construct, arrow-function]
includes: [isConstructor.js] includes: [isConstructor.js]
flags: [async] flags: [async]
---*/ ---*/
@ -31,11 +31,23 @@ var expected = [
var then = Promise.prototype.then; var then = Promise.prototype.then;
Promise.prototype.then = function(resolve) { Promise.prototype.then = function(resolve) {
assert(!isConstructor(resolve)); assert.sameValue(isConstructor(resolve), false, 'isConstructor(resolve) must return false');
assert.sameValue(resolve.length, expected[calls].length); assert.throws(TypeError, () => {
assert.sameValue(resolve.name, expected[calls].name); new resolve();
}, '`new resolve()` throws TypeError');
assert.sameValue(
resolve.length,
expected[calls].length,
'The value of resolve.length is expected to equal the value of expected[calls].length'
);
assert.sameValue(
resolve.name,
expected[calls].name,
'The value of resolve.name is expected to equal the value of expected[calls].name'
);
if (calls === 0) { if (calls === 0) {
assert.sameValue(resolve(), value); assert.sameValue(resolve(), value, 'resolve() must return the value of value');
} }
calls += 1; calls += 1;
return then.call(this, resolve); return then.call(this, resolve);

View File

@ -0,0 +1,31 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-proxycreate
description: >
A Proxy exotic object only accepts a constructor call if target is
constructor.
info: |
ProxyCreate ( target, handler )
If IsCallable(target) is true, then
Set P.[[Call]] as specified in 9.5.12.
If IsConstructor(target) is true, then
Set P.[[Construct]] as specified in 9.5.13.
...
Runtime Semantics: EvaluateNew(constructProduction, arguments)
8. If IsConstructor (constructor) is false, throw a TypeError exception.
includes: [isConstructor.js]
features: [Proxy, Reflect.construct, arrow-function]
---*/
var proxy = new Proxy(eval, {});
proxy(); // the Proxy object is callable
assert.sameValue(isConstructor(proxy), false, 'isConstructor(proxy) must return false');
assert.throws(TypeError, () => {
new proxy();
}, '`new proxy()` throws TypeError');

View File

@ -1,29 +0,0 @@
// Copyright (C) 2015 the V8 project authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
es6id: 9.5.15
description: >
A Proxy exotic object only accepts a constructor call if target is
constructor.
info: |
Proxy ( target, handler )
7. If IsCallable(target) is true, then
b. If target has a [[Construct]] internal method, then
i. Set the [[Construct]] internal method of P as specified in
9.5.14.
...
12.3.3.1.1 Runtime Semantics: EvaluateNew(constructProduction, arguments)
8. If IsConstructor (constructor) is false, throw a TypeError exception.
features: [Proxy]
---*/
var p = new Proxy(eval, {});
p(); // the Proxy object is callable
assert.throws(TypeError, function() {
new p();
});

View File

@ -5,14 +5,24 @@ esid: sec-proxy.revocable
description: > description: >
Requirements for built-in functions, defined in introduction of chapter 17, Requirements for built-in functions, defined in introduction of chapter 17,
are satisfied. are satisfied.
includes: [isConstructor.js]
features: [Proxy, Reflect.construct] features: [Proxy, Reflect.construct]
---*/ ---*/
assert(Object.isExtensible(Proxy.revocable)); assert(Object.isExtensible(Proxy.revocable), 'Object.isExtensible(Proxy.revocable) must return true');
assert.sameValue(typeof Proxy.revocable, 'function'); assert.sameValue(typeof Proxy.revocable, 'function', 'The value of `typeof Proxy.revocable` is "function"');
assert.sameValue(Object.prototype.toString.call(Proxy.revocable), '[object Function]'); assert.sameValue(
assert.sameValue(Object.getPrototypeOf(Proxy.revocable), Function.prototype); Object.prototype.toString.call(Proxy.revocable),
'[object Function]',
'Object.prototype.toString.call(Proxy.revocable) must return "[object Function]"'
);
assert.sameValue(
Object.getPrototypeOf(Proxy.revocable),
Function.prototype,
'Object.getPrototypeOf(Proxy.revocable) must return the value of Function.prototype'
);
assert.sameValue(Proxy.revocable.hasOwnProperty('prototype'), false); assert.sameValue(
assert.sameValue(isConstructor(Proxy.revocable), false); Proxy.revocable.hasOwnProperty('prototype'),
false,
'Proxy.revocable.hasOwnProperty(\'prototype\') must return false'
);

View File

@ -0,0 +1,23 @@
// Copyright (C) 2020 Rick Waldron. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/*---
esid: sec-ecmascript-standard-built-in-objects
description: >
Proxy.revocable does not implement [[Construct]]
info: |
ECMAScript Function Objects
Built-in function objects that are not identified as constructors do not
implement the [[Construct]] internal method unless otherwise specified in
the description of a particular function.
includes: [isConstructor.js]
features: [Reflect.construct, Reflect, arrow-function, Proxy]
---*/
assert.sameValue(isConstructor(Proxy.revocable), false, 'isConstructor(Proxy.revocable) must return false');
assert.throws(TypeError, () => {
new Proxy.revocable({}, {});
}, '`new Proxy.revocable({}, {})` throws TypeError');

View File

@ -10,10 +10,19 @@ info: |
implement the [[Construct]] internal method unless otherwise specified implement the [[Construct]] internal method unless otherwise specified
in the description of a particular function. in the description of a particular function.
includes: [isConstructor.js] includes: [isConstructor.js]
features: [Proxy, Reflect.construct] features: [Proxy, Reflect.construct, arrow-function]
---*/ ---*/
var revocationFunction = Proxy.revocable({}, {}).revoke; var revocationFunction = Proxy.revocable({}, {}).revoke;
assert.sameValue(Object.prototype.hasOwnProperty.call(revocationFunction, "prototype"), false); assert.sameValue(
assert.sameValue(isConstructor(revocationFunction), false); Object.prototype.hasOwnProperty.call(revocationFunction, "prototype"),
false,
'Object.prototype.hasOwnProperty.call(revocationFunction, "prototype") must return false'
);
assert.sameValue(isConstructor(revocationFunction), false, 'isConstructor(revocationFunction) must return false');
assert.throws(TypeError, () => {
new revocationFunction();
}, '`new revocationFunction()` throws TypeError');