OLD | NEW |
| (Empty) |
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 | |
6 "use strict" | |
7 | |
8 let prologue_dead = "(function outer() { if (false) { "; | |
9 let epilogue_dead = " } })();"; | |
10 | |
11 let prologue_live = "(function outer() { "; | |
12 let epilogue_live = "})();"; | |
13 | |
14 // For code which already throws a run-time error in non-strong mode; we assert | |
15 // that we now get the error already compilation time. | |
16 function assertLateErrorsBecomeEarly(code) { | |
17 assertThrows("'use strong'; " + prologue_dead + code + epilogue_dead, | |
18 ReferenceError); | |
19 | |
20 // Make sure the error happens only in strong mode (note that we need strict | |
21 // mode here because of let). | |
22 assertDoesNotThrow("'use strict'; " + prologue_dead + code + epilogue_dead); | |
23 | |
24 // But if we don't put the references inside a dead code, it throws a run-time | |
25 // error (also in strict mode). | |
26 assertThrows("'use strong'; " + prologue_live + code + epilogue_live, | |
27 ReferenceError); | |
28 assertThrows("'use strict'; " + prologue_live + code + epilogue_live, | |
29 ReferenceError); | |
30 } | |
31 | |
32 // For code which doesn't throw an error at all in non-strong mode. | |
33 function assertNonErrorsBecomeEarly(code) { | |
34 assertThrows("'use strong'; " + prologue_dead + code + epilogue_dead, | |
35 ReferenceError); | |
36 assertDoesNotThrow("'use strict'; " + prologue_dead + code + epilogue_dead); | |
37 | |
38 assertThrows("'use strong'; " + prologue_live + code + epilogue_live, | |
39 ReferenceError); | |
40 assertDoesNotThrow("'use strict'; " + prologue_live + code + epilogue_live, | |
41 ReferenceError); | |
42 } | |
43 | |
44 (function InitTimeReferenceForward() { | |
45 // It's never OK to have an init time reference to a class which hasn't been | |
46 // declared. | |
47 assertLateErrorsBecomeEarly( | |
48 `class A extends B { } | |
49 class B {}`); | |
50 | |
51 assertLateErrorsBecomeEarly( | |
52 `class A { | |
53 [B.sm()]() { } | |
54 } | |
55 class B { | |
56 static sm() { return 0; } | |
57 }`); | |
58 })(); | |
59 | |
60 (function InitTimeReferenceBackward() { | |
61 // Backwards is of course fine. | |
62 "use strong"; | |
63 class A { | |
64 static sm() { return 0; } | |
65 } | |
66 let i = "making these classes non-consecutive"; | |
67 class B extends A {}; | |
68 "by inserting statements and declarations in between"; | |
69 class C { | |
70 [A.sm()]() { } | |
71 }; | |
72 })(); | |
73 | |
74 (function BasicMutualRecursion() { | |
75 "use strong"; | |
76 class A { | |
77 m() { B; } | |
78 static sm() { B; } | |
79 } | |
80 // No statements or declarations between the classes. | |
81 class B { | |
82 m() { A; } | |
83 static sm() { A; } | |
84 } | |
85 })(); | |
86 | |
87 (function MutualRecursionWithMoreClasses() { | |
88 "use strong"; | |
89 class A { | |
90 m() { B; C; } | |
91 static sm() { B; C; } | |
92 } | |
93 class B { | |
94 m() { A; C; } | |
95 static sm() { A; C; } | |
96 } | |
97 class C { | |
98 m() { A; B; } | |
99 static sm() { A; B; } | |
100 } | |
101 })(); | |
102 | |
103 (function ReferringForwardInDeeperScopes() { | |
104 "use strong"; | |
105 | |
106 function foo() { | |
107 class A1 { | |
108 m() { B1; } | |
109 } | |
110 class B1 { } | |
111 } | |
112 | |
113 class Outer { | |
114 m() { | |
115 class A2 { | |
116 m() { B2; } | |
117 } | |
118 class B2 { } | |
119 } | |
120 } | |
121 | |
122 for (let i = 0; i < 1; ++i) { | |
123 class A3 { | |
124 m() { B3; } | |
125 } | |
126 class B3 { } | |
127 } | |
128 | |
129 (a, b) => { | |
130 class A4 { | |
131 m() { B4; } | |
132 } | |
133 class B4 { } | |
134 } | |
135 })(); | |
136 | |
137 (function ReferringForwardButClassesNotConsecutive() { | |
138 assertNonErrorsBecomeEarly( | |
139 `class A { | |
140 m() { B; } | |
141 } | |
142 ; | |
143 class B {}`); | |
144 | |
145 assertNonErrorsBecomeEarly( | |
146 `let A = class { | |
147 m() { B; } | |
148 } | |
149 class B {}`); | |
150 | |
151 assertNonErrorsBecomeEarly( | |
152 `class A { | |
153 m() { B1; } // Just a normal use-before-declaration. | |
154 } | |
155 let B1 = class B2 {}`); | |
156 | |
157 assertNonErrorsBecomeEarly( | |
158 `class A { | |
159 m() { B; } | |
160 } | |
161 let i = 0; | |
162 class B {}`); | |
163 | |
164 assertNonErrorsBecomeEarly( | |
165 `class A { | |
166 m() { B; } | |
167 } | |
168 function foo() {} | |
169 class B {}`); | |
170 | |
171 assertNonErrorsBecomeEarly( | |
172 `function foo() { | |
173 class A { | |
174 m() { B; } | |
175 } | |
176 } | |
177 class B {}`); | |
178 | |
179 assertNonErrorsBecomeEarly( | |
180 `class A extends class B { m() { C; } } { | |
181 } | |
182 class C { }`); | |
183 | |
184 assertLateErrorsBecomeEarly( | |
185 `class A extends class B { [C.sm()]() { } } { | |
186 } | |
187 class C { static sm() { return 'a';} }`); | |
188 | |
189 assertLateErrorsBecomeEarly( | |
190 `class A extends class B extends C { } { | |
191 } | |
192 class C { }`); | |
193 })(); | |
194 | |
195 | |
196 (function RegressionForClassResolution() { | |
197 assertNonErrorsBecomeEarly( | |
198 `let A = class B { | |
199 m() { C; } | |
200 } | |
201 ;;;; | |
202 class C {} | |
203 class B {}`); | |
204 })(); | |
205 | |
206 | |
207 (function TestMultipleMethodScopes() { | |
208 "use strong"; | |
209 | |
210 // Test cases where the reference is inside multiple method scopes. | |
211 class A1 { | |
212 m() { | |
213 class C1 { | |
214 m() { B1; } | |
215 } | |
216 } | |
217 } | |
218 class B1 { } | |
219 | |
220 ; | |
221 | |
222 class A2 { | |
223 m() { | |
224 class C2 extends B2 { | |
225 } | |
226 } | |
227 } | |
228 class B2 { } | |
229 })(); | |
OLD | NEW |