diff options
Diffstat (limited to 'chromium/gin')
31 files changed, 190 insertions, 1342 deletions
diff --git a/chromium/gin/BUILD.gn b/chromium/gin/BUILD.gn index d71adf5134a..6b3a66391f1 100644 --- a/chromium/gin/BUILD.gn +++ b/chromium/gin/BUILD.gn @@ -2,9 +2,18 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. +import("//build/buildflag_header.gni") +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", @@ -29,15 +38,6 @@ component("gin") { "isolate_holder.cc", "modules/console.cc", "modules/console.h", - "modules/file_module_provider.cc", - "modules/file_module_provider.h", - "modules/module_registry.cc", - "modules/module_registry.h", - "modules/module_registry_observer.h", - "modules/module_runner_delegate.cc", - "modules/module_runner_delegate.h", - "modules/timer.cc", - "modules/timer.h", "object_template_builder.cc", "object_template_builder.h", "per_context_data.cc", @@ -87,6 +87,7 @@ component("gin") { defines = [ "GIN_IMPLEMENTATION" ] public_deps = [ + ":features", "//base", "//v8", ] @@ -121,20 +122,9 @@ executable("gin_shell") { source_set("gin_test") { testonly = true sources = [ - "test/file.cc", - "test/file.h", - "test/file_runner.cc", - "test/file_runner.h", - "test/gc.cc", - "test/gc.h", - "test/gtest.cc", - "test/gtest.h", "test/v8_test.cc", "test/v8_test.h", ] - data = [ - "test/expect.js", - ] public_deps = [ ":gin", @@ -155,13 +145,10 @@ test("gin_unittests") { "converter_unittest.cc", "data_object_builder_unittest.cc", "interceptor_unittest.cc", - "modules/module_registry_unittest.cc", - "modules/timer_unittest.cc", "per_context_data_unittest.cc", "shell/gin_shell_unittest.cc", "shell_runner_unittest.cc", "test/run_all_unittests.cc", - "test/run_js_tests.cc", "v8_isolate_memory_dump_provider_unittest.cc", "v8_platform_unittest.cc", "wrappable_unittest.cc", @@ -174,13 +161,13 @@ test("gin_unittests") { "//v8", ] - configs += [ "//v8:external_startup_data" ] + configs += [ + "//tools/v8_context_snapshot:use_v8_context_snapshot", + "//v8:external_startup_data", + ] data = [ - "modules/module_registry_unittests.js", "shell/hello_world.js", - "test/file_unittests.js", - "test/gtest_unittests.js", "../OWNERS", ] diff --git a/chromium/gin/arguments_unittest.cc b/chromium/gin/arguments_unittest.cc index 3a262c7818d..75bb3ebb753 100644 --- a/chromium/gin/arguments_unittest.cc +++ b/chromium/gin/arguments_unittest.cc @@ -47,7 +47,8 @@ TEST_F(ArgumentsTest, TestArgumentsHolderCreationContext) { v8::Script::Compile(context, StringToV8(isolate, kCallFunction)) .ToLocalChecked(); v8::Local<v8::Function> function; - ASSERT_TRUE(ConvertFromV8(isolate, script->Run(), &function)); + ASSERT_TRUE(ConvertFromV8(isolate, script->Run(context).ToLocalChecked(), + &function)); v8::Local<v8::Value> args[] = {object}; function->Call(v8::Undefined(isolate), arraysize(args), args); }; diff --git a/chromium/gin/array_buffer.cc b/chromium/gin/array_buffer.cc index 34e83dbc5da..5d503e733b3 100644 --- a/chromium/gin/array_buffer.cc +++ b/chromium/gin/array_buffer.cc @@ -2,13 +2,15 @@ // 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 <stddef.h> #include <stdlib.h> #include "base/allocator/partition_allocator/page_allocator.h" #include "base/logging.h" #include "build/build_config.h" -#include "gin/array_buffer.h" +#include "gin/features.h" #include "gin/per_isolate_data.h" #if defined(OS_POSIX) @@ -17,7 +19,7 @@ #ifndef MAP_ANONYMOUS #define MAP_ANONYMOUS MAP_ANON #endif -#endif +#endif // defined(OS_POSIX) namespace gin { @@ -33,6 +35,7 @@ static_assert(V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT == 2, // ArrayBufferAllocator ------------------------------------------------------- void* ArrayBufferAllocator::Allocate(size_t length) { + // TODO(bbudge) Use partition allocator for malloc/calloc allocations. return calloc(1, length); } @@ -41,11 +44,14 @@ void* ArrayBufferAllocator::AllocateUninitialized(size_t length) { } void* ArrayBufferAllocator::Reserve(size_t length) { - void* const hint = nullptr; -#if defined(OS_POSIX) +#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(hint, length, access_flag, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + mmap(nullptr, length, access_flag, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); if (ret == MAP_FAILED) { return nullptr; } @@ -67,16 +73,15 @@ void ArrayBufferAllocator::Free(void* data, case AllocationMode::kNormal: Free(data, length); return; - case AllocationMode::kReservation: { -#if defined(OS_POSIX) - int const ret = munmap(data, length); - CHECK(!ret); + case AllocationMode::kReservation: +#if BUILDFLAG(USE_PARTITION_ALLOC) + base::FreePages(data, length); +#elif defined(OS_POSIX) + CHECK(!munmap(data, length)); #else - BOOL const ret = VirtualFree(data, 0, MEM_RELEASE); - CHECK(ret); + CHECK(VirtualFree(data, 0, MEM_RELEASE)); #endif return; - } default: NOTREACHED(); } @@ -85,27 +90,40 @@ void ArrayBufferAllocator::Free(void* data, void ArrayBufferAllocator::SetProtection(void* data, size_t length, Protection protection) { +#if BUILDFLAG(USE_PARTITION_ALLOC) switch (protection) { - case Protection::kNoAccess: { -#if defined(OS_POSIX) - int ret = mprotect(data, length, PROT_NONE); - CHECK(!ret); -#else - BOOL ret = VirtualFree(data, length, MEM_DECOMMIT); - CHECK(ret); -#endif + case Protection::kNoAccess: + CHECK(base::SetSystemPagesAccess(data, length, base::PageInaccessible)); break; - } case Protection::kReadWrite: -#if defined(OS_POSIX) - mprotect(data, length, PROT_READ | PROT_WRITE); -#else - VirtualAlloc(data, length, MEM_COMMIT, PAGE_READWRITE); -#endif + 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() { diff --git a/chromium/gin/interceptor_unittest.cc b/chromium/gin/interceptor_unittest.cc index 089920071ec..bf2ca822f29 100644 --- a/chromium/gin/interceptor_unittest.cc +++ b/chromium/gin/interceptor_unittest.cc @@ -143,9 +143,10 @@ class InterceptorTest : public V8Test { EXPECT_FALSE(source.IsEmpty()); gin::TryCatch try_catch(isolate); - v8::Local<v8::Script> script = v8::Script::Compile(source); - EXPECT_FALSE(script.IsEmpty()); - v8::Local<v8::Value> val = script->Run(); + v8::Local<v8::Script> script = + v8::Script::Compile(context_.Get(isolate), source).ToLocalChecked(); + v8::Local<v8::Value> val = + script->Run(context_.Get(isolate)).ToLocalChecked(); EXPECT_FALSE(val.IsEmpty()); v8::Local<v8::Function> func; EXPECT_TRUE(ConvertFromV8(isolate, val, &func)); diff --git a/chromium/gin/isolate_holder.cc b/chromium/gin/isolate_holder.cc index 0018a7f3796..c0aae855fa3 100644 --- a/chromium/gin/isolate_holder.cc +++ b/chromium/gin/isolate_holder.cc @@ -15,6 +15,7 @@ #include "base/message_loop/message_loop.h" #include "base/single_thread_task_runner.h" #include "base/sys_info.h" +#include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "gin/debug_impl.h" #include "gin/function_template.h" @@ -69,10 +70,12 @@ IsolateHolder::IsolateHolder( } isolate_ = v8::Isolate::New(params); - SetUp(std::move(task_runner)); + SetUp(task_runner); } -IsolateHolder::IsolateHolder(v8::StartupData* existing_blob) +IsolateHolder::IsolateHolder( + scoped_refptr<base::SingleThreadTaskRunner> task_runner, + v8::StartupData* existing_blob) : access_mode_(AccessMode::kSingleThread) { CHECK(existing_blob); @@ -86,7 +89,8 @@ IsolateHolder::IsolateHolder(v8::StartupData* existing_blob) new v8::SnapshotCreator(g_reference_table, existing_blob)); isolate_ = snapshot_creator_->GetIsolate(); - SetUp(nullptr); + DCHECK(task_runner->BelongsToCurrentThread()); + SetUp(task_runner); } IsolateHolder::~IsolateHolder() { @@ -140,11 +144,13 @@ void IsolateHolder::EnableIdleTasks( 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)); + isolate_memory_dump_provider_.reset( + new V8IsolateMemoryDumpProvider(this, task_runner)); #if defined(OS_WIN) { void* code_range; diff --git a/chromium/gin/modules/console.cc b/chromium/gin/modules/console.cc index 63fc41eeaf0..8786392b9e6 100644 --- a/chromium/gin/modules/console.cc +++ b/chromium/gin/modules/console.cc @@ -9,41 +9,31 @@ #include "base/strings/string_util.h" #include "gin/arguments.h" #include "gin/converter.h" -#include "gin/object_template_builder.h" -#include "gin/per_isolate_data.h" -#include "gin/public/wrapper_info.h" - -using v8::ObjectTemplate; namespace gin { namespace { -void Log(Arguments* args) { +void Log(const v8::FunctionCallbackInfo<v8::Value>& info) { + Arguments args(info); std::vector<std::string> messages; - if (!args->GetRemaining(&messages)) { - args->ThrowError(); + if (!args.GetRemaining(&messages)) { + args.ThrowError(); return; } printf("%s\n", base::JoinString(messages, " ").c_str()); } -WrapperInfo g_wrapper_info = { kEmbedderNativeGin }; - } // namespace -const char Console::kModuleName[] = "console"; +// static +void Console::Register(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> templ) { + v8::Local<v8::FunctionTemplate> log_templ = + v8::FunctionTemplate::New(isolate, Log); + log_templ->RemovePrototype(); -v8::Local<v8::Value> Console::GetModule(v8::Isolate* isolate) { - PerIsolateData* data = PerIsolateData::From(isolate); - v8::Local<ObjectTemplate> templ = data->GetObjectTemplate(&g_wrapper_info); - if (templ.IsEmpty()) { - templ = ObjectTemplateBuilder(isolate) - .SetMethod("log", Log) - .Build(); - data->SetObjectTemplate(&g_wrapper_info, templ); - } - return templ->NewInstance(isolate->GetCurrentContext()).ToLocalChecked(); + templ->Set(StringToSymbol(isolate, "log"), log_templ); } } // namespace gin diff --git a/chromium/gin/modules/console.h b/chromium/gin/modules/console.h index ff8061ba4a3..4b68aa1a54f 100644 --- a/chromium/gin/modules/console.h +++ b/chromium/gin/modules/console.h @@ -14,8 +14,8 @@ namespace gin { // we'd like to evolve the API to match window.console in browsers. class GIN_EXPORT Console { public: - static const char kModuleName[]; - static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); + static void Register(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> templ); }; } // namespace gin diff --git a/chromium/gin/modules/file_module_provider.cc b/chromium/gin/modules/file_module_provider.cc deleted file mode 100644 index 2edb6088d86..00000000000 --- a/chromium/gin/modules/file_module_provider.cc +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gin/modules/file_module_provider.h" - -#include <stddef.h> - -#include "base/bind.h" -#include "base/files/file_util.h" -#include "base/location.h" -#include "base/single_thread_task_runner.h" -#include "base/strings/string_split.h" -#include "base/threading/thread_task_runner_handle.h" -#include "gin/converter.h" - -namespace gin { - -namespace { - -void AttempToLoadModule(const base::WeakPtr<Runner>& runner, - const std::vector<base::FilePath>& search_paths, - const std::string& id) { - if (!runner) - return; - - std::vector<std::string> components = base::SplitString( - id, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); - - base::FilePath path; - for (size_t i = 0; i < components.size(); ++i) { - // TODO(abarth): Technically the path components can be UTF-8. We don't - // handle that case correctly yet. - path = path.AppendASCII(components[i]); - } - path = path.AddExtension(FILE_PATH_LITERAL("js")); - - for (size_t i = 0; i < search_paths.size(); ++i) { - std::string source; - if (!ReadFileToString(search_paths[i].Append(path), &source)) - continue; - - Runner::Scope scope(runner.get()); - runner->Run(source, id); - return; - } - LOG(ERROR) << "Failed to load module from disk: " << id; -} - -} // namespace - -FileModuleProvider::FileModuleProvider( - const std::vector<base::FilePath>& search_paths) - : search_paths_(search_paths) { -} - -FileModuleProvider::~FileModuleProvider() = default; - -void FileModuleProvider::AttempToLoadModules( - Runner* runner, const std::set<std::string>& ids) { - std::set<std::string> modules = ids; - for (std::set<std::string>::const_iterator it = modules.begin(); - it != modules.end(); ++it) { - const std::string& id = *it; - if (attempted_ids_.count(id)) - continue; - attempted_ids_.insert(id); - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::Bind(AttempToLoadModule, runner->GetWeakPtr(), - search_paths_, id)); - } -} - -} // namespace gin diff --git a/chromium/gin/modules/file_module_provider.h b/chromium/gin/modules/file_module_provider.h deleted file mode 100644 index 7c038879684..00000000000 --- a/chromium/gin/modules/file_module_provider.h +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GIN_MODULES_FILE_MODULE_PROVIDER_H_ -#define GIN_MODULES_FILE_MODULE_PROVIDER_H_ - -#include <set> -#include <string> -#include <vector> - -#include "base/files/file_path.h" -#include "base/macros.h" -#include "gin/gin_export.h" -#include "gin/runner.h" - -namespace gin { - -// FileModuleProvider knows how to load AMD modules off disk. It searches for -// modules in the directories indiciated by |search_paths|. Although we still -// read from the file system on the main thread, we'll eventually want to move -// the reads to a background thread. -class GIN_EXPORT FileModuleProvider { - public: - explicit FileModuleProvider( - const std::vector<base::FilePath>& search_paths); - ~FileModuleProvider(); - - // Searches for modules with |ids| in the file system. If found, the modules - // will be executed asynchronously by |runner|. - void AttempToLoadModules(Runner* runner, const std::set<std::string>& ids); - - private: - std::vector<base::FilePath> search_paths_; - - // We'll only search for a given module once. We remember the set of modules - // we've already looked for in |attempted_ids_|. - std::set<std::string> attempted_ids_; - - DISALLOW_COPY_AND_ASSIGN(FileModuleProvider); -}; - -} // namespace gin - -#endif // GIN_MODULES_FILE_MODULE_PROVIDER_H_ diff --git a/chromium/gin/modules/module_registry.cc b/chromium/gin/modules/module_registry.cc deleted file mode 100644 index cf61f7d8fe6..00000000000 --- a/chromium/gin/modules/module_registry.cc +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gin/modules/module_registry.h" - -#include <stddef.h> -#include <stdint.h> -#include <string> -#include <utility> -#include <vector> - -#include "base/logging.h" -#include "base/memory/ptr_util.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" - -using v8::Context; -using v8::External; -using v8::Function; -using v8::FunctionTemplate; -using v8::Isolate; -using v8::Local; -using v8::Object; -using v8::ObjectTemplate; -using v8::Persistent; -using v8::StackTrace; -using v8::String; -using v8::Value; - -namespace gin { - -struct PendingModule { - PendingModule(); - ~PendingModule(); - - std::string id; - std::vector<std::string> dependencies; - Persistent<Value> factory; -}; - -PendingModule::PendingModule() = default; - -PendingModule::~PendingModule() { - factory.Reset(); -} - -namespace { - -// Key for base::SupportsUserData::Data. -const char kModuleRegistryKey[] = "ModuleRegistry"; - -struct ModuleRegistryData : public base::SupportsUserData::Data { - std::unique_ptr<ModuleRegistry> registry; -}; - -void Define(const v8::FunctionCallbackInfo<Value>& info) { - Arguments args(info); - - if (!info.Length()) - return args.ThrowTypeError("At least one argument is required."); - - std::string id; - std::vector<std::string> dependencies; - v8::Local<Value> factory; - - if (!args.PeekNext().IsEmpty() && args.PeekNext()->IsString()) - args.GetNext(&id); - if (!args.PeekNext().IsEmpty() && args.PeekNext()->IsArray()) - args.GetNext(&dependencies); - if (!args.GetNext(&factory)) - return args.ThrowError(); - - std::unique_ptr<PendingModule> pending(new PendingModule); - pending->id = id; - pending->dependencies = dependencies; - pending->factory.Reset(args.isolate(), factory); - - ModuleRegistry* registry = - ModuleRegistry::From(args.isolate()->GetCurrentContext()); - registry->AddPendingModule(args.isolate(), std::move(pending)); -} - -WrapperInfo g_wrapper_info = { kEmbedderNativeGin }; - -Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) { - PerIsolateData* data = PerIsolateData::From(isolate); - Local<FunctionTemplate> templ = data->GetFunctionTemplate( - &g_wrapper_info); - if (templ.IsEmpty()) { - templ = FunctionTemplate::New(isolate, Define); - templ->RemovePrototype(); - data->SetFunctionTemplate(&g_wrapper_info, templ); - } - return templ; -} - -} // namespace - -ModuleRegistry::ModuleRegistry(Isolate* isolate) - : modules_(isolate, Object::New(isolate)) { -} - -ModuleRegistry::~ModuleRegistry() { - modules_.Reset(); -} - -// static -void ModuleRegistry::RegisterGlobals(Isolate* isolate, - v8::Local<ObjectTemplate> templ) { - templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate)); -} - -// static -bool ModuleRegistry::InstallGlobals(v8::Isolate* isolate, - v8::Local<v8::Object> obj) { - v8::Local<v8::Function> function; - auto maybe_function = - GetDefineTemplate(isolate)->GetFunction(isolate->GetCurrentContext()); - if (!maybe_function.ToLocal(&function)) - return false; - return SetProperty(isolate, obj, StringToSymbol(isolate, "define"), function); -} - -// static -ModuleRegistry* ModuleRegistry::From(v8::Local<Context> context) { - 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, base::WrapUnique(registry_data)); - } - 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, - v8::Local<Value> module) { - DCHECK(!id.empty()); - RegisterModule(isolate, id, module); -} - -void ModuleRegistry::AddPendingModule(Isolate* isolate, - std::unique_ptr<PendingModule> pending) { - const std::string pending_id = pending->id; - const std::vector<std::string> pending_dependencies = pending->dependencies; - AttemptToLoad(isolate, std::move(pending)); - for (auto& observer : observer_list_) - observer.OnDidAddPendingModule(pending_id, pending_dependencies); -} - -void ModuleRegistry::LoadModule(Isolate* isolate, - const std::string& id, - LoadModuleCallback callback) { - if (available_modules_.find(id) != available_modules_.end()) { - // Should we call the callback asynchronously? - callback.Run(GetModule(isolate, id)); - return; - } - waiting_callbacks_.insert(std::make_pair(id, callback)); - - for (size_t i = 0; i < pending_modules_.size(); ++i) { - if (pending_modules_[i]->id == id) - return; - } - - unsatisfied_dependencies_.insert(id); -} - -bool ModuleRegistry::RegisterModule(Isolate* isolate, - const std::string& id, - v8::Local<Value> module) { - if (id.empty() || module.IsEmpty()) - return false; - - v8::Local<Object> modules = Local<Object>::New(isolate, modules_); - if (!SetProperty(isolate, modules, StringToSymbol(isolate, id), module)) - return false; - unsatisfied_dependencies_.erase(id); - available_modules_.insert(id); - - std::pair<LoadModuleCallbackMap::iterator, LoadModuleCallbackMap::iterator> - range = waiting_callbacks_.equal_range(id); - std::vector<LoadModuleCallback> callbacks; - callbacks.reserve(waiting_callbacks_.count(id)); - for (LoadModuleCallbackMap::iterator it = range.first; it != range.second; - ++it) { - callbacks.push_back(it->second); - } - waiting_callbacks_.erase(range.first, range.second); - for (std::vector<LoadModuleCallback>::iterator it = callbacks.begin(); - it != callbacks.end(); - ++it) { - // Should we call the callback asynchronously? - it->Run(module); - } - return true; -} - -bool ModuleRegistry::CheckDependencies(PendingModule* pending) { - size_t num_missing_dependencies = 0; - size_t len = pending->dependencies.size(); - for (size_t i = 0; i < len; ++i) { - const std::string& dependency = pending->dependencies[i]; - if (available_modules_.count(dependency)) - continue; - unsatisfied_dependencies_.insert(dependency); - num_missing_dependencies++; - } - return num_missing_dependencies == 0; -} - -bool ModuleRegistry::Load(Isolate* isolate, - std::unique_ptr<PendingModule> pending) { - if (!pending->id.empty() && available_modules_.count(pending->id)) - return true; // We've already loaded this module. - - uint32_t argc = static_cast<uint32_t>(pending->dependencies.size()); - std::vector<v8::Local<Value> > argv(argc); - for (uint32_t i = 0; i < argc; ++i) - argv[i] = GetModule(isolate, pending->dependencies[i]); - - v8::Local<Value> module = Local<Value>::New(isolate, pending->factory); - - v8::Local<Function> factory; - if (ConvertFromV8(isolate, module, &factory)) { - PerContextData* data = PerContextData::From(isolate->GetCurrentContext()); - Runner* runner = data->runner(); - module = runner->Call(factory, runner->global(), argc, - argv.empty() ? NULL : &argv.front()); - if (pending->id.empty()) - ConvertFromV8(isolate, factory->GetScriptOrigin().ResourceName(), - &pending->id); - } - - return RegisterModule(isolate, pending->id, module); -} - -bool ModuleRegistry::AttemptToLoad(Isolate* isolate, - std::unique_ptr<PendingModule> pending) { - if (!CheckDependencies(pending.get())) { - pending_modules_.push_back(std::move(pending)); - return false; - } - return Load(isolate, std::move(pending)); -} - -v8::Local<v8::Value> ModuleRegistry::GetModule(v8::Isolate* isolate, - const std::string& id) { - v8::Local<Object> modules = Local<Object>::New(isolate, modules_); - v8::Local<String> key = StringToSymbol(isolate, id); - DCHECK(modules->HasOwnProperty(isolate->GetCurrentContext(), key).FromJust()); - return modules->Get(isolate->GetCurrentContext(), key).ToLocalChecked(); -} - -void ModuleRegistry::AttemptToLoadMoreModules(Isolate* isolate) { - bool keep_trying = true; - while (keep_trying) { - keep_trying = false; - PendingModuleVector pending_modules; - pending_modules.swap(pending_modules_); - for (size_t i = 0; i < pending_modules.size(); ++i) { - std::unique_ptr<PendingModule> pending(std::move(pending_modules[i])); - pending_modules[i] = NULL; - if (AttemptToLoad(isolate, std::move(pending))) - keep_trying = true; - } - } -} - -} // namespace gin diff --git a/chromium/gin/modules/module_registry.h b/chromium/gin/modules/module_registry.h deleted file mode 100644 index c1d3a002a2d..00000000000 --- a/chromium/gin/modules/module_registry.h +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GIN_MODULES_MODULE_REGISTRY_H_ -#define GIN_MODULES_MODULE_REGISTRY_H_ - -#include <list> -#include <map> -#include <memory> -#include <set> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "base/observer_list.h" -#include "gin/gin_export.h" -#include "v8/include/v8.h" - -namespace gin { - -class ModuleRegistryObserver; -struct PendingModule; - -// This class implements the Asynchronous Module Definition (AMD) API. -// https://github.com/amdjs/amdjs-api/wiki/AMD -// -// Our implementation isn't complete yet. Missing features: -// 1) Built-in support for require, exports, and module. -// 2) Path resoltuion in module names. -// -// For these reasons, we don't have an "amd" property on the "define" -// function. The spec says we should only add that property once our -// implementation complies with the specification. -// -class GIN_EXPORT ModuleRegistry { - public: - typedef base::Callback<void (v8::Local<v8::Value>)> LoadModuleCallback; - - virtual ~ModuleRegistry(); - - static ModuleRegistry* From(v8::Local<v8::Context> context); - - static void RegisterGlobals(v8::Isolate* isolate, - v8::Local<v8::ObjectTemplate> templ); - - // Installs the necessary functions needed for modules. - // WARNING: this may execute script in the page. - static bool InstallGlobals(v8::Isolate* isolate, v8::Local<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::Local<v8::Value> module); - - // The caller must have already entered our context. - void AddPendingModule(v8::Isolate* isolate, - std::unique_ptr<PendingModule> pending); - - void LoadModule(v8::Isolate* isolate, - const std::string& id, - LoadModuleCallback callback); - - // The caller must have already entered our context. - void AttemptToLoadMoreModules(v8::Isolate* isolate); - - const std::set<std::string>& available_modules() const { - return available_modules_; - } - - const std::set<std::string>& unsatisfied_dependencies() const { - return unsatisfied_dependencies_; - } - - private: - typedef std::vector<std::unique_ptr<PendingModule>> PendingModuleVector; - typedef std::multimap<std::string, LoadModuleCallback> LoadModuleCallbackMap; - - explicit ModuleRegistry(v8::Isolate* isolate); - - bool Load(v8::Isolate* isolate, std::unique_ptr<PendingModule> pending); - bool RegisterModule(v8::Isolate* isolate, - const std::string& id, - v8::Local<v8::Value> module); - - bool CheckDependencies(PendingModule* pending); - bool AttemptToLoad(v8::Isolate* isolate, - std::unique_ptr<PendingModule> pending); - - v8::Local<v8::Value> GetModule(v8::Isolate* isolate, const std::string& id); - - std::set<std::string> available_modules_; - std::set<std::string> unsatisfied_dependencies_; - - LoadModuleCallbackMap waiting_callbacks_; - - PendingModuleVector pending_modules_; - v8::Persistent<v8::Object> modules_; - - base::ObserverList<ModuleRegistryObserver> observer_list_; - - DISALLOW_COPY_AND_ASSIGN(ModuleRegistry); -}; - -} // namespace gin - -#endif // GIN_MODULES_MODULE_REGISTRY_H_ diff --git a/chromium/gin/modules/module_registry_observer.h b/chromium/gin/modules/module_registry_observer.h deleted file mode 100644 index 68ee4adc759..00000000000 --- a/chromium/gin/modules/module_registry_observer.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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/chromium/gin/modules/module_registry_unittest.cc b/chromium/gin/modules/module_registry_unittest.cc deleted file mode 100644 index 3921539016d..00000000000 --- a/chromium/gin/modules/module_registry_unittest.cc +++ /dev/null @@ -1,167 +0,0 @@ -// 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 <stdint.h> - -#include <memory> - -#include "base/bind.h" -#include "base/macros.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()) { - } - - ModuleRunnerDelegate delegate; - std::unique_ptr<ShellRunner> runner; - Runner::Scope scope; -}; - -class ModuleRegistryObserverImpl : public ModuleRegistryObserver { - public: - ModuleRegistryObserverImpl() : did_add_count_(0) {} - - 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); -}; - -void NestedCallback(v8::Local<v8::Value> value) { - FAIL() << "Should not be called"; -} - -void OnModuleLoaded(TestHelper* helper, - v8::Isolate* isolate, - int64_t* counter, - v8::Local<v8::Value> value) { - ASSERT_TRUE(value->IsNumber()); - v8::Local<v8::Integer> int_value = v8::Local<v8::Integer>::Cast(value); - *counter += int_value->Value(); - ModuleRegistry::From(helper->runner->GetContextHolder()->context()) - ->LoadModule(isolate, "two", base::Bind(NestedCallback)); -} - -void OnModuleLoadedNoOp(v8::Local<v8::Value> value) { - ASSERT_TRUE(value->IsNumber()); -} - -} // 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::Local<v8::Context> context = v8::Context::New( - instance_->isolate(), NULL, v8::Local<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]); -} - -// Verifies that multiple LoadModule calls for the same module are handled -// correctly. -TEST_F(ModuleRegistryTest, LoadModuleTest) { - TestHelper helper(instance_->isolate()); - int64_t counter = 0; - std::string source = - "define('one', [], function() {" - " return 1;" - "});"; - - ModuleRegistry::LoadModuleCallback callback = - base::Bind(OnModuleLoaded, &helper, instance_->isolate(), &counter); - for (int i = 0; i < 3; i++) { - ModuleRegistry::From(helper.runner->GetContextHolder()->context()) - ->LoadModule(instance_->isolate(), "one", callback); - } - EXPECT_EQ(0, counter); - helper.runner->Run(source, "script"); - EXPECT_EQ(3, counter); -} - -// Verifies that explicitly loading a module that's already pending does -// not cause the ModuleRegistry's unsatisfied_dependency set to grow. -TEST_F(ModuleRegistryTest, UnsatisfiedDependenciesTest) { - TestHelper helper(instance_->isolate()); - std::string source = - "define('one', ['no_such_module'], function(nsm) {" - " return 1;" - "});"; - ModuleRegistry* registry = - ModuleRegistry::From(helper.runner->GetContextHolder()->context()); - - std::set<std::string> no_such_module_set; - no_such_module_set.insert("no_such_module"); - - // Adds one unsatisfied dependency on "no-such-module". - helper.runner->Run(source, "script"); - EXPECT_EQ(no_such_module_set, registry->unsatisfied_dependencies()); - - // Should have no effect on the unsatisfied_dependencies set. - ModuleRegistry::LoadModuleCallback callback = base::Bind(OnModuleLoadedNoOp); - registry->LoadModule(instance_->isolate(), "one", callback); - EXPECT_EQ(no_such_module_set, registry->unsatisfied_dependencies()); -} - -} // namespace gin diff --git a/chromium/gin/modules/module_registry_unittests.js b/chromium/gin/modules/module_registry_unittests.js deleted file mode 100644 index ca7014899b3..00000000000 --- a/chromium/gin/modules/module_registry_unittests.js +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -define("module0", function() { - return { - "foo": "bar", - } -}); - -define("module2", [ - "gtest", - "module0", - "module1" - ], function(gtest, module0, module1) { - gtest.expectEqual(module0.foo, "bar", - "module0.foo is " + module0.foo); - gtest.expectFalse(module0.bar, - "module0.bar is " + module0.bar); - gtest.expectEqual(module1.baz, "qux", - "module1.baz is " + module1.baz); - gtest.expectFalse(module1.qux, - "module1.qux is " + module1.qux); - - this.result = "PASS"; -}); - -define("module1", { - "baz": "qux", -}); diff --git a/chromium/gin/modules/module_runner_delegate.cc b/chromium/gin/modules/module_runner_delegate.cc deleted file mode 100644 index 0634fff349b..00000000000 --- a/chromium/gin/modules/module_runner_delegate.cc +++ /dev/null @@ -1,66 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gin/modules/module_runner_delegate.h" - -#include "base/bind.h" -#include "base/bind_helpers.h" -#include "gin/modules/module_registry.h" -#include "gin/object_template_builder.h" -#include "gin/public/context_holder.h" - -namespace gin { - -ModuleRunnerDelegate::ModuleRunnerDelegate( - const std::vector<base::FilePath>& search_paths) - : module_provider_(search_paths) { -} - -ModuleRunnerDelegate::~ModuleRunnerDelegate() = default; - -void ModuleRunnerDelegate::AddBuiltinModule(const std::string& id, - ModuleGetter getter) { - builtin_modules_[id] = base::Bind(getter); -} - -void ModuleRunnerDelegate::AddBuiltinModule(const std::string& id, - const ModuleGetterCallback& getter) { - builtin_modules_[id] = getter; -} - -void ModuleRunnerDelegate::AttemptToLoadMoreModules(Runner* runner) { - ModuleRegistry* registry = ModuleRegistry::From( - runner->GetContextHolder()->context()); - registry->AttemptToLoadMoreModules(runner->GetContextHolder()->isolate()); - module_provider_.AttempToLoadModules( - runner, registry->unsatisfied_dependencies()); -} - -v8::Local<v8::ObjectTemplate> ModuleRunnerDelegate::GetGlobalTemplate( - ShellRunner* runner, - v8::Isolate* isolate) { - v8::Local<v8::ObjectTemplate> templ = ObjectTemplateBuilder(isolate).Build(); - ModuleRegistry::RegisterGlobals(isolate, templ); - return templ; -} - -void ModuleRunnerDelegate::DidCreateContext(ShellRunner* runner) { - ShellRunnerDelegate::DidCreateContext(runner); - - v8::Local<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(isolate, it->first, it->second.Run(isolate)); - } -} - -void ModuleRunnerDelegate::DidRunScript(ShellRunner* runner) { - AttemptToLoadMoreModules(runner); -} - -} // namespace gin diff --git a/chromium/gin/modules/module_runner_delegate.h b/chromium/gin/modules/module_runner_delegate.h deleted file mode 100644 index f49594c5318..00000000000 --- a/chromium/gin/modules/module_runner_delegate.h +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GIN_MODULES_MODULE_RUNNER_DELEGATE_H_ -#define GIN_MODULES_MODULE_RUNNER_DELEGATE_H_ - -#include <map> - -#include "base/callback.h" -#include "base/compiler_specific.h" -#include "base/macros.h" -#include "gin/gin_export.h" -#include "gin/modules/file_module_provider.h" -#include "gin/shell_runner.h" -#include "v8/include/v8.h" - -namespace gin { - -typedef v8::Local<v8::Value> (*ModuleGetter)(v8::Isolate* isolate); -typedef base::Callback<v8::Local<v8::Value>(v8::Isolate*)> ModuleGetterCallback; - -// 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 ShellRunnerDelegate { - public: - explicit ModuleRunnerDelegate( - const std::vector<base::FilePath>& search_paths); - ~ModuleRunnerDelegate() override; - - void AddBuiltinModule(const std::string& id, ModuleGetter getter); - void AddBuiltinModule(const std::string& id, - const ModuleGetterCallback& getter); - - protected: - void AttemptToLoadMoreModules(Runner* runner); - - private: - typedef std::map<std::string, ModuleGetterCallback> BuiltinModuleMap; - - // From ShellRunnerDelegate: - v8::Local<v8::ObjectTemplate> GetGlobalTemplate( - ShellRunner* runner, - v8::Isolate* isolate) override; - void DidCreateContext(ShellRunner* runner) override; - void DidRunScript(ShellRunner* runner) override; - - BuiltinModuleMap builtin_modules_; - FileModuleProvider module_provider_; - - DISALLOW_COPY_AND_ASSIGN(ModuleRunnerDelegate); -}; - -} // namespace gin - -#endif // GIN_MODULES_MODULE_RUNNER_DELEGATE_H_ diff --git a/chromium/gin/modules/timer.cc b/chromium/gin/modules/timer.cc deleted file mode 100644 index 1f609001ebe..00000000000 --- a/chromium/gin/modules/timer.cc +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gin/modules/timer.h" - -#include "base/bind.h" -#include "gin/object_template_builder.h" -#include "gin/per_context_data.h" - -namespace gin { - -namespace { - -v8::Local<v8::Private> GetHiddenPropertyName(v8::Isolate* isolate) { - return v8::Private::ForApi(isolate, gin::StringToV8(isolate, "::gin::Timer")); -} - -} // namespace - -// Timer ======================================================================= - -gin::WrapperInfo Timer::kWrapperInfo = { gin::kEmbedderNativeGin }; - -// static -Handle<Timer> Timer::Create(TimerType type, v8::Isolate* isolate, int delay_ms, - v8::Local<v8::Function> function) { - return CreateHandle(isolate, new Timer(isolate, type == TYPE_REPEATING, - delay_ms, function)); -} - -ObjectTemplateBuilder Timer::GetObjectTemplateBuilder(v8::Isolate* isolate) { - // We use Unretained() here because we directly own timer_, so we know it will - // be alive when these methods are called. - return Wrappable<Timer>::GetObjectTemplateBuilder(isolate) - .SetMethod("cancel", - base::Bind(&base::Timer::Stop, base::Unretained(&timer_))) - .SetMethod("reset", - base::Bind(&base::Timer::Reset, base::Unretained(&timer_))); -} - -Timer::Timer(v8::Isolate* isolate, bool repeating, int delay_ms, - v8::Local<v8::Function> function) - : timer_(false, repeating), - runner_(PerContextData::From( - isolate->GetCurrentContext())->runner()->GetWeakPtr()), - weak_factory_(this) { - GetWrapper(runner_->GetContextHolder()->isolate()) - .ToLocalChecked() - ->SetPrivate(isolate->GetCurrentContext(), GetHiddenPropertyName(isolate), - function) - .FromJust(); - timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms), - base::Bind(&Timer::OnTimerFired, weak_factory_.GetWeakPtr())); -} - -Timer::~Timer() = default; - -void Timer::OnTimerFired() { - // This can happen in spite of the weak callback because it is possible for - // a gin::Handle<> to keep this object alive past when the isolate it is part - // of is destroyed. - if (!runner_.get()) { - return; - } - - Runner::Scope scope(runner_.get()); - v8::Isolate* isolate = runner_->GetContextHolder()->isolate(); - - v8::Local<v8::Object> wrapper; - if (!GetWrapper(isolate).ToLocal(&wrapper)) { - return; - } - - v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast( - wrapper - ->GetPrivate(runner_->GetContextHolder()->context(), - GetHiddenPropertyName(isolate)) - .ToLocalChecked()); - runner_->Call(function, v8::Undefined(isolate), 0, NULL); -} - - -// TimerModule ================================================================= - -const char TimerModule::kName[] = "timer"; -WrapperInfo TimerModule::kWrapperInfo = { kEmbedderNativeGin }; - -// static -Handle<TimerModule> TimerModule::Create(v8::Isolate* isolate) { - return CreateHandle(isolate, new TimerModule()); -} - -// static -v8::Local<v8::Value> TimerModule::GetModule(v8::Isolate* isolate) { - return Create(isolate)->GetWrapper(isolate).ToLocalChecked(); -} - -TimerModule::TimerModule() = default; - -TimerModule::~TimerModule() = default; - -ObjectTemplateBuilder TimerModule::GetObjectTemplateBuilder( - v8::Isolate* isolate) { - return Wrappable<TimerModule>::GetObjectTemplateBuilder(isolate) - .SetMethod("createOneShot", - base::Bind(&Timer::Create, Timer::TYPE_ONE_SHOT)) - .SetMethod("createRepeating", - base::Bind(&Timer::Create, Timer::TYPE_REPEATING)); -} - -} // namespace gin diff --git a/chromium/gin/modules/timer.h b/chromium/gin/modules/timer.h deleted file mode 100644 index 1b7f6139eda..00000000000 --- a/chromium/gin/modules/timer.h +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef GIN_MODULES_TIMER_H_ -#define GIN_MODULES_TIMER_H_ - -#include "base/macros.h" -#include "base/memory/weak_ptr.h" -#include "base/timer/timer.h" -#include "gin/gin_export.h" -#include "gin/handle.h" -#include "gin/runner.h" -#include "gin/wrappable.h" -#include "v8/include/v8.h" - -namespace gin { - -class ObjectTemplateBuilder; - -// A simple scriptable timer that can work in one-shot or repeating mode. -class GIN_EXPORT Timer : public Wrappable<Timer> { - public: - enum TimerType { - TYPE_ONE_SHOT, - TYPE_REPEATING - }; - - static WrapperInfo kWrapperInfo; - static Handle<Timer> Create(TimerType type, v8::Isolate* isolate, - int delay_ms, v8::Local<v8::Function> function); - - ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) override; - - private: - Timer(v8::Isolate* isolate, bool repeating, int delay_ms, - v8::Local<v8::Function> function); - ~Timer() override; - void OnTimerFired(); - - base::Timer timer_; - base::WeakPtr<gin::Runner> runner_; - base::WeakPtrFactory<Timer> weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(Timer); -}; - - -class GIN_EXPORT TimerModule : public Wrappable<TimerModule> { - public: - static const char kName[]; - static WrapperInfo kWrapperInfo; - static Handle<TimerModule> Create(v8::Isolate* isolate); - static v8::Local<v8::Value> GetModule(v8::Isolate* isolate); - - private: - TimerModule(); - ~TimerModule() override; - - ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate* isolate) override; -}; - -} // namespace gin - -#endif // GIN_MODULES_TIMER_H_ diff --git a/chromium/gin/modules/timer_unittest.cc b/chromium/gin/modules/timer_unittest.cc deleted file mode 100644 index 2490d231960..00000000000 --- a/chromium/gin/modules/timer_unittest.cc +++ /dev/null @@ -1,148 +0,0 @@ -// Copyright 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "gin/modules/timer.h" - -#include <memory> - -#include "base/run_loop.h" -#include "base/single_thread_task_runner.h" -#include "gin/handle.h" -#include "gin/object_template_builder.h" -#include "gin/public/isolate_holder.h" -#include "gin/shell_runner.h" -#include "gin/test/v8_test.h" -#include "gin/try_catch.h" -#include "gin/wrappable.h" -#include "v8/include/v8.h" - -namespace gin { - -namespace { - -class Result : public Wrappable<Result> { - public: - static WrapperInfo kWrapperInfo; - static Handle<Result> Create(v8::Isolate* isolate) { - return CreateHandle(isolate, new Result()); - } - - int count() const { return count_; } - void set_count(int count) { count_ = count; } - - void Quit() { base::RunLoop::QuitCurrentDeprecated(); } - - private: - Result() : count_(0) { - } - - ~Result() override = default; - - ObjectTemplateBuilder GetObjectTemplateBuilder( - v8::Isolate* isolate) override { - return Wrappable<Result>::GetObjectTemplateBuilder(isolate) - .SetProperty("count", &Result::count, &Result::set_count) - .SetMethod("quit", &Result::Quit); - } - - int count_; -}; - -WrapperInfo Result::kWrapperInfo = { gin::kEmbedderNativeGin }; - -struct TestHelper { - TestHelper(v8::Isolate* isolate) - : runner(new ShellRunner(&delegate, isolate)), - scope(runner.get()), - timer_module(TimerModule::Create(isolate)), - result(Result::Create(isolate)) { - EXPECT_FALSE(runner->global().IsEmpty()); - runner->global()->Set(StringToV8(isolate, "timer"), - timer_module->GetWrapper(isolate).ToLocalChecked()); - runner->global()->Set(StringToV8(isolate, "result"), - result->GetWrapper(isolate).ToLocalChecked()); - } - - ShellRunnerDelegate delegate; - std::unique_ptr<ShellRunner> runner; - Runner::Scope scope; - Handle<TimerModule> timer_module; - Handle<Result> result; -}; - -} // namespace - -typedef V8Test TimerUnittest; - -TEST_F(TimerUnittest, OneShot) { - TestHelper helper(instance_->isolate()); - std::string source = - "timer.createOneShot(0, function() {" - " result.count++;" - "});"; - - helper.runner->Run(source, "script"); - EXPECT_EQ(0, helper.result->count()); - - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(1, helper.result->count()); -} - -TEST_F(TimerUnittest, OneShotCancel) { - TestHelper helper(instance_->isolate()); - std::string source = - "var t = timer.createOneShot(0, function() {" - " result.count++;" - "});" - "t.cancel()"; - - helper.runner->Run(source, "script"); - EXPECT_EQ(0, helper.result->count()); - - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0, helper.result->count()); -} - -TEST_F(TimerUnittest, Repeating) { - TestHelper helper(instance_->isolate()); - - // TODO(aa): Cannot do: if (++result.count == 3) because of v8 bug. Create - // test case and report. - std::string source = - "var t = timer.createRepeating(0, function() {" - " result.count++;" - " if (result.count == 3) {" - " /* Cancel the timer to prevent a hang when ScopedTaskEnvironment " - " flushes main thread tasks. */" - " t.cancel();" - " result.quit();" - " }" - "});"; - - helper.runner->Run(source, "script"); - EXPECT_EQ(0, helper.result->count()); - - base::RunLoop().Run(); - EXPECT_EQ(3, helper.result->count()); -} - -TEST_F(TimerUnittest, TimerCallbackToDestroyedRunner) { - TestHelper helper(instance_->isolate()); - std::string source = - "timer.createOneShot(0, function() {" - " result.count++;" - "});"; - - helper.runner->Run(source, "script"); - EXPECT_EQ(0, helper.result->count()); - - // Destroy runner, which should destroy the timer object we created. - helper.runner.reset(NULL); - base::RunLoop().RunUntilIdle(); - - // Timer should not have run because it was deleted. - EXPECT_EQ(0, helper.result->count()); -} - -} // namespace gin diff --git a/chromium/gin/object_template_builder.cc b/chromium/gin/object_template_builder.cc index c905efeeaa9..53ff01ba41a 100644 --- a/chromium/gin/object_template_builder.cc +++ b/chromium/gin/object_template_builder.cc @@ -49,7 +49,7 @@ IndexedPropertyInterceptor* IndexedInterceptorFromV8( return PerIsolateData::From(isolate)->GetIndexedPropertyInterceptor(base); } -void NamedPropertyGetter(v8::Local<v8::String> property, +void NamedPropertyGetter(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Value>& info) { v8::Isolate* isolate = info.GetIsolate(); NamedPropertyInterceptor* interceptor = @@ -61,7 +61,7 @@ void NamedPropertyGetter(v8::Local<v8::String> property, info.GetReturnValue().Set(interceptor->GetNamedProperty(isolate, name)); } -void NamedPropertySetter(v8::Local<v8::String> property, +void NamedPropertySetter(v8::Local<v8::Name> property, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { v8::Isolate* isolate = info.GetIsolate(); @@ -75,7 +75,7 @@ void NamedPropertySetter(v8::Local<v8::String> property, info.GetReturnValue().Set(value); } -void NamedPropertyQuery(v8::Local<v8::String> property, +void NamedPropertyQuery(v8::Local<v8::Name> property, const v8::PropertyCallbackInfo<v8::Integer>& info) { v8::Isolate* isolate = info.GetIsolate(); NamedPropertyInterceptor* interceptor = @@ -151,11 +151,10 @@ ObjectTemplateBuilder::ObjectTemplateBuilder( ObjectTemplateBuilder::~ObjectTemplateBuilder() = default; ObjectTemplateBuilder& ObjectTemplateBuilder::AddNamedPropertyInterceptor() { - template_->SetNamedPropertyHandler(&NamedPropertyGetter, - &NamedPropertySetter, - &NamedPropertyQuery, - NULL, - &NamedPropertyEnumerator); + template_->SetHandler(v8::NamedPropertyHandlerConfiguration( + &NamedPropertyGetter, &NamedPropertySetter, &NamedPropertyQuery, nullptr, + &NamedPropertyEnumerator, v8::Local<v8::Value>(), + v8::PropertyHandlerFlags::kOnlyInterceptStrings)); return *this; } diff --git a/chromium/gin/per_isolate_data.cc b/chromium/gin/per_isolate_data.cc index 0bc8bec5857..81f805779fc 100644 --- a/chromium/gin/per_isolate_data.cc +++ b/chromium/gin/per_isolate_data.cc @@ -31,7 +31,7 @@ PerIsolateData::PerIsolateData( : isolate_(isolate), allocator_(allocator) { isolate_->SetData(kEmbedderNativeGin, this); - task_runner = task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get(); + DCHECK(task_runner); if (access_mode == IsolateHolder::kUseLocker) { task_runner_ = std::make_shared<V8ForegroundTaskRunnerWithLocker>( isolate, task_runner); diff --git a/chromium/gin/public/isolate_holder.h b/chromium/gin/public/isolate_holder.h index f29b2dea766..8ce49ff6dc3 100644 --- a/chromium/gin/public/isolate_holder.h +++ b/chromium/gin/public/isolate_holder.h @@ -64,7 +64,8 @@ class GIN_EXPORT IsolateHolder { // This constructor is to create V8 snapshot for Blink. // Note this constructor calls isolate->Enter() internally. - explicit IsolateHolder(v8::StartupData* existing_blob); + IsolateHolder(scoped_refptr<base::SingleThreadTaskRunner> task_runner, + v8::StartupData* existing_blob); ~IsolateHolder(); diff --git a/chromium/gin/runner.h b/chromium/gin/runner.h index a898b035e55..928275d595b 100644 --- a/chromium/gin/runner.h +++ b/chromium/gin/runner.h @@ -25,10 +25,6 @@ class GIN_EXPORT Runner { // context by creating an instance of Runner::Scope on the stack. virtual void Run(const std::string& source, const std::string& resource_name) = 0; - virtual v8::Local<v8::Value> Call(v8::Local<v8::Function> function, - v8::Local<v8::Value> receiver, - int argc, - v8::Local<v8::Value> argv[]) = 0; virtual ContextHolder* GetContextHolder() = 0; v8::Local<v8::Object> global() { diff --git a/chromium/gin/shell/gin_main.cc b/chromium/gin/shell/gin_main.cc index 0b8f8b8597e..2340951f415 100644 --- a/chromium/gin/shell/gin_main.cc +++ b/chromium/gin/shell/gin_main.cc @@ -18,8 +18,9 @@ #include "base/threading/thread_task_runner_handle.h" #include "gin/array_buffer.h" #include "gin/modules/console.h" -#include "gin/modules/module_runner_delegate.h" +#include "gin/object_template_builder.h" #include "gin/public/isolate_holder.h" +#include "gin/shell_runner.h" #include "gin/try_catch.h" #include "gin/v8_initializer.h" @@ -40,20 +41,20 @@ void Run(base::WeakPtr<Runner> runner, const base::FilePath& path) { runner->Run(Load(path), path.AsUTF8Unsafe()); } -std::vector<base::FilePath> GetModuleSearchPaths() { - std::vector<base::FilePath> module_base(1); - CHECK(base::GetCurrentDirectory(&module_base[0])); - return module_base; -} - -class GinShellRunnerDelegate : public ModuleRunnerDelegate { +class GinShellRunnerDelegate : public ShellRunnerDelegate { public: - GinShellRunnerDelegate() : ModuleRunnerDelegate(GetModuleSearchPaths()) { - AddBuiltinModule(Console::kModuleName, Console::GetModule); + GinShellRunnerDelegate() {} + + v8::Local<v8::ObjectTemplate> GetGlobalTemplate( + ShellRunner* runner, + v8::Isolate* isolate) override { + v8::Local<v8::ObjectTemplate> templ = + ObjectTemplateBuilder(isolate).Build(); + gin::Console::Register(isolate, templ); + return templ; } void UnhandledException(ShellRunner* runner, TryCatch& try_catch) override { - ModuleRunnerDelegate::UnhandledException(runner, try_catch); LOG(ERROR) << try_catch.GetStackTrace(); } diff --git a/chromium/gin/shell/hello_world.js b/chromium/gin/shell/hello_world.js index 7216fbd18e2..6f09100043c 100644 --- a/chromium/gin/shell/hello_world.js +++ b/chromium/gin/shell/hello_world.js @@ -2,6 +2,4 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -define(["console"], function(console) { - console.log("Hello World"); -}); +log("Hello World"); diff --git a/chromium/gin/shell_runner.cc b/chromium/gin/shell_runner.cc index b98240a1db9..f0524289537 100644 --- a/chromium/gin/shell_runner.cc +++ b/chromium/gin/shell_runner.cc @@ -5,7 +5,6 @@ #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" @@ -76,24 +75,6 @@ void ShellRunner::Run(const std::string& source, Run(script); } -v8::Local<v8::Value> ShellRunner::Call(v8::Local<v8::Function> function, - v8::Local<v8::Value> receiver, - int argc, - v8::Local<v8::Value> argv[]) { - TryCatch try_catch(GetContextHolder()->isolate()); - delegate_->WillRunScript(this); - - auto maybe_result = - function->Call(GetContextHolder()->context(), receiver, argc, argv); - - delegate_->DidRunScript(this); - v8::Local<v8::Value> result; - if (!maybe_result.ToLocal(&result)) - delegate_->UnhandledException(this, try_catch); - - return result; -} - ContextHolder* ShellRunner::GetContextHolder() { return context_holder_.get(); } diff --git a/chromium/gin/shell_runner.h b/chromium/gin/shell_runner.h index f7651f04bbb..10c92df34e0 100644 --- a/chromium/gin/shell_runner.h +++ b/chromium/gin/shell_runner.h @@ -48,10 +48,6 @@ class GIN_EXPORT ShellRunner : public Runner { // Runner overrides: void Run(const std::string& source, const std::string& resource_name) override; - v8::Local<v8::Value> Call(v8::Local<v8::Function> function, - v8::Local<v8::Value> receiver, - int argc, - v8::Local<v8::Value> argv[]) override; ContextHolder* GetContextHolder() override; private: diff --git a/chromium/gin/v8_isolate_memory_dump_provider.cc b/chromium/gin/v8_isolate_memory_dump_provider.cc index b2d8b63e417..7549a99179c 100644 --- a/chromium/gin/v8_isolate_memory_dump_provider.cc +++ b/chromium/gin/v8_isolate_memory_dump_provider.cc @@ -8,7 +8,6 @@ #include <stddef.h> #include "base/strings/stringprintf.h" -#include "base/threading/thread_task_runner_handle.h" #include "base/trace_event/memory_dump_manager.h" #include "base/trace_event/process_memory_dump.h" #include "gin/public/isolate_holder.h" @@ -17,10 +16,12 @@ namespace gin { V8IsolateMemoryDumpProvider::V8IsolateMemoryDumpProvider( - IsolateHolder* isolate_holder) + IsolateHolder* isolate_holder, + scoped_refptr<base::SingleThreadTaskRunner> task_runner) : isolate_holder_(isolate_holder) { + DCHECK(task_runner); base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( - this, "V8Isolate", base::ThreadTaskRunnerHandle::Get()); + this, "V8Isolate", task_runner); } V8IsolateMemoryDumpProvider::~V8IsolateMemoryDumpProvider() { @@ -80,6 +81,36 @@ void DumpCodeStatistics( code_statistics.bytecode_and_metadata_size()); } +// Dump the number of native and detached contexts. +// The result looks as follows in the Chrome trace viewer: +// ====================================== +// Component object_count +// - v8 +// - isolate +// - contexts +// - detached_context 10 +// - native_context 20 +// ====================================== +void DumpContextStatistics( + base::trace_event::ProcessMemoryDump* process_memory_dump, + std::string dump_base_name, + size_t number_of_detached_contexts, + size_t number_of_native_contexts) { + std::string dump_name_prefix = dump_base_name + "/contexts"; + std::string native_context_name = dump_name_prefix + "/native_context"; + auto* native_context_dump = + process_memory_dump->CreateAllocatorDump(native_context_name); + native_context_dump->AddScalar( + "object_count", base::trace_event::MemoryAllocatorDump::kUnitsObjects, + number_of_native_contexts); + std::string detached_context_name = dump_name_prefix + "/detached_context"; + auto* detached_context_dump = + process_memory_dump->CreateAllocatorDump(detached_context_name); + detached_context_dump->AddScalar( + "object_count", base::trace_event::MemoryAllocatorDump::kUnitsObjects, + number_of_detached_contexts); +} + } // namespace anonymous void V8IsolateMemoryDumpProvider::DumpHeapStatistics( @@ -175,6 +206,10 @@ void V8IsolateMemoryDumpProvider::DumpHeapStatistics( system_allocator_name); } + DumpContextStatistics(process_memory_dump, dump_base_name, + heap_statistics.number_of_detached_contexts(), + heap_statistics.number_of_native_contexts()); + // Add an empty row for the heap_spaces. This is to keep the shape of the // dump stable, whether code stats are enabled or not. auto* heap_spaces_dump = diff --git a/chromium/gin/v8_isolate_memory_dump_provider.h b/chromium/gin/v8_isolate_memory_dump_provider.h index d70b790e0e0..b53d2a87ed5 100644 --- a/chromium/gin/v8_isolate_memory_dump_provider.h +++ b/chromium/gin/v8_isolate_memory_dump_provider.h @@ -8,6 +8,7 @@ #include <string> #include "base/macros.h" +#include "base/single_thread_task_runner.h" #include "base/trace_event/memory_dump_provider.h" #include "gin/gin_export.h" @@ -20,7 +21,9 @@ class IsolateHolder; class V8IsolateMemoryDumpProvider : public base::trace_event::MemoryDumpProvider { public: - explicit V8IsolateMemoryDumpProvider(IsolateHolder* isolate_holder); + V8IsolateMemoryDumpProvider( + IsolateHolder* isolate_holder, + scoped_refptr<base::SingleThreadTaskRunner> task_runner); ~V8IsolateMemoryDumpProvider() override; // MemoryDumpProvider implementation. diff --git a/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc b/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc index b04380a6804..a2ed23c18b6 100644 --- a/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc +++ b/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc @@ -52,4 +52,30 @@ TEST_F(V8MemoryDumpProviderTest, DumpStatistics) { ASSERT_TRUE(did_dump_objects_stats); } +TEST_F(V8MemoryDumpProviderTest, DumpContextStatistics) { + base::trace_event::MemoryDumpArgs dump_args = { + base::trace_event::MemoryDumpLevelOfDetail::LIGHT}; + std::unique_ptr<base::trace_event::ProcessMemoryDump> process_memory_dump( + new base::trace_event::ProcessMemoryDump(nullptr, dump_args)); + instance_->isolate_memory_dump_provider_for_testing()->OnMemoryDump( + dump_args, process_memory_dump.get()); + const base::trace_event::ProcessMemoryDump::AllocatorDumpsMap& + allocator_dumps = process_memory_dump->allocator_dumps(); + + bool did_dump_detached_contexts = false; + bool did_dump_native_contexts = false; + for (const auto& it : allocator_dumps) { + const std::string& dump_name = it.first; + if (dump_name.find("contexts/detached_context") != std::string::npos) { + did_dump_detached_contexts = true; + } + if (dump_name.find("contexts/native_context") != std::string::npos) { + did_dump_native_contexts = true; + } + } + + ASSERT_TRUE(did_dump_detached_contexts); + ASSERT_TRUE(did_dump_native_contexts); +} + } // namespace gin diff --git a/chromium/gin/wrappable_unittest.cc b/chromium/gin/wrappable_unittest.cc index e20850f9467..06fbd1851c4 100644 --- a/chromium/gin/wrappable_unittest.cc +++ b/chromium/gin/wrappable_unittest.cc @@ -153,10 +153,10 @@ TEST_F(WrappableTest, GetAndSetProperty) { EXPECT_FALSE(source.IsEmpty()); gin::TryCatch try_catch(isolate); - v8::Local<v8::Script> script = v8::Script::Compile(source); - EXPECT_FALSE(script.IsEmpty()); - v8::Local<v8::Value> val = script->Run(); - EXPECT_FALSE(val.IsEmpty()); + 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[] = { @@ -180,8 +180,10 @@ TEST_F(WrappableTest, CallAsFunction) { "obj(42, 2, 5);" "})"); gin::TryCatch try_catch(isolate); - v8::Local<v8::Script> script = v8::Script::Compile(source); - v8::Local<v8::Value> val = script->Run(); + 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[] = { @@ -203,8 +205,10 @@ TEST_F(WrappableTest, CallAsConstructor) { "new obj(42, 2, 5);" "})"); gin::TryCatch try_catch(isolate); - v8::Local<v8::Script> script = v8::Script::Compile(source); - v8::Local<v8::Value> val = script->Run(); + 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[] = { |