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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « gin/modules/module_registry.h ('k') | gin/modules/module_registry_unittests.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gin/modules/module_registry.h"
6
7 #include <assert.h>
8 #include <string>
9 #include <vector>
10 #include "gin/arguments.h"
11 #include "gin/converter.h"
12 #include "gin/per_isolate_data.h"
13 #include "gin/wrapper_info.h"
14
15 using v8::External;
16 using v8::Handle;
17 using v8::Isolate;
18 using v8::ObjectTemplate;
19
20 namespace gin {
21
22 struct PendingModule {
23 PendingModule();
24 ~PendingModule();
25
26 std::string id;
27 std::vector<std::string> dependencies;
28 v8::Persistent<v8::Value> factory;
29 };
30
31 namespace {
32
33 void Define(const v8::FunctionCallbackInfo<v8::Value>& info) {
34 Arguments args(info);
35
36 if (!info.Length())
37 return args.ThrowTypeError("At least one argument is required.");
38
39 std::string id;
40 std::vector<std::string> dependencies;
41 Handle<v8::Value> factory;
42
43 if (args.PeekNext()->IsString())
44 args.GetNext(&id);
45 if (args.PeekNext()->IsArray())
46 args.GetNext(&dependencies);
47 if (!args.GetNext(&factory))
48 return args.ThrowError();
49
50 PendingModule* pending = new PendingModule;
51 pending->id = id;
52 pending->dependencies = dependencies;
53 pending->factory.Reset(args.isolate(), factory);
54
55 ModuleRegistry* registry =
56 ModuleRegistry::From(args.isolate()->GetCurrentContext());
57 registry->AddPendingModule(args.isolate(), pending);
58 }
59
60 WrapperInfo g_wrapper_info = {};
61
62 v8::Local<v8::FunctionTemplate> GetDefineTemplate(v8::Isolate* isolate) {
63 PerIsolateData* data = PerIsolateData::From(isolate);
64 v8::Local<v8::FunctionTemplate> templ = data->GetFunctionTemplate(
65 &g_wrapper_info);
66 if (templ.IsEmpty()) {
67 templ = v8::FunctionTemplate::New(Define);
68 data->SetFunctionTemplate(&g_wrapper_info, templ);
69 }
70 return templ;
71 }
72
73 Handle<v8::String> GetHiddenValueKey(v8::Isolate* isolate) {
74 return StringToSymbol(isolate, "::gin::ModuleRegistry");
75 }
76
77 } // namespace
78
79
80 PendingModule::PendingModule() {
81 }
82
83 PendingModule::~PendingModule() {
84 factory.Reset();
85 }
86
87 ModuleRegistry::ModuleRegistry(v8::Isolate* isolate)
88 : modules_(isolate, v8::Object::New()) {
89 }
90
91 ModuleRegistry::~ModuleRegistry() {
92 for (PendingModuleList::iterator it = pending_modules_.begin();
93 it != pending_modules_.end(); ++it) {
94 delete *it;
95 }
96 modules_.Reset();
97 }
98
99 void ModuleRegistry::RegisterGlobals(v8::Isolate* isolate,
100 Handle<v8::ObjectTemplate> templ) {
101 templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
102 }
103
104 void ModuleRegistry::AddBuiltinModule(Isolate* isolate,
105 const std::string& id,
106 Handle<ObjectTemplate> templ) {
107 assert(!id.empty());
108 Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_);
109 modules->Set(StringToV8(isolate, id), templ->NewInstance());
110 }
111
112 ModuleRegistry* ModuleRegistry::From(Handle<v8::Context> context) {
113 v8::Isolate* isolate = context->GetIsolate();
114 Handle<v8::String> key = GetHiddenValueKey(isolate);
115 Handle<v8::Value> value = context->Global()->GetHiddenValue(key);
116 Handle<v8::External> external;
117 if (value.IsEmpty() || !ConvertFromV8(value, &external)) {
118 PerContextData* data = PerContextData::From(context);
119 if (!data)
120 return NULL;
121 ModuleRegistry* registry = new ModuleRegistry(isolate);
122 context->Global()->SetHiddenValue(key, v8::External::New(registry));
123 data->AddSupplement(registry);
124 return registry;
125 }
126 return static_cast<ModuleRegistry*>(external->Value());
127 }
128
129 void ModuleRegistry::AddPendingModule(v8::Isolate* isolate,
130 PendingModule* pending) {
131 if (AttemptToLoad(isolate, pending))
132 AttemptToLoadPendingModules(isolate);
133 }
134
135 void ModuleRegistry::Detach(Handle<v8::Context> context) {
136 context->Global()->SetHiddenValue(GetHiddenValueKey(context->GetIsolate()),
137 Handle<v8::Value>());
138 }
139
140 bool ModuleRegistry::AttemptToLoad(v8::Isolate* isolate,
141 PendingModule* pending) {
142 Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_);
143 Handle<v8::String> key = StringToV8(isolate, pending->id);
144
145 if (!pending->id.empty() && modules->HasOwnProperty(key)) {
146 // We've already loaded a module with this name. Ignore the new one.
147 delete pending;
148 return true;
149 }
150
151 size_t argc = pending->dependencies.size();
152 std::vector<Handle<v8::Value> > argv(argc);
153 for (size_t i = 0; i < argc; ++i) {
154 Handle<v8::String> key = StringToV8(isolate, pending->dependencies[i]);
155 if (!modules->HasOwnProperty(key)) {
156 pending_modules_.push_back(pending);
157 return false;
158 }
159 argv[i] = modules->Get(key);
160 }
161
162 Handle<v8::Value> module = v8::Local<v8::Value>::New(
163 isolate, pending->factory);
164
165 Handle<v8::Function> factory;
166 if (ConvertFromV8(module, &factory)) {
167 v8::Handle<v8::Object> global = isolate->GetCurrentContext()->Global();
168 module = factory->Call(global, argc, argv.data());
169 // TODO(abarth): What should we do with exceptions?
170 }
171
172 if (!pending->id.empty() && !module.IsEmpty())
173 modules->Set(key, module);
174
175 delete pending;
176 return true;
177 }
178
179 void ModuleRegistry::AttemptToLoadPendingModules(v8::Isolate* isolate) {
180 PendingModuleList pending_modules;
181 pending_modules.swap(pending_modules_);
182 for (PendingModuleList::iterator it = pending_modules.begin();
183 it != pending_modules.end(); ++it) {
184 AttemptToLoad(isolate, *it);
185 }
186 }
187
188 } // namespace gin
OLDNEW
« 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