OLD | NEW |
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 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "gin/arguments.h" | 11 #include "gin/arguments.h" |
12 #include "gin/converter.h" | 12 #include "gin/converter.h" |
13 #include "gin/per_isolate_data.h" | 13 #include "gin/per_isolate_data.h" |
| 14 #include "gin/public/context_holder.h" |
14 #include "gin/public/wrapper_info.h" | 15 #include "gin/public/wrapper_info.h" |
15 #include "gin/runner.h" | 16 #include "gin/runner.h" |
16 | 17 |
17 using v8::Context; | 18 using v8::Context; |
18 using v8::External; | 19 using v8::External; |
19 using v8::Function; | 20 using v8::Function; |
20 using v8::FunctionTemplate; | 21 using v8::FunctionTemplate; |
21 using v8::Isolate; | 22 using v8::Isolate; |
22 using v8::Local; | 23 using v8::Local; |
23 using v8::Object; | 24 using v8::Object; |
24 using v8::ObjectTemplate; | 25 using v8::ObjectTemplate; |
25 using v8::Persistent; | 26 using v8::Persistent; |
26 using v8::StackTrace; | 27 using v8::StackTrace; |
27 using v8::String; | 28 using v8::String; |
28 using v8::Value; | 29 using v8::Value; |
29 | 30 |
30 namespace gin { | 31 namespace gin { |
31 | 32 |
32 struct PendingModule { | |
33 PendingModule(); | |
34 ~PendingModule(); | |
35 | |
36 std::string id; | |
37 std::vector<std::string> dependencies; | |
38 Persistent<Value> factory; | |
39 }; | |
40 | |
41 PendingModule::PendingModule() { | 33 PendingModule::PendingModule() { |
42 } | 34 } |
43 | 35 |
44 PendingModule::~PendingModule() { | 36 PendingModule::~PendingModule() { |
45 factory.Reset(); | 37 factory.Reset(); |
46 } | 38 } |
47 | 39 |
48 namespace { | 40 namespace { |
49 | 41 |
50 void Define(const v8::FunctionCallbackInfo<Value>& info) { | 42 void Define(const v8::FunctionCallbackInfo<Value>& info) { |
(...skipping 11 matching lines...) Expand all Loading... |
62 if (args.PeekNext()->IsArray()) | 54 if (args.PeekNext()->IsArray()) |
63 args.GetNext(&dependencies); | 55 args.GetNext(&dependencies); |
64 if (!args.GetNext(&factory)) | 56 if (!args.GetNext(&factory)) |
65 return args.ThrowError(); | 57 return args.ThrowError(); |
66 | 58 |
67 scoped_ptr<PendingModule> pending(new PendingModule); | 59 scoped_ptr<PendingModule> pending(new PendingModule); |
68 pending->id = id; | 60 pending->id = id; |
69 pending->dependencies = dependencies; | 61 pending->dependencies = dependencies; |
70 pending->factory.Reset(args.isolate(), factory); | 62 pending->factory.Reset(args.isolate(), factory); |
71 | 63 |
72 ModuleRegistry* registry = | 64 ModuleLoader* loader = |
73 ModuleRegistry::From(args.isolate()->GetCurrentContext()); | 65 ModuleLoader::From(args.isolate()->GetCurrentContext()); |
74 registry->AddPendingModule(args.isolate(), pending.Pass()); | 66 loader->Load(args.isolate()->GetCurrentContext(), pending.Pass()); |
75 } | 67 } |
76 | 68 |
77 WrapperInfo g_wrapper_info = { kEmbedderNativeGin }; | 69 WrapperInfo g_wrapper_info = { kEmbedderNativeGin }; |
78 | 70 |
79 Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) { | 71 Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) { |
80 PerIsolateData* data = PerIsolateData::From(isolate); | 72 PerIsolateData* data = PerIsolateData::From(isolate); |
81 Local<FunctionTemplate> templ = data->GetFunctionTemplate( | 73 Local<FunctionTemplate> templ = data->GetFunctionTemplate( |
82 &g_wrapper_info); | 74 &g_wrapper_info); |
83 if (templ.IsEmpty()) { | 75 if (templ.IsEmpty()) { |
84 templ = FunctionTemplate::New(isolate, Define); | 76 templ = FunctionTemplate::New(isolate, Define); |
85 data->SetFunctionTemplate(&g_wrapper_info, templ); | 77 data->SetFunctionTemplate(&g_wrapper_info, templ); |
86 } | 78 } |
87 return templ; | 79 return templ; |
88 } | 80 } |
89 | 81 |
90 v8::Handle<String> GetHiddenValueKey(Isolate* isolate) { | 82 v8::Handle<String> GetModuleRegistryHiddenValueKey(Isolate* isolate) { |
91 return StringToSymbol(isolate, "::gin::ModuleRegistry"); | 83 return StringToSymbol(isolate, "::gin::ModuleRegistry"); |
92 } | 84 } |
93 | 85 |
| 86 v8::Handle<String> GetModuleLoaderHiddenValueKey(Isolate* isolate) { |
| 87 return StringToSymbol(isolate, "::gin::ModuleLoader"); |
| 88 } |
| 89 |
94 } // namespace | 90 } // namespace |
95 | 91 |
| 92 ModuleLoader* ModuleLoader::From(v8::Handle<Context> context) { |
| 93 Isolate* isolate = context->GetIsolate(); |
| 94 v8::Handle<String> key = GetModuleLoaderHiddenValueKey(isolate); |
| 95 v8::Handle<Value> value = context->Global()->GetHiddenValue(key); |
| 96 v8::Handle<External> external; |
| 97 return (value.IsEmpty() || !ConvertFromV8(isolate, value, &external)) ? |
| 98 NULL : static_cast<ModuleLoader*>(external->Value()); |
| 99 } |
| 100 |
| 101 ModuleLoader::ModuleLoader(v8::Handle<Context> context) { |
| 102 Isolate* isolate = context->GetIsolate(); |
| 103 v8::Handle<String> key = GetModuleLoaderHiddenValueKey(isolate); |
| 104 v8::Handle<Value> value = context->Global()->GetHiddenValue(key); |
| 105 v8::Handle<External> external; |
| 106 DCHECK(value.IsEmpty() || !ConvertFromV8(isolate, value, &external)); |
| 107 PerContextData* data = PerContextData::From(context); |
| 108 DCHECK(data); |
| 109 context->Global()->SetHiddenValue(key, External::New(isolate, this)); |
| 110 data->AddSupplement(scoped_ptr<ContextSupplement>(this)); |
| 111 } |
| 112 |
| 113 ModuleLoader::~ModuleLoader() { |
| 114 } |
| 115 |
| 116 // static |
| 117 void ModuleLoader::RegisterGlobals(Isolate* isolate, |
| 118 v8::Handle<ObjectTemplate> templ) { |
| 119 templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate)); |
| 120 } |
| 121 |
| 122 // static |
| 123 void ModuleLoader::RegisterGlobalsObject(v8::Isolate* isolate, |
| 124 v8::Handle<v8::Object> obj) { |
| 125 obj->Set(StringToSymbol(isolate, "define"), |
| 126 GetDefineTemplate(isolate)->GetFunction()); |
| 127 } |
| 128 |
| 129 void ModuleLoader::Detach(v8::Handle<Context> context) { |
| 130 context->Global()->SetHiddenValue(GetModuleLoaderHiddenValueKey( |
| 131 context->GetIsolate()), |
| 132 v8::Handle<Value>()); |
| 133 } |
| 134 |
96 ModuleRegistry::ModuleRegistry(Isolate* isolate) | 135 ModuleRegistry::ModuleRegistry(Isolate* isolate) |
97 : modules_(isolate, Object::New(isolate)) { | 136 : modules_(isolate, Object::New(isolate)) { |
98 } | 137 } |
99 | 138 |
100 ModuleRegistry::~ModuleRegistry() { | 139 ModuleRegistry::~ModuleRegistry() { |
101 modules_.Reset(); | 140 modules_.Reset(); |
102 } | 141 } |
103 | 142 |
104 void ModuleRegistry::RegisterGlobals(Isolate* isolate, | 143 // static |
105 v8::Handle<ObjectTemplate> templ) { | |
106 templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate)); | |
107 } | |
108 | |
109 ModuleRegistry* ModuleRegistry::From(v8::Handle<Context> context) { | 144 ModuleRegistry* ModuleRegistry::From(v8::Handle<Context> context) { |
110 Isolate* isolate = context->GetIsolate(); | 145 Isolate* isolate = context->GetIsolate(); |
111 v8::Handle<String> key = GetHiddenValueKey(isolate); | 146 v8::Handle<String> key = GetModuleRegistryHiddenValueKey(isolate); |
112 v8::Handle<Value> value = context->Global()->GetHiddenValue(key); | 147 v8::Handle<Value> value = context->Global()->GetHiddenValue(key); |
113 v8::Handle<External> external; | 148 v8::Handle<External> external; |
114 if (value.IsEmpty() || !ConvertFromV8(isolate, value, &external)) { | 149 if (value.IsEmpty() || !ConvertFromV8(isolate, value, &external)) { |
115 PerContextData* data = PerContextData::From(context); | 150 PerContextData* data = PerContextData::From(context); |
116 if (!data) | 151 if (!data) |
117 return NULL; | 152 return NULL; |
118 ModuleRegistry* registry = new ModuleRegistry(isolate); | 153 ModuleRegistry* registry = new ModuleRegistry(isolate); |
119 context->Global()->SetHiddenValue(key, External::New(isolate, registry)); | 154 context->Global()->SetHiddenValue(key, External::New(isolate, registry)); |
120 data->AddSupplement(scoped_ptr<ContextSupplement>(registry)); | 155 data->AddSupplement(scoped_ptr<ContextSupplement>(registry)); |
121 return registry; | 156 return registry; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 LoadModuleCallbackMap::iterator it = waiting_callbacks_.find(id); | 197 LoadModuleCallbackMap::iterator it = waiting_callbacks_.find(id); |
163 if (it == waiting_callbacks_.end()) | 198 if (it == waiting_callbacks_.end()) |
164 return; | 199 return; |
165 LoadModuleCallback callback = it->second; | 200 LoadModuleCallback callback = it->second; |
166 waiting_callbacks_.erase(it); | 201 waiting_callbacks_.erase(it); |
167 // Should we call the callback asynchronously? | 202 // Should we call the callback asynchronously? |
168 callback.Run(module); | 203 callback.Run(module); |
169 } | 204 } |
170 | 205 |
171 void ModuleRegistry::Detach(v8::Handle<Context> context) { | 206 void ModuleRegistry::Detach(v8::Handle<Context> context) { |
172 context->Global()->SetHiddenValue(GetHiddenValueKey(context->GetIsolate()), | 207 context->Global()->SetHiddenValue(GetModuleRegistryHiddenValueKey( |
| 208 context->GetIsolate()), |
173 v8::Handle<Value>()); | 209 v8::Handle<Value>()); |
174 } | 210 } |
175 | 211 |
176 bool ModuleRegistry::CheckDependencies(PendingModule* pending) { | 212 bool ModuleRegistry::CheckDependencies(PendingModule* pending) { |
177 size_t num_missing_dependencies = 0; | 213 size_t num_missing_dependencies = 0; |
178 size_t len = pending->dependencies.size(); | 214 size_t len = pending->dependencies.size(); |
179 for (size_t i = 0; i < len; ++i) { | 215 for (size_t i = 0; i < len; ++i) { |
180 const std::string& dependency = pending->dependencies[i]; | 216 const std::string& dependency = pending->dependencies[i]; |
181 if (available_modules_.count(dependency)) | 217 if (available_modules_.count(dependency)) |
182 continue; | 218 continue; |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
238 for (size_t i = 0; i < pending_modules.size(); ++i) { | 274 for (size_t i = 0; i < pending_modules.size(); ++i) { |
239 scoped_ptr<PendingModule> pending(pending_modules[i]); | 275 scoped_ptr<PendingModule> pending(pending_modules[i]); |
240 pending_modules[i] = NULL; | 276 pending_modules[i] = NULL; |
241 if (AttemptToLoad(isolate, pending.Pass())) | 277 if (AttemptToLoad(isolate, pending.Pass())) |
242 keep_trying = true; | 278 keep_trying = true; |
243 } | 279 } |
244 } | 280 } |
245 } | 281 } |
246 | 282 |
247 } // namespace gin | 283 } // namespace gin |
OLD | NEW |