Chromium Code Reviews| Index: test/cctest/test-parsing.cc |
| diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc |
| index 550ac17a060eccc728c6f92cc5c151475e55b4bc..7fddc01657d5cf684f39a27dac30808526c40761 100644 |
| --- a/test/cctest/test-parsing.cc |
| +++ b/test/cctest/test-parsing.cc |
| @@ -37,6 +37,7 @@ |
| #include "src/objects.h" |
| #include "src/parser.h" |
| #include "src/preparser.h" |
| +#include "src/rewriter.h" |
| #include "src/scanner-character-streams.h" |
| #include "src/token.h" |
| #include "src/utils.h" |
| @@ -2549,3 +2550,108 @@ TEST(FuncNameInferrerEscaped) { |
| i::DeleteArray(two_byte_source); |
| i::DeleteArray(two_byte_name); |
| } |
| + |
| + |
| +TEST(InnerAssignment) { |
| + i::Isolate* isolate = CcTest::i_isolate(); |
| + i::Factory* factory = isolate->factory(); |
| + i::HandleScope scope(isolate); |
| + LocalContext env; |
| + |
| + const char* prefix = "function f() {"; |
| + const char* midfix = " function g() {"; |
| + const char* suffix = "}}"; |
| + struct { const char* source; bool strict; } outers[] = { |
| + { "var x;", false }, |
| + { "var x = 5;", false }, |
| + { "var x; x = 5;", false }, |
| + { "var x; var x = 5;", false }, |
| + { "'use strict'; let x;", true }, |
| + { "'use strict'; let x = 6;", true }, |
| + { "'use strict'; let x; x = 6;", true }, |
| + { "function x() {}", false }, |
| + }; |
| + struct { const char* source; bool assigned; } inners[] = { |
| + { "x = 1;", true }, |
| + { "x++;", true }, |
| + { "++x;", true }, |
| + { "x--;", true }, |
| + { "--x;", true }, |
| + { "{ x = 1; }", true }, |
| + { "'use strict'; { let x; }; x = 0;", true }, |
| + { "'use strict'; { const x = 1; }; x = 0;", true }, |
| + { "'use strict'; { function x() {} }; x = 0;", true }, |
| + { "with ({}) { x = 1; }", true }, |
| + { "eval('');", true }, |
| + { "'use strict'; { let y; eval('') }", true }, |
| + { "function h() { x = 0; }", true }, |
| + { "(function() { x = 0; })", true }, |
| + { "(function() { x = 0; })", true }, |
| + { "with ({}) (function() { x = 0; })", true }, |
| + { "", false }, |
| + { "x;", false }, |
| + { "var x;", false }, |
| + { "var x = 8;", false }, |
| + { "var x; x = 8;", false }, |
| + { "'use strict'; let x;", false }, |
| + { "'use strict'; let x = 8;", false }, |
| + { "'use strict'; let x; x = 8;", false }, |
| + { "'use strict'; const x = 8;", false }, |
| + { "function x() {}", false }, |
| + { "function x() { x = 0; }", false }, |
| + { "'use strict'; { let x; x = 0; }", false }, |
| + { "{ var x; }; x = 0;", false }, |
| + { "with ({}) {}", false }, |
| + { "var x; { with ({}) { x = 1; } }", false }, |
| + { "try {} catch(x) { x = 0; }", false }, |
| + { "try {} catch(x) { with ({}) { x = 1; } }", false }, |
| + // For simplicity, eval unconditionally sets flag to true. |
| + { "var x; { eval('') }", true }, |
| + { "'use strict'; let x; { eval('') }", true }, |
| + { "'use strict'; { let x; eval('') }", true }, |
| + { "try {} catch(x) { eval(''); }", true }, |
| + }; |
| + i::Handle<i::String> var_name = |
| + factory->NewStringFromUtf8(i::CStrVector("x")).ToHandleChecked(); |
|
titzer
2014/06/23 13:03:19
factory->InternalizeUtf8String()?
rossberg
2014/06/24 13:40:43
Done (also below).
|
| + |
| + int prefix_len = Utf8LengthHelper(prefix); |
| + int midfix_len = Utf8LengthHelper(midfix); |
| + int suffix_len = Utf8LengthHelper(suffix); |
| + for (unsigned i = 0; i < ARRAY_SIZE(outers); ++i) { |
| + const char* outer = outers[i].source; |
| + int outer_len = Utf8LengthHelper(outer); |
| + for (unsigned j = 0; j < ARRAY_SIZE(inners); ++j) { |
| + const char* inner = inners[j].source; |
| + int inner_len = Utf8LengthHelper(inner); |
| + int len = prefix_len + outer_len + midfix_len + inner_len + suffix_len; |
| + i::ScopedVector<char> program(len + 1); |
| + i::SNPrintF(program, "%s%s%s%s%s", prefix, outer, midfix, inner, suffix); |
| + i::Handle<i::String> source = factory->NewStringFromUtf8( |
| + i::CStrVector(program.start())).ToHandleChecked(); |
| + |
| + i::Handle<i::Script> script = factory->NewScript(source); |
| + i::CompilationInfoWithZone info(script); |
| + i::Parser parser(&info); |
| + parser.set_allow_harmony_scoping(true); |
| + if (!parser.Parse()) { |
| + // Some combinations (strict + with) cause static errors, ignore. |
| + ASSERT(outers[i].strict); |
| + printf("Skipping "); |
| + source->Print(); |
| + printf("\n"); |
| + continue; |
| + } |
| + CHECK(i::Rewriter::Rewrite(&info)); |
| + CHECK(i::Scope::Analyze(&info)); |
| + CHECK(info.function() != NULL); |
| + |
| + i::Scope* scope = info.function()->scope(); |
| + CHECK_EQ(scope->inner_scopes()->length(), 1); |
| + i::Scope* inner_scope = scope->inner_scopes()->at(0); |
| + i::Variable* var = inner_scope->Lookup(var_name); |
| + CHECK(var != NULL); |
| + CHECK(var->is_used() || !inners[j].assigned); |
| + CHECK(var->is_assigned_in_inner_function() == inners[j].assigned); |
| + } |
| + } |
| +} |