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