From 9128d47594e9e2dcad14f7912fbb09fdd48a9077 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Fri, 15 Apr 2016 12:55:20 -0400 Subject: [PATCH 01/65] add npm badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f25a860..569dad5 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # babel-plugin-angularjs-annotate -[![Circle CI](https://circleci.com/gh/schmod/babel-plugin-angularjs-annotate.svg?style=svg)](https://circleci.com/gh/schmod/bablel-plugin-angularjs-annotate) +[![Circle CI](https://circleci.com/gh/schmod/babel-plugin-angularjs-annotate.svg?style=svg)](https://circleci.com/gh/schmod/bablel-plugin-angularjs-annotate) [![npm version](https://badge.fury.io/js/babel-plugin-angularjs-annotate.svg)](https://badge.fury.io/js/babel-plugin-angularjs-annotate) Experimental fork of [ng-annotate](https://github.com/olov/ng-annotate). Adds Angular 1.x DI annotations to ES5/ES6 code being processed by babel, with support for explicit annotations (`/* @ngInject */`) and implicit annotations of idiomatic Angular code. From 06fc80b573c15fd86c88a9c699083d4d9dec5e39 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Fri, 15 Apr 2016 15:49:48 -0400 Subject: [PATCH 02/65] bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 38e1ae6..a4f6c8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-angularjs-annotate", - "version": "0.1.0", + "version": "0.1.1", "description": "Babel plugin to add angularjs dependency injection annotations", "main": "babel-ng-annotate.js", "repository": { From af61ea2d9affb95939d4cc0dec42f2ce275eedde Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Tue, 21 Jun 2016 17:34:34 -0400 Subject: [PATCH 03/65] bump deps --- package.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index a4f6c8e..904c1c8 100644 --- a/package.json +++ b/package.json @@ -9,18 +9,18 @@ }, "dependencies": { "babel": "^6.5.1", - "babel-plugin-transform-es2015-function-name": "^6.5.0", + "babel-plugin-transform-es2015-function-name": "^6.9.0", "simple-is": "~0.2.0" }, "devDependencies": { - "babel-core": "^6.6.0", - "babel-preset-es2015": "^6.6.0", - "babel-types": "^6.6.1", + "babel-core": "^6.10.4", + "babel-preset-es2015": "^6.9.0", + "babel-types": "^6.10.2", "chalk": "^1.1.1", - "diff": "^2.2.1", + "diff": "^2.2.3", "indent-string": "^2.1.0", - "tap-xunit": "^1.3.1", - "tape": "^4.4.0" + "tap-xunit": "^1.4.0", + "tape": "^4.6.0" }, "keywords": [ "angular", From 86eff3826ff0a3473dbeaf32fb379196fd506298 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Tue, 21 Jun 2016 18:13:01 -0400 Subject: [PATCH 04/65] support for some ES6 class annotations --- babel-ng-annotate.js | 10 +++++++ ng-annotate-main.js | 27 +++++++++++++++-- nginject.js | 47 +++++++++++++++++++++++++---- tests/es6.js | 71 ++++++++++++++++++++++++++++++++++++++++++++ tests/tests.js | 12 ++++++-- 5 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 tests/es6.js diff --git a/babel-ng-annotate.js b/babel-ng-annotate.js index 7f0ad14..fdf651e 100644 --- a/babel-ng-annotate.js +++ b/babel-ng-annotate.js @@ -67,6 +67,16 @@ module.exports = function() { ngInject.inspectDeclarator(path, ctx); } }, + ClassDeclaration: { + enter(path) { + ngInject.inspectClassDeclaration(path, ctx); + } + }, + ClassMethod: { + enter(path) { + ngInject.inspectClassMethod(path, ctx); + } + }, ObjectExpression: { enter(path) { ngInject.inspectObjectExpression(path, ctx); diff --git a/ng-annotate-main.js b/ng-annotate-main.js index f8dc526..b7dbe65 100644 --- a/ng-annotate-main.js +++ b/ng-annotate-main.js @@ -628,7 +628,14 @@ function followReference(path) { const bound = binding.path; if (is.someof(kind, ["const", "let", "var"])) { - assert(t.isVariableDeclarator(bound)); + + if(t.isVariableDeclaration(bound)){ + var declarations = bound.get('declarations'); + assert(declarations.length === 1); + return declarations[0]; + } + + assert(t.isVariableDeclarator(bound) || t.isClassDeclaration(bound)); // {type: "VariableDeclarator", id: {type: "Identifier", name: "foo"}, init: ..} return bound; } else if (kind === "hoisted") { @@ -677,7 +684,6 @@ function judgeInjectArraySuspect(path, ctx) { declaratorName = node.id.name; node = node.init; // var foo = ___; path = path.get("init"); - } else { opath = path; } @@ -690,7 +696,12 @@ function judgeInjectArraySuspect(path, ctx) { path = jumpOverIife(path); node = path.node; - if (isFunctionExpressionWithArgs(node)) { + if (t.isClassDeclaration(node)){ + declaratorName = node.id.name; + node = getConstructor(node); + } + + if (isFunctionExpressionWithArgs(node) || t.isClassMethod(node)) { // var x = 1, y = function(a,b) {}, z; if(node.id && node.id.name !== declaratorName){ @@ -794,6 +805,16 @@ function isGenericProviderName(node) { return t.isLiteral(node) && is.string(node.value); } +function getConstructor(node){ + var body = node.body.body; + for(var i=0; i< body.length; i++){ + let node = body[i]; + if(node.kind === 'constructor'){ + return node; + } + } +} + module.exports.match = match; module.exports.addModuleContextDependentSuspect = addModuleContextDependentSuspect; module.exports.addModuleContextIndependentSuspect = addModuleContextIndependentSuspect; diff --git a/nginject.js b/nginject.js index f673207..4331877 100644 --- a/nginject.js +++ b/nginject.js @@ -13,7 +13,9 @@ module.exports = { inspectFunction: inspectFunction, inspectObjectExpression: inspectObjectExpression, inspectAssignment: inspectAssignment, - inspectDeclarator: inspectDeclarator + inspectDeclarator: inspectDeclarator, + inspectClassDeclaration: inspectClassDeclaration, + inspectClassMethod: inspectClassMethod }; function inspectCallExpression(path, ctx) { @@ -44,18 +46,21 @@ const ngAnnotatePrologueDirectives = ["ngInject", "ngNoInject"]; function inspectFunction(path, ctx) { const node = path.node; - if(inspectComment(path, ctx)){ - return; - } - if(t.isVariableDeclarator(path.parent) && t.isVariableDeclaration(path.parentPath.parent)){ - var annotation = getAnnotation(path.parentPath.parent); + let annotation = getAnnotation(path.parentPath.parent); + if(annotation === null){ + annotation = getAnnotation(node); + } if(annotation !== null){ addSuspect(path.parentPath.parentPath, ctx, !annotation); return; } } + if(inspectComment(path, ctx)){ + return; + } + const str = matchPrologueDirectives(ngAnnotatePrologueDirectives, path); if (!str) { return; @@ -232,6 +237,36 @@ function inspectDeclarator(path, ctx){ } } +function inspectClassDeclaration(path, ctx){ + const node = path.node; + let annotation = getAnnotation(node); + if(annotation !== null){ + addSuspect(path, ctx, !annotation); + } +} + +function inspectClassMethod(path, ctx){ + const node = path.node; + + if(node.kind !== 'constructor'){ + return; + } + + let annotation = getAnnotation(path.node); + if(annotation === null){ + return; + } + + const ancestry = path.getAncestry(); + for(var i=0; i < ancestry.length; i++){ + let ancestor = ancestry[i]; + if(ancestor.isClassDeclaration()){ + addSuspect(ancestor, ctx, !annotation); + return; + } + } +} + function isStringArray(node) { if (!t.isArrayExpression(node)) { return false; diff --git a/tests/es6.js b/tests/es6.js new file mode 100644 index 0000000..1a1429b --- /dev/null +++ b/tests/es6.js @@ -0,0 +1,71 @@ +"use strict"; +module.exports = { + name: "ES6 Tests", + tests: [ + { + name: "simple class", + input: function(){ + class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + angular.module('MyMod').service('MySvc', svc); + }, + expected: function(){ + class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.$inject = ['dep1']; + + angular.module('MyMod').service('MySvc', svc); + } + }, + { + name: "annotated class", + input: function(){ + /* @ngInject */ + class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.foo = 'bar'; + }, + expected: function(){ + /* @ngInject */ + class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.$inject = ['dep1']; + svc.foo = 'bar'; + } + }, + { + name: "annotated constructor", + input: function(){ + class svc { + /* @ngInject */ + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.foo = 'bar'; + }, + expected: function(){ + class svc { + /* @ngInject */ + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.$inject = ['dep1']; + svc.foo = 'bar'; + } + } + ] +}; diff --git a/tests/tests.js b/tests/tests.js index 7281234..537b41b 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -15,7 +15,8 @@ let suites = [ require('./modals'), require('./ngInject'), require('./issues'), - require('./references') + require('./references'), + require('./es6.js') ]; function runSuite(suite){ @@ -53,7 +54,14 @@ function runTest(test) { var expected = babel.transform(fnBody(test.expected), { plugins: [], presets:["./es2015-modified"].map(resolve) }); - t.equals(out.code.trim(), expected.code.trim(), test.name); + t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES5: ' + test.name); + + // And again without the ES6 transformations + out = babel.transform(fnBody(test.input), { plugins: ["../babel-ng-annotate.js"].map(resolve), presets:[].map(resolve) }); + expected = babel.transform(fnBody(test.expected), { plugins: [], presets:[].map(resolve) }); + + t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES2015: ' + test.name); + t.end(); }); From 809dbe741fc2cd28af5e1e33f276ee320671a49d Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Tue, 21 Jun 2016 19:03:24 -0400 Subject: [PATCH 05/65] support exported implicit classes document es6 class patterns Update README.md fix circleci link fix typo in readme --- README.md | 63 ++++++++++++++++++++++++++++++++++------ ng-annotate-main.js | 6 +++- package.json | 3 +- tests/es2015-modified.js | 7 +++-- tests/es6.js | 23 ++++++++++++++- tests/tests.js | 24 ++++++++++----- 6 files changed, 105 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 569dad5..9417bd3 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,16 @@ # babel-plugin-angularjs-annotate -[![Circle CI](https://circleci.com/gh/schmod/babel-plugin-angularjs-annotate.svg?style=svg)](https://circleci.com/gh/schmod/bablel-plugin-angularjs-annotate) [![npm version](https://badge.fury.io/js/babel-plugin-angularjs-annotate.svg)](https://badge.fury.io/js/babel-plugin-angularjs-annotate) +[![Circle CI](https://circleci.com/gh/schmod/babel-plugin-angularjs-annotate.svg?style=svg)](https://circleci.com/gh/schmod/babel-plugin-angularjs-annotate) [![npm version](https://badge.fury.io/js/babel-plugin-angularjs-annotate.svg)](https://badge.fury.io/js/babel-plugin-angularjs-annotate) -Experimental fork of [ng-annotate](https://github.com/olov/ng-annotate). Adds Angular 1.x DI annotations to ES5/ES6 code being processed by babel, with support for explicit annotations (`/* @ngInject */`) and implicit annotations of idiomatic Angular code. +Fork of [ng-annotate](https://github.com/olov/ng-annotate) for Babel users, with a focus on speed and ES6 support. -Work in progress. **Test thoroughly before using this in production.** If stability is a priority, consider [ng-annotate](https://github.com/olov/ng-annotate) -or [babel-ng-annotate](https://github.com/mchmielarski/babel-plugin-ng-annotate), which are both excellent alternatives to this plugin. +Adds Angular 1.x DI annotations to ES5/ES6 code being processed by Babel, with support for explicit annotations (`/* @ngInject */`), and automatic (implicit) annotation of typical Angular code patterns. -This plugin currently supports matching and transforming all of the patterns currently recognized by ng-annotate (explicit and implicit), and passes the relevant portions of ng-annotate's test suite. ES6 support will be expanded in future releases -- contributions are welcome! +Fully compatible with ES5, transpiled ES6, and raw ES6 sources. Offers significantly reduced build times for projects already using Babel, compared to the standalone ng-annotate tool. -See [ng-annotate](https://github.com/olov/ng-annotate)'s documentation for more details. +This plugin currently supports matching and transforming all of the patterns currently recognized by ng-annotate (explicit and implicit), and passes the relevant portions of ng-annotate's test suite. -## Usage +## Installation Use like any other [Babel plugin](https://babeljs.io/docs/plugins/). @@ -30,10 +29,56 @@ and add the plugin to your `.babelrc` file: } ``` +## Usage + +See [ng-annotate](https://github.com/olov/ng-annotate)'s documentation and the [test sources](tests/) for details about the patterns that can be automatically detected by ng-annotate and this plugin, as well as information about how to explicitly mark functions and classes for annotation. + +### ES6 Annotations + +This plugin can annotate some ES6 classes that are not supported by ng-annotate: + +#### Implicit Class Annotation + +If a class is declared as an Angular service or factory in the same file as it is declared, it will be annotated automatically: + +```js +class svc { + constructor(dep1){ + this.dep1 = dep1; + } +} +angular.module('MyMod').service('MySvc', svc); +``` + +Becomes: + +```js +class svc { + constructor(dep1){ + this.dep1 = dep1; + } +} +svc.$inject = ['dep1']; +angular.module('MyMod').service('MySvc', svc); +``` + +#### Explicit Class Annotation + +If a class is exported and used in another file/module, it must be explicitly marked for injection: + +```js +/* @ngInject */ +class svc { + constructor(dep1){ + this.dep1 = dep1; + } +} +``` + ## Goals & Tasks This project/experiment does _not_ seek to replace ng-annotate. However, it does seek to provide similar -functionality for Angular 1.x developers who are already using Babel and/or coding in ES6. +functionality for Angular 1.x developers who are already using Babel and/or writing code in ES6. Because of some of the limitations presented by Babel's transformation process, this project does not aim to achieve feature parity, or provide identical output to ng-annotate. Notably, Babel does not preserve formatting @@ -50,7 +95,7 @@ That being said, this is my short-term todo list: * ✓ Actually pass those tests. * ✓ Pass tests in conjunction with the ES2015 preset. _(almost)_ * ✓ Cleanup. Remove vestigial functionality from the upstream project. -* Support a (very) limited set of ES6-friendly annotation patterns. +* ✓ Support a limited set of ES6-friendly annotation patterns. * ✓ Publish to npm, make a release, etc. ### To run tests: diff --git a/ng-annotate-main.js b/ng-annotate-main.js index b7dbe65..801e96a 100644 --- a/ng-annotate-main.js +++ b/ng-annotate-main.js @@ -688,6 +688,10 @@ function judgeInjectArraySuspect(path, ctx) { opath = path; } + if(t.isExportDeclaration(opath.parent)){ + opath = opath.parentPath; + } + // suspect must be inside of a block or at the top-level (i.e. inside of node.$parent.body[]) if (!node || !opath.parent || (!t.isProgram(opath.parent) && !t.isBlockStatement(opath.parent))) { return; @@ -696,7 +700,7 @@ function judgeInjectArraySuspect(path, ctx) { path = jumpOverIife(path); node = path.node; - if (t.isClassDeclaration(node)){ + if (t.isClass(node)){ declaratorName = node.id.name; node = getConstructor(node); } diff --git a/package.json b/package.json index 904c1c8..d7a17a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-angularjs-annotate", - "version": "0.1.1", + "version": "0.2.0", "description": "Babel plugin to add angularjs dependency injection annotations", "main": "babel-ng-annotate.js", "repository": { @@ -10,6 +10,7 @@ "dependencies": { "babel": "^6.5.1", "babel-plugin-transform-es2015-function-name": "^6.9.0", + "babel-plugin-transform-es2015-modules-commonjs": "^6.9.0", "simple-is": "~0.2.0" }, "devDependencies": { diff --git a/tests/es2015-modified.js b/tests/es2015-modified.js index 97490c2..d3f49fe 100644 --- a/tests/es2015-modified.js +++ b/tests/es2015-modified.js @@ -17,9 +17,12 @@ 'use strict'; const es2015 = require('babel-preset-es2015'); -const bad = require('babel-plugin-transform-es2015-function-name'); +const bad = [ + require('babel-plugin-transform-es2015-function-name'), + require('babel-plugin-transform-es2015-modules-commonjs') +]; -let plugins = es2015.plugins.filter(plugin => plugin !== bad); +let plugins = es2015.plugins.filter(plugin => bad.indexOf(plugin) === -1); module.exports = { plugins: plugins diff --git a/tests/es6.js b/tests/es6.js index 1a1429b..34f8541 100644 --- a/tests/es6.js +++ b/tests/es6.js @@ -19,10 +19,31 @@ module.exports = { } } svc.$inject = ['dep1']; - angular.module('MyMod').service('MySvc', svc); } }, + { + name: "exported class", + noES5: true, // this works with the ES2015 preset, but the transformations + // make it difficult to test + input: ` + export default class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + angular.module('MyMod').service('MySvc', svc); + `, + expected: ` + export default class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.$inject = ['dep1']; + angular.module('MyMod').service('MySvc', svc); + ` + }, { name: "annotated class", input: function(){ diff --git a/tests/tests.js b/tests/tests.js index 537b41b..d711891 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -50,17 +50,23 @@ function runTest(test) { var resolve = (file) => path.resolve(__dirname, file); - var out = babel.transform(fnBody(test.input), { plugins: ["../babel-ng-annotate.js"].map(resolve), presets:["./es2015-modified"].map(resolve) }); - var expected = babel.transform(fnBody(test.expected), { plugins: [], presets:["./es2015-modified"].map(resolve) }); + var out, expected; + // Test transpiled ES5 sources + if(!test.noES5){ + out = babel.transform(fnBody(test.input), { plugins: ["../babel-ng-annotate.js"].map(resolve), presets:["./es2015-modified"].map(resolve) }); + expected = babel.transform(fnBody(test.expected), { plugins: [], presets:["./es2015-modified"].map(resolve) }); - t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES5: ' + test.name); + t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES5: ' + test.name); + } // And again without the ES6 transformations - out = babel.transform(fnBody(test.input), { plugins: ["../babel-ng-annotate.js"].map(resolve), presets:[].map(resolve) }); - expected = babel.transform(fnBody(test.expected), { plugins: [], presets:[].map(resolve) }); + if(!test.noES6){ + out = babel.transform(fnBody(test.input), { plugins: ["../babel-ng-annotate.js"].map(resolve), presets:[].map(resolve) }); + expected = babel.transform(fnBody(test.expected), { plugins: [], presets:[].map(resolve) }); - t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES2015: ' + test.name); + t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES2015: ' + test.name); + } t.end(); }); @@ -75,7 +81,11 @@ function runTest(test) { function fnBody(fn){ - return fn.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]; + if(typeof fn === 'function'){ + return fn.toString().match(/function[^{]+\{([\s\S]*)\}$/)[1]; + } else { + return fn; + } } function wrapInAngularModule(fn){ From 5a6b8c15ee39db3c08fd835918427e6a08a7150f Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Tue, 21 Jun 2016 19:06:23 -0400 Subject: [PATCH 06/65] clarify goals --- README.md | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/README.md b/README.md index 9417bd3..df4287d 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ class svc { } ``` -## Goals & Tasks +## Notes & Philosophy This project/experiment does _not_ seek to replace ng-annotate. However, it does seek to provide similar functionality for Angular 1.x developers who are already using Babel and/or writing code in ES6. @@ -88,16 +88,6 @@ Initially, I had hoped to make very few modifications to the upstream sources, i merging babel support directly into ng-annotate. Unfortunately, Babylon appears to have diverged too far from Acorn to make that goal realistic. (I would love to be wrong here, and would welcome contributions that close the gap between the two projects!) -That being said, this is my short-term todo list: - -* ✓ Support the majority of invocations/annotations currently performed by ng-annotate -* ✓ Split up ng-annotate's test suite to be more granular and tolerant of some of babel's other transforms. -* ✓ Actually pass those tests. -* ✓ Pass tests in conjunction with the ES2015 preset. _(almost)_ -* ✓ Cleanup. Remove vestigial functionality from the upstream project. -* ✓ Support a limited set of ES6-friendly annotation patterns. -* ✓ Publish to npm, make a release, etc. - ### To run tests: ``` From ed88edb773836e70f35efc5e98b17b7b893eabf7 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Tue, 21 Jun 2016 19:23:04 -0400 Subject: [PATCH 07/65] support exported ES6 functions and classes --- babel-ng-annotate.js | 5 +++++ nginject.js | 11 ++++++++++- package.json | 1 - tests/es2015-modified.js | 3 +-- tests/es6.js | 35 +++++++++++++++++++++++++++++++++++ 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/babel-ng-annotate.js b/babel-ng-annotate.js index fdf651e..9fec08f 100644 --- a/babel-ng-annotate.js +++ b/babel-ng-annotate.js @@ -111,6 +111,11 @@ module.exports = function() { addTargets(targets); } }, + ExportDeclaration: { + enter(path) { + ngInject.inspectExportDeclaration(path, ctx); + } + }, Program: { enter(path, file) { ctx.suspects = []; diff --git a/nginject.js b/nginject.js index 4331877..82ba0ef 100644 --- a/nginject.js +++ b/nginject.js @@ -15,7 +15,8 @@ module.exports = { inspectAssignment: inspectAssignment, inspectDeclarator: inspectDeclarator, inspectClassDeclaration: inspectClassDeclaration, - inspectClassMethod: inspectClassMethod + inspectClassMethod: inspectClassMethod, + inspectExportDeclaration: inspectExportDeclaration }; function inspectCallExpression(path, ctx) { @@ -267,6 +268,14 @@ function inspectClassMethod(path, ctx){ } } +function inspectExportDeclaration(path, ctx){ + let annotation = getAnnotation(path.node); + if(annotation === null){ + return; + } + addSuspect(path.get('declaration'), ctx, !annotation); +} + function isStringArray(node) { if (!t.isArrayExpression(node)) { return false; diff --git a/package.json b/package.json index d7a17a1..b0d23d5 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "dependencies": { "babel": "^6.5.1", "babel-plugin-transform-es2015-function-name": "^6.9.0", - "babel-plugin-transform-es2015-modules-commonjs": "^6.9.0", "simple-is": "~0.2.0" }, "devDependencies": { diff --git a/tests/es2015-modified.js b/tests/es2015-modified.js index d3f49fe..a6fba84 100644 --- a/tests/es2015-modified.js +++ b/tests/es2015-modified.js @@ -18,8 +18,7 @@ const es2015 = require('babel-preset-es2015'); const bad = [ - require('babel-plugin-transform-es2015-function-name'), - require('babel-plugin-transform-es2015-modules-commonjs') + require('babel-plugin-transform-es2015-function-name') ]; let plugins = es2015.plugins.filter(plugin => bad.indexOf(plugin) === -1); diff --git a/tests/es6.js b/tests/es6.js index 34f8541..79c5745 100644 --- a/tests/es6.js +++ b/tests/es6.js @@ -44,6 +44,18 @@ module.exports = { angular.module('MyMod').service('MySvc', svc); ` }, + { + name: "exported annotated function", + input: ` + /* @ngInject */ + export default function svc(dep1){} + `, + expected: ` + svc.$inject = ["dep1"]; + /* @ngInject */ + export default function svc(dep1){} + ` + }, { name: "annotated class", input: function(){ @@ -66,6 +78,29 @@ module.exports = { svc.foo = 'bar'; } }, + { + name: "exported annotated class", + noES5: true, + input: ` + /* @ngInject */ + export default class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.foo = 'bar'; + `, + expected: ` + /* @ngInject */ + export default class svc { + constructor(dep1){ + this.dep1 = dep1; + } + } + svc.$inject = ['dep1']; + svc.foo = 'bar'; + ` + }, { name: "annotated constructor", input: function(){ From a501c521c5499e19d2eb11305dac6350c44ff406 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Tue, 21 Jun 2016 19:25:11 -0400 Subject: [PATCH 08/65] update changelog --- CHANGES.md | 5 +++++ README.md | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 403c384..9b12da7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,10 @@ # babel-plugin-angularjs-annotate changelog +## v0.2.0 2016-06-21 + * Add support for ES6 class annotations + * Add support for exported ES6 classes and functions + * Run all tests against transpiled _and_ non-transpiled code. + ## v0.1.0 2016-04-15 * Initial release diff --git a/README.md b/README.md index df4287d..df95ec8 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,13 @@ class svc { } ``` +Exported functions and classes may be annotated. Exported functions must have names: + +```js +/* @ngInject */ +export default function svc(dep1){} +``` + ## Notes & Philosophy This project/experiment does _not_ seek to replace ng-annotate. However, it does seek to provide similar From cccebc4361b293f6834eebca3597de4bd1dd86d6 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 25 Jul 2016 10:54:14 -0400 Subject: [PATCH 09/65] update .babelrc instructions Use idiomatic naming conventions for babel plugins. Webpack user? Using symlinks? Having trouble? You may need to use an absolute path: `plugins: [require.resolve('babel-plugin-angularjs-annotate')]` Closes #2 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index df95ec8..cf2305d 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ and add the plugin to your `.babelrc` file: ```json { "presets": ["es2015"], - "plugins": ["path/to/babel-ng-annotate"] + "plugins": ["angularjs-annotate"] } ``` From 7cdc9c39be166ccd9ea208e83cdf91b613cdf55d Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 25 Jul 2016 14:03:38 -0400 Subject: [PATCH 10/65] support arrow functions --- CHANGES.md | 3 + README.md | 35 ++- babel-ng-annotate.js | 5 + ng-annotate-main.js | 10 +- nginject.js | 14 +- package.json | 2 +- tests/ngInject-arrow.js | 280 +++++++++++++++++++++ tests/simple-arrow.js | 535 ++++++++++++++++++++++++++++++++++++++++ tests/tests.js | 2 + 9 files changed, 876 insertions(+), 10 deletions(-) create mode 100644 tests/ngInject-arrow.js create mode 100644 tests/simple-arrow.js diff --git a/CHANGES.md b/CHANGES.md index 9b12da7..5fdc541 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,8 @@ # babel-plugin-angularjs-annotate changelog +## v0.3.0 2016-07-25 + * Add support for ES6 arrow functions + ## v0.2.0 2016-06-21 * Add support for ES6 class annotations * Add support for exported ES6 classes and functions diff --git a/README.md b/README.md index cf2305d..c6f356a 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,40 @@ See [ng-annotate](https://github.com/olov/ng-annotate)'s documentation and the [ ### ES6 Annotations -This plugin can annotate some ES6 classes that are not supported by ng-annotate: +This plugin can annotate some ES6 classes and arrow functions that are not supported by ng-annotate: + +#### Implicit arrow function annotation + +Arrow functions may be annotated anywhere that a "regular" function expression may be used. + +**NOTE:** There are places where you _shouldn't_ use arrow functions in an Angular application. Inside of an arrow function, the value of `this` is inherited from the lexical scope enclosing the function. For this reason, arrow functions should not be used to declare Angular services or providers. + +_If you choose to ignore this warning, we'll add the annotations to your services and providers anyway, but your application probably won't work. Future releases may treat this condition as an error._ + +```js +angular.module("MyMod").controller("MyCtrl", ($scope, $timeout) => {}); +``` + +Becomes: + +```js +angular.module("MyMod").controller("MyCtrl", ["$scope", "$timeout", ($scope, $timeout) => {}]); +``` + +#### Explicit arrow function annotation + +Arrow functions may also be explicitly marked for annotation. + +```js +var x = /* @ngInject */ ($scope) => {}; +``` + +Becomes: + +```js +var x = /* @ngInject */ ($scope) => {}; +x.$inject = ["$scope"] +``` #### Implicit Class Annotation diff --git a/babel-ng-annotate.js b/babel-ng-annotate.js index 9fec08f..8ef7c63 100644 --- a/babel-ng-annotate.js +++ b/babel-ng-annotate.js @@ -97,6 +97,11 @@ module.exports = function() { ngInject.inspectFunction(path, ctx); } }, + ArrowFunctionExpression: { + enter(path) { + ngInject.inspectFunction(path, ctx); + } + }, FunctionDeclaration: { enter(path) { ngInject.inspectFunction(path, ctx); diff --git a/ng-annotate-main.js b/ng-annotate-main.js index 801e96a..e59119b 100644 --- a/ng-annotate-main.js +++ b/ng-annotate-main.js @@ -639,7 +639,7 @@ function followReference(path) { // {type: "VariableDeclarator", id: {type: "Identifier", name: "foo"}, init: ..} return bound; } else if (kind === "hoisted") { - assert(t.isFunctionDeclaration(bound) || t.isFunctionExpression(bound)); + assert(t.isFunctionDeclaration(bound) || isFunctionExpressionOrArrow(bound)); // FunctionDeclaration is the common case, i.e. // function foo(a, b) {} @@ -775,7 +775,7 @@ function jumpOverIife(path) { console.warn("Not a path"); } - if (!(t.isCallExpression(node) && t.isFunctionExpression(node.callee))) { + if (!(t.isCallExpression(node) && isFunctionExpressionOrArrow(node.callee))) { return path; } @@ -799,8 +799,12 @@ function addModuleContextIndependentSuspect(target, ctx) { ctx.suspects.push(target); } +function isFunctionExpressionOrArrow(node) { + return t.isFunctionExpression(node) || t.isArrowFunctionExpression(node); +} + function isFunctionExpressionWithArgs(node) { - return t.isFunctionExpression(node) && node.params.length >= 1; + return isFunctionExpressionOrArrow(node) && node.params.length >= 1; } function isFunctionDeclarationWithArgs(node) { return t.isFunctionDeclaration(node) && node.params.length >= 1; diff --git a/nginject.js b/nginject.js index 82ba0ef..9c77dc9 100644 --- a/nginject.js +++ b/nginject.js @@ -171,7 +171,7 @@ function inspectObjectExpression(path, ctx) { addSuspect(path, ctx, !annotateEverything); } else { path.get("properties") - .filter(prop => t.isFunctionExpression(prop.node.value)) + .filter(prop => isFunctionExpressionOrArrow(prop.node.value)) .forEach(prop => inspectComment(prop, ctx)); } @@ -203,7 +203,7 @@ function matchPrologueDirectives(prologueDirectives, path) { function inspectAssignment(path, ctx){ const node = path.node; - if(!t.isFunctionExpression(node.right)){ + if(!isFunctionExpressionOrArrow(node.right)){ return; } @@ -221,7 +221,7 @@ function inspectAssignment(path, ctx){ function inspectDeclarator(path, ctx){ const node = path.node; - if(!t.isFunctionExpression(node.init)){ + if(!isFunctionExpressionOrArrow(node.init)){ return; } @@ -352,7 +352,7 @@ function nestedObjectValues(path, res) { path.get("properties").forEach(function(prop) { const v = prop.get("value"); - if (t.isFunctionExpression(v) || t.isArrayExpression(v)) { + if (isFunctionExpressionOrArrow(v) || t.isArrayExpression(v)) { res.push(v); } else if (t.isObjectExpression(v)) { nestedObjectValues(v, res); @@ -369,7 +369,7 @@ function isAnnotatedArray(node) { const elements = node.elements; // last should be a function expression - if (elements.length === 0 || !t.isFunctionExpression(last(elements))) { + if (elements.length === 0 || !isFunctionExpressionOrArrow(last(elements))) { return false; } @@ -383,3 +383,7 @@ function isAnnotatedArray(node) { return true; } + +function isFunctionExpressionOrArrow(node) { + return t.isFunctionExpression(node) || t.isArrowFunctionExpression(node); +} diff --git a/package.json b/package.json index b0d23d5..575a88c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-angularjs-annotate", - "version": "0.2.0", + "version": "0.3.0", "description": "Babel plugin to add angularjs dependency injection annotations", "main": "babel-ng-annotate.js", "repository": { diff --git a/tests/ngInject-arrow.js b/tests/ngInject-arrow.js new file mode 100644 index 0000000..99a81f7 --- /dev/null +++ b/tests/ngInject-arrow.js @@ -0,0 +1,280 @@ +module.exports = { + name: "Explicit ngInject annotations with arrow functions", + tests: [ + { + name: "var x = /* @ngInject */ function($scope)", + input: function(){ + var x = /* @ngInject */ ($scope) => { + }; + }, + expected: function(){ + var x = /* @ngInject */ ($scope) => {}; + x.$inject = ["$scope"] + } + }, + { + name: "Dereferenced method", + input: function(){ + var obj = {}; + obj.bar = /*@ngInject*/ ($scope) => {}; + }, + expected: function(){ + var obj = {}; + obj.bar = /*@ngInject*/ ["$scope", ($scope) => { + }]; + } + }, + { + name: "Prefixed object method", + input: function(){ + obj = { + controller: /*@ngInject*/ ($scope) => {}, + }; + }, + expected: function(){ + obj = { + controller: /*@ngInject*/ ["$scope", ($scope) => {}], + }; + } + }, + { + name: "Prefixed object literal", + input: function(){ + obj = /*@ngInject*/ { + foo: (a) => {}, + bar: (b, c) => {}, + val: 42, + inner: { + circle: (d) => {}, + alalalala: "long", + }, + nest: { many: {levels: (x) => {}}}, + but: { onlythrough: ["object literals", {donttouch: (me) => {}}]}, + }; + }, + expected: function(){ + obj = /*@ngInject*/ { + foo: ["a", (a) => {}], + bar: ["b", "c", (b, c) => {}], + val: 42, + inner: { + circle: ["d", (d) => {}], + alalalala: "long", + }, + nest: { many: {levels: ["x", (x) => {}]}}, + but: { onlythrough: ["object literals", {donttouch: (me) => {}}]}, + }; + } + }, + { + name: "Prefixed object property", + input: function(){ + obj = { + /*@ngInject*/ + foo: (a) => {}, + bar: (b, c) => {}, + }; + }, + expected: function(){ + obj = { + /*@ngInject*/ + foo: ["a", (a) => {}], + bar: (b, c) => {}, + }; + } + }, + { + name: "Prefixed object assignment", + input: function(){ + /*@ngInject*/ + obj = { + foo: (a) => {}, + bar: (b, c) => {}, + val: 42, + inner: { + circle: (d) => {}, + alalalala: "long", + }, + nest: { many: {levels: (x) => {}}}, + but: { onlythrough: ["object literals", {donttouch: (me) => {}}]}, + }; + }, + expected: function(){ + /*@ngInject*/ + obj = { + foo: ["a", (a) => {}], + bar: ["b", "c", (b, c) => {}], + val: 42, + inner: { + circle: ["d", (d) => {}], + alalalala: "long", + }, + nest: { many: {levels: ["x", (x) => {}]}}, + but: { onlythrough: ["object literals", {donttouch: (me) => {}}]}, + }; + } + }, + { + name: "Prefixed object declaration", + input: function(){ + /*@ngInject*/ + var obj = { + foo: (a) => {}, + bar: (b, c) => {}, + val: 42, + inner: { + circle: (d) => {}, + alalalala: "long", + }, + nest: { many: {levels: (x) => {}}}, + but: { onlythrough: ["object literals", {donttouch: (me) => {}}]}, + }; + }, + expected: function(){ + /*@ngInject*/ + var obj = { + foo: ["a", (a) => {}], + bar: ["b", "c", (b, c) => {}], + val: 42, + inner: { + circle: ["d", (d) => {}], + alalalala: "long", + }, + nest: { many: {levels: ["x", (x) => {}]}}, + but: { onlythrough: ["object literals", {donttouch: (me) => {}}]}, + }; + } + }, + { + name: "Function variable", + input: function(){ + // @ngInject + // has trailing semicolon + var foo1 = ($scope) => { + }; + + // @ngInject + // lacks trailing semicolon + var foo2 = ($scope) => { + } + }, + expected: function(){ + // @ngInject + // has trailing semicolon + var foo1 = ($scope) => { + }; + + foo1.$inject = ["$scope"]; + // @ngInject + // lacks trailing semicolon + var foo2 = ($scope) => { + } + foo2.$inject = ["$scope"]; + } + }, + { + name: "Unnecessary annotation", + input: function(){ + // adding an explicit annotation where it isn't needed should work fine + myMod.controller("foo", /*@ngInject*/ ($scope, $timeout) => { + }); + var foo = bar; + }, + expected: function(){ + // adding an explicit annotation where it isn't needed should work fine + myMod.controller("foo", /*@ngInject*/ ["$scope", "$timeout", ($scope, $timeout) => { + }]); + var foo = bar; + } + }, + { + name: "multiple prologues", + input: function(){ + var foos3 = ($scope) => { + // comments are ok before the Directive Prologues + // and there may be multiple Prologues + "use strict"; "ngInject"; + }; + }, + expected: function(){ + var foos3 = ($scope) => { + // comments are ok before the Directive Prologues + // and there may be multiple Prologues + "use strict"; "ngInject"; + }; + foos3.$inject = ["$scope"]; + } + }, + { + name: "prologues in multiple assignment expression", + input: function(){ + var dual1 = (a) => { "ngInject" }, dual2 = (b) => { "ngInject" }; + }, + expected: function(){ + var dual1 = (a) => { "ngInject" }, dual2 = (b) => { "ngInject" }; + dual2.$inject = ["b"]; + dual1.$inject = ["a"]; + } + }, + { + name: "prologue in anonymous function", + input: function(){ + g((c) => { + "ngInject" + }); + }, + expected: function(){ + g(["c", (c) => { + "ngInject" + }]); + } + }, + { + name: "suppress false positives with /*@ngNoInject*/, ngNoInject() and \"ngNoInject\"", + input: function(){ + myMod.controller("suppressed", /*@ngNoInject*/($scope) => { + }); + myMod.controller("suppressed", ngNoInject(($scope) => { + })); + myMod.controller("suppressed", ($scope) => { + "ngNoInject"; + }); + }, + expected: function(){ + myMod.controller("suppressed", /*@ngNoInject*/($scope) => { + }); + myMod.controller("suppressed", ngNoInject(($scope) => { + })); + myMod.controller("suppressed", ($scope) => { + "ngNoInject"; + }); + } + }, + { + name: "annotated directive function", + input: function(){ + /* @ngInject */ + var MyDirective2 = ($stateProvider) => { + $stateProvider.state('astate', { + resolve: { + yoyo: (ma) => { + }, + } + }); + }; + }, + expected: function(){ + /* @ngInject */ + var MyDirective2 = ($stateProvider) => { + $stateProvider.state('astate', { + resolve: { + yoyo: ['ma', (ma) => { + }], + } + }); + }; + MyDirective2.$inject = ['$stateProvider']; + } + } + ] +} diff --git a/tests/simple-arrow.js b/tests/simple-arrow.js new file mode 100644 index 0000000..4210e6a --- /dev/null +++ b/tests/simple-arrow.js @@ -0,0 +1,535 @@ +module.exports = { + name: "Simple Tests (arrow functions)", + tests: [ + { + name: "Long form (arrow function)", + input: function(){ + angular.module("MyMod").controller("MyCtrl", ($scope, $timeout) => { + }); + }, + expected: function(){ + angular.module("MyMod").controller("MyCtrl", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "w/ dependencies (arrow function)", + input: function(){ + angular.module("MyMod", ["OtherMod"]).controller("MyCtrl", ($scope, $timeout) => { + }); + }, + expected: function(){ + angular.module("MyMod", ["OtherMod"]).controller("MyCtrl", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple controller (arrow function)", + input: function(){ + myMod.controller("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.controller("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple service (arrow function)", + input: function(){ + myMod.service("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.service("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple factory (arrow function)", + input: function(){ + myMod.factory("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.factory("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple filter (arrow function)", + input: function(){ + myMod.filter("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.filter("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple directive (arrow function)", + input: function(){ + myMod.directive("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.directive("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple animation (arrow function)", + input: function(){ + myMod.animation("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.animation("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple invoke (arrow function)", + input: function(){ + myMod.invoke("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.invoke("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple store (arrow function)", + input: function(){ + myMod.store("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.store("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple decorator (arrow function)", + input: function(){ + myMod.decorator("foo", ($scope, $timeout) => { + }); + }, + expected: function(){ + myMod.decorator("foo", ["$scope", "$timeout", ($scope, $timeout) => { + }]); + } + }, + { + name: "Simple component (arrow function)", + input: function(){ + myMod.component("foo", {controller: ($scope, $timeout) => {}}); + }, + expected: function(){ + myMod.component("foo", {controller: ["$scope", "$timeout", ($scope, $timeout) => {}]}); + } + }, + { + name: "Implict config function (arrow function)", + input: function(){ + // implicit config function + angular.module("MyMod", ($interpolateProvider) => {}); + angular.module("MyMod", ["OtherMod"], ($interpolateProvider) => {}); + angular.module("MyMod", ["OtherMod"], ($interpolateProvider) => {}).controller("foo", ($scope) => {}); + }, + expected: function(){ + // implicit config function + angular.module("MyMod", ["$interpolateProvider", ($interpolateProvider) => {}]); + angular.module("MyMod", ["OtherMod"], ["$interpolateProvider", ($interpolateProvider) => {}]); + angular.module("MyMod", ["OtherMod"], ["$interpolateProvider", ($interpolateProvider) => {}]).controller("foo", ["$scope", ($scope) => {}]); + } + }, + { + name: "Object property (arrow function)", + input: function(){ + // object property + var myObj = {}; + myObj.myMod = angular.module("MyMod"); + myObj.myMod.controller("foo", ($scope, $timeout) => { a }); + + }, + expected: function(){ + // object property + var myObj = {}; + myObj.myMod = angular.module("MyMod"); + myObj.myMod.controller("foo", ["$scope", "$timeout", ($scope, $timeout) => { a }]); + } + }, + { + name: "Simple invocations w/ no dependencies (arrow function)", + input: function(){ + // no dependencies => no need to wrap the function in an array + myMod.controller("foo", () => { + }); + myMod.service("foo", () => { + }); + myMod.factory("foo", () => { + }); + myMod.directive("foo", () => { + }); + myMod.filter("foo", () => { + }); + myMod.animation("foo", () => { + }); + myMod.invoke("foo", () => { + }); + myMod.store("foo", () => { + }); + myMod.decorator("foo", () => { + }); + myMod.component("foo", {controller: () => {}}); + }, + expected: function(){ + // no dependencies => no need to wrap the function in an array + myMod.controller("foo", () => { + }); + myMod.service("foo", () => { + }); + myMod.factory("foo", () => { + }); + myMod.directive("foo", () => { + }); + myMod.filter("foo", () => { + }); + myMod.animation("foo", () => { + }); + myMod.invoke("foo", () => { + }); + myMod.store("foo", () => { + }); + myMod.decorator("foo", () => { + }); + myMod.component("foo", {controller: () => {}}); + } + }, + { + name: "Simple run/config (arrow function)", + input: function(){ + // run, config don't take names + myMod.run(($scope, $timeout) => { + }); + angular.module("MyMod").run(($scope) => { + }); + myMod.config(($scope, $timeout) => { + }); + angular.module("MyMod").config(() => { + }); + }, + expected: function(){ + // run, config don't take names + myMod.run(["$scope", "$timeout", ($scope, $timeout) => { + }]); + angular.module("MyMod").run(["$scope", ($scope) => { + }]); + myMod.config(["$scope", "$timeout", ($scope, $timeout) => { + }]); + angular.module("MyMod").config(() => { + }); + } + }, + { + name: "Directive return object (arrow function)", + input: function(){ + // directive return object + myMod.directive("foo", ($scope) => { + return { + controller: ($scope, $timeout) => { + bar; + } + } + }); + myMod.directive("foo", ($scope) => { + return { + controller: () => { + bar; + } + } + }); + }, + expected: function(){ + // directive return object + myMod.directive("foo", ["$scope", ($scope) => { + return { + controller: ["$scope", "$timeout", ($scope, $timeout) => { + bar; + }] + } + }]); + myMod.directive("foo", ["$scope", ($scope) => { + return { + controller: () => { + bar; + } + } + }]); + } + }, + { + name: "Simple chaining (arrow function)", + input: function(){ + myMod.directive("foo", ($a, $b) => { + a; + }).factory("foo", () => { + b; + }).config(($c) => { + c; + }).filter("foo", ($d, $e) => { + d; + }).animation("foo", ($f, $g) => { + e; + }).component("foo", {controller: ($scope, $timeout) => { + i; + }}).invoke("foo", ($f, $g) => { + f; + }).decorator("foo", ($f, $g) => { + g; + }).store("foo", ($f, $g) => { + h; + }); + }, + expected: function(){ + myMod.directive("foo", ["$a", "$b", ($a, $b) => { + a; + }]).factory("foo", () => { + b; + }).config(["$c", ($c) => { + c; + }]).filter("foo", ["$d", "$e", ($d, $e) => { + d; + }]).animation("foo", ["$f", "$g", ($f, $g) => { + e; + }]).component("foo", {controller: ["$scope", "$timeout", ($scope, $timeout) => { + i; + }]}).invoke("foo", ["$f", "$g", ($f, $g) => { + f; + }]).decorator("foo", ["$f", "$g", ($f, $g) => { + g; + }]).store("foo", ["$f", "$g", ($f, $g) => { + h; + }]); + } + }, + { + name: "Less simple chaining (arrow function)", + input: function(){ + angular.module("MyMod").directive("foo", ($a, $b) => { + a; + }).provider("foo", () => { + return { + $get: ($scope, $timeout) => { + bar; + }}; + }).value("foo", "bar") + .constant("foo", "bar") + .bootstrap(element, [], {}) + .factory("foo", () => { + b; + }).config(($c) => { + c; + }).filter("foo", ($d, $e) => { + d; + }).animation("foo", ($f, $g) => { + e; + }).component("foo", {controller: ($scope, $timeout) => { + i; + }}).invoke("foo", ($h, $i) => { + f; + }).decorator("foo", ($h, $i) => { + g; + }).store("foo", ($f, $g) => { + h; + }); + }, + expected: function(){ + angular.module("MyMod").directive("foo", ["$a", "$b", ($a, $b) => { + a; + }]).provider("foo", () => { + return { + $get: ["$scope", "$timeout", ($scope, $timeout) => { + bar; + }]}; + }).value("foo", "bar") + .constant("foo", "bar") + .bootstrap(element, [], {}) + .factory("foo", () => { + b; + }).config(["$c", ($c) => { + c; + }]).filter("foo", ["$d", "$e", ($d, $e) => { + d; + }]).animation("foo", ["$f", "$g", ($f, $g) => { + e; + }]).component("foo", {controller: ["$scope", "$timeout", ($scope, $timeout) => { + i; + }]}).invoke("foo", ["$h", "$i", ($h, $i) => { + f; + }]).decorator("foo", ["$h", "$i", ($h, $i) => { + g; + }]).store("foo", ["$f", "$g", ($f, $g) => { + h; + }]); + } + }, + { + name: "$provide (arrow function)", + input: function(){ + angular.module("myMod").controller("foo", () => { + $provide.decorator("foo", ($scope) => {}); + $provide.service("foo", ($scope) => {}); + $provide.factory("foo", ($scope) => {}); + //$provide.provider + $provide.provider("foo", { + $get: ($scope, $timeout) => {} + }); + }); + }, + expected: function(){ + angular.module("myMod").controller("foo", () => { + $provide.decorator("foo", ["$scope", ($scope) => {}]); + $provide.service("foo", ["$scope", ($scope) => {}]); + $provide.factory("foo", ["$scope", ($scope) => {}]); + //$provide.provider + $provide.provider("foo", { + $get: ["$scope", "$timeout", ($scope, $timeout) => {}] + }); + }); + } + }, + { + name: "negative $provide (arrow function)", + input: function(){ + function notInContext() { + $provide.decorator("foo", ($scope) => {}); + $provide.service("foo", ($scope) => {}); + $provide.factory("foo", ($scope) => {}); + $provide.provider("foo", ($scope) => { + this.$get = ($scope) => {}; + return { $get: ($scope, $timeout) => {}}; + }); + $provide.provider("foo", { + $get: ($scope, $timeout) => {} + }); + } + }, + expected: function(){ + function notInContext() { + $provide.decorator("foo", ($scope) => {}); + $provide.service("foo", ($scope) => {}); + $provide.factory("foo", ($scope) => {}); + $provide.provider("foo", ($scope) => { + this.$get = ($scope) => {}; + return { $get: ($scope, $timeout) => {}}; + }); + $provide.provider("foo", { + $get: ($scope, $timeout) => {} + }); + } + } + }, + { + name: "ControllerProvider (arrow function)", + input: function(){ + angular.module("myMod").controller("foo", () => { + $controllerProvider.register("foo", ($scope) => {}); + }); + function notInContext() { + $controllerProvider.register("foo", ($scope) => {}); + } + }, + expected: function(){ + angular.module("myMod").controller("foo", () => { + $controllerProvider.register("foo", ["$scope", ($scope) => {}]); + }); + function notInContext() { + $controllerProvider.register("foo", ($scope) => {}); + } + } + }, + { + name: "directive return object is only valid inside directive (arrow function)", + input: function(){ + myMod.service("donttouch", () => { + return { + controller: ($scope, $timeout) => { + bar; + } + } + }); + + myMod.directive("donttouch", () => { + foo.decorator("me", ($scope) => { + }); + }); + }, + expected: function(){ + myMod.service("donttouch", () => { + return { + controller: ($scope, $timeout) => { + bar; + } + } + }); + + myMod.directive("donttouch", () => { + foo.decorator("me", ["$scope", ($scope) => { + }]); + }); + } + }, + { + name: "IIFE-jumping with reference support (arrow function)", + input: function(){ + var myCtrl = (function () { + return ($scope) => { + }; + })(); + angular.module("MyMod").controller("MyCtrl", myCtrl); + }, + expected: function(){ + var myCtrl = (function () { + return ($scope) => { + }; + })(); + myCtrl.$inject = ["$scope"]; + angular.module("MyMod").controller("MyCtrl", myCtrl); + } + }, + { + name: "advanced IIFE-jumping (with reference support) (arrow function)", + input: function(){ + var myCtrl10 = (() => { + "use strict"; + // the return statement can appear anywhere on the functions topmost level, + // including before the myCtrl function definition + var myCtrl = ($scope) =>{ + foo; + } + return myCtrl; + post; + })(); + angular.module("MyMod").controller("MyCtrl", myCtrl10); + }, + expected: function(){ + var myCtrl10 = (() => { + "use strict"; + // the return statement can appear anywhere on the functions topmost level, + // including before the myCtrl function definition + var myCtrl = ($scope) => { + foo; + } + myCtrl.$inject = ["$scope"]; + return myCtrl; + post; + })(); + angular.module("MyMod").controller("MyCtrl", myCtrl10); + } + } + ] +}; diff --git a/tests/tests.js b/tests/tests.js index d711891..05751d1 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -9,11 +9,13 @@ const path = require('path'); let suites = [ require('./simple'), + require('./simple-arrow'), require('./provider$get'), require('./inside_module'), require('./ui-router'), require('./modals'), require('./ngInject'), + require('./ngInject-arrow'), require('./issues'), require('./references'), require('./es6.js') From e4782f37c33dc08fdf00662d2ce49dd4700676d0 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 25 Jul 2016 14:28:51 -0400 Subject: [PATCH 11/65] support prologue directives in class constructors closes #3 --- nginject.js | 27 +++++++++++++++------------ tests/es6.js | 24 +++++++++++++++++++++++- 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/nginject.js b/nginject.js index 9c77dc9..74dd3fc 100644 --- a/nginject.js +++ b/nginject.js @@ -42,8 +42,6 @@ function inspectCallExpression(path, ctx) { }); } -const ngAnnotatePrologueDirectives = ["ngInject", "ngNoInject"]; - function inspectFunction(path, ctx) { const node = path.node; @@ -62,17 +60,16 @@ function inspectFunction(path, ctx) { return; } - const str = matchPrologueDirectives(ngAnnotatePrologueDirectives, path); - if (!str) { + const annotate = matchPrologueDirectives(path); + if (annotate === null) { return; } - const block = (str === "ngNoInject"); // now add the correct suspect // for function declarations, it is always the function declaration node itself if (t.isFunctionDeclaration(node)) { - addSuspect(path, ctx, block); + addSuspect(path, ctx, !annotate); return; } @@ -86,7 +83,7 @@ function inspectFunction(path, ctx) { // or /*@ngInject*/ var f1 = function(a) .. // f1.$inject = ["a"]; will be added (or rebuilt/removed) if (t.isVariableDeclarator(path.parent)) { - addSuspect(path.parentPath, ctx, block); + addSuspect(path.parentPath, ctx, !annotate); return; } @@ -104,9 +101,9 @@ function inspectFunction(path, ctx) { // }]); const maybeArrayExpression = path.parent; if (isAnnotatedArray(maybeArrayExpression)) { - addSuspect(path.parentPath, ctx, block); + addSuspect(path.parentPath, ctx, !annotate); } else { - addSuspect(path, ctx, block); + addSuspect(path, ctx, !annotate); } } @@ -189,13 +186,16 @@ function inspectObjectExpression(path, ctx) { // }); } -function matchPrologueDirectives(prologueDirectives, path) { +function matchPrologueDirectives(path) { + const prologueDirectives = ["ngInject", "ngNoInject"]; const directives = path.node.body.directives || []; let matches = directives.map(dir => dir.value.value) .filter(val => prologueDirectives.indexOf(val) !== -1); if(matches.length){ - return matches[0]; + let match = matches[0].trim(); + if(match === "ngInject") return true; + if(match === "ngNoInject") return false; } return null; @@ -255,7 +255,10 @@ function inspectClassMethod(path, ctx){ let annotation = getAnnotation(path.node); if(annotation === null){ - return; + annotation = matchPrologueDirectives(path); + if(annotation === null) { + return; + } } const ancestry = path.getAncestry(); diff --git a/tests/es6.js b/tests/es6.js index 79c5745..2da2258 100644 --- a/tests/es6.js +++ b/tests/es6.js @@ -122,6 +122,28 @@ module.exports = { svc.$inject = ['dep1']; svc.foo = 'bar'; } - } + }, + { + name: "constructor with prologue directive", + input: function(){ + class svc { + constructor(dep1){ + 'ngInject'; + this.dep1 = dep1; + } + } + svc.foo = 'bar'; + }, + expected: function(){ + class svc { + constructor(dep1){ + 'ngInject'; + this.dep1 = dep1; + } + } + svc.$inject = ['dep1']; + svc.foo = 'bar'; + } + } ] }; From 5af55471b272bd3c64a76e5c82f031b4e856f3d9 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 25 Jul 2016 14:30:30 -0400 Subject: [PATCH 12/65] document prologue directive features --- README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/README.md b/README.md index c6f356a..d4d9496 100644 --- a/README.md +++ b/README.md @@ -108,6 +108,19 @@ class svc { } ``` +Prologue directives may also be used here: + +```js +class svc { + constructor(dep1){ + "ngInject"; + this.dep1 = dep1; + } +} +``` + +#### Exports + Exported functions and classes may be annotated. Exported functions must have names: ```js From 762176c4b5eb220fe3c039e15092ec143afaf5cb Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 25 Jul 2016 19:26:07 -0400 Subject: [PATCH 13/65] remove old test sources --- tests/original.js | 1016 ----------------------------------- tests/with_annotations.js | 1061 ------------------------------------- 2 files changed, 2077 deletions(-) delete mode 100644 tests/original.js delete mode 100644 tests/with_annotations.js diff --git a/tests/original.js b/tests/original.js deleted file mode 100644 index e9a3d3e..0000000 --- a/tests/original.js +++ /dev/null @@ -1,1016 +0,0 @@ -"use strict"; - -// long form -angular.module("MyMod").controller("MyCtrl", function($scope, $timeout) { -}); - -// w/ dependencies -angular.module("MyMod", ["OtherMod"]).controller("MyCtrl", function($scope, $timeout) { -}); - -// simple -myMod.controller("foo", function($scope, $timeout) { -}); -myMod.service("foo", function($scope, $timeout) { -}); -myMod.factory("foo", function($scope, $timeout) { -}); -myMod.directive("foo", function($scope, $timeout) { -}); -myMod.filter("foo", function($scope, $timeout) { -}); -myMod.animation("foo", function($scope, $timeout) { -}); -myMod.invoke("foo", function($scope, $timeout) { -}); -myMod.store("foo", function($scope, $timeout) { -}); -myMod.decorator("foo", function($scope, $timeout) { -}); -myMod.component("foo", {controller: function($scope, $timeout) {}}); - -// implicit config function -angular.module("MyMod", function($interpolateProvider) {}); -angular.module("MyMod", ["OtherMod"], function($interpolateProvider) {}); -angular.module("MyMod", ["OtherMod"], function($interpolateProvider) {}).controller("foo", function($scope) {}); - -// object property -var myObj = {}; -myObj.myMod = angular.module("MyMod"); -myObj.myMod.controller("foo", function($scope, $timeout) { a }); - -// no dependencies => no need to wrap the function in an array -myMod.controller("foo", function() { -}); -myMod.service("foo", function() { -}); -myMod.factory("foo", function() { -}); -myMod.directive("foo", function() { -}); -myMod.filter("foo", function() { -}); -myMod.animation("foo", function() { -}); -myMod.invoke("foo", function() { -}); -myMod.store("foo", function() { -}); -myMod.decorator("foo", function() { -}); -myMod.component("foo", {controller: function() {}}); - -// run, config don't take names -myMod.run(function($scope, $timeout) { -}); -angular.module("MyMod").run(function($scope) { -}); -myMod.config(function($scope, $timeout) { -}); -angular.module("MyMod").config(function() { -}); - -// directive return object -myMod.directive("foo", function($scope) { - return { - controller: function($scope, $timeout) { - bar; - } - } -}); -myMod.directive("foo", function($scope) { - return { - controller: function() { - bar; - } - } -}); - -// provider, provider $get -myMod.provider("foo", function($scope) { - this.$get = function($scope, $timeout) { - bar; - }; - self.$get = function($scope) {}; - that.$get = function($scope) {}; - ignore.$get = function($scope) {}; -}); -myMod.provider("foo", function() { - this.$get = function() { - bar; - }; -}); -myMod.provider("foo", function() { - return { - $get: function($scope, $timeout) { - bar; - }}; -}); -myMod.provider("foo", function() { - return { - $get: function() { - bar; - }}; -}); -myMod.provider("foo", { - $get: function($scope, $timeout) { - bar; - } -}); -myMod.provider("foo", { - $get: function() { - bar; - } -}); -myMod.provider("foo", { - "$get": function($scope, $timeout) { - bar; - } -}); -myMod.provider("foo", { - '$get': function($scope, $timeout) { - bar; - } -}); - -C - -myMod.provider("foo", extprov); -function extprov(x) { - this.$get = function(a,b) {}; - this.$get = fooget; - this.$get = inner; - - function inner(c, d) { - } -} - -function fooget(b) { - this.$get = fooget2; -} - -function fooget2(c) { -} - -// chaining -myMod.directive("foo", function($a, $b) { - a; -}).factory("foo", function() { - b; - }).config(function($c) { - c; - }).filter("foo", function($d, $e) { - d; - }).animation("foo", function($f, $g) { - e; - }).component("foo", {controller: function($scope, $timeout) { - i; - }}).invoke("foo", function($f, $g) { - f; - }).decorator("foo", function($f, $g) { - g; - }).store("foo", function($f, $g) { - h; - }); - -angular.module("MyMod").directive("foo", function($a, $b) { - a; -}).provider("foo", function() { - return { - $get: function($scope, $timeout) { - bar; - }}; - }).value("foo", "bar") - .constant("foo", "bar") - .bootstrap(element, [], {}) - .factory("foo", function() { - b; - }).config(function($c) { - c; - }).filter("foo", function($d, $e) { - d; - }).animation("foo", function($f, $g) { - e; - }).component("foo", {controller: function($scope, $timeout) { - i; - }}).invoke("foo", function($h, $i) { - f; - }).decorator("foo", function($h, $i) { - g; - }).store("foo", function($f, $g) { - h; - }); - -// $provide -angular.module("myMod").controller("foo", function() { - $provide.decorator("foo", function($scope) {}); - $provide.service("foo", function($scope) {}); - $provide.factory("foo", function($scope) {}); - //$provide.provider - $provide.provider("foo", function($scope) { - this.$get = function($scope) {}; - return { $get: function($scope, $timeout) {}}; - }); - $provide.provider("foo", { - $get: function($scope, $timeout) {} - }); -}); -// negative $provide -function notInContext() { - $provide.decorator("foo", function($scope) {}); - $provide.service("foo", function($scope) {}); - $provide.factory("foo", function($scope) {}); - $provide.provider("foo", function($scope) { - this.$get = function($scope) {}; - return { $get: function($scope, $timeout) {}}; - }); - $provide.provider("foo", { - $get: function($scope, $timeout) {} - }); -} - -// $controllerProvider -angular.module("myMod").controller("foo", function() { - $controllerProvider.register("foo", function($scope) {}); -}); -function notInContext() { - $controllerProvider.register("foo", function($scope) {}); -} - -// special handling for TypeScript __extends -function outer1() { - a; - __extends(); - b; - function foo($a) { - "ngInject"; - } -} -function outer2() { - a; - __not_extends(); - b; - function foo($a) { - "ngInject"; - } -} - -// all the patterns below matches only when we're inside a detected angular module -angular.module("MyMod").directive("pleasematchthis", function() { - - // $injector.invoke - $injector.invoke(function($compile) { - $compile(myElement)(scope); - }); - - // $httpProvider - $httpProvider.interceptors.push(function($scope) { a }); - $httpProvider.responseInterceptors.push(function($scope) { a }, function(a, b) { b }, function() { c }); - - // $routeProvider - $routeProvider.when("path", { - controller: function($scope) { a } - }).when("path2", { - controller: function($scope) { b }, - resolve: { - zero: function() { a }, - more: function($scope, $timeout) { b }, - something: "else", - }, - dontAlterMe: function(arg) {}, - }); - - // ui-router - $stateProvider.state("myState", { - resolve: { - simpleObj: function() { a }, - promiseObj: function($scope, $timeout) { b }, - translations: "translations", - }, - params: { - simple: function($scope) {}, - inValue: { value: function($scope) {}, notThis: function($scope) {} }, - }, - views: { - viewa: { - controller: function($scope, myParam) {}, - controllerProvider: function($stateParams) {}, - templateProvider: function($scope) {}, - dontAlterMe: function(arg) {}, - resolve: { - myParam: function($stateParams) { - return $stateParams.paramFromDI; - } - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: function($scope) {}, - controller: function($scope) {}, - }, - dontAlterMe: null, - }, - controller: function($scope, simpleObj, promiseObj, translations) { c }, - controllerProvider: function($scope) { g }, - templateProvider: function($scope) { h }, - onEnter: function($scope) { d }, - onExit: function($scope) { e }, - dontAlterMe: function(arg) { f }, - }).state("myState2", { - controller: function($scope) {}, - }).state({ - name: "myState3", - controller: function($scope, simpleObj, promiseObj, translations) { c }, - }); - $urlRouterProvider.when("/", function($match) { a; }); - $urlRouterProvider.otherwise("", function(a) { a; }); - $urlRouterProvider.rule(function(a) { a; }).anything().when("/", function($location) { a; }); - - stateHelperProvider.setNestedState({ - controller: function($scope, simpleObj, promiseObj, translations) { c }, - - children: [ - { - name: "a", - controller: function(a) {}, - resolve: { - f: function($a) {}, - }, - children: [ - { - name: "ab", - controller: function(ab) {}, - resolve: { - f: function($ab) {}, - }, - children: [ - { - name: "abc", - controller: function(abc) {}, - resolve: { - f: function($abc) {}, - }, - }, - ], - }, - ], - }, - { - name: "b", - controller: function(b) {}, - views: { - viewa: { - controller: function($scope, myParam) {}, - controllerProvider: function($stateParams) {}, - templateProvider: function($scope) {}, - dontAlterMe: function(arg) {}, - resolve: { - myParam: function($stateParams) { - return $stateParams.paramFromDI; - } - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: function($scope) {}, - controller: function($scope) {}, - }, - dontAlterMe: null, - }, - }, - ], - }); - stateHelperProvider.setNestedState({ - controller: function($scope, simpleObj, promiseObj, translations) { c }, - }, true); - - // angular ui / ui-bootstrap $modal - $modal.open({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $uibModal.open({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - - // angular material design $mdBottomSheet, $mdDialog, $mdToast - $mdDialog.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $mdBottomSheet.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $mdToast.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); -}); - -// none of the patterns below matches because they are not in an angular module context -// this should be a straight copy of the code above, with identical copies in -// with_annotations.js -foobar.irrespective("dontmatchthis", function() { - - // $injector.invoke - $injector.invoke(function($compile) { - $compile(myElement)(scope); - }); - - // $httpProvider - $httpProvider.interceptors.push(function($scope) { a }); - $httpProvider.responseInterceptors.push(function($scope) { a }, function(a, b) { b }, function() { c }); - - // $routeProvider - $routeProvider.when("path", { - controller: function($scope) { a } - }).when("path2", { - controller: function($scope) { b }, - resolve: { - zero: function() { a }, - more: function($scope, $timeout) { b }, - something: "else", - }, - dontAlterMe: function(arg) {}, - }); - - // ui-router - $stateProvider.state("myState", { - resolve: { - simpleObj: function() { a }, - promiseObj: function($scope, $timeout) { b }, - translations: "translations", - }, - views: { - viewa: { - controller: function($scope, myParam) {}, - controllerProvider: function($stateParams) {}, - templateProvider: function($scope) {}, - dontAlterMe: function(arg) {}, - resolve: { - myParam: function($stateParams) { - return $stateParams.paramFromDI; - } - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: function($scope) {}, - controller: function($scope) {}, - }, - dontAlterMe: null, - }, - controller: function($scope, simpleObj, promiseObj, translations) { c }, - controllerProvider: function($scope) { g }, - templateProvider: function($scope) { h }, - onEnter: function($scope) { d }, - onExit: function($scope) { e }, - dontAlterMe: function(arg) { f }, - }).state("myState2", { - controller: function($scope) {}, - }).state({ - name: "myState3", - controller: function($scope, simpleObj, promiseObj, translations) { c }, - }); - $urlRouterProvider.when("/", function($match) { a; }); - $urlRouterProvider.otherwise("", function(a) { a; }); - $urlRouterProvider.rule(function(a) { a; }).anything().when("/", function($location) { a; }); - - stateHelperProvider.setNestedState({ - controller: function($scope, simpleObj, promiseObj, translations) { c }, - - children: [ - { - name: "a", - controller: function(a) {}, - resolve: { - f: function($a) {}, - }, - children: [ - { - name: "ab", - controller: function(ab) {}, - resolve: { - f: function($ab) {}, - }, - children: [ - { - name: "abc", - controller: function(abc) {}, - resolve: { - f: function($abc) {}, - }, - }, - ], - }, - ], - }, - { - name: "b", - controller: function(b) {}, - views: { - viewa: { - controller: function($scope, myParam) {}, - controllerProvider: function($stateParams) {}, - templateProvider: function($scope) {}, - dontAlterMe: function(arg) {}, - resolve: { - myParam: function($stateParams) { - return $stateParams.paramFromDI; - } - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: function($scope) {}, - controller: function($scope) {}, - }, - dontAlterMe: null, - }, - }, - ], - }); - stateHelperProvider.setNestedState({ - controller: function($scope, simpleObj, promiseObj, translations) { c }, - }, true); - - // angular ui / ui-bootstrap $modal - $modal.open({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $uibModal.open({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - - // angular material design $mdBottomSheet, $mdDialog, $mdToast - $mdDialog.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $mdBottomSheet.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $mdToast.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); -}); - -// explicit annotations -var x = /* @ngInject */ function($scope) { -}; - -var obj = {}; -obj.bar = /*@ngInject*/ function($scope) {}; - -obj = { - controller: /*@ngInject*/ function($scope) {}, -}; - -obj = /*@ngInject*/ { - foo: function(a) {}, - bar: function(b, c) {}, - val: 42, - inner: { - circle: function(d) {}, - alalalala: "long", - }, - nest: { many: {levels: function(x) {}}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}; - -obj = { - /*@ngInject*/ - foo: function(a) {}, - bar: function(b, c) {}, -}; - -/*@ngInject*/ -obj = { - foo: function(a) {}, - bar: function(b, c) {}, - val: 42, - inner: { - circle: function(d) {}, - alalalala: "long", - }, - nest: { many: {levels: function(x) {}}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}; - -/*@ngInject*/ -var obj = { - foo: function(a) {}, - bar: function(b, c) {}, - val: 42, - inner: { - circle: function(d) {}, - alalalala: "long", - }, - nest: { many: {levels: function(x) {}}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}; - -// @ngInject -function foo($scope) { -} - -// @ngInject -// otherstuff -function Foo($scope) { -} - -// @ngInject -// has trailing semicolon -var foo1 = function($scope) { -}; - -// @ngInject -// lacks trailing semicolon -var foo2 = function($scope) { -} - -// @ngInject -// has trailing semicolon -bar.foo1 = function($scope) { -}; - -// @ngInject -// lacks trailing semicolon -bar.foo2 = function($scope) { -} - -// let's zip-zag indentation to make sure that the $inject array lines up properly - // @ngInject - function foo3($scope) {} - // @ngInject - function foo4($scope) { - } -/* @ngInject */ function foo5($scope) {} - /* @ngInject */ function foo6($scope) { - } - - // @ngInject - var foo7 = function($scope) { - }; - // @ngInject - var foo8 = function($scope) {}; -// @ngInject -var foo9 = function($scope) { -} - // @ngInject - var foo10 = function($scope) {} - - /* @ngInject */ var foo11 = function($scope) { - }; - /* @ngInject */var foo12 = function($scope) {}; -/* @ngInject */var foo13 = function($scope) { -} - /* @ngInject */var foo14 = function($scope) {} - - -// adding an explicit annotation where it isn't needed should work fine -myMod.controller("foo", /*@ngInject*/ function($scope, $timeout) { -}); - - -// troublesome return forces different placement of $inject array -function outer() { - foo; - return { - controller: MyCtrl, - }; - - // @ngInject - function MyCtrl(a) { - } -} - - -// explicit annotations using ngInject() instead of /*@ngInject*/ -var x = ngInject(function($scope) {}); - -obj = ngInject({ - foo: function(a) {}, - bar: function(b, c) {}, - val: 42, - inner: { - circle: function(d) {}, - alalalala: "long", - }, - nest: { many: {levels: function(x) {}}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}); - - -// explicit annotations using "ngInject" Directive Prologue -function Foo2($scope) { - "ngInject"; -} - -var foos3 = function($scope) { - // comments are ok before the Directive Prologues - // and there may be multiple Prologues - "use strict"; "ngInject"; -}; - -var dual1 = function(a) { "ngInject" }, dual2 = function(b) { "ngInject" }; - -g(function(c) { - "ngInject" -}); - -// Traceur class output example -// class C { -// constructor($scope) { -// "ngInject" -// } -// } -$traceurRuntime.ModuleStore.getAnonymousModule(function() { - "use strict"; - var C = function C($scope) { - "ngInject"; - }; - ($traceurRuntime.createClass)(C, {}, {}); - return {}; -}); - - -// suppress false positives with /*@ngNoInject*/, ngNoInject() and "ngNoInject" -myMod.controller("suppressed", /*@ngNoInject*/function($scope) { -}); -myMod.controller("suppressed", ngNoInject(function($scope) { -})); -myMod.controller("suppressed", function($scope) { - "ngNoInject"; -}); - -// works the same as ngInject i.e. reference-following, IIFE-jumping and so on -/*@ngNoInject*/ -myMod.controller("suppressed", SupFoo1); -myMod.controller("suppressed", SupFoo2); -myMod.controller("suppressed", SupFoo3); -function SupFoo1($scope) { - "ngNoInject"; -} -/*@ngNoInject*/ -function SupFoo2($scope) { -} -var SupFoo3 = ngNoInject(function($scope) { - "ngNoInject"; -}); - - -// regression-test for https://github.com/olov/ng-annotate/issues/221 -var FooBar = (function (_super) { - __extends(FooBar, _super); - /*@ngInject*/ - function FooBar($a, $b) { - _super.call(this); - } - /*@ngInject*/ - FooBar.onEnter = function (callback) { - x; - }; - return FooBar; -})(Bar); -var FooBar2 = (function (_super) { - __extends(FooBar, _super); - function FooBar($a, $b) { - "ngInject"; - _super.call(this); - } - FooBar.onEnter = function (callback) { - "ngInject"; - x; - }; - return FooBar; -})(Bar); - -// snippets that shouldn't fool ng-annotate into generating false positives, -// whether we're inside an angular module or not -myMod.controller("donttouchme", function() { - // lo-dash regression that happened in the brief time frame when - // notes (instad of "notes") would match. see issue #22 - var notesForCurrentPage = _.filter(notes, function (note) { - return note.page.uid === page.uid; - }); -}); - -// not a module declaration short-form, see https://github.com/olov/ng-annotate/issues/82 -$stateProvider.decorator('parent', function (state, parentFn) { - doStuff(); -}); - -// $get is only valid inside provider -myMod.service("donttouch", function() { - this.$get = function(me) { - }; -}); -myMod.service("donttouch", mefn); -function mefn() { - this.$get = function(me) { - }; -} - -// directive return object is only valid inside directive -myMod.service("donttouch", function() { - return { - controller: function($scope, $timeout) { - bar; - } - } -}); - -myMod.directive("donttouch", function() { - foo.decorator("me", function($scope) { - }); -}); - -// IIFE-jumping (primarily for compile-to-JS langs) -angular.module("MyMod").directive("foo", function($a, $b) { - $uibModal.open({ - resolve: { - collection: (function(_this) { - return function($c) { - }; - })(this), - }, - }); -}); - -var x = /*@ngInject*/ (function() { - return function($a) { - }; -})(); - - -// IIFE-jumping with reference support -var myCtrl = (function () { - return function($scope) { - }; -})(); -angular.module("MyMod").controller("MyCtrl", myCtrl); - - -// advanced IIFE-jumping (with reference support) -var myCtrl10 = (function() { - "use strict"; - // the return statement can appear anywhere on the functions topmost level, - // including before the myCtrl function definition - return myCtrl; - function myCtrl($scope) { - foo; - } - post; -})(); -angular.module("MyMod").controller("MyCtrl", myCtrl10); - -var myCtrl11 = (function() { - pre; - var myCtrl = function($scope) { - foo; - }; - mid; - // the return statement can appear anywhere on the functions topmost level, - // including before the myCtrl function definition - return myCtrl; - post; -})(); -angular.module("MyMod").controller("MyCtrl", myCtrl11); - - -// reference support -function MyCtrl1(a, b) { -} -if (true) { - // proper scope analysis including shadowing - let MyCtrl1 = function(c) { - }; - angular.module("MyMod").directive("foo", MyCtrl1); -} -angular.module("MyMod").controller("bar", MyCtrl1); -function MyCtrl2(z) { -} -funcall(/*@ngInject*/ MyCtrl2); // explicit annotation on reference flows back to definition - -angular.module("MyMod").directive("foo", MyDirective); - -function MyDirective($stateProvider) { - $stateProvider.state('astate', { - resolve: { - yoyo: function(ma) { - }, - } - }); -} - -/* @ngInject */ -function MyDirective2($stateProvider) { - $stateProvider.state('astate', { - resolve: { - yoyo: function(ma) { - }, - } - }); -} - -// issue 84 -(function() { - var MyCtrl = function($someDependency) {}; - angular.module('myApp').controller("MyCtrl", MyCtrl); - MyCtrl.prototype.someFunction = function() {}; -})(); - -// empty var declarator -var MyCtrl12; -angular.module("MyMod").controller('MyCtrl', MyCtrl12); - -// issue 115 -module.exports = function() { - "use strict"; - return { - restrict: 'E', - replace: true, - scope: { }, - controller: /*@ngInject*/function($scope, myService) { - }, - templateUrl: "mytemplate" - }; -}; - -// issue #135 -var MyCtrl = (function() { - /*@ngInject*/ - function MyCtrl(a) { - } - - return MyCtrl; -})(); - -myMod.service("a", MyCtrl); diff --git a/tests/with_annotations.js b/tests/with_annotations.js deleted file mode 100644 index 29c3681..0000000 --- a/tests/with_annotations.js +++ /dev/null @@ -1,1061 +0,0 @@ -"use strict"; - -// long form -foo.$inject = ["$scope"]; -Foo.$inject = ["$scope"]; - foo3.$inject = ["$scope"]; - foo4.$inject = ["$scope"]; -foo5.$inject = ["$scope"]; - foo6.$inject = ["$scope"]; -MyCtrl2.$inject = ["z"]; -MyDirective2.$inject = ["$stateProvider"]; -extprov.$inject = ["x"]; -fooget.$inject = ["b"]; -fooget2.$inject = ["c"]; -Foo2.$inject = ["$scope"]; -MyCtrl1.$inject = ["a", "b"]; -MyDirective.$inject = ["$stateProvider"]; -angular.module("MyMod").controller("MyCtrl", ["$scope", "$timeout", function($scope, $timeout) { -}]); - -// w/ dependencies -angular.module("MyMod", ["OtherMod"]).controller("MyCtrl", ["$scope", "$timeout", function($scope, $timeout) { -}]); - -// simple -myMod.controller("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.service("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.factory("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.directive("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.filter("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.animation("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.invoke("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.store("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.decorator("foo", ["$scope", "$timeout", function($scope, $timeout) { -}]); -myMod.component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) {}]}); - -// implicit config function -angular.module("MyMod", ["$interpolateProvider", function($interpolateProvider) {}]); -angular.module("MyMod", ["OtherMod"], ["$interpolateProvider", function($interpolateProvider) {}]); -angular.module("MyMod", ["OtherMod"], ["$interpolateProvider", function($interpolateProvider) {}]).controller("foo", ["$scope", function($scope) {}]); - -// object property -var myObj = {}; -myObj.myMod = angular.module("MyMod"); -myObj.myMod.controller("foo", ["$scope", "$timeout", function($scope, $timeout) { a }]); - -// no dependencies => no need to wrap the function in an array -myMod.controller("foo", function() { -}); -myMod.service("foo", function() { -}); -myMod.factory("foo", function() { -}); -myMod.directive("foo", function() { -}); -myMod.filter("foo", function() { -}); -myMod.animation("foo", function() { -}); -myMod.invoke("foo", function() { -}); -myMod.store("foo", function() { -}); -myMod.decorator("foo", function() { -}); -myMod.component("foo", {controller: function() {}}); - -// run, config don't take names -myMod.run(["$scope", "$timeout", function($scope, $timeout) { -}]); -angular.module("MyMod").run(["$scope", function($scope) { -}]); -myMod.config(["$scope", "$timeout", function($scope, $timeout) { -}]); -angular.module("MyMod").config(function() { -}); - -// directive return object -myMod.directive("foo", ["$scope", function($scope) { - return { - controller: ["$scope", "$timeout", function($scope, $timeout) { - bar; - }] - } -}]); -myMod.directive("foo", ["$scope", function($scope) { - return { - controller: function() { - bar; - } - } -}]); - -// provider, provider $get -myMod.provider("foo", ["$scope", function($scope) { - this.$get = ["$scope", "$timeout", function($scope, $timeout) { - bar; - }]; - self.$get = ["$scope", function($scope) {}]; - that.$get = ["$scope", function($scope) {}]; - ignore.$get = function($scope) {}; -}]); -myMod.provider("foo", function() { - this.$get = function() { - bar; - }; -}); -myMod.provider("foo", function() { - return { - $get: ["$scope", "$timeout", function($scope, $timeout) { - bar; - }]}; -}); -myMod.provider("foo", function() { - return { - $get: function() { - bar; - }}; -}); -myMod.provider("foo", { - $get: ["$scope", "$timeout", function($scope, $timeout) { - bar; - }] -}); -myMod.provider("foo", { - $get: function() { - bar; - } -}); -myMod.provider("foo", { - "$get": ["$scope", "$timeout", function($scope, $timeout) { - bar; - }] -}); -myMod.provider("foo", { - '$get': ["$scope", "$timeout", function($scope, $timeout) { - bar; - }] -}); - -myMod.provider("foo", ["x", function(x) { - this.$get = ["a", "b", function(a,b) {}]; -}]); - -myMod.provider("foo", extprov); -function extprov(x) { - inner.$inject = ["c", "d"]; - this.$get = ["a", "b", function(a,b) {}]; - this.$get = fooget; - this.$get = inner; - - function inner(c, d) { - } -} - -function fooget(b) { - this.$get = fooget2; -} - -function fooget2(c) { -} - -// chaining -myMod.directive("foo", ["$a", "$b", function($a, $b) { - a; -}]).factory("foo", function() { - b; - }).config(["$c", function($c) { - c; - }]).filter("foo", ["$d", "$e", function($d, $e) { - d; - }]).animation("foo", ["$f", "$g", function($f, $g) { - e; - }]).component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) { - i; - }]}).invoke("foo", ["$f", "$g", function($f, $g) { - f; - }]).decorator("foo", ["$f", "$g", function($f, $g) { - g; - }]).store("foo", ["$f", "$g", function($f, $g) { - h; - }]); - -angular.module("MyMod").directive("foo", ["$a", "$b", function($a, $b) { - a; -}]).provider("foo", function() { - return { - $get: ["$scope", "$timeout", function($scope, $timeout) { - bar; - }]}; - }).value("foo", "bar") - .constant("foo", "bar") - .bootstrap(element, [], {}) - .factory("foo", function() { - b; - }).config(["$c", function($c) { - c; - }]).filter("foo", ["$d", "$e", function($d, $e) { - d; - }]).animation("foo", ["$f", "$g", function($f, $g) { - e; - }]).component("foo", {controller: ["$scope", "$timeout", function($scope, $timeout) { - i; - }]}).invoke("foo", ["$h", "$i", function($h, $i) { - f; - }]).decorator("foo", ["$h", "$i", function($h, $i) { - g; - }]).store("foo", ["$f", "$g", function($f, $g) { - h; - }]); - -// $provide -angular.module("myMod").controller("foo", function() { - $provide.decorator("foo", ["$scope", function($scope) {}]); - $provide.service("foo", ["$scope", function($scope) {}]); - $provide.factory("foo", ["$scope", function($scope) {}]); - //$provide.provider - $provide.provider("foo", ["$scope", function($scope) { - this.$get = ["$scope", function($scope) {}]; - return { $get: ["$scope", "$timeout", function($scope, $timeout) {}]}; - }]); - $provide.provider("foo", { - $get: ["$scope", "$timeout", function($scope, $timeout) {}] - }); -}); -// negative $provide -function notInContext() { - $provide.decorator("foo", function($scope) {}); - $provide.service("foo", function($scope) {}); - $provide.factory("foo", function($scope) {}); - $provide.provider("foo", function($scope) { - this.$get = function($scope) {}; - return { $get: function($scope, $timeout) {}}; - }); - $provide.provider("foo", { - $get: function($scope, $timeout) {} - }); -} - -// $controllerProvider -angular.module("myMod").controller("foo", function() { - $controllerProvider.register("foo", ["$scope", function($scope) {}]); -}); -function notInContext() { - $controllerProvider.register("foo", function($scope) {}); -} - -// special handling for TypeScript __extends -function outer1() { - a; - __extends(); - foo.$inject = ["$a"]; - b; - function foo($a) { - "ngInject"; - } -} -function outer2() { - foo.$inject = ["$a"]; - a; - __not_extends(); - b; - function foo($a) { - "ngInject"; - } -} - -// all the patterns below matches only when we're inside a detected angular module -angular.module("MyMod").directive("pleasematchthis", function() { - - // $injector.invoke - $injector.invoke(["$compile", function($compile) { - $compile(myElement)(scope); - }]); - - // $httpProvider - $httpProvider.interceptors.push(["$scope", function($scope) { a }]); - $httpProvider.responseInterceptors.push(["$scope", function($scope) { a }], ["a", "b", function(a, b) { b }], function() { c }); - - // $routeProvider - $routeProvider.when("path", { - controller: ["$scope", function($scope) { a }] - }).when("path2", { - controller: ["$scope", function($scope) { b }], - resolve: { - zero: function() { a }, - more: ["$scope", "$timeout", function($scope, $timeout) { b }], - something: "else", - }, - dontAlterMe: function(arg) {}, - }); - - // ui-router - $stateProvider.state("myState", { - resolve: { - simpleObj: function() { a }, - promiseObj: ["$scope", "$timeout", function($scope, $timeout) { b }], - translations: "translations", - }, - params: { - simple: ["$scope", function($scope) {}], - inValue: { value: ["$scope", function($scope) {}], notThis: function($scope) {} }, - }, - views: { - viewa: { - controller: ["$scope", "myParam", function($scope, myParam) {}], - controllerProvider: ["$stateParams", function($stateParams) {}], - templateProvider: ["$scope", function($scope) {}], - dontAlterMe: function(arg) {}, - resolve: { - myParam: ["$stateParams", function($stateParams) { - return $stateParams.paramFromDI; - }] - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: ["$scope", function($scope) {}], - controller: ["$scope", function($scope) {}], - }, - dontAlterMe: null, - }, - controller: ["$scope", "simpleObj", "promiseObj", "translations", function($scope, simpleObj, promiseObj, translations) { c }], - controllerProvider: ["$scope", function($scope) { g }], - templateProvider: ["$scope", function($scope) { h }], - onEnter: ["$scope", function($scope) { d }], - onExit: ["$scope", function($scope) { e }], - dontAlterMe: function(arg) { f }, - }).state("myState2", { - controller: ["$scope", function($scope) {}], - }).state({ - name: "myState3", - controller: ["$scope", "simpleObj", "promiseObj", "translations", function($scope, simpleObj, promiseObj, translations) { c }], - }); - $urlRouterProvider.when("/", ["$match", function($match) { a; }]); - $urlRouterProvider.otherwise("", function(a) { a; }); - $urlRouterProvider.rule(function(a) { a; }).anything().when("/", ["$location", function($location) { a; }]); - - stateHelperProvider.setNestedState({ - controller: ["$scope", "simpleObj", "promiseObj", "translations", function($scope, simpleObj, promiseObj, translations) { c }], - - children: [ - { - name: "a", - controller: ["a", function(a) {}], - resolve: { - f: ["$a", function($a) {}], - }, - children: [ - { - name: "ab", - controller: ["ab", function(ab) {}], - resolve: { - f: ["$ab", function($ab) {}], - }, - children: [ - { - name: "abc", - controller: ["abc", function(abc) {}], - resolve: { - f: ["$abc", function($abc) {}], - }, - }, - ], - }, - ], - }, - { - name: "b", - controller: ["b", function(b) {}], - views: { - viewa: { - controller: ["$scope", "myParam", function($scope, myParam) {}], - controllerProvider: ["$stateParams", function($stateParams) {}], - templateProvider: ["$scope", function($scope) {}], - dontAlterMe: function(arg) {}, - resolve: { - myParam: ["$stateParams", function($stateParams) { - return $stateParams.paramFromDI; - }] - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: ["$scope", function($scope) {}], - controller: ["$scope", function($scope) {}], - }, - dontAlterMe: null, - }, - }, - ], - }); - stateHelperProvider.setNestedState({ - controller: ["$scope", "simpleObj", "promiseObj", "translations", function($scope, simpleObj, promiseObj, translations) { c }], - }, true); - - // angular ui / ui-bootstrap $modal - $modal.open({ - templateUrl: "str", - controller: ["$scope", function($scope) {}], - resolve: { - items: ["MyService", function(MyService) {}], - data: ["a", "b", function(a, b) {}], - its: 42, - }, - donttouch: function(me) {}, - }); - $uibModal.open({ - templateUrl: "str", - controller: ["$scope", function($scope) {}], - resolve: { - items: ["MyService", function(MyService) {}], - data: ["a", "b", function(a, b) {}], - its: 42, - }, - donttouch: function(me) {}, - }); - - // angular material design $mdBottomSheet, $mdDialog, $mdToast - $mdDialog.show({ - templateUrl: "str", - controller: ["$scope", function($scope) {}], - resolve: { - items: ["MyService", function(MyService) {}], - data: ["a", "b", function(a, b) {}], - its: 42, - }, - donttouch: function(me) {}, - }); - $mdBottomSheet.show({ - templateUrl: "str", - controller: ["$scope", function($scope) {}], - resolve: { - items: ["MyService", function(MyService) {}], - data: ["a", "b", function(a, b) {}], - its: 42, - }, - donttouch: function(me) {}, - }); - $mdToast.show({ - templateUrl: "str", - controller: ["$scope", function($scope) {}], - resolve: { - items: ["MyService", function(MyService) {}], - data: ["a", "b", function(a, b) {}], - its: 42, - }, - donttouch: function(me) {}, - }); -}); - -// none of the patterns below matches because they are not in an angular module context -// this should be a straight copy of the code above, with identical copies in -// with_annotations.js -foobar.irrespective("dontmatchthis", function() { - - // $injector.invoke - $injector.invoke(function($compile) { - $compile(myElement)(scope); - }); - - // $httpProvider - $httpProvider.interceptors.push(function($scope) { a }); - $httpProvider.responseInterceptors.push(function($scope) { a }, function(a, b) { b }, function() { c }); - - // $routeProvider - $routeProvider.when("path", { - controller: function($scope) { a } - }).when("path2", { - controller: function($scope) { b }, - resolve: { - zero: function() { a }, - more: function($scope, $timeout) { b }, - something: "else", - }, - dontAlterMe: function(arg) {}, - }); - - // ui-router - $stateProvider.state("myState", { - resolve: { - simpleObj: function() { a }, - promiseObj: function($scope, $timeout) { b }, - translations: "translations", - }, - views: { - viewa: { - controller: function($scope, myParam) {}, - controllerProvider: function($stateParams) {}, - templateProvider: function($scope) {}, - dontAlterMe: function(arg) {}, - resolve: { - myParam: function($stateParams) { - return $stateParams.paramFromDI; - } - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: function($scope) {}, - controller: function($scope) {}, - }, - dontAlterMe: null, - }, - controller: function($scope, simpleObj, promiseObj, translations) { c }, - controllerProvider: function($scope) { g }, - templateProvider: function($scope) { h }, - onEnter: function($scope) { d }, - onExit: function($scope) { e }, - dontAlterMe: function(arg) { f }, - }).state("myState2", { - controller: function($scope) {}, - }).state({ - name: "myState3", - controller: function($scope, simpleObj, promiseObj, translations) { c }, - }); - $urlRouterProvider.when("/", function($match) { a; }); - $urlRouterProvider.otherwise("", function(a) { a; }); - $urlRouterProvider.rule(function(a) { a; }).anything().when("/", function($location) { a; }); - - stateHelperProvider.setNestedState({ - controller: function($scope, simpleObj, promiseObj, translations) { c }, - - children: [ - { - name: "a", - controller: function(a) {}, - resolve: { - f: function($a) {}, - }, - children: [ - { - name: "ab", - controller: function(ab) {}, - resolve: { - f: function($ab) {}, - }, - children: [ - { - name: "abc", - controller: function(abc) {}, - resolve: { - f: function($abc) {}, - }, - }, - ], - }, - ], - }, - { - name: "b", - controller: function(b) {}, - views: { - viewa: { - controller: function($scope, myParam) {}, - controllerProvider: function($stateParams) {}, - templateProvider: function($scope) {}, - dontAlterMe: function(arg) {}, - resolve: { - myParam: function($stateParams) { - return $stateParams.paramFromDI; - } - }, - }, - viewb: { - dontAlterMe: function(arg) {}, - templateProvider: function($scope) {}, - controller: function($scope) {}, - }, - dontAlterMe: null, - }, - }, - ], - }); - stateHelperProvider.setNestedState({ - controller: function($scope, simpleObj, promiseObj, translations) { c }, - }, true); - - // angular ui / ui-bootstrap $modal - $modal.open({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $uibModal.open({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - - // angular material design $mdBottomSheet, $mdDialog, $mdToast - $mdDialog.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $mdBottomSheet.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); - $mdToast.show({ - templateUrl: "str", - controller: function($scope) {}, - resolve: { - items: function(MyService) {}, - data: function(a, b) {}, - its: 42, - }, - donttouch: function(me) {}, - }); -}); - -// explicit annotations -var x = /* @ngInject */ ["$scope", function($scope) { -}]; - -var obj = {}; -obj.bar = /*@ngInject*/ ["$scope", function($scope) {}]; - -obj = { - controller: /*@ngInject*/ ["$scope", function($scope) {}], -}; - -obj = /*@ngInject*/ { - foo: ["a", function(a) {}], - bar: ["b", "c", function(b, c) {}], - val: 42, - inner: { - circle: ["d", function(d) {}], - alalalala: "long", - }, - nest: { many: {levels: ["x", function(x) {}]}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}; - -obj = { - /*@ngInject*/ - foo: ["a", function(a) {}], - bar: function(b, c) {}, -}; - -/*@ngInject*/ -obj = { - foo: ["a", function(a) {}], - bar: ["b", "c", function(b, c) {}], - val: 42, - inner: { - circle: ["d", function(d) {}], - alalalala: "long", - }, - nest: { many: {levels: ["x", function(x) {}]}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}; - -/*@ngInject*/ -var obj = { - foo: ["a", function(a) {}], - bar: ["b", "c", function(b, c) {}], - val: 42, - inner: { - circle: ["d", function(d) {}], - alalalala: "long", - }, - nest: { many: {levels: ["x", function(x) {}]}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}; - -// @ngInject -function foo($scope) { -} - -// @ngInject -// otherstuff -function Foo($scope) { -} - -// @ngInject -// has trailing semicolon -var foo1 = function($scope) { -}; -foo1.$inject = ["$scope"]; - -// @ngInject -// lacks trailing semicolon -var foo2 = function($scope) { -} -foo2.$inject = ["$scope"]; - -// @ngInject -// has trailing semicolon -bar.foo1 = function($scope) { -}; -bar.foo1.$inject = ["$scope"]; - -// @ngInject -// lacks trailing semicolon -bar.foo2 = function($scope) { -} -bar.foo2.$inject = ["$scope"]; - -// let's zip-zag indentation to make sure that the $inject array lines up properly - // @ngInject - function foo3($scope) {} - // @ngInject - function foo4($scope) { - } -/* @ngInject */ function foo5($scope) {} - /* @ngInject */ function foo6($scope) { - } - - // @ngInject - var foo7 = function($scope) { - }; - foo7.$inject = ["$scope"]; - // @ngInject - var foo8 = function($scope) {}; - foo8.$inject = ["$scope"]; -// @ngInject -var foo9 = function($scope) { -} -foo9.$inject = ["$scope"]; - // @ngInject - var foo10 = function($scope) {} - foo10.$inject = ["$scope"]; - - /* @ngInject */ var foo11 = function($scope) { - }; - foo11.$inject = ["$scope"]; - /* @ngInject */var foo12 = function($scope) {}; - foo12.$inject = ["$scope"]; -/* @ngInject */var foo13 = function($scope) { -} -foo13.$inject = ["$scope"]; - /* @ngInject */var foo14 = function($scope) {} - foo14.$inject = ["$scope"]; - - -// adding an explicit annotation where it isn't needed should work fine -myMod.controller("foo", /*@ngInject*/ ["$scope", "$timeout", function($scope, $timeout) { -}]); - - -// troublesome return forces different placement of $inject array -function outer() { - MyCtrl.$inject = ["a"]; - foo; - return { - controller: MyCtrl, - }; - - // @ngInject - function MyCtrl(a) { - } -} - - -// explicit annotations using ngInject() instead of /*@ngInject*/ -var x = ngInject(["$scope", function($scope) {}]); - -obj = ngInject({ - foo: ["a", function(a) {}], - bar: ["b", "c", function(b, c) {}], - val: 42, - inner: { - circle: ["d", function(d) {}], - alalalala: "long", - }, - nest: { many: {levels: ["x", function(x) {}]}}, - but: { onlythrough: ["object literals", {donttouch: function(me) {}}]}, -}); - - -// explicit annotations using "ngInject" Directive Prologue -function Foo2($scope) { - "ngInject"; -} - -var foos3 = function($scope) { - // comments are ok before the Directive Prologues - // and there may be multiple Prologues - "use strict"; "ngInject"; -}; -foos3.$inject = ["$scope"]; - -var dual1 = function(a) { "ngInject" }, dual2 = function(b) { "ngInject" }; -dual1.$inject = ["a"]; -dual2.$inject = ["b"]; - -g(["c", function(c) { - "ngInject" -}]); - -// Traceur class output example -// class C { -// constructor($scope) { -// "ngInject" -// } -// } -$traceurRuntime.ModuleStore.getAnonymousModule(function() { - "use strict"; - var C = function C($scope) { - "ngInject"; - }; - C.$inject = ["$scope"]; - ($traceurRuntime.createClass)(C, {}, {}); - return {}; -}); - - -// suppress false positives with /*@ngNoInject*/, ngNoInject() and "ngNoInject" -myMod.controller("suppressed", /*@ngNoInject*/function($scope) { -}); -myMod.controller("suppressed", ngNoInject(function($scope) { -})); -myMod.controller("suppressed", function($scope) { - "ngNoInject"; -}); - -// works the same as ngInject i.e. reference-following, IIFE-jumping and so on -/*@ngNoInject*/ -myMod.controller("suppressed", SupFoo1); -myMod.controller("suppressed", SupFoo2); -myMod.controller("suppressed", SupFoo3); -function SupFoo1($scope) { - "ngNoInject"; -} -/*@ngNoInject*/ -function SupFoo2($scope) { -} -var SupFoo3 = ngNoInject(function($scope) { - "ngNoInject"; -}); - - -// regression-test for https://github.com/olov/ng-annotate/issues/221 -var FooBar = (function (_super) { - __extends(FooBar, _super); - /*@ngInject*/ - FooBar.$inject = ["$a", "$b"]; - function FooBar($a, $b) { - _super.call(this); - } - /*@ngInject*/ - FooBar.onEnter = function (callback) { - x; - }; - FooBar.onEnter.$inject = ["callback"]; - return FooBar; -})(Bar); -var FooBar2 = (function (_super) { - __extends(FooBar, _super); - FooBar.$inject = ["$a", "$b"]; - function FooBar($a, $b) { - "ngInject"; - _super.call(this); - } - FooBar.onEnter = ["callback", function (callback) { - "ngInject"; - x; - }]; - return FooBar; -})(Bar); - -// snippets that shouldn't fool ng-annotate into generating false positives, -// whether we're inside an angular module or not -myMod.controller("donttouchme", function() { - // lo-dash regression that happened in the brief time frame when - // notes (instad of "notes") would match. see issue #22 - var notesForCurrentPage = _.filter(notes, function (note) { - return note.page.uid === page.uid; - }); -}); - -// not a module declaration short-form, see https://github.com/olov/ng-annotate/issues/82 -$stateProvider.decorator('parent', function (state, parentFn) { - doStuff(); -}); - -// $get is only valid inside provider -myMod.service("donttouch", function() { - this.$get = function(me) { - }; -}); -myMod.service("donttouch", mefn); -function mefn() { - this.$get = function(me) { - }; -} - -// directive return object is only valid inside directive -myMod.service("donttouch", function() { - return { - controller: function($scope, $timeout) { - bar; - } - } -}); - -myMod.directive("donttouch", function() { - foo.decorator("me", ["$scope", function($scope) { - }]); -}); - -// IIFE-jumping (primarily for compile-to-JS langs) -angular.module("MyMod").directive("foo", ["$a", "$b", function($a, $b) { - $uibModal.open({ - resolve: { - collection: (function(_this) { - return ["$c", function($c) { - }]; - })(this), - }, - }); -}]); - -var x = /*@ngInject*/ (function() { - return ["$a", function($a) { - }]; -})(); - - -// IIFE-jumping with reference support -var myCtrl = (function () { - return function($scope) { - }; -})(); -myCtrl.$inject = ["$scope"]; -angular.module("MyMod").controller("MyCtrl", myCtrl); - - -// advanced IIFE-jumping (with reference support) -var myCtrl10 = (function() { - "use strict"; - // the return statement can appear anywhere on the functions topmost level, - // including before the myCtrl function definition - myCtrl.$inject = ["$scope"]; - return myCtrl; - function myCtrl($scope) { - foo; - } - post; -})(); -angular.module("MyMod").controller("MyCtrl", myCtrl10); - -var myCtrl11 = (function() { - pre; - var myCtrl = function($scope) { - foo; - }; - myCtrl.$inject = ["$scope"]; - mid; - // the return statement can appear anywhere on the functions topmost level, - // including before the myCtrl function definition - return myCtrl; - post; -})(); -angular.module("MyMod").controller("MyCtrl", myCtrl11); - - -// reference support -function MyCtrl1(a, b) { -} -if (true) { - // proper scope analysis including shadowing - let MyCtrl1 = function(c) { - }; - MyCtrl1.$inject = ["c"]; - angular.module("MyMod").directive("foo", MyCtrl1); -} -angular.module("MyMod").controller("bar", MyCtrl1); -function MyCtrl2(z) { -} -funcall(/*@ngInject*/ MyCtrl2); // explicit annotation on reference flows back to definition - -angular.module("MyMod").directive("foo", MyDirective); - -function MyDirective($stateProvider) { - $stateProvider.state('astate', { - resolve: { - yoyo: ["ma", function(ma) { - }], - } - }); -} - -/* @ngInject */ -function MyDirective2($stateProvider) { - $stateProvider.state('astate', { - resolve: { - yoyo: ["ma", function(ma) { - }], - } - }); -} - -// issue 84 -(function() { - var MyCtrl = function($someDependency) {}; - MyCtrl.$inject = ["$someDependency"]; - angular.module('myApp').controller("MyCtrl", MyCtrl); - MyCtrl.prototype.someFunction = function() {}; -})(); - -// empty var declarator -var MyCtrl12; -angular.module("MyMod").controller('MyCtrl', MyCtrl12); - -// issue 115 -module.exports = function() { - "use strict"; - return { - restrict: 'E', - replace: true, - scope: { }, - controller: /*@ngInject*/["$scope", "myService", function($scope, myService) { - }], - templateUrl: "mytemplate" - }; -}; - -// issue #135 -var MyCtrl = (function() { - /*@ngInject*/ - MyCtrl.$inject = ["a"]; - function MyCtrl(a) { - } - - return MyCtrl; -})(); - -myMod.service("a", MyCtrl); From dc6d9c98383c0c68889086f5081d4509e38d952e Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Mon, 25 Jul 2016 19:34:45 -0400 Subject: [PATCH 14/65] option to disable implicit matching closes #4 --- README.md | 15 ++++++++++++++ babel-ng-annotate.js | 32 +++++++++++++++++++----------- ng-annotate-main.js | 6 +++++- package.json | 2 +- tests/es6.js | 7 +++++++ tests/inside_module.js | 3 +++ tests/issues.js | 5 +++++ tests/modals.js | 5 +++++ tests/ngInject-arrow.js | 4 +++- tests/ngInject.js | 4 +++- tests/provider$get.js | 7 +++++++ tests/references.js | 3 +++ tests/simple-arrow.js | 2 +- tests/simple.js | 25 +++++++++++++++++++++++ tests/tests.js | 44 +++++++++++++++++++++++++++++------------ tests/ui-router.js | 3 +++ 16 files changed, 137 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index d4d9496..d348e36 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,21 @@ and add the plugin to your `.babelrc` file: } ``` +## Options + +### `explicitOnly` + +By default, this plugin will attempt to add annotations to common AngularJS code patterns. This behavior can be disabled (requiring you to mark up functions with `/* @ngInject */` or `'ngInject'`). + +To pass this option to the plugin, [add it to your Babel configuration](https://babeljs.io/docs/plugins/#plugin-options): + +```json +{ + "presets": ["es2015"], + "plugins": [["angularjs-annotate", { "explicitOnly" : true}]] +} +``` + ## Usage See [ng-annotate](https://github.com/olov/ng-annotate)'s documentation and the [test sources](tests/) for details about the patterns that can be automatically detected by ng-annotate and this plugin, as well as information about how to explicitly mark functions and classes for annotation. diff --git a/babel-ng-annotate.js b/babel-ng-annotate.js index 8ef7c63..24787ae 100644 --- a/babel-ng-annotate.js +++ b/babel-ng-annotate.js @@ -57,9 +57,11 @@ module.exports = function() { enter(path) { ngInject.inspectAssignment(path, ctx); }, - exit(path) { - let targets = matchProviderGet(path); - addTargets(targets); + exit(path, state) { + if(!state.opts.explicitOnly){ + let targets = matchProviderGet(path); + addTargets(targets); + } } }, VariableDeclarator: { @@ -81,15 +83,19 @@ module.exports = function() { enter(path) { ngInject.inspectObjectExpression(path, ctx); }, - exit(path) { - let targets = matchProviderGet(path); - addTargets(targets); + exit(path, state) { + if(!state.opts.explicitOnly){ + let targets = matchProviderGet(path); + addTargets(targets); + } } }, ReturnStatement: { - exit(path) { - let targets = matchDirectiveReturnObject(path); - addTargets(targets); + exit(path, state) { + if(!state.opts.explicitOnly){ + let targets = matchDirectiveReturnObject(path); + addTargets(targets); + } } }, FunctionExpression: { @@ -111,9 +117,9 @@ module.exports = function() { enter(path) { ngInject.inspectCallExpression(path, ctx); }, - exit(path) { - let targets = match(path, ctx); - addTargets(targets); + exit(path, state) { + let targets = match(path, ctx, state.opts.explicitOnly); + addTargets(targets); } }, ExportDeclaration: { @@ -123,6 +129,8 @@ module.exports = function() { }, Program: { enter(path, file) { + file.opts.explicitOnly = file.opts.explicitOnly || false; + ctx.suspects = []; ctx.blocked = []; ctx.fragments = []; diff --git a/ng-annotate-main.js b/ng-annotate-main.js index e59119b..941e080 100644 --- a/ng-annotate-main.js +++ b/ng-annotate-main.js @@ -16,7 +16,7 @@ const chainedUrlRouterProvider = 2; const chainedStateProvider = 3; const chainedRegular = 4; -function match(path, ctx, matchPlugins) { +function match(path, ctx, explicitOnly) { const node = path.node; const isMethodCall = ( t.isCallExpression(node) && @@ -28,6 +28,10 @@ function match(path, ctx, matchPlugins) { return false; } + if(explicitOnly){ + return false; + } + // matchInjectorInvoke must happen before matchRegular // to prevent false positive ($injector.invoke() outside module) // matchProvide must happen before matchRegular diff --git a/package.json b/package.json index 575a88c..0cdc9e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-angularjs-annotate", - "version": "0.3.0", + "version": "0.4.0", "description": "Babel plugin to add angularjs dependency injection annotations", "main": "babel-ng-annotate.js", "repository": { diff --git a/tests/es6.js b/tests/es6.js index 2da2258..52f5d16 100644 --- a/tests/es6.js +++ b/tests/es6.js @@ -4,6 +4,7 @@ module.exports = { tests: [ { name: "simple class", + implicit: true, input: function(){ class svc { constructor(dep1){ @@ -24,6 +25,7 @@ module.exports = { }, { name: "exported class", + implicit: true, noES5: true, // this works with the ES2015 preset, but the transformations // make it difficult to test input: ` @@ -46,6 +48,7 @@ module.exports = { }, { name: "exported annotated function", + explicit: true, input: ` /* @ngInject */ export default function svc(dep1){} @@ -58,6 +61,7 @@ module.exports = { }, { name: "annotated class", + explicit: true, input: function(){ /* @ngInject */ class svc { @@ -81,6 +85,7 @@ module.exports = { { name: "exported annotated class", noES5: true, + explicit: true, input: ` /* @ngInject */ export default class svc { @@ -103,6 +108,7 @@ module.exports = { }, { name: "annotated constructor", + explicit: true, input: function(){ class svc { /* @ngInject */ @@ -125,6 +131,7 @@ module.exports = { }, { name: "constructor with prologue directive", + explicit: true, input: function(){ class svc { constructor(dep1){ diff --git a/tests/inside_module.js b/tests/inside_module.js index 5878921..d2ad60b 100644 --- a/tests/inside_module.js +++ b/tests/inside_module.js @@ -4,6 +4,7 @@ module.exports = { { name: "Injector invoke", contextDependent: true, + implicit: true, input: function(){ $injector.invoke(function($compile) { $compile(myElement)(scope); @@ -17,6 +18,7 @@ module.exports = { }, { name: "httpProvider", + implicit: true, contextDependent: true, input: function(){ $httpProvider.interceptors.push(function($scope) { a }); @@ -29,6 +31,7 @@ module.exports = { }, { name: "$routeProvider", + implicit: true, contextDependent: true, input: function(){ $routeProvider.when("path", { diff --git a/tests/issues.js b/tests/issues.js index 9cd8dff..fe9d92a 100644 --- a/tests/issues.js +++ b/tests/issues.js @@ -3,6 +3,7 @@ module.exports = { tests: [ { name: "regression-test for https://github.com/olov/ng-annotate/issues/221", + explicit: true, input: function(){ var FooBar = (function (_super) { __extends(FooBar, _super); @@ -87,6 +88,7 @@ module.exports = { { name: "$stateProvider.decorator should not be injected", // not a module declaration short-form, see https://github.com/olov/ng-annotate/issues/82 + implicit: true, input: function(){ $stateProvider.decorator('parent', function (state, parentFn) { doStuff(); @@ -118,6 +120,7 @@ module.exports = { }, { name: "empty var declarator", + implicit: true, input: function(){ var MyCtrl12; angular.module("MyMod").controller('MyCtrl', MyCtrl12); @@ -129,6 +132,7 @@ module.exports = { }, { name: "issue 115", + explicit: true, input: function(){ module.exports = function() { "use strict"; @@ -158,6 +162,7 @@ module.exports = { }, { name: "issue 135", + explicit: true, input: function(){ var MyCtrl = (function() { /*@ngInject*/ diff --git a/tests/modals.js b/tests/modals.js index b09e2e9..6c3345d 100644 --- a/tests/modals.js +++ b/tests/modals.js @@ -3,6 +3,7 @@ module.exports = { tests: [ { name: "Modal Open", + implicit: true, contextDependent: true, input: function(){ $modal.open({ @@ -32,6 +33,7 @@ module.exports = { { name: "uibModal Open", contextDependent: true, + implicit: true, input: function(){ $uibModal.open({ templateUrl: "str", @@ -59,6 +61,7 @@ module.exports = { }, { name: "Material Design Modal", + implicit: true, contextDependent: true, input: function(){ $mdDialog.show({ @@ -88,6 +91,7 @@ module.exports = { { name: "Material Design Bottom Sheet", contextDependent: true, + implicit: true, input: function(){ $mdBottomSheet.show({ templateUrl: "str", @@ -116,6 +120,7 @@ module.exports = { { name: "Material Design Toast", contextDependent: true, + implicit: true, input: function(){ $mdToast.show({ templateUrl: "str", diff --git a/tests/ngInject-arrow.js b/tests/ngInject-arrow.js index 99a81f7..009f33d 100644 --- a/tests/ngInject-arrow.js +++ b/tests/ngInject-arrow.js @@ -257,6 +257,7 @@ module.exports = { var MyDirective2 = ($stateProvider) => { $stateProvider.state('astate', { resolve: { + /* @ngInject */ yoyo: (ma) => { }, } @@ -268,6 +269,7 @@ module.exports = { var MyDirective2 = ($stateProvider) => { $stateProvider.state('astate', { resolve: { + /* @ngInject */ yoyo: ['ma', (ma) => { }], } @@ -276,5 +278,5 @@ module.exports = { MyDirective2.$inject = ['$stateProvider']; } } - ] + ].map(t => { t.explicit=true; return t; }) } diff --git a/tests/ngInject.js b/tests/ngInject.js index 17f1a3b..308e64d 100644 --- a/tests/ngInject.js +++ b/tests/ngInject.js @@ -366,6 +366,7 @@ module.exports = { function MyDirective2($stateProvider) { $stateProvider.state('astate', { resolve: { + /* @ngInject */ yoyo: function(ma) { }, } @@ -379,6 +380,7 @@ module.exports = { function MyDirective2($stateProvider) { $stateProvider.state('astate', { resolve: { + /* @ngInject */ yoyo: ['ma', function(ma) { }], } @@ -386,5 +388,5 @@ module.exports = { } } } - ] + ].map(t => { t.explicit=true; return t; }) } diff --git a/tests/provider$get.js b/tests/provider$get.js index 8dbd851..83fcc95 100644 --- a/tests/provider$get.js +++ b/tests/provider$get.js @@ -3,6 +3,7 @@ module.exports = { tests: [ { name: "No dependencies", + implicit: true, input: function(){ myMod.provider("foo", function() { this.$get = function() { @@ -20,6 +21,7 @@ module.exports = { }, { name: "Simple { $get }", + implicit: true, input: function(){ myMod.provider("foo", { $get: function() { @@ -67,6 +69,7 @@ module.exports = { }, { name: "Simple this.$get", + implicit: true, input: function(){ myMod.provider("foo", function() { this.$get = function() { @@ -90,6 +93,7 @@ module.exports = { }, { name: "Simple return { $get }", + implicit: true, input: function(){ myMod.provider("foo", function() { return { @@ -121,6 +125,7 @@ module.exports = { }, { name: "this.$get w/ reference-following", + implicit: true, input: function(){ myMod.provider("foo", function($scope) { this.$get = function($scope, $timeout) { @@ -144,6 +149,7 @@ module.exports = { }, { name: "this.$get w/ reference-following and hoisting", + implicit: true, input: function(){ myMod.provider("foo", extprov); function extprov(x) { @@ -189,6 +195,7 @@ module.exports = { }, { name: "$get is only valid inside a provider", + implicit: true, input: function(){ // $get is only valid inside provider myMod.service("donttouch", function() { diff --git a/tests/references.js b/tests/references.js index 6304353..902669f 100644 --- a/tests/references.js +++ b/tests/references.js @@ -108,6 +108,7 @@ module.exports = { // }, { name: "proper scope analysis including shadowing", + implicit: true, input: function(){ "use strict"; function MyCtrl1(a, b) { @@ -136,6 +137,7 @@ module.exports = { }, { name: "explicit annotation on reference flows back to definition", + explicit: true, input: function(){ function MyCtrl2(z) { } @@ -151,6 +153,7 @@ module.exports = { }, { name: "hoisted function should chain onto module", + implicit: true, input: function(){ angular.module("MyMod").directive("foo", MyDirective); diff --git a/tests/simple-arrow.js b/tests/simple-arrow.js index 4210e6a..3fe52d4 100644 --- a/tests/simple-arrow.js +++ b/tests/simple-arrow.js @@ -531,5 +531,5 @@ module.exports = { angular.module("MyMod").controller("MyCtrl", myCtrl10); } } - ] + ].map(t => { t.implicit=true; return t; }) }; diff --git a/tests/simple.js b/tests/simple.js index b11e640..195cfe2 100644 --- a/tests/simple.js +++ b/tests/simple.js @@ -3,6 +3,7 @@ module.exports = { tests: [ { name: "Long form", + implicit: true, input: function(){ angular.module("MyMod").controller("MyCtrl", function($scope, $timeout) { }); @@ -14,6 +15,7 @@ module.exports = { }, { name: "w/ dependencies", + implicit: true, input: function(){ angular.module("MyMod", ["OtherMod"]).controller("MyCtrl", function($scope, $timeout) { }); @@ -25,6 +27,7 @@ module.exports = { }, { name: "Simple controller", + implicit: true, input: function(){ myMod.controller("foo", function($scope, $timeout) { }); @@ -36,6 +39,7 @@ module.exports = { }, { name: "Simple service", + implicit: true, input: function(){ myMod.service("foo", function($scope, $timeout) { }); @@ -47,6 +51,7 @@ module.exports = { }, { name: "Simple factory", + implicit: true, input: function(){ myMod.factory("foo", function($scope, $timeout) { }); @@ -58,6 +63,7 @@ module.exports = { }, { name: "Simple filter", + implicit: true, input: function(){ myMod.filter("foo", function($scope, $timeout) { }); @@ -69,6 +75,7 @@ module.exports = { }, { name: "Simple directive", + implicit: true, input: function(){ myMod.directive("foo", function($scope, $timeout) { }); @@ -80,6 +87,7 @@ module.exports = { }, { name: "Simple animation", + implicit: true, input: function(){ myMod.animation("foo", function($scope, $timeout) { }); @@ -91,6 +99,7 @@ module.exports = { }, { name: "Simple invoke", + implicit: true, input: function(){ myMod.invoke("foo", function($scope, $timeout) { }); @@ -102,6 +111,7 @@ module.exports = { }, { name: "Simple store", + implicit: true, input: function(){ myMod.store("foo", function($scope, $timeout) { }); @@ -113,6 +123,7 @@ module.exports = { }, { name: "Simple decorator", + implicit: true, input: function(){ myMod.decorator("foo", function($scope, $timeout) { }); @@ -124,6 +135,7 @@ module.exports = { }, { name: "Simple component", + implicit: true, input: function(){ myMod.component("foo", {controller: function($scope, $timeout) {}}); }, @@ -133,6 +145,7 @@ module.exports = { }, { name: "Implict config function", + implicit: true, input: function(){ // implicit config function angular.module("MyMod", function($interpolateProvider) {}); @@ -148,6 +161,7 @@ module.exports = { }, { name: "Object property", + implicit: true, input: function(){ // object property var myObj = {}; @@ -164,6 +178,7 @@ module.exports = { }, { name: "Simple invocations w/ no dependencies", + implicit: true, input: function(){ // no dependencies => no need to wrap the function in an array myMod.controller("foo", function() { @@ -211,6 +226,7 @@ module.exports = { }, { name: "Simple run/config", + implicit: true, input: function(){ // run, config don't take names myMod.run(function($scope, $timeout) { @@ -236,6 +252,7 @@ module.exports = { }, { name: "Directive return object", + implicit: true, input: function(){ // directive return object myMod.directive("foo", function($scope) { @@ -273,6 +290,7 @@ module.exports = { }, { name: "Simple chaining", + implicit: true, input: function(){ myMod.directive("foo", function($a, $b) { a; @@ -318,6 +336,7 @@ module.exports = { }, { name: "Less simple chaining", + implicit: true, input: function(){ angular.module("MyMod").directive("foo", function($a, $b) { a; @@ -379,6 +398,7 @@ module.exports = { }, { name: "$provide", + implicit: true, input: function(){ angular.module("myMod").controller("foo", function() { $provide.decorator("foo", function($scope) {}); @@ -412,6 +432,7 @@ module.exports = { }, { name: "negative $provide", + implicit: true, input: function(){ function notInContext() { $provide.decorator("foo", function($scope) {}); @@ -443,6 +464,7 @@ module.exports = { }, { name: "ControllerProvider", + implicit: true, input: function(){ angular.module("myMod").controller("foo", function() { $controllerProvider.register("foo", function($scope) {}); @@ -462,6 +484,7 @@ module.exports = { }, { name: "directive return object is only valid inside directive", + implicit: true, input: function(){ myMod.service("donttouch", function() { return { @@ -493,6 +516,7 @@ module.exports = { }, { name: "IIFE-jumping with reference support", + implicit: true, input: function(){ var myCtrl = (function () { return function($scope) { @@ -511,6 +535,7 @@ module.exports = { }, { name: "advanced IIFE-jumping (with reference support)", + implicit: true, input: function(){ var myCtrl10 = (function() { "use strict"; diff --git a/tests/tests.js b/tests/tests.js index 05751d1..5d49e20 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -7,6 +7,11 @@ const indent = require('indent-string'); const tape = require('tape').test; const path = require('path'); +const resolve = (file) => path.resolve(__dirname, file); + +const ES6presets = [resolve("./es2015-modified")]; +const plugin = resolve("../babel-ng-annotate.js"); + let suites = [ require('./simple'), require('./simple-arrow'), @@ -50,24 +55,14 @@ function runTest(test) { // var out = babel.transform(fnBody(test.input), { plugins: "../babel-ng-annotate", presets: ["../es2015-modified"] }); // var expected = babel.transform(fnBody(test.expected), { plugins: [], presets: ["../es2015-modified"] }); - var resolve = (file) => path.resolve(__dirname, file); - - var out, expected; - // Test transpiled ES5 sources if(!test.noES5){ - out = babel.transform(fnBody(test.input), { plugins: ["../babel-ng-annotate.js"].map(resolve), presets:["./es2015-modified"].map(resolve) }); - expected = babel.transform(fnBody(test.expected), { plugins: [], presets:["./es2015-modified"].map(resolve) }); - - t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES5: ' + test.name); + doTransform(t, test, ES6presets, 'ES5'); } // And again without the ES6 transformations - if(!test.noES6){ - out = babel.transform(fnBody(test.input), { plugins: ["../babel-ng-annotate.js"].map(resolve), presets:[].map(resolve) }); - expected = babel.transform(fnBody(test.expected), { plugins: [], presets:[].map(resolve) }); - - t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), 'ES2015: ' + test.name); + if(!test.noES6){ + doTransform(t, test, [], 'ES2015'); } t.end(); @@ -81,6 +76,29 @@ function runTest(test) { // } } +function doTransform(t, test, presets, logPrefix){ + + let out = babel.transform(fnBody(test.input), { plugins: [plugin], presets: presets }); + let expected = babel.transform(fnBody(test.expected), { plugins: [], presets: presets }); + + t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), logPrefix + ': ' + test.name); + + // If test is marked as explicit, it should still work when explicitOnly is on + if(test.explicit){ + out = babel.transform(fnBody(test.input), { plugins: [[plugin, {explicitOnly: true}]], presets:presets }); + + t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), logPrefix + ' explicitOnly: ' + test.name); + } + + // If test is marked as implicit, no transformation should occur when explicitOnly is on + if(test.implicit){ + out = babel.transform(fnBody(test.input), { plugins: [[plugin, {explicitOnly: true}]], presets: presets }); + expected = babel.transform(fnBody(test.input), { plugins: [], presets: presets }); + + t.equals(out.code.trim().replace(/\n/g,''), expected.code.trim().replace(/\n/g,''), logPrefix + 'explicitOnly: ' + test.name); + } + +} function fnBody(fn){ if(typeof fn === 'function'){ diff --git a/tests/ui-router.js b/tests/ui-router.js index 3e217eb..839ec8f 100644 --- a/tests/ui-router.js +++ b/tests/ui-router.js @@ -4,6 +4,7 @@ module.exports = { { name: "ui-router $stateProvider", contextDependent: true, + implicit: true, input: function(){ $stateProvider.state("myState", { resolve: { @@ -94,6 +95,7 @@ module.exports = { { name: "ui-router $urlRouterProvider", contextDependent: true, + implicit: true, input: function(){ $urlRouterProvider.when("/", function($match) { a; }); $urlRouterProvider.otherwise("", function(a) { a; }); @@ -108,6 +110,7 @@ module.exports = { { name: "ui-router stateHelperProvider", contextDependent: true, + implicit: true, input: function(){ stateHelperProvider.setNestedState({ controller: function($scope, simpleObj, promiseObj, translations) { c }, From a5284c22269b2f93bda71b6c57c0286b7cc0f315 Mon Sep 17 00:00:00 2001 From: Andrew Schmadel Date: Wed, 3 Aug 2016 17:46:38 -0400 Subject: [PATCH 15/65] make a REPL? --- index.html | 119 + repl/repl-browser.js | 28728 +++++++++++++++++++++++++++++++++++++++++ repl/repl.js | 14 + 3 files changed, 28861 insertions(+) create mode 100644 index.html create mode 100644 repl/repl-browser.js create mode 100644 repl/repl.js diff --git a/index.html b/index.html new file mode 100644 index 0000000..2ac0834 --- /dev/null +++ b/index.html @@ -0,0 +1,119 @@ + + + + + Codestin Search App + + + + +

babel-plugin-angularjs-annotate

+ +

Get It

+ +On Github + +

Try It

+
+
+

Input

+
+
+
+

Output

+
+ +
+
+ +
+

Errors

+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/repl/repl-browser.js b/repl/repl-browser.js new file mode 100644 index 0000000..9d8179c --- /dev/null +++ b/repl/repl-browser.js @@ -0,0 +1,28728 @@ +(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// when used in node, this will actually load the util module we depend on +// versus loading the builtin util module as happens otherwise +// this is a bug in node module loading as far as I am concerned +var util = require('util/'); + +var pSlice = Array.prototype.slice; +var hasOwn = Object.prototype.hasOwnProperty; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } + else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = stackStartFunction.name; + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function replacer(key, value) { + if (util.isUndefined(value)) { + return '' + value; + } + if (util.isNumber(value) && !isFinite(value)) { + return value.toString(); + } + if (util.isFunction(value) || util.isRegExp(value)) { + return value.toString(); + } + return value; +} + +function truncate(s, n) { + if (util.isString(s)) { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} + +function getMessage(self) { + return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + + self.operator + ' ' + + truncate(JSON.stringify(self.expected, replacer), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (util.isBuffer(actual) && util.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (!util.isObject(actual) && !util.isObject(expected)) { + return actual == expected; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b) { + if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) { + return a === b; + } + var aIsArgs = isArguments(a), + bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + var ka = objectKeys(a), + kb = objectKeys(b), + key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key])) return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } else if (actual instanceof expected) { + return true; + } else if (expected.call({}, actual) === true) { + return true; + } + + return false; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (util.isString(expected)) { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + if (!shouldThrow && expectedException(actual, expected)) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function(err) { if (err) {throw err;}}; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +},{"util/":5}],2:[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],3:[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +(function () { + try { + cachedSetTimeout = setTimeout; + } catch (e) { + cachedSetTimeout = function () { + throw new Error('setTimeout is not defined'); + } + } + try { + cachedClearTimeout = clearTimeout; + } catch (e) { + cachedClearTimeout = function () { + throw new Error('clearTimeout is not defined'); + } + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + return setTimeout(fun, 0); + } else { + return cachedSetTimeout.call(null, fun, 0); + } +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + clearTimeout(marker); + } else { + cachedClearTimeout.call(null, marker); + } +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],4:[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],5:[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"./support/isBuffer":4,"_process":3,"inherits":2}],6:[function(require,module,exports){ +'use strict'; + +var ngAnnotate = require('./ng-annotate-main'); +const ngInject = require('./nginject'); +const is = require('simple-is'); + +const match = ngAnnotate.match; +const addModuleContextDependentSuspect = ngAnnotate.addModuleContextDependentSuspect; +const addModuleContextIndependentSuspect = ngAnnotate.addModuleContextIndependentSuspect; +const judgeSuspects = ngAnnotate.judgeSuspects; +const matchDirectiveReturnObject = ngAnnotate.matchDirectiveReturnObject; +const matchProviderGet = ngAnnotate.matchProviderGet; + + +module.exports = function() { + + var options = {}; + + const re = (options.regexp ? new RegExp(options.regexp) : /^[a-zA-Z0-9_\$\.\s]+$/); + + // suspects is built up with suspect nodes by match. + // A suspect node will get annotations added / removed if it + // fulfills the arrayexpression or functionexpression look, + // and if it is in the correct context (inside an angular + // module definition) + const suspects = []; + + // blocked is an array of blocked suspects. Any target node + // (final, i.e. IIFE-jumped, reference-followed and such) included + // in blocked will be ignored by judgeSuspects + const blocked = []; + + const ctx = { + re: re, + suspects: suspects, + blocked: blocked, + addModuleContextDependentSuspect: addModuleContextDependentSuspect, + addModuleContextIndependentSuspect: addModuleContextIndependentSuspect + }; + + var addTargets = function(targets) { + if (!targets) { + return; + } + if (!is.array(targets)) { + targets = [targets]; + } + + for (let i = 0; i < targets.length; i++) { + addModuleContextDependentSuspect(targets[i], ctx); + } + }; + + return { + visitor: { + AssignmentExpression: { + enter(path) { + ngInject.inspectAssignment(path, ctx); + }, + exit(path, state) { + if(!state.opts.explicitOnly){ + let targets = matchProviderGet(path); + addTargets(targets); + } + } + }, + VariableDeclarator: { + enter(path) { + ngInject.inspectDeclarator(path, ctx); + } + }, + ClassDeclaration: { + enter(path) { + ngInject.inspectClassDeclaration(path, ctx); + } + }, + ClassMethod: { + enter(path) { + ngInject.inspectClassMethod(path, ctx); + } + }, + ObjectExpression: { + enter(path) { + ngInject.inspectObjectExpression(path, ctx); + }, + exit(path, state) { + if(!state.opts.explicitOnly){ + let targets = matchProviderGet(path); + addTargets(targets); + } + } + }, + ReturnStatement: { + exit(path, state) { + if(!state.opts.explicitOnly){ + let targets = matchDirectiveReturnObject(path); + addTargets(targets); + } + } + }, + FunctionExpression: { + enter(path) { + ngInject.inspectFunction(path, ctx); + } + }, + ArrowFunctionExpression: { + enter(path) { + ngInject.inspectFunction(path, ctx); + } + }, + FunctionDeclaration: { + enter(path) { + ngInject.inspectFunction(path, ctx); + } + }, + CallExpression: { + enter(path) { + ngInject.inspectCallExpression(path, ctx); + }, + exit(path, state) { + let targets = match(path, ctx, state.opts.explicitOnly); + addTargets(targets); + } + }, + ExportDeclaration: { + enter(path) { + ngInject.inspectExportDeclaration(path, ctx); + } + }, + Program: { + enter(path, file) { + file.opts.explicitOnly = file.opts.explicitOnly || false; + + ctx.suspects = []; + ctx.blocked = []; + ctx.fragments = []; + + ctx.srcForRange = function(node) { + return file.file.code.slice(node.start, node.end); + }; + }, + exit() { + judgeSuspects(ctx); + } + } + } + }; +} + +},{"./ng-annotate-main":7,"./nginject":8,"simple-is":434}],7:[function(require,module,exports){ +// ng-annotate-main.js +// MIT licensed, see LICENSE file +// Copyright (c) 2013-2016 Olov Lassus + +"use strict"; +const is = require("simple-is"); +const assert = require("assert"); +const ngInject = require("./nginject"); +const scopeTools = require("./scopetools"); +// const optionalAngularDashboardFramework = require("./optionals/angular-dashboard-framework"); +const t = require('babel-types'); + + +const chainedRouteProvider = 1; +const chainedUrlRouterProvider = 2; +const chainedStateProvider = 3; +const chainedRegular = 4; + +function match(path, ctx, explicitOnly) { + const node = path.node; + const isMethodCall = ( + t.isCallExpression(node) && + t.isMemberExpression(node.callee) && + node.callee.computed === false + ); + + if(isMethodCall && ngInject.inspectComment(path, ctx)){ + return false; + } + + if(explicitOnly){ + return false; + } + + // matchInjectorInvoke must happen before matchRegular + // to prevent false positive ($injector.invoke() outside module) + // matchProvide must happen before matchRegular + // to prevent regular from matching it as a short-form + const matchMethodCalls = (isMethodCall && + (matchInjectorInvoke(path) || matchProvide(path, ctx) || matchRegular(path, ctx) || matchNgRoute(path) || matchMaterialShowModalOpen(path) || matchNgUi(path) || matchHttpProvider(path) || matchControllerProvider(path))); + + return matchMethodCalls; +} + +function matchMaterialShowModalOpen(path) { + // $mdDialog.show({.. controller: fn, resolve: {f: function($scope) {}, ..}}); + // $mdToast.show({.. controller: fn, resolve: {f: function($scope) {}, ..}}); + // $mdBottomSheet.show({.. controller: fn, resolve: {f: function($scope) {}, ..}}); + // $modal.open({.. controller: fn, resolve: {f: function($scope) {}, ..}}); + + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + const method = callee.property; // identifier + const args = node.arguments; + + if (t.isIdentifier(obj) && + ((is.someof(obj.name, ["$modal", "$uibModal"]) && method.name === "open") || (is.someof(obj.name, ["$mdDialog", "$mdToast", "$mdBottomSheet"]) && method.name === "show")) && + args.length === 1 && t.isObjectExpression(args[0])) { + let args = path.get("arguments"); + const props = args[0].get("properties"); + const res = [matchProp("controller", props)]; + res.push.apply(res, matchResolve(props)); + return res.filter(Boolean); + } + return false; +} + +function matchDirectiveReturnObject(path) { + const node = path.node; + + // only matches inside directives + // return { .. controller: function($scope, $timeout), ...} + + return limit("directive", t.isReturnStatement(node) && + node.argument && t.isObjectExpression(node.argument) && + matchProp("controller", (path.get && path.get("argument.properties") || node.argument.properties))); +} + +function limit(name, path) { + const node = (path && path.node) || path; + + if (node && !path.$limitToMethodName) { + path.$limitToMethodName = name; + // node.$limitToMethodName = name; + } + return path; +} + +function matchProviderGet(path) { + // only matches inside providers + // (this|self|that).$get = function($scope, $timeout) + // { ... $get: function($scope, $timeout), ...} + const node = path.node; + let memberExpr; + let self; + var yes = limit("provider", (t.isAssignmentExpression(node) && t.isMemberExpression(memberExpr = node.left) && + memberExpr.property.name === "$get" && + (t.isThisExpression(self = memberExpr.object) || (t.isIdentifier(self) && is.someof(self.name, ["self", "that"]))) && + path.get("right")) || + (t.isObjectExpression(node) && matchProp("$get", path.get("properties")))); + + return yes; +} + +function matchNgRoute(path) { + // $routeProvider.when("path", { + // ... + // controller: function($scope) {}, + // resolve: {f: function($scope) {}, ..} + // }) + + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + if (!(obj.$chained === chainedRouteProvider || (t.isIdentifier(obj) && obj.name === "$routeProvider"))) { + return false; + } + node.$chained = chainedRouteProvider; + + const method = callee.property; // identifier + if (method.name !== "when") { + return false; + } + + const args = path.get("arguments"); + if (args.length !== 2) { + return false; + } + const configArg = last(args) + if (!t.isObjectExpression(configArg)) { + return false; + } + + const props = configArg.get("properties"); + const res = [ + matchProp("controller", props) + ]; + // {resolve: ..} + res.push.apply(res, matchResolve(props)); + + const filteredRes = res.filter(Boolean); + return (filteredRes.length === 0 ? false : filteredRes); +} + +function matchNgUi(path) { + // $stateProvider.state("myState", { + // ... + // controller: function($scope) + // controllerProvider: function($scope) + // templateProvider: function($scope) + // onEnter: function($scope) + // onExit: function($scope) + // }); + // $stateProvider.state("myState", {... resolve: {f: function($scope) {}, ..} ..}) + // $stateProvider.state("myState", {... params: {params: {simple: function($scope) {}, inValue: { value: function($scope) {} }} ..}) + // $stateProvider.state("myState", {... views: {... somename: {... controller: fn, controllerProvider: fn, templateProvider: fn, resolve: {f: fn}}}}) + // + // stateHelperProvider.setNestedState({ sameasregularstate, children: [sameasregularstate, ..]}) + // stateHelperProvider.setNestedState({ sameasregularstate, children: [sameasregularstate, ..]}, true) + // + // $urlRouterProvider.when(.., function($scope) {}) + // + // $modal.open see matchMaterialShowModalOpen + + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + const method = callee.property; // identifier + let args = path.get("arguments"); + + // shortcut for $urlRouterProvider.when(.., function($scope) {}) + if (obj.$chained === chainedUrlRouterProvider || (t.isIdentifier(obj) && obj.name === "$urlRouterProvider")) { + node.$chained = chainedUrlRouterProvider; + + if (method.name === "when" && args.length >= 1) { + return last(args); + } + return false; + } + + // everything below is for $stateProvider and stateHelperProvider alone + if (!(obj.$chained === chainedStateProvider || (t.isIdentifier(obj) && is.someof(obj.name, ["$stateProvider", "stateHelperProvider"])))) { + return false; + } + node.$chained = chainedStateProvider; + + if (is.noneof(method.name, ["state", "setNestedState"])) { + return false; + } + + // $stateProvider.state({ ... }) and $stateProvider.state("name", { ... }) + // stateHelperProvider.setNestedState({ .. }) and stateHelperProvider.setNestedState({ .. }, true) + if (!(args.length >= 1 && args.length <= 2)) { + return false; + } + + const configArg = (method.name === "state" ? last(args) : args[0]); + + const res = []; + + recursiveMatch(configArg); + + const filteredRes = res.filter(Boolean); + return (filteredRes.length === 0 ? false : filteredRes); + + + function recursiveMatch(objectExpressionPath) { + if (!objectExpressionPath || !t.isObjectExpression(objectExpressionPath)) { + return false; + } + + const properties = objectExpressionPath.get("properties"); + + matchStateProps(properties, res); + + const childrenArrayExpression = matchProp("children", properties); + const children = childrenArrayExpression && childrenArrayExpression.get("elements"); + + if (!children) { + return; + } + children.forEach(recursiveMatch); + } + + function matchStateProps(props, res) { + const simple = [ + matchProp("controller", props), + matchProp("controllerProvider", props), + matchProp("templateProvider", props), + matchProp("onEnter", props), + matchProp("onExit", props), + ]; + res.push.apply(res, simple); + + // {resolve: ..} + res.push.apply(res, matchResolve(props)); + + // {params: {simple: function($scope) {}, inValue: { value: function($scope) {} }} + const a = matchProp("params", props); + if (a && t.isObjectExpression(a)) { + a.get("properties").forEach(function(prop) { + let value = prop.get("value"); + if (t.isObjectExpression(value)) { + res.push(matchProp("value", value.get("properties"))); + } else { + res.push(value); + } + }); + } + + // {view: ...} + const viewObject = matchProp("views", props); + if (viewObject && t.isObjectExpression(viewObject)) { + viewObject.get("properties").forEach(function(prop) { + let value = prop.get("value"); + if (t.isObjectExpression(value)) { + let props = value.get("properties"); + res.push(matchProp("controller", props)); + res.push(matchProp("controllerProvider", props)); + res.push(matchProp("templateProvider", props)); + res.push.apply(res, matchResolve(props)); + } + }); + } + } +} + +function matchInjectorInvoke(path) { + // $injector.invoke(function($compile) { ... }); + + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + const method = callee.property; // identifier + let args; + + return method.name === "invoke" && + t.isIdentifier(obj) && obj.name === "$injector" && + (args = path.get("arguments")).length >= 1 && args; +} + +function matchHttpProvider(path) { + // $httpProvider.interceptors.push(function($scope) {}); + // $httpProvider.responseInterceptors.push(function($scope) {}); + + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + const method = callee.property; // identifier + let args; + + return (method.name === "push" && + t.isMemberExpression(obj) && !obj.computed && + obj.object.name === "$httpProvider" && is.someof(obj.property.name, ["interceptors", "responseInterceptors"]) && + (args = path.get("arguments")).length >= 1 && args); +} + +function matchControllerProvider(path) { + // $controllerProvider.register("foo", function($scope) {}); + + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + const method = callee.property; // identifier + let args; + + const target = t.isIdentifier(obj) && obj.name === "$controllerProvider" && + method.name === "register" && (args = path.get("arguments")).length === 2 && args[1]; + + if (target) { + target.node.$methodName = method.name; + } + return target; +} + +function matchProvide(path, ctx) { + // $provide.decorator("foo", function($scope) {}); + // $provide.service("foo", function($scope) {}); + // $provide.factory("foo", function($scope) {}); + // $provide.provider("foo", function($scope) {}); + + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + const method = callee.property; // identifier + const args = path.get("arguments"); + + const target = t.isIdentifier(obj) && obj.name === "$provide" && + is.someof(method.name, ["decorator", "service", "factory", "provider"]) && + args.length === 2 && args[1]; + + if (target) { + target.node.$methodName = method.name; + target.$methodName = method.name; + + if (ctx.rename) { + // for eventual rename purposes + return args; + } + } + return target; +} + +function matchRegular(path, ctx) { + // we already know that node is a (non-computed) method call + const node = path.node; + const callee = node.callee; + const obj = callee.object; // identifier or expression + const method = callee.property; // identifier + + // short-cut implicit config special case: + // angular.module("MyMod", function(a) {}) + if (obj.name === "angular" && method.name === "module") { + const args = path.get("arguments"); + if (args.length >= 2) { + node.$chained = chainedRegular; + return last(args); + } + } + + // hardcoded exception: foo.decorator is generally considered a short-form + // declaration but $stateProvider.decorator is not. see https://github.com/olov/ng-annotate/issues/82 + if (obj.name === "$stateProvider" && method.name === "decorator") { + return false; + } + + const matchAngularModule = (obj.$chained === chainedRegular || isReDef(obj,ctx) || isLongDef(obj)) && + is.someof(method.name, ["provider", "value", "constant", "bootstrap", "config", "factory", "directive", "filter", "run", "controller", "service", "animation", "invoke", "store", "decorator", "component"]); + if (!matchAngularModule) { + return false; + } + node.$chained = chainedRegular; + + if (is.someof(method.name, ["value", "constant", "bootstrap"])) { + return false; // affects matchAngularModule because of chaining + } + + const args = node.arguments; + const argPaths = path.get("arguments"); + let target = (is.someof(method.name, ["config", "run"]) ? + args.length === 1 && argPaths[0] : + args.length === 2 && t.isLiteral(args[0]) && is.string(args[0].value) && argPaths[1]); + + if (method.name === "component") { + const controllers = target.get("properties").filter(prop => prop.node.key.name == "controller"); + if(controllers.length === 1) { + target = controllers[0].get("value"); + } else { + return false; + } + } + + if (target) { + target.node.$methodName = method.name; + } + + if (ctx.rename && args.length === 2 && target) { + // for eventual rename purposes + const somethingNameLiteral = args[0]; + return [somethingNameLiteral, target]; + } + return target; +} + +// matches with default regexp +// *.controller("MyCtrl", function($scope, $timeout) {}); +// *.*.controller("MyCtrl", function($scope, $timeout) {}); +// matches with --regexp "^require(.*)$" +// require("app-module").controller("MyCtrl", function($scope) {}); +function isReDef(node, ctx) { + return ctx.re.test(ctx.srcForRange(node)); +} + +// Long form: angular.module(*).controller("MyCtrl", function($scope, $timeout) {}); +function isLongDef(node) { + return node.callee && + node.callee.object && node.callee.object.name === "angular" && + node.callee.property && node.callee.property.name === "module"; +} + +function last(arr) { + return arr[arr.length - 1]; +} + +function matchProp(name, props) { + for (let i = 0; i < props.length; i++) { + const propOrPath = props[i]; + const prop = propOrPath.node || propOrPath; + + if ((t.isIdentifier(prop.key) && prop.key.name === name) || + (t.isLiteral(prop.key) && prop.key.value === name)) { + return (propOrPath.get && propOrPath.get("value")) || prop.value; // FunctionExpression or ArrayExpression + } + } + return null; +} + +function matchResolve(props) { + const resolveObject = matchProp("resolve", props); + if (resolveObject && t.isObjectExpression(resolveObject)) { + return resolveObject.get("properties").map(function(prop) { + return prop.get("value"); + }); + } + return []; +} + +function renamedString(ctx, originalString) { + if (ctx.rename) { + return ctx.rename.get(originalString) || originalString; + } + return originalString; +} + +function insertArray(ctx, path) { + if(!path.node){ + console.warn("Not a path", path, path.loc.start, path.loc.end); + return; + } + + let toParam = path.node.params.map(param => param.name); + let elems = toParam.map(i => t.stringLiteral(i)); + + elems.push(path.node); + + path.replaceWith( + t.expressionStatement( + t.arrayExpression(elems) + ) + ); + +} + +// TODO: Is this necessary? +function renameProviderDeclarationSite(ctx, literalNode, fragments) { + fragments.push({ + start: literalNode.range[0] + 1, + end: literalNode.range[1] - 1, + str: renamedString(ctx, literalNode.value), + loc: { + start: { + line: literalNode.loc.start.line, + column: literalNode.loc.start.column + 1 + }, end: { + line: literalNode.loc.end.line, + column: literalNode.loc.end.column - 1 + } + } + }); +} + +function judgeSuspects(ctx) { + const blocked = ctx.blocked; + + const suspects = makeUnique(ctx.suspects, 1); + + for (let n = 0; n < 42; n++) { + // could be while(true), above is just a safety-net + // in practice it will loop just a couple of times + propagateModuleContextAndMethodName(suspects); + if (!setChainedAndMethodNameThroughIifesAndReferences(suspects)) { + break; + } + } + + // create final suspects by jumping, following, uniq'ing, blocking + const finalSuspects = makeUnique(suspects.map(function(target) { + const jumped = jumpOverIife(target); + const jumpedAndFollowed = followReference(jumped) || jumped; + + if (target.$limitToMethodName && target.$limitToMethodName !== "*never*" && findOuterMethodName(target) !== target.$limitToMethodName) { + return null; + } + + if (blocked.indexOf(jumpedAndFollowed) >= 0) { + return null; + } + + return jumpedAndFollowed; + }).filter(Boolean), 2); + + finalSuspects.forEach(function(path) { + let target = path.node || path; + if (target.$chained !== chainedRegular) { + return; + } + + if (isFunctionExpressionWithArgs(target) && !t.isVariableDeclarator(path.parent)) { + insertArray(ctx, path); + } else if (isGenericProviderName(target)) { + // console.warn("Generic provider rename disabled"); + // renameProviderDeclarationSite(ctx, target, fragments); + } else { + // if it's not array or function-expression, then it's a candidate for foo.$inject = [..] + judgeInjectArraySuspect(path, ctx); + } + }); + + + function propagateModuleContextAndMethodName(suspects) { + suspects.forEach(function(path) { + if (path.node.$chained !== chainedRegular && isInsideModuleContext(path)) { + path.node.$chained = chainedRegular; + } + + if (!path.node.$methodName) { + const methodName = findOuterMethodName(path); + if (methodName) { + path.node.$methodName = methodName; + } + } + }); + } + + function findOuterMethodName(path) { + for (; path && !path.node.$methodName; path = path.parentPath) { + } + return path ? path.node.$methodName : null; + } + + function setChainedAndMethodNameThroughIifesAndReferences(suspects) { + let modified = false; + suspects.forEach(function(path) { + const target = path.node; + + const jumped = jumpOverIife(path); + const jumpedNode = jumped.node; + if (jumpedNode !== target) { // we did skip an IIFE + if (target.$chained === chainedRegular && jumpedNode.$chained !== chainedRegular) { + modified = true; + jumpedNode.$chained = chainedRegular; + } + if (target.$methodName && !jumpedNode.$methodName) { + modified = true; + jumpedNode.$methodName = target.$methodName; + } + } + + const jumpedAndFollowed = followReference(jumped) || jumped; + if (jumpedAndFollowed.node !== jumped.node) { // we did follow a reference + if (jumped.node.$chained === chainedRegular && jumpedAndFollowed.node.$chained !== chainedRegular) { + modified = true; + jumpedAndFollowed.node.$chained = chainedRegular; + } + if (jumped.node.$methodName && !jumpedAndFollowed.node.$methodName) { + modified = true; + jumpedAndFollowed.node.$methodName = jumped.node.$methodName; + } + } + }); + return modified; + } + + function isInsideModuleContext(path) { + let $parent = path.parentPath; + for (; $parent && $parent.node.$chained !== chainedRegular; $parent = $parent.parentPath) { + } + return Boolean($parent); + } + + function makeUnique(suspects, val) { + return suspects.filter(function(target) { + if (target.$seen === val) { + return false; + } + target.$seen = val; + return true; + }); + } +} + +function followReference(path) { + const node = path.node; + if (!scopeTools.isReference(path)) { + return null; + } + + const binding = path.scope.getBinding(node.name); + if(!binding){ + return null; + } + + const kind = binding.kind; + const bound = binding.path; + + if (is.someof(kind, ["const", "let", "var"])) { + + if(t.isVariableDeclaration(bound)){ + var declarations = bound.get('declarations'); + assert(declarations.length === 1); + return declarations[0]; + } + + assert(t.isVariableDeclarator(bound) || t.isClassDeclaration(bound)); + // {type: "VariableDeclarator", id: {type: "Identifier", name: "foo"}, init: ..} + return bound; + } else if (kind === "hoisted") { + assert(t.isFunctionDeclaration(bound) || isFunctionExpressionOrArrow(bound)); + // FunctionDeclaration is the common case, i.e. + // function foo(a, b) {} + + // FunctionExpression is only applicable for cases similar to + // var f = function asdf(a,b) { mymod.controller("asdf", asdf) }; + return bound; + } + + // other kinds should not be handled ("param", "caught") + + return null; +} + +function judgeInjectArraySuspect(path, ctx) { + let node = path.node; + + if (t.isVariableDeclaration(node)) { + // suspect can only be a VariableDeclaration (statement) in case of + // explicitly marked via /*@ngInject*/, not via references because + // references follow to VariableDeclarator (child) + + // /*@ngInject*/ var foo = function($scope) {} and + + if (node.declarations.length !== 1) { + // more than one declarator => exit + return; + } + + // one declarator => jump over declaration into declarator + // rest of code will treat it as any (referenced) declarator + path = path.get("declarations")[0]; + node = path.node; + } + + // onode is a top-level node (inside function block), later verified + // node is inner match, descent in multiple steps + let opath = null; + let declaratorName = null; + if (t.isVariableDeclarator(node)) { + opath = path.parentPath; + + declaratorName = node.id.name; + node = node.init; // var foo = ___; + path = path.get("init"); + } else { + opath = path; + } + + if(t.isExportDeclaration(opath.parent)){ + opath = opath.parentPath; + } + + // suspect must be inside of a block or at the top-level (i.e. inside of node.$parent.body[]) + if (!node || !opath.parent || (!t.isProgram(opath.parent) && !t.isBlockStatement(opath.parent))) { + return; + } + + path = jumpOverIife(path); + node = path.node; + + if (t.isClass(node)){ + declaratorName = node.id.name; + node = getConstructor(node); + } + + if (isFunctionExpressionWithArgs(node) || t.isClassMethod(node)) { + // var x = 1, y = function(a,b) {}, z; + + if(node.id && node.id.name !== declaratorName){ + console.warn("Declarator name different", declaratorName); + } + + assert(declaratorName); + addInjectArrayAfterPath(node.params, opath, declaratorName); + + } else if (isFunctionDeclarationWithArgs(node)) { + // /*@ngInject*/ function foo($scope) {} + addInjectArrayBeforePath(node.params,path,node.id.name); + + } else if (t.isExpressionStatement(node) && t.isAssignmentExpression(node.expression) && + isFunctionExpressionWithArgs(node.expression.right) && !path.get("expression.right").$seen) { + // /*@ngInject*/ foo.bar[0] = function($scope) {} + let inject = buildInjectExpression(node.expression.right.params, t.cloneDeep(node.expression.left)); + path.insertAfter(inject); + + } else if (path = followReference(path)) { + // node was a reference and followed node now is either a + // FunctionDeclaration or a VariableDeclarator + // => recurse + + !path.$seen && judgeInjectArraySuspect(path, ctx); + } + + function buildInjectExpression(params, name){ + let left = t.isNode(name) ? name : t.identifier(name); + let paramStrings = params.map(param => t.stringLiteral(param.name)); + let arr = t.arrayExpression(paramStrings); // ["$scope"] + let member = t.memberExpression(left, t.identifier("$inject")); // foo.$inject = + return t.expressionStatement(t.assignmentExpression("=", member , arr)); + } + + function addInjectArrayBeforePath(params, path, name){ + const binding = path.scope.getBinding(name); + if(binding && binding.kind === 'hoisted'){ + // let block = t.isProgram(binding.scope.block) ? binding.scope.block : binding.scope.block.body; + // block.body.unshift(buildInjectExpression(params, name)); + let expr = buildInjectExpression(params, name); + let block = binding.scope.getBlockParent().path; + if(block.isFunction()){ + block = block.get("body"); + } + block.unshiftContainer("body", [expr]); + } else { + path.insertBefore(buildInjectExpression(params, name)); + } + } + + function addInjectArrayAfterPath(params, path, name){ + let trailingComments; + if(path.node.trailingComments){ + trailingComments = path.node.trailingComments; + path.node.trailingComments = []; + } + let newNode = path.insertAfter(buildInjectExpression(params, name)); + newNode.trailingComments = trailingComments; + } + +} + +function jumpOverIife(path) { + const node = path.node; + if(!path.node){ + console.warn("Not a path"); + } + + if (!(t.isCallExpression(node) && isFunctionExpressionOrArrow(node.callee))) { + return path; + } + + const outerbody = path.get("callee.body.body"); + for (let i = 0; i < outerbody.length; i++) { + const statement = outerbody[i]; + if (t.isReturnStatement(statement)) { + return statement.get("argument"); + } + } + + return path; +} + +function addModuleContextDependentSuspect(target, ctx) { + ctx.suspects.push(target); +} + +function addModuleContextIndependentSuspect(target, ctx) { + target.node.$chained = chainedRegular; + ctx.suspects.push(target); +} + +function isFunctionExpressionOrArrow(node) { + return t.isFunctionExpression(node) || t.isArrowFunctionExpression(node); +} + +function isFunctionExpressionWithArgs(node) { + return isFunctionExpressionOrArrow(node) && node.params.length >= 1; +} +function isFunctionDeclarationWithArgs(node) { + return t.isFunctionDeclaration(node) && node.params.length >= 1; +} +function isGenericProviderName(node) { + return t.isLiteral(node) && is.string(node.value); +} + +function getConstructor(node){ + var body = node.body.body; + for(var i=0; i< body.length; i++){ + let node = body[i]; + if(node.kind === 'constructor'){ + return node; + } + } +} + +module.exports.match = match; +module.exports.addModuleContextDependentSuspect = addModuleContextDependentSuspect; +module.exports.addModuleContextIndependentSuspect = addModuleContextIndependentSuspect; +module.exports.judgeSuspects = judgeSuspects; +module.exports.matchDirectiveReturnObject = matchDirectiveReturnObject; +module.exports.matchProviderGet = matchProviderGet; + +},{"./nginject":8,"./scopetools":439,"assert":1,"babel-types":157,"simple-is":434}],8:[function(require,module,exports){ +// nginject.js +// MIT licensed, see LICENSE file +// Copyright (c) 2013-2016 Olov Lassus + +"use strict"; + +const is = require("simple-is"); +const t = require('babel-types'); + +module.exports = { + inspectComment: inspectComment, + inspectCallExpression: inspectCallExpression, + inspectFunction: inspectFunction, + inspectObjectExpression: inspectObjectExpression, + inspectAssignment: inspectAssignment, + inspectDeclarator: inspectDeclarator, + inspectClassDeclaration: inspectClassDeclaration, + inspectClassMethod: inspectClassMethod, + inspectExportDeclaration: inspectExportDeclaration +}; + +function inspectCallExpression(path, ctx) { + const node = path.node; + const name = node.callee.name; + if(inspectComment(path, ctx)){ + return false; + } + if (t.isIdentifier(node.callee) && (name === "ngInject" || name === "ngNoInject") && node.arguments.length === 1) { + const block = (name === "ngNoInject"); + addSuspect(path.get("arguments")[0], ctx, block); + } + + path.get("arguments").forEach(arg => { + let annotation = getAnnotation(arg.node); + if(!t.isIdentifier(arg) || annotation === null){ + return; + } + let binding = path.scope.getBinding(arg.node.name); + if(binding){ + addSuspect(binding.path, ctx, !annotation); + } + }); +} + +function inspectFunction(path, ctx) { + const node = path.node; + + if(t.isVariableDeclarator(path.parent) && t.isVariableDeclaration(path.parentPath.parent)){ + let annotation = getAnnotation(path.parentPath.parent); + if(annotation === null){ + annotation = getAnnotation(node); + } + if(annotation !== null){ + addSuspect(path.parentPath.parentPath, ctx, !annotation); + return; + } + } + + if(inspectComment(path, ctx)){ + return; + } + + const annotate = matchPrologueDirectives(path); + if (annotate === null) { + return; + } + + // now add the correct suspect + + // for function declarations, it is always the function declaration node itself + if (t.isFunctionDeclaration(node)) { + addSuspect(path, ctx, !annotate); + return; + } + + // node is a function expression below + + // case 1: a function expression which is the rhs of a variable declarator, such as + // var f1 = function(a) { + // "ngInject" + // }; + // in this case we can mark the declarator, same as saying var /*@ngInject*/ f1 = function(a) .. + // or /*@ngInject*/ var f1 = function(a) .. + // f1.$inject = ["a"]; will be added (or rebuilt/removed) + if (t.isVariableDeclarator(path.parent)) { + addSuspect(path.parentPath, ctx, !annotate); + return; + } + + // case 2: an anonymous function expression, such as + // g(function(a) { + // "ngInject" + // }); + // + // the suspect is now its parent annotated array (if any), otherwise itself + // there is a risk of false suspects here, in case the parent annotated array has nothing to do + // with annotations. the risk should be very low and hopefully easy to workaround + // + // added/rebuilt/removed => g(["a", function(a) { + // "ngInject" + // }]); + const maybeArrayExpression = path.parent; + if (isAnnotatedArray(maybeArrayExpression)) { + addSuspect(path.parentPath, ctx, !annotate); + } else { + addSuspect(path, ctx, !annotate); + } +} + +function inspectComment(path, ctx) { + const node = path.node; + + let annotation = getAnnotation(node); + if(annotation !== null){ + addSuspect(path, ctx, !annotation); + return true; + } +} + +function getAnnotation(node){ + if(!node.leadingComments){ + return null; + } + + for(var i=0; i isFunctionExpressionOrArrow(prop.node.value)) + .forEach(prop => inspectComment(prop, ctx)); + } + + // path.get("properties").forEach(prop => { + // if(t.isObjectExpression(prop.node.value)){ + // inspectObjectExpression(prop.get("value"), ctx); + // return; + // } + + // let annotation = getAnnotation(prop.node); + // if(annotation !== null || annotateEverything !== null){ + // let effectiveAnnotation = annotation === null ? annotateEverything : annotation; + // addSuspect(prop.get("value"), ctx, !effectiveAnnotation); + // } + // }); +} + +function matchPrologueDirectives(path) { + const prologueDirectives = ["ngInject", "ngNoInject"]; + const directives = path.node.body.directives || []; + let matches = directives.map(dir => dir.value.value) + .filter(val => prologueDirectives.indexOf(val) !== -1); + + if(matches.length){ + let match = matches[0].trim(); + if(match === "ngInject") return true; + if(match === "ngNoInject") return false; + } + + return null; +} + +function inspectAssignment(path, ctx){ + const node = path.node; + if(!isFunctionExpressionOrArrow(node.right)){ + return; + } + + var candidates = [path.node, node.right]; + if(t.isExpressionStatement(path.parent)){ + candidates.unshift(path.parent); + path = path.parentPath; + } + + let annotation = getAnnotations(candidates); + if(annotation !== null){ + addSuspect(path, ctx, !annotation); + } +} + +function inspectDeclarator(path, ctx){ + const node = path.node; + if(!isFunctionExpressionOrArrow(node.init)){ + return; + } + + var candidates = [node, node.init]; + if(t.isVariableDeclaration(path.parent)){ + path = path.parentPath; + } else { + console.error("not a variable declaration"); + } + + let annotation = getAnnotations(candidates); + if(annotation !== null){ + addSuspect(path, ctx, !annotation); + } +} + +function inspectClassDeclaration(path, ctx){ + const node = path.node; + let annotation = getAnnotation(node); + if(annotation !== null){ + addSuspect(path, ctx, !annotation); + } +} + +function inspectClassMethod(path, ctx){ + const node = path.node; + + if(node.kind !== 'constructor'){ + return; + } + + let annotation = getAnnotation(path.node); + if(annotation === null){ + annotation = matchPrologueDirectives(path); + if(annotation === null) { + return; + } + } + + const ancestry = path.getAncestry(); + for(var i=0; i < ancestry.length; i++){ + let ancestor = ancestry[i]; + if(ancestor.isClassDeclaration()){ + addSuspect(ancestor, ctx, !annotation); + return; + } + } +} + +function inspectExportDeclaration(path, ctx){ + let annotation = getAnnotation(path.node); + if(annotation === null){ + return; + } + addSuspect(path.get('declaration'), ctx, !annotation); +} + +function isStringArray(node) { + if (!t.isArrayExpression(node)) { + return false; + } + return node.elements.length >= 1 && node.elements.every(function(n) { + return t.isLiteral(n) && is.string(n.value); + }); +} + +function findNextStatement(path) { + const body = path.parentPath.get("body"); + for (let i = 0; i < body.length; i++) { + if (body[i].path === path.node) { + return body[i + 1] || null; + } + } + return null; +} + +function addSuspect(path, ctx, block) { + const target = path.node; + if (t.isExpressionStatement(target) && t.isAssignmentExpression(target.expression) && isStringArray(target.expression.right)) { + // /*@ngInject*/ + // FooBar.$inject = ["$a", "$b"]; + // function FooBar($a, $b) {} + const adjustedTarget = findNextStatement(path); + if (adjustedTarget) { + return addSuspect(adjustedTarget, ctx, block); + } + } + + if (t.isObjectExpression(path)) { + // /*@ngInject*/ {f1: function(a), .., {f2: function(b)}} + addObjectExpression(path, ctx); + } else if (t.isAssignmentExpression(target) && t.isObjectExpression(target.right)) { + // /*@ngInject*/ f(x.y = {f1: function(a), .., {f2: function(b)}}) + addObjectExpression(target.get("right"), ctx); + } else if (t.isExpressionStatement(target) && t.isAssignmentExpression(target.expression) && t.isObjectExpression(target.expression.right)) { + // /*@ngInject*/ x.y = {f1: function(a), .., {f2: function(b)}} + addObjectExpression(target.get("expression.right"), ctx); + } else if (t.isVariableDeclaration(target) && target.declarations.length === 1 && target.declarations[0].init && t.isObjectExpression(target.declarations[0].init)) { + // /*@ngInject*/ var x = {f1: function(a), .., {f2: function(b)}} + addObjectExpression(target.get("declarations")[0].get("init"), ctx); + } else if (t.isProperty(target)) { + // {/*@ngInject*/ justthisone: function(a), ..} + let value = path.get("value"); + value.$limitToMethodName = "*never*"; + addOrBlock(value, ctx); + } else { + // /*@ngInject*/ function(a) {} + path.$limitToMethodName = "*never*"; + addOrBlock(path, ctx); + } + + + function addObjectExpression(path, ctx) { + nestedObjectValues(path).forEach(function(n) { + n.$limitToMethodName = "*never*"; + addOrBlock(n, ctx); + }); + } + + function addOrBlock(path, ctx) { + if (block) { + ctx.blocked.push(path); + } else { + ctx.addModuleContextIndependentSuspect(path, ctx) + } + } +} + +function nestedObjectValues(path, res) { + res = res || []; + + path.get("properties").forEach(function(prop) { + const v = prop.get("value"); + if (isFunctionExpressionOrArrow(v) || t.isArrayExpression(v)) { + res.push(v); + } else if (t.isObjectExpression(v)) { + nestedObjectValues(v, res); + } + }); + + return res; +} + +function isAnnotatedArray(node) { + if (!t.isArrayExpression(node)) { + return false; + } + const elements = node.elements; + + // last should be a function expression + if (elements.length === 0 || !isFunctionExpressionOrArrow(last(elements))) { + return false; + } + + // all but last should be string literals + for (let i = 0; i < elements.length - 1; i++) { + const n = elements[i]; + if (!t.isLiteral(n) || !is.string(n.value)) { + return false; + } + } + + return true; +} + +function isFunctionExpressionOrArrow(node) { + return t.isFunctionExpression(node) || t.isArrowFunctionExpression(node); +} + +},{"babel-types":157,"simple-is":434}],9:[function(require,module,exports){ +'use strict'; +module.exports = function () { + return /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; +}; + +},{}],10:[function(require,module,exports){ +'use strict'; + +function assembleStyles () { + var styles = { + modifiers: { + reset: [0, 0], + bold: [1, 22], // 21 isn't widely supported and 22 does the same thing + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + colors: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39] + }, + bgColors: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49] + } + }; + + // fix humans + styles.colors.grey = styles.colors.gray; + + Object.keys(styles).forEach(function (groupName) { + var group = styles[groupName]; + + Object.keys(group).forEach(function (styleName) { + var style = group[styleName]; + + styles[styleName] = group[styleName] = { + open: '\u001b[' + style[0] + 'm', + close: '\u001b[' + style[1] + 'm' + }; + }); + + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + }); + + return styles; +} + +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); + +},{}],11:[function(require,module,exports){ +/*istanbul ignore next*/"use strict"; + +exports.__esModule = true; + +exports.default = function (rawLines, lineNumber, colNumber) { + /*istanbul ignore next*/var opts = arguments.length <= 3 || arguments[3] === undefined ? {} : arguments[3]; + + colNumber = Math.max(colNumber, 0); + + var highlighted = opts.highlightCode && /*istanbul ignore next*/_chalk2.default.supportsColor; + if (highlighted) rawLines = highlight(rawLines); + + var lines = rawLines.split(NEWLINE); + var start = Math.max(lineNumber - 3, 0); + var end = Math.min(lines.length, lineNumber + 3); + + if (!lineNumber && !colNumber) { + start = 0; + end = lines.length; + } + + var numberMaxWidth = String(end).length; + + var frame = lines.slice(start, end).map(function (line, index) { + var number = start + 1 + index; + var paddedNumber = /*istanbul ignore next*/(" " + number).slice(-numberMaxWidth); + var gutter = /*istanbul ignore next*/" " + paddedNumber + " | "; + if (number === lineNumber) { + var markerLine = ""; + if (colNumber) { + var markerSpacing = line.slice(0, colNumber - 1).replace(/[^\t]/g, " "); + markerLine = /*istanbul ignore next*/"\n " + gutter.replace(/\d/g, " ") + markerSpacing + "^"; + } + return (/*istanbul ignore next*/">" + gutter + line + markerLine + ); + } else { + return (/*istanbul ignore next*/" " + gutter + line + ); + } + }).join("\n"); + + if (highlighted) { + return (/*istanbul ignore next*/_chalk2.default.reset(frame) + ); + } else { + return frame; + } +}; + +var /*istanbul ignore next*/_jsTokens = require("js-tokens"); + +/*istanbul ignore next*/ +var _jsTokens2 = _interopRequireDefault(_jsTokens); + +var /*istanbul ignore next*/_esutils = require("esutils"); + +/*istanbul ignore next*/ +var _esutils2 = _interopRequireDefault(_esutils); + +var /*istanbul ignore next*/_chalk = require("chalk"); + +/*istanbul ignore next*/ +var _chalk2 = _interopRequireDefault(_chalk); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Chalk styles for token types. + */ + +var defs = { + string: /*istanbul ignore next*/_chalk2.default.red, + punctuator: /*istanbul ignore next*/_chalk2.default.bold, + curly: /*istanbul ignore next*/_chalk2.default.green, + parens: /*istanbul ignore next*/_chalk2.default.blue.bold, + square: /*istanbul ignore next*/_chalk2.default.yellow, + keyword: /*istanbul ignore next*/_chalk2.default.cyan, + number: /*istanbul ignore next*/_chalk2.default.magenta, + regex: /*istanbul ignore next*/_chalk2.default.magenta, + comment: /*istanbul ignore next*/_chalk2.default.grey, + invalid: /*istanbul ignore next*/_chalk2.default.inverse +}; + +/** + * RegExp to test for newlines in terminal. + */ + +var NEWLINE = /\r\n|[\n\r\u2028\u2029]/; + +/** + * Get the type of token, specifying punctuator type. + */ + +function getTokenType(match) { + var token = /*istanbul ignore next*/_jsTokens2.default.matchToToken(match); + if (token.type === "name" && /*istanbul ignore next*/_esutils2.default.keyword.isReservedWordES6(token.value)) { + return "keyword"; + } + + if (token.type === "punctuator") { + switch (token.value) { + case "{": + case "}": + return "curly"; + case "(": + case ")": + return "parens"; + case "[": + case "]": + return "square"; + } + } + + return token.type; +} + +/** + * Highlight `text`. + */ + +function highlight(text) { + return text.replace( /*istanbul ignore next*/_jsTokens2.default, function () { + /*istanbul ignore next*/ + for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } + + var type = getTokenType(args); + var colorize = defs[type]; + if (colorize) { + return args[0].split(NEWLINE).map(function (str) /*istanbul ignore next*/{ + return colorize(str); + }).join("\n"); + } else { + return args[0]; + } + }); +} + +/** + * Create a code frame, adding line numbers, code highlighting, and pointing to a given position. + */ + +/*istanbul ignore next*/module.exports = exports["default"]; +},{"chalk":249,"esutils":256,"js-tokens":261}],12:[function(require,module,exports){ +/*istanbul ignore next*/"use strict"; + +exports.__esModule = true; +exports.MESSAGES = undefined; + +var _stringify = require("babel-runtime/core-js/json/stringify"); + +var _stringify2 = _interopRequireDefault(_stringify); + +exports.get = get; +/*istanbul ignore next*/exports.parseArgs = parseArgs; + +var /*istanbul ignore next*/_util = require("util"); + +/*istanbul ignore next*/ +var util = _interopRequireWildcard(_util); + +/*istanbul ignore next*/ +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Mapping of messages to be used in Babel. + * Messages can include $0-style placeholders. + */ + +var MESSAGES = /*istanbul ignore next*/exports.MESSAGES = { + tailCallReassignmentDeopt: "Function reference has been reassigned, so it will probably be dereferenced, therefore we can't optimise this with confidence", + classesIllegalBareSuper: "Illegal use of bare super", + classesIllegalSuperCall: "Direct super call is illegal in non-constructor, use super.$1() instead", + scopeDuplicateDeclaration: "Duplicate declaration $1", + settersNoRest: "Setters aren't allowed to have a rest", + noAssignmentsInForHead: "No assignments allowed in for-in/of head", + expectedMemberExpressionOrIdentifier: "Expected type MemberExpression or Identifier", + invalidParentForThisNode: "We don't know how to handle this node within the current parent - please open an issue", + readOnly: "$1 is read-only", + unknownForHead: "Unknown node type $1 in ForStatement", + didYouMean: "Did you mean $1?", + codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2.", + missingTemplatesDirectory: "no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/babel/babel/issues", + unsupportedOutputType: "Unsupported output type $1", + illegalMethodName: "Illegal method name $1", + lostTrackNodePath: "We lost track of this node's position, likely because the AST was directly manipulated", + + modulesIllegalExportName: "Illegal export $1", + modulesDuplicateDeclarations: "Duplicate module declarations with the same source but in different scopes", + + undeclaredVariable: "Reference to undeclared variable $1", + undeclaredVariableType: "Referencing a type alias outside of a type annotation", + undeclaredVariableSuggestion: "Reference to undeclared variable $1 - did you mean $2?", + + traverseNeedsParent: "You must pass a scope and parentPath unless traversing a Program/File. Instead of that you tried to traverse a $1 node without passing scope and parentPath.", + traverseVerifyRootFunction: "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?", + traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2", + traverseVerifyNodeType: "You gave us a visitor for the node type $1 but it's not a valid type", + + pluginNotObject: "Plugin $2 specified in $1 was expected to return an object when invoked but returned $3", + pluginNotFunction: "Plugin $2 specified in $1 was expected to return a function but returned $3", + pluginUnknown: "Unknown plugin $1 specified in $2 at $3, attempted to resolve relative to $4", + pluginInvalidProperty: "Plugin $2 specified in $1 provided an invalid property of $3" +}; + +/** + * Get a message with $0 placeholders replaced by arguments. + */ + +/* eslint max-len: 0 */ + +function get(key) { + /*istanbul ignore next*/ + for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { + args[_key - 1] = arguments[_key]; + } + + var msg = MESSAGES[key]; + if (!msg) throw new ReferenceError( /*istanbul ignore next*/"Unknown message " + /*istanbul ignore next*/(0, _stringify2.default)(key)); + + // stringify args + args = parseArgs(args); + + // replace $0 placeholders with args + return msg.replace(/\$(\d+)/g, function (str, i) { + return args[i - 1]; + }); +} + +/** + * Stingify arguments to be used inside messages. + */ + +function parseArgs(args) { + return args.map(function (val) { + if (val != null && val.inspect) { + return val.inspect(); + } else { + try { + return (/*istanbul ignore next*/(0, _stringify2.default)(val) || val + "" + ); + } catch (e) { + return util.inspect(val); + } + } + }); +} +},{"babel-runtime/core-js/json/stringify":13,"util":5}],13:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/json/stringify"), __esModule: true }; +},{"core-js/library/fn/json/stringify":14}],14:[function(require,module,exports){ +var core = require('../../modules/_core') + , $JSON = core.JSON || (core.JSON = {stringify: JSON.stringify}); +module.exports = function stringify(it){ // eslint-disable-line no-unused-vars + return $JSON.stringify.apply($JSON, arguments); +}; +},{"../../modules/_core":15}],15:[function(require,module,exports){ +var core = module.exports = {version: '2.4.0'}; +if(typeof __e == 'number')__e = core; // eslint-disable-line no-undef +},{}],16:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.scope = exports.path = undefined; + +var _weakMap = require("babel-runtime/core-js/weak-map"); + +var _weakMap2 = _interopRequireDefault(_weakMap); + +exports.clear = clear; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var path = exports.path = new _weakMap2.default(); +var scope = exports.scope = new _weakMap2.default(); + +function clear() { + exports.path = path = new _weakMap2.default(); + exports.scope = scope = new _weakMap2.default(); +} +},{"babel-runtime/core-js/weak-map":48}],17:[function(require,module,exports){ +(function (process){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _path2 = require("./path"); + +var _path3 = _interopRequireDefault(_path2); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var testing = process.env.NODE_ENV === "test"; + +var TraversalContext = function () { + function TraversalContext(scope, opts, state, parentPath) { + (0, _classCallCheck3.default)(this, TraversalContext); + this.queue = null; + + this.parentPath = parentPath; + this.scope = scope; + this.state = state; + this.opts = opts; + } + + /** + * This method does a simple check to determine whether or not we really need to attempt + * visit a node. This will prevent us from constructing a NodePath. + */ + + TraversalContext.prototype.shouldVisit = function shouldVisit(node) { + var opts = this.opts; + if (opts.enter || opts.exit) return true; + + // check if we have a visitor for this node + if (opts[node.type]) return true; + + // check if we're going to traverse into this node + var keys = t.VISITOR_KEYS[node.type]; + if (!keys || !keys.length) return false; + + // we need to traverse into this node so ensure that it has children to traverse into! + for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var key = _ref; + + if (node[key]) return true; + } + + return false; + }; + + TraversalContext.prototype.create = function create(node, obj, key, listKey) { + return _path3.default.get({ + parentPath: this.parentPath, + parent: node, + container: obj, + key: key, + listKey: listKey + }); + }; + + TraversalContext.prototype.maybeQueue = function maybeQueue(path, notPriority) { + if (this.trap) { + throw new Error("Infinite cycle detected"); + } + + if (this.queue) { + if (notPriority) { + this.queue.push(path); + } else { + this.priorityQueue.push(path); + } + } + }; + + TraversalContext.prototype.visitMultiple = function visitMultiple(container, parent, listKey) { + // nothing to traverse! + if (container.length === 0) return false; + + var queue = []; + + // build up initial queue + for (var key = 0; key < container.length; key++) { + var node = container[key]; + if (node && this.shouldVisit(node)) { + queue.push(this.create(parent, container, key, listKey)); + } + } + + return this.visitQueue(queue); + }; + + TraversalContext.prototype.visitSingle = function visitSingle(node, key) { + if (this.shouldVisit(node[key])) { + return this.visitQueue([this.create(node, node, key)]); + } else { + return false; + } + }; + + TraversalContext.prototype.visitQueue = function visitQueue(queue) { + // set queue + this.queue = queue; + this.priorityQueue = []; + + var visited = []; + var stop = false; + + // visit the queue + for (var _iterator2 = queue, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var path = _ref2; + + path.resync(); + + if (path.contexts.length === 0 || path.contexts[path.contexts.length - 1] !== this) { + // The context might already have been pushed when this path was inserted and queued. + // If we always re-pushed here, we could get duplicates and risk leaving contexts + // on the stack after the traversal has completed, which could break things. + path.pushContext(this); + } + + // this path no longer belongs to the tree + if (path.key === null) continue; + + if (testing && queue.length >= 1000) { + this.trap = true; + } + + // ensure we don't visit the same node twice + if (visited.indexOf(path.node) >= 0) continue; + visited.push(path.node); + + if (path.visit()) { + stop = true; + break; + } + + if (this.priorityQueue.length) { + stop = this.visitQueue(this.priorityQueue); + this.priorityQueue = []; + this.queue = queue; + if (stop) break; + } + } + + // clear queue + for (var _iterator3 = queue, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var _path = _ref3; + + _path.popContext(); + } + + // clear queue + this.queue = null; + + return stop; + }; + + TraversalContext.prototype.visit = function visit(node, key) { + var nodes = node[key]; + if (!nodes) return false; + + if (Array.isArray(nodes)) { + return this.visitMultiple(nodes, node, key); + } else { + return this.visitSingle(node, key); + } + }; + + return TraversalContext; +}(); + +exports.default = TraversalContext; +module.exports = exports["default"]; +}).call(this,require('_process')) +},{"./path":26,"_process":3,"babel-runtime/core-js/get-iterator":41,"babel-runtime/helpers/classCallCheck":49,"babel-types":157}],18:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var Hub = function Hub(file, options) { + (0, _classCallCheck3.default)(this, Hub); + + this.file = file; + this.options = options; +}; + +exports.default = Hub; +module.exports = exports["default"]; +},{"babel-runtime/helpers/classCallCheck":49}],19:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.visitors = exports.Hub = exports.Scope = exports.NodePath = undefined; + +var _getOwnPropertySymbols = require("babel-runtime/core-js/object/get-own-property-symbols"); + +var _getOwnPropertySymbols2 = _interopRequireDefault(_getOwnPropertySymbols); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _path = require("./path"); + +Object.defineProperty(exports, "NodePath", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_path).default; + } +}); + +var _scope = require("./scope"); + +Object.defineProperty(exports, "Scope", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_scope).default; + } +}); + +var _hub = require("./hub"); + +Object.defineProperty(exports, "Hub", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_hub).default; + } +}); +exports.default = traverse; + +var _context = require("./context"); + +var _context2 = _interopRequireDefault(_context); + +var _visitors = require("./visitors"); + +var visitors = _interopRequireWildcard(_visitors); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _includes = require("lodash/includes"); + +var _includes2 = _interopRequireDefault(_includes); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _cache = require("./cache"); + +var cache = _interopRequireWildcard(_cache); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.visitors = visitors; +function traverse(parent, opts, scope, state, parentPath) { + if (!parent) return; + if (!opts) opts = {}; + + if (!opts.noScope && !scope) { + if (parent.type !== "Program" && parent.type !== "File") { + throw new Error(messages.get("traverseNeedsParent", parent.type)); + } + } + + visitors.explode(opts); + + traverse.node(parent, opts, scope, state, parentPath); +} + +traverse.visitors = visitors; +traverse.verify = visitors.verify; +traverse.explode = visitors.explode; + +traverse.NodePath = require("./path"); +traverse.Scope = require("./scope"); +traverse.Hub = require("./hub"); + +traverse.cheap = function (node, enter) { + if (!node) return; + + var keys = t.VISITOR_KEYS[node.type]; + if (!keys) return; + + enter(node); + + for (var _iterator = keys, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var key = _ref; + + var subNode = node[key]; + + if (Array.isArray(subNode)) { + for (var _iterator2 = subNode, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _node = _ref2; + + traverse.cheap(_node, enter); + } + } else { + traverse.cheap(subNode, enter); + } + } +}; + +traverse.node = function (node, opts, scope, state, parentPath, skipKeys) { + var keys = t.VISITOR_KEYS[node.type]; + if (!keys) return; + + var context = new _context2.default(scope, opts, state, parentPath); + for (var _iterator3 = keys, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var key = _ref3; + + if (skipKeys && skipKeys[key]) continue; + if (context.visit(node, key)) return; + } +}; + +var CLEAR_KEYS = t.COMMENT_KEYS.concat(["tokens", "comments", "start", "end", "loc", "raw", "rawValue"]); + +traverse.clearNode = function (node) { + for (var _iterator4 = CLEAR_KEYS, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref4; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref4 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref4 = _i4.value; + } + + var _key = _ref4; + + if (node[_key] != null) node[_key] = undefined; + } + + for (var key in node) { + if (key[0] === "_" && node[key] != null) node[key] = undefined; + } + + cache.path.delete(node); + + var syms = (0, _getOwnPropertySymbols2.default)(node); + for (var _iterator5 = syms, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) { + var _ref5; + + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref5 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref5 = _i5.value; + } + + var sym = _ref5; + + node[sym] = null; + } +}; + +traverse.removeProperties = function (tree) { + traverse.cheap(tree, traverse.clearNode); + return tree; +}; + +function hasBlacklistedType(path, state) { + if (path.node.type === state.type) { + state.has = true; + path.stop(); + } +} + +traverse.hasType = function (tree, scope, type, blacklistTypes) { + // the node we're searching in is blacklisted + if ((0, _includes2.default)(blacklistTypes, tree.type)) return false; + + // the type we're looking for is the same as the passed node + if (tree.type === type) return true; + + var state = { + has: false, + type: type + }; + + traverse(tree, { + blacklist: blacklistTypes, + enter: hasBlacklistedType + }, scope, state); + + return state.has; +}; + +traverse.clearCache = function () { + cache.clear(); +}; + +traverse.copyCache = function (source, destination) { + if (cache.path.has(source)) { + cache.path.set(destination, cache.path.get(source)); + } +}; +},{"./cache":16,"./context":17,"./hub":18,"./path":26,"./scope":38,"./visitors":40,"babel-messages":12,"babel-runtime/core-js/get-iterator":41,"babel-runtime/core-js/object/get-own-property-symbols":44,"babel-types":157,"lodash/includes":402}],20:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.findParent = findParent; +exports.find = find; +exports.getFunctionParent = getFunctionParent; +exports.getStatementParent = getStatementParent; +exports.getEarliestCommonAncestorFrom = getEarliestCommonAncestorFrom; +exports.getDeepestCommonAncestorFrom = getDeepestCommonAncestorFrom; +exports.getAncestry = getAncestry; +exports.inType = inType; +exports.inShadow = inShadow; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Call the provided `callback` with the `NodePath`s of all the parents. + * When the `callback` returns a truthy value, we return that node path. + */ + +// This file contains that retrieve or validate anything related to the current paths ancestry. + +function findParent(callback) { + var path = this; + while (path = path.parentPath) { + if (callback(path)) return path; + } + return null; +} + +/** + * Description + */ + +function find(callback) { + var path = this; + do { + if (callback(path)) return path; + } while (path = path.parentPath); + return null; +} + +/** + * Get the parent function of the current path. + */ + +function getFunctionParent() { + return this.findParent(function (path) { + return path.isFunction() || path.isProgram(); + }); +} + +/** + * Walk up the tree until we hit a parent node path in a list. + */ + +function getStatementParent() { + var path = this; + do { + if (Array.isArray(path.container)) { + return path; + } + } while (path = path.parentPath); +} + +/** + * Get the deepest common ancestor and then from it, get the earliest relationship path + * to that ancestor. + * + * Earliest is defined as being "before" all the other nodes in terms of list container + * position and visiting key. + */ + +function getEarliestCommonAncestorFrom(paths) { + return this.getDeepestCommonAncestorFrom(paths, function (deepest, i, ancestries) { + var earliest = void 0; + var keys = t.VISITOR_KEYS[deepest.type]; + + for (var _iterator = ancestries, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var ancestry = _ref; + + var path = ancestry[i + 1]; + + // first path + if (!earliest) { + earliest = path; + continue; + } + + // handle containers + if (path.listKey && earliest.listKey === path.listKey) { + // we're in the same container so check if we're earlier + if (path.key < earliest.key) { + earliest = path; + continue; + } + } + + // handle keys + var earliestKeyIndex = keys.indexOf(earliest.parentKey); + var currentKeyIndex = keys.indexOf(path.parentKey); + if (earliestKeyIndex > currentKeyIndex) { + // key appears before so it's earlier + earliest = path; + } + } + + return earliest; + }); +} + +/** + * Get the earliest path in the tree where the provided `paths` intersect. + * + * TODO: Possible optimisation target. + */ + +function getDeepestCommonAncestorFrom(paths, filter) { + var _this = this; + + if (!paths.length) { + return this; + } + + if (paths.length === 1) { + return paths[0]; + } + + // minimum depth of the tree so we know the highest node + var minDepth = Infinity; + + // last common ancestor + var lastCommonIndex = void 0, + lastCommon = void 0; + + // get the ancestors of the path, breaking when the parent exceeds ourselves + var ancestries = paths.map(function (path) { + var ancestry = []; + + do { + ancestry.unshift(path); + } while ((path = path.parentPath) && path !== _this); + + // save min depth to avoid going too far in + if (ancestry.length < minDepth) { + minDepth = ancestry.length; + } + + return ancestry; + }); + + // get the first ancestry so we have a seed to assess all other ancestries with + var first = ancestries[0]; + + // check ancestor equality + depthLoop: for (var i = 0; i < minDepth; i++) { + var shouldMatch = first[i]; + + for (var _iterator2 = ancestries, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var ancestry = _ref2; + + if (ancestry[i] !== shouldMatch) { + // we've hit a snag + break depthLoop; + } + } + + // next iteration may break so store these so they can be returned + lastCommonIndex = i; + lastCommon = shouldMatch; + } + + if (lastCommon) { + if (filter) { + return filter(lastCommon, lastCommonIndex, ancestries); + } else { + return lastCommon; + } + } else { + throw new Error("Couldn't find intersection"); + } +} + +/** + * Build an array of node paths containing the entire ancestry of the current node path. + * + * NOTE: The current node path is included in this. + */ + +function getAncestry() { + var path = this; + var paths = []; + do { + paths.push(path); + } while (path = path.parentPath); + return paths; +} + +function inType() { + var path = this; + while (path) { + for (var _iterator3 = arguments, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var type = _ref3; + + if (path.node.type === type) return true; + } + path = path.parentPath; + } + + return false; +} + +/** + * Checks whether the binding for 'key' is a local binding in its current function context. + * + * Checks if the current path either is, or has a direct parent function that is, inside + * of a function that is marked for shadowing of a binding matching 'key'. Also returns + * the parent path if the parent path is an arrow, since arrow functions pass through + * binding values to their parent, meaning they have no local bindings. + * + * Shadowing means that when the given binding is transformed, it will read the binding + * value from the container containing the shadow function, rather than from inside the + * shadow function. + * + * Function shadowing is acheieved by adding a "shadow" property on "FunctionExpression" + * and "FunctionDeclaration" node types. + * + * Node's "shadow" props have the following behavior: + * + * - Boolean true will cause the function to shadow both "this" and "arguments". + * - {this: false} Shadows "arguments" but not "this". + * - {arguments: false} Shadows "this" but not "arguments". + * + * Separately, individual identifiers can be flagged with two flags: + * + * - _forceShadow - If truthy, this specific identifier will be bound in the closest + * Function that is not flagged "shadow", or the Program. + * - _shadowedFunctionLiteral - When set to a NodePath, this specific identifier will be bound + * to this NodePath/Node or the Program. If this path is not found relative to the + * starting location path, the closest function will be used. + * + * Please Note, these flags are for private internal use only and should be avoided. + * Only "shadow" is a public property that other transforms may manipulate. + */ + +function inShadow(key) { + var parentFn = this.isFunction() ? this : this.findParent(function (p) { + return p.isFunction(); + }); + if (!parentFn) return; + + if (parentFn.isFunctionExpression() || parentFn.isFunctionDeclaration()) { + var shadow = parentFn.node.shadow; + + // this is because sometimes we may have a `shadow` value of: + // + // { this: false } + // + // we need to catch this case if `inShadow` has been passed a `key` + if (shadow && (!key || shadow[key] !== false)) { + return parentFn; + } + } else if (parentFn.isArrowFunctionExpression()) { + return parentFn; + } + + // normal function, we've found our function context + return null; +} +},{"./index":26,"babel-runtime/core-js/get-iterator":41,"babel-types":157}],21:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.shareCommentsWithSiblings = shareCommentsWithSiblings; +exports.addComment = addComment; +exports.addComments = addComments; +// This file contains methods responsible for dealing with comments. + +/** + * Share comments amongst siblings. + */ + +function shareCommentsWithSiblings() { + var node = this.node; + if (!node) return; + + var trailing = node.trailingComments; + var leading = node.leadingComments; + if (!trailing && !leading) return; + + var prev = this.getSibling(this.key - 1); + var next = this.getSibling(this.key + 1); + + if (!prev.node) prev = next; + if (!next.node) next = prev; + + prev.addComments("trailing", leading); + next.addComments("leading", trailing); +} + +function addComment(type, content, line) { + this.addComments(type, [{ + type: line ? "CommentLine" : "CommentBlock", + value: content + }]); +} + +/** + * Give node `comments` of the specified `type`. + */ + +function addComments(type, comments) { + if (!comments) return; + + var node = this.node; + if (!node) return; + + var key = type + "Comments"; + + if (node[key]) { + node[key] = node[key].concat(comments); + } else { + node[key] = comments; + } +} +},{}],22:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.call = call; +exports._call = _call; +exports.isBlacklisted = isBlacklisted; +exports.visit = visit; +exports.skip = skip; +exports.skipKey = skipKey; +exports.stop = stop; +exports.setScope = setScope; +exports.setContext = setContext; +exports.resync = resync; +exports._resyncParent = _resyncParent; +exports._resyncKey = _resyncKey; +exports._resyncList = _resyncList; +exports._resyncRemoved = _resyncRemoved; +exports.popContext = popContext; +exports.pushContext = pushContext; +exports.setup = setup; +exports.setKey = setKey; +exports.requeue = requeue; +exports._getQueueContexts = _getQueueContexts; + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function call(key) { + var opts = this.opts; + + this.debug(function () { + return key; + }); + + if (this.node) { + if (this._call(opts[key])) return true; + } + + if (this.node) { + return this._call(opts[this.node.type] && opts[this.node.type][key]); + } + + return false; +} // This file contains methods responsible for maintaining a TraversalContext. + +function _call(fns) { + if (!fns) return false; + + for (var _iterator = fns, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var fn = _ref; + + if (!fn) continue; + + var node = this.node; + if (!node) return true; + + var ret = fn.call(this.state, this, this.state); + if (ret) throw new Error("Unexpected return value from visitor method " + fn); + + // node has been replaced, it will have been requeued + if (this.node !== node) return true; + + if (this.shouldStop || this.shouldSkip || this.removed) return true; + } + + return false; +} + +function isBlacklisted() { + var blacklist = this.opts.blacklist; + return blacklist && blacklist.indexOf(this.node.type) > -1; +} + +function visit() { + if (!this.node) { + return false; + } + + if (this.isBlacklisted()) { + return false; + } + + if (this.opts.shouldSkip && this.opts.shouldSkip(this)) { + return false; + } + + if (this.call("enter") || this.shouldSkip) { + this.debug(function () { + return "Skip..."; + }); + return this.shouldStop; + } + + this.debug(function () { + return "Recursing into..."; + }); + _index2.default.node(this.node, this.opts, this.scope, this.state, this, this.skipKeys); + + this.call("exit"); + + return this.shouldStop; +} + +function skip() { + this.shouldSkip = true; +} + +function skipKey(key) { + this.skipKeys[key] = true; +} + +function stop() { + this.shouldStop = true; + this.shouldSkip = true; +} + +function setScope() { + if (this.opts && this.opts.noScope) return; + + var target = this.context && this.context.scope; + + if (!target) { + var path = this.parentPath; + while (path && !target) { + if (path.opts && path.opts.noScope) return; + + target = path.scope; + path = path.parentPath; + } + } + + this.scope = this.getScope(target); + if (this.scope) this.scope.init(); +} + +function setContext(context) { + this.shouldSkip = false; + this.shouldStop = false; + this.removed = false; + this.skipKeys = {}; + + if (context) { + this.context = context; + this.state = context.state; + this.opts = context.opts; + } + + this.setScope(); + + return this; +} + +/** + * Here we resync the node paths `key` and `container`. If they've changed according + * to what we have stored internally then we attempt to resync by crawling and looking + * for the new values. + */ + +function resync() { + if (this.removed) return; + + this._resyncParent(); + this._resyncList(); + this._resyncKey(); + //this._resyncRemoved(); +} + +function _resyncParent() { + if (this.parentPath) { + this.parent = this.parentPath.node; + } +} + +function _resyncKey() { + if (!this.container) return; + + if (this.node === this.container[this.key]) return; + + // grrr, path key is out of sync. this is likely due to a modification to the AST + // not done through our path APIs + + if (Array.isArray(this.container)) { + for (var i = 0; i < this.container.length; i++) { + if (this.container[i] === this.node) { + return this.setKey(i); + } + } + } else { + for (var key in this.container) { + if (this.container[key] === this.node) { + return this.setKey(key); + } + } + } + + // ¯\_(ツ)_/¯ who knows where it's gone lol + this.key = null; +} + +function _resyncList() { + if (!this.parent || !this.inList) return; + + var newContainer = this.parent[this.listKey]; + if (this.container === newContainer) return; + + // container is out of sync. this is likely the result of it being reassigned + this.container = newContainer || null; +} + +function _resyncRemoved() { + if (this.key == null || !this.container || this.container[this.key] !== this.node) { + this._markRemoved(); + } +} + +function popContext() { + this.contexts.pop(); + this.setContext(this.contexts[this.contexts.length - 1]); +} + +function pushContext(context) { + this.contexts.push(context); + this.setContext(context); +} + +function setup(parentPath, container, listKey, key) { + this.inList = !!listKey; + this.listKey = listKey; + this.parentKey = listKey || key; + this.container = container; + + this.parentPath = parentPath || this.parentPath; + this.setKey(key); +} + +function setKey(key) { + this.key = key; + this.node = this.container[this.key]; + this.type = this.node && this.node.type; +} + +function requeue() { + var pathToQueue = arguments.length <= 0 || arguments[0] === undefined ? this : arguments[0]; + + if (pathToQueue.removed) return; + + // TODO(loganfsmyth): This should be switched back to queue in parent contexts + // automatically once T2892 and T7160 have been resolved. See T7166. + // let contexts = this._getQueueContexts(); + var contexts = this.contexts; + + for (var _iterator2 = contexts, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var context = _ref2; + + context.maybeQueue(pathToQueue); + } +} + +function _getQueueContexts() { + var path = this; + var contexts = this.contexts; + while (!contexts.length) { + path = path.parentPath; + contexts = path.contexts; + } + return contexts; +} +},{"../index":19,"babel-runtime/core-js/get-iterator":41}],23:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.toComputedKey = toComputedKey; +exports.ensureBlock = ensureBlock; +exports.arrowFunctionToShadowed = arrowFunctionToShadowed; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function toComputedKey() { + var node = this.node; + + var key = void 0; + if (this.isMemberExpression()) { + key = node.property; + } else if (this.isProperty() || this.isMethod()) { + key = node.key; + } else { + throw new ReferenceError("todo"); + } + + if (!node.computed) { + if (t.isIdentifier(key)) key = t.stringLiteral(key.name); + } + + return key; +} // This file contains methods that convert the path node into another node or some other type of data. + +function ensureBlock() { + return t.ensureBlock(this.node); +} + +function arrowFunctionToShadowed() { + // todo: maybe error + if (!this.isArrowFunctionExpression()) return; + + this.ensureBlock(); + + var node = this.node; + + node.expression = false; + node.type = "FunctionExpression"; + node.shadow = node.shadow || true; +} +},{"babel-types":157}],24:[function(require,module,exports){ +(function (global){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _map = require("babel-runtime/core-js/map"); + +var _map2 = _interopRequireDefault(_map); + +exports.evaluateTruthy = evaluateTruthy; +exports.evaluate = evaluate; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// This file contains Babels metainterpreter that can evaluate static code. + +/* eslint eqeqeq: 0 */ + +var VALID_CALLEES = ["String", "Number", "Math"]; /* eslint indent: 0 */ +/* eslint max-len: 0 */ + +var INVALID_METHODS = ["random"]; + +/** + * Walk the input `node` and statically evaluate if it's truthy. + * + * Returning `true` when we're sure that the expression will evaluate to a + * truthy value, `false` if we're sure that it will evaluate to a falsy + * value and `undefined` if we aren't sure. Because of this please do not + * rely on coercion when using this method and check with === if it's false. + * + * For example do: + * + * if (t.evaluateTruthy(node) === false) falsyLogic(); + * + * **AND NOT** + * + * if (!t.evaluateTruthy(node)) falsyLogic(); + * + */ + +function evaluateTruthy() { + var res = this.evaluate(); + if (res.confident) return !!res.value; +} + +/** + * Walk the input `node` and statically evaluate it. + * + * Returns an object in the form `{ confident, value }`. `confident` indicates + * whether or not we had to drop out of evaluating the expression because of + * hitting an unknown node that we couldn't confidently find the value of. + * + * Example: + * + * t.evaluate(parse("5 + 5")) // { confident: true, value: 10 } + * t.evaluate(parse("!true")) // { confident: true, value: false } + * t.evaluate(parse("foo + foo")) // { confident: false, value: undefined } + * + */ + +function evaluate() { + var confident = true; + var deoptPath = void 0; + var seen = new _map2.default(); + + function deopt(path) { + if (!confident) return; + deoptPath = path; + confident = false; + } + + var value = evaluate(this); + if (!confident) value = undefined; + return { + confident: confident, + deopt: deoptPath, + value: value + }; + + // we wrap the _evaluate method so we can track `seen` nodes, we push an item + // to the map before we actually evaluate it so we can deopt on self recursive + // nodes such as: + // + // var g = a ? 1 : 2, + // a = g * this.foo + // + function evaluate(path) { + var node = path.node; + + + if (seen.has(node)) { + var existing = seen.get(node); + if (existing.resolved) { + return existing.value; + } else { + deopt(path); + return; + } + } else { + var item = { resolved: false }; + seen.set(node, item); + + var val = _evaluate(path); + item.resolved = true; + item.value = value; + return val; + } + } + + function _evaluate(path) { + if (!confident) return; + + var node = path.node; + + + if (path.isSequenceExpression()) { + var exprs = path.get("expressions"); + return evaluate(exprs[exprs.length - 1]); + } + + if (path.isStringLiteral() || path.isNumericLiteral() || path.isBooleanLiteral()) { + return node.value; + } + + if (path.isNullLiteral()) { + return null; + } + + if (path.isTemplateLiteral()) { + var str = ""; + + var i = 0; + var _exprs = path.get("expressions"); + + for (var _iterator = node.quasis, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var elem = _ref; + + // not confident, evaluated an expression we don't like + if (!confident) break; + + // add on cooked element + str += elem.value.cooked; + + // add on interpolated expression if it's present + var expr = _exprs[i++]; + if (expr) str += String(evaluate(expr)); + } + + if (!confident) return; + return str; + } + + if (path.isConditionalExpression()) { + var testResult = evaluate(path.get("test")); + if (!confident) return; + if (testResult) { + return evaluate(path.get("consequent")); + } else { + return evaluate(path.get("alternate")); + } + } + + if (path.isExpressionWrapper()) { + // TypeCastExpression, ExpressionStatement etc + return evaluate(path.get("expression")); + } + + // "foo".length + if (path.isMemberExpression() && !path.parentPath.isCallExpression({ callee: node })) { + var property = path.get("property"); + var object = path.get("object"); + + if (object.isLiteral() && property.isIdentifier()) { + var _value = object.node.value; + var type = typeof _value === "undefined" ? "undefined" : (0, _typeof3.default)(_value); + if (type === "number" || type === "string") { + return _value[property.node.name]; + } + } + } + + if (path.isReferencedIdentifier()) { + var binding = path.scope.getBinding(node.name); + if (binding && binding.hasValue) { + return binding.value; + } else { + if (node.name === "undefined") { + return undefined; + } else if (node.name === "Infinity") { + return Infinity; + } else if (node.name === "NaN") { + return NaN; + } + + var resolved = path.resolve(); + if (resolved === path) { + return deopt(path); + } else { + return evaluate(resolved); + } + } + } + + if (path.isUnaryExpression({ prefix: true })) { + if (node.operator === "void") { + // we don't need to evaluate the argument to know what this will return + return undefined; + } + + var argument = path.get("argument"); + if (node.operator === "typeof" && (argument.isFunction() || argument.isClass())) { + return "function"; + } + + var arg = evaluate(argument); + if (!confident) return; + switch (node.operator) { + case "!": + return !arg; + case "+": + return +arg; + case "-": + return -arg; + case "~": + return ~arg; + case "typeof": + return typeof arg === "undefined" ? "undefined" : (0, _typeof3.default)(arg); + } + } + + if (path.isArrayExpression()) { + var arr = []; + var elems = path.get("elements"); + for (var _iterator2 = elems, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _elem = _ref2; + + _elem = _elem.evaluate(); + + if (_elem.confident) { + arr.push(_elem.value); + } else { + return deopt(_elem); + } + } + return arr; + } + + if (path.isObjectExpression()) { + // todo + } + + if (path.isLogicalExpression()) { + // If we are confident that one side of an && is false, or the left + // side of an || is true, we can be confident about the entire expression + var wasConfident = confident; + var left = evaluate(path.get("left")); + var leftConfident = confident; + confident = wasConfident; + var right = evaluate(path.get("right")); + var rightConfident = confident; + confident = leftConfident && rightConfident; + + switch (node.operator) { + case "||": + // TODO consider having a "truthy type" that doesn't bail on + // left uncertainity but can still evaluate to truthy. + if (left && leftConfident) { + confident = true; + return left; + } + + if (!confident) return; + + return left || right; + case "&&": + if (!left && leftConfident || !right && rightConfident) { + confident = true; + } + + if (!confident) return; + + return left && right; + } + } + + if (path.isBinaryExpression()) { + var _left = evaluate(path.get("left")); + if (!confident) return; + var _right = evaluate(path.get("right")); + if (!confident) return; + + switch (node.operator) { + case "-": + return _left - _right; + case "+": + return _left + _right; + case "/": + return _left / _right; + case "*": + return _left * _right; + case "%": + return _left % _right; + case "**": + return Math.pow(_left, _right); + case "<": + return _left < _right; + case ">": + return _left > _right; + case "<=": + return _left <= _right; + case ">=": + return _left >= _right; + case "==": + return _left == _right; + case "!=": + return _left != _right; + case "===": + return _left === _right; + case "!==": + return _left !== _right; + case "|": + return _left | _right; + case "&": + return _left & _right; + case "^": + return _left ^ _right; + case "<<": + return _left << _right; + case ">>": + return _left >> _right; + case ">>>": + return _left >>> _right; + } + } + + if (path.isCallExpression()) { + var callee = path.get("callee"); + var context = void 0; + var func = void 0; + + // Number(1); + if (callee.isIdentifier() && !path.scope.getBinding(callee.node.name, true) && VALID_CALLEES.indexOf(callee.node.name) >= 0) { + func = global[node.callee.name]; + } + + if (callee.isMemberExpression()) { + var _object = callee.get("object"); + var _property = callee.get("property"); + + // Math.min(1, 2) + if (_object.isIdentifier() && _property.isIdentifier() && VALID_CALLEES.indexOf(_object.node.name) >= 0 && INVALID_METHODS.indexOf(_property.node.name) < 0) { + context = global[_object.node.name]; + func = context[_property.node.name]; + } + + // "abc".charCodeAt(4) + if (_object.isLiteral() && _property.isIdentifier()) { + var _type = (0, _typeof3.default)(_object.node.value); + if (_type === "string" || _type === "number") { + context = _object.node.value; + func = context[_property.node.name]; + } + } + } + + if (func) { + var args = path.get("arguments").map(evaluate); + if (!confident) return; + + return func.apply(context, args); + } + } + + deopt(path); + } +} +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) +},{"babel-runtime/core-js/get-iterator":41,"babel-runtime/core-js/map":42,"babel-runtime/helpers/typeof":50}],25:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.getStatementParent = getStatementParent; +exports.getOpposite = getOpposite; +exports.getCompletionRecords = getCompletionRecords; +exports.getSibling = getSibling; +exports.get = get; +exports._getKey = _getKey; +exports._getPattern = _getPattern; +exports.getBindingIdentifiers = getBindingIdentifiers; +exports.getOuterBindingIdentifiers = getOuterBindingIdentifiers; + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getStatementParent() { + var path = this; + + do { + if (!path.parentPath || Array.isArray(path.container) && path.isStatement()) { + break; + } else { + path = path.parentPath; + } + } while (path); + + if (path && (path.isProgram() || path.isFile())) { + throw new Error("File/Program node, we can't possibly find a statement parent to this"); + } + + return path; +} // This file contains methods responsible for dealing with/retrieving children or siblings. + +function getOpposite() { + if (this.key === "left") { + return this.getSibling("right"); + } else if (this.key === "right") { + return this.getSibling("left"); + } +} + +function getCompletionRecords() { + var paths = []; + + var add = function add(path) { + if (path) paths = paths.concat(path.getCompletionRecords()); + }; + + if (this.isIfStatement()) { + add(this.get("consequent")); + add(this.get("alternate")); + } else if (this.isDoExpression() || this.isFor() || this.isWhile()) { + add(this.get("body")); + } else if (this.isProgram() || this.isBlockStatement()) { + add(this.get("body").pop()); + } else if (this.isFunction()) { + return this.get("body").getCompletionRecords(); + } else if (this.isTryStatement()) { + add(this.get("block")); + add(this.get("handler")); + add(this.get("finalizer")); + } else { + paths.push(this); + } + + return paths; +} + +function getSibling(key) { + return _index2.default.get({ + parentPath: this.parentPath, + parent: this.parent, + container: this.container, + listKey: this.listKey, + key: key + }); +} + +function get(key, context) { + if (context === true) context = this.context; + var parts = key.split("."); + if (parts.length === 1) { + // "foo" + return this._getKey(key, context); + } else { + // "foo.bar" + return this._getPattern(parts, context); + } +} + +function _getKey(key, context) { + var _this = this; + + var node = this.node; + var container = node[key]; + + if (Array.isArray(container)) { + // requested a container so give them all the paths + return container.map(function (_, i) { + return _index2.default.get({ + listKey: key, + parentPath: _this, + parent: node, + container: container, + key: i + }).setContext(context); + }); + } else { + return _index2.default.get({ + parentPath: this, + parent: node, + container: node, + key: key + }).setContext(context); + } +} + +function _getPattern(parts, context) { + var path = this; + for (var _iterator = parts, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var part = _ref; + + if (part === ".") { + path = path.parentPath; + } else { + if (Array.isArray(path)) { + path = path[part]; + } else { + path = path.get(part, context); + } + } + } + return path; +} + +function getBindingIdentifiers(duplicates) { + return t.getBindingIdentifiers(this.node, duplicates); +} + +function getOuterBindingIdentifiers(duplicates) { + return t.getOuterBindingIdentifiers(this.node, duplicates); +} +},{"./index":26,"babel-runtime/core-js/get-iterator":41,"babel-types":157}],26:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _virtualTypes = require("./lib/virtual-types"); + +var virtualTypes = _interopRequireWildcard(_virtualTypes); + +var _debug2 = require("debug"); + +var _debug3 = _interopRequireDefault(_debug2); + +var _invariant = require("invariant"); + +var _invariant2 = _interopRequireDefault(_invariant); + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +var _assign = require("lodash/assign"); + +var _assign2 = _interopRequireDefault(_assign); + +var _scope = require("../scope"); + +var _scope2 = _interopRequireDefault(_scope); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _cache = require("../cache"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* eslint max-len: 0 */ + +var _debug = (0, _debug3.default)("babel"); + +var NodePath = function () { + function NodePath(hub, parent) { + (0, _classCallCheck3.default)(this, NodePath); + + this.parent = parent; + this.hub = hub; + this.contexts = []; + this.data = {}; + this.shouldSkip = false; + this.shouldStop = false; + this.removed = false; + this.state = null; + this.opts = null; + this.skipKeys = null; + this.parentPath = null; + this.context = null; + this.container = null; + this.listKey = null; + this.inList = false; + this.parentKey = null; + this.key = null; + this.node = null; + this.scope = null; + this.type = null; + this.typeAnnotation = null; + } + + NodePath.get = function get(_ref) { + var hub = _ref.hub; + var parentPath = _ref.parentPath; + var parent = _ref.parent; + var container = _ref.container; + var listKey = _ref.listKey; + var key = _ref.key; + + if (!hub && parentPath) { + hub = parentPath.hub; + } + + (0, _invariant2.default)(parent, "To get a node path the parent needs to exist"); + + var targetNode = container[key]; + + var paths = _cache.path.get(parent) || []; + if (!_cache.path.has(parent)) { + _cache.path.set(parent, paths); + } + + var path = void 0; + + for (var i = 0; i < paths.length; i++) { + var pathCheck = paths[i]; + if (pathCheck.node === targetNode) { + path = pathCheck; + break; + } + } + + if (!path) { + path = new NodePath(hub, parent); + paths.push(path); + } + + path.setup(parentPath, container, listKey, key); + + return path; + }; + + NodePath.prototype.getScope = function getScope(scope) { + var ourScope = scope; + + // we're entering a new scope so let's construct it! + if (this.isScope()) { + ourScope = new _scope2.default(this, scope); + } + + return ourScope; + }; + + NodePath.prototype.setData = function setData(key, val) { + return this.data[key] = val; + }; + + NodePath.prototype.getData = function getData(key, def) { + var val = this.data[key]; + if (!val && def) val = this.data[key] = def; + return val; + }; + + NodePath.prototype.buildCodeFrameError = function buildCodeFrameError(msg) { + var Error = arguments.length <= 1 || arguments[1] === undefined ? SyntaxError : arguments[1]; + + return this.hub.file.buildCodeFrameError(this.node, msg, Error); + }; + + NodePath.prototype.traverse = function traverse(visitor, state) { + (0, _index2.default)(this.node, visitor, this.scope, state, this); + }; + + NodePath.prototype.mark = function mark(type, message) { + this.hub.file.metadata.marked.push({ + type: type, + message: message, + loc: this.node.loc + }); + }; + + NodePath.prototype.set = function set(key, node) { + t.validate(this.node, key, node); + this.node[key] = node; + }; + + NodePath.prototype.getPathLocation = function getPathLocation() { + var parts = []; + var path = this; + do { + var key = path.key; + if (path.inList) key = path.listKey + "[" + key + "]"; + parts.unshift(key); + } while (path = path.parentPath); + return parts.join("."); + }; + + NodePath.prototype.debug = function debug(buildMessage) { + if (!_debug.enabled) return; + _debug(this.getPathLocation() + " " + this.type + ": " + buildMessage()); + }; + + return NodePath; +}(); + +exports.default = NodePath; + + +(0, _assign2.default)(NodePath.prototype, require("./ancestry")); +(0, _assign2.default)(NodePath.prototype, require("./inference")); +(0, _assign2.default)(NodePath.prototype, require("./replacement")); +(0, _assign2.default)(NodePath.prototype, require("./evaluation")); +(0, _assign2.default)(NodePath.prototype, require("./conversion")); +(0, _assign2.default)(NodePath.prototype, require("./introspection")); +(0, _assign2.default)(NodePath.prototype, require("./context")); +(0, _assign2.default)(NodePath.prototype, require("./removal")); +(0, _assign2.default)(NodePath.prototype, require("./modification")); +(0, _assign2.default)(NodePath.prototype, require("./family")); +(0, _assign2.default)(NodePath.prototype, require("./comments")); + +var _loop2 = function _loop2() { + if (_isArray) { + if (_i >= _iterator.length) return "break"; + _ref2 = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) return "break"; + _ref2 = _i.value; + } + + var type = _ref2; + + var typeKey = "is" + type; + NodePath.prototype[typeKey] = function (opts) { + return t[typeKey](this.node, opts); + }; + + NodePath.prototype["assert" + type] = function (opts) { + if (!this[typeKey](opts)) { + throw new TypeError("Expected node path of type " + type); + } + }; +}; + +for (var _iterator = t.TYPES, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref2; + + var _ret2 = _loop2(); + + if (_ret2 === "break") break; +} + +var _loop = function _loop(type) { + if (type[0] === "_") return "continue"; + if (t.TYPES.indexOf(type) < 0) t.TYPES.push(type); + + var virtualType = virtualTypes[type]; + + NodePath.prototype["is" + type] = function (opts) { + return virtualType.checkPath(this, opts); + }; +}; + +for (var type in virtualTypes) { + var _ret = _loop(type); + + if (_ret === "continue") continue; +} +module.exports = exports["default"]; +},{"../cache":16,"../index":19,"../scope":38,"./ancestry":20,"./comments":21,"./context":22,"./conversion":23,"./evaluation":24,"./family":25,"./inference":27,"./introspection":30,"./lib/virtual-types":33,"./modification":34,"./removal":35,"./replacement":36,"babel-runtime/core-js/get-iterator":41,"babel-runtime/helpers/classCallCheck":49,"babel-types":157,"debug":250,"invariant":260,"lodash/assign":391}],27:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.getTypeAnnotation = getTypeAnnotation; +exports._getTypeAnnotation = _getTypeAnnotation; +exports.isBaseType = isBaseType; +exports.couldBeBaseType = couldBeBaseType; +exports.baseTypeStrictlyMatches = baseTypeStrictlyMatches; +exports.isGenericType = isGenericType; + +var _inferers = require("./inferers"); + +var inferers = _interopRequireWildcard(_inferers); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Infer the type of the current `NodePath`. + */ + +function getTypeAnnotation() { + if (this.typeAnnotation) return this.typeAnnotation; + + var type = this._getTypeAnnotation() || t.anyTypeAnnotation(); + if (t.isTypeAnnotation(type)) type = type.typeAnnotation; + return this.typeAnnotation = type; +} + +/** + * todo: split up this method + */ + +function _getTypeAnnotation() { + var node = this.node; + + if (!node) { + // handle initializerless variables, add in checks for loop initializers too + if (this.key === "init" && this.parentPath.isVariableDeclarator()) { + var declar = this.parentPath.parentPath; + var declarParent = declar.parentPath; + + // for (let NODE in bar) {} + if (declar.key === "left" && declarParent.isForInStatement()) { + return t.stringTypeAnnotation(); + } + + // for (let NODE of bar) {} + if (declar.key === "left" && declarParent.isForOfStatement()) { + return t.anyTypeAnnotation(); + } + + return t.voidTypeAnnotation(); + } else { + return; + } + } + + if (node.typeAnnotation) { + return node.typeAnnotation; + } + + var inferer = inferers[node.type]; + if (inferer) { + return inferer.call(this, node); + } + + inferer = inferers[this.parentPath.type]; + if (inferer && inferer.validParent) { + return this.parentPath.getTypeAnnotation(); + } +} + +function isBaseType(baseName, soft) { + return _isBaseType(baseName, this.getTypeAnnotation(), soft); +} + +function _isBaseType(baseName, type, soft) { + if (baseName === "string") { + return t.isStringTypeAnnotation(type); + } else if (baseName === "number") { + return t.isNumberTypeAnnotation(type); + } else if (baseName === "boolean") { + return t.isBooleanTypeAnnotation(type); + } else if (baseName === "any") { + return t.isAnyTypeAnnotation(type); + } else if (baseName === "mixed") { + return t.isMixedTypeAnnotation(type); + } else if (baseName === "void") { + return t.isVoidTypeAnnotation(type); + } else { + if (soft) { + return false; + } else { + throw new Error("Unknown base type " + baseName); + } + } +} + +function couldBeBaseType(name) { + var type = this.getTypeAnnotation(); + if (t.isAnyTypeAnnotation(type)) return true; + + if (t.isUnionTypeAnnotation(type)) { + for (var _iterator = type.types, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var type2 = _ref; + + if (t.isAnyTypeAnnotation(type2) || _isBaseType(name, type2, true)) { + return true; + } + } + return false; + } else { + return _isBaseType(name, type, true); + } +} + +function baseTypeStrictlyMatches(right) { + var left = this.getTypeAnnotation(); + right = right.getTypeAnnotation(); + + if (!t.isAnyTypeAnnotation(left) && t.isFlowBaseAnnotation(left)) { + return right.type === left.type; + } +} + +function isGenericType(genericName) { + var type = this.getTypeAnnotation(); + return t.isGenericTypeAnnotation(type) && t.isIdentifier(type.id, { name: genericName }); +} +},{"./inferers":29,"babel-runtime/core-js/get-iterator":41,"babel-types":157}],28:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.default = function (node) { + if (!this.isReferenced()) return; + + // check if a binding exists of this value and if so then return a union type of all + // possible types that the binding could be + var binding = this.scope.getBinding(node.name); + if (binding) { + if (binding.identifier.typeAnnotation) { + return binding.identifier.typeAnnotation; + } else { + return getTypeAnnotationBindingConstantViolations(this, node.name); + } + } + + // built-in values + if (node.name === "undefined") { + return t.voidTypeAnnotation(); + } else if (node.name === "NaN" || node.name === "Infinity") { + return t.numberTypeAnnotation(); + } else if (node.name === "arguments") { + // todo + } +}; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function getTypeAnnotationBindingConstantViolations(path, name) { + var binding = path.scope.getBinding(name); + + var types = []; + path.typeAnnotation = t.unionTypeAnnotation(types); + + var functionConstantViolations = []; + var constantViolations = getConstantViolationsBefore(binding, path, functionConstantViolations); + + var testType = getConditionalAnnotation(path, name); + if (testType) { + (function () { + var testConstantViolations = getConstantViolationsBefore(binding, testType.ifStatement); + + // remove constant violations observed before the IfStatement + constantViolations = constantViolations.filter(function (path) { + return testConstantViolations.indexOf(path) < 0; + }); + + // clear current types and add in observed test type + types.push(testType.typeAnnotation); + })(); + } + + if (constantViolations.length) { + // pick one constant from each scope which will represent the last possible + // control flow path that it could've taken/been + /* This code is broken for the following problems: + * It thinks that assignments can only happen in scopes. + * What about conditionals, if statements without block, + * or guarded assignments. + * It also checks to see if one of the assignments is in the + * same scope and uses that as the only "violation". However, + * the binding is returned by `getConstantViolationsBefore` so we for + * sure always going to return that as the only "violation". + let rawConstantViolations = constantViolations.reverse(); + let visitedScopes = []; + constantViolations = []; + for (let violation of (rawConstantViolations: Array)) { + let violationScope = violation.scope; + if (visitedScopes.indexOf(violationScope) >= 0) continue; + visitedScopes.push(violationScope); + constantViolations.push(violation); + if (violationScope === path.scope) { + constantViolations = [violation]; + break; + } + }*/ + + // add back on function constant violations since we can't track calls + constantViolations = constantViolations.concat(functionConstantViolations); + + // push on inferred types of violated paths + for (var _iterator = constantViolations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var violation = _ref; + + types.push(violation.getTypeAnnotation()); + } + } + + if (types.length) { + return t.createUnionTypeAnnotation(types); + } +} + +function getConstantViolationsBefore(binding, path, functions) { + var violations = binding.constantViolations.slice(); + violations.unshift(binding.path); + return violations.filter(function (violation) { + violation = violation.resolve(); + var status = violation._guessExecutionStatusRelativeTo(path); + if (functions && status === "function") functions.push(violation); + return status === "before"; + }); +} + +function inferAnnotationFromBinaryExpression(name, path) { + var operator = path.node.operator; + + var right = path.get("right").resolve(); + var left = path.get("left").resolve(); + + var target = void 0; + if (left.isIdentifier({ name: name })) { + target = right; + } else if (right.isIdentifier({ name: name })) { + target = left; + } + if (target) { + if (operator === "===") { + return target.getTypeAnnotation(); + } else if (t.BOOLEAN_NUMBER_BINARY_OPERATORS.indexOf(operator) >= 0) { + return t.numberTypeAnnotation(); + } else { + return; + } + } else { + if (operator !== "===") return; + } + + // + var typeofPath = void 0; + var typePath = void 0; + if (left.isUnaryExpression({ operator: "typeof" })) { + typeofPath = left; + typePath = right; + } else if (right.isUnaryExpression({ operator: "typeof" })) { + typeofPath = right; + typePath = left; + } + if (!typePath && !typeofPath) return; + + // ensure that the type path is a Literal + typePath = typePath.resolve(); + if (!typePath.isLiteral()) return; + + // and that it's a string so we can infer it + var typeValue = typePath.node.value; + if (typeof typeValue !== "string") return; + + // and that the argument of the typeof path references us! + if (!typeofPath.get("argument").isIdentifier({ name: name })) return; + + // turn type value into a type annotation + return t.createTypeAnnotationBasedOnTypeof(typePath.node.value); +} + +function getParentConditionalPath(path) { + var parentPath = void 0; + while (parentPath = path.parentPath) { + if (parentPath.isIfStatement() || parentPath.isConditionalExpression()) { + if (path.key === "test") { + return; + } else { + return parentPath; + } + } else { + path = parentPath; + } + } +} + +function getConditionalAnnotation(path, name) { + var ifStatement = getParentConditionalPath(path); + if (!ifStatement) return; + + var test = ifStatement.get("test"); + var paths = [test]; + var types = []; + + do { + var _path = paths.shift().resolve(); + + if (_path.isLogicalExpression()) { + paths.push(_path.get("left")); + paths.push(_path.get("right")); + } + + if (_path.isBinaryExpression()) { + var type = inferAnnotationFromBinaryExpression(name, _path); + if (type) types.push(type); + } + } while (paths.length); + + if (types.length) { + return { + typeAnnotation: t.createUnionTypeAnnotation(types), + ifStatement: ifStatement + }; + } else { + return getConditionalAnnotation(ifStatement, name); + } +} +module.exports = exports["default"]; +},{"babel-runtime/core-js/get-iterator":41,"babel-types":157}],29:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.Class = exports.Function = exports.Identifier = undefined; + +var _infererReference = require("./inferer-reference"); + +Object.defineProperty(exports, "Identifier", { + enumerable: true, + get: function get() { + return _interopRequireDefault(_infererReference).default; + } +}); +exports.VariableDeclarator = VariableDeclarator; +exports.TypeCastExpression = TypeCastExpression; +exports.NewExpression = NewExpression; +exports.TemplateLiteral = TemplateLiteral; +exports.UnaryExpression = UnaryExpression; +exports.BinaryExpression = BinaryExpression; +exports.LogicalExpression = LogicalExpression; +exports.ConditionalExpression = ConditionalExpression; +exports.SequenceExpression = SequenceExpression; +exports.AssignmentExpression = AssignmentExpression; +exports.UpdateExpression = UpdateExpression; +exports.StringLiteral = StringLiteral; +exports.NumericLiteral = NumericLiteral; +exports.BooleanLiteral = BooleanLiteral; +exports.NullLiteral = NullLiteral; +exports.RegExpLiteral = RegExpLiteral; +exports.ObjectExpression = ObjectExpression; +exports.ArrayExpression = ArrayExpression; +exports.RestElement = RestElement; +exports.CallExpression = CallExpression; +exports.TaggedTemplateExpression = TaggedTemplateExpression; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function VariableDeclarator() { + var id = this.get("id"); + + if (id.isIdentifier()) { + return this.get("init").getTypeAnnotation(); + } else { + return; + } +} + +function TypeCastExpression(node) { + return node.typeAnnotation; +} + +TypeCastExpression.validParent = true; + +function NewExpression(node) { + if (this.get("callee").isIdentifier()) { + // only resolve identifier callee + return t.genericTypeAnnotation(node.callee); + } +} + +function TemplateLiteral() { + return t.stringTypeAnnotation(); +} + +function UnaryExpression(node) { + var operator = node.operator; + + if (operator === "void") { + return t.voidTypeAnnotation(); + } else if (t.NUMBER_UNARY_OPERATORS.indexOf(operator) >= 0) { + return t.numberTypeAnnotation(); + } else if (t.STRING_UNARY_OPERATORS.indexOf(operator) >= 0) { + return t.stringTypeAnnotation(); + } else if (t.BOOLEAN_UNARY_OPERATORS.indexOf(operator) >= 0) { + return t.booleanTypeAnnotation(); + } +} + +function BinaryExpression(node) { + var operator = node.operator; + + if (t.NUMBER_BINARY_OPERATORS.indexOf(operator) >= 0) { + return t.numberTypeAnnotation(); + } else if (t.BOOLEAN_BINARY_OPERATORS.indexOf(operator) >= 0) { + return t.booleanTypeAnnotation(); + } else if (operator === "+") { + var right = this.get("right"); + var left = this.get("left"); + + if (left.isBaseType("number") && right.isBaseType("number")) { + // both numbers so this will be a number + return t.numberTypeAnnotation(); + } else if (left.isBaseType("string") || right.isBaseType("string")) { + // one is a string so the result will be a string + return t.stringTypeAnnotation(); + } + + // unsure if left and right are strings or numbers so stay on the safe side + return t.unionTypeAnnotation([t.stringTypeAnnotation(), t.numberTypeAnnotation()]); + } +} + +function LogicalExpression() { + return t.createUnionTypeAnnotation([this.get("left").getTypeAnnotation(), this.get("right").getTypeAnnotation()]); +} + +function ConditionalExpression() { + return t.createUnionTypeAnnotation([this.get("consequent").getTypeAnnotation(), this.get("alternate").getTypeAnnotation()]); +} + +function SequenceExpression() { + return this.get("expressions").pop().getTypeAnnotation(); +} + +function AssignmentExpression() { + return this.get("right").getTypeAnnotation(); +} + +function UpdateExpression(node) { + var operator = node.operator; + if (operator === "++" || operator === "--") { + return t.numberTypeAnnotation(); + } +} + +function StringLiteral() { + return t.stringTypeAnnotation(); +} + +function NumericLiteral() { + return t.numberTypeAnnotation(); +} + +function BooleanLiteral() { + return t.booleanTypeAnnotation(); +} + +function NullLiteral() { + return t.nullLiteralTypeAnnotation(); +} + +function RegExpLiteral() { + return t.genericTypeAnnotation(t.identifier("RegExp")); +} + +function ObjectExpression() { + return t.genericTypeAnnotation(t.identifier("Object")); +} + +function ArrayExpression() { + return t.genericTypeAnnotation(t.identifier("Array")); +} + +function RestElement() { + return ArrayExpression(); +} + +RestElement.validParent = true; + +function Func() { + return t.genericTypeAnnotation(t.identifier("Function")); +} + +exports.Function = Func; +exports.Class = Func; +function CallExpression() { + return resolveCall(this.get("callee")); +} + +function TaggedTemplateExpression() { + return resolveCall(this.get("tag")); +} + +function resolveCall(callee) { + callee = callee.resolve(); + + if (callee.isFunction()) { + if (callee.is("async")) { + if (callee.is("generator")) { + return t.genericTypeAnnotation(t.identifier("AsyncIterator")); + } else { + return t.genericTypeAnnotation(t.identifier("Promise")); + } + } else { + if (callee.node.returnType) { + return callee.node.returnType; + } else { + // todo: get union type of all return arguments + } + } + } +} +},{"./inferer-reference":28,"babel-types":157}],30:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.is = undefined; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.matchesPattern = matchesPattern; +exports.has = has; +exports.isStatic = isStatic; +exports.isnt = isnt; +exports.equals = equals; +exports.isNodeType = isNodeType; +exports.canHaveVariableDeclarationOrExpression = canHaveVariableDeclarationOrExpression; +exports.canSwapBetweenExpressionAndStatement = canSwapBetweenExpressionAndStatement; +exports.isCompletionRecord = isCompletionRecord; +exports.isStatementOrBlock = isStatementOrBlock; +exports.referencesImport = referencesImport; +exports.getSource = getSource; +exports.willIMaybeExecuteBefore = willIMaybeExecuteBefore; +exports._guessExecutionStatusRelativeTo = _guessExecutionStatusRelativeTo; +exports._guessExecutionStatusRelativeToDifferentFunctions = _guessExecutionStatusRelativeToDifferentFunctions; +exports.resolve = resolve; +exports._resolve = _resolve; + +var _includes = require("lodash/includes"); + +var _includes2 = _interopRequireDefault(_includes); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Match the current node if it matches the provided `pattern`. + * + * For example, given the match `React.createClass` it would match the + * parsed nodes of `React.createClass` and `React["createClass"]`. + */ + +function matchesPattern(pattern, allowPartial) { + // not a member expression + if (!this.isMemberExpression()) return false; + + var parts = pattern.split("."); + var search = [this.node]; + var i = 0; + + function matches(name) { + var part = parts[i]; + return part === "*" || name === part; + } + + while (search.length) { + var node = search.shift(); + + if (allowPartial && i === parts.length) { + return true; + } + + if (t.isIdentifier(node)) { + // this part doesn't match + if (!matches(node.name)) return false; + } else if (t.isLiteral(node)) { + // this part doesn't match + if (!matches(node.value)) return false; + } else if (t.isMemberExpression(node)) { + if (node.computed && !t.isLiteral(node.property)) { + // we can't deal with this + return false; + } else { + search.unshift(node.property); + search.unshift(node.object); + continue; + } + } else if (t.isThisExpression(node)) { + if (!matches("this")) return false; + } else { + // we can't deal with this + return false; + } + + // too many parts + if (++i > parts.length) { + return false; + } + } + + return i === parts.length; +} + +/** + * Check whether we have the input `key`. If the `key` references an array then we check + * if the array has any items, otherwise we just check if it's falsy. + */ + +// This file contains methods responsible for introspecting the current path for certain values. + +function has(key) { + var val = this.node && this.node[key]; + if (val && Array.isArray(val)) { + return !!val.length; + } else { + return !!val; + } +} + +/** + * Description + */ + +function isStatic() { + return this.scope.isStatic(this.node); +} + +/** + * Alias of `has`. + */ + +var is = exports.is = has; + +/** + * Opposite of `has`. + */ + +function isnt(key) { + return !this.has(key); +} + +/** + * Check whether the path node `key` strict equals `value`. + */ + +function equals(key, value) { + return this.node[key] === value; +} + +/** + * Check the type against our stored internal type of the node. This is handy when a node has + * been removed yet we still internally know the type and need it to calculate node replacement. + */ + +function isNodeType(type) { + return t.isType(this.type, type); +} + +/** + * This checks whether or not we're in one of the following positions: + * + * for (KEY in right); + * for (KEY;;); + * + * This is because these spots allow VariableDeclarations AND normal expressions so we need + * to tell the path replacement that it's ok to replace this with an expression. + */ + +function canHaveVariableDeclarationOrExpression() { + return (this.key === "init" || this.key === "left") && this.parentPath.isFor(); +} + +/** + * This checks whether we are swapping an arrow function's body between an + * expression and a block statement (or vice versa). + * + * This is because arrow functions may implicitly return an expression, which + * is the same as containing a block statement. + */ + +function canSwapBetweenExpressionAndStatement(replacement) { + if (this.key !== "body" || !this.parentPath.isArrowFunctionExpression()) { + return false; + } + + if (this.isExpression()) { + return t.isBlockStatement(replacement); + } else if (this.isBlockStatement()) { + return t.isExpression(replacement); + } + + return false; +} + +/** + * Check whether the current path references a completion record + */ + +function isCompletionRecord(allowInsideFunction) { + var path = this; + var first = true; + + do { + var container = path.container; + + // we're in a function so can't be a completion record + if (path.isFunction() && !first) { + return !!allowInsideFunction; + } + + first = false; + + // check to see if we're the last item in the container and if we are + // we're a completion record! + if (Array.isArray(container) && path.key !== container.length - 1) { + return false; + } + } while ((path = path.parentPath) && !path.isProgram()); + + return true; +} + +/** + * Check whether or not the current `key` allows either a single statement or block statement + * so we can explode it if necessary. + */ + +function isStatementOrBlock() { + if (this.parentPath.isLabeledStatement() || t.isBlockStatement(this.container)) { + return false; + } else { + return (0, _includes2.default)(t.STATEMENT_OR_BLOCK_KEYS, this.key); + } +} + +/** + * Check if the currently assigned path references the `importName` of `moduleSource`. + */ + +function referencesImport(moduleSource, importName) { + if (!this.isReferencedIdentifier()) return false; + + var binding = this.scope.getBinding(this.node.name); + if (!binding || binding.kind !== "module") return false; + + var path = binding.path; + var parent = path.parentPath; + if (!parent.isImportDeclaration()) return false; + + // check moduleSource + if (parent.node.source.value === moduleSource) { + if (!importName) return true; + } else { + return false; + } + + if (path.isImportDefaultSpecifier() && importName === "default") { + return true; + } + + if (path.isImportNamespaceSpecifier() && importName === "*") { + return true; + } + + if (path.isImportSpecifier() && path.node.imported.name === importName) { + return true; + } + + return false; +} + +/** + * Get the source code associated with this node. + */ + +function getSource() { + var node = this.node; + if (node.end) { + return this.hub.file.code.slice(node.start, node.end); + } else { + return ""; + } +} + +function willIMaybeExecuteBefore(target) { + return this._guessExecutionStatusRelativeTo(target) !== "after"; +} + +/** + * Given a `target` check the execution status of it relative to the current path. + * + * "Execution status" simply refers to where or not we **think** this will execuete + * before or after the input `target` element. + */ + +function _guessExecutionStatusRelativeTo(target) { + // check if the two paths are in different functions, we can't track execution of these + var targetFuncParent = target.scope.getFunctionParent(); + var selfFuncParent = this.scope.getFunctionParent(); + + // here we check the `node` equality as sometimes we may have different paths for the + // same node due to path thrashing + if (targetFuncParent.node !== selfFuncParent.node) { + var status = this._guessExecutionStatusRelativeToDifferentFunctions(targetFuncParent); + if (status) { + return status; + } else { + target = targetFuncParent.path; + } + } + + var targetPaths = target.getAncestry(); + if (targetPaths.indexOf(this) >= 0) return "after"; + + var selfPaths = this.getAncestry(); + + // get ancestor where the branches intersect + var commonPath = void 0; + var targetIndex = void 0; + var selfIndex = void 0; + for (selfIndex = 0; selfIndex < selfPaths.length; selfIndex++) { + var selfPath = selfPaths[selfIndex]; + targetIndex = targetPaths.indexOf(selfPath); + if (targetIndex >= 0) { + commonPath = selfPath; + break; + } + } + if (!commonPath) { + return "before"; + } + + // get the relationship paths that associate these nodes to their common ancestor + var targetRelationship = targetPaths[targetIndex - 1]; + var selfRelationship = selfPaths[selfIndex - 1]; + if (!targetRelationship || !selfRelationship) { + return "before"; + } + + // container list so let's see which one is after the other + if (targetRelationship.listKey && targetRelationship.container === selfRelationship.container) { + return targetRelationship.key > selfRelationship.key ? "before" : "after"; + } + + // otherwise we're associated by a parent node, check which key comes before the other + var targetKeyPosition = t.VISITOR_KEYS[targetRelationship.type].indexOf(targetRelationship.key); + var selfKeyPosition = t.VISITOR_KEYS[selfRelationship.type].indexOf(selfRelationship.key); + return targetKeyPosition > selfKeyPosition ? "before" : "after"; +} + +function _guessExecutionStatusRelativeToDifferentFunctions(targetFuncParent) { + var targetFuncPath = targetFuncParent.path; + if (!targetFuncPath.isFunctionDeclaration()) return; + + // so we're in a completely different function, if this is a function declaration + // then we can be a bit smarter and handle cases where the function is either + // a. not called at all (part of an export) + // b. called directly + var binding = targetFuncPath.scope.getBinding(targetFuncPath.node.id.name); + + // no references! + if (!binding.references) return "before"; + + var referencePaths = binding.referencePaths; + + // verify that all of the references are calls + for (var _iterator = referencePaths, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var path = _ref; + + if (path.key !== "callee" || !path.parentPath.isCallExpression()) { + return; + } + } + + var allStatus = void 0; + + // verify that all the calls have the same execution status + for (var _iterator2 = referencePaths, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _path = _ref2; + + // if a reference is a child of the function we're checking against then we can + // safelty ignore it + var childOfFunction = !!_path.find(function (path) { + return path.node === targetFuncPath.node; + }); + if (childOfFunction) continue; + + var status = this._guessExecutionStatusRelativeTo(_path); + + if (allStatus) { + if (allStatus !== status) return; + } else { + allStatus = status; + } + } + + return allStatus; +} + +/** + * Resolve a "pointer" `NodePath` to it's absolute path. + */ + +function resolve(dangerous, resolved) { + return this._resolve(dangerous, resolved) || this; +} + +function _resolve(dangerous, resolved) { + var _this = this; + + // detect infinite recursion + // todo: possibly have a max length on this just to be safe + if (resolved && resolved.indexOf(this) >= 0) return; + + // we store all the paths we've "resolved" in this array to prevent infinite recursion + resolved = resolved || []; + resolved.push(this); + + if (this.isVariableDeclarator()) { + if (this.get("id").isIdentifier()) { + return this.get("init").resolve(dangerous, resolved); + } else { + // otherwise it's a request for a pattern and that's a bit more tricky + } + } else if (this.isReferencedIdentifier()) { + var binding = this.scope.getBinding(this.node.name); + if (!binding) return; + + // reassigned so we can't really resolve it + if (!binding.constant) return; + + // todo - lookup module in dependency graph + if (binding.kind === "module") return; + + if (binding.path !== this) { + var _ret = function () { + var ret = binding.path.resolve(dangerous, resolved); + // If the identifier resolves to parent node then we can't really resolve it. + if (_this.find(function (parent) { + return parent.node === ret.node; + })) return { + v: void 0 + }; + return { + v: ret + }; + }(); + + if ((typeof _ret === "undefined" ? "undefined" : (0, _typeof3.default)(_ret)) === "object") return _ret.v; + } + } else if (this.isTypeCastExpression()) { + return this.get("expression").resolve(dangerous, resolved); + } else if (dangerous && this.isMemberExpression()) { + // this is dangerous, as non-direct target assignments will mutate it's state + // making this resolution inaccurate + + var targetKey = this.toComputedKey(); + if (!t.isLiteral(targetKey)) return; + + var targetName = targetKey.value; + + var target = this.get("object").resolve(dangerous, resolved); + + if (target.isObjectExpression()) { + var props = target.get("properties"); + for (var _iterator3 = props, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var prop = _ref3; + + if (!prop.isProperty()) continue; + + var key = prop.get("key"); + + // { foo: obj } + var match = prop.isnt("computed") && key.isIdentifier({ name: targetName }); + + // { "foo": "obj" } or { ["foo"]: "obj" } + match = match || key.isLiteral({ value: targetName }); + + if (match) return prop.get("value").resolve(dangerous, resolved); + } + } else if (target.isArrayExpression() && !isNaN(+targetName)) { + var elems = target.get("elements"); + var elem = elems[targetName]; + if (elem) return elem.resolve(dangerous, resolved); + } + } +} +},{"babel-runtime/core-js/get-iterator":41,"babel-runtime/helpers/typeof":50,"babel-types":157,"lodash/includes":402}],31:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var referenceVisitor = { + ReferencedIdentifier: function ReferencedIdentifier(path, state) { + if (path.isJSXIdentifier() && _babelTypes.react.isCompatTag(path.node.name)) { + return; + } + + // direct references that we need to track to hoist this to the highest scope we can + var binding = path.scope.getBinding(path.node.name); + if (!binding) return; + + // this binding isn't accessible from the parent scope so we can safely ignore it + // eg. it's in a closure etc + if (binding !== state.scope.getBinding(path.node.name)) return; + + if (binding.constant) { + state.bindings[path.node.name] = binding; + } else { + for (var _iterator = binding.constantViolations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var violationPath = _ref; + + state.breakOnScopePaths = state.breakOnScopePaths.concat(violationPath.getAncestry()); + } + } + } +}; + +var PathHoister = function () { + function PathHoister(path, scope) { + (0, _classCallCheck3.default)(this, PathHoister); + + this.breakOnScopePaths = []; + this.bindings = {}; + this.scopes = []; + this.scope = scope; + this.path = path; + } + + PathHoister.prototype.isCompatibleScope = function isCompatibleScope(scope) { + for (var key in this.bindings) { + var binding = this.bindings[key]; + if (!scope.bindingIdentifierEquals(key, binding.identifier)) { + return false; + } + } + + return true; + }; + + PathHoister.prototype.getCompatibleScopes = function getCompatibleScopes() { + var scope = this.path.scope; + do { + if (this.isCompatibleScope(scope)) { + this.scopes.push(scope); + } else { + break; + } + + if (this.breakOnScopePaths.indexOf(scope.path) >= 0) { + break; + } + } while (scope = scope.parent); + }; + + PathHoister.prototype.getAttachmentPath = function getAttachmentPath() { + var scopes = this.scopes; + + var scope = scopes.pop(); + if (!scope) return; + + if (scope.path.isFunction()) { + if (this.hasOwnParamBindings(scope)) { + // should ignore this scope since it's ourselves + if (this.scope === scope) return; + + // needs to be attached to the body + return scope.path.get("body").get("body")[0]; + } else { + // doesn't need to be be attached to this scope + return this.getNextScopeStatementParent(); + } + } else if (scope.path.isProgram()) { + return this.getNextScopeStatementParent(); + } + }; + + PathHoister.prototype.getNextScopeStatementParent = function getNextScopeStatementParent() { + var scope = this.scopes.pop(); + if (scope) return scope.path.getStatementParent(); + }; + + PathHoister.prototype.hasOwnParamBindings = function hasOwnParamBindings(scope) { + for (var name in this.bindings) { + if (!scope.hasOwnBinding(name)) continue; + + var binding = this.bindings[name]; + if (binding.kind === "param") return true; + } + return false; + }; + + PathHoister.prototype.run = function run() { + var node = this.path.node; + if (node._hoisted) return; + node._hoisted = true; + + this.path.traverse(referenceVisitor, this); + + this.getCompatibleScopes(); + + var attachTo = this.getAttachmentPath(); + if (!attachTo) return; + + // don't bother hoisting to the same function as this will cause multiple branches to be evaluated more than once leading to a bad optimisation + if (attachTo.getFunctionParent() === this.path.getFunctionParent()) return; + + var uid = attachTo.scope.generateUidIdentifier("ref"); + + attachTo.insertBefore([t.variableDeclaration("var", [t.variableDeclarator(uid, this.path.node)])]); + + var parent = this.path.parentPath; + + if (parent.isJSXElement() && this.path.container === parent.node.children) { + // turning the `span` in `
` to an expression so we need to wrap it with + // an expression container + uid = t.JSXExpressionContainer(uid); + } + + this.path.replaceWith(uid); + }; + + return PathHoister; +}(); + +exports.default = PathHoister; +module.exports = exports["default"]; +},{"babel-runtime/core-js/get-iterator":41,"babel-runtime/helpers/classCallCheck":49,"babel-types":157}],32:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +// this file contains hooks that handle ancestry cleanup of parent nodes when removing children + +/** + * Pre hooks should be used for either rejecting removal or delegating removal + */ + +var hooks = exports.hooks = [function (self, parent) { + if (self.key === "body" && parent.isArrowFunctionExpression()) { + self.replaceWith(self.scope.buildUndefinedNode()); + return true; + } +}, function (self, parent) { + var removeParent = false; + + // while (NODE); + // removing the test of a while/switch, we can either just remove it entirely *or* turn the `test` into `true` + // unlikely that the latter will ever be what's wanted so we just remove the loop to avoid infinite recursion + removeParent = removeParent || self.key === "test" && (parent.isWhile() || parent.isSwitchCase()); + + // export NODE; + // just remove a declaration for an export as this is no longer valid + removeParent = removeParent || self.key === "declaration" && parent.isExportDeclaration(); + + // label: NODE + // stray labeled statement with no body + removeParent = removeParent || self.key === "body" && parent.isLabeledStatement(); + + // let NODE; + // remove an entire declaration if there are no declarators left + removeParent = removeParent || self.listKey === "declarations" && parent.isVariableDeclaration() && parent.node.declarations.length === 1; + + // NODE; + // remove the entire expression statement if there's no expression + removeParent = removeParent || self.key === "expression" && parent.isExpressionStatement(); + + if (removeParent) { + parent.remove(); + return true; + } +}, function (self, parent) { + if (parent.isSequenceExpression() && parent.node.expressions.length === 1) { + // (node, NODE); + // we've just removed the second element of a sequence expression so let's turn that sequence + // expression into a regular expression + parent.replaceWith(parent.node.expressions[0]); + return true; + } +}, function (self, parent) { + if (parent.isBinary()) { + // left + NODE; + // NODE + right; + // we're in a binary expression, better remove it and replace it with the last expression + if (self.key === "left") { + parent.replaceWith(parent.node.right); + } else { + // key === "right" + parent.replaceWith(parent.node.left); + } + return true; + } +}]; +},{}],33:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; +exports.Flow = exports.Pure = exports.Generated = exports.User = exports.Var = exports.BlockScoped = exports.Referenced = exports.Scope = exports.Expression = exports.Statement = exports.BindingIdentifier = exports.ReferencedMemberExpression = exports.ReferencedIdentifier = undefined; + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +var ReferencedIdentifier = exports.ReferencedIdentifier = { + types: ["Identifier", "JSXIdentifier"], + checkPath: function checkPath(_ref, opts) { + var node = _ref.node; + var parent = _ref.parent; + + if (!t.isIdentifier(node, opts)) { + if (t.isJSXIdentifier(node, opts)) { + if (_babelTypes.react.isCompatTag(node.name)) return false; + } else { + // not a JSXIdentifier or an Identifier + return false; + } + } + + // check if node is referenced + return t.isReferenced(node, parent); + } +}; + +var ReferencedMemberExpression = exports.ReferencedMemberExpression = { + types: ["MemberExpression"], + checkPath: function checkPath(_ref2) { + var node = _ref2.node; + var parent = _ref2.parent; + + return t.isMemberExpression(node) && t.isReferenced(node, parent); + } +}; + +var BindingIdentifier = exports.BindingIdentifier = { + types: ["Identifier"], + checkPath: function checkPath(_ref3) { + var node = _ref3.node; + var parent = _ref3.parent; + + return t.isIdentifier(node) && t.isBinding(node, parent); + } +}; + +var Statement = exports.Statement = { + types: ["Statement"], + checkPath: function checkPath(_ref4) { + var node = _ref4.node; + var parent = _ref4.parent; + + if (t.isStatement(node)) { + if (t.isVariableDeclaration(node)) { + if (t.isForXStatement(parent, { left: node })) return false; + if (t.isForStatement(parent, { init: node })) return false; + } + + return true; + } else { + return false; + } + } +}; + +var Expression = exports.Expression = { + types: ["Expression"], + checkPath: function checkPath(path) { + if (path.isIdentifier()) { + return path.isReferencedIdentifier(); + } else { + return t.isExpression(path.node); + } + } +}; + +var Scope = exports.Scope = { + types: ["Scopable"], + checkPath: function checkPath(path) { + return t.isScope(path.node, path.parent); + } +}; + +var Referenced = exports.Referenced = { + checkPath: function checkPath(path) { + return t.isReferenced(path.node, path.parent); + } +}; + +var BlockScoped = exports.BlockScoped = { + checkPath: function checkPath(path) { + return t.isBlockScoped(path.node); + } +}; + +var Var = exports.Var = { + types: ["VariableDeclaration"], + checkPath: function checkPath(path) { + return t.isVar(path.node); + } +}; + +var User = exports.User = { + checkPath: function checkPath(path) { + return path.node && !!path.node.loc; + } +}; + +var Generated = exports.Generated = { + checkPath: function checkPath(path) { + return !path.isUser(); + } +}; + +var Pure = exports.Pure = { + checkPath: function checkPath(path, opts) { + return path.scope.isPure(path.node, opts); + } +}; + +var Flow = exports.Flow = { + types: ["Flow", "ImportDeclaration", "ExportDeclaration"], + checkPath: function checkPath(_ref5) { + var node = _ref5.node; + + if (t.isFlow(node)) { + return true; + } else if (t.isImportDeclaration(node)) { + return node.importKind === "type" || node.importKind === "typeof"; + } else if (t.isExportDeclaration(node)) { + return node.exportKind === "type"; + } else { + return false; + } + } +}; +},{"babel-types":157}],34:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.insertBefore = insertBefore; +exports._containerInsert = _containerInsert; +exports._containerInsertBefore = _containerInsertBefore; +exports._containerInsertAfter = _containerInsertAfter; +exports._maybePopFromStatements = _maybePopFromStatements; +exports.insertAfter = insertAfter; +exports.updateSiblingKeys = updateSiblingKeys; +exports._verifyNodeList = _verifyNodeList; +exports.unshiftContainer = unshiftContainer; +exports.pushContainer = pushContainer; +exports.hoist = hoist; + +var _cache = require("../cache"); + +var _hoister = require("./lib/hoister"); + +var _hoister2 = _interopRequireDefault(_hoister); + +var _index = require("./index"); + +var _index2 = _interopRequireDefault(_index); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * Insert the provided nodes before the current one. + */ + +/* eslint max-len: 0 */ +// This file contains methods that modify the path/node in some ways. + +function insertBefore(nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + if (this.parentPath.isExpressionStatement() || this.parentPath.isLabeledStatement()) { + return this.parentPath.insertBefore(nodes); + } else if (this.isNodeType("Expression") || this.parentPath.isForStatement() && this.key === "init") { + if (this.node) nodes.push(this.node); + this.replaceExpressionWithStatements(nodes); + } else { + this._maybePopFromStatements(nodes); + if (Array.isArray(this.container)) { + return this._containerInsertBefore(nodes); + } else if (this.isStatementOrBlock()) { + if (this.node) nodes.push(this.node); + this._replaceWith(t.blockStatement(nodes)); + } else { + throw new Error("We don't know what to do with this node type. We were previously a Statement but we can't fit in here?"); + } + } + + return [this]; +} + +function _containerInsert(from, nodes) { + this.updateSiblingKeys(from, nodes.length); + + var paths = []; + + for (var i = 0; i < nodes.length; i++) { + var to = from + i; + var node = nodes[i]; + this.container.splice(to, 0, node); + + if (this.context) { + var path = this.context.create(this.parent, this.container, to, this.listKey); + + // While this path may have a context, there is currently no guarantee that the context + // will be the active context, because `popContext` may leave a final context in place. + // We should remove this `if` and always push once T7171 has been resolved. + if (this.context.queue) path.pushContext(this.context); + paths.push(path); + } else { + paths.push(_index2.default.get({ + parentPath: this.parentPath, + parent: this.parent, + container: this.container, + listKey: this.listKey, + key: to + })); + } + } + + var contexts = this._getQueueContexts(); + + for (var _iterator = paths, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var _path = _ref; + + _path.setScope(); + _path.debug(function () { + return "Inserted."; + }); + + for (var _iterator2 = contexts, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var context = _ref2; + + context.maybeQueue(_path, true); + } + } + + return paths; +} + +function _containerInsertBefore(nodes) { + return this._containerInsert(this.key, nodes); +} + +function _containerInsertAfter(nodes) { + return this._containerInsert(this.key + 1, nodes); +} + +function _maybePopFromStatements(nodes) { + var last = nodes[nodes.length - 1]; + var isIdentifier = t.isIdentifier(last) || t.isExpressionStatement(last) && t.isIdentifier(last.expression); + + if (isIdentifier && !this.isCompletionRecord()) { + nodes.pop(); + } +} + +/** + * Insert the provided nodes after the current one. When inserting nodes after an + * expression, ensure that the completion record is correct by pushing the current node. + */ + +function insertAfter(nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + if (this.parentPath.isExpressionStatement() || this.parentPath.isLabeledStatement()) { + return this.parentPath.insertAfter(nodes); + } else if (this.isNodeType("Expression") || this.parentPath.isForStatement() && this.key === "init") { + if (this.node) { + var temp = this.scope.generateDeclaredUidIdentifier(); + nodes.unshift(t.expressionStatement(t.assignmentExpression("=", temp, this.node))); + nodes.push(t.expressionStatement(temp)); + } + this.replaceExpressionWithStatements(nodes); + } else { + this._maybePopFromStatements(nodes); + if (Array.isArray(this.container)) { + return this._containerInsertAfter(nodes); + } else if (this.isStatementOrBlock()) { + if (this.node) nodes.unshift(this.node); + this._replaceWith(t.blockStatement(nodes)); + } else { + throw new Error("We don't know what to do with this node type. We were previously a Statement but we can't fit in here?"); + } + } + + return [this]; +} + +/** + * Update all sibling node paths after `fromIndex` by `incrementBy`. + */ + +function updateSiblingKeys(fromIndex, incrementBy) { + if (!this.parent) return; + + var paths = _cache.path.get(this.parent); + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (path.key >= fromIndex) { + path.key += incrementBy; + } + } +} + +function _verifyNodeList(nodes) { + if (!nodes) { + return []; + } + + if (nodes.constructor !== Array) { + nodes = [nodes]; + } + + for (var i = 0; i < nodes.length; i++) { + var node = nodes[i]; + var msg = void 0; + + if (!node) { + msg = "has falsy node"; + } else if ((typeof node === "undefined" ? "undefined" : (0, _typeof3.default)(node)) !== "object") { + msg = "contains a non-object node"; + } else if (!node.type) { + msg = "without a type"; + } else if (node instanceof _index2.default) { + msg = "has a NodePath when it expected a raw object"; + } + + if (msg) { + var type = Array.isArray(node) ? "array" : typeof node === "undefined" ? "undefined" : (0, _typeof3.default)(node); + throw new Error("Node list " + msg + " with the index of " + i + " and type of " + type); + } + } + + return nodes; +} + +function unshiftContainer(listKey, nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + // get the first path and insert our nodes before it, if it doesn't exist then it + // doesn't matter, our nodes will be inserted anyway + var path = _index2.default.get({ + parentPath: this, + parent: this.node, + container: this.node[listKey], + listKey: listKey, + key: 0 + }); + + return path.insertBefore(nodes); +} + +function pushContainer(listKey, nodes) { + this._assertUnremoved(); + + nodes = this._verifyNodeList(nodes); + + // get an invisible path that represents the last node + 1 and replace it with our + // nodes, effectively inlining it + + var container = this.node[listKey]; + var path = _index2.default.get({ + parentPath: this, + parent: this.node, + container: container, + listKey: listKey, + key: container.length + }); + + return path.replaceWithMultiple(nodes); +} + +/** + * Hoist the current node to the highest scope possible and return a UID + * referencing it. + */ + +function hoist() { + var scope = arguments.length <= 0 || arguments[0] === undefined ? this.scope : arguments[0]; + + var hoister = new _hoister2.default(this, scope); + return hoister.run(); +} +},{"../cache":16,"./index":26,"./lib/hoister":31,"babel-runtime/core-js/get-iterator":41,"babel-runtime/helpers/typeof":50,"babel-types":157}],35:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.remove = remove; +exports._callRemovalHooks = _callRemovalHooks; +exports._remove = _remove; +exports._markRemoved = _markRemoved; +exports._assertUnremoved = _assertUnremoved; + +var _removalHooks = require("./lib/removal-hooks"); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function remove() { + this._assertUnremoved(); + + this.resync(); + + if (this._callRemovalHooks()) { + this._markRemoved(); + return; + } + + this.shareCommentsWithSiblings(); + this._remove(); + this._markRemoved(); +} // This file contains methods responsible for removing a node. + +function _callRemovalHooks() { + for (var _iterator = _removalHooks.hooks, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var fn = _ref; + + if (fn(this, this.parentPath)) return true; + } +} + +function _remove() { + if (Array.isArray(this.container)) { + this.container.splice(this.key, 1); + this.updateSiblingKeys(this.key, -1); + } else { + this._replaceWith(null); + } +} + +function _markRemoved() { + this.shouldSkip = true; + this.removed = true; + this.node = null; +} + +function _assertUnremoved() { + if (this.removed) { + throw this.buildCodeFrameError("NodePath has been removed so is read-only."); + } +} +},{"./lib/removal-hooks":32,"babel-runtime/core-js/get-iterator":41}],36:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.replaceWithMultiple = replaceWithMultiple; +exports.replaceWithSourceString = replaceWithSourceString; +exports.replaceWith = replaceWith; +exports._replaceWith = _replaceWith; +exports.replaceExpressionWithStatements = replaceExpressionWithStatements; +exports.replaceInline = replaceInline; + +var _babelCodeFrame = require("babel-code-frame"); + +var _babelCodeFrame2 = _interopRequireDefault(_babelCodeFrame); + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +var _index3 = require("./index"); + +var _index4 = _interopRequireDefault(_index3); + +var _babylon = require("babylon"); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var hoistVariablesVisitor = { + Function: function Function(path) { + path.skip(); + }, + VariableDeclaration: function VariableDeclaration(path) { + if (path.node.kind !== "var") return; + + var bindings = path.getBindingIdentifiers(); + for (var key in bindings) { + path.scope.push({ id: bindings[key] }); + } + + var exprs = []; + + for (var _iterator = path.node.declarations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var declar = _ref; + + if (declar.init) { + exprs.push(t.expressionStatement(t.assignmentExpression("=", declar.id, declar.init))); + } + } + + path.replaceWithMultiple(exprs); + } +}; + +/** + * Replace a node with an array of multiple. This method performs the following steps: + * + * - Inherit the comments of first provided node with that of the current node. + * - Insert the provided nodes after the current node. + * - Remove the current node. + */ + +/* eslint max-len: 0 */ +// This file contains methods responsible for replacing a node with another. + +function replaceWithMultiple(nodes) { + this.resync(); + + nodes = this._verifyNodeList(nodes); + t.inheritLeadingComments(nodes[0], this.node); + t.inheritTrailingComments(nodes[nodes.length - 1], this.node); + this.node = this.container[this.key] = null; + this.insertAfter(nodes); + + if (this.node) { + this.requeue(); + } else { + this.remove(); + } +} + +/** + * Parse a string as an expression and replace the current node with the result. + * + * NOTE: This is typically not a good idea to use. Building source strings when + * transforming ASTs is an antipattern and SHOULD NOT be encouraged. Even if it's + * easier to use, your transforms will be extremely brittle. + */ + +function replaceWithSourceString(replacement) { + this.resync(); + + try { + replacement = "(" + replacement + ")"; + replacement = (0, _babylon.parse)(replacement); + } catch (err) { + var loc = err.loc; + if (loc) { + err.message += " - make sure this is an expression."; + err.message += "\n" + (0, _babelCodeFrame2.default)(replacement, loc.line, loc.column + 1); + } + throw err; + } + + replacement = replacement.program.body[0].expression; + _index2.default.removeProperties(replacement); + return this.replaceWith(replacement); +} + +/** + * Replace the current node with another. + */ + +function replaceWith(replacement) { + this.resync(); + + if (this.removed) { + throw new Error("You can't replace this node, we've already removed it"); + } + + if (replacement instanceof _index4.default) { + replacement = replacement.node; + } + + if (!replacement) { + throw new Error("You passed `path.replaceWith()` a falsy node, use `path.remove()` instead"); + } + + if (this.node === replacement) { + return; + } + + if (this.isProgram() && !t.isProgram(replacement)) { + throw new Error("You can only replace a Program root node with another Program node"); + } + + if (Array.isArray(replacement)) { + throw new Error("Don't use `path.replaceWith()` with an array of nodes, use `path.replaceWithMultiple()`"); + } + + if (typeof replacement === "string") { + throw new Error("Don't use `path.replaceWith()` with a source string, use `path.replaceWithSourceString()`"); + } + + if (this.isNodeType("Statement") && t.isExpression(replacement)) { + if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement)) { + // replacing a statement with an expression so wrap it in an expression statement + replacement = t.expressionStatement(replacement); + } + } + + if (this.isNodeType("Expression") && t.isStatement(replacement)) { + if (!this.canHaveVariableDeclarationOrExpression() && !this.canSwapBetweenExpressionAndStatement(replacement)) { + // replacing an expression with a statement so let's explode it + return this.replaceExpressionWithStatements([replacement]); + } + } + + var oldNode = this.node; + if (oldNode) { + t.inheritsComments(replacement, oldNode); + t.removeComments(oldNode); + } + + // replace the node + this._replaceWith(replacement); + this.type = replacement.type; + + // potentially create new scope + this.setScope(); + + // requeue for visiting + this.requeue(); +} + +/** + * Description + */ + +function _replaceWith(node) { + if (!this.container) { + throw new ReferenceError("Container is falsy"); + } + + if (this.inList) { + t.validate(this.parent, this.key, [node]); + } else { + t.validate(this.parent, this.key, node); + } + + this.debug(function () { + return "Replace with " + (node && node.type); + }); + + this.node = this.container[this.key] = node; +} + +/** + * This method takes an array of statements nodes and then explodes it + * into expressions. This method retains completion records which is + * extremely important to retain original semantics. + */ + +function replaceExpressionWithStatements(nodes) { + this.resync(); + + var toSequenceExpression = t.toSequenceExpression(nodes, this.scope); + + if (t.isSequenceExpression(toSequenceExpression)) { + var exprs = toSequenceExpression.expressions; + + if (exprs.length >= 2 && this.parentPath.isExpressionStatement()) { + this._maybePopFromStatements(exprs); + } + + // could be just one element due to the previous maybe popping + if (exprs.length === 1) { + this.replaceWith(exprs[0]); + } else { + this.replaceWith(toSequenceExpression); + } + } else if (toSequenceExpression) { + this.replaceWith(toSequenceExpression); + } else { + var container = t.functionExpression(null, [], t.blockStatement(nodes)); + container.shadow = true; + + this.replaceWith(t.callExpression(container, [])); + this.traverse(hoistVariablesVisitor); + + // add implicit returns to all ending expression statements + var completionRecords = this.get("callee").getCompletionRecords(); + for (var _iterator2 = completionRecords, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var path = _ref2; + + if (!path.isExpressionStatement()) continue; + + var loop = path.findParent(function (path) { + return path.isLoop(); + }); + if (loop) { + var callee = this.get("callee"); + + var uid = callee.scope.generateDeclaredUidIdentifier("ret"); + callee.get("body").pushContainer("body", t.returnStatement(uid)); + + path.get("expression").replaceWith(t.assignmentExpression("=", uid, path.node.expression)); + } else { + path.replaceWith(t.returnStatement(path.node.expression)); + } + } + + return this.node; + } +} + +function replaceInline(nodes) { + this.resync(); + + if (Array.isArray(nodes)) { + if (Array.isArray(this.container)) { + nodes = this._verifyNodeList(nodes); + this._containerInsertAfter(nodes); + return this.remove(); + } else { + return this.replaceWithMultiple(nodes); + } + } else { + return this.replaceWith(nodes); + } +} +},{"../index":19,"./index":26,"babel-code-frame":11,"babel-runtime/core-js/get-iterator":41,"babel-types":157,"babylon":248}],37:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * This class is responsible for a binding inside of a scope. + * + * It tracks the following: + * + * * Node path. + * * Amount of times referenced by other nodes. + * * Paths to nodes that reassign or modify this binding. + * * The kind of binding. (Is it a parameter, declaration etc) + */ + +var Binding = function () { + function Binding(_ref) { + var existing = _ref.existing; + var identifier = _ref.identifier; + var scope = _ref.scope; + var path = _ref.path; + var kind = _ref.kind; + (0, _classCallCheck3.default)(this, Binding); + + this.identifier = identifier; + this.scope = scope; + this.path = path; + this.kind = kind; + + this.constantViolations = []; + this.constant = true; + + this.referencePaths = []; + this.referenced = false; + this.references = 0; + + this.clearValue(); + + if (existing) { + this.constantViolations = [].concat(existing.path, existing.constantViolations, this.constantViolations); + } + } + + Binding.prototype.deoptValue = function deoptValue() { + this.clearValue(); + this.hasDeoptedValue = true; + }; + + Binding.prototype.setValue = function setValue(value) { + if (this.hasDeoptedValue) return; + this.hasValue = true; + this.value = value; + }; + + Binding.prototype.clearValue = function clearValue() { + this.hasDeoptedValue = false; + this.hasValue = false; + this.value = null; + }; + + /** + * Register a constant violation with the provided `path`. + */ + + Binding.prototype.reassign = function reassign(path) { + this.constant = false; + if (this.constantViolations.indexOf(path) !== -1) { + return; + } + this.constantViolations.push(path); + }; + + /** + * Increment the amount of references to this binding. + */ + + Binding.prototype.reference = function reference(path) { + if (this.referencePaths.indexOf(path) !== -1) { + return; + } + this.referenced = true; + this.references++; + this.referencePaths.push(path); + }; + + /** + * Decrement the amount of references to this binding. + */ + + Binding.prototype.dereference = function dereference() { + this.references--; + this.referenced = !!this.references; + }; + + return Binding; +}(); + +exports.default = Binding; +module.exports = exports["default"]; +},{"babel-runtime/helpers/classCallCheck":49}],38:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +var _create = require("babel-runtime/core-js/object/create"); + +var _create2 = _interopRequireDefault(_create); + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +var _includes = require("lodash/includes"); + +var _includes2 = _interopRequireDefault(_includes); + +var _repeat = require("lodash/repeat"); + +var _repeat2 = _interopRequireDefault(_repeat); + +var _renamer = require("./lib/renamer"); + +var _renamer2 = _interopRequireDefault(_renamer); + +var _index = require("../index"); + +var _index2 = _interopRequireDefault(_index); + +var _defaults = require("lodash/defaults"); + +var _defaults2 = _interopRequireDefault(_defaults); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _binding2 = require("./binding"); + +var _binding3 = _interopRequireDefault(_binding2); + +var _globals = require("globals"); + +var _globals2 = _interopRequireDefault(_globals); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _cache = require("../cache"); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +// Number of calls to the crawl method to figure out whether we're +// somewhere inside a call that was trigerred by call. This is meant +// to be used to figure out whether a warning should be trigerred. +// See `warnOnFlowBinding`. +/* eslint max-len: 0 */ + +var _crawlCallsCount = 0; + +/** + * To avoid creating a new Scope instance for each traversal, we maintain a cache on the + * node itself containing all scopes it has been associated with. + */ + +function getCache(path, parentScope, self) { + var scopes = _cache.scope.get(path.node) || []; + + for (var _iterator = scopes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var scope = _ref; + + if (scope.parent === parentScope && scope.path === path) return scope; + } + + scopes.push(self); + + if (!_cache.scope.has(path.node)) { + _cache.scope.set(path.node, scopes); + } +} + +// + +var collectorVisitor = { + For: function For(path) { + for (var _iterator2 = t.FOR_INIT_KEYS, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var key = _ref2; + + var declar = path.get(key); + if (declar.isVar()) path.scope.getFunctionParent().registerBinding("var", declar); + } + }, + Declaration: function Declaration(path) { + // delegate block scope handling to the `blockVariableVisitor` + if (path.isBlockScoped()) return; + + // this will be hit again once we traverse into it after this iteration + if (path.isExportDeclaration() && path.get("declaration").isDeclaration()) return; + + // TODO(amasad): remove support for flow as bindings (See warning below). + //if (path.isFlow()) return; + + // we've ran into a declaration! + path.scope.getFunctionParent().registerDeclaration(path); + }, + ReferencedIdentifier: function ReferencedIdentifier(path, state) { + state.references.push(path); + }, + ForXStatement: function ForXStatement(path, state) { + var left = path.get("left"); + if (left.isPattern() || left.isIdentifier()) { + state.constantViolations.push(left); + } + }, + + + ExportDeclaration: { + exit: function exit(_ref3) { + var node = _ref3.node; + var scope = _ref3.scope; + + var declar = node.declaration; + if (t.isClassDeclaration(declar) || t.isFunctionDeclaration(declar)) { + var _id = declar.id; + if (!_id) return; + + var binding = scope.getBinding(_id.name); + if (binding) binding.reference(); + } else if (t.isVariableDeclaration(declar)) { + for (var _iterator3 = declar.declarations, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref4; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref4 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref4 = _i3.value; + } + + var decl = _ref4; + + var ids = t.getBindingIdentifiers(decl); + for (var name in ids) { + var _binding = scope.getBinding(name); + if (_binding) _binding.reference(); + } + } + } + } + }, + + LabeledStatement: function LabeledStatement(path) { + path.scope.getProgramParent().addGlobal(path.node); + path.scope.getBlockParent().registerDeclaration(path); + }, + AssignmentExpression: function AssignmentExpression(path, state) { + state.assignments.push(path); + }, + UpdateExpression: function UpdateExpression(path, state) { + state.constantViolations.push(path.get("argument")); + }, + UnaryExpression: function UnaryExpression(path, state) { + if (path.node.operator === "delete") { + state.constantViolations.push(path.get("argument")); + } + }, + BlockScoped: function BlockScoped(path) { + var scope = path.scope; + if (scope.path === path) scope = scope.parent; + scope.getBlockParent().registerDeclaration(path); + }, + ClassDeclaration: function ClassDeclaration(path) { + var id = path.node.id; + if (!id) return; + + var name = id.name; + path.scope.bindings[name] = path.scope.getBinding(name); + }, + Block: function Block(path) { + var paths = path.get("body"); + for (var _iterator4 = paths, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref5; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref5 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref5 = _i4.value; + } + + var bodyPath = _ref5; + + if (bodyPath.isFunctionDeclaration()) { + path.scope.getBlockParent().registerDeclaration(bodyPath); + } + } + } +}; + +var uid = 0; + +var Scope = function () { + + /** + * This searches the current "scope" and collects all references/bindings + * within. + */ + + function Scope(path, parentScope) { + (0, _classCallCheck3.default)(this, Scope); + + if (parentScope && parentScope.block === path.node) { + return parentScope; + } + + var cached = getCache(path, parentScope, this); + if (cached) return cached; + + this.uid = uid++; + this.parent = parentScope; + this.hub = path.hub; + + this.parentBlock = path.parent; + this.block = path.node; + this.path = path; + } + + /** + * Globals. + */ + + /** + * Variables available in current context. + */ + + /** + * Traverse node with current scope and path. + */ + + Scope.prototype.traverse = function traverse(node, opts, state) { + (0, _index2.default)(node, opts, this, state, this.path); + }; + + /** + * Generate a unique identifier and add it to the current scope. + */ + + Scope.prototype.generateDeclaredUidIdentifier = function generateDeclaredUidIdentifier() { + var name = arguments.length <= 0 || arguments[0] === undefined ? "temp" : arguments[0]; + + var id = this.generateUidIdentifier(name); + this.push({ id: id }); + return id; + }; + + /** + * Generate a unique identifier. + */ + + Scope.prototype.generateUidIdentifier = function generateUidIdentifier() { + var name = arguments.length <= 0 || arguments[0] === undefined ? "temp" : arguments[0]; + + return t.identifier(this.generateUid(name)); + }; + + /** + * Generate a unique `_id1` binding. + */ + + Scope.prototype.generateUid = function generateUid() { + var name = arguments.length <= 0 || arguments[0] === undefined ? "temp" : arguments[0]; + + name = t.toIdentifier(name).replace(/^_+/, "").replace(/[0-9]+$/g, ""); + + var uid = void 0; + var i = 0; + do { + uid = this._generateUid(name, i); + i++; + } while (this.hasBinding(uid) || this.hasGlobal(uid) || this.hasReference(uid)); + + var program = this.getProgramParent(); + program.references[uid] = true; + program.uids[uid] = true; + + return uid; + }; + + /** + * Generate an `_id1`. + */ + + Scope.prototype._generateUid = function _generateUid(name, i) { + var id = name; + if (i > 1) id += i; + return "_" + id; + }; + + /** + * Generate a unique identifier based on a node. + */ + + Scope.prototype.generateUidIdentifierBasedOnNode = function generateUidIdentifierBasedOnNode(parent, defaultName) { + var node = parent; + + if (t.isAssignmentExpression(parent)) { + node = parent.left; + } else if (t.isVariableDeclarator(parent)) { + node = parent.id; + } else if (t.isObjectProperty(node) || t.isObjectMethod(node)) { + node = node.key; + } + + var parts = []; + + var add = function add(node) { + if (t.isModuleDeclaration(node)) { + if (node.source) { + add(node.source); + } else if (node.specifiers && node.specifiers.length) { + for (var _iterator5 = node.specifiers, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) { + var _ref6; + + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref6 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref6 = _i5.value; + } + + var specifier = _ref6; + + add(specifier); + } + } else if (node.declaration) { + add(node.declaration); + } + } else if (t.isModuleSpecifier(node)) { + add(node.local); + } else if (t.isMemberExpression(node)) { + add(node.object); + add(node.property); + } else if (t.isIdentifier(node)) { + parts.push(node.name); + } else if (t.isLiteral(node)) { + parts.push(node.value); + } else if (t.isCallExpression(node)) { + add(node.callee); + } else if (t.isObjectExpression(node) || t.isObjectPattern(node)) { + for (var _iterator6 = node.properties, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : (0, _getIterator3.default)(_iterator6);;) { + var _ref7; + + if (_isArray6) { + if (_i6 >= _iterator6.length) break; + _ref7 = _iterator6[_i6++]; + } else { + _i6 = _iterator6.next(); + if (_i6.done) break; + _ref7 = _i6.value; + } + + var prop = _ref7; + + add(prop.key || prop.argument); + } + } + }; + + add(node); + + var id = parts.join("$"); + id = id.replace(/^_/, "") || defaultName || "ref"; + + return this.generateUidIdentifier(id.slice(0, 20)); + }; + + /** + * Determine whether evaluating the specific input `node` is a consequenceless reference. ie. + * evaluating it wont result in potentially arbitrary code from being ran. The following are + * whitelisted and determined not to cause side effects: + * + * - `this` expressions + * - `super` expressions + * - Bound identifiers + */ + + Scope.prototype.isStatic = function isStatic(node) { + if (t.isThisExpression(node) || t.isSuper(node)) { + return true; + } + + if (t.isIdentifier(node)) { + var binding = this.getBinding(node.name); + if (binding) { + return binding.constant; + } else { + return this.hasBinding(node.name); + } + } + + return false; + }; + + /** + * Possibly generate a memoised identifier if it is not static and has consequences. + */ + + Scope.prototype.maybeGenerateMemoised = function maybeGenerateMemoised(node, dontPush) { + if (this.isStatic(node)) { + return null; + } else { + var _id2 = this.generateUidIdentifierBasedOnNode(node); + if (!dontPush) this.push({ id: _id2 }); + return _id2; + } + }; + + Scope.prototype.checkBlockScopedCollisions = function checkBlockScopedCollisions(local, kind, name, id) { + // ignore parameters + if (kind === "param") return; + + // ignore hoisted functions if there's also a local let + if (kind === "hoisted" && local.kind === "let") return; + + var duplicate = false; + + // don't allow duplicate bindings to exist alongside + if (!duplicate) duplicate = kind === "let" || local.kind === "let" || local.kind === "const" || local.kind === "module"; + + // don't allow a local of param with a kind of let + if (!duplicate) duplicate = local.kind === "param" && (kind === "let" || kind === "const"); + + if (duplicate) { + throw this.hub.file.buildCodeFrameError(id, messages.get("scopeDuplicateDeclaration", name), TypeError); + } + }; + + Scope.prototype.rename = function rename(oldName, newName, block) { + var binding = this.getBinding(oldName); + if (binding) { + newName = newName || this.generateUidIdentifier(oldName).name; + return new _renamer2.default(binding, oldName, newName).rename(block); + } + }; + + Scope.prototype._renameFromMap = function _renameFromMap(map, oldName, newName, value) { + if (map[oldName]) { + map[newName] = value; + map[oldName] = null; + } + }; + + Scope.prototype.dump = function dump() { + var sep = (0, _repeat2.default)("-", 60); + console.log(sep); + var scope = this; + do { + console.log("#", scope.block.type); + for (var name in scope.bindings) { + var binding = scope.bindings[name]; + console.log(" -", name, { + constant: binding.constant, + references: binding.references, + violations: binding.constantViolations.length, + kind: binding.kind + }); + } + } while (scope = scope.parent); + console.log(sep); + }; + + Scope.prototype.toArray = function toArray(node, i) { + var file = this.hub.file; + + if (t.isIdentifier(node)) { + var binding = this.getBinding(node.name); + if (binding && binding.constant && binding.path.isGenericType("Array")) return node; + } + + if (t.isArrayExpression(node)) { + return node; + } + + if (t.isIdentifier(node, { name: "arguments" })) { + return t.callExpression(t.memberExpression(t.memberExpression(t.memberExpression(t.identifier("Array"), t.identifier("prototype")), t.identifier("slice")), t.identifier("call")), [node]); + } + + var helperName = "toArray"; + var args = [node]; + if (i === true) { + helperName = "toConsumableArray"; + } else if (i) { + args.push(t.numericLiteral(i)); + helperName = "slicedToArray"; + // TODO if (this.hub.file.isLoose("es6.forOf")) helperName += "-loose"; + } + return t.callExpression(file.addHelper(helperName), args); + }; + + Scope.prototype.registerDeclaration = function registerDeclaration(path) { + if (path.isLabeledStatement()) { + this.registerBinding("label", path); + } else if (path.isFunctionDeclaration()) { + this.registerBinding("hoisted", path.get("id"), path); + } else if (path.isVariableDeclaration()) { + var declarations = path.get("declarations"); + for (var _iterator7 = declarations, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : (0, _getIterator3.default)(_iterator7);;) { + var _ref8; + + if (_isArray7) { + if (_i7 >= _iterator7.length) break; + _ref8 = _iterator7[_i7++]; + } else { + _i7 = _iterator7.next(); + if (_i7.done) break; + _ref8 = _i7.value; + } + + var declar = _ref8; + + this.registerBinding(path.node.kind, declar); + } + } else if (path.isClassDeclaration()) { + this.registerBinding("let", path); + } else if (path.isImportDeclaration()) { + var specifiers = path.get("specifiers"); + for (var _iterator8 = specifiers, _isArray8 = Array.isArray(_iterator8), _i8 = 0, _iterator8 = _isArray8 ? _iterator8 : (0, _getIterator3.default)(_iterator8);;) { + var _ref9; + + if (_isArray8) { + if (_i8 >= _iterator8.length) break; + _ref9 = _iterator8[_i8++]; + } else { + _i8 = _iterator8.next(); + if (_i8.done) break; + _ref9 = _i8.value; + } + + var specifier = _ref9; + + this.registerBinding("module", specifier); + } + } else if (path.isExportDeclaration()) { + var _declar = path.get("declaration"); + if (_declar.isClassDeclaration() || _declar.isFunctionDeclaration() || _declar.isVariableDeclaration()) { + this.registerDeclaration(_declar); + } + } else { + this.registerBinding("unknown", path); + } + }; + + Scope.prototype.buildUndefinedNode = function buildUndefinedNode() { + if (this.hasBinding("undefined")) { + return t.unaryExpression("void", t.numericLiteral(0), true); + } else { + return t.identifier("undefined"); + } + }; + + Scope.prototype.registerConstantViolation = function registerConstantViolation(path) { + var ids = path.getBindingIdentifiers(); + for (var name in ids) { + var binding = this.getBinding(name); + if (binding) binding.reassign(path); + } + }; + + Scope.prototype.registerBinding = function registerBinding(kind, path) { + var bindingPath = arguments.length <= 2 || arguments[2] === undefined ? path : arguments[2]; + + if (!kind) throw new ReferenceError("no `kind`"); + + if (path.isVariableDeclaration()) { + var declarators = path.get("declarations"); + for (var _iterator9 = declarators, _isArray9 = Array.isArray(_iterator9), _i9 = 0, _iterator9 = _isArray9 ? _iterator9 : (0, _getIterator3.default)(_iterator9);;) { + var _ref10; + + if (_isArray9) { + if (_i9 >= _iterator9.length) break; + _ref10 = _iterator9[_i9++]; + } else { + _i9 = _iterator9.next(); + if (_i9.done) break; + _ref10 = _i9.value; + } + + var declar = _ref10; + + this.registerBinding(kind, declar); + } + return; + } + + var parent = this.getProgramParent(); + var ids = path.getBindingIdentifiers(true); + + for (var name in ids) { + for (var _iterator10 = ids[name], _isArray10 = Array.isArray(_iterator10), _i10 = 0, _iterator10 = _isArray10 ? _iterator10 : (0, _getIterator3.default)(_iterator10);;) { + var _ref11; + + if (_isArray10) { + if (_i10 >= _iterator10.length) break; + _ref11 = _iterator10[_i10++]; + } else { + _i10 = _iterator10.next(); + if (_i10.done) break; + _ref11 = _i10.value; + } + + var _id3 = _ref11; + + var local = this.getOwnBinding(name); + if (local) { + // same identifier so continue safely as we're likely trying to register it + // multiple times + if (local.identifier === _id3) continue; + + this.checkBlockScopedCollisions(local, kind, name, _id3); + } + + // It's erroneous that we currently consider flow a binding, however, we can't + // remove it because people might be depending on it. See warning section + // in `warnOnFlowBinding`. + if (local && local.path.isFlow()) local = null; + + parent.references[name] = true; + + this.bindings[name] = new _binding3.default({ + identifier: _id3, + existing: local, + scope: this, + path: bindingPath, + kind: kind + }); + } + } + }; + + Scope.prototype.addGlobal = function addGlobal(node) { + this.globals[node.name] = node; + }; + + Scope.prototype.hasUid = function hasUid(name) { + var scope = this; + + do { + if (scope.uids[name]) return true; + } while (scope = scope.parent); + + return false; + }; + + Scope.prototype.hasGlobal = function hasGlobal(name) { + var scope = this; + + do { + if (scope.globals[name]) return true; + } while (scope = scope.parent); + + return false; + }; + + Scope.prototype.hasReference = function hasReference(name) { + var scope = this; + + do { + if (scope.references[name]) return true; + } while (scope = scope.parent); + + return false; + }; + + Scope.prototype.isPure = function isPure(node, constantsOnly) { + if (t.isIdentifier(node)) { + var binding = this.getBinding(node.name); + if (!binding) return false; + if (constantsOnly) return binding.constant; + return true; + } else if (t.isClass(node)) { + if (node.superClass && !this.isPure(node.superClass, constantsOnly)) return false; + return this.isPure(node.body, constantsOnly); + } else if (t.isClassBody(node)) { + for (var _iterator11 = node.body, _isArray11 = Array.isArray(_iterator11), _i11 = 0, _iterator11 = _isArray11 ? _iterator11 : (0, _getIterator3.default)(_iterator11);;) { + var _ref12; + + if (_isArray11) { + if (_i11 >= _iterator11.length) break; + _ref12 = _iterator11[_i11++]; + } else { + _i11 = _iterator11.next(); + if (_i11.done) break; + _ref12 = _i11.value; + } + + var method = _ref12; + + if (!this.isPure(method, constantsOnly)) return false; + } + return true; + } else if (t.isBinary(node)) { + return this.isPure(node.left, constantsOnly) && this.isPure(node.right, constantsOnly); + } else if (t.isArrayExpression(node)) { + for (var _iterator12 = node.elements, _isArray12 = Array.isArray(_iterator12), _i12 = 0, _iterator12 = _isArray12 ? _iterator12 : (0, _getIterator3.default)(_iterator12);;) { + var _ref13; + + if (_isArray12) { + if (_i12 >= _iterator12.length) break; + _ref13 = _iterator12[_i12++]; + } else { + _i12 = _iterator12.next(); + if (_i12.done) break; + _ref13 = _i12.value; + } + + var elem = _ref13; + + if (!this.isPure(elem, constantsOnly)) return false; + } + return true; + } else if (t.isObjectExpression(node)) { + for (var _iterator13 = node.properties, _isArray13 = Array.isArray(_iterator13), _i13 = 0, _iterator13 = _isArray13 ? _iterator13 : (0, _getIterator3.default)(_iterator13);;) { + var _ref14; + + if (_isArray13) { + if (_i13 >= _iterator13.length) break; + _ref14 = _iterator13[_i13++]; + } else { + _i13 = _iterator13.next(); + if (_i13.done) break; + _ref14 = _i13.value; + } + + var prop = _ref14; + + if (!this.isPure(prop, constantsOnly)) return false; + } + return true; + } else if (t.isClassMethod(node)) { + if (node.computed && !this.isPure(node.key, constantsOnly)) return false; + if (node.kind === "get" || node.kind === "set") return false; + return true; + } else if (t.isClassProperty(node) || t.isObjectProperty(node)) { + if (node.computed && !this.isPure(node.key, constantsOnly)) return false; + return this.isPure(node.value, constantsOnly); + } else if (t.isUnaryExpression(node)) { + return this.isPure(node.argument, constantsOnly); + } else { + return t.isPureish(node); + } + }; + + /** + * Set some arbitrary data on the current scope. + */ + + Scope.prototype.setData = function setData(key, val) { + return this.data[key] = val; + }; + + /** + * Recursively walk up scope tree looking for the data `key`. + */ + + Scope.prototype.getData = function getData(key) { + var scope = this; + do { + var data = scope.data[key]; + if (data != null) return data; + } while (scope = scope.parent); + }; + + /** + * Recursively walk up scope tree looking for the data `key` and if it exists, + * remove it. + */ + + Scope.prototype.removeData = function removeData(key) { + var scope = this; + do { + var data = scope.data[key]; + if (data != null) scope.data[key] = null; + } while (scope = scope.parent); + }; + + Scope.prototype.init = function init() { + if (!this.references) this.crawl(); + }; + + Scope.prototype.crawl = function crawl() { + _crawlCallsCount++; + this._crawl(); + _crawlCallsCount--; + }; + + Scope.prototype._crawl = function _crawl() { + var path = this.path; + + // + + this.references = (0, _create2.default)(null); + this.bindings = (0, _create2.default)(null); + this.globals = (0, _create2.default)(null); + this.uids = (0, _create2.default)(null); + this.data = (0, _create2.default)(null); + + // ForStatement - left, init + + if (path.isLoop()) { + for (var _iterator14 = t.FOR_INIT_KEYS, _isArray14 = Array.isArray(_iterator14), _i14 = 0, _iterator14 = _isArray14 ? _iterator14 : (0, _getIterator3.default)(_iterator14);;) { + var _ref15; + + if (_isArray14) { + if (_i14 >= _iterator14.length) break; + _ref15 = _iterator14[_i14++]; + } else { + _i14 = _iterator14.next(); + if (_i14.done) break; + _ref15 = _i14.value; + } + + var key = _ref15; + + var node = path.get(key); + if (node.isBlockScoped()) this.registerBinding(node.node.kind, node); + } + } + + // FunctionExpression - id + + if (path.isFunctionExpression() && path.has("id")) { + if (!path.get("id").node[t.NOT_LOCAL_BINDING]) { + this.registerBinding("local", path.get("id"), path); + } + } + + // Class + + if (path.isClassExpression() && path.has("id")) { + if (!path.get("id").node[t.NOT_LOCAL_BINDING]) { + this.registerBinding("local", path); + } + } + + // Function - params, rest + + if (path.isFunction()) { + var params = path.get("params"); + for (var _iterator15 = params, _isArray15 = Array.isArray(_iterator15), _i15 = 0, _iterator15 = _isArray15 ? _iterator15 : (0, _getIterator3.default)(_iterator15);;) { + var _ref16; + + if (_isArray15) { + if (_i15 >= _iterator15.length) break; + _ref16 = _iterator15[_i15++]; + } else { + _i15 = _iterator15.next(); + if (_i15.done) break; + _ref16 = _i15.value; + } + + var param = _ref16; + + this.registerBinding("param", param); + } + } + + // CatchClause - param + + if (path.isCatchClause()) { + this.registerBinding("let", path); + } + + // Program + + var parent = this.getProgramParent(); + if (parent.crawling) return; + + var state = { + references: [], + constantViolations: [], + assignments: [] + }; + + this.crawling = true; + path.traverse(collectorVisitor, state); + this.crawling = false; + + // register assignments + for (var _iterator16 = state.assignments, _isArray16 = Array.isArray(_iterator16), _i16 = 0, _iterator16 = _isArray16 ? _iterator16 : (0, _getIterator3.default)(_iterator16);;) { + var _ref17; + + if (_isArray16) { + if (_i16 >= _iterator16.length) break; + _ref17 = _iterator16[_i16++]; + } else { + _i16 = _iterator16.next(); + if (_i16.done) break; + _ref17 = _i16.value; + } + + var _path = _ref17; + + // register undeclared bindings as globals + var ids = _path.getBindingIdentifiers(); + var programParent = void 0; + for (var name in ids) { + if (_path.scope.getBinding(name)) continue; + + programParent = programParent || _path.scope.getProgramParent(); + programParent.addGlobal(ids[name]); + } + + // register as constant violation + _path.scope.registerConstantViolation(_path); + } + + // register references + for (var _iterator17 = state.references, _isArray17 = Array.isArray(_iterator17), _i17 = 0, _iterator17 = _isArray17 ? _iterator17 : (0, _getIterator3.default)(_iterator17);;) { + var _ref18; + + if (_isArray17) { + if (_i17 >= _iterator17.length) break; + _ref18 = _iterator17[_i17++]; + } else { + _i17 = _iterator17.next(); + if (_i17.done) break; + _ref18 = _i17.value; + } + + var ref = _ref18; + + var binding = ref.scope.getBinding(ref.node.name); + if (binding) { + binding.reference(ref); + } else { + ref.scope.getProgramParent().addGlobal(ref.node); + } + } + + // register constant violations + for (var _iterator18 = state.constantViolations, _isArray18 = Array.isArray(_iterator18), _i18 = 0, _iterator18 = _isArray18 ? _iterator18 : (0, _getIterator3.default)(_iterator18);;) { + var _ref19; + + if (_isArray18) { + if (_i18 >= _iterator18.length) break; + _ref19 = _iterator18[_i18++]; + } else { + _i18 = _iterator18.next(); + if (_i18.done) break; + _ref19 = _i18.value; + } + + var _path2 = _ref19; + + _path2.scope.registerConstantViolation(_path2); + } + }; + + Scope.prototype.push = function push(opts) { + var path = this.path; + + if (!path.isBlockStatement() && !path.isProgram()) { + path = this.getBlockParent().path; + } + + if (path.isSwitchStatement()) { + path = this.getFunctionParent().path; + } + + if (path.isLoop() || path.isCatchClause() || path.isFunction()) { + t.ensureBlock(path.node); + path = path.get("body"); + } + + var unique = opts.unique; + var kind = opts.kind || "var"; + var blockHoist = opts._blockHoist == null ? 2 : opts._blockHoist; + + var dataKey = "declaration:" + kind + ":" + blockHoist; + var declarPath = !unique && path.getData(dataKey); + + if (!declarPath) { + var declar = t.variableDeclaration(kind, []); + declar._generated = true; + declar._blockHoist = blockHoist; + + var _path$unshiftContaine = path.unshiftContainer("body", [declar]); + + declarPath = _path$unshiftContaine[0]; + + if (!unique) path.setData(dataKey, declarPath); + } + + var declarator = t.variableDeclarator(opts.id, opts.init); + declarPath.node.declarations.push(declarator); + this.registerBinding(kind, declarPath.get("declarations").pop()); + }; + + /** + * Walk up to the top of the scope tree and get the `Program`. + */ + + Scope.prototype.getProgramParent = function getProgramParent() { + var scope = this; + do { + if (scope.path.isProgram()) { + return scope; + } + } while (scope = scope.parent); + throw new Error("We couldn't find a Function or Program..."); + }; + + /** + * Walk up the scope tree until we hit either a Function or reach the + * very top and hit Program. + */ + + Scope.prototype.getFunctionParent = function getFunctionParent() { + var scope = this; + do { + if (scope.path.isFunctionParent()) { + return scope; + } + } while (scope = scope.parent); + throw new Error("We couldn't find a Function or Program..."); + }; + + /** + * Walk up the scope tree until we hit either a BlockStatement/Loop/Program/Function/Switch or reach the + * very top and hit Program. + */ + + Scope.prototype.getBlockParent = function getBlockParent() { + var scope = this; + do { + if (scope.path.isBlockParent()) { + return scope; + } + } while (scope = scope.parent); + throw new Error("We couldn't find a BlockStatement, For, Switch, Function, Loop or Program..."); + }; + + /** + * Walks the scope tree and gathers **all** bindings. + */ + + Scope.prototype.getAllBindings = function getAllBindings() { + var ids = (0, _create2.default)(null); + + var scope = this; + do { + (0, _defaults2.default)(ids, scope.bindings); + scope = scope.parent; + } while (scope); + + return ids; + }; + + /** + * Walks the scope tree and gathers all declarations of `kind`. + */ + + Scope.prototype.getAllBindingsOfKind = function getAllBindingsOfKind() { + var ids = (0, _create2.default)(null); + + for (var _iterator19 = arguments, _isArray19 = Array.isArray(_iterator19), _i19 = 0, _iterator19 = _isArray19 ? _iterator19 : (0, _getIterator3.default)(_iterator19);;) { + var _ref20; + + if (_isArray19) { + if (_i19 >= _iterator19.length) break; + _ref20 = _iterator19[_i19++]; + } else { + _i19 = _iterator19.next(); + if (_i19.done) break; + _ref20 = _i19.value; + } + + var kind = _ref20; + + var scope = this; + do { + for (var name in scope.bindings) { + var binding = scope.bindings[name]; + if (binding.kind === kind) ids[name] = binding; + } + scope = scope.parent; + } while (scope); + } + + return ids; + }; + + Scope.prototype.bindingIdentifierEquals = function bindingIdentifierEquals(name, node) { + return this.getBindingIdentifier(name) === node; + }; + + Scope.prototype.warnOnFlowBinding = function warnOnFlowBinding(binding) { + if (_crawlCallsCount === 0 && binding && binding.path.isFlow()) { + console.warn("\n You or one of the Babel plugins you are using are using Flow declarations as bindings.\n Support for this will be removed in version 6.8. To find out the caller, grep for this\n message and change it to a `console.trace()`.\n "); + } + return binding; + }; + + Scope.prototype.getBinding = function getBinding(name) { + var scope = this; + + do { + var binding = scope.getOwnBinding(name); + if (binding) return this.warnOnFlowBinding(binding); + } while (scope = scope.parent); + }; + + Scope.prototype.getOwnBinding = function getOwnBinding(name) { + return this.warnOnFlowBinding(this.bindings[name]); + }; + + Scope.prototype.getBindingIdentifier = function getBindingIdentifier(name) { + var info = this.getBinding(name); + return info && info.identifier; + }; + + Scope.prototype.getOwnBindingIdentifier = function getOwnBindingIdentifier(name) { + var binding = this.bindings[name]; + return binding && binding.identifier; + }; + + Scope.prototype.hasOwnBinding = function hasOwnBinding(name) { + return !!this.getOwnBinding(name); + }; + + Scope.prototype.hasBinding = function hasBinding(name, noGlobals) { + if (!name) return false; + if (this.hasOwnBinding(name)) return true; + if (this.parentHasBinding(name, noGlobals)) return true; + if (this.hasUid(name)) return true; + if (!noGlobals && (0, _includes2.default)(Scope.globals, name)) return true; + if (!noGlobals && (0, _includes2.default)(Scope.contextVariables, name)) return true; + return false; + }; + + Scope.prototype.parentHasBinding = function parentHasBinding(name, noGlobals) { + return this.parent && this.parent.hasBinding(name, noGlobals); + }; + + /** + * Move a binding of `name` to another `scope`. + */ + + Scope.prototype.moveBindingTo = function moveBindingTo(name, scope) { + var info = this.getBinding(name); + if (info) { + info.scope.removeOwnBinding(name); + info.scope = scope; + scope.bindings[name] = info; + } + }; + + Scope.prototype.removeOwnBinding = function removeOwnBinding(name) { + delete this.bindings[name]; + }; + + Scope.prototype.removeBinding = function removeBinding(name) { + // clear literal binding + var info = this.getBinding(name); + if (info) { + info.scope.removeOwnBinding(name); + } + + // clear uids with this name - https://github.com/babel/babel/issues/2101 + var scope = this; + do { + if (scope.uids[name]) { + scope.uids[name] = false; + } + } while (scope = scope.parent); + }; + + return Scope; +}(); + +Scope.globals = (0, _keys2.default)(_globals2.default.builtin); +Scope.contextVariables = ["arguments", "undefined", "Infinity", "NaN"]; +exports.default = Scope; +module.exports = exports["default"]; +},{"../cache":16,"../index":19,"./binding":37,"./lib/renamer":39,"babel-messages":12,"babel-runtime/core-js/get-iterator":41,"babel-runtime/core-js/object/create":43,"babel-runtime/core-js/object/keys":45,"babel-runtime/helpers/classCallCheck":49,"babel-types":157,"globals":258,"lodash/defaults":395,"lodash/includes":402,"lodash/repeat":423}],39:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck"); + +var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); + +var _binding = require("../binding"); + +var _binding2 = _interopRequireDefault(_binding); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +var renameVisitor = { + ReferencedIdentifier: function ReferencedIdentifier(_ref, state) { + var node = _ref.node; + + if (node.name === state.oldName) { + node.name = state.newName; + } + }, + Scope: function Scope(path, state) { + if (!path.scope.bindingIdentifierEquals(state.oldName, state.binding.identifier)) { + path.skip(); + } + }, + "AssignmentExpression|Declaration": function AssignmentExpressionDeclaration(path, state) { + var ids = path.getOuterBindingIdentifiers(); + + for (var name in ids) { + if (name === state.oldName) ids[name].name = state.newName; + } + } +}; + +var Renamer = function () { + function Renamer(binding, oldName, newName) { + (0, _classCallCheck3.default)(this, Renamer); + + this.newName = newName; + this.oldName = oldName; + this.binding = binding; + } + + Renamer.prototype.maybeConvertFromExportDeclaration = function maybeConvertFromExportDeclaration(parentDeclar) { + var exportDeclar = parentDeclar.parentPath.isExportDeclaration() && parentDeclar.parentPath; + if (!exportDeclar) return; + + // build specifiers that point back to this export declaration + var isDefault = exportDeclar.isExportDefaultDeclaration(); + + if (isDefault && (parentDeclar.isFunctionDeclaration() || parentDeclar.isClassDeclaration()) && !parentDeclar.node.id) { + // Ensure that default class and function exports have a name so they have a identifier to + // reference from the export specifier list. + parentDeclar.node.id = parentDeclar.scope.generateUidIdentifier("default"); + } + + var bindingIdentifiers = parentDeclar.getOuterBindingIdentifiers(); + var specifiers = []; + + for (var name in bindingIdentifiers) { + var localName = name === this.oldName ? this.newName : name; + var exportedName = isDefault ? "default" : name; + specifiers.push(t.exportSpecifier(t.identifier(localName), t.identifier(exportedName))); + } + + var aliasDeclar = t.exportNamedDeclaration(null, specifiers); + + // hoist to the top if it's a function + if (parentDeclar.isFunctionDeclaration()) { + aliasDeclar._blockHoist = 3; + } + + exportDeclar.insertAfter(aliasDeclar); + exportDeclar.replaceWith(parentDeclar.node); + }; + + Renamer.prototype.maybeConvertFromClassFunctionDeclaration = function maybeConvertFromClassFunctionDeclaration(path) { + return; // TODO + + // retain the `name` of a class/function declaration + + if (!path.isFunctionDeclaration() && !path.isClassDeclaration()) return; + if (this.binding.kind !== "hoisted") return; + + path.node.id = t.identifier(this.oldName); + path.node._blockHoist = 3; + + path.replaceWith(t.variableDeclaration("let", [t.variableDeclarator(t.identifier(this.newName), t.toExpression(path.node))])); + }; + + Renamer.prototype.maybeConvertFromClassFunctionExpression = function maybeConvertFromClassFunctionExpression(path) { + return; // TODO + + // retain the `name` of a class/function expression + + if (!path.isFunctionExpression() && !path.isClassExpression()) return; + if (this.binding.kind !== "local") return; + + path.node.id = t.identifier(this.oldName); + + this.binding.scope.parent.push({ + id: t.identifier(this.newName) + }); + + path.replaceWith(t.assignmentExpression("=", t.identifier(this.newName), path.node)); + }; + + Renamer.prototype.rename = function rename(block) { + var binding = this.binding; + var oldName = this.oldName; + var newName = this.newName; + var scope = binding.scope; + var path = binding.path; + + + var parentDeclar = path.find(function (path) { + return path.isDeclaration() || path.isFunctionExpression(); + }); + if (parentDeclar) { + this.maybeConvertFromExportDeclaration(parentDeclar); + } + + scope.traverse(block || scope.block, renameVisitor, this); + + if (!block) { + scope.removeOwnBinding(oldName); + scope.bindings[newName] = binding; + this.binding.identifier.name = newName; + } + + if (binding.type === "hoisted") { + // https://github.com/babel/babel/issues/2435 + // todo: hoist and convert function to a let + } + + if (parentDeclar) { + this.maybeConvertFromClassFunctionDeclaration(parentDeclar); + this.maybeConvertFromClassFunctionExpression(parentDeclar); + } + }; + + return Renamer; +}(); + +exports.default = Renamer; +module.exports = exports["default"]; +},{"../binding":37,"babel-runtime/helpers/classCallCheck":49,"babel-types":157}],40:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _typeof2 = require("babel-runtime/helpers/typeof"); + +var _typeof3 = _interopRequireDefault(_typeof2); + +var _keys = require("babel-runtime/core-js/object/keys"); + +var _keys2 = _interopRequireDefault(_keys); + +var _getIterator2 = require("babel-runtime/core-js/get-iterator"); + +var _getIterator3 = _interopRequireDefault(_getIterator2); + +exports.explode = explode; +exports.verify = verify; +exports.merge = merge; + +var _virtualTypes = require("./path/lib/virtual-types"); + +var virtualTypes = _interopRequireWildcard(_virtualTypes); + +var _babelMessages = require("babel-messages"); + +var messages = _interopRequireWildcard(_babelMessages); + +var _babelTypes = require("babel-types"); + +var t = _interopRequireWildcard(_babelTypes); + +var _clone = require("lodash/clone"); + +var _clone2 = _interopRequireDefault(_clone); + +function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } } + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/** + * explode() will take a visitor object with all of the various shorthands + * that we support, and validates & normalizes it into a common format, ready + * to be used in traversal + * + * The various shorthands are: + * * `Identifier() { ... }` -> `Identifier: { enter() { ... } }` + * * `"Identifier|NumericLiteral": { ... }` -> `Identifier: { ... }, NumericLiteral: { ... }` + * * Aliases in `babel-types`: e.g. `Property: { ... }` -> `ObjectProperty: { ... }, ClassProperty: { ... }` + * + * Other normalizations are: + * * Visitors of virtual types are wrapped, so that they are only visited when + * their dynamic check passes + * * `enter` and `exit` functions are wrapped in arrays, to ease merging of + * visitors + */ +function explode(visitor) { + if (visitor._exploded) return visitor; + visitor._exploded = true; + + // normalise pipes + for (var nodeType in visitor) { + if (shouldIgnoreKey(nodeType)) continue; + + var parts = nodeType.split("|"); + if (parts.length === 1) continue; + + var fns = visitor[nodeType]; + delete visitor[nodeType]; + + for (var _iterator = parts, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) { + var _ref; + + if (_isArray) { + if (_i >= _iterator.length) break; + _ref = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + _ref = _i.value; + } + + var part = _ref; + + visitor[part] = fns; + } + } + + // verify data structure + verify(visitor); + + // make sure there's no __esModule type since this is because we're using loose mode + // and it sets __esModule to be enumerable on all modules :( + delete visitor.__esModule; + + // ensure visitors are objects + ensureEntranceObjects(visitor); + + // ensure enter/exit callbacks are arrays + ensureCallbackArrays(visitor); + + // add type wrappers + for (var _iterator2 = (0, _keys2.default)(visitor), _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) { + var _ref2; + + if (_isArray2) { + if (_i2 >= _iterator2.length) break; + _ref2 = _iterator2[_i2++]; + } else { + _i2 = _iterator2.next(); + if (_i2.done) break; + _ref2 = _i2.value; + } + + var _nodeType3 = _ref2; + + if (shouldIgnoreKey(_nodeType3)) continue; + + var wrapper = virtualTypes[_nodeType3]; + if (!wrapper) continue; + + // wrap all the functions + var _fns2 = visitor[_nodeType3]; + for (var type in _fns2) { + _fns2[type] = wrapCheck(wrapper, _fns2[type]); + } + + // clear it from the visitor + delete visitor[_nodeType3]; + + if (wrapper.types) { + for (var _iterator4 = wrapper.types, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) { + var _ref4; + + if (_isArray4) { + if (_i4 >= _iterator4.length) break; + _ref4 = _iterator4[_i4++]; + } else { + _i4 = _iterator4.next(); + if (_i4.done) break; + _ref4 = _i4.value; + } + + var _type = _ref4; + + // merge the visitor if necessary or just put it back in + if (visitor[_type]) { + mergePair(visitor[_type], _fns2); + } else { + visitor[_type] = _fns2; + } + } + } else { + mergePair(visitor, _fns2); + } + } + + // add aliases + for (var _nodeType in visitor) { + if (shouldIgnoreKey(_nodeType)) continue; + + var _fns = visitor[_nodeType]; + + var aliases = t.FLIPPED_ALIAS_KEYS[_nodeType]; + + var deprecratedKey = t.DEPRECATED_KEYS[_nodeType]; + if (deprecratedKey) { + console.trace("Visitor defined for " + _nodeType + " but it has been renamed to " + deprecratedKey); + aliases = [deprecratedKey]; + } + + if (!aliases) continue; + + // clear it from the visitor + delete visitor[_nodeType]; + + for (var _iterator3 = aliases, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) { + var _ref3; + + if (_isArray3) { + if (_i3 >= _iterator3.length) break; + _ref3 = _iterator3[_i3++]; + } else { + _i3 = _iterator3.next(); + if (_i3.done) break; + _ref3 = _i3.value; + } + + var alias = _ref3; + + var existing = visitor[alias]; + if (existing) { + mergePair(existing, _fns); + } else { + visitor[alias] = (0, _clone2.default)(_fns); + } + } + } + + for (var _nodeType2 in visitor) { + if (shouldIgnoreKey(_nodeType2)) continue; + + ensureCallbackArrays(visitor[_nodeType2]); + } + + return visitor; +} + +function verify(visitor) { + if (visitor._verified) return; + + if (typeof visitor === "function") { + throw new Error(messages.get("traverseVerifyRootFunction")); + } + + for (var nodeType in visitor) { + if (nodeType === "enter" || nodeType === "exit") { + validateVisitorMethods(nodeType, visitor[nodeType]); + } + + if (shouldIgnoreKey(nodeType)) continue; + + if (t.TYPES.indexOf(nodeType) < 0) { + throw new Error(messages.get("traverseVerifyNodeType", nodeType)); + } + + var visitors = visitor[nodeType]; + if ((typeof visitors === "undefined" ? "undefined" : (0, _typeof3.default)(visitors)) === "object") { + for (var visitorKey in visitors) { + if (visitorKey === "enter" || visitorKey === "exit") { + // verify that it just contains functions + validateVisitorMethods(nodeType + "." + visitorKey, visitors[visitorKey]); + } else { + throw new Error(messages.get("traverseVerifyVisitorProperty", nodeType, visitorKey)); + } + } + } + } + + visitor._verified = true; +} + +function validateVisitorMethods(path, val) { + var fns = [].concat(val); + for (var _iterator5 = fns, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) { + var _ref5; + + if (_isArray5) { + if (_i5 >= _iterator5.length) break; + _ref5 = _iterator5[_i5++]; + } else { + _i5 = _iterator5.next(); + if (_i5.done) break; + _ref5 = _i5.value; + } + + var fn = _ref5; + + if (typeof fn !== "function") { + throw new TypeError("Non-function found defined in " + path + " with type " + (typeof fn === "undefined" ? "undefined" : (0, _typeof3.default)(fn))); + } + } +} + +function merge(visitors) { + var states = arguments.length <= 1 || arguments[1] === undefined ? [] : arguments[1]; + + var rootVisitor = {}; + + for (var i = 0; i < visitors.length; i++) { + var visitor = visitors[i]; + var state = states[i]; + + explode(visitor); + + for (var type in visitor) { + var visitorType = visitor[type]; + + // if we have state then overload the callbacks to take it + if (state) visitorType = wrapWithState(visitorType, state); + + var nodeVisitor = rootVisitor[type] = rootVisitor[type] || {}; + mergePair(nodeVisitor, visitorType); + } + } + + return rootVisitor; +} + +function wrapWithState(oldVisitor, state) { + var newVisitor = {}; + + for (var key in oldVisitor) { + var fns = oldVisitor[key]; + + // not an enter/exit array of callbacks + if (!Array.isArray(fns)) continue; + + fns = fns.map(function (fn) { + var newFn = function newFn(path) { + return fn.call(state, path, state); + }; + newFn.toString = function () { + return fn.toString(); + }; + return newFn; + }); + + newVisitor[key] = fns; + } + + return newVisitor; +} + +function ensureEntranceObjects(obj) { + for (var key in obj) { + if (shouldIgnoreKey(key)) continue; + + var fns = obj[key]; + if (typeof fns === "function") { + obj[key] = { enter: fns }; + } + } +} + +function ensureCallbackArrays(obj) { + if (obj.enter && !Array.isArray(obj.enter)) obj.enter = [obj.enter]; + if (obj.exit && !Array.isArray(obj.exit)) obj.exit = [obj.exit]; +} + +function wrapCheck(wrapper, fn) { + var newFn = function newFn(path) { + if (wrapper.checkPath(path)) { + return fn.apply(this, arguments); + } + }; + newFn.toString = function () { + return fn.toString(); + }; + return newFn; +} + +function shouldIgnoreKey(key) { + // internal/hidden key + if (key[0] === "_") return true; + + // ignore function keys + if (key === "enter" || key === "exit" || key === "shouldSkip") return true; + + // ignore other options + if (key === "blacklist" || key === "noScope" || key === "skipKeys") return true; + + return false; +} + +function mergePair(dest, src) { + for (var key in src) { + dest[key] = [].concat(dest[key] || [], src[key]); + } +} +},{"./path/lib/virtual-types":33,"babel-messages":12,"babel-runtime/core-js/get-iterator":41,"babel-runtime/core-js/object/keys":45,"babel-runtime/helpers/typeof":50,"babel-types":157,"lodash/clone":393}],41:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/get-iterator"), __esModule: true }; +},{"core-js/library/fn/get-iterator":51}],42:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/map"), __esModule: true }; +},{"core-js/library/fn/map":52}],43:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/create"), __esModule: true }; +},{"core-js/library/fn/object/create":53}],44:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/get-own-property-symbols"), __esModule: true }; +},{"core-js/library/fn/object/get-own-property-symbols":54}],45:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/object/keys"), __esModule: true }; +},{"core-js/library/fn/object/keys":55}],46:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/symbol"), __esModule: true }; +},{"core-js/library/fn/symbol":56}],47:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/symbol/iterator"), __esModule: true }; +},{"core-js/library/fn/symbol/iterator":57}],48:[function(require,module,exports){ +module.exports = { "default": require("core-js/library/fn/weak-map"), __esModule: true }; +},{"core-js/library/fn/weak-map":58}],49:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +exports.default = function (instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +}; +},{}],50:[function(require,module,exports){ +"use strict"; + +exports.__esModule = true; + +var _iterator = require("../core-js/symbol/iterator"); + +var _iterator2 = _interopRequireDefault(_iterator); + +var _symbol = require("../core-js/symbol"); + +var _symbol2 = _interopRequireDefault(_symbol); + +var _typeof = typeof _symbol2.default === "function" && typeof _iterator2.default === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default ? "symbol" : typeof obj; }; + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.default = typeof _symbol2.default === "function" && _typeof(_iterator2.default) === "symbol" ? function (obj) { + return typeof obj === "undefined" ? "undefined" : _typeof(obj); +} : function (obj) { + return obj && typeof _symbol2.default === "function" && obj.constructor === _symbol2.default ? "symbol" : typeof obj === "undefined" ? "undefined" : _typeof(obj); +}; +},{"../core-js/symbol":46,"../core-js/symbol/iterator":47}],51:[function(require,module,exports){ +require('../modules/web.dom.iterable'); +require('../modules/es6.string.iterator'); +module.exports = require('../modules/core.get-iterator'); +},{"../modules/core.get-iterator":133,"../modules/es6.string.iterator":139,"../modules/web.dom.iterable":145}],52:[function(require,module,exports){ +require('../modules/es6.object.to-string'); +require('../modules/es6.string.iterator'); +require('../modules/web.dom.iterable'); +require('../modules/es6.map'); +require('../modules/es7.map.to-json'); +module.exports = require('../modules/_core').Map; +},{"../modules/_core":74,"../modules/es6.map":135,"../modules/es6.object.to-string":138,"../modules/es6.string.iterator":139,"../modules/es7.map.to-json":142,"../modules/web.dom.iterable":145}],53:[function(require,module,exports){ +require('../../modules/es6.object.create'); +var $Object = require('../../modules/_core').Object; +module.exports = function create(P, D){ + return $Object.create(P, D); +}; +},{"../../modules/_core":74,"../../modules/es6.object.create":136}],54:[function(require,module,exports){ +require('../../modules/es6.symbol'); +module.exports = require('../../modules/_core').Object.getOwnPropertySymbols; +},{"../../modules/_core":74,"../../modules/es6.symbol":140}],55:[function(require,module,exports){ +require('../../modules/es6.object.keys'); +module.exports = require('../../modules/_core').Object.keys; +},{"../../modules/_core":74,"../../modules/es6.object.keys":137}],56:[function(require,module,exports){ +require('../../modules/es6.symbol'); +require('../../modules/es6.object.to-string'); +require('../../modules/es7.symbol.async-iterator'); +require('../../modules/es7.symbol.observable'); +module.exports = require('../../modules/_core').Symbol; +},{"../../modules/_core":74,"../../modules/es6.object.to-string":138,"../../modules/es6.symbol":140,"../../modules/es7.symbol.async-iterator":143,"../../modules/es7.symbol.observable":144}],57:[function(require,module,exports){ +require('../../modules/es6.string.iterator'); +require('../../modules/web.dom.iterable'); +module.exports = require('../../modules/_wks-ext').f('iterator'); +},{"../../modules/_wks-ext":130,"../../modules/es6.string.iterator":139,"../../modules/web.dom.iterable":145}],58:[function(require,module,exports){ +require('../modules/es6.object.to-string'); +require('../modules/web.dom.iterable'); +require('../modules/es6.weak-map'); +module.exports = require('../modules/_core').WeakMap; +},{"../modules/_core":74,"../modules/es6.object.to-string":138,"../modules/es6.weak-map":141,"../modules/web.dom.iterable":145}],59:[function(require,module,exports){ +module.exports = function(it){ + if(typeof it != 'function')throw TypeError(it + ' is not a function!'); + return it; +}; +},{}],60:[function(require,module,exports){ +module.exports = function(){ /* empty */ }; +},{}],61:[function(require,module,exports){ +module.exports = function(it, Constructor, name, forbiddenField){ + if(!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)){ + throw TypeError(name + ': incorrect invocation!'); + } return it; +}; +},{}],62:[function(require,module,exports){ +var isObject = require('./_is-object'); +module.exports = function(it){ + if(!isObject(it))throw TypeError(it + ' is not an object!'); + return it; +}; +},{"./_is-object":92}],63:[function(require,module,exports){ +var forOf = require('./_for-of'); + +module.exports = function(iter, ITERATOR){ + var result = []; + forOf(iter, false, result.push, result, ITERATOR); + return result; +}; + +},{"./_for-of":83}],64:[function(require,module,exports){ +// false -> Array#indexOf +// true -> Array#includes +var toIObject = require('./_to-iobject') + , toLength = require('./_to-length') + , toIndex = require('./_to-index'); +module.exports = function(IS_INCLUDES){ + return function($this, el, fromIndex){ + var O = toIObject($this) + , length = toLength(O.length) + , index = toIndex(fromIndex, length) + , value; + // Array#includes uses SameValueZero equality algorithm + if(IS_INCLUDES && el != el)while(length > index){ + value = O[index++]; + if(value != value)return true; + // Array#toIndex ignores holes, Array#includes - not + } else for(;length > index; index++)if(IS_INCLUDES || index in O){ + if(O[index] === el)return IS_INCLUDES || index || 0; + } return !IS_INCLUDES && -1; + }; +}; +},{"./_to-index":122,"./_to-iobject":124,"./_to-length":125}],65:[function(require,module,exports){ +// 0 -> Array#forEach +// 1 -> Array#map +// 2 -> Array#filter +// 3 -> Array#some +// 4 -> Array#every +// 5 -> Array#find +// 6 -> Array#findIndex +var ctx = require('./_ctx') + , IObject = require('./_iobject') + , toObject = require('./_to-object') + , toLength = require('./_to-length') + , asc = require('./_array-species-create'); +module.exports = function(TYPE, $create){ + var IS_MAP = TYPE == 1 + , IS_FILTER = TYPE == 2 + , IS_SOME = TYPE == 3 + , IS_EVERY = TYPE == 4 + , IS_FIND_INDEX = TYPE == 6 + , NO_HOLES = TYPE == 5 || IS_FIND_INDEX + , create = $create || asc; + return function($this, callbackfn, that){ + var O = toObject($this) + , self = IObject(O) + , f = ctx(callbackfn, that, 3) + , length = toLength(self.length) + , index = 0 + , result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined + , val, res; + for(;length > index; index++)if(NO_HOLES || index in self){ + val = self[index]; + res = f(val, index, O); + if(TYPE){ + if(IS_MAP)result[index] = res; // map + else if(res)switch(TYPE){ + case 3: return true; // some + case 5: return val; // find + case 6: return index; // findIndex + case 2: result.push(val); // filter + } else if(IS_EVERY)return false; // every + } + } + return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result; + }; +}; +},{"./_array-species-create":67,"./_ctx":75,"./_iobject":89,"./_to-length":125,"./_to-object":126}],66:[function(require,module,exports){ +var isObject = require('./_is-object') + , isArray = require('./_is-array') + , SPECIES = require('./_wks')('species'); + +module.exports = function(original){ + var C; + if(isArray(original)){ + C = original.constructor; + // cross-realm fallback + if(typeof C == 'function' && (C === Array || isArray(C.prototype)))C = undefined; + if(isObject(C)){ + C = C[SPECIES]; + if(C === null)C = undefined; + } + } return C === undefined ? Array : C; +}; +},{"./_is-array":91,"./_is-object":92,"./_wks":131}],67:[function(require,module,exports){ +// 9.4.2.3 ArraySpeciesCreate(originalArray, length) +var speciesConstructor = require('./_array-species-constructor'); + +module.exports = function(original, length){ + return new (speciesConstructor(original))(length); +}; +},{"./_array-species-constructor":66}],68:[function(require,module,exports){ +// getting tag from 19.1.3.6 Object.prototype.toString() +var cof = require('./_cof') + , TAG = require('./_wks')('toStringTag') + // ES3 wrong here + , ARG = cof(function(){ return arguments; }()) == 'Arguments'; + +// fallback for IE11 Script Access Denied error +var tryGet = function(it, key){ + try { + return it[key]; + } catch(e){ /* empty */ } +}; + +module.exports = function(it){ + var O, T, B; + return it === undefined ? 'Undefined' : it === null ? 'Null' + // @@toStringTag case + : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T + // builtinTag case + : ARG ? cof(O) + // ES3 arguments fallback + : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B; +}; +},{"./_cof":69,"./_wks":131}],69:[function(require,module,exports){ +var toString = {}.toString; + +module.exports = function(it){ + return toString.call(it).slice(8, -1); +}; +},{}],70:[function(require,module,exports){ +'use strict'; +var dP = require('./_object-dp').f + , create = require('./_object-create') + , hide = require('./_hide') + , redefineAll = require('./_redefine-all') + , ctx = require('./_ctx') + , anInstance = require('./_an-instance') + , defined = require('./_defined') + , forOf = require('./_for-of') + , $iterDefine = require('./_iter-define') + , step = require('./_iter-step') + , setSpecies = require('./_set-species') + , DESCRIPTORS = require('./_descriptors') + , fastKey = require('./_meta').fastKey + , SIZE = DESCRIPTORS ? '_s' : 'size'; + +var getEntry = function(that, key){ + // fast case + var index = fastKey(key), entry; + if(index !== 'F')return that._i[index]; + // frozen object case + for(entry = that._f; entry; entry = entry.n){ + if(entry.k == key)return entry; + } +}; + +module.exports = { + getConstructor: function(wrapper, NAME, IS_MAP, ADDER){ + var C = wrapper(function(that, iterable){ + anInstance(that, C, NAME, '_i'); + that._i = create(null); // index + that._f = undefined; // first entry + that._l = undefined; // last entry + that[SIZE] = 0; // size + if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that); + }); + redefineAll(C.prototype, { + // 23.1.3.1 Map.prototype.clear() + // 23.2.3.2 Set.prototype.clear() + clear: function clear(){ + for(var that = this, data = that._i, entry = that._f; entry; entry = entry.n){ + entry.r = true; + if(entry.p)entry.p = entry.p.n = undefined; + delete data[entry.i]; + } + that._f = that._l = undefined; + that[SIZE] = 0; + }, + // 23.1.3.3 Map.prototype.delete(key) + // 23.2.3.4 Set.prototype.delete(value) + 'delete': function(key){ + var that = this + , entry = getEntry(that, key); + if(entry){ + var next = entry.n + , prev = entry.p; + delete that._i[entry.i]; + entry.r = true; + if(prev)prev.n = next; + if(next)next.p = prev; + if(that._f == entry)that._f = next; + if(that._l == entry)that._l = prev; + that[SIZE]--; + } return !!entry; + }, + // 23.2.3.6 Set.prototype.forEach(callbackfn, thisArg = undefined) + // 23.1.3.5 Map.prototype.forEach(callbackfn, thisArg = undefined) + forEach: function forEach(callbackfn /*, that = undefined */){ + anInstance(this, C, 'forEach'); + var f = ctx(callbackfn, arguments.length > 1 ? arguments[1] : undefined, 3) + , entry; + while(entry = entry ? entry.n : this._f){ + f(entry.v, entry.k, this); + // revert to the last existing entry + while(entry && entry.r)entry = entry.p; + } + }, + // 23.1.3.7 Map.prototype.has(key) + // 23.2.3.7 Set.prototype.has(value) + has: function has(key){ + return !!getEntry(this, key); + } + }); + if(DESCRIPTORS)dP(C.prototype, 'size', { + get: function(){ + return defined(this[SIZE]); + } + }); + return C; + }, + def: function(that, key, value){ + var entry = getEntry(that, key) + , prev, index; + // change existing entry + if(entry){ + entry.v = value; + // create new entry + } else { + that._l = entry = { + i: index = fastKey(key, true), // <- index + k: key, // <- key + v: value, // <- value + p: prev = that._l, // <- previous entry + n: undefined, // <- next entry + r: false // <- removed + }; + if(!that._f)that._f = entry; + if(prev)prev.n = entry; + that[SIZE]++; + // add to index + if(index !== 'F')that._i[index] = entry; + } return that; + }, + getEntry: getEntry, + setStrong: function(C, NAME, IS_MAP){ + // add .keys, .values, .entries, [@@iterator] + // 23.1.3.4, 23.1.3.8, 23.1.3.11, 23.1.3.12, 23.2.3.5, 23.2.3.8, 23.2.3.10, 23.2.3.11 + $iterDefine(C, NAME, function(iterated, kind){ + this._t = iterated; // target + this._k = kind; // kind + this._l = undefined; // previous + }, function(){ + var that = this + , kind = that._k + , entry = that._l; + // revert to the last existing entry + while(entry && entry.r)entry = entry.p; + // get next entry + if(!that._t || !(that._l = entry = entry ? entry.n : that._t._f)){ + // or finish the iteration + that._t = undefined; + return step(1); + } + // return step by kind + if(kind == 'keys' )return step(0, entry.k); + if(kind == 'values')return step(0, entry.v); + return step(0, [entry.k, entry.v]); + }, IS_MAP ? 'entries' : 'values' , !IS_MAP, true); + + // add [@@species], 23.1.2.2, 23.2.2.2 + setSpecies(NAME); + } +}; +},{"./_an-instance":61,"./_ctx":75,"./_defined":76,"./_descriptors":77,"./_for-of":83,"./_hide":86,"./_iter-define":95,"./_iter-step":96,"./_meta":100,"./_object-create":102,"./_object-dp":103,"./_redefine-all":115,"./_set-species":117}],71:[function(require,module,exports){ +// https://github.com/DavidBruant/Map-Set.prototype.toJSON +var classof = require('./_classof') + , from = require('./_array-from-iterable'); +module.exports = function(NAME){ + return function toJSON(){ + if(classof(this) != NAME)throw TypeError(NAME + "#toJSON isn't generic"); + return from(this); + }; +}; +},{"./_array-from-iterable":63,"./_classof":68}],72:[function(require,module,exports){ +'use strict'; +var redefineAll = require('./_redefine-all') + , getWeak = require('./_meta').getWeak + , anObject = require('./_an-object') + , isObject = require('./_is-object') + , anInstance = require('./_an-instance') + , forOf = require('./_for-of') + , createArrayMethod = require('./_array-methods') + , $has = require('./_has') + , arrayFind = createArrayMethod(5) + , arrayFindIndex = createArrayMethod(6) + , id = 0; + +// fallback for uncaught frozen keys +var uncaughtFrozenStore = function(that){ + return that._l || (that._l = new UncaughtFrozenStore); +}; +var UncaughtFrozenStore = function(){ + this.a = []; +}; +var findUncaughtFrozen = function(store, key){ + return arrayFind(store.a, function(it){ + return it[0] === key; + }); +}; +UncaughtFrozenStore.prototype = { + get: function(key){ + var entry = findUncaughtFrozen(this, key); + if(entry)return entry[1]; + }, + has: function(key){ + return !!findUncaughtFrozen(this, key); + }, + set: function(key, value){ + var entry = findUncaughtFrozen(this, key); + if(entry)entry[1] = value; + else this.a.push([key, value]); + }, + 'delete': function(key){ + var index = arrayFindIndex(this.a, function(it){ + return it[0] === key; + }); + if(~index)this.a.splice(index, 1); + return !!~index; + } +}; + +module.exports = { + getConstructor: function(wrapper, NAME, IS_MAP, ADDER){ + var C = wrapper(function(that, iterable){ + anInstance(that, C, NAME, '_i'); + that._i = id++; // collection id + that._l = undefined; // leak store for uncaught frozen objects + if(iterable != undefined)forOf(iterable, IS_MAP, that[ADDER], that); + }); + redefineAll(C.prototype, { + // 23.3.3.2 WeakMap.prototype.delete(key) + // 23.4.3.3 WeakSet.prototype.delete(value) + 'delete': function(key){ + if(!isObject(key))return false; + var data = getWeak(key); + if(data === true)return uncaughtFrozenStore(this)['delete'](key); + return data && $has(data, this._i) && delete data[this._i]; + }, + // 23.3.3.4 WeakMap.prototype.has(key) + // 23.4.3.4 WeakSet.prototype.has(value) + has: function has(key){ + if(!isObject(key))return false; + var data = getWeak(key); + if(data === true)return uncaughtFrozenStore(this).has(key); + return data && $has(data, this._i); + } + }); + return C; + }, + def: function(that, key, value){ + var data = getWeak(anObject(key), true); + if(data === true)uncaughtFrozenStore(that).set(key, value); + else data[that._i] = value; + return that; + }, + ufstore: uncaughtFrozenStore +}; +},{"./_an-instance":61,"./_an-object":62,"./_array-methods":65,"./_for-of":83,"./_has":85,"./_is-object":92,"./_meta":100,"./_redefine-all":115}],73:[function(require,module,exports){ +'use strict'; +var global = require('./_global') + , $export = require('./_export') + , meta = require('./_meta') + , fails = require('./_fails') + , hide = require('./_hide') + , redefineAll = require('./_redefine-all') + , forOf = require('./_for-of') + , anInstance = require('./_an-instance') + , isObject = require('./_is-object') + , setToStringTag = require('./_set-to-string-tag') + , dP = require('./_object-dp').f + , each = require('./_array-methods')(0) + , DESCRIPTORS = require('./_descriptors'); + +module.exports = function(NAME, wrapper, methods, common, IS_MAP, IS_WEAK){ + var Base = global[NAME] + , C = Base + , ADDER = IS_MAP ? 'set' : 'add' + , proto = C && C.prototype + , O = {}; + if(!DESCRIPTORS || typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function(){ + new C().entries().next(); + }))){ + // create collection constructor + C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER); + redefineAll(C.prototype, methods); + meta.NEED = true; + } else { + C = wrapper(function(target, iterable){ + anInstance(target, C, NAME, '_c'); + target._c = new Base; + if(iterable != undefined)forOf(iterable, IS_MAP, target[ADDER], target); + }); + each('add,clear,delete,forEach,get,has,set,keys,values,entries,toJSON'.split(','),function(KEY){ + var IS_ADDER = KEY == 'add' || KEY == 'set'; + if(KEY in proto && !(IS_WEAK && KEY == 'clear'))hide(C.prototype, KEY, function(a, b){ + anInstance(this, C, KEY); + if(!IS_ADDER && IS_WEAK && !isObject(a))return KEY == 'get' ? undefined : false; + var result = this._c[KEY](a === 0 ? 0 : a, b); + return IS_ADDER ? this : result; + }); + }); + if('size' in proto)dP(C.prototype, 'size', { + get: function(){ + return this._c.size; + } + }); + } + + setToStringTag(C, NAME); + + O[NAME] = C; + $export($export.G + $export.W + $export.F, O); + + if(!IS_WEAK)common.setStrong(C, NAME, IS_MAP); + + return C; +}; +},{"./_an-instance":61,"./_array-methods":65,"./_descriptors":77,"./_export":81,"./_fails":82,"./_for-of":83,"./_global":84,"./_hide":86,"./_is-object":92,"./_meta":100,"./_object-dp":103,"./_redefine-all":115,"./_set-to-string-tag":118}],74:[function(require,module,exports){ +arguments[4][15][0].apply(exports,arguments) +},{"dup":15}],75:[function(require,module,exports){ +// optional / simple context binding +var aFunction = require('./_a-function'); +module.exports = function(fn, that, length){ + aFunction(fn); + if(that === undefined)return fn; + switch(length){ + case 1: return function(a){ + return fn.call(that, a); + }; + case 2: return function(a, b){ + return fn.call(that, a, b); + }; + case 3: return function(a, b, c){ + return fn.call(that, a, b, c); + }; + } + return function(/* ...args */){ + return fn.apply(that, arguments); + }; +}; +},{"./_a-function":59}],76:[function(require,module,exports){ +// 7.2.1 RequireObjectCoercible(argument) +module.exports = function(it){ + if(it == undefined)throw TypeError("Can't call method on " + it); + return it; +}; +},{}],77:[function(require,module,exports){ +// Thank's IE8 for his funny defineProperty +module.exports = !require('./_fails')(function(){ + return Object.defineProperty({}, 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_fails":82}],78:[function(require,module,exports){ +var isObject = require('./_is-object') + , document = require('./_global').document + // in old IE typeof document.createElement is 'object' + , is = isObject(document) && isObject(document.createElement); +module.exports = function(it){ + return is ? document.createElement(it) : {}; +}; +},{"./_global":84,"./_is-object":92}],79:[function(require,module,exports){ +// IE 8- don't enum bug keys +module.exports = ( + 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf' +).split(','); +},{}],80:[function(require,module,exports){ +// all enumerable object keys, includes symbols +var getKeys = require('./_object-keys') + , gOPS = require('./_object-gops') + , pIE = require('./_object-pie'); +module.exports = function(it){ + var result = getKeys(it) + , getSymbols = gOPS.f; + if(getSymbols){ + var symbols = getSymbols(it) + , isEnum = pIE.f + , i = 0 + , key; + while(symbols.length > i)if(isEnum.call(it, key = symbols[i++]))result.push(key); + } return result; +}; +},{"./_object-gops":108,"./_object-keys":111,"./_object-pie":112}],81:[function(require,module,exports){ +var global = require('./_global') + , core = require('./_core') + , ctx = require('./_ctx') + , hide = require('./_hide') + , PROTOTYPE = 'prototype'; + +var $export = function(type, name, source){ + var IS_FORCED = type & $export.F + , IS_GLOBAL = type & $export.G + , IS_STATIC = type & $export.S + , IS_PROTO = type & $export.P + , IS_BIND = type & $export.B + , IS_WRAP = type & $export.W + , exports = IS_GLOBAL ? core : core[name] || (core[name] = {}) + , expProto = exports[PROTOTYPE] + , target = IS_GLOBAL ? global : IS_STATIC ? global[name] : (global[name] || {})[PROTOTYPE] + , key, own, out; + if(IS_GLOBAL)source = name; + for(key in source){ + // contains in native + own = !IS_FORCED && target && target[key] !== undefined; + if(own && key in exports)continue; + // export native or passed + out = own ? target[key] : source[key]; + // prevent global pollution for namespaces + exports[key] = IS_GLOBAL && typeof target[key] != 'function' ? source[key] + // bind timers to global for call from export context + : IS_BIND && own ? ctx(out, global) + // wrap global constructors for prevent change them in library + : IS_WRAP && target[key] == out ? (function(C){ + var F = function(a, b, c){ + if(this instanceof C){ + switch(arguments.length){ + case 0: return new C; + case 1: return new C(a); + case 2: return new C(a, b); + } return new C(a, b, c); + } return C.apply(this, arguments); + }; + F[PROTOTYPE] = C[PROTOTYPE]; + return F; + // make static versions for prototype methods + })(out) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out; + // export proto methods to core.%CONSTRUCTOR%.methods.%NAME% + if(IS_PROTO){ + (exports.virtual || (exports.virtual = {}))[key] = out; + // export proto methods to core.%CONSTRUCTOR%.prototype.%NAME% + if(type & $export.R && expProto && !expProto[key])hide(expProto, key, out); + } + } +}; +// type bitmap +$export.F = 1; // forced +$export.G = 2; // global +$export.S = 4; // static +$export.P = 8; // proto +$export.B = 16; // bind +$export.W = 32; // wrap +$export.U = 64; // safe +$export.R = 128; // real proto method for `library` +module.exports = $export; +},{"./_core":74,"./_ctx":75,"./_global":84,"./_hide":86}],82:[function(require,module,exports){ +module.exports = function(exec){ + try { + return !!exec(); + } catch(e){ + return true; + } +}; +},{}],83:[function(require,module,exports){ +var ctx = require('./_ctx') + , call = require('./_iter-call') + , isArrayIter = require('./_is-array-iter') + , anObject = require('./_an-object') + , toLength = require('./_to-length') + , getIterFn = require('./core.get-iterator-method') + , BREAK = {} + , RETURN = {}; +var exports = module.exports = function(iterable, entries, fn, that, ITERATOR){ + var iterFn = ITERATOR ? function(){ return iterable; } : getIterFn(iterable) + , f = ctx(fn, that, entries ? 2 : 1) + , index = 0 + , length, step, iterator, result; + if(typeof iterFn != 'function')throw TypeError(iterable + ' is not iterable!'); + // fast case for arrays with default iterator + if(isArrayIter(iterFn))for(length = toLength(iterable.length); length > index; index++){ + result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]); + if(result === BREAK || result === RETURN)return result; + } else for(iterator = iterFn.call(iterable); !(step = iterator.next()).done; ){ + result = call(iterator, f, step.value, entries); + if(result === BREAK || result === RETURN)return result; + } +}; +exports.BREAK = BREAK; +exports.RETURN = RETURN; +},{"./_an-object":62,"./_ctx":75,"./_is-array-iter":90,"./_iter-call":93,"./_to-length":125,"./core.get-iterator-method":132}],84:[function(require,module,exports){ +// https://github.com/zloirock/core-js/issues/86#issuecomment-115759028 +var global = module.exports = typeof window != 'undefined' && window.Math == Math + ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')(); +if(typeof __g == 'number')__g = global; // eslint-disable-line no-undef +},{}],85:[function(require,module,exports){ +var hasOwnProperty = {}.hasOwnProperty; +module.exports = function(it, key){ + return hasOwnProperty.call(it, key); +}; +},{}],86:[function(require,module,exports){ +var dP = require('./_object-dp') + , createDesc = require('./_property-desc'); +module.exports = require('./_descriptors') ? function(object, key, value){ + return dP.f(object, key, createDesc(1, value)); +} : function(object, key, value){ + object[key] = value; + return object; +}; +},{"./_descriptors":77,"./_object-dp":103,"./_property-desc":114}],87:[function(require,module,exports){ +module.exports = require('./_global').document && document.documentElement; +},{"./_global":84}],88:[function(require,module,exports){ +module.exports = !require('./_descriptors') && !require('./_fails')(function(){ + return Object.defineProperty(require('./_dom-create')('div'), 'a', {get: function(){ return 7; }}).a != 7; +}); +},{"./_descriptors":77,"./_dom-create":78,"./_fails":82}],89:[function(require,module,exports){ +// fallback for non-array-like ES3 and non-enumerable old V8 strings +var cof = require('./_cof'); +module.exports = Object('z').propertyIsEnumerable(0) ? Object : function(it){ + return cof(it) == 'String' ? it.split('') : Object(it); +}; +},{"./_cof":69}],90:[function(require,module,exports){ +// check on default Array iterator +var Iterators = require('./_iterators') + , ITERATOR = require('./_wks')('iterator') + , ArrayProto = Array.prototype; + +module.exports = function(it){ + return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it); +}; +},{"./_iterators":97,"./_wks":131}],91:[function(require,module,exports){ +// 7.2.2 IsArray(argument) +var cof = require('./_cof'); +module.exports = Array.isArray || function isArray(arg){ + return cof(arg) == 'Array'; +}; +},{"./_cof":69}],92:[function(require,module,exports){ +module.exports = function(it){ + return typeof it === 'object' ? it !== null : typeof it === 'function'; +}; +},{}],93:[function(require,module,exports){ +// call something on iterator step with safe closing on error +var anObject = require('./_an-object'); +module.exports = function(iterator, fn, value, entries){ + try { + return entries ? fn(anObject(value)[0], value[1]) : fn(value); + // 7.4.6 IteratorClose(iterator, completion) + } catch(e){ + var ret = iterator['return']; + if(ret !== undefined)anObject(ret.call(iterator)); + throw e; + } +}; +},{"./_an-object":62}],94:[function(require,module,exports){ +'use strict'; +var create = require('./_object-create') + , descriptor = require('./_property-desc') + , setToStringTag = require('./_set-to-string-tag') + , IteratorPrototype = {}; + +// 25.1.2.1.1 %IteratorPrototype%[@@iterator]() +require('./_hide')(IteratorPrototype, require('./_wks')('iterator'), function(){ return this; }); + +module.exports = function(Constructor, NAME, next){ + Constructor.prototype = create(IteratorPrototype, {next: descriptor(1, next)}); + setToStringTag(Constructor, NAME + ' Iterator'); +}; +},{"./_hide":86,"./_object-create":102,"./_property-desc":114,"./_set-to-string-tag":118,"./_wks":131}],95:[function(require,module,exports){ +'use strict'; +var LIBRARY = require('./_library') + , $export = require('./_export') + , redefine = require('./_redefine') + , hide = require('./_hide') + , has = require('./_has') + , Iterators = require('./_iterators') + , $iterCreate = require('./_iter-create') + , setToStringTag = require('./_set-to-string-tag') + , getPrototypeOf = require('./_object-gpo') + , ITERATOR = require('./_wks')('iterator') + , BUGGY = !([].keys && 'next' in [].keys()) // Safari has buggy iterators w/o `next` + , FF_ITERATOR = '@@iterator' + , KEYS = 'keys' + , VALUES = 'values'; + +var returnThis = function(){ return this; }; + +module.exports = function(Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED){ + $iterCreate(Constructor, NAME, next); + var getMethod = function(kind){ + if(!BUGGY && kind in proto)return proto[kind]; + switch(kind){ + case KEYS: return function keys(){ return new Constructor(this, kind); }; + case VALUES: return function values(){ return new Constructor(this, kind); }; + } return function entries(){ return new Constructor(this, kind); }; + }; + var TAG = NAME + ' Iterator' + , DEF_VALUES = DEFAULT == VALUES + , VALUES_BUG = false + , proto = Base.prototype + , $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT] + , $default = $native || getMethod(DEFAULT) + , $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined + , $anyNative = NAME == 'Array' ? proto.entries || $native : $native + , methods, key, IteratorPrototype; + // Fix native + if($anyNative){ + IteratorPrototype = getPrototypeOf($anyNative.call(new Base)); + if(IteratorPrototype !== Object.prototype){ + // Set @@toStringTag to native iterators + setToStringTag(IteratorPrototype, TAG, true); + // fix for some old engines + if(!LIBRARY && !has(IteratorPrototype, ITERATOR))hide(IteratorPrototype, ITERATOR, returnThis); + } + } + // fix Array#{values, @@iterator}.name in V8 / FF + if(DEF_VALUES && $native && $native.name !== VALUES){ + VALUES_BUG = true; + $default = function values(){ return $native.call(this); }; + } + // Define iterator + if((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])){ + hide(proto, ITERATOR, $default); + } + // Plug for library + Iterators[NAME] = $default; + Iterators[TAG] = returnThis; + if(DEFAULT){ + methods = { + values: DEF_VALUES ? $default : getMethod(VALUES), + keys: IS_SET ? $default : getMethod(KEYS), + entries: $entries + }; + if(FORCED)for(key in methods){ + if(!(key in proto))redefine(proto, key, methods[key]); + } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods); + } + return methods; +}; +},{"./_export":81,"./_has":85,"./_hide":86,"./_iter-create":94,"./_iterators":97,"./_library":99,"./_object-gpo":109,"./_redefine":116,"./_set-to-string-tag":118,"./_wks":131}],96:[function(require,module,exports){ +module.exports = function(done, value){ + return {value: value, done: !!done}; +}; +},{}],97:[function(require,module,exports){ +module.exports = {}; +},{}],98:[function(require,module,exports){ +var getKeys = require('./_object-keys') + , toIObject = require('./_to-iobject'); +module.exports = function(object, el){ + var O = toIObject(object) + , keys = getKeys(O) + , length = keys.length + , index = 0 + , key; + while(length > index)if(O[key = keys[index++]] === el)return key; +}; +},{"./_object-keys":111,"./_to-iobject":124}],99:[function(require,module,exports){ +module.exports = true; +},{}],100:[function(require,module,exports){ +var META = require('./_uid')('meta') + , isObject = require('./_is-object') + , has = require('./_has') + , setDesc = require('./_object-dp').f + , id = 0; +var isExtensible = Object.isExtensible || function(){ + return true; +}; +var FREEZE = !require('./_fails')(function(){ + return isExtensible(Object.preventExtensions({})); +}); +var setMeta = function(it){ + setDesc(it, META, {value: { + i: 'O' + ++id, // object ID + w: {} // weak collections IDs + }}); +}; +var fastKey = function(it, create){ + // return primitive with prefix + if(!isObject(it))return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it; + if(!has(it, META)){ + // can't set metadata to uncaught frozen object + if(!isExtensible(it))return 'F'; + // not necessary to add metadata + if(!create)return 'E'; + // add missing metadata + setMeta(it); + // return object ID + } return it[META].i; +}; +var getWeak = function(it, create){ + if(!has(it, META)){ + // can't set metadata to uncaught frozen object + if(!isExtensible(it))return true; + // not necessary to add metadata + if(!create)return false; + // add missing metadata + setMeta(it); + // return hash weak collections IDs + } return it[META].w; +}; +// add metadata on freeze-family methods calling +var onFreeze = function(it){ + if(FREEZE && meta.NEED && isExtensible(it) && !has(it, META))setMeta(it); + return it; +}; +var meta = module.exports = { + KEY: META, + NEED: false, + fastKey: fastKey, + getWeak: getWeak, + onFreeze: onFreeze +}; +},{"./_fails":82,"./_has":85,"./_is-object":92,"./_object-dp":103,"./_uid":128}],101:[function(require,module,exports){ +'use strict'; +// 19.1.2.1 Object.assign(target, source, ...) +var getKeys = require('./_object-keys') + , gOPS = require('./_object-gops') + , pIE = require('./_object-pie') + , toObject = require('./_to-object') + , IObject = require('./_iobject') + , $assign = Object.assign; + +// should work with symbols and should have deterministic property order (V8 bug) +module.exports = !$assign || require('./_fails')(function(){ + var A = {} + , B = {} + , S = Symbol() + , K = 'abcdefghijklmnopqrst'; + A[S] = 7; + K.split('').forEach(function(k){ B[k] = k; }); + return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K; +}) ? function assign(target, source){ // eslint-disable-line no-unused-vars + var T = toObject(target) + , aLen = arguments.length + , index = 1 + , getSymbols = gOPS.f + , isEnum = pIE.f; + while(aLen > index){ + var S = IObject(arguments[index++]) + , keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S) + , length = keys.length + , j = 0 + , key; + while(length > j)if(isEnum.call(S, key = keys[j++]))T[key] = S[key]; + } return T; +} : $assign; +},{"./_fails":82,"./_iobject":89,"./_object-gops":108,"./_object-keys":111,"./_object-pie":112,"./_to-object":126}],102:[function(require,module,exports){ +// 19.1.2.2 / 15.2.3.5 Object.create(O [, Properties]) +var anObject = require('./_an-object') + , dPs = require('./_object-dps') + , enumBugKeys = require('./_enum-bug-keys') + , IE_PROTO = require('./_shared-key')('IE_PROTO') + , Empty = function(){ /* empty */ } + , PROTOTYPE = 'prototype'; + +// Create object with fake `null` prototype: use iframe Object with cleared prototype +var createDict = function(){ + // Thrash, waste and sodomy: IE GC bug + var iframe = require('./_dom-create')('iframe') + , i = enumBugKeys.length + , gt = '>' + , iframeDocument; + iframe.style.display = 'none'; + require('./_html').appendChild(iframe); + iframe.src = 'javascript:'; // eslint-disable-line no-script-url + // createDict = iframe.contentWindow.Object; + // html.removeChild(iframe); + iframeDocument = iframe.contentWindow.document; + iframeDocument.open(); + iframeDocument.write('