<commit_before>/** @license MIT License (c) copyright <NAME> & <NAME> */

/**
 * Licensed under the MIT License at:
 * http://www.opensource.org/licenses/mit-license.php
 */

(function(define) { 'use strict';
define(function(require) {

	var when, sequence, poll, array, object, async, loader, Lifecycle, Resolver,
		proxy, createPluginRegistry, defaultPlugins,
		defer, chain, whenAll, scope, undef;

	when = require('when');
	sequence = require('when/sequence');
	poll = require('when/poll');
	array = require('./array');
	object = require('./object');
	async = require('./async');
	loader = require('./loader');
	Lifecycle = require('./lifecycle');
	Resolver = require('./resolver');
	proxy = require('./proxy');
	createPluginRegistry = require('./plugin/registry');
	defaultPlugins = require('./plugin/defaultPlugins');

	defer = when.defer;
	chain = when.chain;
	whenAll = when.all;

	function createScope(spec, parent, options) {
		var s = Object.create(scope, options ? createPropertyDescriptors(options) : {});
		return s.init(spec, parent);
	}

	function createPropertyDescriptors(options) {
		return Object.keys(options).reduce(function(descriptor, key) {
			descriptor[key] = { value: options[key] };
			return descriptor;
		}, {});
	}

	scope = {
		contextHandlers: {},

		init: function(spec, parent) {
			var self, ready, destroyed, taskContext;

			self = this;
			ready = defer();
			destroyed = defer();

			this.parent = parent || {};
			this.ready = ready.promise;
			this.destroyed = destroyed.promise;

			this._inherit(this.parent, ready.promise, destroyed.promise);
			this._initPluginApi();
			this._initDefaultPlugins();
			this._configure();

			taskContext = {
				components: this.components,
				spec: this.spec
			};

			this._executeTasks = function(tasks) {
				return sequence(tasks, taskContext);
			};

			this._destroy = function() {
				this._destroy = noop;
				return this._destroyComponents(destroyed.resolver);
			};

			return this._executeInitializers()
				.then(prepareScope)
				.then(finalizeScope)
				.yield(ready.promise);

			function prepareScope() {
				self._parseSpec(spec, ready.resolver);
				self._createComponents(spec);
			}

			function finalizeScope() {
				self._ensureAllModulesLoaded();
			}
		},

		destroy: function() {
			return this._destroy();
		},

		getModule: function(moduleId, spec) {
			var self, module;

			self = this;
			module = defer();

			scanPluginWhenLoaded(typeof moduleId == 'string'
				? this.moduleLoader(moduleId)
				: moduleId, module.resolver);

			return module.promise;

			function scanPluginWhenLoaded(loadModulePromise, moduleReadyResolver) {

				var loadPromise = when(loadModulePromise, function (module) {
					return when(self._scanPlugin(module, spec), function() {
						chain(self.modulesReady, moduleReadyResolver, module);
					});
				}, moduleReadyResolver.reject);

				self.modulesToLoad && self.modulesToLoad.push(loadPromise);

			}
		},

		getProxy: function(nameOrComponent /*, onBehalfOf */) {
			var self = this;
			return typeof nameOrComponent == 'string'
				? when(this._resolveRefName(nameOrComponent, {} /*, onBehalfOf */), function (component) {
					return self._createProxy(component);
				})
				: self._createProxy(nameOrComponent);
		},

		_createProxy: function(component, metadata) {
			var self, lifecycle;

			self = this;
			lifecycle = this.lifecycle;

			return when(this.modulesReady, function() {
				var componentProxy = self.plugins.proxiers.reduce(
					function(proxy, proxyHandler) {
						return proxyHandler(proxy) || proxy;
					},
					proxy.create(component, lifecycle, metadata)
				);

				if(metadata) {
					componentProxy.path = self._createPath(metadata.id);
					self.proxiedComponents.push(componentProxy);
				}

				return componentProxy;
			});
		},

		_inherit: function(parent, ready, destroyed) {
			var self = this;

			// Descend scope and plugins from parent so that this scope can
			// use them directly via the prototype chain

			this._api = {
				createChild: wireChild.bind(this),
				destroy: this.destroy.bind(this),
				resolve: function(ref, onBehalfOf) {
					return when.resolve(self._resolveRefName(ref, {}, onBehalfOf));
				}
			};

			WireContext.prototype = this._createWireApi(this._api, object.inherit(parent.components));
			this.components = new WireContext();
			WireContext.prototype = undef;

			this.metadata = object.inherit(parent.metadata);

			this.path = this._createPath(this.name, parent.path);
			this.plugins = createPluginRegistry(parent.plugins||{}, ready, destroyed);

			this.contextHandlers.init = array.delegate(this.contextHandlers.init);
			this.contextHandlers.destroy = array.delegate(this.contextHandlers.destroy);

			this.proxiedComponents = [];

			// These should not be public
			this.modulesToLoad = [];
			this.modulesReady = defer();
			this.moduleLoader = loader(parent, this).load;

			// When the parent begins its destroy phase, this child must
			// begin its destroy phase and complete it before the parent.
			// The context hierarchy will be destroyed from child to parent.
			if (parent.destroyed) {
				when(parent.destroyed, this.destroy.bind(this));
			}

			function wireChild(spec, options) {
				return self.createContext(spec, {
					moduleLoader: self.moduleLoader,
					components: self.components,
					metadata: self.metadata,
					destroyed: destroyed
				}, options);
			}
		},

		_initPluginApi: function() {
			// Plugin API
			// wire() API that is passed to plugins.
			var self, pluginApi;

			self = this;
			pluginApi = this._pluginApi = function (spec, name, path) {
				return self._resolveItem(spec, { id: self._createPath(name, path) });
			};

			pluginApi.createChild = this._api.createChild;
			pluginApi.resolveRef = this._api.resolve;
			pluginApi.getProxy = this.getProxy.bind(this);
			pluginApi.loadModule = this.getModule.bind(this);
		},

		_initDefaultPlugins: function() {
			defaultPlugins.forEach(this._scanPlugin, this);
		},

		_createWireApi: function(api, context) {
			var wireApi = this._wireApi = context.wire = function() {
				return api.createChild.apply(undef, arguments);
			};
			wireApi.destroy = context.destroy = api.destroy;

			// Consider deprecating resolve
			// Any reference you could resolve using this should simply be injected instead.
			wireApi.resolve = context.resolve = api.resolve;

			return context;
		},

		_configure: function() {
			var config = {
				pluginApi: this._pluginApi,
				plugins: this.plugins
			};

			this.lifecycle = new Lifecycle(config);
			this.resolver = this._pluginApi.resolver = new Resolver(config);
		},

		_executeInitializers: function() {
			return this._executeTasks(this.contextHandlers.init);
		},

		_parseSpec: function(spec, scopeResolver) {
			var promises, components, metadata, name, d;

			components = this.components;
			metadata = this.metadata;
			promises = [];

			// Setup a promise for each item in this scope
			for (name in spec) {
				// An initializer may have inserted concrete components
				// into the context.  If so, they override components of the
				// same name from the input spec
				if(!object.hasOwn(components, name)) {
					d = defer();

					metadata[name] = {
						id: name,
						spec: spec[name],
						promise: d.promise,
						resolver: d.resolver
					};

					promises.push(components[name] = d.promise);
				}
			}

			// When all scope item promises are resolved, the scope
			// is ready. When this scope is ready, resolve the promise
			// with the objects that were created
			chain(whenAll(promises), scopeResolver, this);
		},

		_createComponents: function(spec) {
			// Process/create each item in scope and resolve its
			// promise when completed.
			var metadata = this.metadata;
			Object.keys(metadata).forEach(function(name) {
				this._createScopeItem(spec[name], metadata[name]);
			}.bind(this));
		},

		_createScopeItem: function(spec, itemMetadata) {
			// NOTE: Order is important here.
			// The object & local property assignment MUST happen before
			// the chain resolves so that the concrete item is in place.
			// Otherwise, the whole scope can be marked as resolved before
			// the final item has been resolved.
			var name, item, self;

			self = this;
			name = itemMetadata.id;
			item = this._resolveItem(spec, itemMetadata);

			when(item, function (resolved) {
				self._makeResolvable(itemMetadata, resolved);
				itemMetadata.resolver.resolve(resolved);
			}, itemMetadata.resolver.reject);
		},

		_makeResolvable: function(metadata, component) {
			this.components[metadata.id] = proxy.getTarget(async.getValue(component));
		},

		_resolveItem: function(spec, itemMetadata) {
			var item;

			if (this.resolver.isRef(spec)) {
				// Reference
				item = this._resolveRef(spec, itemMetadata.id);
			} else {
				// Component
				item = this._createItem(spec, itemMetadata);
			}

			return item;
		},

		_createItem: function(spec, itemMetadata) {
			var created;

			if (Array.isArray(spec)) {
				// Array
				created = this._createArray(spec, itemMetadata);

			} else if (object.isObject(spec)) {
				// component spec, create the component
				created = this._createComponent(spec, itemMetadata);

			} else {
				// Plain value
				created = when.resolve(spec);
			}

			return created;
		},

		_createArray: function(arrayDef, arrayMetadata) {
			var self = this;
			// Minor optimization, if it's an empty array spec, just return an empty array.
			return arrayDef.length
				? when.map(arrayDef, function(item) {
					return self._resolveItem(item, { id: arrayMetadata.id + '[]' });
				})
				: [];
		},

		_createComponent: function(spec, componentMetadata) {

			var self, name;

			self = this;
			name = componentMetadata.id;

			// Look for a factory, then use it to create the object
			return when(this._findFactory(spec),
				function (factory) {
					var component = defer();

					if (!spec.id) {
						spec.id = name;
					}

					factory(component.resolver, spec, self._pluginApi);

					return when(component.promise, function(createdComponent) {
						return self.plugins.isPlugin(createdComponent)
							? createdComponent
							: self._processComponent(createdComponent, componentMetadata);
					}).then(proxy.getTarget);
				},
				function () {
					// No factory found, treat object spec as a nested scope
					return createScope(spec, self).then(function(childScope) {
						return object.safeMixin({}, childScope.components);
					});
				}
			);
		},

		_processComponent: function(component, metadata) {
			var lifecycle, self;

			lifecycle = this.lifecycle;
			self = this;

			return when(self._createProxy(component, metadata), function(proxy) {
				metadata.proxy = proxy;
				return proxy.init();

			}).then(function(proxy) {
				// Components become resolvable after the initialization phase
				// This allows circular references to be resolved after init
				self._makeResolvable(metadata, proxy);
				return proxy.startup();
			});
		},

		_findFactory: function(spec) {<commit_msg>Removing link from metadata to proxy. Not needed, and paves the way for metadata to be used to create many proxies<commit_after>/** @license MIT License (c) copyright <NAME> & <NAME> */

/**
 * Licensed under the MIT License at:
 * http://www.opensource.org/licenses/mit-license.php
 */

(function(define) { 'use strict';
define(function(require) {

	var when, sequence, poll, array, object, async, loader, Lifecycle, Resolver,
		proxy, createPluginRegistry, defaultPlugins,
		defer, chain, whenAll, scope, undef;

	when = require('when');
	sequence = require('when/sequence');
	poll = require('when/poll');
	array = require('./array');
	object = require('./object');
	async = require('./async');
	loader = require('./loader');
	Lifecycle = require('./lifecycle');
	Resolver = require('./resolver');
	proxy = require('./proxy');
	createPluginRegistry = require('./plugin/registry');
	defaultPlugins = require('./plugin/defaultPlugins');

	defer = when.defer;
	chain = when.chain;
	whenAll = when.all;

	function createScope(spec, parent, options) {
		var s = Object.create(scope, options ? createPropertyDescriptors(options) : {});
		return s.init(spec, parent);
	}

	function createPropertyDescriptors(options) {
		return Object.keys(options).reduce(function(descriptor, key) {
			descriptor[key] = { value: options[key] };
			return descriptor;
		}, {});
	}

	scope = {
		contextHandlers: {},

		init: function(spec, parent) {
			var self, ready, destroyed, taskContext;

			self = this;
			ready = defer();
			destroyed = defer();

			this.parent = parent || {};
			this.ready = ready.promise;
			this.destroyed = destroyed.promise;

			this._inherit(this.parent, ready.promise, destroyed.promise);
			this._initPluginApi();
			this._initDefaultPlugins();
			this._configure();

			taskContext = {
				components: this.components,
				spec: this.spec
			};

			this._executeTasks = function(tasks) {
				return sequence(tasks, taskContext);
			};

			this._destroy = function() {
				this._destroy = noop;
				return this._destroyComponents(destroyed.resolver);
			};

			return this._executeInitializers()
				.then(prepareScope)
				.then(finalizeScope)
				.yield(ready.promise);

			function prepareScope() {
				self._parseSpec(spec, ready.resolver);
				self._createComponents(spec);
			}

			function finalizeScope() {
				self._ensureAllModulesLoaded();
			}
		},

		destroy: function() {
			return this._destroy();
		},

		getModule: function(moduleId, spec) {
			var self, module;

			self = this;
			module = defer();

			scanPluginWhenLoaded(typeof moduleId == 'string'
				? this.moduleLoader(moduleId)
				: moduleId, module.resolver);

			return module.promise;

			function scanPluginWhenLoaded(loadModulePromise, moduleReadyResolver) {

				var loadPromise = when(loadModulePromise, function (module) {
					return when(self._scanPlugin(module, spec), function() {
						chain(self.modulesReady, moduleReadyResolver, module);
					});
				}, moduleReadyResolver.reject);

				self.modulesToLoad && self.modulesToLoad.push(loadPromise);

			}
		},

		getProxy: function(nameOrComponent /*, onBehalfOf */) {
			var self = this;
			return typeof nameOrComponent == 'string'
				? when(this._resolveRefName(nameOrComponent, {} /*, onBehalfOf */), function (component) {
					return self._createProxy(component);
				})
				: self._createProxy(nameOrComponent);
		},

		_createProxy: function(component, metadata) {
			var self, lifecycle;

			self = this;
			lifecycle = this.lifecycle;

			return when(this.modulesReady, function() {
				var componentProxy = self.plugins.proxiers.reduce(
					function(proxy, proxyHandler) {
						return proxyHandler(proxy) || proxy;
					},
					proxy.create(component, lifecycle, metadata)
				);

				if(metadata) {
					componentProxy.path = self._createPath(metadata.id);
					self.proxiedComponents.push(componentProxy);
				}

				return componentProxy;
			});
		},

		_inherit: function(parent, ready, destroyed) {
			var self = this;

			// Descend scope and plugins from parent so that this scope can
			// use them directly via the prototype chain

			this._api = {
				createChild: wireChild.bind(this),
				destroy: this.destroy.bind(this),
				resolve: function(ref, onBehalfOf) {
					return when.resolve(self._resolveRefName(ref, {}, onBehalfOf));
				}
			};

			WireContext.prototype = this._createWireApi(this._api, object.inherit(parent.components));
			this.components = new WireContext();
			WireContext.prototype = undef;

			this.metadata = object.inherit(parent.metadata);

			this.path = this._createPath(this.name, parent.path);
			this.plugins = createPluginRegistry(parent.plugins||{}, ready, destroyed);

			this.contextHandlers.init = array.delegate(this.contextHandlers.init);
			this.contextHandlers.destroy = array.delegate(this.contextHandlers.destroy);

			this.proxiedComponents = [];

			// These should not be public
			this.modulesToLoad = [];
			this.modulesReady = defer();
			this.moduleLoader = loader(parent, this).load;

			// When the parent begins its destroy phase, this child must
			// begin its destroy phase and complete it before the parent.
			// The context hierarchy will be destroyed from child to parent.
			if (parent.destroyed) {
				when(parent.destroyed, this.destroy.bind(this));
			}

			function wireChild(spec, options) {
				return self.createContext(spec, {
					moduleLoader: self.moduleLoader,
					components: self.components,
					metadata: self.metadata,
					destroyed: destroyed
				}, options);
			}
		},

		_initPluginApi: function() {
			// Plugin API
			// wire() API that is passed to plugins.
			var self, pluginApi;

			self = this;
			pluginApi = this._pluginApi = function (spec, name, path) {
				return self._resolveItem(spec, { id: self._createPath(name, path) });
			};

			pluginApi.createChild = this._api.createChild;
			pluginApi.resolveRef = this._api.resolve;
			pluginApi.getProxy = this.getProxy.bind(this);
			pluginApi.loadModule = this.getModule.bind(this);
		},

		_initDefaultPlugins: function() {
			defaultPlugins.forEach(this._scanPlugin, this);
		},

		_createWireApi: function(api, context) {
			var wireApi = this._wireApi = context.wire = function() {
				return api.createChild.apply(undef, arguments);
			};
			wireApi.destroy = context.destroy = api.destroy;

			// Consider deprecating resolve
			// Any reference you could resolve using this should simply be injected instead.
			wireApi.resolve = context.resolve = api.resolve;

			return context;
		},

		_configure: function() {
			var config = {
				pluginApi: this._pluginApi,
				plugins: this.plugins
			};

			this.lifecycle = new Lifecycle(config);
			this.resolver = this._pluginApi.resolver = new Resolver(config);
		},

		_executeInitializers: function() {
			return this._executeTasks(this.contextHandlers.init);
		},

		_parseSpec: function(spec, scopeResolver) {
			var promises, components, metadata, name, d;

			components = this.components;
			metadata = this.metadata;
			promises = [];

			// Setup a promise for each item in this scope
			for (name in spec) {
				// An initializer may have inserted concrete components
				// into the context.  If so, they override components of the
				// same name from the input spec
				if(!object.hasOwn(components, name)) {
					d = defer();

					metadata[name] = {
						id: name,
						spec: spec[name],
						promise: d.promise,
						resolver: d.resolver
					};

					promises.push(components[name] = d.promise);
				}
			}

			// When all scope item promises are resolved, the scope
			// is ready. When this scope is ready, resolve the promise
			// with the objects that were created
			chain(whenAll(promises), scopeResolver, this);
		},

		_createComponents: function(spec) {
			// Process/create each item in scope and resolve its
			// promise when completed.
			var metadata = this.metadata;
			Object.keys(metadata).forEach(function(name) {
				this._createScopeItem(spec[name], metadata[name]);
			}.bind(this));
		},

		_createScopeItem: function(spec, itemMetadata) {
			// NOTE: Order is important here.
			// The object & local property assignment MUST happen before
			// the chain resolves so that the concrete item is in place.
			// Otherwise, the whole scope can be marked as resolved before
			// the final item has been resolved.
			var item, itemResolver, self;

			self = this;
			item = this._resolveItem(spec, itemMetadata);
			itemResolver = itemMetadata.resolver;

			when(item, function (resolved) {
				self._makeResolvable(itemMetadata, resolved);
				itemResolver.resolve(resolved);
			}, itemResolver.reject);
		},

		_makeResolvable: function(metadata, component) {
			this.components[metadata.id] = proxy.getTarget(async.getValue(component));
		},

		_resolveItem: function(spec, itemMetadata) {
			var item;

			if (this.resolver.isRef(spec)) {
				// Reference
				item = this._resolveRef(spec, itemMetadata.id);
			} else {
				// Component
				item = this._createItem(spec, itemMetadata);
			}

			return item;
		},

		_createItem: function(spec, itemMetadata) {
			var created;

			if (Array.isArray(spec)) {
				// Array
				created = this._createArray(spec, itemMetadata);

			} else if (object.isObject(spec)) {
				// component spec, create the component
				created = this._createComponent(spec, itemMetadata);

			} else {
				// Plain value
				created = when.resolve(spec);
			}

			return created;
		},

		_createArray: function(arrayDef, arrayMetadata) {
			var self = this;
			// Minor optimization, if it's an empty array spec, just return an empty array.
			return arrayDef.length
				? when.map(arrayDef, function(item) {
					return self._resolveItem(item, { id: arrayMetadata.id + '[]' });
				})
				: [];
		},

		_createComponent: function(spec, componentMetadata) {

			var self, name;

			self = this;
			name = componentMetadata.id;

			// Look for a factory, then use it to create the object
			return when(this._findFactory(spec),
				function (factory) {
					var component = defer();

					if (!spec.id) {
						spec.id = name;
					}

					factory(component.resolver, spec, self._pluginApi);

					return when(component.promise, function(createdComponent) {
						return self.plugins.isPlugin(createdComponent)
							? createdComponent
							: self._processComponent(createdComponent, componentMetadata);
					}).then(proxy.getTarget);
				},
				function () {
					// No factory found, treat object spec as a nested scope
					return createScope(spec, self).then(function(childScope) {
						return object.safeMixin({}, childScope.components);
					});
				}
			);
		},

		_processComponent: function(component, metadata) {
			var lifecycle, self;

			lifecycle = this.lifecycle;
			self = this;

			return when(self._createProxy(component, metadata), function(proxy) {
				return proxy.init();

			}).then(function(proxy) {
				// Components become resolvable after the initialization phase
				// This allows circular references to be resolved after init
				self._makeResolvable(metadata, proxy);
				return proxy.startup();
			});
		},

		_findFactory: function(spec) {
{'fraction_non_alphanumeric': 0.12333709131905299, 'fraction_numerical': 0.0, 'mean_word_length': 3.4140127388535033, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7407812', 'n_tokens_mistral': 7963, 'n_tokens_neox': 6376, 'n_words': 1612}