diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /js/src/tests/non262/Function | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/non262/Function')
83 files changed, 5590 insertions, 0 deletions
diff --git a/js/src/tests/non262/Function/10.1.6-01.js b/js/src/tests/non262/Function/10.1.6-01.js new file mode 100644 index 0000000000..fbb98616e1 --- /dev/null +++ b/js/src/tests/non262/Function/10.1.6-01.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 293782; +var summary = 'Local variables should not be enumerable properties of the function'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function f() +{ + var x,y + } + +var p; +actual = ''; + +for (p in f) +{ + actual += p + ','; +} +expect = ''; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/10.1.6.js b/js/src/tests/non262/Function/10.1.6.js new file mode 100644 index 0000000000..504001cb1a --- /dev/null +++ b/js/src/tests/non262/Function/10.1.6.js @@ -0,0 +1,23 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 293782; +var summary = 'Local variables can cause predefined function object properties to be undefined'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function f() +{ + var name=1; +} + +expect = 'f'; +actual = f.name; + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/10.2.1.1.6.js b/js/src/tests/non262/Function/10.2.1.1.6.js new file mode 100644 index 0000000000..69613386cd --- /dev/null +++ b/js/src/tests/non262/Function/10.2.1.1.6.js @@ -0,0 +1,35 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function strictThis() { 'use strict'; return this; } + +/* Check that calls of flat closure slots get the right |this|. */ +function flat(g) { + function h() { return g(); } + return h; +} +assertEq(flat(strictThis)(), undefined); + +/* Check that calls up upvars get the right |this|. */ +function upvar(f) { + function h() { + return f(); + } + return h(); +} +assertEq(upvar(strictThis), undefined); + +/* Check that calls to with-object properties get an appropriate 'this'. */ +var obj = { f: strictThis }; +with (obj) { + /* + * The method won't compile anything containing a 'with', but it can + * compile 'g'. + */ + function g() { return f(); } + assertEq(g(), obj); +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/Function/15.3.4.3-01.js b/js/src/tests/non262/Function/15.3.4.3-01.js new file mode 100644 index 0000000000..955d773766 --- /dev/null +++ b/js/src/tests/non262/Function/15.3.4.3-01.js @@ -0,0 +1,245 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden <jwalden+code@mit.edu> + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 562448; +var summary = 'Function.prototype.apply should accept any arraylike arguments'; +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectTypeError(fun, msg) +{ + try + { + fun(); + assertEq(true, false, "should have thrown a TypeError"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, msg + "; instead threw " + e); + } +} + +function fun() { } + +var global = this; + + +/* Step 1. */ +var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}]; +for (var i = 0, sz = nonfuns.length; i < sz; i++) +{ + var f = function() + { + Function.prototype.apply.apply(nonfuns[i], [1, 2, 3]); + }; + var msg = + "expected TypeError calling Function.prototype.apply with uncallable this"; + expectTypeError(f, msg); +} + + +/* Step 2. */ +var thisObj = {}; + +var currentThis, currentThisBox; +function funLength() +{ + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this, currentThis, "wrong this"); +} +function strictFunLength() +{ + "use strict"; + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this, currentThis, "wrong this"); +} + +currentThis = global; +funLength.apply(); +funLength.apply(undefined); +funLength.apply(undefined, undefined); +funLength.apply(undefined, null); + +currentThis = undefined; +strictFunLength.apply(); +strictFunLength.apply(undefined); +strictFunLength.apply(undefined, undefined); +strictFunLength.apply(undefined, null); + +currentThis = null; +strictFunLength.apply(null); +strictFunLength.apply(null, undefined); +strictFunLength.apply(null, null); + +currentThis = thisObj; +funLength.apply(thisObj); +funLength.apply(thisObj, null); +funLength.apply(thisObj, undefined); +strictFunLength.apply(thisObj); +strictFunLength.apply(thisObj, null); +strictFunLength.apply(thisObj, undefined); + +currentThis = 17; +strictFunLength.apply(17); +strictFunLength.apply(17, null); +strictFunLength.apply(17, undefined); + +function funThisPrimitive() +{ + assertEq(arguments.length, 0, "should have been called with no arguments"); + assertEq(this instanceof currentThisBox, true, + "this not instanceof " + currentThisBox); + assertEq(this.valueOf(), currentThis, + "wrong this valueOf()"); +} + +currentThis = 17; +currentThisBox = Number; +funThisPrimitive.apply(17); +funThisPrimitive.apply(17, undefined); +funThisPrimitive.apply(17, null); + +currentThis = "foopy"; +currentThisBox = String; +funThisPrimitive.apply("foopy"); +funThisPrimitive.apply("foopy", undefined); +funThisPrimitive.apply("foopy", null); + +currentThis = false; +currentThisBox = Boolean; +funThisPrimitive.apply(false); +funThisPrimitive.apply(false, undefined); +funThisPrimitive.apply(false, null); + + +/* Step 3. */ +var nonobjs = [1, -1, 2.5, "[[Call]]", true, false]; +for (var i = 0, sz = nonobjs.length; i < sz; i++) +{ + var f = function() { fun.apply(thisObj, nonobjs[i]); }; + var msg = "should have thrown a TypeError with non-object arguments"; + expectTypeError(f, msg); +} + + +/* Step 4. */ +var args = { get length() { throw 42; } }; +try +{ + fun.apply(thisObj, args); +} +catch (e) +{ + assertEq(e, 42, "didn't throw result of [[Get]] on arguments object"); +} + + +/* + * NB: There was an erratum removing the steps numbered 5 and 7 in the original + * version of ES5; see also the comments in js_fun_apply. + */ + +/* Step 5. */ +var called = false; +var argsObjectLength = + { length: { valueOf: function() { called = true; return 17; } } }; + +fun.apply({}, argsObjectLength); +assertEq(called, true, "should have been set in valueOf called via ToUint32"); + +var upvar = "unset"; +var argsObjectPrimitiveLength = + { + length: + { + valueOf: function() { upvar = "valueOf"; return {}; }, + toString: function() + { + upvar = upvar === "valueOf" ? "both" : "toString"; + return 17; + } + } + }; +fun.apply({}, argsObjectPrimitiveLength); +assertEq(upvar, "both", "didn't call all hooks properly"); + + +/* Step 6-9. */ +var seenThis, res, steps; +var argsAccessors = + { + length: 4, + get 0() { steps.push("0"); return 1; }, + get 1() { steps.push("1"); return 2; }, + // make sure values shine through holes + get 3() { steps.push("3"); return 8; }, + }; + +Object.prototype[2] = 729; + +seenThis = "not seen"; +function argsAsArray() +{ + seenThis = this; + steps.push(Math.PI); + return Array.prototype.map.call(arguments, function(v) { return v; }); +} + +steps = []; +res = argsAsArray.apply(thisObj, argsAccessors); +assertEq(seenThis, thisObj, "saw wrong this"); + +assertEq(steps.length, 4, "wrong steps: " + steps); +assertEq(steps[0], "0", "bad step 0"); +assertEq(steps[1], "1", "bad step 1"); +assertEq(steps[2], "3", "bad step 3"); +assertEq(steps[3], Math.PI, "bad last step"); + +assertEq(res.length, 4, "wrong return: " + res); +assertEq(res[0], 1, "wrong ret[0]"); +assertEq(res[1], 2, "wrong ret[0]"); +assertEq(res[2], 729, "wrong ret[0]"); +assertEq(res[3], 8, "wrong ret[0]"); + +seenThis = "not seen"; +function strictArgsAsArray() +{ + "use strict"; + seenThis = this; + steps.push(NaN); + return Array.prototype.map.call(arguments, function(v) { return v; }); +} + +steps = []; +res = strictArgsAsArray.apply(null, argsAccessors); +assertEq(seenThis, null, "saw wrong this"); + +assertEq(steps.length, 4, "wrong steps: " + steps); +assertEq(steps[0], "0", "bad step 0"); +assertEq(steps[1], "1", "bad step 1"); +assertEq(steps[2], "3", "bad step 3"); +assertEq(steps[3], 0 / 0, "bad last step"); + +assertEq(res.length, 4, "wrong return: " + res); +assertEq(res[0], 1, "wrong ret[0]"); +assertEq(res[1], 2, "wrong ret[0]"); +assertEq(res[2], 729, "wrong ret[0]"); +assertEq(res[3], 8, "wrong ret[0]"); + +strictArgsAsArray.apply(17, argsAccessors); +assertEq(seenThis, 17, "saw wrong this"); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/Function-arguments-gc.js b/js/src/tests/non262/Function/Function-arguments-gc.js new file mode 100644 index 0000000000..2504523362 --- /dev/null +++ b/js/src/tests/non262/Function/Function-arguments-gc.js @@ -0,0 +1,40 @@ +// |reftest| skip-if(Android) +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Christian Holler <decoder@own-hero.net> + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 623301; +var summary = "Properly root argument names during Function()"; +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +if (typeof gczeal === "function") + gczeal(2); + +function crashMe(n) +{ + var nasty = []; + while (n--) + nasty.push("a" + n); + return Function.apply(null, nasty); +} + +var count = 64; // exact value not important +assertEq(crashMe(count + 1).length, count); + +if (typeof gczeal === "function") + gczeal(0); // reset + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/Function-prototype.js b/js/src/tests/non262/Function/Function-prototype.js new file mode 100644 index 0000000000..218b1d54ca --- /dev/null +++ b/js/src/tests/non262/Function/Function-prototype.js @@ -0,0 +1,11 @@ +var desc = Object.getOwnPropertyDescriptor(Function.prototype, "length"); +assertDeepEq(desc, + {value: 0, writable: false, enumerable: false, configurable: true}); + +assertEq(Function.prototype.prototype, undefined); +assertEq(Function.prototype.callee, undefined); +assertThrowsInstanceOf(() => Function.prototype.caller, TypeError); +assertThrowsInstanceOf(() => Function.prototype.arguments, TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/Function-with-eval.js b/js/src/tests/non262/Function/Function-with-eval.js new file mode 100644 index 0000000000..981abf2d04 --- /dev/null +++ b/js/src/tests/non262/Function/Function-with-eval.js @@ -0,0 +1,25 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(new Function( + "eval('var foo = 915805');" + + "return foo;" + )(), + 915805); + +assertEq(new Function( + "eval('function foo() {" + + "return 915805;" + + "}');" + + "return foo;" + )()(), + 915805); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/Function/Object-toSource.js b/js/src/tests/non262/Function/Object-toSource.js new file mode 100644 index 0000000000..16b2346fbf --- /dev/null +++ b/js/src/tests/non262/Function/Object-toSource.js @@ -0,0 +1,373 @@ +// |reftest| skip-if(!Object.prototype.toSource) + +var BUGNUMBER = 1317400; +var summary = "Function string representation in Object.prototype.toSource"; + +print(BUGNUMBER + ": " + summary); + +// Methods. + +assertEq(({ foo(){} }).toSource(), + "({foo(){}})"); +assertEq(({ *foo(){} }).toSource(), + "({*foo(){}})"); +assertEq(({ async foo(){} }).toSource(), + "({async foo(){}})"); + +assertEq(({ 1(){} }).toSource(), + "({1(){}})"); + +// Methods with more spacing. +// Spacing is kept. + +assertEq(({ foo (){} }).toSource(), + "({foo (){}})"); +assertEq(({ foo () {} }).toSource(), + "({foo () {}})"); + +// Methods with computed name. +// Method syntax is composed. + +let name = "foo"; +assertEq(({ [name](){} }).toSource(), + "({foo(){}})"); +assertEq(({ *[name](){} }).toSource(), + "({*foo(){}})"); +assertEq(({ async [name](){} }).toSource(), + "({async foo(){}})"); + +assertEq(({ [ Symbol.iterator ](){} }).toSource(), + "({[Symbol.iterator](){}})"); + +// Accessors. + +assertEq(({ get foo(){} }).toSource(), + "({get foo(){}})"); +assertEq(({ set foo(v){} }).toSource(), + "({set foo(v){}})"); + +// Accessors with computed name. +// Method syntax is composed. + +assertEq(({ get [name](){} }).toSource(), + "({get foo(){}})"); +assertEq(({ set [name](v){} }).toSource(), + "({set foo(v){}})"); + +assertEq(({ get [ Symbol.iterator ](){} }).toSource(), + "({get [Symbol.iterator](){}})"); +assertEq(({ set [ Symbol.iterator ](v){} }).toSource(), + "({set [Symbol.iterator](v){}})"); + +// Getter and setter with same name. +// Getter always comes before setter. + +assertEq(({ get foo(){}, set foo(v){} }).toSource(), + "({get foo(){}, set foo(v){}})"); +assertEq(({ set foo(v){}, get foo(){} }).toSource(), + "({get foo(){}, set foo(v){}})"); + +// Normal properties. + +assertEq(({ foo: function(){} }).toSource(), + "({foo:(function(){})})"); +assertEq(({ foo: function bar(){} }).toSource(), + "({foo:(function bar(){})})"); +assertEq(({ foo: function*(){} }).toSource(), + "({foo:(function*(){})})"); +assertEq(({ foo: async function(){} }).toSource(), + "({foo:(async function(){})})"); + +// Normal properties with computed name. + +assertEq(({ [ Symbol.iterator ]: function(){} }).toSource(), + "({[Symbol.iterator]:(function(){})})"); + +// Dynamically defined properties with function expression. +// Never become a method syntax. + +let obj = {}; +obj.foo = function() {}; +assertEq(obj.toSource(), + "({foo:(function() {})})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function() {}}); +assertEq(obj.toSource(), + "({})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({foo:(function() {})})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true}); +assertEq(obj.toSource(), + "({foo:(function bar() {})})"); + +obj = {}; +Object.defineProperty(obj, Symbol.iterator, {value: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({[Symbol.iterator]:(function() {})})"); + +// Dynamically defined property with other object's method. +// Method syntax is composed. + +let method = ({foo() {}}).foo; + +obj = {}; +Object.defineProperty(obj, "foo", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "bar", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({bar() {}})"); + +method = ({*foo() {}}).foo; + +obj = {}; +Object.defineProperty(obj, "bar", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({*bar() {}})"); + +method = ({async foo() {}}).foo; + +obj = {}; +Object.defineProperty(obj, "bar", {value: method, enumerable: true}); +assertEq(obj.toSource(), + "({async bar() {}})"); + +// Dynamically defined accessors. +// Accessor syntax is composed. + +obj = {}; +Object.defineProperty(obj, "foo", {get: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +obj = {}; +Object.defineProperty(obj, Symbol.iterator, {get: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({get [Symbol.iterator]() {}})"); + +obj = {}; +Object.defineProperty(obj, Symbol.iterator, {set: function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({set [Symbol.iterator]() {}})"); + +// Dynamically defined accessors with other object's accessors. +// Accessor syntax is composed. + +let accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set; +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ get bar() {} }, "bar").get; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set foo(v) {} }, "foo").set; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +accessor = Object.getOwnPropertyDescriptor({ set bar(v) {} }, "bar").set; +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +// Methods with proxy. +// Treated as normal property. + +method = ({foo() {}}).foo; +let handler = { + get(that, name) { + if (name == "toSource") { + return function() { + return that.toSource(); + }; + } + return that[name]; + } +}; +let proxy = new Proxy(method, handler); + +obj = {}; +Object.defineProperty(obj, "foo", {value: proxy, enumerable: true}); +assertEq(obj.toSource(), + "({foo:foo() {}})"); + +// Accessors with proxy. +// Accessor syntax is composed. + +accessor = Object.getOwnPropertyDescriptor({ get foo() {} }, "foo").get; +proxy = new Proxy(accessor, handler); + +obj = {}; +Object.defineProperty(obj, "foo", {get: proxy, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: proxy, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +// Methods from other global. +// Treated as normal property in the cross-compartment case. + +let g = newGlobal(); + +method = g.eval("({ foo() {} }).foo"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: method, enumerable: true}); +assertEq((obj.toSource() === "({foo:foo() {}})" || + obj.toSource() === "({foo() {}})"), + true); + +// Accessors from other global. +// Accessor syntax is composed. + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {get: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({get foo(v) {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get foo() {} }, 'foo').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ get bar() {} }, 'bar').get"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set foo(v) {} }, 'foo').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +accessor = g.eval("Object.getOwnPropertyDescriptor({ set bar(v) {} }, 'bar').set"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: accessor, enumerable: true}); +assertEq(obj.toSource(), + "({set foo(v) {}})"); + +// **** Some weird cases **** + +// Accessors with generator or async. + +obj = {}; +Object.defineProperty(obj, "foo", {get: function*() {}, enumerable: true}); +assertEq(obj.toSource(), + "({get foo() {}})"); + +obj = {}; +Object.defineProperty(obj, "foo", {set: async function() {}, enumerable: true}); +assertEq(obj.toSource(), + "({set foo() {}})"); + +// Modified toSource. + +obj = { foo() {} }; +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({hello})"); + +obj = { foo() {} }; +obj.foo.toSource = () => "bar() {}"; +assertEq(obj.toSource(), + "({bar() {}})"); + +// Modified toSource with different method name. + +obj = {}; +Object.defineProperty(obj, "foo", {value: function bar() {}, enumerable: true}); +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({foo:hello})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: function* bar() {}, enumerable: true}); +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({foo:hello})"); + +obj = {}; +Object.defineProperty(obj, "foo", {value: async function bar() {}, enumerable: true}); +obj.foo.toSource = () => "hello"; +assertEq(obj.toSource(), + "({foo:hello})"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/arguments-caller-callee.js b/js/src/tests/non262/Function/arguments-caller-callee.js new file mode 100644 index 0000000000..57efd9eb91 --- /dev/null +++ b/js/src/tests/non262/Function/arguments-caller-callee.js @@ -0,0 +1,64 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'arguments-caller-callee.js'; +var BUGNUMBER = 514563; +var summary = "arguments.caller and arguments.callee are poison pills in ES5, " + + "later changed in ES2017 to only poison pill arguments.callee."; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// behavior + +function expectTypeError(fun) +{ + try + { + fun(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected TypeError calling function" + + ("name" in fun ? " " + fun.name : "") + ", instead got: " + e); + } +} + +function bar() { "use strict"; return arguments; } +assertEq(bar().caller, undefined); // No error when accessing arguments.caller in ES2017+ +expectTypeError(function barCallee() { bar().callee; }); + +function baz() { return arguments; } +assertEq(baz().callee, baz); + + +// accessor identity + +function strictMode() { "use strict"; return arguments; } +var canonicalTTE = Object.getOwnPropertyDescriptor(strictMode(), "callee").get; + +var args = strictMode(); + +var argsCaller = Object.getOwnPropertyDescriptor(args, "caller"); +assertEq(argsCaller, undefined); + +var argsCallee = Object.getOwnPropertyDescriptor(args, "callee"); +assertEq("get" in argsCallee, true); +assertEq("set" in argsCallee, true); +assertEq(argsCallee.get, canonicalTTE); +assertEq(argsCallee.set, canonicalTTE); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/arguments-extra-property.js b/js/src/tests/non262/Function/arguments-extra-property.js new file mode 100644 index 0000000000..017734382d --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/arguments-iterator.js b/js/src/tests/non262/Function/arguments-iterator.js new file mode 100644 index 0000000000..5610b8a245 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/arguments-parameter-shadowing.js b/js/src/tests/non262/Function/arguments-parameter-shadowing.js new file mode 100644 index 0000000000..bc2b430112 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/arguments-property-attributes.js b/js/src/tests/non262/Function/arguments-property-attributes.js new file mode 100644 index 0000000000..f50c1e6dad --- /dev/null +++ b/js/src/tests/non262/Function/arguments-property-attributes.js @@ -0,0 +1,98 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'arguments-property-attributes.js'; +var BUGNUMBER = 516255; +var summary = "Attributes for properties of arguments objects"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// normal + +function args() { return arguments; } +var a = args(0, 1); + +var argProps = Object.getOwnPropertyNames(a).sort(); +assertEq(argProps.indexOf("callee") >= 0, true); +assertEq(argProps.indexOf("0") >= 0, true); +assertEq(argProps.indexOf("1") >= 0, true); +assertEq(argProps.indexOf("length") >= 0, true); + +var calleeDesc = Object.getOwnPropertyDescriptor(a, "callee"); +assertEq(calleeDesc.value, args); +assertEq(calleeDesc.writable, true); +assertEq(calleeDesc.enumerable, false); +assertEq(calleeDesc.configurable, true); + +var zeroDesc = Object.getOwnPropertyDescriptor(a, "0"); +assertEq(zeroDesc.value, 0); +assertEq(zeroDesc.writable, true); +assertEq(zeroDesc.enumerable, true); +assertEq(zeroDesc.configurable, true); + +var oneDesc = Object.getOwnPropertyDescriptor(a, "1"); +assertEq(oneDesc.value, 1); +assertEq(oneDesc.writable, true); +assertEq(oneDesc.enumerable, true); +assertEq(oneDesc.configurable, true); + +var lengthDesc = Object.getOwnPropertyDescriptor(a, "length"); +assertEq(lengthDesc.value, 2); +assertEq(lengthDesc.writable, true); +assertEq(lengthDesc.enumerable, false); +assertEq(lengthDesc.configurable, true); + + +// strict + +function strictArgs() { "use strict"; return arguments; } +var sa = strictArgs(0, 1); + +var strictArgProps = Object.getOwnPropertyNames(sa).sort(); +assertEq(strictArgProps.indexOf("callee") >= 0, true); +assertEq(strictArgProps.indexOf("caller") >= 0, false); +assertEq(strictArgProps.indexOf("0") >= 0, true); +assertEq(strictArgProps.indexOf("1") >= 0, true); +assertEq(strictArgProps.indexOf("length") >= 0, true); + +var strictCalleeDesc = Object.getOwnPropertyDescriptor(sa, "callee"); +assertEq(typeof strictCalleeDesc.get, "function"); +assertEq(typeof strictCalleeDesc.set, "function"); +assertEq(strictCalleeDesc.get, strictCalleeDesc.set); +assertEq(strictCalleeDesc.enumerable, false); +assertEq(strictCalleeDesc.configurable, false); + +var strictCallerDesc = Object.getOwnPropertyDescriptor(sa, "caller"); +assertEq(strictCallerDesc, undefined); + +var strictZeroDesc = Object.getOwnPropertyDescriptor(sa, "0"); +assertEq(strictZeroDesc.value, 0); +assertEq(strictZeroDesc.writable, true); +assertEq(strictZeroDesc.enumerable, true); +assertEq(strictZeroDesc.configurable, true); + +var strictOneDesc = Object.getOwnPropertyDescriptor(sa, "1"); +assertEq(strictOneDesc.value, 1); +assertEq(strictOneDesc.writable, true); +assertEq(strictOneDesc.enumerable, true); +assertEq(strictOneDesc.configurable, true); + +var strictLengthDesc = Object.getOwnPropertyDescriptor(sa, "length"); +assertEq(strictLengthDesc.value, 2); +assertEq(strictLengthDesc.writable, true); +assertEq(strictLengthDesc.enumerable, false); +assertEq(strictLengthDesc.configurable, true); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/arrow-has-duplicated.js b/js/src/tests/non262/Function/arrow-has-duplicated.js new file mode 100644 index 0000000000..19096ebf88 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/bound-length-and-name.js b/js/src/tests/non262/Function/bound-length-and-name.js new file mode 100644 index 0000000000..ef2f1ffbcd --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/bound-non-constructable.js b/js/src/tests/non262/Function/bound-non-constructable.js new file mode 100644 index 0000000000..cee1dd580d --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/bound-prototype.js b/js/src/tests/non262/Function/bound-prototype.js new file mode 100644 index 0000000000..8b0f295a58 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/browser.js b/js/src/tests/non262/Function/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/non262/Function/browser.js diff --git a/js/src/tests/non262/Function/builtin-no-construct.js b/js/src/tests/non262/Function/builtin-no-construct.js new file mode 100644 index 0000000000..b41ae56f11 --- /dev/null +++ b/js/src/tests/non262/Function/builtin-no-construct.js @@ -0,0 +1,52 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function checkMethod(method) { + try { + new method(); + assertEq(0, 1, "not reached " + method); + } catch (e) { + assertEq(e.message.indexOf(" is not a constructor") === -1, false); + } +} + +function checkMethods(proto) { + var names = Object.getOwnPropertyNames(proto); + for (var i = 0; i < names.length; i++) { + var name = names[i]; + if (["constructor", "arguments", "caller"].indexOf(name) >= 0) + continue; + var prop = proto[name]; + if (typeof prop === "function") + checkMethod(prop); + } +} + +checkMethod(Function.prototype); +checkMethods(JSON); +checkMethods(Math); +checkMethods(Proxy); + +var builtin_ctors = [ + Object, Function, Array, String, Boolean, Number, Date, RegExp, Error, + EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError, +]; + +for (var i = 0; i < builtin_ctors.length; i++) { + checkMethods(builtin_ctors[i]); + checkMethods(builtin_ctors[i].prototype); +} + +var builtin_funcs = [ + eval, isFinite, isNaN, parseFloat, parseInt, + decodeURI, decodeURIComponent, encodeURI, encodeURIComponent +]; + +for (var i = 0; i < builtin_funcs.length; i++) { + checkMethod(builtin_funcs[i]); +} + +if (typeof reportCompare == 'function') + reportCompare(0, 0, "ok"); diff --git a/js/src/tests/non262/Function/builtin-no-prototype.js b/js/src/tests/non262/Function/builtin-no-prototype.js new file mode 100644 index 0000000000..b5a8cc9f6e --- /dev/null +++ b/js/src/tests/non262/Function/builtin-no-prototype.js @@ -0,0 +1,40 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 4 -*- */ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(undefined, void 0); + +assertEq(Function.prototype.hasOwnProperty('prototype'), false); +assertEq(Function.prototype.prototype, undefined); + +var builtin_ctors = [ + Object, Function, Array, String, Boolean, Number, Date, RegExp, Error, + EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError +]; + +for (var i = 0; i < builtin_ctors.length; i++) { + var c = builtin_ctors[i]; + assertEq(typeof c.prototype, (c === Function) ? "function" : "object"); + assertEq(c.prototype.constructor, c); +} + +var builtin_funcs = [ + eval, isFinite, isNaN, parseFloat, parseInt, + decodeURI, decodeURIComponent, encodeURI, encodeURIComponent +]; + +for (var i = 0; i < builtin_funcs.length; i++) { + assertEq(builtin_funcs[i].hasOwnProperty('prototype'), false); + assertEq(builtin_funcs[i].prototype, undefined); +} + +var names = Object.getOwnPropertyNames(Math); +for (var i = 0; i < names.length; i++) { + var m = Math[names[i]]; + if (typeof m === "function") + assertEq(m.prototype, undefined); +} + +reportCompare(0, 0, "don't crash"); diff --git a/js/src/tests/non262/Function/configurable-length-builtins.js b/js/src/tests/non262/Function/configurable-length-builtins.js new file mode 100644 index 0000000000..f28eaae157 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/configurable-length.js b/js/src/tests/non262/Function/configurable-length.js new file mode 100644 index 0000000000..127038fb56 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/construct-bound-proxy-with-many-arguments.js b/js/src/tests/non262/Function/construct-bound-proxy-with-many-arguments.js new file mode 100644 index 0000000000..6c9bb41a38 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/constructor-binding.js b/js/src/tests/non262/Function/constructor-binding.js new file mode 100644 index 0000000000..e82274d279 --- /dev/null +++ b/js/src/tests/non262/Function/constructor-binding.js @@ -0,0 +1,11 @@ +var BUGNUMBER = 636635; +var summary = "A function created by Function constructor shouldn't have anonymous binding"; + +print(BUGNUMBER + ": " + summary); + +assertEq(new Function("return typeof anonymous")(), "undefined"); +assertEq(new Function("return function() { return typeof anonymous; }")()(), "undefined"); +assertEq(new Function("return function() { eval(''); return typeof anonymous; }")()(), "undefined"); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/create-function-parse-before-getprototype.js b/js/src/tests/non262/Function/create-function-parse-before-getprototype.js new file mode 100644 index 0000000000..2095abfb28 --- /dev/null +++ b/js/src/tests/non262/Function/create-function-parse-before-getprototype.js @@ -0,0 +1,17 @@ +var getProtoCalled = false; + +var newTarget = Object.defineProperty(function(){}.bind(), "prototype", { + get() { + getProtoCalled = true; + return null; + } +}); + +assertThrowsInstanceOf(() => { + Reflect.construct(Function, ["@error"], newTarget); +}, SyntaxError); + +assertEq(getProtoCalled, false); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/function-bind.js b/js/src/tests/non262/Function/function-bind.js new file mode 100644 index 0000000000..9fdaf41a97 --- /dev/null +++ b/js/src/tests/non262/Function/function-bind.js @@ -0,0 +1,280 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'function-bind.js'; +var BUGNUMBER = 429507; +var summary = "ES5: Function.prototype.bind"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// ad-hoc testing + +assertEq(Function.prototype.hasOwnProperty("bind"), true); + +var bind = Function.prototype.bind; +assertEq(bind.length, 1); + + +var strictReturnThis = function() { "use strict"; return this; }; + +assertEq(strictReturnThis.bind(undefined)(), undefined); +assertEq(strictReturnThis.bind(null)(), null); + +var obj = {}; +assertEq(strictReturnThis.bind(obj)(), obj); + +assertEq(strictReturnThis.bind(NaN)(), NaN); + +assertEq(strictReturnThis.bind(true)(), true); +assertEq(strictReturnThis.bind(false)(), false); + +assertEq(strictReturnThis.bind("foopy")(), "foopy"); + + +// rigorous, step-by-step testing + +function expectThrowTypeError(fun) +{ + try + { + var r = fun(); + throw new Error("didn't throw TypeError, returned " + r); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "didn't throw TypeError, got: " + e); + } +} + +/* + * 1. Let Target be the this value. + * 2. If IsCallable(Target) is false, throw a TypeError exception. + */ +expectThrowTypeError(function() { bind.call(null); }); +expectThrowTypeError(function() { bind.call(undefined); }); +expectThrowTypeError(function() { bind.call(NaN); }); +expectThrowTypeError(function() { bind.call(0); }); +expectThrowTypeError(function() { bind.call(-0); }); +expectThrowTypeError(function() { bind.call(17); }); +expectThrowTypeError(function() { bind.call(42); }); +expectThrowTypeError(function() { bind.call("foobar"); }); +expectThrowTypeError(function() { bind.call(true); }); +expectThrowTypeError(function() { bind.call(false); }); +expectThrowTypeError(function() { bind.call([]); }); +expectThrowTypeError(function() { bind.call({}); }); + + +/* + * 3. Let A be a new (possibly empty) internal list of all of the argument + * values provided after thisArg (arg1, arg2 etc), in order. + * 4. Let F be a new native ECMAScript object . + * 5. Set all the internal methods, except for [[Get]], of F as specified in + * 8.12. + * 6. Set the [[Get]] internal property of F as specified in 15.3.5.4. + * 7. Set the [[TargetFunction]] internal property of F to Target. + * 8. Set the [[BoundThis]] internal property of F to the value of thisArg. + * 9. Set the [[BoundArgs]] internal property of F to A. + */ +// throughout + + +/* 10. Set the [[Class]] internal property of F to "Function". */ +var toString = Object.prototype.toString; +assertEq(toString.call(function(){}), "[object Function]"); +assertEq(toString.call(function a(){}), "[object Function]"); +assertEq(toString.call(function(a){}), "[object Function]"); +assertEq(toString.call(function a(b){}), "[object Function]"); +assertEq(toString.call(function(){}.bind()), "[object Function]"); +assertEq(toString.call(function a(){}.bind()), "[object Function]"); +assertEq(toString.call(function(a){}.bind()), "[object Function]"); +assertEq(toString.call(function a(b){}.bind()), "[object Function]"); + + +/* + * 11. Set the [[Prototype]] internal property of F to the standard built-in + * Function prototype object as specified in 15.3.3.1. + */ +assertEq(Object.getPrototypeOf(bind.call(function(){})), Function.prototype); +assertEq(Object.getPrototypeOf(bind.call(function a(){})), Function.prototype); +assertEq(Object.getPrototypeOf(bind.call(function(a){})), Function.prototype); +assertEq(Object.getPrototypeOf(bind.call(function a(b){})), Function.prototype); + + +/* + * 12. Set the [[Call]] internal property of F as described in 15.3.4.5.1. + */ +var a = Array.bind(1, 2); +assertEq(a().length, 2); +assertEq(a(4).length, 2); +assertEq(a(4, 8).length, 3); + +function t() { return this; } +var bt = t.bind(t); +assertEq(bt(), t); + +function callee() { return arguments.callee; } +var call = callee.bind(); +assertEq(call(), callee); +assertEq(new call(), callee); + + +/* + * 13. Set the [[Construct]] internal property of F as described in 15.3.4.5.2. + */ +function Point(x, y) +{ + this.x = x; + this.y = y; +} +var YAxisPoint = Point.bind(null, 0) + +assertEq(YAxisPoint.hasOwnProperty("prototype"), false); +var p = new YAxisPoint(5); +assertEq(p.x, 0); +assertEq(p.y, 5); +assertEq(p instanceof Point, true); +assertEq(p instanceof YAxisPoint, true); +assertEq(Object.prototype.toString.call(YAxisPoint), "[object Function]"); +assertEq(YAxisPoint.length, 1); + + +/* + * 14. Set the [[HasInstance]] internal property of F as described in + * 15.3.4.5.3. + */ +function JoinArguments() +{ + this.args = Array.prototype.join.call(arguments, ", "); +} + +var Join1 = JoinArguments.bind(null, 1); +var Join2 = Join1.bind(null, 2); +var Join3 = Join2.bind(null, 3); +var Join4 = Join3.bind(null, 4); +var Join5 = Join4.bind(null, 5); +var Join6 = Join5.bind(null, 6); + +var r = new Join6(7); +assertEq(r instanceof Join6, true); +assertEq(r instanceof Join5, true); +assertEq(r instanceof Join4, true); +assertEq(r instanceof Join3, true); +assertEq(r instanceof Join2, true); +assertEq(r instanceof Join1, true); +assertEq(r instanceof JoinArguments, true); +assertEq(r.args, "1, 2, 3, 4, 5, 6, 7"); + + +/* + * 15. If the [[Class]] internal property of Target is "Function", then + * a. Let L be the length property of Target minus the length of A. + * b. Set the length own property of F to either 0 or L, whichever is larger. + * 16. Else set the length own property of F to 0. + */ +function none() { return arguments.length; } +assertEq(none.bind(1, 2)(3, 4), 3); +assertEq(none.bind(1, 2)(), 1); +assertEq(none.bind(1)(2, 3), 2); +assertEq(none.bind().length, 0); +assertEq(none.bind(null).length, 0); +assertEq(none.bind(null, 1).length, 0); +assertEq(none.bind(null, 1, 2).length, 0); + +function one(a) { } +assertEq(one.bind().length, 1); +assertEq(one.bind(null).length, 1); +assertEq(one.bind(null, 1).length, 0); +assertEq(one.bind(null, 1, 2).length, 0); + +// retch +var br = Object.create(null, { length: { value: 0 } }); +try +{ + br = bind.call(/a/g, /a/g, "aaaa"); +} +catch (e) { /* nothing */ } +assertEq(br.length, 0); + + +/* + * 17. Set the attributes of the length own property of F to the values + * specified in 15.3.5.1. + */ +var len1Desc = + Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(), "length"); +assertEq(len1Desc.value, 3); +assertEq(len1Desc.writable, false); +assertEq(len1Desc.enumerable, false); +assertEq(len1Desc.configurable, true); + +var len2Desc = + Object.getOwnPropertyDescriptor(function(a, b, c){}.bind(null, 2), "length"); +assertEq(len2Desc.value, 2); +assertEq(len2Desc.writable, false); +assertEq(len2Desc.enumerable, false); +assertEq(len2Desc.configurable, true); + + +/* + * 18. Set the [[Extensible]] internal property of F to true. + */ +var bound = (function() { }).bind(); + +var isExtensible = Object.isExtensible || function() { return true; }; +assertEq(isExtensible(bound), true); + +bound.foo = 17; +var fooDesc = Object.getOwnPropertyDescriptor(bound, "foo"); +assertEq(fooDesc.value, 17); +assertEq(fooDesc.writable, true); +assertEq(fooDesc.enumerable, true); +assertEq(fooDesc.configurable, true); + + +/* + * Steps 19-21 are removed from ES6, instead implemented through "arguments" and + * "caller" accessors on Function.prototype. So no own properties, but do check + * for the same observable behavior (modulo where the accessors live). + */ +function strict() { "use strict"; } +function nonstrict() {} + +function testBound(fun) +{ + var boundf = fun.bind(); + + assertEq(Object.getOwnPropertyDescriptor(boundf, "arguments"), undefined, + "should be no arguments property"); + assertEq(Object.getOwnPropertyDescriptor(boundf, "caller"), undefined, + "should be no caller property"); + + expectThrowTypeError(function() { return boundf.arguments; }); + expectThrowTypeError(function() { return boundf.caller; }); +} + +testBound(strict); +testBound(nonstrict); + +assertEq((function unbound(){"body"}).bind().toString(), `function() { + [native code] +}`); + + +/* 22. Return F. */ +var passim = function p(){}.bind(1); +assertEq(typeof passim, "function"); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/function-call.js b/js/src/tests/non262/Function/function-call.js new file mode 100644 index 0000000000..756b583842 --- /dev/null +++ b/js/src/tests/non262/Function/function-call.js @@ -0,0 +1,134 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + * Contributor: + * Jeff Walden <jwalden+code@mit.edu> + */ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 575535; +var summary = 'Function.prototype.call'; +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function expectTypeError(fun, msg) +{ + try + { + fun(); + assertEq(true, false, "should have thrown a TypeError"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, msg + "; instead threw " + e); + } +} + +function fun() { } + +var global = this; + +assertEq(Function.prototype.call.length, 1); + + +/* Step 1. */ +var nonfuns = [null, 1, -1, 2.5, "[[Call]]", undefined, true, false, {}]; +for (var i = 0, sz = nonfuns.length; i < sz; i++) +{ + var f = function() + { + Function.prototype.call.apply(nonfuns[i]); + }; + var msg = + "expected TypeError calling Function.prototype.call with uncallable this"; + expectTypeError(f, msg); +} + + +/* Steps 2-4. */ +function none() +{ + assertEq(this, global, "bad this"); + assertEq(arguments.length, 0, "wrong arguments"); +} + +none.call(); +none.call(undefined); +none.call(null); + +var seenThis; +function strictNone() +{ + "use strict"; + assertEq(this, seenThis, "bad this"); + assertEq(arguments.length, 0, "wrong arguments"); +} + +seenThis = undefined; +strictNone.call(); +strictNone.call(undefined); + +seenThis = null; +strictNone.call(null); + +seenThis = 17; +strictNone.call(17); + +var seenThisBox, args; +function some() +{ + assertEq(this instanceof seenThisBox, true, + "this not instanceof " + seenThisBox); + assertEq(this.valueOf(), seenThis, + "wrong this valueOf()"); + assertEq(arguments.length, args.length, "wrong arguments count"); + for (var i = 0; i < args.length; i++) + assertEq(arguments[i], args[i], "wrong argument " + i); +} + +seenThis = false; +seenThisBox = Boolean; +args = [8, 6, 7, NaN, undefined, 0.3]; +some.call(false, 8, 6, 7, NaN, undefined, 0.3); + +var obj = {}; + +seenThis = "foo"; +seenThisBox = String; +args = [obj]; +some.call("foo", obj); + +seenThis = obj; +seenThisBox = Object; +some.call(obj, obj); + +function strictSome() +{ + "use strict"; + assertEq(this, seenThis, "wrong this"); + assertEq(arguments.length, args.length, "wrong arguments count"); + for (var i = 0; i < args.length; i++) + assertEq(arguments[i], args[i], "wrong argument " + i); +} + +seenThis = NaN; +args = [8, 6, 7, NaN, undefined, 0.3]; +strictSome.call(NaN, 8, 6, 7, NaN, undefined, 0.3); + +seenThis = "foo"; +args = [obj]; +strictSome.call("foo", obj); + +seenThis = obj; +strictSome.call(obj, obj); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/function-caller-restrictions.js b/js/src/tests/non262/Function/function-caller-restrictions.js new file mode 100644 index 0000000000..36c31279ba --- /dev/null +++ b/js/src/tests/non262/Function/function-caller-restrictions.js @@ -0,0 +1,29 @@ +// Function#caller restrictions as proposed by +// https://github.com/claudepache/es-legacy-function-reflection/ + +function caller() { + return caller.caller; +} + +assertEq(caller(), null); +assertEq(Reflect.apply(caller, undefined, []), null); + +assertEq([0].map(caller)[0], null); + +(function strict() { + "use strict"; + assertEq(caller(), null); +})(); + +(async function() { + assertEq(caller(), null); +})(); + +assertEq(function*() { + yield caller(); +}().next().value, null); + + +if (typeof reportCompare === "function") { + reportCompare(true, true); +} diff --git a/js/src/tests/non262/Function/function-caller.js b/js/src/tests/non262/Function/function-caller.js new file mode 100644 index 0000000000..2b0812d4f1 --- /dev/null +++ b/js/src/tests/non262/Function/function-caller.js @@ -0,0 +1,45 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'function-caller.js'; +var BUGNUMBER = 514581; +var summary = "Function.prototype.caller should throw a TypeError for " + + "strict-mode functions"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// behavior + +function expectTypeError(fun) +{ + try + { + fun(); + throw new Error("didn't throw"); + } + catch (e) + { + assertEq(e instanceof TypeError, true, + "expected TypeError calling function" + + ("name" in fun ? " " + fun.name : "") + ", instead got: " + e); + } +} + +function bar() { "use strict"; } +expectTypeError(function barCaller() { bar.caller; }); + +function baz() { "use strict"; return 17; } +expectTypeError(function bazCaller() { baz.caller; }); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/function-constructor-toString-arguments-before-parsing-params.js b/js/src/tests/non262/Function/function-constructor-toString-arguments-before-parsing-params.js new file mode 100644 index 0000000000..4e88a00966 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/function-name-assignment.js b/js/src/tests/non262/Function/function-name-assignment.js new file mode 100644 index 0000000000..5e4d1c004f --- /dev/null +++ b/js/src/tests/non262/Function/function-name-assignment.js @@ -0,0 +1,139 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on assignment"; + +print(BUGNUMBER + ": " + summary); + +var fooSymbol = Symbol("foo"); +var emptySymbol = Symbol(""); +var undefSymbol = Symbol(); +var globalVar; + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testAssignmentExpression(expr, named) { + eval(` + var assignment; + assignment = ${expr}; + assertEq(assignment.name, named ? "named" : "assignment"); + + globalVar = ${expr}; + assertEq(globalVar.name, named ? "named" : "globalVar"); + + var obj = { dynamic: null }; + with (obj) { + dynamic = ${expr}; + } + assertEq(obj.dynamic.name, named ? "named" : "dynamic"); + + (function namedLambda(param1, param2) { + var assignedToNamedLambda; + assignedToNamedLambda = namedLambda = ${expr}; + assertEq(namedLambda.name, "namedLambda"); + assertEq(assignedToNamedLambda.name, named ? "named" : "namedLambda"); + + param1 = ${expr}; + assertEq(param1.name, named ? "named" : "param1"); + + { + let param1 = ${expr}; + assertEq(param1.name, named ? "named" : "param1"); + + param2 = ${expr}; + assertEq(param2.name, named ? "named" : "param2"); + } + })(); + + { + let nextedLexical1, nextedLexical2; + { + let nextedLexical1 = ${expr}; + assertEq(nextedLexical1.name, named ? "named" : "nextedLexical1"); + + nextedLexical2 = ${expr}; + assertEq(nextedLexical2.name, named ? "named" : "nextedLexical2"); + } + } + `); + + // Not applicable cases: not IsIdentifierRef. + eval(` + var inParen; + (inParen) = ${expr}; + assertEq(inParen.name, named ? "named" : ""); + `); + + // Not applicable cases: not direct RHS. + if (!expr.includes("=>")) { + eval(` + var a = true && ${expr}; + assertEq(a.name, named ? "named" : ""); + `); + } else { + // Arrow function cannot be RHS of &&. + eval(` + var a = true && (${expr}); + assertEq(a.name, named ? "named" : ""); + `); + } + + // Not applicable cases: property. + eval(` + var obj = {}; + + obj.prop = ${expr}; + assertEq(obj.prop.name, named ? "named" : ""); + + obj["literal"] = ${expr}; + assertEq(obj["literal"].name, named ? "named" : ""); + `); + + // Not applicable cases: assigned again. + eval(` + var tmp = [${expr}]; + assertEq(tmp[0].name, named ? "named" : ""); + + var assignment; + assignment = tmp[0]; + assertEq(assignment.name, named ? "named" : ""); + `); +} +for (var [expr, named] of exprs) { + testAssignmentExpression(expr, named); +} + +function testVariableDeclaration(expr, named) { + eval(` + var varDecl = ${expr}; + assertEq(varDecl.name, named ? "named" : "varDecl"); + `); +} +for (var [expr, named] of exprs) { + testVariableDeclaration(expr, named); +} + +function testLexicalBinding(expr, named) { + eval(` + let lexical = ${expr}; + assertEq(lexical.name, named ? "named" : "lexical"); + + const constLexical = ${expr}; + assertEq(constLexical.name, named ? "named" : "constLexical"); + `); +} +for (var [expr, named] of exprs) { + testLexicalBinding(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-binding.js b/js/src/tests/non262/Function/function-name-binding.js new file mode 100644 index 0000000000..bdd6c131c0 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-binding.js @@ -0,0 +1,54 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on binding pattern"; + +print(BUGNUMBER + ": " + summary); + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testAssignmentProperty(expr, named) { + var f = eval(`(function({ prop1 = ${expr} }) { return prop1; })`); + assertEq(f({}).name, named ? "named" : "prop1"); + + eval(` + var { prop1 = ${expr} } = {}; + assertEq(prop1.name, named ? "named" : "prop1"); + `); +} +for (var [expr, named] of exprs) { + testAssignmentProperty(expr, named); +} + +function testAssignmentElement(expr, named) { + var f = eval(`(function([elem1 = ${expr}]) { return elem1; })`); + assertEq(f([]).name, named ? "named" : "elem1"); + + eval(` + var [elem1 = ${expr}] = []; + assertEq(elem1.name, named ? "named" : "elem1"); + `); +} +for (var [expr, named] of exprs) { + testAssignmentElement(expr, named); +} + +function testSingleNameBinding(expr, named) { + var f = eval(`(function(param1 = ${expr}) { return param1; })`); + assertEq(f().name, named ? "named" : "param1"); +} +for (var [expr, named] of exprs) { + testSingleNameBinding(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-class.js b/js/src/tests/non262/Function/function-name-class.js new file mode 100644 index 0000000000..edde690556 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-class.js @@ -0,0 +1,32 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous class with name method shouldn't be affected by assignment"; + +print(BUGNUMBER + ": " + summary); + +var classWithStaticNameMethod = class { static name() {} }; +assertEq(typeof classWithStaticNameMethod.name, "function"); + +var classWithStaticNameGetter = class { static get name() { return "static name"; } }; +assertEq(typeof Object.getOwnPropertyDescriptor(classWithStaticNameGetter, "name").get, "function"); +assertEq(classWithStaticNameGetter.name, "static name"); + +var classWithStaticNameSetter = class { static set name(v) {} }; +assertEq(typeof Object.getOwnPropertyDescriptor(classWithStaticNameSetter, "name").set, "function"); + +var n = "NAME".toLowerCase(); +var classWithStaticNameMethodComputed = class { static [n]() {} }; +assertEq(typeof classWithStaticNameMethodComputed.name, "function"); + +// It doesn't apply for non-static method. + +var classWithNameMethod = class { name() {} }; +assertEq(classWithNameMethod.name, "classWithNameMethod"); + +var classWithNameGetter = class { get name() { return "name"; } }; +assertEq(classWithNameGetter.name, "classWithNameGetter"); + +var classWithNameSetter = class { set name(v) {} }; +assertEq(classWithNameSetter.name, "classWithNameSetter"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-computed-01.js b/js/src/tests/non262/Function/function-name-computed-01.js new file mode 100644 index 0000000000..ee74dfd6bb --- /dev/null +++ b/js/src/tests/non262/Function/function-name-computed-01.js @@ -0,0 +1,57 @@ +var obj = { + ["func"]: function() {}, + ["genFunc"]: function*() {}, + ["asyncFunc"]: async function() {}, + ["asyncGenFunc"]: async function*() {}, + ["arrowFunc"]: ()=>{}, + ["asyncArrowFunc"]: async ()=>{}, + ["method"]() {}, + ["anonClass"]: class {}, + ["nonAnonymousFunc"]: function F() {}, + ["nonAnonymousClass"]: class C{}, + get ["getter"]() {}, + set ["setter"](x) {}, +}; + +assertEq(obj.func.name, "func"); +assertEq(obj.genFunc.name, "genFunc"); +assertEq(obj.asyncFunc.name, "asyncFunc"); +assertEq(obj.asyncGenFunc.name, "asyncGenFunc"); +assertEq(obj.arrowFunc.name, "arrowFunc"); +assertEq(obj.asyncArrowFunc.name, "asyncArrowFunc"); +assertEq(obj.method.name, "method"); +assertEq(obj.anonClass.name, "anonClass"); +assertEq(obj.nonAnonymousFunc.name, "F"); +assertEq(obj.nonAnonymousClass.name, "C"); + +assertEq(Object.getOwnPropertyDescriptor(obj, "getter").get.name, "get getter"); +assertEq(Object.getOwnPropertyDescriptor(obj, "setter").set.name, "set setter"); + +let dummy = class { + ["func"]() {} + *["genFunc"] () {} + async ["asyncFunc"]() {} + async *["asyncGenFunc"]() {} + ["arrowFunc"] = ()=>{} + ["asyncArrowFunc"] = async ()=>{}; + ["method"]() {} + get ["getter"]() {} + set ["setter"](x) {} +}; + +dum = new dummy(); + +assertEq(dum.func.name, "func"); +assertEq(dum.genFunc.name, "genFunc"); +assertEq(dum.asyncFunc.name, "asyncFunc"); +assertEq(dum.asyncGenFunc.name, "asyncGenFunc"); +assertEq(dum.arrowFunc.name, "arrowFunc"); +assertEq(dum.asyncArrowFunc.name, "asyncArrowFunc"); +assertEq(dum.method.name, "method"); + +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "getter").get.name, "get getter"); +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "setter").set.name, "set setter"); + +if (typeof reportCompare === "function") + reportCompare(true, true); + diff --git a/js/src/tests/non262/Function/function-name-computed-02.js b/js/src/tests/non262/Function/function-name-computed-02.js new file mode 100644 index 0000000000..54048aee49 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-computed-02.js @@ -0,0 +1,57 @@ +var obj = { + [1]: function() {}, + [2]: function*() {}, + [3]: async function() {}, + [4]: async function*() {}, + [5]: ()=>{}, + [6]: async ()=>{}, + [7] () {}, + [8]: class {}, + [9]: function F() {}, + [10]: class C{}, + get [11]() {}, + set [12](x) {}, +}; + +assertEq(obj[1].name, "1"); +assertEq(obj[2].name, "2"); +assertEq(obj[3].name, "3"); +assertEq(obj[4].name, "4"); +assertEq(obj[5].name, "5"); +assertEq(obj[6].name, "6"); +assertEq(obj[7].name, "7"); +assertEq(obj[8].name, "8"); +assertEq(obj[9].name, "F"); +assertEq(obj[10].name, "C"); +assertEq(Object.getOwnPropertyDescriptor(obj, "11").get.name, "get 11"); +assertEq(Object.getOwnPropertyDescriptor(obj, "12").set.name, "set 12"); + +let dummy = class { + [1]() {} + *[2]() {} + async [3]() {} + async *[4]() {} + [5] = ()=>{} + [6] = async ()=>{}; + [7] () {} + get [11]() {} + set [12](x) {} +}; + +dum = new dummy(); + +assertEq(dum[1].name, "1"); +assertEq(dum[2].name, "2"); +assertEq(dum[3].name, "3"); +assertEq(dum[4].name, "4"); +assertEq(dum[5].name, "5"); +assertEq(dum[6].name, "6"); +assertEq(dum[7].name, "7"); + +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "11").get.name, "get 11"); +assertEq(Object.getOwnPropertyDescriptor(dummy.prototype, "12").set.name, "set 12"); + + +if (typeof reportCompare === "function") + reportCompare(true, true); + diff --git a/js/src/tests/non262/Function/function-name-for.js b/js/src/tests/non262/Function/function-name-for.js new file mode 100644 index 0000000000..2f04a5fa8d --- /dev/null +++ b/js/src/tests/non262/Function/function-name-for.js @@ -0,0 +1,31 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on for-in initializer"; + +print(BUGNUMBER + ": " + summary); + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testForInHead(expr, named) { + eval(` + for (var forInHead = ${expr} in {}) { + } + `); + assertEq(forInHead.name, named ? "named" : "forInHead"); +} +for (var [expr, named] of exprs) { + testForInHead(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-method.js b/js/src/tests/non262/Function/function-name-method.js new file mode 100644 index 0000000000..3b2eeee793 --- /dev/null +++ b/js/src/tests/non262/Function/function-name-method.js @@ -0,0 +1,70 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on method definition"; + +print(BUGNUMBER + ": " + summary); + +var fooSymbol = Symbol("foo"); +var emptySymbol = Symbol(""); +var undefSymbol = Symbol(); + +function testMethod(prefix, classPrefix="", prototype=false) { + var param = (prefix == "set" || prefix == "static set") ? "v" : ""; + var sep = classPrefix ? "" : ","; + var objOrClass = eval(`(${classPrefix}{ + ${prefix} prop(${param}) {} ${sep} + ${prefix} "literal"(${param}) {} ${sep} + ${prefix} ""(${param}) {} ${sep} + ${prefix} 5(${param}) {} ${sep} + ${prefix} [Symbol.iterator](${param}) {} ${sep} + ${prefix} [fooSymbol](${param}) {} ${sep} + ${prefix} [emptySymbol](${param}) {} ${sep} + ${prefix} [undefSymbol](${param}) {} ${sep} + ${prefix} [/a/](${param}) {} ${sep} + })`); + + var target = prototype ? objOrClass.prototype : objOrClass; + + function testOne(methodName, expectedName) { + var f; + if (prefix == "get" || prefix == "static get") { + f = Object.getOwnPropertyDescriptor(target, methodName).get; + expectedName = "get " + expectedName; + } else if (prefix == "set" || prefix == "static set") { + f = Object.getOwnPropertyDescriptor(target, methodName).set; + expectedName = "set " + expectedName; + } else { + f = Object.getOwnPropertyDescriptor(target, methodName).value; + } + + assertEq(f.name, expectedName); + } + testOne("prop", "prop"); + testOne("literal", "literal"); + testOne("", ""); + testOne(5, "5"); + testOne(Symbol.iterator, "[Symbol.iterator]"); + testOne(fooSymbol, "[foo]"); + testOne(emptySymbol, "[]"); + testOne(undefSymbol, ""); + testOne(/a/, "/a/"); +} +testMethod(""); +testMethod("*"); +testMethod("async"); +testMethod("get"); +testMethod("set"); + +testMethod("", "class", true); +testMethod("*", "class", true); +testMethod("async", "class", true); +testMethod("get", "class", true); +testMethod("set", "class", true); + +testMethod("static", "class"); +testMethod("static *", "class"); +testMethod("static async", "class"); +testMethod("static get", "class"); +testMethod("static set", "class"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name-property.js b/js/src/tests/non262/Function/function-name-property.js new file mode 100644 index 0000000000..7ad174b10f --- /dev/null +++ b/js/src/tests/non262/Function/function-name-property.js @@ -0,0 +1,58 @@ +var BUGNUMBER = 883377; +var summary = "Anonymous function name should be set based on property name"; + +print(BUGNUMBER + ": " + summary); + +var fooSymbol = Symbol("foo"); +var emptySymbol = Symbol(""); +var undefSymbol = Symbol(); + +var exprs = [ + ["function() {}", false], + ["function named() {}", true], + ["function*() {}", false], + ["function* named() {}", true], + ["async function() {}", false], + ["async function named() {}", true], + ["() => {}", false], + ["async () => {}", false], + ["class {}", false], + ["class named {}", true], +]; + +function testPropertyDefinition(expr, named) { + var obj = eval(`({ + prop: ${expr}, + "literal": ${expr}, + "": ${expr}, + 5: ${expr}, + 0.4: ${expr}, + [Symbol.iterator]: ${expr}, + [fooSymbol]: ${expr}, + [emptySymbol]: ${expr}, + [undefSymbol]: ${expr}, + [/a/]: ${expr}, + })`); + assertEq(obj.prop.name, named ? "named" : "prop"); + assertEq(obj["literal"].name, named ? "named" : "literal"); + assertEq(obj[""].name, named ? "named" : ""); + assertEq(obj[5].name, named ? "named" : "5"); + assertEq(obj[0.4].name, named ? "named" : "0.4"); + assertEq(obj[Symbol.iterator].name, named ? "named" : "[Symbol.iterator]"); + assertEq(obj[fooSymbol].name, named ? "named" : "[foo]"); + assertEq(obj[emptySymbol].name, named ? "named" : "[]"); + assertEq(obj[undefSymbol].name, named ? "named" : ""); + assertEq(obj[/a/].name, named ? "named" : "/a/"); + + // Not applicable cases: __proto__. + obj = { + __proto__: function() {} + }; + assertEq(obj.__proto__.name, ""); +} +for (var [expr, named] of exprs) { + testPropertyDefinition(expr, named); +} + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-name.js b/js/src/tests/non262/Function/function-name.js new file mode 100644 index 0000000000..7beca56df5 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/function-toString-builtin-name.js b/js/src/tests/non262/Function/function-toString-builtin-name.js new file mode 100644 index 0000000000..709e7e846b --- /dev/null +++ b/js/src/tests/non262/Function/function-toString-builtin-name.js @@ -0,0 +1,53 @@ +// Repeats the test from 'Function/function-toString-builtin.js' and additionally +// verifies the name matches the expected value. +// +// This behaviour is not required by the ECMAScript standard. + +// Greatly (!) simplified patterns for the PropertyName production. +var propertyName = [ + // PropertyName :: LiteralPropertyName :: IdentifierName + "\\w+", + + // PropertyName :: LiteralPropertyName :: StringLiteral + "(?:'[^']*')", + "(?:\"[^\"]*\")", + + // PropertyName :: LiteralPropertyName :: NumericLiteral + "\\d+", + + // PropertyName :: ComputedPropertyName + "(?:\\[[^\\]]+\\])", +].join("|") + +var nativeCode = RegExp([ + "^", "function", ("(" + propertyName + ")?"), "\\(", "\\)", "\\{", "\\[native code\\]", "\\}", "$" +].join("\\s*")); + +function assertFunctionName(fun, expected) { + var match = nativeCode.exec(fun.toString()); + assertEq(match[1], expected); +} + +// Bound functions are considered built-ins. +assertFunctionName(function(){}.bind(), undefined); +assertFunctionName(function fn(){}.bind(), undefined); + +// Built-ins which are well-known intrinsic objects. +assertFunctionName(Array, "Array"); +assertFunctionName(Object.prototype.toString, "toString"); +assertFunctionName(decodeURI, "decodeURI"); + +// Other built-in functions. +assertFunctionName(Math.asin, "asin"); +assertFunctionName(String.prototype.blink, "blink"); +assertFunctionName(RegExp.prototype[Symbol.split], "[Symbol.split]"); + +// Built-in getter functions. +assertFunctionName(Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get, "flags"); +assertFunctionName(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get, "__proto__"); + +// Built-in setter functions. +assertFunctionName(Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set, "__proto__"); + +if (typeof reportCompare === "function") + reportCompare(0, 0); diff --git a/js/src/tests/non262/Function/function-toString-builtin.js b/js/src/tests/non262/Function/function-toString-builtin.js new file mode 100644 index 0000000000..d4efc81c14 --- /dev/null +++ b/js/src/tests/non262/Function/function-toString-builtin.js @@ -0,0 +1,42 @@ + +// Greatly (!) simplified patterns for the PropertyName production. +var propertyName = [ + // PropertyName :: LiteralPropertyName :: IdentifierName + "\\w+", + + // PropertyName :: LiteralPropertyName :: StringLiteral + "(?:'[^']*')", + "(?:\"[^\"]*\")", + + // PropertyName :: LiteralPropertyName :: NumericLiteral + "\\d+", + + // PropertyName :: ComputedPropertyName + "(?:\\[[^\\]]+\\])", +].join("|") + +var nativeCode = RegExp([ + "^", "function", ("(?:" + propertyName + ")?"), "\\(", "\\)", "\\{", "\\[native code\\]", "\\}", "$" +].join("\\s*")); + + +// Bound functions are considered built-ins. +reportMatch(nativeCode, function(){}.bind().toString()); +reportMatch(nativeCode, function fn(){}.bind().toString()); + +// Built-ins which are well-known intrinsic objects. +reportMatch(nativeCode, Array.toString()); +reportMatch(nativeCode, Object.prototype.toString.toString()); +reportMatch(nativeCode, decodeURI.toString()); + +// Other built-in functions. +reportMatch(nativeCode, Math.asin.toString()); +reportMatch(nativeCode, String.prototype.blink.toString()); +reportMatch(nativeCode, RegExp.prototype[Symbol.split].toString()); + +// Built-in getter functions. +reportMatch(nativeCode, Object.getOwnPropertyDescriptor(RegExp.prototype, "flags").get.toString()); +reportMatch(nativeCode, Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").get.toString()); + +// Built-in setter functions. +reportMatch(nativeCode, Object.getOwnPropertyDescriptor(Object.prototype, "__proto__").set.toString()); diff --git a/js/src/tests/non262/Function/get-function-realm.js b/js/src/tests/non262/Function/get-function-realm.js new file mode 100644 index 0000000000..4efd94f971 --- /dev/null +++ b/js/src/tests/non262/Function/get-function-realm.js @@ -0,0 +1,45 @@ +var g1 = newGlobal(); +var g1Fun = g1.eval("function Fun() {}; Fun"); + +// Bound function => cross-realm function. +var bound1 = Function.prototype.bind.call(g1Fun); +assertEq(Object.getPrototypeOf(new bound1()), g1.Fun.prototype); + +// Proxy => cross-realm function. +var proxy1 = new Proxy(g1Fun, { + get: function() {} // Ensure "prototype" is |undefined|. +}); +assertEq(Object.getPrototypeOf(new proxy1()), g1.Object.prototype); + +// Proxy => bound function => cross-realm function. +var proxy2 = new Proxy(bound1, { + get: function() {} +}); +assertEq(Object.getPrototypeOf(new proxy2()), g1.Object.prototype); + +// Revoked proxy => cross-realm function. +var r1 = Proxy.revocable(g1Fun, { + get: function(t, name) { + assertEq(name, "prototype"); + r1.revoke(); + } +}); +assertThrowsInstanceOf(() => new r1.proxy(), g1.TypeError); + +// Bound function => proxy => bound function => cross-realm function. +var bound2 = Function.prototype.bind.call(proxy2); +assertEq(Object.getPrototypeOf(new bound2()), g1.Object.prototype); + +// Proxy => cross-realm revoked proxy => cross-realm function. +var r2 = Proxy.revocable(g1Fun, { + get: function(t, name) { + assertEq(name, "prototype"); + r2.revoke(); + } +}); +var g2 = newGlobal(); +var proxy3 = new g2.Proxy(r2.proxy, {}); +assertThrowsInstanceOf(() => new proxy3(), g1.TypeError); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/has-instance-jitted.js b/js/src/tests/non262/Function/has-instance-jitted.js new file mode 100644 index 0000000000..a2d33abc7f --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/has-instance.js b/js/src/tests/non262/Function/has-instance.js new file mode 100644 index 0000000000..f0c7bf28e1 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/implicit-this-in-parameter-expression.js b/js/src/tests/non262/Function/implicit-this-in-parameter-expression.js new file mode 100644 index 0000000000..c58c53e2af --- /dev/null +++ b/js/src/tests/non262/Function/implicit-this-in-parameter-expression.js @@ -0,0 +1,18 @@ + +function f(a = eval(` + function g() { + 'use strict'; + return this; + } + + with ({}) { + g() /* implicit return value */ + } + `)) { + return a +}; + +assertEq(f(), undefined); + +if (typeof reportCompare === "function") + reportCompare(true, true); diff --git a/js/src/tests/non262/Function/invalid-parameter-list.js b/js/src/tests/non262/Function/invalid-parameter-list.js new file mode 100644 index 0000000000..8aae89ef15 --- /dev/null +++ b/js/src/tests/non262/Function/invalid-parameter-list.js @@ -0,0 +1,27 @@ +// This constructor behaves like `Function` without checking +// if the parameter list end is at the expected position. +// We use this to make sure that the tests we use are otherwise +// syntactically correct. +function DumpFunction(...args) { + let code = "function anonymous("; + code += args.slice(0, -1).join(", "); + code += ") {\n"; + code += args[args.length -1]; + code += "\n}"; + eval(code); +} + +const tests = [ + ["/*", "*/) {"], + ["//", ") {"], + ["a = `", "` ) {"], + [") { var x = function (", "} "], + ["x = function (", "}) {"] +]; + +for (const test of tests) { + DumpFunction(...test); + assertThrowsInstanceOf(() => new Function(...test), SyntaxError); +} + +reportCompare(0, 0, 'ok'); diff --git a/js/src/tests/non262/Function/length-with-destructuring-and-parameter-expression.js b/js/src/tests/non262/Function/length-with-destructuring-and-parameter-expression.js new file mode 100644 index 0000000000..a3f00ac1f2 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/line-terminator-before-arrow.js b/js/src/tests/non262/Function/line-terminator-before-arrow.js new file mode 100644 index 0000000000..52bdce7f3b --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/method-has-duplicated.js b/js/src/tests/non262/Function/method-has-duplicated.js new file mode 100644 index 0000000000..dc0a9dfb42 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/parameter-redeclaration.js b/js/src/tests/non262/Function/parameter-redeclaration.js new file mode 100644 index 0000000000..74e55e3aa9 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/redefine-arguments-length.js b/js/src/tests/non262/Function/redefine-arguments-length.js new file mode 100644 index 0000000000..ad9ae742ff --- /dev/null +++ b/js/src/tests/non262/Function/redefine-arguments-length.js @@ -0,0 +1,65 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'redefine-arguments-length.js'; +//----------------------------------------------------------------------------- +var BUGNUMBER = 539766; +var summary = + "Object.defineProperty sets arguments.length without setting the " + + "length-overridden bit"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function test_JSOP_ARGCNT() +{ + var length = "length"; + Object.defineProperty(arguments, length, { value: 17 }); + assertEq(arguments.length, 17); + assertEq(arguments[length], 17); +} +test_JSOP_ARGCNT(); + +function test_js_fun_apply() +{ + var length = "length"; + Object.defineProperty(arguments, length, { value: 17 }); + + function fun() + { + assertEq(arguments.length, 17); + assertEq(arguments[length], 17); + assertEq(arguments[0], "foo"); + for (var i = 1; i < 17; i++) + assertEq(arguments[i], undefined); + } + fun.apply(null, arguments); +} +test_js_fun_apply("foo"); + +function test_array_toString_sub_1() +{ + Object.defineProperty(arguments, "length", { value: 1 }); + arguments.join = [].join; + assertEq([].toString.call(arguments), "1"); +} +test_array_toString_sub_1(1, 2); + +function test_array_toString_sub_2() +{ + Object.defineProperty(arguments, "length", { value: 1 }); + assertEq([].toLocaleString.call(arguments), "1"); +} +test_array_toString_sub_2(1, 2); + + +/******************************************************************************/ + +reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/regress-123371.js b/js/src/tests/non262/Function/regress-123371.js new file mode 100644 index 0000000000..58294c6a02 --- /dev/null +++ b/js/src/tests/non262/Function/regress-123371.js @@ -0,0 +1,19 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 123371; +var summary = 'Do not crash when newline separates function name from arglist'; +var actual = 'No Crash'; +var expect = 'No Crash'; + + +printBugNumber(BUGNUMBER); +printStatus (summary); + +printStatus +('function call succeeded'); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-131964.js b/js/src/tests/non262/Function/regress-131964.js new file mode 100644 index 0000000000..d7451f040e --- /dev/null +++ b/js/src/tests/non262/Function/regress-131964.js @@ -0,0 +1,159 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * + * Date: 19 Mar 2002 + * SUMMARY: Function declarations in global or function scope are {DontDelete}. + * Function declarations in eval scope are not {DontDelete}. + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=131964 + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 131964; +var summary = 'Functions defined in global or function scope are {DontDelete}'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +status = inSection(1); +function f() +{ + return 'f lives!'; +} +delete f; + +try +{ + actual = f(); +} +catch(e) +{ + actual = 'f was deleted'; +} + +expect = 'f lives!'; +addThis(); + + + +/* + * Try the same test in function scope - + */ +status = inSection(2); +function g() +{ + function f() + { + return 'f lives!'; + } + delete f; + + try + { + actual = f(); + } + catch(e) + { + actual = 'f was deleted'; + } + + expect = 'f lives!'; + addThis(); +} +g(); + + + +/* + * Try the same test in eval scope - here we EXPECT the function to be deleted (?) + */ +status = inSection(3); +var s = ''; +s += 'function h()'; +s += '{ '; +s += ' return "h lives!";'; +s += '}'; +s += 'delete h;'; + +s += 'try'; +s += '{'; +s += ' actual = h();'; +s += '}'; +s += 'catch(e)'; +s += '{'; +s += ' actual = "h was deleted";'; +s += '}'; + +s += 'expect = "h was deleted";'; +s += 'addThis();'; +eval(s); + + +/* + * Define the function in eval scope, but delete it in global scope - + */ +status = inSection(4); +s = ''; +s += 'function k()'; +s += '{ '; +s += ' return "k lives!";'; +s += '}'; +eval(s); + +delete k; + +try +{ + actual = k(); +} +catch(e) +{ + actual = 'k was deleted'; +} + +expect = 'k was deleted'; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function wasDeleted(functionName) +{ + return functionName + ' was deleted...'; +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i<UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} diff --git a/js/src/tests/non262/Function/regress-137181.js b/js/src/tests/non262/Function/regress-137181.js new file mode 100644 index 0000000000..6fddde2d1a --- /dev/null +++ b/js/src/tests/non262/Function/regress-137181.js @@ -0,0 +1,76 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * + * Date: 12 Apr 2002 + * SUMMARY: delete arguments[i] should break connection to local reference + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=137181 + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 137181; +var summary = 'delete arguments[i] should break connection to local reference'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +status = inSection(1); +function f1(x) +{ + x = 1; + delete arguments[0]; + return x; +} +actual = f1(0); // (bug: Rhino was returning |undefined|) +expect = 1; +addThis(); + + +status = inSection(2); +function f2(x) +{ + x = 1; + delete arguments[0]; + arguments[0] = -1; + return x; +} +actual = f2(0); // (bug: Rhino was returning -1) +expect = 1; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i<UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} diff --git a/js/src/tests/non262/Function/regress-178389.js b/js/src/tests/non262/Function/regress-178389.js new file mode 100644 index 0000000000..e1735adf86 --- /dev/null +++ b/js/src/tests/non262/Function/regress-178389.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 178389; +var summary = 'Function.prototype.toSource should not override Function.prototype.toString'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function f() +{ + var g = function (){}; +} + +expect = f.toString(); + +Function.prototype.toSource = function () { return ''; }; + +actual = f.toString(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-193555.js b/js/src/tests/non262/Function/regress-193555.js new file mode 100644 index 0000000000..c9c45f3311 --- /dev/null +++ b/js/src/tests/non262/Function/regress-193555.js @@ -0,0 +1,99 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * + * Date: 17 February 2003 + * SUMMARY: Testing access to function name from inside function + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=193555 + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 193555; +var summary = 'Testing access to function name from inside function'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +// test via function statement +status = inSection(1); +function f() {return f.toString();}; +actual = f(); +expect = f.toString(); +addThis(); + +// test via function expression +status = inSection(2); +var x = function g() {return g.toString();}; +actual = x(); +expect = x.toString(); +addThis(); + +// test via eval() outside function +status = inSection(3); +eval ('function a() {return a.toString();}'); +actual = a(); +expect = a.toString(); +addThis(); + +status = inSection(4); +eval ('var y = function b() {return b.toString();}'); +actual = y(); +expect = y.toString(); +addThis(); + +// test via eval() inside function +status = inSection(5); +function c() {return eval('c').toString();}; +actual = c(); +expect = c.toString(); +addThis(); + +status = inSection(6); +var z = function d() {return eval('d').toString();}; +actual = z(); +expect = z.toString(); +addThis(); + +// test via two evals! +status = inSection(7); +eval('var w = function e() {return eval("e").toString();}'); +actual = w(); +expect = w.toString(); +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i<UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} diff --git a/js/src/tests/non262/Function/regress-222029-001.js b/js/src/tests/non262/Function/regress-222029-001.js new file mode 100644 index 0000000000..a58e60bc3d --- /dev/null +++ b/js/src/tests/non262/Function/regress-222029-001.js @@ -0,0 +1,123 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * + * Date: 13 Oct 2003 + * SUMMARY: Make our f.caller property match IE's wrt f.apply and f.call + * See http://bugzilla.mozilla.org/show_bug.cgi?id=222029 + * + * Below, when gg calls f via |f.call|, we have this call chain: + * + * calls calls + * gg() ---------> Function.prototype.call() ---------> f() + * + * + * The question this bug addresses is, "What should we say |f.caller| is?" + * + * Before this fix, SpiderMonkey said it was |Function.prototype.call|. + * After this fix, SpiderMonkey emulates IE and says |gg| instead. + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 222029; +var summary = "Make our f.caller property match IE's wrt f.apply and f.call"; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +function f() +{ + return f.caller.p ; +} + + +/* + * Call |f| directly + */ +function g() +{ + return f(); +} +g.p = "hello"; + + +/* + * Call |f| via |f.call| + */ +function gg() +{ + return f.call(this); +} +gg.p = "hello"; + + +/* + * Call |f| via |f.apply| + */ +function ggg() +{ + return f.apply(this); +} +ggg.p = "hello"; + + +/* + * Shadow |p| on |Function.prototype.call|, |Function.prototype.apply|. + * In Sections 2 and 3 below, we no longer expect to recover this value - + */ +Function.prototype.call.p = "goodbye"; +Function.prototype.apply.p = "goodbye"; + + + +status = inSection(1); +actual = g(); +expect = "hello"; +addThis(); + +status = inSection(2); +actual = gg(); +expect = "hello"; +addThis(); + +status = inSection(3); +actual = ggg(); +expect = "hello"; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i<UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} diff --git a/js/src/tests/non262/Function/regress-222029-002.js b/js/src/tests/non262/Function/regress-222029-002.js new file mode 100644 index 0000000000..96f68a2661 --- /dev/null +++ b/js/src/tests/non262/Function/regress-222029-002.js @@ -0,0 +1,132 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * + * Date: 13 Oct 2003 + * SUMMARY: Make our f.caller property match IE's wrt f.apply and f.call + * See http://bugzilla.mozilla.org/show_bug.cgi?id=222029 + * + * Below, when gg calls f via |f.call|, we have this call chain: + * + * calls calls + * gg() ---------> Function.prototype.call() ---------> f() + * + * + * The question this bug addresses is, "What should we say |f.caller| is?" + * + * Before this fix, SpiderMonkey said it was |Function.prototype.call|. + * After this fix, SpiderMonkey emulates IE and says |gg| instead. + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 222029; +var summary = "Make our f.caller property match IE's wrt f.apply and f.call"; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + +/* + * Try to confuse the engine by adding a |p| property to everything! + */ +var p = 'global'; +var o = {p:'object'}; + + +function f(obj) +{ + return f.caller.p ; +} + + +/* + * Call |f| directly + */ +function g(obj) +{ + var p = 'local'; + return f(obj); +} +g.p = "hello"; + + +/* + * Call |f| via |f.call| + */ +function gg(obj) +{ + var p = 'local'; + return f.call(obj, obj); +} +gg.p = "hello"; + + +/* + * Call |f| via |f.apply| + */ +function ggg(obj) +{ + var p = 'local'; + return f.apply(obj, [obj]); +} +ggg.p = "hello"; + + +/* + * Shadow |p| on |Function.prototype.call|, |Function.prototype.apply|. + * In Sections 2 and 3 below, we no longer expect to recover this value - + */ +Function.prototype.call.p = "goodbye"; +Function.prototype.apply.p = "goodbye"; + + + +status = inSection(1); +actual = g(o); +expect = "hello"; +addThis(); + +status = inSection(2); +actual = gg(o); +expect = "hello"; +addThis(); + +status = inSection(3); +actual = ggg(o); +expect = "hello"; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i<UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} diff --git a/js/src/tests/non262/Function/regress-292215.js b/js/src/tests/non262/Function/regress-292215.js new file mode 100644 index 0000000000..c264b74178 --- /dev/null +++ b/js/src/tests/non262/Function/regress-292215.js @@ -0,0 +1,37 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 292215; +var summary = 'Set arguments'; +var actual = ''; +var expect = '00012'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + + +function zeroArguments () { + arguments[1] = '0'; + actual += arguments[1]; +} + +function oneArgument (x) { + arguments[1] = '1'; + actual += arguments[1]; +} + +function twoArguments (x,y) { + arguments[1] = '2'; + actual += arguments[1]; +} + +zeroArguments(); +zeroArguments(1); +zeroArguments('a', 'b'); +oneArgument(); +twoArguments(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-313570.js b/js/src/tests/non262/Function/regress-313570.js new file mode 100644 index 0000000000..eb3039650b --- /dev/null +++ b/js/src/tests/non262/Function/regress-313570.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 313570; +var summary = 'length of objects whose prototype chain includes a function'; +var actual = ''; +var expect = ''; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +function tmp() {} +tmp.prototype = function(a, b, c) {}; +var obj = new tmp(); + +// arity +expect = 3; +actual = obj.length; +reportCompare(expect, actual, summary + ': arity'); + +// immutable +obj.length = 10; + +expect = 3; +actual = obj.length; +reportCompare(expect, actual, summary + ': immutable'); + diff --git a/js/src/tests/non262/Function/regress-338001.js b/js/src/tests/non262/Function/regress-338001.js new file mode 100644 index 0000000000..6afdc4f6fc --- /dev/null +++ b/js/src/tests/non262/Function/regress-338001.js @@ -0,0 +1,42 @@ +// |reftest| skip-if(Android) silentfail slow +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 BUGNUMBER = 338001; +var summary = 'integer overflow in jsfun.c:Function'; +var actual = 'No Crash'; +var expect = /No Crash|InternalError: allocation size overflow/; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +expectExitCode(0); +expectExitCode(5); + +var fe="f"; + +try +{ + for (i=0; i<25; i++) + fe += fe; + + var fu=new Function( + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + "done" + ); +} +catch(ex) +{ + // handle changed 1.9 branch behavior. see bug 422348 + actual = ex + ''; +} + +print('Done: ' + actual); + +reportMatch(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-338121-01.js b/js/src/tests/non262/Function/regress-338121-01.js new file mode 100644 index 0000000000..e51d8c952e --- /dev/null +++ b/js/src/tests/non262/Function/regress-338121-01.js @@ -0,0 +1,33 @@ +// |reftest| skip-if(Android) silentfail slow +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 BUGNUMBER = 338121; +var summary = 'Issues with JS_ARENA_ALLOCATE_CAST'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +expectExitCode(0); +expectExitCode(5); +expectExitCode(3); + +var fe="v"; + +for (i=0; i<25; i++) + fe += fe; + +var fu=new Function( + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + "done" + ); + +print('Done'); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-338121-02.js b/js/src/tests/non262/Function/regress-338121-02.js new file mode 100644 index 0000000000..f051c00ce2 --- /dev/null +++ b/js/src/tests/non262/Function/regress-338121-02.js @@ -0,0 +1,36 @@ +// |reftest| skip-if(Android) silentfail skip -- disabled pending bug 657444 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 BUGNUMBER = 338121; +var summary = 'Issues with JS_ARENA_ALLOCATE_CAST'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +expectExitCode(0); +expectExitCode(5); + +var fe="vv"; + +for (i=0; i<24; i++) + fe += fe; + +var fu=new Function( + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + "done" + ); + +//alert("fu="+fu); +//print("fu="+fu); +var fuout = 'fu=' + fu; + +print('Done'); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-338121-03.js b/js/src/tests/non262/Function/regress-338121-03.js new file mode 100644 index 0000000000..4fd6ea2928 --- /dev/null +++ b/js/src/tests/non262/Function/regress-338121-03.js @@ -0,0 +1,38 @@ +// |reftest| skip-if(Android) silentfail slow +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 BUGNUMBER = 338121; +var summary = 'Issues with JS_ARENA_ALLOCATE_CAST'; +var actual = 'No Crash'; +var expect = 'No Crash'; + +printBugNumber(BUGNUMBER); +printStatus (summary); + +expectExitCode(0); +expectExitCode(5); + +var fe="vv"; + +for (i=0; i<24; i++) + fe += fe; + +var fu=new Function( + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, fe, + fe, fe, fe, + "done" + ); + +//alert("fu="+fu); +//print("fu="+fu); +var fuout = 'fu=' + fu; + +print('Done'); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-344052.js b/js/src/tests/non262/Function/regress-344052.js new file mode 100644 index 0000000000..f9f747276f --- /dev/null +++ b/js/src/tests/non262/Function/regress-344052.js @@ -0,0 +1,27 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 344052; +var summary = 'Function prototype - simple shared property'; +var actual = ''; +var expect = 'true'; + +Function.prototype.foo = true; +function y(){}; + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + actual = String(y.foo); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Function/regress-364023.js b/js/src/tests/non262/Function/regress-364023.js new file mode 100644 index 0000000000..6102351a6a --- /dev/null +++ b/js/src/tests/non262/Function/regress-364023.js @@ -0,0 +1,37 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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 BUGNUMBER = 364023; +var summary = 'Do not crash in JS::GetPrivate'; +var actual = 'No Crash'; +var expect = 'No Crash'; + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + function exploit() { + var code = ""; + for(var i = 0; i < 0x10000; i++) { + if(i == 125) { + code += "void 0x10000050505050;\n"; + } else { + code += "void " + (0x10000000000000 + i) + ";\n"; + } + } + code += "function foo() {}\n"; + eval(code); + } + exploit(); + + reportCompare(expect, actual, summary); +} diff --git a/js/src/tests/non262/Function/regress-49286.js b/js/src/tests/non262/Function/regress-49286.js new file mode 100644 index 0000000000..0b748b3ebf --- /dev/null +++ b/js/src/tests/non262/Function/regress-49286.js @@ -0,0 +1,100 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * Date: 2001-07-10 + * + * SUMMARY: Invoking try...catch through Function.call + * See http://bugzilla.mozilla.org/show_bug.cgi?id=49286 + * + * 1) Define a function with a try...catch block in it + * 2) Invoke the function via the call method of Function + * 3) Pass bad syntax to the try...catch block + * 4) We should catch the error! + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 49286; +var summary = 'Invoking try...catch through Function.call'; +var cnErrorCaught = 'Error caught'; +var cnErrorNotCaught = 'Error NOT caught'; +var cnGoodSyntax = '1==2'; +var cnBadSyntax = '1=2'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +var obj = new testObject(); + +status = 'Section A of test: direct call of f'; +actual = f.call(obj); +expect = cnErrorCaught; +addThis(); + +status = 'Section B of test: indirect call of f'; +actual = g.call(obj); +expect = cnErrorCaught; +addThis(); + + + +//----------------------------------------- +test(); +//----------------------------------------- + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i=0; i<UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} + + +// An object storing bad syntax as a property - +function testObject() +{ + this.badSyntax = cnBadSyntax; + this.goodSyntax = cnGoodSyntax; +} + + +// A function wrapping a try...catch block +function f() +{ + try + { + eval(this.badSyntax); + } + catch(e) + { + return cnErrorCaught; + } + return cnErrorNotCaught; +} + + +// A function wrapping a call to f - +function g() +{ + return f.call(this); +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} diff --git a/js/src/tests/non262/Function/regress-518103.js b/js/src/tests/non262/Function/regress-518103.js new file mode 100644 index 0000000000..70bab0d572 --- /dev/null +++ b/js/src/tests/non262/Function/regress-518103.js @@ -0,0 +1,27 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 518103; +var summary = 'lambda constructor "method" vs. instanceof'; +var actual; +var expect; + +printBugNumber(BUGNUMBER); +printStatus(summary); + +var Y = {widget: {}}; + +Y.widget.DataSource = function () {}; +Y.widget.DS_JSArray = function (A) { this.data = A; }; +Y.widget.DS_JSArray.prototype = new Y.widget.DataSource(); + +var J = new Y.widget.DS_JSArray( [ ] ); + +actual = J instanceof Y.widget.DataSource; +expect = true; + +reportCompare(expect, actual, summary); + +printStatus("All tests passed!"); diff --git a/js/src/tests/non262/Function/regress-524826.js b/js/src/tests/non262/Function/regress-524826.js new file mode 100644 index 0000000000..da1dfbba08 --- /dev/null +++ b/js/src/tests/non262/Function/regress-524826.js @@ -0,0 +1,28 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 524826; +var summary = 'null-closure property initialiser mis-brands object literal scope'; +var actual; +var expect; + +printBugNumber(BUGNUMBER); +printStatus(summary); + +function make(g) { + var o = {f: function(a,b) { return a*b; }, g: g}; + return o; +} +var z = -1; +var x = make(function(c) { return c*z; }); +var y = make(function(c) { return -c*z; }); + +function callg(o, c) { return o.g(c); }; +actual = callg(x, 1); +expect = -callg(y, 1); + +reportCompare(expect, actual, summary); + +printStatus("All tests passed!"); diff --git a/js/src/tests/non262/Function/regress-528082.js b/js/src/tests/non262/Function/regress-528082.js new file mode 100644 index 0000000000..1ca7b77cbb --- /dev/null +++ b/js/src/tests/non262/Function/regress-528082.js @@ -0,0 +1,20 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 528082; +var summary = 'named function expression function-name-as-upvar slot botch'; + +printBugNumber(BUGNUMBER); +printStatus(summary); + +function f() { + return function g(a) { return function () { return g; }(); }(); +} +var actual = typeof f(); +var expect = "function"; + +reportCompare(expect, actual, summary); + +printStatus("All tests passed!"); diff --git a/js/src/tests/non262/Function/regress-533254.js b/js/src/tests/non262/Function/regress-533254.js new file mode 100644 index 0000000000..b0e319818b --- /dev/null +++ b/js/src/tests/non262/Function/regress-533254.js @@ -0,0 +1,28 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 533254; +var summary = 'init-method late in table-big initialiser screwup'; + +printBugNumber(BUGNUMBER); +printStatus(summary); + +function f() { + var proto = {p8:8}; + var obj = { + p0:0, p1:1, p2:2, p3:3, p4:4, p5:5, p6:6, p7:7, p8:8, p9:9, + p10:0, p11:1, p12:2, p13:3, p14:4, p15:5, p16:6, p17:7, p18:8, p19:9, + m: function() { return 42; } + }; + return obj; +} +var expect = f(), + actual = f(); + +expect += ''; +actual += ''; +reportCompare(expect, actual, summary); + +printStatus("All tests passed!"); diff --git a/js/src/tests/non262/Function/regress-545980.js b/js/src/tests/non262/Function/regress-545980.js new file mode 100644 index 0000000000..5e29def494 --- /dev/null +++ b/js/src/tests/non262/Function/regress-545980.js @@ -0,0 +1,41 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BUGNUMBER = 518103; +var summary = 'partial flat closures must not reach across funargs'; +var actual = "no crash"; +var expect = actual; + +function Timer(){} +Timer.prototype = { initWithCallback: function (o) {Timer.q.push(o)} }; +Timer.q = []; + +var later; +var ac = {startSearch: function(q,s,n,o){later=o}}; + +var bm = {insertBookmark: function(){}, getIdForItemAt: function(){}}; + +function run_test() { + var tagIds = []; + + (function doSearch(query) { + ac.startSearch(query, "", null, { + onSearchResult: function() { + var num = tagIds.length; + + var timer = new Timer; + var next = query.slice(1); + timer.initWithCallback({ notify: function() { return doSearch(next); } }); + } + }); + })("title"); +} + +run_test(); +later.onSearchResult(); +for (var i in Timer.q) + Timer.q[i].notify(); + +reportCompare(expect, actual, summary); diff --git a/js/src/tests/non262/Function/regress-58274.js b/js/src/tests/non262/Function/regress-58274.js new file mode 100644 index 0000000000..f8ef3e5880 --- /dev/null +++ b/js/src/tests/non262/Function/regress-58274.js @@ -0,0 +1,189 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * + * Date: 15 July 2002 + * SUMMARY: Testing functions with double-byte names + * See http://bugzilla.mozilla.org/show_bug.cgi?id=58274 + * + * Here is a sample of the problem: + * + * js> function f\u02B1 () {} + * + * js> f\u02B1.toSource(); + * function f¦() {} + * + * js> f\u02B1.toSource().toSource(); + * (new String("function f\xB1() {}")) + * + * + * See how the high-byte information (the 02) has been lost? + * The same thing was happening with the toString() method: + * + * js> f\u02B1.toString(); + * + * function f¦() { + * } + * + * js> f\u02B1.toString().toSource(); + * (new String("\nfunction f\xB1() {\n}\n")) + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 58274; +var summary = 'Testing functions with double-byte names'; +var ERR = 'UNEXPECTED ERROR! \n'; +var ERR_MALFORMED_NAME = ERR + 'Could not find function name in: \n\n'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var sEval; +var sName; + + +sEval = "function f\u02B2() {return 42;}"; +eval(sEval); +sName = getFunctionName(f\u02B2); + +// Test function call - +status = inSection(1); +actual = f\u02B2(); +expect = 42; +addThis(); + +// Test both characters of function name - +status = inSection(2); +actual = sName[0]; +expect = sEval[9]; +addThis(); + +status = inSection(3); +actual = sName[1]; +expect = sEval[10]; +addThis(); + + + +sEval = "function f\u02B2\u0AAA () {return 84;}"; +eval(sEval); +sName = getFunctionName(f\u02B2\u0AAA); + +// Test function call - +status = inSection(4); +actual = f\u02B2\u0AAA(); +expect = 84; +addThis(); + +// Test all three characters of function name - +status = inSection(5); +actual = sName[0]; +expect = sEval[9]; +addThis(); + +status = inSection(6); +actual = sName[1]; +expect = sEval[10]; +addThis(); + +status = inSection(7); +actual = sName[2]; +expect = sEval[11]; +addThis(); + + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + + +/* + * Goal: test that f.toString() contains the proper function name. + * + * Note, however, f.toString() is implementation-independent. For example, + * it may begin with '\nfunction' instead of 'function'. Therefore we use + * a regexp to make sure we extract the name properly. + * + * Here we assume that f has been defined by means of a function statement, + * and not a function expression (where it wouldn't have to have a name). + * + * Rhino uses a Unicode representation for f.toString(); whereas + * SpiderMonkey uses an ASCII representation, putting escape sequences + * for non-ASCII characters. For example, if a function is called f\u02B1, + * then in Rhino the toString() method will present a 2-character Unicode + * string for its name, whereas SpiderMonkey will present a 7-character + * ASCII string for its name: the string literal 'f\u02B1'. + * + * So we force the lexer to condense the string before using it. + * This will give uniform results in Rhino and SpiderMonkey. + */ +function getFunctionName(f) +{ + var s = condenseStr(f.toString()); + var re = /\s*function\s+(\S+)\s*\(/; + var arr = s.match(re); + + if (!(arr && arr[1])) + return ERR_MALFORMED_NAME + s; + return arr[1]; +} + + +/* + * This function is the opposite of functions like escape(), which take + * Unicode characters and return escape sequences for them. Here, we force + * the lexer to turn escape sequences back into single characters. + * + * Note we can't simply do |eval(str)|, since in practice |str| will be an + * identifier somewhere in the program (e.g. a function name); thus |eval(str)| + * would return the object that the identifier represents: not what we want. + * + * So we surround |str| lexicographically with quotes to force the lexer to + * evaluate it as a string. Have to strip out any linefeeds first, however - + */ +function condenseStr(str) +{ + /* + * You won't be able to do the next step if |str| has + * any carriage returns or linefeeds in it. For example: + * + * js> eval("'" + '\nHello' + "'"); + * 1: SyntaxError: unterminated string literal: + * 1: ' + * 1: ^ + * + * So replace them with the empty string - + */ + str = str.replace(/[\r\n]/g, '') + return eval("'" + str + "'"); +} + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus(summary); + + for (var i=0; i<UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} diff --git a/js/src/tests/non262/Function/regress-85880.js b/js/src/tests/non262/Function/regress-85880.js new file mode 100644 index 0000000000..d5d6d63175 --- /dev/null +++ b/js/src/tests/non262/Function/regress-85880.js @@ -0,0 +1,136 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * Date: 2001-06-14 + * + * SUMMARY: Regression test for Bugzilla bug 85880 + * + * Rhino interpreted mode was nulling out the arguments object of a + * function if it happened to call another function inside its body. + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=85880 + * + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 85880; +var summary = 'Arguments object of g(){f()} should not be null'; +var cnNonNull = 'Arguments != null'; +var cnNull = 'Arguments == null'; +var cnRecurse = true; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; + + +function f1(x) +{ +} + + +function f2() +{ + return f2.arguments; +} +status = 'Section A of test'; +actual = (f2() == null); +expect = false; +addThis(); + +status = 'Section B of test'; +actual = (f2(0) == null); +expect = false; +addThis(); + + +function f3() +{ + f1(); + return f3.arguments; +} +status = 'Section C of test'; +actual = (f3() == null); +expect = false; +addThis(); + +status = 'Section D of test'; +actual = (f3(0) == null); +expect = false; +addThis(); + + +function f4() +{ + f1(); + f2(); + f3(); + return f4.arguments; +} +status = 'Section E of test'; +actual = (f4() == null); +expect = false; +addThis(); + +status = 'Section F of test'; +actual = (f4(0) == null); +expect = false; +addThis(); + + +function f5() +{ + if (cnRecurse) + { + cnRecurse = false; + f5(); + } + return f5.arguments; +} +status = 'Section G of test'; +actual = (f5() == null); +expect = false; +addThis(); + +status = 'Section H of test'; +actual = (f5(0) == null); +expect = false; +addThis(); + + + +//------------------------------------------------------------------------------------------------- +test(); +//------------------------------------------------------------------------------------------------- + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = isThisNull(actual); + expectedvalues[UBound] = isThisNull(expect); + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i = 0; i < UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} + + +function isThisNull(bool) +{ + return bool? cnNull : cnNonNull + } diff --git a/js/src/tests/non262/Function/regress-94506.js b/js/src/tests/non262/Function/regress-94506.js new file mode 100644 index 0000000000..048c7fcfaf --- /dev/null +++ b/js/src/tests/non262/Function/regress-94506.js @@ -0,0 +1,126 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * Date: 08 August 2001 + * + * SUMMARY: When we invoke a function, the arguments object should take + * a back seat to any local identifier named "arguments". + * + * See http://bugzilla.mozilla.org/show_bug.cgi?id=94506 + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 94506; +var summary = 'Testing functions employing identifiers named "arguments"'; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var TYPE_OBJECT = typeof new Object(); +var arguments = 5555; + + +// use a parameter named "arguments" +function F1(arguments) +{ + return arguments; +} + + +// use a local variable named "arguments" +function F2() +{ + var arguments = 55; + return arguments; +} + + +// same thing in a different order. CHANGES THE RESULT! +function F3() +{ + return arguments; + var arguments = 555; +} + + +// use the global variable above named "arguments" +function F4() +{ + return arguments; +} + + + +/* + * In Sections 1 and 2, expect the local identifier, not the arguments object. + * In Sections 3 and 4, expect the arguments object, not the the identifier. + */ + +status = 'Section 1 of test'; +actual = F1(5); +expect = 5; +addThis(); + + +status = 'Section 2 of test'; +actual = F2(); +expect = 55; +addThis(); + + +status = 'Section 3 of test'; +actual = typeof F3(); +expect = TYPE_OBJECT; +addThis(); + + +status = 'Section 4 of test'; +actual = typeof F4(); +expect = TYPE_OBJECT; +addThis(); + + +// Let's try calling F1 without providing a parameter - +status = 'Section 5 of test'; +actual = F1(); +expect = undefined; +addThis(); + + +// Let's try calling F1 with too many parameters - +status = 'Section 6 of test'; +actual = F1(3,33,333); +expect = 3; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = actual; + expectedvalues[UBound] = expect; + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i = 0; i < UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} diff --git a/js/src/tests/non262/Function/regress-97921.js b/js/src/tests/non262/Function/regress-97921.js new file mode 100644 index 0000000000..1bea04a1dd --- /dev/null +++ b/js/src/tests/non262/Function/regress-97921.js @@ -0,0 +1,115 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* 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/. */ + +/* + * Date: 10 September 2001 + * + * SUMMARY: Testing with() statement with nested functions + * See http://bugzilla.mozilla.org/show_bug.cgi?id=97921 + * + * Brendan: "The bug is peculiar to functions that have formal parameters, + * but that are called with fewer actual arguments than the declared number + * of formal parameters." + */ +//----------------------------------------------------------------------------- +var UBound = 0; +var BUGNUMBER = 97921; +var summary = 'Testing with() statement with nested functions'; +var cnYES = 'Inner value === outer value'; +var cnNO = "Inner value !== outer value!"; +var status = ''; +var statusitems = []; +var actual = ''; +var actualvalues = []; +var expect= ''; +var expectedvalues = []; +var outerValue = ''; +var innerValue = ''; +var useWith = ''; + + +function F(i) +{ + i = 0; + if(useWith) with(1){i;} + i++; + + outerValue = i; // capture value of i in outer function + F1 = function() {innerValue = i;}; // capture value of i in inner function + F1(); +} + + +status = inSection(1); +useWith=false; +F(); // call F without supplying the argument +actual = innerValue === outerValue; +expect = true; +addThis(); + +status = inSection(2); +useWith=true; +F(); // call F without supplying the argument +actual = innerValue === outerValue; +expect = true; +addThis(); + + +function G(i) +{ + i = 0; + with (new Object()) {i=100}; + i++; + + outerValue = i; // capture value of i in outer function + G1 = function() {innerValue = i;}; // capture value of i in inner function + G1(); +} + + +status = inSection(3); +G(); // call G without supplying the argument +actual = innerValue === 101; +expect = true; +addThis(); + +status = inSection(4); +G(); // call G without supplying the argument +actual = innerValue === outerValue; +expect = true; +addThis(); + + + +//----------------------------------------------------------------------------- +test(); +//----------------------------------------------------------------------------- + + +function addThis() +{ + statusitems[UBound] = status; + actualvalues[UBound] = areTheseEqual(actual); + expectedvalues[UBound] = areTheseEqual(expect); + UBound++; +} + + +function test() +{ + printBugNumber(BUGNUMBER); + printStatus (summary); + + for (var i = 0; i < UBound; i++) + { + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); + } +} + + +function areTheseEqual(yes) +{ + return yes? cnYES : cnNO + } diff --git a/js/src/tests/non262/Function/rest-has-duplicated.js b/js/src/tests/non262/Function/rest-has-duplicated.js new file mode 100644 index 0000000000..67577ab4e3 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/rest-parameter-names.js b/js/src/tests/non262/Function/rest-parameter-names.js new file mode 100644 index 0000000000..6cfa01dcfb --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/return-finally.js b/js/src/tests/non262/Function/return-finally.js new file mode 100644 index 0000000000..fe075d4576 --- /dev/null +++ b/js/src/tests/non262/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/non262/Function/shell.js b/js/src/tests/non262/Function/shell.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/non262/Function/shell.js diff --git a/js/src/tests/non262/Function/spread-iterator-primitive.js b/js/src/tests/non262/Function/spread-iterator-primitive.js new file mode 100644 index 0000000000..79320ad7f1 --- /dev/null +++ b/js/src/tests/non262/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); diff --git a/js/src/tests/non262/Function/strict-arguments.js b/js/src/tests/non262/Function/strict-arguments.js new file mode 100644 index 0000000000..fce5f756c2 --- /dev/null +++ b/js/src/tests/non262/Function/strict-arguments.js @@ -0,0 +1,453 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'strict-arguments.js'; +var BUGNUMBER = 516255; +var summary = + "ES5 strict mode: arguments objects of strict mode functions must copy " + + "argument values"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +function arrayEvery(arr, fun) +{ + return Array.prototype.every.call(arr, fun); +} + +function arraysEqual(a1, a2) +{ + return a1.length === a2.length && + arrayEvery(a1, function(v, i) { return v === a2[i]; }); +} + + +/************************ + * NON-STRICT ARGUMENTS * + ************************/ + +var obj = {}; + +function noargs() { return arguments; } + +assertEq(arraysEqual(noargs(), []), true); +assertEq(arraysEqual(noargs(1), [1]), true); +assertEq(arraysEqual(noargs(2, obj, 8), [2, obj, 8]), true); + +function args(a) { return arguments; } + +assertEq(arraysEqual(args(), []), true); +assertEq(arraysEqual(args(1), [1]), true); +assertEq(arraysEqual(args(1, obj), [1, obj]), true); +assertEq(arraysEqual(args("foopy"), ["foopy"]), true); + +function assign(a) +{ + a = 17; + return arguments; +} + +assertEq(arraysEqual(assign(1), [17]), true); + +function getLaterAssign(a) +{ + var o = arguments; + a = 17; + return o; +} + +assertEq(arraysEqual(getLaterAssign(1), [17]), true); + +function assignElementGetParameter(a) +{ + arguments[0] = 17; + return a; +} + +assertEq(assignElementGetParameter(42), 17); + +function assignParameterGetElement(a) +{ + a = 17; + return arguments[0]; +} + +assertEq(assignParameterGetElement(42), 17); + +function assignArgSub(x, y) +{ + arguments[0] = 3; + return arguments[0]; +} + +assertEq(assignArgSub(1), 3); + +function assignArgSubParamUse(x, y) +{ + arguments[0] = 3; + assertEq(x, 3); + return arguments[0]; +} + +assertEq(assignArgSubParamUse(1), 3); + +function assignArgumentsElement(x, y) +{ + arguments[0] = 3; + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(assignArgumentsElement(1), 3); + +function assignArgumentsElementParamUse(x, y) +{ + arguments[0] = 3; + assertEq(x, 3); + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(assignArgumentsElementParamUse(1), 3); + +/******************** + * STRICT ARGUMENTS * + ********************/ + +function strictNoargs() +{ + "use strict"; + return arguments; +} + +assertEq(arraysEqual(strictNoargs(), []), true); +assertEq(arraysEqual(strictNoargs(1), [1]), true); +assertEq(arraysEqual(strictNoargs(1, obj), [1, obj]), true); + +function strictArgs(a) +{ + "use strict"; + return arguments; +} + +assertEq(arraysEqual(strictArgs(), []), true); +assertEq(arraysEqual(strictArgs(1), [1]), true); +assertEq(arraysEqual(strictArgs(1, obj), [1, obj]), true); + +function strictAssign(a) +{ + "use strict"; + a = 17; + return arguments; +} + +assertEq(arraysEqual(strictAssign(), []), true); +assertEq(arraysEqual(strictAssign(1), [1]), true); +assertEq(arraysEqual(strictAssign(1, obj), [1, obj]), true); + +var upper; +function strictAssignAfter(a) +{ + "use strict"; + upper = arguments; + a = 42; + return upper; +} + +assertEq(arraysEqual(strictAssignAfter(), []), true); +assertEq(arraysEqual(strictAssignAfter(17), [17]), true); +assertEq(arraysEqual(strictAssignAfter(obj), [obj]), true); + +function strictMaybeAssignOuterParam(p) +{ + "use strict"; + function inner() { p = 17; } + return arguments; +} + +assertEq(arraysEqual(strictMaybeAssignOuterParam(), []), true); +assertEq(arraysEqual(strictMaybeAssignOuterParam(42), [42]), true); +assertEq(arraysEqual(strictMaybeAssignOuterParam(obj), [obj]), true); + +function strictAssignOuterParam(p) +{ + "use strict"; + function inner() { p = 17; } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictAssignOuterParam(), []), true); +assertEq(arraysEqual(strictAssignOuterParam(17), [17]), true); +assertEq(arraysEqual(strictAssignOuterParam(obj), [obj]), true); + +function strictAssignOuterParamPSYCH(p) +{ + "use strict"; + function inner(p) { p = 17; } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictAssignOuterParamPSYCH(), []), true); +assertEq(arraysEqual(strictAssignOuterParamPSYCH(17), [17]), true); +assertEq(arraysEqual(strictAssignOuterParamPSYCH(obj), [obj]), true); + +function strictEval(code, p) +{ + "use strict"; + eval(code); + return arguments; +} + +assertEq(arraysEqual(strictEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictEval("arguments[0] = 17"), [17]), true); +assertEq(arraysEqual(strictEval("arguments[0] = 17", 42), [17, 42]), true); + +function strictMaybeNestedEval(code, p) +{ + "use strict"; + function inner() { eval(code); } + return arguments; +} + +assertEq(arraysEqual(strictMaybeNestedEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictMaybeNestedEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictMaybeNestedEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictMaybeNestedEval("p = 2", 17), ["p = 2", 17]), true); + +function strictNestedEval(code, p) +{ + "use strict"; + function inner() { eval(code); } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictNestedEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictNestedEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictNestedEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictNestedEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictNestedEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); +assertEq(arraysEqual(strictNestedEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); + +function strictAssignArguments(a) +{ + "use strict"; + arguments[0] = 42; + return a; +} + +assertEq(strictAssignArguments(), undefined); +assertEq(strictAssignArguments(obj), obj); +assertEq(strictAssignArguments(17), 17); + +function strictAssignParameterGetElement(a) +{ + "use strict"; + a = 17; + return arguments[0]; +} + +assertEq(strictAssignParameterGetElement(42), 42); + +function strictAssignArgSub(x, y) +{ + "use strict"; + arguments[0] = 3; + return arguments[0]; +} + +assertEq(strictAssignArgSub(1), 3); + +function strictAssignArgSubParamUse(x, y) +{ + "use strict"; + arguments[0] = 3; + assertEq(x, 1); + return arguments[0]; +} + +assertEq(strictAssignArgSubParamUse(1), 3); + +function strictAssignArgumentsElement(x, y) +{ + "use strict"; + arguments[0] = 3; + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(strictAssignArgumentsElement(1), 3); + +function strictAssignArgumentsElementParamUse(x, y) +{ + "use strict"; + arguments[0] = 3; + assertEq(x, 1); + return arguments[Math.random() ? "0" : 0]; // nix arguments[const] optimizations +} + +assertEq(strictAssignArgumentsElementParamUse(1), 3); + +function strictNestedAssignShadowVar(p) +{ + "use strict"; + function inner() + { + var p = 12; + function innermost() { p = 1776; return 12; } + return innermost(); + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowVar(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowVar(obj), [obj]), true); + +function strictNestedAssignShadowCatch(p) +{ + "use strict"; + function inner() + { + try + { + } + catch (p) + { + var f = function innermost() { p = 1776; return 12; }; + f(); + } + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowCatch(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowCatch(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatch(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatch(obj), [obj]), true); + +function strictNestedAssignShadowCatchCall(p) +{ + "use strict"; + function inner() + { + try + { + } + catch (p) + { + var f = function innermost() { p = 1776; return 12; }; + f(); + } + } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowCatchCall(obj), [obj]), true); + +function strictNestedAssignShadowFunction(p) +{ + "use strict"; + function inner() + { + function p() { } + p = 1776; + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowFunction(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowFunction(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunction(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunction(obj), [obj]), true); + +function strictNestedAssignShadowFunctionCall(p) +{ + "use strict"; + function inner() + { + function p() { } + p = 1776; + } + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionCall(obj), [obj]), true); + +function strictNestedShadowAndMaybeEval(code, p) +{ + "use strict"; + function inner(p) { eval(code); } + return arguments; +} + +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); +assertEq(arraysEqual(strictNestedShadowAndMaybeEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); + +function strictNestedShadowAndEval(code, p) +{ + "use strict"; + function inner(p) { eval(code); } + return arguments; +} + +assertEq(arraysEqual(strictNestedShadowAndEval("1", 2), ["1", 2]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("arguments"), ["arguments"]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("p = 2"), ["p = 2"]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("p = 2", 17), ["p = 2", 17]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("arguments[0] = 17"), ["arguments[0] = 17"]), true); +assertEq(arraysEqual(strictNestedShadowAndEval("arguments[0] = 17", 42), ["arguments[0] = 17", 42]), true); + +function strictEvalContainsMutation(code) +{ + "use strict"; + return eval(code); +} + +assertEq(arraysEqual(strictEvalContainsMutation("code = 17; arguments"), ["code = 17; arguments"]), true); +assertEq(arraysEqual(strictEvalContainsMutation("arguments[0] = 17; arguments"), [17]), true); +assertEq(strictEvalContainsMutation("arguments[0] = 17; code"), "arguments[0] = 17; code"); + +function strictNestedAssignShadowFunctionName(p) +{ + "use strict"; + function inner() + { + function p() { p = 1776; } + p(); + } + inner(); + return arguments; +} + +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(), []), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(99), [99]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(""), [""]), true); +assertEq(arraysEqual(strictNestedAssignShadowFunctionName(obj), [obj]), true); + + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/Function/throw-type-error.js b/js/src/tests/non262/Function/throw-type-error.js new file mode 100644 index 0000000000..68dd6e1d07 --- /dev/null +++ b/js/src/tests/non262/Function/throw-type-error.js @@ -0,0 +1,16 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/publicdomain/zero/1.0/ + +const ThrowTypeError = function(){ + "use strict"; + return Object.getOwnPropertyDescriptor(arguments, "callee").get; +}(); + +assertDeepEq(Object.getOwnPropertyDescriptor(ThrowTypeError, "length"), { + value: 0, writable: false, enumerable: false, configurable: false +}); + +assertEq(Object.isFrozen(ThrowTypeError), true); + +if (typeof reportCompare == "function") + reportCompare(true, true); |