escodegen 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rspec', '~> 2.11.0'
7
+ gem 'rr', '~> 1.0.4'
8
+ end
@@ -0,0 +1,3 @@
1
+ === 1.0.0
2
+
3
+ * Birthday!
data/LICENSE ADDED
@@ -0,0 +1,177 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
data/NOTICE ADDED
@@ -0,0 +1,22 @@
1
+ This license came with the escodegen JavaScript library, available at:
2
+ https://github.com/Constellation/escodegen
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright
8
+ notice, this list of conditions and the following disclaimer.
9
+ * Redistributions in binary form must reproduce the above copyright
10
+ notice, this list of conditions and the following disclaimer in the
11
+ documentation and/or other materials provided with the distribution.
12
+
13
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
17
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
20
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,71 @@
1
+ ## escodegen-rb [![Build Status](https://secure.travis-ci.org/camertron/escodegen-rb.png?branch=master)](http://travis-ci.org/camertron/escodegen-rb)
2
+
3
+ escodegen (https://github.com/Constellation/escodegen) is an ECMAScript code generator that converts an abstract syntax tree (such as one created by Esprima) into ECMAScript. This library wraps the escodegen JavaScript library for easy use within Ruby.
4
+
5
+ ### Installation
6
+
7
+ Install the gem as you would any other:
8
+
9
+ ```
10
+ gem install escodegen
11
+ ```
12
+
13
+ Then, require it in your project:
14
+
15
+ ```ruby
16
+ require 'escodegen'
17
+ ```
18
+
19
+ ### Generating JavaScript from an AST
20
+
21
+ Let's say you have an AST for the expression `7 + 8;`:
22
+
23
+ ```ruby
24
+ ast = {
25
+ :type => "Program",
26
+ :body => [{
27
+ :type => "ExpressionStatement",
28
+ :expression => {
29
+ :left => {
30
+ :type => "Literal",
31
+ :value => 7
32
+ },
33
+ :type => "BinaryExpression",
34
+ :right => {
35
+ :type => "Literal",
36
+ :value => 8
37
+ },
38
+ :operator => "+"
39
+ }
40
+ }]
41
+ }
42
+ ```
43
+
44
+ Here's how to use escodegen to generate the JavaScript from the AST:
45
+
46
+ ```ruby
47
+ generator = Escodegen::Generator.new
48
+ generator.generate(ast)
49
+ ```
50
+
51
+ This should output `7 + 8;`.
52
+
53
+ ## Requirements
54
+
55
+ No external requirements.
56
+
57
+ ## Running Tests
58
+
59
+ Run `bundle exec rake` or `bundle exec rspec`.
60
+
61
+ ## Authors
62
+
63
+ * Cameron C. Dutro: https://github.com/camertron
64
+ * The escodegen team including Yusuke Suzuki: https://github.com/Constellation
65
+
66
+ ## Links
67
+ * escodegen [https://github.com/Constellation/escodegen](https://github.com/Constellation/escodegen)
68
+
69
+ ## License
70
+
71
+ Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'rubygems' unless ENV['NO_RUBYGEMS']
4
+
5
+ require 'bundler'
6
+ require 'rspec/core/rake_task'
7
+ require 'rubygems/package_task'
8
+
9
+ require './lib/escodegen'
10
+
11
+ Bundler::GemHelper.install_tasks
12
+
13
+ task :default => :spec
14
+
15
+ desc 'Run specs'
16
+ RSpec::Core::RakeTask.new do |t|
17
+ t.pattern = './spec/**/*_spec.rb'
18
+ end
@@ -0,0 +1,25 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), 'lib')
2
+ require 'escodegen/version'
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "escodegen"
6
+ s.version = Escodegen::VERSION
7
+ s.authors = ["Cameron Dutro", "Yusuke Suzuki"]
8
+ s.email = ["cdutro@twitter.com", "@Constellation"]
9
+ s.homepage = "https://github.com/Constellation/escodegen"
10
+
11
+ s.description = s.summary = "Ruby wrapper around the escodegen JavaScript generator that generates ECMA script from an abstract syntax tree."
12
+
13
+ s.platform = Gem::Platform::RUBY
14
+ s.has_rdoc = true
15
+
16
+ s.add_dependency 'therubyracer', '~> 0.9.10'
17
+ s.add_dependency 'commonjs', '~> 0.2.6'
18
+
19
+ s.add_development_dependency 'rake'
20
+ s.add_development_dependency 'rspec', '~> 2.11.0'
21
+ s.add_development_dependency 'rr', '~> 1.0.4'
22
+
23
+ s.require_path = 'lib'
24
+ s.files = Dir["{lib,spec,vendor}/**/*", "Gemfile", "History.txt", "LICENSE", "NOTICE", "README.md", "Rakefile", "escodegen.gemspec"]
25
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'v8'
4
+ require 'commonjs'
5
+
6
+ require 'escodegen/generator'
7
+
8
+ module Escodegen
9
+ def self.load_path
10
+ @load_path ||= File.expand_path(File.join(File.dirname(__FILE__), "../vendor"))
11
+ end
12
+
13
+ def self.new_environment
14
+ context = V8::Context.new
15
+ env = CommonJS::Environment.new(context, :path => Escodegen.load_path)
16
+ env.require("escodegen")
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ # encoding: UTF-8
2
+
3
+ module Escodegen
4
+ class Generator
5
+ def initialize
6
+ @escodegen = Escodegen.new_environment
7
+ end
8
+
9
+ def generate(ast, options = {})
10
+ @escodegen.generate(ast, options)
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: UTF-8
2
+
3
+ module Escodegen
4
+ VERSION = "1.0.0"
5
+ end
@@ -0,0 +1,11 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.join(File.dirname(__FILE__), "spec_helper")
4
+
5
+ describe Escodegen do
6
+ describe "#load_path" do
7
+ it "escodegen.js should exist at the load path" do
8
+ File.should exist(File.join(Escodegen.load_path, "escodegen.js"))
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.join(File.dirname(__FILE__), "spec_helper")
4
+
5
+ EXPRESSION = "7 + 8;"
6
+ AST = {
7
+ :type => "Program",
8
+ :body => [{
9
+ :type => "ExpressionStatement",
10
+ :expression => {
11
+ :left => {
12
+ :type => "Literal",
13
+ :value => 7
14
+ },
15
+ :type => "BinaryExpression",
16
+ :right => {
17
+ :type => "Literal",
18
+ :value => 8
19
+ },
20
+ :operator => "+"
21
+ }
22
+ }]
23
+ }
24
+
25
+ describe Escodegen::Generator do
26
+ describe "#generate" do
27
+ it "should parse a basic js AST" do
28
+ result = Escodegen::Generator.new.generate(AST)
29
+ result.should == EXPRESSION
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,8 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'rspec'
4
+ require 'escodegen'
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :rr
8
+ end
@@ -0,0 +1,2211 @@
1
+ /*
2
+ Copyright (C) 2012 Michael Ficarra <escodegen.copyright@michael.ficarra.me>
3
+ Copyright (C) 2012 Robert Gust-Bardon <donate@robert.gust-bardon.org>
4
+ Copyright (C) 2012 John Freeman <jfreeman08@gmail.com>
5
+ Copyright (C) 2012 Ariya Hidayat <ariya.hidayat@gmail.com>
6
+ Copyright (C) 2012 Mathias Bynens <mathias@qiwi.be>
7
+ Copyright (C) 2012 Joost-Wim Boekesteijn <joost-wim@boekesteijn.nl>
8
+ Copyright (C) 2012 Kris Kowal <kris.kowal@cixar.com>
9
+ Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
10
+ Copyright (C) 2012 Arpad Borsos <arpad.borsos@googlemail.com>
11
+ Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
12
+
13
+ Redistribution and use in source and binary forms, with or without
14
+ modification, are permitted provided that the following conditions are met:
15
+
16
+ * Redistributions of source code must retain the above copyright
17
+ notice, this list of conditions and the following disclaimer.
18
+ * Redistributions in binary form must reproduce the above copyright
19
+ notice, this list of conditions and the following disclaimer in the
20
+ documentation and/or other materials provided with the distribution.
21
+
22
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25
+ ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
26
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
27
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
+ */
33
+
34
+ /*jslint bitwise:true */
35
+ /*global escodegen:true, exports:true, generateStatement:true, generateExpression:true, generateFunctionBody:true, process:true, require:true, define:true*/
36
+
37
+ (function (factory, global) {
38
+ 'use strict';
39
+
40
+ // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js,
41
+ // and plain browser loading,
42
+ if (typeof define === 'function' && define.amd) {
43
+ define(['exports'], function (exports) {
44
+ factory(exports, global);
45
+ });
46
+ } else if (typeof exports !== 'undefined') {
47
+ factory(exports, global);
48
+ } else {
49
+ factory((global.escodegen = {}), global);
50
+ }
51
+ }(function (exports, global) {
52
+ 'use strict';
53
+
54
+ var Syntax,
55
+ Precedence,
56
+ BinaryPrecedence,
57
+ Regex,
58
+ VisitorKeys,
59
+ VisitorOption,
60
+ SourceNode,
61
+ isArray,
62
+ base,
63
+ indent,
64
+ json,
65
+ renumber,
66
+ hexadecimal,
67
+ quotes,
68
+ escapeless,
69
+ newline,
70
+ space,
71
+ parentheses,
72
+ semicolons,
73
+ safeConcatenation,
74
+ directive,
75
+ extra,
76
+ parse,
77
+ sourceMap;
78
+
79
+ Syntax = {
80
+ AssignmentExpression: 'AssignmentExpression',
81
+ ArrayExpression: 'ArrayExpression',
82
+ ArrayPattern: 'ArrayPattern',
83
+ BlockStatement: 'BlockStatement',
84
+ BinaryExpression: 'BinaryExpression',
85
+ BreakStatement: 'BreakStatement',
86
+ CallExpression: 'CallExpression',
87
+ CatchClause: 'CatchClause',
88
+ ComprehensionBlock: 'ComprehensionBlock',
89
+ ComprehensionExpression: 'ComprehensionExpression',
90
+ ConditionalExpression: 'ConditionalExpression',
91
+ ContinueStatement: 'ContinueStatement',
92
+ DirectiveStatement: 'DirectiveStatement',
93
+ DoWhileStatement: 'DoWhileStatement',
94
+ DebuggerStatement: 'DebuggerStatement',
95
+ EmptyStatement: 'EmptyStatement',
96
+ ExpressionStatement: 'ExpressionStatement',
97
+ ForStatement: 'ForStatement',
98
+ ForInStatement: 'ForInStatement',
99
+ FunctionDeclaration: 'FunctionDeclaration',
100
+ FunctionExpression: 'FunctionExpression',
101
+ Identifier: 'Identifier',
102
+ IfStatement: 'IfStatement',
103
+ Literal: 'Literal',
104
+ LabeledStatement: 'LabeledStatement',
105
+ LogicalExpression: 'LogicalExpression',
106
+ MemberExpression: 'MemberExpression',
107
+ NewExpression: 'NewExpression',
108
+ ObjectExpression: 'ObjectExpression',
109
+ ObjectPattern: 'ObjectPattern',
110
+ Program: 'Program',
111
+ Property: 'Property',
112
+ ReturnStatement: 'ReturnStatement',
113
+ SequenceExpression: 'SequenceExpression',
114
+ SwitchStatement: 'SwitchStatement',
115
+ SwitchCase: 'SwitchCase',
116
+ ThisExpression: 'ThisExpression',
117
+ ThrowStatement: 'ThrowStatement',
118
+ TryStatement: 'TryStatement',
119
+ UnaryExpression: 'UnaryExpression',
120
+ UpdateExpression: 'UpdateExpression',
121
+ VariableDeclaration: 'VariableDeclaration',
122
+ VariableDeclarator: 'VariableDeclarator',
123
+ WhileStatement: 'WhileStatement',
124
+ WithStatement: 'WithStatement',
125
+ YieldExpression: 'YieldExpression',
126
+
127
+ };
128
+
129
+ Precedence = {
130
+ Sequence: 0,
131
+ Assignment: 1,
132
+ Conditional: 2,
133
+ LogicalOR: 3,
134
+ LogicalAND: 4,
135
+ BitwiseOR: 5,
136
+ BitwiseXOR: 6,
137
+ BitwiseAND: 7,
138
+ Equality: 8,
139
+ Relational: 9,
140
+ BitwiseSHIFT: 10,
141
+ Additive: 11,
142
+ Multiplicative: 12,
143
+ Unary: 13,
144
+ Postfix: 14,
145
+ Call: 15,
146
+ New: 16,
147
+ Member: 17,
148
+ Primary: 18
149
+ };
150
+
151
+ BinaryPrecedence = {
152
+ '||': Precedence.LogicalOR,
153
+ '&&': Precedence.LogicalAND,
154
+ '|': Precedence.BitwiseOR,
155
+ '^': Precedence.BitwiseXOR,
156
+ '&': Precedence.BitwiseAND,
157
+ '==': Precedence.Equality,
158
+ '!=': Precedence.Equality,
159
+ '===': Precedence.Equality,
160
+ '!==': Precedence.Equality,
161
+ 'is': Precedence.Equality,
162
+ 'isnt': Precedence.Equality,
163
+ '<': Precedence.Relational,
164
+ '>': Precedence.Relational,
165
+ '<=': Precedence.Relational,
166
+ '>=': Precedence.Relational,
167
+ 'in': Precedence.Relational,
168
+ 'instanceof': Precedence.Relational,
169
+ '<<': Precedence.BitwiseSHIFT,
170
+ '>>': Precedence.BitwiseSHIFT,
171
+ '>>>': Precedence.BitwiseSHIFT,
172
+ '+': Precedence.Additive,
173
+ '-': Precedence.Additive,
174
+ '*': Precedence.Multiplicative,
175
+ '%': Precedence.Multiplicative,
176
+ '/': Precedence.Multiplicative
177
+ };
178
+
179
+ Regex = {
180
+ NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
181
+ };
182
+
183
+ function getDefaultOptions() {
184
+ // default options
185
+ return {
186
+ indent: null,
187
+ base: null,
188
+ parse: null,
189
+ comment: false,
190
+ format: {
191
+ indent: {
192
+ style: ' ',
193
+ base: 0,
194
+ adjustMultilineComment: false
195
+ },
196
+ json: false,
197
+ renumber: false,
198
+ hexadecimal: false,
199
+ quotes: 'single',
200
+ escapeless: false,
201
+ compact: false,
202
+ parentheses: true,
203
+ semicolons: true,
204
+ safeConcatenation: false
205
+ },
206
+ moz: {
207
+ starlessGenerator: false,
208
+ parenthesizedComprehensionBlock: false
209
+ },
210
+ sourceMap: null,
211
+ sourceMapWithCode: false,
212
+ directive: false,
213
+ verbatim: null
214
+ };
215
+ }
216
+
217
+ function stringToArray(str) {
218
+ var length = str.length,
219
+ result = [],
220
+ i;
221
+ for (i = 0; i < length; i += 1) {
222
+ result[i] = str.charAt(i);
223
+ }
224
+ return result;
225
+ }
226
+
227
+ function stringRepeat(str, num) {
228
+ var result = '';
229
+
230
+ for (num |= 0; num > 0; num >>>= 1, str += str) {
231
+ if (num & 1) {
232
+ result += str;
233
+ }
234
+ }
235
+
236
+ return result;
237
+ }
238
+
239
+ isArray = Array.isArray;
240
+ if (!isArray) {
241
+ isArray = function isArray(array) {
242
+ return Object.prototype.toString.call(array) === '[object Array]';
243
+ };
244
+ }
245
+
246
+ // Fallback for the non SourceMap environment
247
+ function SourceNodeMock(line, column, filename, chunk) {
248
+ var result = [];
249
+
250
+ function flatten(input) {
251
+ var i, iz;
252
+ if (isArray(input)) {
253
+ for (i = 0, iz = input.length; i < iz; ++i) {
254
+ flatten(input[i]);
255
+ }
256
+ } else if (input instanceof SourceNodeMock) {
257
+ result.push(input);
258
+ } else if (typeof input === 'string' && input) {
259
+ result.push(input);
260
+ }
261
+ }
262
+
263
+ flatten(chunk);
264
+ this.children = result;
265
+ }
266
+
267
+ SourceNodeMock.prototype.toString = function toString() {
268
+ var res = '', i, iz, node;
269
+ for (i = 0, iz = this.children.length; i < iz; ++i) {
270
+ node = this.children[i];
271
+ if (node instanceof SourceNodeMock) {
272
+ res += node.toString();
273
+ } else {
274
+ res += node;
275
+ }
276
+ }
277
+ return res;
278
+ };
279
+
280
+ SourceNodeMock.prototype.replaceRight = function replaceRight(pattern, replacement) {
281
+ var last = this.children[this.children.length - 1];
282
+ if (last instanceof SourceNodeMock) {
283
+ last.replaceRight(pattern, replacement);
284
+ } else if (typeof last === 'string') {
285
+ this.children[this.children.length - 1] = last.replace(pattern, replacement);
286
+ } else {
287
+ this.children.push(''.replace(pattern, replacement));
288
+ }
289
+ return this;
290
+ };
291
+
292
+ SourceNodeMock.prototype.join = function join(sep) {
293
+ var i, iz, result;
294
+ result = [];
295
+ iz = this.children.length;
296
+ if (iz > 0) {
297
+ for (i = 0, iz -= 1; i < iz; ++i) {
298
+ result.push(this.children[i], sep);
299
+ }
300
+ result.push(this.children[iz]);
301
+ this.children = result;
302
+ }
303
+ return this;
304
+ };
305
+
306
+ function endsWithLineTerminator(str) {
307
+ var ch = str.charAt(str.length - 1);
308
+ return ch === '\r' || ch === '\n';
309
+ }
310
+
311
+ function shallowCopy(obj) {
312
+ var ret = {}, key;
313
+ for (key in obj) {
314
+ if (obj.hasOwnProperty(key)) {
315
+ ret[key] = obj[key];
316
+ }
317
+ }
318
+ return ret;
319
+ }
320
+
321
+ function deepCopy(obj) {
322
+ var ret = {}, key, val;
323
+ for (key in obj) {
324
+ if (obj.hasOwnProperty(key)) {
325
+ val = obj[key];
326
+ if (typeof val === 'object' && val !== null) {
327
+ ret[key] = deepCopy(val);
328
+ } else {
329
+ ret[key] = val;
330
+ }
331
+ }
332
+ }
333
+ return ret;
334
+ }
335
+
336
+ function updateDeeply(target, override) {
337
+ var key, val;
338
+
339
+ function isHashObject(target) {
340
+ return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
341
+ }
342
+
343
+ for (key in override) {
344
+ if (override.hasOwnProperty(key)) {
345
+ val = override[key];
346
+ if (isHashObject(val)) {
347
+ if (isHashObject(target[key])) {
348
+ updateDeeply(target[key], val);
349
+ } else {
350
+ target[key] = updateDeeply({}, val);
351
+ }
352
+ } else {
353
+ target[key] = val;
354
+ }
355
+ }
356
+ }
357
+ return target;
358
+ }
359
+
360
+ function generateNumber(value) {
361
+ var result, point, temp, exponent, pos;
362
+
363
+ if (value !== value) {
364
+ throw new Error('Numeric literal whose value is NaN');
365
+ }
366
+ if (value < 0 || (value === 0 && 1 / value < 0)) {
367
+ throw new Error('Numeric literal whose value is negative');
368
+ }
369
+
370
+ if (value === 1 / 0) {
371
+ return json ? 'null' : renumber ? '1e400' : '1e+400';
372
+ }
373
+
374
+ result = '' + value;
375
+ if (!renumber || result.length < 3) {
376
+ return result;
377
+ }
378
+
379
+ point = result.indexOf('.');
380
+ if (!json && result.charAt(0) === '0' && point === 1) {
381
+ point = 0;
382
+ result = result.slice(1);
383
+ }
384
+ temp = result;
385
+ result = result.replace('e+', 'e');
386
+ exponent = 0;
387
+ if ((pos = temp.indexOf('e')) > 0) {
388
+ exponent = +temp.slice(pos + 1);
389
+ temp = temp.slice(0, pos);
390
+ }
391
+ if (point >= 0) {
392
+ exponent -= temp.length - point - 1;
393
+ temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
394
+ }
395
+ pos = 0;
396
+ while (temp.charAt(temp.length + pos - 1) === '0') {
397
+ pos -= 1;
398
+ }
399
+ if (pos !== 0) {
400
+ exponent -= pos;
401
+ temp = temp.slice(0, pos);
402
+ }
403
+ if (exponent !== 0) {
404
+ temp += 'e' + exponent;
405
+ }
406
+ if ((temp.length < result.length ||
407
+ (hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length)) &&
408
+ +temp === value) {
409
+ result = temp;
410
+ }
411
+
412
+ return result;
413
+ }
414
+
415
+ function escapeAllowedCharacter(ch, next) {
416
+ var code = ch.charCodeAt(0), hex = code.toString(16), result = '\\';
417
+
418
+ switch (ch) {
419
+ case '\b':
420
+ result += 'b';
421
+ break;
422
+ case '\f':
423
+ result += 'f';
424
+ break;
425
+ case '\t':
426
+ result += 't';
427
+ break;
428
+ default:
429
+ if (json || code > 0xff) {
430
+ result += 'u' + '0000'.slice(hex.length) + hex;
431
+ } else if (ch === '\u0000' && '0123456789'.indexOf(next) < 0) {
432
+ result += '0';
433
+ } else if (ch === '\v') {
434
+ result += 'v';
435
+ } else {
436
+ result += 'x' + '00'.slice(hex.length) + hex;
437
+ }
438
+ break;
439
+ }
440
+
441
+ return result;
442
+ }
443
+
444
+ function escapeDisallowedCharacter(ch) {
445
+ var result = '\\';
446
+ switch (ch) {
447
+ case '\\':
448
+ result += '\\';
449
+ break;
450
+ case '\n':
451
+ result += 'n';
452
+ break;
453
+ case '\r':
454
+ result += 'r';
455
+ break;
456
+ case '\u2028':
457
+ result += 'u2028';
458
+ break;
459
+ case '\u2029':
460
+ result += 'u2029';
461
+ break;
462
+ default:
463
+ throw new Error('Incorrectly classified character');
464
+ }
465
+
466
+ return result;
467
+ }
468
+
469
+ function escapeDirective(str) {
470
+ var i, iz, ch, single, buf, quote;
471
+
472
+ buf = str;
473
+ if (typeof buf[0] === 'undefined') {
474
+ buf = stringToArray(buf);
475
+ }
476
+
477
+ quote = quotes === 'double' ? '"' : '\'';
478
+ for (i = 0, iz = buf.length; i < iz; i += 1) {
479
+ ch = buf[i];
480
+ if (ch === '\'') {
481
+ quote = '"';
482
+ break;
483
+ } else if (ch === '"') {
484
+ quote = '\'';
485
+ break;
486
+ } else if (ch === '\\') {
487
+ i += 1;
488
+ }
489
+ }
490
+
491
+ return quote + str + quote;
492
+ }
493
+
494
+ function escapeString(str) {
495
+ var result = '', i, len, ch, next, singleQuotes = 0, doubleQuotes = 0, single;
496
+
497
+ if (typeof str[0] === 'undefined') {
498
+ str = stringToArray(str);
499
+ }
500
+
501
+ for (i = 0, len = str.length; i < len; i += 1) {
502
+ ch = str[i];
503
+ if (ch === '\'') {
504
+ singleQuotes += 1;
505
+ } else if (ch === '"') {
506
+ doubleQuotes += 1;
507
+ } else if (ch === '/' && json) {
508
+ result += '\\';
509
+ } else if ('\\\n\r\u2028\u2029'.indexOf(ch) >= 0) {
510
+ result += escapeDisallowedCharacter(ch);
511
+ continue;
512
+ } else if ((json && ch < ' ') || !(json || escapeless || (ch >= ' ' && ch <= '~'))) {
513
+ result += escapeAllowedCharacter(ch, str[i + 1]);
514
+ continue;
515
+ }
516
+ result += ch;
517
+ }
518
+
519
+ single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
520
+ str = result;
521
+ result = single ? '\'' : '"';
522
+
523
+ if (typeof str[0] === 'undefined') {
524
+ str = stringToArray(str);
525
+ }
526
+
527
+ for (i = 0, len = str.length; i < len; i += 1) {
528
+ ch = str[i];
529
+ if ((ch === '\'' && single) || (ch === '"' && !single)) {
530
+ result += '\\';
531
+ }
532
+ result += ch;
533
+ }
534
+
535
+ return result + (single ? '\'' : '"');
536
+ }
537
+
538
+ function isWhiteSpace(ch) {
539
+ return '\t\v\f \xa0'.indexOf(ch) >= 0 || (ch.charCodeAt(0) >= 0x1680 && '\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u202f\u205f\u3000\ufeff'.indexOf(ch) >= 0);
540
+ }
541
+
542
+ function isLineTerminator(ch) {
543
+ return '\n\r\u2028\u2029'.indexOf(ch) >= 0;
544
+ }
545
+
546
+ function isIdentifierPart(ch) {
547
+ return (ch === '$') || (ch === '_') || (ch === '\\') ||
548
+ (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
549
+ ((ch >= '0') && (ch <= '9')) ||
550
+ ((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
551
+ }
552
+
553
+ function toSourceNode(generated, node) {
554
+ if (node == null) {
555
+ if (generated instanceof SourceNode) {
556
+ return generated;
557
+ } else {
558
+ node = {};
559
+ }
560
+ }
561
+ if (node.loc == null) {
562
+ return new SourceNode(null, null, sourceMap, generated);
563
+ }
564
+ return new SourceNode(node.loc.start.line, node.loc.start.column, (sourceMap === true ? node.loc.source || null : sourceMap), generated);
565
+ }
566
+
567
+ function join(left, right) {
568
+ var leftSource = toSourceNode(left).toString(),
569
+ rightSource = toSourceNode(right).toString(),
570
+ leftChar = leftSource.charAt(leftSource.length - 1),
571
+ rightChar = rightSource.charAt(0);
572
+
573
+ if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
574
+ return [left, ' ', right];
575
+ } else if (isWhiteSpace(leftChar) || isLineTerminator(leftChar) || isWhiteSpace(rightChar) || isLineTerminator(rightChar)) {
576
+ return [left, right];
577
+ }
578
+ return [left, space, right];
579
+ }
580
+
581
+ function addIndent(stmt) {
582
+ return [base, stmt];
583
+ }
584
+
585
+ function withIndent(fn) {
586
+ var previousBase, result;
587
+ previousBase = base;
588
+ base += indent;
589
+ result = fn.call(this, base);
590
+ base = previousBase;
591
+ return result;
592
+ }
593
+
594
+ function calculateSpaces(str) {
595
+ var i;
596
+ for (i = str.length - 1; i >= 0; i -= 1) {
597
+ if (isLineTerminator(str.charAt(i))) {
598
+ break;
599
+ }
600
+ }
601
+ return (str.length - 1) - i;
602
+ }
603
+
604
+ function adjustMultilineComment(value, specialBase) {
605
+ var array, i, len, line, j, ch, spaces, previousBase;
606
+
607
+ array = value.split(/\r\n|[\r\n]/);
608
+ spaces = Number.MAX_VALUE;
609
+
610
+ // first line doesn't have indentation
611
+ for (i = 1, len = array.length; i < len; i += 1) {
612
+ line = array[i];
613
+ j = 0;
614
+ while (j < line.length && isWhiteSpace(line[j])) {
615
+ j += 1;
616
+ }
617
+ if (spaces > j) {
618
+ spaces = j;
619
+ }
620
+ }
621
+
622
+ if (typeof specialBase !== 'undefined') {
623
+ // pattern like
624
+ // {
625
+ // var t = 20; /*
626
+ // * this is comment
627
+ // */
628
+ // }
629
+ previousBase = base;
630
+ if (array[1][spaces] === '*') {
631
+ specialBase += ' ';
632
+ }
633
+ base = specialBase;
634
+ } else {
635
+ if (spaces & 1) {
636
+ // /*
637
+ // *
638
+ // */
639
+ // If spaces are odd number, above pattern is considered.
640
+ // We waste 1 space.
641
+ spaces -= 1;
642
+ }
643
+ previousBase = base;
644
+ }
645
+
646
+ for (i = 1, len = array.length; i < len; i += 1) {
647
+ array[i] = toSourceNode(addIndent(array[i].slice(spaces))).join('');
648
+ }
649
+
650
+ base = previousBase;
651
+
652
+ return array.join('\n');
653
+ }
654
+
655
+ function generateComment(comment, specialBase) {
656
+ if (comment.type === 'Line') {
657
+ if (endsWithLineTerminator(comment.value)) {
658
+ return '//' + comment.value;
659
+ } else {
660
+ // Always use LineTerminator
661
+ return '//' + comment.value + '\n';
662
+ }
663
+ }
664
+ if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
665
+ return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
666
+ }
667
+ return '/*' + comment.value + '*/';
668
+ }
669
+
670
+ function addCommentsToStatement(stmt, result) {
671
+ var i, len, comment, save, node, tailingToStatement, specialBase, fragment;
672
+
673
+ if (stmt.leadingComments && stmt.leadingComments.length > 0) {
674
+ save = result;
675
+
676
+ comment = stmt.leadingComments[0];
677
+ result = [];
678
+ if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
679
+ result.push('\n');
680
+ }
681
+ result.push(generateComment(comment));
682
+ if (!endsWithLineTerminator(toSourceNode(result).toString())) {
683
+ result.push('\n');
684
+ }
685
+
686
+ for (i = 1, len = stmt.leadingComments.length; i < len; i += 1) {
687
+ comment = stmt.leadingComments[i];
688
+ fragment = [generateComment(comment)];
689
+ if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
690
+ fragment.push('\n');
691
+ }
692
+ result.push(addIndent(fragment));
693
+ }
694
+
695
+ result.push(addIndent(save));
696
+ }
697
+
698
+ if (stmt.trailingComments) {
699
+ tailingToStatement = !endsWithLineTerminator(toSourceNode(result).toString());
700
+ specialBase = stringRepeat(' ', calculateSpaces(toSourceNode([base, result, indent]).toString()));
701
+ for (i = 0, len = stmt.trailingComments.length; i < len; i += 1) {
702
+ comment = stmt.trailingComments[i];
703
+ if (tailingToStatement) {
704
+ // We assume target like following script
705
+ //
706
+ // var t = 20; /**
707
+ // * This is comment of t
708
+ // */
709
+ if (i === 0) {
710
+ // first case
711
+ result.push(indent);
712
+ } else {
713
+ result.push(specialBase);
714
+ }
715
+ result.push(generateComment(comment, specialBase));
716
+ } else {
717
+ result.push(addIndent(generateComment(comment)));
718
+ }
719
+ if (i !== len - 1 && !endsWithLineTerminator(toSourceNode(result).toString())) {
720
+ result.push('\n');
721
+ }
722
+ }
723
+ }
724
+
725
+ return result;
726
+ }
727
+
728
+ function parenthesize(text, current, should) {
729
+ if (current < should) {
730
+ return ['(', text, ')'];
731
+ }
732
+ return text;
733
+ }
734
+
735
+ function maybeBlock(stmt, semicolonOptional, functionBody) {
736
+ var result, noLeadingComment;
737
+
738
+ noLeadingComment = !extra.comment || !stmt.leadingComments;
739
+
740
+ if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
741
+ return [space, generateStatement(stmt, { functionBody: functionBody })];
742
+ }
743
+
744
+ if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {
745
+ return ';';
746
+ }
747
+
748
+ withIndent(function () {
749
+ result = [newline, addIndent(generateStatement(stmt, { semicolonOptional: semicolonOptional, functionBody: functionBody }))];
750
+ });
751
+
752
+ return result;
753
+ }
754
+
755
+ function maybeBlockSuffix(stmt, result) {
756
+ var ends = endsWithLineTerminator(toSourceNode(result).toString());
757
+ if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) {
758
+ return [result, space];
759
+ }
760
+ if (ends) {
761
+ return [result, base];
762
+ }
763
+ return [result, newline, base];
764
+ }
765
+
766
+ function generateVerbatim(expr, option) {
767
+ var i, result;
768
+ result = expr[extra.verbatim].split(/\r\n|\n/);
769
+ for (i = 1; i < result.length; i++) {
770
+ result[i] = newline + base + result[i];
771
+ }
772
+
773
+ result = parenthesize(result, Precedence.Sequence, option.precedence);
774
+ return toSourceNode(result, expr);
775
+ }
776
+
777
+ function generateFunctionBody(node) {
778
+ var result, i, len, expr;
779
+ result = ['('];
780
+ for (i = 0, len = node.params.length; i < len; i += 1) {
781
+ result.push(node.params[i].name);
782
+ if (i + 1 < len) {
783
+ result.push(',' + space);
784
+ }
785
+ }
786
+ result.push(')');
787
+
788
+ if (node.expression) {
789
+ result.push(space);
790
+ expr = generateExpression(node.body, {
791
+ precedence: Precedence.Assignment,
792
+ allowIn: true,
793
+ allowCall: true
794
+ });
795
+ if (expr.toString().charAt(0) === '{') {
796
+ expr = ['(', expr, ')'];
797
+ }
798
+ result.push(expr);
799
+ } else {
800
+ result.push(maybeBlock(node.body, false, true));
801
+ }
802
+ return result;
803
+ }
804
+
805
+ function generateExpression(expr, option) {
806
+ var result, precedence, currentPrecedence, i, len, raw, fragment, multiline, leftChar, leftSource, rightChar, rightSource, allowIn, allowCall, allowUnparenthesizedNew, property, key, value;
807
+
808
+ precedence = option.precedence;
809
+ allowIn = option.allowIn;
810
+ allowCall = option.allowCall;
811
+
812
+ if (extra.verbatim && expr.hasOwnProperty(extra.verbatim)) {
813
+ return generateVerbatim(expr, option);
814
+ }
815
+
816
+ switch (expr.type) {
817
+ case Syntax.SequenceExpression:
818
+ result = [];
819
+ allowIn |= (Precedence.Sequence < precedence);
820
+ for (i = 0, len = expr.expressions.length; i < len; i += 1) {
821
+ result.push(generateExpression(expr.expressions[i], {
822
+ precedence: Precedence.Assignment,
823
+ allowIn: allowIn,
824
+ allowCall: true
825
+ }));
826
+ if (i + 1 < len) {
827
+ result.push(',' + space);
828
+ }
829
+ }
830
+ result = parenthesize(result, Precedence.Sequence, precedence);
831
+ break;
832
+
833
+ case Syntax.AssignmentExpression:
834
+ allowIn |= (Precedence.Assignment < precedence);
835
+ result = parenthesize(
836
+ [
837
+ generateExpression(expr.left, {
838
+ precedence: Precedence.Call,
839
+ allowIn: allowIn,
840
+ allowCall: true
841
+ }),
842
+ space + expr.operator + space,
843
+ generateExpression(expr.right, {
844
+ precedence: Precedence.Assignment,
845
+ allowIn: allowIn,
846
+ allowCall: true
847
+ })
848
+ ],
849
+ Precedence.Assignment,
850
+ precedence
851
+ );
852
+ break;
853
+
854
+ case Syntax.ConditionalExpression:
855
+ allowIn |= (Precedence.Conditional < precedence);
856
+ result = parenthesize(
857
+ [
858
+ generateExpression(expr.test, {
859
+ precedence: Precedence.LogicalOR,
860
+ allowIn: allowIn,
861
+ allowCall: true
862
+ }),
863
+ space + '?' + space,
864
+ generateExpression(expr.consequent, {
865
+ precedence: Precedence.Assignment,
866
+ allowIn: allowIn,
867
+ allowCall: true
868
+ }),
869
+ space + ':' + space,
870
+ generateExpression(expr.alternate, {
871
+ precedence: Precedence.Assignment,
872
+ allowIn: allowIn,
873
+ allowCall: true
874
+ })
875
+ ],
876
+ Precedence.Conditional,
877
+ precedence
878
+ );
879
+ break;
880
+
881
+ case Syntax.LogicalExpression:
882
+ case Syntax.BinaryExpression:
883
+ currentPrecedence = BinaryPrecedence[expr.operator];
884
+
885
+ allowIn |= (currentPrecedence < precedence);
886
+
887
+ result = join(
888
+ generateExpression(expr.left, {
889
+ precedence: currentPrecedence,
890
+ allowIn: allowIn,
891
+ allowCall: true
892
+ }),
893
+ expr.operator
894
+ );
895
+
896
+ fragment = generateExpression(expr.right, {
897
+ precedence: currentPrecedence + 1,
898
+ allowIn: allowIn,
899
+ allowCall: true
900
+ });
901
+
902
+ if (expr.operator === '/' && fragment.toString().charAt(0) === '/') {
903
+ // If '/' concats with '/', it is interpreted as comment start
904
+ result.push(' ', fragment);
905
+ } else {
906
+ result = join(result, fragment);
907
+ }
908
+
909
+ if (expr.operator === 'in' && !allowIn) {
910
+ result = ['(', result, ')'];
911
+ } else {
912
+ result = parenthesize(result, currentPrecedence, precedence);
913
+ }
914
+
915
+ break;
916
+
917
+ case Syntax.CallExpression:
918
+ result = [generateExpression(expr.callee, {
919
+ precedence: Precedence.Call,
920
+ allowIn: true,
921
+ allowCall: true,
922
+ allowUnparenthesizedNew: false
923
+ })];
924
+
925
+ result.push('(');
926
+ for (i = 0, len = expr['arguments'].length; i < len; i += 1) {
927
+ result.push(generateExpression(expr['arguments'][i], {
928
+ precedence: Precedence.Assignment,
929
+ allowIn: true,
930
+ allowCall: true
931
+ }));
932
+ if (i + 1 < len) {
933
+ result.push(',' + space);
934
+ }
935
+ }
936
+ result.push(')');
937
+
938
+ if (!allowCall) {
939
+ result = ['(', result, ')'];
940
+ } else {
941
+ result = parenthesize(result, Precedence.Call, precedence);
942
+ }
943
+ break;
944
+
945
+ case Syntax.NewExpression:
946
+ len = expr['arguments'].length;
947
+ allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew;
948
+
949
+ result = join(
950
+ 'new',
951
+ generateExpression(expr.callee, {
952
+ precedence: Precedence.New,
953
+ allowIn: true,
954
+ allowCall: false,
955
+ allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0
956
+ })
957
+ );
958
+
959
+ if (!allowUnparenthesizedNew || parentheses || len > 0) {
960
+ result.push('(');
961
+ for (i = 0; i < len; i += 1) {
962
+ result.push(generateExpression(expr['arguments'][i], {
963
+ precedence: Precedence.Assignment,
964
+ allowIn: true,
965
+ allowCall: true
966
+ }));
967
+ if (i + 1 < len) {
968
+ result.push(',' + space);
969
+ }
970
+ }
971
+ result.push(')');
972
+ }
973
+
974
+ result = parenthesize(result, Precedence.New, precedence);
975
+ break;
976
+
977
+ case Syntax.MemberExpression:
978
+ result = [generateExpression(expr.object, {
979
+ precedence: Precedence.Call,
980
+ allowIn: true,
981
+ allowCall: allowCall,
982
+ allowUnparenthesizedNew: false
983
+ })];
984
+
985
+ if (expr.computed) {
986
+ result.push('[', generateExpression(expr.property, {
987
+ precedence: Precedence.Sequence,
988
+ allowIn: true,
989
+ allowCall: allowCall
990
+ }), ']');
991
+ } else {
992
+ if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
993
+ if (result.indexOf('.') < 0) {
994
+ if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) {
995
+ result.push('.');
996
+ }
997
+ }
998
+ }
999
+ result.push('.' + expr.property.name);
1000
+ }
1001
+
1002
+ result = parenthesize(result, Precedence.Member, precedence);
1003
+ break;
1004
+
1005
+ case Syntax.UnaryExpression:
1006
+ fragment = generateExpression(expr.argument, {
1007
+ precedence: Precedence.Unary,
1008
+ allowIn: true,
1009
+ allowCall: true
1010
+ });
1011
+
1012
+ if (space === '') {
1013
+ result = join(expr.operator, fragment);
1014
+ } else {
1015
+ result = [expr.operator];
1016
+ if (expr.operator.length > 2) {
1017
+ // delete, void, typeof
1018
+ // get `typeof []`, not `typeof[]`
1019
+ result = join(result, fragment);
1020
+ } else {
1021
+ // Prevent inserting spaces between operator and argument if it is unnecessary
1022
+ // like, `!cond`
1023
+ leftSource = toSourceNode(result).toString();
1024
+ leftChar = leftSource.charAt(leftSource.length - 1);
1025
+ rightChar = fragment.toString().charAt(0);
1026
+
1027
+ if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
1028
+ result.push(' ', fragment);
1029
+ } else {
1030
+ result.push(fragment);
1031
+ }
1032
+ }
1033
+ }
1034
+ result = parenthesize(result, Precedence.Unary, precedence);
1035
+ break;
1036
+
1037
+ case Syntax.YieldExpression:
1038
+ if (expr.delegate) {
1039
+ result = 'yield*';
1040
+ } else {
1041
+ result = 'yield';
1042
+ }
1043
+ if (expr.argument) {
1044
+ result = join(
1045
+ result,
1046
+ generateExpression(expr.argument, {
1047
+ precedence: Precedence.Assignment,
1048
+ allowIn: true,
1049
+ allowCall: true
1050
+ })
1051
+ );
1052
+ }
1053
+ break;
1054
+
1055
+ case Syntax.UpdateExpression:
1056
+ if (expr.prefix) {
1057
+ result = parenthesize(
1058
+ [
1059
+ expr.operator,
1060
+ generateExpression(expr.argument, {
1061
+ precedence: Precedence.Unary,
1062
+ allowIn: true,
1063
+ allowCall: true
1064
+ })
1065
+ ],
1066
+ Precedence.Unary,
1067
+ precedence
1068
+ );
1069
+ } else {
1070
+ result = parenthesize(
1071
+ [
1072
+ generateExpression(expr.argument, {
1073
+ precedence: Precedence.Postfix,
1074
+ allowIn: true,
1075
+ allowCall: true
1076
+ }),
1077
+ expr.operator
1078
+ ],
1079
+ Precedence.Postfix,
1080
+ precedence
1081
+ );
1082
+ }
1083
+ break;
1084
+
1085
+ case Syntax.FunctionExpression:
1086
+ result = 'function';
1087
+ if (expr.id) {
1088
+ result += ' ' + expr.id.name;
1089
+ } else {
1090
+ result += space;
1091
+ }
1092
+
1093
+ result = [result, generateFunctionBody(expr)];
1094
+ break;
1095
+
1096
+ case Syntax.ArrayPattern:
1097
+ case Syntax.ArrayExpression:
1098
+ if (!expr.elements.length) {
1099
+ result = '[]';
1100
+ break;
1101
+ }
1102
+ multiline = expr.elements.length > 1;
1103
+ result = ['[', multiline ? newline : ''];
1104
+ withIndent(function (indent) {
1105
+ for (i = 0, len = expr.elements.length; i < len; i += 1) {
1106
+ if (!expr.elements[i]) {
1107
+ if (multiline) {
1108
+ result.push(indent);
1109
+ }
1110
+ if (i + 1 === len) {
1111
+ result.push(',');
1112
+ }
1113
+ } else {
1114
+ result.push(multiline ? indent : '', generateExpression(expr.elements[i], {
1115
+ precedence: Precedence.Assignment,
1116
+ allowIn: true,
1117
+ allowCall: true
1118
+ }));
1119
+ }
1120
+ if (i + 1 < len) {
1121
+ result.push(',' + (multiline ? newline : space));
1122
+ }
1123
+ }
1124
+ });
1125
+ if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
1126
+ result.push(newline);
1127
+ }
1128
+ result.push(multiline ? base : '', ']');
1129
+ break;
1130
+
1131
+ case Syntax.Property:
1132
+ if (expr.kind === 'get' || expr.kind === 'set') {
1133
+ result = [
1134
+ expr.kind + ' ',
1135
+ generateExpression(expr.key, {
1136
+ precedence: Precedence.Sequence,
1137
+ allowIn: true,
1138
+ allowCall: true
1139
+ }),
1140
+ generateFunctionBody(expr.value)
1141
+ ];
1142
+ } else {
1143
+ if (expr.shorthand) {
1144
+ result = generateExpression(expr.key, {
1145
+ precedence: Precedence.Sequence,
1146
+ allowIn: true,
1147
+ allowCall: true
1148
+ });
1149
+ } else if (expr.method) {
1150
+ result = [];
1151
+ if (expr.value.generator) {
1152
+ result.push('*');
1153
+ }
1154
+ result.push(generateExpression(expr.key, {
1155
+ precedence: Precedence.Sequence,
1156
+ allowIn: true,
1157
+ allowCall: true
1158
+ }), generateFunctionBody(expr.value));
1159
+ } else {
1160
+ result = [
1161
+ generateExpression(expr.key, {
1162
+ precedence: Precedence.Sequence,
1163
+ allowIn: true,
1164
+ allowCall: true
1165
+ }),
1166
+ ':' + space,
1167
+ generateExpression(expr.value, {
1168
+ precedence: Precedence.Assignment,
1169
+ allowIn: true,
1170
+ allowCall: true
1171
+ })
1172
+ ];
1173
+ }
1174
+ }
1175
+ break;
1176
+
1177
+ case Syntax.ObjectExpression:
1178
+ if (!expr.properties.length) {
1179
+ result = '{}';
1180
+ break;
1181
+ }
1182
+ multiline = expr.properties.length > 1;
1183
+ result = ['{', multiline ? newline : ''];
1184
+
1185
+ withIndent(function (indent) {
1186
+ for (i = 0, len = expr.properties.length; i < len; i += 1) {
1187
+ result.push(multiline ? indent : '', generateExpression(expr.properties[i], {
1188
+ precedence: Precedence.Sequence,
1189
+ allowIn: true,
1190
+ allowCall: true
1191
+ }));
1192
+ if (i + 1 < len) {
1193
+ result.push(',' + (multiline ? newline : space));
1194
+ }
1195
+ }
1196
+ });
1197
+
1198
+ if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
1199
+ result.push(newline);
1200
+ }
1201
+ result.push(multiline ? base : '', '}');
1202
+ break;
1203
+
1204
+ case Syntax.ObjectPattern:
1205
+ // A little different from ObjectExpression
1206
+ // And for future difference, we split this.
1207
+ if (!expr.properties.length) {
1208
+ result = '{}';
1209
+ break;
1210
+ }
1211
+ multiline = false;
1212
+ if (expr.properties.length > 1) {
1213
+ for (i = 0, len = expr.properties.length; i < len; i += 1) {
1214
+ property = expr.properties[i];
1215
+ if (!property.shorthand) {
1216
+ multiline = true;
1217
+ break;
1218
+ }
1219
+ }
1220
+ }
1221
+ result = ['{', multiline ? newline : ''];
1222
+
1223
+ withIndent(function (indent) {
1224
+ for (i = 0, len = expr.properties.length; i < len; i += 1) {
1225
+ result.push(multiline ? indent : '', generateExpression(expr.properties[i], {
1226
+ precedence: Precedence.Sequence,
1227
+ allowIn: true,
1228
+ allowCall: true
1229
+ }));
1230
+ if (i + 1 < len) {
1231
+ result.push(',' + (multiline ? newline : space));
1232
+ }
1233
+ }
1234
+ });
1235
+
1236
+ if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
1237
+ result.push(newline);
1238
+ }
1239
+ result.push(multiline ? base : '', '}');
1240
+ break;
1241
+
1242
+ case Syntax.ThisExpression:
1243
+ result = 'this';
1244
+ break;
1245
+
1246
+ case Syntax.Identifier:
1247
+ result = expr.name;
1248
+ break;
1249
+
1250
+ case Syntax.Literal:
1251
+ if (expr.hasOwnProperty('raw') && parse) {
1252
+ try {
1253
+ raw = parse(expr.raw).body[0].expression;
1254
+ if (raw.type === Syntax.Literal) {
1255
+ if (raw.value === expr.value) {
1256
+ result = expr.raw;
1257
+ break;
1258
+ }
1259
+ }
1260
+ } catch (e) {
1261
+ // not use raw property
1262
+ }
1263
+ }
1264
+
1265
+ if (expr.value === null) {
1266
+ result = 'null';
1267
+ break;
1268
+ }
1269
+
1270
+ if (typeof expr.value === 'string') {
1271
+ result = escapeString(expr.value);
1272
+ break;
1273
+ }
1274
+
1275
+ if (typeof expr.value === 'number') {
1276
+ result = generateNumber(expr.value);
1277
+ break;
1278
+ }
1279
+
1280
+ result = expr.value.toString();
1281
+ break;
1282
+
1283
+ case Syntax.ComprehensionExpression:
1284
+ result = [
1285
+ '[',
1286
+ generateExpression(expr.body, {
1287
+ precedence: Precedence.Assignment,
1288
+ allowIn: true,
1289
+ allowCall: true
1290
+ })
1291
+ ];
1292
+
1293
+ if (expr.blocks) {
1294
+ for (i = 0, len = expr.blocks.length; i < len; i += 1) {
1295
+ fragment = generateExpression(expr.blocks[i], {
1296
+ precedence: Precedence.Sequence,
1297
+ allowIn: true,
1298
+ allowCall: true
1299
+ });
1300
+ result = join(result, fragment);
1301
+ }
1302
+ }
1303
+
1304
+ if (expr.filter) {
1305
+ result = join(result, 'if' + space);
1306
+ fragment = generateExpression(expr.filter, {
1307
+ precedence: Precedence.Sequence,
1308
+ allowIn: true,
1309
+ allowCall: true
1310
+ });
1311
+ if (extra.moz.parenthesizedComprehensionBlock) {
1312
+ result = join(result, [ '(', fragment, ')' ]);
1313
+ } else {
1314
+ result = join(result, fragment);
1315
+ }
1316
+ }
1317
+ result.push(']');
1318
+ break;
1319
+
1320
+ case Syntax.ComprehensionBlock:
1321
+ if (expr.left.type === Syntax.VariableDeclaration) {
1322
+ fragment = [
1323
+ expr.left.kind + ' ',
1324
+ generateStatement(expr.left.declarations[0], {
1325
+ allowIn: false
1326
+ })
1327
+ ];
1328
+ } else {
1329
+ fragment = generateExpression(expr.left, {
1330
+ precedence: Precedence.Call,
1331
+ allowIn: true,
1332
+ allowCall: true
1333
+ });
1334
+ }
1335
+
1336
+ fragment = join(fragment, expr.of ? 'of' : 'in');
1337
+ fragment = join(fragment, generateExpression(expr.right, {
1338
+ precedence: Precedence.Sequence,
1339
+ allowIn: true,
1340
+ allowCall: true
1341
+ }));
1342
+
1343
+ if (extra.moz.parenthesizedComprehensionBlock) {
1344
+ result = [ 'for' + space + '(', fragment, ')' ];
1345
+ } else {
1346
+ result = join('for' + space, fragment);
1347
+ }
1348
+ break;
1349
+
1350
+ default:
1351
+ throw new Error('Unknown expression type: ' + expr.type);
1352
+ }
1353
+
1354
+ return toSourceNode(result, expr);
1355
+ }
1356
+
1357
+ function generateStatement(stmt, option) {
1358
+ var i, len, result, node, allowIn, functionBody, directiveContext, fragment, semicolon;
1359
+
1360
+ allowIn = true;
1361
+ semicolon = ';';
1362
+ functionBody = false;
1363
+ directiveContext = false;
1364
+ if (option) {
1365
+ allowIn = option.allowIn === undefined || option.allowIn;
1366
+ if (!semicolons && option.semicolonOptional === true) {
1367
+ semicolon = '';
1368
+ }
1369
+ functionBody = option.functionBody;
1370
+ directiveContext = option.directiveContext;
1371
+ }
1372
+
1373
+ switch (stmt.type) {
1374
+ case Syntax.BlockStatement:
1375
+ result = ['{', newline];
1376
+
1377
+ withIndent(function () {
1378
+ for (i = 0, len = stmt.body.length; i < len; i += 1) {
1379
+ fragment = addIndent(generateStatement(stmt.body[i], {
1380
+ semicolonOptional: i === len - 1,
1381
+ directiveContext: functionBody
1382
+ }));
1383
+ result.push(fragment);
1384
+ if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
1385
+ result.push(newline);
1386
+ }
1387
+ }
1388
+ });
1389
+
1390
+ result.push(addIndent('}'));
1391
+ break;
1392
+
1393
+ case Syntax.BreakStatement:
1394
+ if (stmt.label) {
1395
+ result = 'break ' + stmt.label.name + semicolon;
1396
+ } else {
1397
+ result = 'break' + semicolon;
1398
+ }
1399
+ break;
1400
+
1401
+ case Syntax.ContinueStatement:
1402
+ if (stmt.label) {
1403
+ result = 'continue ' + stmt.label.name + semicolon;
1404
+ } else {
1405
+ result = 'continue' + semicolon;
1406
+ }
1407
+ break;
1408
+
1409
+ case Syntax.DirectiveStatement:
1410
+ if (stmt.raw) {
1411
+ result = stmt.raw + semicolon;
1412
+ } else {
1413
+ result = escapeDirective(stmt.directive) + semicolon;
1414
+ }
1415
+ break;
1416
+
1417
+ case Syntax.DoWhileStatement:
1418
+ // Because `do 42 while (cond)` is Syntax Error. We need semicolon.
1419
+ result = join('do', maybeBlock(stmt.body));
1420
+ result = maybeBlockSuffix(stmt.body, result);
1421
+ result = join(result, [
1422
+ 'while' + space + '(',
1423
+ generateExpression(stmt.test, {
1424
+ precedence: Precedence.Sequence,
1425
+ allowIn: true,
1426
+ allowCall: true
1427
+ }),
1428
+ ')' + semicolon
1429
+ ]);
1430
+ break;
1431
+
1432
+ case Syntax.CatchClause:
1433
+ withIndent(function () {
1434
+ result = [
1435
+ 'catch' + space + '(',
1436
+ generateExpression(stmt.param, {
1437
+ precedence: Precedence.Sequence,
1438
+ allowIn: true,
1439
+ allowCall: true
1440
+ }),
1441
+ ')'
1442
+ ];
1443
+ });
1444
+ result.push(maybeBlock(stmt.body));
1445
+ break;
1446
+
1447
+ case Syntax.DebuggerStatement:
1448
+ result = 'debugger' + semicolon;
1449
+ break;
1450
+
1451
+ case Syntax.EmptyStatement:
1452
+ result = ';';
1453
+ break;
1454
+
1455
+ case Syntax.ExpressionStatement:
1456
+ result = [generateExpression(stmt.expression, {
1457
+ precedence: Precedence.Sequence,
1458
+ allowIn: true,
1459
+ allowCall: true
1460
+ })];
1461
+ // 12.4 '{', 'function' is not allowed in this position.
1462
+ // wrap expression with parentheses
1463
+ if (result.toString().charAt(0) === '{' || (result.toString().slice(0, 8) === 'function' && " (".indexOf(result.toString().charAt(8)) >= 0) || (directive && directiveContext && stmt.expression.type === Syntax.Literal && typeof stmt.expression.value === 'string')) {
1464
+ result = ['(', result, ')' + semicolon];
1465
+ } else {
1466
+ result.push(semicolon);
1467
+ }
1468
+ break;
1469
+
1470
+ case Syntax.VariableDeclarator:
1471
+ if (stmt.init) {
1472
+ result = [
1473
+ generateExpression(stmt.id, {
1474
+ precedence: Precedence.Assignment,
1475
+ allowIn: allowIn,
1476
+ allowCall: true
1477
+ }) + space + '=' + space,
1478
+ generateExpression(stmt.init, {
1479
+ precedence: Precedence.Assignment,
1480
+ allowIn: allowIn,
1481
+ allowCall: true
1482
+ })
1483
+ ];
1484
+ } else {
1485
+ result = stmt.id.name;
1486
+ }
1487
+ break;
1488
+
1489
+ case Syntax.VariableDeclaration:
1490
+ result = [stmt.kind];
1491
+ // special path for
1492
+ // var x = function () {
1493
+ // };
1494
+ if (stmt.declarations.length === 1 && stmt.declarations[0].init &&
1495
+ stmt.declarations[0].init.type === Syntax.FunctionExpression) {
1496
+ result.push(' ', generateStatement(stmt.declarations[0], {
1497
+ allowIn: allowIn
1498
+ }));
1499
+ } else {
1500
+ // VariableDeclarator is typed as Statement,
1501
+ // but joined with comma (not LineTerminator).
1502
+ // So if comment is attached to target node, we should specialize.
1503
+ withIndent(function () {
1504
+ node = stmt.declarations[0];
1505
+ if (extra.comment && node.leadingComments) {
1506
+ result.push('\n', addIndent(generateStatement(node, {
1507
+ allowIn: allowIn
1508
+ })));
1509
+ } else {
1510
+ result.push(' ', generateStatement(node, {
1511
+ allowIn: allowIn
1512
+ }));
1513
+ }
1514
+
1515
+ for (i = 1, len = stmt.declarations.length; i < len; i += 1) {
1516
+ node = stmt.declarations[i];
1517
+ if (extra.comment && node.leadingComments) {
1518
+ result.push(',' + newline, addIndent(generateStatement(node, {
1519
+ allowIn: allowIn
1520
+ })));
1521
+ } else {
1522
+ result.push(',' + space, generateStatement(node, {
1523
+ allowIn: allowIn
1524
+ }));
1525
+ }
1526
+ }
1527
+ });
1528
+ }
1529
+ result.push(semicolon);
1530
+ break;
1531
+
1532
+ case Syntax.ThrowStatement:
1533
+ result = [join(
1534
+ 'throw',
1535
+ generateExpression(stmt.argument, {
1536
+ precedence: Precedence.Sequence,
1537
+ allowIn: true,
1538
+ allowCall: true
1539
+ })
1540
+ ), semicolon];
1541
+ break;
1542
+
1543
+ case Syntax.TryStatement:
1544
+ result = ['try', maybeBlock(stmt.block)];
1545
+ result = maybeBlockSuffix(stmt.block, result);
1546
+ for (i = 0, len = stmt.handlers.length; i < len; i += 1) {
1547
+ result = join(result, generateStatement(stmt.handlers[i]));
1548
+ if (stmt.finalizer || i + 1 !== len) {
1549
+ result = maybeBlockSuffix(stmt.handlers[i].body, result);
1550
+ }
1551
+ }
1552
+ if (stmt.finalizer) {
1553
+ result = join(result, ['finally', maybeBlock(stmt.finalizer)]);
1554
+ }
1555
+ break;
1556
+
1557
+ case Syntax.SwitchStatement:
1558
+ withIndent(function () {
1559
+ result = [
1560
+ 'switch' + space + '(',
1561
+ generateExpression(stmt.discriminant, {
1562
+ precedence: Precedence.Sequence,
1563
+ allowIn: true,
1564
+ allowCall: true
1565
+ }),
1566
+ ')' + space + '{' + newline
1567
+ ];
1568
+ });
1569
+ if (stmt.cases) {
1570
+ for (i = 0, len = stmt.cases.length; i < len; i += 1) {
1571
+ fragment = addIndent(generateStatement(stmt.cases[i], {semicolonOptional: i === len - 1}));
1572
+ result.push(fragment);
1573
+ if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
1574
+ result.push(newline);
1575
+ }
1576
+ }
1577
+ }
1578
+ result.push(addIndent('}'));
1579
+ break;
1580
+
1581
+ case Syntax.SwitchCase:
1582
+ withIndent(function () {
1583
+ if (stmt.test) {
1584
+ result = [
1585
+ join('case', generateExpression(stmt.test, {
1586
+ precedence: Precedence.Sequence,
1587
+ allowIn: true,
1588
+ allowCall: true
1589
+ })),
1590
+ ':'
1591
+ ];
1592
+ } else {
1593
+ result = ['default:'];
1594
+ }
1595
+
1596
+ i = 0;
1597
+ len = stmt.consequent.length;
1598
+ if (len && stmt.consequent[0].type === Syntax.BlockStatement) {
1599
+ fragment = maybeBlock(stmt.consequent[0]);
1600
+ result.push(fragment);
1601
+ i = 1;
1602
+ }
1603
+
1604
+ if (i !== len && !endsWithLineTerminator(toSourceNode(result).toString())) {
1605
+ result.push(newline);
1606
+ }
1607
+
1608
+ for (; i < len; i += 1) {
1609
+ fragment = addIndent(generateStatement(stmt.consequent[i], {semicolonOptional: i === len - 1 && semicolon === ''}));
1610
+ result.push(fragment);
1611
+ if (i + 1 !== len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
1612
+ result.push(newline);
1613
+ }
1614
+ }
1615
+ });
1616
+ break;
1617
+
1618
+ case Syntax.IfStatement:
1619
+ withIndent(function () {
1620
+ result = [
1621
+ 'if' + space + '(',
1622
+ generateExpression(stmt.test, {
1623
+ precedence: Precedence.Sequence,
1624
+ allowIn: true,
1625
+ allowCall: true
1626
+ }),
1627
+ ')'
1628
+ ];
1629
+ });
1630
+ if (stmt.alternate) {
1631
+ result.push(maybeBlock(stmt.consequent));
1632
+ result = maybeBlockSuffix(stmt.consequent, result);
1633
+ if (stmt.alternate.type === Syntax.IfStatement) {
1634
+ result = join(result, ['else ', generateStatement(stmt.alternate, {semicolonOptional: semicolon === ''})]);
1635
+ } else {
1636
+ result = join(result, join('else', maybeBlock(stmt.alternate, semicolon === '')));
1637
+ }
1638
+ } else {
1639
+ result.push(maybeBlock(stmt.consequent, semicolon === ''));
1640
+ }
1641
+ break;
1642
+
1643
+ case Syntax.ForStatement:
1644
+ withIndent(function () {
1645
+ result = ['for' + space + '('];
1646
+ if (stmt.init) {
1647
+ if (stmt.init.type === Syntax.VariableDeclaration) {
1648
+ result.push(generateStatement(stmt.init, {allowIn: false}));
1649
+ } else {
1650
+ result.push(generateExpression(stmt.init, {
1651
+ precedence: Precedence.Sequence,
1652
+ allowIn: false,
1653
+ allowCall: true
1654
+ }), ';');
1655
+ }
1656
+ } else {
1657
+ result.push(';');
1658
+ }
1659
+
1660
+ if (stmt.test) {
1661
+ result.push(space, generateExpression(stmt.test, {
1662
+ precedence: Precedence.Sequence,
1663
+ allowIn: true,
1664
+ allowCall: true
1665
+ }), ';');
1666
+ } else {
1667
+ result.push(';');
1668
+ }
1669
+
1670
+ if (stmt.update) {
1671
+ result.push(space, generateExpression(stmt.update, {
1672
+ precedence: Precedence.Sequence,
1673
+ allowIn: true,
1674
+ allowCall: true
1675
+ }), ')');
1676
+ } else {
1677
+ result.push(')');
1678
+ }
1679
+ });
1680
+
1681
+ result.push(maybeBlock(stmt.body, semicolon === ''));
1682
+ break;
1683
+
1684
+ case Syntax.ForInStatement:
1685
+ result = ['for' + space + '('];
1686
+ withIndent(function () {
1687
+ if (stmt.left.type === Syntax.VariableDeclaration) {
1688
+ withIndent(function () {
1689
+ result.push(stmt.left.kind + ' ', generateStatement(stmt.left.declarations[0], {
1690
+ allowIn: false
1691
+ }));
1692
+ });
1693
+ } else {
1694
+ result.push(generateExpression(stmt.left, {
1695
+ precedence: Precedence.Call,
1696
+ allowIn: true,
1697
+ allowCall: true
1698
+ }));
1699
+ }
1700
+
1701
+ result = join(result, 'in');
1702
+ result = [join(
1703
+ result,
1704
+ generateExpression(stmt.right, {
1705
+ precedence: Precedence.Sequence,
1706
+ allowIn: true,
1707
+ allowCall: true
1708
+ })
1709
+ ), ')'];
1710
+ });
1711
+ result.push(maybeBlock(stmt.body, semicolon === ''));
1712
+ break;
1713
+
1714
+ case Syntax.LabeledStatement:
1715
+ result = [stmt.label.name + ':', maybeBlock(stmt.body, semicolon === '')];
1716
+ break;
1717
+
1718
+ case Syntax.Program:
1719
+ len = stmt.body.length;
1720
+ result = [safeConcatenation && len > 0 ? '\n' : ''];
1721
+ for (i = 0; i < len; i += 1) {
1722
+ fragment = addIndent(
1723
+ generateStatement(stmt.body[i], {
1724
+ semicolonOptional: !safeConcatenation && i === len - 1,
1725
+ directiveContext: true
1726
+ })
1727
+ );
1728
+ result.push(fragment);
1729
+ if (i + 1 < len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
1730
+ result.push(newline);
1731
+ }
1732
+ }
1733
+ break;
1734
+
1735
+ case Syntax.FunctionDeclaration:
1736
+ result = [(stmt.generator && !extra.moz.starlessGenerator ? 'function* ' : 'function ') + stmt.id.name, generateFunctionBody(stmt)];
1737
+ break;
1738
+
1739
+ case Syntax.ReturnStatement:
1740
+ if (stmt.argument) {
1741
+ result = [join(
1742
+ 'return',
1743
+ generateExpression(stmt.argument, {
1744
+ precedence: Precedence.Sequence,
1745
+ allowIn: true,
1746
+ allowCall: true
1747
+ })
1748
+ ), semicolon];
1749
+ } else {
1750
+ result = ['return' + semicolon];
1751
+ }
1752
+ break;
1753
+
1754
+ case Syntax.WhileStatement:
1755
+ withIndent(function () {
1756
+ result = [
1757
+ 'while' + space + '(',
1758
+ generateExpression(stmt.test, {
1759
+ precedence: Precedence.Sequence,
1760
+ allowIn: true,
1761
+ allowCall: true
1762
+ }),
1763
+ ')'
1764
+ ];
1765
+ });
1766
+ result.push(maybeBlock(stmt.body, semicolon === ''));
1767
+ break;
1768
+
1769
+ case Syntax.WithStatement:
1770
+ withIndent(function () {
1771
+ result = [
1772
+ 'with' + space + '(',
1773
+ generateExpression(stmt.object, {
1774
+ precedence: Precedence.Sequence,
1775
+ allowIn: true,
1776
+ allowCall: true
1777
+ }),
1778
+ ')'
1779
+ ];
1780
+ });
1781
+ result.push(maybeBlock(stmt.body, semicolon === ''));
1782
+ break;
1783
+
1784
+ default:
1785
+ throw new Error('Unknown statement type: ' + stmt.type);
1786
+ }
1787
+
1788
+ // Attach comments
1789
+
1790
+ if (extra.comment) {
1791
+ result = addCommentsToStatement(stmt, result);
1792
+ }
1793
+
1794
+ fragment = toSourceNode(result).toString();
1795
+ if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') {
1796
+ result = toSourceNode(result).replaceRight(/\s+$/, '');
1797
+ }
1798
+
1799
+ return toSourceNode(result, stmt);
1800
+ }
1801
+
1802
+ function generate(node, options) {
1803
+ var defaultOptions = getDefaultOptions(), result, pair;
1804
+
1805
+ if (options != null) {
1806
+ // Obsolete options
1807
+ //
1808
+ // `options.indent`
1809
+ // `options.base`
1810
+ //
1811
+ // Instead of them, we can use `option.format.indent`.
1812
+ if (typeof options.indent === 'string') {
1813
+ defaultOptions.format.indent.style = options.indent;
1814
+ }
1815
+ if (typeof options.base === 'number') {
1816
+ defaultOptions.format.indent.base = options.base;
1817
+ }
1818
+ options = updateDeeply(defaultOptions, options);
1819
+ indent = options.format.indent.style;
1820
+ if (typeof options.base === 'string') {
1821
+ base = options.base;
1822
+ } else {
1823
+ base = stringRepeat(indent, options.format.indent.base);
1824
+ }
1825
+ } else {
1826
+ options = defaultOptions;
1827
+ indent = options.format.indent.style;
1828
+ base = stringRepeat(indent, options.format.indent.base);
1829
+ }
1830
+ json = options.format.json;
1831
+ renumber = options.format.renumber;
1832
+ hexadecimal = json ? false : options.format.hexadecimal;
1833
+ quotes = json ? 'double' : options.format.quotes;
1834
+ escapeless = options.format.escapeless;
1835
+ if (options.format.compact) {
1836
+ newline = space = indent = base = '';
1837
+ } else {
1838
+ newline = '\n';
1839
+ space = ' ';
1840
+ }
1841
+ parentheses = options.format.parentheses;
1842
+ semicolons = options.format.semicolons;
1843
+ safeConcatenation = options.format.safeConcatenation;
1844
+ directive = options.directive;
1845
+ parse = json ? null : options.parse;
1846
+ sourceMap = options.sourceMap;
1847
+ extra = options;
1848
+
1849
+ if (sourceMap) {
1850
+ if (typeof process !== 'undefined') {
1851
+ // We assume environment is node.js
1852
+ SourceNode = require('source-map').SourceNode;
1853
+ } else {
1854
+ SourceNode = global.sourceMap.SourceNode;
1855
+ }
1856
+ } else {
1857
+ SourceNode = SourceNodeMock;
1858
+ }
1859
+
1860
+ switch (node.type) {
1861
+ case Syntax.BlockStatement:
1862
+ case Syntax.BreakStatement:
1863
+ case Syntax.CatchClause:
1864
+ case Syntax.ContinueStatement:
1865
+ case Syntax.DirectiveStatement:
1866
+ case Syntax.DoWhileStatement:
1867
+ case Syntax.DebuggerStatement:
1868
+ case Syntax.EmptyStatement:
1869
+ case Syntax.ExpressionStatement:
1870
+ case Syntax.ForStatement:
1871
+ case Syntax.ForInStatement:
1872
+ case Syntax.FunctionDeclaration:
1873
+ case Syntax.IfStatement:
1874
+ case Syntax.LabeledStatement:
1875
+ case Syntax.Program:
1876
+ case Syntax.ReturnStatement:
1877
+ case Syntax.SwitchStatement:
1878
+ case Syntax.SwitchCase:
1879
+ case Syntax.ThrowStatement:
1880
+ case Syntax.TryStatement:
1881
+ case Syntax.VariableDeclaration:
1882
+ case Syntax.VariableDeclarator:
1883
+ case Syntax.WhileStatement:
1884
+ case Syntax.WithStatement:
1885
+ result = generateStatement(node);
1886
+ break;
1887
+
1888
+ case Syntax.AssignmentExpression:
1889
+ case Syntax.ArrayExpression:
1890
+ case Syntax.ArrayPattern:
1891
+ case Syntax.BinaryExpression:
1892
+ case Syntax.CallExpression:
1893
+ case Syntax.ConditionalExpression:
1894
+ case Syntax.FunctionExpression:
1895
+ case Syntax.Identifier:
1896
+ case Syntax.Literal:
1897
+ case Syntax.LogicalExpression:
1898
+ case Syntax.MemberExpression:
1899
+ case Syntax.NewExpression:
1900
+ case Syntax.ObjectExpression:
1901
+ case Syntax.ObjectPattern:
1902
+ case Syntax.Property:
1903
+ case Syntax.SequenceExpression:
1904
+ case Syntax.ThisExpression:
1905
+ case Syntax.UnaryExpression:
1906
+ case Syntax.UpdateExpression:
1907
+ case Syntax.YieldExpression:
1908
+
1909
+ result = generateExpression(node, {
1910
+ precedence: Precedence.Sequence,
1911
+ allowIn: true,
1912
+ allowCall: true
1913
+ });
1914
+ break;
1915
+
1916
+ default:
1917
+ throw new Error('Unknown node type: ' + node.type);
1918
+ }
1919
+
1920
+ if (!sourceMap) {
1921
+ return result.toString();
1922
+ }
1923
+
1924
+ pair = result.toStringWithSourceMap({file: options.sourceMap});
1925
+
1926
+ if (options.sourceMapWithCode) {
1927
+ return pair;
1928
+ }
1929
+ return pair.map.toString();
1930
+ }
1931
+
1932
+ // simple visitor implementation
1933
+
1934
+ VisitorKeys = {
1935
+ AssignmentExpression: ['left', 'right'],
1936
+ ArrayExpression: ['elements'],
1937
+ ArrayPattern: ['elements'],
1938
+ BlockStatement: ['body'],
1939
+ BinaryExpression: ['left', 'right'],
1940
+ BreakStatement: ['label'],
1941
+ CallExpression: ['callee', 'arguments'],
1942
+ CatchClause: ['param', 'body'],
1943
+ ConditionalExpression: ['test', 'consequent', 'alternate'],
1944
+ ContinueStatement: ['label'],
1945
+ DirectiveStatement: [],
1946
+ DoWhileStatement: ['body', 'test'],
1947
+ DebuggerStatement: [],
1948
+ EmptyStatement: [],
1949
+ ExpressionStatement: ['expression'],
1950
+ ForStatement: ['init', 'test', 'update', 'body'],
1951
+ ForInStatement: ['left', 'right', 'body'],
1952
+ FunctionDeclaration: ['id', 'params', 'body'],
1953
+ FunctionExpression: ['id', 'params', 'body'],
1954
+ Identifier: [],
1955
+ IfStatement: ['test', 'consequent', 'alternate'],
1956
+ Literal: [],
1957
+ LabeledStatement: ['label', 'body'],
1958
+ LogicalExpression: ['left', 'right'],
1959
+ MemberExpression: ['object', 'property'],
1960
+ NewExpression: ['callee', 'arguments'],
1961
+ ObjectExpression: ['properties'],
1962
+ ObjectPattern: ['properties'],
1963
+ Program: ['body'],
1964
+ Property: ['key', 'value'],
1965
+ ReturnStatement: ['argument'],
1966
+ SequenceExpression: ['expressions'],
1967
+ SwitchStatement: ['discriminant', 'cases'],
1968
+ SwitchCase: ['test', 'consequent'],
1969
+ ThisExpression: [],
1970
+ ThrowStatement: ['argument'],
1971
+ TryStatement: ['block', 'handlers', 'finalizer'],
1972
+ UnaryExpression: ['argument'],
1973
+ UpdateExpression: ['argument'],
1974
+ VariableDeclaration: ['declarations'],
1975
+ VariableDeclarator: ['id', 'init'],
1976
+ WhileStatement: ['test', 'body'],
1977
+ WithStatement: ['object', 'body'],
1978
+ YieldExpression: ['argument']
1979
+ };
1980
+
1981
+ VisitorOption = {
1982
+ Break: 1,
1983
+ Skip: 2
1984
+ };
1985
+
1986
+ function traverse(top, visitor) {
1987
+ var worklist, leavelist, node, ret, current, current2, candidates, candidate, marker = {};
1988
+
1989
+ worklist = [ top ];
1990
+ leavelist = [ null ];
1991
+
1992
+ while (worklist.length) {
1993
+ node = worklist.pop();
1994
+
1995
+ if (node === marker) {
1996
+ node = leavelist.pop();
1997
+ if (visitor.leave) {
1998
+ ret = visitor.leave(node, leavelist[leavelist.length - 1]);
1999
+ } else {
2000
+ ret = undefined;
2001
+ }
2002
+ if (ret === VisitorOption.Break) {
2003
+ return;
2004
+ }
2005
+ } else if (node) {
2006
+ if (visitor.enter) {
2007
+ ret = visitor.enter(node, leavelist[leavelist.length - 1]);
2008
+ } else {
2009
+ ret = undefined;
2010
+ }
2011
+
2012
+ if (ret === VisitorOption.Break) {
2013
+ return;
2014
+ }
2015
+
2016
+ worklist.push(marker);
2017
+ leavelist.push(node);
2018
+
2019
+ if (ret !== VisitorOption.Skip) {
2020
+ candidates = VisitorKeys[node.type];
2021
+ current = candidates.length;
2022
+ while ((current -= 1) >= 0) {
2023
+ candidate = node[candidates[current]];
2024
+ if (candidate) {
2025
+ if (isArray(candidate)) {
2026
+ current2 = candidate.length;
2027
+ while ((current2 -= 1) >= 0) {
2028
+ if (candidate[current2]) {
2029
+ worklist.push(candidate[current2]);
2030
+ }
2031
+ }
2032
+ } else {
2033
+ worklist.push(candidate);
2034
+ }
2035
+ }
2036
+ }
2037
+ }
2038
+ }
2039
+ }
2040
+ }
2041
+
2042
+ // based on LLVM libc++ upper_bound / lower_bound
2043
+ // MIT License
2044
+
2045
+ function upperBound(array, func) {
2046
+ var diff, len, i, current;
2047
+
2048
+ len = array.length;
2049
+ i = 0;
2050
+
2051
+ while (len) {
2052
+ diff = len >>> 1;
2053
+ current = i + diff;
2054
+ if (func(array[current])) {
2055
+ len = diff;
2056
+ } else {
2057
+ i = current + 1;
2058
+ len -= diff + 1;
2059
+ }
2060
+ }
2061
+ return i;
2062
+ }
2063
+
2064
+ function lowerBound(array, func) {
2065
+ var diff, len, i, current;
2066
+
2067
+ len = array.length;
2068
+ i = 0;
2069
+
2070
+ while (len) {
2071
+ diff = len >>> 1;
2072
+ current = i + diff;
2073
+ if (func(array[current])) {
2074
+ i = current + 1;
2075
+ len -= diff + 1;
2076
+ } else {
2077
+ len = diff;
2078
+ }
2079
+ }
2080
+ return i;
2081
+ }
2082
+
2083
+ function extendCommentRange(comment, tokens) {
2084
+ var target, token;
2085
+
2086
+ target = upperBound(tokens, function search(token) {
2087
+ return token.range[0] > comment.range[0];
2088
+ });
2089
+
2090
+ comment.extendedRange = [comment.range[0], comment.range[1]];
2091
+
2092
+ if (target !== tokens.length) {
2093
+ comment.extendedRange[1] = tokens[target].range[0];
2094
+ }
2095
+
2096
+ target -= 1;
2097
+ if (target >= 0) {
2098
+ if (target < tokens.length) {
2099
+ comment.extendedRange[0] = tokens[target].range[1];
2100
+ } else if (token.length) {
2101
+ comment.extendedRange[1] = tokens[tokens.length - 1].range[0];
2102
+ }
2103
+ }
2104
+
2105
+ return comment;
2106
+ }
2107
+
2108
+ function attachComments(tree, providedComments, tokens) {
2109
+ // At first, we should calculate extended comment ranges.
2110
+ var comments = [], comment, len, i;
2111
+
2112
+ if (!tree.range) {
2113
+ throw new Error('attachComments needs range information');
2114
+ }
2115
+
2116
+ // tokens array is empty, we attach comments to tree as 'leadingComments'
2117
+ if (!tokens.length) {
2118
+ if (providedComments.length) {
2119
+ for (i = 0, len = providedComments.length; i < len; i += 1) {
2120
+ comment = deepCopy(providedComments[i]);
2121
+ comment.extendedRange = [0, tree.range[0]];
2122
+ comments.push(comment);
2123
+ }
2124
+ tree.leadingComments = comments;
2125
+ }
2126
+ return tree;
2127
+ }
2128
+
2129
+ for (i = 0, len = providedComments.length; i < len; i += 1) {
2130
+ comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
2131
+ }
2132
+
2133
+ // This is based on John Freeman's implementation.
2134
+ traverse(tree, {
2135
+ cursor: 0,
2136
+ enter: function (node) {
2137
+ var comment;
2138
+
2139
+ while (this.cursor < comments.length) {
2140
+ comment = comments[this.cursor];
2141
+ if (comment.extendedRange[1] > node.range[0]) {
2142
+ break;
2143
+ }
2144
+
2145
+ if (comment.extendedRange[1] === node.range[0]) {
2146
+ if (!node.leadingComments) {
2147
+ node.leadingComments = [];
2148
+ }
2149
+ node.leadingComments.push(comment);
2150
+ comments.splice(this.cursor, 1);
2151
+ } else {
2152
+ this.cursor += 1;
2153
+ }
2154
+ }
2155
+
2156
+ // already out of owned node
2157
+ if (this.cursor === comments.length) {
2158
+ return VisitorOption.Break;
2159
+ }
2160
+
2161
+ if (comments[this.cursor].extendedRange[0] > node.range[1]) {
2162
+ return VisitorOption.Skip;
2163
+ }
2164
+ }
2165
+ });
2166
+
2167
+ traverse(tree, {
2168
+ cursor: 0,
2169
+ leave: function (node) {
2170
+ var comment;
2171
+
2172
+ while (this.cursor < comments.length) {
2173
+ comment = comments[this.cursor];
2174
+ if (node.range[1] < comment.extendedRange[0]) {
2175
+ break;
2176
+ }
2177
+
2178
+ if (node.range[1] === comment.extendedRange[0]) {
2179
+ if (!node.trailingComments) {
2180
+ node.trailingComments = [];
2181
+ }
2182
+ node.trailingComments.push(comment);
2183
+ comments.splice(this.cursor, 1);
2184
+ } else {
2185
+ this.cursor += 1;
2186
+ }
2187
+ }
2188
+
2189
+ // already out of owned node
2190
+ if (this.cursor === comments.length) {
2191
+ return VisitorOption.Break;
2192
+ }
2193
+
2194
+ if (comments[this.cursor].extendedRange[0] > node.range[1]) {
2195
+ return VisitorOption.Skip;
2196
+ }
2197
+ }
2198
+ });
2199
+
2200
+ return tree;
2201
+ }
2202
+
2203
+ // Sync with package.json.
2204
+ exports.version = '0.0.14-dev';
2205
+
2206
+ exports.generate = generate;
2207
+ exports.traverse = traverse;
2208
+ exports.attachComments = attachComments;
2209
+
2210
+ }, this));
2211
+ /* vim: set sw=4 ts=4 et tw=80 : */