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