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

Side by Side Diff: gin/modules/module_registry.cc

Issue 74753002: Introduce gin_shell (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix more header nits 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_runner_delegate.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gin/modules/module_registry.h" 5 #include "gin/modules/module_registry.h"
6 6
7 #include <assert.h>
8 #include <string> 7 #include <string>
9 #include <vector> 8 #include <vector>
9
10 #include "base/logging.h"
10 #include "gin/arguments.h" 11 #include "gin/arguments.h"
11 #include "gin/converter.h" 12 #include "gin/converter.h"
12 #include "gin/per_isolate_data.h" 13 #include "gin/per_isolate_data.h"
13 #include "gin/wrapper_info.h" 14 #include "gin/wrapper_info.h"
14 15
16 using v8::Context;
15 using v8::External; 17 using v8::External;
18 using v8::Function;
19 using v8::FunctionCallbackInfo;
20 using v8::FunctionTemplate;
16 using v8::Handle; 21 using v8::Handle;
17 using v8::Isolate; 22 using v8::Isolate;
23 using v8::Local;
24 using v8::Object;
18 using v8::ObjectTemplate; 25 using v8::ObjectTemplate;
26 using v8::Persistent;
27 using v8::StackTrace;
28 using v8::String;
29 using v8::Value;
19 30
20 namespace gin { 31 namespace gin {
21 32
22 struct PendingModule { 33 struct PendingModule {
23 PendingModule(); 34 PendingModule();
24 ~PendingModule(); 35 ~PendingModule();
25 36
26 std::string id; 37 std::string id;
27 std::vector<std::string> dependencies; 38 std::vector<std::string> dependencies;
28 v8::Persistent<v8::Value> factory; 39 Persistent<Value> factory;
29 }; 40 };
30 41
42 PendingModule::PendingModule() {
43 }
44
45 PendingModule::~PendingModule() {
46 factory.Reset();
47 }
48
31 namespace { 49 namespace {
32 50
33 void Define(const v8::FunctionCallbackInfo<v8::Value>& info) { 51 void Define(const FunctionCallbackInfo<Value>& info) {
34 Arguments args(info); 52 Arguments args(info);
35 53
36 if (!info.Length()) 54 if (!info.Length())
37 return args.ThrowTypeError("At least one argument is required."); 55 return args.ThrowTypeError("At least one argument is required.");
38 56
39 std::string id; 57 std::string id;
40 std::vector<std::string> dependencies; 58 std::vector<std::string> dependencies;
41 Handle<v8::Value> factory; 59 Handle<Value> factory;
42 60
43 if (args.PeekNext()->IsString()) 61 if (args.PeekNext()->IsString())
44 args.GetNext(&id); 62 args.GetNext(&id);
45 if (args.PeekNext()->IsArray()) 63 if (args.PeekNext()->IsArray())
46 args.GetNext(&dependencies); 64 args.GetNext(&dependencies);
47 if (!args.GetNext(&factory)) 65 if (!args.GetNext(&factory))
48 return args.ThrowError(); 66 return args.ThrowError();
49 67
50 PendingModule* pending = new PendingModule; 68 scoped_ptr<PendingModule> pending(new PendingModule);
51 pending->id = id; 69 pending->id = id;
52 pending->dependencies = dependencies; 70 pending->dependencies = dependencies;
53 pending->factory.Reset(args.isolate(), factory); 71 pending->factory.Reset(args.isolate(), factory);
54 72
55 ModuleRegistry* registry = 73 ModuleRegistry* registry =
56 ModuleRegistry::From(args.isolate()->GetCurrentContext()); 74 ModuleRegistry::From(args.isolate()->GetCurrentContext());
57 registry->AddPendingModule(args.isolate(), pending); 75 registry->AddPendingModule(args.isolate(), pending.Pass());
58 } 76 }
59 77
60 WrapperInfo g_wrapper_info = {}; 78 WrapperInfo g_wrapper_info = {};
61 79
62 v8::Local<v8::FunctionTemplate> GetDefineTemplate(v8::Isolate* isolate) { 80 Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) {
63 PerIsolateData* data = PerIsolateData::From(isolate); 81 PerIsolateData* data = PerIsolateData::From(isolate);
64 v8::Local<v8::FunctionTemplate> templ = data->GetFunctionTemplate( 82 Local<FunctionTemplate> templ = data->GetFunctionTemplate(
65 &g_wrapper_info); 83 &g_wrapper_info);
66 if (templ.IsEmpty()) { 84 if (templ.IsEmpty()) {
67 templ = v8::FunctionTemplate::New(Define); 85 templ = FunctionTemplate::New(Define);
68 data->SetFunctionTemplate(&g_wrapper_info, templ); 86 data->SetFunctionTemplate(&g_wrapper_info, templ);
69 } 87 }
70 return templ; 88 return templ;
71 } 89 }
72 90
73 Handle<v8::String> GetHiddenValueKey(v8::Isolate* isolate) { 91 Handle<String> GetHiddenValueKey(Isolate* isolate) {
74 return StringToSymbol(isolate, "::gin::ModuleRegistry"); 92 return StringToSymbol(isolate, "::gin::ModuleRegistry");
75 } 93 }
76 94
95 std::string GetImplicitModuleName(const std::string& explicit_name) {
96 if (!explicit_name.empty())
97 return explicit_name;
98 std::string implicit_name;
99 Handle<StackTrace> trace = StackTrace::CurrentStackTrace(1);
100 Handle<String> script_name = trace->GetFrame(0)->GetScriptName();
101 if (!script_name.IsEmpty())
102 ConvertFromV8(script_name, &implicit_name);
103 return implicit_name;
104 }
105
77 } // namespace 106 } // namespace
78 107
79 108 ModuleRegistry::ModuleRegistry(Isolate* isolate)
80 PendingModule::PendingModule() { 109 : modules_(isolate, Object::New()) {
81 }
82
83 PendingModule::~PendingModule() {
84 factory.Reset();
85 }
86
87 ModuleRegistry::ModuleRegistry(v8::Isolate* isolate)
88 : modules_(isolate, v8::Object::New()) {
89 } 110 }
90 111
91 ModuleRegistry::~ModuleRegistry() { 112 ModuleRegistry::~ModuleRegistry() {
92 for (PendingModuleList::iterator it = pending_modules_.begin();
93 it != pending_modules_.end(); ++it) {
94 delete *it;
95 }
96 modules_.Reset(); 113 modules_.Reset();
97 } 114 }
98 115
99 void ModuleRegistry::RegisterGlobals(v8::Isolate* isolate, 116 void ModuleRegistry::RegisterGlobals(Isolate* isolate,
100 Handle<v8::ObjectTemplate> templ) { 117 Handle<ObjectTemplate> templ) {
101 templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate)); 118 templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
102 } 119 }
103 120
121 ModuleRegistry* ModuleRegistry::From(Handle<Context> context) {
122 Isolate* isolate = context->GetIsolate();
123 Handle<String> key = GetHiddenValueKey(isolate);
124 Handle<Value> value = context->Global()->GetHiddenValue(key);
125 Handle<External> external;
126 if (value.IsEmpty() || !ConvertFromV8(value, &external)) {
127 PerContextData* data = PerContextData::From(context);
128 if (!data)
129 return NULL;
130 ModuleRegistry* registry = new ModuleRegistry(isolate);
131 context->Global()->SetHiddenValue(key, External::New(isolate, registry));
132 data->AddSupplement(scoped_ptr<ContextSupplement>(registry));
133 return registry;
134 }
135 return static_cast<ModuleRegistry*>(external->Value());
136 }
137
104 void ModuleRegistry::AddBuiltinModule(Isolate* isolate, 138 void ModuleRegistry::AddBuiltinModule(Isolate* isolate,
105 const std::string& id, 139 const std::string& id,
106 Handle<ObjectTemplate> templ) { 140 Handle<ObjectTemplate> templ) {
107 assert(!id.empty()); 141 DCHECK(!id.empty());
108 Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_); 142 RegisterModule(isolate, id, templ->NewInstance());
109 modules->Set(StringToV8(isolate, id), templ->NewInstance());
110 } 143 }
111 144
112 ModuleRegistry* ModuleRegistry::From(Handle<v8::Context> context) { 145 void ModuleRegistry::AddPendingModule(Isolate* isolate,
113 v8::Isolate* isolate = context->GetIsolate(); 146 scoped_ptr<PendingModule> pending) {
114 Handle<v8::String> key = GetHiddenValueKey(isolate); 147 AttemptToLoad(isolate, pending.Pass());
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 } 148 }
128 149
129 void ModuleRegistry::AddPendingModule(v8::Isolate* isolate, 150 void ModuleRegistry::RegisterModule(Isolate* isolate,
130 PendingModule* pending) { 151 const std::string& id,
131 if (AttemptToLoad(isolate, pending)) 152 Handle<Value> module) {
132 AttemptToLoadPendingModules(isolate); 153 if (id.empty() || module.IsEmpty())
154 return;
155
156 unsatisfied_dependencies_.erase(id);
157 available_modules_.insert(id);
158 Handle<Object> modules = Local<Object>::New(isolate, modules_);
159 modules->Set(StringToSymbol(isolate, id), module);
133 } 160 }
134 161
135 void ModuleRegistry::Detach(Handle<v8::Context> context) { 162 void ModuleRegistry::Detach(Handle<Context> context) {
136 context->Global()->SetHiddenValue(GetHiddenValueKey(context->GetIsolate()), 163 context->Global()->SetHiddenValue(GetHiddenValueKey(context->GetIsolate()),
137 Handle<v8::Value>()); 164 Handle<Value>());
138 } 165 }
139 166
140 bool ModuleRegistry::AttemptToLoad(v8::Isolate* isolate, 167 bool ModuleRegistry::CheckDependencies(PendingModule* pending) {
141 PendingModule* pending) { 168 size_t num_missing_dependencies = 0;
142 Handle<v8::Object> modules = v8::Local<v8::Object>::New(isolate, modules_); 169 size_t len = pending->dependencies.size();
143 Handle<v8::String> key = StringToV8(isolate, pending->id); 170 for (size_t i = 0; i < len; ++i) {
171 const std::string& dependency = pending->dependencies[i];
172 if (available_modules_.count(dependency))
173 continue;
174 unsatisfied_dependencies_.insert(dependency);
175 num_missing_dependencies++;
176 }
177 return num_missing_dependencies == 0;
178 }
144 179
145 if (!pending->id.empty() && modules->HasOwnProperty(key)) { 180 void ModuleRegistry::Load(Isolate* isolate, scoped_ptr<PendingModule> pending) {
146 // We've already loaded a module with this name. Ignore the new one. 181 if (!pending->id.empty() && available_modules_.count(pending->id))
147 delete pending; 182 return; // We've already loaded this module.
148 return true;
149 }
150 183
184 Handle<Object> modules = Local<Object>::New(isolate, modules_);
151 size_t argc = pending->dependencies.size(); 185 size_t argc = pending->dependencies.size();
152 std::vector<Handle<v8::Value> > argv(argc); 186 std::vector<Handle<Value> > argv(argc);
153 for (size_t i = 0; i < argc; ++i) { 187 for (size_t i = 0; i < argc; ++i) {
154 Handle<v8::String> key = StringToV8(isolate, pending->dependencies[i]); 188 Handle<String> key = StringToSymbol(isolate, pending->dependencies[i]);
155 if (!modules->HasOwnProperty(key)) { 189 DCHECK(modules->HasOwnProperty(key));
156 pending_modules_.push_back(pending);
157 return false;
158 }
159 argv[i] = modules->Get(key); 190 argv[i] = modules->Get(key);
160 } 191 }
161 192
162 Handle<v8::Value> module = v8::Local<v8::Value>::New( 193 Handle<Value> module = Local<Value>::New(isolate, pending->factory);
163 isolate, pending->factory);
164 194
165 Handle<v8::Function> factory; 195 Handle<Function> factory;
166 if (ConvertFromV8(module, &factory)) { 196 if (ConvertFromV8(module, &factory)) {
167 v8::Handle<v8::Object> global = isolate->GetCurrentContext()->Global(); 197 Handle<Object> global = isolate->GetCurrentContext()->Global();
168 module = factory->Call(global, argc, argv.data()); 198 module = factory->Call(global, argc, argv.data());
169 // TODO(abarth): What should we do with exceptions? 199 // TODO(abarth): What should we do with exceptions?
170 } 200 }
171 201
172 if (!pending->id.empty() && !module.IsEmpty()) 202 RegisterModule(isolate, GetImplicitModuleName(pending->id), module);
173 modules->Set(key, module); 203 }
174 204
175 delete pending; 205 bool ModuleRegistry::AttemptToLoad(Isolate* isolate,
206 scoped_ptr<PendingModule> pending) {
207 if (!CheckDependencies(pending.get())) {
208 pending_modules_.push_back(pending.release());
209 return false;
210 }
211 Load(isolate, pending.Pass());
176 return true; 212 return true;
177 } 213 }
178 214
179 void ModuleRegistry::AttemptToLoadPendingModules(v8::Isolate* isolate) { 215 void ModuleRegistry::AttemptToLoadMoreModules(Isolate* isolate) {
180 PendingModuleList pending_modules; 216 bool keep_trying = true;
181 pending_modules.swap(pending_modules_); 217 while (keep_trying) {
182 for (PendingModuleList::iterator it = pending_modules.begin(); 218 keep_trying = false;
183 it != pending_modules.end(); ++it) { 219 PendingModuleVector pending_modules;
184 AttemptToLoad(isolate, *it); 220 pending_modules.swap(pending_modules_);
221 for (size_t i = 0; i < pending_modules.size(); ++i) {
222 scoped_ptr<PendingModule> pending(pending_modules[i]);
223 pending_modules[i] = NULL;
224 if (AttemptToLoad(isolate, pending.Pass()))
225 keep_trying = true;
226 }
185 } 227 }
186 } 228 }
187 229
188 } // namespace gin 230 } // namespace gin
OLDNEW
« no previous file with comments | « gin/modules/module_registry.h ('k') | gin/modules/module_runner_delegate.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698