strict-mode.js revision e0cee9b3ed82e2391fd85d118aeaa4ea361c687d
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// '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); 172CheckStrictMode("var x = { \ 173 123: 1, \ 174 123.00000000000000000000000000000000000000000000000000000000000000000001: 2 \ 175}", SyntaxError); 176 177// Non-conflicting data properties. 178(function StrictModeNonDuplicate() { 179 "use strict"; 180 var x = { 123 : 1, "0123" : 2 }; 181 var x = { 182 123: 1, 183 '123.00000000000000000000000000000000000000000000000000000000000000000001': 184 2 185 }; 186})(); 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); 224CheckStrictMode("function strict() { print(arguments = undefined); }", 225 SyntaxError); 226CheckStrictMode("function strict() { var x = eval = undefined; }", SyntaxError); 227CheckStrictMode("function strict() { var x = arguments = undefined; }", 228 SyntaxError); 229 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); 234CheckStrictMode("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); 240CheckStrictMode("function strict() { eval <<= undefined; }", SyntaxError); 241CheckStrictMode("function strict() { arguments >>= undefined; }", SyntaxError); 242CheckStrictMode("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); 250 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 283// 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 314// 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); 368 assertThrows("function foo (" + word + ", " + word + ") { 'use strict'; }", 369 SyntaxError); 370 assertThrows("function foo (a, " + word + ") { 'use strict'; }", SyntaxError); 371 assertThrows("function foo (" + word + ", a) { 'use strict'; }", SyntaxError); 372 assertThrows("function foo (a, " + word + ", b) { 'use strict'; }", 373 SyntaxError); 374 assertThrows("var foo = function (" + word + ") { 'use strict'; }", 375 SyntaxError); 376 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'; } };"); 380 assertThrows("var x = { get foo(" + word + ") { 'use strict'; } };", 381 SyntaxError); 382 assertThrows("var x = { set foo(" + word + ") { 'use strict'; } };", 383 SyntaxError); 384} 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); }); 429 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})(); 960