├── .eslintrc.js ├── .gitignore ├── .travis.yml ├── README.md ├── lib ├── shake.js └── shake │ ├── analyzer.js │ ├── eval.js │ ├── graph.js │ ├── module.js │ └── walk.js ├── package-lock.json ├── package.json └── test ├── analyzer-test.js ├── eval-test.js ├── fixtures.js └── graph-test.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'browser': false, 4 | 'commonjs': true, 5 | 'node': true, 6 | 'es6': true 7 | }, 8 | 'parserOptions': { 9 | 'ecmaVersion': 8 10 | }, 11 | 'extends': 'eslint:recommended', 12 | 'rules': { 13 | 'indent': [ 14 | 'error', 15 | 2, 16 | { 17 | 'FunctionDeclaration': { 18 | 'parameters': 'first' 19 | }, 20 | 'FunctionExpression': { 21 | 'parameters': 'first' 22 | }, 23 | 'CallExpression': { 24 | 'arguments': 'first' 25 | } 26 | } 27 | ], 28 | 'linebreak-style': [ 29 | 'error', 30 | 'unix' 31 | ], 32 | 'quotes': [ 33 | 'error', 34 | 'single' 35 | ], 36 | 'semi': [ 37 | 'error', 38 | 'always' 39 | ], 40 | 'max-len': [ 41 | 'error', 42 | 80, 43 | 2 44 | ] 45 | } 46 | }; 47 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | npm-debug.log 3 | .nyc_output/ 4 | coverage/ 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | node_js: 4 | - "stable" 5 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CommonJS Tree Shaker 2 | [![NPM version](https://badge.fury.io/js/common-shake.svg)](http://badge.fury.io/js/common-shake) 3 | [![Build Status](https://secure.travis-ci.org/indutny/common-shake.svg)](http://travis-ci.org/indutny/common-shake) 4 | 5 | See [webpack-common-shake][0] for [webpack][1] plugin. 6 | 7 | ## Usage 8 | 9 | ```js 10 | const acorn = require('acorn'); 11 | const Analyzer = require('common-shake').Analyzer; 12 | 13 | const a = new Analyzer(); 14 | 15 | a.run(acorn.parse(` 16 | 'use strict'; 17 | const lib = require('./a.js'); 18 | exports.a = lib.a; 19 | `, { locations: true }), 'index.js'); 20 | 21 | a.run(acorn.parse(` 22 | 'use strict'; 23 | exports.a = 42; 24 | `, { locations: true }), 'a.js'); 25 | 26 | a.resolve('index.js', './a.js', 'a.js'); 27 | console.log(a.isSuccess(), a.bailouts); 28 | // true false 29 | 30 | console.log(a.getModule('index.js').getInfo()); 31 | // { bailouts: false, declarations: [ 'a' ], uses: [] } 32 | 33 | console.log(a.getModule('a.js').getInfo()); 34 | // { bailouts: false, declarations: [ 'a' ], uses: [ 'a' ] } 35 | 36 | const module = a.getModule('a.js'); 37 | a.getDeclarations().forEach((decl) => { 38 | console.log(module.isUsed(decl.name) ? 'used' : 'not used'); 39 | console.log(decl.name, decl.ast); 40 | }); 41 | 42 | // If you want to mark all exported values of module as used: 43 | a.getModule('root').forceExport(); 44 | ``` 45 | 46 | ## Graphviz 47 | 48 | For debugging and inspection purposes a graph in [dot][2] format may be 49 | generated from the modules hierarchy using following API: 50 | 51 | ```js 52 | const Graph = require('common-shake').Graph; 53 | const graph = new Graph('/path/to/working/dir'); 54 | 55 | console.log(graph.generate(analyzer.getModules())); 56 | ``` 57 | 58 | ## LICENSE 59 | 60 | This software is licensed under the MIT License. 61 | 62 | Copyright Fedor Indutny, 2017. 63 | 64 | Permission is hereby granted, free of charge, to any person obtaining a 65 | copy of this software and associated documentation files (the 66 | "Software"), to deal in the Software without restriction, including 67 | without limitation the rights to use, copy, modify, merge, publish, 68 | distribute, sublicense, and/or sell copies of the Software, and to permit 69 | persons to whom the Software is furnished to do so, subject to the 70 | following conditions: 71 | 72 | The above copyright notice and this permission notice shall be included 73 | in all copies or substantial portions of the Software. 74 | 75 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 76 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 77 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 78 | NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 79 | DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 80 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 81 | USE OR OTHER DEALINGS IN THE SOFTWARE. 82 | 83 | [0]: https://github.com/indutny/webpack-common-shake 84 | [1]: https://webpack.github.io/ 85 | [2]: http://www.graphviz.org/content/dot-language 86 | -------------------------------------------------------------------------------- /lib/shake.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | exports.walk = require('./shake/walk'); 4 | exports.evaluateConst = require('./shake/eval'); 5 | 6 | exports.Module = require('./shake/module'); 7 | exports.Analyzer = require('./shake/analyzer'); 8 | exports.Graph = require('./shake/graph'); 9 | -------------------------------------------------------------------------------- /lib/shake/analyzer.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const escope = require('escope'); 4 | const debug = require('debug')('common-shake:analyzer'); 5 | 6 | const shake = require('../shake'); 7 | const walk = shake.walk; 8 | const Module = shake.Module; 9 | 10 | function Analyzer() { 11 | // All `Module` instances by resource 12 | this.modules = new Map(); 13 | 14 | // All unresolved `Module` instances by parent resource + path 15 | this.unresolved = new Map(); 16 | 17 | // Uses of required module. Map from ast node to `Module` instance 18 | this.moduleUses = null; 19 | 20 | // Uses of `exports` in module. A collection of AST nodes. 21 | this.exportsUses = null; 22 | 23 | // Uses of `require` in module. A collection of AST nodes. 24 | this.requireUses = null; 25 | 26 | // Any global bailouts 27 | this.bailouts = false; 28 | } 29 | module.exports = Analyzer; 30 | 31 | // Public API 32 | 33 | Analyzer.prototype.run = function run(ast, resource) { 34 | this.requireUses = new Set(); 35 | this.exportsUses = new Set(); 36 | this.moduleUses = new Map(); 37 | 38 | const current = this.getModule(resource); 39 | 40 | this.gather(ast, current); 41 | this.sift(ast, current); 42 | 43 | this.moduleUses = null; 44 | this.exportsUses = null; 45 | this.requireUses = null; 46 | 47 | return current; 48 | }; 49 | 50 | Analyzer.prototype.resolve = function resolve(issuer, name, to) { 51 | debug('resolve %j:%j => %j', issuer, name, to); 52 | 53 | const unresolved = this.getUnresolvedModule(issuer, name); 54 | const resolved = this.getModule(to); 55 | 56 | // Already resolved 57 | if (unresolved === resolved) 58 | return; 59 | 60 | resolved.mergeFrom(unresolved); 61 | resolved.addIssuer(this.getModule(issuer)); 62 | this.unresolved.get(issuer).set(name, to); 63 | }; 64 | 65 | Analyzer.prototype.getModule = function getModule(resource) { 66 | let module; 67 | if (this.modules.has(resource)) { 68 | module = this.modules.get(resource); 69 | } else { 70 | module = new Module(resource); 71 | this.modules.set(resource, module); 72 | } 73 | return module; 74 | }; 75 | 76 | Analyzer.prototype.getModules = function getModules() { 77 | return Array.from(this.modules.values()); 78 | }; 79 | 80 | Analyzer.prototype.isSuccess = function isSuccess() { 81 | return this.bailouts === false; 82 | }; 83 | 84 | // Private API 85 | 86 | Analyzer.prototype.gather = function gather(ast, current) { 87 | const manager = escope.analyze(ast, { 88 | ecmaVersion: 6, 89 | sourceType: 'module', 90 | optimistic: true, 91 | ignoreEval: true, 92 | impliedStrict: true 93 | }); 94 | 95 | const scope = manager.acquireAll(ast); 96 | 97 | const declarations = []; 98 | 99 | const queue = scope.slice(); 100 | while (queue.length !== 0) { 101 | const scope = queue.shift(); 102 | 103 | for (let i = 0; i < scope.childScopes.length; i++) 104 | queue.push(scope.childScopes[i]); 105 | 106 | // Skip variables declared in dynamic scopes 107 | if (scope.dynamic) 108 | continue; 109 | 110 | for (let i = 0; i < scope.variables.length; i++) 111 | declarations.push(scope.variables[i]); 112 | } 113 | 114 | // Just to avoid double-bailouts 115 | const seenDefs = new Set(); 116 | for (let i = 0; i < declarations.length; i++) { 117 | const decl = declarations[i]; 118 | 119 | const defs = decl.defs.filter(def => this.isRequireDef(def, decl)); 120 | if (defs.length === 0) 121 | continue; 122 | 123 | if (decl.defs.length !== 1) { 124 | defs.forEach((def) => { 125 | if (seenDefs.has(def.node)) 126 | return; 127 | seenDefs.add(def.node); 128 | 129 | const name = def.node.init.arguments[0].value; 130 | const module = this.getUnresolvedModule(current.resource, name); 131 | 132 | module.bailout('`require` variable override', def.node.loc, 133 | current.resource); 134 | }); 135 | continue; 136 | } 137 | 138 | const node = defs[0].node; 139 | if (seenDefs.has(node)) 140 | continue; 141 | seenDefs.add(node); 142 | 143 | const name = shake.evaluateConst(node.init.arguments[0]); 144 | const module = this.getUnresolvedModule(current.resource, name); 145 | 146 | // Destructuring 147 | if (node.id.type === 'ObjectPattern') { 148 | this.gatherDestructured(module, node.id, current); 149 | continue; 150 | } 151 | 152 | if (node.id.type !== 'Identifier') { 153 | module.bailout('`require` used in unknown way', node.loc, 154 | current.resource); 155 | continue; 156 | } 157 | 158 | for (let i = 0; i < decl.references.length; i++) { 159 | const ref = decl.references[i]; 160 | if (ref.identifier !== node.id) 161 | this.moduleUses.set(ref.identifier, module); 162 | } 163 | } 164 | }; 165 | 166 | Analyzer.prototype.gatherDestructured = function gatherDestructured(module, 167 | id, 168 | current) { 169 | for (let i = 0; i < id.properties.length; i++) { 170 | const prop = id.properties[i]; 171 | 172 | if (prop.key.type !== (prop.computed ? 'Literal' : 'Identifier')) { 173 | module.bailout('Dynamic properties in `require` destructuring', id.loc, 174 | current.resource); 175 | continue; 176 | } 177 | 178 | const key = prop.key.name || prop.key.value; 179 | module.use(key, current, false); 180 | } 181 | }; 182 | 183 | Analyzer.prototype.isRequireDef = function isRequireDef(def, decl) { 184 | if (def.type !== 'Variable') 185 | return false; 186 | 187 | const node = def.node; 188 | if (node.type !== 'VariableDeclarator') 189 | return false; 190 | 191 | if (node.id.type === 'Identifier') { 192 | if (node.id.name === 'exports') { 193 | this.markOverriddenUses(this.exportsUses, decl.references); 194 | return false; 195 | } else if (node.id.name === 'require') { 196 | this.markOverriddenUses(this.requireUses, decl.references); 197 | return false; 198 | } 199 | } 200 | 201 | const init = node.init; 202 | if (!init || init.type !== 'CallExpression') 203 | return false; 204 | 205 | if (init.callee.type !== 'Identifier' || init.callee.name !== 'require') 206 | return false; 207 | 208 | const args = init.arguments; 209 | if (args.length < 1) 210 | return false; 211 | 212 | try { 213 | shake.evaluateConst(args[0]); 214 | } catch (e) { 215 | return false; 216 | } 217 | 218 | // Overridden `require` 219 | if (this.requireUses.has(init.callee)) 220 | return false; 221 | this.requireUses.add(init.callee); 222 | 223 | return true; 224 | }; 225 | 226 | Analyzer.prototype.markOverriddenUses = function markOverriddenUses(set, refs) { 227 | for (let i = 0; i < refs.length; i++) 228 | set.add(refs[i].identifier); 229 | }; 230 | 231 | Analyzer.prototype.isExports = function isExports(node) { 232 | // `exports` 233 | if (node.type === 'Identifier' && node.name === 'exports') 234 | return true; 235 | 236 | // `module.exports` 237 | if (node.type !== 'MemberExpression') 238 | return false; 239 | 240 | const isStatic = 241 | node.property.type === (node.computed ? 'Literal' : 'Identifier'); 242 | if (!isStatic) 243 | return false; 244 | 245 | const key = node.property.name || node.property.value; 246 | return key === 'exports'; 247 | }; 248 | 249 | Analyzer.prototype.sift = function sift(ast, current) { 250 | walk(ast, { 251 | AssignmentExpression: node => this.siftAssignment(node, current), 252 | MemberExpression: node => this.siftMember(node, current, false), 253 | Identifier: node => this.siftRequireUse(node, current), 254 | CallExpression: node => this.siftCall(node, current), 255 | NewExpression: node => this.siftNew(node, current), 256 | UnaryExpression: node => this.siftUnaryExpression(node), 257 | }); 258 | 259 | this.moduleUses.forEach((module, use) => { 260 | module.bailout('Escaping value or unknown use', use.loc, current.resource); 261 | }); 262 | }; 263 | 264 | Analyzer.prototype.siftAssignment = function siftAssignment(node, current) { 265 | if (node.left.type === 'Identifier') { 266 | if (node.left.name === 'exports') { 267 | if (this.exportsUses.has(node.left)) 268 | return; 269 | this.exportsUses.add(node.left); 270 | 271 | current.bailout('`exports` assignment', node.loc); 272 | return; 273 | } 274 | if (node.left.name === 'require') { 275 | if (this.requireUses.has(node.left)) 276 | return; 277 | 278 | this.requireUses.add(node.left); 279 | current.bailout('`require` assignment', node.loc); 280 | return; 281 | } 282 | } 283 | 284 | if (node.left.type !== 'MemberExpression') 285 | return; 286 | 287 | const member = node.left; 288 | 289 | if (this.moduleUses.has(member.object)) { 290 | const module = this.moduleUses.get(member.object); 291 | this.moduleUses.delete(member.object); 292 | module.bailout('Module property assignment', node.loc, current.resource); 293 | return; 294 | } 295 | 296 | const isExports = this.isExports(member.object); 297 | if (!isExports && member.object.type !== 'Identifier') 298 | return; 299 | 300 | const object = isExports ? 'exports' : member.object.name; 301 | if (object !== 'exports' && object !== 'module') 302 | return; 303 | 304 | if (member.property.type !== (member.computed ? 'Literal' : 'Identifier')) { 305 | if (object === 'exports') { 306 | if (this.exportsUses.has(member.object)) 307 | return; 308 | this.exportsUses.add(member.object); 309 | 310 | current.bailout('Dynamic CommonJS export', member.loc); 311 | } else { 312 | current.bailout('Dynamic `module` use', member.loc); 313 | } 314 | return; 315 | } 316 | 317 | const name = member.property.name || member.property.value; 318 | 319 | if (object === 'module') { 320 | if (name !== 'exports') 321 | return; 322 | 323 | this.siftModuleExports(node, current); 324 | return; 325 | } 326 | 327 | if (this.exportsUses.has(member.object)) 328 | return; 329 | this.exportsUses.add(member.object); 330 | 331 | // `exports.a = imported.b` 332 | if (node.right.type === 'MemberExpression') 333 | this.siftMember(node.right, current, name); 334 | 335 | const decl = { 336 | type: 'exports', 337 | name, 338 | ast: node 339 | }; 340 | 341 | if (!current.declare(decl)) { 342 | current.bailout('Simultaneous assignment to both `exports` and ' + 343 | '`module.exports`', node.loc); 344 | } 345 | }; 346 | 347 | Analyzer.prototype.siftModuleExports = function siftModuleExports(node, 348 | current) { 349 | if (node.right.type !== 'ObjectExpression') { 350 | current.bailout('`module.exports` assignment', node.loc, null, 'info'); 351 | return; 352 | } 353 | 354 | // `module.exports = {}` 355 | const props = node.right.properties; 356 | const pairs = []; 357 | for (let i = 0; i < props.length; i++) { 358 | const prop = props[i]; 359 | 360 | if (prop.computed || 361 | (prop.key.type !== 'Literal' && prop.key.type !== 'Identifier')) { 362 | current.bailout('Dynamic `module.exports` property', prop.loc, null); 363 | continue; 364 | } 365 | 366 | const key = prop.key.name || prop.key.value; 367 | 368 | // `module.exports = { a: imported.b }` 369 | if (prop.kind === 'init' && prop.value.type === 'MemberExpression') 370 | this.siftMember(prop.value, current, key); 371 | 372 | pairs.push({ 373 | type: 'module.exports', 374 | name: key, 375 | ast: prop 376 | }); 377 | } 378 | 379 | if (!current.multiDeclare(pairs)) { 380 | current.bailout('Simultaneous assignment to both `exports` and ' + 381 | '`module.exports`', node.loc); 382 | } 383 | }; 384 | 385 | Analyzer.prototype.siftMember = function siftMember(node, current, recursive) { 386 | let module; 387 | if (this.isExports(node.object)) { 388 | // Do not track assignments twice 389 | if (this.exportsUses.has(node.object)) 390 | return; 391 | this.exportsUses.add(node.object); 392 | 393 | module = current; 394 | } else if (node.object.type === 'Identifier' && 395 | node.object.name === 'require') { 396 | // It is ok to use `require` properties 397 | this.requireUses.add(node.object); 398 | return; 399 | } else if (this.moduleUses.has(node.object)) { 400 | module = this.moduleUses.get(node.object); 401 | this.moduleUses.delete(node.object); 402 | } else if (node.object.type === 'CallExpression') { 403 | module = this.siftRequireCall(node.object, current); 404 | if (!module) 405 | return; 406 | } else { 407 | return; 408 | } 409 | 410 | if (node.property.type !== (node.computed ? 'Literal' : 'Identifier')) { 411 | if (module === current) { 412 | module.bailout('Dynamic CommonJS use', node.loc); 413 | } else { 414 | const reason = 'Dynamic CommonJS import'; 415 | module.bailout(reason, node.loc, current.resource); 416 | } 417 | return; 418 | } 419 | 420 | // TODO(indutny): build dependency tree for self-uses. They should not retain 421 | // themselves or others if unused. 422 | const prop = node.property.name || node.property.value; 423 | module.use(prop, current, recursive); 424 | 425 | // For recursive imports 426 | return { module, property: prop }; 427 | }; 428 | 429 | Analyzer.prototype.siftCall = function siftCall(node, current) { 430 | // `lib()` 431 | if (this.moduleUses.has(node.callee)) { 432 | const module = this.moduleUses.get(node.callee); 433 | this.moduleUses.delete(node.callee); 434 | module.bailout('Imported library call', node.loc, current.resource, 'info'); 435 | return; 436 | } 437 | 438 | const module = this.siftRequireCall(node, current); 439 | if (!module) 440 | return; 441 | 442 | // TODO(indutny): support `var lib; lib = require('...')` 443 | module.bailout('Escaping `require` call', node.loc, current.resource); 444 | }; 445 | 446 | Analyzer.prototype.siftNew = function siftNew(node, current) { 447 | // `new lib()` 448 | if (!this.moduleUses.has(node.callee)) 449 | return; 450 | 451 | const module = this.moduleUses.get(node.callee); 452 | this.moduleUses.delete(node.callee); 453 | module.bailout('Imported library new call', node.loc, current.resource, 454 | 'info'); 455 | }; 456 | 457 | Analyzer.prototype.siftUnaryExpression = function siftUnaryExpression(node) { 458 | if (node.operator !== 'typeof') 459 | return false; 460 | 461 | // Mark `typeof require` as a valid use of `require` 462 | const argument = node.argument; 463 | if (argument.type !== 'Identifier' || argument.name !== 'require') 464 | return false; 465 | 466 | if (this.requireUses.has(argument)) 467 | return false; 468 | this.requireUses.add(argument); 469 | }; 470 | 471 | Analyzer.prototype.siftRequireCall = function siftRequireCall(node, current) { 472 | const callee = node.callee; 473 | if (callee.type !== 'Identifier' || callee.name !== 'require') 474 | return false; 475 | 476 | // Valid `require` use 477 | if (this.requireUses.has(callee)) 478 | return false; 479 | this.requireUses.add(callee); 480 | 481 | const args = node.arguments; 482 | if (args.length < 1) 483 | return false; 484 | 485 | let arg; 486 | let fail = false; 487 | try { 488 | arg = shake.evaluateConst(args[0]); 489 | } catch (e) { 490 | fail = true; 491 | } 492 | 493 | if (fail || typeof arg !== 'string') { 494 | const msg = 'Dynamic argument of `require`'; 495 | current.bailout(msg, node.loc); 496 | this.bailout(msg, node.loc, current.resource); 497 | return false; 498 | } 499 | 500 | // TODO(indutny): support `require('./lib')()` 501 | return this.getUnresolvedModule(current.resource, arg); 502 | }; 503 | 504 | Analyzer.prototype.siftRequireUse = function siftRequireUse(node, current) { 505 | if (node.type !== 'Identifier' || node.name !== 'require') 506 | return; 507 | 508 | if (this.requireUses.has(node)) 509 | return; 510 | this.requireUses.add(node); 511 | 512 | current.bailout('Invalid use of `require`', node.loc); 513 | this.bailout('Invalid use of `require`', node.loc, current.resource); 514 | }; 515 | 516 | Analyzer.prototype.getUnresolvedModule = function getUnresolvedModule(issuer, 517 | name) { 518 | let issuerMap; 519 | if (this.unresolved.has(issuer)) { 520 | issuerMap = this.unresolved.get(issuer); 521 | } else { 522 | issuerMap = new Map(); 523 | this.unresolved.set(issuer, issuerMap); 524 | } 525 | 526 | let module; 527 | if (issuerMap.has(name)) { 528 | module = issuerMap.get(name); 529 | } else { 530 | module = new Module(name); 531 | issuerMap.set(name, module); 532 | } 533 | 534 | // Already resolved 535 | if (typeof module === 'string') 536 | return this.getModule(module); 537 | 538 | return module; 539 | }; 540 | 541 | Analyzer.prototype.bailout = function bailout(reason, loc, source) { 542 | if (this.bailouts) 543 | this.bailouts.push({ reason, loc, source }); 544 | else 545 | this.bailouts = [ { reason, loc, source } ]; 546 | }; 547 | -------------------------------------------------------------------------------- /lib/shake/eval.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | function evaluateBinary(node) { 4 | const op = node.operator; 5 | 6 | const left = evaluateConst(node.left); 7 | const right = evaluateConst(node.right); 8 | 9 | if (op === '+') 10 | return left + right; 11 | 12 | throw new Error(`Unsupported binary operation: "${op}"`); 13 | } 14 | 15 | function evaluateConst(node) { 16 | if (node.type === 'Literal') 17 | return node.value; 18 | 19 | if (node.type === 'BinaryExpression') 20 | return evaluateBinary(node); 21 | 22 | throw new Error(`Unsupported node type: "${node.type}"`); 23 | } 24 | module.exports = evaluateConst; 25 | -------------------------------------------------------------------------------- /lib/shake/graph.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | 5 | function Graph(dir) { 6 | this.dir = dir || '.'; 7 | this.relativeCache = new Map(); 8 | } 9 | module.exports = Graph; 10 | 11 | Graph.prototype.generate = function generate(modules) { 12 | const seen = new Set(); 13 | const queue = modules.slice(); 14 | 15 | let out = 'digraph {\n'; 16 | out += ' ranksep=1.2;\n'; 17 | while (queue.length !== 0) { 18 | const module = queue.shift(); 19 | 20 | if (seen.has(module)) 21 | continue; 22 | seen.add(module); 23 | 24 | out += this.generateModule(module); 25 | } 26 | out += '}\n'; 27 | return out; 28 | }; 29 | 30 | Graph.prototype.relative = function relative(file) { 31 | file = file || ''; 32 | if (this.relativeCache.has(file)) 33 | return this.relativeCache.get(file); 34 | 35 | const relative = path.relative(this.dir, file); 36 | this.relativeCache.set(file, relative); 37 | return relative; 38 | }; 39 | 40 | Graph.prototype.escape = function escape(str) { 41 | return `"${str.replace(/"/g, '\\"')}"`; 42 | }; 43 | 44 | Graph.prototype.declarationId = function declarationId(module, name) { 45 | return this.escape(`{${this.relative(module.resource)}}[${name}]`); 46 | }; 47 | 48 | Graph.prototype.moduleId = function moduleId(module) { 49 | return this.escape(`{${this.relative(module.resource)}}/require`); 50 | }; 51 | 52 | Graph.prototype.generateModule = function generateModule(module) { 53 | const resource = this.escape('cluster://' + this.relative(module.resource)); 54 | const label = this.escape(this.relative(module.resource)); 55 | 56 | let out = ''; 57 | 58 | const color = module.bailouts === false ? 'black' : 'red'; 59 | let cluster = ` subgraph ${resource} {\n`; 60 | cluster += ` label=${label};\n`; 61 | cluster += ` color=${color};\n`; 62 | cluster += ` ${this.moduleId(module)} [label=require shape=diamond];\n`; 63 | 64 | const issuersSeen = new Set(); 65 | const declarationsSeen = new Set(); 66 | 67 | const declare = (name) => { 68 | const id = this.declarationId(module, name); 69 | if (declarationsSeen.has(name)) 70 | return id; 71 | 72 | declarationsSeen.add(name); 73 | 74 | const color = module.bailouts === false ? 75 | module.isUsed(name) ? 'black' : 'blue' : 76 | 'red'; 77 | 78 | const shortId = this.escape(`${name}`); 79 | cluster += ` ${id} [label=${shortId} color=${color}];\n`; 80 | 81 | return id; 82 | }; 83 | 84 | // Add all declarations 85 | module.declarations.forEach((declaration) => { 86 | declare(declaration.name); 87 | }); 88 | 89 | // Add uses 90 | module.uses.forEach((issuers, name) => { 91 | issuers.forEach((issuer) => { 92 | issuersSeen.add(issuer); 93 | 94 | out += ` ${this.moduleId(issuer)} -> ${declare(name)};\n`; 95 | }); 96 | }); 97 | 98 | // Add dynamic issuer edges (without particular uses) 99 | module.issuers.forEach((issuer) => { 100 | if (issuersSeen.has(issuer)) 101 | return; 102 | issuersSeen.add(issuer); 103 | 104 | out += ` ${this.moduleId(issuer)} -> ${declare('[*]')};\n`; 105 | }); 106 | 107 | cluster += ' }\n'; 108 | 109 | return cluster + out; 110 | }; 111 | -------------------------------------------------------------------------------- /lib/shake/module.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const debug = require('debug')('common-shake:module'); 4 | 5 | function Module(resource) { 6 | this.resource = resource; 7 | this.bailouts = false; 8 | this.issuers = new Set(); 9 | this.uses = new Map(); 10 | this.declarations = []; 11 | 12 | this.pendingUses = []; 13 | this.computing = false; 14 | this.forced = false; 15 | } 16 | module.exports = Module; 17 | 18 | // Public API 19 | 20 | Module.prototype.forceExport = function forceExport() { 21 | this.forced = true; 22 | }; 23 | 24 | Module.prototype.isUsed = function isUsed(name) { 25 | this.compute(); 26 | 27 | if (this.bailouts || this.forced) 28 | return true; 29 | 30 | // Detect loops 31 | if (this.computing) { 32 | const pending = this.pendingUses.some(use => use.property === name); 33 | if (pending) 34 | return true; 35 | } 36 | 37 | return this.uses.has(name); 38 | }; 39 | 40 | Module.prototype.getInfo = function getInfo() { 41 | this.compute(); 42 | 43 | return { 44 | bailouts: this.bailouts, 45 | declarations: this.declarations.map(decl => decl.name), 46 | uses: Array.from(this.uses.keys()) 47 | }; 48 | }; 49 | 50 | Module.prototype.getDeclarations = function getDeclarations() { 51 | return this.declarations.slice(); 52 | }; 53 | 54 | // Private API 55 | 56 | Module.prototype.bailout = function bailout(reason, loc, source, level) { 57 | const bail = { 58 | reason, 59 | loc, 60 | source: source || null, 61 | level: level || 'warning' 62 | }; 63 | if (this.bailouts) 64 | this.bailouts.push(bail); 65 | else 66 | this.bailouts = [ bail ]; 67 | this.sealed = false; 68 | }; 69 | 70 | Module.prototype.use = function use(property, from, recursive) { 71 | if (recursive !== false) { 72 | debug('pending use this=%j property=%j from=%j recursive=%j', 73 | this.resource, property, from.resource, recursive); 74 | this.pendingUses.push({ property, from, recursive }); 75 | return; 76 | } 77 | 78 | debug('use this=%j property=%j from=%j recursive=%j', 79 | this.resource, property, from.resource, recursive); 80 | 81 | if (this.uses.has(property)) 82 | this.uses.get(property).add(from); 83 | else 84 | this.uses.set(property, new Set([ from ])); 85 | }; 86 | 87 | Module.prototype.seal = function seal() { 88 | this.sealed = true; 89 | }; 90 | 91 | Module.prototype.declare = function declare(property) { 92 | this.declarations.push(property); 93 | 94 | return !this.sealed; 95 | }; 96 | 97 | Module.prototype.multiDeclare = function multiDeclare(declarations) { 98 | const success = this.declarations.length === 0 && !this.sealed; 99 | this.seal(); 100 | for (let i = 0; i < declarations.length; i++) 101 | this.declarations.push(declarations[i]); 102 | return success; 103 | }; 104 | 105 | Module.prototype.mergeFrom = function mergeFrom(unresolved) { 106 | if (unresolved.bailouts) { 107 | unresolved.bailouts.forEach((b) => { 108 | this.bailout(b.reason, b.loc, b.source, b.level); 109 | }); 110 | } 111 | 112 | unresolved.uses.forEach((from, property) => { 113 | from.forEach(resource => this.use(property, resource, false)); 114 | }); 115 | unresolved.declarations.forEach(declaration => this.declare(declaration)); 116 | this.pendingUses = this.pendingUses.concat(unresolved.pendingUses); 117 | 118 | unresolved.clear(); 119 | }; 120 | 121 | Module.prototype.addIssuer = function addIssuer(issuer) { 122 | this.issuers.add(issuer); 123 | }; 124 | 125 | Module.prototype.clear = function clear() { 126 | this.uses = null; 127 | this.declarations = null; 128 | this.pendingUses = null; 129 | }; 130 | 131 | Module.prototype.compute = function compute() { 132 | // Already computed or cleared 133 | if (this.pendingUses === null) 134 | return; 135 | 136 | if (this.computing) 137 | return; 138 | this.computing = true; 139 | debug('compute this=%j pending=%d', this.resource, this.pendingUses.length); 140 | 141 | // Do several passes until it will stabilize 142 | // TODO(indutny): what is complexity of this? Exponential? 143 | let before; 144 | do { 145 | before = this.pendingUses.length; 146 | 147 | // NOTE: it is important to overwrite this, since recursive lookups will 148 | // get to it. 149 | this.pendingUses = this.pendingUses.filter((use) => { 150 | return use.from.isUsed(use.recursive); 151 | }); 152 | debug('compute pass this=%j before=%d after=%d', 153 | this.resource, before, this.pendingUses.length); 154 | } while (this.pendingUses.length !== before); 155 | 156 | this.pendingUses.forEach(use => this.use(use.property, use.from, false)); 157 | 158 | this.pendingUses = null; 159 | this.computing = false; 160 | }; 161 | -------------------------------------------------------------------------------- /lib/shake/walk.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const walk = require('acorn/dist/walk'); 4 | 5 | const BASE = Object.assign({ 6 | // acorn-dynamic-import support 7 | Import: () => {} 8 | }, walk.base); 9 | 10 | // Pre-order walker 11 | module.exports = (node, visitors) => { 12 | const state = null; 13 | const override = false; 14 | !function c(node, st, override) { 15 | var type = override || node.type, found = visitors[type]; 16 | if (found) found(node, st); 17 | BASE[type](node, st, c); 18 | }(node, state, override); 19 | }; 20 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common-shake", 3 | "version": "2.1.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "5.1.1", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", 10 | "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==" 11 | }, 12 | "acorn-dynamic-import": { 13 | "version": "2.0.2", 14 | "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-2.0.2.tgz", 15 | "integrity": "sha1-x1K9IQvvZ5UBtsbLf8hPj0cVjMQ=", 16 | "dev": true, 17 | "requires": { 18 | "acorn": "4.0.13" 19 | }, 20 | "dependencies": { 21 | "acorn": { 22 | "version": "4.0.13", 23 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz", 24 | "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c=", 25 | "dev": true 26 | } 27 | } 28 | }, 29 | "acorn-jsx": { 30 | "version": "3.0.1", 31 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 32 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 33 | "dev": true, 34 | "requires": { 35 | "acorn": "3.3.0" 36 | }, 37 | "dependencies": { 38 | "acorn": { 39 | "version": "3.3.0", 40 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 41 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 42 | "dev": true 43 | } 44 | } 45 | }, 46 | "ajv": { 47 | "version": "4.11.8", 48 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", 49 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", 50 | "dev": true, 51 | "requires": { 52 | "co": "4.6.0", 53 | "json-stable-stringify": "1.0.1" 54 | } 55 | }, 56 | "ajv-keywords": { 57 | "version": "1.5.1", 58 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", 59 | "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", 60 | "dev": true 61 | }, 62 | "ansi-escapes": { 63 | "version": "2.0.0", 64 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", 65 | "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", 66 | "dev": true 67 | }, 68 | "ansi-regex": { 69 | "version": "2.1.1", 70 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 71 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 72 | "dev": true 73 | }, 74 | "ansi-styles": { 75 | "version": "2.2.1", 76 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 77 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 78 | "dev": true 79 | }, 80 | "argparse": { 81 | "version": "1.0.9", 82 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", 83 | "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", 84 | "dev": true, 85 | "requires": { 86 | "sprintf-js": "1.0.3" 87 | } 88 | }, 89 | "array-union": { 90 | "version": "1.0.2", 91 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", 92 | "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", 93 | "dev": true, 94 | "requires": { 95 | "array-uniq": "1.0.3" 96 | } 97 | }, 98 | "array-uniq": { 99 | "version": "1.0.3", 100 | "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", 101 | "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", 102 | "dev": true 103 | }, 104 | "arrify": { 105 | "version": "1.0.1", 106 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 107 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 108 | "dev": true 109 | }, 110 | "assert-text": { 111 | "version": "1.1.2", 112 | "resolved": "https://registry.npmjs.org/assert-text/-/assert-text-1.1.2.tgz", 113 | "integrity": "sha1-lywiuqub9xs/dKkEMmbcdmOKVaI=", 114 | "dev": true 115 | }, 116 | "babel-code-frame": { 117 | "version": "6.22.0", 118 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.22.0.tgz", 119 | "integrity": "sha1-AnYgvuVnqIwyVhV05/0IAdMxGOQ=", 120 | "dev": true, 121 | "requires": { 122 | "chalk": "1.1.3", 123 | "esutils": "2.0.2", 124 | "js-tokens": "3.0.2" 125 | } 126 | }, 127 | "balanced-match": { 128 | "version": "1.0.0", 129 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 130 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 131 | "dev": true 132 | }, 133 | "brace-expansion": { 134 | "version": "1.1.8", 135 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", 136 | "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", 137 | "dev": true, 138 | "requires": { 139 | "balanced-match": "1.0.0", 140 | "concat-map": "0.0.1" 141 | } 142 | }, 143 | "browser-stdout": { 144 | "version": "1.3.0", 145 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 146 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 147 | "dev": true 148 | }, 149 | "caller-path": { 150 | "version": "0.1.0", 151 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 152 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 153 | "dev": true, 154 | "requires": { 155 | "callsites": "0.2.0" 156 | } 157 | }, 158 | "callsites": { 159 | "version": "0.2.0", 160 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 161 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 162 | "dev": true 163 | }, 164 | "chalk": { 165 | "version": "1.1.3", 166 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 167 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 168 | "dev": true, 169 | "requires": { 170 | "ansi-styles": "2.2.1", 171 | "escape-string-regexp": "1.0.5", 172 | "has-ansi": "2.0.0", 173 | "strip-ansi": "3.0.1", 174 | "supports-color": "2.0.0" 175 | }, 176 | "dependencies": { 177 | "supports-color": { 178 | "version": "2.0.0", 179 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 180 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 181 | "dev": true 182 | } 183 | } 184 | }, 185 | "circular-json": { 186 | "version": "0.3.1", 187 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.1.tgz", 188 | "integrity": "sha1-vos2rvzN6LPKeqLWr8B6NyQsDS0=", 189 | "dev": true 190 | }, 191 | "cli-cursor": { 192 | "version": "2.1.0", 193 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", 194 | "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", 195 | "dev": true, 196 | "requires": { 197 | "restore-cursor": "2.0.0" 198 | } 199 | }, 200 | "cli-width": { 201 | "version": "2.1.0", 202 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.1.0.tgz", 203 | "integrity": "sha1-sjTKIJsp72b8UY2bmNWEewDt8Ao=", 204 | "dev": true 205 | }, 206 | "co": { 207 | "version": "4.6.0", 208 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 209 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 210 | "dev": true 211 | }, 212 | "commander": { 213 | "version": "2.9.0", 214 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 215 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 216 | "dev": true, 217 | "requires": { 218 | "graceful-readlink": "1.0.1" 219 | } 220 | }, 221 | "concat-map": { 222 | "version": "0.0.1", 223 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 224 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 225 | "dev": true 226 | }, 227 | "concat-stream": { 228 | "version": "1.6.0", 229 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", 230 | "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", 231 | "dev": true, 232 | "requires": { 233 | "inherits": "2.0.3", 234 | "readable-stream": "2.3.3", 235 | "typedarray": "0.0.6" 236 | } 237 | }, 238 | "core-util-is": { 239 | "version": "1.0.2", 240 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 241 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", 242 | "dev": true 243 | }, 244 | "d": { 245 | "version": "1.0.0", 246 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", 247 | "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", 248 | "requires": { 249 | "es5-ext": "0.10.23" 250 | } 251 | }, 252 | "debug": { 253 | "version": "2.6.8", 254 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", 255 | "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", 256 | "requires": { 257 | "ms": "2.0.0" 258 | }, 259 | "dependencies": { 260 | "ms": { 261 | "version": "2.0.0", 262 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 263 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 264 | } 265 | } 266 | }, 267 | "deep-is": { 268 | "version": "0.1.3", 269 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 270 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 271 | "dev": true 272 | }, 273 | "del": { 274 | "version": "2.2.2", 275 | "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", 276 | "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", 277 | "dev": true, 278 | "requires": { 279 | "globby": "5.0.0", 280 | "is-path-cwd": "1.0.0", 281 | "is-path-in-cwd": "1.0.0", 282 | "object-assign": "4.1.1", 283 | "pify": "2.3.0", 284 | "pinkie-promise": "2.0.1", 285 | "rimraf": "2.6.1" 286 | } 287 | }, 288 | "diff": { 289 | "version": "3.2.0", 290 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", 291 | "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", 292 | "dev": true 293 | }, 294 | "doctrine": { 295 | "version": "2.0.0", 296 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", 297 | "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", 298 | "dev": true, 299 | "requires": { 300 | "esutils": "2.0.2", 301 | "isarray": "1.0.0" 302 | } 303 | }, 304 | "es5-ext": { 305 | "version": "0.10.23", 306 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.23.tgz", 307 | "integrity": "sha1-dXi1G+l0IHpUh4IbVlOMIk5Oezg=", 308 | "requires": { 309 | "es6-iterator": "2.0.1", 310 | "es6-symbol": "3.1.1" 311 | } 312 | }, 313 | "es6-iterator": { 314 | "version": "2.0.1", 315 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.1.tgz", 316 | "integrity": "sha1-jjGcnwRTv1ddN0lAplWSDlnKVRI=", 317 | "requires": { 318 | "d": "1.0.0", 319 | "es5-ext": "0.10.23", 320 | "es6-symbol": "3.1.1" 321 | } 322 | }, 323 | "es6-map": { 324 | "version": "0.1.5", 325 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", 326 | "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", 327 | "requires": { 328 | "d": "1.0.0", 329 | "es5-ext": "0.10.23", 330 | "es6-iterator": "2.0.1", 331 | "es6-set": "0.1.5", 332 | "es6-symbol": "3.1.1", 333 | "event-emitter": "0.3.5" 334 | } 335 | }, 336 | "es6-set": { 337 | "version": "0.1.5", 338 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", 339 | "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", 340 | "requires": { 341 | "d": "1.0.0", 342 | "es5-ext": "0.10.23", 343 | "es6-iterator": "2.0.1", 344 | "es6-symbol": "3.1.1", 345 | "event-emitter": "0.3.5" 346 | } 347 | }, 348 | "es6-symbol": { 349 | "version": "3.1.1", 350 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", 351 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", 352 | "requires": { 353 | "d": "1.0.0", 354 | "es5-ext": "0.10.23" 355 | } 356 | }, 357 | "es6-weak-map": { 358 | "version": "2.0.2", 359 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", 360 | "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", 361 | "requires": { 362 | "d": "1.0.0", 363 | "es5-ext": "0.10.23", 364 | "es6-iterator": "2.0.1", 365 | "es6-symbol": "3.1.1" 366 | } 367 | }, 368 | "escape-string-regexp": { 369 | "version": "1.0.5", 370 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 371 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 372 | "dev": true 373 | }, 374 | "escope": { 375 | "version": "3.6.0", 376 | "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", 377 | "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", 378 | "requires": { 379 | "es6-map": "0.1.5", 380 | "es6-weak-map": "2.0.2", 381 | "esrecurse": "4.2.0", 382 | "estraverse": "4.2.0" 383 | } 384 | }, 385 | "eslint": { 386 | "version": "4.1.1", 387 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.1.1.tgz", 388 | "integrity": "sha1-+svfz+Pg+s06i4DcmMTmwTrlgt8=", 389 | "dev": true, 390 | "requires": { 391 | "babel-code-frame": "6.22.0", 392 | "chalk": "1.1.3", 393 | "concat-stream": "1.6.0", 394 | "debug": "2.6.8", 395 | "doctrine": "2.0.0", 396 | "eslint-scope": "3.7.1", 397 | "espree": "3.4.3", 398 | "esquery": "1.0.0", 399 | "estraverse": "4.2.0", 400 | "esutils": "2.0.2", 401 | "file-entry-cache": "2.0.0", 402 | "glob": "7.1.2", 403 | "globals": "9.18.0", 404 | "ignore": "3.3.3", 405 | "imurmurhash": "0.1.4", 406 | "inquirer": "3.1.1", 407 | "is-my-json-valid": "2.16.0", 408 | "is-resolvable": "1.0.0", 409 | "js-yaml": "3.8.4", 410 | "json-stable-stringify": "1.0.1", 411 | "levn": "0.3.0", 412 | "lodash": "4.17.4", 413 | "minimatch": "3.0.4", 414 | "mkdirp": "0.5.1", 415 | "natural-compare": "1.4.0", 416 | "optionator": "0.8.2", 417 | "path-is-inside": "1.0.2", 418 | "pluralize": "4.0.0", 419 | "progress": "2.0.0", 420 | "require-uncached": "1.0.3", 421 | "strip-json-comments": "2.0.1", 422 | "table": "4.0.1", 423 | "text-table": "0.2.0" 424 | }, 425 | "dependencies": { 426 | "debug": { 427 | "version": "2.6.8", 428 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", 429 | "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", 430 | "dev": true, 431 | "requires": { 432 | "ms": "2.0.0" 433 | } 434 | }, 435 | "glob": { 436 | "version": "7.1.2", 437 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", 438 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", 439 | "dev": true, 440 | "requires": { 441 | "fs.realpath": "1.0.0", 442 | "inflight": "1.0.6", 443 | "inherits": "2.0.3", 444 | "minimatch": "3.0.4", 445 | "once": "1.4.0", 446 | "path-is-absolute": "1.0.1" 447 | } 448 | }, 449 | "ms": { 450 | "version": "2.0.0", 451 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 452 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", 453 | "dev": true 454 | } 455 | } 456 | }, 457 | "eslint-scope": { 458 | "version": "3.7.1", 459 | "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", 460 | "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", 461 | "dev": true, 462 | "requires": { 463 | "esrecurse": "4.2.0", 464 | "estraverse": "4.2.0" 465 | } 466 | }, 467 | "espree": { 468 | "version": "3.4.3", 469 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", 470 | "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", 471 | "dev": true, 472 | "requires": { 473 | "acorn": "5.1.1", 474 | "acorn-jsx": "3.0.1" 475 | } 476 | }, 477 | "esprima": { 478 | "version": "3.1.3", 479 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", 480 | "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", 481 | "dev": true 482 | }, 483 | "esquery": { 484 | "version": "1.0.0", 485 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", 486 | "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", 487 | "dev": true, 488 | "requires": { 489 | "estraverse": "4.2.0" 490 | } 491 | }, 492 | "esrecurse": { 493 | "version": "4.2.0", 494 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", 495 | "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", 496 | "requires": { 497 | "estraverse": "4.2.0", 498 | "object-assign": "4.1.1" 499 | } 500 | }, 501 | "estraverse": { 502 | "version": "4.2.0", 503 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", 504 | "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" 505 | }, 506 | "esutils": { 507 | "version": "2.0.2", 508 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", 509 | "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", 510 | "dev": true 511 | }, 512 | "event-emitter": { 513 | "version": "0.3.5", 514 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 515 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 516 | "requires": { 517 | "d": "1.0.0", 518 | "es5-ext": "0.10.23" 519 | } 520 | }, 521 | "external-editor": { 522 | "version": "2.0.4", 523 | "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", 524 | "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", 525 | "dev": true, 526 | "requires": { 527 | "iconv-lite": "0.4.18", 528 | "jschardet": "1.4.2", 529 | "tmp": "0.0.31" 530 | } 531 | }, 532 | "fast-levenshtein": { 533 | "version": "2.0.6", 534 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 535 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 536 | "dev": true 537 | }, 538 | "figures": { 539 | "version": "2.0.0", 540 | "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", 541 | "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", 542 | "dev": true, 543 | "requires": { 544 | "escape-string-regexp": "1.0.5" 545 | } 546 | }, 547 | "file-entry-cache": { 548 | "version": "2.0.0", 549 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 550 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 551 | "dev": true, 552 | "requires": { 553 | "flat-cache": "1.2.2", 554 | "object-assign": "4.1.1" 555 | } 556 | }, 557 | "flat-cache": { 558 | "version": "1.2.2", 559 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", 560 | "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", 561 | "dev": true, 562 | "requires": { 563 | "circular-json": "0.3.1", 564 | "del": "2.2.2", 565 | "graceful-fs": "4.1.11", 566 | "write": "0.2.1" 567 | } 568 | }, 569 | "fs.realpath": { 570 | "version": "1.0.0", 571 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 572 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 573 | "dev": true 574 | }, 575 | "generate-function": { 576 | "version": "2.0.0", 577 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", 578 | "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", 579 | "dev": true 580 | }, 581 | "generate-object-property": { 582 | "version": "1.2.0", 583 | "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", 584 | "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", 585 | "dev": true, 586 | "requires": { 587 | "is-property": "1.0.2" 588 | } 589 | }, 590 | "glob": { 591 | "version": "7.1.1", 592 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 593 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 594 | "dev": true, 595 | "requires": { 596 | "fs.realpath": "1.0.0", 597 | "inflight": "1.0.6", 598 | "inherits": "2.0.3", 599 | "minimatch": "3.0.4", 600 | "once": "1.4.0", 601 | "path-is-absolute": "1.0.1" 602 | } 603 | }, 604 | "globals": { 605 | "version": "9.18.0", 606 | "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", 607 | "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", 608 | "dev": true 609 | }, 610 | "globby": { 611 | "version": "5.0.0", 612 | "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", 613 | "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", 614 | "dev": true, 615 | "requires": { 616 | "array-union": "1.0.2", 617 | "arrify": "1.0.1", 618 | "glob": "7.1.1", 619 | "object-assign": "4.1.1", 620 | "pify": "2.3.0", 621 | "pinkie-promise": "2.0.1" 622 | } 623 | }, 624 | "graceful-fs": { 625 | "version": "4.1.11", 626 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", 627 | "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", 628 | "dev": true 629 | }, 630 | "graceful-readlink": { 631 | "version": "1.0.1", 632 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 633 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 634 | "dev": true 635 | }, 636 | "growl": { 637 | "version": "1.9.2", 638 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 639 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 640 | "dev": true 641 | }, 642 | "has-ansi": { 643 | "version": "2.0.0", 644 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 645 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 646 | "dev": true, 647 | "requires": { 648 | "ansi-regex": "2.1.1" 649 | } 650 | }, 651 | "has-flag": { 652 | "version": "1.0.0", 653 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 654 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 655 | "dev": true 656 | }, 657 | "iconv-lite": { 658 | "version": "0.4.18", 659 | "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", 660 | "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", 661 | "dev": true 662 | }, 663 | "ignore": { 664 | "version": "3.3.3", 665 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.3.tgz", 666 | "integrity": "sha1-QyNS5XrM2HqzEQ6C0/6g5HgSFW0=", 667 | "dev": true 668 | }, 669 | "imurmurhash": { 670 | "version": "0.1.4", 671 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 672 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 673 | "dev": true 674 | }, 675 | "inflight": { 676 | "version": "1.0.6", 677 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 678 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 679 | "dev": true, 680 | "requires": { 681 | "once": "1.4.0", 682 | "wrappy": "1.0.2" 683 | } 684 | }, 685 | "inherits": { 686 | "version": "2.0.3", 687 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", 688 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", 689 | "dev": true 690 | }, 691 | "inquirer": { 692 | "version": "3.1.1", 693 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.1.1.tgz", 694 | "integrity": "sha512-H50sHQwgvvaTBd3HpKMVtL/u6LoHDvYym51gd7bGQe/+9HkCE+J0/3N5FJLfd6O6oz44hHewC2Pc2LodzWVafQ==", 695 | "dev": true, 696 | "requires": { 697 | "ansi-escapes": "2.0.0", 698 | "chalk": "1.1.3", 699 | "cli-cursor": "2.1.0", 700 | "cli-width": "2.1.0", 701 | "external-editor": "2.0.4", 702 | "figures": "2.0.0", 703 | "lodash": "4.17.4", 704 | "mute-stream": "0.0.7", 705 | "run-async": "2.3.0", 706 | "rx-lite": "4.0.8", 707 | "rx-lite-aggregates": "4.0.8", 708 | "string-width": "2.1.0", 709 | "strip-ansi": "3.0.1", 710 | "through": "2.3.8" 711 | } 712 | }, 713 | "is-fullwidth-code-point": { 714 | "version": "2.0.0", 715 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 716 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 717 | "dev": true 718 | }, 719 | "is-my-json-valid": { 720 | "version": "2.16.0", 721 | "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.0.tgz", 722 | "integrity": "sha1-8Hndm/2uZe4gOKrorLyGqxCeNpM=", 723 | "dev": true, 724 | "requires": { 725 | "generate-function": "2.0.0", 726 | "generate-object-property": "1.2.0", 727 | "jsonpointer": "4.0.1", 728 | "xtend": "4.0.1" 729 | } 730 | }, 731 | "is-path-cwd": { 732 | "version": "1.0.0", 733 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", 734 | "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", 735 | "dev": true 736 | }, 737 | "is-path-in-cwd": { 738 | "version": "1.0.0", 739 | "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", 740 | "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", 741 | "dev": true, 742 | "requires": { 743 | "is-path-inside": "1.0.0" 744 | } 745 | }, 746 | "is-path-inside": { 747 | "version": "1.0.0", 748 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", 749 | "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", 750 | "dev": true, 751 | "requires": { 752 | "path-is-inside": "1.0.2" 753 | } 754 | }, 755 | "is-promise": { 756 | "version": "2.1.0", 757 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", 758 | "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", 759 | "dev": true 760 | }, 761 | "is-property": { 762 | "version": "1.0.2", 763 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 764 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", 765 | "dev": true 766 | }, 767 | "is-resolvable": { 768 | "version": "1.0.0", 769 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", 770 | "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", 771 | "dev": true, 772 | "requires": { 773 | "tryit": "1.0.3" 774 | } 775 | }, 776 | "isarray": { 777 | "version": "1.0.0", 778 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 779 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", 780 | "dev": true 781 | }, 782 | "js-tokens": { 783 | "version": "3.0.2", 784 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 785 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 786 | "dev": true 787 | }, 788 | "js-yaml": { 789 | "version": "3.8.4", 790 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.8.4.tgz", 791 | "integrity": "sha1-UgtFZPhlc7qWZir4Woyvp7S1pvY=", 792 | "dev": true, 793 | "requires": { 794 | "argparse": "1.0.9", 795 | "esprima": "3.1.3" 796 | } 797 | }, 798 | "jschardet": { 799 | "version": "1.4.2", 800 | "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.4.2.tgz", 801 | "integrity": "sha1-KqEH8UKvQSHRRWWdRPUIMJYeaZo=", 802 | "dev": true 803 | }, 804 | "json-stable-stringify": { 805 | "version": "1.0.1", 806 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 807 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 808 | "dev": true, 809 | "requires": { 810 | "jsonify": "0.0.0" 811 | } 812 | }, 813 | "json3": { 814 | "version": "3.3.2", 815 | "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 816 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", 817 | "dev": true 818 | }, 819 | "jsonify": { 820 | "version": "0.0.0", 821 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 822 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", 823 | "dev": true 824 | }, 825 | "jsonpointer": { 826 | "version": "4.0.1", 827 | "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", 828 | "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", 829 | "dev": true 830 | }, 831 | "levn": { 832 | "version": "0.3.0", 833 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 834 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 835 | "dev": true, 836 | "requires": { 837 | "prelude-ls": "1.1.2", 838 | "type-check": "0.3.2" 839 | } 840 | }, 841 | "lodash": { 842 | "version": "4.17.4", 843 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", 844 | "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", 845 | "dev": true 846 | }, 847 | "lodash._baseassign": { 848 | "version": "3.2.0", 849 | "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 850 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", 851 | "dev": true, 852 | "requires": { 853 | "lodash._basecopy": "3.0.1", 854 | "lodash.keys": "3.1.2" 855 | } 856 | }, 857 | "lodash._basecopy": { 858 | "version": "3.0.1", 859 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 860 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", 861 | "dev": true 862 | }, 863 | "lodash._basecreate": { 864 | "version": "3.0.3", 865 | "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 866 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", 867 | "dev": true 868 | }, 869 | "lodash._getnative": { 870 | "version": "3.9.1", 871 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 872 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", 873 | "dev": true 874 | }, 875 | "lodash._isiterateecall": { 876 | "version": "3.0.9", 877 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 878 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", 879 | "dev": true 880 | }, 881 | "lodash.create": { 882 | "version": "3.1.1", 883 | "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 884 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", 885 | "dev": true, 886 | "requires": { 887 | "lodash._baseassign": "3.2.0", 888 | "lodash._basecreate": "3.0.3", 889 | "lodash._isiterateecall": "3.0.9" 890 | } 891 | }, 892 | "lodash.isarguments": { 893 | "version": "3.1.0", 894 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 895 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", 896 | "dev": true 897 | }, 898 | "lodash.isarray": { 899 | "version": "3.0.4", 900 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 901 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", 902 | "dev": true 903 | }, 904 | "lodash.keys": { 905 | "version": "3.1.2", 906 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 907 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 908 | "dev": true, 909 | "requires": { 910 | "lodash._getnative": "3.9.1", 911 | "lodash.isarguments": "3.1.0", 912 | "lodash.isarray": "3.0.4" 913 | } 914 | }, 915 | "mimic-fn": { 916 | "version": "1.1.0", 917 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", 918 | "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", 919 | "dev": true 920 | }, 921 | "minimatch": { 922 | "version": "3.0.4", 923 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 924 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 925 | "dev": true, 926 | "requires": { 927 | "brace-expansion": "1.1.8" 928 | } 929 | }, 930 | "minimist": { 931 | "version": "0.0.8", 932 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 933 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 934 | "dev": true 935 | }, 936 | "mkdirp": { 937 | "version": "0.5.1", 938 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 939 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 940 | "dev": true, 941 | "requires": { 942 | "minimist": "0.0.8" 943 | } 944 | }, 945 | "mocha": { 946 | "version": "3.4.2", 947 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz", 948 | "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=", 949 | "dev": true, 950 | "requires": { 951 | "browser-stdout": "1.3.0", 952 | "commander": "2.9.0", 953 | "debug": "2.6.8", 954 | "diff": "3.2.0", 955 | "escape-string-regexp": "1.0.5", 956 | "glob": "7.1.1", 957 | "growl": "1.9.2", 958 | "json3": "3.3.2", 959 | "lodash.create": "3.1.1", 960 | "mkdirp": "0.5.1", 961 | "supports-color": "3.1.2" 962 | } 963 | }, 964 | "mute-stream": { 965 | "version": "0.0.7", 966 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", 967 | "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", 968 | "dev": true 969 | }, 970 | "natural-compare": { 971 | "version": "1.4.0", 972 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 973 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 974 | "dev": true 975 | }, 976 | "nyc": { 977 | "version": "11.0.3", 978 | "resolved": "https://registry.npmjs.org/nyc/-/nyc-11.0.3.tgz", 979 | "integrity": "sha1-DCi8ZpqFFiFwm/eghQMDS+44ErY=", 980 | "dev": true, 981 | "requires": { 982 | "archy": "1.0.0", 983 | "arrify": "1.0.1", 984 | "caching-transform": "1.0.1", 985 | "convert-source-map": "1.5.0", 986 | "debug-log": "1.0.1", 987 | "default-require-extensions": "1.0.0", 988 | "find-cache-dir": "0.1.1", 989 | "find-up": "2.1.0", 990 | "foreground-child": "1.5.6", 991 | "glob": "7.1.2", 992 | "istanbul-lib-coverage": "1.1.1", 993 | "istanbul-lib-hook": "1.0.7", 994 | "istanbul-lib-instrument": "1.7.3", 995 | "istanbul-lib-report": "1.1.1", 996 | "istanbul-lib-source-maps": "1.2.1", 997 | "istanbul-reports": "1.1.1", 998 | "md5-hex": "1.3.0", 999 | "merge-source-map": "1.0.4", 1000 | "micromatch": "2.3.11", 1001 | "mkdirp": "0.5.1", 1002 | "resolve-from": "2.0.0", 1003 | "rimraf": "2.6.1", 1004 | "signal-exit": "3.0.2", 1005 | "spawn-wrap": "1.3.7", 1006 | "test-exclude": "4.1.1", 1007 | "yargs": "8.0.2", 1008 | "yargs-parser": "5.0.0" 1009 | }, 1010 | "dependencies": { 1011 | "align-text": { 1012 | "version": "0.1.4", 1013 | "bundled": true, 1014 | "dev": true, 1015 | "requires": { 1016 | "kind-of": "3.2.2", 1017 | "longest": "1.0.1", 1018 | "repeat-string": "1.6.1" 1019 | } 1020 | }, 1021 | "amdefine": { 1022 | "version": "1.0.1", 1023 | "bundled": true, 1024 | "dev": true 1025 | }, 1026 | "ansi-regex": { 1027 | "version": "2.1.1", 1028 | "bundled": true, 1029 | "dev": true 1030 | }, 1031 | "ansi-styles": { 1032 | "version": "2.2.1", 1033 | "bundled": true, 1034 | "dev": true 1035 | }, 1036 | "append-transform": { 1037 | "version": "0.4.0", 1038 | "bundled": true, 1039 | "dev": true, 1040 | "requires": { 1041 | "default-require-extensions": "1.0.0" 1042 | } 1043 | }, 1044 | "archy": { 1045 | "version": "1.0.0", 1046 | "bundled": true, 1047 | "dev": true 1048 | }, 1049 | "arr-diff": { 1050 | "version": "2.0.0", 1051 | "bundled": true, 1052 | "dev": true, 1053 | "requires": { 1054 | "arr-flatten": "1.0.3" 1055 | } 1056 | }, 1057 | "arr-flatten": { 1058 | "version": "1.0.3", 1059 | "bundled": true, 1060 | "dev": true 1061 | }, 1062 | "array-unique": { 1063 | "version": "0.2.1", 1064 | "bundled": true, 1065 | "dev": true 1066 | }, 1067 | "arrify": { 1068 | "version": "1.0.1", 1069 | "bundled": true, 1070 | "dev": true 1071 | }, 1072 | "async": { 1073 | "version": "1.5.2", 1074 | "bundled": true, 1075 | "dev": true 1076 | }, 1077 | "babel-code-frame": { 1078 | "version": "6.22.0", 1079 | "bundled": true, 1080 | "dev": true, 1081 | "requires": { 1082 | "chalk": "1.1.3", 1083 | "esutils": "2.0.2", 1084 | "js-tokens": "3.0.1" 1085 | } 1086 | }, 1087 | "babel-generator": { 1088 | "version": "6.25.0", 1089 | "bundled": true, 1090 | "dev": true, 1091 | "requires": { 1092 | "babel-messages": "6.23.0", 1093 | "babel-runtime": "6.23.0", 1094 | "babel-types": "6.25.0", 1095 | "detect-indent": "4.0.0", 1096 | "jsesc": "1.3.0", 1097 | "lodash": "4.17.4", 1098 | "source-map": "0.5.6", 1099 | "trim-right": "1.0.1" 1100 | } 1101 | }, 1102 | "babel-messages": { 1103 | "version": "6.23.0", 1104 | "bundled": true, 1105 | "dev": true, 1106 | "requires": { 1107 | "babel-runtime": "6.23.0" 1108 | } 1109 | }, 1110 | "babel-runtime": { 1111 | "version": "6.23.0", 1112 | "bundled": true, 1113 | "dev": true, 1114 | "requires": { 1115 | "core-js": "2.4.1", 1116 | "regenerator-runtime": "0.10.5" 1117 | } 1118 | }, 1119 | "babel-template": { 1120 | "version": "6.25.0", 1121 | "bundled": true, 1122 | "dev": true, 1123 | "requires": { 1124 | "babel-runtime": "6.23.0", 1125 | "babel-traverse": "6.25.0", 1126 | "babel-types": "6.25.0", 1127 | "babylon": "6.17.4", 1128 | "lodash": "4.17.4" 1129 | } 1130 | }, 1131 | "babel-traverse": { 1132 | "version": "6.25.0", 1133 | "bundled": true, 1134 | "dev": true, 1135 | "requires": { 1136 | "babel-code-frame": "6.22.0", 1137 | "babel-messages": "6.23.0", 1138 | "babel-runtime": "6.23.0", 1139 | "babel-types": "6.25.0", 1140 | "babylon": "6.17.4", 1141 | "debug": "2.6.8", 1142 | "globals": "9.18.0", 1143 | "invariant": "2.2.2", 1144 | "lodash": "4.17.4" 1145 | } 1146 | }, 1147 | "babel-types": { 1148 | "version": "6.25.0", 1149 | "bundled": true, 1150 | "dev": true, 1151 | "requires": { 1152 | "babel-runtime": "6.23.0", 1153 | "esutils": "2.0.2", 1154 | "lodash": "4.17.4", 1155 | "to-fast-properties": "1.0.3" 1156 | } 1157 | }, 1158 | "babylon": { 1159 | "version": "6.17.4", 1160 | "bundled": true, 1161 | "dev": true 1162 | }, 1163 | "balanced-match": { 1164 | "version": "1.0.0", 1165 | "bundled": true, 1166 | "dev": true 1167 | }, 1168 | "brace-expansion": { 1169 | "version": "1.1.8", 1170 | "bundled": true, 1171 | "dev": true, 1172 | "requires": { 1173 | "balanced-match": "1.0.0", 1174 | "concat-map": "0.0.1" 1175 | } 1176 | }, 1177 | "braces": { 1178 | "version": "1.8.5", 1179 | "bundled": true, 1180 | "dev": true, 1181 | "requires": { 1182 | "expand-range": "1.8.2", 1183 | "preserve": "0.2.0", 1184 | "repeat-element": "1.1.2" 1185 | } 1186 | }, 1187 | "builtin-modules": { 1188 | "version": "1.1.1", 1189 | "bundled": true, 1190 | "dev": true 1191 | }, 1192 | "caching-transform": { 1193 | "version": "1.0.1", 1194 | "bundled": true, 1195 | "dev": true, 1196 | "requires": { 1197 | "md5-hex": "1.3.0", 1198 | "mkdirp": "0.5.1", 1199 | "write-file-atomic": "1.3.4" 1200 | } 1201 | }, 1202 | "camelcase": { 1203 | "version": "1.2.1", 1204 | "bundled": true, 1205 | "dev": true, 1206 | "optional": true 1207 | }, 1208 | "center-align": { 1209 | "version": "0.1.3", 1210 | "bundled": true, 1211 | "dev": true, 1212 | "optional": true, 1213 | "requires": { 1214 | "align-text": "0.1.4", 1215 | "lazy-cache": "1.0.4" 1216 | } 1217 | }, 1218 | "chalk": { 1219 | "version": "1.1.3", 1220 | "bundled": true, 1221 | "dev": true, 1222 | "requires": { 1223 | "ansi-styles": "2.2.1", 1224 | "escape-string-regexp": "1.0.5", 1225 | "has-ansi": "2.0.0", 1226 | "strip-ansi": "3.0.1", 1227 | "supports-color": "2.0.0" 1228 | } 1229 | }, 1230 | "cliui": { 1231 | "version": "2.1.0", 1232 | "bundled": true, 1233 | "dev": true, 1234 | "optional": true, 1235 | "requires": { 1236 | "center-align": "0.1.3", 1237 | "right-align": "0.1.3", 1238 | "wordwrap": "0.0.2" 1239 | }, 1240 | "dependencies": { 1241 | "wordwrap": { 1242 | "version": "0.0.2", 1243 | "bundled": true, 1244 | "dev": true, 1245 | "optional": true 1246 | } 1247 | } 1248 | }, 1249 | "code-point-at": { 1250 | "version": "1.1.0", 1251 | "bundled": true, 1252 | "dev": true 1253 | }, 1254 | "commondir": { 1255 | "version": "1.0.1", 1256 | "bundled": true, 1257 | "dev": true 1258 | }, 1259 | "concat-map": { 1260 | "version": "0.0.1", 1261 | "bundled": true, 1262 | "dev": true 1263 | }, 1264 | "convert-source-map": { 1265 | "version": "1.5.0", 1266 | "bundled": true, 1267 | "dev": true 1268 | }, 1269 | "core-js": { 1270 | "version": "2.4.1", 1271 | "bundled": true, 1272 | "dev": true 1273 | }, 1274 | "cross-spawn": { 1275 | "version": "4.0.2", 1276 | "bundled": true, 1277 | "dev": true, 1278 | "requires": { 1279 | "lru-cache": "4.1.1", 1280 | "which": "1.2.14" 1281 | } 1282 | }, 1283 | "debug": { 1284 | "version": "2.6.8", 1285 | "bundled": true, 1286 | "dev": true, 1287 | "requires": { 1288 | "ms": "2.0.0" 1289 | } 1290 | }, 1291 | "debug-log": { 1292 | "version": "1.0.1", 1293 | "bundled": true, 1294 | "dev": true 1295 | }, 1296 | "decamelize": { 1297 | "version": "1.2.0", 1298 | "bundled": true, 1299 | "dev": true 1300 | }, 1301 | "default-require-extensions": { 1302 | "version": "1.0.0", 1303 | "bundled": true, 1304 | "dev": true, 1305 | "requires": { 1306 | "strip-bom": "2.0.0" 1307 | } 1308 | }, 1309 | "detect-indent": { 1310 | "version": "4.0.0", 1311 | "bundled": true, 1312 | "dev": true, 1313 | "requires": { 1314 | "repeating": "2.0.1" 1315 | } 1316 | }, 1317 | "error-ex": { 1318 | "version": "1.3.1", 1319 | "bundled": true, 1320 | "dev": true, 1321 | "requires": { 1322 | "is-arrayish": "0.2.1" 1323 | } 1324 | }, 1325 | "escape-string-regexp": { 1326 | "version": "1.0.5", 1327 | "bundled": true, 1328 | "dev": true 1329 | }, 1330 | "esutils": { 1331 | "version": "2.0.2", 1332 | "bundled": true, 1333 | "dev": true 1334 | }, 1335 | "execa": { 1336 | "version": "0.5.1", 1337 | "bundled": true, 1338 | "dev": true, 1339 | "requires": { 1340 | "cross-spawn": "4.0.2", 1341 | "get-stream": "2.3.1", 1342 | "is-stream": "1.1.0", 1343 | "npm-run-path": "2.0.2", 1344 | "p-finally": "1.0.0", 1345 | "signal-exit": "3.0.2", 1346 | "strip-eof": "1.0.0" 1347 | } 1348 | }, 1349 | "expand-brackets": { 1350 | "version": "0.1.5", 1351 | "bundled": true, 1352 | "dev": true, 1353 | "requires": { 1354 | "is-posix-bracket": "0.1.1" 1355 | } 1356 | }, 1357 | "expand-range": { 1358 | "version": "1.8.2", 1359 | "bundled": true, 1360 | "dev": true, 1361 | "requires": { 1362 | "fill-range": "2.2.3" 1363 | } 1364 | }, 1365 | "extglob": { 1366 | "version": "0.3.2", 1367 | "bundled": true, 1368 | "dev": true, 1369 | "requires": { 1370 | "is-extglob": "1.0.0" 1371 | } 1372 | }, 1373 | "filename-regex": { 1374 | "version": "2.0.1", 1375 | "bundled": true, 1376 | "dev": true 1377 | }, 1378 | "fill-range": { 1379 | "version": "2.2.3", 1380 | "bundled": true, 1381 | "dev": true, 1382 | "requires": { 1383 | "is-number": "2.1.0", 1384 | "isobject": "2.1.0", 1385 | "randomatic": "1.1.7", 1386 | "repeat-element": "1.1.2", 1387 | "repeat-string": "1.6.1" 1388 | } 1389 | }, 1390 | "find-cache-dir": { 1391 | "version": "0.1.1", 1392 | "bundled": true, 1393 | "dev": true, 1394 | "requires": { 1395 | "commondir": "1.0.1", 1396 | "mkdirp": "0.5.1", 1397 | "pkg-dir": "1.0.0" 1398 | } 1399 | }, 1400 | "find-up": { 1401 | "version": "2.1.0", 1402 | "bundled": true, 1403 | "dev": true, 1404 | "requires": { 1405 | "locate-path": "2.0.0" 1406 | } 1407 | }, 1408 | "for-in": { 1409 | "version": "1.0.2", 1410 | "bundled": true, 1411 | "dev": true 1412 | }, 1413 | "for-own": { 1414 | "version": "0.1.5", 1415 | "bundled": true, 1416 | "dev": true, 1417 | "requires": { 1418 | "for-in": "1.0.2" 1419 | } 1420 | }, 1421 | "foreground-child": { 1422 | "version": "1.5.6", 1423 | "bundled": true, 1424 | "dev": true, 1425 | "requires": { 1426 | "cross-spawn": "4.0.2", 1427 | "signal-exit": "3.0.2" 1428 | } 1429 | }, 1430 | "fs.realpath": { 1431 | "version": "1.0.0", 1432 | "bundled": true, 1433 | "dev": true 1434 | }, 1435 | "get-caller-file": { 1436 | "version": "1.0.2", 1437 | "bundled": true, 1438 | "dev": true 1439 | }, 1440 | "get-stream": { 1441 | "version": "2.3.1", 1442 | "bundled": true, 1443 | "dev": true, 1444 | "requires": { 1445 | "object-assign": "4.1.1", 1446 | "pinkie-promise": "2.0.1" 1447 | } 1448 | }, 1449 | "glob": { 1450 | "version": "7.1.2", 1451 | "bundled": true, 1452 | "dev": true, 1453 | "requires": { 1454 | "fs.realpath": "1.0.0", 1455 | "inflight": "1.0.6", 1456 | "inherits": "2.0.3", 1457 | "minimatch": "3.0.4", 1458 | "once": "1.4.0", 1459 | "path-is-absolute": "1.0.1" 1460 | } 1461 | }, 1462 | "glob-base": { 1463 | "version": "0.3.0", 1464 | "bundled": true, 1465 | "dev": true, 1466 | "requires": { 1467 | "glob-parent": "2.0.0", 1468 | "is-glob": "2.0.1" 1469 | } 1470 | }, 1471 | "glob-parent": { 1472 | "version": "2.0.0", 1473 | "bundled": true, 1474 | "dev": true, 1475 | "requires": { 1476 | "is-glob": "2.0.1" 1477 | } 1478 | }, 1479 | "globals": { 1480 | "version": "9.18.0", 1481 | "bundled": true, 1482 | "dev": true 1483 | }, 1484 | "graceful-fs": { 1485 | "version": "4.1.11", 1486 | "bundled": true, 1487 | "dev": true 1488 | }, 1489 | "handlebars": { 1490 | "version": "4.0.10", 1491 | "bundled": true, 1492 | "dev": true, 1493 | "requires": { 1494 | "async": "1.5.2", 1495 | "optimist": "0.6.1", 1496 | "source-map": "0.4.4", 1497 | "uglify-js": "2.8.29" 1498 | }, 1499 | "dependencies": { 1500 | "source-map": { 1501 | "version": "0.4.4", 1502 | "bundled": true, 1503 | "dev": true, 1504 | "requires": { 1505 | "amdefine": "1.0.1" 1506 | } 1507 | } 1508 | } 1509 | }, 1510 | "has-ansi": { 1511 | "version": "2.0.0", 1512 | "bundled": true, 1513 | "dev": true, 1514 | "requires": { 1515 | "ansi-regex": "2.1.1" 1516 | } 1517 | }, 1518 | "has-flag": { 1519 | "version": "1.0.0", 1520 | "bundled": true, 1521 | "dev": true 1522 | }, 1523 | "hosted-git-info": { 1524 | "version": "2.4.2", 1525 | "bundled": true, 1526 | "dev": true 1527 | }, 1528 | "imurmurhash": { 1529 | "version": "0.1.4", 1530 | "bundled": true, 1531 | "dev": true 1532 | }, 1533 | "inflight": { 1534 | "version": "1.0.6", 1535 | "bundled": true, 1536 | "dev": true, 1537 | "requires": { 1538 | "once": "1.4.0", 1539 | "wrappy": "1.0.2" 1540 | } 1541 | }, 1542 | "inherits": { 1543 | "version": "2.0.3", 1544 | "bundled": true, 1545 | "dev": true 1546 | }, 1547 | "invariant": { 1548 | "version": "2.2.2", 1549 | "bundled": true, 1550 | "dev": true, 1551 | "requires": { 1552 | "loose-envify": "1.3.1" 1553 | } 1554 | }, 1555 | "invert-kv": { 1556 | "version": "1.0.0", 1557 | "bundled": true, 1558 | "dev": true 1559 | }, 1560 | "is-arrayish": { 1561 | "version": "0.2.1", 1562 | "bundled": true, 1563 | "dev": true 1564 | }, 1565 | "is-buffer": { 1566 | "version": "1.1.5", 1567 | "bundled": true, 1568 | "dev": true 1569 | }, 1570 | "is-builtin-module": { 1571 | "version": "1.0.0", 1572 | "bundled": true, 1573 | "dev": true, 1574 | "requires": { 1575 | "builtin-modules": "1.1.1" 1576 | } 1577 | }, 1578 | "is-dotfile": { 1579 | "version": "1.0.3", 1580 | "bundled": true, 1581 | "dev": true 1582 | }, 1583 | "is-equal-shallow": { 1584 | "version": "0.1.3", 1585 | "bundled": true, 1586 | "dev": true, 1587 | "requires": { 1588 | "is-primitive": "2.0.0" 1589 | } 1590 | }, 1591 | "is-extendable": { 1592 | "version": "0.1.1", 1593 | "bundled": true, 1594 | "dev": true 1595 | }, 1596 | "is-extglob": { 1597 | "version": "1.0.0", 1598 | "bundled": true, 1599 | "dev": true 1600 | }, 1601 | "is-finite": { 1602 | "version": "1.0.2", 1603 | "bundled": true, 1604 | "dev": true, 1605 | "requires": { 1606 | "number-is-nan": "1.0.1" 1607 | } 1608 | }, 1609 | "is-fullwidth-code-point": { 1610 | "version": "1.0.0", 1611 | "bundled": true, 1612 | "dev": true, 1613 | "requires": { 1614 | "number-is-nan": "1.0.1" 1615 | } 1616 | }, 1617 | "is-glob": { 1618 | "version": "2.0.1", 1619 | "bundled": true, 1620 | "dev": true, 1621 | "requires": { 1622 | "is-extglob": "1.0.0" 1623 | } 1624 | }, 1625 | "is-number": { 1626 | "version": "2.1.0", 1627 | "bundled": true, 1628 | "dev": true, 1629 | "requires": { 1630 | "kind-of": "3.2.2" 1631 | } 1632 | }, 1633 | "is-posix-bracket": { 1634 | "version": "0.1.1", 1635 | "bundled": true, 1636 | "dev": true 1637 | }, 1638 | "is-primitive": { 1639 | "version": "2.0.0", 1640 | "bundled": true, 1641 | "dev": true 1642 | }, 1643 | "is-stream": { 1644 | "version": "1.1.0", 1645 | "bundled": true, 1646 | "dev": true 1647 | }, 1648 | "is-utf8": { 1649 | "version": "0.2.1", 1650 | "bundled": true, 1651 | "dev": true 1652 | }, 1653 | "isarray": { 1654 | "version": "1.0.0", 1655 | "bundled": true, 1656 | "dev": true 1657 | }, 1658 | "isexe": { 1659 | "version": "2.0.0", 1660 | "bundled": true, 1661 | "dev": true 1662 | }, 1663 | "isobject": { 1664 | "version": "2.1.0", 1665 | "bundled": true, 1666 | "dev": true, 1667 | "requires": { 1668 | "isarray": "1.0.0" 1669 | } 1670 | }, 1671 | "istanbul-lib-coverage": { 1672 | "version": "1.1.1", 1673 | "bundled": true, 1674 | "dev": true 1675 | }, 1676 | "istanbul-lib-hook": { 1677 | "version": "1.0.7", 1678 | "bundled": true, 1679 | "dev": true, 1680 | "requires": { 1681 | "append-transform": "0.4.0" 1682 | } 1683 | }, 1684 | "istanbul-lib-instrument": { 1685 | "version": "1.7.3", 1686 | "bundled": true, 1687 | "dev": true, 1688 | "requires": { 1689 | "babel-generator": "6.25.0", 1690 | "babel-template": "6.25.0", 1691 | "babel-traverse": "6.25.0", 1692 | "babel-types": "6.25.0", 1693 | "babylon": "6.17.4", 1694 | "istanbul-lib-coverage": "1.1.1", 1695 | "semver": "5.3.0" 1696 | } 1697 | }, 1698 | "istanbul-lib-report": { 1699 | "version": "1.1.1", 1700 | "bundled": true, 1701 | "dev": true, 1702 | "requires": { 1703 | "istanbul-lib-coverage": "1.1.1", 1704 | "mkdirp": "0.5.1", 1705 | "path-parse": "1.0.5", 1706 | "supports-color": "3.2.3" 1707 | }, 1708 | "dependencies": { 1709 | "supports-color": { 1710 | "version": "3.2.3", 1711 | "bundled": true, 1712 | "dev": true, 1713 | "requires": { 1714 | "has-flag": "1.0.0" 1715 | } 1716 | } 1717 | } 1718 | }, 1719 | "istanbul-lib-source-maps": { 1720 | "version": "1.2.1", 1721 | "bundled": true, 1722 | "dev": true, 1723 | "requires": { 1724 | "debug": "2.6.8", 1725 | "istanbul-lib-coverage": "1.1.1", 1726 | "mkdirp": "0.5.1", 1727 | "rimraf": "2.6.1", 1728 | "source-map": "0.5.6" 1729 | } 1730 | }, 1731 | "istanbul-reports": { 1732 | "version": "1.1.1", 1733 | "bundled": true, 1734 | "dev": true, 1735 | "requires": { 1736 | "handlebars": "4.0.10" 1737 | } 1738 | }, 1739 | "js-tokens": { 1740 | "version": "3.0.1", 1741 | "bundled": true, 1742 | "dev": true 1743 | }, 1744 | "jsesc": { 1745 | "version": "1.3.0", 1746 | "bundled": true, 1747 | "dev": true 1748 | }, 1749 | "kind-of": { 1750 | "version": "3.2.2", 1751 | "bundled": true, 1752 | "dev": true, 1753 | "requires": { 1754 | "is-buffer": "1.1.5" 1755 | } 1756 | }, 1757 | "lazy-cache": { 1758 | "version": "1.0.4", 1759 | "bundled": true, 1760 | "dev": true, 1761 | "optional": true 1762 | }, 1763 | "lcid": { 1764 | "version": "1.0.0", 1765 | "bundled": true, 1766 | "dev": true, 1767 | "requires": { 1768 | "invert-kv": "1.0.0" 1769 | } 1770 | }, 1771 | "load-json-file": { 1772 | "version": "1.1.0", 1773 | "bundled": true, 1774 | "dev": true, 1775 | "requires": { 1776 | "graceful-fs": "4.1.11", 1777 | "parse-json": "2.2.0", 1778 | "pify": "2.3.0", 1779 | "pinkie-promise": "2.0.1", 1780 | "strip-bom": "2.0.0" 1781 | } 1782 | }, 1783 | "locate-path": { 1784 | "version": "2.0.0", 1785 | "bundled": true, 1786 | "dev": true, 1787 | "requires": { 1788 | "p-locate": "2.0.0", 1789 | "path-exists": "3.0.0" 1790 | }, 1791 | "dependencies": { 1792 | "path-exists": { 1793 | "version": "3.0.0", 1794 | "bundled": true, 1795 | "dev": true 1796 | } 1797 | } 1798 | }, 1799 | "lodash": { 1800 | "version": "4.17.4", 1801 | "bundled": true, 1802 | "dev": true 1803 | }, 1804 | "longest": { 1805 | "version": "1.0.1", 1806 | "bundled": true, 1807 | "dev": true 1808 | }, 1809 | "loose-envify": { 1810 | "version": "1.3.1", 1811 | "bundled": true, 1812 | "dev": true, 1813 | "requires": { 1814 | "js-tokens": "3.0.1" 1815 | } 1816 | }, 1817 | "lru-cache": { 1818 | "version": "4.1.1", 1819 | "bundled": true, 1820 | "dev": true, 1821 | "requires": { 1822 | "pseudomap": "1.0.2", 1823 | "yallist": "2.1.2" 1824 | } 1825 | }, 1826 | "md5-hex": { 1827 | "version": "1.3.0", 1828 | "bundled": true, 1829 | "dev": true, 1830 | "requires": { 1831 | "md5-o-matic": "0.1.1" 1832 | } 1833 | }, 1834 | "md5-o-matic": { 1835 | "version": "0.1.1", 1836 | "bundled": true, 1837 | "dev": true 1838 | }, 1839 | "mem": { 1840 | "version": "1.1.0", 1841 | "bundled": true, 1842 | "dev": true, 1843 | "requires": { 1844 | "mimic-fn": "1.1.0" 1845 | } 1846 | }, 1847 | "merge-source-map": { 1848 | "version": "1.0.4", 1849 | "bundled": true, 1850 | "dev": true, 1851 | "requires": { 1852 | "source-map": "0.5.6" 1853 | } 1854 | }, 1855 | "micromatch": { 1856 | "version": "2.3.11", 1857 | "bundled": true, 1858 | "dev": true, 1859 | "requires": { 1860 | "arr-diff": "2.0.0", 1861 | "array-unique": "0.2.1", 1862 | "braces": "1.8.5", 1863 | "expand-brackets": "0.1.5", 1864 | "extglob": "0.3.2", 1865 | "filename-regex": "2.0.1", 1866 | "is-extglob": "1.0.0", 1867 | "is-glob": "2.0.1", 1868 | "kind-of": "3.2.2", 1869 | "normalize-path": "2.1.1", 1870 | "object.omit": "2.0.1", 1871 | "parse-glob": "3.0.4", 1872 | "regex-cache": "0.4.3" 1873 | } 1874 | }, 1875 | "mimic-fn": { 1876 | "version": "1.1.0", 1877 | "bundled": true, 1878 | "dev": true 1879 | }, 1880 | "minimatch": { 1881 | "version": "3.0.4", 1882 | "bundled": true, 1883 | "dev": true, 1884 | "requires": { 1885 | "brace-expansion": "1.1.8" 1886 | } 1887 | }, 1888 | "minimist": { 1889 | "version": "0.0.8", 1890 | "bundled": true, 1891 | "dev": true 1892 | }, 1893 | "mkdirp": { 1894 | "version": "0.5.1", 1895 | "bundled": true, 1896 | "dev": true, 1897 | "requires": { 1898 | "minimist": "0.0.8" 1899 | } 1900 | }, 1901 | "ms": { 1902 | "version": "2.0.0", 1903 | "bundled": true, 1904 | "dev": true 1905 | }, 1906 | "normalize-package-data": { 1907 | "version": "2.3.8", 1908 | "bundled": true, 1909 | "dev": true, 1910 | "requires": { 1911 | "hosted-git-info": "2.4.2", 1912 | "is-builtin-module": "1.0.0", 1913 | "semver": "5.3.0", 1914 | "validate-npm-package-license": "3.0.1" 1915 | } 1916 | }, 1917 | "normalize-path": { 1918 | "version": "2.1.1", 1919 | "bundled": true, 1920 | "dev": true, 1921 | "requires": { 1922 | "remove-trailing-separator": "1.0.2" 1923 | } 1924 | }, 1925 | "npm-run-path": { 1926 | "version": "2.0.2", 1927 | "bundled": true, 1928 | "dev": true, 1929 | "requires": { 1930 | "path-key": "2.0.1" 1931 | } 1932 | }, 1933 | "number-is-nan": { 1934 | "version": "1.0.1", 1935 | "bundled": true, 1936 | "dev": true 1937 | }, 1938 | "object-assign": { 1939 | "version": "4.1.1", 1940 | "bundled": true, 1941 | "dev": true 1942 | }, 1943 | "object.omit": { 1944 | "version": "2.0.1", 1945 | "bundled": true, 1946 | "dev": true, 1947 | "requires": { 1948 | "for-own": "0.1.5", 1949 | "is-extendable": "0.1.1" 1950 | } 1951 | }, 1952 | "once": { 1953 | "version": "1.4.0", 1954 | "bundled": true, 1955 | "dev": true, 1956 | "requires": { 1957 | "wrappy": "1.0.2" 1958 | } 1959 | }, 1960 | "optimist": { 1961 | "version": "0.6.1", 1962 | "bundled": true, 1963 | "dev": true, 1964 | "requires": { 1965 | "minimist": "0.0.8", 1966 | "wordwrap": "0.0.3" 1967 | } 1968 | }, 1969 | "os-homedir": { 1970 | "version": "1.0.2", 1971 | "bundled": true, 1972 | "dev": true 1973 | }, 1974 | "os-locale": { 1975 | "version": "2.0.0", 1976 | "bundled": true, 1977 | "dev": true, 1978 | "requires": { 1979 | "execa": "0.5.1", 1980 | "lcid": "1.0.0", 1981 | "mem": "1.1.0" 1982 | } 1983 | }, 1984 | "p-finally": { 1985 | "version": "1.0.0", 1986 | "bundled": true, 1987 | "dev": true 1988 | }, 1989 | "p-limit": { 1990 | "version": "1.1.0", 1991 | "bundled": true, 1992 | "dev": true 1993 | }, 1994 | "p-locate": { 1995 | "version": "2.0.0", 1996 | "bundled": true, 1997 | "dev": true, 1998 | "requires": { 1999 | "p-limit": "1.1.0" 2000 | } 2001 | }, 2002 | "parse-glob": { 2003 | "version": "3.0.4", 2004 | "bundled": true, 2005 | "dev": true, 2006 | "requires": { 2007 | "glob-base": "0.3.0", 2008 | "is-dotfile": "1.0.3", 2009 | "is-extglob": "1.0.0", 2010 | "is-glob": "2.0.1" 2011 | } 2012 | }, 2013 | "parse-json": { 2014 | "version": "2.2.0", 2015 | "bundled": true, 2016 | "dev": true, 2017 | "requires": { 2018 | "error-ex": "1.3.1" 2019 | } 2020 | }, 2021 | "path-exists": { 2022 | "version": "2.1.0", 2023 | "bundled": true, 2024 | "dev": true, 2025 | "requires": { 2026 | "pinkie-promise": "2.0.1" 2027 | } 2028 | }, 2029 | "path-is-absolute": { 2030 | "version": "1.0.1", 2031 | "bundled": true, 2032 | "dev": true 2033 | }, 2034 | "path-key": { 2035 | "version": "2.0.1", 2036 | "bundled": true, 2037 | "dev": true 2038 | }, 2039 | "path-parse": { 2040 | "version": "1.0.5", 2041 | "bundled": true, 2042 | "dev": true 2043 | }, 2044 | "path-type": { 2045 | "version": "1.1.0", 2046 | "bundled": true, 2047 | "dev": true, 2048 | "requires": { 2049 | "graceful-fs": "4.1.11", 2050 | "pify": "2.3.0", 2051 | "pinkie-promise": "2.0.1" 2052 | } 2053 | }, 2054 | "pify": { 2055 | "version": "2.3.0", 2056 | "bundled": true, 2057 | "dev": true 2058 | }, 2059 | "pinkie": { 2060 | "version": "2.0.4", 2061 | "bundled": true, 2062 | "dev": true 2063 | }, 2064 | "pinkie-promise": { 2065 | "version": "2.0.1", 2066 | "bundled": true, 2067 | "dev": true, 2068 | "requires": { 2069 | "pinkie": "2.0.4" 2070 | } 2071 | }, 2072 | "pkg-dir": { 2073 | "version": "1.0.0", 2074 | "bundled": true, 2075 | "dev": true, 2076 | "requires": { 2077 | "find-up": "1.1.2" 2078 | }, 2079 | "dependencies": { 2080 | "find-up": { 2081 | "version": "1.1.2", 2082 | "bundled": true, 2083 | "dev": true, 2084 | "requires": { 2085 | "path-exists": "2.1.0", 2086 | "pinkie-promise": "2.0.1" 2087 | } 2088 | } 2089 | } 2090 | }, 2091 | "preserve": { 2092 | "version": "0.2.0", 2093 | "bundled": true, 2094 | "dev": true 2095 | }, 2096 | "pseudomap": { 2097 | "version": "1.0.2", 2098 | "bundled": true, 2099 | "dev": true 2100 | }, 2101 | "randomatic": { 2102 | "version": "1.1.7", 2103 | "bundled": true, 2104 | "dev": true, 2105 | "requires": { 2106 | "is-number": "3.0.0", 2107 | "kind-of": "4.0.0" 2108 | }, 2109 | "dependencies": { 2110 | "is-number": { 2111 | "version": "3.0.0", 2112 | "bundled": true, 2113 | "dev": true, 2114 | "requires": { 2115 | "kind-of": "3.2.2" 2116 | }, 2117 | "dependencies": { 2118 | "kind-of": { 2119 | "version": "3.2.2", 2120 | "bundled": true, 2121 | "dev": true, 2122 | "requires": { 2123 | "is-buffer": "1.1.5" 2124 | } 2125 | } 2126 | } 2127 | }, 2128 | "kind-of": { 2129 | "version": "4.0.0", 2130 | "bundled": true, 2131 | "dev": true, 2132 | "requires": { 2133 | "is-buffer": "1.1.5" 2134 | } 2135 | } 2136 | } 2137 | }, 2138 | "read-pkg": { 2139 | "version": "1.1.0", 2140 | "bundled": true, 2141 | "dev": true, 2142 | "requires": { 2143 | "load-json-file": "1.1.0", 2144 | "normalize-package-data": "2.3.8", 2145 | "path-type": "1.1.0" 2146 | } 2147 | }, 2148 | "read-pkg-up": { 2149 | "version": "1.0.1", 2150 | "bundled": true, 2151 | "dev": true, 2152 | "requires": { 2153 | "find-up": "1.1.2", 2154 | "read-pkg": "1.1.0" 2155 | }, 2156 | "dependencies": { 2157 | "find-up": { 2158 | "version": "1.1.2", 2159 | "bundled": true, 2160 | "dev": true, 2161 | "requires": { 2162 | "path-exists": "2.1.0", 2163 | "pinkie-promise": "2.0.1" 2164 | } 2165 | } 2166 | } 2167 | }, 2168 | "regenerator-runtime": { 2169 | "version": "0.10.5", 2170 | "bundled": true, 2171 | "dev": true 2172 | }, 2173 | "regex-cache": { 2174 | "version": "0.4.3", 2175 | "bundled": true, 2176 | "dev": true, 2177 | "requires": { 2178 | "is-equal-shallow": "0.1.3", 2179 | "is-primitive": "2.0.0" 2180 | } 2181 | }, 2182 | "remove-trailing-separator": { 2183 | "version": "1.0.2", 2184 | "bundled": true, 2185 | "dev": true 2186 | }, 2187 | "repeat-element": { 2188 | "version": "1.1.2", 2189 | "bundled": true, 2190 | "dev": true 2191 | }, 2192 | "repeat-string": { 2193 | "version": "1.6.1", 2194 | "bundled": true, 2195 | "dev": true 2196 | }, 2197 | "repeating": { 2198 | "version": "2.0.1", 2199 | "bundled": true, 2200 | "dev": true, 2201 | "requires": { 2202 | "is-finite": "1.0.2" 2203 | } 2204 | }, 2205 | "require-directory": { 2206 | "version": "2.1.1", 2207 | "bundled": true, 2208 | "dev": true 2209 | }, 2210 | "require-main-filename": { 2211 | "version": "1.0.1", 2212 | "bundled": true, 2213 | "dev": true 2214 | }, 2215 | "resolve-from": { 2216 | "version": "2.0.0", 2217 | "bundled": true, 2218 | "dev": true 2219 | }, 2220 | "right-align": { 2221 | "version": "0.1.3", 2222 | "bundled": true, 2223 | "dev": true, 2224 | "optional": true, 2225 | "requires": { 2226 | "align-text": "0.1.4" 2227 | } 2228 | }, 2229 | "rimraf": { 2230 | "version": "2.6.1", 2231 | "bundled": true, 2232 | "dev": true, 2233 | "requires": { 2234 | "glob": "7.1.2" 2235 | } 2236 | }, 2237 | "semver": { 2238 | "version": "5.3.0", 2239 | "bundled": true, 2240 | "dev": true 2241 | }, 2242 | "set-blocking": { 2243 | "version": "2.0.0", 2244 | "bundled": true, 2245 | "dev": true 2246 | }, 2247 | "signal-exit": { 2248 | "version": "3.0.2", 2249 | "bundled": true, 2250 | "dev": true 2251 | }, 2252 | "slide": { 2253 | "version": "1.1.6", 2254 | "bundled": true, 2255 | "dev": true 2256 | }, 2257 | "source-map": { 2258 | "version": "0.5.6", 2259 | "bundled": true, 2260 | "dev": true 2261 | }, 2262 | "spawn-wrap": { 2263 | "version": "1.3.7", 2264 | "bundled": true, 2265 | "dev": true, 2266 | "requires": { 2267 | "foreground-child": "1.5.6", 2268 | "mkdirp": "0.5.1", 2269 | "os-homedir": "1.0.2", 2270 | "rimraf": "2.6.1", 2271 | "signal-exit": "3.0.2", 2272 | "which": "1.2.14" 2273 | } 2274 | }, 2275 | "spdx-correct": { 2276 | "version": "1.0.2", 2277 | "bundled": true, 2278 | "dev": true, 2279 | "requires": { 2280 | "spdx-license-ids": "1.2.2" 2281 | } 2282 | }, 2283 | "spdx-expression-parse": { 2284 | "version": "1.0.4", 2285 | "bundled": true, 2286 | "dev": true 2287 | }, 2288 | "spdx-license-ids": { 2289 | "version": "1.2.2", 2290 | "bundled": true, 2291 | "dev": true 2292 | }, 2293 | "string-width": { 2294 | "version": "2.0.0", 2295 | "bundled": true, 2296 | "dev": true, 2297 | "requires": { 2298 | "is-fullwidth-code-point": "2.0.0", 2299 | "strip-ansi": "3.0.1" 2300 | }, 2301 | "dependencies": { 2302 | "is-fullwidth-code-point": { 2303 | "version": "2.0.0", 2304 | "bundled": true, 2305 | "dev": true 2306 | } 2307 | } 2308 | }, 2309 | "strip-ansi": { 2310 | "version": "3.0.1", 2311 | "bundled": true, 2312 | "dev": true, 2313 | "requires": { 2314 | "ansi-regex": "2.1.1" 2315 | } 2316 | }, 2317 | "strip-bom": { 2318 | "version": "2.0.0", 2319 | "bundled": true, 2320 | "dev": true, 2321 | "requires": { 2322 | "is-utf8": "0.2.1" 2323 | } 2324 | }, 2325 | "strip-eof": { 2326 | "version": "1.0.0", 2327 | "bundled": true, 2328 | "dev": true 2329 | }, 2330 | "supports-color": { 2331 | "version": "2.0.0", 2332 | "bundled": true, 2333 | "dev": true 2334 | }, 2335 | "test-exclude": { 2336 | "version": "4.1.1", 2337 | "bundled": true, 2338 | "dev": true, 2339 | "requires": { 2340 | "arrify": "1.0.1", 2341 | "micromatch": "2.3.11", 2342 | "object-assign": "4.1.1", 2343 | "read-pkg-up": "1.0.1", 2344 | "require-main-filename": "1.0.1" 2345 | } 2346 | }, 2347 | "to-fast-properties": { 2348 | "version": "1.0.3", 2349 | "bundled": true, 2350 | "dev": true 2351 | }, 2352 | "trim-right": { 2353 | "version": "1.0.1", 2354 | "bundled": true, 2355 | "dev": true 2356 | }, 2357 | "uglify-js": { 2358 | "version": "2.8.29", 2359 | "bundled": true, 2360 | "dev": true, 2361 | "optional": true, 2362 | "requires": { 2363 | "source-map": "0.5.6", 2364 | "uglify-to-browserify": "1.0.2", 2365 | "yargs": "3.10.0" 2366 | }, 2367 | "dependencies": { 2368 | "yargs": { 2369 | "version": "3.10.0", 2370 | "bundled": true, 2371 | "dev": true, 2372 | "optional": true, 2373 | "requires": { 2374 | "camelcase": "1.2.1", 2375 | "cliui": "2.1.0", 2376 | "decamelize": "1.2.0", 2377 | "window-size": "0.1.0" 2378 | } 2379 | } 2380 | } 2381 | }, 2382 | "uglify-to-browserify": { 2383 | "version": "1.0.2", 2384 | "bundled": true, 2385 | "dev": true, 2386 | "optional": true 2387 | }, 2388 | "validate-npm-package-license": { 2389 | "version": "3.0.1", 2390 | "bundled": true, 2391 | "dev": true, 2392 | "requires": { 2393 | "spdx-correct": "1.0.2", 2394 | "spdx-expression-parse": "1.0.4" 2395 | } 2396 | }, 2397 | "which": { 2398 | "version": "1.2.14", 2399 | "bundled": true, 2400 | "dev": true, 2401 | "requires": { 2402 | "isexe": "2.0.0" 2403 | } 2404 | }, 2405 | "which-module": { 2406 | "version": "2.0.0", 2407 | "bundled": true, 2408 | "dev": true 2409 | }, 2410 | "window-size": { 2411 | "version": "0.1.0", 2412 | "bundled": true, 2413 | "dev": true, 2414 | "optional": true 2415 | }, 2416 | "wordwrap": { 2417 | "version": "0.0.3", 2418 | "bundled": true, 2419 | "dev": true 2420 | }, 2421 | "wrap-ansi": { 2422 | "version": "2.1.0", 2423 | "bundled": true, 2424 | "dev": true, 2425 | "requires": { 2426 | "string-width": "1.0.2", 2427 | "strip-ansi": "3.0.1" 2428 | }, 2429 | "dependencies": { 2430 | "string-width": { 2431 | "version": "1.0.2", 2432 | "bundled": true, 2433 | "dev": true, 2434 | "requires": { 2435 | "code-point-at": "1.1.0", 2436 | "is-fullwidth-code-point": "1.0.0", 2437 | "strip-ansi": "3.0.1" 2438 | } 2439 | } 2440 | } 2441 | }, 2442 | "wrappy": { 2443 | "version": "1.0.2", 2444 | "bundled": true, 2445 | "dev": true 2446 | }, 2447 | "write-file-atomic": { 2448 | "version": "1.3.4", 2449 | "bundled": true, 2450 | "dev": true, 2451 | "requires": { 2452 | "graceful-fs": "4.1.11", 2453 | "imurmurhash": "0.1.4", 2454 | "slide": "1.1.6" 2455 | } 2456 | }, 2457 | "y18n": { 2458 | "version": "3.2.1", 2459 | "bundled": true, 2460 | "dev": true 2461 | }, 2462 | "yallist": { 2463 | "version": "2.1.2", 2464 | "bundled": true, 2465 | "dev": true 2466 | }, 2467 | "yargs": { 2468 | "version": "8.0.2", 2469 | "bundled": true, 2470 | "dev": true, 2471 | "requires": { 2472 | "camelcase": "4.1.0", 2473 | "cliui": "3.2.0", 2474 | "decamelize": "1.2.0", 2475 | "get-caller-file": "1.0.2", 2476 | "os-locale": "2.0.0", 2477 | "read-pkg-up": "2.0.0", 2478 | "require-directory": "2.1.1", 2479 | "require-main-filename": "1.0.1", 2480 | "set-blocking": "2.0.0", 2481 | "string-width": "2.0.0", 2482 | "which-module": "2.0.0", 2483 | "y18n": "3.2.1", 2484 | "yargs-parser": "7.0.0" 2485 | }, 2486 | "dependencies": { 2487 | "camelcase": { 2488 | "version": "4.1.0", 2489 | "bundled": true, 2490 | "dev": true 2491 | }, 2492 | "cliui": { 2493 | "version": "3.2.0", 2494 | "bundled": true, 2495 | "dev": true, 2496 | "requires": { 2497 | "string-width": "1.0.2", 2498 | "strip-ansi": "3.0.1", 2499 | "wrap-ansi": "2.1.0" 2500 | }, 2501 | "dependencies": { 2502 | "string-width": { 2503 | "version": "1.0.2", 2504 | "bundled": true, 2505 | "dev": true, 2506 | "requires": { 2507 | "code-point-at": "1.1.0", 2508 | "is-fullwidth-code-point": "1.0.0", 2509 | "strip-ansi": "3.0.1" 2510 | } 2511 | } 2512 | } 2513 | }, 2514 | "load-json-file": { 2515 | "version": "2.0.0", 2516 | "bundled": true, 2517 | "dev": true, 2518 | "requires": { 2519 | "graceful-fs": "4.1.11", 2520 | "parse-json": "2.2.0", 2521 | "pify": "2.3.0", 2522 | "strip-bom": "3.0.0" 2523 | } 2524 | }, 2525 | "path-type": { 2526 | "version": "2.0.0", 2527 | "bundled": true, 2528 | "dev": true, 2529 | "requires": { 2530 | "pify": "2.3.0" 2531 | } 2532 | }, 2533 | "read-pkg": { 2534 | "version": "2.0.0", 2535 | "bundled": true, 2536 | "dev": true, 2537 | "requires": { 2538 | "load-json-file": "2.0.0", 2539 | "normalize-package-data": "2.3.8", 2540 | "path-type": "2.0.0" 2541 | } 2542 | }, 2543 | "read-pkg-up": { 2544 | "version": "2.0.0", 2545 | "bundled": true, 2546 | "dev": true, 2547 | "requires": { 2548 | "find-up": "2.1.0", 2549 | "read-pkg": "2.0.0" 2550 | } 2551 | }, 2552 | "strip-bom": { 2553 | "version": "3.0.0", 2554 | "bundled": true, 2555 | "dev": true 2556 | }, 2557 | "yargs-parser": { 2558 | "version": "7.0.0", 2559 | "bundled": true, 2560 | "dev": true, 2561 | "requires": { 2562 | "camelcase": "4.1.0" 2563 | } 2564 | } 2565 | } 2566 | }, 2567 | "yargs-parser": { 2568 | "version": "5.0.0", 2569 | "bundled": true, 2570 | "dev": true, 2571 | "requires": { 2572 | "camelcase": "3.0.0" 2573 | }, 2574 | "dependencies": { 2575 | "camelcase": { 2576 | "version": "3.0.0", 2577 | "bundled": true, 2578 | "dev": true 2579 | } 2580 | } 2581 | } 2582 | } 2583 | }, 2584 | "object-assign": { 2585 | "version": "4.1.1", 2586 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 2587 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 2588 | }, 2589 | "once": { 2590 | "version": "1.4.0", 2591 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 2592 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 2593 | "dev": true, 2594 | "requires": { 2595 | "wrappy": "1.0.2" 2596 | } 2597 | }, 2598 | "onetime": { 2599 | "version": "2.0.1", 2600 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", 2601 | "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", 2602 | "dev": true, 2603 | "requires": { 2604 | "mimic-fn": "1.1.0" 2605 | } 2606 | }, 2607 | "optionator": { 2608 | "version": "0.8.2", 2609 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", 2610 | "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", 2611 | "dev": true, 2612 | "requires": { 2613 | "deep-is": "0.1.3", 2614 | "fast-levenshtein": "2.0.6", 2615 | "levn": "0.3.0", 2616 | "prelude-ls": "1.1.2", 2617 | "type-check": "0.3.2", 2618 | "wordwrap": "1.0.0" 2619 | } 2620 | }, 2621 | "os-tmpdir": { 2622 | "version": "1.0.2", 2623 | "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", 2624 | "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", 2625 | "dev": true 2626 | }, 2627 | "path-is-absolute": { 2628 | "version": "1.0.1", 2629 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 2630 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 2631 | "dev": true 2632 | }, 2633 | "path-is-inside": { 2634 | "version": "1.0.2", 2635 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 2636 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 2637 | "dev": true 2638 | }, 2639 | "pify": { 2640 | "version": "2.3.0", 2641 | "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", 2642 | "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", 2643 | "dev": true 2644 | }, 2645 | "pinkie": { 2646 | "version": "2.0.4", 2647 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 2648 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 2649 | "dev": true 2650 | }, 2651 | "pinkie-promise": { 2652 | "version": "2.0.1", 2653 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 2654 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 2655 | "dev": true, 2656 | "requires": { 2657 | "pinkie": "2.0.4" 2658 | } 2659 | }, 2660 | "pluralize": { 2661 | "version": "4.0.0", 2662 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", 2663 | "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", 2664 | "dev": true 2665 | }, 2666 | "prelude-ls": { 2667 | "version": "1.1.2", 2668 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 2669 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 2670 | "dev": true 2671 | }, 2672 | "process-nextick-args": { 2673 | "version": "1.0.7", 2674 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 2675 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", 2676 | "dev": true 2677 | }, 2678 | "progress": { 2679 | "version": "2.0.0", 2680 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", 2681 | "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", 2682 | "dev": true 2683 | }, 2684 | "readable-stream": { 2685 | "version": "2.3.3", 2686 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", 2687 | "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", 2688 | "dev": true, 2689 | "requires": { 2690 | "core-util-is": "1.0.2", 2691 | "inherits": "2.0.3", 2692 | "isarray": "1.0.0", 2693 | "process-nextick-args": "1.0.7", 2694 | "safe-buffer": "5.1.1", 2695 | "string_decoder": "1.0.3", 2696 | "util-deprecate": "1.0.2" 2697 | } 2698 | }, 2699 | "require-uncached": { 2700 | "version": "1.0.3", 2701 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 2702 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 2703 | "dev": true, 2704 | "requires": { 2705 | "caller-path": "0.1.0", 2706 | "resolve-from": "1.0.1" 2707 | } 2708 | }, 2709 | "resolve-from": { 2710 | "version": "1.0.1", 2711 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 2712 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 2713 | "dev": true 2714 | }, 2715 | "restore-cursor": { 2716 | "version": "2.0.0", 2717 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", 2718 | "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", 2719 | "dev": true, 2720 | "requires": { 2721 | "onetime": "2.0.1", 2722 | "signal-exit": "3.0.2" 2723 | } 2724 | }, 2725 | "rimraf": { 2726 | "version": "2.6.1", 2727 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", 2728 | "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", 2729 | "dev": true, 2730 | "requires": { 2731 | "glob": "7.1.1" 2732 | } 2733 | }, 2734 | "run-async": { 2735 | "version": "2.3.0", 2736 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", 2737 | "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", 2738 | "dev": true, 2739 | "requires": { 2740 | "is-promise": "2.1.0" 2741 | } 2742 | }, 2743 | "rx-lite": { 2744 | "version": "4.0.8", 2745 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", 2746 | "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", 2747 | "dev": true 2748 | }, 2749 | "rx-lite-aggregates": { 2750 | "version": "4.0.8", 2751 | "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", 2752 | "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", 2753 | "dev": true, 2754 | "requires": { 2755 | "rx-lite": "4.0.8" 2756 | } 2757 | }, 2758 | "safe-buffer": { 2759 | "version": "5.1.1", 2760 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", 2761 | "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", 2762 | "dev": true 2763 | }, 2764 | "signal-exit": { 2765 | "version": "3.0.2", 2766 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 2767 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", 2768 | "dev": true 2769 | }, 2770 | "slice-ansi": { 2771 | "version": "0.0.4", 2772 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", 2773 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", 2774 | "dev": true 2775 | }, 2776 | "sprintf-js": { 2777 | "version": "1.0.3", 2778 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2779 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2780 | "dev": true 2781 | }, 2782 | "string_decoder": { 2783 | "version": "1.0.3", 2784 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 2785 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 2786 | "dev": true, 2787 | "requires": { 2788 | "safe-buffer": "5.1.1" 2789 | } 2790 | }, 2791 | "string-width": { 2792 | "version": "2.1.0", 2793 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.0.tgz", 2794 | "integrity": "sha1-AwZkVh/BRslCPsfZeP4kV0N/5tA=", 2795 | "dev": true, 2796 | "requires": { 2797 | "is-fullwidth-code-point": "2.0.0", 2798 | "strip-ansi": "4.0.0" 2799 | }, 2800 | "dependencies": { 2801 | "ansi-regex": { 2802 | "version": "3.0.0", 2803 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 2804 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 2805 | "dev": true 2806 | }, 2807 | "strip-ansi": { 2808 | "version": "4.0.0", 2809 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2810 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2811 | "dev": true, 2812 | "requires": { 2813 | "ansi-regex": "3.0.0" 2814 | } 2815 | } 2816 | } 2817 | }, 2818 | "strip-ansi": { 2819 | "version": "3.0.1", 2820 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 2821 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 2822 | "dev": true, 2823 | "requires": { 2824 | "ansi-regex": "2.1.1" 2825 | } 2826 | }, 2827 | "strip-json-comments": { 2828 | "version": "2.0.1", 2829 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 2830 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 2831 | "dev": true 2832 | }, 2833 | "supports-color": { 2834 | "version": "3.1.2", 2835 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 2836 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", 2837 | "dev": true, 2838 | "requires": { 2839 | "has-flag": "1.0.0" 2840 | } 2841 | }, 2842 | "table": { 2843 | "version": "4.0.1", 2844 | "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", 2845 | "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", 2846 | "dev": true, 2847 | "requires": { 2848 | "ajv": "4.11.8", 2849 | "ajv-keywords": "1.5.1", 2850 | "chalk": "1.1.3", 2851 | "lodash": "4.17.4", 2852 | "slice-ansi": "0.0.4", 2853 | "string-width": "2.1.0" 2854 | } 2855 | }, 2856 | "text-table": { 2857 | "version": "0.2.0", 2858 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2859 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2860 | "dev": true 2861 | }, 2862 | "through": { 2863 | "version": "2.3.8", 2864 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2865 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 2866 | "dev": true 2867 | }, 2868 | "tmp": { 2869 | "version": "0.0.31", 2870 | "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", 2871 | "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", 2872 | "dev": true, 2873 | "requires": { 2874 | "os-tmpdir": "1.0.2" 2875 | } 2876 | }, 2877 | "tryit": { 2878 | "version": "1.0.3", 2879 | "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", 2880 | "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", 2881 | "dev": true 2882 | }, 2883 | "type-check": { 2884 | "version": "0.3.2", 2885 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 2886 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 2887 | "dev": true, 2888 | "requires": { 2889 | "prelude-ls": "1.1.2" 2890 | } 2891 | }, 2892 | "typedarray": { 2893 | "version": "0.0.6", 2894 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 2895 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 2896 | "dev": true 2897 | }, 2898 | "util-deprecate": { 2899 | "version": "1.0.2", 2900 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2901 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", 2902 | "dev": true 2903 | }, 2904 | "wordwrap": { 2905 | "version": "1.0.0", 2906 | "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", 2907 | "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", 2908 | "dev": true 2909 | }, 2910 | "wrappy": { 2911 | "version": "1.0.2", 2912 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2913 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2914 | "dev": true 2915 | }, 2916 | "write": { 2917 | "version": "0.2.1", 2918 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 2919 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 2920 | "dev": true, 2921 | "requires": { 2922 | "mkdirp": "0.5.1" 2923 | } 2924 | }, 2925 | "xtend": { 2926 | "version": "4.0.1", 2927 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", 2928 | "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", 2929 | "dev": true 2930 | } 2931 | } 2932 | } 2933 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "common-shake", 3 | "version": "2.1.0", 4 | "description": "CommonJS Tree Shake", 5 | "main": "lib/shake.js", 6 | "repository": { 7 | "type": "git", 8 | "url": "git+ssh://git@github.com/indutny/common-shake.git" 9 | }, 10 | "scripts": { 11 | "lint": "eslint lib/*.js lib/**/*.js test/*.js", 12 | "test": "nyc --reporter=html mocha --reporter=spec test/*-test.js && npm run lint" 13 | }, 14 | "files": [ 15 | "lib" 16 | ], 17 | "keywords": [ 18 | "commonjs", 19 | "tree", 20 | "shake" 21 | ], 22 | "author": "Fedor Indutny (http://darksi.de/)", 23 | "license": "MIT", 24 | "dependencies": { 25 | "acorn": "^5.1.1", 26 | "debug": "^2.6.8", 27 | "escope": "^3.6.0" 28 | }, 29 | "devDependencies": { 30 | "acorn-dynamic-import": "^2.0.2", 31 | "assert-text": "^1.1.2", 32 | "eslint": "^4.1.1", 33 | "mocha": "^3.4.2", 34 | "nyc": "^11.0.3" 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /test/analyzer-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* globals describe it beforeEach afterEach */ 3 | 4 | const assert = require('assert'); 5 | const fixtures = require('./fixtures'); 6 | const parse = fixtures.parse; 7 | 8 | const shake = require('../'); 9 | const Analyzer = shake.Analyzer; 10 | 11 | const EMPTY = { 12 | bailouts: false, 13 | uses: [], 14 | declarations: [] 15 | }; 16 | 17 | function simplifyDecl(decl) { 18 | return { 19 | type: decl.type, 20 | name: decl.name, 21 | ast: decl.ast.type 22 | }; 23 | } 24 | 25 | describe('Analyzer', () => { 26 | let analyzer; 27 | 28 | beforeEach(() => { 29 | analyzer = new Analyzer(); 30 | }); 31 | 32 | afterEach(() => { 33 | analyzer = null; 34 | }); 35 | 36 | it('should find all exported values', () => { 37 | analyzer.run(parse(` 38 | exports.a = 1; 39 | exports.b = 2; 40 | 41 | !function() { 42 | module.exports.c = 3; 43 | }(); 44 | `), 'root'); 45 | 46 | assert.deepEqual(analyzer.getModule('root').getInfo(), { 47 | bailouts: false, 48 | uses: [], 49 | declarations: [ 'a', 'b', 'c' ] 50 | }); 51 | 52 | const decls = analyzer.getModule('root').getDeclarations(); 53 | 54 | assert.deepEqual(decls.map(simplifyDecl), [ 55 | { type: 'exports', name: 'a', ast: 'AssignmentExpression' }, 56 | { type: 'exports', name: 'b', ast: 'AssignmentExpression' }, 57 | { type: 'exports', name: 'c', ast: 'AssignmentExpression' } 58 | ]); 59 | }); 60 | 61 | it('should find all imported values', () => { 62 | analyzer.run(parse(` 63 | const lib = require('./a'); 64 | 65 | lib.a(); 66 | lib.b(); 67 | require('./a').c(); 68 | `), 'root'); 69 | 70 | analyzer.run(parse(` 71 | exports.a = 1; 72 | exports.b = 2; 73 | exports.c = 3; 74 | exports.d = 4; 75 | `), 'a'); 76 | 77 | analyzer.resolve('root', './a', 'a'); 78 | 79 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 80 | assert.deepEqual(analyzer.getModule('a').getInfo(), { 81 | bailouts: false, 82 | uses: [ 'a', 'b', 'c' ], 83 | declarations: [ 'a', 'b', 'c', 'd' ] 84 | }); 85 | }); 86 | 87 | it('should find all self-used values', () => { 88 | analyzer.run(parse(` 89 | exports.a = 1; 90 | exports.b = () => {}; 91 | 92 | exports.c = () => { 93 | return exports.b(); 94 | }; 95 | 96 | exports.d = () => { 97 | return module.exports.c(); 98 | }; 99 | `), 'root'); 100 | 101 | assert.deepEqual(analyzer.getModule('root').getInfo(), { 102 | bailouts: false, 103 | uses: [ 'b', 'c' ], 104 | declarations: [ 'a', 'b', 'c', 'd' ] 105 | }); 106 | }); 107 | 108 | it('should not count disguised `exports` use as export', () => { 109 | analyzer.run(parse(` 110 | function a() { 111 | var exports = {}; 112 | exports.a = a; 113 | } 114 | 115 | exports.b = 1; 116 | `), 'root'); 117 | 118 | assert.deepEqual(analyzer.getModule('root').getInfo(), { 119 | bailouts: false, 120 | uses: [], 121 | declarations: [ 'b' ] 122 | }); 123 | }); 124 | 125 | it('should support object destructuring', () => { 126 | analyzer.run(parse(` 127 | const { a, b } = require('./a'); 128 | `), 'root'); 129 | 130 | analyzer.run(parse(` 131 | exports.a = 1; 132 | exports.b = 2; 133 | exports.c = 3; 134 | `), 'a'); 135 | 136 | analyzer.resolve('root', './a', 'a'); 137 | 138 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 139 | assert.deepEqual(analyzer.getModule('a').getInfo(), { 140 | bailouts: false, 141 | uses: [ 'a', 'b' ], 142 | declarations: [ 'a', 'b', 'c' ] 143 | }); 144 | }); 145 | 146 | it('should not support dynamic object destructuring', () => { 147 | analyzer.run(parse(` 148 | const prop = 'a'; 149 | const { [prop]: name } = require('./a'); 150 | `), 'root'); 151 | 152 | analyzer.run(parse(` 153 | exports.a = 1; 154 | exports.b = 2; 155 | exports.c = 3; 156 | `), 'a'); 157 | 158 | analyzer.resolve('root', './a', 'a'); 159 | 160 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 161 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 162 | { 163 | loc: { 164 | start: { column: 12, line: 3 }, 165 | end: { column: 28, line: 3 } 166 | }, 167 | source: 'root', 168 | reason: 'Dynamic properties in `require` destructuring', 169 | level: 'warning' 170 | } 171 | ]); 172 | assert.deepEqual(analyzer.bailouts, false); 173 | }); 174 | 175 | it('should not support array destructuring', () => { 176 | analyzer.run(parse(` 177 | const [ a, b ] = require('./a'); 178 | `), 'root'); 179 | 180 | analyzer.run(parse(` 181 | exports.a = 1; 182 | exports.b = 2; 183 | exports.c = 3; 184 | `), 'a'); 185 | 186 | analyzer.resolve('root', './a', 'a'); 187 | 188 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 189 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 190 | { 191 | loc: { 192 | start: { column: 12, line: 2 }, 193 | end: { column: 37, line: 2 } 194 | }, 195 | source: 'root', 196 | reason: '`require` used in unknown way', 197 | level: 'warning' 198 | } 199 | ]); 200 | assert.deepEqual(analyzer.bailouts, false); 201 | }); 202 | 203 | it('should not count disguised `require` use as import', () => { 204 | analyzer.run(parse(` 205 | const lib = require('./a'); 206 | 207 | lib.a(); 208 | function a() { 209 | const require = () => {}; 210 | const lib = require('./a'); 211 | lib.b(); 212 | } 213 | `), 'root'); 214 | 215 | analyzer.run(parse(` 216 | exports.a = 1; 217 | exports.b = 2; 218 | `), 'a'); 219 | 220 | analyzer.resolve('root', './a', 'a'); 221 | 222 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 223 | assert.deepEqual(analyzer.getModule('a').getInfo(), { 224 | bailouts: false, 225 | uses: [ 'a' ], 226 | declarations: [ 'a', 'b' ] 227 | }); 228 | }); 229 | 230 | it('should not count redefined variable as import', () => { 231 | analyzer.run(parse(` 232 | var lib = require('./a'); 233 | 234 | lib.a(); 235 | 236 | var lib = require('./b'); 237 | lib.b(); 238 | `), 'root'); 239 | 240 | analyzer.run(parse(` 241 | exports.a = 1; 242 | exports.b = 2; 243 | `), 'a'); 244 | 245 | analyzer.resolve('root', './a', 'a'); 246 | analyzer.resolve('root', './b', 'b'); 247 | 248 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 249 | assert.deepEqual(analyzer.getModule('a').getInfo(), { 250 | bailouts: [ 251 | { 252 | loc: { 253 | start: { column: 10, line: 2 }, 254 | end: { column: 30, line: 2 } 255 | }, 256 | source: 'root', 257 | reason: '`require` variable override', 258 | level: 'warning' 259 | } 260 | ], 261 | uses: [], 262 | declarations: [ 'a', 'b' ] 263 | }); 264 | assert.deepEqual(analyzer.getModule('b').getInfo(), { 265 | bailouts: [ 266 | { 267 | loc: { 268 | start: { column: 10, line: 6 }, 269 | end: { column: 30, line: 6 } 270 | }, 271 | source: 'root', 272 | reason: '`require` variable override', 273 | level: 'warning' 274 | } 275 | ], 276 | uses: [], 277 | declarations: [] 278 | }); 279 | assert.deepEqual(analyzer.bailouts, false); 280 | }); 281 | 282 | it('should bailout on assignment to `exports`', () => { 283 | analyzer.run(parse(` 284 | exports = {}; 285 | exports.a = 1; 286 | `), 'root'); 287 | 288 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 289 | { 290 | loc: { 291 | start: { column: 6, line: 2 }, 292 | end: { column: 18, line: 2 } 293 | }, 294 | source: null, 295 | reason: '`exports` assignment', 296 | level: 'warning' 297 | } 298 | ]); 299 | assert.deepEqual(analyzer.bailouts, false); 300 | }); 301 | 302 | it('should bailout on assignment to `require`', () => { 303 | analyzer.run(parse(` 304 | require = () => {}; 305 | `), 'root'); 306 | 307 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 308 | { 309 | loc: { 310 | start: { column: 6, line: 2 }, 311 | end: { column: 24, line: 2 } 312 | }, 313 | source: null, 314 | reason: '`require` assignment', 315 | level: 'warning' 316 | } 317 | ]); 318 | assert.deepEqual(analyzer.bailouts, false); 319 | }); 320 | 321 | it('should bailout on dynamic `require`', () => { 322 | analyzer.run(parse(` 323 | const lib = require(Math.random()); 324 | `), 'root'); 325 | 326 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 327 | { 328 | loc: { 329 | start: { column: 18, line: 2 }, 330 | end: { column: 40, line: 2 } 331 | }, 332 | source: null, 333 | reason: 'Dynamic argument of `require`', 334 | level: 'warning' 335 | } 336 | ]); 337 | assert.deepEqual(analyzer.bailouts, [ 338 | { 339 | loc: { 340 | start: { column: 18, line: 2 }, 341 | end: { column: 40, line: 2 } 342 | }, 343 | source: 'root', 344 | reason: 'Dynamic argument of `require`' 345 | } 346 | ]); 347 | }); 348 | 349 | it('should not bailout use of `require` properties', () => { 350 | analyzer.run(parse(` 351 | require.cache[a] = 1; 352 | `), 'root'); 353 | 354 | assert(analyzer.isSuccess()); 355 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 356 | }); 357 | 358 | it('should bailout on invalide use of `require`', () => { 359 | analyzer.run(parse(` 360 | escape(require); 361 | `), 'root'); 362 | 363 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 364 | { 365 | loc: { 366 | start: { column: 13, line: 2 }, 367 | end: { column: 20, line: 2 } 368 | }, 369 | source: null, 370 | reason: 'Invalid use of `require`', 371 | level: 'warning' 372 | } 373 | ]); 374 | assert.deepEqual(analyzer.bailouts, [ 375 | { 376 | loc: { 377 | start: { column: 13, line: 2 }, 378 | end: { column: 20, line: 2 } 379 | }, 380 | source: 'root', 381 | reason: 'Invalid use of `require`' 382 | } 383 | ]); 384 | }); 385 | 386 | it('should not bailout on `typeof require`', () => { 387 | analyzer.run(parse(` 388 | if (typeof require === 'function') { 389 | console.log("ok"); 390 | } 391 | `), 'root'); 392 | 393 | assert.strictEqual(analyzer.getModule('root').getInfo().bailouts, false); 394 | }); 395 | 396 | it('should bailout on assignment to `module.exports`', () => { 397 | analyzer.run(parse(` 398 | module.exports = () => {}; 399 | `), 'root'); 400 | 401 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 402 | { 403 | loc: { 404 | start: { column: 6, line: 2 }, 405 | end: { column: 31, line: 2 } 406 | }, 407 | source: null, 408 | reason: '`module.exports` assignment', 409 | level: 'info' 410 | } 411 | ]); 412 | assert.deepEqual(analyzer.bailouts, false); 413 | }); 414 | 415 | it('should not bailout on assignment to other `module` properties', () => { 416 | analyzer.run(parse(` 417 | module.lamports = () => {}; 418 | `), 'root'); 419 | 420 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, false); 421 | assert.deepEqual(analyzer.bailouts, false); 422 | }); 423 | 424 | it('should support object literal in `module.exports`', () => { 425 | analyzer.run(parse(` 426 | module.exports = { 427 | a: 1, 428 | "b": 2 429 | }; 430 | `), 'root'); 431 | 432 | assert.deepEqual(analyzer.getModule('root').getInfo(), { 433 | bailouts: false, 434 | uses: [], 435 | declarations: [ 'a', 'b' ] 436 | }); 437 | 438 | const decls = analyzer.getModule('root').getDeclarations(); 439 | assert.deepEqual(decls.map(simplifyDecl), [ 440 | { type: 'module.exports', name: 'a', ast: 'Property' }, 441 | { type: 'module.exports', name: 'b', ast: 'Property' } 442 | ]); 443 | }); 444 | 445 | it('should bailout on dynamic keys in `module.exports`', () => { 446 | analyzer.run(parse(` 447 | module.exports = { 448 | [a]: 1, 449 | "b": 2 450 | }; 451 | `), 'root'); 452 | 453 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 454 | { 455 | loc: { 456 | start: { column: 8, line: 3 }, 457 | end: { column: 14, line: 3 } 458 | }, 459 | source: null, 460 | reason: 'Dynamic `module.exports` property', 461 | level: 'warning' 462 | } 463 | ]); 464 | }); 465 | 466 | it('should not support simultaneous `module.exports` and `exports`', () => { 467 | analyzer.run(parse(` 468 | exports.c = 1; 469 | module.exports = { 470 | a: 2, 471 | b: 3 472 | }; 473 | `), 'root'); 474 | 475 | analyzer.run(parse(` 476 | module.exports = { 477 | a: 2, 478 | b: 3 479 | }; 480 | exports.c = 1; 481 | `), 'rev-root'); 482 | 483 | assert.deepEqual(analyzer.getModule('root').getInfo(), { 484 | bailouts: [ { 485 | loc: { 486 | start: { column: 6, line: 3 }, 487 | end: { column: 7, line: 6 } 488 | }, 489 | source: null, 490 | reason: 'Simultaneous assignment to both `exports` and ' + 491 | '`module.exports`', 492 | level: 'warning' 493 | } ], 494 | uses: [], 495 | declarations: [ 'c', 'a', 'b' ] 496 | }); 497 | 498 | assert.deepEqual(analyzer.getModule('rev-root').getInfo(), { 499 | bailouts: [ { 500 | loc: { 501 | start: { column: 6, line: 6 }, 502 | end: { column: 19, line: 6 } 503 | }, 504 | source: null, 505 | reason: 'Simultaneous assignment to both `exports` and ' + 506 | '`module.exports`', 507 | level: 'warning' 508 | } ], 509 | uses: [], 510 | declarations: [ 'a', 'b', 'c' ] 511 | }); 512 | }); 513 | 514 | it('should bailout on dynamic export', () => { 515 | analyzer.run(parse(` 516 | exports[Math.random()] = 1; 517 | `), 'root'); 518 | 519 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 520 | { 521 | loc: { 522 | start: { column: 6, line: 2 }, 523 | end: { column: 28, line: 2 } 524 | }, 525 | source: null, 526 | reason: 'Dynamic CommonJS export', 527 | level: 'warning' 528 | } 529 | ]); 530 | assert.deepEqual(analyzer.bailouts, false); 531 | }); 532 | 533 | it('should bailout on dynamic `module` use', () => { 534 | analyzer.run(parse(` 535 | module[Math.random()] = 1; 536 | `), 'root'); 537 | 538 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 539 | { 540 | loc: { 541 | start: { column: 6, line: 2 }, 542 | end: { column: 27, line: 2 } 543 | }, 544 | source: null, 545 | reason: 'Dynamic `module` use', 546 | level: 'warning' 547 | } 548 | ]); 549 | assert.deepEqual(analyzer.bailouts, false); 550 | }); 551 | 552 | it('should bailout on dynamic self-use', () => { 553 | analyzer.run(parse(` 554 | exports[Math.random()](); 555 | module.exports[Math.random()](); 556 | `), 'root'); 557 | 558 | assert.deepEqual(analyzer.getModule('root').getInfo().bailouts, [ 559 | { 560 | loc: { 561 | start: { column: 6, line: 2 }, 562 | end: { column: 28, line: 2 } 563 | }, 564 | source: null, 565 | reason: 'Dynamic CommonJS use', 566 | level: 'warning' 567 | }, 568 | { 569 | loc: { 570 | start: { column: 6, line: 3 }, 571 | end: { column: 35, line: 3 } 572 | }, 573 | source: null, 574 | reason: 'Dynamic CommonJS use', 575 | level: 'warning' 576 | } 577 | ]); 578 | assert.deepEqual(analyzer.bailouts, false); 579 | }); 580 | 581 | it('should bailout on dynamic import', () => { 582 | analyzer.run(parse(` 583 | const lib = require('./a'); 584 | 585 | lib[Math.random()](); 586 | `), 'root'); 587 | 588 | analyzer.run(parse(''), 'a'); 589 | analyzer.resolve('root', './a', 'a'); 590 | 591 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 592 | { 593 | loc: { 594 | start: { column: 6, line: 4 }, 595 | end: { column: 24, line: 4 } 596 | }, 597 | source: 'root', 598 | reason: 'Dynamic CommonJS import', 599 | level: 'warning' 600 | } 601 | ]); 602 | assert.deepEqual(analyzer.bailouts, false); 603 | }); 604 | 605 | it('should bailout on assignment to imported library', () => { 606 | analyzer.run(parse(` 607 | const lib = require('./a'); 608 | 609 | lib.override = true; 610 | `), 'root'); 611 | 612 | analyzer.run(parse(''), 'a'); 613 | analyzer.resolve('root', './a', 'a'); 614 | 615 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 616 | { 617 | loc: { 618 | start: { column: 6, line: 4 }, 619 | end: { column: 25, line: 4 } 620 | }, 621 | source: 'root', 622 | reason: 'Module property assignment', 623 | level: 'warning' 624 | } 625 | ]); 626 | assert.deepEqual(analyzer.bailouts, false); 627 | }); 628 | 629 | it('should bailout on escaping imported library', () => { 630 | analyzer.run(parse(` 631 | const lib = require('./a'); 632 | 633 | send(lib); 634 | `), 'root'); 635 | 636 | analyzer.run(parse(''), 'a'); 637 | analyzer.resolve('root', './a', 'a'); 638 | 639 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 640 | { 641 | loc: { 642 | start: { column: 11, line: 4 }, 643 | end: { column: 14, line: 4 } 644 | }, 645 | source: 'root', 646 | reason: 'Escaping value or unknown use', 647 | level: 'warning' 648 | } 649 | ]); 650 | assert.deepEqual(analyzer.bailouts, false); 651 | }); 652 | 653 | it('should bailout on imported library call', () => { 654 | analyzer.run(parse(` 655 | const lib = require('./a'); 656 | 657 | lib(); 658 | `), 'root'); 659 | 660 | analyzer.run(parse(''), 'a'); 661 | analyzer.resolve('root', './a', 'a'); 662 | 663 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 664 | { 665 | loc: { 666 | start: { column: 6, line: 4 }, 667 | end: { column: 11, line: 4 } 668 | }, 669 | source: 'root', 670 | reason: 'Imported library call', 671 | level: 'info' 672 | } 673 | ]); 674 | assert.deepEqual(analyzer.bailouts, false); 675 | }); 676 | 677 | it('should bailout on imported library new call', () => { 678 | analyzer.run(parse(` 679 | const lib = require('./a'); 680 | 681 | new lib(); 682 | `), 'root'); 683 | 684 | analyzer.run(parse(''), 'a'); 685 | analyzer.resolve('root', './a', 'a'); 686 | 687 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 688 | { 689 | loc: { 690 | start: { column: 6, line: 4 }, 691 | end: { column: 15, line: 4 } 692 | }, 693 | source: 'root', 694 | reason: 'Imported library new call', 695 | level: 'info' 696 | } 697 | ]); 698 | assert.deepEqual(analyzer.bailouts, false); 699 | }); 700 | 701 | it('should bailout on deferred require', () => { 702 | analyzer.run(parse(` 703 | var lib; 704 | lib = require('./a'); 705 | 706 | lib.a(); 707 | lib.b(); 708 | `), 'root'); 709 | 710 | analyzer.run(parse(` 711 | exports.a = 1; 712 | exports.b = 2; 713 | exports.c = 3; 714 | `), 'a'); 715 | 716 | analyzer.resolve('root', './a', 'a'); 717 | 718 | assert.deepEqual(analyzer.getModule('root').getInfo(), EMPTY); 719 | assert.deepEqual(analyzer.getModule('a').getInfo().bailouts, [ 720 | { 721 | loc: { 722 | start: { column: 12, line: 3 }, 723 | end: { column: 26, line: 3 } 724 | }, 725 | source: 'root', 726 | reason: 'Escaping `require` call', 727 | level: 'warning' 728 | } 729 | ]); 730 | }); 731 | 732 | it('should not bailout on const require argument', () => { 733 | analyzer.run(parse(` 734 | const lib = require('./a' + 'b'); 735 | 736 | lib.a(); 737 | `), 'root'); 738 | 739 | analyzer.run(parse('exports.a = 1;'), 'ab'); 740 | analyzer.resolve('root', './ab', 'ab'); 741 | 742 | assert.deepEqual(analyzer.getModule('ab').getInfo(), { 743 | bailouts: false, 744 | declarations: [ 'a' ], 745 | uses: [ 'a' ] 746 | }); 747 | assert(analyzer.isSuccess()); 748 | }); 749 | 750 | it('should not fail on dynamic import', () => { 751 | assert.doesNotThrow(() => { 752 | analyzer.run(parse('import("ohai")'), 'root'); 753 | }); 754 | }); 755 | 756 | it('should not throw on double-resolve', () => { 757 | assert.doesNotThrow(() => { 758 | analyzer.resolve('root', './a', 'a'); 759 | analyzer.resolve('root', './a', 'a'); 760 | analyzer.resolve('root', './a', 'a'); 761 | }); 762 | }); 763 | 764 | it('should find recursive dependencies', () => { 765 | analyzer.run(parse(` 766 | const lib = require('./a'); 767 | const mlib = require('./ma'); 768 | 769 | exports.a = lib.a; 770 | exports.b = mlib.a; 771 | `), 'root'); 772 | 773 | analyzer.run(parse(` 774 | exports.a = require('./b').a; 775 | exports.c = require('./b').b; 776 | exports.b = exports.c; 777 | `), 'a'); 778 | 779 | analyzer.run(parse(` 780 | module.exports = { 781 | a: require('./mb').a, 782 | b: require('./mb').b 783 | }; 784 | `), 'ma'); 785 | 786 | analyzer.getModule('root').forceExport(); 787 | 788 | analyzer.resolve('root', './a', 'a'); 789 | analyzer.resolve('root', './ma', 'ma'); 790 | analyzer.resolve('a', './b', 'b'); 791 | analyzer.resolve('ma', './mb', 'mb'); 792 | 793 | assert.deepEqual(analyzer.getModule('a').getInfo(), { 794 | bailouts: false, 795 | uses: [ 'a' ], 796 | declarations: [ 'a', 'c', 'b' ] 797 | }); 798 | 799 | assert.deepEqual(analyzer.getModule('b').getInfo(), { 800 | bailouts: false, 801 | uses: [ 'a' ], 802 | declarations: [] 803 | }); 804 | 805 | assert.deepEqual(analyzer.getModule('ma').getInfo(), { 806 | bailouts: false, 807 | uses: [ 'a' ], 808 | declarations: [ 'a', 'b' ] 809 | }); 810 | 811 | assert.deepEqual(analyzer.getModule('mb').getInfo(), { 812 | bailouts: false, 813 | uses: [ 'a' ], 814 | declarations: [] 815 | }); 816 | }); 817 | 818 | it('should not choke on async/await', () => { 819 | assert.doesNotThrow(() => { 820 | analyzer.run(parse(` 821 | 'use strict'; 822 | 823 | const fn = async function() { 824 | await other(); 825 | }; 826 | `), 'root'); 827 | }); 828 | }); 829 | }); 830 | -------------------------------------------------------------------------------- /test/eval-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* globals describe it */ 3 | 4 | const assert = require('assert'); 5 | const fixtures = require('./fixtures'); 6 | 7 | const shake = require('../'); 8 | const evaluateConst = shake.evaluateConst; 9 | 10 | const parse = (source) => { 11 | return fixtures.parse(source).body[0].expression; 12 | }; 13 | 14 | describe('Evaluator', () => { 15 | it('should evaluate number literal', () => { 16 | assert.strictEqual(evaluateConst(parse('1')), 1); 17 | }); 18 | 19 | it('should evaluate string literal', () => { 20 | assert.strictEqual(evaluateConst(parse('"1"')), '1'); 21 | }); 22 | 23 | it('should evaluate binary addition', () => { 24 | assert.strictEqual(evaluateConst(parse('"1" + "2"')), '12'); 25 | }); 26 | 27 | it('should throw on unknown binary operation', () => { 28 | assert.throws(() => { 29 | evaluateConst(parse('"1" / "2"')); 30 | }); 31 | }); 32 | 33 | it('should throw on unknown node type', () => { 34 | assert.throws(() => { 35 | evaluateConst(parse('a()')); 36 | }); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /test/fixtures.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const acorn = require('acorn-dynamic-import').default; 4 | 5 | exports.parse = (source) => { 6 | return acorn.parse(source, { 7 | locations: true, 8 | sourceType: 'module', 9 | ecmaVersion: 2017, 10 | plugins: { 11 | dynamicImport: true 12 | } 13 | }); 14 | }; 15 | -------------------------------------------------------------------------------- /test/graph-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | /* globals describe it beforeEach afterEach */ 3 | 4 | const assertText = require('assert-text'); 5 | const fixtures = require('./fixtures'); 6 | const parse = fixtures.parse; 7 | 8 | assertText.options.trim = true; 9 | 10 | const shake = require('../'); 11 | const Analyzer = shake.Analyzer; 12 | const Graph = shake.Graph; 13 | 14 | describe('Graph', () => { 15 | let analyzer; 16 | let graph; 17 | 18 | beforeEach(() => { 19 | analyzer = new Analyzer(); 20 | graph = new Graph(__dirname); 21 | }); 22 | 23 | afterEach(() => { 24 | analyzer = null; 25 | graph = null; 26 | }); 27 | 28 | it('should find all exported values', () => { 29 | analyzer.run(parse(` 30 | // Import all 31 | require('./a')[K]; 32 | 33 | require('./b').bprop; 34 | 35 | exports.prop = 1; 36 | `), 'root'); 37 | 38 | analyzer.run(parse(` 39 | exports.aprop = 1; 40 | `), 'a'); 41 | 42 | analyzer.run(parse(` 43 | exports.bprop = 1; 44 | `), 'b'); 45 | 46 | analyzer.resolve('root', './a', 'a'); 47 | analyzer.resolve('root', './b', 'b'); 48 | 49 | const out = graph.generate(analyzer.getModules()); 50 | assertText.equal(out, `digraph { 51 | ranksep=1.2; 52 | subgraph "cluster://../root" { 53 | label="../root"; 54 | color=black; 55 | "{../root}/require" [label=require shape=diamond]; 56 | "{../root}[prop]" [label="prop" color=blue]; 57 | } 58 | subgraph "cluster://../a" { 59 | label="../a"; 60 | color=red; 61 | "{../a}/require" [label=require shape=diamond]; 62 | "{../a}[aprop]" [label="aprop" color=red]; 63 | "{../a}[[*]]" [label="[*]" color=red]; 64 | } 65 | "{../root}/require" -> "{../a}[[*]]"; 66 | subgraph "cluster://../b" { 67 | label="../b"; 68 | color=black; 69 | "{../b}/require" [label=require shape=diamond]; 70 | "{../b}[bprop]" [label="bprop" color=black]; 71 | } 72 | "{../root}/require" -> "{../b}[bprop]"; 73 | }`); 74 | }); 75 | }); 76 | --------------------------------------------------------------------------------