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