1// Copyright 2011 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6//     * Redistributions of source code must retain the above copyright
7//       notice, this list of conditions and the following disclaimer.
8//     * Redistributions in binary form must reproduce the above
9//       copyright notice, this list of conditions and the following
10//       disclaimer in the documentation and/or other materials provided
11//       with the distribution.
12//     * Neither the name of Google Inc. nor the names of its
13//       contributors may be used to endorse or promote products derived
14//       from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28function CheckStrictMode(code, exception) {
29  assertDoesNotThrow(code);
30  assertThrows("'use strict';\n" + code, exception);
31  assertThrows('"use strict";\n' + code, exception);
32  assertDoesNotThrow("\
33    function outer() {\
34      function inner() {\n"
35        + code +
36      "\n}\
37    }");
38  assertThrows("\
39    function outer() {\
40      'use strict';\
41      function inner() {\n"
42        + code +
43      "\n}\
44    }", exception);
45}
46
47function CheckFunctionConstructorStrictMode() {
48  var args = [];
49  for (var i = 0; i < arguments.length; i ++) {
50    args[i] = arguments[i];
51  }
52  // Create non-strict function. No exception.
53  args[arguments.length] = "";
54  assertDoesNotThrow(function() {
55    Function.apply(this, args);
56  });
57  // Create strict mode function. Exception expected.
58  args[arguments.length] = "'use strict';";
59  assertThrows(function() {
60    Function.apply(this, args);
61  }, SyntaxError);
62}
63
64// Incorrect 'use strict' directive.
65(function UseStrictEscape() {
66  "use\\x20strict";
67  with ({}) {};
68})();
69
70// Incorrectly place 'use strict' directive.
71assertThrows("function foo (x) 'use strict'; {}", SyntaxError);
72
73// 'use strict' in non-directive position.
74(function UseStrictNonDirective() {
75  void(0);
76  "use strict";
77  with ({}) {};
78})();
79
80// Multiple directives, including "use strict".
81assertThrows('\
82"directive 1";\
83"another directive";\
84"use strict";\
85"directive after strict";\
86"and one more";\
87with({}) {}', SyntaxError);
88
89// 'with' disallowed in strict mode.
90CheckStrictMode("with({}) {}", SyntaxError);
91
92// Function named 'eval'.
93CheckStrictMode("function eval() {}", SyntaxError);
94
95// Function named 'arguments'.
96CheckStrictMode("function arguments() {}", SyntaxError);
97
98// Function parameter named 'eval'.
99CheckStrictMode("function foo(a, b, eval, c, d) {}", SyntaxError);
100
101// Function parameter named 'arguments'.
102CheckStrictMode("function foo(a, b, arguments, c, d) {}", SyntaxError);
103
104// Property accessor parameter named 'eval'.
105CheckStrictMode("var o = { set foo(eval) {} }", SyntaxError);
106
107// Property accessor parameter named 'arguments'.
108CheckStrictMode("var o = { set foo(arguments) {} }", SyntaxError);
109
110// Duplicate function parameter name.
111CheckStrictMode("function foo(a, b, c, d, b) {}", SyntaxError);
112
113// Function constructor: eval parameter name.
114CheckFunctionConstructorStrictMode("eval");
115
116// Function constructor: arguments parameter name.
117CheckFunctionConstructorStrictMode("arguments");
118
119// Function constructor: duplicate parameter name.
120CheckFunctionConstructorStrictMode("a", "b", "c", "b");
121CheckFunctionConstructorStrictMode("a,b,c,b");
122
123// catch(eval)
124CheckStrictMode("try{}catch(eval){};", SyntaxError);
125
126// catch(arguments)
127CheckStrictMode("try{}catch(arguments){};", SyntaxError);
128
129// var eval
130CheckStrictMode("var eval;", SyntaxError);
131
132// var arguments
133CheckStrictMode("var arguments;", SyntaxError);
134
135// Strict mode applies to the function in which the directive is used..
136assertThrows('\
137function foo(eval) {\
138  "use strict";\
139}', SyntaxError);
140
141// Strict mode doesn't affect the outer stop of strict code.
142(function NotStrict(eval) {
143  function Strict() {
144    "use strict";
145  }
146  with ({}) {};
147})();
148
149// Octal literal
150CheckStrictMode("var x = 012");
151CheckStrictMode("012");
152CheckStrictMode("'Hello octal\\032'");
153CheckStrictMode("function octal() { return 012; }");
154CheckStrictMode("function octal() { return '\\032'; }");
155
156(function ValidEscape() {
157  "use strict";
158  var x = '\0';
159  var y = "\0";
160})();
161
162// Octal before "use strict"
163assertThrows('\
164  function strict() {\
165    "octal\\032directive";\
166    "use strict";\
167  }', SyntaxError);
168
169(function StrictModeNonDuplicate() {
170  "use strict";
171  var x = { 123 : 1, "0123" : 2 };
172  var x = {
173    123: 1,
174    '123.00000000000000000000000000000000000000000000000000000000000000000001':
175      2
176  };
177})();
178
179// Duplicate data properties are allowed in ES6
180(function StrictModeDuplicateES6() {
181  'use strict';
182  var x = {
183    123: 1,
184    123.00000000000000000000000000000000000000000000000000000000000000000001: 2
185  };
186  var x = { dupe : 1, nondupe: 3, dupe : 2 };
187  var x = { '1234' : 1, '2345' : 2, '1234' : 3 };
188  var x = { '1234' : 1, '2345' : 2, 1234 : 3 };
189  var x = { 3.14 : 1, 2.71 : 2, 3.14 : 3 };
190  var x = { 3.14 : 1, '3.14' : 2 };
191
192  var x = { get foo() { }, get foo() { } };
193  var x = { get foo(){}, get 'foo'(){}};
194  var x = { get 12(){}, get '12'(){}};
195
196  // Two setters
197  var x = { set foo(v) { }, set foo(v) { } };
198  var x = { set foo(v) { }, set 'foo'(v) { } };
199  var x = { set 13(v) { }, set '13'(v) { } };
200
201  // Setter and data
202  var x = { foo: 'data', set foo(v) { } };
203  var x = { set foo(v) { }, foo: 'data' };
204  var x = { foo: 'data', set 'foo'(v) { } };
205  var x = { set foo(v) { }, 'foo': 'data' };
206  var x = { 'foo': 'data', set foo(v) { } };
207  var x = { set 'foo'(v) { }, foo: 'data' };
208  var x = { 'foo': 'data', set 'foo'(v) { } };
209  var x = { set 'foo'(v) { }, 'foo': 'data' };
210  var x = { 12: 1, set '12'(v){}};
211  var x = { 12: 1, set 12(v){}};
212  var x = { '12': 1, set '12'(v){}};
213  var x = { '12': 1, set 12(v){}};
214
215  // Getter and data
216  var x = { foo: 'data', get foo() { } };
217  var x = { get foo() { }, foo: 'data' };
218  var x = { 'foo': 'data', get foo() { } };
219  var x = { get 'foo'() { }, 'foo': 'data' };
220  var x = { '12': 1, get '12'(){}};
221  var x = { '12': 1, get 12(){}};
222})();
223
224// Assignment to eval or arguments
225CheckStrictMode("function strict() { eval = undefined; }", SyntaxError);
226CheckStrictMode("function strict() { arguments = undefined; }", SyntaxError);
227CheckStrictMode("function strict() { print(eval = undefined); }", SyntaxError);
228CheckStrictMode("function strict() { print(arguments = undefined); }",
229                SyntaxError);
230CheckStrictMode("function strict() { var x = eval = undefined; }", SyntaxError);
231CheckStrictMode("function strict() { var x = arguments = undefined; }",
232                SyntaxError);
233
234// Compound assignment to eval or arguments
235CheckStrictMode("function strict() { eval *= undefined; }", SyntaxError);
236CheckStrictMode("function strict() { arguments /= undefined; }", SyntaxError);
237CheckStrictMode("function strict() { print(eval %= undefined); }", SyntaxError);
238CheckStrictMode("function strict() { print(arguments %= undefined); }",
239                SyntaxError);
240CheckStrictMode("function strict() { var x = eval += undefined; }",
241                SyntaxError);
242CheckStrictMode("function strict() { var x = arguments -= undefined; }",
243                SyntaxError);
244CheckStrictMode("function strict() { eval <<= undefined; }", SyntaxError);
245CheckStrictMode("function strict() { arguments >>= undefined; }", SyntaxError);
246CheckStrictMode("function strict() { print(eval >>>= undefined); }",
247                SyntaxError);
248CheckStrictMode("function strict() { print(arguments &= undefined); }",
249                SyntaxError);
250CheckStrictMode("function strict() { var x = eval ^= undefined; }",
251                SyntaxError);
252CheckStrictMode("function strict() { var x = arguments |= undefined; }",
253                SyntaxError);
254
255// Postfix increment with eval or arguments
256CheckStrictMode("function strict() { eval++; }", SyntaxError);
257CheckStrictMode("function strict() { arguments++; }", SyntaxError);
258CheckStrictMode("function strict() { print(eval++); }", SyntaxError);
259CheckStrictMode("function strict() { print(arguments++); }", SyntaxError);
260CheckStrictMode("function strict() { var x = eval++; }", SyntaxError);
261CheckStrictMode("function strict() { var x = arguments++; }", SyntaxError);
262
263// Postfix decrement with eval or arguments
264CheckStrictMode("function strict() { eval--; }", SyntaxError);
265CheckStrictMode("function strict() { arguments--; }", SyntaxError);
266CheckStrictMode("function strict() { print(eval--); }", SyntaxError);
267CheckStrictMode("function strict() { print(arguments--); }", SyntaxError);
268CheckStrictMode("function strict() { var x = eval--; }", SyntaxError);
269CheckStrictMode("function strict() { var x = arguments--; }", SyntaxError);
270
271// Prefix increment with eval or arguments
272CheckStrictMode("function strict() { ++eval; }", SyntaxError);
273CheckStrictMode("function strict() { ++arguments; }", SyntaxError);
274CheckStrictMode("function strict() { print(++eval); }", SyntaxError);
275CheckStrictMode("function strict() { print(++arguments); }", SyntaxError);
276CheckStrictMode("function strict() { var x = ++eval; }", SyntaxError);
277CheckStrictMode("function strict() { var x = ++arguments; }", SyntaxError);
278
279// Prefix decrement with eval or arguments
280CheckStrictMode("function strict() { --eval; }", SyntaxError);
281CheckStrictMode("function strict() { --arguments; }", SyntaxError);
282CheckStrictMode("function strict() { print(--eval); }", SyntaxError);
283CheckStrictMode("function strict() { print(--arguments); }", SyntaxError);
284CheckStrictMode("function strict() { var x = --eval; }", SyntaxError);
285CheckStrictMode("function strict() { var x = --arguments; }", SyntaxError);
286
287// Delete of an unqualified identifier
288CheckStrictMode("delete unqualified;", SyntaxError);
289CheckStrictMode("function strict() { delete unqualified; }", SyntaxError);
290CheckStrictMode("function function_name() { delete function_name; }",
291                SyntaxError);
292CheckStrictMode("function strict(parameter) { delete parameter; }",
293                SyntaxError);
294CheckStrictMode("function strict() { var variable; delete variable; }",
295                SyntaxError);
296CheckStrictMode("var variable; delete variable;", SyntaxError);
297
298(function TestStrictDelete() {
299  "use strict";
300  // "delete this" is allowed in strict mode and should work.
301  function strict_delete() { delete this; }
302  strict_delete();
303})();
304
305// Prefix unary operators other than delete, ++, -- are valid in strict mode
306(function StrictModeUnaryOperators() {
307  "use strict";
308  var x = [void eval, typeof eval, +eval, -eval, ~eval, !eval];
309  var y = [void arguments, typeof arguments,
310           +arguments, -arguments, ~arguments, !arguments];
311})();
312
313// 7.6.1.2 Future Reserved Words in strict mode
314var future_strict_reserved_words = [
315  "implements",
316  "interface",
317  "let",
318  "package",
319  "private",
320  "protected",
321  "public",
322  "static",
323  "yield" ];
324
325function testFutureStrictReservedWord(word) {
326  // Simple use of each reserved word
327  CheckStrictMode("var " + word + " = 1;", SyntaxError);
328  CheckStrictMode("typeof (" + word + ");", SyntaxError);
329
330  // object literal properties
331  eval("var x = { " + word + " : 42 };");
332  eval("var x = { get " + word + " () {} };");
333  eval("var x = { set " + word + " (value) {} };");
334  eval("var x = { get " + word + " () { 'use strict'; } };");
335  eval("var x = { set " + word + " (value) { 'use strict'; } };");
336
337  // object literal with string literal property names
338  eval("var x = { '" + word + "' : 42 };");
339  eval("var x = { get '" + word + "' () { } };");
340  eval("var x = { set '" + word + "' (value) { } };");
341  eval("var x = { get '" + word + "' () { 'use strict'; } };");
342  eval("var x = { set '" + word + "' (value) { 'use strict'; } };");
343
344  // Function names and arguments, strict and non-strict contexts
345  CheckStrictMode("function " + word + " () {}", SyntaxError);
346  CheckStrictMode("function foo (" + word + ") {}", SyntaxError);
347  CheckStrictMode("function foo (" + word + ", " + word + ") {}", SyntaxError);
348  CheckStrictMode("function foo (a, " + word + ") {}", SyntaxError);
349  CheckStrictMode("function foo (" + word + ", a) {}", SyntaxError);
350  CheckStrictMode("function foo (a, " + word + ", b) {}", SyntaxError);
351  CheckStrictMode("var foo = function (" + word + ") {}", SyntaxError);
352
353  // Function names and arguments when the body is strict
354  assertThrows("function " + word + " () { 'use strict'; }", SyntaxError);
355  assertThrows("function foo (" + word + ", " + word + ") { 'use strict'; }",
356               SyntaxError);
357  assertThrows("function foo (a, " + word + ") { 'use strict'; }", SyntaxError);
358  assertThrows("function foo (" + word + ", a) { 'use strict'; }", SyntaxError);
359  assertThrows("function foo (a, " + word + ", b) { 'use strict'; }",
360               SyntaxError);
361  assertThrows("var foo = function (" + word + ") { 'use strict'; }",
362               SyntaxError);
363
364  // setter parameter when the body is strict
365  CheckStrictMode("var x = { set foo(" + word + ") {} };", SyntaxError);
366  assertThrows("var x = { set foo(" + word + ") { 'use strict'; } };",
367               SyntaxError);
368}
369
370for (var i = 0; i < future_strict_reserved_words.length; i++) {
371  testFutureStrictReservedWord(future_strict_reserved_words[i]);
372}
373
374function testAssignToUndefined(test, should_throw) {
375  try {
376    test();
377  } catch (e) {
378    assertTrue(should_throw, "strict mode");
379    assertInstanceof(e, ReferenceError, "strict mode");
380    return;
381  }
382  assertFalse(should_throw, "strict mode");
383}
384
385function repeat(n, f) {
386  for (var i = 0; i < n; i ++) { f(); }
387}
388
389function assignToUndefined() {
390  "use strict";
391  possibly_undefined_variable_for_strict_mode_test = "should throw?";
392}
393
394testAssignToUndefined(assignToUndefined, true);
395testAssignToUndefined(assignToUndefined, true);
396testAssignToUndefined(assignToUndefined, true);
397
398possibly_undefined_variable_for_strict_mode_test = "value";
399
400testAssignToUndefined(assignToUndefined, false);
401testAssignToUndefined(assignToUndefined, false);
402testAssignToUndefined(assignToUndefined, false);
403
404delete possibly_undefined_variable_for_strict_mode_test;
405
406testAssignToUndefined(assignToUndefined, true);
407testAssignToUndefined(assignToUndefined, true);
408testAssignToUndefined(assignToUndefined, true);
409
410repeat(10, function() { testAssignToUndefined(assignToUndefined, true); });
411possibly_undefined_variable_for_strict_mode_test = "value";
412repeat(10, function() { testAssignToUndefined(assignToUndefined, false); });
413delete possibly_undefined_variable_for_strict_mode_test;
414repeat(10, function() { testAssignToUndefined(assignToUndefined, true); });
415possibly_undefined_variable_for_strict_mode_test = undefined;
416repeat(10, function() { testAssignToUndefined(assignToUndefined, false); });
417
418function assignToUndefinedWithEval() {
419  "use strict";
420  possibly_undefined_variable_for_strict_mode_test_with_eval = "should throw?";
421  eval("");
422}
423
424testAssignToUndefined(assignToUndefinedWithEval, true);
425testAssignToUndefined(assignToUndefinedWithEval, true);
426testAssignToUndefined(assignToUndefinedWithEval, true);
427
428possibly_undefined_variable_for_strict_mode_test_with_eval = "value";
429
430testAssignToUndefined(assignToUndefinedWithEval, false);
431testAssignToUndefined(assignToUndefinedWithEval, false);
432testAssignToUndefined(assignToUndefinedWithEval, false);
433
434delete possibly_undefined_variable_for_strict_mode_test_with_eval;
435
436testAssignToUndefined(assignToUndefinedWithEval, true);
437testAssignToUndefined(assignToUndefinedWithEval, true);
438testAssignToUndefined(assignToUndefinedWithEval, true);
439
440repeat(10, function() {
441             testAssignToUndefined(assignToUndefinedWithEval, true);
442           });
443possibly_undefined_variable_for_strict_mode_test_with_eval = "value";
444repeat(10, function() {
445             testAssignToUndefined(assignToUndefinedWithEval, false);
446           });
447delete possibly_undefined_variable_for_strict_mode_test_with_eval;
448repeat(10, function() {
449             testAssignToUndefined(assignToUndefinedWithEval, true);
450           });
451possibly_undefined_variable_for_strict_mode_test_with_eval = undefined;
452repeat(10, function() {
453             testAssignToUndefined(assignToUndefinedWithEval, false);
454           });
455
456
457
458(function testDeleteNonConfigurable() {
459  function delete_property(o) {
460    "use strict";
461    delete o.property;
462  }
463  function delete_element(o, i) {
464    "use strict";
465    delete o[i];
466  }
467
468  var object = {};
469
470  Object.defineProperty(object, "property", { value: "property_value" });
471  Object.defineProperty(object, "1", { value: "one" });
472  Object.defineProperty(object, 7, { value: "seven" });
473  Object.defineProperty(object, 3.14, { value: "pi" });
474
475  assertThrows(function() { delete_property(object); }, TypeError);
476  assertEquals(object.property, "property_value");
477  assertThrows(function() { delete_element(object, "1"); }, TypeError);
478  assertThrows(function() { delete_element(object, 1); }, TypeError);
479  assertEquals(object[1], "one");
480  assertThrows(function() { delete_element(object, "7"); }, TypeError);
481  assertThrows(function() { delete_element(object, 7); }, TypeError);
482  assertEquals(object[7], "seven");
483  assertThrows(function() { delete_element(object, "3.14"); }, TypeError);
484  assertThrows(function() { delete_element(object, 3.14); }, TypeError);
485  assertEquals(object[3.14], "pi");
486})();
487
488// Not transforming this in Function.call and Function.apply.
489(function testThisTransformCallApply() {
490  function non_strict() {
491    return this;
492  }
493  function strict() {
494    "use strict";
495    return this;
496  }
497
498  var global_object = (function() { return this; })();
499  var object = {};
500
501  // Non-strict call.
502  assertTrue(non_strict.call(null) === global_object);
503  assertTrue(non_strict.call(undefined) === global_object);
504  assertEquals(typeof non_strict.call(7), "object");
505  assertEquals(typeof non_strict.call("Hello"), "object");
506  assertTrue(non_strict.call(object) === object);
507
508  // Non-strict apply.
509  assertTrue(non_strict.apply(null) === global_object);
510  assertTrue(non_strict.apply(undefined) === global_object);
511  assertEquals(typeof non_strict.apply(7), "object");
512  assertEquals(typeof non_strict.apply("Hello"), "object");
513  assertTrue(non_strict.apply(object) === object);
514
515  // Strict call.
516  assertTrue(strict.call(null) === null);
517  assertTrue(strict.call(undefined) === undefined);
518  assertEquals(typeof strict.call(7), "number");
519  assertEquals(typeof strict.call("Hello"), "string");
520  assertTrue(strict.call(object) === object);
521
522  // Strict apply.
523  assertTrue(strict.apply(null) === null);
524  assertTrue(strict.apply(undefined) === undefined);
525  assertEquals(typeof strict.apply(7), "number");
526  assertEquals(typeof strict.apply("Hello"), "string");
527  assertTrue(strict.apply(object) === object);
528})();
529
530(function testThisTransform() {
531  try {
532    function strict() {
533      "use strict";
534      return typeof(this);
535    }
536    function nonstrict() {
537      return typeof(this);
538    }
539
540    // Concat to avoid symbol.
541    var strict_name = "str" + "ict";
542    var nonstrict_name = "non" + "str" + "ict";
543    var strict_number = 17;
544    var nonstrict_number = 19;
545    var strict_name_get = "str" + "ict" + "get";
546    var nonstrict_name_get = "non" + "str" + "ict" + "get"
547    var strict_number_get = 23;
548    var nonstrict_number_get = 29;
549
550    function install(t) {
551      t.prototype.strict = strict;
552      t.prototype.nonstrict = nonstrict;
553      t.prototype[strict_number] = strict;
554      t.prototype[nonstrict_number] = nonstrict;
555      Object.defineProperty(t.prototype, strict_name_get,
556                            { get: function() { return strict; },
557                              configurable: true });
558      Object.defineProperty(t.prototype, nonstrict_name_get,
559                            { get: function() { return nonstrict; },
560                              configurable: true });
561      Object.defineProperty(t.prototype, strict_number_get,
562                            { get: function() { return strict; },
563                              configurable: true });
564      Object.defineProperty(t.prototype, nonstrict_number_get,
565                            { get: function() { return nonstrict; },
566                              configurable: true });
567    }
568
569    function cleanup(t) {
570      delete t.prototype.strict;
571      delete t.prototype.nonstrict;
572      delete t.prototype[strict_number];
573      delete t.prototype[nonstrict_number];
574      delete t.prototype[strict_name_get];
575      delete t.prototype[nonstrict_name_get];
576      delete t.prototype[strict_number_get];
577      delete t.prototype[nonstrict_number_get];
578    }
579
580    // Set up fakes
581    install(String);
582    install(Number);
583    install(Boolean)
584
585    function callStrict(o) {
586      return o.strict();
587    }
588    function callNonStrict(o) {
589      return o.nonstrict();
590    }
591    function callKeyedStrict(o) {
592      return o[strict_name]();
593    }
594    function callKeyedNonStrict(o) {
595      return o[nonstrict_name]();
596    }
597    function callIndexedStrict(o) {
598      return o[strict_number]();
599    }
600    function callIndexedNonStrict(o) {
601      return o[nonstrict_number]();
602    }
603    function callStrictGet(o) {
604      return o.strictget();
605    }
606    function callNonStrictGet(o) {
607      return o.nonstrictget();
608    }
609    function callKeyedStrictGet(o) {
610      return o[strict_name_get]();
611    }
612    function callKeyedNonStrictGet(o) {
613      return o[nonstrict_name_get]();
614    }
615    function callIndexedStrictGet(o) {
616      return o[strict_number_get]();
617    }
618    function callIndexedNonStrictGet(o) {
619      return o[nonstrict_number_get]();
620    }
621
622    for (var i = 0; i < 10; i ++) {
623      assertEquals(("hello").strict(), "string");
624      assertEquals(("hello").nonstrict(), "object");
625      assertEquals(("hello")[strict_name](), "string");
626      assertEquals(("hello")[nonstrict_name](), "object");
627      assertEquals(("hello")[strict_number](), "string");
628      assertEquals(("hello")[nonstrict_number](), "object");
629
630      assertEquals((10 + i).strict(), "number");
631      assertEquals((10 + i).nonstrict(), "object");
632      assertEquals((10 + i)[strict_name](), "number");
633      assertEquals((10 + i)[nonstrict_name](), "object");
634      assertEquals((10 + i)[strict_number](), "number");
635      assertEquals((10 + i)[nonstrict_number](), "object");
636
637      assertEquals((true).strict(), "boolean");
638      assertEquals((true).nonstrict(), "object");
639      assertEquals((true)[strict_name](), "boolean");
640      assertEquals((true)[nonstrict_name](), "object");
641      assertEquals((true)[strict_number](), "boolean");
642      assertEquals((true)[nonstrict_number](), "object");
643
644      assertEquals((false).strict(), "boolean");
645      assertEquals((false).nonstrict(), "object");
646      assertEquals((false)[strict_name](), "boolean");
647      assertEquals((false)[nonstrict_name](), "object");
648      assertEquals((false)[strict_number](), "boolean");
649      assertEquals((false)[nonstrict_number](), "object");
650
651      assertEquals(callStrict("howdy"), "string");
652      assertEquals(callNonStrict("howdy"), "object");
653      assertEquals(callKeyedStrict("howdy"), "string");
654      assertEquals(callKeyedNonStrict("howdy"), "object");
655      assertEquals(callIndexedStrict("howdy"), "string");
656      assertEquals(callIndexedNonStrict("howdy"), "object");
657
658      assertEquals(callStrict(17 + i), "number");
659      assertEquals(callNonStrict(17 + i), "object");
660      assertEquals(callKeyedStrict(17 + i), "number");
661      assertEquals(callKeyedNonStrict(17 + i), "object");
662      assertEquals(callIndexedStrict(17 + i), "number");
663      assertEquals(callIndexedNonStrict(17 + i), "object");
664
665      assertEquals(callStrict(true), "boolean");
666      assertEquals(callNonStrict(true), "object");
667      assertEquals(callKeyedStrict(true), "boolean");
668      assertEquals(callKeyedNonStrict(true), "object");
669      assertEquals(callIndexedStrict(true), "boolean");
670      assertEquals(callIndexedNonStrict(true), "object");
671
672      assertEquals(callStrict(false), "boolean");
673      assertEquals(callNonStrict(false), "object");
674      assertEquals(callKeyedStrict(false), "boolean");
675      assertEquals(callKeyedNonStrict(false), "object");
676      assertEquals(callIndexedStrict(false), "boolean");
677      assertEquals(callIndexedNonStrict(false), "object");
678
679      // All of the above, with getters
680      assertEquals(("hello").strictget(), "string");
681      assertEquals(("hello").nonstrictget(), "object");
682      assertEquals(("hello")[strict_name_get](), "string");
683      assertEquals(("hello")[nonstrict_name_get](), "object");
684      assertEquals(("hello")[strict_number_get](), "string");
685      assertEquals(("hello")[nonstrict_number_get](), "object");
686
687      assertEquals((10 + i).strictget(), "number");
688      assertEquals((10 + i).nonstrictget(), "object");
689      assertEquals((10 + i)[strict_name_get](), "number");
690      assertEquals((10 + i)[nonstrict_name_get](), "object");
691      assertEquals((10 + i)[strict_number_get](), "number");
692      assertEquals((10 + i)[nonstrict_number_get](), "object");
693
694      assertEquals((true).strictget(), "boolean");
695      assertEquals((true).nonstrictget(), "object");
696      assertEquals((true)[strict_name_get](), "boolean");
697      assertEquals((true)[nonstrict_name_get](), "object");
698      assertEquals((true)[strict_number_get](), "boolean");
699      assertEquals((true)[nonstrict_number_get](), "object");
700
701      assertEquals((false).strictget(), "boolean");
702      assertEquals((false).nonstrictget(), "object");
703      assertEquals((false)[strict_name_get](), "boolean");
704      assertEquals((false)[nonstrict_name_get](), "object");
705      assertEquals((false)[strict_number_get](), "boolean");
706      assertEquals((false)[nonstrict_number_get](), "object");
707
708      assertEquals(callStrictGet("howdy"), "string");
709      assertEquals(callNonStrictGet("howdy"), "object");
710      assertEquals(callKeyedStrictGet("howdy"), "string");
711      assertEquals(callKeyedNonStrictGet("howdy"), "object");
712      assertEquals(callIndexedStrictGet("howdy"), "string");
713      assertEquals(callIndexedNonStrictGet("howdy"), "object");
714
715      assertEquals(callStrictGet(17 + i), "number");
716      assertEquals(callNonStrictGet(17 + i), "object");
717      assertEquals(callKeyedStrictGet(17 + i), "number");
718      assertEquals(callKeyedNonStrictGet(17 + i), "object");
719      assertEquals(callIndexedStrictGet(17 + i), "number");
720      assertEquals(callIndexedNonStrictGet(17 + i), "object");
721
722      assertEquals(callStrictGet(true), "boolean");
723      assertEquals(callNonStrictGet(true), "object");
724      assertEquals(callKeyedStrictGet(true), "boolean");
725      assertEquals(callKeyedNonStrictGet(true), "object");
726      assertEquals(callIndexedStrictGet(true), "boolean");
727      assertEquals(callIndexedNonStrictGet(true), "object");
728
729      assertEquals(callStrictGet(false), "boolean");
730      assertEquals(callNonStrictGet(false), "object");
731      assertEquals(callKeyedStrictGet(false), "boolean");
732      assertEquals(callKeyedNonStrictGet(false), "object");
733      assertEquals(callIndexedStrictGet(false), "boolean");
734      assertEquals(callIndexedNonStrictGet(false), "object");
735
736    }
737  } finally {
738    // Cleanup
739    cleanup(String);
740    cleanup(Number);
741    cleanup(Boolean);
742  }
743})();
744
745
746(function ObjectEnvironment() {
747  var o = {};
748  Object.defineProperty(o, "foo", { value: "FOO", writable: false });
749  assertThrows(
750    function () {
751      with (o) {
752        (function() {
753          "use strict";
754          foo = "Hello";
755        })();
756      }
757    },
758    TypeError);
759})();
760
761
762(function TestSetPropertyWithoutSetter() {
763  var o = { get foo() { return "Yey"; } };
764  assertThrows(
765    function broken() {
766      "use strict";
767      o.foo = (0xBADBAD00 >> 1);
768    },
769    TypeError);
770})();
771
772
773(function TestSetPropertyNonConfigurable() {
774  var frozen = Object.freeze({});
775  var sealed = Object.seal({});
776
777  function strict(o) {
778    "use strict";
779    o.property = "value";
780  }
781
782  assertThrows(function() { strict(frozen); }, TypeError);
783  assertThrows(function() { strict(sealed); }, TypeError);
784})();
785
786
787(function TestAssignmentToReadOnlyProperty() {
788  "use strict";
789
790  var o = {};
791  Object.defineProperty(o, "property", { value: 7 });
792
793  assertThrows(function() { o.property = "new value"; }, TypeError);
794  assertThrows(function() { o.property += 10; }, TypeError);
795  assertThrows(function() { o.property -= 10; }, TypeError);
796  assertThrows(function() { o.property *= 10; }, TypeError);
797  assertThrows(function() { o.property /= 10; }, TypeError);
798  assertThrows(function() { o.property++; }, TypeError);
799  assertThrows(function() { o.property--; }, TypeError);
800  assertThrows(function() { ++o.property; }, TypeError);
801  assertThrows(function() { --o.property; }, TypeError);
802
803  var name = "prop" + "erty"; // to avoid symbol path.
804  assertThrows(function() { o[name] = "new value"; }, TypeError);
805  assertThrows(function() { o[name] += 10; }, TypeError);
806  assertThrows(function() { o[name] -= 10; }, TypeError);
807  assertThrows(function() { o[name] *= 10; }, TypeError);
808  assertThrows(function() { o[name] /= 10; }, TypeError);
809  assertThrows(function() { o[name]++; }, TypeError);
810  assertThrows(function() { o[name]--; }, TypeError);
811  assertThrows(function() { ++o[name]; }, TypeError);
812  assertThrows(function() { --o[name]; }, TypeError);
813
814  assertEquals(o.property, 7);
815})();
816
817
818(function TestAssignmentToReadOnlyLoop() {
819  var name = "prop" + "erty"; // to avoid symbol path.
820  var o = {};
821  Object.defineProperty(o, "property", { value: 7 });
822
823  function strict(o, name) {
824    "use strict";
825    o[name] = "new value";
826  }
827
828  for (var i = 0; i < 10; i ++) {
829    var exception = false;
830    try {
831      strict(o, name);
832    } catch(e) {
833      exception = true;
834      assertInstanceof(e, TypeError);
835    }
836    assertTrue(exception);
837  }
838})();
839
840
841// Specialized KeyedStoreIC experiencing miss.
842(function testKeyedStoreICStrict() {
843  var o = [9,8,7,6,5,4,3,2,1];
844
845  function test(o, i, v) {
846    "use strict";
847    o[i] = v;
848  }
849
850  for (var i = 0; i < 10; i ++) {
851    test(o, 5, 17);        // start specialized for smi indices
852    assertEquals(o[5], 17);
853    test(o, "a", 19);
854    assertEquals(o["a"], 19);
855    test(o, "5", 29);
856    assertEquals(o[5], 29);
857    test(o, 100000, 31);
858    assertEquals(o[100000], 31);
859  }
860})();
861
862
863(function TestSetElementWithoutSetter() {
864  "use strict";
865
866  var o = { };
867  Object.defineProperty(o, 0, { get : function() { } });
868
869  var zero_smi = 0;
870  var zero_number = new Number(0);
871  var zero_symbol = "0";
872  var zero_string = "-0-".substring(1,2);
873
874  assertThrows(function() { o[zero_smi] = "new value"; }, TypeError);
875  assertThrows(function() { o[zero_number] = "new value"; }, TypeError);
876  assertThrows(function() { o[zero_symbol] = "new value"; }, TypeError);
877  assertThrows(function() { o[zero_string] = "new value"; }, TypeError);
878})();
879
880
881(function TestSetElementNonConfigurable() {
882  "use strict";
883  var frozen = Object.freeze({});
884  var sealed = Object.seal({});
885
886  var zero_number = 0;
887  var zero_symbol = "0";
888  var zero_string = "-0-".substring(1,2);
889
890  assertThrows(function() { frozen[zero_number] = "value"; }, TypeError);
891  assertThrows(function() { sealed[zero_number] = "value"; }, TypeError);
892  assertThrows(function() { frozen[zero_symbol] = "value"; }, TypeError);
893  assertThrows(function() { sealed[zero_symbol] = "value"; }, TypeError);
894  assertThrows(function() { frozen[zero_string] = "value"; }, TypeError);
895  assertThrows(function() { sealed[zero_string] = "value"; }, TypeError);
896})();
897
898
899(function TestAssignmentToReadOnlyElement() {
900  "use strict";
901
902  var o = {};
903  Object.defineProperty(o, 7, { value: 17 });
904
905  var seven_smi = 7;
906  var seven_number = new Number(7);
907  var seven_symbol = "7";
908  var seven_string = "-7-".substring(1,2);
909
910  // Index with number.
911  assertThrows(function() { o[seven_smi] = "value"; }, TypeError);
912  assertThrows(function() { o[seven_smi] += 10; }, TypeError);
913  assertThrows(function() { o[seven_smi] -= 10; }, TypeError);
914  assertThrows(function() { o[seven_smi] *= 10; }, TypeError);
915  assertThrows(function() { o[seven_smi] /= 10; }, TypeError);
916  assertThrows(function() { o[seven_smi]++; }, TypeError);
917  assertThrows(function() { o[seven_smi]--; }, TypeError);
918  assertThrows(function() { ++o[seven_smi]; }, TypeError);
919  assertThrows(function() { --o[seven_smi]; }, TypeError);
920
921  assertThrows(function() { o[seven_number] = "value"; }, TypeError);
922  assertThrows(function() { o[seven_number] += 10; }, TypeError);
923  assertThrows(function() { o[seven_number] -= 10; }, TypeError);
924  assertThrows(function() { o[seven_number] *= 10; }, TypeError);
925  assertThrows(function() { o[seven_number] /= 10; }, TypeError);
926  assertThrows(function() { o[seven_number]++; }, TypeError);
927  assertThrows(function() { o[seven_number]--; }, TypeError);
928  assertThrows(function() { ++o[seven_number]; }, TypeError);
929  assertThrows(function() { --o[seven_number]; }, TypeError);
930
931  assertThrows(function() { o[seven_symbol] = "value"; }, TypeError);
932  assertThrows(function() { o[seven_symbol] += 10; }, TypeError);
933  assertThrows(function() { o[seven_symbol] -= 10; }, TypeError);
934  assertThrows(function() { o[seven_symbol] *= 10; }, TypeError);
935  assertThrows(function() { o[seven_symbol] /= 10; }, TypeError);
936  assertThrows(function() { o[seven_symbol]++; }, TypeError);
937  assertThrows(function() { o[seven_symbol]--; }, TypeError);
938  assertThrows(function() { ++o[seven_symbol]; }, TypeError);
939  assertThrows(function() { --o[seven_symbol]; }, TypeError);
940
941  assertThrows(function() { o[seven_string] = "value"; }, TypeError);
942  assertThrows(function() { o[seven_string] += 10; }, TypeError);
943  assertThrows(function() { o[seven_string] -= 10; }, TypeError);
944  assertThrows(function() { o[seven_string] *= 10; }, TypeError);
945  assertThrows(function() { o[seven_string] /= 10; }, TypeError);
946  assertThrows(function() { o[seven_string]++; }, TypeError);
947  assertThrows(function() { o[seven_string]--; }, TypeError);
948  assertThrows(function() { ++o[seven_string]; }, TypeError);
949  assertThrows(function() { --o[seven_string]; }, TypeError);
950
951  assertEquals(o[seven_number], 17);
952  assertEquals(o[seven_symbol], 17);
953  assertEquals(o[seven_string], 17);
954})();
955
956
957(function TestAssignmentToReadOnlyLoop() {
958  "use strict";
959
960  var o = {};
961  Object.defineProperty(o, 7, { value: 17 });
962
963  var seven_smi = 7;
964  var seven_number = new Number(7);
965  var seven_symbol = "7";
966  var seven_string = "-7-".substring(1,2);
967
968  for (var i = 0; i < 10; i ++) {
969    assertThrows(function() { o[seven_smi] = "value" }, TypeError);
970    assertThrows(function() { o[seven_number] = "value" }, TypeError);
971    assertThrows(function() { o[seven_symbol] = "value" }, TypeError);
972    assertThrows(function() { o[seven_string] = "value" }, TypeError);
973  }
974
975  assertEquals(o[7], 17);
976})();
977
978
979(function TestAssignmentToStringLength() {
980  "use strict";
981
982  var str_val = "string";
983  var str_obj = new String(str_val);
984  var str_cat = str_val + str_val + str_obj;
985
986  assertThrows(function() { str_val.length = 1; }, TypeError);
987  assertThrows(function() { str_obj.length = 1; }, TypeError);
988  assertThrows(function() { str_cat.length = 1; }, TypeError);
989})();
990
991
992(function TestArgumentsAliasing() {
993  function strict(a, b) {
994    "use strict";
995    a = "c";
996    b = "d";
997    return [a, b, arguments[0], arguments[1]];
998  }
999
1000  function nonstrict(a, b) {
1001    a = "c";
1002    b = "d";
1003    return [a, b, arguments[0], arguments[1]];
1004  }
1005
1006  assertEquals(["c", "d", "a", "b"], strict("a", "b"));
1007  assertEquals(["c", "d", "c", "d"], nonstrict("a", "b"));
1008})();
1009
1010
1011function CheckFunctionPillDescriptor(func, name) {
1012
1013  function CheckPill(pill) {
1014    assertEquals("function", typeof pill);
1015    assertInstanceof(pill, Function);
1016    pill.property = "value";
1017    assertEquals(pill.value, undefined);
1018    assertThrows(function() { 'use strict'; pill.property = "value"; },
1019                 TypeError);
1020    assertThrows(pill, TypeError);
1021    assertEquals(undefined, pill.prototype);
1022  }
1023
1024  // Poisoned accessors are no longer own properties
1025  func = Object.getPrototypeOf(func);
1026  var descriptor = Object.getOwnPropertyDescriptor(func, name);
1027  CheckPill(descriptor.get)
1028  CheckPill(descriptor.set);
1029  assertFalse(descriptor.enumerable);
1030  // In ES6, restricted function properties are configurable
1031  assertTrue(descriptor.configurable);
1032}
1033
1034
1035function CheckArgumentsPillDescriptor(func, name) {
1036
1037  function CheckPill(pill) {
1038    assertEquals("function", typeof pill);
1039    assertInstanceof(pill, Function);
1040    pill.property = "value";
1041    assertEquals(pill.value, undefined);
1042    assertThrows(function() { 'use strict'; pill.property = "value"; },
1043                 TypeError);
1044    assertThrows(pill, TypeError);
1045    assertEquals(undefined, pill.prototype);
1046  }
1047
1048  var descriptor = Object.getOwnPropertyDescriptor(func, name);
1049  CheckPill(descriptor.get)
1050  CheckPill(descriptor.set);
1051  assertFalse(descriptor.enumerable);
1052  assertFalse(descriptor.configurable);
1053}
1054
1055
1056(function TestStrictFunctionPills() {
1057  function strict() {
1058    "use strict";
1059  }
1060  assertThrows(function() { strict.caller; }, TypeError);
1061  assertThrows(function() { strict.arguments; }, TypeError);
1062  assertThrows(function() { strict.caller = 42; }, TypeError);
1063  assertThrows(function() { strict.arguments = 42; }, TypeError);
1064
1065  var another = new Function("'use strict'");
1066  assertThrows(function() { another.caller; }, TypeError);
1067  assertThrows(function() { another.arguments; }, TypeError);
1068  assertThrows(function() { another.caller = 42; }, TypeError);
1069  assertThrows(function() { another.arguments = 42; }, TypeError);
1070
1071  var third = (function() { "use strict"; return function() {}; })();
1072  assertThrows(function() { third.caller; }, TypeError);
1073  assertThrows(function() { third.arguments; }, TypeError);
1074  assertThrows(function() { third.caller = 42; }, TypeError);
1075  assertThrows(function() { third.arguments = 42; }, TypeError);
1076
1077  CheckFunctionPillDescriptor(strict, "caller");
1078  CheckFunctionPillDescriptor(strict, "arguments");
1079  CheckFunctionPillDescriptor(another, "caller");
1080  CheckFunctionPillDescriptor(another, "arguments");
1081  CheckFunctionPillDescriptor(third, "caller");
1082  CheckFunctionPillDescriptor(third, "arguments");
1083})();
1084
1085
1086(function TestStrictFunctionWritablePrototype() {
1087  "use strict";
1088  function TheClass() {
1089  }
1090  assertThrows(function() { TheClass.caller; }, TypeError);
1091  assertThrows(function() { TheClass.arguments; }, TypeError);
1092
1093  // Strict functions must have writable prototype.
1094  TheClass.prototype = {
1095    func: function() { return "func_value"; },
1096    get accessor() { return "accessor_value"; },
1097    property: "property_value",
1098  };
1099
1100  var o = new TheClass();
1101  assertEquals(o.func(), "func_value");
1102  assertEquals(o.accessor, "accessor_value");
1103  assertEquals(o.property, "property_value");
1104})();
1105
1106
1107(function TestStrictArgumentPills() {
1108  function strict() {
1109    "use strict";
1110    return arguments;
1111  }
1112
1113  var args = strict();
1114  CheckArgumentsPillDescriptor(args, "caller");
1115  CheckArgumentsPillDescriptor(args, "callee");
1116
1117  args = strict(17, "value", strict);
1118  assertEquals(17, args[0])
1119  assertEquals("value", args[1])
1120  assertEquals(strict, args[2]);
1121  CheckArgumentsPillDescriptor(args, "caller");
1122  CheckArgumentsPillDescriptor(args, "callee");
1123
1124  function outer() {
1125    "use strict";
1126    function inner() {
1127      return arguments;
1128    }
1129    return inner;
1130  }
1131
1132  var args = outer()();
1133  CheckArgumentsPillDescriptor(args, "caller");
1134  CheckArgumentsPillDescriptor(args, "callee");
1135
1136  args = outer()(17, "value", strict);
1137  assertEquals(17, args[0])
1138  assertEquals("value", args[1])
1139  assertEquals(strict, args[2]);
1140  CheckArgumentsPillDescriptor(args, "caller");
1141  CheckArgumentsPillDescriptor(args, "callee");
1142})();
1143
1144
1145(function TestNonStrictFunctionCallerPillSimple() {
1146  function return_my_caller() {
1147    return return_my_caller.caller;
1148  }
1149
1150  function strict() {
1151    "use strict";
1152    return return_my_caller();
1153  }
1154  assertSame(null, strict());
1155
1156  function non_strict() {
1157    return return_my_caller();
1158  }
1159  assertSame(non_strict(), non_strict);
1160})();
1161
1162
1163(function TestNonStrictFunctionCallerPill() {
1164  function strict(n) {
1165    "use strict";
1166    return non_strict(n);
1167  }
1168
1169  function recurse(n, then) {
1170    if (n > 0) {
1171      return recurse(n - 1, then);
1172    } else {
1173      return then();
1174    }
1175  }
1176
1177  function non_strict(n) {
1178    return recurse(n, function() { return non_strict.caller; });
1179  }
1180
1181  function test(n) {
1182    return recurse(n, function() { return strict(n); });
1183  }
1184
1185  for (var i = 0; i < 10; i ++) {
1186    assertSame(null, test(i));
1187  }
1188})();
1189
1190
1191(function TestNonStrictFunctionCallerDescriptorPill() {
1192  function strict(n) {
1193    "use strict";
1194    return non_strict(n);
1195  }
1196
1197  function recurse(n, then) {
1198    if (n > 0) {
1199      return recurse(n - 1, then);
1200    } else {
1201      return then();
1202    }
1203  }
1204
1205  function non_strict(n) {
1206    return recurse(n, function() {
1207      return Object.getOwnPropertyDescriptor(non_strict, "caller").value;
1208    });
1209  }
1210
1211  function test(n) {
1212    return recurse(n, function() { return strict(n); });
1213  }
1214
1215  for (var i = 0; i < 10; i ++) {
1216    assertSame(null, test(i));
1217  }
1218})();
1219
1220
1221(function TestStrictModeEval() {
1222  "use strict";
1223  eval("var eval_local = 10;");
1224  assertThrows(function() { return eval_local; }, ReferenceError);
1225})();
1226