diff --git a/lib/models/addons-factory.js b/lib/models/addons-factory.js index 7801198bd2..4a67cd1988 100644 --- a/lib/models/addons-factory.js +++ b/lib/models/addons-factory.js @@ -4,7 +4,7 @@ @module ember-cli */ -const DAG = require('../utilities/DAG'); +const DAGMap = require('dag-map').default; let logger = require('heimdalljs-logger')('ember-cli:addons-factory'); const heimdall = require('heimdalljs'); @@ -27,7 +27,7 @@ class AddonsFactory { let addonParentName = typeof addonParent.name === 'function' ? addonParent.name() : addonParent.name; let initializeAddonsToken = heimdall.start(`${addonParentName}: initializeAddons`); - let graph = new DAG(); + let graph = new DAGMap(); const Addon = require('../models/addon'); let addonInfo, emberAddonConfig; @@ -38,12 +38,12 @@ class AddonsFactory { addonInfo = addonPackages[name]; emberAddonConfig = addonInfo.pkg['ember-addon']; - graph.addEdges(name, addonInfo, emberAddonConfig.before, emberAddonConfig.after); + graph.add(name, addonInfo, emberAddonConfig.before, emberAddonConfig.after); } let addons = []; - graph.topsort(vertex => { - let addonInfo = vertex.value; + graph.each((key, value) => { + let addonInfo = value; if (addonInfo) { let initializeAddonToken = heimdall.start({ name: `initialize ${addonInfo.name}`, diff --git a/lib/utilities/DAG.js b/lib/utilities/DAG.js deleted file mode 100644 index 5dcf8061b1..0000000000 --- a/lib/utilities/DAG.js +++ /dev/null @@ -1,176 +0,0 @@ -'use strict'; - -function visit(vertex, fn, visited, path) { - let name = vertex.name, - vertices = vertex.incoming, - names = vertex.incomingNames, - len = names.length, - i; - if (!visited) { - visited = {}; - } - if (!path) { - path = []; - } - if (visited.hasOwnProperty(name)) { - return; - } - path.push(name); - visited[name] = true; - for (i = 0; i < len; i++) { - visit(vertices[names[i]], fn, visited, path); - } - fn(vertex, path); - path.pop(); -} - -class DAG { - /** - * Directed acyclic graph. - * - * see [Wikipedia](https://en.wikipedia.org/wiki/Directed_acyclic_graph). - * - * @class DAG - * @constructor - */ - constructor() { - /** - * Array of all known vertex names. - * - * @final - * @property names - * @type Array - */ - this.names = []; - - /** - * Hash of vertices keyed by name. - * - * @final - * @property vertices - * @type Object - */ - this.vertices = {}; - } - - /** - * Adds a new vertex to the graph. - * - * @method add - * @param {String} name Name of the vertex - * @return {Object|undefined} The new vertex or the already existing vertex with the same name - */ - add(name) { - if (!name) { return; } - if (this.vertices.hasOwnProperty(name)) { - return this.vertices[name]; - } - let vertex = { - name, - incoming: {}, - incomingNames: [], - hasOutgoing: false, - value: null, - }; - - this.vertices[name] = vertex; - this.names.push(name); - return vertex; - } - - /** - * Assigns `value` to the vertex named `name`. - * - * Creates a new vertex if a vertex named `name` does not exist yet. - * - * @method map - * @param {String} name Name of the vertex - * @param {any} value Value of the vertex - */ - map(name, value) { - this.add(name).value = value; - } - - /** - * Adds an edge between two vertices. - * - * @method addEdge - * @param fromName Name of the `from` vertex - * @param toName Name of the `to` vertex - * @throws {Error} if a cycle is detected - */ - addEdge(fromName, toName) { - if (!fromName || !toName || fromName === toName) { - return; - } - let from = this.add(fromName), to = this.add(toName); - if (to.incoming.hasOwnProperty(fromName)) { - return; - } - function checkCycle(vertex, path) { - if (vertex.name === toName) { - throw new Error(`cycle detected: ${toName} <- ${path.join(' <- ')}`); - } - } - visit(from, checkCycle); - from.hasOutgoing = true; - to.incoming[fromName] = from; - to.incomingNames.push(fromName); - } - - /** - * Traverses the graph depth-first. - * - * Each vertex will only be visited once even if it has multiple parent vertices. - * - * @method topsort - * @param {Function} fn Function that is called with each vertex and the path to it - */ - topsort(fn) { - let visited = {}, - vertices = this.vertices, - names = this.names, - len = names.length, - i, vertex; - for (i = 0; i < len; i++) { - vertex = vertices[names[i]]; - if (!vertex.hasOutgoing) { - visit(vertex, fn, visited); - } - } - } - - /** - * Assigns `value` to the vertex named `name` and creates the edges defined by `before` and `after`. - * - * @method addEdges - * @param {String} name Name of the vertex - * @param {any} value Value of the vertex - * @param {String|Array} before Adds edges from `name` to each of `before` - * @param {String|Array} after Adds edges from each of `after` to `name` - */ - addEdges(name, value, before, after) { - let i; - this.map(name, value); - if (before) { - if (typeof before === 'string') { - this.addEdge(name, before); - } else { - for (i = 0; i < before.length; i++) { - this.addEdge(name, before[i]); - } - } - } - if (after) { - if (typeof after === 'string') { - this.addEdge(after, name); - } else { - for (i = 0; i < after.length; i++) { - this.addEdge(after[i], name); - } - } - } - } -} - -module.exports = DAG; diff --git a/package.json b/package.json index 1d065d3dba..279c317a1d 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ "configstore": "^3.0.0", "console-ui": "^1.0.2", "core-object": "^3.0.0", + "dag-map": "^2.0.2", "diff": "^3.2.0", "ember-cli-broccoli-sane-watcher": "^2.0.4", "ember-cli-get-component-path-option": "^1.0.0", diff --git a/yarn.lock b/yarn.lock index 5b46ae8a9b..c4e417a91a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1295,6 +1295,10 @@ d@^0.1.1, d@~0.1.1: dependencies: es5-ext "~0.10.2" +dag-map@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dag-map/-/dag-map-2.0.2.tgz#9714b472de82a1843de2fba9b6876938cab44c68" + debug@2, debug@^2.1.0, debug@^2.1.1, debug@^2.1.3, debug@^2.2.0: version "2.6.2" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.2.tgz#dfa96a861ee9b8c2f29349b3bcc41aa599a71e0f"