diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-03 13:42:47 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-15 10:27:51 +0000 |
commit | 8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (patch) | |
tree | d29d987c4d7b173cf853279b79a51598f104b403 /chromium/gin | |
parent | 830c9e163d31a9180fadca926b3e1d7dfffb5021 (diff) | |
download | qtwebengine-chromium-8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec.tar.gz |
BASELINE: Update Chromium to 66.0.3359.156
Change-Id: I0c9831ad39911a086b6377b16f995ad75a51e441
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/gin')
-rw-r--r-- | chromium/gin/BUILD.gn | 10 | ||||
-rw-r--r-- | chromium/gin/arguments_unittest.cc | 3 | ||||
-rw-r--r-- | chromium/gin/array_buffer.cc | 89 | ||||
-rw-r--r-- | chromium/gin/array_buffer.h | 4 | ||||
-rw-r--r-- | chromium/gin/array_buffer_unittest.cc | 90 | ||||
-rw-r--r-- | chromium/gin/converter.h | 36 | ||||
-rw-r--r-- | chromium/gin/converter_unittest.cc | 59 | ||||
-rw-r--r-- | chromium/gin/function_template.h | 14 | ||||
-rw-r--r-- | chromium/gin/interceptor_unittest.cc | 2 | ||||
-rw-r--r-- | chromium/gin/isolate_holder.cc | 97 | ||||
-rw-r--r-- | chromium/gin/object_template_builder.h | 5 | ||||
-rw-r--r-- | chromium/gin/public/isolate_holder.h | 21 | ||||
-rw-r--r-- | chromium/gin/public/v8_platform.h | 7 | ||||
-rw-r--r-- | chromium/gin/v8_initializer.cc | 101 | ||||
-rw-r--r-- | chromium/gin/v8_initializer.h | 25 | ||||
-rw-r--r-- | chromium/gin/v8_platform.cc | 98 | ||||
-rw-r--r-- | chromium/gin/wrappable.h | 5 | ||||
-rw-r--r-- | chromium/gin/wrappable_unittest.cc | 88 |
18 files changed, 291 insertions, 463 deletions
diff --git a/chromium/gin/BUILD.gn b/chromium/gin/BUILD.gn index 6b3a66391f1..2684e608fcb 100644 --- a/chromium/gin/BUILD.gn +++ b/chromium/gin/BUILD.gn @@ -7,13 +7,6 @@ import("//build/config/allocator.gni") import("//testing/test.gni") import("//v8/gni/v8.gni") -# "features" to avoid collision with existing gin_features.h file. -buildflag_header("features") { - header = "features.h" - - flags = [ "USE_PARTITION_ALLOC=$use_partition_alloc" ] -} - component("gin") { sources = [ "arguments.cc", @@ -87,7 +80,6 @@ component("gin") { defines = [ "GIN_IMPLEMENTATION" ] public_deps = [ - ":features", "//base", "//v8", ] @@ -158,6 +150,8 @@ test("gin_unittests") { ":gin_shell", ":gin_test", "//base/test:test_support", + "//testing/gmock", + "//testing/gtest", "//v8", ] diff --git a/chromium/gin/arguments_unittest.cc b/chromium/gin/arguments_unittest.cc index 75bb3ebb753..6b6809a5f74 100644 --- a/chromium/gin/arguments_unittest.cc +++ b/chromium/gin/arguments_unittest.cc @@ -74,8 +74,7 @@ TEST_F(ArgumentsTest, TestGetAll) { V8List list1 = { gin::ConvertToV8(isolate, 1), gin::StringToV8(isolate, "some string"), - gin::ConvertToV8(context, std::vector<double>({2.0, 3.0})) - .ToLocalChecked(), + gin::ConvertToV8(isolate, std::vector<double>({2.0, 3.0})), }; bool called1 = false; diff --git a/chromium/gin/array_buffer.cc b/chromium/gin/array_buffer.cc index 5d503e733b3..f84934bfd71 100644 --- a/chromium/gin/array_buffer.cc +++ b/chromium/gin/array_buffer.cc @@ -9,8 +9,8 @@ #include "base/allocator/partition_allocator/page_allocator.h" #include "base/logging.h" +#include "base/partition_alloc_buildflags.h" #include "build/build_config.h" -#include "gin/features.h" #include "gin/per_isolate_data.h" #if defined(OS_POSIX) @@ -43,89 +43,10 @@ void* ArrayBufferAllocator::AllocateUninitialized(size_t length) { return malloc(length); } -void* ArrayBufferAllocator::Reserve(size_t length) { -#if BUILDFLAG(USE_PARTITION_ALLOC) - const bool commit = false; - return base::AllocPages(nullptr, length, base::kPageAllocationGranularity, - base::PageInaccessible, commit); -#elif defined(OS_POSIX) - int const access_flag = PROT_NONE; - void* const ret = - mmap(nullptr, length, access_flag, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - if (ret == MAP_FAILED) { - return nullptr; - } - return ret; -#else - DWORD const access_flag = PAGE_NOACCESS; - return VirtualAlloc(hint, length, MEM_RESERVE, access_flag); -#endif -} - void ArrayBufferAllocator::Free(void* data, size_t length) { free(data); } -void ArrayBufferAllocator::Free(void* data, - size_t length, - AllocationMode mode) { - switch (mode) { - case AllocationMode::kNormal: - Free(data, length); - return; - case AllocationMode::kReservation: -#if BUILDFLAG(USE_PARTITION_ALLOC) - base::FreePages(data, length); -#elif defined(OS_POSIX) - CHECK(!munmap(data, length)); -#else - CHECK(VirtualFree(data, 0, MEM_RELEASE)); -#endif - return; - default: - NOTREACHED(); - } -} - -void ArrayBufferAllocator::SetProtection(void* data, - size_t length, - Protection protection) { -#if BUILDFLAG(USE_PARTITION_ALLOC) - switch (protection) { - case Protection::kNoAccess: - CHECK(base::SetSystemPagesAccess(data, length, base::PageInaccessible)); - break; - case Protection::kReadWrite: - CHECK(base::SetSystemPagesAccess(data, length, base::PageReadWrite)); - break; - default: - NOTREACHED(); - } -#elif defined(OS_POSIX) - switch (protection) { - case Protection::kNoAccess: - CHECK_EQ(0, mprotect(data, length, PROT_NONE)); - break; - case Protection::kReadWrite: - CHECK_EQ(0, mprotect(data, length, PROT_READ | PROT_WRITE)); - break; - default: - NOTREACHED(); - } -#else // !defined(OS_POSIX) - switch (protection) { - case Protection::kNoAccess: - CHECK_NE(0, VirtualFree(data, length, MEM_DECOMMIT)); - break; - case Protection::kReadWrite: - CHECK_NE(nullptr, VirtualAlloc(data, length, MEM_COMMIT, PAGE_READWRITE)); - break; - default: - NOTREACHED(); - } -#endif // !defined(OS_POSIX) -} - ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() { static ArrayBufferAllocator* instance = new ArrayBufferAllocator(); return instance; @@ -197,11 +118,13 @@ ArrayBuffer::Private::Private(v8::Isolate* isolate, // Take ownership of the array buffer. CHECK(!array->IsExternal()); v8::ArrayBuffer::Contents contents = array->Externalize(); + // We shouldn't receive large page-allocated array buffers. + CHECK_NE(v8::ArrayBuffer::Allocator::AllocationMode::kReservation, + contents.AllocationMode()); buffer_ = contents.Data(); length_ = contents.ByteLength(); allocation_base_ = contents.AllocationBase(); allocation_length_ = contents.AllocationLength(); - allocation_mode_ = contents.AllocationMode(); DCHECK(reinterpret_cast<uintptr_t>(allocation_base_) <= reinterpret_cast<uintptr_t>(buffer_)); @@ -218,8 +141,8 @@ ArrayBuffer::Private::Private(v8::Isolate* isolate, } ArrayBuffer::Private::~Private() { - PerIsolateData::From(isolate_)->allocator()->Free( - allocation_base_, allocation_length_, allocation_mode_); + PerIsolateData::From(isolate_)->allocator()->Free(allocation_base_, + allocation_length_); } void ArrayBuffer::Private::FirstWeakCallback( diff --git a/chromium/gin/array_buffer.h b/chromium/gin/array_buffer.h index 0b2b1ecfd91..2aef366ac81 100644 --- a/chromium/gin/array_buffer.h +++ b/chromium/gin/array_buffer.h @@ -21,11 +21,7 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { public: void* Allocate(size_t length) override; void* AllocateUninitialized(size_t length) override; - void* Reserve(size_t length) override; void Free(void* data, size_t length) override; - void Free(void* data, size_t length, AllocationMode mode) override; - - void SetProtection(void* data, size_t length, Protection protection) override; GIN_EXPORT static ArrayBufferAllocator* SharedInstance(); }; diff --git a/chromium/gin/array_buffer_unittest.cc b/chromium/gin/array_buffer_unittest.cc index 479808d52d0..b19ff7bcfb9 100644 --- a/chromium/gin/array_buffer_unittest.cc +++ b/chromium/gin/array_buffer_unittest.cc @@ -8,11 +8,6 @@ #include "gin/public/isolate_holder.h" #include "gin/test/v8_test.h" -#if defined(OS_POSIX) -#include <setjmp.h> -#include <signal.h> -#endif - namespace gin { using ArrayBufferTest = V8Test; @@ -21,94 +16,17 @@ namespace { const size_t kBufferLength = 65536; } +// Make sure we can allocate, access and free memory. TEST_F(ArrayBufferTest, AllocateAndFreeBuffer) { v8::Isolate* const isolate = instance_->isolate(); v8::ArrayBuffer::Allocator* const allocator = PerIsolateData::From(isolate)->allocator(); void* buffer = allocator->Allocate(kBufferLength); + char* buffer0 = reinterpret_cast<char*>(buffer); + *buffer0 = '0'; // ASCII zero + CHECK_EQ('0', *buffer0); allocator->Free(buffer, kBufferLength); } -TEST_F(ArrayBufferTest, ReserveAndReleaseBuffer) { - v8::Isolate* const isolate = instance_->isolate(); - v8::ArrayBuffer::Allocator* const allocator = - PerIsolateData::From(isolate)->allocator(); - - void* buffer = allocator->Reserve(kBufferLength); - allocator->Free(buffer, kBufferLength, - v8::ArrayBuffer::Allocator::AllocationMode::kReservation); -} - -TEST_F(ArrayBufferTest, SetProtectionReadWrite) { - v8::Isolate* const isolate = instance_->isolate(); - v8::ArrayBuffer::Allocator* const allocator = - PerIsolateData::From(isolate)->allocator(); - - void* buffer = allocator->Reserve(kBufferLength); - allocator->SetProtection(buffer, kBufferLength, - v8::ArrayBuffer::Allocator::Protection::kReadWrite); - volatile int* int_buffer = static_cast<volatile int*>(buffer); - // Try assigning to the buffer. This will fault if we don't SetProtection - // first. - int_buffer[0] = 42; - allocator->Free(buffer, kBufferLength, - v8::ArrayBuffer::Allocator::AllocationMode::kReservation); -} - -#if defined(OS_POSIX) - -namespace { -sigjmp_buf g_continuation_; - -void SignalHandler(int signal, siginfo_t* info, void*) { - siglongjmp(g_continuation_, 1); -} -} // namespace - -TEST_F(ArrayBufferTest, ReservationReadOnlyByDefault) { - v8::Isolate* const isolate = instance_->isolate(); - v8::ArrayBuffer::Allocator* const allocator = - PerIsolateData::From(isolate)->allocator(); - - void* buffer = allocator->Reserve(kBufferLength); - volatile int* int_buffer = static_cast<volatile int*>(buffer); - - // Install a signal handler so we can catch the fault we're about to trigger. - struct sigaction action = {}; - struct sigaction old_action = {}; - action.sa_sigaction = SignalHandler; - sigemptyset(&action.sa_mask); - action.sa_flags = SA_SIGINFO; - sigaction(SIGSEGV, &action, &old_action); -#if defined(OS_MACOSX) - // On Mac, sometimes we get SIGBUS instead of SIGSEGV. - struct sigaction old_bus_action; - sigaction(SIGBUS, &action, &old_bus_action); -#endif - - int const save_sigs = 1; - if (!sigsetjmp(g_continuation_, save_sigs)) { - // Try assigning to the buffer. This will fault if we don't SetProtection - // first. - int_buffer[0] = 42; - } else { - // if sigsetjmp returns nonzero, then we are returning from our handler. - - sigaction(SIGSEGV, &old_action, nullptr); -#if defined(OS_MACOSX) - sigaction(SIGBUS, &old_bus_action, nullptr); -#endif - - allocator->Free(buffer, kBufferLength, - v8::ArrayBuffer::Allocator::AllocationMode::kReservation); - SUCCEED(); - return; - } - - FAIL(); -} - -#endif // OS_POSIX - } // namespace gin diff --git a/chromium/gin/converter.h b/chromium/gin/converter.h index be48516e2a0..c47ec0af000 100644 --- a/chromium/gin/converter.h +++ b/chromium/gin/converter.h @@ -8,6 +8,7 @@ #include <stdint.h> #include <string> +#include <type_traits> #include <vector> #include "base/logging.h" @@ -163,15 +164,24 @@ struct GIN_EXPORT Converter<v8::Local<v8::Value> > { template<typename T> struct Converter<std::vector<T> > { - static v8::MaybeLocal<v8::Value> ToV8(v8::Local<v8::Context> context, - const std::vector<T>& val) { - v8::Isolate* isolate = context->GetIsolate(); + static std::conditional_t<ToV8ReturnsMaybe<T>::value, + v8::MaybeLocal<v8::Value>, + v8::Local<v8::Value>> + ToV8(v8::Isolate* isolate, const std::vector<T>& val) { + v8::Local<v8::Context> context = isolate->GetCurrentContext(); v8::Local<v8::Array> result( v8::Array::New(isolate, static_cast<int>(val.size()))); for (uint32_t i = 0; i < val.size(); ++i) { - auto maybe = result->Set(context, i, Converter<T>::ToV8(isolate, val[i])); - if (maybe.IsNothing() || !maybe.FromJust()) - return v8::MaybeLocal<v8::Value>(); + v8::MaybeLocal<v8::Value> maybe = Converter<T>::ToV8(isolate, val[i]); + v8::Local<v8::Value> element; + if (!maybe.ToLocal(&element)) + return {}; + bool property_created; + if (!result->CreateDataProperty(context, i, element) + .To(&property_created) || + !property_created) { + NOTREACHED() << "CreateDataProperty should always succeed here."; + } } return result; } @@ -202,20 +212,18 @@ struct Converter<std::vector<T> > { template<typename T> struct ToV8ReturnsMaybe<std::vector<T>> { - static const bool value = true; + static const bool value = ToV8ReturnsMaybe<T>::value; }; // Convenience functions that deduce T. -template<typename T> -v8::Local<v8::Value> ConvertToV8(v8::Isolate* isolate, T input) { +template <typename T> +std::conditional_t<ToV8ReturnsMaybe<T>::value, + v8::MaybeLocal<v8::Value>, + v8::Local<v8::Value>> +ConvertToV8(v8::Isolate* isolate, T input) { return Converter<T>::ToV8(isolate, input); } -template<typename T> -v8::MaybeLocal<v8::Value> ConvertToV8(v8::Local<v8::Context> context, T input) { - return Converter<T>::ToV8(context, input); -} - template<typename T, bool = ToV8ReturnsMaybe<T>::value> struct ToV8Traits; template <typename T> diff --git a/chromium/gin/converter_unittest.cc b/chromium/gin/converter_unittest.cc index a198f40c666..967ca13423f 100644 --- a/chromium/gin/converter_unittest.cc +++ b/chromium/gin/converter_unittest.cc @@ -9,8 +9,11 @@ #include <stdint.h> #include "base/compiler_specific.h" +#include "gin/handle.h" #include "gin/public/isolate_holder.h" #include "gin/test/v8_test.h" +#include "gin/wrappable.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "v8/include/v8.h" @@ -116,16 +119,58 @@ TEST_F(ConverterTest, Vector) { expected.push_back(0); expected.push_back(1); - auto maybe = Converter<std::vector<int>>::ToV8( - instance_->isolate()->GetCurrentContext(), expected); - Local<Value> js_value; - EXPECT_TRUE(maybe.ToLocal(&js_value)); - Local<Array> js_array2 = Local<Array>::Cast(js_value); - EXPECT_EQ(3u, js_array2->Length()); + auto js_array = + Converter<std::vector<int>>::ToV8(instance_->isolate(), expected) + .As<Array>(); + EXPECT_EQ(3u, js_array->Length()); for (size_t i = 0; i < expected.size(); ++i) { EXPECT_TRUE(Integer::New(instance_->isolate(), expected[i]) - ->StrictEquals(js_array2->Get(static_cast<int>(i)))); + ->StrictEquals(js_array->Get(static_cast<int>(i)))); } } +TEST_F(ConverterTest, VectorOfVectors) { + HandleScope handle_scope(instance_->isolate()); + + std::vector<std::vector<int>> vector_of_vectors = { + {1, 2, 3}, {4, 5, 6}, + }; + + v8::Local<v8::Value> v8_value = + ConvertToV8(instance_->isolate(), vector_of_vectors); + std::vector<std::vector<int>> out_value; + ASSERT_TRUE(ConvertFromV8(instance_->isolate(), v8_value, &out_value)); + EXPECT_THAT(out_value, testing::ContainerEq(vector_of_vectors)); +} + +namespace { + +class MyObject : public Wrappable<MyObject> { + public: + static WrapperInfo kWrapperInfo; + + static gin::Handle<MyObject> Create(v8::Isolate* isolate) { + return CreateHandle(isolate, new MyObject()); + } +}; + +WrapperInfo MyObject::kWrapperInfo = {kEmbedderNativeGin}; + +} // namespace + +TEST_F(ConverterTest, VectorOfWrappables) { + v8::Isolate* isolate = instance_->isolate(); + v8::HandleScope handle_scope(isolate); + + Handle<MyObject> obj = MyObject::Create(isolate); + std::vector<MyObject*> vector = {obj.get()}; + v8::MaybeLocal<v8::Value> maybe = ConvertToV8(isolate, vector); + v8::Local<v8::Value> array; + ASSERT_TRUE(maybe.ToLocal(&array)); + + std::vector<MyObject*> out_value; + ASSERT_TRUE(ConvertFromV8(isolate, array, &out_value)); + EXPECT_THAT(out_value, testing::ContainerEq(vector)); +} + } // namespace gin diff --git a/chromium/gin/function_template.h b/chromium/gin/function_template.h index 1cbe78ccd48..1e60649a091 100644 --- a/chromium/gin/function_template.h +++ b/chromium/gin/function_template.h @@ -225,20 +225,6 @@ v8::Local<v8::FunctionTemplate> CreateFunctionTemplate( return tmpl; } -// 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, - base::RepeatingCallback<Sig> callback, - int callback_flags = 0) { - typedef internal::CallbackHolder<Sig> HolderT; - HolderT* holder = new HolderT(isolate, std::move(callback), callback_flags); - tmpl->SetCallAsFunctionHandler(&internal::Dispatcher<Sig>::DispatchToCallback, - ConvertToV8<v8::Local<v8::External> >( - isolate, holder->GetHandle(isolate))); -} - } // namespace gin #endif // GIN_FUNCTION_TEMPLATE_H_ diff --git a/chromium/gin/interceptor_unittest.cc b/chromium/gin/interceptor_unittest.cc index bf2ca822f29..c085702743b 100644 --- a/chromium/gin/interceptor_unittest.cc +++ b/chromium/gin/interceptor_unittest.cc @@ -151,7 +151,7 @@ class InterceptorTest : public V8Test { v8::Local<v8::Function> func; EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); v8::Local<v8::Value> argv[] = { - ConvertToV8(isolate->GetCurrentContext(), obj.get()).ToLocalChecked(), + ConvertToV8(isolate, obj.get()).ToLocalChecked(), }; func->Call(v8::Undefined(isolate), 1, argv); EXPECT_FALSE(try_catch.HasCaught()); diff --git a/chromium/gin/isolate_holder.cc b/chromium/gin/isolate_holder.cc index c0aae855fa3..56402d477ca 100644 --- a/chromium/gin/isolate_holder.cc +++ b/chromium/gin/isolate_holder.cc @@ -41,56 +41,55 @@ IsolateHolder::IsolateHolder( : IsolateHolder(std::move(task_runner), access_mode, kAllowAtomicsWait, - nullptr) {} + IsolateCreationMode::kNormal) {} IsolateHolder::IsolateHolder( scoped_refptr<base::SingleThreadTaskRunner> task_runner, AccessMode access_mode, AllowAtomicsWaitMode atomics_wait_mode, - v8::StartupData* startup_data) + IsolateCreationMode isolate_creation_mode) : access_mode_(access_mode) { + DCHECK(task_runner); + DCHECK(task_runner->BelongsToCurrentThread()); + v8::ArrayBuffer::Allocator* allocator = g_array_buffer_allocator; CHECK(allocator) << "You need to invoke gin::IsolateHolder::Initialize first"; - v8::Isolate::CreateParams params; - params.entry_hook = DebugImpl::GetFunctionEntryHook(); - params.code_event_handler = DebugImpl::GetJitCodeEventHandler(); - params.constraints.ConfigureDefaults(base::SysInfo::AmountOfPhysicalMemory(), - base::SysInfo::AmountOfVirtualMemory()); - params.array_buffer_allocator = allocator; - params.allow_atomics_wait = atomics_wait_mode == kAllowAtomicsWait; - params.external_references = g_reference_table; - - if (startup_data) { - CHECK(g_reference_table); - V8Initializer::GetV8ContextSnapshotData(startup_data); - if (startup_data->data) { - params.snapshot_blob = startup_data; - } + if (isolate_creation_mode == IsolateCreationMode::kCreateSnapshot) { + // This branch is called when creating a V8 snapshot for Blink. + // Note SnapshotCreator calls isolate->Enter() in its construction. + snapshot_creator_.reset(new v8::SnapshotCreator(g_reference_table)); + isolate_ = snapshot_creator_->GetIsolate(); + } else { + v8::Isolate::CreateParams params; + params.entry_hook = DebugImpl::GetFunctionEntryHook(); + params.code_event_handler = DebugImpl::GetJitCodeEventHandler(); + params.constraints.ConfigureDefaults( + base::SysInfo::AmountOfPhysicalMemory(), + base::SysInfo::AmountOfVirtualMemory()); + params.array_buffer_allocator = allocator; + params.allow_atomics_wait = + atomics_wait_mode == AllowAtomicsWaitMode::kAllowAtomicsWait; + params.external_references = g_reference_table; + + isolate_ = v8::Isolate::New(params); } - isolate_ = v8::Isolate::New(params); - SetUp(task_runner); -} - -IsolateHolder::IsolateHolder( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - v8::StartupData* existing_blob) - : access_mode_(AccessMode::kSingleThread) { - CHECK(existing_blob); - - v8::StartupData unused_natives; - V8Initializer::GetV8ExternalSnapshotData(&unused_natives, existing_blob); - if (!existing_blob->data) { - existing_blob = nullptr; + isolate_data_.reset( + new PerIsolateData(isolate_, allocator, access_mode_, task_runner)); + isolate_memory_dump_provider_.reset( + new V8IsolateMemoryDumpProvider(this, task_runner)); +#if defined(OS_WIN) + { + void* code_range; + size_t size; + isolate_->GetCodeRange(&code_range, &size); + Debug::CodeRangeCreatedCallback callback = + DebugImpl::GetCodeRangeCreatedCallback(); + if (code_range && size && callback) + callback(code_range, size); } - - snapshot_creator_.reset( - new v8::SnapshotCreator(g_reference_table, existing_blob)); - isolate_ = snapshot_creator_->GetIsolate(); - - DCHECK(task_runner->BelongsToCurrentThread()); - SetUp(task_runner); +#endif } IsolateHolder::~IsolateHolder() { @@ -142,26 +141,4 @@ void IsolateHolder::EnableIdleTasks( isolate_data_->EnableIdleTasks(std::move(idle_task_runner)); } -void IsolateHolder::SetUp( - scoped_refptr<base::SingleThreadTaskRunner> task_runner) { - DCHECK(task_runner); - v8::ArrayBuffer::Allocator* allocator = g_array_buffer_allocator; - CHECK(allocator) << "You need to invoke gin::IsolateHolder::Initialize first"; - isolate_data_.reset( - new PerIsolateData(isolate_, allocator, access_mode_, task_runner)); - isolate_memory_dump_provider_.reset( - new V8IsolateMemoryDumpProvider(this, task_runner)); -#if defined(OS_WIN) - { - void* code_range; - size_t size; - isolate_->GetCodeRange(&code_range, &size); - Debug::CodeRangeCreatedCallback callback = - DebugImpl::GetCodeRangeCreatedCallback(); - if (code_range && size && callback) - callback(code_range, size); - } -#endif -} - } // namespace gin diff --git a/chromium/gin/object_template_builder.h b/chromium/gin/object_template_builder.h index 33106233c77..92230ea06d3 100644 --- a/chromium/gin/object_template_builder.h +++ b/chromium/gin/object_template_builder.h @@ -85,11 +85,6 @@ class GIN_EXPORT ObjectTemplateBuilder { return SetPropertyImpl(name, CreateFunctionTemplate(isolate_, getter), CreateFunctionTemplate(isolate_, setter)); } - template<typename T> - ObjectTemplateBuilder& SetCallAsFunctionHandler(const T& callback) { - SetAsFunctionHandler(isolate_, template_, callback); - return *this; - } ObjectTemplateBuilder& AddNamedPropertyInterceptor(); ObjectTemplateBuilder& AddIndexedPropertyInterceptor(); diff --git a/chromium/gin/public/isolate_holder.h b/chromium/gin/public/isolate_holder.h index 8ce49ff6dc3..2509aca609f 100644 --- a/chromium/gin/public/isolate_holder.h +++ b/chromium/gin/public/isolate_holder.h @@ -53,20 +53,21 @@ class GIN_EXPORT IsolateHolder { kStableAndExperimentalV8Extras, }; + // Indicates how the Isolate instance will be created. + enum class IsolateCreationMode { + kNormal, + kCreateSnapshot, + }; + explicit IsolateHolder( scoped_refptr<base::SingleThreadTaskRunner> task_runner); IsolateHolder(scoped_refptr<base::SingleThreadTaskRunner> task_runner, AccessMode access_mode); - IsolateHolder(scoped_refptr<base::SingleThreadTaskRunner> task_runner, - AccessMode access_mode, - AllowAtomicsWaitMode atomics_wait_mode, - v8::StartupData* startup_data); - - // This constructor is to create V8 snapshot for Blink. - // Note this constructor calls isolate->Enter() internally. - IsolateHolder(scoped_refptr<base::SingleThreadTaskRunner> task_runner, - v8::StartupData* existing_blob); - + IsolateHolder( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + AccessMode access_mode, + AllowAtomicsWaitMode atomics_wait_mode, + IsolateCreationMode isolate_creation_mode = IsolateCreationMode::kNormal); ~IsolateHolder(); // Should be invoked once before creating IsolateHolder instances to diff --git a/chromium/gin/public/v8_platform.h b/chromium/gin/public/v8_platform.h index cbbebc0760f..0429d028b6a 100644 --- a/chromium/gin/public/v8_platform.h +++ b/chromium/gin/public/v8_platform.h @@ -8,6 +8,7 @@ #include "base/compiler_specific.h" #include "base/lazy_instance.h" #include "base/macros.h" +#include "base/partition_alloc_buildflags.h" #include "gin/gin_export.h" #include "v8/include/v8-platform.h" @@ -18,8 +19,12 @@ class GIN_EXPORT V8Platform : public v8::Platform { public: static V8Platform* Get(); - // v8::Platform implementation. +// v8::Platform implementation. +// Some configurations do not use page_allocator. +#if BUILDFLAG(USE_PARTITION_ALLOC) + v8::PageAllocator* GetPageAllocator() override; void OnCriticalMemoryPressure() override; +#endif std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( v8::Isolate*) override; std::shared_ptr<v8::TaskRunner> GetBackgroundTaskRunner( diff --git a/chromium/gin/v8_initializer.cc b/chromium/gin/v8_initializer.cc index 03353beb9dd..9e0df626b2a 100644 --- a/chromium/gin/v8_initializer.cc +++ b/chromium/gin/v8_initializer.cc @@ -41,7 +41,6 @@ namespace { // None of these globals are ever freed nor closed. base::MemoryMappedFile* g_mapped_natives = nullptr; base::MemoryMappedFile* g_mapped_snapshot = nullptr; -base::MemoryMappedFile* g_mapped_v8_context_snapshot = nullptr; bool GenerateEntropy(unsigned char* buffer, size_t amount) { base::RandBytes(buffer, amount); @@ -87,25 +86,33 @@ const char kSnapshotFileName32[] = "snapshot_blob_32.bin"; const char kSnapshotFileName[] = "snapshot_blob.bin"; #endif // defined(OS_ANDROID) +const char* GetSnapshotFileName( + const V8Initializer::V8SnapshotFileType file_type) { + switch (file_type) { + case V8Initializer::V8SnapshotFileType::kDefault: + return kSnapshotFileName; + case V8Initializer::V8SnapshotFileType::kWithAdditionalContext: + return kV8ContextSnapshotFileName; + } + NOTREACHED(); + return nullptr; +} + void GetV8FilePath(const char* file_name, base::FilePath* path_out) { -#if !defined(OS_MACOSX) - base::FilePath data_path; #if defined(OS_ANDROID) // This is the path within the .apk. - data_path = base::FilePath(FILE_PATH_LITERAL("assets")); -#elif defined(OS_POSIX) - PathService::Get(base::DIR_EXE, &data_path); -#elif defined(OS_WIN) - PathService::Get(base::DIR_MODULE, &data_path); -#endif - DCHECK(!data_path.empty()); - - *path_out = data_path.AppendASCII(file_name); -#else // !defined(OS_MACOSX) + *path_out = + base::FilePath(FILE_PATH_LITERAL("assets")).AppendASCII(file_name); +#elif defined(OS_MACOSX) base::ScopedCFTypeRef<CFStringRef> natives_file_name( base::SysUTF8ToCFStringRef(file_name)); *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); -#endif // !defined(OS_MACOSX) +#else + base::FilePath data_path; + bool r = PathService::Get(base::DIR_ASSETS, &data_path); + DCHECK(r); + *path_out = data_path.AppendASCII(file_name); +#endif } bool MapV8File(base::PlatformFile platform_file, @@ -242,14 +249,12 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode, #if defined(V8_USE_EXTERNAL_STARTUP_DATA) v8::StartupData natives; - natives.data = reinterpret_cast<const char*>(g_mapped_natives->data()); - natives.raw_size = static_cast<int>(g_mapped_natives->length()); + GetMappedFileData(g_mapped_natives, &natives); v8::V8::SetNativesDataBlob(&natives); if (g_mapped_snapshot) { v8::StartupData snapshot; - snapshot.data = reinterpret_cast<const char*>(g_mapped_snapshot->data()); - snapshot.raw_size = static_cast<int>(g_mapped_snapshot->length()); + GetMappedFileData(g_mapped_snapshot, &snapshot); v8::V8::SetSnapshotDataBlob(&snapshot); } #endif // V8_USE_EXTERNAL_STARTUP_DATA @@ -281,26 +286,26 @@ void V8Initializer::GetV8ExternalSnapshotData(const char** natives_data_out, *snapshot_size_out = snapshot.raw_size; } -// static -void V8Initializer::GetV8ContextSnapshotData(v8::StartupData* snapshot) { - GetMappedFileData(g_mapped_v8_context_snapshot, snapshot); -} - #if defined(V8_USE_EXTERNAL_STARTUP_DATA) // static -void V8Initializer::LoadV8Snapshot() { - if (g_mapped_snapshot) +void V8Initializer::LoadV8Snapshot(V8SnapshotFileType snapshot_file_type) { + if (g_mapped_snapshot) { + // TODO(crbug.com/802962): Confirm not loading different type of snapshot + // files in a process. return; + } - LoadV8FileResult result = MapOpenedFile(GetOpenedFile(kSnapshotFileName), - &g_mapped_snapshot); + LoadV8FileResult result = + MapOpenedFile(GetOpenedFile(GetSnapshotFileName(snapshot_file_type)), + &g_mapped_snapshot); // V8 can't start up without the source of the natives, but it can // start up (slower) without the snapshot. UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, V8_LOAD_MAX_VALUE); } +// static void V8Initializer::LoadV8Natives() { if (g_mapped_natives) return; @@ -314,20 +319,11 @@ void V8Initializer::LoadV8Natives() { } // static -void V8Initializer::LoadV8ContextSnapshot() { - if (g_mapped_v8_context_snapshot) - return; - - MapOpenedFile(GetOpenedFile(kV8ContextSnapshotFileName), - &g_mapped_v8_context_snapshot); - - // TODO(peria): Check if the snapshot file is loaded successfully. -} - -// static -void V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile snapshot_pf, - int64_t snapshot_offset, - int64_t snapshot_size) { +void V8Initializer::LoadV8SnapshotFromFD( + base::PlatformFile snapshot_pf, + int64_t snapshot_offset, + int64_t snapshot_size, + V8SnapshotFileType snapshot_file_type) { if (g_mapped_snapshot) return; @@ -345,7 +341,7 @@ void V8Initializer::LoadV8SnapshotFromFD(base::PlatformFile snapshot_pf, if (!MapV8File(snapshot_pf, snapshot_region, &g_mapped_snapshot)) result = V8_LOAD_FAILED_MAP; if (result == V8_LOAD_SUCCESS) { - g_opened_files.Get()[kSnapshotFileName] = + g_opened_files.Get()[GetSnapshotFileName(snapshot_file_type)] = std::make_pair(snapshot_pf, snapshot_region); } UMA_HISTOGRAM_ENUMERATION("V8.Initializer.LoadV8Snapshot.Result", result, @@ -375,27 +371,6 @@ void V8Initializer::LoadV8NativesFromFD(base::PlatformFile natives_pf, std::make_pair(natives_pf, natives_region); } -// static -void V8Initializer::LoadV8ContextSnapshotFromFD(base::PlatformFile snapshot_pf, - int64_t snapshot_offset, - int64_t snapshot_size) { - if (g_mapped_v8_context_snapshot) - return; - CHECK_NE(base::kInvalidPlatformFile, snapshot_pf); - - base::MemoryMappedFile::Region snapshot_region = - base::MemoryMappedFile::Region::kWholeFile; - if (snapshot_size != 0 || snapshot_offset != 0) { - snapshot_region.offset = snapshot_offset; - snapshot_region.size = snapshot_size; - } - - if (MapV8File(snapshot_pf, snapshot_region, &g_mapped_v8_context_snapshot)) { - g_opened_files.Get()[kV8ContextSnapshotFileName] = - std::make_pair(snapshot_pf, snapshot_region); - } -} - #if defined(OS_ANDROID) // static base::FilePath V8Initializer::GetNativesFilePath() { diff --git a/chromium/gin/v8_initializer.h b/chromium/gin/v8_initializer.h index 0c0da3c70c5..e427c213e42 100644 --- a/chromium/gin/v8_initializer.h +++ b/chromium/gin/v8_initializer.h @@ -33,19 +33,22 @@ class GIN_EXPORT V8Initializer { const char** snapshot_data_out, int* snapshot_size_out); - // Get address and size information for currently loaded V8 context snapshot. - // If no snapshot is loaded, the return values are nullptr and 0. - static void GetV8ContextSnapshotData(v8::StartupData* snapshot); - #if defined(V8_USE_EXTERNAL_STARTUP_DATA) + // Indicates which file to load as a snapshot blob image. + enum class V8SnapshotFileType { + kDefault, + + // Snapshot augmented with customized contexts, which can be deserialized + // using v8::Context::FromSnapshot. + kWithAdditionalContext, + }; // Load V8 snapshot from default resources, if they are available. - static void LoadV8Snapshot(); + static void LoadV8Snapshot( + V8SnapshotFileType snapshot_file_type = V8SnapshotFileType::kDefault); // Load V8 natives source from default resources. Contains asserts // so that it will not return if natives cannot be loaded. static void LoadV8Natives(); - // Load V8 context snapshot from default resources, if they are available. - static void LoadV8ContextSnapshot(); // Load V8 snapshot from user provided platform file descriptors. // The offset and size arguments, if non-zero, specify the portions @@ -53,18 +56,14 @@ class GIN_EXPORT V8Initializer { // the snapshot, this function does not return a status. static void LoadV8SnapshotFromFD(base::PlatformFile snapshot_fd, int64_t snapshot_offset, - int64_t snapshot_size); + int64_t snapshot_size, + V8SnapshotFileType snapshot_file_type); // Similar to LoadV8SnapshotFromFD, but for the source of the natives. // Without the natives we cannot continue, so this function contains // release mode asserts and won't return if it fails. static void LoadV8NativesFromFD(base::PlatformFile natives_fd, int64_t natives_offset, int64_t natives_size); - // Load V8 context snapshot from user provided platform file descriptors. - // Other details are same with LoadV8SnapshotFromFD. - static void LoadV8ContextSnapshotFromFD(base::PlatformFile snapshot_fd, - int64_t snapshot_offset, - int64_t snapshot_size); #if defined(OS_ANDROID) static base::FilePath GetNativesFilePath(); diff --git a/chromium/gin/v8_platform.cc b/chromium/gin/v8_platform.cc index 299c83d4601..3be0a541d33 100644 --- a/chromium/gin/v8_platform.cc +++ b/chromium/gin/v8_platform.cc @@ -6,9 +6,11 @@ #include <algorithm> +#include "base/allocator/partition_allocator/address_space_randomization.h" #include "base/allocator/partition_allocator/page_allocator.h" #include "base/bind.h" #include "base/bit_cast.h" +#include "base/bits.h" #include "base/debug/stack_trace.h" #include "base/location.h" #include "base/rand_util.h" @@ -153,6 +155,86 @@ class TimeClamper { base::LazyInstance<TimeClamper>::Leaky g_time_clamper = LAZY_INSTANCE_INITIALIZER; +#if BUILDFLAG(USE_PARTITION_ALLOC) +base::PageAccessibilityConfiguration GetPageConfig( + v8::PageAllocator::Permission permission) { + switch (permission) { + case v8::PageAllocator::Permission::kReadWrite: + return base::PageReadWrite; + case v8::PageAllocator::Permission::kReadWriteExecute: + return base::PageReadWriteExecute; + case v8::PageAllocator::Permission::kReadExecute: + return base::PageReadExecute; + default: + DCHECK_EQ(v8::PageAllocator::Permission::kNoAccess, permission); + return base::PageInaccessible; + } +} + +class PageAllocator : public v8::PageAllocator { + public: + ~PageAllocator() override = default; + + size_t AllocatePageSize() override { + return base::kPageAllocationGranularity; + } + + size_t CommitPageSize() override { return base::kSystemPageSize; } + + void SetRandomMmapSeed(int64_t seed) override { + base::SetRandomPageBaseSeed(seed); + } + + void* GetRandomMmapAddr() override { return base::GetRandomPageBase(); } + + void* AllocatePages(void* address, + size_t length, + size_t alignment, + v8::PageAllocator::Permission permissions) override { + base::PageAccessibilityConfiguration config = GetPageConfig(permissions); + bool commit = (permissions != v8::PageAllocator::Permission::kNoAccess); + return base::AllocPages(address, length, alignment, config, + base::PageTag::kV8, commit); + } + + bool FreePages(void* address, size_t length) override { + base::FreePages(address, length); + return true; + } + + bool ReleasePages(void* address, size_t length, size_t new_length) override { + DCHECK_LT(new_length, length); + uint8_t* release_base = reinterpret_cast<uint8_t*>(address) + new_length; + size_t release_size = length - new_length; +#if defined(OS_POSIX) + // On POSIX, we can unmap the trailing pages. + base::FreePages(release_base, release_size); +#else // defined(OS_WIN) + // On Windows, we can only de-commit the trailing pages. + base::DecommitSystemPages(release_base, release_size); +#endif + return true; + } + + bool SetPermissions(void* address, + size_t length, + Permission permissions) override { + // If V8 sets permissions to none, we can discard the memory. + if (permissions == v8::PageAllocator::Permission::kNoAccess) { + base::DecommitSystemPages(address, length); + return true; + } else { + return base::SetSystemPagesAccess(address, length, + GetPageConfig(permissions)); + } + } +}; + +base::LazyInstance<PageAllocator>::Leaky g_page_allocator = + LAZY_INSTANCE_INITIALIZER; + +#endif // BUILDFLAG(USE_PARTITION_ALLOC) + } // namespace class V8Platform::TracingControllerImpl : public v8::TracingController { @@ -223,13 +305,19 @@ V8Platform::V8Platform() : tracing_controller_(new TracingControllerImpl) {} V8Platform::~V8Platform() = default; +#if BUILDFLAG(USE_PARTITION_ALLOC) +v8::PageAllocator* V8Platform::GetPageAllocator() { + return g_page_allocator.Pointer(); +} + void V8Platform::OnCriticalMemoryPressure() { -#if defined(OS_WIN) - // Some configurations do not use page_allocator. Only 32 bit Windows systems - // reserve memory currently. +// We only have a reservation on 32-bit Windows systems. +// TODO(bbudge) Make the #if's in BlinkInitializer match. +#if defined(OS_WIN) && defined(ARCH_CPU_32_BITS) base::ReleaseReservation(); #endif } +#endif // BUILDFLAG(USE_PARTITION_ALLOC) std::shared_ptr<v8::TaskRunner> V8Platform::GetForegroundTaskRunner( v8::Isolate* isolate) { @@ -239,7 +327,9 @@ std::shared_ptr<v8::TaskRunner> V8Platform::GetForegroundTaskRunner( std::shared_ptr<v8::TaskRunner> V8Platform::GetBackgroundTaskRunner( v8::Isolate* isolate) { - return std::make_shared<V8BackgroundTaskRunner>(); + static std::shared_ptr<v8::TaskRunner> v8_background_task_runner = + std::make_shared<V8BackgroundTaskRunner>(); + return v8_background_task_runner; } size_t V8Platform::NumberOfAvailableBackgroundThreads() { diff --git a/chromium/gin/wrappable.h b/chromium/gin/wrappable.h index 9026e659727..46da9a57143 100644 --- a/chromium/gin/wrappable.h +++ b/chromium/gin/wrappable.h @@ -115,10 +115,9 @@ template <typename T> struct Converter<T*, typename std::enable_if< std::is_convertible<T*, WrappableBase*>::value>::type> { - static v8::MaybeLocal<v8::Value> ToV8(v8::Local<v8::Context> context, - T* val) { + static v8::MaybeLocal<v8::Value> ToV8(v8::Isolate* isolate, T* val) { v8::Local<v8::Object> wrapper; - if (!val->GetWrapper(context->GetIsolate()).ToLocal(&wrapper)) + if (!val->GetWrapper(isolate).ToLocal(&wrapper)) return v8::MaybeLocal<v8::Value>(); return v8::MaybeLocal<v8::Value>(wrapper); } diff --git a/chromium/gin/wrappable_unittest.cc b/chromium/gin/wrappable_unittest.cc index 06fbd1851c4..6a1cb450afa 100644 --- a/chromium/gin/wrappable_unittest.cc +++ b/chromium/gin/wrappable_unittest.cc @@ -57,44 +57,12 @@ class MyObject : public BaseClass, int value_; }; -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: - ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) final { - return Wrappable<MyCallableObject>::GetObjectTemplateBuilder(isolate) - .SetCallAsFunctionHandler(&MyCallableObject::Call); - } - - MyCallableObject() : result_(0) { - } - - ~MyCallableObject() override = default; - - void Call(int val1, int val2, int val3, const gin::Arguments& arguments) { - if (arguments.IsConstructCall()) - arguments.ThrowTypeError("Cannot be called as constructor."); - else - result_ = val1; - } - - int result_; -}; - class MyObject2 : public Wrappable<MyObject2> { public: static WrapperInfo kWrapperInfo; }; WrapperInfo MyObject::kWrapperInfo = { kEmbedderNativeGin }; -WrapperInfo MyCallableObject::kWrapperInfo = { kEmbedderNativeGin }; WrapperInfo MyObject2::kWrapperInfo = { kEmbedderNativeGin }; typedef V8Test WrappableTest; @@ -106,7 +74,7 @@ TEST_F(WrappableTest, WrapAndUnwrap) { Handle<MyObject> obj = MyObject::Create(isolate); v8::Local<v8::Value> wrapper = - ConvertToV8(isolate->GetCurrentContext(), obj.get()).ToLocalChecked(); + ConvertToV8(isolate, obj.get()).ToLocalChecked(); EXPECT_FALSE(wrapper.IsEmpty()); MyObject* unwrapped = NULL; @@ -131,8 +99,7 @@ TEST_F(WrappableTest, UnwrapFailures) { // An object that's wrapping a C++ object of the wrong type. thing.Clear(); - thing = ConvertToV8(isolate->GetCurrentContext(), new MyObject2()) - .ToLocalChecked(); + thing = ConvertToV8(isolate, new MyObject2()).ToLocalChecked(); EXPECT_FALSE(ConvertFromV8(isolate, thing, &unwrapped)); EXPECT_FALSE(unwrapped); } @@ -160,7 +127,7 @@ TEST_F(WrappableTest, GetAndSetProperty) { v8::Local<v8::Function> func; EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); v8::Local<v8::Value> argv[] = { - ConvertToV8(isolate->GetCurrentContext(), obj.get()).ToLocalChecked(), + ConvertToV8(isolate, obj.get()).ToLocalChecked(), }; func->Call(v8::Undefined(isolate), 1, argv); EXPECT_FALSE(try_catch.HasCaught()); @@ -169,53 +136,4 @@ TEST_F(WrappableTest, GetAndSetProperty) { EXPECT_EQ(191, obj->value()); } -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::Local<v8::String> source = StringToV8(isolate, - "(function(obj) {" - "obj(42, 2, 5);" - "})"); - gin::TryCatch try_catch(isolate); - v8::Local<v8::Script> script = - v8::Script::Compile(context_.Get(isolate), source).ToLocalChecked(); - v8::Local<v8::Value> val = - script->Run(context_.Get(isolate)).ToLocalChecked(); - v8::Local<v8::Function> func; - EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); - v8::Local<v8::Value> argv[] = { - ConvertToV8(isolate->GetCurrentContext(), object.get()).ToLocalChecked(), - }; - func->Call(v8::Undefined(isolate), 1, argv); - EXPECT_FALSE(try_catch.HasCaught()); - EXPECT_EQ(42, object->result()); -} - -TEST_F(WrappableTest, CallAsConstructor) { - v8::Isolate* isolate = instance_->isolate(); - v8::HandleScope handle_scope(isolate); - - gin::Handle<MyCallableObject> object(MyCallableObject::Create(isolate)); - EXPECT_EQ(0, object->result()); - v8::Local<v8::String> source = StringToV8(isolate, - "(function(obj) {" - "new obj(42, 2, 5);" - "})"); - gin::TryCatch try_catch(isolate); - v8::Local<v8::Script> script = - v8::Script::Compile(context_.Get(isolate), source).ToLocalChecked(); - v8::Local<v8::Value> val = - script->Run(context_.Get(isolate)).ToLocalChecked(); - v8::Local<v8::Function> func; - EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); - v8::Local<v8::Value> argv[] = { - ConvertToV8(isolate->GetCurrentContext(), object.get()).ToLocalChecked(), - }; - func->Call(v8::Undefined(isolate), 1, argv); - EXPECT_TRUE(try_catch.HasCaught()); -} - } // namespace gin |