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