// Copyright 2013 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef GIN_MODULES_MODULE_REGISTRY_H_ #define GIN_MODULES_MODULE_REGISTRY_H_ #include <list> #include <map> #include <set> #include <string> #include "base/callback.h" #include "base/compiler_specific.h" #include "base/memory/scoped_ptr.h" #include "base/memory/scoped_vector.h" #include "base/observer_list.h" #include "gin/gin_export.h" #include "v8/include/v8.h" namespace gin { class ModuleRegistryObserver; struct PendingModule; // This class implements the Asynchronous Module Definition (AMD) API. // https://github.com/amdjs/amdjs-api/wiki/AMD // // Our implementation isn't complete yet. Missing features: // 1) Built-in support for require, exports, and module. // 2) Path resoltuion in module names. // // For these reasons, we don't have an "amd" property on the "define" // function. The spec says we should only add that property once our // implementation complies with the specification. // class GIN_EXPORT ModuleRegistry { public: typedef base::Callback<void (v8::Handle<v8::Value>)> LoadModuleCallback; virtual ~ModuleRegistry(); static ModuleRegistry* From(v8::Handle<v8::Context> context); static void RegisterGlobals(v8::Isolate* isolate, v8::Handle<v8::ObjectTemplate> templ); // Installs the necessary functions needed for modules. // WARNING: this may execute script in the page. static void InstallGlobals(v8::Isolate* isolate, v8::Handle<v8::Object> obj); void AddObserver(ModuleRegistryObserver* observer); void RemoveObserver(ModuleRegistryObserver* observer); // The caller must have already entered our context. void AddBuiltinModule(v8::Isolate* isolate, const std::string& id, v8::Handle<v8::Value> module); // The caller must have already entered our context. void AddPendingModule(v8::Isolate* isolate, scoped_ptr<PendingModule> pending); void LoadModule(v8::Isolate* isolate, const std::string& id, LoadModuleCallback callback); // The caller must have already entered our context. void AttemptToLoadMoreModules(v8::Isolate* isolate); const std::set<std::string>& available_modules() const { return available_modules_; } const std::set<std::string>& unsatisfied_dependencies() const { return unsatisfied_dependencies_; } private: typedef ScopedVector<PendingModule> PendingModuleVector; typedef std::multimap<std::string, LoadModuleCallback> LoadModuleCallbackMap; explicit ModuleRegistry(v8::Isolate* isolate); void Load(v8::Isolate* isolate, scoped_ptr<PendingModule> pending); void RegisterModule(v8::Isolate* isolate, const std::string& id, v8::Handle<v8::Value> module); bool CheckDependencies(PendingModule* pending); bool AttemptToLoad(v8::Isolate* isolate, scoped_ptr<PendingModule> pending); v8::Handle<v8::Value> GetModule(v8::Isolate* isolate, const std::string& id); std::set<std::string> available_modules_; std::set<std::string> unsatisfied_dependencies_; LoadModuleCallbackMap waiting_callbacks_; PendingModuleVector pending_modules_; v8::Persistent<v8::Object> modules_; ObserverList<ModuleRegistryObserver> observer_list_; DISALLOW_COPY_AND_ASSIGN(ModuleRegistry); }; } // namespace gin #endif // GIN_MODULES_MODULE_REGISTRY_H_