define(function(require) {
var when, array, object, priority, instantiate, nsKey, nsSeparator;
array = require('../array');
object = require('../object');
priority = require('./priority');
instantiate = require('../instantiate');
function PluginRegistry() {
this.contextListeners = [];
PluginRegistry.prototype = {
scanModule: function (module, spec, namespace) {
pluginFactory = discoverPlugin(module);
if (!allowPlugin(pluginFactory, this.plugins)) {
this.plugins.push(pluginFactory);
return when(instantiate(pluginFactory, [spec]),
plugin && self.registerPlugin(plugin, namespace || getNamespace(spec));
registerPlugin: function (plugin, namespace) {
addNamespace(namespace, this._namespaces);
addPlugin(plugin.resolvers, this.resolvers, namespace);
addPlugin(plugin.factories, this.factories, namespace);
addPlugin(plugin.facets, this.facets, namespace);
this.listeners.push(plugin);
this.contextListeners.push(plugin.context);
this._registerProxies(plugin.proxies);
_registerProxies: function (proxiesToAdd) {
this.proxiers = priority.sortReverse(array.union(this.proxiers, proxiesToAdd));
function discoverPlugin(module) {
if(typeof module.wire$plugin === 'function') {
plugin = module.wire$plugin;
} else if(typeof module === 'function') {
function getNamespace(spec) {
if(typeof spec === 'object' && nsKey in spec) {
function addNamespace(namespace, namespaces) {
if(namespace && namespace in namespaces) {
throw new Error('plugin namespace already in use: ' + namespace);
namespaces[namespace] = 1;
function allowPlugin(plugin, existing) {
return typeof plugin === 'function' && existing.indexOf(plugin) === -1;
function addPlugin(src, registry, namespace) {
var newPluginName, namespacedName;
for (newPluginName in src) {
namespacedName = makeNamespace(newPluginName, namespace);
if (object.hasOwn(registry, namespacedName)) {
throw new Error('Two plugins for same type in scope: ' + namespacedName);
registry[namespacedName] = src[newPluginName];
function makeNamespace(pluginName, namespace) {
return namespace ? (namespace + nsSeparator + pluginName) : pluginName;
}(typeof define === 'function' ? define : function(factory) { module.exports = factory(require); }));