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 3 // found in the LICENSE file. 4 5 #ifndef GIN_MODULES_MODULE_REGISTRY_H_ 6 #define GIN_MODULES_MODULE_REGISTRY_H_ 7 8 #include <list> 9 #include <map> 10 #include <set> 11 #include <string> 12 13 #include "base/callback.h" 14 #include "base/compiler_specific.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_vector.h" 17 #include "base/observer_list.h" 18 #include "gin/gin_export.h" 19 #include "v8/include/v8.h" 20 21 namespace gin { 22 23 class ModuleRegistryObserver; 24 struct PendingModule; 25 26 // This class implements the Asynchronous Module Definition (AMD) API. 27 // https://github.com/amdjs/amdjs-api/wiki/AMD 28 // 29 // Our implementation isn't complete yet. Missing features: 30 // 1) Built-in support for require, exports, and module. 31 // 2) Path resoltuion in module names. 32 // 33 // For these reasons, we don't have an "amd" property on the "define" 34 // function. The spec says we should only add that property once our 35 // implementation complies with the specification. 36 // 37 class GIN_EXPORT ModuleRegistry { 38 public: 39 typedef base::Callback<void (v8::Handle<v8::Value>)> LoadModuleCallback; 40 41 virtual ~ModuleRegistry(); 42 43 static ModuleRegistry* From(v8::Handle<v8::Context> context); 44 45 static void RegisterGlobals(v8::Isolate* isolate, 46 v8::Handle<v8::ObjectTemplate> templ); 47 48 // Installs the necessary functions needed for modules. 49 // WARNING: this may execute script in the page. 50 static void InstallGlobals(v8::Isolate* isolate, v8::Handle<v8::Object> obj); 51 52 void AddObserver(ModuleRegistryObserver* observer); 53 void RemoveObserver(ModuleRegistryObserver* observer); 54 55 // The caller must have already entered our context. 56 void AddBuiltinModule(v8::Isolate* isolate, const std::string& id, 57 v8::Handle<v8::Value> module); 58 59 // The caller must have already entered our context. 60 void AddPendingModule(v8::Isolate* isolate, 61 scoped_ptr<PendingModule> pending); 62 63 void LoadModule(v8::Isolate* isolate, 64 const std::string& id, 65 LoadModuleCallback callback); 66 67 // The caller must have already entered our context. 68 void AttemptToLoadMoreModules(v8::Isolate* isolate); 69 available_modules()70 const std::set<std::string>& available_modules() const { 71 return available_modules_; 72 } 73 unsatisfied_dependencies()74 const std::set<std::string>& unsatisfied_dependencies() const { 75 return unsatisfied_dependencies_; 76 } 77 78 private: 79 typedef ScopedVector<PendingModule> PendingModuleVector; 80 typedef std::multimap<std::string, LoadModuleCallback> LoadModuleCallbackMap; 81 82 explicit ModuleRegistry(v8::Isolate* isolate); 83 84 void Load(v8::Isolate* isolate, scoped_ptr<PendingModule> pending); 85 void RegisterModule(v8::Isolate* isolate, 86 const std::string& id, 87 v8::Handle<v8::Value> module); 88 89 bool CheckDependencies(PendingModule* pending); 90 bool AttemptToLoad(v8::Isolate* isolate, scoped_ptr<PendingModule> pending); 91 92 v8::Handle<v8::Value> GetModule(v8::Isolate* isolate, const std::string& id); 93 94 std::set<std::string> available_modules_; 95 std::set<std::string> unsatisfied_dependencies_; 96 97 LoadModuleCallbackMap waiting_callbacks_; 98 99 PendingModuleVector pending_modules_; 100 v8::Persistent<v8::Object> modules_; 101 102 ObserverList<ModuleRegistryObserver> observer_list_; 103 104 DISALLOW_COPY_AND_ASSIGN(ModuleRegistry); 105 }; 106 107 } // namespace gin 108 109 #endif // GIN_MODULES_MODULE_REGISTRY_H_ 110