From c55d2ab7c344e35a3ceb93cf1d4d30019584db82 Mon Sep 17 00:00:00 2001 From: Rick Waldron <waldron.rick@gmail.com> Date: Thu, 19 Apr 2018 16:44:52 -0400 Subject: [PATCH] Extensive Function toString updates for "Function.prototype.toString revision" proposal. (#1510) Fixes gh-1453 --- harness/nativeFunctionMatcher.js | 16 +- harness/wellKnownIntrinsicObjects.js | 458 ++++++++++++++++++ .../toString/anonymous-intrinsics.js | 12 - .../prototype/toString/bound-function.js | 15 +- .../toString/built-in-function-object.js | 48 ++ .../Function/prototype/toString/intrinsics.js | 24 - .../toString/proxy-arrow-function.js | 22 + .../toString/proxy-async-function.js | 22 + .../proxy-async-generator-function.js | 22 + ...proxy-async-generator-method-definition.js | 22 + .../toString/proxy-async-method-definition.js | 22 + .../toString/proxy-bound-function.js | 22 + .../prototype/toString/proxy-class.js | 22 + .../toString/proxy-function-expression.js | 22 + .../toString/proxy-generator-function.js | 22 + .../toString/proxy-method-definition.js | 22 + .../toString/proxy-non-callable-throws.js | 16 + .../Function/prototype/toString/proxy.js | 17 - .../well-known-intrinsic-object-functions.js | 28 ++ 19 files changed, 792 insertions(+), 62 deletions(-) create mode 100644 harness/wellKnownIntrinsicObjects.js delete mode 100644 test/built-ins/Function/prototype/toString/anonymous-intrinsics.js create mode 100644 test/built-ins/Function/prototype/toString/built-in-function-object.js delete mode 100644 test/built-ins/Function/prototype/toString/intrinsics.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-arrow-function.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-async-function.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-async-generator-function.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-async-generator-method-definition.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-async-method-definition.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-bound-function.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-class.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-function-expression.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-generator-function.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-method-definition.js create mode 100644 test/built-ins/Function/prototype/toString/proxy-non-callable-throws.js delete mode 100644 test/built-ins/Function/prototype/toString/proxy.js create mode 100644 test/built-ins/Function/prototype/toString/well-known-intrinsic-object-functions.js diff --git a/harness/nativeFunctionMatcher.js b/harness/nativeFunctionMatcher.js index 52120ea48e..9b43d8f4d7 100644 --- a/harness/nativeFunctionMatcher.js +++ b/harness/nativeFunctionMatcher.js @@ -1,9 +1,14 @@ // Copyright (C) 2017 Ecma International. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. /*--- -description: | +description: Assert _NativeFunction_ Syntax +info: | This regex makes a best-effort determination that the tested string matches the NativeFunction grammar production without requiring a correct tokeniser. + + NativeFunction : + function _IdentifierName_ opt ( _FormalParameters_ ) { [ native code ] } + ---*/ const NATIVE_FUNCTION_RE = /\bfunction\b[\s\S]*\([\s\S]*\)[\s\S]*\{[\s\S]*\[[\s\S]*\bnative\b[\s\S]+\bcode\b[\s\S]*\][\s\S]*\}/; @@ -12,11 +17,14 @@ const assertToStringOrNativeFunction = function(fn, expected) { try { assert.sameValue(actual, expected); } catch (unused) { - assertNativeFunction(fn); + assertNativeFunction(fn, expected); } }; -const assertNativeFunction = function(fn) { +const assertNativeFunction = function(fn, special) { const actual = "" + fn; - assert(NATIVE_FUNCTION_RE.test(actual), "looks pretty much like a NativeFunction"); + assert( + NATIVE_FUNCTION_RE.test(actual), + "Conforms to NativeFunction Syntax: '" + actual + "'." + (special ? "(" + special + ")" : "") + ); }; diff --git a/harness/wellKnownIntrinsicObjects.js b/harness/wellKnownIntrinsicObjects.js new file mode 100644 index 0000000000..2c1ce9df82 --- /dev/null +++ b/harness/wellKnownIntrinsicObjects.js @@ -0,0 +1,458 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +description: | + An Array of all representable Well-Known Intrinsic Objects +---*/ + +const WellKnownIntrinsicObjects = [ + { + intrinsicName: "%Array%", + globalNameOrSource: "Array" + }, + { + intrinsicName: "%ArrayBuffer%", + globalNameOrSource: "ArrayBuffer" + }, + { + intrinsicName: "%ArrayBufferPrototype%", + globalNameOrSource: "ArrayBuffer.prototype" + }, + { + intrinsicName: "%ArrayIteratorPrototype%", + globalNameOrSource: "Object.getPrototypeOf([][Symbol.iterator]())" + }, + { + intrinsicName: "%ArrayPrototype%", + globalNameOrSource: "Array.prototype" + }, + { + intrinsicName: "%ArrayProto_entries%", + globalNameOrSource: "Array.prototype.entries" + }, + { + intrinsicName: "%ArrayProto_forEach%", + globalNameOrSource: "Array.prototype.forEach" + }, + { + intrinsicName: "%ArrayProto_keys%", + globalNameOrSource: "Array.prototype.keys" + }, + { + intrinsicName: "%ArrayProto_values%", + globalNameOrSource: "Array.prototype.values" + }, + { + intrinsicName: "%AsyncFromSyncIteratorPrototype%", + globalNameOrSource: "undefined" + }, + { + intrinsicName: "%AsyncFunction%", + globalNameOrSource: "(async function() {}).constructor" + }, + { + intrinsicName: "%AsyncFunctionPrototype%", + globalNameOrSource: "(async function() {}).constructor.prototype" + }, + { + intrinsicName: "%AsyncGenerator%", + globalNameOrSource: "Object.getPrototypeOf((async function * () {})())" + }, + { + intrinsicName: "%AsyncGeneratorFunction%", + globalNameOrSource: "Object.getPrototypeOf(async function * () {})" + }, + { + intrinsicName: "%AsyncGeneratorPrototype%", + globalNameOrSource: "Object.getPrototypeOf(async function * () {}).prototype" + }, + { + intrinsicName: "%AsyncIteratorPrototype%", + globalNameOrSource: "((async function * () {})())[Symbol.asyncIterator]()" + }, + { + intrinsicName: "%Atomics%", + globalNameOrSource: "Atomics" + }, + { + intrinsicName: "%Boolean%", + globalNameOrSource: "Boolean" + }, + { + intrinsicName: "%BooleanPrototype%", + globalNameOrSource: "Boolean.prototype" + }, + { + intrinsicName: "%DataView%", + globalNameOrSource: "DataView" + }, + { + intrinsicName: "%DataViewPrototype%", + globalNameOrSource: "DataView.prototype" + }, + { + intrinsicName: "%Date%", + globalNameOrSource: "Date" + }, + { + intrinsicName: "%DatePrototype%", + globalNameOrSource: "Date.prototype" + }, + { + intrinsicName: "%decodeURI%", + globalNameOrSource: "decodeURI" + }, + { + intrinsicName: "%decodeURIComponent%", + globalNameOrSource: "decodeURIComponent" + }, + { + intrinsicName: "%encodeURI%", + globalNameOrSource: "encodeURI" + }, + { + intrinsicName: "%encodeURIComponent%", + globalNameOrSource: "encodeURIComponent" + }, + { + intrinsicName: "%Error%", + globalNameOrSource: "Error" + }, + { + intrinsicName: "%ErrorPrototype%", + globalNameOrSource: "Error.prototype" + }, + { + intrinsicName: "%eval%", + globalNameOrSource: "eval" + }, + { + intrinsicName: "%EvalError%", + globalNameOrSource: "EvalError" + }, + { + intrinsicName: "%EvalErrorPrototype%", + globalNameOrSource: "EvalError.prototype" + }, + { + intrinsicName: "%Float32Array%", + globalNameOrSource: "Float32Array" + }, + { + intrinsicName: "%Float32ArrayPrototype%", + globalNameOrSource: "Float32Array.prototype" + }, + { + intrinsicName: "%Float64Array%", + globalNameOrSource: "Float64Array" + }, + { + intrinsicName: "%Float64ArrayPrototype%", + globalNameOrSource: "Float64Array.prototype" + }, + { + intrinsicName: "%Function%", + globalNameOrSource: "Function" + }, + { + intrinsicName: "%FunctionPrototype%", + globalNameOrSource: "Function.prototype" + }, + { + intrinsicName: "%Generator%", + globalNameOrSource: "Object.getPrototypeOf((function * () {})())" + }, + { + intrinsicName: "%GeneratorFunction%", + globalNameOrSource: "Object.getPrototypeOf(function * () {})" + }, + { + intrinsicName: "%GeneratorPrototype%", + globalNameOrSource: "Object.getPrototypeOf(function * () {}).prototype" + }, + { + intrinsicName: "%Int8Array%", + globalNameOrSource: "Int8Array" + }, + { + intrinsicName: "%Int8ArrayPrototype%", + globalNameOrSource: "Int8Array.prototype" + }, + { + intrinsicName: "%Int16Array%", + globalNameOrSource: "Int16Array" + }, + { + intrinsicName: "%Int16ArrayPrototype%", + globalNameOrSource: "Int16Array.prototype" + }, + { + intrinsicName: "%Int32Array%", + globalNameOrSource: "Int32Array" + }, + { + intrinsicName: "%Int32ArrayPrototype%", + globalNameOrSource: "Int32Array.prototype" + }, + { + intrinsicName: "%isFinite%", + globalNameOrSource: "isFinite" + }, + { + intrinsicName: "%isNaN%", + globalNameOrSource: "isNaN" + }, + { + intrinsicName: "%IteratorPrototype%", + globalNameOrSource: "Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))" + }, + { + intrinsicName: "%JSON%", + globalNameOrSource: "JSON" + }, + { + intrinsicName: "%JSONParse%", + globalNameOrSource: "JSON.parse" + }, + { + intrinsicName: "%Map%", + globalNameOrSource: "Map" + }, + { + intrinsicName: "%MapIteratorPrototype%", + globalNameOrSource: "Object.getPrototypeOf(new Map()[Symbol.iterator]())" + }, + { + intrinsicName: "%MapPrototype%", + globalNameOrSource: "Map.prototype" + }, + { + intrinsicName: "%Math%", + globalNameOrSource: "Math" + }, + { + intrinsicName: "%Number%", + globalNameOrSource: "Number" + }, + { + intrinsicName: "%NumberPrototype%", + globalNameOrSource: "Number.prototype" + }, + { + intrinsicName: "%Object%", + globalNameOrSource: "Object" + }, + { + intrinsicName: "%ObjectPrototype%", + globalNameOrSource: "Object.prototype" + }, + { + intrinsicName: "%ObjProto_toString%", + globalNameOrSource: "Object.prototype.toString" + }, + { + intrinsicName: "%ObjProto_valueOf%", + globalNameOrSource: "Object.prototype.valueOf" + }, + { + intrinsicName: "%parseFloat%", + globalNameOrSource: "parseFloat" + }, + { + intrinsicName: "%parseInt%", + globalNameOrSource: "parseInt" + }, + { + intrinsicName: "%Promise%", + globalNameOrSource: "Promise" + }, + { + intrinsicName: "%PromisePrototype%", + globalNameOrSource: "Promise.prototype" + }, + { + intrinsicName: "%PromiseProto_then%", + globalNameOrSource: "Promise.prototype.then" + }, + { + intrinsicName: "%Promise_all%", + globalNameOrSource: "Promise.all" + }, + { + intrinsicName: "%Promise_reject%", + globalNameOrSource: "Promise.reject" + }, + { + intrinsicName: "%Promise_resolve%", + globalNameOrSource: "Promise.resolve" + }, + { + intrinsicName: "%Proxy%", + globalNameOrSource: "Proxy" + }, + { + intrinsicName: "%RangeError%", + globalNameOrSource: "RangeError" + }, + { + intrinsicName: "%RangeErrorPrototype%", + globalNameOrSource: "RangeError.prototype" + }, + { + intrinsicName: "%ReferenceError%", + globalNameOrSource: "ReferenceError" + }, + { + intrinsicName: "%ReferenceErrorPrototype%", + globalNameOrSource: "ReferenceError.prototype" + }, + { + intrinsicName: "%Reflect%", + globalNameOrSource: "Reflect" + }, + { + intrinsicName: "%RegExp%", + globalNameOrSource: "RegExp" + }, + { + intrinsicName: "%RegExpPrototype%", + globalNameOrSource: "RegExp.prototype" + }, + { + intrinsicName: "%Set%", + globalNameOrSource: "Set" + }, + { + intrinsicName: "%SetIteratorPrototype%", + globalNameOrSource: "Object.getPrototypeOf(new Set()[Symbol.iterator]())" + }, + { + intrinsicName: "%SetPrototype%", + globalNameOrSource: "Set.prototype" + }, + { + intrinsicName: "%SharedArrayBuffer%", + globalNameOrSource: "SharedArrayBuffer" + }, + { + intrinsicName: "%SharedArrayBufferPrototype%", + globalNameOrSource: "SharedArrayBuffer.prototype" + }, + { + intrinsicName: "%String%", + globalNameOrSource: "String" + }, + { + intrinsicName: "%StringIteratorPrototype%", + globalNameOrSource: "Object.getPrototypeOf(new String()[Symbol.iterator]())" + }, + { + intrinsicName: "%StringPrototype%", + globalNameOrSource: "String.prototype" + }, + { + intrinsicName: "%Symbol%", + globalNameOrSource: "Symbol" + }, + { + intrinsicName: "%SymbolPrototype%", + globalNameOrSource: "Symbol.prototype" + }, + { + intrinsicName: "%SyntaxError%", + globalNameOrSource: "SyntaxError" + }, + { + intrinsicName: "%SyntaxErrorPrototype%", + globalNameOrSource: "SyntaxError.prototype" + }, + { + intrinsicName: "%ThrowTypeError%", + globalNameOrSource: "(function() { 'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'callee').get })()" + }, + { + intrinsicName: "%TypedArray%", + globalNameOrSource: "Object.getPrototypeOf(Uint8Array)" + }, + { + intrinsicName: "%TypedArrayPrototype%", + globalNameOrSource: "Object.getPrototypeOf(Uint8Array).prototype" + }, + { + intrinsicName: "%TypeError%", + globalNameOrSource: "TypeError" + }, + { + intrinsicName: "%TypeErrorPrototype%", + globalNameOrSource: "TypeError.prototype" + }, + { + intrinsicName: "%Uint8Array%", + globalNameOrSource: "Uint8Array" + }, + { + intrinsicName: "%Uint8ArrayPrototype%", + globalNameOrSource: "Uint8Array.prototype" + }, + { + intrinsicName: "%Uint8ClampedArray%", + globalNameOrSource: "Uint8ClampedArray" + }, + { + intrinsicName: "%Uint8ClampedArrayPrototype%", + globalNameOrSource: "Uint8ClampedArray.prototype" + }, + { + intrinsicName: "%Uint16Array%", + globalNameOrSource: "Uint16Array" + }, + { + intrinsicName: "%Uint16ArrayPrototype%", + globalNameOrSource: "Uint16Array.prototype" + }, + { + intrinsicName: "%Uint32Array%", + globalNameOrSource: "Uint32Array" + }, + { + intrinsicName: "%Uint32ArrayPrototype%", + globalNameOrSource: "Uint32Array.prototype" + }, + { + intrinsicName: "%URIError%", + globalNameOrSource: "URIError" + }, + { + intrinsicName: "%URIErrorPrototype%", + globalNameOrSource: "URIError.prototype" + }, + { + intrinsicName: "%WeakMap%", + globalNameOrSource: "WeakMap" + }, + { + intrinsicName: "%WeakMapPrototype%", + globalNameOrSource: "WeakMap.prototype" + }, + { + intrinsicName: "%WeakSet%", + globalNameOrSource: "WeakSet" + }, + { + intrinsicName: "%WeakSetPrototype%", + globalNameOrSource: "WeakSet.prototype" + } +]; + + +WellKnownIntrinsicObjects.forEach(wkio => { + var actual; + + try { + actual = new Function("return " + wkio.globalNameOrSource)(); + } catch (exception) { + // Nothing to do here. + } + + wkio.reference = actual; +}); diff --git a/test/built-ins/Function/prototype/toString/anonymous-intrinsics.js b/test/built-ins/Function/prototype/toString/anonymous-intrinsics.js deleted file mode 100644 index 6c6783e339..0000000000 --- a/test/built-ins/Function/prototype/toString/anonymous-intrinsics.js +++ /dev/null @@ -1,12 +0,0 @@ -// Copyright (C) 2018 Michael Ficarra. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-function.prototype.tostring -description: Function.prototype.toString on anonymous well-known intrinsic function objects -includes: [nativeFunctionMatcher.js] ----*/ - -var ThrowTypeError = (function() { "use strict"; return Object.getOwnPropertyDescriptor(arguments, "callee").get })() -assert.sameValue(ThrowTypeError.name, ""); -assertNativeFunction(ThrowTypeError); diff --git a/test/built-ins/Function/prototype/toString/bound-function.js b/test/built-ins/Function/prototype/toString/bound-function.js index 20881fb71e..1d4ab3a4e0 100644 --- a/test/built-ins/Function/prototype/toString/bound-function.js +++ b/test/built-ins/Function/prototype/toString/bound-function.js @@ -1,12 +1,17 @@ // Copyright (C) 2016 Michael Ficarra. All rights reserved. +// Copyright (C) 2018 the V8 project authors. All rights reserved. // This code is governed by the BSD license found in the LICENSE file. - /*--- esid: sec-function.prototype.tostring -description: Function.prototype.toString on bound function exotic objects +description: > + toString bound function does not throw (bound Function Expression) +info: | + ... + If func is a Bound Function exotic object or a built-in Function object, + then return an implementation-dependent String source code representation + of func. The representation must have the syntax of a NativeFunction + ... includes: [nativeFunctionMatcher.js] ---*/ -let f = function(){}.bind(null); - -assertNativeFunction(f); +assertNativeFunction(function() {}.bind({})); diff --git a/test/built-ins/Function/prototype/toString/built-in-function-object.js b/test/built-ins/Function/prototype/toString/built-in-function-object.js new file mode 100644 index 0000000000..a87201a7e4 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/built-in-function-object.js @@ -0,0 +1,48 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of built-in Function object +info: | + ... + If func is a Bound Function exotic object or a built-in Function object, then return an implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +includes: [fnGlobalObject.js, nativeFunctionMatcher.js, wellKnownIntrinsicObjects.js] +features: [arrow-function] +---*/ + +var visited = []; +var verified = []; + +function visit(object) { + if (visited.includes(object)) { + return; + } + + visited.push(object); + + if (typeof object === "function") { + assertNativeFunction(object); + verified.push(object.name); + } + + for (var property of Object.getOwnPropertyNames(object)) { + if (typeof object[property] === "function" || + typeof object[property] === "object") { + try { + visit(object[property], assertNativeFunction); + } catch(error) { + /* we don't actually want to do anything about failures here */ + } + } + } +} + +visit(WellKnownIntrinsicObjects.map(wkio => wkio.reference)); +assert.notSameValue(verified.length, 0); diff --git a/test/built-ins/Function/prototype/toString/intrinsics.js b/test/built-ins/Function/prototype/toString/intrinsics.js deleted file mode 100644 index 7cb08d4ba8..0000000000 --- a/test/built-ins/Function/prototype/toString/intrinsics.js +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (C) 2016 Michael Ficarra. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-function.prototype.tostring -description: Function.prototype.toString on well-known intrinsic function objects -includes: [nativeFunctionMatcher.js] ----*/ - -let intrinsics = { - Array, ArrayBuffer, Boolean, DataView, Date, decodeURI, decodeURIComponent, encodeURI, - encodeURIComponent, Error, eval, EvalError, Float32Array, Float64Array, Function, Int8Array, - Int16Array, Int32Array, isFinite, isNaN, Map, Number, Object, parseFloat, parseInt, Promise, - Proxy, RangeError, ReferenceError, RegExp, Set, String, Symbol, SyntaxError, TypeError, - Uint8Array, Uint8ClampedArray, Uint16Array, Uint32Array, URIError, WeakMap, WeakSet, -}; - -for (let intrinsicName in intrinsics) { - let intrinsic = intrinsics[intrinsicName]; - let str = Function.prototype.toString.call(intrinsic); - assert.sameValue(typeof str, "string"); - assert(RegExp('\\b' + intrinsicName + '\\b').test(str), "contains its name"); - assertNativeFunction(intrinsic); -} diff --git a/test/built-ins/Function/prototype/toString/proxy-arrow-function.js b/test/built-ins/Function/prototype/toString/proxy-arrow-function.js new file mode 100644 index 0000000000..05d151a499 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-arrow-function.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Arrow Function) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [arrow-function, Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy(() => {}, {})); +assertNativeFunction(new Proxy(() => {}, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-async-function.js b/test/built-ins/Function/prototype/toString/proxy-async-function.js new file mode 100644 index 0000000000..14524c72b1 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-async-function.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Async Function Expression) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [async-functions, Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy(async function() {}, {})); +assertNativeFunction(new Proxy(async function() {}, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-async-generator-function.js b/test/built-ins/Function/prototype/toString/proxy-async-generator-function.js new file mode 100644 index 0000000000..0a9ec13853 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-async-generator-function.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Async Generator Function Expression) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [async-functions, generators, Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy(async function * () {}, {})); +assertNativeFunction(new Proxy(async function * () {}, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-async-generator-method-definition.js b/test/built-ins/Function/prototype/toString/proxy-async-generator-method-definition.js new file mode 100644 index 0000000000..c7d8d874ab --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-async-generator-method-definition.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Async Generator Method Definition) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [async-functions, generators, Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy({ async * method() {} }.method, {})); +assertNativeFunction(new Proxy({ async * method() {} }.method, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-async-method-definition.js b/test/built-ins/Function/prototype/toString/proxy-async-method-definition.js new file mode 100644 index 0000000000..c75842e6a7 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-async-method-definition.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Async Method Definition) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [async-functions, generators, Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy({ async method() {} }.method, {})); +assertNativeFunction(new Proxy({ async method() {} }.method, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-bound-function.js b/test/built-ins/Function/prototype/toString/proxy-bound-function.js new file mode 100644 index 0000000000..49011aa967 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-bound-function.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (bound Function Expression) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy(function() {}.bind({}), {})); +assertNativeFunction(new Proxy(function() {}.bind({}), { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-class.js b/test/built-ins/Function/prototype/toString/proxy-class.js new file mode 100644 index 0000000000..bc4d976165 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-class.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Class Expression) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [class, Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy(class {}, {})); +assertNativeFunction(new Proxy(class {}, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-function-expression.js b/test/built-ins/Function/prototype/toString/proxy-function-expression.js new file mode 100644 index 0000000000..4c782f1f8a --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-function-expression.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Function Expression) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy(function() {}, {})); +assertNativeFunction(new Proxy(function() {}, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-generator-function.js b/test/built-ins/Function/prototype/toString/proxy-generator-function.js new file mode 100644 index 0000000000..f4a118b21f --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-generator-function.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Generator Function Expression) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [generators, Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy(function * () {}, {})); +assertNativeFunction(new Proxy(function * () {}, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-method-definition.js b/test/built-ins/Function/prototype/toString/proxy-method-definition.js new file mode 100644 index 0000000000..cc648e3e38 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-method-definition.js @@ -0,0 +1,22 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for function target does not throw (Method Definition) +info: | + ... + If Type(func) is Object and IsCallable(func) is true, then return an + implementation-dependent String source code representation of func. + The representation must have the syntax of a NativeFunction. + ... + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +features: [Proxy] +includes: [nativeFunctionMatcher.js] +---*/ + +assertNativeFunction(new Proxy({ method() {} }.method, {})); +assertNativeFunction(new Proxy({ method() {} }.method, { apply() {} }).apply); diff --git a/test/built-ins/Function/prototype/toString/proxy-non-callable-throws.js b/test/built-ins/Function/prototype/toString/proxy-non-callable-throws.js new file mode 100644 index 0000000000..3f803bd651 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/proxy-non-callable-throws.js @@ -0,0 +1,16 @@ +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Proxy for non-callable target throws +info: | + ... + Throw a TypeError exception. + +features: [Proxy] +---*/ + +assert.throws(TypeError, function() { + Function.prototype.toString.call(new Proxy({}, {})); +}); diff --git a/test/built-ins/Function/prototype/toString/proxy.js b/test/built-ins/Function/prototype/toString/proxy.js deleted file mode 100644 index fa5c39b945..0000000000 --- a/test/built-ins/Function/prototype/toString/proxy.js +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (C) 2018 Michael Ficarra. All rights reserved. -// This code is governed by the BSD license found in the LICENSE file. - -/*--- -esid: sec-function.prototype.tostring -description: Function.prototype.toString on a proxied function -info: | - Function.prototype.toString accepts any callable, including proxied - functions, and produces a NativeFunction -includes: [nativeFunctionMatcher.js] ----*/ - -const f = new Proxy(function(){}, {}); -assertNativeFunction(f); - -const g = new Proxy(f, { apply() {} }); -assertNativeFunction(g); diff --git a/test/built-ins/Function/prototype/toString/well-known-intrinsic-object-functions.js b/test/built-ins/Function/prototype/toString/well-known-intrinsic-object-functions.js new file mode 100644 index 0000000000..337016c2b1 --- /dev/null +++ b/test/built-ins/Function/prototype/toString/well-known-intrinsic-object-functions.js @@ -0,0 +1,28 @@ +// Copyright (C) 2016 Michael Ficarra. All rights reserved. +// Copyright (C) 2018 the V8 project authors. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-function.prototype.tostring +description: > + toString of Well-Known Intrinsic Object +info: | + ... + If func is a Bound Function exotic object or a built-in Function object, then return an implementation-dependent String source code representation of func. The representation must have the syntax of a NativeFunction. Additionally, if func is a Well-known Intrinsic Object and is not identified as an anonymous function, the portion of the returned String that would be matched by IdentifierName must be the initial value of the name property of func. + + NativeFunction: + function IdentifierName_opt ( FormalParameters ) { [ native code ] } + +includes: [nativeFunctionMatcher.js, wellKnownIntrinsicObjects.js] +features: [destructuring-binding, template] +---*/ + + +WellKnownIntrinsicObjects.forEach(({intrinsicName, reference}) => { + if (typeof reference === "function") { + assert.sameValue( + ("" + reference).includes(reference.name), true, + `toString of Well-Known Intrinsic Object function should produce a string that matches NativeFunction syntax:\n${reference}\nis missing "${reference.name}"\n\n` + ); + assertNativeFunction(reference, intrinsicName); + } +}); -- GitLab