1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 2f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// found in the LICENSE file. 4f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gin/modules/module_registry.h" 6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <string> 8f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include <vector> 9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/logging.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gin/arguments.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gin/converter.h" 13a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/modules/module_registry_observer.h" 14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "gin/per_context_data.h" 15f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gin/per_isolate_data.h" 16f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gin/public/wrapper_info.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "gin/runner.h" 18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::Context; 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::External; 21f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::Function; 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::FunctionTemplate; 23f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::Isolate; 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::Local; 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::Object; 26f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::ObjectTemplate; 27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::Persistent; 28f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::StackTrace; 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::String; 30f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)using v8::Value; 31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 32f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace gin { 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct PendingModule { 35f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PendingModule(); 36f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ~PendingModule(); 37f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 38f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string id; 39f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::vector<std::string> dependencies; 40f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Persistent<Value> factory; 41f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}; 42f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 43f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)PendingModule::PendingModule() { 44f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 45f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 46f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)PendingModule::~PendingModule() { 47f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) factory.Reset(); 48f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 49f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)namespace { 51f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Key for base::SupportsUserData::Data. 53a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)const char kModuleRegistryKey[] = "ModuleRegistry"; 54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)struct ModuleRegistryData : public base::SupportsUserData::Data { 56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<ModuleRegistry> registry; 57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}; 58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void Define(const v8::FunctionCallbackInfo<Value>& info) { 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Arguments args(info); 61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!info.Length()) 63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return args.ThrowTypeError("At least one argument is required."); 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::string id; 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::vector<std::string> dependencies; 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<Value> factory; 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (args.PeekNext()->IsString()) 70f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) args.GetNext(&id); 71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (args.PeekNext()->IsArray()) 72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) args.GetNext(&dependencies); 73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!args.GetNext(&factory)) 74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return args.ThrowError(); 75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<PendingModule> pending(new PendingModule); 77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending->id = id; 78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending->dependencies = dependencies; 79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending->factory.Reset(args.isolate(), factory); 80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ModuleRegistry* registry = 82f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ModuleRegistry::From(args.isolate()->GetCurrentContext()); 83f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) registry->AddPendingModule(args.isolate(), pending.Pass()); 84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)WrapperInfo g_wrapper_info = { kEmbedderNativeGin }; 87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 88f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)Local<FunctionTemplate> GetDefineTemplate(Isolate* isolate) { 89f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PerIsolateData* data = PerIsolateData::From(isolate); 90f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Local<FunctionTemplate> templ = data->GetFunctionTemplate( 91f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &g_wrapper_info); 92f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (templ.IsEmpty()) { 93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) templ = FunctionTemplate::New(isolate, Define); 94f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) data->SetFunctionTemplate(&g_wrapper_info, templ); 95f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 96f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return templ; 97f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 99f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace 100f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 101f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ModuleRegistry::ModuleRegistry(Isolate* isolate) 1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : modules_(isolate, Object::New(isolate)) { 103f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ModuleRegistry::~ModuleRegistry() { 106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modules_.Reset(); 107f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 108f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 109a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 110f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ModuleRegistry::RegisterGlobals(Isolate* isolate, 111f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<ObjectTemplate> templ) { 112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate)); 113f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 114f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ModuleRegistry::InstallGlobals(v8::Isolate* isolate, 117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) v8::Handle<v8::Object> obj) { 118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) obj->Set(StringToSymbol(isolate, "define"), 119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) GetDefineTemplate(isolate)->GetFunction()); 120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// static 123f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ModuleRegistry* ModuleRegistry::From(v8::Handle<Context> context) { 124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) PerContextData* data = PerContextData::From(context); 125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!data) 126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return NULL; 127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ModuleRegistryData* registry_data = static_cast<ModuleRegistryData*>( 129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) data->GetUserData(kModuleRegistryKey)); 130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!registry_data) { 131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // PerContextData takes ownership of ModuleRegistryData. 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) registry_data = new ModuleRegistryData; 133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) registry_data->registry.reset(new ModuleRegistry(context->GetIsolate())); 134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) data->SetUserData(kModuleRegistryKey, registry_data); 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return registry_data->registry.get(); 137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ModuleRegistry::AddObserver(ModuleRegistryObserver* observer) { 140a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) observer_list_.AddObserver(observer); 141a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 142a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 143a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ModuleRegistry::RemoveObserver(ModuleRegistryObserver* observer) { 144a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) observer_list_.RemoveObserver(observer); 145f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ModuleRegistry::AddBuiltinModule(Isolate* isolate, const std::string& id, 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) v8::Handle<Value> module) { 149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(!id.empty()); 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) RegisterModule(isolate, id, module); 151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ModuleRegistry::AddPendingModule(Isolate* isolate, 154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<PendingModule> pending) { 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::string pending_id = pending->id; 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const std::vector<std::string> pending_dependencies = pending->dependencies; 157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) AttemptToLoad(isolate, pending.Pass()); 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) FOR_EACH_OBSERVER(ModuleRegistryObserver, observer_list_, 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnDidAddPendingModule(pending_id, pending_dependencies)); 160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ModuleRegistry::LoadModule(Isolate* isolate, 163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& id, 164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) LoadModuleCallback callback) { 165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (available_modules_.find(id) != available_modules_.end()) { 166f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Should we call the callback asynchronously? 167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) callback.Run(GetModule(isolate, id)); 168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch waiting_callbacks_.insert(std::make_pair(id, callback)); 171f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) unsatisfied_dependencies_.insert(id); 172f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 173f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 174f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ModuleRegistry::RegisterModule(Isolate* isolate, 175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& id, 176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<Value> module) { 177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (id.empty() || module.IsEmpty()) 178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; 179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) unsatisfied_dependencies_.erase(id); 181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) available_modules_.insert(id); 182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<Object> modules = Local<Object>::New(isolate, modules_); 183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) modules->Set(StringToSymbol(isolate, id), module); 184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 185116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::pair<LoadModuleCallbackMap::iterator, LoadModuleCallbackMap::iterator> 186116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch range = waiting_callbacks_.equal_range(id); 187116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch std::vector<LoadModuleCallback> callbacks; 188116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callbacks.reserve(waiting_callbacks_.count(id)); 189116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (LoadModuleCallbackMap::iterator it = range.first; it != range.second; 190116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++it) { 191116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch callbacks.push_back(it->second); 192116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 193116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch waiting_callbacks_.erase(range.first, range.second); 194116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (std::vector<LoadModuleCallback>::iterator it = callbacks.begin(); 195116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it != callbacks.end(); 196116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ++it) { 197116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Should we call the callback asynchronously? 198116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it->Run(module); 199116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ModuleRegistry::CheckDependencies(PendingModule* pending) { 203f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t num_missing_dependencies = 0; 204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) size_t len = pending->dependencies.size(); 205f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t i = 0; i < len; ++i) { 206f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& dependency = pending->dependencies[i]; 207f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (available_modules_.count(dependency)) 208f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) continue; 209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) unsatisfied_dependencies_.insert(dependency); 210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) num_missing_dependencies++; 211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return num_missing_dependencies == 0; 213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ModuleRegistry::Load(Isolate* isolate, scoped_ptr<PendingModule> pending) { 216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!pending->id.empty() && available_modules_.count(pending->id)) 217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return; // We've already loaded this module. 218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) uint32_t argc = static_cast<uint32_t>(pending->dependencies.size()); 220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) std::vector<v8::Handle<Value> > argv(argc); 221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (uint32_t i = 0; i < argc; ++i) 222f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) argv[i] = GetModule(isolate, pending->dependencies[i]); 223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 224f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<Value> module = Local<Value>::New(isolate, pending->factory); 225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 226f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<Function> factory; 227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (ConvertFromV8(isolate, module, &factory)) { 228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PerContextData* data = PerContextData::From(isolate->GetCurrentContext()); 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Runner* runner = data->runner(); 230a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) module = runner->Call(factory, runner->global(), argc, 231a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) argv.empty() ? NULL : &argv.front()); 232f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (pending->id.empty()) 233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConvertFromV8(isolate, factory->GetScriptOrigin().ResourceName(), 234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) &pending->id); 235f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 236f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RegisterModule(isolate, pending->id, module); 238f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 239f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 240f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool ModuleRegistry::AttemptToLoad(Isolate* isolate, 241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<PendingModule> pending) { 242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!CheckDependencies(pending.get())) { 243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending_modules_.push_back(pending.release()); 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return false; 245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) Load(isolate, pending.Pass()); 247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return true; 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)v8::Handle<v8::Value> ModuleRegistry::GetModule(v8::Isolate* isolate, 251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const std::string& id) { 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<Object> modules = Local<Object>::New(isolate, modules_); 253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) v8::Handle<String> key = StringToSymbol(isolate, id); 254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(modules->HasOwnProperty(key)); 255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return modules->Get(key); 256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ModuleRegistry::AttemptToLoadMoreModules(Isolate* isolate) { 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool keep_trying = true; 260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) while (keep_trying) { 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) keep_trying = false; 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PendingModuleVector pending_modules; 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending_modules.swap(pending_modules_); 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) for (size_t i = 0; i < pending_modules.size(); ++i) { 265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<PendingModule> pending(pending_modules[i]); 266f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) pending_modules[i] = NULL; 267f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (AttemptToLoad(isolate, pending.Pass())) 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) keep_trying = true; 269f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 270f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} // namespace gin 274