From a22998a223ecdcd926d152baea8a8703bcb57d61 Mon Sep 17 00:00:00 2001 From: "abarth@chromium.org" Date: Sun, 10 Nov 2013 05:00:50 +0000 Subject: This CL introduces a lightweight bindings system for V8 called gin Unlike the extensions V8 bindings, gin is based on ObjectTemplates rather than on evaluating script. Unlike the Blink V8 bindings, gin isn't tightly coupled to Blink. In fact, gin's only link-time dependency is V8. We plan to use gin to build the V8 bindings for Mojo (see https://codereview.chromium.org/59153005/ for an example of how they will be used). In the long term, gin could serve as a basis for both the Blink and the extension system bindings, but we don't have any immediate plans to pursue that use of this code. This code is largely inspired by a lightweight bindings system designed by Aaron Boodman. Review URL: https://codereview.chromium.org/67763002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@234160 0039d316-1c4b-4281-b951-d872f2087c98 --- gin/DEPS | 7 ++ gin/OWNERS | 2 + gin/README | 8 +++ gin/array_buffer.cc | 150 ++++++++++++++++++++++++++++++++++++++++++ gin/array_buffer.h | 45 +++++++++++++ gin/converter.cc | 102 ++++++++++++++++++++++++++++ gin/converter.h | 121 ++++++++++++++++++++++++++++++++++ gin/converter_unittest.cc | 128 +++++++++++++++++++++++++++++++++++ gin/gin.gyp | 54 +++++++++++++++ gin/initialize.cc | 38 +++++++++++ gin/initialize.h | 14 ++++ gin/per_isolate_data.cc | 33 ++++++++++ gin/per_isolate_data.h | 38 +++++++++++ gin/runner.cc | 64 ++++++++++++++++++ gin/runner.h | 67 +++++++++++++++++++ gin/runner_unittest.cc | 55 ++++++++++++++++ gin/test/run_all_unittests.cc | 20 ++++++ gin/test/v8_test.cc | 33 ++++++++++ gin/test/v8_test.h | 30 +++++++++ gin/wrapper_info.cc | 16 +++++ gin/wrapper_info.h | 25 +++++++ 21 files changed, 1050 insertions(+) create mode 100644 gin/DEPS create mode 100644 gin/OWNERS create mode 100644 gin/README create mode 100644 gin/array_buffer.cc create mode 100644 gin/array_buffer.h create mode 100644 gin/converter.cc create mode 100644 gin/converter.h create mode 100644 gin/converter_unittest.cc create mode 100644 gin/gin.gyp create mode 100644 gin/initialize.cc create mode 100644 gin/initialize.h create mode 100644 gin/per_isolate_data.cc create mode 100644 gin/per_isolate_data.h create mode 100644 gin/runner.cc create mode 100644 gin/runner.h create mode 100644 gin/runner_unittest.cc create mode 100644 gin/test/run_all_unittests.cc create mode 100644 gin/test/v8_test.cc create mode 100644 gin/test/v8_test.h create mode 100644 gin/wrapper_info.cc create mode 100644 gin/wrapper_info.h (limited to 'gin') diff --git a/gin/DEPS b/gin/DEPS new file mode 100644 index 0000000..6e9bed8 --- /dev/null +++ b/gin/DEPS @@ -0,0 +1,7 @@ +include_rules = [ + "+v8", + + # Use of base is allowed in tests. We can also use base in production code + # as long as we don't introduce a link-time dependency. + "+base", +] diff --git a/gin/OWNERS b/gin/OWNERS new file mode 100644 index 0000000..98c7ef8 --- /dev/null +++ b/gin/OWNERS @@ -0,0 +1,2 @@ +aa@chromium.org +abarth@chromium.org diff --git a/gin/README b/gin/README new file mode 100644 index 0000000..82d0618 --- /dev/null +++ b/gin/README @@ -0,0 +1,8 @@ +Gin - Lightweight bindings for V8 +================================= + +This directory contains gin, a lightweight bindings library for V8. These +bindings are not compatible with the V8 bindings used by Blink because both +want to control the v8::Isolate's internal data field. Maybe in some future +world we'll refactor the Blink V8 bindings to use this system. In the meantime, +these bindings are convenient for projects other than Blink that use V8. diff --git a/gin/array_buffer.cc b/gin/array_buffer.cc new file mode 100644 index 0000000..e8236fc --- /dev/null +++ b/gin/array_buffer.cc @@ -0,0 +1,150 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gin/array_buffer.h" + +#include + +namespace gin { + +COMPILE_ASSERT(V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT == 2, + array_buffers_must_have_two_internal_fields); + +static const int kBufferViewPrivateIndex = 0; + +// ArrayBufferAllocator ------------------------------------------------------- + +void* ArrayBufferAllocator::Allocate(size_t length) { + return calloc(1, length); +} + +void* ArrayBufferAllocator::AllocateUninitialized(size_t length) { + return malloc(length); +} + +void ArrayBufferAllocator::Free(void* data, size_t length) { + free(data); +} + +ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() { + static ArrayBufferAllocator* instance = new ArrayBufferAllocator(); + return instance; +} + +// BufferView::Private -------------------------------------------------------- + +// This class exists to solve a tricky lifetime problem. The V8 API doesn't +// want to expose a direct view into the memory behind an array buffer because +// V8 might deallocate that memory during garbage collection. Instead, the V8 +// API forces us to externalize the buffer and take ownership of the memory. +// In order to know when to free the memory, we need to figure out both when +// we're done with it and when V8 is done with it. +// +// To determine whether we're done with the memory, every view we have into +// the array buffer takes a reference to the BufferView::Private object that +// actually owns the memory. To determine when V8 is done with the memory, we +// open a weak handle to the ArrayBuffer object. When we receive the weak +// callback, we know the object is about to be garbage collected and we can +// drop V8's implied reference to the memory. +// +// The final subtlety is that we need every BufferView into the same array +// buffer to AddRef the same BufferView::Private. To make that work, we store a +// pointer to the BufferView::Private object in an internal field of the +// ArrayBuffer object. +// +class BufferView::Private { + public: + static scoped_refptr From(v8::Isolate* isolate, + v8::Handle array); + + void AddRef(); + void Release(); + + void* buffer() const { return buffer_; } + size_t length() const { return length_; } + + private: + Private(v8::Isolate* isolate, v8::Handle array); + ~Private(); + + static void WeakCallback( + const v8::WeakCallbackData& data); + + size_t ref_count_; + v8::Persistent array_buffer_; + void* buffer_; + size_t length_; +}; + +scoped_refptr BufferView::Private::From( + v8::Isolate* isolate, v8::Handle array) { + if (array->IsExternal()) { + return make_scoped_refptr(static_cast( + array->GetAlignedPointerFromInternalField(kBufferViewPrivateIndex))); + } + return make_scoped_refptr(new Private(isolate, array)); +} + +void BufferView::Private::AddRef() { + ++ref_count_; +} + +void BufferView::Private::Release() { + if (--ref_count_) + return; + delete this; +} + +BufferView::Private::Private(v8::Isolate* isolate, + v8::Handle array) + : ref_count_(0), + array_buffer_(isolate, array) { + // Take ownership of the array buffer. + v8::ArrayBuffer::Contents contents = array->Externalize(); + buffer_ = contents.Data(); + length_ = contents.ByteLength(); + + array->SetAlignedPointerInInternalField(kBufferViewPrivateIndex, this); + + AddRef(); // Balanced in WeakCallback. + array_buffer_.SetWeak(this, WeakCallback); +} + +BufferView::Private::~Private() { + ArrayBufferAllocator::SharedInstance()->Free(buffer_, length_); +} + +void BufferView::Private::WeakCallback( + const v8::WeakCallbackData& data) { + Private* parameter = data.GetParameter(); + parameter->array_buffer_.Reset(); + parameter->Release(); // Balanced in BufferView::Private::Private. +} + +// BufferView ----------------------------------------------------------------- + +BufferView::BufferView(v8::Isolate* isolate, + v8::Handle view) { + Initialize(isolate, view->Buffer()); + uint8_t* ptr = static_cast(bytes_); + bytes_ = static_cast(ptr + view->ByteOffset()); + num_bytes_ = view->ByteLength(); +} + +BufferView::BufferView(v8::Isolate* isolate, + v8::Handle array) { + Initialize(isolate, array); +} + +BufferView::~BufferView() { +} + +void BufferView::Initialize(v8::Isolate* isolate, + v8::Handle array) { + private_ = BufferView::Private::From(isolate, array); + bytes_ = private_->buffer(); + num_bytes_ = private_->length(); +} + +} // namespace gin diff --git a/gin/array_buffer.h b/gin/array_buffer.h new file mode 100644 index 0000000..b48a687 --- /dev/null +++ b/gin/array_buffer.h @@ -0,0 +1,45 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GIN_ARRAY_BUFFER_H_ +#define GIN_ARRAY_BUFFER_H_ + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/ref_counted.h" // For scoped_refptr only! +#include "v8/include/v8.h" + +namespace gin { + +class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { + public: + virtual void* Allocate(size_t length) OVERRIDE; + virtual void* AllocateUninitialized(size_t length) OVERRIDE; + virtual void Free(void* data, size_t length) OVERRIDE; + + static ArrayBufferAllocator* SharedInstance(); +}; + +class BufferView { + public: + BufferView(v8::Isolate* isolate, v8::Handle view); + BufferView(v8::Isolate* isolate, v8::Handle buffer); + ~BufferView(); + + void* bytes() const { return bytes_; } + size_t num_bytes() const { return num_bytes_; } + + private: + class Private; + + void Initialize(v8::Isolate* isolate, v8::Handle buffer); + + scoped_refptr private_; + void* bytes_; + size_t num_bytes_; +}; + +} // namespace gin + +#endif // GIN_ARRAY_BUFFER_H_ diff --git a/gin/converter.cc b/gin/converter.cc new file mode 100644 index 0000000..6b30985 --- /dev/null +++ b/gin/converter.cc @@ -0,0 +1,102 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gin/converter.h" + +#include "v8/include/v8.h" + +using v8::Boolean; +using v8::Function; +using v8::Handle; +using v8::Integer; +using v8::Isolate; +using v8::Number; +using v8::Object; +using v8::String; +using v8::Value; + +namespace gin { + +Handle Converter::ToV8(Isolate* isolate, bool val) { + return Boolean::New(val).As(); +} + +bool Converter::FromV8(Handle val, bool* out) { + *out = val->BooleanValue(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, int32_t val) { + return Integer::New(val, isolate).As(); +} + +bool Converter::FromV8(Handle val, int32_t* out) { + if (!val->IsInt32()) + return false; + *out = val->Int32Value(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, uint32_t val) { + return Integer::NewFromUnsigned(val, isolate).As(); +} + +bool Converter::FromV8(Handle val, uint32_t* out) { + if (!val->IsUint32()) + return false; + *out = val->Uint32Value(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, double val) { + return Number::New(isolate, val).As(); +} + +bool Converter::FromV8(Handle val, double* out) { + if (!val->IsNumber()) + return false; + *out = val->NumberValue(); + return true; +} + +Handle Converter::ToV8(Isolate* isolate, + const std::string& val) { + return String::NewFromUtf8(isolate, + val.data(), + String::kNormalString, + val.length()); +} + +bool Converter::FromV8(Handle val, + std::string* out) { + if (!val->IsString()) + return false; + Handle str = Handle::Cast(val); + int length = str->Utf8Length(); + out->resize(length); + str->WriteUtf8(&(*out)[0], length, NULL, String::NO_NULL_TERMINATION); + return true; +} + +bool Converter >::FromV8(Handle val, + Handle* out) { + if (!val->IsFunction()) + return false; + *out = Handle::Cast(val); + return true; +} + +Handle Converter >::ToV8(Handle val) { + return val.As(); +} + +bool Converter >::FromV8(Handle val, + Handle* out) { + if (!val->IsObject()) + return false; + *out = Handle::Cast(val); + return true; +} + +} // namespace gin diff --git a/gin/converter.h b/gin/converter.h new file mode 100644 index 0000000..eb84be2 --- /dev/null +++ b/gin/converter.h @@ -0,0 +1,121 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GIN_CONVERTER_H_ +#define GIN_CONVERTER_H_ + +#include +#include + +#include "v8/include/v8.h" + +namespace gin { + +template +struct Converter {}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + bool val); + static bool FromV8(v8::Handle val, + bool* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + int32_t val); + static bool FromV8(v8::Handle val, + int32_t* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + uint32_t val); + static bool FromV8(v8::Handle val, + uint32_t* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + double val); + static bool FromV8(v8::Handle val, + double* out); +}; + +template<> +struct Converter { + static v8::Handle ToV8(v8::Isolate* isolate, + const std::string& val); + static bool FromV8(v8::Handle val, + std::string* out); +}; + +template<> +struct Converter > { + static bool FromV8(v8::Handle val, + v8::Handle* out); +}; + +template<> +struct Converter > { + static v8::Handle ToV8(v8::Handle val); + static bool FromV8(v8::Handle val, + v8::Handle* out); +}; + +template +struct Converter > { + static v8::Handle ToV8(v8::Isolate* isolate, + const std::vector& val) { + v8::Handle result(v8::Array::New(static_cast(val.size()))); + for (size_t i = 0; i < val.size(); ++i) { + result->Set(static_cast(i), Converter::ToV8(isolate, val[i])); + } + return result; + } + + static bool FromV8(v8::Handle val, + std::vector* out) { + if (!val->IsArray()) + return false; + + std::vector result; + v8::Handle array(v8::Handle::Cast(val)); + uint32_t length = array->Length(); + for (uint32_t i = 0; i < length; ++i) { + T item; + if (!Converter::FromV8(array->Get(i), &item)) + return false; + result.push_back(item); + } + + out->swap(result); + return true; + } +}; + +// Convenience functions that deduce T. +template +v8::Handle ConvertToV8(v8::Isolate* isolate, + T input) { + return Converter::ToV8(isolate, input); +} + +inline v8::Handle StringToV8( + v8::Isolate* isolate, std::string input) { + return ConvertToV8(isolate, input).As(); +} + +template +bool ConvertFromV8(v8::Handle input, T* result) { + return Converter::FromV8(input, result); +} + +} // namespace gin + +#endif // GIN_CONVERTER_H_ diff --git a/gin/converter_unittest.cc b/gin/converter_unittest.cc new file mode 100644 index 0000000..b98a6da --- /dev/null +++ b/gin/converter_unittest.cc @@ -0,0 +1,128 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gin/converter.h" + +#include + +#include "base/basictypes.h" +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "gin/test/v8_test.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "v8/include/v8.h" + +using v8::Array; +using v8::Boolean; +using v8::Handle; +using v8::HandleScope; +using v8::Integer; +using v8::Null; +using v8::Number; +using v8::Object; +using v8::String; +using v8::Undefined; +using v8::Value; + +namespace gin { + +typedef V8Test ConverterTest; + +TEST_F(ConverterTest, Bool) { + HandleScope handle_scope(isolate_); + + EXPECT_TRUE(Converter::ToV8(isolate_, true)->StrictEquals( + Boolean::New(true))); + EXPECT_TRUE(Converter::ToV8(isolate_, false)->StrictEquals( + Boolean::New(false))); + + struct { + Handle input; + bool expected; + } test_data[] = { + { Boolean::New(false).As(), false }, + { Boolean::New(true).As(), true }, + { Number::New(0).As(), false }, + { Number::New(1).As(), true }, + { Number::New(-1).As(), true }, + { Number::New(0.1).As(), true }, + { String::New("").As(), false }, + { String::New("foo").As(), true }, + { Object::New().As(), true }, + { Null().As(), false }, + { Undefined().As(), false }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) { + bool result = false; + EXPECT_TRUE(Converter::FromV8(test_data[i].input, &result)); + EXPECT_EQ(test_data[i].expected, result); + + result = true; + EXPECT_TRUE(Converter::FromV8(test_data[i].input, &result)); + EXPECT_EQ(test_data[i].expected, result); + } +} + +TEST_F(ConverterTest, Int32) { + HandleScope handle_scope(isolate_); + + int test_data_to[] = {-1, 0, 1}; + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data_to); ++i) { + EXPECT_TRUE(Converter::ToV8(isolate_, + test_data_to[i])->StrictEquals(Integer::New(test_data_to[i]))); + } + + struct { + v8::Handle input; + bool expect_sucess; + int expected_result; + } test_data_from[] = { + { Boolean::New(false).As(), false, 0 }, + { Boolean::New(true).As(), false, 0 }, + { Integer::New(-1).As(), true, -1 }, + { Integer::New(0).As(), true, 0 }, + { Integer::New(1).As(), true, 1 }, + { Number::New(-1).As(), true, -1 }, + { Number::New(1.1).As(), false, 0 }, + { String::New("42").As(), false, 0 }, + { String::New("foo").As(), false, 0 }, + { Object::New().As(), false, 0 }, + { Array::New().As(), false, 0 }, + { v8::Null().As(), false, 0 }, + { v8::Undefined().As(), false, 0 }, + }; + + for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data_from); ++i) { + int32_t result = std::numeric_limits::min(); + bool success = Converter::FromV8(test_data_from[i].input, &result); + EXPECT_EQ(test_data_from[i].expect_sucess, success) << i; + if (success) + EXPECT_EQ(test_data_from[i].expected_result, result) << i; + } +} + +TEST_F(ConverterTest, Vector) { + HandleScope handle_scope(isolate_); + + std::vector expected; + expected.push_back(-1); + expected.push_back(0); + expected.push_back(1); + + Handle js_array = Handle::Cast( + Converter >::ToV8(isolate_, expected)); + ASSERT_FALSE(js_array.IsEmpty()); + EXPECT_EQ(3u, js_array->Length()); + for (size_t i = 0; i < expected.size(); ++i) { + EXPECT_TRUE(Integer::New(expected[i])->StrictEquals( + js_array->Get(static_cast(i)))); + } + + std::vector actual; + EXPECT_TRUE(Converter >::FromV8(js_array, &actual)); + EXPECT_EQ(expected, actual); +} + +} // namespace gin diff --git a/gin/gin.gyp b/gin/gin.gyp new file mode 100644 index 0000000..ca133dd --- /dev/null +++ b/gin/gin.gyp @@ -0,0 +1,54 @@ +# Copyright 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'chromium_code': 1, + }, + 'targets': [ + { + 'target_name': 'gin', + 'type': 'static_library', + 'include_dirs': [ + '..' + ], + 'dependencies': [ + '../v8/tools/gyp/v8.gyp:v8', + ], + 'export_dependent_settings': [ + '../v8/tools/gyp/v8.gyp:v8', + ], + 'sources': [ + 'array_buffer.cc', + 'array_buffer.h', + 'converter.cc', + 'converter.h', + 'initialize.cc', + 'initialize.h', + 'per_isolate_data.cc', + 'per_isolate_data.h', + 'runner.cc', + 'runner.h', + 'wrapper_info.cc', + 'wrapper_info.h', + ], + }, + { + 'target_name': 'gin_unittests', + 'type': 'executable', + 'dependencies': [ + '../base/base.gyp:base', + '../base/base.gyp:run_all_unittests', + '../testing/gtest.gyp:gtest', + 'gin', + ], + 'sources': [ + 'test/v8_test.cc', + 'test/run_all_unittests.cc', + 'converter_unittest.cc', + 'runner_unittest.cc', + ], + }, + ], +} diff --git a/gin/initialize.cc b/gin/initialize.cc new file mode 100644 index 0000000..450ff2a --- /dev/null +++ b/gin/initialize.cc @@ -0,0 +1,38 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gin/initialize.h" + +#include +#include + +#include "gin/array_buffer.h" +#include "gin/per_isolate_data.h" + +namespace gin { + +namespace { + +bool GenerateEntropy(unsigned char* buffer, size_t amount) { + // TODO(abarth): Gin needs a source of entropy. + return false; +} + +const char kFlags[] = "--use_strict --harmony"; + +} + +void Initialize() { + v8::V8::SetArrayBufferAllocator(ArrayBufferAllocator::SharedInstance()); + v8::V8::InitializeICU(); + v8::V8::SetFlagsFromString(kFlags, strlen(kFlags)); + v8::V8::SetEntropySource(&GenerateEntropy); + v8::V8::Initialize(); + + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HandleScope handle_scope(isolate); + new PerIsolateData(isolate); +} + +} // namespace gin diff --git a/gin/initialize.h b/gin/initialize.h new file mode 100644 index 0000000..4ebcf8d --- /dev/null +++ b/gin/initialize.h @@ -0,0 +1,14 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GIN_INITIALIZE_H_ +#define GIN_INITIALIZE_H_ + +namespace gin { + +void Initialize(); + +} // namespace gin + +#endif // GIN_INITIALIZE_H_ diff --git a/gin/per_isolate_data.cc b/gin/per_isolate_data.cc new file mode 100644 index 0000000..1320904 --- /dev/null +++ b/gin/per_isolate_data.cc @@ -0,0 +1,33 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gin/per_isolate_data.h" + +using v8::Eternal; +using v8::Handle; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::ObjectTemplate; + +namespace gin { + +PerIsolateData::PerIsolateData(Isolate* isolate) + : isolate_(isolate) { + isolate_->SetData(this); +} + +PerIsolateData::~PerIsolateData() { +} + +PerIsolateData* PerIsolateData::From(Isolate* isolate) { + return static_cast(isolate->GetData()); +} + +void PerIsolateData::RegisterObjectTemplate( + WrapperInfo* info, Local object_template) { + object_templates_[info] = Eternal(isolate_, object_template); +} + +} // namespace gin diff --git a/gin/per_isolate_data.h b/gin/per_isolate_data.h new file mode 100644 index 0000000..72467b8 --- /dev/null +++ b/gin/per_isolate_data.h @@ -0,0 +1,38 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef GIN_PER_ISOLATE_DATA_H_ +#define GIN_PER_ISOLATE_DATA_H_ + +#include + +#include "base/basictypes.h" +#include "gin/wrapper_info.h" +#include "v8/include/v8.h" + +namespace gin { + +class PerIsolateData { + public: + explicit PerIsolateData(v8::Isolate* isolate); + ~PerIsolateData(); + + static PerIsolateData* From(v8::Isolate* isolate); + + void RegisterObjectTemplate(WrapperInfo* info, + v8::Local object_template); + + private: + typedef std::map< + WrapperInfo*, v8::Eternal > ObjectTemplateMap; + + v8::Isolate* isolate_; + ObjectTemplateMap object_templates_; + + DISALLOW_COPY_AND_ASSIGN(PerIsolateData); +}; + +} // namespace gin + +#endif // GIN_PER_ISOLATE_DATA_H_ diff --git a/gin/runner.cc b/gin/runner.cc new file mode 100644 index 0000000..cf98399 --- /dev/null +++ b/gin/runner.cc @@ -0,0 +1,64 @@ +// Copyright 2013 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "gin/runner.h" + +#include "gin/converter.h" + +using v8::Context; +using v8::Function; +using v8::Handle; +using v8::HandleScope; +using v8::Isolate; +using v8::Local; +using v8::Object; +using v8::Script; +using v8::String; +using v8::Value; + +namespace gin { + +RunnerDelegate::~RunnerDelegate() { +} + +Runner::Runner(RunnerDelegate* delegate, Isolate* isolate) + : delegate_(delegate), + isolate_(isolate) { + HandleScope handle_scope(isolate_); + context_.Reset(isolate_, Context::New(isolate_)); +} + +Runner::~Runner() { + // TODO(abarth): Figure out how to set kResetInDestructor to true. + context_.Reset(); +} + +void Runner::Run(Handle