deps: update v8 to 4.3.61.21
[platform/upstream/nodejs.git] / deps / v8 / test / mjsunit / strong / declaration-after-use.js
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Flags: --strong-mode --harmony_rest_parameters --harmony_arrow_functions --harmony_classes --harmony_computed-property_names
6
7 // Note that it's essential for these tests that the reference is inside dead
8 // code (because we already produce ReferenceErrors for run-time unresolved
9 // variables and don't want to confuse those with strong mode errors). But the
10 // errors should *not* be inside lazy, unexecuted functions, since lazy parsing
11 // doesn't produce strong mode scoping errors).
12
13 // In addition, assertThrows will call eval and that changes variable binding
14 // types (see e.g., UNBOUND_EVAL_SHADOWED). We can avoid unwanted side effects
15 // by wrapping the code to be tested inside an outer function.
16 function assertThrowsHelper(code) {
17   "use strict";
18   let prologue = "(function outer() { if (false) { ";
19   let epilogue = " } })();";
20
21   assertThrows("'use strong'; " + prologue + code + epilogue, ReferenceError);
22
23   // Make sure the error happens only in strong mode (note that we need strict
24   // mode here because of let).
25   assertDoesNotThrow("'use strict'; " + prologue + code + epilogue);
26 }
27
28 (function DeclarationAfterUse() {
29   // Note that these tests only test cases where the declaration is found but is
30   // after the use. In particular, we cannot yet detect cases where the use can
31   // possibly bind to a global variable.
32   assertThrowsHelper("x; let x = 0;");
33   assertThrowsHelper("function f() { x; let x = 0; }");
34   assertThrowsHelper("function f() { x; } let x = 0;");
35
36   // These tests needs to be done a bit more manually, since var is not allowed
37   // in strong mode:
38   assertThrows(
39       `(function outer() {
40         function f() { 'use strong'; if (false) { x; } } var x = 0; f();
41       })()`,
42       ReferenceError);
43   assertDoesNotThrow(
44       "(function outer() {\n" +
45       "  function f() { if (false) { x; } } var x = 0; f(); \n" +
46       "})()");
47
48   assertThrows(
49       "(function outer() {\n" +
50       "  function f() { 'use strong'; if (false) { x; } } var x; f(); \n" +
51       "})()",
52       ReferenceError);
53   assertDoesNotThrow(
54       "(function outer() {\n" +
55       "  function f() { if (false) { x; } } var x; f(); \n" +
56       "})()");
57
58   // Errors are also detected when the declaration and the use are in the same
59   // eval scope.
60   assertThrows("'use strong'; eval('if (false) { x; let x = 0;}')",
61                ReferenceError);
62   assertDoesNotThrow("'use strict'; eval('if (false) { x; let x = 0; }')");
63
64   // Use occurring in the initializer of the declaration:
65   assertThrowsHelper("let x = x + 1;");
66   assertThrowsHelper("let x = x;");
67   assertThrowsHelper("let x = y, y = 4;");
68   assertThrowsHelper("let x = function() { x; }");
69   assertThrowsHelper("let x = a => { x; }");
70   assertThrowsHelper("function f(x) { return x; }; let x = f(x);");
71   assertThrowsHelper("const x = x;");
72   assertThrowsHelper("const x = function() { x; }");
73   assertThrowsHelper("const x = a => { x; }");
74   assertThrowsHelper("function f(x) {return x}; const x = f(x);");
75
76   assertThrowsHelper("for (let x = x; ; ) { }");
77   assertThrowsHelper("for (const x = x; ; ) { }");
78   assertThrowsHelper("for (let x = y, y; ; ) { }");
79   assertThrowsHelper("for (const x = y, y = 0; ; ) { }");
80
81   // Computed property names
82   assertThrowsHelper("let o = { 'a': 'b', [o.a]: 'c'};");
83 })();
84
85
86 (function DeclarationAfterUseInClasses() {
87   assertThrowsHelper("class C extends C { }");
88   assertThrowsHelper("let C = class C2 extends C { }");
89   assertThrowsHelper("let C = class C2 extends C2 { }");
90
91   assertThrowsHelper("let C = class C2 { constructor() { C; } }");
92   assertThrowsHelper("let C = class C2 { method() { C; } }");
93   assertThrowsHelper("let C = class C2 { *generator_method() { C; } }");
94
95   assertThrowsHelper(
96       `let C = class C2 {
97         static a() { return 'A'; }
98         [C.a()]() { return 'B'; }
99       };`);
100
101   assertThrowsHelper(
102       `let C = class C2 {
103         static a() { return 'A'; }
104         [C2.a()]() { return 'B'; }
105       };`);
106
107   assertThrowsHelper(
108       `let C = class C2 {
109         [(function() { C; return 'A';})()]() { return 'B'; }
110       };`);
111
112   // The reference to C or C2 is inside a function, but not a method.
113   assertThrowsHelper(
114       `let C = class C2 {
115         [(function() { C2; return 'A';})()]() { return 'B'; }
116       };`);
117
118   assertThrowsHelper(
119       `let C = class C2 {
120         [(function() { C; return 'A';})()]() { return 'B'; }
121       };`);
122
123   // The reference to C or C2 is inside a method, but it's not a method of the
124   // relevant class (C2).
125   assertThrowsHelper(
126       `let C = class C2 {
127         [(new (class D { m() { C2; return 'A'; } })).m()]() {
128           return 'B';
129         }
130       }`);
131
132   assertThrowsHelper(
133       `let C = class C2 {
134         [(new (class D { m() { C; return 'A'; } })).m()]() {
135           return 'B';
136         }
137       }`);
138
139   assertThrowsHelper(
140       `let C = class C2 {
141         [({m() { C2; return 'A'; }}).m()]() { return 'B'; }
142       }`);
143
144   assertThrowsHelper(
145       `let C = class C2 {
146         [({m() { C; return 'A'; }}).m()]() { return 'B'; }
147       }`);
148
149   assertThrowsHelper(
150       `class COuter {
151         m() {
152           class CInner {
153             [({ m() { CInner; return 'A'; } }).m()]() {
154                 return 'B';
155             }
156           }
157         }
158       }`);
159 })();
160
161
162 (function UsesWhichAreFine() {
163   "use strong";
164
165   let var1 = 0;
166   var1;
167
168   let var2a = 0, var2b = var2a + 1, var2c = 2 + var2b;
169
170   for (let var3 = 0; var3 < 1; var3++) {
171     var3;
172   }
173
174   for (let var4a = 0, var4b = var4a; var4a + var4b < 4; var4a++, var4b++) {
175     var4a;
176     var4b;
177   }
178
179   let var5 = 5;
180   for (; var5 < 10; ++var5) { }
181
182   let arr = [1, 2];
183   for (let i of arr) {
184     i;
185   }
186
187   let var6 = [1, 2];
188   // The second var6 resolves to outside (not to the first var6).
189   for (let var6 of var6) { var6; }
190
191   try {
192     throw "error";
193   } catch (e) {
194     e;
195   }
196
197   function func1() { func1; this; }
198   func1();
199   func1;
200
201   function * func2() { func2; this; }
202   func2();
203   func2;
204
205   function func4(p, ...rest) { p; rest; this; func2; }
206   func4();
207
208   let func5 = (p1, p2) => { p1; p2; };
209   func5();
210
211   let func5b = p1 => p1;
212   func5b();
213
214   function func6() {
215     var1, var2a, var2b, var2c;
216   }
217
218   (function eval1() {
219     let var7 = 0; // Declaration position will be something large.
220     // But use position will be something small, however, this is not an error,
221     // since the use is inside an eval scope.
222     eval("var7;");
223   })();
224
225
226   class C1 { constructor() { C1; } }; new C1();
227   let C2 = class C3 { constructor() { C3; } }; new C2();
228
229   class C4 { method() { C4; } *generator_method() { C4; } }; new C4();
230   let C5 = class C6 { method() { C6; } *generator_method() { C6; } }; new C5();
231
232   class C7 { static method() { C7; } }; new C7();
233   let C8 = class C9 { static method() { C9; } }; new C8();
234
235   class C10 { get x() { C10; } }; new C10();
236   let C11 = class C12 { get x() { C12; } }; new C11();
237
238   // Regression test for unnamed classes.
239   let C13 = class { m() { var1; } };
240
241   class COuter {
242     m() {
243       class CInner {
244         // Here we can refer to COuter but not to CInner (see corresponding
245         // assertion test):
246         [({ m() { COuter; return 'A'; } }).m()]() { return 'B'; }
247         // And here we can refer to both:
248         n() { COuter; CInner; }
249       }
250       return new CInner();
251     }
252   }
253   (new COuter()).m().n();
254
255   // Making sure the check which is supposed to prevent "object literal inside
256   // computed property name references the class name" is not too generic:
257   class C14 { m() { let obj = { n() { C14 } }; obj.n(); } }; (new C14()).m();
258 })();