babel-schmooze-sprockets 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/bin/console +14 -0
  3. data/bin/export-external-helpers +3 -0
  4. data/bin/setup +6 -0
  5. data/bin/update-npm-deps +8 -0
  6. data/examples/myapp/Gemfile +4 -5
  7. data/examples/myapp/Gemfile.lock +69 -93
  8. data/examples/myapp/app/assets/javascripts/code/hello.es6 +5 -1
  9. data/examples/myapp/app/views/layouts/application.html.erb +1 -0
  10. data/examples/myapp/app/views/site/home.html.erb +0 -1
  11. data/lib/babel-schmooze-sprockets/babel_processor.rb +6 -4
  12. data/lib/babel-schmooze-sprockets/engine.rb +1 -4
  13. data/lib/babel-schmooze-sprockets/version.rb +1 -1
  14. data/node_modules/amdefine/package.json +8 -1
  15. data/node_modules/babel-core/node_modules/babel-runtime/package.json +9 -5
  16. data/node_modules/babel-core/node_modules/babel-traverse/.npmignore +3 -0
  17. data/node_modules/babel-core/node_modules/babel-traverse/README.md +1 -0
  18. data/node_modules/babel-core/node_modules/babel-traverse/lib/cache.js +20 -0
  19. data/node_modules/babel-core/node_modules/babel-traverse/lib/context.js +219 -0
  20. data/node_modules/babel-core/node_modules/babel-traverse/lib/hub.js +19 -0
  21. data/node_modules/babel-core/node_modules/babel-traverse/lib/index.js +250 -0
  22. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/ancestry.js +317 -0
  23. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/comments.js +55 -0
  24. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/context.js +297 -0
  25. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/conversion.js +48 -0
  26. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/evaluation.js +406 -0
  27. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/family.js +168 -0
  28. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/index.js +245 -0
  29. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/inference/index.js +151 -0
  30. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/inference/inferer-reference.js +225 -0
  31. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/inference/inferers.js +198 -0
  32. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/introspection.js +518 -0
  33. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/lib/hoister.js +166 -0
  34. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/lib/removal-hooks.js +64 -0
  35. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/lib/virtual-types.js +141 -0
  36. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/modification.js +293 -0
  37. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/removal.js +72 -0
  38. data/node_modules/babel-core/node_modules/babel-traverse/lib/path/replacement.js +302 -0
  39. data/node_modules/babel-core/node_modules/babel-traverse/lib/scope/binding.js +105 -0
  40. data/node_modules/babel-core/node_modules/babel-traverse/lib/scope/index.js +1222 -0
  41. data/node_modules/babel-core/node_modules/babel-traverse/lib/scope/lib/renamer.js +154 -0
  42. data/node_modules/babel-core/node_modules/babel-traverse/lib/visitors.js +360 -0
  43. data/node_modules/babel-core/node_modules/babel-traverse/package.json +107 -0
  44. data/node_modules/babel-core/node_modules/core-js/package.json +20 -2
  45. data/node_modules/babel-core/package.json +31 -24
  46. data/node_modules/babel-generator/lib/buffer.js +69 -70
  47. data/node_modules/babel-generator/lib/generators/base.js +16 -12
  48. data/node_modules/babel-generator/lib/generators/classes.js +28 -19
  49. data/node_modules/babel-generator/lib/generators/expressions.js +76 -99
  50. data/node_modules/babel-generator/lib/generators/flow.js +178 -119
  51. data/node_modules/babel-generator/lib/generators/jsx.js +38 -29
  52. data/node_modules/babel-generator/lib/generators/methods.js +34 -25
  53. data/node_modules/babel-generator/lib/generators/modules.js +67 -40
  54. data/node_modules/babel-generator/lib/generators/statements.js +93 -76
  55. data/node_modules/babel-generator/lib/generators/template-literals.js +12 -11
  56. data/node_modules/babel-generator/lib/generators/types.js +56 -49
  57. data/node_modules/babel-generator/lib/index.js +52 -39
  58. data/node_modules/babel-generator/lib/node/index.js +12 -18
  59. data/node_modules/babel-generator/lib/node/parentheses.js +23 -27
  60. data/node_modules/babel-generator/lib/node/whitespace.js +20 -26
  61. data/node_modules/babel-generator/lib/position.js +5 -5
  62. data/node_modules/babel-generator/lib/printer.js +52 -81
  63. data/node_modules/babel-generator/lib/source-map.js +9 -11
  64. data/node_modules/babel-generator/lib/whitespace.js +13 -13
  65. data/node_modules/babel-generator/node_modules/babel-runtime/package.json +19 -6
  66. data/node_modules/babel-generator/node_modules/babel-types/.npmignore +3 -0
  67. data/node_modules/babel-generator/node_modules/babel-types/README.md +1141 -0
  68. data/node_modules/babel-generator/node_modules/babel-types/lib/constants.js +40 -0
  69. data/node_modules/babel-generator/node_modules/babel-types/lib/converters.js +378 -0
  70. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/core.js +704 -0
  71. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/es2015.js +354 -0
  72. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/experimental.js +85 -0
  73. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/flow.js +319 -0
  74. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/index.js +247 -0
  75. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/init.js +15 -0
  76. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/jsx.js +137 -0
  77. data/node_modules/babel-generator/node_modules/babel-types/lib/definitions/misc.js +21 -0
  78. data/node_modules/babel-generator/node_modules/babel-types/lib/flow.js +129 -0
  79. data/node_modules/babel-generator/node_modules/babel-types/lib/index.js +848 -0
  80. data/node_modules/babel-generator/node_modules/babel-types/lib/react.js +83 -0
  81. data/node_modules/babel-generator/node_modules/babel-types/lib/retrievers.js +123 -0
  82. data/node_modules/babel-generator/node_modules/babel-types/lib/validators.js +276 -0
  83. data/node_modules/babel-generator/node_modules/babel-types/package.json +103 -0
  84. data/node_modules/babel-generator/node_modules/core-js/package.json +10 -5
  85. data/node_modules/babel-generator/package.json +19 -16
  86. data/node_modules/babel-helpers/node_modules/babel-runtime/package.json +19 -3
  87. data/node_modules/babel-helpers/node_modules/core-js/package.json +20 -4
  88. data/node_modules/babel-helpers/package.json +8 -1
  89. data/node_modules/babel-register/node_modules/babel-runtime/package.json +19 -3
  90. data/node_modules/babel-register/node_modules/core-js/package.json +20 -4
  91. data/node_modules/babel-register/package.json +8 -1
  92. data/node_modules/balanced-match/package.json +8 -1
  93. data/node_modules/brace-expansion/package.json +19 -12
  94. data/node_modules/concat-map/package.json +9 -2
  95. data/node_modules/convert-source-map/package.json +8 -1
  96. data/node_modules/detect-indent/package.json +8 -1
  97. data/node_modules/get-stdin/package.json +8 -1
  98. data/node_modules/home-or-tmp/package.json +9 -2
  99. data/node_modules/is-finite/package.json +8 -2
  100. data/node_modules/json5/package.json +8 -1
  101. data/node_modules/minimatch/README.md +2 -9
  102. data/node_modules/minimatch/minimatch.js +15 -3
  103. data/node_modules/minimatch/package.json +29 -21
  104. data/node_modules/minimist/package.json +8 -1
  105. data/node_modules/mkdirp/node_modules/minimist/package.json +8 -1
  106. data/node_modules/mkdirp/package.json +8 -1
  107. data/node_modules/number-is-nan/package.json +8 -1
  108. data/node_modules/os-tmpdir/package.json +8 -1
  109. data/node_modules/path-exists/package.json +8 -1
  110. data/node_modules/path-is-absolute/package.json +8 -1
  111. data/node_modules/repeating/package.json +15 -11
  112. data/node_modules/shebang-regex/package.json +8 -1
  113. data/node_modules/slash/package.json +8 -1
  114. data/node_modules/source-map-support/node_modules/source-map/package.json +8 -1
  115. data/node_modules/source-map-support/package.json +8 -1
  116. data/node_modules/source-map/package.json +8 -1
  117. data/node_modules/user-home/package.json +8 -1
  118. data/package.json +1 -1
  119. metadata +54 -6
  120. data/node_modules/brace-expansion/.npmignore +0 -3
  121. data/node_modules/brace-expansion/example.js +0 -8
  122. data/node_modules/minimatch/browser.js +0 -1159
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.shareCommentsWithSiblings = shareCommentsWithSiblings;
5
+ exports.addComment = addComment;
6
+ exports.addComments = addComments;
7
+ // This file contains methods responsible for dealing with comments.
8
+
9
+ /**
10
+ * Share comments amongst siblings.
11
+ */
12
+
13
+ function shareCommentsWithSiblings() {
14
+ var node = this.node;
15
+ if (!node) return;
16
+
17
+ var trailing = node.trailingComments;
18
+ var leading = node.leadingComments;
19
+ if (!trailing && !leading) return;
20
+
21
+ var prev = this.getSibling(this.key - 1);
22
+ var next = this.getSibling(this.key + 1);
23
+
24
+ if (!prev.node) prev = next;
25
+ if (!next.node) next = prev;
26
+
27
+ prev.addComments("trailing", leading);
28
+ next.addComments("leading", trailing);
29
+ }
30
+
31
+ function addComment(type, content, line) {
32
+ this.addComments(type, [{
33
+ type: line ? "CommentLine" : "CommentBlock",
34
+ value: content
35
+ }]);
36
+ }
37
+
38
+ /**
39
+ * Give node `comments` of the specified `type`.
40
+ */
41
+
42
+ function addComments(type, comments) {
43
+ if (!comments) return;
44
+
45
+ var node = this.node;
46
+ if (!node) return;
47
+
48
+ var key = type + "Comments";
49
+
50
+ if (node[key]) {
51
+ node[key] = node[key].concat(comments);
52
+ } else {
53
+ node[key] = comments;
54
+ }
55
+ }
@@ -0,0 +1,297 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+
5
+ var _getIterator2 = require("babel-runtime/core-js/get-iterator");
6
+
7
+ var _getIterator3 = _interopRequireDefault(_getIterator2);
8
+
9
+ exports.call = call;
10
+ exports._call = _call;
11
+ exports.isBlacklisted = isBlacklisted;
12
+ exports.visit = visit;
13
+ exports.skip = skip;
14
+ exports.skipKey = skipKey;
15
+ exports.stop = stop;
16
+ exports.setScope = setScope;
17
+ exports.setContext = setContext;
18
+ exports.resync = resync;
19
+ exports._resyncParent = _resyncParent;
20
+ exports._resyncKey = _resyncKey;
21
+ exports._resyncList = _resyncList;
22
+ exports._resyncRemoved = _resyncRemoved;
23
+ exports.popContext = popContext;
24
+ exports.pushContext = pushContext;
25
+ exports.setup = setup;
26
+ exports.setKey = setKey;
27
+ exports.requeue = requeue;
28
+ exports._getQueueContexts = _getQueueContexts;
29
+
30
+ var _index = require("../index");
31
+
32
+ var _index2 = _interopRequireDefault(_index);
33
+
34
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
35
+
36
+ function call(key) {
37
+ var opts = this.opts;
38
+
39
+ this.debug(function () {
40
+ return key;
41
+ });
42
+
43
+ if (this.node) {
44
+ if (this._call(opts[key])) return true;
45
+ }
46
+
47
+ if (this.node) {
48
+ return this._call(opts[this.node.type] && opts[this.node.type][key]);
49
+ }
50
+
51
+ return false;
52
+ } // This file contains methods responsible for maintaining a TraversalContext.
53
+
54
+ function _call(fns) {
55
+ if (!fns) return false;
56
+
57
+ for (var _iterator = fns, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) {
58
+ var _ref;
59
+
60
+ if (_isArray) {
61
+ if (_i >= _iterator.length) break;
62
+ _ref = _iterator[_i++];
63
+ } else {
64
+ _i = _iterator.next();
65
+ if (_i.done) break;
66
+ _ref = _i.value;
67
+ }
68
+
69
+ var fn = _ref;
70
+
71
+ if (!fn) continue;
72
+
73
+ var node = this.node;
74
+ if (!node) return true;
75
+
76
+ var ret = fn.call(this.state, this, this.state);
77
+ if (ret) throw new Error("Unexpected return value from visitor method " + fn);
78
+
79
+ // node has been replaced, it will have been requeued
80
+ if (this.node !== node) return true;
81
+
82
+ if (this.shouldStop || this.shouldSkip || this.removed) return true;
83
+ }
84
+
85
+ return false;
86
+ }
87
+
88
+ function isBlacklisted() {
89
+ var blacklist = this.opts.blacklist;
90
+ return blacklist && blacklist.indexOf(this.node.type) > -1;
91
+ }
92
+
93
+ function visit() {
94
+ if (!this.node) {
95
+ return false;
96
+ }
97
+
98
+ if (this.isBlacklisted()) {
99
+ return false;
100
+ }
101
+
102
+ if (this.opts.shouldSkip && this.opts.shouldSkip(this)) {
103
+ return false;
104
+ }
105
+
106
+ if (this.call("enter") || this.shouldSkip) {
107
+ this.debug(function () {
108
+ return "Skip...";
109
+ });
110
+ return this.shouldStop;
111
+ }
112
+
113
+ this.debug(function () {
114
+ return "Recursing into...";
115
+ });
116
+ _index2.default.node(this.node, this.opts, this.scope, this.state, this, this.skipKeys);
117
+
118
+ this.call("exit");
119
+
120
+ return this.shouldStop;
121
+ }
122
+
123
+ function skip() {
124
+ this.shouldSkip = true;
125
+ }
126
+
127
+ function skipKey(key) {
128
+ this.skipKeys[key] = true;
129
+ }
130
+
131
+ function stop() {
132
+ this.shouldStop = true;
133
+ this.shouldSkip = true;
134
+ }
135
+
136
+ function setScope() {
137
+ if (this.opts && this.opts.noScope) return;
138
+
139
+ var target = this.context && this.context.scope;
140
+
141
+ if (!target) {
142
+ var path = this.parentPath;
143
+ while (path && !target) {
144
+ if (path.opts && path.opts.noScope) return;
145
+
146
+ target = path.scope;
147
+ path = path.parentPath;
148
+ }
149
+ }
150
+
151
+ this.scope = this.getScope(target);
152
+ if (this.scope) this.scope.init();
153
+ }
154
+
155
+ function setContext(context) {
156
+ this.shouldSkip = false;
157
+ this.shouldStop = false;
158
+ this.removed = false;
159
+ this.skipKeys = {};
160
+
161
+ if (context) {
162
+ this.context = context;
163
+ this.state = context.state;
164
+ this.opts = context.opts;
165
+ }
166
+
167
+ this.setScope();
168
+
169
+ return this;
170
+ }
171
+
172
+ /**
173
+ * Here we resync the node paths `key` and `container`. If they've changed according
174
+ * to what we have stored internally then we attempt to resync by crawling and looking
175
+ * for the new values.
176
+ */
177
+
178
+ function resync() {
179
+ if (this.removed) return;
180
+
181
+ this._resyncParent();
182
+ this._resyncList();
183
+ this._resyncKey();
184
+ //this._resyncRemoved();
185
+ }
186
+
187
+ function _resyncParent() {
188
+ if (this.parentPath) {
189
+ this.parent = this.parentPath.node;
190
+ }
191
+ }
192
+
193
+ function _resyncKey() {
194
+ if (!this.container) return;
195
+
196
+ if (this.node === this.container[this.key]) return;
197
+
198
+ // grrr, path key is out of sync. this is likely due to a modification to the AST
199
+ // not done through our path APIs
200
+
201
+ if (Array.isArray(this.container)) {
202
+ for (var i = 0; i < this.container.length; i++) {
203
+ if (this.container[i] === this.node) {
204
+ return this.setKey(i);
205
+ }
206
+ }
207
+ } else {
208
+ for (var key in this.container) {
209
+ if (this.container[key] === this.node) {
210
+ return this.setKey(key);
211
+ }
212
+ }
213
+ }
214
+
215
+ // ¯\_(ツ)_/¯ who knows where it's gone lol
216
+ this.key = null;
217
+ }
218
+
219
+ function _resyncList() {
220
+ if (!this.parent || !this.inList) return;
221
+
222
+ var newContainer = this.parent[this.listKey];
223
+ if (this.container === newContainer) return;
224
+
225
+ // container is out of sync. this is likely the result of it being reassigned
226
+ this.container = newContainer || null;
227
+ }
228
+
229
+ function _resyncRemoved() {
230
+ if (this.key == null || !this.container || this.container[this.key] !== this.node) {
231
+ this._markRemoved();
232
+ }
233
+ }
234
+
235
+ function popContext() {
236
+ this.contexts.pop();
237
+ this.setContext(this.contexts[this.contexts.length - 1]);
238
+ }
239
+
240
+ function pushContext(context) {
241
+ this.contexts.push(context);
242
+ this.setContext(context);
243
+ }
244
+
245
+ function setup(parentPath, container, listKey, key) {
246
+ this.inList = !!listKey;
247
+ this.listKey = listKey;
248
+ this.parentKey = listKey || key;
249
+ this.container = container;
250
+
251
+ this.parentPath = parentPath || this.parentPath;
252
+ this.setKey(key);
253
+ }
254
+
255
+ function setKey(key) {
256
+ this.key = key;
257
+ this.node = this.container[this.key];
258
+ this.type = this.node && this.node.type;
259
+ }
260
+
261
+ function requeue() {
262
+ var pathToQueue = arguments.length <= 0 || arguments[0] === undefined ? this : arguments[0];
263
+
264
+ if (pathToQueue.removed) return;
265
+
266
+ // TODO(loganfsmyth): This should be switched back to queue in parent contexts
267
+ // automatically once T2892 and T7160 have been resolved. See T7166.
268
+ // let contexts = this._getQueueContexts();
269
+ var contexts = this.contexts;
270
+
271
+ for (var _iterator2 = contexts, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) {
272
+ var _ref2;
273
+
274
+ if (_isArray2) {
275
+ if (_i2 >= _iterator2.length) break;
276
+ _ref2 = _iterator2[_i2++];
277
+ } else {
278
+ _i2 = _iterator2.next();
279
+ if (_i2.done) break;
280
+ _ref2 = _i2.value;
281
+ }
282
+
283
+ var context = _ref2;
284
+
285
+ context.maybeQueue(pathToQueue);
286
+ }
287
+ }
288
+
289
+ function _getQueueContexts() {
290
+ var path = this;
291
+ var contexts = this.contexts;
292
+ while (!contexts.length) {
293
+ path = path.parentPath;
294
+ contexts = path.contexts;
295
+ }
296
+ return contexts;
297
+ }
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.toComputedKey = toComputedKey;
5
+ exports.ensureBlock = ensureBlock;
6
+ exports.arrowFunctionToShadowed = arrowFunctionToShadowed;
7
+
8
+ var _babelTypes = require("babel-types");
9
+
10
+ var t = _interopRequireWildcard(_babelTypes);
11
+
12
+ 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; } }
13
+
14
+ function toComputedKey() {
15
+ var node = this.node;
16
+
17
+ var key = void 0;
18
+ if (this.isMemberExpression()) {
19
+ key = node.property;
20
+ } else if (this.isProperty() || this.isMethod()) {
21
+ key = node.key;
22
+ } else {
23
+ throw new ReferenceError("todo");
24
+ }
25
+
26
+ if (!node.computed) {
27
+ if (t.isIdentifier(key)) key = t.stringLiteral(key.name);
28
+ }
29
+
30
+ return key;
31
+ } // This file contains methods that convert the path node into another node or some other type of data.
32
+
33
+ function ensureBlock() {
34
+ return t.ensureBlock(this.node);
35
+ }
36
+
37
+ function arrowFunctionToShadowed() {
38
+ // todo: maybe error
39
+ if (!this.isArrowFunctionExpression()) return;
40
+
41
+ this.ensureBlock();
42
+
43
+ var node = this.node;
44
+
45
+ node.expression = false;
46
+ node.type = "FunctionExpression";
47
+ node.shadow = node.shadow || true;
48
+ }
@@ -0,0 +1,406 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+
5
+ var _typeof2 = require("babel-runtime/helpers/typeof");
6
+
7
+ var _typeof3 = _interopRequireDefault(_typeof2);
8
+
9
+ var _getIterator2 = require("babel-runtime/core-js/get-iterator");
10
+
11
+ var _getIterator3 = _interopRequireDefault(_getIterator2);
12
+
13
+ var _map = require("babel-runtime/core-js/map");
14
+
15
+ var _map2 = _interopRequireDefault(_map);
16
+
17
+ exports.evaluateTruthy = evaluateTruthy;
18
+ exports.evaluate = evaluate;
19
+
20
+ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
21
+
22
+ // This file contains Babels metainterpreter that can evaluate static code.
23
+
24
+ /* eslint eqeqeq: 0 */
25
+
26
+ var VALID_CALLEES = ["String", "Number", "Math"]; /* eslint indent: 0 */
27
+ /* eslint max-len: 0 */
28
+
29
+ var INVALID_METHODS = ["random"];
30
+
31
+ /**
32
+ * Walk the input `node` and statically evaluate if it's truthy.
33
+ *
34
+ * Returning `true` when we're sure that the expression will evaluate to a
35
+ * truthy value, `false` if we're sure that it will evaluate to a falsy
36
+ * value and `undefined` if we aren't sure. Because of this please do not
37
+ * rely on coercion when using this method and check with === if it's false.
38
+ *
39
+ * For example do:
40
+ *
41
+ * if (t.evaluateTruthy(node) === false) falsyLogic();
42
+ *
43
+ * **AND NOT**
44
+ *
45
+ * if (!t.evaluateTruthy(node)) falsyLogic();
46
+ *
47
+ */
48
+
49
+ function evaluateTruthy() {
50
+ var res = this.evaluate();
51
+ if (res.confident) return !!res.value;
52
+ }
53
+
54
+ /**
55
+ * Walk the input `node` and statically evaluate it.
56
+ *
57
+ * Returns an object in the form `{ confident, value }`. `confident` indicates
58
+ * whether or not we had to drop out of evaluating the expression because of
59
+ * hitting an unknown node that we couldn't confidently find the value of.
60
+ *
61
+ * Example:
62
+ *
63
+ * t.evaluate(parse("5 + 5")) // { confident: true, value: 10 }
64
+ * t.evaluate(parse("!true")) // { confident: true, value: false }
65
+ * t.evaluate(parse("foo + foo")) // { confident: false, value: undefined }
66
+ *
67
+ */
68
+
69
+ function evaluate() {
70
+ var confident = true;
71
+ var deoptPath = void 0;
72
+ var seen = new _map2.default();
73
+
74
+ function deopt(path) {
75
+ if (!confident) return;
76
+ deoptPath = path;
77
+ confident = false;
78
+ }
79
+
80
+ var value = evaluate(this);
81
+ if (!confident) value = undefined;
82
+ return {
83
+ confident: confident,
84
+ deopt: deoptPath,
85
+ value: value
86
+ };
87
+
88
+ // we wrap the _evaluate method so we can track `seen` nodes, we push an item
89
+ // to the map before we actually evaluate it so we can deopt on self recursive
90
+ // nodes such as:
91
+ //
92
+ // var g = a ? 1 : 2,
93
+ // a = g * this.foo
94
+ //
95
+ function evaluate(path) {
96
+ var node = path.node;
97
+
98
+
99
+ if (seen.has(node)) {
100
+ var existing = seen.get(node);
101
+ if (existing.resolved) {
102
+ return existing.value;
103
+ } else {
104
+ deopt(path);
105
+ return;
106
+ }
107
+ } else {
108
+ var item = { resolved: false };
109
+ seen.set(node, item);
110
+
111
+ var val = _evaluate(path);
112
+ item.resolved = true;
113
+ item.value = value;
114
+ return val;
115
+ }
116
+ }
117
+
118
+ function _evaluate(path) {
119
+ if (!confident) return;
120
+
121
+ var node = path.node;
122
+
123
+
124
+ if (path.isSequenceExpression()) {
125
+ var exprs = path.get("expressions");
126
+ return evaluate(exprs[exprs.length - 1]);
127
+ }
128
+
129
+ if (path.isStringLiteral() || path.isNumericLiteral() || path.isBooleanLiteral()) {
130
+ return node.value;
131
+ }
132
+
133
+ if (path.isNullLiteral()) {
134
+ return null;
135
+ }
136
+
137
+ if (path.isTemplateLiteral()) {
138
+ var str = "";
139
+
140
+ var i = 0;
141
+ var _exprs = path.get("expressions");
142
+
143
+ for (var _iterator = node.quasis, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) {
144
+ var _ref;
145
+
146
+ if (_isArray) {
147
+ if (_i >= _iterator.length) break;
148
+ _ref = _iterator[_i++];
149
+ } else {
150
+ _i = _iterator.next();
151
+ if (_i.done) break;
152
+ _ref = _i.value;
153
+ }
154
+
155
+ var elem = _ref;
156
+
157
+ // not confident, evaluated an expression we don't like
158
+ if (!confident) break;
159
+
160
+ // add on cooked element
161
+ str += elem.value.cooked;
162
+
163
+ // add on interpolated expression if it's present
164
+ var expr = _exprs[i++];
165
+ if (expr) str += String(evaluate(expr));
166
+ }
167
+
168
+ if (!confident) return;
169
+ return str;
170
+ }
171
+
172
+ if (path.isConditionalExpression()) {
173
+ var testResult = evaluate(path.get("test"));
174
+ if (!confident) return;
175
+ if (testResult) {
176
+ return evaluate(path.get("consequent"));
177
+ } else {
178
+ return evaluate(path.get("alternate"));
179
+ }
180
+ }
181
+
182
+ if (path.isExpressionWrapper()) {
183
+ // TypeCastExpression, ExpressionStatement etc
184
+ return evaluate(path.get("expression"));
185
+ }
186
+
187
+ // "foo".length
188
+ if (path.isMemberExpression() && !path.parentPath.isCallExpression({ callee: node })) {
189
+ var property = path.get("property");
190
+ var object = path.get("object");
191
+
192
+ if (object.isLiteral() && property.isIdentifier()) {
193
+ var _value = object.node.value;
194
+ var type = typeof _value === "undefined" ? "undefined" : (0, _typeof3.default)(_value);
195
+ if (type === "number" || type === "string") {
196
+ return _value[property.node.name];
197
+ }
198
+ }
199
+ }
200
+
201
+ if (path.isReferencedIdentifier()) {
202
+ var binding = path.scope.getBinding(node.name);
203
+ if (binding && binding.hasValue) {
204
+ return binding.value;
205
+ } else {
206
+ if (node.name === "undefined") {
207
+ return undefined;
208
+ } else if (node.name === "Infinity") {
209
+ return Infinity;
210
+ } else if (node.name === "NaN") {
211
+ return NaN;
212
+ }
213
+
214
+ var resolved = path.resolve();
215
+ if (resolved === path) {
216
+ return deopt(path);
217
+ } else {
218
+ return evaluate(resolved);
219
+ }
220
+ }
221
+ }
222
+
223
+ if (path.isUnaryExpression({ prefix: true })) {
224
+ if (node.operator === "void") {
225
+ // we don't need to evaluate the argument to know what this will return
226
+ return undefined;
227
+ }
228
+
229
+ var argument = path.get("argument");
230
+ if (node.operator === "typeof" && (argument.isFunction() || argument.isClass())) {
231
+ return "function";
232
+ }
233
+
234
+ var arg = evaluate(argument);
235
+ if (!confident) return;
236
+ switch (node.operator) {
237
+ case "!":
238
+ return !arg;
239
+ case "+":
240
+ return +arg;
241
+ case "-":
242
+ return -arg;
243
+ case "~":
244
+ return ~arg;
245
+ case "typeof":
246
+ return typeof arg === "undefined" ? "undefined" : (0, _typeof3.default)(arg);
247
+ }
248
+ }
249
+
250
+ if (path.isArrayExpression()) {
251
+ var arr = [];
252
+ var elems = path.get("elements");
253
+ for (var _iterator2 = elems, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) {
254
+ var _ref2;
255
+
256
+ if (_isArray2) {
257
+ if (_i2 >= _iterator2.length) break;
258
+ _ref2 = _iterator2[_i2++];
259
+ } else {
260
+ _i2 = _iterator2.next();
261
+ if (_i2.done) break;
262
+ _ref2 = _i2.value;
263
+ }
264
+
265
+ var _elem = _ref2;
266
+
267
+ _elem = _elem.evaluate();
268
+
269
+ if (_elem.confident) {
270
+ arr.push(_elem.value);
271
+ } else {
272
+ return deopt(_elem);
273
+ }
274
+ }
275
+ return arr;
276
+ }
277
+
278
+ if (path.isObjectExpression()) {
279
+ // todo
280
+ }
281
+
282
+ if (path.isLogicalExpression()) {
283
+ // If we are confident that one side of an && is false, or the left
284
+ // side of an || is true, we can be confident about the entire expression
285
+ var wasConfident = confident;
286
+ var left = evaluate(path.get("left"));
287
+ var leftConfident = confident;
288
+ confident = wasConfident;
289
+ var right = evaluate(path.get("right"));
290
+ var rightConfident = confident;
291
+ confident = leftConfident && rightConfident;
292
+
293
+ switch (node.operator) {
294
+ case "||":
295
+ // TODO consider having a "truthy type" that doesn't bail on
296
+ // left uncertainity but can still evaluate to truthy.
297
+ if (left && leftConfident) {
298
+ confident = true;
299
+ return left;
300
+ }
301
+
302
+ if (!confident) return;
303
+
304
+ return left || right;
305
+ case "&&":
306
+ if (!left && leftConfident || !right && rightConfident) {
307
+ confident = true;
308
+ }
309
+
310
+ if (!confident) return;
311
+
312
+ return left && right;
313
+ }
314
+ }
315
+
316
+ if (path.isBinaryExpression()) {
317
+ var _left = evaluate(path.get("left"));
318
+ if (!confident) return;
319
+ var _right = evaluate(path.get("right"));
320
+ if (!confident) return;
321
+
322
+ switch (node.operator) {
323
+ case "-":
324
+ return _left - _right;
325
+ case "+":
326
+ return _left + _right;
327
+ case "/":
328
+ return _left / _right;
329
+ case "*":
330
+ return _left * _right;
331
+ case "%":
332
+ return _left % _right;
333
+ case "**":
334
+ return Math.pow(_left, _right);
335
+ case "<":
336
+ return _left < _right;
337
+ case ">":
338
+ return _left > _right;
339
+ case "<=":
340
+ return _left <= _right;
341
+ case ">=":
342
+ return _left >= _right;
343
+ case "==":
344
+ return _left == _right;
345
+ case "!=":
346
+ return _left != _right;
347
+ case "===":
348
+ return _left === _right;
349
+ case "!==":
350
+ return _left !== _right;
351
+ case "|":
352
+ return _left | _right;
353
+ case "&":
354
+ return _left & _right;
355
+ case "^":
356
+ return _left ^ _right;
357
+ case "<<":
358
+ return _left << _right;
359
+ case ">>":
360
+ return _left >> _right;
361
+ case ">>>":
362
+ return _left >>> _right;
363
+ }
364
+ }
365
+
366
+ if (path.isCallExpression()) {
367
+ var callee = path.get("callee");
368
+ var context = void 0;
369
+ var func = void 0;
370
+
371
+ // Number(1);
372
+ if (callee.isIdentifier() && !path.scope.getBinding(callee.node.name, true) && VALID_CALLEES.indexOf(callee.node.name) >= 0) {
373
+ func = global[node.callee.name];
374
+ }
375
+
376
+ if (callee.isMemberExpression()) {
377
+ var _object = callee.get("object");
378
+ var _property = callee.get("property");
379
+
380
+ // Math.min(1, 2)
381
+ if (_object.isIdentifier() && _property.isIdentifier() && VALID_CALLEES.indexOf(_object.node.name) >= 0 && INVALID_METHODS.indexOf(_property.node.name) < 0) {
382
+ context = global[_object.node.name];
383
+ func = context[_property.node.name];
384
+ }
385
+
386
+ // "abc".charCodeAt(4)
387
+ if (_object.isLiteral() && _property.isIdentifier()) {
388
+ var _type = (0, _typeof3.default)(_object.node.value);
389
+ if (_type === "string" || _type === "number") {
390
+ context = _object.node.value;
391
+ func = context[_property.node.name];
392
+ }
393
+ }
394
+ }
395
+
396
+ if (func) {
397
+ var args = path.get("arguments").map(evaluate);
398
+ if (!confident) return;
399
+
400
+ return func.apply(context, args);
401
+ }
402
+ }
403
+
404
+ deopt(path);
405
+ }
406
+ }