Author: [email protected]
Date: Tue May  5 02:38:45 2009
New Revision: 1857

Modified:
    branches/bleeding_edge/include/v8.h
    branches/bleeding_edge/src/api.cc
    branches/bleeding_edge/src/bootstrapper.cc
    branches/bleeding_edge/src/contexts.h
    branches/bleeding_edge/src/debug.cc
    branches/bleeding_edge/src/debug.h
    branches/bleeding_edge/test/cctest/test-debug.cc

Log:
Add the ability to set embedder data on created contexts from the API.

Expose the active context where a break event occoured through the debug  
message handler.
Review URL: http://codereview.chromium.org/109013

Modified: branches/bleeding_edge/include/v8.h
==============================================================================
--- branches/bleeding_edge/include/v8.h (original)
+++ branches/bleeding_edge/include/v8.h Tue May  5 02:38:45 2009
@@ -2260,6 +2260,14 @@
    static bool InContext();

    /**
+   * Associate an additional data object with the context. This is mainly  
used
+   * with the debugger to provide additional information on the context  
through
+   * the debugger API.
+   */
+  void SetData(Handle<Value> data);
+  Local<Value> GetData();
+
+  /**
     * Stack-allocated class which sets the execution context for all
     * operations executed within a local scope.
     */

Modified: branches/bleeding_edge/src/api.cc
==============================================================================
--- branches/bleeding_edge/src/api.cc   (original)
+++ branches/bleeding_edge/src/api.cc   Tue May  5 02:38:45 2009
@@ -445,6 +445,40 @@
  }


+void Context::SetData(v8::Handle<Value> data) {
+  if (IsDeadCheck("v8::Context::SetData()")) return;
+  ENTER_V8;
+  {
+    HandleScope scope;
+    i::Handle<i::Context> env = Utils::OpenHandle(this);
+    i::Handle<i::Object> raw_data = Utils::OpenHandle(*data);
+    ASSERT(env->IsGlobalContext());
+    if (env->IsGlobalContext()) {
+      env->set_data(*raw_data);
+    }
+  }
+}
+
+
+v8::Local<v8::Value> Context::GetData() {
+  if (IsDeadCheck("v8::Context::GetData()")) return v8::Local<Value>();
+  ENTER_V8;
+  i::Object* raw_result = NULL;
+  {
+    HandleScope scope;
+    i::Handle<i::Context> env = Utils::OpenHandle(this);
+    ASSERT(env->IsGlobalContext());
+    if (env->IsGlobalContext()) {
+      raw_result = env->data();
+    } else {
+      return Local<Value>();
+    }
+  }
+  i::Handle<i::Object> result(raw_result);
+  return Utils::ToLocal(result);
+}
+
+
  void** v8::HandleScope::RawClose(void** value) {
    if (!ApiCheck(!is_closed_,
                  "v8::HandleScope::Close()",

Modified: branches/bleeding_edge/src/bootstrapper.cc
==============================================================================
--- branches/bleeding_edge/src/bootstrapper.cc  (original)
+++ branches/bleeding_edge/src/bootstrapper.cc  Tue May  5 02:38:45 2009
@@ -833,6 +833,9 @@

    // Initialize the out of memory slot.
    global_context()->set_out_of_memory(Heap::false_value());
+
+  // Initialize the data slot.
+  global_context()->set_data(Heap::undefined_value());
  }



Modified: branches/bleeding_edge/src/contexts.h
==============================================================================
--- branches/bleeding_edge/src/contexts.h       (original)
+++ branches/bleeding_edge/src/contexts.h       Tue May  5 02:38:45 2009
@@ -94,7 +94,8 @@
    V(SCRIPT_FUNCTION_INDEX, JSFunction, script_function) \
    V(CONTEXT_EXTENSION_FUNCTION_INDEX, JSFunction,  
context_extension_function) \
    V(OUT_OF_MEMORY_INDEX, Object, out_of_memory) \
-  V(MAP_CACHE_INDEX, Object, map_cache)
+  V(MAP_CACHE_INDEX, Object, map_cache) \
+  V(CONTEXT_DATA_INDEX, Object, data)

  // JSFunctions are pairs (context, function code), sometimes also called
  // closures. A Context object is used to represent function contexts and
@@ -213,6 +214,7 @@
      CONTEXT_EXTENSION_FUNCTION_INDEX,
      OUT_OF_MEMORY_INDEX,
      MAP_CACHE_INDEX,
+    CONTEXT_DATA_INDEX,
      GLOBAL_CONTEXT_SLOTS
    };


Modified: branches/bleeding_edge/src/debug.cc
==============================================================================
--- branches/bleeding_edge/src/debug.cc (original)
+++ branches/bleeding_edge/src/debug.cc Tue May  5 02:38:45 2009
@@ -2172,7 +2172,7 @@


  v8::Handle<v8::Context> MessageImpl::GetEventContext() const {
-  return v8::Handle<v8::Context>();
+  return v8::Utils::ToLocal(Debug::debugger_entry()->GetContext());
  }



Modified: branches/bleeding_edge/src/debug.h
==============================================================================
--- branches/bleeding_edge/src/debug.h  (original)
+++ branches/bleeding_edge/src/debug.h  Tue May  5 02:38:45 2009
@@ -687,6 +687,9 @@
    // Check whether there are any JavaScript frames on the stack.
    inline bool HasJavaScriptFrames() { return has_js_frames_; }

+  // Get the active context from before entering the debugger.
+  inline Handle<Context> GetContext() { return save_.context(); }
+
   private:
    EnterDebugger* prev_;  // Previous debugger entry if entered recursively.
    JavaScriptFrameIterator it_;

Modified: branches/bleeding_edge/test/cctest/test-debug.cc
==============================================================================
--- branches/bleeding_edge/test/cctest/test-debug.cc    (original)
+++ branches/bleeding_edge/test/cctest/test-debug.cc    Tue May  5 02:38:45  
2009
@@ -167,11 +167,22 @@
        (*env)->Global()->Get(v8::String::New(function_name)));
  }

+
+// Compile and run the supplied source and return the requested function.
+static v8::Local<v8::Function> CompileFunction(const char* source,
+                                               const char* function_name) {
+  v8::Script::Compile(v8::String::New(source))->Run();
+  return v8::Local<v8::Function>::Cast(
+     
v8::Context::GetCurrent()->Global()->Get(v8::String::New(function_name)));
+}
+
+
  // Helper function that compiles and runs the source.
  static v8::Local<v8::Value> CompileRun(const char* source) {
    return v8::Script::Compile(v8::String::New(source))->Run();
  }

+
  // Is there any debug info for the function?
  static bool HasDebugInfo(v8::Handle<v8::Function> fun) {
    Handle<v8::internal::JSFunction> f = v8::Utils::OpenHandle(*fun);
@@ -4587,4 +4598,85 @@
    CHECK_EQ(2, break_point_hit_count);
    CHECK_EQ("new name", last_script_name_hit);
    CHECK_EQ("abc 123", last_script_data_hit);
+}
+
+
+static v8::Persistent<v8::Context> expected_context;
+static v8::Handle<v8::Value> expected_context_data;
+
+
+// Check that the expected context is the one generating the debug event.
+static void ContextCheckMessageHandler(const v8::Debug::Message& message) {
+  CHECK(message.GetEventContext() == expected_context);
+  CHECK(message.GetEventContext()->GetData()->StrictEquals(
+      expected_context_data));
+  message_handler_hit_count++;
+
+  const int kBufferSize = 1000;
+  uint16_t buffer[kBufferSize];
+  const char* command_continue =
+    "{\"seq\":0,"
+     "\"type\":\"request\","
+     "\"command\":\"continue\"}";
+
+  // Send a continue command for break events.
+  if (message.GetEvent() == v8::Break) {
+    v8::Debug::SendCommand(buffer, AsciiToUtf16(command_continue, buffer));
+  }
+}
+
+
+// Test which creates two contexts and sets different embedder data on  
each.
+// Checks that this data is set correctly and that when the debug message
+// handler is called the expected context is the one active.
+TEST(ContextData) {
+  v8::HandleScope scope;
+
+  v8::Debug::SetMessageHandler2(ContextCheckMessageHandler);
+
+  // Create two contexts.
+  v8::Persistent<v8::Context> context_1;
+  v8::Persistent<v8::Context> context_2;
+  v8::Handle<v8::ObjectTemplate> global_template =
+      v8::Handle<v8::ObjectTemplate>();
+  v8::Handle<v8::Value> global_object = v8::Handle<v8::Value>();
+  context_1 = v8::Context::New(NULL, global_template, global_object);
+  context_2 = v8::Context::New(NULL, global_template, global_object);
+
+  // Default data value is undefined.
+  CHECK(context_1->GetData()->IsUndefined());
+  CHECK(context_2->GetData()->IsUndefined());
+
+  // Set and check different data values.
+  v8::Handle<v8::Value> data_1 = v8::Number::New(1);
+  v8::Handle<v8::Value> data_2 = v8::String::New("2");
+  context_1->SetData(data_1);
+  context_2->SetData(data_2);
+  CHECK(context_1->GetData()->StrictEquals(data_1));
+  CHECK(context_2->GetData()->StrictEquals(data_2));
+
+  // Simple test function which causes a break.
+  char* source = "function f() { debugger; }";
+
+  // Enter and run function in the first context.
+  {
+    v8::Context::Scope context_scope(context_1);
+    expected_context = context_1;
+    expected_context_data = data_1;
+    v8::Local<v8::Function> f = CompileFunction(source, "f");
+    f->Call(context_1->Global(), 0, NULL);
+  }
+
+
+  // Enter and run function in the second context.
+  {
+    v8::Context::Scope context_scope(context_2);
+    expected_context = context_2;
+    expected_context_data = data_2;
+    v8::Local<v8::Function> f = CompileFunction(source, "f");
+    f->Call(context_2->Global(), 0, NULL);
+  }
+
+  // Two times compile event and two times break event.
+  CHECK_GT(message_handler_hit_count, 4);
  }

--~--~---------~--~----~------------~-------~--~----~
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
-~----------~----~----~----~------~----~------~--~---

Reply via email to