1// Copyright 2013 the V8 project authors. All rights reserved. 2// Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved. 3// 4// Redistribution and use in source and binary forms, with or without 5// modification, are permitted provided that the following conditions 6// are met: 7// 1. Redistributions of source code must retain the above copyright 8// notice, this list of conditions and the following disclaimer. 9// 2. Redistributions in binary form must reproduce the above copyright 10// notice, this list of conditions and the following disclaimer in the 11// documentation and/or other materials provided with the distribution. 12// 13// THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16// DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20// ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 24description("Test behaviour of strict mode"); 25 26var globalThisTest; 27function testThis() { 28 "use strict"; 29 return this; 30} 31function testThisDotAccess() { 32 "use strict"; 33 return this.length; 34} 35function testThisBracketAccess(prop) { 36 "use strict"; 37 return this[prop]; 38} 39function testGlobalAccess() { 40 return testThis(); 41} 42function shouldBeSyntaxError(str) { 43 shouldThrow(str); 44 shouldThrow("(function(){" + str + "})"); 45} 46function testLineContinuation() { 47 "use stric\ 48t"; 49 return this; 50} 51function testEscapeSequence() { 52 "use\u0020strict"; 53 return this; 54} 55 56shouldBe("testThis.call(null)", "null"); 57shouldBe("testThis.call(1)", "1"); 58shouldBe("testThis.call(true)", "true"); 59shouldBe("testThis.call(false)", "false"); 60shouldBe("testThis.call(undefined)", "undefined"); 61shouldBeFalse("testLineContinuation.call(undefined) === undefined"); 62shouldBeFalse("testEscapeSequence.call(undefined) === undefined"); 63shouldBe("testThis.call('a string')", "'a string'"); 64shouldBe("testThisDotAccess.call('a string')", "'a string'.length"); 65shouldThrow("testThisDotAccess.call(null)"); 66shouldThrow("testThisDotAccess.call(undefined)"); 67shouldBeUndefined("testThisDotAccess.call(true)"); 68shouldBeUndefined("testThisDotAccess.call(false)"); 69shouldBeUndefined("testThisDotAccess.call(1)"); 70shouldBe("testThisBracketAccess.call('a string', 'length')", "'a string'.length"); 71shouldThrow("testThisBracketAccess.call(null, 'length')"); 72shouldThrow("testThisBracketAccess.call(undefined, 'length')"); 73shouldBeUndefined("testThisBracketAccess.call(true, 'length')"); 74shouldBeUndefined("testThisBracketAccess.call(false, 'length')"); 75shouldBeUndefined("testThisBracketAccess.call(1, 'length')"); 76shouldBeUndefined("Function('\"use strict\"; return this;')()"); 77shouldThrow("Function('\"use strict\"; with({});')"); 78 79 80shouldBe("testGlobalAccess()", "undefined"); 81shouldBe("testThis.call()", "undefined"); 82shouldBe("testThis.apply()", "undefined"); 83shouldBe("testThis.call(undefined)", "undefined"); 84shouldBe("testThis.apply(undefined)", "undefined"); 85 86shouldBeSyntaxError("(function eval(){'use strict';})"); 87shouldBeSyntaxError("(function (eval){'use strict';})"); 88shouldBeSyntaxError("(function arguments(){'use strict';})"); 89shouldBeSyntaxError("(function (arguments){'use strict';})"); 90shouldBeSyntaxError("(function (){'use strict'; var eval;})"); 91shouldBeSyntaxError("(function (){'use strict'; var arguments;})"); 92shouldBeSyntaxError("(function (){'use strict'; try{}catch(eval){}})"); 93shouldBeSyntaxError("(function (){'use strict'; try{}catch(arguments){}})"); 94shouldBeSyntaxError("(function (a, a){'use strict';})"); 95shouldBeSyntaxError("(function (a){'use strict'; delete a;})()"); 96shouldBeSyntaxError("(function (){'use strict'; var a; delete a;})()"); 97shouldBeSyntaxError("(function (){var a; function f() {'use strict'; delete a;} })()"); 98shouldBeSyntaxError("(function (){'use strict'; with(1){};})"); 99shouldThrow("(function (){'use strict'; arguments.callee; })()"); 100shouldThrow("(function (){'use strict'; arguments.caller; })()"); 101shouldThrow("(function f(){'use strict'; f.arguments; })()"); 102shouldThrow("(function f(){'use strict'; f.caller; })()"); 103shouldThrow("(function f(){'use strict'; f.arguments=5; })()"); 104shouldThrow("(function f(){'use strict'; f.caller=5; })()"); 105shouldThrow("(function (arg){'use strict'; arguments.callee; })()"); 106shouldThrow("(function (arg){'use strict'; arguments.caller; })()"); 107shouldThrow("(function f(arg){'use strict'; f.arguments; })()"); 108shouldThrow("(function f(arg){'use strict'; f.caller; })()"); 109shouldThrow("(function f(arg){'use strict'; f.arguments=5; })()"); 110shouldThrow("(function f(arg){'use strict'; f.caller=5; })()"); 111 112// arguments/caller poisoning should be visible on the intrinsic %FunctionPrototype%, but not throw with 'in' & 'hasOwnProperty'. 113shouldBeTrue('"caller" in function(){"use strict"}'); 114shouldBeFalse('(function(){"use strict";}).hasOwnProperty("caller")'); 115shouldBeTrue('(function(){"use strict";}).__proto__.hasOwnProperty("caller")'); 116shouldBeTrue('"arguments" in function(){"use strict"}'); 117shouldBeFalse('(function(){"use strict";}).hasOwnProperty("arguments")'); 118shouldBeTrue('(function(){"use strict";}).__proto__.hasOwnProperty("arguments")'); 119 120shouldBeSyntaxError("'use strict'; (function (){with(1){};})"); 121shouldBeSyntaxError("'use strict'; (function (){var a; delete a;})"); 122shouldBeSyntaxError("'use strict'; var a; (function (){ delete a;})"); 123shouldBeSyntaxError("var a; (function (){ 'use strict'; delete a;})"); 124shouldBeSyntaxError("'misc directive'; 'use strict'; with({}){}"); 125shouldThrow("'use strict'; return"); 126shouldBeSyntaxError("'use strict'; break"); 127shouldBeSyntaxError("'use strict'; continue"); 128shouldThrow("'use strict'; for(;;)return"); 129shouldBeSyntaxError("'use strict'; for(;;)break missingLabel"); 130shouldBeSyntaxError("'use strict'; for(;;)continue missingLabel"); 131shouldBeSyntaxError("'use strict'; 007;"); 132shouldBeSyntaxError("'use strict'; '\\007';"); 133shouldBeSyntaxError("'\\007'; 'use strict';"); 134 135var someDeclaredGlobal; 136aDeletableProperty = 'test'; 137 138shouldBeSyntaxError("'use strict'; delete aDeletableProperty;"); 139shouldBeSyntaxError("'use strict'; (function (){ delete someDeclaredGlobal;})"); 140shouldBeSyntaxError("(function (){ 'use strict'; delete someDeclaredGlobal;})"); 141shouldBeTrue("'use strict'; if (0) { someGlobal = 'Shouldn\\'t be able to assign this.'; }; true;"); 142shouldThrow("'use strict'; someGlobal = 'Shouldn\\'t be able to assign this.'; "); 143shouldThrow("'use strict'; (function f(){ f = 'shouldn\\'t be able to assign to function expression name'; })()"); 144shouldThrow("'use strict'; eval('var introducedVariable = \"FAIL: variable introduced into containing scope\";'); introducedVariable"); 145var objectWithReadonlyProperty = {}; 146Object.defineProperty(objectWithReadonlyProperty, "prop", {value: "value", writable:false}); 147shouldThrow("'use strict'; objectWithReadonlyProperty.prop = 'fail'"); 148shouldThrow("'use strict'; delete objectWithReadonlyProperty.prop"); 149readonlyPropName = "prop"; 150shouldThrow("'use strict'; delete objectWithReadonlyProperty[readonlyPropName]"); 151shouldBeSyntaxError("'use strict'; ++eval"); 152shouldBeSyntaxError("'use strict'; eval++"); 153shouldBeSyntaxError("'use strict'; --eval"); 154shouldBeSyntaxError("'use strict'; eval--"); 155shouldBeSyntaxError("'use strict'; function f() { ++arguments }"); 156shouldBeSyntaxError("'use strict'; function f() { arguments++ }"); 157shouldBeSyntaxError("'use strict'; function f() { --arguments }"); 158shouldBeSyntaxError("'use strict'; function f() { arguments-- }"); 159var global = this; 160shouldThrow("global.eval('\"use strict\"; if (0) ++arguments; true;')"); 161shouldBeSyntaxError("'use strict'; ++(1, eval)"); 162shouldBeSyntaxError("'use strict'; (1, eval)++"); 163shouldBeSyntaxError("'use strict'; --(1, eval)"); 164shouldBeSyntaxError("'use strict'; (1, eval)--"); 165shouldBeSyntaxError("'use strict'; function f() { ++(1, arguments) }"); 166shouldBeSyntaxError("'use strict'; function f() { (1, arguments)++ }"); 167shouldBeSyntaxError("'use strict'; function f() { --(1, arguments) }"); 168shouldBeSyntaxError("'use strict'; function f() { (1, arguments)-- }"); 169shouldBeSyntaxError("'use strict'; undefined; if (0) delete +a.b"); 170shouldBeSyntaxError("'use strict'; undefined; if (0) delete ++a.b"); 171shouldBeSyntaxError("'use strict'; undefined; if (0) delete void a.b"); 172 173shouldBeTrue("(function (a){'use strict'; a = false; return a !== arguments[0]; })(true)"); 174shouldBeTrue("(function (a){'use strict'; arguments[0] = false; return a !== arguments[0]; })(true)"); 175shouldBeTrue("(function (a){'use strict'; a=false; return arguments; })(true)[0]"); 176shouldBeTrue("(function (a){'use strict'; arguments[0]=false; return a; })(true)"); 177shouldBeTrue("(function (a){'use strict'; arguments[0]=true; return arguments; })(false)[0]"); 178shouldBeTrue("(function (){'use strict'; arguments[0]=true; return arguments; })(false)[0]"); 179shouldBeTrue("(function (a){'use strict'; arguments[0]=true; a=false; return arguments; })()[0]"); 180shouldBeTrue("(function (a){'use strict'; arguments[0]=false; a=true; return a; })()"); 181shouldBeTrue("(function (a){'use strict'; arguments[0]=true; return arguments; })()[0]"); 182shouldBeTrue("(function (){'use strict'; arguments[0]=true; return arguments; })()[0]"); 183 184// Same tests again, this time forcing an activation to be created as well 185shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); a = false; return a !== arguments[0]; })(true)"); 186shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); arguments[0] = false; return a !== arguments[0]; })(true)"); 187shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); a=false; return arguments; })(true)[0]"); 188shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); arguments[0]=false; return a; })(true)"); 189shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); arguments[0]=true; return arguments; })(false)[0]"); 190shouldBeTrue("(function (){'use strict'; var local; (function (){local;})(); arguments[0]=true; return arguments; })(false)[0]"); 191shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); arguments[0]=true; a=false; return arguments; })()[0]"); 192shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); arguments[0]=true; return arguments; })()[0]"); 193shouldBeTrue("(function (a){'use strict'; var local; (function (){local;})(); arguments[0]=false; a=true; return a; })()"); 194shouldBeTrue("(function (){'use strict'; var local; (function (){local;})(); arguments[0]=true; return arguments; })()[0]"); 195 196shouldBeTrue("'use strict'; (function (){var a = true; eval('var a = false'); return a; })()"); 197shouldBeTrue("(function (){var a = true; eval('\"use strict\"; var a = false'); return a; })()"); 198 199shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(f.__proto__, 'arguments').value; })()"); 200shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(f.__proto__, 'caller').value; })()"); 201shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'callee').value; })()"); 202shouldBeUndefined("(function f(arg){'use strict'; return Object.getOwnPropertyDescriptor(arguments, 'caller').value; })()"); 203shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(arguments, 'caller'); return descriptor.get === descriptor.set; })()"); 204shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(arguments, 'callee'); return descriptor.get === descriptor.set; })()"); 205shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f.__proto__, 'caller'); return descriptor.get === descriptor.set; })()"); 206shouldBeTrue("(function f(arg){'use strict'; var descriptor = Object.getOwnPropertyDescriptor(f.__proto__, 'arguments'); return descriptor.get === descriptor.set; })()"); 207shouldBeTrue("'use strict'; (function f() { for(var i in this); })(); true;") 208 209shouldBeSyntaxError("'use strict'\u033b"); 210shouldBeSyntaxError("'use strict'5.f"); 211shouldBeSyntaxError("'use strict';\u033b"); 212shouldBeSyntaxError("'use strict';5.f"); 213shouldBeSyntaxError("'use strict';1-(eval=1);"); 214shouldBeSyntaxError("'use strict';arguments=1;"); 215shouldBeSyntaxError("'use strict';1-(arguments=1);"); 216shouldBeSyntaxError("'use strict';var a=(eval=1);"); 217shouldBeSyntaxError("'use strict';var a=(arguments=1);"); 218 219var aGlobal = false; 220shouldBeTrue("'use strict'; try { throw 1; } catch (e) { aGlobal = true; }"); 221aGlobal = false; 222shouldBeTrue("'use strict'; (function () { try { throw 1; } catch (e) { aGlobal = true; }})(); aGlobal;"); 223aGlobal = false; 224shouldBeTrue("(function () {'use strict'; try { throw 1; } catch (e) { aGlobal = true; }})(); aGlobal;"); 225aGlobal = false; 226shouldBeTrue("try { throw 1; } catch (e) { aGlobal = true; }"); 227aGlobal = false; 228shouldBeTrue("(function () { try { throw 1; } catch (e) { aGlobal = true; }})(); aGlobal;"); 229aGlobal = false; 230shouldBeTrue("(function () {try { throw 1; } catch (e) { aGlobal = true; }})(); aGlobal;"); 231 232// Make sure this doesn't crash! 233shouldBe('String(Object.getOwnPropertyDescriptor((function() { "use strict"; }).__proto__, "caller").get)', "'function () {\\n [native code]\\n}'"); 234