summaryrefslogtreecommitdiff
path: root/gin
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2014-03-18 10:20:56 +0000
committerTorne (Richard Coles) <torne@google.com>2014-03-18 10:20:56 +0000
commita1401311d1ab56c4ed0a474bd38c108f75cb0cd9 (patch)
tree3437151d9ae1ce20a1e53a0d98c19ca01c786394 /gin
parentaf5066f1e36c6579e74752647e6c584438f80f94 (diff)
downloadchromium_org-a1401311d1ab56c4ed0a474bd38c108f75cb0cd9.tar.gz
Merge from Chromium at DEPS revision 257591
This commit was generated by merge_to_master.py. Change-Id: I0010df2ec3fbb5d4947cd026de2feb150ce7a6b5
Diffstat (limited to 'gin')
-rw-r--r--gin/arguments.h11
-rw-r--r--gin/array_buffer.cc29
-rw-r--r--gin/context_holder.cc7
-rw-r--r--gin/converter.cc4
-rw-r--r--gin/converter.h3
-rw-r--r--gin/converter_unittest.cc2
-rw-r--r--gin/function_template.h14
-rw-r--r--gin/function_template.h.pump14
-rw-r--r--gin/gin.gyp10
-rw-r--r--gin/gin.target.darwin-arm.mk15
-rw-r--r--gin/gin.target.darwin-mips.mk15
-rw-r--r--gin/gin.target.darwin-x86.mk25
-rw-r--r--gin/gin.target.linux-arm.mk15
-rw-r--r--gin/gin.target.linux-mips.mk15
-rw-r--r--gin/gin.target.linux-x86.mk25
-rw-r--r--gin/handle.h5
-rw-r--r--gin/interceptor.cc64
-rw-r--r--gin/interceptor.h63
-rw-r--r--gin/interceptor_unittest.cc159
-rw-r--r--gin/isolate_holder.cc14
-rw-r--r--gin/modules/module_registry.cc64
-rw-r--r--gin/modules/module_registry.h19
-rw-r--r--gin/modules/module_registry_observer.h31
-rw-r--r--gin/modules/module_registry_unittest.cc99
-rw-r--r--gin/modules/module_runner_delegate.cc26
-rw-r--r--gin/modules/module_runner_delegate.h13
-rw-r--r--gin/modules/timer.cc10
-rw-r--r--gin/modules/timer_unittest.cc8
-rw-r--r--gin/object_template_builder.cc141
-rw-r--r--gin/object_template_builder.h23
-rw-r--r--gin/per_context_data.cc33
-rw-r--r--gin/per_context_data.h40
-rw-r--r--gin/per_context_data_unittest.cc34
-rw-r--r--gin/per_isolate_data.cc57
-rw-r--r--gin/per_isolate_data.h30
-rw-r--r--gin/public/context_holder.h4
-rw-r--r--gin/public/isolate_holder.h9
-rw-r--r--gin/runner.cc96
-rw-r--r--gin/runner.h51
-rw-r--r--gin/shell/gin_main.cc6
-rw-r--r--gin/shell_runner.cc112
-rw-r--r--gin/shell_runner.h68
-rw-r--r--gin/shell_runner_unittest.cc (renamed from gin/runner_unittest.cc)8
-rw-r--r--gin/test/file_runner.cc9
-rw-r--r--gin/test/file_runner.h3
-rw-r--r--gin/wrappable.cc8
-rw-r--r--gin/wrappable_unittest.cc80
47 files changed, 1267 insertions, 324 deletions
diff --git a/gin/arguments.h b/gin/arguments.h
index ec4ae80e88..509c22ca14 100644
--- a/gin/arguments.h
+++ b/gin/arguments.h
@@ -56,6 +56,17 @@ class GIN_EXPORT Arguments {
return true;
}
+ bool Skip() {
+ if (next_ >= info_->Length())
+ return false;
+ next_++;
+ return true;
+ }
+
+ int Length() const {
+ return info_->Length();
+ }
+
template<typename T>
void Return(T val) {
info_->GetReturnValue().Set(ConvertToV8(isolate_, val));
diff --git a/gin/array_buffer.cc b/gin/array_buffer.cc
index ee9f2a5867..68237bcbf8 100644
--- a/gin/array_buffer.cc
+++ b/gin/array_buffer.cc
@@ -2,17 +2,23 @@
// 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>
+#include "base/logging.h"
+#include "gin/array_buffer.h"
+#include "gin/per_isolate_data.h"
+
namespace gin {
+namespace {
+
+gin::WrapperInfo g_array_buffer_wrapper_info = {gin::kEmbedderNativeGin};
+
+} // namespace
+
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) {
@@ -72,6 +78,7 @@ class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> {
v8::Persistent<v8::ArrayBuffer> array_buffer_;
scoped_refptr<Private> self_reference_;
+ v8::Isolate* isolate_;
void* buffer_;
size_t length_;
};
@@ -79,28 +86,34 @@ class ArrayBuffer::Private : public base::RefCounted<ArrayBuffer::Private> {
scoped_refptr<ArrayBuffer::Private> ArrayBuffer::Private::From(
v8::Isolate* isolate, v8::Handle<v8::ArrayBuffer> array) {
if (array->IsExternal()) {
+ CHECK_EQ(WrapperInfo::From(v8::Handle<v8::Object>::Cast(array)),
+ &g_array_buffer_wrapper_info)
+ << "Cannot mix blink and gin ArrayBuffers";
return make_scoped_refptr(static_cast<Private*>(
- array->GetAlignedPointerFromInternalField(kBufferViewPrivateIndex)));
+ array->GetAlignedPointerFromInternalField(kEncodedValueIndex)));
}
return make_scoped_refptr(new Private(isolate, array));
}
ArrayBuffer::Private::Private(v8::Isolate* isolate,
v8::Handle<v8::ArrayBuffer> array)
- : array_buffer_(isolate, array) {
+ : array_buffer_(isolate, array), isolate_(isolate) {
// Take ownership of the array buffer.
+ CHECK(!array->IsExternal());
v8::ArrayBuffer::Contents contents = array->Externalize();
buffer_ = contents.Data();
length_ = contents.ByteLength();
- array->SetAlignedPointerInInternalField(kBufferViewPrivateIndex, this);
+ array->SetAlignedPointerInInternalField(kWrapperInfoIndex,
+ &g_array_buffer_wrapper_info);
+ array->SetAlignedPointerInInternalField(kEncodedValueIndex, this);
self_reference_ = this; // Cleared in WeakCallback.
array_buffer_.SetWeak(this, WeakCallback);
}
ArrayBuffer::Private::~Private() {
- ArrayBufferAllocator::SharedInstance()->Free(buffer_, length_);
+ PerIsolateData::From(isolate_)->allocator()->Free(buffer_, length_);
}
void ArrayBuffer::Private::WeakCallback(
diff --git a/gin/context_holder.cc b/gin/context_holder.cc
index fba2a2a8bf..241b25622c 100644
--- a/gin/context_holder.cc
+++ b/gin/context_holder.cc
@@ -14,17 +14,14 @@ ContextHolder::ContextHolder(v8::Isolate* isolate)
}
ContextHolder::~ContextHolder() {
- v8::HandleScope handle_scope(isolate());
- v8::Handle<v8::Context> context = this->context();
-
- data_->Detach(context);
+ // PerContextData needs to be destroyed before the context.
data_.reset();
}
void ContextHolder::SetContext(v8::Handle<v8::Context> context) {
DCHECK(context_.IsEmpty());
context_.Reset(isolate_, context);
- data_.reset(new PerContextData(context));
+ data_.reset(new PerContextData(this, context));
}
} // namespace gin
diff --git a/gin/converter.cc b/gin/converter.cc
index 07437b7edc..29da322c1a 100644
--- a/gin/converter.cc
+++ b/gin/converter.cc
@@ -35,7 +35,7 @@ Handle<Value> Converter<int32_t>::ToV8(Isolate* isolate, int32_t val) {
bool Converter<int32_t>::FromV8(Isolate* isolate, Handle<Value> val,
int32_t* out) {
- if (!val->IsInt32())
+ if (!val->IsNumber())
return false;
*out = val->Int32Value();
return true;
@@ -47,7 +47,7 @@ Handle<Value> Converter<uint32_t>::ToV8(Isolate* isolate, uint32_t val) {
bool Converter<uint32_t>::FromV8(Isolate* isolate, Handle<Value> val,
uint32_t* out) {
- if (!val->IsUint32())
+ if (!val->IsNumber())
return false;
*out = val->Uint32Value();
return true;
diff --git a/gin/converter.h b/gin/converter.h
index 1ce459e15c..e5c95fc1f9 100644
--- a/gin/converter.h
+++ b/gin/converter.h
@@ -176,8 +176,7 @@ struct Converter<std::vector<T> > {
// Convenience functions that deduce T.
template<typename T>
-v8::Handle<v8::Value> ConvertToV8(v8::Isolate* isolate,
- T input) {
+v8::Handle<v8::Value> ConvertToV8(v8::Isolate* isolate, T input) {
return Converter<T>::ToV8(isolate, input);
}
diff --git a/gin/converter_unittest.cc b/gin/converter_unittest.cc
index 791d7e66ec..cf1affc0e1 100644
--- a/gin/converter_unittest.cc
+++ b/gin/converter_unittest.cc
@@ -89,7 +89,7 @@ TEST_F(ConverterTest, Int32) {
{ 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 },
+ { Number::New(instance_->isolate(), 1.1).As<Value>(), true, 1 },
{ 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 },
diff --git a/gin/function_template.h b/gin/function_template.h
index fe95f519ef..7ba54b5910 100644
--- a/gin/function_template.h
+++ b/gin/function_template.h
@@ -501,6 +501,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
holder->GetHandle(isolate)));
}
+// CreateFunctionHandler installs a CallAsFunction handler on the given
+// object template that forwards to a provided C++ function or base::Callback.
+template<typename Sig>
+void CreateFunctionHandler(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> tmpl,
+ const base::Callback<Sig> callback,
+ int callback_flags = 0) {
+ typedef internal::CallbackHolder<Sig> HolderT;
+ HolderT* holder = new HolderT(isolate, callback, callback_flags);
+ tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback,
+ ConvertToV8<v8::Handle<v8::External> >(
+ isolate, holder->GetHandle(isolate)));
+}
+
} // namespace gin
#endif // GIN_FUNCTION_TEMPLATE_H_
diff --git a/gin/function_template.h.pump b/gin/function_template.h.pump
index 6f5badee92..20b2821e0e 100644
--- a/gin/function_template.h.pump
+++ b/gin/function_template.h.pump
@@ -221,6 +221,20 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate(
holder->GetHandle(isolate)));
}
+// CreateFunctionHandler installs a CallAsFunction handler on the given
+// object template that forwards to a provided C++ function or base::Callback.
+template<typename Sig>
+void CreateFunctionHandler(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> tmpl,
+ const base::Callback<Sig> callback,
+ int callback_flags = 0) {
+ typedef internal::CallbackHolder<Sig> HolderT;
+ HolderT* holder = new HolderT(isolate, callback, callback_flags);
+ tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback,
+ ConvertToV8<v8::Handle<v8::External> >(
+ isolate, holder->GetHandle(isolate)));
+}
+
} // namespace gin
#endif // GIN_FUNCTION_TEMPLATE_H_
diff --git a/gin/gin.gyp b/gin/gin.gyp
index 78c8fb1d97..1b15dd16c4 100644
--- a/gin/gin.gyp
+++ b/gin/gin.gyp
@@ -35,6 +35,8 @@
'function_template.h',
'gin_export.h',
'handle.h',
+ 'interceptor.cc',
+ 'interceptor.h',
'isolate_holder.cc',
'modules/console.cc',
'modules/console.h',
@@ -42,6 +44,7 @@
'modules/file_module_provider.h',
'modules/module_registry.cc',
'modules/module_registry.h',
+ 'modules/module_registry_observer.h',
'modules/module_runner_delegate.cc',
'modules/module_runner_delegate.h',
'modules/timer.cc',
@@ -58,6 +61,8 @@
'public/wrapper_info.h',
'runner.cc',
'runner.h',
+ 'shell_runner.cc',
+ 'shell_runner.h',
'try_catch.cc',
'try_catch.h',
'wrappable.cc',
@@ -114,10 +119,13 @@
],
'sources': [
'converter_unittest.cc',
+ 'interceptor_unittest.cc',
+ 'modules/module_registry_unittest.cc',
'modules/timer_unittest.cc',
+ 'per_context_data_unittest.cc',
+ 'shell_runner_unittest.cc',
'test/run_all_unittests.cc',
'test/run_js_tests.cc',
- 'runner_unittest.cc',
'wrappable_unittest.cc',
],
},
diff --git a/gin/gin.target.darwin-arm.mk b/gin/gin.target.darwin-arm.mk
index 9da148631c..6d6bee45f1 100644
--- a/gin/gin.target.darwin-arm.mk
+++ b/gin/gin.target.darwin-arm.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
gin/converter.cc \
gin/dictionary.cc \
gin/function_template.cc \
+ gin/interceptor.cc \
gin/isolate_holder.cc \
gin/modules/console.cc \
gin/modules/file_module_provider.cc \
@@ -40,6 +41,7 @@ LOCAL_SRC_FILES := \
gin/per_context_data.cc \
gin/per_isolate_data.cc \
gin/runner.cc \
+ gin/shell_runner.cc \
gin/try_catch.cc \
gin/wrappable.cc \
gin/wrapper_info.cc
@@ -82,6 +84,7 @@ MY_CFLAGS_Debug := \
MY_DEFS_Debug := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -89,14 +92,15 @@ MY_DEFS_Debug := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -169,6 +173,7 @@ MY_CFLAGS_Release := \
MY_DEFS_Release := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -176,14 +181,15 @@ MY_DEFS_Release := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -223,9 +229,11 @@ LOCAL_CPPFLAGS_Release := \
LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
### Rules for final target.
LOCAL_LDFLAGS_Debug := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -237,7 +245,6 @@ LOCAL_LDFLAGS_Debug := \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--icf=safe \
- -Wl,--fatal-warnings \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
@@ -245,6 +252,7 @@ LOCAL_LDFLAGS_Debug := \
LOCAL_LDFLAGS_Release := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -259,7 +267,6 @@ LOCAL_LDFLAGS_Release := \
-Wl,-O1 \
-Wl,--as-needed \
-Wl,--gc-sections \
- -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel
diff --git a/gin/gin.target.darwin-mips.mk b/gin/gin.target.darwin-mips.mk
index da8b23434c..1e1588ff47 100644
--- a/gin/gin.target.darwin-mips.mk
+++ b/gin/gin.target.darwin-mips.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
gin/converter.cc \
gin/dictionary.cc \
gin/function_template.cc \
+ gin/interceptor.cc \
gin/isolate_holder.cc \
gin/modules/console.cc \
gin/modules/file_module_provider.cc \
@@ -40,6 +41,7 @@ LOCAL_SRC_FILES := \
gin/per_context_data.cc \
gin/per_isolate_data.cc \
gin/runner.cc \
+ gin/shell_runner.cc \
gin/try_catch.cc \
gin/wrappable.cc \
gin/wrapper_info.cc
@@ -81,6 +83,7 @@ MY_CFLAGS_Debug := \
MY_DEFS_Debug := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -88,14 +91,15 @@ MY_DEFS_Debug := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -167,6 +171,7 @@ MY_CFLAGS_Release := \
MY_DEFS_Release := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -174,14 +179,15 @@ MY_DEFS_Release := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -221,9 +227,11 @@ LOCAL_CPPFLAGS_Release := \
LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
### Rules for final target.
LOCAL_LDFLAGS_Debug := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -233,7 +241,6 @@ LOCAL_LDFLAGS_Debug := \
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--fatal-warnings \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
@@ -241,6 +248,7 @@ LOCAL_LDFLAGS_Debug := \
LOCAL_LDFLAGS_Release := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -253,7 +261,6 @@ LOCAL_LDFLAGS_Release := \
-Wl,-O1 \
-Wl,--as-needed \
-Wl,--gc-sections \
- -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel
diff --git a/gin/gin.target.darwin-x86.mk b/gin/gin.target.darwin-x86.mk
index f0d0cb4504..0e2450ca66 100644
--- a/gin/gin.target.darwin-x86.mk
+++ b/gin/gin.target.darwin-x86.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
gin/converter.cc \
gin/dictionary.cc \
gin/function_template.cc \
+ gin/interceptor.cc \
gin/isolate_holder.cc \
gin/modules/console.cc \
gin/modules/file_module_provider.cc \
@@ -40,6 +41,7 @@ LOCAL_SRC_FILES := \
gin/per_context_data.cc \
gin/per_isolate_data.cc \
gin/runner.cc \
+ gin/shell_runner.cc \
gin/try_catch.cc \
gin/wrappable.cc \
gin/wrapper_info.cc
@@ -57,11 +59,10 @@ MY_CFLAGS_Debug := \
-fvisibility=hidden \
-pipe \
-fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
-msse2 \
-mfpmath=sse \
+ -mmmx \
+ -m32 \
-fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
@@ -84,6 +85,7 @@ MY_CFLAGS_Debug := \
MY_DEFS_Debug := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -91,14 +93,15 @@ MY_DEFS_Debug := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -145,11 +148,10 @@ MY_CFLAGS_Release := \
-fvisibility=hidden \
-pipe \
-fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
-msse2 \
-mfpmath=sse \
+ -mmmx \
+ -m32 \
-fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
@@ -172,6 +174,7 @@ MY_CFLAGS_Release := \
MY_DEFS_Release := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -179,14 +182,15 @@ MY_DEFS_Release := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -225,9 +229,11 @@ LOCAL_CPPFLAGS_Release := \
LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
### Rules for final target.
LOCAL_LDFLAGS_Debug := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -237,7 +243,6 @@ LOCAL_LDFLAGS_Debug := \
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--fatal-warnings \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
@@ -245,6 +250,7 @@ LOCAL_LDFLAGS_Debug := \
LOCAL_LDFLAGS_Release := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -257,7 +263,6 @@ LOCAL_LDFLAGS_Release := \
-Wl,-O1 \
-Wl,--as-needed \
-Wl,--gc-sections \
- -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel
diff --git a/gin/gin.target.linux-arm.mk b/gin/gin.target.linux-arm.mk
index 9da148631c..6d6bee45f1 100644
--- a/gin/gin.target.linux-arm.mk
+++ b/gin/gin.target.linux-arm.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
gin/converter.cc \
gin/dictionary.cc \
gin/function_template.cc \
+ gin/interceptor.cc \
gin/isolate_holder.cc \
gin/modules/console.cc \
gin/modules/file_module_provider.cc \
@@ -40,6 +41,7 @@ LOCAL_SRC_FILES := \
gin/per_context_data.cc \
gin/per_isolate_data.cc \
gin/runner.cc \
+ gin/shell_runner.cc \
gin/try_catch.cc \
gin/wrappable.cc \
gin/wrapper_info.cc
@@ -82,6 +84,7 @@ MY_CFLAGS_Debug := \
MY_DEFS_Debug := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -89,14 +92,15 @@ MY_DEFS_Debug := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -169,6 +173,7 @@ MY_CFLAGS_Release := \
MY_DEFS_Release := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -176,14 +181,15 @@ MY_DEFS_Release := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -223,9 +229,11 @@ LOCAL_CPPFLAGS_Release := \
LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
### Rules for final target.
LOCAL_LDFLAGS_Debug := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -237,7 +245,6 @@ LOCAL_LDFLAGS_Debug := \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
-Wl,--icf=safe \
- -Wl,--fatal-warnings \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
@@ -245,6 +252,7 @@ LOCAL_LDFLAGS_Debug := \
LOCAL_LDFLAGS_Release := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -259,7 +267,6 @@ LOCAL_LDFLAGS_Release := \
-Wl,-O1 \
-Wl,--as-needed \
-Wl,--gc-sections \
- -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel
diff --git a/gin/gin.target.linux-mips.mk b/gin/gin.target.linux-mips.mk
index da8b23434c..1e1588ff47 100644
--- a/gin/gin.target.linux-mips.mk
+++ b/gin/gin.target.linux-mips.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
gin/converter.cc \
gin/dictionary.cc \
gin/function_template.cc \
+ gin/interceptor.cc \
gin/isolate_holder.cc \
gin/modules/console.cc \
gin/modules/file_module_provider.cc \
@@ -40,6 +41,7 @@ LOCAL_SRC_FILES := \
gin/per_context_data.cc \
gin/per_isolate_data.cc \
gin/runner.cc \
+ gin/shell_runner.cc \
gin/try_catch.cc \
gin/wrappable.cc \
gin/wrapper_info.cc
@@ -81,6 +83,7 @@ MY_CFLAGS_Debug := \
MY_DEFS_Debug := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -88,14 +91,15 @@ MY_DEFS_Debug := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -167,6 +171,7 @@ MY_CFLAGS_Release := \
MY_DEFS_Release := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -174,14 +179,15 @@ MY_DEFS_Release := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -221,9 +227,11 @@ LOCAL_CPPFLAGS_Release := \
LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
### Rules for final target.
LOCAL_LDFLAGS_Debug := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -233,7 +241,6 @@ LOCAL_LDFLAGS_Debug := \
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--fatal-warnings \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
@@ -241,6 +248,7 @@ LOCAL_LDFLAGS_Debug := \
LOCAL_LDFLAGS_Release := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -253,7 +261,6 @@ LOCAL_LDFLAGS_Release := \
-Wl,-O1 \
-Wl,--as-needed \
-Wl,--gc-sections \
- -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel
diff --git a/gin/gin.target.linux-x86.mk b/gin/gin.target.linux-x86.mk
index f0d0cb4504..0e2450ca66 100644
--- a/gin/gin.target.linux-x86.mk
+++ b/gin/gin.target.linux-x86.mk
@@ -30,6 +30,7 @@ LOCAL_SRC_FILES := \
gin/converter.cc \
gin/dictionary.cc \
gin/function_template.cc \
+ gin/interceptor.cc \
gin/isolate_holder.cc \
gin/modules/console.cc \
gin/modules/file_module_provider.cc \
@@ -40,6 +41,7 @@ LOCAL_SRC_FILES := \
gin/per_context_data.cc \
gin/per_isolate_data.cc \
gin/runner.cc \
+ gin/shell_runner.cc \
gin/try_catch.cc \
gin/wrappable.cc \
gin/wrapper_info.cc
@@ -57,11 +59,10 @@ MY_CFLAGS_Debug := \
-fvisibility=hidden \
-pipe \
-fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
-msse2 \
-mfpmath=sse \
+ -mmmx \
+ -m32 \
-fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
@@ -84,6 +85,7 @@ MY_CFLAGS_Debug := \
MY_DEFS_Debug := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -91,14 +93,15 @@ MY_DEFS_Debug := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -145,11 +148,10 @@ MY_CFLAGS_Release := \
-fvisibility=hidden \
-pipe \
-fPIC \
- -m32 \
- -mmmx \
- -march=pentium4 \
-msse2 \
-mfpmath=sse \
+ -mmmx \
+ -m32 \
-fuse-ld=gold \
-ffunction-sections \
-funwind-tables \
@@ -172,6 +174,7 @@ MY_CFLAGS_Release := \
MY_DEFS_Release := \
'-DV8_DEPRECATION_WARNINGS' \
+ '-DBLINK_SCALE_FILTERS_AT_RECORD_TIME' \
'-D_FILE_OFFSET_BITS=64' \
'-DNO_TCMALLOC' \
'-DDISABLE_NACL' \
@@ -179,14 +182,15 @@ MY_DEFS_Release := \
'-DUSE_LIBJPEG_TURBO=1' \
'-DUSE_PROPRIETARY_CODECS' \
'-DENABLE_CONFIGURATION_POLICY' \
+ '-DENABLE_NEW_GAMEPAD_API=1' \
'-DDISCARDABLE_MEMORY_ALWAYS_SUPPORTED_NATIVELY' \
'-DSYSTEM_NATIVELY_SIGNALS_MEMORY_PRESSURE' \
- '-DUSE_OPENSSL=1' \
'-DENABLE_EGLIMAGE=1' \
'-DCLD_VERSION=1' \
'-DENABLE_PRINTING=1' \
'-DENABLE_MANAGED_USERS=1' \
'-DGIN_IMPLEMENTATION' \
+ '-DUSE_OPENSSL=1' \
'-D__STDC_CONSTANT_MACROS' \
'-D__STDC_FORMAT_MACROS' \
'-DANDROID' \
@@ -225,9 +229,11 @@ LOCAL_CPPFLAGS_Release := \
LOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) $(MY_DEFS_$(GYP_CONFIGURATION))
LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) $(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))
LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))
+LOCAL_ASFLAGS := $(LOCAL_CFLAGS)
### Rules for final target.
LOCAL_LDFLAGS_Debug := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -237,7 +243,6 @@ LOCAL_LDFLAGS_Debug := \
-nostdlib \
-Wl,--no-undefined \
-Wl,--exclude-libs=ALL \
- -Wl,--fatal-warnings \
-Wl,--gc-sections \
-Wl,--warn-shared-textrel \
-Wl,-O1 \
@@ -245,6 +250,7 @@ LOCAL_LDFLAGS_Debug := \
LOCAL_LDFLAGS_Release := \
+ -Wl,--fatal-warnings \
-Wl,-z,now \
-Wl,-z,relro \
-Wl,-z,noexecstack \
@@ -257,7 +263,6 @@ LOCAL_LDFLAGS_Release := \
-Wl,-O1 \
-Wl,--as-needed \
-Wl,--gc-sections \
- -Wl,--fatal-warnings \
-Wl,--warn-shared-textrel
diff --git a/gin/handle.h b/gin/handle.h
index da1de347f2..01db6606f1 100644
--- a/gin/handle.h
+++ b/gin/handle.h
@@ -60,7 +60,10 @@ struct Converter<gin::Handle<T> > {
// 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);
+ v8::Handle<v8::Object> wrapper = object->GetWrapper(isolate);
+ if (wrapper.IsEmpty())
+ return gin::Handle<T>();
+ return gin::Handle<T>(wrapper, object);
}
} // namespace gin
diff --git a/gin/interceptor.cc b/gin/interceptor.cc
new file mode 100644
index 0000000000..7efc32ee68
--- /dev/null
+++ b/gin/interceptor.cc
@@ -0,0 +1,64 @@
+// Copyright 2014 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/interceptor.h"
+
+#include <map>
+
+#include "gin/per_isolate_data.h"
+
+namespace gin {
+
+NamedPropertyInterceptor::NamedPropertyInterceptor(v8::Isolate* isolate,
+ WrappableBase* base)
+ : isolate_(isolate), base_(base) {
+ PerIsolateData::From(isolate_)->SetNamedPropertyInterceptor(base_, this);
+}
+
+NamedPropertyInterceptor::~NamedPropertyInterceptor() {
+ PerIsolateData::From(isolate_)->ClearNamedPropertyInterceptor(base_, this);
+}
+
+v8::Local<v8::Value> NamedPropertyInterceptor::GetNamedProperty(
+ v8::Isolate* isolate,
+ const std::string& property) {
+ return v8::Local<v8::Value>();
+}
+
+void NamedPropertyInterceptor::SetNamedProperty(v8::Isolate* isolate,
+ const std::string& property,
+ v8::Local<v8::Value> value) {}
+
+std::vector<std::string> NamedPropertyInterceptor::EnumerateNamedProperties(
+ v8::Isolate* isolate) {
+ return std::vector<std::string>();
+}
+
+IndexedPropertyInterceptor::IndexedPropertyInterceptor(v8::Isolate* isolate,
+ WrappableBase* base)
+ : isolate_(isolate), base_(base) {
+ PerIsolateData::From(isolate_)->SetIndexedPropertyInterceptor(base_, this);
+}
+
+IndexedPropertyInterceptor::~IndexedPropertyInterceptor() {
+ PerIsolateData::From(isolate_)->ClearIndexedPropertyInterceptor(base_, this);
+}
+
+v8::Local<v8::Value> IndexedPropertyInterceptor::GetIndexedProperty(
+ v8::Isolate* isolate,
+ uint32_t index) {
+ return v8::Local<v8::Value>();
+}
+
+void IndexedPropertyInterceptor::SetIndexedProperty(
+ v8::Isolate* isolate,
+ uint32_t index,
+ v8::Local<v8::Value> value) {}
+
+std::vector<uint32_t> IndexedPropertyInterceptor::EnumerateIndexedProperties(
+ v8::Isolate* isolate) {
+ return std::vector<uint32_t>();
+}
+
+} // namespace gin
diff --git a/gin/interceptor.h b/gin/interceptor.h
new file mode 100644
index 0000000000..802929b837
--- /dev/null
+++ b/gin/interceptor.h
@@ -0,0 +1,63 @@
+// Copyright 2014 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_INTERCEPTOR_H_
+#define GIN_INTERCEPTOR_H_
+
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "gin/gin_export.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+class WrappableBase;
+
+// Base class for gin::Wrappable-derived classes that want to implement a
+// property interceptor.
+class GIN_EXPORT NamedPropertyInterceptor {
+ public:
+ NamedPropertyInterceptor(v8::Isolate* isolate, WrappableBase* base);
+ virtual ~NamedPropertyInterceptor();
+
+ virtual v8::Local<v8::Value> GetNamedProperty(v8::Isolate* isolate,
+ const std::string& property);
+ virtual void SetNamedProperty(v8::Isolate* isolate,
+ const std::string& property,
+ v8::Local<v8::Value> value);
+ virtual std::vector<std::string> EnumerateNamedProperties(
+ v8::Isolate* isolate);
+
+ private:
+ v8::Isolate* isolate_;
+ WrappableBase* base_;
+
+ DISALLOW_COPY_AND_ASSIGN(NamedPropertyInterceptor);
+};
+
+class GIN_EXPORT IndexedPropertyInterceptor {
+ public:
+ IndexedPropertyInterceptor(v8::Isolate* isolate, WrappableBase* base);
+ virtual ~IndexedPropertyInterceptor();
+
+ virtual v8::Local<v8::Value> GetIndexedProperty(v8::Isolate* isolate,
+ uint32_t index);
+ virtual void SetIndexedProperty(v8::Isolate* isolate,
+ uint32_t index,
+ v8::Local<v8::Value> value);
+ virtual std::vector<uint32_t> EnumerateIndexedProperties(
+ v8::Isolate* isolate);
+
+ private:
+ v8::Isolate* isolate_;
+ WrappableBase* base_;
+
+ DISALLOW_COPY_AND_ASSIGN(IndexedPropertyInterceptor);
+};
+
+} // namespace gin
+
+#endif // GIN_INTERCEPTOR_H_
diff --git a/gin/interceptor_unittest.cc b/gin/interceptor_unittest.cc
new file mode 100644
index 0000000000..ee6b7dc50a
--- /dev/null
+++ b/gin/interceptor_unittest.cc
@@ -0,0 +1,159 @@
+// Copyright 2014 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/interceptor.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 MyInterceptor : public Wrappable<MyInterceptor>,
+ public NamedPropertyInterceptor,
+ public IndexedPropertyInterceptor {
+ public:
+ static WrapperInfo kWrapperInfo;
+
+ static gin::Handle<MyInterceptor> Create(v8::Isolate* isolate) {
+ return CreateHandle(isolate, new MyInterceptor(isolate));
+ }
+
+ int value() const { return value_; }
+ void set_value(int value) { value_ = value; }
+
+ // gin::NamedPropertyInterceptor
+ virtual v8::Local<v8::Value> GetNamedProperty(v8::Isolate* isolate,
+ const std::string& property)
+ OVERRIDE {
+ if (property == "value") {
+ return ConvertToV8(isolate, value_);
+ } else if (property == "func") {
+ return CreateFunctionTemplate(isolate,
+ base::Bind(&MyInterceptor::Call),
+ HolderIsFirstArgument)->GetFunction();
+ } else {
+ return v8::Local<v8::Value>();
+ }
+ }
+ virtual void SetNamedProperty(v8::Isolate* isolate,
+ const std::string& property,
+ v8::Local<v8::Value> value) OVERRIDE {
+ if (property != "value")
+ return;
+ ConvertFromV8(isolate, value, &value_);
+ }
+ virtual std::vector<std::string> EnumerateNamedProperties(
+ v8::Isolate* isolate) OVERRIDE {
+ std::vector<std::string> result;
+ result.push_back("func");
+ result.push_back("value");
+ return result;
+ }
+
+ // gin::IndexedPropertyInterceptor
+ virtual v8::Local<v8::Value> GetIndexedProperty(v8::Isolate* isolate,
+ uint32_t index) OVERRIDE {
+ if (index == 0)
+ return ConvertToV8(isolate, value_);
+ return v8::Local<v8::Value>();
+ }
+ virtual void SetIndexedProperty(v8::Isolate* isolate,
+ uint32_t index,
+ v8::Local<v8::Value> value) OVERRIDE {
+ if (index != 0)
+ return;
+ ConvertFromV8(isolate, value, &value_);
+ }
+ virtual std::vector<uint32_t> EnumerateIndexedProperties(v8::Isolate* isolate)
+ OVERRIDE {
+ std::vector<uint32_t> result;
+ result.push_back(0);
+ return result;
+ }
+
+ private:
+ explicit MyInterceptor(v8::Isolate* isolate)
+ : NamedPropertyInterceptor(isolate, this),
+ IndexedPropertyInterceptor(isolate, this),
+ value_(0) {}
+ virtual ~MyInterceptor() {}
+
+ // gin::Wrappable
+ virtual ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate)
+ OVERRIDE {
+ return Wrappable<MyInterceptor>::GetObjectTemplateBuilder(isolate)
+ .AddNamedPropertyInterceptor()
+ .AddIndexedPropertyInterceptor();
+ }
+
+ int Call(int value) {
+ int tmp = value_;
+ value_ = value;
+ return tmp;
+ }
+
+ int value_;
+};
+
+WrapperInfo MyInterceptor::kWrapperInfo = {kEmbedderNativeGin};
+
+class InterceptorTest : public V8Test {
+ public:
+ void RunInterceptorTest(const std::string& script_source) {
+ v8::Isolate* isolate = instance_->isolate();
+ v8::HandleScope handle_scope(isolate);
+
+ gin::Handle<MyInterceptor> obj = MyInterceptor::Create(isolate);
+
+ obj->set_value(42);
+ EXPECT_EQ(42, obj->value());
+
+ v8::Handle<v8::String> source = StringToV8(isolate, script_source);
+ EXPECT_FALSE(source.IsEmpty());
+
+ gin::TryCatch try_catch;
+ v8::Handle<v8::Script> script = v8::Script::Compile(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());
+ }
+};
+
+TEST_F(InterceptorTest, NamedInterceptor) {
+ RunInterceptorTest(
+ "(function (obj) {"
+ " if (obj.value !== 42) throw 'FAIL';"
+ " else obj.value = 191; })");
+}
+
+TEST_F(InterceptorTest, NamedInterceptorCall) {
+ RunInterceptorTest(
+ "(function (obj) {"
+ " if (obj.func(191) !== 42) throw 'FAIL';"
+ " })");
+}
+
+TEST_F(InterceptorTest, IndexedInterceptor) {
+ RunInterceptorTest(
+ "(function (obj) {"
+ " if (obj[0] !== 42) throw 'FAIL';"
+ " else obj[0] = 191; })");
+}
+
+} // namespace gin
diff --git a/gin/isolate_holder.cc b/gin/isolate_holder.cc
index 411f26acec..bb243490dc 100644
--- a/gin/isolate_holder.cc
+++ b/gin/isolate_holder.cc
@@ -53,14 +53,14 @@ IsolateHolder::IsolateHolder()
constraints.ConfigureDefaults(base::SysInfo::AmountOfPhysicalMemory(),
base::SysInfo::NumberOfProcessors());
v8::SetResourceConstraints(isolate_, &constraints);
- Init();
+ Init(ArrayBufferAllocator::SharedInstance());
}
-IsolateHolder::IsolateHolder(v8::Isolate* isolate)
- : isolate_owner_(false),
- isolate_(isolate) {
+IsolateHolder::IsolateHolder(v8::Isolate* isolate,
+ v8::ArrayBuffer::Allocator* allocator)
+ : isolate_owner_(false), isolate_(isolate) {
EnsureV8Initialized(false);
- Init();
+ Init(allocator);
}
IsolateHolder::~IsolateHolder() {
@@ -69,10 +69,10 @@ IsolateHolder::~IsolateHolder() {
isolate_->Dispose();
}
-void IsolateHolder::Init() {
+void IsolateHolder::Init(v8::ArrayBuffer::Allocator* allocator) {
v8::Isolate::Scope isolate_scope(isolate_);
v8::HandleScope handle_scope(isolate_);
- isolate_data_.reset(new PerIsolateData(isolate_));
+ isolate_data_.reset(new PerIsolateData(isolate_, allocator));
}
} // namespace gin
diff --git a/gin/modules/module_registry.cc b/gin/modules/module_registry.cc
index eda34880e7..3712f1a41a 100644
--- a/gin/modules/module_registry.cc
+++ b/gin/modules/module_registry.cc
@@ -10,6 +10,8 @@
#include "base/logging.h"
#include "gin/arguments.h"
#include "gin/converter.h"
+#include "gin/modules/module_registry_observer.h"
+#include "gin/per_context_data.h"
#include "gin/per_isolate_data.h"
#include "gin/public/wrapper_info.h"
#include "gin/runner.h"
@@ -47,6 +49,13 @@ PendingModule::~PendingModule() {
namespace {
+// Key for base::SupportsUserData::Data.
+const char kModuleRegistryKey[] = "ModuleRegistry";
+
+struct ModuleRegistryData : public base::SupportsUserData::Data {
+ scoped_ptr<ModuleRegistry> registry;
+};
+
void Define(const v8::FunctionCallbackInfo<Value>& info) {
Arguments args(info);
@@ -87,10 +96,6 @@ Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) {
return templ;
}
-v8::Handle<String> GetHiddenValueKey(Isolate* isolate) {
- return StringToSymbol(isolate, "::gin::ModuleRegistry");
-}
-
} // namespace
ModuleRegistry::ModuleRegistry(Isolate* isolate)
@@ -101,26 +106,42 @@ ModuleRegistry::~ModuleRegistry() {
modules_.Reset();
}
+// static
void ModuleRegistry::RegisterGlobals(Isolate* isolate,
v8::Handle<ObjectTemplate> templ) {
templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
}
+// static
+void ModuleRegistry::InstallGlobals(v8::Isolate* isolate,
+ v8::Handle<v8::Object> obj) {
+ obj->Set(StringToSymbol(isolate, "define"),
+ GetDefineTemplate(isolate)->GetFunction());
+}
+
+// static
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;
+ PerContextData* data = PerContextData::From(context);
+ if (!data)
+ return NULL;
+
+ ModuleRegistryData* registry_data = static_cast<ModuleRegistryData*>(
+ data->GetUserData(kModuleRegistryKey));
+ if (!registry_data) {
+ // PerContextData takes ownership of ModuleRegistryData.
+ registry_data = new ModuleRegistryData;
+ registry_data->registry.reset(new ModuleRegistry(context->GetIsolate()));
+ data->SetUserData(kModuleRegistryKey, registry_data);
}
- return static_cast<ModuleRegistry*>(external->Value());
+ return registry_data->registry.get();
+}
+
+void ModuleRegistry::AddObserver(ModuleRegistryObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void ModuleRegistry::RemoveObserver(ModuleRegistryObserver* observer) {
+ observer_list_.RemoveObserver(observer);
}
void ModuleRegistry::AddBuiltinModule(Isolate* isolate, const std::string& id,
@@ -131,7 +152,11 @@ void ModuleRegistry::AddBuiltinModule(Isolate* isolate, const std::string& id,
void ModuleRegistry::AddPendingModule(Isolate* isolate,
scoped_ptr<PendingModule> pending) {
+ const std::string pending_id = pending->id;
+ const std::vector<std::string> pending_dependencies = pending->dependencies;
AttemptToLoad(isolate, pending.Pass());
+ FOR_EACH_OBSERVER(ModuleRegistryObserver, observer_list_,
+ OnDidAddPendingModule(pending_id, pending_dependencies));
}
void ModuleRegistry::LoadModule(Isolate* isolate,
@@ -168,11 +193,6 @@ void ModuleRegistry::RegisterModule(Isolate* isolate,
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();
diff --git a/gin/modules/module_registry.h b/gin/modules/module_registry.h
index 755875c353..5775a34a3d 100644
--- a/gin/modules/module_registry.h
+++ b/gin/modules/module_registry.h
@@ -13,11 +13,14 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
+#include "base/observer_list.h"
#include "gin/gin_export.h"
-#include "gin/per_context_data.h"
+#include "v8/include/v8.h"
namespace gin {
+class ModuleRegistryObserver;
struct PendingModule;
// This class implements the Asynchronous Module Definition (AMD) API.
@@ -31,7 +34,7 @@ struct PendingModule;
// function. The spec says we should only add that property once our
// implementation complies with the specification.
//
-class GIN_EXPORT ModuleRegistry : public ContextSupplement {
+class GIN_EXPORT ModuleRegistry {
public:
typedef base::Callback<void (v8::Handle<v8::Value>)> LoadModuleCallback;
@@ -42,6 +45,13 @@ class GIN_EXPORT ModuleRegistry : public ContextSupplement {
static void RegisterGlobals(v8::Isolate* isolate,
v8::Handle<v8::ObjectTemplate> templ);
+ // Installs the necessary functions needed for modules.
+ // WARNING: this may execute script in the page.
+ static void InstallGlobals(v8::Isolate* isolate, v8::Handle<v8::Object> obj);
+
+ void AddObserver(ModuleRegistryObserver* observer);
+ void RemoveObserver(ModuleRegistryObserver* observer);
+
// The caller must have already entered our context.
void AddBuiltinModule(v8::Isolate* isolate, const std::string& id,
v8::Handle<v8::Value> module);
@@ -71,9 +81,6 @@ class GIN_EXPORT ModuleRegistry : public ContextSupplement {
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,
@@ -92,6 +99,8 @@ class GIN_EXPORT ModuleRegistry : public ContextSupplement {
PendingModuleVector pending_modules_;
v8::Persistent<v8::Object> modules_;
+ ObserverList<ModuleRegistryObserver> observer_list_;
+
DISALLOW_COPY_AND_ASSIGN(ModuleRegistry);
};
diff --git a/gin/modules/module_registry_observer.h b/gin/modules/module_registry_observer.h
new file mode 100644
index 0000000000..68ee4adc75
--- /dev/null
+++ b/gin/modules/module_registry_observer.h
@@ -0,0 +1,31 @@
+// Copyright 2014 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_OBSERVER_H_
+#define GIN_MODULES_MODULE_REGISTRY_OBSERVER_H_
+
+#include <string>
+#include <vector>
+
+#include "gin/gin_export.h"
+
+namespace gin {
+
+// Notified of interesting events from ModuleRegistry.
+class GIN_EXPORT ModuleRegistryObserver {
+ public:
+ // Called from AddPendingModule(). |id| is the id/name of the module and
+ // |dependencies| this list of modules |id| depends upon.
+ virtual void OnDidAddPendingModule(
+ const std::string& id,
+ const std::vector<std::string>& dependencies) = 0;
+
+ protected:
+ virtual ~ModuleRegistryObserver() {}
+};
+
+} // namespace gin
+
+#endif // GIN_MODULES_MODULE_REGISTRY_OBSERVER_H_
+
diff --git a/gin/modules/module_registry_unittest.cc b/gin/modules/module_registry_unittest.cc
new file mode 100644
index 0000000000..0ffdc0c3dd
--- /dev/null
+++ b/gin/modules/module_registry_unittest.cc
@@ -0,0 +1,99 @@
+// Copyright 2014 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 "base/message_loop/message_loop.h"
+#include "gin/modules/module_registry_observer.h"
+#include "gin/modules/module_runner_delegate.h"
+#include "gin/public/context_holder.h"
+#include "gin/public/isolate_holder.h"
+#include "gin/shell_runner.h"
+#include "gin/test/v8_test.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+namespace {
+
+struct TestHelper {
+ TestHelper(v8::Isolate* isolate)
+ : delegate(std::vector<base::FilePath>()),
+ runner(new ShellRunner(&delegate, isolate)),
+ scope(runner.get()) {
+ }
+
+ base::MessageLoop message_loop;
+ ModuleRunnerDelegate delegate;
+ scoped_ptr<ShellRunner> runner;
+ Runner::Scope scope;
+};
+
+class ModuleRegistryObserverImpl : public ModuleRegistryObserver {
+ public:
+ ModuleRegistryObserverImpl() : did_add_count_(0) {}
+
+ virtual void OnDidAddPendingModule(
+ const std::string& id,
+ const std::vector<std::string>& dependencies) OVERRIDE {
+ did_add_count_++;
+ id_ = id;
+ dependencies_ = dependencies;
+ }
+
+ int did_add_count() { return did_add_count_; }
+ const std::string& id() const { return id_; }
+ const std::vector<std::string>& dependencies() const { return dependencies_; }
+
+ private:
+ int did_add_count_;
+ std::string id_;
+ std::vector<std::string> dependencies_;
+
+ DISALLOW_COPY_AND_ASSIGN(ModuleRegistryObserverImpl);
+};
+
+} // namespace
+
+typedef V8Test ModuleRegistryTest;
+
+// Verifies ModuleRegistry is not available after ContextHolder has been
+// deleted.
+TEST_F(ModuleRegistryTest, DestroyedWithContext) {
+ v8::Isolate::Scope isolate_scope(instance_->isolate());
+ v8::HandleScope handle_scope(instance_->isolate());
+ v8::Handle<v8::Context> context = v8::Context::New(
+ instance_->isolate(), NULL, v8::Handle<v8::ObjectTemplate>());
+ {
+ ContextHolder context_holder(instance_->isolate());
+ context_holder.SetContext(context);
+ ModuleRegistry* registry = ModuleRegistry::From(context);
+ EXPECT_TRUE(registry != NULL);
+ }
+ ModuleRegistry* registry = ModuleRegistry::From(context);
+ EXPECT_TRUE(registry == NULL);
+}
+
+// Verifies ModuleRegistryObserver is notified appropriately.
+TEST_F(ModuleRegistryTest, ModuleRegistryObserverTest) {
+ TestHelper helper(instance_->isolate());
+ std::string source =
+ "define('id', ['dep1', 'dep2'], function() {"
+ " return function() {};"
+ "});";
+
+ ModuleRegistryObserverImpl observer;
+ ModuleRegistry::From(helper.runner->GetContextHolder()->context())->
+ AddObserver(&observer);
+ helper.runner->Run(source, "script");
+ ModuleRegistry::From(helper.runner->GetContextHolder()->context())->
+ RemoveObserver(&observer);
+ EXPECT_EQ(1, observer.did_add_count());
+ EXPECT_EQ("id", observer.id());
+ ASSERT_EQ(2u, observer.dependencies().size());
+ EXPECT_EQ("dep1", observer.dependencies()[0]);
+ EXPECT_EQ("dep2", observer.dependencies()[1]);
+}
+
+} // namespace gin
diff --git a/gin/modules/module_runner_delegate.cc b/gin/modules/module_runner_delegate.cc
index 2a9f95cd76..16b5afd030 100644
--- a/gin/modules/module_runner_delegate.cc
+++ b/gin/modules/module_runner_delegate.cc
@@ -6,6 +6,7 @@
#include "gin/modules/module_registry.h"
#include "gin/object_template_builder.h"
+#include "gin/public/context_holder.h"
namespace gin {
@@ -23,34 +24,35 @@ void ModuleRunnerDelegate::AddBuiltinModule(const std::string& id,
}
void ModuleRunnerDelegate::AttemptToLoadMoreModules(Runner* runner) {
- ModuleRegistry* registry = ModuleRegistry::From(runner->context());
- registry->AttemptToLoadMoreModules(runner->isolate());
+ ModuleRegistry* registry = ModuleRegistry::From(
+ runner->GetContextHolder()->context());
+ registry->AttemptToLoadMoreModules(runner->GetContextHolder()->isolate());
module_provider_.AttempToLoadModules(
runner, registry->unsatisfied_dependencies());
}
v8::Handle<v8::ObjectTemplate> ModuleRunnerDelegate::GetGlobalTemplate(
- Runner* runner) {
- v8::Handle<v8::ObjectTemplate> templ =
- ObjectTemplateBuilder(runner->isolate()).Build();
- ModuleRegistry::RegisterGlobals(runner->isolate(), templ);
+ ShellRunner* runner,
+ v8::Isolate* isolate) {
+ v8::Handle<v8::ObjectTemplate> templ = ObjectTemplateBuilder(isolate).Build();
+ ModuleRegistry::RegisterGlobals(isolate, templ);
return templ;
}
-void ModuleRunnerDelegate::DidCreateContext(Runner* runner) {
- RunnerDelegate::DidCreateContext(runner);
+void ModuleRunnerDelegate::DidCreateContext(ShellRunner* runner) {
+ ShellRunnerDelegate::DidCreateContext(runner);
- v8::Handle<v8::Context> context = runner->context();
+ v8::Handle<v8::Context> context = runner->GetContextHolder()->context();
ModuleRegistry* registry = ModuleRegistry::From(context);
+ v8::Isolate* isolate = runner->GetContextHolder()->isolate();
for (BuiltinModuleMap::const_iterator it = builtin_modules_.begin();
it != builtin_modules_.end(); ++it) {
- registry->AddBuiltinModule(runner->isolate(), it->first,
- it->second(runner->isolate()));
+ registry->AddBuiltinModule(isolate, it->first, it->second(isolate));
}
}
-void ModuleRunnerDelegate::DidRunScript(Runner* runner) {
+void ModuleRunnerDelegate::DidRunScript(ShellRunner* runner) {
AttemptToLoadMoreModules(runner);
}
diff --git a/gin/modules/module_runner_delegate.h b/gin/modules/module_runner_delegate.h
index 3ce056f250..09d4582dd7 100644
--- a/gin/modules/module_runner_delegate.h
+++ b/gin/modules/module_runner_delegate.h
@@ -10,7 +10,7 @@
#include "base/compiler_specific.h"
#include "gin/gin_export.h"
#include "gin/modules/file_module_provider.h"
-#include "gin/runner.h"
+#include "gin/shell_runner.h"
namespace gin {
@@ -19,7 +19,7 @@ typedef v8::Local<v8::Value> (*ModuleGetter)(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 {
+class GIN_EXPORT ModuleRunnerDelegate : public ShellRunnerDelegate {
public:
explicit ModuleRunnerDelegate(
const std::vector<base::FilePath>& search_paths);
@@ -33,11 +33,12 @@ class GIN_EXPORT ModuleRunnerDelegate : public RunnerDelegate {
private:
typedef std::map<std::string, ModuleGetter> BuiltinModuleMap;
- // From RunnerDelegate:
+ // From ShellRunnerDelegate:
virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(
- Runner* runner) OVERRIDE;
- virtual void DidCreateContext(Runner* runner) OVERRIDE;
- virtual void DidRunScript(Runner* runner) OVERRIDE;
+ ShellRunner* runner,
+ v8::Isolate* isolate) OVERRIDE;
+ virtual void DidCreateContext(ShellRunner* runner) OVERRIDE;
+ virtual void DidRunScript(ShellRunner* runner) OVERRIDE;
BuiltinModuleMap builtin_modules_;
FileModuleProvider module_provider_;
diff --git a/gin/modules/timer.cc b/gin/modules/timer.cc
index 6d59f56cc3..3196dda425 100644
--- a/gin/modules/timer.cc
+++ b/gin/modules/timer.cc
@@ -45,8 +45,8 @@ Timer::Timer(v8::Isolate* isolate, bool repeating, int delay_ms,
timer_(false, repeating),
runner_(PerContextData::From(
isolate->GetCurrentContext())->runner()->GetWeakPtr()) {
- GetWrapper(runner_->isolate())->SetHiddenValue(GetHiddenPropertyName(isolate),
- function);
+ GetWrapper(runner_->GetContextHolder()->isolate())->SetHiddenValue(
+ GetHiddenPropertyName(isolate), function);
timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
base::Bind(&Timer::OnTimerFired, weak_factory_.GetWeakPtr()));
}
@@ -63,10 +63,10 @@ void Timer::OnTimerFired() {
}
Runner::Scope scope(runner_.get());
+ v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(
- GetWrapper(runner_->isolate())->GetHiddenValue(
- GetHiddenPropertyName(runner_->isolate())));
- runner_->Call(function, v8::Undefined(runner_->isolate()), 0, NULL);
+ GetWrapper(isolate)->GetHiddenValue(GetHiddenPropertyName(isolate)));
+ runner_->Call(function, v8::Undefined(isolate), 0, NULL);
}
diff --git a/gin/modules/timer_unittest.cc b/gin/modules/timer_unittest.cc
index 9826747542..f7fd8f22e6 100644
--- a/gin/modules/timer_unittest.cc
+++ b/gin/modules/timer_unittest.cc
@@ -9,7 +9,7 @@
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/public/isolate_holder.h"
-#include "gin/runner.h"
+#include "gin/shell_runner.h"
#include "gin/test/v8_test.h"
#include "gin/try_catch.h"
#include "gin/wrappable.h"
@@ -54,7 +54,7 @@ WrapperInfo Result::kWrapperInfo = { gin::kEmbedderNativeGin };
struct TestHelper {
TestHelper(v8::Isolate* isolate)
- : runner(new Runner(&delegate, isolate)),
+ : runner(new ShellRunner(&delegate, isolate)),
scope(runner.get()),
timer_module(TimerModule::Create(isolate)),
result(Result::Create(isolate)) {
@@ -70,8 +70,8 @@ struct TestHelper {
base::TimeDelta::FromMilliseconds(0));
}
- RunnerDelegate delegate;
- scoped_ptr<Runner> runner;
+ ShellRunnerDelegate delegate;
+ scoped_ptr<ShellRunner> runner;
Runner::Scope scope;
Handle<TimerModule> timer_module;
Handle<Result> result;
diff --git a/gin/object_template_builder.cc b/gin/object_template_builder.cc
index 8bc271450a..603166cfab 100644
--- a/gin/object_template_builder.cc
+++ b/gin/object_template_builder.cc
@@ -3,10 +3,133 @@
// found in the LICENSE file.
#include "gin/object_template_builder.h"
+
+#include "gin/interceptor.h"
+#include "gin/per_isolate_data.h"
#include "gin/public/wrapper_info.h"
namespace gin {
+namespace {
+
+WrappableBase* WrappableFromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val) {
+ 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.
+ if (!info)
+ return NULL;
+
+ // We don't further validate the type of the object, but assume it's derived
+ // from WrappableBase. We look up the pointer in a global registry, to make
+ // sure it's actually pointed to a valid life object.
+ return static_cast<WrappableBase*>(
+ obj->GetAlignedPointerFromInternalField(kEncodedValueIndex));
+}
+
+NamedPropertyInterceptor* NamedInterceptorFromV8(v8::Isolate* isolate,
+ v8::Handle<v8::Value> val) {
+ WrappableBase* base = WrappableFromV8(isolate, val);
+ if (!base)
+ return NULL;
+ return PerIsolateData::From(isolate)->GetNamedPropertyInterceptor(base);
+}
+
+IndexedPropertyInterceptor* IndexedInterceptorFromV8(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Value> val) {
+ WrappableBase* base = WrappableFromV8(isolate, val);
+ if (!base)
+ return NULL;
+ return PerIsolateData::From(isolate)->GetIndexedPropertyInterceptor(base);
+}
+
+void NamedPropertyGetter(v8::Local<v8::String> property,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ NamedPropertyInterceptor* interceptor =
+ NamedInterceptorFromV8(isolate, info.Holder());
+ if (!interceptor)
+ return;
+ std::string name;
+ ConvertFromV8(isolate, property, &name);
+ info.GetReturnValue().Set(interceptor->GetNamedProperty(isolate, name));
+}
+
+void NamedPropertySetter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ NamedPropertyInterceptor* interceptor =
+ NamedInterceptorFromV8(isolate, info.Holder());
+ if (!interceptor)
+ return;
+ std::string name;
+ ConvertFromV8(isolate, property, &name);
+ interceptor->SetNamedProperty(isolate, name, value);
+}
+
+void NamedPropertyQuery(v8::Local<v8::String> property,
+ const v8::PropertyCallbackInfo<v8::Integer>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ NamedPropertyInterceptor* interceptor =
+ NamedInterceptorFromV8(isolate, info.Holder());
+ if (!interceptor)
+ return;
+ std::string name;
+ ConvertFromV8(isolate, property, &name);
+ if (interceptor->GetNamedProperty(isolate, name).IsEmpty())
+ return;
+ info.GetReturnValue().Set(0);
+}
+
+void NamedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ NamedPropertyInterceptor* interceptor =
+ NamedInterceptorFromV8(isolate, info.Holder());
+ if (!interceptor)
+ return;
+ info.GetReturnValue().Set(v8::Handle<v8::Array>::Cast(
+ ConvertToV8(isolate, interceptor->EnumerateNamedProperties(isolate))));
+}
+
+void IndexedPropertyGetter(uint32_t index,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ IndexedPropertyInterceptor* interceptor =
+ IndexedInterceptorFromV8(isolate, info.Holder());
+ if (!interceptor)
+ return;
+ info.GetReturnValue().Set(interceptor->GetIndexedProperty(isolate, index));
+}
+
+void IndexedPropertySetter(uint32_t index,
+ v8::Local<v8::Value> value,
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ IndexedPropertyInterceptor* interceptor =
+ IndexedInterceptorFromV8(isolate, info.Holder());
+ if (!interceptor)
+ return;
+ interceptor->SetIndexedProperty(isolate, index, value);
+}
+
+void IndexedPropertyEnumerator(
+ const v8::PropertyCallbackInfo<v8::Array>& info) {
+ v8::Isolate* isolate = info.GetIsolate();
+ IndexedPropertyInterceptor* interceptor =
+ IndexedInterceptorFromV8(isolate, info.Holder());
+ if (!interceptor)
+ return;
+ info.GetReturnValue().Set(v8::Handle<v8::Array>::Cast(
+ ConvertToV8(isolate, interceptor->EnumerateIndexedProperties(isolate))));
+}
+
+} // namespace
+
ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate)
: isolate_(isolate), template_(v8::ObjectTemplate::New(isolate)) {
template_->SetInternalFieldCount(kNumberOfInternalFields);
@@ -15,6 +138,24 @@ ObjectTemplateBuilder::ObjectTemplateBuilder(v8::Isolate* isolate)
ObjectTemplateBuilder::~ObjectTemplateBuilder() {
}
+ObjectTemplateBuilder& ObjectTemplateBuilder::AddNamedPropertyInterceptor() {
+ template_->SetNamedPropertyHandler(&NamedPropertyGetter,
+ &NamedPropertySetter,
+ &NamedPropertyQuery,
+ NULL,
+ &NamedPropertyEnumerator);
+ return *this;
+}
+
+ObjectTemplateBuilder& ObjectTemplateBuilder::AddIndexedPropertyInterceptor() {
+ template_->SetIndexedPropertyHandler(&IndexedPropertyGetter,
+ &IndexedPropertySetter,
+ NULL,
+ NULL,
+ &IndexedPropertyEnumerator);
+ return *this;
+}
+
ObjectTemplateBuilder& ObjectTemplateBuilder::SetImpl(
const base::StringPiece& name, v8::Handle<v8::Data> val) {
template_->Set(StringToSymbol(isolate_, name), val);
diff --git a/gin/object_template_builder.h b/gin/object_template_builder.h
index 6367b71245..3d025a9deb 100644
--- a/gin/object_template_builder.h
+++ b/gin/object_template_builder.h
@@ -27,6 +27,11 @@ struct CallbackTraits {
T callback) {
return CreateFunctionTemplate(isolate, base::Bind(callback));
}
+ static void SetAsFunctionHandler(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> tmpl,
+ T callback) {
+ CreateFunctionHandler(isolate, tmpl, base::Bind(callback));
+ }
};
// Specialization for base::Callback.
@@ -36,6 +41,11 @@ struct CallbackTraits<base::Callback<T> > {
v8::Isolate* isolate, const base::Callback<T>& callback) {
return CreateFunctionTemplate(isolate, callback);
}
+ static void SetAsFunctionHandler(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> tmpl,
+ const base::Callback<T>& callback) {
+ CreateFunctionHandler(isolate, tmpl, callback);
+ }
};
// Specialization for member function pointers. We need to handle this case
@@ -50,6 +60,12 @@ struct CallbackTraits<T, typename base::enable_if<
return CreateFunctionTemplate(isolate, base::Bind(callback),
HolderIsFirstArgument);
}
+ static void SetAsFunctionHandler(v8::Isolate* isolate,
+ v8::Local<v8::ObjectTemplate> tmpl,
+ T callback) {
+ CreateFunctionHandler(
+ isolate, tmpl, base::Bind(callback), HolderIsFirstArgument);
+ }
};
// This specialization allows people to construct function templates directly if
@@ -103,6 +119,13 @@ class GIN_EXPORT ObjectTemplateBuilder {
CallbackTraits<T>::CreateTemplate(isolate_, getter),
CallbackTraits<U>::CreateTemplate(isolate_, setter));
}
+ template<typename T>
+ ObjectTemplateBuilder& SetCallAsFunctionHandler(const T& callback) {
+ CallbackTraits<T>::SetAsFunctionHandler(isolate_, template_, callback);
+ return *this;
+ }
+ ObjectTemplateBuilder& AddNamedPropertyInterceptor();
+ ObjectTemplateBuilder& AddIndexedPropertyInterceptor();
v8::Local<v8::ObjectTemplate> Build();
diff --git a/gin/per_context_data.cc b/gin/per_context_data.cc
index 5183d00102..178c0d122c 100644
--- a/gin/per_context_data.cc
+++ b/gin/per_context_data.cc
@@ -10,43 +10,24 @@
namespace gin {
-ContextSupplement::ContextSupplement() {
-}
-
-ContextSupplement::~ContextSupplement() {
-}
-
-PerContextData::PerContextData(v8::Handle<v8::Context> context)
- : runner_(NULL) {
+PerContextData::PerContextData(ContextHolder* context_holder,
+ v8::Handle<v8::Context> context)
+ : context_holder_(context_holder),
+ 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(
+ v8::HandleScope handle_scope(context_holder_->isolate());
+ context_holder_->context()->SetAlignedPointerInEmbedderData(
kPerContextDataStartIndex + kEmbedderNativeGin, NULL);
-
- SuplementVector supplements;
- supplements.swap(supplements_);
-
- for (SuplementVector::iterator it = supplements.begin();
- it != supplements.end(); ++it) {
- (*it)->Detach(context);
- }
}
+// static
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/gin/per_context_data.h b/gin/per_context_data.h
index 3ad68d2d37..0d1165345d 100644
--- a/gin/per_context_data.h
+++ b/gin/per_context_data.h
@@ -6,53 +6,39 @@
#define GIN_PER_CONTEXT_DATA_H_
#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
+#include "base/supports_user_data.h"
#include "gin/gin_export.h"
#include "v8/include/v8.h"
namespace gin {
+class ContextHolder;
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 {
+// class stores all the Gin-related data that varies per context. Arbitrary data
+// can be associated with this class by way of the SupportsUserData methods.
+// Instances of this class (and any associated user data) are destroyed before
+// the associated v8::Context.
+class GIN_EXPORT PerContextData : public base::SupportsUserData {
public:
- explicit PerContextData(v8::Handle<v8::Context> context);
- ~PerContextData();
+ PerContextData(ContextHolder* context_holder,
+ v8::Handle<v8::Context> context);
+ virtual ~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);
+ static PerContextData* From(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);
+ ContextHolder* context_holder() { return context_holder_; }
private:
- typedef ScopedVector<ContextSupplement> SuplementVector;
-
+ ContextHolder* context_holder_;
Runner* runner_;
- SuplementVector supplements_;
DISALLOW_COPY_AND_ASSIGN(PerContextData);
};
diff --git a/gin/per_context_data_unittest.cc b/gin/per_context_data_unittest.cc
new file mode 100644
index 0000000000..4d79587195
--- /dev/null
+++ b/gin/per_context_data_unittest.cc
@@ -0,0 +1,34 @@
+// Copyright 2014 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 "gin/public/context_holder.h"
+#include "gin/public/isolate_holder.h"
+#include "gin/test/v8_test.h"
+#include "v8/include/v8.h"
+
+namespace gin {
+
+typedef V8Test PerContextDataTest;
+
+// Verifies PerContextData can be looked up by context and that it is not
+// available once ContextHolder is destroyed.
+TEST_F(PerContextDataTest, LookupAndDestruction) {
+ v8::Isolate::Scope isolate_scope(instance_->isolate());
+ v8::HandleScope handle_scope(instance_->isolate());
+ v8::Handle<v8::Context> context = v8::Context::New(
+ instance_->isolate(), NULL, v8::Handle<v8::ObjectTemplate>());
+ {
+ ContextHolder context_holder(instance_->isolate());
+ context_holder.SetContext(context);
+ PerContextData* per_context_data = PerContextData::From(context);
+ EXPECT_TRUE(per_context_data != NULL);
+ EXPECT_EQ(&context_holder, per_context_data->context_holder());
+ }
+ PerContextData* per_context_data = PerContextData::From(context);
+ EXPECT_TRUE(per_context_data == NULL);
+}
+
+} // namespace gin
diff --git a/gin/per_isolate_data.cc b/gin/per_isolate_data.cc
index 6c2397ba50..b3f24abe00 100644
--- a/gin/per_isolate_data.cc
+++ b/gin/per_isolate_data.cc
@@ -2,9 +2,11 @@
// 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/per_isolate_data.h"
#include "gin/public/gin_embedders.h"
+using v8::ArrayBuffer;
using v8::Eternal;
using v8::Isolate;
using v8::Local;
@@ -14,8 +16,9 @@ using v8::ObjectTemplate;
namespace gin {
-PerIsolateData::PerIsolateData(Isolate* isolate)
- : isolate_(isolate) {
+PerIsolateData::PerIsolateData(Isolate* isolate,
+ ArrayBuffer::Allocator* allocator)
+ : isolate_(isolate), allocator_(allocator) {
isolate_->SetData(kEmbedderNativeGin, this);
}
@@ -53,4 +56,54 @@ v8::Local<v8::FunctionTemplate> PerIsolateData::GetFunctionTemplate(
return it->second.Get(isolate_);
}
+void PerIsolateData::SetIndexedPropertyInterceptor(
+ WrappableBase* base,
+ IndexedPropertyInterceptor* interceptor) {
+ indexed_interceptors_[base] = interceptor;
+}
+
+void PerIsolateData::SetNamedPropertyInterceptor(
+ WrappableBase* base,
+ NamedPropertyInterceptor* interceptor) {
+ named_interceptors_[base] = interceptor;
+}
+
+void PerIsolateData::ClearIndexedPropertyInterceptor(
+ WrappableBase* base,
+ IndexedPropertyInterceptor* interceptor) {
+ IndexedPropertyInterceptorMap::iterator it = indexed_interceptors_.find(base);
+ if (it != indexed_interceptors_.end())
+ indexed_interceptors_.erase(it);
+ else
+ NOTREACHED();
+}
+
+void PerIsolateData::ClearNamedPropertyInterceptor(
+ WrappableBase* base,
+ NamedPropertyInterceptor* interceptor) {
+ NamedPropertyInterceptorMap::iterator it = named_interceptors_.find(base);
+ if (it != named_interceptors_.end())
+ named_interceptors_.erase(it);
+ else
+ NOTREACHED();
+}
+
+IndexedPropertyInterceptor* PerIsolateData::GetIndexedPropertyInterceptor(
+ WrappableBase* base) {
+ IndexedPropertyInterceptorMap::iterator it = indexed_interceptors_.find(base);
+ if (it != indexed_interceptors_.end())
+ return it->second;
+ else
+ return NULL;
+}
+
+NamedPropertyInterceptor* PerIsolateData::GetNamedPropertyInterceptor(
+ WrappableBase* base) {
+ NamedPropertyInterceptorMap::iterator it = named_interceptors_.find(base);
+ if (it != named_interceptors_.end())
+ return it->second;
+ else
+ return NULL;
+}
+
} // namespace gin
diff --git a/gin/per_isolate_data.h b/gin/per_isolate_data.h
index ed93545474..fbdbca7e0e 100644
--- a/gin/per_isolate_data.h
+++ b/gin/per_isolate_data.h
@@ -14,11 +14,15 @@
namespace gin {
+class IndexedPropertyInterceptor;
+class NamedPropertyInterceptor;
+class WrappableBase;
+
// 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(v8::Isolate* isolate, v8::ArrayBuffer::Allocator* allocator);
~PerIsolateData();
static PerIsolateData* From(v8::Isolate* isolate);
@@ -38,19 +42,43 @@ class GIN_EXPORT PerIsolateData {
v8::Local<v8::ObjectTemplate> GetObjectTemplate(WrapperInfo* info);
v8::Local<v8::FunctionTemplate> GetFunctionTemplate(WrapperInfo* info);
+ // We maintain a map from Wrappable objects that derive from one of the
+ // interceptor interfaces to the interceptor interface pointers.
+ void SetIndexedPropertyInterceptor(WrappableBase* base,
+ IndexedPropertyInterceptor* interceptor);
+ void SetNamedPropertyInterceptor(WrappableBase* base,
+ NamedPropertyInterceptor* interceptor);
+
+ void ClearIndexedPropertyInterceptor(WrappableBase* base,
+ IndexedPropertyInterceptor* interceptor);
+ void ClearNamedPropertyInterceptor(WrappableBase* base,
+ NamedPropertyInterceptor* interceptor);
+
+ IndexedPropertyInterceptor* GetIndexedPropertyInterceptor(
+ WrappableBase* base);
+ NamedPropertyInterceptor* GetNamedPropertyInterceptor(WrappableBase* base);
+
v8::Isolate* isolate() { return isolate_; }
+ v8::ArrayBuffer::Allocator* allocator() { return allocator_; }
private:
typedef std::map<
WrapperInfo*, v8::Eternal<v8::ObjectTemplate> > ObjectTemplateMap;
typedef std::map<
WrapperInfo*, v8::Eternal<v8::FunctionTemplate> > FunctionTemplateMap;
+ typedef std::map<WrappableBase*, IndexedPropertyInterceptor*>
+ IndexedPropertyInterceptorMap;
+ typedef std::map<WrappableBase*, NamedPropertyInterceptor*>
+ NamedPropertyInterceptorMap;
// PerIsolateData doesn't actually own |isolate_|. Instead, the isolate is
// owned by the IsolateHolder, which also owns the PerIsolateData.
v8::Isolate* isolate_;
+ v8::ArrayBuffer::Allocator* allocator_;
ObjectTemplateMap object_templates_;
FunctionTemplateMap function_templates_;
+ IndexedPropertyInterceptorMap indexed_interceptors_;
+ NamedPropertyInterceptorMap named_interceptors_;
DISALLOW_COPY_AND_ASSIGN(PerIsolateData);
};
diff --git a/gin/public/context_holder.h b/gin/public/context_holder.h
index f8f0c4727a..afbcf23d73 100644
--- a/gin/public/context_holder.h
+++ b/gin/public/context_holder.h
@@ -25,9 +25,7 @@ enum ContextEmbedderDataFields {
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.
+// ContextHolder is a generic class for holding a v8::Context.
class GIN_EXPORT ContextHolder {
public:
explicit ContextHolder(v8::Isolate* isolate);
diff --git a/gin/public/isolate_holder.h b/gin/public/isolate_holder.h
index d68e4d5a58..eebafa7bcf 100644
--- a/gin/public/isolate_holder.h
+++ b/gin/public/isolate_holder.h
@@ -8,10 +8,7 @@
#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
#include "gin/gin_export.h"
-
-namespace v8 {
-class Isolate;
-}
+#include "v8/include/v8.h"
namespace gin {
@@ -30,14 +27,14 @@ class PerIsolateData;
class GIN_EXPORT IsolateHolder {
public:
IsolateHolder();
- explicit IsolateHolder(v8::Isolate* isolate);
+ IsolateHolder(v8::Isolate* isolate, v8::ArrayBuffer::Allocator* allocator);
~IsolateHolder();
v8::Isolate* isolate() { return isolate_; }
private:
- void Init();
+ void Init(v8::ArrayBuffer::Allocator* allocator);
bool isolate_owner_;
v8::Isolate* isolate_;
diff --git a/gin/runner.cc b/gin/runner.cc
index e8e4089d5f..6f018b165b 100644
--- a/gin/runner.cc
+++ b/gin/runner.cc
@@ -4,106 +4,18 @@
#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) {
- CHECK(false) << try_catch.GetStackTrace();
-}
-
-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() : weak_factory_(this) {
}
Runner::~Runner() {
}
-void Runner::Run(const std::string& source, const std::string& resource_name) {
- TryCatch try_catch;
- v8::Handle<Script> script = Script::New(StringToV8(isolate(), source),
- StringToV8(isolate(), resource_name));
- if (try_catch.HasCaught()) {
- delegate_->UnhandledException(this, try_catch);
- return;
- }
-
- Run(script);
-}
-
-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()) {
+ : isolate_scope_(runner->GetContextHolder()->isolate()),
+ handle_scope_(runner->GetContextHolder()->isolate()),
+ scope_(runner->GetContextHolder()->context()) {
}
Runner::Scope::~Scope() {
diff --git a/gin/runner.h b/gin/runner.h
index 943bcedba1..36a75d2f95 100644
--- a/gin/runner.h
+++ b/gin/runner.h
@@ -10,47 +10,28 @@
#include "base/memory/weak_ptr.h"
#include "gin/gin_export.h"
#include "gin/public/context_holder.h"
+#include "v8/include/v8.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 {
+// Runner is responsible for running code in a v8::Context.
+class GIN_EXPORT Runner {
public:
- Runner(RunnerDelegate* delegate, v8::Isolate* isolate);
- ~Runner();
+ Runner();
+ virtual ~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();
+ virtual void Run(const std::string& source,
+ const std::string& resource_name) = 0;
+ virtual v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
+ v8::Handle<v8::Value> receiver,
+ int argc,
+ v8::Handle<v8::Value> argv[]) = 0;
+ virtual ContextHolder* GetContextHolder() = 0;
+
+ v8::Handle<v8::Object> global() {
+ return GetContextHolder()->context()->Global();
}
// Useful for running script in this context asynchronously. Rather than
@@ -75,8 +56,6 @@ class GIN_EXPORT Runner : public ContextHolder {
private:
friend class Scope;
- RunnerDelegate* delegate_;
-
base::WeakPtrFactory<Runner> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(Runner);
diff --git a/gin/shell/gin_main.cc b/gin/shell/gin_main.cc
index 0ff52cc229..6673b6a685 100644
--- a/gin/shell/gin_main.cc
+++ b/gin/shell/gin_main.cc
@@ -33,7 +33,7 @@ void Run(base::WeakPtr<Runner> runner, const base::FilePath& path) {
std::vector<base::FilePath> GetModuleSearchPaths() {
std::vector<base::FilePath> module_base(1);
- CHECK(file_util::GetCurrentDirectory(&module_base[0]));
+ CHECK(base::GetCurrentDirectory(&module_base[0]));
return module_base;
}
@@ -43,7 +43,7 @@ class ShellRunnerDelegate : public ModuleRunnerDelegate {
AddBuiltinModule(Console::kModuleName, Console::GetModule);
}
- virtual void UnhandledException(Runner* runner,
+ virtual void UnhandledException(ShellRunner* runner,
TryCatch& try_catch) OVERRIDE {
ModuleRunnerDelegate::UnhandledException(runner, try_catch);
LOG(ERROR) << try_catch.GetStackTrace();
@@ -66,7 +66,7 @@ int main(int argc, char** argv) {
base::MessageLoop message_loop;
gin::ShellRunnerDelegate delegate;
- gin::Runner runner(&delegate, instance.isolate());
+ gin::ShellRunner runner(&delegate, instance.isolate());
{
gin::Runner::Scope scope(&runner);
diff --git a/gin/shell_runner.cc b/gin/shell_runner.cc
new file mode 100644
index 0000000000..8d98e425d7
--- /dev/null
+++ b/gin/shell_runner.cc
@@ -0,0 +1,112 @@
+// Copyright 2014 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/shell_runner.h"
+
+#include "gin/converter.h"
+#include "gin/modules/module_registry.h"
+#include "gin/per_context_data.h"
+#include "gin/public/context_holder.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 {
+
+ShellRunnerDelegate::ShellRunnerDelegate() {
+}
+
+ShellRunnerDelegate::~ShellRunnerDelegate() {
+}
+
+v8::Handle<ObjectTemplate> ShellRunnerDelegate::GetGlobalTemplate(
+ ShellRunner* runner,
+ v8::Isolate* isolate) {
+ return v8::Handle<ObjectTemplate>();
+}
+
+void ShellRunnerDelegate::DidCreateContext(ShellRunner* runner) {
+}
+
+void ShellRunnerDelegate::WillRunScript(ShellRunner* runner) {
+}
+
+void ShellRunnerDelegate::DidRunScript(ShellRunner* runner) {
+}
+
+void ShellRunnerDelegate::UnhandledException(ShellRunner* runner,
+ TryCatch& try_catch) {
+ CHECK(false) << try_catch.GetStackTrace();
+}
+
+ShellRunner::ShellRunner(ShellRunnerDelegate* delegate, Isolate* isolate)
+ : delegate_(delegate) {
+ v8::Isolate::Scope isolate_scope(isolate);
+ HandleScope handle_scope(isolate);
+ v8::Handle<v8::Context> context =
+ Context::New(isolate, NULL, delegate_->GetGlobalTemplate(this, isolate));
+
+ context_holder_.reset(new ContextHolder(isolate));
+ context_holder_->SetContext(context);
+ PerContextData::From(context)->set_runner(this);
+
+ v8::Context::Scope scope(context);
+ delegate_->DidCreateContext(this);
+}
+
+ShellRunner::~ShellRunner() {
+}
+
+void ShellRunner::Run(const std::string& source,
+ const std::string& resource_name) {
+ TryCatch try_catch;
+ v8::Isolate* isolate = GetContextHolder()->isolate();
+ v8::Handle<Script> script = Script::Compile(
+ StringToV8(isolate, source), StringToV8(isolate, resource_name));
+ if (try_catch.HasCaught()) {
+ delegate_->UnhandledException(this, try_catch);
+ return;
+ }
+
+ Run(script);
+}
+
+v8::Handle<v8::Value> ShellRunner::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;
+}
+
+ContextHolder* ShellRunner::GetContextHolder() {
+ return context_holder_.get();
+}
+
+void ShellRunner::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);
+ }
+}
+
+} // namespace gin
diff --git a/gin/shell_runner.h b/gin/shell_runner.h
new file mode 100644
index 0000000000..645bc8e6df
--- /dev/null
+++ b/gin/shell_runner.h
@@ -0,0 +1,68 @@
+// Copyright 2014 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_SHELL_RUNNER_H_
+#define GIN_SHELL_RUNNER_H_
+
+#include "gin/runner.h"
+
+namespace gin {
+
+class ContextHolder;
+class ShellRunner;
+class TryCatch;
+
+// Subclass ShellRunnerDelegate to customize the behavior of ShellRunner.
+// Typical embedders will want to subclass one of the specialized
+// ShellRunnerDelegates, such as ModuleRunnerDelegate.
+class GIN_EXPORT ShellRunnerDelegate {
+ public:
+ ShellRunnerDelegate();
+ virtual ~ShellRunnerDelegate();
+
+ // Returns the template for the global object.
+ virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(
+ ShellRunner* runner,
+ v8::Isolate* isolate);
+ virtual void DidCreateContext(ShellRunner* runner);
+ virtual void WillRunScript(ShellRunner* runner);
+ virtual void DidRunScript(ShellRunner* runner);
+ virtual void UnhandledException(ShellRunner* runner, TryCatch& try_catch);
+};
+
+// ShellRunner executes the script/functions directly in a v8::Context.
+// ShellRunner owns a ContextHolder and v8::Context, both of which are destroyed
+// when the ShellRunner is deleted.
+class GIN_EXPORT ShellRunner : public Runner {
+ public:
+ ShellRunner(ShellRunnerDelegate* delegate, v8::Isolate* isolate);
+ virtual ~ShellRunner();
+
+ // 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.
+
+ // Runner overrides:
+ virtual void Run(const std::string& source,
+ const std::string& resource_name) OVERRIDE;
+ virtual v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
+ v8::Handle<v8::Value> receiver,
+ int argc,
+ v8::Handle<v8::Value> argv[]) OVERRIDE;
+ virtual ContextHolder* GetContextHolder() OVERRIDE;
+
+ private:
+ friend class Scope;
+
+ void Run(v8::Handle<v8::Script> script);
+
+ ShellRunnerDelegate* delegate_;
+
+ scoped_ptr<ContextHolder> context_holder_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShellRunner);
+};
+
+} // namespace gin
+
+#endif // GIN_SHELL_RUNNER_H_
diff --git a/gin/runner_unittest.cc b/gin/shell_runner_unittest.cc
index 3723956df6..93c071fc1e 100644
--- a/gin/runner_unittest.cc
+++ b/gin/shell_runner_unittest.cc
@@ -1,8 +1,8 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 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/shell_runner.h"
#include "base/compiler_specific.h"
#include "gin/converter.h"
@@ -21,9 +21,9 @@ TEST(RunnerTest, Run) {
gin::IsolateHolder instance;
- RunnerDelegate delegate;
+ ShellRunnerDelegate delegate;
Isolate* isolate = instance.isolate();
- Runner runner(&delegate, isolate);
+ ShellRunner runner(&delegate, isolate);
Runner::Scope scope(&runner);
runner.Run(source, "test_data.js");
diff --git a/gin/test/file_runner.cc b/gin/test/file_runner.cc
index 7b9127368d..86cb2f34b8 100644
--- a/gin/test/file_runner.cc
+++ b/gin/test/file_runner.cc
@@ -10,6 +10,7 @@
#include "gin/converter.h"
#include "gin/modules/console.h"
#include "gin/modules/module_registry.h"
+#include "gin/public/context_holder.h"
#include "gin/public/isolate_holder.h"
#include "gin/test/gtest.h"
#include "gin/try_catch.h"
@@ -38,7 +39,7 @@ FileRunnerDelegate::FileRunnerDelegate()
FileRunnerDelegate::~FileRunnerDelegate() {
}
-void FileRunnerDelegate::UnhandledException(Runner* runner,
+void FileRunnerDelegate::UnhandledException(ShellRunner* runner,
TryCatch& try_catch) {
ModuleRunnerDelegate::UnhandledException(runner, try_catch);
FAIL() << try_catch.GetStackTrace();
@@ -53,7 +54,7 @@ void RunTestFromFile(const base::FilePath& path, FileRunnerDelegate* delegate,
base::MessageLoop message_loop;
gin::IsolateHolder instance;
- gin::Runner runner(delegate, instance.isolate());
+ gin::ShellRunner runner(delegate, instance.isolate());
{
gin::Runner::Scope scope(&runner);
v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
@@ -65,8 +66,8 @@ void RunTestFromFile(const base::FilePath& path, FileRunnerDelegate* delegate,
message_loop.Run();
}
- v8::Handle<v8::Value> result = runner.context()->Global()->Get(
- StringToSymbol(runner.isolate(), "result"));
+ v8::Handle<v8::Value> result = runner.global()->Get(
+ StringToSymbol(runner.GetContextHolder()->isolate(), "result"));
EXPECT_EQ("PASS", V8ToString(result));
}
}
diff --git a/gin/test/file_runner.h b/gin/test/file_runner.h
index 267023d8f0..f248fb59fa 100644
--- a/gin/test/file_runner.h
+++ b/gin/test/file_runner.h
@@ -24,7 +24,8 @@ class FileRunnerDelegate : public ModuleRunnerDelegate {
private:
// From ModuleRunnerDelegate:
- virtual void UnhandledException(Runner* runner, TryCatch& try_catch) OVERRIDE;
+ virtual void UnhandledException(ShellRunner* runner,
+ TryCatch& try_catch) OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(FileRunnerDelegate);
};
diff --git a/gin/wrappable.cc b/gin/wrappable.cc
index 8d41ce06c4..a330fefc8e 100644
--- a/gin/wrappable.cc
+++ b/gin/wrappable.cc
@@ -44,6 +44,14 @@ v8::Handle<v8::Object> WrappableBase::GetWrapperImpl(v8::Isolate* isolate,
}
CHECK_EQ(kNumberOfInternalFields, templ->InternalFieldCount());
v8::Handle<v8::Object> wrapper = templ->NewInstance();
+ // |wrapper| may be empty in some extreme cases, e.g., when
+ // Object.prototype.constructor is overwritten.
+ if (wrapper.IsEmpty()) {
+ // The current wrappable object will be no longer managed by V8. Delete this
+ // now.
+ delete this;
+ return wrapper;
+ }
wrapper->SetAlignedPointerInInternalField(kWrapperInfoIndex, info);
wrapper->SetAlignedPointerInInternalField(kEncodedValueIndex, this);
wrapper_.Reset(isolate, wrapper);
diff --git a/gin/wrappable_unittest.cc b/gin/wrappable_unittest.cc
index 09fef241ab..4916153be5 100644
--- a/gin/wrappable_unittest.cc
+++ b/gin/wrappable_unittest.cc
@@ -74,6 +74,36 @@ class MyObjectSubclass : public MyObject {
}
};
+class MyCallableObject : public Wrappable<MyCallableObject> {
+ public:
+ static WrapperInfo kWrapperInfo;
+
+ static gin::Handle<MyCallableObject> Create(v8::Isolate* isolate) {
+ return CreateHandle(isolate, new MyCallableObject());
+ }
+
+ int result() { return result_; }
+
+ private:
+ virtual ObjectTemplateBuilder GetObjectTemplateBuilder(
+ v8::Isolate* isolate) OVERRIDE {
+ return Wrappable<MyCallableObject>::GetObjectTemplateBuilder(isolate)
+ .SetCallAsFunctionHandler(&MyCallableObject::Call);
+ }
+
+ MyCallableObject() : result_(0) {
+ }
+
+ virtual ~MyCallableObject() {
+ }
+
+ void Call(int val) {
+ result_ = val;
+ }
+
+ int result_;
+};
+
class MyObject2 : public Wrappable<MyObject2> {
public:
static WrapperInfo kWrapperInfo;
@@ -90,6 +120,7 @@ ObjectTemplateBuilder MyObject::GetObjectTemplateBuilder(v8::Isolate* isolate) {
.SetProperty("value", &MyObject::value, &MyObject::set_value);
}
+WrapperInfo MyCallableObject::kWrapperInfo = { kEmbedderNativeGin };
WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin };
WrapperInfo MyObjectBlink::kWrapperInfo = { kEmbedderNativeGin };
@@ -153,7 +184,7 @@ TEST_F(WrappableTest, GetAndSetProperty) {
EXPECT_FALSE(source.IsEmpty());
gin::TryCatch try_catch;
- v8::Handle<v8::Script> script = v8::Script::New(source);
+ v8::Handle<v8::Script> script = v8::Script::Compile(source);
EXPECT_FALSE(script.IsEmpty());
v8::Handle<v8::Value> val = script->Run();
EXPECT_FALSE(val.IsEmpty());
@@ -179,7 +210,7 @@ TEST_F(WrappableTest, WrappableSubclass) {
"obj.sayHello('Lily');"
"})");
gin::TryCatch try_catch;
- v8::Handle<v8::Script> script = v8::Script::New(source);
+ v8::Handle<v8::Script> script = v8::Script::Compile(source);
v8::Handle<v8::Value> val = script->Run();
v8::Handle<v8::Function> func;
EXPECT_TRUE(ConvertFromV8(isolate, val, &func));
@@ -191,4 +222,49 @@ TEST_F(WrappableTest, WrappableSubclass) {
EXPECT_EQ("Hello, Lily", object->result);
}
+TEST_F(WrappableTest, ErrorInObjectConstructorProperty) {
+ v8::Isolate* isolate = instance_->isolate();
+ v8::HandleScope handle_scope(isolate);
+
+ v8::Handle<v8::String> source = StringToV8(
+ isolate,
+ "(function() {"
+ " Object.defineProperty(Object.prototype, 'constructor', {"
+ " get: function() { throw 'Error'; },"
+ " set: function() { throw 'Error'; }"
+ " });"
+ "})();");
+ EXPECT_FALSE(source.IsEmpty());
+ v8::Handle<v8::Script> script = v8::Script::Compile(source);
+ script->Run();
+
+ gin::TryCatch try_catch;
+ gin::Handle<MyObject> obj = MyObject::Create(isolate);
+ EXPECT_TRUE(obj.IsEmpty());
+ EXPECT_TRUE(try_catch.HasCaught());
+}
+
+TEST_F(WrappableTest, CallAsFunction) {
+ v8::Isolate* isolate = instance_->isolate();
+ v8::HandleScope handle_scope(isolate);
+
+ gin::Handle<MyCallableObject> object(MyCallableObject::Create(isolate));
+ EXPECT_EQ(0, object->result());
+ v8::Handle<v8::String> source = StringToV8(isolate,
+ "(function(obj) {"
+ "obj(42);"
+ "})");
+ gin::TryCatch try_catch;
+ v8::Handle<v8::Script> script = v8::Script::Compile(source);
+ v8::Handle<v8::Value> val = script->Run();
+ v8::Handle<v8::Function> func;
+ EXPECT_TRUE(ConvertFromV8(isolate, val, &func));
+ v8::Handle<v8::Value> argv[] = {
+ ConvertToV8(isolate, object.get())
+ };
+ func->Call(v8::Undefined(isolate), 1, argv);
+ EXPECT_FALSE(try_catch.HasCaught());
+ EXPECT_EQ(42, object->result());
+}
+
} // namespace gin