summaryrefslogtreecommitdiff
path: root/chromium/gin
diff options
context:
space:
mode:
authorAndras Becsi <andras.becsi@digia.com>2014-03-18 13:16:26 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2014-03-20 15:55:39 +0100
commit3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch)
tree92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/gin
parente90d7c4b152c56919d963987e2503f9909a666d2 (diff)
downloadqtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies needed on Windows. Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42 Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu> Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/gin')
-rw-r--r--chromium/gin/DEPS4
-rw-r--r--chromium/gin/OWNERS3
-rw-r--r--chromium/gin/README8
-rw-r--r--chromium/gin/arguments.cc48
-rw-r--r--chromium/gin/arguments.h80
-rw-r--r--chromium/gin/array_buffer.cc176
-rw-r--r--chromium/gin/array_buffer.h80
-rw-r--r--chromium/gin/context_holder.cc33
-rw-r--r--chromium/gin/converter.cc193
-rw-r--r--chromium/gin/converter.h194
-rw-r--r--chromium/gin/converter_unittest.cc133
-rw-r--r--chromium/gin/dictionary.cc42
-rw-r--r--chromium/gin/dictionary.h65
-rw-r--r--chromium/gin/function_template.cc26
-rw-r--r--chromium/gin/function_template.h357
-rw-r--r--chromium/gin/function_template.h.pump213
-rw-r--r--chromium/gin/gin.gyp122
-rw-r--r--chromium/gin/gin_export.h29
-rw-r--r--chromium/gin/handle.h68
-rw-r--r--chromium/gin/isolate_holder.cc79
-rw-r--r--chromium/gin/modules/console.cc49
-rw-r--r--chromium/gin/modules/console.h23
-rw-r--r--chromium/gin/modules/file_module_provider.cc72
-rw-r--r--chromium/gin/modules/file_module_provider.h44
-rw-r--r--chromium/gin/modules/module_registry.cc248
-rw-r--r--chromium/gin/modules/module_registry.h101
-rw-r--r--chromium/gin/modules/module_registry_unittests.js30
-rw-r--r--chromium/gin/modules/module_runner_delegate.cc55
-rw-r--r--chromium/gin/modules/module_runner_delegate.h56
-rw-r--r--chromium/gin/object_template_builder.cc36
-rw-r--r--chromium/gin/object_template_builder.h124
-rw-r--r--chromium/gin/per_context_data.cc52
-rw-r--r--chromium/gin/per_context_data.h62
-rw-r--r--chromium/gin/per_isolate_data.cc56
-rw-r--r--chromium/gin/per_isolate_data.h60
-rw-r--r--chromium/gin/public/context_holder.h54
-rw-r--r--chromium/gin/public/gin_embedders.h21
-rw-r--r--chromium/gin/public/isolate_holder.h51
-rw-r--r--chromium/gin/public/wrapper_info.h32
-rw-r--r--chromium/gin/runner.cc102
-rw-r--r--chromium/gin/runner.h87
-rw-r--r--chromium/gin/runner_unittest.cc37
-rw-r--r--chromium/gin/shell/gin_main.cc85
-rw-r--r--chromium/gin/try_catch.cc49
-rw-r--r--chromium/gin/try_catch.h33
-rw-r--r--chromium/gin/wrappable.cc72
-rw-r--r--chromium/gin/wrappable.h101
-rw-r--r--chromium/gin/wrappable_unittest.cc149
-rw-r--r--chromium/gin/wrapper_info.cc17
49 files changed, 3911 insertions, 0 deletions
diff --git a/chromium/gin/DEPS b/chromium/gin/DEPS
new file mode 100644
index 00000000000..4e3f30adc78
--- /dev/null
+++ b/chromium/gin/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+base",
+ "+v8",
+]
diff --git a/chromium/gin/OWNERS b/chromium/gin/OWNERS
new file mode 100644
index 00000000000..35dde41b938
--- /dev/null
+++ b/chromium/gin/OWNERS
@@ -0,0 +1,3 @@
+aa@chromium.org
+abarth@chromium.org
+jochen@chromium.org
diff --git a/chromium/gin/README b/chromium/gin/README
new file mode 100644
index 00000000000..82d06188f3f
--- /dev/null
+++ b/chromium/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/chromium/gin/arguments.cc b/chromium/gin/arguments.cc
new file mode 100644
index 00000000000..c43ff283aa2
--- /dev/null
+++ b/chromium/gin/arguments.cc
@@ -0,0 +1,48 @@
+// 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/arguments.h"
+
+#include "base/strings/stringprintf.h"
+#include "gin/converter.h"
+
+namespace gin {
+
+Arguments::Arguments()
+ : isolate_(NULL),
+ info_(NULL),
+ next_(0),
+ insufficient_arguments_(false) {
+}
+
+Arguments::Arguments(const v8::FunctionCallbackInfo<v8::Value>& info)
+ : isolate_(info.GetIsolate()),
+ info_(&info),
+ next_(0),
+ insufficient_arguments_(false) {
+}
+
+Arguments::~Arguments() {
+}
+
+v8::Handle<v8::Value> Arguments::PeekNext() const {
+ if (next_ >= info_->Length())
+ return v8::Handle<v8::Value>();
+ return (*info_)[next_];
+}
+
+void Arguments::ThrowError() const {
+ if (insufficient_arguments_)
+ return ThrowTypeError("Insufficient number of arguments.");
+
+ ThrowTypeError(base::StringPrintf(
+ "Error processing argument %d.", next_ - 1));
+}
+
+void Arguments::ThrowTypeError(const std::string& message) const {
+ isolate_->ThrowException(v8::Exception::TypeError(
+ StringToV8(isolate_, message)));
+}
+
+} // namespace gin
diff --git a/chromium/gin/arguments.h b/chromium/gin/arguments.h
new file mode 100644
index 00000000000..ec4ae80e882
--- /dev/null
+++ b/chromium/gin/arguments.h
@@ -0,0 +1,80 @@
+// 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_ARGUMENTS_H_
+#define GIN_ARGUMENTS_H_
+
+#include "base/basictypes.h"
+#include "gin/converter.h"
+#include "gin/gin_export.h"
+
+namespace gin {
+
+// Arguments is a wrapper around v8::FunctionCallbackInfo that integrates
+// with Converter to make it easier to marshall arguments and return values
+// between V8 and C++.
+class GIN_EXPORT Arguments {
+ public:
+ Arguments();
+ explicit Arguments(const v8::FunctionCallbackInfo<v8::Value>& info);
+ ~Arguments();
+
+ template<typename T>
+ bool GetHolder(T* out) {
+ return ConvertFromV8(isolate_, info_->Holder(), out);
+ }
+
+ template<typename T>
+ bool GetData(T* out) {
+ return ConvertFromV8(isolate_, info_->Data(), out);
+ }
+
+ template<typename T>
+ bool GetNext(T* out) {
+ if (next_ >= info_->Length()) {
+ insufficient_arguments_ = true;
+ return false;
+ }
+ v8::Handle<v8::Value> val = (*info_)[next_++];
+ return ConvertFromV8(isolate_, val, out);
+ }
+
+ template<typename T>
+ bool GetRemaining(std::vector<T>* out) {
+ if (next_ >= info_->Length()) {
+ insufficient_arguments_ = true;
+ return false;
+ }
+ int remaining = info_->Length() - next_;
+ out->resize(remaining);
+ for (int i = 0; i < remaining; ++i) {
+ v8::Handle<v8::Value> val = (*info_)[next_++];
+ if (!ConvertFromV8(isolate_, val, &out->at(i)))
+ return false;
+ }
+ return true;
+ }
+
+ template<typename T>
+ void Return(T val) {
+ info_->GetReturnValue().Set(ConvertToV8(isolate_, val));
+ }
+
+ v8::Handle<v8::Value> PeekNext() const;
+
+ void ThrowError() const;
+ void ThrowTypeError(const std::string& message) const;
+
+ v8::Isolate* isolate() const { return isolate_; }
+
+ private:
+ v8::Isolate* isolate_;
+ const v8::FunctionCallbackInfo<v8::Value>* info_;
+ int next_;
+ bool insufficient_arguments_;
+};
+
+} // namespace gin
+
+#endif // GIN_ARGUMENTS_H_
diff --git a/chromium/gin/array_buffer.cc b/chromium/gin/array_buffer.cc
new file mode 100644
index 00000000000..ee9f2a5867b
--- /dev/null
+++ b/chromium/gin/array_buffer.cc
@@ -0,0 +1,176 @@
+// 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 <stdlib.h>
+
+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;
+}
+
+// ArrayBuffer::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 ArrayBuffer::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 ArrayBuffer into the same array
+// buffer to AddRef the same ArrayBuffer::Private. To make that work, we store
+// a pointer to the ArrayBuffer::Private object in an internal field of the
+// ArrayBuffer object.
+//
+class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> {
+ public:
+ static scoped_refptr<Private> From(v8::Isolate* isolate,
+ v8::Handle<v8::ArrayBuffer> array);
+
+ void* buffer() const { return buffer_; }
+ size_t length() const { return length_; }
+
+ private:
+ friend class base::RefCounted<Private>;
+
+ Private(v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array);
+ ~Private();
+
+ static void WeakCallback(
+ const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data);
+
+ v8::Persistent<v8::ArrayBuffer> array_buffer_;
+ scoped_refptr<Private> self_reference_;
+ void* buffer_;
+ size_t length_;
+};
+
+scoped_refptr<ArrayBuffer::Private> ArrayBuffer::Private::From(
+ v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array) {
+ if (array->IsExternal()) {
+ return make_scoped_refptr(static_cast<Private*>(
+ array->GetAlignedPointerFromInternalField(kBufferViewPrivateIndex)));
+ }
+ return make_scoped_refptr(new Private(isolate, array));
+}
+
+ArrayBuffer::Private::Private(v8::Isolate* isolate,
+ v8::Handle<v8::ArrayBuffer> array)
+ : 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);
+
+ self_reference_ = this; // Cleared in WeakCallback.
+ array_buffer_.SetWeak(this, WeakCallback);
+}
+
+ArrayBuffer::Private::~Private() {
+ ArrayBufferAllocator::SharedInstance()->Free(buffer_, length_);
+}
+
+void ArrayBuffer::Private::WeakCallback(
+ const v8::WeakCallbackData<v8::ArrayBuffer, Private>& data) {
+ Private* parameter = data.GetParameter();
+ parameter->array_buffer_.Reset();
+ parameter->self_reference_ = NULL;
+}
+
+// ArrayBuffer ----------------------------------------------------------------
+
+ArrayBuffer::ArrayBuffer()
+ : bytes_(0),
+ num_bytes_(0) {
+}
+
+ArrayBuffer::ArrayBuffer(v8::Isolate* isolate,
+ v8::Handle<v8::ArrayBuffer> array) {
+ private_ = ArrayBuffer::Private::From(isolate, array);
+ bytes_ = private_->buffer();
+ num_bytes_ = private_->length();
+}
+
+ArrayBuffer::~ArrayBuffer() {
+}
+
+ArrayBuffer& ArrayBuffer::operator=(const ArrayBuffer& other) {
+ private_ = other.private_;
+ bytes_ = other.bytes_;
+ num_bytes_ = other.num_bytes_;
+ return *this;
+}
+
+// Converter<ArrayBuffer> -----------------------------------------------------
+
+bool Converter<ArrayBuffer>::FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ ArrayBuffer* out) {
+ if (!val->IsArrayBuffer())
+ return false;
+ *out = ArrayBuffer(isolate, v8::Handle<v8::ArrayBuffer>::Cast(val));
+ return true;
+}
+
+// ArrayBufferView ------------------------------------------------------------
+
+ArrayBufferView::ArrayBufferView()
+ : offset_(0),
+ num_bytes_(0) {
+}
+
+ArrayBufferView::ArrayBufferView(v8::Isolate* isolate,
+ v8::Handle<v8::ArrayBufferView> view)
+ : array_buffer_(isolate, view->Buffer()),
+ offset_(view->ByteOffset()),
+ num_bytes_(view->ByteLength()) {
+}
+
+ArrayBufferView::~ArrayBufferView() {
+}
+
+// Converter<ArrayBufferView> -------------------------------------------------
+
+bool Converter<ArrayBufferView>::FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ ArrayBufferView* out) {
+ if (!val->IsArrayBufferView())
+ return false;
+ *out = ArrayBufferView(isolate, v8::Handle<v8::ArrayBufferView>::Cast(val));
+ return true;
+}
+
+} // namespace gin
diff --git a/chromium/gin/array_buffer.h b/chromium/gin/array_buffer.h
new file mode 100644
index 00000000000..7886fa9be05
--- /dev/null
+++ b/chromium/gin/array_buffer.h
@@ -0,0 +1,80 @@
+// 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"
+#include "gin/converter.h"
+#include "gin/gin_export.h"
+#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 GIN_EXPORT ArrayBuffer {
+ public:
+ ArrayBuffer();
+ explicit ArrayBuffer(v8::Isolate* isolate);
+ ArrayBuffer(v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> buffer);
+ ~ArrayBuffer();
+ ArrayBuffer& operator=(const ArrayBuffer& other);
+
+ void* bytes() const { return bytes_; }
+ size_t num_bytes() const { return num_bytes_; }
+
+ private:
+ class Private;
+
+ scoped_refptr<Private> private_;
+ void* bytes_;
+ size_t num_bytes_;
+
+ DISALLOW_COPY(ArrayBuffer);
+};
+
+template<>
+struct GIN_EXPORT Converter<ArrayBuffer> {
+ static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
+ ArrayBuffer* out);
+};
+
+class GIN_EXPORT ArrayBufferView {
+ public:
+ ArrayBufferView();
+ ArrayBufferView(v8::Isolate* isolate, v8::Handle<v8::ArrayBufferView> view);
+ ~ArrayBufferView();
+
+ void* bytes() const {
+ return static_cast<uint8_t*>(array_buffer_.bytes()) + offset_;
+ }
+ size_t num_bytes() const { return num_bytes_; }
+
+ private:
+ ArrayBuffer array_buffer_;
+ size_t offset_;
+ size_t num_bytes_;
+
+ DISALLOW_COPY(ArrayBufferView);
+};
+
+template<>
+struct GIN_EXPORT Converter<ArrayBufferView> {
+ static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
+ ArrayBufferView* out);
+};
+
+} // namespace gin
+
+#endif // GIN_ARRAY_BUFFER_H_
diff --git a/chromium/gin/context_holder.cc b/chromium/gin/context_holder.cc
new file mode 100644
index 00000000000..32b50518376
--- /dev/null
+++ b/chromium/gin/context_holder.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/public/context_holder.h"
+
+#include "base/logging.h"
+#include "gin/per_context_data.h"
+
+namespace gin {
+
+ContextHolder::ContextHolder(v8::Isolate* isolate)
+ : isolate_(isolate) {
+}
+
+ContextHolder::~ContextHolder() {
+ v8::HandleScope handle_scope(isolate());
+ v8::Handle<v8::Context> context = this->context();
+
+ data_->Detach(context);
+ data_.reset();
+
+ // TODO(abarth): Figure out how to set kResetInDestructor to true.
+ context_.Reset();
+}
+
+void ContextHolder::SetContext(v8::Handle<v8::Context> context) {
+ DCHECK(context_.IsEmpty());
+ context_.Reset(isolate_, context);
+ data_.reset(new PerContextData(context));
+}
+
+} // namespace gin
diff --git a/chromium/gin/converter.cc b/chromium/gin/converter.cc
new file mode 100644
index 00000000000..54736f95aaf
--- /dev/null
+++ b/chromium/gin/converter.cc
@@ -0,0 +1,193 @@
+// 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::ArrayBuffer;
+using v8::Boolean;
+using v8::External;
+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<Value> Converter<bool>::ToV8(Isolate* isolate, bool val) {
+ return Boolean::New(isolate, val).As<Value>();
+}
+
+bool Converter<bool>::FromV8(Isolate* isolate, Handle<Value> val, bool* out) {
+ *out = val->BooleanValue();
+ return true;
+}
+
+Handle<Value> Converter<int32_t>::ToV8(Isolate* isolate, int32_t val) {
+ return Integer::New(isolate, val).As<Value>();
+}
+
+bool Converter<int32_t>::FromV8(Isolate* isolate, Handle<Value> val,
+ int32_t* out) {
+ if (!val->IsInt32())
+ return false;
+ *out = val->Int32Value();
+ return true;
+}
+
+Handle<Value> Converter<uint32_t>::ToV8(Isolate* isolate, uint32_t val) {
+ return Integer::NewFromUnsigned(isolate, val).As<Value>();
+}
+
+bool Converter<uint32_t>::FromV8(Isolate* isolate, Handle<Value> val,
+ uint32_t* out) {
+ if (!val->IsUint32())
+ return false;
+ *out = val->Uint32Value();
+ return true;
+}
+
+Handle<Value> Converter<int64_t>::ToV8(Isolate* isolate, int64_t val) {
+ return Number::New(isolate, static_cast<double>(val)).As<Value>();
+}
+
+bool Converter<int64_t>::FromV8(Isolate* isolate, Handle<Value> val,
+ int64_t* out) {
+ if (!val->IsNumber())
+ return false;
+ // Even though IntegerValue returns int64_t, JavaScript cannot represent
+ // the full precision of int64_t, which means some rounding might occur.
+ *out = val->IntegerValue();
+ return true;
+}
+
+Handle<Value> Converter<uint64_t>::ToV8(Isolate* isolate, uint64_t val) {
+ return Number::New(isolate, static_cast<double>(val)).As<Value>();
+}
+
+bool Converter<uint64_t>::FromV8(Isolate* isolate, Handle<Value> val,
+ uint64_t* out) {
+ if (!val->IsNumber())
+ return false;
+ *out = static_cast<uint64_t>(val->IntegerValue());
+ return true;
+}
+
+Handle<Value> Converter<double>::ToV8(Isolate* isolate, double val) {
+ return Number::New(isolate, val).As<Value>();
+}
+
+bool Converter<double>::FromV8(Isolate* isolate, Handle<Value> val,
+ double* out) {
+ if (!val->IsNumber())
+ return false;
+ *out = val->NumberValue();
+ return true;
+}
+
+Handle<Value> Converter<base::StringPiece>::ToV8(
+ Isolate* isolate, const base::StringPiece& val) {
+ return String::NewFromUtf8(isolate, val.data(), String::kNormalString,
+ static_cast<uint32_t>(val.length()));
+}
+
+Handle<Value> Converter<std::string>::ToV8(Isolate* isolate,
+ const std::string& val) {
+ return Converter<base::StringPiece>::ToV8(isolate, val);
+}
+
+bool Converter<std::string>::FromV8(Isolate* isolate, Handle<Value> val,
+ std::string* out) {
+ if (!val->IsString())
+ return false;
+ Handle<String> str = Handle<String>::Cast(val);
+ int length = str->Utf8Length();
+ out->resize(length);
+ str->WriteUtf8(&(*out)[0], length, NULL, String::NO_NULL_TERMINATION);
+ return true;
+}
+
+bool Converter<Handle<Function> >::FromV8(Isolate* isolate, Handle<Value> val,
+ Handle<Function>* out) {
+ if (!val->IsFunction())
+ return false;
+ *out = Handle<Function>::Cast(val);
+ return true;
+}
+
+Handle<Value> Converter<Handle<Object> >::ToV8(Isolate* isolate,
+ Handle<Object> val) {
+ return val.As<Value>();
+}
+
+bool Converter<Handle<Object> >::FromV8(Isolate* isolate, Handle<Value> val,
+ Handle<Object>* out) {
+ if (!val->IsObject())
+ return false;
+ *out = Handle<Object>::Cast(val);
+ return true;
+}
+
+Handle<Value> Converter<Handle<ArrayBuffer> >::ToV8(Isolate* isolate,
+ Handle<ArrayBuffer> val) {
+ return val.As<Value>();
+}
+
+bool Converter<Handle<ArrayBuffer> >::FromV8(Isolate* isolate,
+ Handle<Value> val,
+ Handle<ArrayBuffer>* out) {
+ if (!val->IsArrayBuffer())
+ return false;
+ *out = Handle<ArrayBuffer>::Cast(val);
+ return true;
+}
+
+Handle<Value> Converter<Handle<External> >::ToV8(Isolate* isolate,
+ Handle<External> val) {
+ return val.As<Value>();
+}
+
+bool Converter<Handle<External> >::FromV8(Isolate* isolate,
+ v8::Handle<Value> val,
+ Handle<External>* out) {
+ if (!val->IsExternal())
+ return false;
+ *out = Handle<External>::Cast(val);
+ return true;
+}
+
+Handle<Value> Converter<Handle<Value> >::ToV8(Isolate* isolate,
+ Handle<Value> val) {
+ return val;
+}
+
+bool Converter<Handle<Value> >::FromV8(Isolate* isolate, Handle<Value> val,
+ Handle<Value>* out) {
+ *out = val;
+ return true;
+}
+
+v8::Handle<v8::String> StringToSymbol(v8::Isolate* isolate,
+ const base::StringPiece& val) {
+ return String::NewFromUtf8(isolate,
+ val.data(),
+ String::kInternalizedString,
+ static_cast<uint32_t>(val.length()));
+}
+
+std::string V8ToString(v8::Handle<v8::Value> value) {
+ if (value.IsEmpty())
+ return std::string();
+ std::string result;
+ if (!ConvertFromV8(NULL, value, &result))
+ return std::string();
+ return result;
+}
+
+} // namespace gin
diff --git a/chromium/gin/converter.h b/chromium/gin/converter.h
new file mode 100644
index 00000000000..ee029a7f770
--- /dev/null
+++ b/chromium/gin/converter.h
@@ -0,0 +1,194 @@
+// 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 <string>
+#include <vector>
+
+#include "base/strings/string_piece.h"
+#include "gin/gin_export.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+template<typename T, typename Enable = void>
+struct Converter {};
+
+template<>
+struct GIN_EXPORT Converter<bool> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ bool val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ bool* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<int32_t> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ int32_t val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ int32_t* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<uint32_t> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ uint32_t val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ uint32_t* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<int64_t> {
+ // Warning: JavaScript cannot represent 64 integers precisely.
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ int64_t val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ int64_t* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<uint64_t> {
+ // Warning: JavaScript cannot represent 64 integers precisely.
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ uint64_t val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ uint64_t* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<double> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ double val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ double* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<base::StringPiece> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ const base::StringPiece& val);
+ // No conversion out is possible because StringPiece does not contain storage.
+};
+
+template<>
+struct GIN_EXPORT Converter<std::string> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ const std::string& val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ std::string* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<v8::Handle<v8::Function> > {
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ v8::Handle<v8::Function>* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<v8::Handle<v8::Object> > {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ v8::Handle<v8::Object> val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ v8::Handle<v8::Object>* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<v8::Handle<v8::ArrayBuffer> > {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ v8::Handle<v8::ArrayBuffer> val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ v8::Handle<v8::ArrayBuffer>* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<v8::Handle<v8::External> > {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ v8::Handle<v8::External> val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ v8::Handle<v8::External>* out);
+};
+
+template<>
+struct GIN_EXPORT Converter<v8::Handle<v8::Value> > {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ v8::Handle<v8::Value>* out);
+};
+
+template<typename T>
+struct Converter<std::vector<T> > {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ const std::vector<T>& val) {
+ v8::Handle<v8::Array> result(
+ v8::Array::New(isolate, static_cast<int>(val.size())));
+ for (size_t i = 0; i < val.size(); ++i) {
+ result->Set(static_cast<int>(i), Converter<T>::ToV8(isolate, val[i]));
+ }
+ return result;
+ }
+
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ std::vector<T>* out) {
+ if (!val->IsArray())
+ return false;
+
+ std::vector<T> result;
+ v8::Handle<v8::Array> array(v8::Handle<v8::Array>::Cast(val));
+ uint32_t length = array->Length();
+ for (uint32_t i = 0; i < length; ++i) {
+ T item;
+ if (!Converter<T>::FromV8(isolate, array->Get(i), &item))
+ return false;
+ result.push_back(item);
+ }
+
+ out->swap(result);
+ return true;
+ }
+};
+
+// Convenience functions that deduce T.
+template<typename T>
+v8::Handle<v8::Value> ConvertToV8(v8::Isolate* isolate,
+ T input) {
+ return Converter<T>::ToV8(isolate, input);
+}
+
+GIN_EXPORT inline v8::Handle<v8::String> StringToV8(
+ v8::Isolate* isolate,
+ const base::StringPiece& input) {
+ return ConvertToV8(isolate, input).As<v8::String>();
+}
+
+GIN_EXPORT v8::Handle<v8::String> StringToSymbol(v8::Isolate* isolate,
+ const base::StringPiece& val);
+
+template<typename T>
+bool ConvertFromV8(v8::Isolate* isolate, v8::Handle<v8::Value> input,
+ T* result) {
+ return Converter<T>::FromV8(isolate, input, result);
+}
+
+GIN_EXPORT std::string V8ToString(v8::Handle<v8::Value> value);
+
+} // namespace gin
+
+#endif // GIN_CONVERTER_H_
diff --git a/chromium/gin/converter_unittest.cc b/chromium/gin/converter_unittest.cc
new file mode 100644
index 00000000000..9b831b91ac0
--- /dev/null
+++ b/chromium/gin/converter_unittest.cc
@@ -0,0 +1,133 @@
+// 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 <limits.h>
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "gin/public/isolate_holder.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(instance_->isolate());
+
+ EXPECT_TRUE(Converter<bool>::ToV8(instance_->isolate(), true)->StrictEquals(
+ Boolean::New(instance_->isolate(), true)));
+ EXPECT_TRUE(Converter<bool>::ToV8(instance_->isolate(), false)->StrictEquals(
+ Boolean::New(instance_->isolate(), false)));
+
+ struct {
+ Handle<Value> input;
+ bool expected;
+ } test_data[] = {
+ { Boolean::New(instance_->isolate(), false).As<Value>(), false },
+ { Boolean::New(instance_->isolate(), true).As<Value>(), true },
+ { Number::New(instance_->isolate(), 0).As<Value>(), false },
+ { Number::New(instance_->isolate(), 1).As<Value>(), true },
+ { Number::New(instance_->isolate(), -1).As<Value>(), true },
+ { Number::New(instance_->isolate(), 0.1).As<Value>(), true },
+ { String::NewFromUtf8(instance_->isolate(), "").As<Value>(), false },
+ { String::NewFromUtf8(instance_->isolate(), "foo").As<Value>(), true },
+ { Object::New(instance_->isolate()).As<Value>(), true },
+ { Null(instance_->isolate()).As<Value>(), false },
+ { Undefined(instance_->isolate()).As<Value>(), false },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data); ++i) {
+ bool result = false;
+ EXPECT_TRUE(Converter<bool>::FromV8(instance_->isolate(),
+ test_data[i].input, &result));
+ EXPECT_EQ(test_data[i].expected, result);
+
+ result = true;
+ EXPECT_TRUE(Converter<bool>::FromV8(instance_->isolate(),
+ test_data[i].input, &result));
+ EXPECT_EQ(test_data[i].expected, result);
+ }
+}
+
+TEST_F(ConverterTest, Int32) {
+ HandleScope handle_scope(instance_->isolate());
+
+ int test_data_to[] = {-1, 0, 1};
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data_to); ++i) {
+ EXPECT_TRUE(Converter<int32_t>::ToV8(instance_->isolate(),
+ test_data_to[i])->StrictEquals(Integer::New(test_data_to[i])));
+ }
+
+ struct {
+ v8::Handle<v8::Value> input;
+ bool expect_sucess;
+ int expected_result;
+ } test_data_from[] = {
+ { Boolean::New(instance_->isolate(), false).As<Value>(), false, 0 },
+ { Boolean::New(instance_->isolate(), true).As<Value>(), false, 0 },
+ { Integer::New(instance_->isolate(), -1).As<Value>(), true, -1 },
+ { Integer::New(instance_->isolate(), 0).As<Value>(), true, 0 },
+ { Integer::New(instance_->isolate(), 1).As<Value>(), true, 1 },
+ { Number::New(instance_->isolate(), -1).As<Value>(), true, -1 },
+ { Number::New(instance_->isolate(), 1.1).As<Value>(), false, 0 },
+ { String::NewFromUtf8(instance_->isolate(), "42").As<Value>(), false, 0 },
+ { String::NewFromUtf8(instance_->isolate(), "foo").As<Value>(), false, 0 },
+ { Object::New(instance_->isolate()).As<Value>(), false, 0 },
+ { Array::New(instance_->isolate()).As<Value>(), false, 0 },
+ { v8::Null(instance_->isolate()).As<Value>(), false, 0 },
+ { v8::Undefined(instance_->isolate()).As<Value>(), false, 0 },
+ };
+
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_data_from); ++i) {
+ int32_t result = std::numeric_limits<int32_t>::min();
+ bool success = Converter<int32_t>::FromV8(instance_->isolate(),
+ 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(instance_->isolate());
+
+ std::vector<int> expected;
+ expected.push_back(-1);
+ expected.push_back(0);
+ expected.push_back(1);
+
+ Handle<Array> js_array = Handle<Array>::Cast(
+ Converter<std::vector<int> >::ToV8(instance_->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(instance_->isolate(), expected[i])
+ ->StrictEquals(js_array->Get(static_cast<int>(i))));
+ }
+
+ std::vector<int> actual;
+ EXPECT_TRUE(Converter<std::vector<int> >::FromV8(instance_->isolate(),
+ js_array, &actual));
+ EXPECT_EQ(expected, actual);
+}
+
+} // namespace gin
diff --git a/chromium/gin/dictionary.cc b/chromium/gin/dictionary.cc
new file mode 100644
index 00000000000..d3361228bb2
--- /dev/null
+++ b/chromium/gin/dictionary.cc
@@ -0,0 +1,42 @@
+// 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/dictionary.h"
+
+namespace gin {
+
+Dictionary::Dictionary(v8::Isolate* isolate)
+ : isolate_(isolate) {
+}
+
+Dictionary::Dictionary(v8::Isolate* isolate,
+ v8::Handle<v8::Object> object)
+ : isolate_(isolate),
+ object_(object) {
+}
+
+Dictionary::~Dictionary() {
+}
+
+Dictionary Dictionary::CreateEmpty(v8::Isolate* isolate) {
+ Dictionary dictionary(isolate);
+ dictionary.object_ = v8::Object::New(isolate);
+ return dictionary;
+}
+
+v8::Handle<v8::Value> Converter<Dictionary>::ToV8(v8::Isolate* isolate,
+ Dictionary val) {
+ return val.object_;
+}
+
+bool Converter<Dictionary>::FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ Dictionary* out) {
+ if (!val->IsObject())
+ return false;
+ *out = Dictionary(isolate, v8::Handle<v8::Object>::Cast(val));
+ return true;
+}
+
+} // namespace gin
diff --git a/chromium/gin/dictionary.h b/chromium/gin/dictionary.h
new file mode 100644
index 00000000000..972108fbb43
--- /dev/null
+++ b/chromium/gin/dictionary.h
@@ -0,0 +1,65 @@
+// 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_DICTIONARY_H_
+#define GIN_DICTIONARY_H_
+
+#include "gin/converter.h"
+#include "gin/gin_export.h"
+
+namespace gin {
+
+// Dictionary is useful when writing bindings for a function that either
+// receives an arbitrary JavaScript object as an argument or returns an
+// arbitrary JavaScript object as a result. For example, Dictionary is useful
+// when you might use the |dictionary| type in WebIDL:
+//
+// http://heycam.github.io/webidl/#idl-dictionaries
+//
+// WARNING: You cannot retain a Dictionary object in the heap. The underlying
+// storage for Dictionary is tied to the closest enclosing
+// v8::HandleScope. Generally speaking, you should store a Dictionary
+// on the stack.
+//
+class GIN_EXPORT Dictionary {
+ public:
+ explicit Dictionary(v8::Isolate* isolate);
+ Dictionary(v8::Isolate* isolate, v8::Handle<v8::Object> object);
+ ~Dictionary();
+
+ static Dictionary CreateEmpty(v8::Isolate* isolate);
+
+ template<typename T>
+ bool Get(const std::string& key, T* out) {
+ v8::Handle<v8::Value> val = object_->Get(StringToV8(isolate_, key));
+ return ConvertFromV8(isolate_, val, out);
+ }
+
+ template<typename T>
+ bool Set(const std::string& key, T val) {
+ return object_->Set(StringToV8(isolate_, key), ConvertToV8(isolate_, val));
+ }
+
+ v8::Isolate* isolate() const { return isolate_; }
+
+ private:
+ friend struct Converter<Dictionary>;
+
+ // TODO(aa): Remove this. Instead, get via FromV8(), Set(), and Get().
+ v8::Isolate* isolate_;
+ v8::Handle<v8::Object> object_;
+};
+
+template<>
+struct GIN_EXPORT Converter<Dictionary> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ Dictionary val);
+ static bool FromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ Dictionary* out);
+};
+
+} // namespace gin
+
+#endif // GIN_DICTIONARY_H_
diff --git a/chromium/gin/function_template.cc b/chromium/gin/function_template.cc
new file mode 100644
index 00000000000..5dd5ecd3d50
--- /dev/null
+++ b/chromium/gin/function_template.cc
@@ -0,0 +1,26 @@
+// 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/function_template.h"
+
+#include "gin/per_isolate_data.h"
+
+namespace gin {
+
+WrapperInfo internal::CallbackHolderBase::kWrapperInfo = { kEmbedderNativeGin };
+
+void InitFunctionTemplates(PerIsolateData* isolate_data) {
+ if (!isolate_data->GetObjectTemplate(
+ &internal::CallbackHolderBase::kWrapperInfo).IsEmpty()) {
+ return;
+ }
+
+ v8::Handle<v8::ObjectTemplate> templ(
+ v8::ObjectTemplate::New(isolate_data->isolate()));
+ templ->SetInternalFieldCount(kNumberOfInternalFields);
+ isolate_data->SetObjectTemplate(&internal::CallbackHolderBase::kWrapperInfo,
+ templ);
+}
+
+} // namespace gin
diff --git a/chromium/gin/function_template.h b/chromium/gin/function_template.h
new file mode 100644
index 00000000000..14f6e78fe2f
--- /dev/null
+++ b/chromium/gin/function_template.h
@@ -0,0 +1,357 @@
+// This file was GENERATED by command:
+// pump.py function_template.h.pump
+// DO NOT EDIT BY HAND!!!
+
+
+
+#ifndef GIN_FUNCTION_TEMPLATE_H_
+#define GIN_FUNCTION_TEMPLATE_H_
+
+// 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 "base/callback.h"
+#include "base/logging.h"
+#include "gin/arguments.h"
+#include "gin/converter.h"
+#include "gin/gin_export.h"
+#include "gin/handle.h"
+#include "gin/public/gin_embedders.h"
+#include "gin/public/wrapper_info.h"
+#include "gin/wrappable.h"
+
+#include "v8/include/v8.h"
+
+namespace gin {
+
+class PerIsolateData;
+
+enum CreateFunctionTemplateFlags {
+ HolderIsFirstArgument = 1 << 0,
+};
+
+namespace internal {
+
+template<typename T>
+struct CallbackParamTraits {
+ typedef T LocalType;
+};
+template<typename T>
+struct CallbackParamTraits<const T&> {
+ typedef T LocalType;
+};
+template<typename T>
+struct CallbackParamTraits<const T*> {
+ typedef T* LocalType;
+};
+
+
+// CallbackHolder and CallbackHolderBase are used to pass a base::Callback from
+// CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to
+// DispatchToCallback, where it is invoked.
+//
+// v8::FunctionTemplate only supports passing void* as data so how do we know
+// when to delete the base::Callback? That's where CallbackHolderBase comes in.
+// It inherits from Wrappable, which delete itself when both (a) the refcount
+// via base::RefCounted has dropped to zero, and (b) there are no more
+// JavaScript references in V8.
+
+// This simple base class is used so that we can share a single object template
+// among every CallbackHolder instance.
+class GIN_EXPORT CallbackHolderBase : public Wrappable<CallbackHolderBase> {
+ public:
+ static WrapperInfo kWrapperInfo;
+ protected:
+ virtual ~CallbackHolderBase() {}
+};
+
+template<typename Sig>
+class CallbackHolder : public CallbackHolderBase {
+ public:
+ CallbackHolder(const base::Callback<Sig>& callback, int flags)
+ : callback(callback), flags(flags) {}
+ base::Callback<Sig> callback;
+ int flags;
+ private:
+ virtual ~CallbackHolder() {}
+};
+
+
+// This set of templates invokes a base::Callback, converts the return type to a
+// JavaScript value, and returns that value to script via the provided
+// gin::Arguments object.
+//
+// In C++, you can declare the function foo(void), but you can't pass a void
+// expression to foo. As a result, we must specialize the case of Callbacks that
+// have the void return type.
+template<typename R, typename P1 = void, typename P2 = void,
+ typename P3 = void, typename P4 = void>
+struct Invoker {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<R(P1, P2, P3, P4)>& callback,
+ const P1& a1,
+ const P2& a2,
+ const P3& a3,
+ const P4& a4) {
+ args->Return(callback.Run(a1, a2, a3, a4));
+ }
+};
+template<typename P1, typename P2, typename P3, typename P4>
+struct Invoker<void, P1, P2, P3, P4> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<void(P1, P2, P3, P4)>& callback,
+ const P1& a1,
+ const P2& a2,
+ const P3& a3,
+ const P4& a4) {
+ callback.Run(a1, a2, a3, a4);
+ }
+};
+
+template<typename R, typename P1, typename P2, typename P3>
+struct Invoker<R, P1, P2, P3, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<R(P1, P2, P3)>& callback,
+ const P1& a1,
+ const P2& a2,
+ const P3& a3) {
+ args->Return(callback.Run(a1, a2, a3));
+ }
+};
+template<typename P1, typename P2, typename P3>
+struct Invoker<void, P1, P2, P3, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<void(P1, P2, P3)>& callback,
+ const P1& a1,
+ const P2& a2,
+ const P3& a3) {
+ callback.Run(a1, a2, a3);
+ }
+};
+
+template<typename R, typename P1, typename P2>
+struct Invoker<R, P1, P2, void, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<R(P1, P2)>& callback,
+ const P1& a1,
+ const P2& a2) {
+ args->Return(callback.Run(a1, a2));
+ }
+};
+template<typename P1, typename P2>
+struct Invoker<void, P1, P2, void, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<void(P1, P2)>& callback,
+ const P1& a1,
+ const P2& a2) {
+ callback.Run(a1, a2);
+ }
+};
+
+template<typename R, typename P1>
+struct Invoker<R, P1, void, void, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<R(P1)>& callback,
+ const P1& a1) {
+ args->Return(callback.Run(a1));
+ }
+};
+template<typename P1>
+struct Invoker<void, P1, void, void, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<void(P1)>& callback,
+ const P1& a1) {
+ callback.Run(a1);
+ }
+};
+
+template<typename R>
+struct Invoker<R, void, void, void, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<R()>& callback) {
+ args->Return(callback.Run());
+ }
+};
+template<>
+struct Invoker<void, void, void, void, void> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<void()>& callback) {
+ callback.Run();
+ }
+};
+
+
+template<typename T>
+bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
+ T* result) {
+ if (is_first && (create_flags & HolderIsFirstArgument) != 0) {
+ return args->GetHolder(result);
+ } else {
+ return args->GetNext(result);
+ }
+}
+
+// For advanced use cases, we allow callers to request the unparsed Arguments
+// object and poke around in it directly.
+inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
+ Arguments* result) {
+ *result = *args;
+ return true;
+}
+
+
+// DispatchToCallback converts all the JavaScript arguments to C++ types and
+// invokes the base::Callback.
+template<typename Sig>
+struct Dispatcher {
+};
+
+template<typename R>
+struct Dispatcher<R()> {
+ static void DispatchToCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Arguments args(info);
+ CallbackHolderBase* holder_base = NULL;
+ CHECK(args.GetData(&holder_base));
+
+ typedef CallbackHolder<R()> HolderT;
+ HolderT* holder = static_cast<HolderT*>(holder_base);
+
+ Invoker<R>::Go(&args, holder->callback);
+ }
+};
+
+template<typename R, typename P1>
+struct Dispatcher<R(P1)> {
+ static void DispatchToCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Arguments args(info);
+ CallbackHolderBase* holder_base = NULL;
+ CHECK(args.GetData(&holder_base));
+
+ typedef CallbackHolder<R(P1)> HolderT;
+ HolderT* holder = static_cast<HolderT*>(holder_base);
+
+ typename CallbackParamTraits<P1>::LocalType a1;
+ if (!GetNextArgument(&args, holder->flags, true, &a1)) {
+ args.ThrowError();
+ return;
+ }
+
+ Invoker<R, P1>::Go(&args, holder->callback, a1);
+ }
+};
+
+template<typename R, typename P1, typename P2>
+struct Dispatcher<R(P1, P2)> {
+ static void DispatchToCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Arguments args(info);
+ CallbackHolderBase* holder_base = NULL;
+ CHECK(args.GetData(&holder_base));
+
+ typedef CallbackHolder<R(P1, P2)> HolderT;
+ HolderT* holder = static_cast<HolderT*>(holder_base);
+
+ typename CallbackParamTraits<P1>::LocalType a1;
+ typename CallbackParamTraits<P2>::LocalType a2;
+ if (!GetNextArgument(&args, holder->flags, true, &a1) ||
+ !GetNextArgument(&args, holder->flags, false, &a2)) {
+ args.ThrowError();
+ return;
+ }
+
+ Invoker<R, P1, P2>::Go(&args, holder->callback, a1, a2);
+ }
+};
+
+template<typename R, typename P1, typename P2, typename P3>
+struct Dispatcher<R(P1, P2, P3)> {
+ static void DispatchToCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Arguments args(info);
+ CallbackHolderBase* holder_base = NULL;
+ CHECK(args.GetData(&holder_base));
+
+ typedef CallbackHolder<R(P1, P2, P3)> HolderT;
+ HolderT* holder = static_cast<HolderT*>(holder_base);
+
+ typename CallbackParamTraits<P1>::LocalType a1;
+ typename CallbackParamTraits<P2>::LocalType a2;
+ typename CallbackParamTraits<P3>::LocalType a3;
+ if (!GetNextArgument(&args, holder->flags, true, &a1) ||
+ !GetNextArgument(&args, holder->flags, false, &a2) ||
+ !GetNextArgument(&args, holder->flags, false, &a3)) {
+ args.ThrowError();
+ return;
+ }
+
+ Invoker<R, P1, P2, P3>::Go(&args, holder->callback, a1, a2, a3);
+ }
+};
+
+template<typename R, typename P1, typename P2, typename P3, typename P4>
+struct Dispatcher<R(P1, P2, P3, P4)> {
+ static void DispatchToCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Arguments args(info);
+ CallbackHolderBase* holder_base = NULL;
+ CHECK(args.GetData(&holder_base));
+
+ typedef CallbackHolder<R(P1, P2, P3, P4)> HolderT;
+ HolderT* holder = static_cast<HolderT*>(holder_base);
+
+ typename CallbackParamTraits<P1>::LocalType a1;
+ typename CallbackParamTraits<P2>::LocalType a2;
+ typename CallbackParamTraits<P3>::LocalType a3;
+ typename CallbackParamTraits<P4>::LocalType a4;
+ if (!GetNextArgument(&args, holder->flags, true, &a1) ||
+ !GetNextArgument(&args, holder->flags, false, &a2) ||
+ !GetNextArgument(&args, holder->flags, false, &a3) ||
+ !GetNextArgument(&args, holder->flags, false, &a4)) {
+ args.ThrowError();
+ return;
+ }
+
+ Invoker<R, P1, P2, P3, P4>::Go(&args, holder->callback, a1, a2, a3, a4);
+ }
+};
+
+} // namespace internal
+
+
+// This should be called once per-isolate to initialize the function template
+// system.
+GIN_EXPORT void InitFunctionTemplates(PerIsolateData* isolate_data);
+
+
+// CreateFunctionTemplate creates a v8::FunctionTemplate that will create
+// JavaScript functions that execute a provided C++ function or base::Callback.
+// JavaScript arguments are automatically converted via gin::Converter, as is
+// the return value of the C++ function, if any.
+template<typename Sig>
+v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
+ v8::Isolate* isolate, const base::Callback<Sig> callback,
+ int callback_flags = 0) {
+ typedef internal::CallbackHolder<Sig> HolderT;
+ gin::Handle<HolderT> holder = CreateHandle(
+ isolate, new HolderT(callback, callback_flags));
+ return v8::FunctionTemplate::New(
+ &internal::Dispatcher<Sig>::DispatchToCallback,
+ ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get()));
+}
+
+} // namespace gin
+
+#endif // GIN_FUNCTION_TEMPLATE_H_
diff --git a/chromium/gin/function_template.h.pump b/chromium/gin/function_template.h.pump
new file mode 100644
index 00000000000..fad718febc2
--- /dev/null
+++ b/chromium/gin/function_template.h.pump
@@ -0,0 +1,213 @@
+$$ This is a pump file for generating file templates. Pump is a python
+$$ script that is part of the Google Test suite of utilities. Description
+$$ can be found here:
+$$
+$$ http://code.google.com/p/googletest/wiki/PumpManual
+$$
+
+#ifndef GIN_FUNCTION_TEMPLATE_H_
+#define GIN_FUNCTION_TEMPLATE_H_
+
+$var MAX_ARITY = 4
+
+// 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 "base/callback.h"
+#include "base/logging.h"
+#include "gin/arguments.h"
+#include "gin/converter.h"
+#include "gin/gin_export.h"
+#include "gin/handle.h"
+#include "gin/public/gin_embedders.h"
+#include "gin/public/wrapper_info.h"
+#include "gin/wrappable.h"
+
+#include "v8/include/v8.h"
+
+namespace gin {
+
+class PerIsolateData;
+
+enum CreateFunctionTemplateFlags {
+ HolderIsFirstArgument = 1 << 0,
+};
+
+namespace internal {
+
+template<typename T>
+struct CallbackParamTraits {
+ typedef T LocalType;
+};
+template<typename T>
+struct CallbackParamTraits<const T&> {
+ typedef T LocalType;
+};
+template<typename T>
+struct CallbackParamTraits<const T*> {
+ typedef T* LocalType;
+};
+
+
+// CallbackHolder and CallbackHolderBase are used to pass a base::Callback from
+// CreateFunctionTemplate through v8 (via v8::FunctionTemplate) to
+// DispatchToCallback, where it is invoked.
+//
+// v8::FunctionTemplate only supports passing void* as data so how do we know
+// when to delete the base::Callback? That's where CallbackHolderBase comes in.
+// It inherits from Wrappable, which delete itself when both (a) the refcount
+// via base::RefCounted has dropped to zero, and (b) there are no more
+// JavaScript references in V8.
+
+// This simple base class is used so that we can share a single object template
+// among every CallbackHolder instance.
+class GIN_EXPORT CallbackHolderBase : public Wrappable<CallbackHolderBase> {
+ public:
+ static WrapperInfo kWrapperInfo;
+
+ protected:
+ virtual ~CallbackHolderBase() {}
+};
+
+template<typename Sig>
+class CallbackHolder : public CallbackHolderBase {
+ public:
+ CallbackHolder(const base::Callback<Sig>& callback, int flags)
+ : callback(callback), flags(flags) {}
+ base::Callback<Sig> callback;
+ int flags;
+ private:
+ virtual ~CallbackHolder() {}
+};
+
+
+// This set of templates invokes a base::Callback, converts the return type to a
+// JavaScript value, and returns that value to script via the provided
+// gin::Arguments object.
+//
+// In C++, you can declare the function foo(void), but you can't pass a void
+// expression to foo. As a result, we must specialize the case of Callbacks that
+// have the void return type.
+
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$var INV_ARITY = MAX_ARITY - ARITY
+$range ARG 1..INV_ARITY
+$range VOID INV_ARITY+1..MAX_ARITY
+
+$if ARITY == 0 [[
+template<typename R$for ARG [[, typename P$(ARG) = void]]>
+struct Invoker {
+]] $else [[
+template<typename R$for ARG [[, typename P$(ARG)]]>
+struct Invoker<R$for ARG [[, P$(ARG)]]$for VOID [[, void]]> {
+]]
+
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<R($for ARG , [[P$(ARG)]])>& callback$for ARG [[,
+ const P$(ARG)& a$(ARG)]]) {
+ args->Return(callback.Run($for ARG, [[a$(ARG)]]));
+ }
+};
+template<$for ARG , [[typename P$(ARG)]]>
+struct Invoker<void$for ARG [[, P$(ARG)]]$for VOID [[, void]]> {
+ inline static void Go(
+ Arguments* args,
+ const base::Callback<void($for ARG , [[P$(ARG)]])>& callback$for ARG [[,
+ const P$(ARG)& a$(ARG)]]) {
+ callback.Run($for ARG, [[a$(ARG)]]);
+ }
+};
+
+
+]]
+
+template<typename T>
+bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
+ T* result) {
+ if (is_first && (create_flags & HolderIsFirstArgument) != 0) {
+ return args->GetHolder(result);
+ } else {
+ return args->GetNext(result);
+ }
+}
+
+// For advanced use cases, we allow callers to request the unparsed Arguments
+// object and poke around in it directly.
+inline bool GetNextArgument(Arguments* args, int create_flags, bool is_first,
+ Arguments* result) {
+ *result = *args;
+ return true;
+}
+
+
+// DispatchToCallback converts all the JavaScript arguments to C++ types and
+// invokes the base::Callback.
+template<typename Sig>
+struct Dispatcher {
+};
+
+$range ARITY 0..MAX_ARITY
+$for ARITY [[
+$range ARG 1..ARITY
+
+template<typename R$for ARG [[, typename P$(ARG)]]>
+struct Dispatcher<R($for ARG , [[P$(ARG)]])> {
+ static void DispatchToCallback(
+ const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Arguments args(info);
+ CallbackHolderBase* holder_base = NULL;
+ CHECK(args.GetData(&holder_base));
+
+ typedef CallbackHolder<R($for ARG , [[P$(ARG)]])> HolderT;
+ HolderT* holder = static_cast<HolderT*>(holder_base);
+
+$if ARITY != 0 [[
+
+
+$for ARG [[ typename CallbackParamTraits<P$(ARG)>::LocalType a$(ARG);
+
+]]
+ if ($for ARG ||
+ [[!GetNextArgument(&args, holder->flags, $if ARG == 1 [[true]] $else [[false]], &a$(ARG))]]) {
+ args.ThrowError();
+ return;
+ }
+
+]]
+
+ Invoker<R$for ARG [[, P$(ARG)]]>::Go(&args, holder->callback$for ARG [[, a$(ARG)]]);
+ }
+};
+
+]]
+
+} // namespace internal
+
+
+// This should be called once per-isolate to initialize the function template
+// system.
+GIN_EXPORT void InitFunctionTemplates(PerIsolateData* isolate_data);
+
+
+// CreateFunctionTemplate creates a v8::FunctionTemplate that will create
+// JavaScript functions that execute a provided C++ function or base::Callback.
+// JavaScript arguments are automatically converted via gin::Converter, as is
+// the return value of the C++ function, if any.
+template<typename Sig>
+v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
+ v8::Isolate* isolate, const base::Callback<Sig> callback,
+ int callback_flags = 0) {
+ typedef internal::CallbackHolder<Sig> HolderT;
+ gin::Handle<HolderT> holder = CreateHandle(
+ isolate, new HolderT(callback, callback_flags));
+ return v8::FunctionTemplate::New(
+ &internal::Dispatcher<Sig>::DispatchToCallback,
+ ConvertToV8<internal::CallbackHolderBase*>(isolate, holder.get()));
+}
+
+} // namespace gin
+
+#endif // GIN_FUNCTION_TEMPLATE_H_
diff --git a/chromium/gin/gin.gyp b/chromium/gin/gin.gyp
new file mode 100644
index 00000000000..8af1e8b85e0
--- /dev/null
+++ b/chromium/gin/gin.gyp
@@ -0,0 +1,122 @@
+# 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': '<(component)',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../v8/tools/gyp/v8.gyp:v8',
+ ],
+ 'export_dependent_settings': [
+ '../base/base.gyp:base',
+ '../v8/tools/gyp/v8.gyp:v8',
+ ],
+ 'defines': [
+ 'GIN_IMPLEMENTATION',
+ ],
+ 'sources': [
+ 'arguments.cc',
+ 'arguments.h',
+ 'array_buffer.cc',
+ 'array_buffer.h',
+ 'context_holder.cc',
+ 'converter.cc',
+ 'converter.h',
+ 'dictionary.cc',
+ 'dictionary.h',
+ 'function_template.cc',
+ 'function_template.h',
+ 'gin_export.h',
+ 'handle.h',
+ 'isolate_holder.cc',
+ 'modules/console.cc',
+ 'modules/console.h',
+ 'modules/file_module_provider.cc',
+ 'modules/file_module_provider.h',
+ 'modules/module_registry.cc',
+ 'modules/module_registry.h',
+ 'modules/module_runner_delegate.cc',
+ 'modules/module_runner_delegate.h',
+ 'object_template_builder.cc',
+ 'object_template_builder.h',
+ 'per_context_data.cc',
+ 'per_context_data.h',
+ 'per_isolate_data.cc',
+ 'per_isolate_data.h',
+ 'public/context_holder.h',
+ 'public/gin_embedders.h',
+ 'public/isolate_holder.h',
+ 'public/wrapper_info.h',
+ 'runner.cc',
+ 'runner.h',
+ 'try_catch.cc',
+ 'try_catch.h',
+ 'wrappable.cc',
+ 'wrappable.h',
+ 'wrapper_info.cc',
+ ],
+ },
+ {
+ 'target_name': 'gin_shell',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../base/base.gyp:base_i18n',
+ '../v8/tools/gyp/v8.gyp:v8',
+ 'gin',
+ ],
+ 'sources': [
+ 'shell/gin_main.cc',
+ ],
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '1', # /SUBSYSTEM:CONSOLE
+ },
+ },
+ },
+ {
+ 'target_name': 'gin_test',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../testing/gtest.gyp:gtest',
+ '../v8/tools/gyp/v8.gyp:v8',
+ 'gin',
+ ],
+ 'export_dependent_settings': [
+ '../testing/gtest.gyp:gtest',
+ 'gin',
+ ],
+ 'sources': [
+ 'test/file_runner.cc',
+ 'test/file_runner.h',
+ 'test/gtest.cc',
+ 'test/gtest.h',
+ 'test/v8_test.cc',
+ 'test/v8_test.h',
+ ],
+ },
+ {
+ 'target_name': 'gin_unittests',
+ 'type': 'executable',
+ 'dependencies': [
+ '../base/base.gyp:run_all_unittests',
+ '../v8/tools/gyp/v8.gyp:v8',
+ 'gin_test',
+ ],
+ 'sources': [
+ 'converter_unittest.cc',
+ 'test/run_all_unittests.cc',
+ 'test/run_js_tests.cc',
+ 'runner_unittest.cc',
+ 'wrappable_unittest.cc',
+ ],
+ },
+ ],
+}
diff --git a/chromium/gin/gin_export.h b/chromium/gin/gin_export.h
new file mode 100644
index 00000000000..fc4bf9bc003
--- /dev/null
+++ b/chromium/gin/gin_export.h
@@ -0,0 +1,29 @@
+// 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_GIN_EXPORT_H_
+#define GIN_GIN_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(GIN_IMPLEMENTATION)
+#define GIN_EXPORT __declspec(dllexport)
+#else
+#define GIN_EXPORT __declspec(dllimport)
+#endif // defined(GIN_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(GIN_IMPLEMENTATION)
+#define GIN_EXPORT __attribute__((visibility("default")))
+#else
+#define GIN_EXPORT
+#endif // defined(GIN_IMPLEMENTATION)
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define GIN_EXPORT
+#endif
+
+#endif // GIN_GIN_EXPORT_H_
diff --git a/chromium/gin/handle.h b/chromium/gin/handle.h
new file mode 100644
index 00000000000..da1de347f23
--- /dev/null
+++ b/chromium/gin/handle.h
@@ -0,0 +1,68 @@
+// 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_HANDLE_H_
+#define GIN_HANDLE_H_
+
+#include "gin/converter.h"
+
+namespace gin {
+
+// You can use gin::Handle on the stack to retain a gin::Wrappable object.
+// Currently we don't have a mechanism for retaining a gin::Wrappable object
+// in the C++ heap because strong references from C++ to V8 can cause memory
+// leaks.
+template<typename T>
+class Handle {
+ public:
+ Handle() : object_(NULL) {}
+
+ Handle(v8::Handle<v8::Value> wrapper, T* object)
+ : wrapper_(wrapper),
+ object_(object) {
+ }
+
+ bool IsEmpty() const { return !object_; }
+
+ void Clear() {
+ wrapper_.Clear();
+ object_ = NULL;
+ }
+
+ T* operator->() const { return object_; }
+ v8::Handle<v8::Value> ToV8() const { return wrapper_; }
+ T* get() const { return object_; }
+
+ private:
+ v8::Handle<v8::Value> wrapper_;
+ T* object_;
+};
+
+template<typename T>
+struct Converter<gin::Handle<T> > {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate,
+ const gin::Handle<T>& val) {
+ return val.ToV8();
+ }
+ static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val,
+ gin::Handle<T>* out) {
+ T* object = NULL;
+ if (!Converter<T*>::FromV8(isolate, val, &object)) {
+ return false;
+ }
+ *out = gin::Handle<T>(val, object);
+ return true;
+ }
+};
+
+// This function is a convenient way to create a handle from a raw pointer
+// without having to write out the type of the object explicitly.
+template<typename T>
+gin::Handle<T> CreateHandle(v8::Isolate* isolate, T* object) {
+ return gin::Handle<T>(object->GetWrapper(isolate), object);
+}
+
+} // namespace gin
+
+#endif // GIN_HANDLE_H_
diff --git a/chromium/gin/isolate_holder.cc b/chromium/gin/isolate_holder.cc
new file mode 100644
index 00000000000..1929ebd0342
--- /dev/null
+++ b/chromium/gin/isolate_holder.cc
@@ -0,0 +1,79 @@
+// 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/public/isolate_holder.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "base/logging.h"
+#include "base/rand_util.h"
+#include "base/sys_info.h"
+#include "gin/array_buffer.h"
+#include "gin/function_template.h"
+#include "gin/per_isolate_data.h"
+
+namespace gin {
+
+namespace {
+
+bool GenerateEntropy(unsigned char* buffer, size_t amount) {
+ base::RandBytes(buffer, amount);
+ return true;
+}
+
+
+void EnsureV8Initialized(bool gin_managed) {
+ static bool v8_is_initialized = false;
+ static bool v8_is_gin_managed = false;
+ if (v8_is_initialized) {
+ CHECK_EQ(v8_is_gin_managed, gin_managed);
+ return;
+ }
+ v8_is_initialized = true;
+ v8_is_gin_managed = gin_managed;
+ if (!gin_managed)
+ return;
+
+ v8::V8::SetArrayBufferAllocator(ArrayBufferAllocator::SharedInstance());
+ static const char v8_flags[] = "--use_strict --harmony";
+ v8::V8::SetFlagsFromString(v8_flags, sizeof(v8_flags) - 1);
+ v8::V8::SetEntropySource(&GenerateEntropy);
+ v8::V8::Initialize();
+}
+
+} // namespace
+
+IsolateHolder::IsolateHolder()
+ : isolate_owner_(true) {
+ EnsureV8Initialized(true);
+ isolate_ = v8::Isolate::New();
+ v8::ResourceConstraints constraints;
+ constraints.ConfigureDefaults(base::SysInfo::AmountOfPhysicalMemory(),
+ base::SysInfo::NumberOfProcessors());
+ v8::SetResourceConstraints(isolate_, &constraints);
+ Init();
+}
+
+IsolateHolder::IsolateHolder(v8::Isolate* isolate)
+ : isolate_owner_(false),
+ isolate_(isolate) {
+ EnsureV8Initialized(false);
+ Init();
+}
+
+IsolateHolder::~IsolateHolder() {
+ isolate_data_.reset();
+ if (isolate_owner_)
+ isolate_->Dispose();
+}
+
+void IsolateHolder::Init() {
+ v8::Isolate::Scope isolate_scope(isolate_);
+ v8::HandleScope handle_scope(isolate_);
+ isolate_data_.reset(new PerIsolateData(isolate_));
+ InitFunctionTemplates(isolate_data_.get());
+}
+
+} // namespace gin
diff --git a/chromium/gin/modules/console.cc b/chromium/gin/modules/console.cc
new file mode 100644
index 00000000000..14849944bfa
--- /dev/null
+++ b/chromium/gin/modules/console.cc
@@ -0,0 +1,49 @@
+// 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/modules/console.h"
+
+#include <iostream>
+
+#include "base/strings/string_util.h"
+#include "gin/arguments.h"
+#include "gin/converter.h"
+#include "gin/per_isolate_data.h"
+#include "gin/public/wrapper_info.h"
+
+using v8::ObjectTemplate;
+
+namespace gin {
+
+namespace {
+
+void Log(const v8::FunctionCallbackInfo<v8::Value>& info) {
+ Arguments args(info);
+
+ std::vector<std::string> messages;
+ if (!args.GetRemaining(&messages))
+ return args.ThrowTypeError("Expected strings.");
+
+ std::cout << JoinString(messages, ' ') << std::endl;
+}
+
+WrapperInfo g_wrapper_info = { kEmbedderNativeGin };
+
+} // namespace
+
+const char Console::kModuleName[] = "console";
+
+v8::Local<ObjectTemplate> Console::GetTemplate(v8::Isolate* isolate) {
+ PerIsolateData* data = PerIsolateData::From(isolate);
+ v8::Local<ObjectTemplate> templ = data->GetObjectTemplate(&g_wrapper_info);
+ if (templ.IsEmpty()) {
+ templ = ObjectTemplate::New();
+ templ->Set(StringToSymbol(isolate, "log"),
+ v8::FunctionTemplate::New(isolate, Log));
+ data->SetObjectTemplate(&g_wrapper_info, templ);
+ }
+ return templ;
+}
+
+} // namespace gin
diff --git a/chromium/gin/modules/console.h b/chromium/gin/modules/console.h
new file mode 100644
index 00000000000..8753961dd2b
--- /dev/null
+++ b/chromium/gin/modules/console.h
@@ -0,0 +1,23 @@
+// 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_MODULES_CONSOLE_H_
+#define GIN_MODULES_CONSOLE_H_
+
+#include "gin/gin_export.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+// The Console module provides a basic API for printing to stdout. Over time,
+// we'd like to evolve the API to match window.console in browsers.
+class GIN_EXPORT Console {
+ public:
+ static const char kModuleName[];
+ static v8::Local<v8::ObjectTemplate> GetTemplate(v8::Isolate* isolate);
+};
+
+} // namespace gin
+
+#endif // GIN_MODULES_CONSOLE_H_
diff --git a/chromium/gin/modules/file_module_provider.cc b/chromium/gin/modules/file_module_provider.cc
new file mode 100644
index 00000000000..990dcd000c0
--- /dev/null
+++ b/chromium/gin/modules/file_module_provider.cc
@@ -0,0 +1,72 @@
+// 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/modules/file_module_provider.h"
+
+#include "base/bind.h"
+#include "base/file_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/strings/string_split.h"
+#include "gin/converter.h"
+
+namespace gin {
+
+namespace {
+
+void AttempToLoadModule(const base::WeakPtr<Runner>& runner,
+ const std::vector<base::FilePath>& search_paths,
+ const std::string& id) {
+ if (!runner)
+ return;
+
+ std::vector<std::string> components;
+ base::SplitString(id, '/', &components);
+
+ base::FilePath path;
+ for (size_t i = 0; i < components.size(); ++i) {
+ // TODO(abarth): Technically the path components can be UTF-8. We don't
+ // handle that case correctly yet.
+ path = path.AppendASCII(components[i]);
+ }
+ path = path.AddExtension(FILE_PATH_LITERAL("js"));
+
+ for (size_t i = 0; i < search_paths.size(); ++i) {
+ std::string source;
+ if (!ReadFileToString(search_paths[i].Append(path), &source))
+ continue;
+
+ Runner::Scope scope(runner.get());
+ v8::Handle<v8::Script> script = v8::Script::New(
+ StringToV8(runner->isolate(), source),
+ StringToV8(runner->isolate(), id));
+ runner->Run(script);
+ return;
+ }
+}
+
+} // namespace
+
+FileModuleProvider::FileModuleProvider(
+ const std::vector<base::FilePath>& search_paths)
+ : search_paths_(search_paths) {
+}
+
+FileModuleProvider::~FileModuleProvider() {
+}
+
+void FileModuleProvider::AttempToLoadModules(
+ Runner* runner, const std::set<std::string>& ids) {
+ std::set<std::string> modules = ids;
+ for (std::set<std::string>::const_iterator it = modules.begin();
+ it != modules.end(); ++it) {
+ const std::string& id = *it;
+ if (attempted_ids_.count(id))
+ continue;
+ attempted_ids_.insert(id);
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ AttempToLoadModule, runner->GetWeakPtr(), search_paths_, id));
+ }
+}
+
+} // namespace gin
diff --git a/chromium/gin/modules/file_module_provider.h b/chromium/gin/modules/file_module_provider.h
new file mode 100644
index 00000000000..dd75a0feaf1
--- /dev/null
+++ b/chromium/gin/modules/file_module_provider.h
@@ -0,0 +1,44 @@
+// 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_MODULES_FILE_MODULE_PROVIDER_H_
+#define GIN_MODULES_FILE_MODULE_PROVIDER_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/files/file_path.h"
+#include "gin/gin_export.h"
+#include "gin/runner.h"
+
+namespace gin {
+
+// FileModuleProvider knows how to load AMD modules off disk. It searches for
+// modules in the directories indiciated by |search_paths|. Although we still
+// read from the file system on the main thread, we'll eventually want to move
+// the reads to a background thread.
+class GIN_EXPORT FileModuleProvider {
+ public:
+ explicit FileModuleProvider(
+ const std::vector<base::FilePath>& search_paths);
+ ~FileModuleProvider();
+
+ // Searches for modules with |ids| in the file system. If found, the modules
+ // will be executed asynchronously by |runner|.
+ void AttempToLoadModules(Runner* runner, const std::set<std::string>& ids);
+
+ private:
+ std::vector<base::FilePath> search_paths_;
+
+ // We'll only search for a given module once. We remember the set of modules
+ // we've already looked for in |attempted_ids_|.
+ std::set<std::string> attempted_ids_;
+
+ DISALLOW_COPY_AND_ASSIGN(FileModuleProvider);
+};
+
+} // namespace gin
+
+#endif // GIN_MODULES_FILE_MODULE_PROVIDER_H_
diff --git a/chromium/gin/modules/module_registry.cc b/chromium/gin/modules/module_registry.cc
new file mode 100644
index 00000000000..9dd3dbe9810
--- /dev/null
+++ b/chromium/gin/modules/module_registry.cc
@@ -0,0 +1,248 @@
+// 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/modules/module_registry.h"
+
+#include <string>
+#include <vector>
+
+#include "base/logging.h"
+#include "gin/arguments.h"
+#include "gin/converter.h"
+#include "gin/per_isolate_data.h"
+#include "gin/public/wrapper_info.h"
+#include "gin/runner.h"
+
+using v8::Context;
+using v8::External;
+using v8::Function;
+using v8::FunctionTemplate;
+using v8::Isolate;
+using v8::Local;
+using v8::Object;
+using v8::ObjectTemplate;
+using v8::Persistent;
+using v8::StackTrace;
+using v8::String;
+using v8::Value;
+
+namespace gin {
+
+struct PendingModule {
+ PendingModule();
+ ~PendingModule();
+
+ std::string id;
+ std::vector<std::string> dependencies;
+ Persistent<Value> factory;
+};
+
+PendingModule::PendingModule() {
+}
+
+PendingModule::~PendingModule() {
+ factory.Reset();
+}
+
+namespace {
+
+void Define(const v8::FunctionCallbackInfo<Value>& info) {
+ Arguments args(info);
+
+ if (!info.Length())
+ return args.ThrowTypeError("At least one argument is required.");
+
+ std::string id;
+ std::vector<std::string> dependencies;
+ v8::Handle<Value> factory;
+
+ if (args.PeekNext()->IsString())
+ args.GetNext(&id);
+ if (args.PeekNext()->IsArray())
+ args.GetNext(&dependencies);
+ if (!args.GetNext(&factory))
+ return args.ThrowError();
+
+ scoped_ptr<PendingModule> pending(new PendingModule);
+ pending->id = id;
+ pending->dependencies = dependencies;
+ pending->factory.Reset(args.isolate(), factory);
+
+ ModuleRegistry* registry =
+ ModuleRegistry::From(args.isolate()->GetCurrentContext());
+ registry->AddPendingModule(args.isolate(), pending.Pass());
+}
+
+WrapperInfo g_wrapper_info = { kEmbedderNativeGin };
+
+Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) {
+ PerIsolateData* data = PerIsolateData::From(isolate);
+ Local<FunctionTemplate> templ = data->GetFunctionTemplate(
+ &g_wrapper_info);
+ if (templ.IsEmpty()) {
+ templ = FunctionTemplate::New(isolate, Define);
+ data->SetFunctionTemplate(&g_wrapper_info, templ);
+ }
+ return templ;
+}
+
+v8::Handle<String> GetHiddenValueKey(Isolate* isolate) {
+ return StringToSymbol(isolate, "::gin::ModuleRegistry");
+}
+
+} // namespace
+
+ModuleRegistry::ModuleRegistry(Isolate* isolate)
+ : modules_(isolate, Object::New()) {
+}
+
+ModuleRegistry::~ModuleRegistry() {
+ modules_.Reset();
+}
+
+void ModuleRegistry::RegisterGlobals(Isolate* isolate,
+ v8::Handle<ObjectTemplate> templ) {
+ templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
+}
+
+ModuleRegistry* ModuleRegistry::From(v8::Handle<Context> context) {
+ Isolate* isolate = context->GetIsolate();
+ v8::Handle<String> key = GetHiddenValueKey(isolate);
+ v8::Handle<Value> value = context->Global()->GetHiddenValue(key);
+ v8::Handle<External> external;
+ if (value.IsEmpty() || !ConvertFromV8(isolate, value, &external)) {
+ PerContextData* data = PerContextData::From(context);
+ if (!data)
+ return NULL;
+ ModuleRegistry* registry = new ModuleRegistry(isolate);
+ context->Global()->SetHiddenValue(key, External::New(isolate, registry));
+ data->AddSupplement(scoped_ptr<ContextSupplement>(registry));
+ return registry;
+ }
+ return static_cast<ModuleRegistry*>(external->Value());
+}
+
+void ModuleRegistry::AddBuiltinModule(Isolate* isolate,
+ const std::string& id,
+ v8::Handle<ObjectTemplate> templ) {
+ DCHECK(!id.empty());
+ RegisterModule(isolate, id, templ->NewInstance());
+}
+
+void ModuleRegistry::AddPendingModule(Isolate* isolate,
+ scoped_ptr<PendingModule> pending) {
+ AttemptToLoad(isolate, pending.Pass());
+}
+
+void ModuleRegistry::LoadModule(Isolate* isolate,
+ const std::string& id,
+ LoadModuleCallback callback) {
+ if (available_modules_.find(id) != available_modules_.end()) {
+ // Should we call the callback asynchronously?
+ callback.Run(GetModule(isolate, id));
+ return;
+ }
+ // Should we support multiple callers waiting on the same module?
+ DCHECK(waiting_callbacks_.find(id) == waiting_callbacks_.end());
+ waiting_callbacks_[id] = callback;
+ unsatisfied_dependencies_.insert(id);
+}
+
+void ModuleRegistry::RegisterModule(Isolate* isolate,
+ const std::string& id,
+ v8::Handle<Value> module) {
+ if (id.empty() || module.IsEmpty())
+ return;
+
+ unsatisfied_dependencies_.erase(id);
+ available_modules_.insert(id);
+ v8::Handle<Object> modules = Local<Object>::New(isolate, modules_);
+ modules->Set(StringToSymbol(isolate, id), module);
+
+ LoadModuleCallbackMap::iterator it = waiting_callbacks_.find(id);
+ if (it == waiting_callbacks_.end())
+ return;
+ LoadModuleCallback callback = it->second;
+ waiting_callbacks_.erase(it);
+ // Should we call the callback asynchronously?
+ callback.Run(module);
+}
+
+void ModuleRegistry::Detach(v8::Handle<Context> context) {
+ context->Global()->SetHiddenValue(GetHiddenValueKey(context->GetIsolate()),
+ v8::Handle<Value>());
+}
+
+bool ModuleRegistry::CheckDependencies(PendingModule* pending) {
+ size_t num_missing_dependencies = 0;
+ size_t len = pending->dependencies.size();
+ for (size_t i = 0; i < len; ++i) {
+ const std::string& dependency = pending->dependencies[i];
+ if (available_modules_.count(dependency))
+ continue;
+ unsatisfied_dependencies_.insert(dependency);
+ num_missing_dependencies++;
+ }
+ return num_missing_dependencies == 0;
+}
+
+void ModuleRegistry::Load(Isolate* isolate, scoped_ptr<PendingModule> pending) {
+ if (!pending->id.empty() && available_modules_.count(pending->id))
+ return; // We've already loaded this module.
+
+ uint32_t argc = static_cast<uint32_t>(pending->dependencies.size());
+ std::vector<v8::Handle<Value> > argv(argc);
+ for (uint32_t i = 0; i < argc; ++i)
+ argv[i] = GetModule(isolate, pending->dependencies[i]);
+
+ v8::Handle<Value> module = Local<Value>::New(isolate, pending->factory);
+
+ v8::Handle<Function> factory;
+ if (ConvertFromV8(isolate, module, &factory)) {
+ PerContextData* data = PerContextData::From(isolate->GetCurrentContext());
+ Runner* runner = data->runner();
+ module = runner->Call(factory, runner->global(), argc,
+ argv.empty() ? NULL : &argv.front());
+ if (pending->id.empty())
+ ConvertFromV8(isolate, factory->GetScriptOrigin().ResourceName(),
+ &pending->id);
+ }
+
+ RegisterModule(isolate, pending->id, module);
+}
+
+bool ModuleRegistry::AttemptToLoad(Isolate* isolate,
+ scoped_ptr<PendingModule> pending) {
+ if (!CheckDependencies(pending.get())) {
+ pending_modules_.push_back(pending.release());
+ return false;
+ }
+ Load(isolate, pending.Pass());
+ return true;
+}
+
+v8::Handle<v8::Value> ModuleRegistry::GetModule(v8::Isolate* isolate,
+ const std::string& id) {
+ v8::Handle<Object> modules = Local<Object>::New(isolate, modules_);
+ v8::Handle<String> key = StringToSymbol(isolate, id);
+ DCHECK(modules->HasOwnProperty(key));
+ return modules->Get(key);
+}
+
+void ModuleRegistry::AttemptToLoadMoreModules(Isolate* isolate) {
+ bool keep_trying = true;
+ while (keep_trying) {
+ keep_trying = false;
+ PendingModuleVector pending_modules;
+ pending_modules.swap(pending_modules_);
+ for (size_t i = 0; i < pending_modules.size(); ++i) {
+ scoped_ptr<PendingModule> pending(pending_modules[i]);
+ pending_modules[i] = NULL;
+ if (AttemptToLoad(isolate, pending.Pass()))
+ keep_trying = true;
+ }
+ }
+}
+
+} // namespace gin
diff --git a/chromium/gin/modules/module_registry.h b/chromium/gin/modules/module_registry.h
new file mode 100644
index 00000000000..27606cd9a54
--- /dev/null
+++ b/chromium/gin/modules/module_registry.h
@@ -0,0 +1,101 @@
+// 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_MODULES_MODULE_REGISTRY_H_
+#define GIN_MODULES_MODULE_REGISTRY_H_
+
+#include <list>
+#include <map>
+#include <set>
+#include <string>
+
+#include "base/callback.h"
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_ptr.h"
+#include "gin/gin_export.h"
+#include "gin/per_context_data.h"
+
+namespace gin {
+
+struct PendingModule;
+
+// This class implements the Asynchronous Module Definition (AMD) API.
+// https://github.com/amdjs/amdjs-api/wiki/AMD
+//
+// Our implementation isn't complete yet. Missing features:
+// 1) Built-in support for require, exports, and module.
+// 2) Path resoltuion in module names.
+//
+// For these reasons, we don't have an "amd" property on the "define"
+// function. The spec says we should only add that property once our
+// implementation complies with the specification.
+//
+class GIN_EXPORT ModuleRegistry : public ContextSupplement {
+ public:
+ typedef base::Callback<void (v8::Handle<v8::Value>)> LoadModuleCallback;
+
+ virtual ~ModuleRegistry();
+
+ static ModuleRegistry* From(v8::Handle<v8::Context> context);
+
+ static void RegisterGlobals(v8::Isolate* isolate,
+ v8::Handle<v8::ObjectTemplate> templ);
+
+ // The caller must have already entered our context.
+ void AddBuiltinModule(v8::Isolate* isolate,
+ const std::string& id,
+ v8::Handle<v8::ObjectTemplate> templ);
+
+ // The caller must have already entered our context.
+ void AddPendingModule(v8::Isolate* isolate,
+ scoped_ptr<PendingModule> pending);
+
+ void LoadModule(v8::Isolate* isolate,
+ const std::string& id,
+ LoadModuleCallback callback);
+
+ // The caller must have already entered our context.
+ void AttemptToLoadMoreModules(v8::Isolate* isolate);
+
+ const std::set<std::string>& available_modules() const {
+ return available_modules_;
+ }
+
+ const std::set<std::string>& unsatisfied_dependencies() const {
+ return unsatisfied_dependencies_;
+ }
+
+ private:
+ typedef ScopedVector<PendingModule> PendingModuleVector;
+ typedef std::map<std::string, LoadModuleCallback> LoadModuleCallbackMap;
+
+ explicit ModuleRegistry(v8::Isolate* isolate);
+
+ // From ContextSupplement:
+ virtual void Detach(v8::Handle<v8::Context> context) OVERRIDE;
+
+ void Load(v8::Isolate* isolate, scoped_ptr<PendingModule> pending);
+ void RegisterModule(v8::Isolate* isolate,
+ const std::string& id,
+ v8::Handle<v8::Value> module);
+
+ bool CheckDependencies(PendingModule* pending);
+ bool AttemptToLoad(v8::Isolate* isolate, scoped_ptr<PendingModule> pending);
+
+ v8::Handle<v8::Value> GetModule(v8::Isolate* isolate, const std::string& id);
+
+ std::set<std::string> available_modules_;
+ std::set<std::string> unsatisfied_dependencies_;
+
+ LoadModuleCallbackMap waiting_callbacks_;
+
+ PendingModuleVector pending_modules_;
+ v8::Persistent<v8::Object> modules_;
+
+ DISALLOW_COPY_AND_ASSIGN(ModuleRegistry);
+};
+
+} // namespace gin
+
+#endif // GIN_MODULES_MODULE_REGISTRY_H_
diff --git a/chromium/gin/modules/module_registry_unittests.js b/chromium/gin/modules/module_registry_unittests.js
new file mode 100644
index 00000000000..ca7014899b3
--- /dev/null
+++ b/chromium/gin/modules/module_registry_unittests.js
@@ -0,0 +1,30 @@
+// 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.
+
+define("module0", function() {
+ return {
+ "foo": "bar",
+ }
+});
+
+define("module2", [
+ "gtest",
+ "module0",
+ "module1"
+ ], function(gtest, module0, module1) {
+ gtest.expectEqual(module0.foo, "bar",
+ "module0.foo is " + module0.foo);
+ gtest.expectFalse(module0.bar,
+ "module0.bar is " + module0.bar);
+ gtest.expectEqual(module1.baz, "qux",
+ "module1.baz is " + module1.baz);
+ gtest.expectFalse(module1.qux,
+ "module1.qux is " + module1.qux);
+
+ this.result = "PASS";
+});
+
+define("module1", {
+ "baz": "qux",
+});
diff --git a/chromium/gin/modules/module_runner_delegate.cc b/chromium/gin/modules/module_runner_delegate.cc
new file mode 100644
index 00000000000..9bf2863c203
--- /dev/null
+++ b/chromium/gin/modules/module_runner_delegate.cc
@@ -0,0 +1,55 @@
+// 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/modules/module_runner_delegate.h"
+
+#include "gin/modules/module_registry.h"
+
+namespace gin {
+
+ModuleRunnerDelegate::ModuleRunnerDelegate(
+ const std::vector<base::FilePath>& search_paths)
+ : module_provider_(search_paths) {
+}
+
+ModuleRunnerDelegate::~ModuleRunnerDelegate() {
+}
+
+void ModuleRunnerDelegate::AddBuiltinModule(const std::string& id,
+ ModuleTemplateGetter templ) {
+ builtin_modules_[id] = templ;
+}
+
+void ModuleRunnerDelegate::AttemptToLoadMoreModules(Runner* runner) {
+ ModuleRegistry* registry = ModuleRegistry::From(runner->context());
+ registry->AttemptToLoadMoreModules(runner->isolate());
+ module_provider_.AttempToLoadModules(
+ runner, registry->unsatisfied_dependencies());
+}
+
+v8::Handle<v8::ObjectTemplate> ModuleRunnerDelegate::GetGlobalTemplate(
+ Runner* runner) {
+ v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New();
+ ModuleRegistry::RegisterGlobals(runner->isolate(), templ);
+ return templ;
+}
+
+void ModuleRunnerDelegate::DidCreateContext(Runner* runner) {
+ RunnerDelegate::DidCreateContext(runner);
+
+ v8::Handle<v8::Context> context = runner->context();
+ ModuleRegistry* registry = ModuleRegistry::From(context);
+
+ for (BuiltinModuleMap::const_iterator it = builtin_modules_.begin();
+ it != builtin_modules_.end(); ++it) {
+ registry->AddBuiltinModule(runner->isolate(), it->first,
+ it->second(runner->isolate()));
+ }
+}
+
+void ModuleRunnerDelegate::DidRunScript(Runner* runner) {
+ AttemptToLoadMoreModules(runner);
+}
+
+} // namespace gin
diff --git a/chromium/gin/modules/module_runner_delegate.h b/chromium/gin/modules/module_runner_delegate.h
new file mode 100644
index 00000000000..06077f479bb
--- /dev/null
+++ b/chromium/gin/modules/module_runner_delegate.h
@@ -0,0 +1,56 @@
+// 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_MODULES_MODULE_RUNNER_DELEGATE_H_
+#define GIN_MODULES_MODULE_RUNNER_DELEGATE_H_
+
+#include <map>
+
+#include "base/compiler_specific.h"
+#include "gin/gin_export.h"
+#include "gin/modules/file_module_provider.h"
+#include "gin/runner.h"
+
+namespace gin {
+
+typedef v8::Local<v8::ObjectTemplate> (*ModuleTemplateGetter)(
+ v8::Isolate* isolate);
+
+// Emebedders that use AMD modules will probably want to use a RunnerDelegate
+// that inherits from ModuleRunnerDelegate. ModuleRunnerDelegate lets embedders
+// register built-in modules and routes module requests to FileModuleProvider.
+class GIN_EXPORT ModuleRunnerDelegate : public RunnerDelegate {
+ public:
+ explicit ModuleRunnerDelegate(
+ const std::vector<base::FilePath>& search_paths);
+ virtual ~ModuleRunnerDelegate();
+
+ // Lets you register a built-in module. Built-in modules are instantiated by
+ // creating a new instance of a v8::ObjectTemplate rather than by executing
+ // code. This function takes a ModuleTemplateGetter rather than a
+ // v8::ObjectTemplate directly so that embedders can create object templates
+ // lazily.
+ void AddBuiltinModule(const std::string& id, ModuleTemplateGetter templ);
+
+ protected:
+ void AttemptToLoadMoreModules(Runner* runner);
+
+ private:
+ typedef std::map<std::string, ModuleTemplateGetter> BuiltinModuleMap;
+
+ // From RunnerDelegate:
+ virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(
+ Runner* runner) OVERRIDE;
+ virtual void DidCreateContext(Runner* runner) OVERRIDE;
+ virtual void DidRunScript(Runner* runner) OVERRIDE;
+
+ BuiltinModuleMap builtin_modules_;
+ FileModuleProvider module_provider_;
+
+ DISALLOW_COPY_AND_ASSIGN(ModuleRunnerDelegate);
+};
+
+} // namespace gin
+
+#endif // GIN_MODULES_MODULE_RUNNER_DELEGATE_H_
diff --git a/chromium/gin/object_template_builder.cc b/chromium/gin/object_template_builder.cc
new file mode 100644
index 00000000000..6dc6d2fe849
--- /dev/null
+++ b/chromium/gin/object_template_builder.cc
@@ -0,0 +1,36 @@
+// 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/object_template_builder.h"
+
+namespace gin {
+
+ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate)
+ : isolate_(isolate), template_(v8::ObjectTemplate::New(isolate)) {
+}
+
+ObjectTemplateBuilder::~ObjectTemplateBuilder() {
+}
+
+ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl(
+ const base::StringPiece& name, v8::Handle<v8::Data> val) {
+ template_->Set(StringToSymbol(isolate_, name), val);
+ return *this;
+}
+
+ObjectTemplateBuilder& ObjectTemplateBuilder::SetPropertyImpl(
+ const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter,
+ v8::Handle<v8::FunctionTemplate> setter) {
+ template_->SetAccessorProperty(StringToSymbol(isolate_, name), getter,
+ setter);
+ return *this;
+}
+
+v8::Local<v8::ObjectTemplate> ObjectTemplateBuilder::Build() {
+ v8::Local<v8::ObjectTemplate> result = template_;
+ template_.Clear();
+ return result;
+}
+
+} // namespace gin
diff --git a/chromium/gin/object_template_builder.h b/chromium/gin/object_template_builder.h
new file mode 100644
index 00000000000..6367b71245c
--- /dev/null
+++ b/chromium/gin/object_template_builder.h
@@ -0,0 +1,124 @@
+// 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_OBJECT_TEMPLATE_BUILDER_H_
+#define GIN_OBJECT_TEMPLATE_BUILDER_H_
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/strings/string_piece.h"
+#include "base/template_util.h"
+#include "gin/converter.h"
+#include "gin/function_template.h"
+#include "gin/gin_export.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+namespace {
+
+// Base template - used only for non-member function pointers. Other types
+// either go to one of the below specializations, or go here and fail to compile
+// because of base::Bind().
+template<typename T, typename Enable = void>
+struct CallbackTraits {
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
+ T callback) {
+ return CreateFunctionTemplate(isolate, base::Bind(callback));
+ }
+};
+
+// Specialization for base::Callback.
+template<typename T>
+struct CallbackTraits<base::Callback<T> > {
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate(
+ v8::Isolate* isolate, const base::Callback<T>& callback) {
+ return CreateFunctionTemplate(isolate, callback);
+ }
+};
+
+// Specialization for member function pointers. We need to handle this case
+// specially because the first parameter for callbacks to MFP should typically
+// come from the the JavaScript "this" object the function was called on, not
+// from the first normal parameter.
+template<typename T>
+struct CallbackTraits<T, typename base::enable_if<
+ base::is_member_function_pointer<T>::value>::type> {
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate(v8::Isolate* isolate,
+ T callback) {
+ return CreateFunctionTemplate(isolate, base::Bind(callback),
+ HolderIsFirstArgument);
+ }
+};
+
+// This specialization allows people to construct function templates directly if
+// they need to do fancier stuff.
+template<>
+struct GIN_EXPORT CallbackTraits<v8::Handle<v8::FunctionTemplate> > {
+ static v8::Handle<v8::FunctionTemplate> CreateTemplate(
+ v8::Handle<v8::FunctionTemplate> templ) {
+ return templ;
+ }
+};
+
+} // namespace
+
+
+// ObjectTemplateBuilder provides a handy interface to creating
+// v8::ObjectTemplate instances with various sorts of properties.
+class GIN_EXPORT ObjectTemplateBuilder {
+ public:
+ explicit ObjectTemplateBuilder(v8::Isolate* isolate);
+ ~ObjectTemplateBuilder();
+
+ // It's against Google C++ style to return a non-const ref, but we take some
+ // poetic license here in order that all calls to Set() can be via the '.'
+ // operator and line up nicely.
+ template<typename T>
+ ObjectTemplateBuilder& SetValue(const base::StringPiece& name, T val) {
+ return SetImpl(name, ConvertToV8(isolate_, val));
+ }
+
+ // In the following methods, T and U can be function pointer, member function
+ // pointer, base::Callback, or v8::FunctionTemplate. Most clients will want to
+ // use one of the first two options. Also see gin::CreateFunctionTemplate()
+ // for creating raw function templates.
+ template<typename T>
+ ObjectTemplateBuilder& SetMethod(const base::StringPiece& name,
+ const T& callback) {
+ return SetImpl(name, CallbackTraits<T>::CreateTemplate(isolate_, callback));
+ }
+ template<typename T>
+ ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
+ const T& getter) {
+ return SetPropertyImpl(name,
+ CallbackTraits<T>::CreateTemplate(isolate_, getter),
+ v8::Local<v8::FunctionTemplate>());
+ }
+ template<typename T, typename U>
+ ObjectTemplateBuilder& SetProperty(const base::StringPiece& name,
+ const T& getter, const U& setter) {
+ return SetPropertyImpl(name,
+ CallbackTraits<T>::CreateTemplate(isolate_, getter),
+ CallbackTraits<U>::CreateTemplate(isolate_, setter));
+ }
+
+ v8::Local<v8::ObjectTemplate> Build();
+
+ private:
+ ObjectTemplateBuilder& SetImpl(const base::StringPiece& name,
+ v8::Handle<v8::Data> val);
+ ObjectTemplateBuilder& SetPropertyImpl(
+ const base::StringPiece& name, v8::Handle<v8::FunctionTemplate> getter,
+ v8::Handle<v8::FunctionTemplate> setter);
+
+ v8::Isolate* isolate_;
+
+ // ObjectTemplateBuilder should only be used on the stack.
+ v8::Local<v8::ObjectTemplate> template_;
+};
+
+} // namespace gin
+
+#endif // GIN_OBJECT_TEMPLATE_BUILDER_H_
diff --git a/chromium/gin/per_context_data.cc b/chromium/gin/per_context_data.cc
new file mode 100644
index 00000000000..5183d00102b
--- /dev/null
+++ b/chromium/gin/per_context_data.cc
@@ -0,0 +1,52 @@
+// 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_context_data.h"
+
+#include "base/logging.h"
+#include "gin/public/context_holder.h"
+#include "gin/public/wrapper_info.h"
+
+namespace gin {
+
+ContextSupplement::ContextSupplement() {
+}
+
+ContextSupplement::~ContextSupplement() {
+}
+
+PerContextData::PerContextData(v8::Handle<v8::Context> context)
+ : runner_(NULL) {
+ context->SetAlignedPointerInEmbedderData(
+ kPerContextDataStartIndex + kEmbedderNativeGin, this);
+}
+
+PerContextData::~PerContextData() {
+ DCHECK(supplements_.empty());
+}
+
+void PerContextData::Detach(v8::Handle<v8::Context> context) {
+ DCHECK(From(context) == this);
+ context->SetAlignedPointerInEmbedderData(
+ kPerContextDataStartIndex + kEmbedderNativeGin, NULL);
+
+ SuplementVector supplements;
+ supplements.swap(supplements_);
+
+ for (SuplementVector::iterator it = supplements.begin();
+ it != supplements.end(); ++it) {
+ (*it)->Detach(context);
+ }
+}
+
+PerContextData* PerContextData::From(v8::Handle<v8::Context> context) {
+ return static_cast<PerContextData*>(
+ context->GetAlignedPointerFromEmbedderData(kEncodedValueIndex));
+}
+
+void PerContextData::AddSupplement(scoped_ptr<ContextSupplement> supplement) {
+ supplements_.push_back(supplement.release());
+}
+
+} // namespace gin
diff --git a/chromium/gin/per_context_data.h b/chromium/gin/per_context_data.h
new file mode 100644
index 00000000000..3ad68d2d37c
--- /dev/null
+++ b/chromium/gin/per_context_data.h
@@ -0,0 +1,62 @@
+// 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_CONTEXT_DATA_H_
+#define GIN_PER_CONTEXT_DATA_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "gin/gin_export.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+class Runner;
+
+// Embedders can store additional per-context data by subclassing
+// ContextSupplement.
+class GIN_EXPORT ContextSupplement {
+ public:
+ ContextSupplement();
+ virtual ~ContextSupplement();
+
+ // Detach will be called before ContextHolder disposes the v8::Context.
+ // Embedders should not interact with |context| after Detach has been called.
+ virtual void Detach(v8::Handle<v8::Context> context) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ContextSupplement);
+};
+
+// There is one instance of PerContextData per v8::Context managed by Gin. This
+// class stores all the Gin-related data that varies per context.
+class GIN_EXPORT PerContextData {
+ public:
+ explicit PerContextData(v8::Handle<v8::Context> context);
+ ~PerContextData();
+
+ // Can return NULL after the ContextHolder has detached from context.
+ static PerContextData* From(v8::Handle<v8::Context>);
+ void Detach(v8::Handle<v8::Context> context);
+
+ // The Runner associated with this context. To execute script in this context,
+ // please use the appropriate API on Runner.
+ Runner* runner() const { return runner_; }
+ void set_runner(Runner* runner) { runner_ = runner; }
+
+ void AddSupplement(scoped_ptr<ContextSupplement> supplement);
+
+ private:
+ typedef ScopedVector<ContextSupplement> SuplementVector;
+
+ Runner* runner_;
+ SuplementVector supplements_;
+
+ DISALLOW_COPY_AND_ASSIGN(PerContextData);
+};
+
+} // namespace gin
+
+#endif // GIN_PER_CONTEXT_DATA_H_
diff --git a/chromium/gin/per_isolate_data.cc b/chromium/gin/per_isolate_data.cc
new file mode 100644
index 00000000000..6c2397ba50b
--- /dev/null
+++ b/chromium/gin/per_isolate_data.cc
@@ -0,0 +1,56 @@
+// 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"
+#include "gin/public/gin_embedders.h"
+
+using v8::Eternal;
+using v8::Isolate;
+using v8::Local;
+using v8::Object;
+using v8::FunctionTemplate;
+using v8::ObjectTemplate;
+
+namespace gin {
+
+PerIsolateData::PerIsolateData(Isolate* isolate)
+ : isolate_(isolate) {
+ isolate_->SetData(kEmbedderNativeGin, this);
+}
+
+PerIsolateData::~PerIsolateData() {
+ isolate_->SetData(kEmbedderNativeGin, NULL);
+}
+
+PerIsolateData* PerIsolateData::From(Isolate* isolate) {
+ return static_cast<PerIsolateData*>(isolate->GetData(kEmbedderNativeGin));
+}
+
+void PerIsolateData::SetObjectTemplate(WrapperInfo* info,
+ Local<ObjectTemplate> templ) {
+ object_templates_[info] = Eternal<ObjectTemplate>(isolate_, templ);
+}
+
+void PerIsolateData::SetFunctionTemplate(WrapperInfo* info,
+ Local<FunctionTemplate> templ) {
+ function_templates_[info] = Eternal<FunctionTemplate>(isolate_, templ);
+}
+
+v8::Local<v8::ObjectTemplate> PerIsolateData::GetObjectTemplate(
+ WrapperInfo* info) {
+ ObjectTemplateMap::iterator it = object_templates_.find(info);
+ if (it == object_templates_.end())
+ return v8::Local<v8::ObjectTemplate>();
+ return it->second.Get(isolate_);
+}
+
+v8::Local<v8::FunctionTemplate> PerIsolateData::GetFunctionTemplate(
+ WrapperInfo* info) {
+ FunctionTemplateMap::iterator it = function_templates_.find(info);
+ if (it == function_templates_.end())
+ return v8::Local<v8::FunctionTemplate>();
+ return it->second.Get(isolate_);
+}
+
+} // namespace gin
diff --git a/chromium/gin/per_isolate_data.h b/chromium/gin/per_isolate_data.h
new file mode 100644
index 00000000000..ed935454749
--- /dev/null
+++ b/chromium/gin/per_isolate_data.h
@@ -0,0 +1,60 @@
+// 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 <map>
+
+#include "base/basictypes.h"
+#include "gin/gin_export.h"
+#include "gin/public/wrapper_info.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+// There is one instance of PerIsolateData per v8::Isolate managed by Gin. This
+// class stores all the Gin-related data that varies per isolate.
+class GIN_EXPORT PerIsolateData {
+ public:
+ explicit PerIsolateData(v8::Isolate* isolate);
+ ~PerIsolateData();
+
+ static PerIsolateData* From(v8::Isolate* isolate);
+
+ // Each isolate is associated with a collection of v8::ObjectTemplates and
+ // v8::FunctionTemplates. Typically these template objects are created
+ // lazily.
+ void SetObjectTemplate(WrapperInfo* info,
+ v8::Local<v8::ObjectTemplate> object_template);
+ void SetFunctionTemplate(WrapperInfo* info,
+ v8::Local<v8::FunctionTemplate> function_template);
+
+ // These are low-level functions for retrieving object or function templates
+ // stored in this object. Because these templates are often created lazily,
+ // most clients should call higher-level functions that know how to populate
+ // these templates if they haven't already been created.
+ v8::Local<v8::ObjectTemplate> GetObjectTemplate(WrapperInfo* info);
+ v8::Local<v8::FunctionTemplate> GetFunctionTemplate(WrapperInfo* info);
+
+ v8::Isolate* isolate() { return isolate_; }
+
+ private:
+ typedef std::map<
+ WrapperInfo*, v8::Eternal<v8::ObjectTemplate> > ObjectTemplateMap;
+ typedef std::map<
+ WrapperInfo*, v8::Eternal<v8::FunctionTemplate> > FunctionTemplateMap;
+
+ // PerIsolateData doesn't actually own |isolate_|. Instead, the isolate is
+ // owned by the IsolateHolder, which also owns the PerIsolateData.
+ v8::Isolate* isolate_;
+ ObjectTemplateMap object_templates_;
+ FunctionTemplateMap function_templates_;
+
+ DISALLOW_COPY_AND_ASSIGN(PerIsolateData);
+};
+
+} // namespace gin
+
+#endif // GIN_PER_ISOLATE_DATA_H_
diff --git a/chromium/gin/public/context_holder.h b/chromium/gin/public/context_holder.h
new file mode 100644
index 00000000000..09fe248a373
--- /dev/null
+++ b/chromium/gin/public/context_holder.h
@@ -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.
+
+#ifndef GIN_PUBLIC_CONTEXT_HOLDER_H_
+#define GIN_PUBLIC_CONTEXT_HOLDER_H_
+
+#include <list>
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "gin/gin_export.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+// Gin embedder that store embedder data in v8::Contexts must do so in a
+// single field with the index kPerContextDataStartIndex + GinEmbedder-enum.
+// The field at kDebugIdIndex is treated specially by V8 and is reserved for
+// a V8 debugger implementation (not used by gin).
+enum ContextEmbedderDataFields {
+ kDebugIdIndex = 0,
+ kPerContextDataStartIndex,
+};
+
+class PerContextData;
+
+// ContextHolder is a generic class for holding a v8::Context. Rather than
+// using ContextHolder directly, most code should use a subclass of
+// ContextHolder, such as Runner.
+class GIN_EXPORT ContextHolder {
+ public:
+ explicit ContextHolder(v8::Isolate* isolate);
+ ~ContextHolder();
+
+ v8::Isolate* isolate() const { return isolate_; }
+
+ v8::Handle<v8::Context> context() const {
+ return v8::Local<v8::Context>::New(isolate_, context_);
+ }
+
+ void SetContext(v8::Handle<v8::Context> context);
+
+ private:
+ v8::Isolate* isolate_;
+ v8::Persistent<v8::Context> context_;
+ scoped_ptr<PerContextData> data_;
+
+ DISALLOW_COPY_AND_ASSIGN(ContextHolder);
+};
+
+} // namespace gin
+
+#endif // GIN_PUBLIC_CONTEXT_HOLDER_H_
diff --git a/chromium/gin/public/gin_embedders.h b/chromium/gin/public/gin_embedders.h
new file mode 100644
index 00000000000..bffe6e0856e
--- /dev/null
+++ b/chromium/gin/public/gin_embedders.h
@@ -0,0 +1,21 @@
+// 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_PUBLIC_GIN_EMBEDDERS_H_
+#define GIN_PUBLIC_GIN_EMBEDDERS_H_
+
+namespace gin {
+
+// The GinEmbedder is used to identify the owner of embedder data stored on
+// v8 objects, and is used as in index into the embedder data slots of a
+// v8::Isolate.
+
+enum GinEmbedder {
+ kEmbedderNativeGin,
+ kEmbedderBlink,
+};
+
+} // namespace gin
+
+#endif // GIN_PUBLIC_GIN_EMBEDDERS_H_
diff --git a/chromium/gin/public/isolate_holder.h b/chromium/gin/public/isolate_holder.h
new file mode 100644
index 00000000000..d68e4d5a58b
--- /dev/null
+++ b/chromium/gin/public/isolate_holder.h
@@ -0,0 +1,51 @@
+// 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_PUBLIC_ISOLATE_HOLDER_H_
+#define GIN_PUBLIC_ISOLATE_HOLDER_H_
+
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "gin/gin_export.h"
+
+namespace v8 {
+class Isolate;
+}
+
+namespace gin {
+
+class PerIsolateData;
+
+// To embed Gin, first create an instance of IsolateHolder to hold the
+// v8::Isolate in which you will execute JavaScript. You might wish to subclass
+// IsolateHolder if you want to tie more state to the lifetime of the
+//
+// You can use gin in two modes: either gin manages V8, or the gin-embedder
+// manages gin. If gin manages V8, use the IsolateHolder constructor without
+// parameters, otherwise, the gin-embedder needs to create v8::Isolates and
+// pass them to IsolateHolder.
+//
+// It is not possible to mix the two.
+class GIN_EXPORT IsolateHolder {
+ public:
+ IsolateHolder();
+ explicit IsolateHolder(v8::Isolate* isolate);
+
+ ~IsolateHolder();
+
+ v8::Isolate* isolate() { return isolate_; }
+
+ private:
+ void Init();
+
+ bool isolate_owner_;
+ v8::Isolate* isolate_;
+ scoped_ptr<PerIsolateData> isolate_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(IsolateHolder);
+};
+
+} // namespace gin
+
+#endif // GIN_PUBLIC_ISOLATE_HOLDER_H_
diff --git a/chromium/gin/public/wrapper_info.h b/chromium/gin/public/wrapper_info.h
new file mode 100644
index 00000000000..31b2a981e3c
--- /dev/null
+++ b/chromium/gin/public/wrapper_info.h
@@ -0,0 +1,32 @@
+// 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_PUBLIC_WRAPPER_INFO_H_
+#define GIN_PUBLIC_WRAPPER_INFO_H_
+
+#include "gin/gin_export.h"
+#include "gin/public/gin_embedders.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+// Gin embedder that use their own WrapperInfo-like structs must ensure that
+// the first field is of type GinEmbedderId and has the correct id set. They
+// also should use kWrapperInfoIndex to start their WrapperInfo-like struct
+// and ensure that all objects have kNumberOfInternalFields internal fields.
+
+enum InternalFields {
+ kWrapperInfoIndex,
+ kEncodedValueIndex,
+ kNumberOfInternalFields,
+};
+
+struct GIN_EXPORT WrapperInfo {
+ static WrapperInfo* From(v8::Handle<v8::Object> object);
+ const GinEmbedder embedder;
+};
+
+} // namespace gin
+
+#endif // GIN_PUBLIC_WRAPPER_INFO_H_
diff --git a/chromium/gin/runner.cc b/chromium/gin/runner.cc
new file mode 100644
index 00000000000..37e16a09c74
--- /dev/null
+++ b/chromium/gin/runner.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/runner.h"
+
+#include "gin/converter.h"
+#include "gin/per_context_data.h"
+#include "gin/try_catch.h"
+
+using v8::Context;
+using v8::HandleScope;
+using v8::Isolate;
+using v8::Object;
+using v8::ObjectTemplate;
+using v8::Script;
+
+namespace gin {
+
+RunnerDelegate::RunnerDelegate() {
+}
+
+RunnerDelegate::~RunnerDelegate() {
+}
+
+v8::Handle<ObjectTemplate> RunnerDelegate::GetGlobalTemplate(Runner* runner) {
+ return v8::Handle<ObjectTemplate>();
+}
+
+void RunnerDelegate::DidCreateContext(Runner* runner) {
+}
+
+void RunnerDelegate::WillRunScript(Runner* runner) {
+}
+
+void RunnerDelegate::DidRunScript(Runner* runner) {
+}
+
+void RunnerDelegate::UnhandledException(Runner* runner, TryCatch& try_catch) {
+}
+
+Runner::Runner(RunnerDelegate* delegate, Isolate* isolate)
+ : ContextHolder(isolate),
+ delegate_(delegate),
+ weak_factory_(this) {
+ v8::Isolate::Scope isolate_scope(isolate);
+ HandleScope handle_scope(isolate);
+ v8::Handle<v8::Context> context =
+ Context::New(isolate, NULL, delegate_->GetGlobalTemplate(this));
+
+ SetContext(context);
+ PerContextData::From(context)->set_runner(this);
+
+ v8::Context::Scope scope(context);
+ delegate_->DidCreateContext(this);
+}
+
+Runner::~Runner() {
+}
+
+void Runner::Run(const std::string& source, const std::string& resource_name) {
+ Run(Script::New(StringToV8(isolate(), source),
+ StringToV8(isolate(), resource_name)));
+}
+
+void Runner::Run(v8::Handle<Script> script) {
+ TryCatch try_catch;
+ delegate_->WillRunScript(this);
+
+ script->Run();
+
+ delegate_->DidRunScript(this);
+ if (try_catch.HasCaught())
+ delegate_->UnhandledException(this, try_catch);
+}
+
+v8::Handle<v8::Value> Runner::Call(v8::Handle<v8::Function> function,
+ v8::Handle<v8::Value> receiver,
+ int argc,
+ v8::Handle<v8::Value> argv[]) {
+ TryCatch try_catch;
+ delegate_->WillRunScript(this);
+
+ v8::Handle<v8::Value> result = function->Call(receiver, argc, argv);
+
+ delegate_->DidRunScript(this);
+ if (try_catch.HasCaught())
+ delegate_->UnhandledException(this, try_catch);
+
+ return result;
+}
+
+Runner::Scope::Scope(Runner* runner)
+ : isolate_scope_(runner->isolate()),
+ handle_scope_(runner->isolate()),
+ scope_(runner->context()) {
+}
+
+Runner::Scope::~Scope() {
+}
+
+} // namespace gin
diff --git a/chromium/gin/runner.h b/chromium/gin/runner.h
new file mode 100644
index 00000000000..943bcedba1c
--- /dev/null
+++ b/chromium/gin/runner.h
@@ -0,0 +1,87 @@
+// 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_RUNNER_H_
+#define GIN_RUNNER_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "gin/gin_export.h"
+#include "gin/public/context_holder.h"
+
+namespace gin {
+
+class Runner;
+class TryCatch;
+
+// Subclass RunnerDelegate to customize the behavior of |Runner|. Typical
+// embedders will want to subclass one of the specialized RunnerDelegates,
+// such as ModuleRunnerDelegate.
+class GIN_EXPORT RunnerDelegate {
+ public:
+ RunnerDelegate();
+ virtual ~RunnerDelegate();
+
+ // Returns the template for the global object.
+ virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(Runner* runner);
+ virtual void DidCreateContext(Runner* runner);
+ virtual void WillRunScript(Runner* runner);
+ virtual void DidRunScript(Runner* runner);
+ virtual void UnhandledException(Runner* runner, TryCatch& try_catch);
+};
+
+// Runner lets you run code in a v8::Context. Upon construction, Runner will
+// create a v8::Context. Upon destruction, Runner will dispose the context.
+class GIN_EXPORT Runner : public ContextHolder {
+ public:
+ Runner(RunnerDelegate* delegate, v8::Isolate* isolate);
+ ~Runner();
+
+ // Before running script in this context, you'll need to enter the runner's
+ // context by creating an instance of Runner::Scope on the stack.
+ void Run(const std::string& source, const std::string& resource_name);
+ void Run(v8::Handle<v8::Script> script);
+
+ v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
+ v8::Handle<v8::Value> receiver,
+ int argc,
+ v8::Handle<v8::Value> argv[]);
+
+ v8::Handle<v8::Object> global() const {
+ return context()->Global();
+ }
+
+ // Useful for running script in this context asynchronously. Rather than
+ // holding a raw pointer to the runner, consider holding a WeakPtr.
+ base::WeakPtr<Runner> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+ }
+
+ class GIN_EXPORT Scope {
+ public:
+ explicit Scope(Runner* runner);
+ ~Scope();
+
+ private:
+ v8::Isolate::Scope isolate_scope_;
+ v8::HandleScope handle_scope_;
+ v8::Context::Scope scope_;
+
+ DISALLOW_COPY_AND_ASSIGN(Scope);
+ };
+
+ private:
+ friend class Scope;
+
+ RunnerDelegate* delegate_;
+
+ base::WeakPtrFactory<Runner> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(Runner);
+};
+
+} // namespace gin
+
+#endif // GIN_RUNNER_H_
diff --git a/chromium/gin/runner_unittest.cc b/chromium/gin/runner_unittest.cc
new file mode 100644
index 00000000000..3723956df6a
--- /dev/null
+++ b/chromium/gin/runner_unittest.cc
@@ -0,0 +1,37 @@
+// 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 "base/compiler_specific.h"
+#include "gin/converter.h"
+#include "gin/public/isolate_holder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using v8::Isolate;
+using v8::Object;
+using v8::Script;
+using v8::String;
+
+namespace gin {
+
+TEST(RunnerTest, Run) {
+ std::string source = "this.result = 'PASS';\n";
+
+ gin::IsolateHolder instance;
+
+ RunnerDelegate delegate;
+ Isolate* isolate = instance.isolate();
+ Runner runner(&delegate, isolate);
+ Runner::Scope scope(&runner);
+ runner.Run(source, "test_data.js");
+
+ std::string result;
+ EXPECT_TRUE(Converter<std::string>::FromV8(isolate,
+ runner.global()->Get(StringToV8(isolate, "result")),
+ &result));
+ EXPECT_EQ("PASS", result);
+}
+
+} // namespace gin
diff --git a/chromium/gin/shell/gin_main.cc b/chromium/gin/shell/gin_main.cc
new file mode 100644
index 00000000000..24fa6df1528
--- /dev/null
+++ b/chromium/gin/shell/gin_main.cc
@@ -0,0 +1,85 @@
+// 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 "base/at_exit.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/i18n/icu_util.h"
+#include "base/message_loop/message_loop.h"
+#include "gin/modules/console.h"
+#include "gin/modules/module_runner_delegate.h"
+#include "gin/public/isolate_holder.h"
+#include "gin/test/file_runner.h"
+#include "gin/try_catch.h"
+
+namespace gin {
+namespace {
+
+std::string Load(const base::FilePath& path) {
+ std::string source;
+ if (!ReadFileToString(path, &source))
+ LOG(FATAL) << "Unable to read " << path.LossyDisplayName();
+ return source;
+}
+
+void Run(base::WeakPtr<Runner> runner, const base::FilePath& path) {
+ if (!runner)
+ return;
+ Runner::Scope scope(runner.get());
+ runner->Run(Load(path), path.AsUTF8Unsafe());
+}
+
+std::vector<base::FilePath> GetModuleSearchPaths() {
+ std::vector<base::FilePath> module_base(1);
+ CHECK(file_util::GetCurrentDirectory(&module_base[0]));
+ return module_base;
+}
+
+class ShellRunnerDelegate : public ModuleRunnerDelegate {
+ public:
+ ShellRunnerDelegate() : ModuleRunnerDelegate(GetModuleSearchPaths()) {
+ AddBuiltinModule(Console::kModuleName, Console::GetTemplate);
+ }
+
+ virtual void UnhandledException(Runner* runner,
+ TryCatch& try_catch) OVERRIDE {
+ ModuleRunnerDelegate::UnhandledException(runner, try_catch);
+ LOG(ERROR) << try_catch.GetStackTrace();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ShellRunnerDelegate);
+};
+
+} // namespace
+} // namespace gin
+
+int main(int argc, char** argv) {
+ base::AtExitManager at_exit;
+ CommandLine::Init(argc, argv);
+ base::i18n::InitializeICU();
+
+ gin::IsolateHolder instance;
+
+ base::MessageLoop message_loop;
+
+ gin::ShellRunnerDelegate delegate;
+ gin::Runner runner(&delegate, instance.isolate());
+
+ {
+ gin::Runner::Scope scope(&runner);
+ v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
+ }
+
+ CommandLine::StringVector args = CommandLine::ForCurrentProcess()->GetArgs();
+ for (CommandLine::StringVector::const_iterator it = args.begin();
+ it != args.end(); ++it) {
+ base::MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
+ gin::Run, runner.GetWeakPtr(), base::FilePath(*it)));
+ }
+
+ message_loop.RunUntilIdle();
+ return 0;
+}
diff --git a/chromium/gin/try_catch.cc b/chromium/gin/try_catch.cc
new file mode 100644
index 00000000000..a44e28e9fe5
--- /dev/null
+++ b/chromium/gin/try_catch.cc
@@ -0,0 +1,49 @@
+// 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/try_catch.h"
+
+#include <sstream>
+
+#include "gin/converter.h"
+
+namespace gin {
+
+TryCatch::TryCatch() {
+}
+
+TryCatch::~TryCatch() {
+}
+
+bool TryCatch::HasCaught() {
+ return try_catch_.HasCaught();
+}
+
+std::string TryCatch::GetStackTrace() {
+ if (!HasCaught()) {
+ return "";
+ }
+
+ std::stringstream ss;
+ v8::Handle<v8::Message> message = try_catch_.Message();
+ ss << V8ToString(message->Get()) << std::endl
+ << V8ToString(message->GetSourceLine()) << std::endl;
+
+ v8::Handle<v8::StackTrace> trace = message->GetStackTrace();
+ if (trace.IsEmpty())
+ return ss.str();
+
+ int len = trace->GetFrameCount();
+ for (int i = 0; i < len; ++i) {
+ v8::Handle<v8::StackFrame> frame = trace->GetFrame(i);
+ ss << V8ToString(frame->GetScriptName()) << ":"
+ << frame->GetLineNumber() << ":"
+ << frame->GetColumn() << ": "
+ << V8ToString(frame->GetFunctionName())
+ << std::endl;
+ }
+ return ss.str();
+}
+
+} // namespace gin
diff --git a/chromium/gin/try_catch.h b/chromium/gin/try_catch.h
new file mode 100644
index 00000000000..633b9092341
--- /dev/null
+++ b/chromium/gin/try_catch.h
@@ -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.
+
+#ifndef GIN_TRY_CATCH_H_
+#define GIN_TRY_CATCH_H_
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "gin/gin_export.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+// TryCatch is a convenient wrapper around v8::TryCatch.
+class GIN_EXPORT TryCatch {
+ public:
+ TryCatch();
+ ~TryCatch();
+
+ bool HasCaught();
+ std::string GetStackTrace();
+
+ private:
+ v8::TryCatch try_catch_;
+
+ DISALLOW_COPY_AND_ASSIGN(TryCatch);
+};
+
+} // namespace gin
+
+#endif // GIN_TRY_CATCH_H_
diff --git a/chromium/gin/wrappable.cc b/chromium/gin/wrappable.cc
new file mode 100644
index 00000000000..4a9ef0e1935
--- /dev/null
+++ b/chromium/gin/wrappable.cc
@@ -0,0 +1,72 @@
+// 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/wrappable.h"
+
+#include "base/logging.h"
+#include "gin/per_isolate_data.h"
+
+namespace gin {
+
+WrappableBase::WrappableBase() {
+}
+
+WrappableBase::~WrappableBase() {
+ wrapper_.Reset();
+}
+
+v8::Handle<v8::Object> WrappableBase::GetWrapperImpl(
+ v8::Isolate* isolate, WrapperInfo* wrapper_info) {
+ if (wrapper_.IsEmpty())
+ CreateWrapper(isolate, wrapper_info);
+ return v8::Local<v8::Object>::New(isolate, wrapper_);
+}
+
+void WrappableBase::WeakCallback(
+ const v8::WeakCallbackData<v8::Object, WrappableBase>& data) {
+ WrappableBase* wrappable = data.GetParameter();
+ wrappable->wrapper_.Reset();
+ delete wrappable;
+}
+
+v8::Handle<v8::Object> WrappableBase::CreateWrapper(v8::Isolate* isolate,
+ WrapperInfo* info) {
+ PerIsolateData* data = PerIsolateData::From(isolate);
+ v8::Local<v8::ObjectTemplate> templ = data->GetObjectTemplate(info);
+ CHECK(!templ.IsEmpty()); // Don't forget to register an object template.
+ CHECK_EQ(kNumberOfInternalFields, templ->InternalFieldCount());
+ v8::Handle<v8::Object> wrapper = templ->NewInstance();
+ wrapper->SetAlignedPointerInInternalField(kWrapperInfoIndex, info);
+ wrapper->SetAlignedPointerInInternalField(kEncodedValueIndex, this);
+ wrapper_.Reset(isolate, wrapper);
+ wrapper_.SetWeak(this, WeakCallback);
+ return wrapper;
+}
+
+namespace internal {
+
+void* FromV8Impl(v8::Isolate* isolate, v8::Handle<v8::Value> val,
+ WrapperInfo* wrapper_info) {
+ if (!val->IsObject())
+ return NULL;
+ v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(val);
+ WrapperInfo* info = WrapperInfo::From(obj);
+
+ // If this fails, the object is not managed by Gin. It is either a normal JS
+ // object that's not wrapping any external C++ object, or it is wrapping some
+ // C++ object, but that object isn't managed by Gin (maybe Blink).
+ if (!info)
+ return NULL;
+
+ // If this fails, the object is managed by Gin, but it's not wrapping an
+ // instance of the C++ class associated with wrapper_info.
+ if (info != wrapper_info)
+ return NULL;
+
+ return obj->GetAlignedPointerFromInternalField(kEncodedValueIndex);
+}
+
+} // namespace internal
+
+} // namespace gin
diff --git a/chromium/gin/wrappable.h b/chromium/gin/wrappable.h
new file mode 100644
index 00000000000..755707166bb
--- /dev/null
+++ b/chromium/gin/wrappable.h
@@ -0,0 +1,101 @@
+// 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_WRAPPABLE_H_
+#define GIN_WRAPPABLE_H_
+
+#include "base/template_util.h"
+#include "gin/converter.h"
+#include "gin/gin_export.h"
+#include "gin/public/wrapper_info.h"
+
+namespace gin {
+
+namespace internal {
+
+GIN_EXPORT void* FromV8Impl(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val,
+ WrapperInfo* info);
+
+} // namespace internal
+
+
+// Wrappable is a base class for C++ objects that have corresponding v8 wrapper
+// objects. To retain a Wrappable object on the stack, use a gin::Handle.
+//
+// USAGE:
+// // my_class.h
+// class MyClass : Wrappable<MyClass> {
+// ...
+// };
+//
+// // my_class.cc
+// INIT_WRAPABLE(MyClass);
+//
+// Subclasses should also typically have private constructors and expose a
+// static Create function that returns a gin::Handle. Forcing creators through
+// this static Create function will enforce that clients actually create a
+// wrapper for the object. If clients fail to create a wrapper for a wrappable
+// object, the object will leak because we use the weak callback from the
+// wrapper as the signal to delete the wrapped object.
+template<typename T>
+class Wrappable;
+
+
+// Non-template base class to share code between templates instances.
+class GIN_EXPORT WrappableBase {
+ protected:
+ WrappableBase();
+ virtual ~WrappableBase();
+ v8::Handle<v8::Object> GetWrapperImpl(v8::Isolate* isolate,
+ WrapperInfo* wrapper_info);
+ v8::Handle<v8::Object> CreateWrapper(v8::Isolate* isolate,
+ WrapperInfo* wrapper_info);
+ v8::Persistent<v8::Object> wrapper_; // Weak
+
+ private:
+ static void WeakCallback(
+ const v8::WeakCallbackData<v8::Object, WrappableBase>& data);
+
+ DISALLOW_COPY_AND_ASSIGN(WrappableBase);
+};
+
+
+template<typename T>
+class Wrappable : public WrappableBase {
+ public:
+ // Retrieve (or create) the v8 wrapper object cooresponding to this object.
+ // To customize the wrapper created for a subclass, override GetWrapperInfo()
+ // instead of overriding this function.
+ v8::Handle<v8::Object> GetWrapper(v8::Isolate* isolate) {
+ return GetWrapperImpl(isolate, &T::kWrapperInfo);
+ }
+
+ protected:
+ Wrappable() {}
+ virtual ~Wrappable() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Wrappable);
+};
+
+
+// This converter handles any subclass of Wrappable.
+template<typename T>
+struct Converter<T*, typename base::enable_if<
+ base::is_convertible<T*, Wrappable<T>*>::value>::type> {
+ static v8::Handle<v8::Value> ToV8(v8::Isolate* isolate, T* val) {
+ return val->GetWrapper(isolate);
+ }
+
+ static bool FromV8(v8::Isolate* isolate, v8::Handle<v8::Value> val, T** out) {
+ *out = static_cast<T*>(internal::FromV8Impl(isolate, val,
+ &T::kWrapperInfo));
+ return *out != NULL;
+ }
+};
+
+} // namespace gin
+
+#endif // GIN_WRAPPABLE_H_
diff --git a/chromium/gin/wrappable_unittest.cc b/chromium/gin/wrappable_unittest.cc
new file mode 100644
index 00000000000..3499eedcc18
--- /dev/null
+++ b/chromium/gin/wrappable_unittest.cc
@@ -0,0 +1,149 @@
+// 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 "base/logging.h"
+#include "gin/arguments.h"
+#include "gin/handle.h"
+#include "gin/object_template_builder.h"
+#include "gin/per_isolate_data.h"
+#include "gin/public/isolate_holder.h"
+#include "gin/test/v8_test.h"
+#include "gin/try_catch.h"
+#include "gin/wrappable.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gin {
+
+class MyObject : public Wrappable<MyObject> {
+ public:
+ static WrapperInfo kWrapperInfo;
+
+ static gin::Handle<MyObject> Create(v8::Isolate* isolate) {
+ return CreateHandle(isolate, new MyObject());
+ }
+
+ int value() const { return value_; }
+ void set_value(int value) { value_ = value; }
+
+ private:
+ MyObject() : value_(0) {}
+ virtual ~MyObject() {}
+
+ int value_;
+};
+
+class MyObject2 : public Wrappable<MyObject2> {
+ public:
+ static WrapperInfo kWrapperInfo;
+};
+
+class MyObjectBlink : public Wrappable<MyObjectBlink> {
+ public:
+ static WrapperInfo kWrapperInfo;
+};
+
+WrapperInfo MyObject::kWrapperInfo = { kEmbedderNativeGin };
+WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin };
+WrapperInfo MyObjectBlink::kWrapperInfo = { kEmbedderNativeGin };
+
+void RegisterTemplates(v8::Isolate* isolate) {
+ PerIsolateData* data = PerIsolateData::From(isolate);
+ DCHECK(data->GetObjectTemplate(&MyObject::kWrapperInfo).IsEmpty());
+
+ v8::Handle<v8::ObjectTemplate> templ = ObjectTemplateBuilder(isolate)
+ .SetProperty("value", &MyObject::value, &MyObject::set_value)
+ .Build();
+ templ->SetInternalFieldCount(kNumberOfInternalFields);
+ data->SetObjectTemplate(&MyObject::kWrapperInfo, templ);
+
+ templ = v8::ObjectTemplate::New(isolate);
+ templ->SetInternalFieldCount(kNumberOfInternalFields);
+ data->SetObjectTemplate(&MyObject2::kWrapperInfo, templ);
+
+ templ = v8::ObjectTemplate::New(isolate);
+ templ->SetInternalFieldCount(kNumberOfInternalFields);
+ data->SetObjectTemplate(&MyObjectBlink::kWrapperInfo, templ);
+}
+
+typedef V8Test WrappableTest;
+
+TEST_F(WrappableTest, WrapAndUnwrap) {
+ v8::Isolate* isolate = instance_->isolate();
+ v8::HandleScope handle_scope(isolate);
+
+ RegisterTemplates(isolate);
+ Handle<MyObject> obj = MyObject::Create(isolate);
+
+ v8::Handle<v8::Value> wrapper = ConvertToV8(isolate, obj.get());
+ EXPECT_FALSE(wrapper.IsEmpty());
+
+ MyObject* unwrapped = NULL;
+ EXPECT_TRUE(ConvertFromV8(isolate, wrapper, &unwrapped));
+ EXPECT_EQ(obj.get(), unwrapped);
+}
+
+TEST_F(WrappableTest, UnwrapFailures) {
+ v8::Isolate* isolate = instance_->isolate();
+ v8::HandleScope handle_scope(isolate);
+
+ RegisterTemplates(isolate);
+
+ // Something that isn't an object.
+ v8::Handle<v8::Value> thing = v8::Number::New(42);
+ MyObject* unwrapped = NULL;
+ EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped));
+ EXPECT_FALSE(unwrapped);
+
+ // An object that's not wrapping anything.
+ thing = v8::Object::New(isolate);
+ EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped));
+ EXPECT_FALSE(unwrapped);
+
+ // An object that's wrapping a C++ object from Blink.
+ thing.Clear();
+ thing = ConvertToV8(isolate, new MyObjectBlink());
+ EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped));
+ EXPECT_FALSE(unwrapped);
+
+ // An object that's wrapping a C++ object of the wrong type.
+ thing.Clear();
+ thing = ConvertToV8(isolate, new MyObject2());
+ EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped));
+ EXPECT_FALSE(unwrapped);
+}
+
+TEST_F(WrappableTest, GetAndSetProperty) {
+ v8::Isolate* isolate = instance_->isolate();
+ v8::HandleScope handle_scope(isolate);
+
+ RegisterTemplates(isolate);
+ gin::Handle<MyObject> obj = MyObject::Create(isolate);
+
+ obj->set_value(42);
+ EXPECT_EQ(42, obj->value());
+
+ v8::Handle<v8::String> source = StringToV8(isolate,
+ "(function (obj) {"
+ " if (obj.value !== 42) throw 'FAIL';"
+ " else obj.value = 191; })");
+ EXPECT_FALSE(source.IsEmpty());
+
+ gin::TryCatch try_catch;
+ v8::Handle<v8::Script> script = v8::Script::New(source);
+ EXPECT_FALSE(script.IsEmpty());
+ v8::Handle<v8::Value> val = script->Run();
+ EXPECT_FALSE(val.IsEmpty());
+ v8::Handle<v8::Function> func;
+ EXPECT_TRUE(ConvertFromV8(isolate, val, &func));
+ v8::Handle<v8::Value> argv[] = {
+ ConvertToV8(isolate, obj.get()),
+ };
+ func->Call(v8::Undefined(isolate), 1, argv);
+ EXPECT_FALSE(try_catch.HasCaught());
+ EXPECT_EQ("", try_catch.GetStackTrace());
+
+ EXPECT_EQ(191, obj->value());
+}
+
+} // namespace gin
diff --git a/chromium/gin/wrapper_info.cc b/chromium/gin/wrapper_info.cc
new file mode 100644
index 00000000000..6bf831696b0
--- /dev/null
+++ b/chromium/gin/wrapper_info.cc
@@ -0,0 +1,17 @@
+// 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/public/wrapper_info.h"
+
+namespace gin {
+
+WrapperInfo* WrapperInfo::From(v8::Handle<v8::Object> object) {
+ if (object->InternalFieldCount() != kNumberOfInternalFields)
+ return NULL;
+ WrapperInfo* info = static_cast<WrapperInfo*>(
+ object->GetAlignedPointerFromInternalField(kWrapperInfoIndex));
+ return info->embedder == kEmbedderNativeGin ? info : NULL;
+}
+
+} // namespace gin