From 19b5a5a635e24814c784e00bab1607f384b0cd9d Mon Sep 17 00:00:00 2001 From: Alexey Shvayka Date: Wed, 10 Jul 2019 21:00:04 +0300 Subject: [PATCH] Improve Object#toString coverage (#2202) * Move proxies with non-string toStringTag to separate file * Add coverage for async proxy functions * Add coverage for built-ins with non-string toStringTag * Move async proxy function tests to new file --- .../toString/proxy-function-async.js | 32 ++++++++ .../prototype/toString/proxy-function.js | 13 ++-- .../toString/symbol-tag-non-str-builtin.js | 76 +++++++++++++++++++ .../symbol-tag-non-str-proxy-function.js | 55 ++++++++++++++ 4 files changed, 170 insertions(+), 6 deletions(-) create mode 100644 test/built-ins/Object/prototype/toString/proxy-function-async.js create mode 100644 test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js create mode 100644 test/built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js diff --git a/test/built-ins/Object/prototype/toString/proxy-function-async.js b/test/built-ins/Object/prototype/toString/proxy-function-async.js new file mode 100644 index 0000000000..07322015b3 --- /dev/null +++ b/test/built-ins/Object/prototype/toString/proxy-function-async.js @@ -0,0 +1,32 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-object.prototype.tostring +description: Proxy of async function is treated as a function. +info: | + ProxyCreate ( target, handler ) + + [...] + 7. If IsCallable(target) is true, then + a. Set P.[[Call]] as specified in 9.5.12. + + Object.prototype.toString ( ) + + [...] + 7. Else if O has a [[Call]] internal method, let builtinTag be "Function". +features: [async-functions, Proxy, Symbol.toStringTag] +---*/ + +var asyncProxy = new Proxy(async function() {}, {}); +var asyncProxyProxy = new Proxy(asyncProxy, {}); + +assert.sameValue( + Object.prototype.toString.call(asyncProxy), + '[object AsyncFunction]', + 'async function proxy' +); +assert.sameValue( + Object.prototype.toString.call(asyncProxyProxy), + '[object AsyncFunction]', + 'proxy for async function proxy' +); diff --git a/test/built-ins/Object/prototype/toString/proxy-function.js b/test/built-ins/Object/prototype/toString/proxy-function.js index 965aeba623..3b221a1557 100644 --- a/test/built-ins/Object/prototype/toString/proxy-function.js +++ b/test/built-ins/Object/prototype/toString/proxy-function.js @@ -14,7 +14,7 @@ info: | a. Set the [[Call]] internal method of P as specified in 9.5.12. [...] -features: [generators, Proxy, Symbol.toStringTag] +features: [generators, async-functions, Proxy, Symbol.toStringTag] ---*/ var functionProxy = new Proxy(function() {}, {}); @@ -53,13 +53,14 @@ assert.sameValue( 'proxy for generator function proxy' ); -delete generatorProxy.constructor.prototype[Symbol.toStringTag]; +var asyncProxy = new Proxy(async function() {}, {}); +var asyncProxyProxy = new Proxy(asyncProxy, {}); assert.sameValue( - Object.prototype.toString.call(generatorProxy), '[object Function]', 'generator function proxy without Symbol.toStringTag' + Object.prototype.toString.call(asyncProxy), '[object AsyncFunction]', 'async function proxy' ); assert.sameValue( - Object.prototype.toString.call(generatorProxyProxy), - '[object Function]', - 'proxy for generator function proxy without Symbol.toStringTag' + Object.prototype.toString.call(asyncProxyProxy), + '[object AsyncFunction]', + 'proxy for async function proxy' ); diff --git a/test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js b/test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js new file mode 100644 index 0000000000..a19e840699 --- /dev/null +++ b/test/built-ins/Object/prototype/toString/symbol-tag-non-str-builtin.js @@ -0,0 +1,76 @@ +// Copyright (C) 2019 Alexey Shvayka. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-object.prototype.tostring +description: > + Non-string values of `Symbol.toStringTag` property are ignored. +info: | + Object.prototype.toString ( ) + + [...] + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". +features: [Symbol.toStringTag, Symbol.iterator, generators] +---*/ + +var toString = Object.prototype.toString; +var defaultTag = '[object Object]'; + +delete Symbol.prototype[Symbol.toStringTag]; +assert.sameValue(toString.call(Symbol('desc')), defaultTag); + +Object.defineProperty(Math, Symbol.toStringTag, {value: Symbol()}); +assert.sameValue(toString.call(Math), defaultTag); + +var strIter = ''[Symbol.iterator](); +var strIterProto = Object.getPrototypeOf(strIter); +delete strIterProto[Symbol.toStringTag]; +assert.sameValue(toString.call(strIter), defaultTag); + +var arrIter = [][Symbol.iterator](); +var arrIterProto = Object.getPrototypeOf(arrIter) +Object.defineProperty(arrIterProto, Symbol.toStringTag, {value: null}); +assert.sameValue(toString.call(arrIter), defaultTag); + +var map = new Map(); +delete Map.prototype[Symbol.toStringTag]; +assert.sameValue(toString.call(map), defaultTag); + +var mapIter = map[Symbol.iterator](); +var mapIterProto = Object.getPrototypeOf(mapIter); +Object.defineProperty(mapIterProto, Symbol.toStringTag, { + get: function() { return new String('ShouldNotBeUnwrapped'); }, +}); +assert.sameValue(toString.call(mapIter), defaultTag); + +var set = new Set(); +delete Set.prototype[Symbol.toStringTag]; +assert.sameValue(toString.call(set), defaultTag); + +var setIter = set[Symbol.iterator](); +var setIterProto = Object.getPrototypeOf(setIter); +Object.defineProperty(setIterProto, Symbol.toStringTag, {value: false}); +assert.sameValue(toString.call(setIter), defaultTag); + +var wm = new WeakMap(); +delete WeakMap.prototype[Symbol.toStringTag]; +assert.sameValue(toString.call(wm), defaultTag); + +var ws = new WeakSet(); +Object.defineProperty(WeakSet.prototype, Symbol.toStringTag, {value: 0}); +assert.sameValue(toString.call(ws), defaultTag); + +delete JSON[Symbol.toStringTag]; +assert.sameValue(toString.call(JSON), defaultTag); + +var gen = (function* () {})(); +var genProto = Object.getPrototypeOf(gen); +Object.defineProperty(genProto, Symbol.toStringTag, { + get: function() { return {}; }, +}); +assert.sameValue(toString.call(gen), defaultTag); + +var promise = new Promise(function() {}); +delete Promise.prototype[Symbol.toStringTag]; +assert.sameValue(toString.call(promise), defaultTag); diff --git a/test/built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js b/test/built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js new file mode 100644 index 0000000000..fcc5bee12c --- /dev/null +++ b/test/built-ins/Object/prototype/toString/symbol-tag-non-str-proxy-function.js @@ -0,0 +1,55 @@ +// Copyright (C) 2016 the Apple Inc. All rights reserved. +// This code is governed by the BSD license found in the LICENSE file. +/*--- +esid: sec-object.prototype.tostring +description: > + Non-string values of `Symbol.toStringTag` property are ignored. +info: | + ProxyCreate ( target, handler ) + + [...] + 7. If IsCallable(target) is true, then + a. Set P.[[Call]] as specified in 9.5.12. + + Object.prototype.toString ( ) + + [...] + 7. Else if O has a [[Call]] internal method, let builtinTag be "Function". + [...] + 15. Let tag be ? Get(O, @@toStringTag). + 16. If Type(tag) is not String, set tag to builtinTag. + 17. Return the string-concatenation of "[object ", tag, and "]". +features: [generators, async-functions, Proxy, Symbol.toStringTag] +---*/ + +var generatorProxy = new Proxy(function* () {}, {}); +var generatorProxyProxy = new Proxy(generatorProxy, {}); +delete generatorProxy.constructor.prototype[Symbol.toStringTag]; + +assert.sameValue( + Object.prototype.toString.call(generatorProxy), + '[object Function]', + 'generator function proxy without Symbol.toStringTag' +); +assert.sameValue( + Object.prototype.toString.call(generatorProxyProxy), + '[object Function]', + 'proxy for generator function proxy without Symbol.toStringTag' +); + +var asyncProxy = new Proxy(async function() {}, {}); +var asyncProxyProxy = new Proxy(asyncProxy, {}); +Object.defineProperty(asyncProxy.constructor.prototype, Symbol.toStringTag, { + value: undefined, +}); + +assert.sameValue( + Object.prototype.toString.call(asyncProxy), + '[object Function]', + 'async function proxy without Symbol.toStringTag' +); +assert.sameValue( + Object.prototype.toString.call(asyncProxyProxy), + '[object Function]', + 'proxy for async function proxy without Symbol.toStringTag' +);