| 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 |