Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2964)

Unified Diff: gin/modules/module_registry.cc

Issue 62333018: Implement Asynchronous Module Definition API for Mojo (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address Aaron's comments Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gin/modules/module_registry.h ('k') | gin/modules/module_registry_unittests.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gin/modules/module_registry.cc
diff --git a/gin/modules/module_registry.cc b/gin/modules/module_registry.cc
new file mode 100644
index 0000000000000000000000000000000000000000..78a102c0a6da5186e83987ecef41716181d4c8f0
--- /dev/null
+++ b/gin/modules/module_registry.cc
@@ -0,0 +1,188 @@
+// 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 <assert.h>
+#include <string>
+#include <vector>
+#include "gin/arguments.h"
+#include "gin/converter.h"
+#include "gin/per_isolate_data.h"
+#include "gin/wrapper_info.h"
+
+using v8::External;
+using v8::Handle;
+using v8::Isolate;
+using v8::ObjectTemplate;
+
+namespace gin {
+
+struct PendingModule {
+ PendingModule();
+ ~PendingModule();
+
+ std::string id;
+ std::vector<std::string> dependencies;
+ v8::Persistent<v8::Value> factory;
+};
+
+namespace {
+
+void Define(const v8::FunctionCallbackInfo<v8::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;
+ Handle<v8::Value> factory;
+
+ if (args.PeekNext()->IsString())
+ args.GetNext(&id);
+ if (args.PeekNext()->IsArray())
+ args.GetNext(&dependencies);
+ if (!args.GetNext(&factory))
+ return args.ThrowError();
+
+ PendingModule* pending = new PendingModule;
+ pending->id = id;
+ pending->dependencies = dependencies;
+ pending->factory.Reset(args.isolate(), factory);
+
+ ModuleRegistry* registry =
+ ModuleRegistry::From(args.isolate()->GetCurrentContext());
+ registry->AddPendingModule(args.isolate(), pending);
+}
+
+WrapperInfo g_wrapper_info = {};
+
+v8::Local<v8::FunctionTemplate> GetDefineTemplate(v8::Isolate* isolate) {
+ PerIsolateData* data = PerIsolateData::From(isolate);
+ v8::Local<v8::FunctionTemplate> templ = data->GetFunctionTemplate(
+ &g_wrapper_info);
+ if (templ.IsEmpty()) {
+ templ = v8::FunctionTemplate::New(Define);
+ data->SetFunctionTemplate(&g_wrapper_info, templ);
+ }
+ return templ;
+}
+
+Handle<v8::String> GetHiddenValueKey(v8::Isolate* isolate) {
+ return StringToSymbol(isolate, "::gin::ModuleRegistry");
+}
+
+} // namespace
+
+
+PendingModule::PendingModule() {
+}
+
+PendingModule::~PendingModule() {
+ factory.Reset();
+}
+
+ModuleRegistry::ModuleRegistry(v8::Isolate* isolate)
+ : modules_(isolate, v8::Object::New()) {
+}
+
+ModuleRegistry::~ModuleRegistry() {
+ for (PendingModuleList::iterator it = pending_modules_.begin();
+ it != pending_modules_.end(); ++it) {
+ delete *it;
+ }
+ modules_.Reset();
+}
+
+void ModuleRegistry::RegisterGlobals(v8::Isolate* isolate,
+ Handle<v8::ObjectTemplate> templ) {
+ templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
+}
+
+void ModuleRegistry::AddBuiltinModule(Isolate* isolate,
+ const std::string& id,
+ Handle<ObjectTemplate> templ) {
+ assert(!id.empty());
+ Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_);
+ modules->Set(StringToV8(isolate, id), templ->NewInstance());
+}
+
+ModuleRegistry* ModuleRegistry::From(Handle<v8::Context> context) {
+ v8::Isolate* isolate = context->GetIsolate();
+ Handle<v8::String> key = GetHiddenValueKey(isolate);
+ Handle<v8::Value> value = context->Global()->GetHiddenValue(key);
+ Handle<v8::External> external;
+ if (value.IsEmpty() || !ConvertFromV8(value, &external)) {
+ PerContextData* data = PerContextData::From(context);
+ if (!data)
+ return NULL;
+ ModuleRegistry* registry = new ModuleRegistry(isolate);
+ context->Global()->SetHiddenValue(key, v8::External::New(registry));
+ data->AddSupplement(registry);
+ return registry;
+ }
+ return static_cast<ModuleRegistry*>(external->Value());
+}
+
+void ModuleRegistry::AddPendingModule(v8::Isolate* isolate,
+ PendingModule* pending) {
+ if (AttemptToLoad(isolate, pending))
+ AttemptToLoadPendingModules(isolate);
+}
+
+void ModuleRegistry::Detach(Handle<v8::Context> context) {
+ context->Global()->SetHiddenValue(GetHiddenValueKey(context->GetIsolate()),
+ Handle<v8::Value>());
+}
+
+bool ModuleRegistry::AttemptToLoad(v8::Isolate* isolate,
+ PendingModule* pending) {
+ Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_);
+ Handle<v8::String> key = StringToV8(isolate, pending->id);
+
+ if (!pending->id.empty() && modules->HasOwnProperty(key)) {
+ // We've already loaded a module with this name. Ignore the new one.
+ delete pending;
+ return true;
+ }
+
+ size_t argc = pending->dependencies.size();
+ std::vector<Handle<v8::Value> > argv(argc);
+ for (size_t i = 0; i < argc; ++i) {
+ Handle<v8::String> key = StringToV8(isolate, pending->dependencies[i]);
+ if (!modules->HasOwnProperty(key)) {
+ pending_modules_.push_back(pending);
+ return false;
+ }
+ argv[i] = modules->Get(key);
+ }
+
+ Handle<v8::Value> module = v8::Local<v8::Value>::New(
+ isolate, pending->factory);
+
+ Handle<v8::Function> factory;
+ if (ConvertFromV8(module, &factory)) {
+ v8::Handle<v8::Object> global = isolate->GetCurrentContext()->Global();
+ module = factory->Call(global, argc, argv.data());
+ // TODO(abarth): What should we do with exceptions?
+ }
+
+ if (!pending->id.empty() && !module.IsEmpty())
+ modules->Set(key, module);
+
+ delete pending;
+ return true;
+}
+
+void ModuleRegistry::AttemptToLoadPendingModules(v8::Isolate* isolate) {
+ PendingModuleList pending_modules;
+ pending_modules.swap(pending_modules_);
+ for (PendingModuleList::iterator it = pending_modules.begin();
+ it != pending_modules.end(); ++it) {
+ AttemptToLoad(isolate, *it);
+ }
+}
+
+} // namespace gin
« no previous file with comments | « gin/modules/module_registry.h ('k') | gin/modules/module_registry_unittests.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698