diff options
Diffstat (limited to 'js/src/tests/ecma_6/Function')
24 files changed, 1098 insertions, 0 deletions
diff --git a/js/src/tests/ecma_6/Function/arguments-extra-property.js b/js/src/tests/ecma_6/Function/arguments-extra-property.js new file mode 100644 index 000000000..017734382 --- /dev/null +++ b/js/src/tests/ecma_6/Function/arguments-extra-property.js @@ -0,0 +1,33 @@ +var BUGNUMBER = 1263811; +var summary = "GetElem for modified arguments shouldn't be optimized to get original argument."; + +print(BUGNUMBER + ": " + summary); + +function testModifyFirst() { + function f() { + Object.defineProperty(arguments, 1, { value: 30 }); + assertEq(arguments[1], 30); + } + for (let i = 0; i < 10; i++) + f(10, 20); +} +testModifyFirst(); + +function testModifyLater() { + function f() { + var ans = 20; + for (let i = 0; i < 10; i++) { + if (i == 5) { + Object.defineProperty(arguments, 1, { value: 30 }); + ans = 30; + } + assertEq(arguments[1], ans); + } + } + for (let i = 0; i < 10; i++) + f(10, 20); +} +testModifyLater(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Function/arguments-iterator.js b/js/src/tests/ecma_6/Function/arguments-iterator.js new file mode 100644 index 000000000..5610b8a24 --- /dev/null +++ b/js/src/tests/ecma_6/Function/arguments-iterator.js @@ -0,0 +1,167 @@ +var BUGNUMBER = 992617; +var summary = "Implement arguments[@@iterator]."; + +print(BUGNUMBER + ": " + summary); + +// MappedArgumentsObject +let mapped = [ + function(a, b, c) { + assertEq(Symbol.iterator in arguments, true); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + arguments[Symbol.iterator] = 10; + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + Object.defineProperty(arguments, Symbol.iterator, { + value: 10, writable: true, enumerable: true, configurable: true + }); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function(a, b, c) { + assertEq(arguments[Symbol.iterator], Array.prototype[Symbol.iterator]); + }, + function(a, b, c) { + assertEq(arguments[Symbol.iterator].name, "values"); + }, + function(a, b, c) { + var desc = Object.getOwnPropertyDescriptor(arguments, Symbol.iterator); + assertEq("value" in desc, true); + assertEq(desc.value, Array.prototype[Symbol.iterator]); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + }, + function(a, b, c) { + var iter = arguments[Symbol.iterator](); + assertDeepEq(iter.next(), { value: 10, done: false }); + assertDeepEq(iter.next(), { value: 20, done: false }); + assertDeepEq(iter.next(), { value: 30, done: false }); + assertDeepEq(iter.next(), { value: undefined, done: true }); + }, + function(a, b, c) { + assertDeepEq([...arguments], [10, 20, 30]); + }, + function(a, b, c) { + b = 40; + assertDeepEq([...arguments], [10, 40, 30]); + }, + function(a, b, c) { + arguments.length = 4; + assertDeepEq([...arguments], [10, 20, 30, undefined]); + }, + function(a, b, c) { + arguments[5] = 50; + assertDeepEq([...arguments], [10, 20, 30]); + }, + function(a, b, c) { + arguments[Symbol.iterator] = function*() { + yield 40; + yield 50; + yield 60; + }; + assertDeepEq([...arguments], [40, 50, 60]); + }, +]; +for (let f of mapped) { + f(10, 20, 30); +} + +var g1 = newGlobal(); +assertEq(g1.eval(` +function f(a, b, c) { + return arguments[Symbol.iterator].name; +} +f(1, 2, 3); +`), "values"); + +// UnmappedArgumentsObject +let unmapped = [ + function([a], b, c) { + assertEq(Symbol.iterator in arguments, true); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + arguments[Symbol.iterator] = 10; + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + Object.defineProperty(arguments, Symbol.iterator, { + value: 10, writable: true, enumerable: true, configurable: true + }); + delete arguments[Symbol.iterator]; + assertEq(Symbol.iterator in arguments, false); + }, + function([a], b, c) { + assertEq(arguments[Symbol.iterator], Array.prototype[Symbol.iterator]); + }, + function([a], b, c) { + assertEq(arguments[Symbol.iterator].name, "values"); + }, + function([a], b, c) { + var desc = Object.getOwnPropertyDescriptor(arguments, Symbol.iterator); + assertEq("value" in desc, true); + assertEq(desc.value, Array.prototype[Symbol.iterator]); + assertEq(desc.writable, true); + assertEq(desc.enumerable, false); + assertEq(desc.configurable, true); + }, + function([a], b, c) { + var iter = arguments[Symbol.iterator](); + assertDeepEq(iter.next(), { value: [10], done: false }); + assertDeepEq(iter.next(), { value: 20, done: false }); + assertDeepEq(iter.next(), { value: 30, done: false }); + assertDeepEq(iter.next(), { value: undefined, done: true }); + }, + function([a], b, c) { + assertDeepEq([...arguments], [[10], 20, 30]); + }, + function([a], b, c) { + b = 40; + assertDeepEq([...arguments], [[10], 20, 30]); + }, + function([a], b, c) { + arguments.length = 4; + assertDeepEq([...arguments], [[10], 20, 30, undefined]); + }, + function([a], b, c) { + arguments[5] = 50; + assertDeepEq([...arguments], [[10], 20, 30]); + }, + function([a], b, c) { + arguments[Symbol.iterator] = function*() { + yield 40; + yield 50; + yield 60; + }; + assertDeepEq([...arguments], [40, 50, 60]); + }, +]; +for (let f of unmapped) { + f([10], 20, 30); +} + +var g2 = newGlobal(); +assertEq(g2.eval(` +function f([a], b, c) { + return arguments[Symbol.iterator].name; +} +f([1], 2, 3); +`), "values"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Function/arguments-parameter-shadowing.js b/js/src/tests/ecma_6/Function/arguments-parameter-shadowing.js new file mode 100644 index 000000000..bc2b43011 --- /dev/null +++ b/js/src/tests/ecma_6/Function/arguments-parameter-shadowing.js @@ -0,0 +1,22 @@ +// Test that var declarations of arguments "shadows" the arguments binding +// used in parameter expressions. + +function g8(h = () => arguments) { + var arguments = 0; + assertEq(arguments, 0); + assertEq(arguments === h(), false); +} +g8(); + +function g9(h = () => arguments) { + var arguments; + assertEq(void 0 === arguments, false); + assertEq(h(), arguments); + arguments = 0; + assertEq(arguments, 0); + assertEq(arguments === h(), false); +} +g9(); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Function/arrow-has-duplicated.js b/js/src/tests/ecma_6/Function/arrow-has-duplicated.js new file mode 100644 index 000000000..19096ebf8 --- /dev/null +++ b/js/src/tests/ecma_6/Function/arrow-has-duplicated.js @@ -0,0 +1,15 @@ +// Make sure duplicated name is allowed in non-strict. +function f0(a, a) { +} + +// SyntaxError should be thrown if arrow function has duplicated name. +assertThrowsInstanceOf(() => eval(` +(a, a) => { +}; +`), SyntaxError); +assertThrowsInstanceOf(() => eval(` +(a, ...a) => { +}; +`), SyntaxError); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Function/bound-length-and-name.js b/js/src/tests/ecma_6/Function/bound-length-and-name.js new file mode 100644 index 000000000..ef2f1ffbc --- /dev/null +++ b/js/src/tests/ecma_6/Function/bound-length-and-name.js @@ -0,0 +1,40 @@ +var proxy = new Proxy(function() {}, { + getOwnPropertyDescriptor(target, name) { + assertEq(name, "length"); + return {value: 3, configurable: true}; + }, + + get(target, name) { + if (name == "length") + return 3; + if (name == "name") + return "hello world"; + assertEq(false, true); + } +}) + +var bound = Function.prototype.bind.call(proxy); +assertEq(bound.name, "bound hello world"); +assertEq(bound.length, 3); + +var fun = function() {}; +Object.defineProperty(fun, "name", {value: 1337}); +Object.defineProperty(fun, "length", {value: "15"}); +bound = fun.bind(); +assertEq(bound.name, "bound "); +assertEq(bound.length, 0); + +Object.defineProperty(fun, "length", {value: Number.MAX_SAFE_INTEGER}); +bound = fun.bind(); +assertEq(bound.length, Number.MAX_SAFE_INTEGER); + +Object.defineProperty(fun, "length", {value: -100}); +bound = fun.bind(); +assertEq(bound.length, 0); + +fun = function f(a, ...b) { }; +assertEq(fun.length, 1); +bound = fun.bind(); +assertEq(bound.length, 1); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Function/bound-non-constructable.js b/js/src/tests/ecma_6/Function/bound-non-constructable.js new file mode 100644 index 000000000..cee1dd580 --- /dev/null +++ b/js/src/tests/ecma_6/Function/bound-non-constructable.js @@ -0,0 +1,17 @@ +var objects = [ + Math.sin.bind(null), + new Proxy(Math.sin.bind(null), {}), + Function.prototype.bind.call(new Proxy(Math.sin, {})) +] + +for (var obj of objects) { + // Target is not constructable, so a new array should be created internally. + assertDeepEq(Array.from.call(obj, [1, 2, 3]), [1, 2, 3]); + assertDeepEq(Array.of.call(obj, 1, 2, 3), [1, 2, 3]); + + // Make sure they are callable, but not constructable. + obj(); + assertThrowsInstanceOf(() => new obj, TypeError); +} + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Function/bound-prototype.js b/js/src/tests/ecma_6/Function/bound-prototype.js new file mode 100644 index 000000000..8b0f295a5 --- /dev/null +++ b/js/src/tests/ecma_6/Function/bound-prototype.js @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +function Bound(fn) { + return Function.prototype.bind.call(fn); +} + +var fnDefaultPrototype = function(){}; +assertEq(Object.getPrototypeOf(Bound(fnDefaultPrototype)), Function.prototype); + +var fnGeneratorPrototype = function*(){}; +assertEq(Object.getPrototypeOf(Bound(fnGeneratorPrototype)), function*(){}.constructor.prototype); + +var fnCustomPrototype = Object.setPrototypeOf(function(){}, Array.prototype); +assertEq(Object.getPrototypeOf(Bound(fnCustomPrototype)), Array.prototype); + +var fnNullPrototype = Object.setPrototypeOf(function(){}, null); +assertEq(Object.getPrototypeOf(Bound(fnNullPrototype)), null); + + +function LoggingProxy(target) { + var log = []; + var proxy = new Proxy(target, new Proxy({}, { + get(target, propertyKey, receiver) { + log.push(propertyKey); + } + })); + return {proxy, log}; +} + +var {proxy, log} = LoggingProxy(function(){}); +Bound(proxy); +assertEqArray(log, ["getPrototypeOf", "getOwnPropertyDescriptor", "get", "get"]); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/ecma_6/Function/browser.js b/js/src/tests/ecma_6/Function/browser.js new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/js/src/tests/ecma_6/Function/browser.js diff --git a/js/src/tests/ecma_6/Function/configurable-length-builtins.js b/js/src/tests/ecma_6/Function/configurable-length-builtins.js new file mode 100644 index 000000000..f28eaae15 --- /dev/null +++ b/js/src/tests/ecma_6/Function/configurable-length-builtins.js @@ -0,0 +1,21 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Deleting .length from a variety of builtin functions works as expected. +for (var fun of [Math.sin, Array.prototype.map, eval]) { + assertEq(delete fun.length, true); + assertEq(fun.hasOwnProperty("length"), false); + assertEq("length" in fun, true); // still inheriting Function.prototype.length + assertEq(fun.length, 0); + + // The inherited property is nonwritable, so assigning still fails + // (silently, in sloppy mode). + fun.length = Math.hypot; + assertEq(fun.length, 0); + + // It can be shadowed via defineProperty. + Object.defineProperty(fun, "length", {value: Math.hypot}); + assertEq(fun.length, Math.hypot); +} + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Function/configurable-length.js b/js/src/tests/ecma_6/Function/configurable-length.js new file mode 100644 index 000000000..127038fb5 --- /dev/null +++ b/js/src/tests/ecma_6/Function/configurable-length.js @@ -0,0 +1,86 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ */ + +// Very simple initial test that the "length" property of a function is +// configurable. More thorough tests follow. +var f = function (a1, a2, a3, a4) {}; +assertEq(delete f.length, true); +assertEq(f.hasOwnProperty("length"), false); +assertEq(f.length, 0); // inherited from Function.prototype.length +assertEq(delete Function.prototype.length, true); +assertEq(f.length, undefined); + + +// Now for the details. +// +// Many of these tests are poking at the "resolve hook" mechanism SM uses to +// lazily create this property, which is wonky and deserving of some extra +// skepticism. + +// We've deleted Function.prototype.length. Check that the resolve hook does +// not resurrect it. +assertEq("length" in Function.prototype, false); +Function.prototype.length = 7; +assertEq(Function.prototype.length, 7); +delete Function.prototype.length; +assertEq(Function.prototype.length, undefined); + +// OK, define Function.prototype.length back to its original state per spec, so +// the remaining tests can run in a more typical environment. +Object.defineProperty(Function.prototype, "length", {value: 0, configurable: true}); + +// Check the property descriptor of a function length property. +var g = function f(a1, a2, a3, a4, a5) {}; +var desc = Object.getOwnPropertyDescriptor(g, "length"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); +assertEq(desc.value, 5); + +// After deleting the length property, assigning to f.length fails because +// Function.prototype.length is non-writable. In strict mode it would throw. +delete g.length; +g.length = 12; +assertEq(g.hasOwnProperty("length"), false); +assertEq(g.length, 0); + +// After deleting both the length property and Function.prototype.length, +// assigning to f.length creates a new plain old data property. +delete Function.prototype.length; +g.length = 13; +var desc = Object.getOwnPropertyDescriptor(g, "length"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, true); +assertEq(desc.writable, true); +assertEq(desc.value, 13); + +// Deleting the .length of one instance of a FunctionDeclaration does not +// affect other instances. +function mkfun() { + function fun(a1, a2, a3, a4, a5) {} + return fun; +} +g = mkfun(); +var h = mkfun(); +delete h.length; +assertEq(g.length, 5); +assertEq(mkfun().length, 5); + +// Object.defineProperty on a brand-new function is sufficient to cause the +// LENGTH_RESOLVED flag to be set. +g = mkfun(); +Object.defineProperty(g, "length", {value: 0}); +assertEq(delete g.length, true); +assertEq(g.hasOwnProperty("length"), false); + +// Object.defineProperty on a brand-new function correctly merges new +// attributes with the builtin ones. +g = mkfun(); +Object.defineProperty(g, "length", { value: 42 }); +desc = Object.getOwnPropertyDescriptor(g, "length"); +assertEq(desc.configurable, true); +assertEq(desc.enumerable, false); +assertEq(desc.writable, false); +assertEq(desc.value, 42); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Function/construct-bound-proxy-with-many-arguments.js b/js/src/tests/ecma_6/Function/construct-bound-proxy-with-many-arguments.js new file mode 100644 index 000000000..6c9bb41a3 --- /dev/null +++ b/js/src/tests/ecma_6/Function/construct-bound-proxy-with-many-arguments.js @@ -0,0 +1,13 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +var proxy = Function.prototype.bind.call(new Proxy(Array, {})); +for (var i = 10; i < 50; ++i) { + var args = Array(i).fill(i); + var array = new proxy(...args); + assertEqArray(array, args); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Function/function-constructor-toString-arguments-before-parsing-params.js b/js/src/tests/ecma_6/Function/function-constructor-toString-arguments-before-parsing-params.js new file mode 100644 index 000000000..4e88a0096 --- /dev/null +++ b/js/src/tests/ecma_6/Function/function-constructor-toString-arguments-before-parsing-params.js @@ -0,0 +1,23 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 920479; +var summary = + "Convert all arguments passed to Function() to string before doing any " + + "parsing of the to-be-created Function's parameters or body text"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +assertThrowsValue(() => Function("@", { toString() { throw 42; } }), 42); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/ecma_6/Function/function-name.js b/js/src/tests/ecma_6/Function/function-name.js new file mode 100644 index 000000000..7beca56df --- /dev/null +++ b/js/src/tests/ecma_6/Function/function-name.js @@ -0,0 +1,64 @@ +function testFunctionName(f) { + var name = f.name; + f.name = 'g'; + assertEq(f.name, name); + assertEq(delete f.name, true); + assertEq(f.name, ''); + assertEq(f.hasOwnProperty('name'), false); + f.name = 'g'; + assertEq(f.name, ''); + Object.defineProperty(f, 'name', {value: 'g'}); + assertEq(f.name, 'g'); +} +function testFunctionNameStrict(f) { + "use strict"; + var name = f.name; + var error; + try { + f.name = 'g'; + } catch (e) { + error = e; + } + assertEq(f.name, name); + assertEq(error instanceof TypeError, true); + assertEq(delete f.name, true); + assertEq(f.name, ''); + assertEq(f.hasOwnProperty('name'), false); + error = null; + try { + f.name = 'g'; + } catch (e) { + error = e; + } + assertEq(f.name, ''); + assertEq(error instanceof TypeError, true); + Object.defineProperty(f, 'name', {value: 'g'}); + assertEq(f.name, 'g'); +} + +assertEq(Object.getOwnPropertyDescriptor(Object, "name").writable, false); +assertEq(Object.getOwnPropertyDescriptor(Object, "name").enumerable, false); +assertEq(Object.getOwnPropertyDescriptor(Object, "name").configurable, true); +assertEq(Object.getOwnPropertyDescriptor(Object, "name").value, 'Object'); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").writable, false); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").enumerable, false); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").configurable, true); +assertEq(Object.getOwnPropertyDescriptor(function f(){}, "name").value, 'f'); + +// Basic test ensuring that Object.defineProperty works on pristine function. +function f() {}; +Object.defineProperty(f, 'name', {value: 'g'}); +assertEq(f.name, 'g'); + +// .name behaves as expected on scripted function. +testFunctionName(function f(){}); +testFunctionNameStrict(function f(){}); +// .name behaves as expected on builtin function. +testFunctionName(Function.prototype.apply); +testFunctionNameStrict(Function.prototype.call); +// .name behaves as expected on self-hosted builtin function. +testFunctionName(Array.prototype.forEach); +testFunctionNameStrict(Array.prototype.some); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/ecma_6/Function/has-instance-jitted.js b/js/src/tests/ecma_6/Function/has-instance-jitted.js new file mode 100644 index 000000000..a2d33abc7 --- /dev/null +++ b/js/src/tests/ecma_6/Function/has-instance-jitted.js @@ -0,0 +1,96 @@ +const OriginalHasInstance = Function.prototype[Symbol.hasInstance]; + +// Ensure that folding doesn't impact user defined @@hasInstance methods. +{ + function Test() { + this.x = 1; + } + + Object.defineProperty(Test, Symbol.hasInstance, + {writable: true, value: () => false}); + + function x(t) { + return t instanceof Test; + } + + function y() { + let t = new Test; + let b = true; + for (let i = 0; i < 10; i++) { + b = b && x(t); + } + return b; + } + + + function z() { + let f = 0; + let t = 0; + for (let i = 0; i < 100; i++) + assertEq(y(), false); + } + + z(); +} + +// Ensure that the jitting does not clobber user defined @@hasInstance methods. +{ + function a() { + function b() {}; + b.__proto__ = a.prototype; + return b; + }; + let c = new a(); + + let t = 0; + let f = 0; + let e = 0; + for (let i = 0; i < 40000; i++) { + if (i == 20000) + Object.defineProperty(a.prototype, Symbol.hasInstance, + {writable: true, value: () => true}); + if (i == 30000) + Object.setPrototypeOf(c, Function.prototype); + + if (1 instanceof c) { + t++; + } else { + f++; + } + } + + assertEq(t, 10000); + assertEq(f, 30000); +} + +{ + function a() {}; + function b() {}; + Object.defineProperty(a, Symbol.hasInstance, {writable: true, value: () => true}); + assertEq(b instanceof a, true); + for (let _ of Array(10000)) + assertEq(b instanceof a, true); +} + +{ + function a(){}; + function b(){}; + function c(){}; + function d(){}; + function e(){}; + Object.defineProperty(a, Symbol.hasInstance, {value: () => true }); + Object.defineProperty(b, Symbol.hasInstance, {value: () => true }); + Object.defineProperty(c, Symbol.hasInstance, {value: () => true }); + Object.defineProperty(d, Symbol.hasInstance, {value: () => true }); + let funcs = [a, b, c, d]; + for (let f of funcs) + assertEq(e instanceof f, true); + + for (let _ of Array(10001)) { + for (let f of funcs) + assertEq(e instanceof f, true); + } +} + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Function/has-instance.js b/js/src/tests/ecma_6/Function/has-instance.js new file mode 100644 index 000000000..f0c7bf28e --- /dev/null +++ b/js/src/tests/ecma_6/Function/has-instance.js @@ -0,0 +1,101 @@ +// It is possible to override Function.prototype[@@hasInstance]. +let passed = false; +let obj = { foo: true }; +let C = function(){}; + +Object.defineProperty(C, Symbol.hasInstance, { + value: function(inst) { passed = inst.foo; return false; } +}); + +assertEq(obj instanceof C, false); +assertEq(passed, true); + +{ + let obj = { + [Symbol.hasInstance](v) { return true; }, + }; + let whatevs = {}; + assertEq(whatevs instanceof obj, true); +} + +{ + + function zzzz() {}; + let xxxx = new zzzz(); + assertEq(xxxx instanceof zzzz, true); + assertEq(zzzz[Symbol.hasInstance](xxxx), true); + +} + +// Non-callable objects should return false. +const nonCallables = [ + 1, + undefined, + null, + "nope", +] + +for (let nonCallable of nonCallables) { + assertEq(nonCallable instanceof Function, false); + assertEq(nonCallable instanceof Object, false); +} + +// Non-callables should throw when used on the right hand side +// of `instanceof`. +assertThrowsInstanceOf(() => { + function foo() {}; + let obj = {}; + foo instanceof obj; +}, TypeError); + +// Non-callables do not throw for overridden methods +let o = {[Symbol.hasInstance](v) { return true; }} +assertEq(1 instanceof o, true); + +// Non-callables return false instead of an exception when +// Function.prototype[Symbol.hasInstance] is called directly. +for (let nonCallable of nonCallables) { + assertEq(Function.prototype[Symbol.hasInstance].call(nonCallable, Object), false); +} + +// It should be possible to call the Symbol.hasInstance method directly. +assertEq(Function.prototype[Symbol.hasInstance].call(Function, () => 1), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Function, Object), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Function, null), false); +assertEq(Function.prototype[Symbol.hasInstance].call(Function, Array), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Object, Array), true); +assertEq(Function.prototype[Symbol.hasInstance].call(Array, Function), false); +assertEq(Function.prototype[Symbol.hasInstance].call(({}), Function), false); +assertEq(Function.prototype[Symbol.hasInstance].call(), false) +assertEq(Function.prototype[Symbol.hasInstance].call(({})), false) + +// Ensure that bound functions are unwrapped properly +let bindme = {x: function() {}}; +let instance = new bindme.x(); +let xOuter = bindme.x; +let bound = xOuter.bind(bindme); +let doubleBound = bound.bind(bindme); +let tripleBound = bound.bind(doubleBound); +assertEq(Function.prototype[Symbol.hasInstance].call(bound, instance), true); +assertEq(Function.prototype[Symbol.hasInstance].call(doubleBound, instance), true); +assertEq(Function.prototype[Symbol.hasInstance].call(tripleBound, instance), true); + +// Function.prototype[Symbol.hasInstance] is not configurable +let desc = Object.getOwnPropertyDescriptor(Function.prototype, Symbol.hasInstance); +assertEq(desc.configurable, false); + +// Attempting to use a non-callable @@hasInstance triggers a type error +// Bug 1280892 +assertThrowsInstanceOf(() => { + var fun = function() {} + var p = new Proxy(fun, { + get(target, key) { + return /not-callable/; + } + }); + fun instanceof p; +}, TypeError); + + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Function/length-with-destructuring-and-parameter-expression.js b/js/src/tests/ecma_6/Function/length-with-destructuring-and-parameter-expression.js new file mode 100644 index 000000000..a3f00ac1f --- /dev/null +++ b/js/src/tests/ecma_6/Function/length-with-destructuring-and-parameter-expression.js @@ -0,0 +1,31 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +assertEq(function([a = 0]){}.length, 1); +assertEq(function({p: a = 0}){}.length, 1); +assertEq(function({a = 0}){}.length, 1); +assertEq(function({[0]: a}){}.length, 1); + +assertEq(function([a = 0], [b = 0]){}.length, 2); +assertEq(function({p: a = 0}, [b = 0]){}.length, 2); +assertEq(function({a = 0}, [b = 0]){}.length, 2); +assertEq(function({[0]: a}, [b = 0]){}.length, 2); + +assertEq(function(x, [a = 0]){}.length, 2); +assertEq(function(x, {p: a = 0}){}.length, 2); +assertEq(function(x, {a = 0}){}.length, 2); +assertEq(function(x, {[0]: a}){}.length, 2); + +assertEq(function(x = 0, [a = 0]){}.length, 0); +assertEq(function(x = 0, {p: a = 0}){}.length, 0); +assertEq(function(x = 0, {a = 0}){}.length, 0); +assertEq(function(x = 0, {[0]: a}){}.length, 0); + +assertEq(function([a = 0], ...r){}.length, 1); +assertEq(function({p: a = 0}, ...r){}.length, 1); +assertEq(function({a = 0}, ...r){}.length, 1); +assertEq(function({[0]: a}, ...r){}.length, 1); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/ecma_6/Function/line-terminator-before-arrow.js b/js/src/tests/ecma_6/Function/line-terminator-before-arrow.js new file mode 100644 index 000000000..52bdce7f3 --- /dev/null +++ b/js/src/tests/ecma_6/Function/line-terminator-before-arrow.js @@ -0,0 +1,9 @@ +assertThrowsInstanceOf(() => eval("() \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("a \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a) /*\n*/ => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, b) \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, b = 1) \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, ...b) \n => {}"), SyntaxError); +assertThrowsInstanceOf(() => eval("(a, b = 1, ...c) \n => {}"), SyntaxError); + +reportCompare(0, 0, "ok"); diff --git a/js/src/tests/ecma_6/Function/method-has-duplicated.js b/js/src/tests/ecma_6/Function/method-has-duplicated.js new file mode 100644 index 000000000..dc0a9dfb4 --- /dev/null +++ b/js/src/tests/ecma_6/Function/method-has-duplicated.js @@ -0,0 +1,19 @@ +// Make sure duplicated name is allowed in non-strict. +function f0(a) { +} + +// SyntaxError should be thrown if method definition has duplicated name. +assertThrowsInstanceOf(() => eval(` +({ + m1(a, a) { + } +}); +`), SyntaxError); +assertThrowsInstanceOf(() => eval(` +({ + m2(a, ...a) { + } +}); +`), SyntaxError); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Function/parameter-redeclaration.js b/js/src/tests/ecma_6/Function/parameter-redeclaration.js new file mode 100644 index 000000000..74e55e3aa --- /dev/null +++ b/js/src/tests/ecma_6/Function/parameter-redeclaration.js @@ -0,0 +1,19 @@ +// 'var' is allowed to redeclare parameters. +function f1(a = 0) { + var a; +} + +// 'let' and 'const' at body-level are not allowed to redeclare parameters. +assertThrowsInstanceOf(() => { + eval(`function f2(a = 0) { + let a; + }`); +}, SyntaxError); +assertThrowsInstanceOf(() => { + eval(`function f3(a = 0) { + const a; + }`); +}, SyntaxError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Function/rest-has-duplicated.js b/js/src/tests/ecma_6/Function/rest-has-duplicated.js new file mode 100644 index 000000000..67577ab4e --- /dev/null +++ b/js/src/tests/ecma_6/Function/rest-has-duplicated.js @@ -0,0 +1,17 @@ +// Make sure duplicated name is allowed in non-strict. +function f0(a, a) { +} + +// SyntaxError should be thrown if rest parameter name is duplicated. +assertThrowsInstanceOf(() => eval(` +function f1(a, ...a) { +} +`), SyntaxError); + +// SyntaxError should be thrown if there is a duplicated parameter. +assertThrowsInstanceOf(() => eval(` +function f2(a, a, ...b) { +} +`), SyntaxError); + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/ecma_6/Function/rest-parameter-names.js b/js/src/tests/ecma_6/Function/rest-parameter-names.js new file mode 100644 index 000000000..6cfa01dcf --- /dev/null +++ b/js/src/tests/ecma_6/Function/rest-parameter-names.js @@ -0,0 +1,68 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 1288460; +var summary = + "Rest parameters to functions can be named |yield| or |eval| or |let| in " + "non-strict code"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var f1 = (...yield) => yield + 42; +assertEq(f1(), "42"); +assertEq(f1(1), "142"); + +var f2 = (...eval) => eval + 42; +assertEq(f2(), "42"); +assertEq(f2(1), "142"); + +var f3 = (...let) => let + 42; +assertEq(f3(), "42"); +assertEq(f3(1), "142"); + +function g1(x, ...yield) +{ + return yield + x; +} +assertEq(g1(0, 42), "420"); + +function g2(x, ...eval) +{ + return eval + x; +} +assertEq(g2(0, 42), "420"); + +function g3(x, ...let) +{ + return let + x; +} +assertEq(g3(0, 42), "420"); + +function h() +{ + "use strict"; + + var badNames = ["yield", "eval", "let"]; + + for (var badName of ["yield", "eval", "let"]) + { + assertThrowsInstanceOf(() => eval(`var q = (...${badName}) => ${badName} + 42;`), + SyntaxError); + + assertThrowsInstanceOf(() => eval(`function r(x, ...${badName}) { return x + ${badName}; }`), + SyntaxError); + } +} +h(); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/ecma_6/Function/return-finally.js b/js/src/tests/ecma_6/Function/return-finally.js new file mode 100644 index 000000000..fe075d457 --- /dev/null +++ b/js/src/tests/ecma_6/Function/return-finally.js @@ -0,0 +1,172 @@ +var BUGNUMBER = 1202134; +var summary = "Return value should not be overwritten by finally block with normal execution."; + +print(BUGNUMBER + ": " + summary); + +// ==== single ==== + +var f; +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is return + try { + return 42; + } finally { + return 43; + } +}; +assertEq(f(), 43); + +f = function() { + // F.[[type]] is throw + try { + return 42; + } finally { + throw 43; + } +}; +var caught = false; +try { + f(); +} catch (e) { + assertEq(e, 43); + caught = true; +} +assertEq(caught, true); + +f = function() { + // F.[[type]] is break + do try { + return 42; + } finally { + break; + } while (false); + return 43; +}; +assertEq(f(), 43); + +f = function() { + // F.[[type]] is break + L: try { + return 42; + } finally { + break L; + } + return 43; +}; +assertEq(f(), 43); + +f = function() { + // F.[[type]] is continue + do try { + return 42; + } finally { + continue; + } while (false); + return 43; +}; +assertEq(f(), 43); + +// ==== nested ==== + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is break + do try { + return 43; + } finally { + break; + } while (0); + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is break + L: try { + return 43; + } finally { + break L; + } + } +} +assertEq(f(), 42); + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is continue + do try { + return 43; + } finally { + continue; + } while (0); + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is normal + // B.[[type]] is normal + try { + // F.[[type]] is throw + try { + return 43; + } finally { + throw 9; + } + } catch (e) { + } + } +}; +assertEq(f(), 42); + +f = function() { + // F.[[type]] is return + try { + return 41; + } finally { + // F.[[type]] is normal + // B.[[type]] is return + try { + return 42; + } finally { + // F.[[type]] is break + do try { + return 43; + } finally { + break; + } while (0); + } + } +}; +assertEq(f(), 42); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/ecma_6/Function/shell.js b/js/src/tests/ecma_6/Function/shell.js new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/js/src/tests/ecma_6/Function/shell.js diff --git a/js/src/tests/ecma_6/Function/spread-iterator-primitive.js b/js/src/tests/ecma_6/Function/spread-iterator-primitive.js new file mode 100644 index 000000000..79320ad7f --- /dev/null +++ b/js/src/tests/ecma_6/Function/spread-iterator-primitive.js @@ -0,0 +1,28 @@ +var BUGNUMBER = 1021835; +var summary = "Returning non-object from @@iterator should throw"; + +print(BUGNUMBER + ": " + summary); + +let primitives = [ + 1, + true, + undefined, + null, + "foo", + Symbol.iterator +]; + +function f() { +} + +for (let primitive of primitives) { + let arg = { + [Symbol.iterator]() { + return primitive; + } + }; + assertThrowsInstanceOf(() => f(...arg), TypeError); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); |