From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- js/src/tests/non262/Symbol/as-base-value.js | 87 ++++++++++++ js/src/tests/non262/Symbol/browser.js | 0 js/src/tests/non262/Symbol/comparisons.js | 34 +++++ js/src/tests/non262/Symbol/constructor.js | 35 +++++ js/src/tests/non262/Symbol/conversions.js | 89 ++++++++++++ js/src/tests/non262/Symbol/enumeration-order.js | 40 ++++++ js/src/tests/non262/Symbol/enumeration.js | 52 +++++++ js/src/tests/non262/Symbol/equality.js | 30 ++++ js/src/tests/non262/Symbol/errors.js | 17 +++ js/src/tests/non262/Symbol/for-in-order.js | 33 +++++ js/src/tests/non262/Symbol/for.js | 31 +++++ js/src/tests/non262/Symbol/json-stringify-keys.js | 19 +++ .../tests/non262/Symbol/json-stringify-values.js | 33 +++++ js/src/tests/non262/Symbol/keyFor.js | 15 ++ js/src/tests/non262/Symbol/property-accessor.js | 39 ++++++ js/src/tests/non262/Symbol/property-basics.js | 44 ++++++ js/src/tests/non262/Symbol/property-inheritance.js | 50 +++++++ js/src/tests/non262/Symbol/property-nonwritable.js | 31 +++++ js/src/tests/non262/Symbol/property-reflection.js | 136 ++++++++++++++++++ js/src/tests/non262/Symbol/realms.js | 36 +++++ js/src/tests/non262/Symbol/shell.js | 0 js/src/tests/non262/Symbol/species.js | 30 ++++ js/src/tests/non262/Symbol/surfaces.js | 34 +++++ .../symbol-object-not-unboxed-for-value-to-id.js | 31 +++++ .../non262/Symbol/toPrimitive-undefined-or-null.js | 18 +++ js/src/tests/non262/Symbol/toPrimitive.js | 39 ++++++ js/src/tests/non262/Symbol/toString.js | 27 ++++ js/src/tests/non262/Symbol/toStringTag.js | 155 +++++++++++++++++++++ js/src/tests/non262/Symbol/typed-arrays.js | 17 +++ js/src/tests/non262/Symbol/typeof.js | 11 ++ js/src/tests/non262/Symbol/valueOf.js | 22 +++ js/src/tests/non262/Symbol/well-known.js | 42 ++++++ 32 files changed, 1277 insertions(+) create mode 100644 js/src/tests/non262/Symbol/as-base-value.js create mode 100644 js/src/tests/non262/Symbol/browser.js create mode 100644 js/src/tests/non262/Symbol/comparisons.js create mode 100644 js/src/tests/non262/Symbol/constructor.js create mode 100644 js/src/tests/non262/Symbol/conversions.js create mode 100644 js/src/tests/non262/Symbol/enumeration-order.js create mode 100644 js/src/tests/non262/Symbol/enumeration.js create mode 100644 js/src/tests/non262/Symbol/equality.js create mode 100644 js/src/tests/non262/Symbol/errors.js create mode 100644 js/src/tests/non262/Symbol/for-in-order.js create mode 100644 js/src/tests/non262/Symbol/for.js create mode 100644 js/src/tests/non262/Symbol/json-stringify-keys.js create mode 100644 js/src/tests/non262/Symbol/json-stringify-values.js create mode 100644 js/src/tests/non262/Symbol/keyFor.js create mode 100644 js/src/tests/non262/Symbol/property-accessor.js create mode 100644 js/src/tests/non262/Symbol/property-basics.js create mode 100644 js/src/tests/non262/Symbol/property-inheritance.js create mode 100644 js/src/tests/non262/Symbol/property-nonwritable.js create mode 100644 js/src/tests/non262/Symbol/property-reflection.js create mode 100644 js/src/tests/non262/Symbol/realms.js create mode 100644 js/src/tests/non262/Symbol/shell.js create mode 100644 js/src/tests/non262/Symbol/species.js create mode 100644 js/src/tests/non262/Symbol/surfaces.js create mode 100644 js/src/tests/non262/Symbol/symbol-object-not-unboxed-for-value-to-id.js create mode 100644 js/src/tests/non262/Symbol/toPrimitive-undefined-or-null.js create mode 100644 js/src/tests/non262/Symbol/toPrimitive.js create mode 100644 js/src/tests/non262/Symbol/toString.js create mode 100644 js/src/tests/non262/Symbol/toStringTag.js create mode 100644 js/src/tests/non262/Symbol/typed-arrays.js create mode 100644 js/src/tests/non262/Symbol/typeof.js create mode 100644 js/src/tests/non262/Symbol/valueOf.js create mode 100644 js/src/tests/non262/Symbol/well-known.js (limited to 'js/src/tests/non262/Symbol') diff --git a/js/src/tests/non262/Symbol/as-base-value.js b/js/src/tests/non262/Symbol/as-base-value.js new file mode 100644 index 0000000000..f0e8400a22 --- /dev/null +++ b/js/src/tests/non262/Symbol/as-base-value.js @@ -0,0 +1,87 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Like other primitives, symbols can be treated as objects, using object-like +// syntax: `symbol.prop` or `symbol[key]`. +// +// In ECMAScript spec jargon, this creates a Reference whose base value is a +// primitive Symbol value. + +var symbols = [ + Symbol(), + Symbol("ponies"), + Symbol.for("sym"), + Symbol.iterator +]; + +// Test accessor property, used below. +var gets, sets; +Object.defineProperty(Symbol.prototype, "prop", { + get: function () { + "use strict"; + gets++; + assertEq(typeof this, "symbol"); + assertEq(this, sym); + return "got"; + }, + set: function (v) { + "use strict"; + sets++; + assertEq(typeof this, "symbol"); + assertEq(this, sym); + assertEq(v, "newvalue"); + } +}); + +for (var sym of symbols) { + assertEq(sym.constructor, Symbol); + + // method on Object.prototype + assertEq(sym.hasOwnProperty("constructor"), false); + assertEq(sym.toLocaleString(), sym.toString()); // once .toString() exists + + // custom method monkeypatched onto Symbol.prototype + Symbol.prototype.nonStrictMethod = function (arg) { + assertEq(arg, "ok"); + assertEq(this instanceof Symbol, true); + assertEq(this.valueOf(), sym); + return 13; + }; + assertEq(sym.nonStrictMethod("ok"), 13); + + // the same, but strict mode + Symbol.prototype.strictMethod = function (arg) { + "use strict"; + assertEq(arg, "ok2"); + assertEq(this, sym); + return 14; + }; + assertEq(sym.strictMethod("ok2"), 14); + + // getter/setter on Symbol.prototype + gets = 0; + sets = 0; + var propname = "prop"; + + assertEq(sym.prop, "got"); + assertEq(gets, 1); + assertEq(sym[propname], "got"); + assertEq(gets, 2); + + assertEq(sym.prop = "newvalue", "newvalue"); + assertEq(sets, 1); + assertEq(sym[propname] = "newvalue", "newvalue"); + assertEq(sets, 2); + + // non-existent property + assertEq(sym.noSuchProp, undefined); + var noSuchPropName = "nonesuch"; + assertEq(sym[noSuchPropName], undefined); + + // non-existent method + assertThrowsInstanceOf(() => sym.noSuchProp(), TypeError); + assertThrowsInstanceOf(() => sym[noSuchPropName](), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/browser.js b/js/src/tests/non262/Symbol/browser.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Symbol/comparisons.js b/js/src/tests/non262/Symbol/comparisons.js new file mode 100644 index 0000000000..d2105c8a1a --- /dev/null +++ b/js/src/tests/non262/Symbol/comparisons.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var symbols = [ + Symbol(), + Symbol("0"), + Symbol.for("snowman"), + Symbol.iterator +]; + +var values = [ + undefined, null, 0, 3.14, -0, NaN, "", "alphabet", Symbol("0"), + {}, [] +]; + +for (var comparator of ["==", "!=", "===", "!=="]) { + var f = Function("a, b", "return a " + comparator + " b;"); + var expected = (comparator[0] == '!'); + for (var a of symbols) { + for (var b of values) + assertEq(f(a, b), expected); + } +} + +for (var comparator of ["<", "<=", ">", ">="]) { + var f = Function("a, b", "return a " + comparator + " b;"); + for (var a of symbols) { + for (var b of values) + assertThrowsInstanceOf(() => f(a, b), TypeError); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/constructor.js b/js/src/tests/non262/Symbol/constructor.js new file mode 100644 index 0000000000..5143b02a9e --- /dev/null +++ b/js/src/tests/non262/Symbol/constructor.js @@ -0,0 +1,35 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Symbol(symbol) throws a TypeError. +var sym = Symbol(); +assertThrowsInstanceOf(() => Symbol(sym), TypeError); + +// Symbol(undefined) is equivalent to Symbol(). +assertEq(Symbol(undefined).toString(), "Symbol()"); + +// Otherwise, Symbol(v) means Symbol(ToString(v)). +assertEq(Symbol(7).toString(), "Symbol(7)"); +assertEq(Symbol(true).toString(), "Symbol(true)"); +assertEq(Symbol(null).toString(), "Symbol(null)"); +assertEq(Symbol([1, 2]).toString(), "Symbol(1,2)"); +var symobj = Object(sym); +assertThrowsInstanceOf(() => Symbol(symobj), TypeError); + +var hits = 0; +var obj = { + toString: function () { + hits++; + return "ponies"; + } +}; +assertEq(Symbol(obj).toString(), "Symbol(ponies)"); +assertEq(hits, 1); + +assertEq(Object.getPrototypeOf(Symbol.prototype), Object.prototype); + +// Symbol.prototype is not itself a Symbol object. +assertThrowsInstanceOf(() => Symbol.prototype.valueOf(), TypeError); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/conversions.js b/js/src/tests/non262/Symbol/conversions.js new file mode 100644 index 0000000000..e6265f09c9 --- /dev/null +++ b/js/src/tests/non262/Symbol/conversions.js @@ -0,0 +1,89 @@ +// Section numbers cite ES6 rev 24 (2014 April 27). + +var symbols = [ + Symbol(), + Symbol("one"), + Symbol.for("two"), + Symbol.iterator +]; + +function testSymbolConversions(sym) { + // 7.1.2 ToBoolean + assertEq(Boolean(sym), true); + assertEq(!sym, false); + assertEq(sym || 13, sym); + assertEq(sym && 13, 13); + + // 7.1.3 ToNumber + assertThrowsInstanceOf(() => +sym, TypeError); + assertThrowsInstanceOf(() => sym | 0, TypeError); + + // 7.1.12 ToString + assertThrowsInstanceOf(() => "" + sym, TypeError); + assertThrowsInstanceOf(() => sym + "", TypeError); + assertThrowsInstanceOf(() => "" + [1, 2, sym], TypeError); + assertThrowsInstanceOf(() => ["simple", "thimble", sym].join(), TypeError); + + // 21.1.1.1 String() + assertEq(String(sym), sym.toString()); + + // 21.1.1.2 new String() + assertThrowsInstanceOf(() => new String(sym), TypeError); + + // 7.1.13 ToObject + var obj = Object(sym); + assertEq(typeof obj, "object"); + assertEq(Object.prototype.toString.call(obj), "[object Symbol]"); + assertEq(Object.getPrototypeOf(obj), Symbol.prototype); + assertEq(Object.getOwnPropertyNames(obj).length, 0); + assertEq(Object(sym) === Object(sym), false); // new object each time + var f = function () { return this; }; + assertEq(f.call(sym) === f.call(sym), false); // new object each time +} + + +for (var sym of symbols) { + testSymbolConversions(sym); + + // 7.1.1 ToPrimitive + var symobj = Object(sym); + assertThrowsInstanceOf(() => Number(symobj), TypeError); + assertThrowsInstanceOf(() => String(symobj), TypeError); + assertThrowsInstanceOf(() => symobj < 0, TypeError); + assertThrowsInstanceOf(() => 0 < symobj, TypeError); + assertThrowsInstanceOf(() => symobj + 1, TypeError); + assertThrowsInstanceOf(() => "" + symobj, TypeError); + assertEq(sym == symobj, true); + assertEq(sym === symobj, false); + assertEq(symobj == 0, false); + assertEq(0 != symobj, true); + + // 7.1.12 ToString + assertThrowsInstanceOf(() => String(Object(sym)), TypeError); +} + +// Deleting Symbol.prototype[@@toPrimitive] does not change the behavior of +// conversions from a symbol to other types. +delete Symbol.prototype[Symbol.toPrimitive]; +assertEq(Symbol.toPrimitive in Symbol.prototype, false); +testSymbolConversions(symbols[0]); + +// It does change the behavior of ToPrimitive on Symbol objects, though. +// It causes the default algorithm (OrdinaryToPrimitive) to be used. +var VALUEOF_CALLED = 117.25; +Symbol.prototype.valueOf = function () { return VALUEOF_CALLED; }; +Symbol.prototype.toString = function () { return "toString called"; }; +for (var sym of symbols) { + var symobj = Object(sym); + assertEq(Number(symobj), VALUEOF_CALLED); + assertEq(String(symobj), "toString called"); + assertEq(symobj < 0, VALUEOF_CALLED < 0); + assertEq(0 < symobj, 0 < VALUEOF_CALLED); + assertEq(symobj + 1, VALUEOF_CALLED + 1); + assertEq("" + symobj, "" + VALUEOF_CALLED); + assertEq(symobj == 0, false); + assertEq(0 != symobj, true); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/enumeration-order.js b/js/src/tests/non262/Symbol/enumeration-order.js new file mode 100644 index 0000000000..8bcd1f02ff --- /dev/null +++ b/js/src/tests/non262/Symbol/enumeration-order.js @@ -0,0 +1,40 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Symbols follow all other property keys in the result list. +var log; +function LoggingProxy() { + return new Proxy({}, { + defineProperty: (t, key, desc) => { + log.push(key); + return true; + } + }); +} + +var keys = [ + "before", + Symbol(), + "during", + Symbol.for("during"), + Symbol.iterator, + "after" +]; +var descs = {}; +for (var k of keys) + descs[k] = {configurable: true, value: 0}; + +function test(descsObj) { + log = []; + Object.defineProperties(LoggingProxy(), descs); + assertEq(log.length, keys.length); + assertDeepEq(log.map(k => typeof k), ["string", "string", "string", "symbol", "symbol", "symbol"]); + for (var key of keys) + assertEq(log.indexOf(key) !== -1, true); +} + +test(descs); +test(new Proxy(descs, {})); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/enumeration.js b/js/src/tests/non262/Symbol/enumeration.js new file mode 100644 index 0000000000..de993d69a7 --- /dev/null +++ b/js/src/tests/non262/Symbol/enumeration.js @@ -0,0 +1,52 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// for-in loops skip properties with symbol keys, even enumerable properties. +var obj = {}; +obj[Symbol.for("moon")] = "sun"; +obj[Symbol("asleep")] = "awake"; +obj[Symbol.iterator] = "List"; +for (var x in obj) + throw "FAIL: " + String(x); + +// This includes inherited properties. +var obj2 = Object.create(obj); +for (var x in obj2) + throw "FAIL: " + String(x); + +// The same goes for proxies. +var p = new Proxy(obj, {}); +for (var x in p) + throw "FAIL: " + String(x); +var p2 = new Proxy(obj2, {}); +for (var x in p2) + throw "FAIL: " + String(x); + +// Object.keys() and .getOwnPropertyNames() also skip symbols. +assertEq(Object.keys(obj).length, 0); +assertEq(Object.keys(p).length, 0); +assertEq(Object.keys(obj2).length, 0); +assertEq(Object.keys(p2).length, 0); +assertEq(Object.getOwnPropertyNames(obj).length, 0); +assertEq(Object.getOwnPropertyNames(p).length, 0); +assertEq(Object.getOwnPropertyNames(obj2).length, 0); +assertEq(Object.getOwnPropertyNames(p2).length, 0); + +// Test interaction of Object.keys(), proxies, and symbol property keys. +var log = []; +var h = { + ownKeys: (t) => { + log.push("ownKeys"); + return ["a", "0", Symbol.for("moon"), Symbol("asleep"), Symbol.iterator]; + }, + getOwnPropertyDescriptor: (t, key) => { + log.push("gopd", key); + return {configurable: true, enumerable: true, value: 0, writable: true}; + } +}; +p = new Proxy({}, h); +assertDeepEq(Object.keys(p), ["a", "0"]); +assertDeepEq(log, ["ownKeys", "gopd", "a", "gopd", "0"]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/equality.js b/js/src/tests/non262/Symbol/equality.js new file mode 100644 index 0000000000..eaa091ba43 --- /dev/null +++ b/js/src/tests/non262/Symbol/equality.js @@ -0,0 +1,30 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Symbol.for returns the same symbol whenever the same argument is passed. +assertEq(Symbol.for("q") === Symbol.for("q"), true); + +// Several distinct Symbol values. +var symbols = [ + Symbol(), + Symbol("Symbol.iterator"), + Symbol("Symbol.iterator"), // distinct new symbol with the same description + Symbol.for("Symbol.iterator"), + Symbol.iterator +]; + +// Distinct symbols are never equal to each other, even if they have the same +// description. +for (var i = 0; i < symbols.length; i++) { + for (var j = i; j < symbols.length; j++) { + var expected = (i === j); + assertEq(symbols[i] == symbols[j], expected); + assertEq(symbols[i] != symbols[j], !expected); + assertEq(symbols[i] === symbols[j], expected); + assertEq(symbols[i] !== symbols[j], !expected); + assertEq(Object.is(symbols[i], symbols[j]), expected); + } +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/errors.js b/js/src/tests/non262/Symbol/errors.js new file mode 100644 index 0000000000..d6eb37abc4 --- /dev/null +++ b/js/src/tests/non262/Symbol/errors.js @@ -0,0 +1,17 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Section numbers cite ES6 rev 24 (2014 April 27). + +var sym = Symbol(); + +// 7.2.2 IsCallable +assertThrowsInstanceOf(() => sym(), TypeError); +assertThrowsInstanceOf(() => Function.prototype.call.call(sym), TypeError); + +// 7.2.5 IsConstructor +assertThrowsInstanceOf(() => new sym(), TypeError); +assertThrowsInstanceOf(() => new Symbol(), TypeError); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/for-in-order.js b/js/src/tests/non262/Symbol/for-in-order.js new file mode 100644 index 0000000000..7d1f234305 --- /dev/null +++ b/js/src/tests/non262/Symbol/for-in-order.js @@ -0,0 +1,33 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// ES6 does not specify enumeration order, but implementations mostly retain +// property insertion order -- and must, for web compatibility. This test checks +// that symbol-keyed properties do not interfere with that order. + +var obj = {}; +obj[Symbol("moon")] = 0; +obj.x = 1; +obj[Symbol.for("y")] = 2 +obj.y = 3; +obj[Symbol.iterator] = function* () { yield 4; }; +obj.z = 5; +Object.prototype[Symbol.for("comet")] = 6; + +var keys = []; +for (var k in obj) + keys.push(k); +assertDeepEq(keys, ["x", "y", "z"]); +assertDeepEq(Object.keys(obj), ["x", "y", "z"]); + +// Test with more properties. +for (var i = 0; i < 1000; i++) + obj[Symbol(i)] = i; +obj.w = 1000; +keys = [] +for (var k in obj) + keys.push(k); +assertDeepEq(keys, ["x", "y", "z", "w"]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/for.js b/js/src/tests/non262/Symbol/for.js new file mode 100644 index 0000000000..43e2855113 --- /dev/null +++ b/js/src/tests/non262/Symbol/for.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Symbol.for called twice with the same argument returns the same symbol. +assertEq(Symbol.for("ponies"), Symbol.for("ponies")); + +// Called twice with equal strings: still the same result. +var one = Array(64+1).join("x"); +var two = Array(8+1).join(Array(8+1).join("x")); +assertEq(Symbol.for(one), Symbol.for(two)); + +// Symbols created by calling Symbol() are not in the symbol registry. +var sym = Symbol("123"); +assertEq(Symbol.for("123") !== sym, true); + +// Empty string is fine. +assertEq(typeof Symbol.for(""), "symbol"); + +// Primitive arguments. +assertEq(Symbol.for(3), Symbol.for("3")); +assertEq(Symbol.for(null), Symbol.for("null")); +assertEq(Symbol.for(undefined), Symbol.for("undefined")); +assertEq(Symbol.for(), Symbol.for("undefined")); + +// Symbol.for ignores the 'this' value. +var foo = Symbol.for("foo") +assertEq(Symbol.for.call(String, "foo"), foo); +assertEq(Symbol.for.call(3.14, "foo"), foo); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/json-stringify-keys.js b/js/src/tests/non262/Symbol/json-stringify-keys.js new file mode 100644 index 0000000000..3818cbb339 --- /dev/null +++ b/js/src/tests/non262/Symbol/json-stringify-keys.js @@ -0,0 +1,19 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// JSON.stringify ignores symbol-keyed properties, even enumerable ones. + +var obj = {a: 1}; +obj[Symbol.for("ponies")] = {toJSON: function () { throw "fit"; }}; +obj[Symbol.iterator] = {toJSON: function () { throw "fit"; }}; +assertEq(JSON.stringify(obj), '{"a":1}'); + +var replacer = function (k, v) { + if (typeof k === "symbol") + throw "fit"; + return v; +}; +assertEq(JSON.stringify(obj, replacer), '{"a":1}'); + +if (typeof reportCompare === 'function') + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Symbol/json-stringify-values.js b/js/src/tests/non262/Symbol/json-stringify-values.js new file mode 100644 index 0000000000..0fe32eee54 --- /dev/null +++ b/js/src/tests/non262/Symbol/json-stringify-values.js @@ -0,0 +1,33 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// To JSON.stringify, symbols are the same as undefined. + +var symbols = [ + Symbol(), + Symbol.for("ponies"), + Symbol.iterator +]; + +for (var sym of symbols) { + assertEq(JSON.stringify(sym), undefined); + assertEq(JSON.stringify([sym]), "[null]"); + + // JSON.stringify skips symbol-valued properties! + assertEq(JSON.stringify({x: sym}), '{}'); + + // However such properties are passed to the replacerFunction if any. + var replacer = function (key, val) { + assertEq(typeof this, "object"); + if (typeof val === "symbol") { + assertEq(val, sym); + return "ding"; + } + return val; + }; + assertEq(JSON.stringify(sym, replacer), '"ding"'); + assertEq(JSON.stringify({x: sym}, replacer), '{"x":"ding"}'); +} + +if (typeof reportCompare === 'function') + reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Symbol/keyFor.js b/js/src/tests/non262/Symbol/keyFor.js new file mode 100644 index 0000000000..868c3bda74 --- /dev/null +++ b/js/src/tests/non262/Symbol/keyFor.js @@ -0,0 +1,15 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +assertEq(Symbol.keyFor(Symbol.for("moon")), "moon"); +assertEq(Symbol.keyFor(Symbol.for("")), ""); +assertEq(Symbol.keyFor(Symbol("moon")), undefined); +assertEq(Symbol.keyFor(Symbol.iterator), undefined); + +assertThrowsInstanceOf(() => Symbol.keyFor(), TypeError); +assertThrowsInstanceOf(() => Symbol.keyFor(Object(Symbol("moon"))), TypeError); + +assertEq(Symbol.keyFor.length, 1); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/property-accessor.js b/js/src/tests/non262/Symbol/property-accessor.js new file mode 100644 index 0000000000..7a2c149a1e --- /dev/null +++ b/js/src/tests/non262/Symbol/property-accessor.js @@ -0,0 +1,39 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var obj = {}; +var sym = Symbol(); + +var gets = 0; +var sets = []; +Object.defineProperty(obj, sym, { + get: function () { return ++gets; }, + set: function (v) { sets.push(v); } +}); + +// getter +for (var i = 1; i < 9; i++) + assertEq(obj[sym], i); + +// setter +var expected = []; +for (var i = 0; i < 9; i++) { + assertEq(obj[sym] = i, i); + expected.push(i); +} +assertDeepEq(sets, expected); + +// increment operator +gets = 0; +sets = []; +assertEq(obj[sym]++, 1); +assertDeepEq(sets, [2]); + +// assignment +gets = 0; +sets = []; +assertEq(obj[sym] *= 12, 12); +assertDeepEq(sets, [12]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/property-basics.js b/js/src/tests/non262/Symbol/property-basics.js new file mode 100644 index 0000000000..63bcb3867c --- /dev/null +++ b/js/src/tests/non262/Symbol/property-basics.js @@ -0,0 +1,44 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var symbols = [ + Symbol(), + Symbol("one"), + Symbol.for("two"), + Symbol.iterator, + Object(Symbol()) +]; + +for (var sym of symbols) { + var obj = {}; + + // access a nonexistent property + assertEq(sym in obj, false); + assertEq(obj.hasOwnProperty(sym), false); + assertEq(obj[sym], undefined); + assertEq(typeof obj[sym], "undefined"); + assertEq(Object.getOwnPropertyDescriptor(obj, sym), undefined); + + // assign, then try accessing again + obj[sym] = "ok"; + assertEq(sym in obj, true); + assertEq(obj.hasOwnProperty(sym), true); + assertEq(obj[sym], "ok"); + assertDeepEq(Object.getOwnPropertyDescriptor(obj, sym), { + value: "ok", + writable: true, + enumerable: true, + configurable: true + }); + + // assign again, observe value is overwritten + obj[sym] = 12; + assertEq(obj[sym], 12); + + // increment + assertEq(obj[sym]++, 12); + assertEq(obj[sym], 13); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/property-inheritance.js b/js/src/tests/non262/Symbol/property-inheritance.js new file mode 100644 index 0000000000..2fe6189689 --- /dev/null +++ b/js/src/tests/non262/Symbol/property-inheritance.js @@ -0,0 +1,50 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var sym = Symbol.for("hello"); +function F() {} +var f = new F(); + +// inherited data property +F.prototype[sym] = "world"; +assertEq(sym in f, true); +assertEq(f.hasOwnProperty(sym), false); +assertEq(f[sym], "world"); + +// shadowing assignment +f[sym] = "kitty"; +assertEq(f[sym], "kitty"); +assertEq(F.prototype[sym], "world"); + +// deletion, revealing previously shadowed property +assertEq(delete f[sym], true); +assertEq(f.hasOwnProperty(sym), false); +assertEq(f[sym], "world"); + +// inherited accessor property +var value = undefined; +Object.defineProperty(F.prototype, sym, { + configurable: true, + get: function () { return 23; }, + set: function (v) { value = v; } +}); +assertEq(sym in f, true); +assertEq(f.hasOwnProperty(sym), false); +assertEq(f[sym], 23); +f[sym] = "gravity"; +assertEq(value, "gravity"); + +// inherited accessor property with no setter +Object.defineProperty(F.prototype, sym, { + set: undefined +}); +assertThrowsInstanceOf(function () { "use strict"; f[sym] = 0; }, TypeError); + +// deeply inherited accessor property +var g = Object.create(f); +for (var i = 0; i < 100; i++) + g = Object.create(g); +assertEq(g[sym], 23); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/property-nonwritable.js b/js/src/tests/non262/Symbol/property-nonwritable.js new file mode 100644 index 0000000000..3e58383c78 --- /dev/null +++ b/js/src/tests/non262/Symbol/property-nonwritable.js @@ -0,0 +1,31 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var sym = Symbol.for("moon"); +function checkNotWritable(obj) { + // In sloppy mode, assigning to a nonwritable property silently fails. + obj[sym] = "portals"; + assertEq(obj[sym], "cheese"); + + // In strict mode code, it throws. + assertThrowsInstanceOf(function () { "use strict"; obj[sym] = "robots"; }, TypeError); + assertEq(obj[sym], "cheese"); +} + +var x = {}; +Object.defineProperty(x, sym, { + configurable: true, + enumerable: true, + value: "cheese", + writable: false +}); + +checkNotWritable(x); + +// Assignment can't shadow inherited nonwritable properties either. +var y = Object.create(x); +checkNotWritable(y); +checkNotWritable(Object.create(y)); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/property-reflection.js b/js/src/tests/non262/Symbol/property-reflection.js new file mode 100644 index 0000000000..5bdecf6632 --- /dev/null +++ b/js/src/tests/non262/Symbol/property-reflection.js @@ -0,0 +1,136 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Basic tests for standard Object APIs interacting with symbols. + +// Object.defineProperty +function F() {} +var f = new F; +Object.defineProperty(f, Symbol.for("name"), { + configurable: true, + value: "eff" +}); +assertEq("name" in f, false); +assertEq("Symbol(name)" in f, false); +assertEq(Symbol.for("name") in f, true); +assertEq(f[Symbol.for("name")], "eff"); + +// Object.defineProperties +function D() {} +var descs = new D; +var s1 = Symbol("s1"); +var hits = 0; +descs[s1] = { + get: () => hits++, + set: undefined, + enumerable: true, + configurable: true +}; +var s2 = Symbol("s2"); +descs[s2] = { + value: {}, + writable: true, + enumerable: false, + configurable: true +}; +var s3 = Symbol("s3"); +D.prototype[s3] = {value: "FAIL"}; +assertEq(Object.defineProperties(f, descs), f); +assertEq(s1 in f, true); +assertEq(f[s1], 0); +assertEq(hits, 1); +assertEq(s2 in f, true); +assertEq(f[s2], descs[s2].value); +assertEq(s3 in f, false); + +// Object.create +var n = Object.create({}, descs); +assertEq(s1 in n, true); +assertEq(n[s1], 1); +assertEq(hits, 2); +assertEq(s2 in n, true); +assertEq(n[s2], descs[s2].value); +assertEq(s3 in n, false); + +// Object.getOwnPropertyDescriptor +var desc = Object.getOwnPropertyDescriptor(n, s1); +assertDeepEq(desc, descs[s1]); +assertEq(desc.get, descs[s1].get); +desc = Object.getOwnPropertyDescriptor(n, s2); +assertDeepEq(desc, descs[s2]); +assertEq(desc.value, descs[s2].value); + +// Object.prototype.hasOwnProperty +assertEq(descs.hasOwnProperty(s1), true); +assertEq(descs.hasOwnProperty(s2), true); +assertEq(descs.hasOwnProperty(s3), false); +assertEq([].hasOwnProperty(Symbol.iterator), false); +assertEq(Array.prototype.hasOwnProperty(Symbol.iterator), true); + +// Object.prototype.propertyIsEnumerable +assertEq(n.propertyIsEnumerable(s1), true); +assertEq(n.propertyIsEnumerable(s2), false); +assertEq(n.propertyIsEnumerable(s3), false); // no such property +assertEq(D.prototype.propertyIsEnumerable(s3), true); +assertEq(descs.propertyIsEnumerable(s3), false); // inherited properties are not considered + +// Object.preventExtensions +var obj = {}; +obj[s1] = 1; +assertEq(Object.preventExtensions(obj), obj); +assertThrowsInstanceOf(function () { "use strict"; obj[s2] = 2; }, TypeError); +obj[s2] = 2; // still no effect +assertEq(s2 in obj, false); + +// Object.isSealed, Object.isFrozen +assertEq(Object.isSealed(obj), false); +assertEq(Object.isFrozen(obj), false); +assertEq(delete obj[s1], true); +assertEq(Object.isSealed(obj), true); +assertEq(Object.isFrozen(obj), true); + +obj = {}; +obj[s1] = 1; +Object.preventExtensions(obj); +Object.defineProperty(obj, s1, {configurable: false}); // still writable +assertEq(Object.isSealed(obj), true); +assertEq(Object.isFrozen(obj), false); +obj[s1] = 2; +assertEq(obj[s1], 2); +Object.defineProperty(obj, s1, {writable: false}); +assertEq(Object.isFrozen(obj), true); + +// Object.seal, Object.freeze +var obj = {}; +obj[s1] = 1; +Object.seal(obj); +desc = Object.getOwnPropertyDescriptor(obj, s1); +assertEq(desc.configurable, false); +assertEq(desc.writable, true); +Object.freeze(obj); +assertEq(Object.getOwnPropertyDescriptor(obj, s1).writable, false); + +// Object.setPrototypeOf purges caches for symbol-keyed properties. +var proto = {}; +proto[s1] = 1; +Object.defineProperty(proto, s2, { + get: () => 2, + set: v => undefined +}); +var obj = Object.create(proto); +var last1, last2; +var N = 9; +for (var i = 0; i < N; i++) { + last1 = obj[s1]; + last2 = obj[s2]; + obj[s2] = "marker"; + if (i === N - 2) + Object.setPrototypeOf(obj, {}); +} +assertEq(last1, undefined); +assertEq(last2, undefined); +assertEq(obj.hasOwnProperty(s2), true); +assertEq(obj[s2], "marker"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/realms.js b/js/src/tests/non262/Symbol/realms.js new file mode 100644 index 0000000000..98a1284ee0 --- /dev/null +++ b/js/src/tests/non262/Symbol/realms.js @@ -0,0 +1,36 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Symbols can be shared across realms. + +if (typeof Reflect !== "undefined" && typeof Reflect.Realm === "function") { + throw new Error("Congratulations on implementing Reflect.Realm! " + + "Please update this test to use it."); +} +if (typeof newGlobal === "function") { + var g = newGlobal(); + var gj = g.eval("jones = Symbol('jones')"); + assertEq(typeof gj, "symbol"); + assertEq(g.jones, g.jones); + assertEq(gj, g.jones); + assertEq(gj !== Symbol("jones"), true); + + // A symbol can be round-tripped to another realm and back; + // the result is the original symbol. + var smith = Symbol("smith"); + g.smith = smith; // put smith into the realm + assertEq(g.smith, smith); // pull it back out + + // Spot-check that non-generic methods can be applied to symbols and Symbol + // objects from other realms. + assertEq(Symbol.prototype.toString.call(gj), "Symbol(jones)"); + assertEq(Symbol.prototype.toString.call(g.eval("Object(Symbol('brown'))")), + "Symbol(brown)"); + + // Symbol.for functions share a symbol registry across all realms. + assertEq(g.Symbol.for("ponies"), Symbol.for("ponies")); + assertEq(g.eval("Symbol.for('rainbows')"), Symbol.for("rainbows")); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/shell.js b/js/src/tests/non262/Symbol/shell.js new file mode 100644 index 0000000000..e69de29bb2 diff --git a/js/src/tests/non262/Symbol/species.js b/js/src/tests/non262/Symbol/species.js new file mode 100644 index 0000000000..ba45066e1e --- /dev/null +++ b/js/src/tests/non262/Symbol/species.js @@ -0,0 +1,30 @@ +var BUGNUMBER = 1131043; +var summary = "Implement @@species getter for builtin types"; + +print(BUGNUMBER + ": " + summary); + +var TypedArray = Object.getPrototypeOf(Int8Array); + +for (var C of [Array, Map, Set, RegExp, + Int8Array, Uint8Array, Uint8ClampedArray, + Int16Array, Uint16Array, Int32Array, Uint32Array, + Float32Array, Float64Array, + ArrayBuffer]) { + assertEq(C[Symbol.species], C); +} + +for (C of [Array, Map, Set, RegExp, + TypedArray, + ArrayBuffer]) { + var desc = Object.getOwnPropertyDescriptor(C, Symbol.species); + assertDeepEq(Object.keys(desc).sort(), ["configurable", "enumerable", "get", "set"]); + assertEq(desc.set, undefined); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + assertEq(desc.get.apply(null), null); + assertEq(desc.get.apply(undefined), undefined); + assertEq(desc.get.apply(42), 42); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/surfaces.js b/js/src/tests/non262/Symbol/surfaces.js new file mode 100644 index 0000000000..7b3ef9f9b2 --- /dev/null +++ b/js/src/tests/non262/Symbol/surfaces.js @@ -0,0 +1,34 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Test superficial properties of the Symbol constructor and prototype. + +var desc = Object.getOwnPropertyDescriptor(this, "Symbol"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, true); +assertEq(typeof Symbol, "function"); +assertEq(Symbol.length, 0); + +desc = Object.getOwnPropertyDescriptor(Symbol, "prototype"); +assertEq(desc.configurable, false); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); + +assertEq(Symbol.prototype.constructor, Symbol); +desc = Object.getOwnPropertyDescriptor(Symbol.prototype, "constructor"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, true); + +desc = Object.getOwnPropertyDescriptor(Symbol, "iterator"); +assertEq(desc.configurable, false); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); + +assertEq(Symbol.for.length, 1); +assertEq(Symbol.prototype.toString.length, 0); +assertEq(Symbol.prototype.valueOf.length, 0); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/symbol-object-not-unboxed-for-value-to-id.js b/js/src/tests/non262/Symbol/symbol-object-not-unboxed-for-value-to-id.js new file mode 100644 index 0000000000..d889a77162 --- /dev/null +++ b/js/src/tests/non262/Symbol/symbol-object-not-unboxed-for-value-to-id.js @@ -0,0 +1,31 @@ +// Create a symbol and a wrapper for it. +var s = Symbol(); +var so = Object(s); + +// Create a symbol-valued property key using |s|. +var o = {[s]: 0}; + +// The default Symbol.prototype[@@toPrimitive] will unbox the symbol object as needed. +assertEq(o.propertyIsEnumerable(so), true); +assertEq(o.hasOwnProperty(so), true); + +// After redefining Symbol.prototype[@@toPrimitive], any calls to the ToPropertyKey +// abstract operation will no longer unbox the symbol object. +Object.defineProperty(Symbol.prototype, Symbol.toPrimitive, { + value: function() { + return "foo"; + } +}); + +// |o| doesn't have a string-valued property named "foo". +assertEq(o.propertyIsEnumerable(so), false); +assertEq(o.hasOwnProperty(so), false); + +o.foo = 123; + +// After |o.foo| was added, both calls should return true again. +assertEq(o.propertyIsEnumerable(so), true); +assertEq(o.hasOwnProperty(so), true); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/toPrimitive-undefined-or-null.js b/js/src/tests/non262/Symbol/toPrimitive-undefined-or-null.js new file mode 100644 index 0000000000..f43642e0f8 --- /dev/null +++ b/js/src/tests/non262/Symbol/toPrimitive-undefined-or-null.js @@ -0,0 +1,18 @@ +for (let method of [undefined, null]) { + let obj = { + [Symbol.toPrimitive]: method, + toString: () => "pass", + }; + assertEq("" + obj, "pass"); +} + +for (let method of [true, false, 0, 123, "", "abc", Symbol(), {}]) { + let obj = { + [Symbol.toPrimitive]: method, + toString: () => "pass", + }; + assertThrowsInstanceOf(() => "" + obj, TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/toPrimitive.js b/js/src/tests/non262/Symbol/toPrimitive.js new file mode 100644 index 0000000000..06262f99c6 --- /dev/null +++ b/js/src/tests/non262/Symbol/toPrimitive.js @@ -0,0 +1,39 @@ +// ES6 19.4.3.4 Symbol.prototype[@@toPrimitive](hint) + +// This method gets the primitive symbol from a Symbol wrapper object. +var sym = Symbol.for("truth") +var obj = Object(sym); +assertEq(obj[Symbol.toPrimitive]("default"), sym); + +// The hint argument is ignored. +assertEq(obj[Symbol.toPrimitive]("number"), sym); +assertEq(obj[Symbol.toPrimitive]("string"), sym); +assertEq(obj[Symbol.toPrimitive](), sym); +assertEq(obj[Symbol.toPrimitive](Math.atan2), sym); + +// The this value can also be a primitive symbol. +assertEq(sym[Symbol.toPrimitive](), sym); + +// Or a wrapper to a Symbol object in another compartment. +var obj2 = newGlobal().Object(sym); +assertEq(obj2[Symbol.toPrimitive]("default"), sym); + +// Otherwise a TypeError is thrown. +var symbolToPrimitive = Symbol.prototype[Symbol.toPrimitive]; +var nonSymbols = [ + undefined, null, true, 13, NaN, "justice", {}, [sym], + symbolToPrimitive, + new Proxy(obj, {}) +]; +for (var value of nonSymbols) { + assertThrowsInstanceOf(() => symbolToPrimitive.call(value, "string"), TypeError); +} + +// Surface features: +assertEq(symbolToPrimitive.name, "[Symbol.toPrimitive]"); +var desc = Object.getOwnPropertyDescriptor(Symbol.prototype, Symbol.toPrimitive); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); + +reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/toString.js b/js/src/tests/non262/Symbol/toString.js new file mode 100644 index 0000000000..b7bbda8762 --- /dev/null +++ b/js/src/tests/non262/Symbol/toString.js @@ -0,0 +1,27 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var cases = [ + {sym: Symbol(), str: "Symbol()"}, + {sym: Symbol("ok"), str: "Symbol(ok)"}, + {sym: Symbol("\0"), str: "Symbol(\0)"}, + {sym: Symbol.iterator, str: "Symbol(Symbol.iterator)"}, + {sym: Symbol.for("dummies"), str: "Symbol(dummies)"} +]; + +// Symbol.prototype.toString works on both primitive symbols and Symbol +// objects. +for (var test of cases) { + assertEq(test.sym.toString(), test.str); + assertEq(Object(test.sym).toString(), test.str); +} + +// Any other value throws. +var nonsymbols = [ + undefined, null, "not-ok", new String("still-not-ok"), {}, [] +]; +for (var nonsym of nonsymbols) + assertThrowsInstanceOf(() => Symbol.prototype.toString.call(nonsym), TypeError); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/toStringTag.js b/js/src/tests/non262/Symbol/toStringTag.js new file mode 100644 index 0000000000..20aac2c42c --- /dev/null +++ b/js/src/tests/non262/Symbol/toStringTag.js @@ -0,0 +1,155 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// ES6 19.1.3.6 Object.prototype.toString ( ) +function testToString() { + var tests = [ + [undefined, "[object Undefined]"], + [null, "[object Null]"], + [[], "[object Array]"], + [new String("abc"), "[object String]"], + [(function () {return arguments;})(), "[object Arguments]"], + [(function () {"use strict"; return arguments;})(), "[object Arguments]"], + [function() {}, "[object Function]"], + [new Error("abc"), "[object Error]"], + [true, "[object Boolean]"], + [5, "[object Number]"], + [new Date(), "[object Date]"], + [/regexp/, "[object RegExp]"], + [{[Symbol.toStringTag]: "abc"}, "[object abc]"], + [Object.create(JSON), "[object JSON]"], + [Object.create(new Number), "[object Object]"], + [Object.create(new Number, {[Symbol.toStringTag]: {value: "abc"}}), "[object abc]"], + [(function() { var x = new Number(); x[Symbol.toStringTag] = "abc"; return x; })(), "[object abc]"], + [[], "[object Array]"] + ]; + + // Testing if the values are obtained the right way. + for (let [value, expected] of tests) { + let result = Object.prototype.toString.call(value); + assertEq(result, expected); + } +} +testToString(); + +function testProxy() { + var count = 0; + var metaHandler = new Proxy({}, { + get(target, property, receiver) { + assertEq(property, "get"); + + return function(target, property, receiver) { + assertEq(property, Symbol.toStringTag); + count++; + return undefined; + } + } + }); + + assertEq(Object.prototype.toString.call(new Proxy({}, metaHandler)), "[object Object]") + assertEq(Object.prototype.toString.call(new Proxy(new Date, metaHandler)), "[object Object]") + assertEq(Object.prototype.toString.call(new Proxy([], metaHandler)), "[object Array]") + assertEq(Object.prototype.toString.call(new Proxy(function() {}, metaHandler)), "[object Function]") + var {proxy, revoke} = Proxy.revocable({}, metaHandler); + revoke(); + assertThrowsInstanceOf(() => Object.prototype.toString.call(proxy), TypeError); + + assertEq(count, 4); +} +testProxy(); + +// Tests the passed objects toStringTag values and ensures it's +// desc is writable: false, enumerable: false, configurable: true +function testDefault(object, expected) { + let desc = Object.getOwnPropertyDescriptor(object, Symbol.toStringTag); + assertEq(desc.value, expected); + assertEq(desc.writable, false); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); +} + +// ES6 19.4.3.5 Symbol.prototype [ @@toStringTag ] +testDefault(Symbol.prototype, "Symbol"); + +// ES6 20.2.1.9 Math [ @@toStringTag ] +testDefault(Math, "Math"); + +// ES6 21.1.5.2.2 %StringIteratorPrototype% [ @@toStringTag ] +testDefault(""[Symbol.iterator]().__proto__, "String Iterator") + +// ES6 22.1.5.2.2 %ArrayIteratorPrototype% [ @@toStringTag ] +testDefault([][Symbol.iterator]().__proto__, "Array Iterator") + +// ES6 22.2.3.31 get %TypedArray%.prototype [ @@toStringTag ] +function testTypedArray() { + let ta = (new Uint8Array(0)).__proto__.__proto__; + let desc = Object.getOwnPropertyDescriptor(ta, Symbol.toStringTag); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + assertEq(desc.set, undefined); + + let get = desc.get; + assertEq(get.name, "get [Symbol.toStringTag]"); + assertEq(get.call(3.14), undefined); + assertEq(get.call({}), undefined); + assertEq(get.call(ta), undefined); + + let types = [ + Int8Array, + Uint8Array, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array + ]; + + for (let type of types) { + let array = new type(0); + assertEq(get.call(array), type.name); + assertEq(Object.prototype.toString.call(array), `[object ${type.name}]`); + } +} +testTypedArray(); + +// ES6 23.1.3.13 Map.prototype [ @@toStringTag ] +testDefault(Map.prototype, "Map"); + +// ES6 23.1.5.2.2 %MapIteratorPrototype% [ @@toStringTag ] +testDefault(new Map()[Symbol.iterator]().__proto__, "Map Iterator") + +// ES6 23.2.3.12 Set.prototype [ @@toStringTag ] +testDefault(Set.prototype, "Set"); + +// ES6 23.2.5.2.2 %SetIteratorPrototype% [ @@toStringTag ] +testDefault(new Set()[Symbol.iterator]().__proto__, "Set Iterator") + +// ES6 23.3.3.6 WeakMap.prototype [ @@toStringTag ] +testDefault(WeakMap.prototype, "WeakMap"); + +// ES6 23.4.3.5 WeakSet.prototype [ @@toStringTag ] +testDefault(WeakSet.prototype, "WeakSet"); + +// ES6 24.1.4.4 ArrayBuffer.prototype [ @@toStringTag ] +testDefault(ArrayBuffer.prototype, "ArrayBuffer"); + +// ES6 24.2.4.21 DataView.prototype[ @@toStringTag ] +testDefault(DataView.prototype, "DataView"); + +// ES6 24.3.3 JSON [ @@toStringTag ] +testDefault(JSON, "JSON"); + +// ES6 25.2.3.3 GeneratorFunction.prototype [ @@toStringTag ] +testDefault(function* () {}.constructor.prototype, "GeneratorFunction"); + +// ES6 25.3.1.5 Generator.prototype [ @@toStringTag ] +testDefault(function* () {}().__proto__.__proto__, "Generator"); + +// ES6 25.4.5.4 Promise.prototype [ @@toStringTag ] +testDefault(Promise.prototype, "Promise"); + +// AsyncFunction.prototype [ @@toStringTag ] +testDefault(async function() {}.constructor.prototype, "AsyncFunction"); + +reportCompare(true, true); diff --git a/js/src/tests/non262/Symbol/typed-arrays.js b/js/src/tests/non262/Symbol/typed-arrays.js new file mode 100644 index 0000000000..a07cf396bb --- /dev/null +++ b/js/src/tests/non262/Symbol/typed-arrays.js @@ -0,0 +1,17 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Symbol-to-number type conversions involving typed arrays. + +for (var T of [Uint8Array, Uint8ClampedArray, Int16Array, Float32Array]) { + // Typed array constructors convert symbols using ToNumber(), which throws. + assertThrowsInstanceOf(() => new T([Symbol("a")]), TypeError); + + // Assignment does the same. + var arr = new T([1]); + assertThrowsInstanceOf(() => { arr[0] = Symbol.iterator; }, TypeError); + assertEq(arr[0], 1); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/typeof.js b/js/src/tests/non262/Symbol/typeof.js new file mode 100644 index 0000000000..104ae66dfd --- /dev/null +++ b/js/src/tests/non262/Symbol/typeof.js @@ -0,0 +1,11 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +assertEq(typeof Symbol(), "symbol"); +assertEq(typeof Symbol("ponies"), "symbol"); +assertEq(typeof Symbol.for("ponies"), "symbol"); + +assertEq(typeof Object(Symbol()), "object"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/valueOf.js b/js/src/tests/non262/Symbol/valueOf.js new file mode 100644 index 0000000000..a3823c3ffd --- /dev/null +++ b/js/src/tests/non262/Symbol/valueOf.js @@ -0,0 +1,22 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var symbols = [ + Symbol(), + Symbol("ok"), + Symbol.for("dummies"), + Symbol.iterator +]; + +for (var sym of symbols) { + assertEq(sym.valueOf(), sym); + assertEq(Object(sym).valueOf(), sym); +} + +// Any other value throws. +var nonsymbols = [undefined, null, NaN, {}, Symbol.prototype]; +for (var nonsym of nonsymbols) + assertThrowsInstanceOf(() => Symbol.prototype.valueOf.call(nonsym), TypeError); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Symbol/well-known.js b/js/src/tests/non262/Symbol/well-known.js new file mode 100644 index 0000000000..095d333a00 --- /dev/null +++ b/js/src/tests/non262/Symbol/well-known.js @@ -0,0 +1,42 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +var names = [ + "isConcatSpreadable", + "iterator", + "match", + "replace", + "search", + "species", + "hasInstance", + "split", + "toPrimitive", + "unscopables", + "asyncIterator" +]; + +for (var name of names) { + // Well-known symbols exist. + assertEq(typeof Symbol[name], "symbol"); + + // They are never in the registry. + assertEq(Symbol[name] !== Symbol.for("Symbol." + name), true); + + // They are shared across realms. + if (typeof Realm === 'function') + throw new Error("please update this test to use Realms"); + if (typeof newGlobal === 'function') { + var g = newGlobal(); + assertEq(Symbol[name], g.Symbol[name]); + } + + // Descriptor is all false. + var desc = Object.getOwnPropertyDescriptor(Symbol, name); + assertEq(typeof desc.value, "symbol"); + assertEq(desc.writable, false); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, false); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); -- cgit v1.2.3