1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 | "use strict";
|
60 |
|
61 | var astNodeTypes = require("./lib/ast-node-types"),
|
62 | commentAttachment = require("./lib/comment-attachment"),
|
63 | TokenTranslator = require("./lib/token-translator"),
|
64 | acornJSX = require("acorn-jsx/inject"),
|
65 | rawAcorn = require("acorn");
|
66 |
|
67 |
|
68 | var acorn = acornJSX(rawAcorn);
|
69 | var DEFAULT_ECMA_VERSION = 5;
|
70 | var lookahead,
|
71 | extra,
|
72 | lastToken;
|
73 |
|
74 |
|
75 |
|
76 |
|
77 |
|
78 |
|
79 | function resetExtra() {
|
80 | extra = {
|
81 | tokens: null,
|
82 | range: false,
|
83 | loc: false,
|
84 | comment: false,
|
85 | comments: [],
|
86 | tolerant: false,
|
87 | errors: [],
|
88 | strict: false,
|
89 | ecmaFeatures: {},
|
90 | ecmaVersion: DEFAULT_ECMA_VERSION,
|
91 | isModule: false
|
92 | };
|
93 | }
|
94 |
|
95 |
|
96 |
|
97 | var tt = acorn.tokTypes,
|
98 | getLineInfo = acorn.getLineInfo;
|
99 |
|
100 |
|
101 | tt.jsxAttrValueToken = {};
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 | function normalizeEcmaVersion(ecmaVersion) {
|
109 | if (typeof ecmaVersion === "number") {
|
110 | var version = ecmaVersion;
|
111 |
|
112 |
|
113 |
|
114 | if (version >= 2015) {
|
115 | version -= 2009;
|
116 | }
|
117 |
|
118 | switch (version) {
|
119 | case 3:
|
120 | case 5:
|
121 | case 6:
|
122 | case 7:
|
123 | case 8:
|
124 | case 9:
|
125 | case 10:
|
126 | return version;
|
127 |
|
128 | default:
|
129 | throw new Error("Invalid ecmaVersion.");
|
130 | }
|
131 | } else {
|
132 | return DEFAULT_ECMA_VERSION;
|
133 | }
|
134 | }
|
135 |
|
136 |
|
137 |
|
138 |
|
139 |
|
140 |
|
141 |
|
142 | function isValidNode(node) {
|
143 | switch (node.type) {
|
144 | case "ImportDeclaration":
|
145 | case "ExportNamedDeclaration":
|
146 | case "ExportDefaultDeclaration":
|
147 | case "ExportAllDeclaration":
|
148 | return extra.isModule;
|
149 |
|
150 | default:
|
151 | return true;
|
152 | }
|
153 | }
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 |
|
161 |
|
162 | function esprimaFinishNode(result) {
|
163 |
|
164 | if (!isValidNode(result)) {
|
165 | this.unexpected(result.start);
|
166 | }
|
167 |
|
168 |
|
169 |
|
170 | if (result.type === "TemplateElement") {
|
171 |
|
172 |
|
173 | var terminalDollarBraceL = this.input.slice(result.end, result.end + 2) === "${";
|
174 |
|
175 | if (result.range) {
|
176 | result.range[0]--;
|
177 | result.range[1] += (terminalDollarBraceL ? 2 : 1);
|
178 | }
|
179 |
|
180 | if (result.loc) {
|
181 | result.loc.start.column--;
|
182 | result.loc.end.column += (terminalDollarBraceL ? 2 : 1);
|
183 | }
|
184 | }
|
185 |
|
186 | if (extra.attachComment) {
|
187 | commentAttachment.processComment(result);
|
188 | }
|
189 |
|
190 | if (result.type.indexOf("Function") > -1 && !result.generator) {
|
191 | result.generator = false;
|
192 | }
|
193 |
|
194 | return result;
|
195 | }
|
196 |
|
197 |
|
198 |
|
199 |
|
200 |
|
201 |
|
202 |
|
203 | function isValidToken(parser) {
|
204 | var ecma = extra.ecmaFeatures;
|
205 | var type = parser.type;
|
206 |
|
207 | switch (type) {
|
208 | case tt.jsxName:
|
209 | case tt.jsxText:
|
210 | case tt.jsxTagStart:
|
211 | case tt.jsxTagEnd:
|
212 | return ecma.jsx;
|
213 |
|
214 |
|
215 | case tt.regexp:
|
216 | if (extra.ecmaVersion < 6 && parser.value.flags && parser.value.flags.indexOf("y") > -1) {
|
217 | return false;
|
218 | }
|
219 |
|
220 | return true;
|
221 |
|
222 | default:
|
223 | return true;
|
224 | }
|
225 | }
|
226 |
|
227 |
|
228 |
|
229 |
|
230 |
|
231 |
|
232 |
|
233 | function wrapFinishNode(finishNode) {
|
234 | return function(node, type, pos, loc) {
|
235 | var result = finishNode.call(this, node, type, pos, loc);
|
236 | return esprimaFinishNode.call(this, result);
|
237 | };
|
238 | }
|
239 |
|
240 | acorn.plugins.espree = function(instance) {
|
241 |
|
242 | instance.extend("finishNode", wrapFinishNode);
|
243 |
|
244 | instance.extend("finishNodeAt", wrapFinishNode);
|
245 |
|
246 | instance.extend("next", function(next) {
|
247 | return function() {
|
248 | if (!isValidToken(this)) {
|
249 | this.unexpected();
|
250 | }
|
251 | return next.call(this);
|
252 | };
|
253 | });
|
254 |
|
255 | instance.extend("parseTopLevel", function(parseTopLevel) {
|
256 | return function(node) {
|
257 | if (extra.ecmaFeatures.impliedStrict && this.options.ecmaVersion >= 5) {
|
258 | this.strict = true;
|
259 | }
|
260 | return parseTopLevel.call(this, node);
|
261 | };
|
262 | });
|
263 |
|
264 | |
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 | instance.raise = instance.raiseRecoverable = function(pos, message) {
|
272 | var loc = getLineInfo(this.input, pos);
|
273 | var err = new SyntaxError(message);
|
274 | err.index = pos;
|
275 | err.lineNumber = loc.line;
|
276 | err.column = loc.column + 1;
|
277 | throw err;
|
278 | };
|
279 |
|
280 | |
281 |
|
282 |
|
283 |
|
284 |
|
285 |
|
286 | instance.unexpected = function(pos) {
|
287 | var message = "Unexpected token";
|
288 |
|
289 | if (pos !== null && pos !== undefined) {
|
290 | this.pos = pos;
|
291 |
|
292 | if (this.options.locations) {
|
293 | while (this.pos < this.lineStart) {
|
294 | this.lineStart = this.input.lastIndexOf("\n", this.lineStart - 2) + 1;
|
295 | --this.curLine;
|
296 | }
|
297 | }
|
298 |
|
299 | this.nextToken();
|
300 | }
|
301 |
|
302 | if (this.end > this.start) {
|
303 | message += " " + this.input.slice(this.start, this.end);
|
304 | }
|
305 |
|
306 | this.raise(this.start, message);
|
307 | };
|
308 |
|
309 | |
310 |
|
311 |
|
312 |
|
313 |
|
314 |
|
315 |
|
316 | instance.extend("jsx_readString", function(jsxReadString) {
|
317 | return function(quote) {
|
318 | var result = jsxReadString.call(this, quote);
|
319 | if (this.type === tt.string) {
|
320 | extra.jsxAttrValueToken = true;
|
321 | }
|
322 |
|
323 | return result;
|
324 | };
|
325 | });
|
326 | };
|
327 |
|
328 |
|
329 |
|
330 |
|
331 |
|
332 |
|
333 |
|
334 |
|
335 |
|
336 |
|
337 |
|
338 |
|
339 |
|
340 | function tokenize(code, options) {
|
341 | var toString,
|
342 | tokens,
|
343 | impliedStrict,
|
344 | translator = new TokenTranslator(tt, code);
|
345 |
|
346 | toString = String;
|
347 | if (typeof code !== "string" && !(code instanceof String)) {
|
348 | code = toString(code);
|
349 | }
|
350 |
|
351 | lookahead = null;
|
352 |
|
353 |
|
354 | options = Object.assign({}, options);
|
355 |
|
356 | var acornOptions = {
|
357 | ecmaVersion: DEFAULT_ECMA_VERSION,
|
358 | plugins: {
|
359 | espree: true
|
360 | }
|
361 | };
|
362 |
|
363 | resetExtra();
|
364 |
|
365 |
|
366 | options.tokens = true;
|
367 | extra.tokens = [];
|
368 |
|
369 | extra.range = (typeof options.range === "boolean") && options.range;
|
370 | acornOptions.ranges = extra.range;
|
371 |
|
372 | extra.loc = (typeof options.loc === "boolean") && options.loc;
|
373 | acornOptions.locations = extra.loc;
|
374 |
|
375 | extra.comment = typeof options.comment === "boolean" && options.comment;
|
376 |
|
377 | if (extra.comment) {
|
378 | acornOptions.onComment = function() {
|
379 | var comment = convertAcornCommentToEsprimaComment.apply(this, arguments);
|
380 | extra.comments.push(comment);
|
381 | };
|
382 | }
|
383 |
|
384 | extra.tolerant = typeof options.tolerant === "boolean" && options.tolerant;
|
385 |
|
386 | acornOptions.ecmaVersion = extra.ecmaVersion = normalizeEcmaVersion(options.ecmaVersion);
|
387 |
|
388 |
|
389 | if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") {
|
390 | extra.ecmaFeatures = Object.assign({}, options.ecmaFeatures);
|
391 | impliedStrict = extra.ecmaFeatures.impliedStrict;
|
392 | extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict;
|
393 | }
|
394 |
|
395 | try {
|
396 | var tokenizer = acorn.tokenizer(code, acornOptions);
|
397 | while ((lookahead = tokenizer.getToken()).type !== tt.eof) {
|
398 | translator.onToken(lookahead, extra);
|
399 | }
|
400 |
|
401 |
|
402 | tokens = extra.tokens;
|
403 |
|
404 | if (extra.comment) {
|
405 | tokens.comments = extra.comments;
|
406 | }
|
407 | if (extra.tolerant) {
|
408 | tokens.errors = extra.errors;
|
409 | }
|
410 | } catch (e) {
|
411 | throw e;
|
412 | }
|
413 | return tokens;
|
414 | }
|
415 |
|
416 |
|
417 |
|
418 |
|
419 |
|
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 |
|
426 |
|
427 |
|
428 |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 | function convertAcornCommentToEsprimaComment(block, text, start, end, startLoc, endLoc) {
|
434 | var comment = {
|
435 | type: block ? "Block" : "Line",
|
436 | value: text
|
437 | };
|
438 |
|
439 | if (typeof start === "number") {
|
440 | comment.start = start;
|
441 | comment.end = end;
|
442 | comment.range = [start, end];
|
443 | }
|
444 |
|
445 | if (typeof startLoc === "object") {
|
446 | comment.loc = {
|
447 | start: startLoc,
|
448 | end: endLoc
|
449 | };
|
450 | }
|
451 |
|
452 | return comment;
|
453 | }
|
454 |
|
455 |
|
456 |
|
457 |
|
458 |
|
459 |
|
460 |
|
461 |
|
462 |
|
463 | function parse(code, options) {
|
464 | var program,
|
465 | toString = String,
|
466 | translator,
|
467 | impliedStrict,
|
468 | acornOptions = {
|
469 | ecmaVersion: DEFAULT_ECMA_VERSION,
|
470 | plugins: {
|
471 | espree: true
|
472 | }
|
473 | };
|
474 |
|
475 | lastToken = null;
|
476 |
|
477 | if (typeof code !== "string" && !(code instanceof String)) {
|
478 | code = toString(code);
|
479 | }
|
480 |
|
481 | resetExtra();
|
482 | commentAttachment.reset();
|
483 |
|
484 | if (typeof options !== "undefined") {
|
485 | extra.range = (typeof options.range === "boolean") && options.range;
|
486 | extra.loc = (typeof options.loc === "boolean") && options.loc;
|
487 | extra.attachComment = (typeof options.attachComment === "boolean") && options.attachComment;
|
488 |
|
489 | if (extra.loc && options.source !== null && options.source !== undefined) {
|
490 | extra.source = toString(options.source);
|
491 | }
|
492 |
|
493 | if (typeof options.tokens === "boolean" && options.tokens) {
|
494 | extra.tokens = [];
|
495 | translator = new TokenTranslator(tt, code);
|
496 | }
|
497 | if (typeof options.comment === "boolean" && options.comment) {
|
498 | extra.comment = true;
|
499 | extra.comments = [];
|
500 | }
|
501 | if (typeof options.tolerant === "boolean" && options.tolerant) {
|
502 | extra.errors = [];
|
503 | }
|
504 | if (extra.attachComment) {
|
505 | extra.range = true;
|
506 | extra.comments = [];
|
507 | commentAttachment.reset();
|
508 | }
|
509 |
|
510 | acornOptions.ecmaVersion = extra.ecmaVersion = normalizeEcmaVersion(options.ecmaVersion);
|
511 |
|
512 | if (options.sourceType === "module") {
|
513 | extra.isModule = true;
|
514 |
|
515 |
|
516 | if (acornOptions.ecmaVersion < 6) {
|
517 | acornOptions.ecmaVersion = 6;
|
518 | extra.ecmaVersion = 6;
|
519 | }
|
520 |
|
521 | acornOptions.sourceType = "module";
|
522 | }
|
523 |
|
524 |
|
525 | if (options.ecmaFeatures && typeof options.ecmaFeatures === "object") {
|
526 | extra.ecmaFeatures = Object.assign({}, options.ecmaFeatures);
|
527 | impliedStrict = extra.ecmaFeatures.impliedStrict;
|
528 | extra.ecmaFeatures.impliedStrict = typeof impliedStrict === "boolean" && impliedStrict;
|
529 | if (options.ecmaFeatures.globalReturn) {
|
530 | acornOptions.allowReturnOutsideFunction = true;
|
531 | }
|
532 | }
|
533 |
|
534 |
|
535 | acornOptions.onToken = function(token) {
|
536 | if (extra.tokens) {
|
537 | translator.onToken(token, extra);
|
538 | }
|
539 | if (token.type !== tt.eof) {
|
540 | lastToken = token;
|
541 | }
|
542 | };
|
543 |
|
544 | if (extra.attachComment || extra.comment) {
|
545 | acornOptions.onComment = function() {
|
546 | var comment = convertAcornCommentToEsprimaComment.apply(this, arguments);
|
547 | extra.comments.push(comment);
|
548 |
|
549 | if (extra.attachComment) {
|
550 | commentAttachment.addComment(comment);
|
551 | }
|
552 | };
|
553 | }
|
554 |
|
555 | if (extra.range) {
|
556 | acornOptions.ranges = true;
|
557 | }
|
558 |
|
559 | if (extra.loc) {
|
560 | acornOptions.locations = true;
|
561 | }
|
562 |
|
563 | if (extra.ecmaFeatures.jsx) {
|
564 |
|
565 | acornOptions.plugins = {
|
566 | jsx: true,
|
567 | espree: true
|
568 | };
|
569 | }
|
570 | }
|
571 |
|
572 | program = acorn.parse(code, acornOptions);
|
573 | program.sourceType = extra.isModule ? "module" : "script";
|
574 |
|
575 | if (extra.comment || extra.attachComment) {
|
576 | program.comments = extra.comments;
|
577 | }
|
578 |
|
579 | if (extra.tokens) {
|
580 | program.tokens = extra.tokens;
|
581 | }
|
582 |
|
583 | |
584 |
|
585 |
|
586 |
|
587 |
|
588 |
|
589 |
|
590 | if (program.range) {
|
591 | program.range[0] = program.body.length ? program.body[0].range[0] : program.range[0];
|
592 | program.range[1] = lastToken ? lastToken.range[1] : program.range[1];
|
593 | }
|
594 |
|
595 | if (program.loc) {
|
596 | program.loc.start = program.body.length ? program.body[0].loc.start : program.loc.start;
|
597 | program.loc.end = lastToken ? lastToken.loc.end : program.loc.end;
|
598 | }
|
599 |
|
600 | return program;
|
601 | }
|
602 |
|
603 |
|
604 |
|
605 |
|
606 |
|
607 | exports.version = require("./package.json").version;
|
608 |
|
609 | exports.tokenize = tokenize;
|
610 |
|
611 | exports.parse = parse;
|
612 |
|
613 |
|
614 |
|
615 | exports.Syntax = (function() {
|
616 | var name, types = {};
|
617 |
|
618 | if (typeof Object.create === "function") {
|
619 | types = Object.create(null);
|
620 | }
|
621 |
|
622 | for (name in astNodeTypes) {
|
623 | if (astNodeTypes.hasOwnProperty(name)) {
|
624 | types[name] = astNodeTypes[name];
|
625 | }
|
626 | }
|
627 |
|
628 | if (typeof Object.freeze === "function") {
|
629 | Object.freeze(types);
|
630 | }
|
631 |
|
632 | return types;
|
633 | }());
|
634 |
|
635 |
|
636 | exports.VisitorKeys = (function() {
|
637 | var visitorKeys = require("./lib/visitor-keys");
|
638 | var name,
|
639 | keys = {};
|
640 |
|
641 | if (typeof Object.create === "function") {
|
642 | keys = Object.create(null);
|
643 | }
|
644 |
|
645 | for (name in visitorKeys) {
|
646 | if (visitorKeys.hasOwnProperty(name)) {
|
647 | keys[name] = visitorKeys[name];
|
648 | }
|
649 | }
|
650 |
|
651 | if (typeof Object.freeze === "function") {
|
652 | Object.freeze(keys);
|
653 | }
|
654 |
|
655 | return keys;
|
656 | }());
|