diff options
Diffstat (limited to 'js/src/tests/non262/strict')
52 files changed, 2453 insertions, 0 deletions
diff --git a/js/src/tests/non262/strict/10.4.2.js b/js/src/tests/non262/strict/10.4.2.js new file mode 100644 index 0000000000..b68578d64d --- /dev/null +++ b/js/src/tests/non262/strict/10.4.2.js @@ -0,0 +1,55 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* Direct calls to eval should inherit the strictness of the calling code. */ +assertEq(testLenientAndStrict("eval('010')", + completesNormally, + raisesException(SyntaxError)), + true); + +/* + * Directives in the eval code itself should always override a direct + * caller's strictness. + */ +assertEq(testLenientAndStrict("eval('\"use strict\"; 010')", + raisesException(SyntaxError), + raisesException(SyntaxError)), + true); + +/* Code passed to indirect calls to eval should never be strict. */ +assertEq(testLenientAndStrict("var evil=eval; evil('010')", + completesNormally, + completesNormally), + true); + +/* + * Code passed to the Function constructor never inherits the caller's + * strictness. + */ +assertEq(completesNormally("Function('010')"), + true); +assertEq(raisesException(SyntaxError)("Function('\"use strict\"; 010')"), + true); + +/* + * If 'eval' causes a frame's primitive |this| to become wrapped, the frame should see the same + * wrapper object as the eval code. + */ +var call_this, eval_this; +function f(code) { + /* + * At this point, a primitive |this| has not yet been wrapped. A + * reference to |this| from the eval call should wrap it, and the wrapper + * should be stored where the call frame can see it. + */ + eval(code); + call_this = this; +} +f.call(true, 'eval_this = this'); +assertEq(call_this, eval_this); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/10.4.3.js b/js/src/tests/non262/strict/10.4.3.js new file mode 100644 index 0000000000..b70a6a0d77 --- /dev/null +++ b/js/src/tests/non262/strict/10.4.3.js @@ -0,0 +1,58 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var obj = {} + +function strict() { "use strict"; return this; } +assertEq(strict.call(""), ""); +assertEq(strict.call(true), true); +assertEq(strict.call(42), 42); +assertEq(strict.call(null), null); +assertEq(strict.call(undefined), undefined); +assertEq(strict.call(obj), obj); +assertEq(new strict() instanceof Object, true); + +/* + * The compiler internally converts x['foo'] to x.foo. Writing x[s] where + * s='foo' is enough to throw it off the scent for now. + */ +var strictString = 'strict'; + +Boolean.prototype.strict = strict; +assertEq(true.strict(), true); +assertEq(true[strictString](), true); + +Number.prototype.strict = strict; +assertEq((42).strict(), 42); +assertEq(42[strictString](), 42); + +String.prototype.strict = strict; +assertEq("".strict(), ""); +assertEq(""[strictString](), ""); + +function lenient() { return this; } +assertEq(lenient.call("") instanceof String, true); +assertEq(lenient.call(true) instanceof Boolean, true); +assertEq(lenient.call(42) instanceof Number, true); +assertEq(lenient.call(null), this); +assertEq(lenient.call(undefined), this); +assertEq(lenient.call(obj), obj); +assertEq(new lenient() instanceof Object, true); + +var lenientString = 'lenient'; + +Boolean.prototype.lenient = lenient; +assertEq(true.lenient() instanceof Boolean, true); +assertEq(true[lenientString]() instanceof Boolean, true); + +Number.prototype.lenient = lenient; +assertEq(42[lenientString]() instanceof Number, true); + +String.prototype.lenient = lenient; +assertEq(""[lenientString]() instanceof String, true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/10.6.js b/js/src/tests/non262/strict/10.6.js new file mode 100644 index 0000000000..3001d0ddcd --- /dev/null +++ b/js/src/tests/non262/strict/10.6.js @@ -0,0 +1,55 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function callFunctionBody(expr) { + return ( + '(function f() {\n' + + 'Object.defineProperties(arguments, {1: { writable: false },\n' + + ' 2: { configurable: false },\n' + + ' 3: { writable: false,\n' + + ' configurable: false }});\n' + + 'return (' + expr + ');\n' + + '})(0, 1, 2, 3);'); +} + +assertEq(testLenientAndStrict(callFunctionBody('arguments[0] = 42'), + returns(42), returns(42)), + true); + +assertEq(testLenientAndStrict(callFunctionBody('delete arguments[0]'), + returns(true), returns(true)), + true); + + +assertEq(testLenientAndStrict(callFunctionBody('arguments[1] = 42'), + returns(42), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict(callFunctionBody('delete arguments[1]'), + returns(true), returns(true)), + true); + + +assertEq(testLenientAndStrict(callFunctionBody('arguments[2] = 42'), + returns(42), returns(42)), + true); + +assertEq(testLenientAndStrict(callFunctionBody('delete arguments[2]'), + returns(false), raisesException(TypeError)), + true); + + +assertEq(testLenientAndStrict(callFunctionBody('arguments[3] = 42'), + returns(42), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict(callFunctionBody('delete arguments[3]'), + returns(false), raisesException(TypeError)), + true); + + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.1.5.js b/js/src/tests/non262/strict/11.1.5.js new file mode 100644 index 0000000000..7ba12fa98a --- /dev/null +++ b/js/src/tests/non262/strict/11.1.5.js @@ -0,0 +1,171 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* Simple identifier labels. */ +assertEq(testLenientAndStrict('({x:1, x:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({x:1, y:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({x:1, y:1, x:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +/* Property names can be written as strings, too. */ +assertEq(testLenientAndStrict('({x:1, "x":1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({"x":1, x:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({"x":1, "x":1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +/* Numeric property names. */ +assertEq(testLenientAndStrict('({1.5:1, 1.5:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({1.5:1, 15e-1:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({6.02214179e23:1, 6.02214179e23:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({6.02214179e23:1, 3.1415926535:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({ 1: 1, "1": 2 })', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({ "1": 1, 1: 2 })', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({ 2.5: 1, "2.5": 2 })', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({ "2.5": 1, 2.5: 2 })', + parsesSuccessfully, + parsesSuccessfully), + true); + +/* Many properties, to exercise JSAtomList's hash-table variant. */ +assertEq(testLenientAndStrict('({a:1, b:1, c:1, d:1, e:1, f:1, g:1, h:1, i:1, j:1, k:1, l:1, m:1, n:1, o:1, p:1, q:1, r:1, s:1, t:1, u:1, v:1, w:1, x:1, y:1, z:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({a:1, b:1, c:1, d:1, e:1, f:1, g:1, h:1, i:1, j:1, k:1, l:1, m:1, n:1, o:1, p:1, q:1, r:1, s:1, t:1, u:1, v:1, w:1, x:1, y:1, a:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +/* + * Getters, setters, and value properties should conflict only when + * appropriate. + */ +assertEq(testLenientAndStrict('({get x() {}, x:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({x:1, get x() {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({set x(q) {}, x:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({x:1, set x(q) {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({1:1, set 1(q) {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({set 1(q) {}, 1:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({"1":1, set 1(q) {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({set 1(q) {}, "1":1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({get x() {}, set x(q) {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({set x(q) {}, get x() {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({get x() {}, set x(q) {}, x:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({set x(q) {}, get x() {}, x:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({get x() {}, get x() {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({set x(q) {}, set x(q) {}})', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('({get x() {}, set x(q) {}, y:1})', + parsesSuccessfully, + parsesSuccessfully), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.13.1.js b/js/src/tests/non262/strict/11.13.1.js new file mode 100644 index 0000000000..d3d3e6989d --- /dev/null +++ b/js/src/tests/non262/strict/11.13.1.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * Simple assignment expressions in strict mode code must not be + * assignments to 'eval' or 'arguments'. + */ +assertEq(testLenientAndStrict('arguments=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('eval=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(arguments)=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(eval)=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.13.2.js b/js/src/tests/non262/strict/11.13.2.js new file mode 100644 index 0000000000..678f0b614b --- /dev/null +++ b/js/src/tests/non262/strict/11.13.2.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * Compound assignment expressions in strict mode code must not be + * assignments to 'eval' or 'arguments'. + */ +assertEq(testLenientAndStrict('arguments+=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('eval+=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(arguments)+=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(eval)+=1', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.3.1.js b/js/src/tests/non262/strict/11.3.1.js new file mode 100644 index 0000000000..159f785838 --- /dev/null +++ b/js/src/tests/non262/strict/11.3.1.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * Postfix increment expressions must not have 'eval' or 'arguments' + * as their operands. + */ +assertEq(testLenientAndStrict('arguments++', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('eval++', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(arguments)++', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(eval)++', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.3.2.js b/js/src/tests/non262/strict/11.3.2.js new file mode 100644 index 0000000000..c8225e1297 --- /dev/null +++ b/js/src/tests/non262/strict/11.3.2.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * Postfix decrement expressions must not have 'eval' or 'arguments' + * as their operands. + */ +assertEq(testLenientAndStrict('arguments--', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('eval--', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(arguments)--', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(eval)--', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.4.1.js b/js/src/tests/non262/strict/11.4.1.js new file mode 100644 index 0000000000..1125962a35 --- /dev/null +++ b/js/src/tests/non262/strict/11.4.1.js @@ -0,0 +1,45 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* Deleting an identifier is a syntax error in strict mode code only. */ +assertEq(testLenientAndStrict('delete x;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +/* + * A reference expression surrounded by parens is itself a reference + * expression. + */ +assertEq(testLenientAndStrict('delete (x);', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +/* Deleting other sorts of expressions are not syntax errors in either mode. */ +assertEq(testLenientAndStrict('delete x.y;', + parsesSuccessfully, + parsesSuccessfully), + true); +assertEq(testLenientAndStrict('delete Object();', + returns(true), + returns(true)), + true); + +/* Functions should inherit the surrounding code's strictness. */ +assertEq(testLenientAndStrict('function f() { delete x; }', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +/* Local directives override the surrounding code's strictness. */ +assertEq(testLenientAndStrict('function f() { "use strict"; delete x; }', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.4.4.js b/js/src/tests/non262/strict/11.4.4.js new file mode 100644 index 0000000000..bd22b54f5c --- /dev/null +++ b/js/src/tests/non262/strict/11.4.4.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * Prefix increment expressions must not have 'eval' or 'arguments' as + * their operands. + */ +assertEq(testLenientAndStrict('++arguments', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('++eval', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('++(arguments)', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('++(eval)', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/11.4.5.js b/js/src/tests/non262/strict/11.4.5.js new file mode 100644 index 0000000000..754b8f96ef --- /dev/null +++ b/js/src/tests/non262/strict/11.4.5.js @@ -0,0 +1,29 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * Prefix decrement expressions must not have 'eval' or 'arguments' as + * their operands. + */ +assertEq(testLenientAndStrict('--arguments', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('--eval', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('--(arguments)', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('--(eval)', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/12.10.1.js b/js/src/tests/non262/strict/12.10.1.js new file mode 100644 index 0000000000..f45c77ad28 --- /dev/null +++ b/js/src/tests/non262/strict/12.10.1.js @@ -0,0 +1,30 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * 'with' statements are forbidden in strict top-level code. This is + * eval code, but that's close enough. + */ +assertEq(testLenientAndStrict('with (1) {}', + completesNormally, + raisesException(SyntaxError)), + true); + +/* 'with' statements are forbidden in strict function code. */ +assertEq(testLenientAndStrict('function f() { "use strict"; with (1) {} }', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); + +/* + * A use strict directive in a function mustn't affect the strictness + * of subsequent code. + */ +assertEq(parsesSuccessfully('function f() { "use strict"; }; with (1) {}'), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/12.14.1.js b/js/src/tests/non262/strict/12.14.1.js new file mode 100644 index 0000000000..e7f9b303bd --- /dev/null +++ b/js/src/tests/non262/strict/12.14.1.js @@ -0,0 +1,37 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * In strict mode, the identifier bound by a 'catch' clause may not + * be 'eval' or 'arguments'. + */ +assertEq(testLenientAndStrict('try{}catch(eval){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('try{}catch([eval]){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('try{}catch({x:eval}){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('try{}catch(arguments){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('try{}catch([arguments]){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('try{}catch({x:arguments}){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/12.2.1-01.js b/js/src/tests/non262/strict/12.2.1-01.js new file mode 100644 index 0000000000..674c7a7c60 --- /dev/null +++ b/js/src/tests/non262/strict/12.2.1-01.js @@ -0,0 +1,75 @@ +// |reftest| skip-if(Android) +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * In strict mode code, 'let' and 'const' declarations may not bind + * 'eval' or 'arguments'. + */ +assertEq(testLenientAndStrict('let eval;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('let x,eval;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('let arguments;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('let x,arguments;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('const eval = undefined;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('const x = undefined,eval = undefined;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('const arguments = undefined;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('const x = undefined,arguments = undefined;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +/* + * In strict mode code, 'let' declarations appearing in 'for' + * or 'for in' statements may not bind 'eval' or 'arguments'. + */ +assertEq(testLenientAndStrict('for (let eval in [])break;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('for (let [eval] in [])break;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('for (let {x:eval} in [])break;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('for (let arguments in [])break;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('for (let [arguments] in [])break;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('for (let {x:arguments} in [])break;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/12.2.1.js b/js/src/tests/non262/strict/12.2.1.js new file mode 100644 index 0000000000..ba348cf432 --- /dev/null +++ b/js/src/tests/non262/strict/12.2.1.js @@ -0,0 +1,25 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(testLenientAndStrict('var eval;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('var x,eval;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('var arguments;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('var x,arguments;', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/13.1.js b/js/src/tests/non262/strict/13.1.js new file mode 100644 index 0000000000..137a36d10c --- /dev/null +++ b/js/src/tests/non262/strict/13.1.js @@ -0,0 +1,345 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * In strict mode, it is a syntax error for an identifier to appear + * more than once in a function's argument list. + */ + +/* + * The parameters of ordinary function definitions should not contain + * duplicate identifiers. + */ +assertEq(testLenientAndStrict('function f(x,y) {}', + parsesSuccessfully, + parsesSuccessfully), + true); +assertEq(testLenientAndStrict('function f(x,x) {}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f(x,y,z,y) {}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +/* Exercise the hashed local name map case. */ +assertEq(testLenientAndStrict('function f(a,b,c,d,e,f,g,h,d) {}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +/* + * SpiderMonkey has always treated duplicates in destructuring + * patterns as an error. Strict mode should not affect this. + */ +assertEq(testLenientAndStrict('function f([x,y]) {}', + parsesSuccessfully, + parsesSuccessfully), + true); +assertEq(testLenientAndStrict('function f([x,x]){}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f(x,[x]){}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); + +/* + * Strict rules apply to the parameters if the function's body is + * strict. + */ +assertEq(testLenientAndStrict('function f(x,x) { "use strict" };', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); + +/* + * Calls to the function constructor should not be affected by the + * strictness of the calling code, but should be affected by the + * strictness of the function body. + */ +assertEq(testLenientAndStrict('Function("x","x","")', + completesNormally, + completesNormally), + true); +assertEq(testLenientAndStrict('Function("x","y","")', + completesNormally, + completesNormally), + true); +assertEq(testLenientAndStrict('Function("x","x","\'use strict\'")', + raisesException(SyntaxError), + raisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('Function("x","y","\'use strict\'")', + completesNormally, + completesNormally), + true); + + +/* + * The parameter lists of function expressions should not contain + * duplicate identifiers. + */ +assertEq(testLenientAndStrict('(function (x,x) {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function (x,y) {})', + parsesSuccessfully, + parsesSuccessfully), + true); + +/* + * All permutations of: + * - For the two magic identifiers 'arguments' or 'eval' + * - For function definitions, function expressions, expression closures, + * and getter and setter property definitions, + * - For forms that inherit their context's strictness, and forms that + * include their own strictness directives, + * - For ordinary parameters, array destructuring parameters, and + * object destructuring parameters, + * - the magic identifiers may be used to name such parameters + * in lenient code, but not in strict code + * - the magic identifiers may be used as function names in lenient code, + * but not in strict code + */ +assertEq(testLenientAndStrict('function f(eval){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f([eval]){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f({x:eval}){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function eval(){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f(eval){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f([eval]){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f({x:eval}){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function eval(){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f(eval){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f([eval]){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f({x:eval}){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function eval(){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f(eval){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f([eval]){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f({x:eval}){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function eval(){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f(eval) {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f([eval]) {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f({x:eval}) {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function eval() {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x(eval){}})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x([eval]){}})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x({x:eval}){}})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x(eval){"use strict";}})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x([eval]){"use strict";}})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x({x:eval}){"use strict";}})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f(arguments){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f([arguments]){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f({x:arguments}){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function arguments(){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f(arguments){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f([arguments]){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function f({x:arguments}){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('function arguments(){"use strict";}', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f(arguments){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f([arguments]){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f({x:arguments}){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function arguments(){})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f(arguments){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f([arguments]){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f({x:arguments}){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function arguments(){"use strict";})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f(arguments) {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f([arguments]) {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function f({x:arguments}) {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('(function arguments() {})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x(arguments){}})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x([arguments]){}})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x({x:arguments}){}})', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x(arguments){"use strict";}})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x([arguments]){"use strict";}})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('({set x({x:arguments}){"use strict";}})', + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); + +/* + * Functions produced using the Function constructor may not use + * 'eval' or 'arguments' as a parameter name if their body is strict + * mode code. The strictness of the calling code does not affect the + * constraints applied to the parameters. + */ +assertEq(testLenientAndStrict('Function("eval","")', + completesNormally, + completesNormally), + true); +assertEq(testLenientAndStrict('Function("eval","\'use strict\';")', + raisesException(SyntaxError), + raisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict('Function("arguments","")', + completesNormally, + completesNormally), + true); +assertEq(testLenientAndStrict('Function("arguments","\'use strict\';")', + raisesException(SyntaxError), + raisesException(SyntaxError)), + true); + + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.10.7.js b/js/src/tests/non262/strict/15.10.7.js new file mode 100644 index 0000000000..5f1d4fa9fd --- /dev/null +++ b/js/src/tests/non262/strict/15.10.7.js @@ -0,0 +1,15 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(testLenientAndStrict('var r = /foo/; r.lastIndex = 42; r.lastIndex', + returns(42), returns(42)), + true); +assertEq(testLenientAndStrict('var r = /foo/; delete r.lastIndex', + returns(false), raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.3.4.5.js b/js/src/tests/non262/strict/15.3.4.5.js new file mode 100644 index 0000000000..bc93bb67ae --- /dev/null +++ b/js/src/tests/non262/strict/15.3.4.5.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function strict() { 'use strict'; return this; } +function lenient() { return this; } +var obj = {}; + +assertEq(strict.bind(true)(), true); +assertEq(strict.bind(42)(), 42); +assertEq(strict.bind("")(), ""); +assertEq(strict.bind(null)(), null); +assertEq(strict.bind(undefined)(), undefined); +assertEq(strict.bind(obj)(), obj); + +assertEq(lenient.bind(true)() instanceof Boolean, true); +assertEq(lenient.bind(42)() instanceof Number, true); +assertEq(lenient.bind("")() instanceof String, true); +assertEq(lenient.bind(null)(), this); +assertEq(lenient.bind(undefined)(), this); +assertEq(lenient.bind(obj)(), obj); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.3.5.1.js b/js/src/tests/non262/strict/15.3.5.1.js new file mode 100644 index 0000000000..163928ee41 --- /dev/null +++ b/js/src/tests/non262/strict/15.3.5.1.js @@ -0,0 +1,16 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function fn() { + return function(a, b, c) { }; +} + +assertEq(testLenientAndStrict('var f = fn(); f.length = 1; f.length', + returns(3), raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.3.5.2.js b/js/src/tests/non262/strict/15.3.5.2.js new file mode 100644 index 0000000000..3106a09853 --- /dev/null +++ b/js/src/tests/non262/strict/15.3.5.2.js @@ -0,0 +1,16 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function fn() { + return function(a, b, c) { }; +} + +assertEq(testLenientAndStrict('var f = fn(); delete f.prototype', + returns(false), raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.4.4.11.js b/js/src/tests/non262/strict/15.4.4.11.js new file mode 100644 index 0000000000..a4c38faa7a --- /dev/null +++ b/js/src/tests/non262/strict/15.4.4.11.js @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function arr() { + return Object.defineProperty([20, 10, 30], 0, {writable: false}); +} + +assertEq(testLenientAndStrict('var a = arr(); a.sort()', + raisesException(TypeError), + raisesException(TypeError)), + true); + +function obj() { + var o = {0: 20, 1: 10, 2: 30, length: 3}; + Object.defineProperty(o, 0, {writable: false}); + return o; +} + +assertEq(testLenientAndStrict('var o = obj(); Array.prototype.sort.call(o)', + raisesException(TypeError), + raisesException(TypeError)), + true); + +// The behavior of sort is implementation-defined if the object being +// sorted is sparse, so I'm not sure how to test its behavior on +// non-configurable properties. + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.4.4.12.js b/js/src/tests/non262/strict/15.4.4.12.js new file mode 100644 index 0000000000..5b98c8a717 --- /dev/null +++ b/js/src/tests/non262/strict/15.4.4.12.js @@ -0,0 +1,50 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function arr() { + return Object.defineProperty([1, 2, 3], 0, {writable: false}); +} + +function obj() { + var o = {0: 1, 1: 2, 2: 3, length: 3}; + Object.defineProperty(o, 0, {writable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = arr(); [a.splice(0, 1), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = obj(); [Array.prototype.splice.call(o, 0, 1), o]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +function agap() { + var a = [1, 2, , 4]; + Object.defineProperty(a, 1, {configurable: false}); + return a; +} + +function ogap() { + var o = {0: 1, 1: 2, /* no 2 */ 3: 4, length: 4}; + Object.defineProperty(o, 1, {configurable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = agap(); [a.splice(0, 1), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = ogap(); [Array.prototype.splice.call(o, 0, 1), o]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.4.4.13.js b/js/src/tests/non262/strict/15.4.4.13.js new file mode 100644 index 0000000000..05d757aea7 --- /dev/null +++ b/js/src/tests/non262/strict/15.4.4.13.js @@ -0,0 +1,50 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function arr() { + return Object.defineProperty([1, 2, 3], 0, {writable: false}); +} + +function obj() { + var o = {0: 1, 1: 2, 2: 3, length: 3}; + Object.defineProperty(o, 0, {writable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = arr(); [a.unshift(40, 50), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = obj(); [Array.prototype.unshift.call(o, 40, 50), o]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +function agap() { + var a = [1, 2, , 4]; + Object.defineProperty(a, 3, {configurable: false}); + return a; +} + +function ogap() { + var o = {0: 1, 1: 2, /* no 2 */ 3: 4, length: 4}; + Object.defineProperty(o, 3, {configurable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = agap(); [a.unshift(9), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = ogap(); [Array.prototype.unshift.call(o, 9), o]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.4.4.6.js b/js/src/tests/non262/strict/15.4.4.6.js new file mode 100644 index 0000000000..2625f1ba91 --- /dev/null +++ b/js/src/tests/non262/strict/15.4.4.6.js @@ -0,0 +1,28 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function arr() { + return Object.defineProperty([1, 2, 3], 2, {configurable: false}); +} + +function obj() { + var o = {0: 1, 1: 2, 2: 3, length: 3}; + Object.defineProperty(o, 2, {configurable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = arr(); [a.pop(), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = obj(); [Array.prototype.pop.call(o), o]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.4.4.8.js b/js/src/tests/non262/strict/15.4.4.8.js new file mode 100644 index 0000000000..6768714057 --- /dev/null +++ b/js/src/tests/non262/strict/15.4.4.8.js @@ -0,0 +1,50 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function arr() { + return Object.defineProperty([1, 2, 3], 0, {writable: false}); +} + +function obj() { + var o = {0: 1, 1: 2, 2: 3, length: 3}; + Object.defineProperty(o, 0, {writable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = arr(); a.reverse()', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = obj(); Array.prototype.reverse.call(o)', + raisesException(TypeError), + raisesException(TypeError)), + true); + +function agap() { + var a = [1, 2, , 4]; + Object.defineProperty(a, 1, {configurable: false}); + return a; +} + +function ogap() { + var o = {0: 1, 1: 2, /* no 2 */ 3: 4, length: 4}; + Object.defineProperty(o, 1, {configurable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = agap(); a.reverse()', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = ogap(); Array.prototype.reverse.call(o)', + raisesException(TypeError), + raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.4.4.9.js b/js/src/tests/non262/strict/15.4.4.9.js new file mode 100644 index 0000000000..4d08fe98f9 --- /dev/null +++ b/js/src/tests/non262/strict/15.4.4.9.js @@ -0,0 +1,50 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function arr() { + return Object.defineProperty([10, 20, 30], 0, {writable: false}); +} + +function obj() { + var o = {0: 10, 1: 20, 2: 30, length: 3}; + Object.defineProperty(o, 0, {writable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = arr(); [a.shift(), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = obj(); [Array.prototype.shift.call(o), o]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +function agap() { + var a = [1, 2, , 4]; + Object.defineProperty(a, 1, {configurable: false}); + return a; +} + +function ogap() { + var o = {0: 1, 1: 2, /* no 2 */ 3: 4, length: 4}; + Object.defineProperty(o, 1, {configurable: false}); + return o; +} + +assertEq(testLenientAndStrict('var a = agap(); [a.shift(), a]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = ogap(); [Array.prototype.shift.call(o), o]', + raisesException(TypeError), + raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.4.5.1.js b/js/src/tests/non262/strict/15.4.5.1.js new file mode 100644 index 0000000000..3fb04ebd61 --- /dev/null +++ b/js/src/tests/non262/strict/15.4.5.1.js @@ -0,0 +1,84 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var out = {}; + +function arr() { + return Object.defineProperty([1, 2, 3, 4], 2, {configurable: false}); +} + +function nonStrict1(out) +{ + var a = out.array = arr(); + a.length = 2; +} + +function strict1(out) +{ + "use strict"; + var a = out.array = arr(); + a.length = 2; + return a; +} + +out.array = null; +nonStrict1(out); +assertEq(deepEqual(out.array, [1, 2, 3]), true); + +out.array = null; +try +{ + strict1(out); + throw "no error"; +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "expected TypeError, got " + e); +} +assertEq(deepEqual(out.array, [1, 2, 3]), true); + +// Internally, SpiderMonkey has two representations for arrays: +// fast-but-inflexible, and slow-but-flexible. Adding a non-index property +// to an array turns it into the latter. We should test on both kinds. +function addx(obj) { + obj.x = 5; + return obj; +} + +function nonStrict2(out) +{ + var a = out.array = addx(arr()); + a.length = 2; +} + +function strict2(out) +{ + "use strict"; + var a = out.array = addx(arr()); + a.length = 2; +} + +out.array = null; +nonStrict2(out); +assertEq(deepEqual(out.array, addx([1, 2, 3])), true); + +out.array = null; +try +{ + strict2(out); + throw "no error"; +} +catch (e) +{ + assertEq(e instanceof TypeError, true, "expected TypeError, got " + e); +} +assertEq(deepEqual(out.array, addx([1, 2, 3])), true); + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("Tests complete"); diff --git a/js/src/tests/non262/strict/15.5.5.1.js b/js/src/tests/non262/strict/15.5.5.1.js new file mode 100644 index 0000000000..f07828eb5c --- /dev/null +++ b/js/src/tests/non262/strict/15.5.5.1.js @@ -0,0 +1,26 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function str() { + return new String("foo"); +} + +assertEq(testLenientAndStrict('var s = str(); s.length = 1; s.length', + returns(3), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('var s = str(); delete s.length', + returns(false), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('"foo".length = 1', + returns(1), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('delete "foo".length', + returns(false), raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/15.5.5.2.js b/js/src/tests/non262/strict/15.5.5.2.js new file mode 100644 index 0000000000..fa2c9231f1 --- /dev/null +++ b/js/src/tests/non262/strict/15.5.5.2.js @@ -0,0 +1,15 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(testLenientAndStrict('"foo"[0] = 1', + returns(1), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('delete "foo"[0]', + returns(false), raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/8.12.5.js b/js/src/tests/non262/strict/8.12.5.js new file mode 100644 index 0000000000..c351c19c3f --- /dev/null +++ b/js/src/tests/non262/strict/8.12.5.js @@ -0,0 +1,82 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function obj() { + var o = {all: 1, nowrite: 1, noconfig: 1, noble: 1}; + Object.defineProperty(o, 'nowrite', {writable: false}); + Object.defineProperty(o, 'noconfig', {configurable: false}); + Object.defineProperty(o, 'noble', {writable: false, configurable: false}); + return o; +} + +assertEq(testLenientAndStrict('var o = obj(); o.all = 2; o.all', + returns(2), returns(2)), + true); + +assertEq(testLenientAndStrict('var o = obj(); o.nowrite = 2; o.nowrite', + returns(1), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = obj(); o.noconfig = 2; o.noconfig', + returns(2), returns(2)), + true); + +assertEq(testLenientAndStrict('var o = obj(); o.noble = 2; o.noble', + returns(1), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('obj().nowrite++', + returns(1), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('++obj().nowrite', + returns(2), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('obj().nowrite--', + returns(1), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('--obj().nowrite', + returns(0), raisesException(TypeError)), + true); + + +function arr() { + return Object.defineProperties([1, 1, 1, 1], + { 1: { writable: false }, + 2: { configurable: false }, + 3: { writable: false, configurable: false }}); +} + +assertEq(testLenientAndStrict('var a = arr(); a[0] = 2; a[0]', + returns(2), returns(2)), + true); + +assertEq(testLenientAndStrict('var a = arr(); a[1] = 2; a[1]', + returns(1), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var a = arr(); a[2] = 2; a[2]', + returns(2), returns(2)), + true); + +assertEq(testLenientAndStrict('var a = arr(); a[3] = 2; a[3]', + returns(1), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('arr()[1]++', + returns(1), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('++arr()[1]', + returns(2), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('arr()[1]--', + returns(1), raisesException(TypeError)), + true); +assertEq(testLenientAndStrict('--arr()[1]', + returns(0), raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/8.12.7-2.js b/js/src/tests/non262/strict/8.12.7-2.js new file mode 100644 index 0000000000..2fd4dbae38 --- /dev/null +++ b/js/src/tests/non262/strict/8.12.7-2.js @@ -0,0 +1,21 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +// delete o[p] only performs ToString(p) once, even if there's a strict error. +var hits = 0; +var p = { + toString: function () { + hits++; + return "noconfig"; + } +}; +assertEq(testLenientAndStrict('var o = Object.freeze({noconfig: "ow"}); delete o[p]', + returns(false), raisesException(TypeError)), + true); +assertEq(hits, 2); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/8.12.7.js b/js/src/tests/non262/strict/8.12.7.js new file mode 100644 index 0000000000..518adc799d --- /dev/null +++ b/js/src/tests/non262/strict/8.12.7.js @@ -0,0 +1,32 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +function setup() { + var o = {all: 1, nowrite: 1, noconfig: 1, noble: 1}; + Object.defineProperty(o, 'nowrite', {writable: false}); + Object.defineProperty(o, 'noconfig', {configurable: false}); + Object.defineProperty(o, 'noble', {writable: false, configurable: false}); + return o; +} + +assertEq(testLenientAndStrict('var o = setup(); delete o.all', + returns(true), returns(true)), + true); + +assertEq(testLenientAndStrict('var o = setup(); delete o.nowrite', + returns(true), returns(true)), + true); + +assertEq(testLenientAndStrict('var o = setup(); delete o.noconfig', + returns(false), raisesException(TypeError)), + true); + +assertEq(testLenientAndStrict('var o = setup(); delete o.noble', + returns(false), raisesException(TypeError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/8.7.2-01.js b/js/src/tests/non262/strict/8.7.2-01.js new file mode 100644 index 0000000000..8e1d76106b --- /dev/null +++ b/js/src/tests/non262/strict/8.7.2-01.js @@ -0,0 +1,17 @@ +// |reftest| skip-if(Android) +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* Check that assignment to a let-bound variable is permitted in both lenient and strict modes. */ + +/* Assigning to a let-declared variable is okay in strict and loose modes. */ +assertEq(testLenientAndStrict('let let_declared; let_declared=1', + completesNormally, + completesNormally), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/8.7.2.js b/js/src/tests/non262/strict/8.7.2.js new file mode 100644 index 0000000000..76b474cd71 --- /dev/null +++ b/js/src/tests/non262/strict/8.7.2.js @@ -0,0 +1,56 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* + * These tests depend on the fact that testLenientAndStrict tries the + * strict case first; otherwise, the non-strict evaluation creates the + * variable. Ugh. Ideally, we would use evalcx, but that's not + * available in the browser. + */ + +/* Assigning to an undeclared variable should fail in strict mode. */ +assertEq(testLenientAndStrict('undeclared=1', + completesNormally, + raisesException(ReferenceError)), + true); + +/* + * Assigning to a var-declared variable should be okay in strict and + * lenient modes. + */ +assertEq(testLenientAndStrict('var var_declared; var_declared=1', + completesNormally, + completesNormally), + true); + +/* + * We mustn't report errors until the code is actually run; the variable + * could be created in the mean time. + */ +assertEq(testLenientAndStrict('undeclared_at_compiletime=1', + parsesSuccessfully, + parsesSuccessfully), + true); + +function obj() { + var o = { x: 1, y: 1 }; + Object.defineProperty(o, 'x', { writable: false }); + return o; +} + +/* Put EXPR in a strict mode code context with 'with' bindings in scope. */ +function in_strict_with(expr) { + return "with(obj()) { (function () { 'use strict'; " + expr + " })(); }"; +} + +assertEq(raisesException(TypeError)(in_strict_with('x = 2; y = 2;')), true); +assertEq(raisesException(TypeError)(in_strict_with('x++;')), true); +assertEq(raisesException(TypeError)(in_strict_with('++x;')), true); +assertEq(raisesException(TypeError)(in_strict_with('x--;')), true); +assertEq(raisesException(TypeError)(in_strict_with('--x;')), true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/B.1.1.js b/js/src/tests/non262/strict/B.1.1.js new file mode 100644 index 0000000000..cf36711dce --- /dev/null +++ b/js/src/tests/non262/strict/B.1.1.js @@ -0,0 +1,31 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* Octal integer literal at top level. */ +assertEq(testLenientAndStrict('010', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +/* Octal integer literal in strict function body */ +assertEq(parseRaisesException(SyntaxError) + ('function f() { "use strict"; 010; }'), + true); + + +/* + * Octal integer literal after strict function body (restoration of + * scanner state) + */ +assertEq(parsesSuccessfully('function f() { "use strict"; }; 010'), + true); + +/* Octal integer literal in function body */ +assertEq(parsesSuccessfully('function f() { 010; }'), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/B.1.2.js b/js/src/tests/non262/strict/B.1.2.js new file mode 100644 index 0000000000..b44108fe13 --- /dev/null +++ b/js/src/tests/non262/strict/B.1.2.js @@ -0,0 +1,38 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(testLenientAndStrict('"\\010"', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +assertEq(testLenientAndStrict('"\\00"', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +assertEq(testLenientAndStrict('"\\1"', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +assertEq(testLenientAndStrict('"\\08"', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +assertEq(testLenientAndStrict('"\\0"', + parsesSuccessfully, + parsesSuccessfully), + true); + +assertEq(testLenientAndStrict('"\\0x"', + parsesSuccessfully, + parsesSuccessfully), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/assign-to-callee-name.js b/js/src/tests/non262/strict/assign-to-callee-name.js new file mode 100644 index 0000000000..3c2efba2e2 --- /dev/null +++ b/js/src/tests/non262/strict/assign-to-callee-name.js @@ -0,0 +1,42 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'assign-to-callee-name.js'; +var BUGNUMBER = 610350; +var summary = + "Assigning to a function expression's name within that function should " + + "throw a TypeError in strict mode code"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +var f = function assignSelfStrict() { "use strict"; assignSelfStrict = 12; }; + +try +{ + var r = f(); + throw new Error("should have thrown a TypeError, returned " + r); +} +catch (e) +{ + assertEq(e instanceof TypeError, true, + "didn't throw a TypeError: " + e); +} + +var assignSelf = 42; +var f2 = function assignSelf() { assignSelf = 12; }; + +f2(); // shouldn't throw, does nothing +assertEq(assignSelf, 42); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/strict/browser.js b/js/src/tests/non262/strict/browser.js new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/js/src/tests/non262/strict/browser.js diff --git a/js/src/tests/non262/strict/directive-prologue-01.js b/js/src/tests/non262/strict/directive-prologue-01.js new file mode 100644 index 0000000000..681fa92933 --- /dev/null +++ b/js/src/tests/non262/strict/directive-prologue-01.js @@ -0,0 +1,78 @@ +// Any copyright is dedicated to the Public Domain. +// http://creativecommons.org/licenses/publicdomain/ + +//----------------------------------------------------------------------------- +var BUGNUMBER = 601262; +var summary = + "A string literal containing an octal escape before a strict mode " + + "directive should be a syntax error"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +try +{ + eval(" '\\145'; 'use strict'; "); + throw new Error("no error thrown for eval"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, + "wrong error for octal-escape before strict directive in eval"); +} + +try +{ + Function(" '\\145'; 'use strict'; "); + throw new Error("no error thrown for Function"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, + "wrong error for octal-escape before strict directive in Function"); +} + +try +{ + eval(" function f(){ '\\145'; 'use strict'; } "); + throw new Error("no error thrown for eval of function"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, + "wrong error for octal-escape before strict directive in eval of " + + "function"); +} + +try +{ + Function(" function f(){ '\\145'; 'use strict'; } "); + throw new Error("no error thrown for eval of function"); +} +catch (e) +{ + assertEq(e instanceof SyntaxError, true, + "wrong error for octal-escape before strict directive in eval of " + + "function"); +} + +eval("function notAnError1() { 5; '\\145'; function g() { 'use strict'; } }"); + +Function("function notAnError2() { 5; '\\145'; function g() { 'use strict'; } }"); + +function notAnError3() +{ + 5; + "\145"; + function g() { "use strict"; } +} + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/strict/eval-variable-environment.js b/js/src/tests/non262/strict/eval-variable-environment.js new file mode 100644 index 0000000000..a10f43f431 --- /dev/null +++ b/js/src/tests/non262/strict/eval-variable-environment.js @@ -0,0 +1,67 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var code; + +code = + "eval('var x = 2; typeof x');"; +assertEq(testLenientAndStrict(code, returns("number"), returns("number")), + true); + +code = + "eval('\"use strict\"; var x = 2; typeof x');"; +assertEq(testLenientAndStrict(code, returns("number"), returns("number")), + true); + +code = + "eval('var x = 2;'); " + + "typeof x"; +assertEq(testLenientAndStrict(code, returns("number"), returns("undefined")), + true); + +code = + "eval('\"use strict\"; var x = 2;'); " + + "typeof x"; +assertEq(testLenientAndStrict(code, returns("undefined"), returns("undefined")), + true); + +code = + "eval('\"use strict\"; var x = 2; typeof x'); " + + "typeof x"; +assertEq(testLenientAndStrict(code, returns("undefined"), returns("undefined")), + true); + +code = + "function test() " + + "{ " + + " eval('var x = 2;'); " + + " return typeof x; " + + "} " + + "test();"; +assertEq(testLenientAndStrict(code, returns("number"), returns("undefined")), + true); + +code = + "function test() " + + "{ " + + " 'use strict'; " + + " eval('var x = 2;'); " + + " return typeof x; " + + "} " + + "test();"; +assertEq(testLenientAndStrict(code, returns("undefined"), returns("undefined")), + true); + +code = + "function test() " + + "{ " + + " eval('\"use strict\"; var x = 2;'); " + + " return typeof x; " + + "} " + + "test();"; +assertEq(testLenientAndStrict(code, returns("undefined"), returns("undefined")), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/primitive-assignment.js b/js/src/tests/non262/strict/primitive-assignment.js new file mode 100644 index 0000000000..4b2ee79f0e --- /dev/null +++ b/js/src/tests/non262/strict/primitive-assignment.js @@ -0,0 +1,23 @@ +let primitives = [ + 10, + false, + "test", + Symbol() +]; + +let key = "key"; + +for (let value of primitives) { + // Doesn't throw outside strict mode. + assertEq(value.x = 5, 5); + assertEq(value[key] = 6, 6); + + assertThrowsInstanceOf(function() { "use strict"; value.x = 5; }, TypeError); + assertThrowsInstanceOf(function() { "use strict"; value[key] = 6; }, TypeError); + + let target = {}; + assertEq(Reflect.set(target, key, 5, value), false); + assertEq(key in target, false); +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/primitive-this-getter.js b/js/src/tests/non262/strict/primitive-this-getter.js new file mode 100644 index 0000000000..55fd79d9df --- /dev/null +++ b/js/src/tests/non262/strict/primitive-this-getter.js @@ -0,0 +1,56 @@ +let primitives = [ + 10, + false, + "test", + Symbol() +] + +let getter = "getter"; +let getter2 = "getter2"; +let key = "key"; + +for (let value of primitives) { + let prototype = Object.getPrototypeOf(value); + + // Strict getters receive a primitive this value. + Object.defineProperty(prototype, "getter", {get: function() { + "use strict"; + assertEq(this, value); + return "getter"; + }}) + + assertEq(value.getter, "getter"); + assertEq(value[getter], "getter"); + + // The proxy's [[Get]] trap is also invoked with primitive receiver values. + let proxy = new Proxy({}, { + get(target, property, receiver) { + assertEq(property, "key"); + assertEq(receiver, value); + return "get"; + } + }); + + Object.setPrototypeOf(prototype, proxy); + assertEq(value.key, "get"); + assertEq(value[key], "get"); + assertEq(value.getter, "getter"); + assertEq(value[getter], "getter"); + + // A getter still gets a primitive this value even after going through a proxy. + proxy = new Proxy({ + get getter2() { + "use strict"; + assertEq(this, value); + return "getter2"; + } + }, {}); + + Object.setPrototypeOf(prototype, proxy); + assertEq(value.getter2, "getter2"); + assertEq(value[getter2], "getter2"); + assertEq(value.getter, "getter"); + assertEq(value[getter], "getter"); +} + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/primitive-this-no-writeback.js b/js/src/tests/non262/strict/primitive-this-no-writeback.js new file mode 100644 index 0000000000..2f58fb2316 --- /dev/null +++ b/js/src/tests/non262/strict/primitive-this-no-writeback.js @@ -0,0 +1,20 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* Verify that GETTHISPROP does not update the frame's |this| slot. */ + +var f = String.prototype.m = function () { + "use strict"; + assertEq(this, "s"); + // The GETTHISPROP should not cause |this| to become wrapped. + return [this.m, this]; +}; +var a = "s".m(); +assertEq(a[0], f); +assertEq(a[1], "s"); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/rebind-eval-should-fail-in-strict-mode.js b/js/src/tests/non262/strict/rebind-eval-should-fail-in-strict-mode.js new file mode 100644 index 0000000000..41f0076273 --- /dev/null +++ b/js/src/tests/non262/strict/rebind-eval-should-fail-in-strict-mode.js @@ -0,0 +1,39 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var BadSyntaxStrings = [ + "function foo1() { \"use strict\"; try {} catch (eval) {} }", + "function foo2() { \"use strict\"; let eval = 9; foo(); }", + "function foo3() { \"use strict\"; for (let eval = 3;;) { foo(); }}", + "function foo4() { \"use strict\"; for (let eval in {a:1}) { foo(); }}", + "function foo5() { \"use strict\"; for (let eval of [1, 2, 3]) { foo(); }}", + "function foo6() { \"use strict\"; var eval = 12; }", + "function foo7() { \"use strict\"; for (var eval = 3;;) { foo(); }}", + "function foo8() { \"use strict\"; for (var eval in {a:1}) { foo(); }}", + "function foo9() { \"use strict\"; for (var eval of [1, 2, 3]) { foo(); }}", + "function foo10() { \"use strict\"; const eval = 12; }", + "function foo11() { \"use strict\"; for (const eval = 3;;) { foo(); }}", + "function foo12() { \"use strict\"; return [eval for (eval of [1, 2, 3])]; }", + "function foo13() { \"use strict\"; return [eval for (eval in {a:3})]; }", + "function foo14() { \"use strict\"; return (eval for (eval of [1, 2, 3])); }", + "function foo15() { \"use strict\"; return (eval for (eval in {a:3})); }" +]; + +function testString(s, i) { + var gotSyntaxError = -1; + try { + eval(s); + } catch(err) { + if (err instanceof SyntaxError) + gotSyntaxError = i; + } + + assertEq(gotSyntaxError, i); +} + +for (var i = 0; i < BadSyntaxStrings.length; i++) + testString(BadSyntaxStrings[i], i); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/regress-532041.js b/js/src/tests/non262/strict/regress-532041.js new file mode 100644 index 0000000000..82311f3b9c --- /dev/null +++ b/js/src/tests/non262/strict/regress-532041.js @@ -0,0 +1,17 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + + +/* + * JSFunction::findDuplicateFormal (nee js_FindDuplicateFormal), used + * by strict checks, sometimes failed to choose the correct branch of + * the fun->u.i.names union: it used the argument count, not the + * overall name count. + */ +function f(a1,a2,a3,a4,a5) { "use strict"; var v1, v2, v3, v4, v5, v6, v7; } + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/regress-532254.js b/js/src/tests/non262/strict/regress-532254.js new file mode 100644 index 0000000000..d45dbba6f5 --- /dev/null +++ b/js/src/tests/non262/strict/regress-532254.js @@ -0,0 +1,13 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +assertEq(testLenientAndStrict('function f(eval,[x]){}', + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/regress-599159.js b/js/src/tests/non262/strict/regress-599159.js new file mode 100644 index 0000000000..71a413e2d9 --- /dev/null +++ b/js/src/tests/non262/strict/regress-599159.js @@ -0,0 +1,33 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +// Shu's test +function test(makeNonArray) { + function C() {} + C.prototype = [] + if (makeNonArray) + C.prototype.constructor = C + c = new C(); + c.push("foo"); + return c.length +} +assertEq(test(true), 1); +assertEq(test(false), 1); + +// jorendorff's longer test +var a = []; +a.slowify = 1; +var b = Object.create(a); +b.length = 12; +assertEq(b.length, 12); + +// jorendorff's shorter test +var b = Object.create(Array.prototype); +b.length = 12; +assertEq(b.length, 12); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/shell.js b/js/src/tests/non262/strict/shell.js new file mode 100644 index 0000000000..9d8c8695ee --- /dev/null +++ b/js/src/tests/non262/strict/shell.js @@ -0,0 +1,65 @@ +/* -*- 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/. */ + +(function(global) { + + /* + * Return true if both of these return true: + * - LENIENT_PRED applied to CODE + * - STRICT_PRED applied to CODE with a use strict directive added to the front + * + * Run STRICT_PRED first, for testing code that affects the global environment + * in loose mode, but fails in strict mode. + */ + global.testLenientAndStrict = function testLenientAndStrict(code, lenient_pred, strict_pred) { + return (strict_pred("'use strict'; " + code) && + lenient_pred(code)); + } + + /* + * parsesSuccessfully(CODE) returns true if CODE parses as function + * code without an error. + */ + global.parsesSuccessfully = function parsesSuccessfully(code) { + try { + Function(code); + return true; + } catch (exception) { + return false; + } + }; + + /* + * parseRaisesException(EXCEPTION)(CODE) returns true if parsing CODE + * as function code raises EXCEPTION. + */ + global.parseRaisesException = function parseRaisesException(exception) { + return function (code) { + try { + Function(code); + return false; + } catch (actual) { + return exception.prototype.isPrototypeOf(actual); + } + }; + }; + + /* + * returns(VALUE)(CODE) returns true if evaluating CODE (as eval code) + * completes normally (rather than throwing an exception), yielding a value + * strictly equal to VALUE. + */ + global.returns = function returns(value) { + return function(code) { + try { + return eval(code) === value; + } catch (exception) { + return false; + } + } + } + +})(this); diff --git a/js/src/tests/non262/strict/strict-function-statements.js b/js/src/tests/non262/strict/strict-function-statements.js new file mode 100644 index 0000000000..e6dc151394 --- /dev/null +++ b/js/src/tests/non262/strict/strict-function-statements.js @@ -0,0 +1,94 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +// Ordinary function definitions should be unaffected. +assertEq(testLenientAndStrict("function f() { }", + parsesSuccessfully, + parsesSuccessfully), + true); + +// Lambdas are always permitted within blocks. +assertEq(testLenientAndStrict("{ (function f() { }) }", + parsesSuccessfully, + parsesSuccessfully), + true); + +// Function statements within unbraced blocks are forbidden in strict mode code. +// They are allowed only under if statements in sloppy mode. +assertEq(testLenientAndStrict("if (true) function f() { }", + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict("while (true) function f() { }", + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict("do function f() { } while (true);", + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict("for(;;) function f() { }", + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict("for(x in []) function f() { }", + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict("with(o) function f() { }", + parseRaisesException(SyntaxError), + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict("switch(1) { case 1: function f() { } }", + parsesSuccessfully, + parsesSuccessfully), + true); +assertEq(testLenientAndStrict("x: function f() { }", + parsesSuccessfully, + parseRaisesException(SyntaxError)), + true); +assertEq(testLenientAndStrict("try { function f() { } } catch (x) { }", + parsesSuccessfully, + parsesSuccessfully), + true); + +// Lambdas are always permitted within any sort of statement. +assertEq(testLenientAndStrict("if (true) (function f() { })", + parsesSuccessfully, + parsesSuccessfully), + true); + +// Function statements are permitted in blocks within lenient functions. +assertEq(parsesSuccessfully("function f() { function g() { } }"), + true); + +// Function statements are permitted in if statement within lenient functions. +assertEq(parsesSuccessfully("function f() { if (true) function g() { } }"), + true); + +assertEq(parseRaisesException(SyntaxError) + ("function f() { 'use strict'; if (true) function g() { } }"), + true); + +assertEq(parsesSuccessfully("function f() { 'use strict'; { function g() { } } }"), + true); + +assertEq(parsesSuccessfully("function f() { 'use strict'; if (true) (function g() { }) }"), + true); + +assertEq(parsesSuccessfully("function f() { 'use strict'; { (function g() { }) } }"), + true); + +// Eval should behave the same way. (The parse-only tests use the Function constructor.) +assertEq(testLenientAndStrict("function f() { }", + completesNormally, + completesNormally), + true); +assertEq(testLenientAndStrict("{ function f() { } }", + completesNormally, + completesNormally), + true); + +reportCompare(true, true); diff --git a/js/src/tests/non262/strict/strict-this-is-not-truthy.js b/js/src/tests/non262/strict/strict-this-is-not-truthy.js new file mode 100644 index 0000000000..ec1a86837a --- /dev/null +++ b/js/src/tests/non262/strict/strict-this-is-not-truthy.js @@ -0,0 +1,12 @@ +// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+
+// See bug 630543.
+
+function f() {
+ "use strict";
+ return !this;
+}
+assertEq(f.call(null), true);
+
+reportCompare(0, 0, 'ok');
diff --git a/js/src/tests/non262/strict/this-for-function-expression-recursion.js b/js/src/tests/non262/strict/this-for-function-expression-recursion.js new file mode 100644 index 0000000000..197b4646cf --- /dev/null +++ b/js/src/tests/non262/strict/this-for-function-expression-recursion.js @@ -0,0 +1,44 @@ +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +var gTestfile = 'this-for-function-expression-recursion.js'; +var BUGNUMBER = 611276; +var summary = "JSOP_CALLEE should push undefined, not null, for this"; + +print(BUGNUMBER + ": " + summary); + +/************** + * BEGIN TEST * + **************/ + +// Calling a named function expression (not function statement) uses the +// JSOP_CALLEE opcode. This opcode pushes its own |this|, distinct from the +// normal call path; verify that that |this| value is properly |undefined|. + +var calleeThisFun = + function calleeThisFun(recurring) + { + if (recurring) + return this; + return calleeThisFun(true); + }; +assertEq(calleeThisFun(false), this); + +var calleeThisStrictFun = + function calleeThisStrictFun(recurring) + { + "use strict"; + if (recurring) + return this; + return calleeThisStrictFun(true); + }; +assertEq(calleeThisStrictFun(false), undefined); + +/******************************************************************************/ + +if (typeof reportCompare === "function") + reportCompare(true, true); + +print("All tests passed!"); diff --git a/js/src/tests/non262/strict/unbrand-this.js b/js/src/tests/non262/strict/unbrand-this.js new file mode 100644 index 0000000000..219d1588e1 --- /dev/null +++ b/js/src/tests/non262/strict/unbrand-this.js @@ -0,0 +1,45 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ + +/* + * Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/licenses/publicdomain/ + */ + +/* Test JSOP_UNBRANDTHIS's behavior on object and non-object |this| values. */ + +function strict() { + "use strict"; + this.insert = function(){ bar(); }; + function bar() {} +} + +var exception; + +// Try 'undefined' as a |this| value. +exception = null; +try { + strict.call(undefined); +} catch (x) { + exception = x; +} +assertEq(exception instanceof TypeError, true); + +// Try 'null' as a |this| value. +exception = null; +try { + strict.call(null); +} catch (x) { + exception = x; +} +assertEq(exception instanceof TypeError, true); + +// An object as a |this| value should be fine. +exception = null; +try { + strict.call({}); +} catch (x) { + exception = x; +} +assertEq(exception, null); + +reportCompare(true, true); |