summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/strict
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /js/src/tests/non262/strict
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/tests/non262/strict')
-rw-r--r--js/src/tests/non262/strict/10.4.2.js55
-rw-r--r--js/src/tests/non262/strict/10.4.3.js58
-rw-r--r--js/src/tests/non262/strict/10.6.js55
-rw-r--r--js/src/tests/non262/strict/11.1.5.js171
-rw-r--r--js/src/tests/non262/strict/11.13.1.js29
-rw-r--r--js/src/tests/non262/strict/11.13.2.js29
-rw-r--r--js/src/tests/non262/strict/11.3.1.js29
-rw-r--r--js/src/tests/non262/strict/11.3.2.js29
-rw-r--r--js/src/tests/non262/strict/11.4.1.js45
-rw-r--r--js/src/tests/non262/strict/11.4.4.js29
-rw-r--r--js/src/tests/non262/strict/11.4.5.js29
-rw-r--r--js/src/tests/non262/strict/12.10.1.js30
-rw-r--r--js/src/tests/non262/strict/12.14.1.js37
-rw-r--r--js/src/tests/non262/strict/12.2.1-01.js75
-rw-r--r--js/src/tests/non262/strict/12.2.1.js25
-rw-r--r--js/src/tests/non262/strict/13.1.js345
-rw-r--r--js/src/tests/non262/strict/15.10.7.js15
-rw-r--r--js/src/tests/non262/strict/15.3.4.5.js26
-rw-r--r--js/src/tests/non262/strict/15.3.5.1.js16
-rw-r--r--js/src/tests/non262/strict/15.3.5.2.js16
-rw-r--r--js/src/tests/non262/strict/15.4.4.11.js32
-rw-r--r--js/src/tests/non262/strict/15.4.4.12.js50
-rw-r--r--js/src/tests/non262/strict/15.4.4.13.js50
-rw-r--r--js/src/tests/non262/strict/15.4.4.6.js28
-rw-r--r--js/src/tests/non262/strict/15.4.4.8.js50
-rw-r--r--js/src/tests/non262/strict/15.4.4.9.js50
-rw-r--r--js/src/tests/non262/strict/15.4.5.1.js84
-rw-r--r--js/src/tests/non262/strict/15.5.5.1.js26
-rw-r--r--js/src/tests/non262/strict/15.5.5.2.js15
-rw-r--r--js/src/tests/non262/strict/8.12.5.js82
-rw-r--r--js/src/tests/non262/strict/8.12.7-2.js21
-rw-r--r--js/src/tests/non262/strict/8.12.7.js32
-rw-r--r--js/src/tests/non262/strict/8.7.2-01.js17
-rw-r--r--js/src/tests/non262/strict/8.7.2.js56
-rw-r--r--js/src/tests/non262/strict/B.1.1.js31
-rw-r--r--js/src/tests/non262/strict/B.1.2.js38
-rw-r--r--js/src/tests/non262/strict/assign-to-callee-name.js42
-rw-r--r--js/src/tests/non262/strict/browser.js0
-rw-r--r--js/src/tests/non262/strict/directive-prologue-01.js78
-rw-r--r--js/src/tests/non262/strict/eval-variable-environment.js67
-rw-r--r--js/src/tests/non262/strict/primitive-assignment.js23
-rw-r--r--js/src/tests/non262/strict/primitive-this-getter.js56
-rw-r--r--js/src/tests/non262/strict/primitive-this-no-writeback.js20
-rw-r--r--js/src/tests/non262/strict/rebind-eval-should-fail-in-strict-mode.js39
-rw-r--r--js/src/tests/non262/strict/regress-532041.js17
-rw-r--r--js/src/tests/non262/strict/regress-532254.js13
-rw-r--r--js/src/tests/non262/strict/regress-599159.js33
-rw-r--r--js/src/tests/non262/strict/shell.js65
-rw-r--r--js/src/tests/non262/strict/strict-function-statements.js94
-rw-r--r--js/src/tests/non262/strict/strict-this-is-not-truthy.js12
-rw-r--r--js/src/tests/non262/strict/this-for-function-expression-recursion.js44
-rw-r--r--js/src/tests/non262/strict/unbrand-this.js45
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);