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

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

Powered by Google App Engine
This is Rietveld 408576698