Add unit test for r11818.
authormstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 21 Jun 2012 11:31:30 +0000 (11:31 +0000)
committermstarzinger@chromium.org <mstarzinger@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Thu, 21 Jun 2012 11:31:30 +0000 (11:31 +0000)
R=rossberg@chromium.org
TEST=cctest/test-decls/ExistsInHiddenPrototype

Review URL: https://chromiumcodereview.appspot.com/10628002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@11896 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

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

index 12b753b..fadb511 100644 (file)
@@ -1318,8 +1318,9 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DeclareGlobals) {
         Object* obj = *global;
         do {
           JSObject::cast(obj)->LocalLookup(*name, &lookup);
+          if (lookup.IsProperty()) break;
           obj = obj->GetPrototype();
-        } while (!lookup.IsFound() && obj->IsJSObject() &&
+        } while (obj->IsJSObject() &&
                  JSObject::cast(obj)->map()->is_hidden_prototype());
       } else {
         global->Lookup(*name, &lookup);
index e6bdc9f..b55f417 100644 (file)
@@ -72,6 +72,10 @@ class DeclarationContext {
 
   void InitializeIfNeeded();
 
+  // Perform optional initialization steps on the context after it has
+  // been created. Defaults to none but may be overwritten.
+  virtual void PostInitializeContext(Handle<Context> context) {}
+
   // Get the holder for the interceptor. Default to the instance template
   // but may be overwritten.
   virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
@@ -120,6 +124,7 @@ void DeclarationContext::InitializeIfNeeded() {
   context_ = Context::New(0, function->InstanceTemplate(), Local<Value>());
   context_->Enter();
   is_initialized_ = true;
+  PostInitializeContext(context_);
 }
 
 
@@ -536,9 +541,9 @@ TEST(ExistsInPrototype) {
 
   { ExistsInPrototypeContext context;
     context.Check("var x; x",
-                  0,  // get
                   0,
-                  0,  // declaration
+                  0,
+                  0,
                   EXPECT_RESULT, Undefined());
   }
 
@@ -546,7 +551,7 @@ TEST(ExistsInPrototype) {
     context.Check("var x = 0; x",
                   0,
                   0,
-                  0,  // declaration
+                  0,
                   EXPECT_RESULT, Number::New(0));
   }
 
@@ -554,7 +559,7 @@ TEST(ExistsInPrototype) {
     context.Check("const x; x",
                   0,
                   0,
-                  0,  // declaration
+                  0,
                   EXPECT_RESULT, Undefined());
   }
 
@@ -562,7 +567,7 @@ TEST(ExistsInPrototype) {
     context.Check("const x = 0; x",
                   0,
                   0,
-                  0,  // declaration
+                  0,
                   EXPECT_RESULT, Number::New(0));
   }
 }
@@ -591,7 +596,88 @@ TEST(AbsentInPrototype) {
     context.Check("if (false) { var x = 0; }; x",
                   0,
                   0,
-                  0,  // declaration
+                  0,
                   EXPECT_RESULT, Undefined());
   }
 }
+
+
+
+class ExistsInHiddenPrototypeContext: public DeclarationContext {
+ public:
+  ExistsInHiddenPrototypeContext() {
+    hidden_proto_ = FunctionTemplate::New();
+    hidden_proto_->SetHiddenPrototype(true);
+  }
+
+ protected:
+  virtual v8::Handle<Integer> Query(Local<String> key) {
+    // Let it seem that the property exists in the hidden prototype object.
+    return Integer::New(v8::None);
+  }
+
+  // Install the hidden prototype after the global object has been created.
+  virtual void PostInitializeContext(Handle<Context> context) {
+    Local<Object> global_object = context->Global();
+    Local<Object> hidden_proto = hidden_proto_->GetFunction()->NewInstance();
+    context->DetachGlobal();
+    context->Global()->SetPrototype(hidden_proto);
+    context->ReattachGlobal(global_object);
+  }
+
+  // Use the hidden prototype as the holder for the interceptors.
+  virtual Local<ObjectTemplate> GetHolder(Local<FunctionTemplate> function) {
+    return hidden_proto_->InstanceTemplate();
+  }
+
+ private:
+  Local<FunctionTemplate> hidden_proto_;
+};
+
+
+TEST(ExistsInHiddenPrototype) {
+  i::FLAG_es52_globals = true;
+  HandleScope scope;
+
+  { ExistsInHiddenPrototypeContext context;
+    context.Check("var x; x",
+                  1,  // access
+                  0,
+                  2,  // declaration + initialization
+                  EXPECT_EXCEPTION);  // x is not defined!
+  }
+
+  { ExistsInHiddenPrototypeContext context;
+    context.Check("var x = 0; x",
+                  1,  // access
+                  1,  // initialization
+                  2,  // declaration + initialization
+                  EXPECT_RESULT, Number::New(0));
+  }
+
+  { ExistsInHiddenPrototypeContext context;
+    context.Check("function x() { }; x",
+                  0,
+                  0,
+                  0,
+                  EXPECT_RESULT);
+  }
+
+  // TODO(mstarzinger): The semantics of global const is vague.
+  { ExistsInHiddenPrototypeContext context;
+    context.Check("const x; x",
+                  0,
+                  0,
+                  1,  // (re-)declaration
+                  EXPECT_RESULT, Undefined());
+  }
+
+  // TODO(mstarzinger): The semantics of global const is vague.
+  { ExistsInHiddenPrototypeContext context;
+    context.Check("const x = 0; x",
+                  0,
+                  0,
+                  1,  // (re-)declaration
+                  EXPECT_RESULT, Number::New(0));
+  }
+}