harmony-scoping: Correct dynamic lookups on a top level.
authordslomov@chromium.org <dslomov@chromium.org>
Wed, 29 Oct 2014 10:59:41 +0000 (10:59 +0000)
committerdslomov@chromium.org <dslomov@chromium.org>
Wed, 29 Oct 2014 11:00:15 +0000 (11:00 +0000)
R=rossberg@chromium.org

Review URL: https://codereview.chromium.org/650663003

Cr-Commit-Position: refs/heads/master@{#24975}
git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24975 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/contexts.cc
test/cctest/test-decls.cc

index 30c474d..537d92d 100644 (file)
@@ -122,13 +122,30 @@ Handle<Object> Context::Lookup(Handle<String> name,
     PrintF(")\n");
   }
 
+  bool visited_global_context = false;
+
   do {
     if (FLAG_trace_contexts) {
       PrintF(" - looking in context %p", reinterpret_cast<void*>(*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>(context->global_object()->global_context());
+      visited_global_context = true;
+      if (FLAG_trace_contexts) {
+        PrintF("   - switching to current global context %p\n",
+               reinterpret_cast<void*>(*context));
+      }
+    }
+
     // 1. Check global objects, subjects of with, and extension objects.
     if (context->IsNativeContext() ||
         context->IsWithContext() ||
@@ -163,7 +180,8 @@ Handle<Object> Context::Lookup(Handle<String> 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<ScopeInfo> scope_info;
index 34f0b69..f2ccdab 100644 (file)
@@ -713,3 +713,37 @@ TEST(CrossScriptConflicts) {
     }
   }
 }
+
+
+TEST(CrossScriptDynamicLookup) {
+  i::FLAG_harmony_scoping = true;
+
+  HandleScope handle_scope(CcTest::isolate());
+
+  {
+    SimpleContext context;
+    Local<String> undefined_string = String::NewFromUtf8(
+        CcTest::isolate(), "undefined", String::kInternalizedString);
+    Local<String> 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);
+  }
+}