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