1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/js/src/tests/ecma_3/Function/scope-002.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,211 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * Date: 28 May 2001 1.11 + * 1.12 + * SUMMARY: Functions are scoped statically, not dynamically 1.13 + * 1.14 + * See ECMA Section 10.1.4 Scope Chain and Identifier Resolution 1.15 + * (This section defines the scope chain of an execution context) 1.16 + * 1.17 + * See ECMA Section 12.10 The with Statement 1.18 + * 1.19 + * See ECMA Section 13 Function Definition 1.20 + * (This section defines the scope chain of a function object as that 1.21 + * of the running execution context when the function was declared) 1.22 + * 1.23 + * Like scope-001.js, but using assignment var f = function expression 1.24 + * instead of a function declaration: function f() {} etc. 1.25 + */ 1.26 +//----------------------------------------------------------------------------- 1.27 +var UBound = 0; 1.28 +var BUGNUMBER = '(none)'; 1.29 +var summary = 'Testing that functions are scoped statically, not dynamically'; 1.30 +var self = this; // capture a reference to the global object 1.31 +var status = ''; 1.32 +var statusitems = [ ]; 1.33 +var actual = ''; 1.34 +var actualvalues = [ ]; 1.35 +var expect= ''; 1.36 +var expectedvalues = [ ]; 1.37 + 1.38 + 1.39 +/* 1.40 + * In this section the expected value is 1, not 2. 1.41 + * 1.42 + * Why? f captures its scope chain from when it's declared, and imposes that chain 1.43 + * when it's executed. In other words, f's scope chain is from when it was compiled. 1.44 + * Since f is a top-level function, this is the global object only. Hence 'a' resolves to 1. 1.45 + */ 1.46 +status = 'Section A of test'; 1.47 +var a = 1; 1.48 +var f = function () {return a;}; 1.49 +var obj = {a:2}; 1.50 +with (obj) 1.51 +{ 1.52 + actual = f(); 1.53 +} 1.54 +expect = 1; 1.55 +addThis(); 1.56 + 1.57 + 1.58 +/* 1.59 + * In this section the expected value is 2, not 1. That is because here 1.60 + * f's associated scope chain now includes 'obj' before the global object. 1.61 + */ 1.62 +status = 'Section B of test'; 1.63 +var a = 1; 1.64 +var obj = {a:2}; 1.65 +with (obj) 1.66 +{ 1.67 + var f = function () {return a;}; 1.68 + actual = f(); 1.69 +} 1.70 +expect = 2; 1.71 +addThis(); 1.72 + 1.73 + 1.74 +/* 1.75 + * Like Section B , except that we call f outside the with block. 1.76 + * By the principles explained above, we still expect 2 - 1.77 + */ 1.78 +status = 'Section C of test'; 1.79 +var a = 1; 1.80 +var obj = {a:2}; 1.81 +with (obj) 1.82 +{ 1.83 + var f = function () {return a;}; 1.84 +} 1.85 +actual = f(); 1.86 +expect = 2; 1.87 +addThis(); 1.88 + 1.89 + 1.90 +/* 1.91 + * Like Section C, but with one more level of indirection - 1.92 + */ 1.93 +status = 'Section D of test'; 1.94 +var a = 1; 1.95 +var obj = {a:2, obj:{a:3}}; 1.96 +with (obj) 1.97 +{ 1.98 + with (obj) 1.99 + { 1.100 + var f = function () {return a;}; 1.101 + } 1.102 +} 1.103 +actual = f(); 1.104 +expect = 3; 1.105 +addThis(); 1.106 + 1.107 + 1.108 +/* 1.109 + * Like Section C, but here we actually delete obj before calling f. 1.110 + * We still expect 2 - 1.111 + */ 1.112 +status = 'Section E of test'; 1.113 +var a = 1; 1.114 +var obj = {a:2}; 1.115 +with (obj) 1.116 +{ 1.117 + var f = function () {return a;}; 1.118 +} 1.119 +delete obj; 1.120 +actual = f(); 1.121 +expect = 2; 1.122 +addThis(); 1.123 + 1.124 + 1.125 +/* 1.126 + * Like Section E. Here we redefine obj and call f under with (obj) - 1.127 + * We still expect 2 - 1.128 + */ 1.129 +status = 'Section F of test'; 1.130 +var a = 1; 1.131 +var obj = {a:2}; 1.132 +with (obj) 1.133 +{ 1.134 + var f = function () {return a;}; 1.135 +} 1.136 +delete obj; 1.137 +var obj = {a:3}; 1.138 +with (obj) 1.139 +{ 1.140 + actual = f(); 1.141 +} 1.142 +expect = 2; // NOT 3 !!! 1.143 +addThis(); 1.144 + 1.145 + 1.146 +/* 1.147 + * Explicitly verify that f exists at global level, even though 1.148 + * it was defined under the with(obj) block - 1.149 + */ 1.150 +status = 'Section G of test'; 1.151 +var a = 1; 1.152 +var obj = {a:2}; 1.153 +with (obj) 1.154 +{ 1.155 + var f = function () {return a;}; 1.156 +} 1.157 +actual = String([obj.hasOwnProperty('f'), self.hasOwnProperty('f')]); 1.158 +expect = String([false, true]); 1.159 +addThis(); 1.160 + 1.161 + 1.162 +/* 1.163 + * Explicitly verify that f exists at global level, even though 1.164 + * it was defined under the with(obj) block - 1.165 + */ 1.166 +status = 'Section H of test'; 1.167 +var a = 1; 1.168 +var obj = {a:2}; 1.169 +with (obj) 1.170 +{ 1.171 + var f = function () {return a;}; 1.172 +} 1.173 +actual = String(['f' in obj, 'f' in self]); 1.174 +expect = String([false, true]); 1.175 +addThis(); 1.176 + 1.177 + 1.178 + 1.179 +//------------------------------------------------------------------------------------------------- 1.180 +test(); 1.181 +//------------------------------------------------------------------------------------------------- 1.182 + 1.183 + 1.184 +function addThis() 1.185 +{ 1.186 + statusitems[UBound] = status; 1.187 + actualvalues[UBound] = actual; 1.188 + expectedvalues[UBound] = expect; 1.189 + UBound++; 1.190 + resetTestVars(); 1.191 +} 1.192 + 1.193 + 1.194 +function resetTestVars() 1.195 +{ 1.196 + delete a; 1.197 + delete obj; 1.198 + delete f; 1.199 +} 1.200 + 1.201 + 1.202 +function test() 1.203 +{ 1.204 + enterFunc ('test'); 1.205 + printBugNumber(BUGNUMBER); 1.206 + printStatus (summary); 1.207 + 1.208 + for (var i = 0; i < UBound; i++) 1.209 + { 1.210 + reportCompare(expectedvalues[i], actualvalues[i], statusitems[i]); 1.211 + } 1.212 + 1.213 + exitFunc ('test'); 1.214 +}