Chromium Code Reviews| 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 |