Index: test/cctest/test-parsing.cc |
diff --git a/test/cctest/test-parsing.cc b/test/cctest/test-parsing.cc |
index f55a625d6b6b5ff72a18525c6ff2667d26c9025b..b82b7c44ac184ac143357001135ab96e3cc466d9 100644 |
--- a/test/cctest/test-parsing.cc |
+++ b/test/cctest/test-parsing.cc |
@@ -42,6 +42,7 @@ |
#include "src/scanner-character-streams.h" |
#include "src/token.h" |
#include "src/utils.h" |
+ |
#include "test/cctest/cctest.h" |
TEST(ScanKeywords) { |
@@ -2852,6 +2853,167 @@ TEST(RegressionLazyFunctionWithErrorWithArg) { |
} |
+TEST(SerializationOfMaybeAssignmentFlag) { |
+ i::Isolate* isolate = CcTest::i_isolate(); |
+ i::Factory* factory = isolate->factory(); |
+ i::HandleScope scope(isolate); |
+ LocalContext env; |
+ |
+ const char* src = |
+ "function h() {" |
+ " var result = [];" |
+ " function f() {" |
+ " result.push(2);" |
+ " }" |
+ " function assertResult(r) {" |
+ " f();" |
+ " result = [];" |
+ " }" |
+ " assertResult([2]);" |
+ " assertResult([2]);" |
+ " return f;" |
+ "};" |
+ "h();"; |
+ |
+ i::ScopedVector<char> program(Utf8LengthHelper(src) + 1); |
+ i::SNPrintF(program, "%s", src); |
+ i::Handle<i::String> source = factory->InternalizeUtf8String(program.start()); |
+ source->PrintOn(stdout); |
+ printf("\n"); |
+ i::Zone zone(isolate); |
+ v8::Local<v8::Value> v = CompileRun(src); |
+ i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); |
+ i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); |
+ i::Context* context = f->context(); |
+ i::AstValueFactory avf(&zone, isolate->heap()->HashSeed()); |
+ avf.Internalize(isolate); |
+ const i::AstRawString* name = avf.GetOneByteString("result"); |
+ i::Handle<i::String> str = name->string(); |
+ CHECK(str->IsInternalizedString()); |
+ i::Scope* global_scope = |
+ new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone); |
+ global_scope->Initialize(); |
+ i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone); |
+ ASSERT(s != global_scope); |
+ ASSERT(name != NULL); |
+ |
+ // Get result from h's function context (that is f's context) |
+ i::Variable* var = s->Lookup(name); |
+ |
+ CHECK(var != NULL); |
+ // Maybe assigned should survive deserialization |
+ CHECK(var->maybe_assigned() == i::kMaybeAssigned); |
+ // TODO(sigurds) Figure out if is_used should survive context serialization. |
+} |
+ |
+ |
+TEST(IfArgumentsArrayAccessedThenParametersMaybeAssigned) { |
+ i::Isolate* isolate = CcTest::i_isolate(); |
+ i::Factory* factory = isolate->factory(); |
+ i::HandleScope scope(isolate); |
+ LocalContext env; |
+ |
+ |
+ const char* src = |
+ "function f(x) {" |
+ " var a = arguments;" |
+ " function g(i) {" |
+ " ++a[0];" |
+ " };" |
+ " return g;" |
+ " }" |
+ "f(0);"; |
+ |
+ i::ScopedVector<char> program(Utf8LengthHelper(src) + 1); |
+ i::SNPrintF(program, "%s", src); |
+ i::Handle<i::String> source = factory->InternalizeUtf8String(program.start()); |
+ source->PrintOn(stdout); |
+ printf("\n"); |
+ i::Zone zone(isolate); |
+ v8::Local<v8::Value> v = CompileRun(src); |
+ i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); |
+ i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); |
+ i::Context* context = f->context(); |
+ i::AstValueFactory avf(&zone, isolate->heap()->HashSeed()); |
+ avf.Internalize(isolate); |
+ |
+ i::Scope* global_scope = |
+ new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone); |
+ global_scope->Initialize(); |
+ i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone); |
+ ASSERT(s != global_scope); |
+ const i::AstRawString* name_x = avf.GetOneByteString("x"); |
+ |
+ // Get result from f's function context (that is g's outer context) |
+ i::Variable* var_x = s->Lookup(name_x); |
+ CHECK(var_x != NULL); |
+ CHECK(var_x->maybe_assigned() == i::kMaybeAssigned); |
+} |
+ |
+ |
+TEST(ExportsMaybeAssigned) { |
+ i::FLAG_use_strict = true; |
+ i::FLAG_harmony_scoping = true; |
+ i::FLAG_harmony_modules = true; |
+ |
+ i::Isolate* isolate = CcTest::i_isolate(); |
+ i::Factory* factory = isolate->factory(); |
+ i::HandleScope scope(isolate); |
+ LocalContext env; |
+ |
+ const char* src = |
+ "module A {" |
+ " export var x = 1;" |
+ " export function f() { return x };" |
+ " export const y = 2;" |
+ " module B {}" |
+ " export module C {}" |
+ "};" |
+ "A.f"; |
+ |
+ i::ScopedVector<char> program(Utf8LengthHelper(src) + 1); |
+ i::SNPrintF(program, "%s", src); |
+ i::Handle<i::String> source = factory->InternalizeUtf8String(program.start()); |
+ source->PrintOn(stdout); |
+ printf("\n"); |
+ i::Zone zone(isolate); |
+ v8::Local<v8::Value> v = CompileRun(src); |
+ i::Handle<i::Object> o = v8::Utils::OpenHandle(*v); |
+ i::Handle<i::JSFunction> f = i::Handle<i::JSFunction>::cast(o); |
+ i::Context* context = f->context(); |
+ i::AstValueFactory avf(&zone, isolate->heap()->HashSeed()); |
+ avf.Internalize(isolate); |
+ |
+ i::Scope* global_scope = |
+ new (&zone) i::Scope(NULL, i::GLOBAL_SCOPE, &avf, &zone); |
+ global_scope->Initialize(); |
+ i::Scope* s = i::Scope::DeserializeScopeChain(context, global_scope, &zone); |
+ ASSERT(s != global_scope); |
+ const i::AstRawString* name_x = avf.GetOneByteString("x"); |
+ const i::AstRawString* name_f = avf.GetOneByteString("f"); |
+ const i::AstRawString* name_y = avf.GetOneByteString("y"); |
+ const i::AstRawString* name_B = avf.GetOneByteString("B"); |
+ const i::AstRawString* name_C = avf.GetOneByteString("C"); |
+ |
+ // Get result from h's function context (that is f's context) |
+ i::Variable* var_x = s->Lookup(name_x); |
+ CHECK(var_x != NULL); |
+ CHECK(var_x->maybe_assigned() == i::kMaybeAssigned); |
+ i::Variable* var_f = s->Lookup(name_f); |
+ CHECK(var_f != NULL); |
+ CHECK(var_f->maybe_assigned() == i::kMaybeAssigned); |
+ i::Variable* var_y = s->Lookup(name_y); |
+ CHECK(var_y != NULL); |
+ CHECK(var_y->maybe_assigned() == i::kNotAssigned); |
+ i::Variable* var_B = s->Lookup(name_B); |
+ CHECK(var_B != NULL); |
+ CHECK(var_B->maybe_assigned() == i::kNotAssigned); |
+ i::Variable* var_C = s->Lookup(name_C); |
+ CHECK(var_C != NULL); |
+ CHECK(var_C->maybe_assigned() == i::kNotAssigned); |
+} |
+ |
+ |
TEST(InnerAssignment) { |
i::Isolate* isolate = CcTest::i_isolate(); |
i::Factory* factory = isolate->factory(); |
@@ -2940,6 +3102,10 @@ TEST(InnerAssignment) { |
{ "(function(x) { eval(''); })", true, false }, |
}; |
+ // Used to trigger lazy compilation of function |
+ int comment_len = 2048; |
+ i::ScopedVector<char> comment(comment_len + 1); |
+ i::SNPrintF(comment, "/*%0*d*/", comment_len - 4, 0); |
int prefix_len = Utf8LengthHelper(prefix); |
int midfix_len = Utf8LengthHelper(midfix); |
int suffix_len = Utf8LengthHelper(suffix); |
@@ -2947,36 +3113,48 @@ TEST(InnerAssignment) { |
const char* outer = outers[i].source; |
int outer_len = Utf8LengthHelper(outer); |
for (unsigned j = 0; j < ARRAY_SIZE(inners); ++j) { |
- if (outers[i].strict && inners[j].with) continue; |
- 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->InternalizeUtf8String(program.start()); |
- source->PrintOn(stdout); |
- printf("\n"); |
- |
- i::Handle<i::Script> script = factory->NewScript(source); |
- i::CompilationInfoWithZone info(script); |
- i::Parser parser(&info); |
- parser.set_allow_harmony_scoping(true); |
- CHECK(parser.Parse()); |
- 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); |
- const i::AstRawString* var_name = |
- info.ast_value_factory()->GetOneByteString("x"); |
- i::Variable* var = inner_scope->Lookup(var_name); |
- bool expected = outers[i].assigned || inners[j].assigned; |
- CHECK(var != NULL); |
- CHECK(var->is_used() || !expected); |
- CHECK(var->maybe_assigned() == expected); |
+ for (unsigned outer_lazy = 0; outer_lazy < 2; ++outer_lazy) { |
+ for (unsigned inner_lazy = 0; inner_lazy < 2; ++inner_lazy) { |
+ if (outers[i].strict && inners[j].with) continue; |
+ const char* inner = inners[j].source; |
+ int inner_len = Utf8LengthHelper(inner); |
+ |
+ int outer_comment_len = outer_lazy ? comment_len : 0; |
+ int inner_comment_len = inner_lazy ? comment_len : 0; |
+ const char* outer_comment = outer_lazy ? comment.start() : ""; |
+ const char* inner_comment = inner_lazy ? comment.start() : ""; |
+ int len = prefix_len + outer_comment_len + outer_len + midfix_len + |
+ inner_comment_len + inner_len + suffix_len; |
+ i::ScopedVector<char> program(len + 1); |
+ |
+ i::SNPrintF(program, "%s%s%s%s%s%s%s", prefix, outer_comment, outer, |
+ midfix, inner_comment, inner, suffix); |
+ i::Handle<i::String> source = |
+ factory->InternalizeUtf8String(program.start()); |
+ source->PrintOn(stdout); |
+ printf("\n"); |
+ |
+ i::Handle<i::Script> script = factory->NewScript(source); |
+ i::CompilationInfoWithZone info(script); |
+ i::Parser parser(&info); |
+ parser.set_allow_harmony_scoping(true); |
+ CHECK(parser.Parse()); |
+ 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); |
+ const i::AstRawString* var_name = |
+ info.ast_value_factory()->GetOneByteString("x"); |
+ i::Variable* var = inner_scope->Lookup(var_name); |
+ bool expected = outers[i].assigned || inners[j].assigned; |
+ CHECK(var != NULL); |
+ CHECK(var->is_used() || !expected); |
+ CHECK((var->maybe_assigned() == i::kMaybeAssigned) == expected); |
+ } |
+ } |
} |
} |
} |