OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 the V8 project authors. All rights reserved. | |
vogelheim
2017/02/07 09:11:23
I'd be slightly happier if this file were in the p
marja
2017/02/07 13:38:14
Done.
| |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "src/ast/ast.h" | |
6 #include "src/compiler.h" | |
7 #include "src/objects-inl.h" | |
8 #include "src/parsing/parse-info.h" | |
9 #include "src/parsing/parsing.h" | |
10 | |
11 #include "test/cctest/cctest.h" | |
12 #include "test/cctest/scope-test-helper.h" | |
13 #include "test/cctest/unicode-helpers.h" | |
14 | |
15 TEST(PreParserScopeAnalysis) { | |
16 i::FLAG_lazy_inner_functions = true; | |
17 i::FLAG_preparser_scope_analysis = true; | |
18 i::Isolate* isolate = CcTest::i_isolate(); | |
19 i::Factory* factory = isolate->factory(); | |
20 i::HandleScope scope(isolate); | |
21 LocalContext env; | |
22 | |
23 const char* prefix = "(function outer() { "; | |
24 const char* suffix = " })();"; | |
25 int prefix_len = Utf8LengthHelper(prefix); | |
26 int suffix_len = Utf8LengthHelper(suffix); | |
vogelheim
2017/02/07 09:11:23
nitpick, and entirely unrelated to this CL: With t
marja
2017/02/07 13:38:14
Lol, this was some brainless copy paste...
Howeve
| |
27 | |
28 // The scope start positions must match; note the extra space in lazy_inner. | |
29 const char* lazy_inner = " function inner(%s) { %s }"; | |
30 const char* eager_inner = "(function inner(%s) { %s })()"; | |
31 | |
32 struct { | |
33 const char* params; | |
34 const char* source; | |
35 } inners[] = { | |
36 // Simple cases | |
37 {"", "var1;"}, | |
38 {"", "var1 = 5;"}, | |
39 {"", "if (true) {}"}, | |
40 {"", "function f1() {}"}, | |
41 | |
42 // Var declarations and assignments. | |
43 {"", "var var1;"}, | |
44 {"", "var var1; var1 = 5;"}, | |
45 {"", "if (true) { var var1; }"}, | |
46 {"", "if (true) { var var1; var1 = 5; }"}, | |
47 {"", "var var1; function f() { var1; }"}, | |
48 {"", "var var1; var1 = 5; function f() { var1; }"}, | |
49 {"", "var var1; function f() { var1 = 5; }"}, | |
50 | |
51 // Let declarations and assignments. | |
52 {"", "let var1;"}, | |
53 {"", "let var1; var1 = 5;"}, | |
54 {"", "if (true) { let var1; }"}, | |
55 {"", "if (true) { let var1; var1 = 5; }"}, | |
56 {"", "let var1; function f() { var1; }"}, | |
57 {"", "let var1; var1 = 5; function f() { var1; }"}, | |
58 {"", "let var1; function f() { var1 = 5; }"}, | |
59 | |
60 // Const declarations. | |
61 {"", "const var1 = 5;"}, | |
62 {"", "if (true) { const var1 = 5; }"}, | |
63 {"", "const var1 = 5; function f() { var1; }"}, | |
64 | |
65 // Redeclarations. | |
66 {"", "var var1; var var1;"}, | |
67 {"", "var var1; var var1; var1 = 5;"}, | |
68 {"", "var var1; if (true) { var var1; }"}, | |
69 {"", "if (true) { var var1; var var1; }"}, | |
70 {"", "var var1; if (true) { var var1; var1 = 5; }"}, | |
71 {"", "if (true) { var var1; var var1; var1 = 5; }"}, | |
72 {"", "var var1; var var1; function f() { var1; }"}, | |
73 {"", "var var1; var var1; function f() { var1 = 5; }"}, | |
74 | |
75 // Shadowing declarations. | |
76 {"", "var var1; if (true) { var var1; }"}, | |
77 {"", "var var1; if (true) { let var1; }"}, | |
78 {"", "let var1; if (true) { let var1; }"}, | |
79 | |
80 {"", "var var1; if (true) { const var1 = 0; }"}, | |
81 {"", "const var1 = 0; if (true) { const var1 = 0; }"}, | |
82 | |
83 // Arguments and this. | |
84 {"", "arguments;"}, | |
85 {"", "arguments = 5;"}, | |
86 {"", "if (true) { arguments; }"}, | |
87 {"", "if (true) { arguments = 5; }"}, | |
88 {"", "function f() { arguments; }"}, | |
89 {"", "function f() { arguments = 5; }"}, | |
90 | |
91 {"", "this;"}, | |
92 {"", "if (true) { this; }"}, | |
93 {"", "function f() { this; }"}, | |
94 | |
95 // Variable called "arguments" | |
96 {"", "var arguments;"}, | |
97 {"", "var arguments; arguments = 5;"}, | |
98 {"", "if (true) { var arguments; }"}, | |
99 {"", "if (true) { var arguments; arguments = 5; }"}, | |
100 {"", "var arguments; function f() { arguments; }"}, | |
101 {"", "var arguments; arguments = 5; function f() { arguments; }"}, | |
102 {"", "var arguments; function f() { arguments = 5; }"}, | |
103 | |
104 {"", "let arguments;"}, | |
105 {"", "let arguments; arguments = 5;"}, | |
106 {"", "if (true) { let arguments; }"}, | |
107 {"", "if (true) { let arguments; arguments = 5; }"}, | |
108 {"", "let arguments; function f() { arguments; }"}, | |
109 {"", "let arguments; arguments = 5; function f() { arguments; }"}, | |
110 {"", "let arguments; function f() { arguments = 5; }"}, | |
111 | |
112 {"", "const arguments = 5;"}, | |
113 {"", "if (true) { const arguments = 5; }"}, | |
114 {"", "const arguments = 5; function f() { arguments; }"}, | |
115 | |
116 // Destructuring declarations. | |
117 {"", "var [var1, var2] = [1, 2];"}, | |
118 {"", "var [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"}, | |
119 {"", "var [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"}, | |
120 {"", "var [var1, ...var2] = [1, 2, 3];"}, | |
121 | |
122 {"", "var {var1: var2, var3: var4} = {var1: 1, var3: 2};"}, | |
123 {"", | |
124 "var {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"}, | |
125 {"", "var {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"}, | |
126 | |
127 {"", "let [var1, var2] = [1, 2];"}, | |
128 {"", "let [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"}, | |
129 {"", "let [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"}, | |
130 {"", "let [var1, ...var2] = [1, 2, 3];"}, | |
131 | |
132 {"", "let {var1: var2, var3: var4} = {var1: 1, var3: 2};"}, | |
133 {"", | |
134 "let {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"}, | |
135 {"", "let {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"}, | |
136 | |
137 {"", "const [var1, var2] = [1, 2];"}, | |
138 {"", "const [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"}, | |
139 {"", "const [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"}, | |
140 {"", "const [var1, ...var2] = [1, 2, 3];"}, | |
141 | |
142 {"", "const {var1: var2, var3: var4} = {var1: 1, var3: 2};"}, | |
143 {"", | |
144 "const {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"}, | |
145 {"", "const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"}, | |
146 | |
147 // Referencing the function variable. | |
148 {"", "inner;"}, | |
149 {"", "function f1() { f1; }"}, | |
150 {"", "function f1() { inner; }"}, | |
151 {"", "function f1() { function f2() { f1; } }"}, | |
152 {"", "function arguments() {}"}, | |
153 {"", "function f1() {} function f1() {}"}, | |
154 {"", "var f1; function f1() {}"}, | |
155 | |
156 // Assigning to the function variable. | |
157 {"", "inner = 3;"}, | |
158 {"", "function f1() { f1 = 3; }"}, | |
159 {"", "function f1() { f1; } f1 = 3;"}, | |
160 {"", "function arguments() {} arguments = 8"}, | |
161 {"", "function f1() {} f1 = 3; function f1() {}"}, | |
162 | |
163 // Evals. | |
164 {"", "var var1; eval('');"}, | |
165 {"", "var var1; function f1() { eval(''); }"}, | |
166 {"", "let var1; eval('');"}, | |
167 {"", "let var1; function f1() { eval(''); }"}, | |
168 {"", "const var1 = 10; eval('');"}, | |
169 {"", "const var1 = 10; function f1() { eval(''); }"}, | |
170 | |
171 // Standard for loops. | |
172 {"", "for (var var1 = 0; var1 < 10; ++var1) { }"}, | |
173 {"", "for (let var1 = 0; var1 < 10; ++var1) { }"}, | |
174 {"", "for (const var1 = 0; var1 < 10; ++var1) { }"}, | |
175 | |
176 {"", | |
177 "for (var var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"}, | |
178 {"", | |
179 "for (let var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"}, | |
180 {"", | |
181 "for (const var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"}, | |
182 {"", | |
183 "'use strict'; for (var var1 = 0; var1 < 10; ++var1) { function foo() { " | |
184 "var1; } }"}, | |
185 {"", | |
186 "'use strict'; for (let var1 = 0; var1 < 10; ++var1) { function foo() { " | |
187 "var1; } }"}, | |
188 {"", | |
189 "'use strict'; for (const var1 = 0; var1 < 10; ++var1) { function foo() " | |
190 "{ var1; } }"}, | |
191 | |
192 // For of loops | |
193 {"", "for (var1 of [1, 2]) { }"}, | |
194 {"", "for (var var1 of [1, 2]) { }"}, | |
195 {"", "for (let var1 of [1, 2]) { }"}, | |
196 {"", "for (const var1 of [1, 2]) { }"}, | |
197 | |
198 {"", "for (var1 of [1, 2]) { var1; }"}, | |
199 {"", "for (var var1 of [1, 2]) { var1; }"}, | |
200 {"", "for (let var1 of [1, 2]) { var1; }"}, | |
201 {"", "for (const var1 of [1, 2]) { var1; }"}, | |
202 | |
203 {"", "for (var1 of [1, 2]) { var1 = 0; }"}, | |
204 {"", "for (var var1 of [1, 2]) { var1 = 0; }"}, | |
205 {"", "for (let var1 of [1, 2]) { var1 = 0; }"}, | |
206 {"", "for (const var1 of [1, 2]) { var1 = 0; }"}, | |
207 | |
208 {"", "for (var1 of [1, 2]) { function foo() { var1; } }"}, | |
209 {"", "for (var var1 of [1, 2]) { function foo() { var1; } }"}, | |
210 {"", "for (let var1 of [1, 2]) { function foo() { var1; } }"}, | |
211 {"", "for (const var1 of [1, 2]) { function foo() { var1; } }"}, | |
212 | |
213 {"", "for (var1 of [1, 2]) { function foo() { var1 = 0; } }"}, | |
214 {"", "for (var var1 of [1, 2]) { function foo() { var1 = 0; } }"}, | |
215 {"", "for (let var1 of [1, 2]) { function foo() { var1 = 0; } }"}, | |
216 {"", "for (const var1 of [1, 2]) { function foo() { var1 = 0; } }"}, | |
217 | |
218 // For in loops | |
219 {"", "for (var1 in {a: 6}) { }"}, | |
220 {"", "for (var var1 in {a: 6}) { }"}, | |
221 {"", "for (let var1 in {a: 6}) { }"}, | |
222 {"", "for (const var1 in {a: 6}) { }"}, | |
223 | |
224 {"", "for (var1 in {a: 6}) { var1; }"}, | |
225 {"", "for (var var1 in {a: 6}) { var1; }"}, | |
226 {"", "for (let var1 in {a: 6}) { var1; }"}, | |
227 {"", "for (const var1 in {a: 6}) { var1; }"}, | |
228 | |
229 {"", "for (var1 in {a: 6}) { var1 = 0; }"}, | |
230 {"", "for (var var1 in {a: 6}) { var1 = 0; }"}, | |
231 {"", "for (let var1 in {a: 6}) { var1 = 0; }"}, | |
232 {"", "for (const var1 in {a: 6}) { var1 = 0; }"}, | |
233 | |
234 {"", "for (var1 in {a: 6}) { function foo() { var1; } }"}, | |
235 {"", "for (var var1 in {a: 6}) { function foo() { var1; } }"}, | |
236 {"", "for (let var1 in {a: 6}) { function foo() { var1; } }"}, | |
237 {"", "for (const var1 in {a: 6}) { function foo() { var1; } }"}, | |
238 | |
239 {"", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
240 {"", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
241 {"", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
242 {"", "for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
243 | |
244 {"", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
245 {"", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
246 {"", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
247 {"", "for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"}, | |
248 | |
249 // Loops without declarations | |
250 {"", "var var1 = 0; for ( ; var1 < 2; ++var1) { }"}, | |
251 {"", | |
252 "var var1 = 0; for ( ; var1 < 2; ++var1) { function foo() { var1; } }"}, | |
253 {"", "var var1 = 0; for ( ; var1 > 2; ) { }"}, | |
254 {"", "var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1; } }"}, | |
255 {"", | |
256 "var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1 = 6; } }"}, | |
257 | |
258 {"", "var var1 = 0; for(var1; var1 < 2; ++var1) { }"}, | |
259 {"", | |
260 "var var1 = 0; for (var1; var1 < 2; ++var1) { function foo() { var1; } " | |
261 "}"}, | |
262 {"", "var var1 = 0; for (var1; var1 > 2; ) { }"}, | |
263 {"", "var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1; } }"}, | |
264 {"", | |
265 "var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1 = 6; } }"}, | |
266 | |
267 // Sloppy block functions. | |
268 {"", "if (true) { function f1() {} }"}, | |
269 {"", "if (true) { function f1() {} function f1() {} }"}, | |
270 {"", "if (true) { if (true) { function f1() {} } }"}, | |
271 {"", "if (true) { if (true) { function f1() {} function f1() {} } }"}, | |
272 {"", "if (true) { function f1() {} f1 = 3; }"}, | |
273 | |
274 {"", "if (true) { function f1() {} function foo() { f1; } }"}, | |
275 {"", "if (true) { function f1() {} } function foo() { f1; }"}, | |
276 {"", | |
277 "if (true) { function f1() {} function f1() {} function foo() { f1; } " | |
278 "}"}, | |
279 {"", | |
280 "if (true) { function f1() {} function f1() {} } function foo() { f1; " | |
281 "}"}, | |
282 {"", | |
283 "if (true) { if (true) { function f1() {} } function foo() { f1; } }"}, | |
284 {"", | |
285 "if (true) { if (true) { function f1() {} function f1() {} } function " | |
286 "foo() { f1; } }"}, | |
287 {"", "if (true) { function f1() {} f1 = 3; function foo() { f1; } }"}, | |
288 {"", "if (true) { function f1() {} f1 = 3; } function foo() { f1; }"}, | |
289 | |
290 {"", "function inner2() { if (true) { function f1() {} } }"}, | |
291 {"", "function inner2() { if (true) { function f1() {} f1 = 3; } }"}, | |
292 | |
293 {"", "var f1 = 1; if (true) { function f1() {} }"}, | |
294 {"", "var f1 = 1; if (true) { function f1() {} } function foo() { f1; }"}, | |
295 }; | |
296 | |
297 for (unsigned i = 0; i < arraysize(inners); ++i) { | |
298 // First compile with the lazy inner function and extract the scope data. | |
299 const char* inner_function = lazy_inner; | |
300 int inner_function_len = Utf8LengthHelper(inner_function) - 4; | |
301 | |
302 int params_len = Utf8LengthHelper(inners[i].params); | |
303 int source_len = Utf8LengthHelper(inners[i].source); | |
304 int len = | |
305 prefix_len + inner_function_len + params_len + source_len + suffix_len; | |
306 | |
307 i::ScopedVector<char> lazy_program(len + 1); | |
308 i::SNPrintF(lazy_program, "%s", prefix); | |
309 i::SNPrintF(lazy_program + prefix_len, inner_function, inners[i].params, | |
310 inners[i].source); | |
311 i::SNPrintF(lazy_program + prefix_len + inner_function_len + params_len + | |
312 source_len, | |
313 "%s", suffix); | |
314 | |
315 i::Handle<i::String> source = | |
316 factory->InternalizeUtf8String(lazy_program.start()); | |
317 source->PrintOn(stdout); | |
318 printf("\n"); | |
319 | |
320 i::Handle<i::Script> script = factory->NewScript(source); | |
321 i::Zone zone(CcTest::i_isolate()->allocator(), ZONE_NAME); | |
322 i::ParseInfo lazy_info(&zone, script); | |
323 | |
324 // No need to run scope analysis; preparser scope data is produced when | |
325 // parsing. | |
326 CHECK(i::parsing::ParseProgram(&lazy_info)); | |
327 | |
328 // Then parse eagerly and check against the scope data. | |
329 inner_function = eager_inner; | |
330 inner_function_len = Utf8LengthHelper(inner_function) - 4; | |
331 len = | |
332 prefix_len + inner_function_len + params_len + source_len + suffix_len; | |
333 | |
334 i::ScopedVector<char> eager_program(len + 1); | |
335 i::SNPrintF(eager_program, "%s", prefix); | |
336 i::SNPrintF(eager_program + prefix_len, inner_function, inners[i].params, | |
337 inners[i].source); | |
338 i::SNPrintF(eager_program + prefix_len + inner_function_len + params_len + | |
339 source_len, | |
340 "%s", suffix); | |
341 | |
342 source = factory->InternalizeUtf8String(eager_program.start()); | |
343 source->PrintOn(stdout); | |
344 printf("\n"); | |
345 | |
346 script = factory->NewScript(source); | |
347 i::ParseInfo eager_info(&zone, script); | |
348 eager_info.set_allow_lazy_parsing(false); | |
349 | |
350 CHECK(i::parsing::ParseProgram(&eager_info)); | |
351 CHECK(i::Compiler::Analyze(&eager_info)); | |
352 | |
353 i::Scope* scope = | |
354 eager_info.literal()->scope()->inner_scope()->inner_scope(); | |
355 DCHECK_NOT_NULL(scope); | |
356 DCHECK_NULL(scope->sibling()); | |
357 DCHECK(scope->is_function_scope()); | |
358 | |
359 size_t index = 0; | |
360 i::ScopeTestHelper::CompareScopeToData( | |
361 scope, lazy_info.preparsed_scope_data(), index); | |
362 } | |
363 } | |
OLD | NEW |