diff --git a/src/contexts.cc b/src/contexts.cc index 30c474d5ff..537d92d0f4 100644 --- a/src/contexts.cc +++ b/src/contexts.cc @@ -122,13 +122,30 @@ Handle Context::Lookup(Handle name, PrintF(")\n"); } + bool visited_global_context = false; + do { if (FLAG_trace_contexts) { PrintF(" - looking in context %p", reinterpret_cast(*context)); + if (context->IsGlobalContext()) PrintF(" (global context)"); if (context->IsNativeContext()) PrintF(" (native context)"); PrintF("\n"); } + if (follow_context_chain && FLAG_harmony_scoping && + !visited_global_context && + (context->IsGlobalContext() || context->IsNativeContext())) { + // For lexical scoping, on a top level, we might resolve to the + // lexical bindings introduced by later scrips. Therefore we need to + // switch to the the last added global context during lookup here. + context = Handle(context->global_object()->global_context()); + visited_global_context = true; + if (FLAG_trace_contexts) { + PrintF(" - switching to current global context %p\n", + reinterpret_cast(*context)); + } + } + // 1. Check global objects, subjects of with, and extension objects. if (context->IsNativeContext() || context->IsWithContext() || @@ -163,7 +180,8 @@ Handle Context::Lookup(Handle name, } // 2. Check the context proper if it has slots. - if (context->IsFunctionContext() || context->IsBlockContext()) { + if (context->IsFunctionContext() || context->IsBlockContext() || + (FLAG_harmony_scoping && context->IsGlobalContext())) { // Use serialized scope information of functions and blocks to search // for the context index. Handle scope_info; diff --git a/test/cctest/test-decls.cc b/test/cctest/test-decls.cc index 34f0b69643..f2ccdab6c0 100644 --- a/test/cctest/test-decls.cc +++ b/test/cctest/test-decls.cc @@ -713,3 +713,37 @@ TEST(CrossScriptConflicts) { } } } + + +TEST(CrossScriptDynamicLookup) { + i::FLAG_harmony_scoping = true; + + HandleScope handle_scope(CcTest::isolate()); + + { + SimpleContext context; + Local undefined_string = String::NewFromUtf8( + CcTest::isolate(), "undefined", String::kInternalizedString); + Local number_string = String::NewFromUtf8( + CcTest::isolate(), "number", String::kInternalizedString); + + context.Check( + "function f(o) { with(o) { return x; } }" + "function g(o) { with(o) { x = 15; } }" + "function h(o) { with(o) { return typeof x; } }", + EXPECT_RESULT, Undefined(CcTest::isolate())); + context.Check("h({})", EXPECT_RESULT, undefined_string); + context.Check( + "'use strict';" + "let x = 1;" + "f({})", + EXPECT_RESULT, Number::New(CcTest::isolate(), 1)); + context.Check( + "'use strict';" + "g({});" + "x", + EXPECT_RESULT, Number::New(CcTest::isolate(), 15)); + context.Check("f({})", EXPECT_RESULT, Number::New(CcTest::isolate(), 15)); + context.Check("h({})", EXPECT_RESULT, number_string); + } +}