sweetjs 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +17 -0
- data/LICENSE.txt +20 -0
- data/README.md +39 -0
- data/Rakefile +125 -0
- data/lib/sweetjs.rb +78 -0
- data/lib/sweetjs/escodegen.js +1963 -0
- data/lib/sweetjs/sweet.js +5149 -0
- data/lib/sweetjs/underscore.js +1189 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/sweet_spec.rb +43 -0
- data/sweetjs.gemspec +77 -0
- metadata +149 -0
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
execjs_runtimes = {
|
6
|
+
"RubyRacer" => "therubyracer",
|
7
|
+
"RubyRhino" => "therubyrhino",
|
8
|
+
"Mustang" => "mustang"
|
9
|
+
}
|
10
|
+
|
11
|
+
if ENV["EXECJS_RUNTIME"] && execjs_runtimes[ENV["EXECJS_RUNTIME"]]
|
12
|
+
gem execjs_runtimes[ENV["EXECJS_RUNTIME"]], :group => :development
|
13
|
+
end
|
14
|
+
|
15
|
+
# Engine
|
16
|
+
gem ENV["MULTI_JSON_ENGINE"], :group => :development if ENV["MULTI_JSON_ENGINE"]
|
17
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Garry Hill
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# Sweet Javascript Macros from Ruby
|
2
|
+
|
3
|
+
This is a Ruby wrapper around the [Sweet.js macro processor](http://sweetjs.org).
|
4
|
+
|
5
|
+
Go to [sweetjs.org](http://sweetjs.org) for more information.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
gem install sweetjs
|
10
|
+
|
11
|
+
Ensure that your environment has a JavaScript interpreter supported by
|
12
|
+
[ExecJS](https://github.com/sstephenson/execjs). Using the
|
13
|
+
[therubyracer](https://github.com/cowboyd/therubyracer) gem is a good option.
|
14
|
+
|
15
|
+
In your `Gemfile`:
|
16
|
+
|
17
|
+
gem "sweetjs"
|
18
|
+
gem "therubyracer"
|
19
|
+
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
require 'sweetjs'
|
24
|
+
|
25
|
+
SweetJS.new.compile(File.read("source.sjs"))
|
26
|
+
# => processed JavaScript source
|
27
|
+
|
28
|
+
# Or alternatively:
|
29
|
+
SweetJS.compile(File.read("source.sjs"))
|
30
|
+
|
31
|
+
## Acknowledgements
|
32
|
+
|
33
|
+
Thanks to [Ville Lautanala](https://github.com/lautis) who unwittingly wrote
|
34
|
+
most of the code and the README.
|
35
|
+
|
36
|
+
## Copyright
|
37
|
+
|
38
|
+
© Garry Hill, [Magnetised Ltd](https://magnetised.net/). Released under MIT license, see [LICENSE.txt](https://github.com/magnetised/sweetjs/blob/master/LICENSE.txt) for more details.
|
39
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "bundler"
|
3
|
+
|
4
|
+
begin
|
5
|
+
Bundler.setup(:default, :development)
|
6
|
+
rescue Bundler::BundlerError => e
|
7
|
+
$stderr.puts e.message
|
8
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
9
|
+
exit e.status_code
|
10
|
+
end
|
11
|
+
|
12
|
+
require 'rake'
|
13
|
+
require 'date'
|
14
|
+
|
15
|
+
require 'rspec/core'
|
16
|
+
require 'rspec/core/rake_task'
|
17
|
+
|
18
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
19
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :spec
|
23
|
+
|
24
|
+
#############################################################################
|
25
|
+
#
|
26
|
+
# Helper functions
|
27
|
+
#
|
28
|
+
#############################################################################
|
29
|
+
|
30
|
+
def name
|
31
|
+
@name ||= Dir['*.gemspec'].first.split('.').first
|
32
|
+
end
|
33
|
+
|
34
|
+
def version
|
35
|
+
line = File.read("lib/sweetjs.rb")[/^\s*VERSION\s*=\s*.*/]
|
36
|
+
line.match(/.*VERSION\s*=\s*['"](.*)['"]/)[1]
|
37
|
+
end
|
38
|
+
|
39
|
+
def date
|
40
|
+
Date.today.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
def rubyforge_project
|
44
|
+
name
|
45
|
+
end
|
46
|
+
|
47
|
+
def gemspec_file
|
48
|
+
"#{name}.gemspec"
|
49
|
+
end
|
50
|
+
|
51
|
+
def gem_file
|
52
|
+
"#{name}-#{version}.gem"
|
53
|
+
end
|
54
|
+
|
55
|
+
def replace_header(head, header_name)
|
56
|
+
head.sub!(/(\.#{header_name}\s*= ').*'/) { "#{$1}#{send(header_name)}'"}
|
57
|
+
end
|
58
|
+
|
59
|
+
#############################################################################
|
60
|
+
#
|
61
|
+
# Packaging tasks
|
62
|
+
#
|
63
|
+
#############################################################################
|
64
|
+
|
65
|
+
desc "Create tag v#{version} and build and push #{gem_file} to Rubygems"
|
66
|
+
task :release => :build do
|
67
|
+
unless `git branch` =~ /^\* master$/
|
68
|
+
puts "You must be on the master branch to release!"
|
69
|
+
exit!
|
70
|
+
end
|
71
|
+
sh "git commit --allow-empty -a -m 'Release #{version}'"
|
72
|
+
sh "git tag v#{version}"
|
73
|
+
sh "git push origin master"
|
74
|
+
sh "git push origin v#{version}"
|
75
|
+
sh "gem push pkg/#{name}-#{version}.gem"
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "Build #{gem_file} into the pkg directory"
|
79
|
+
task :build => :gemspec do
|
80
|
+
sh "mkdir -p pkg"
|
81
|
+
sh "gem build #{gemspec_file}"
|
82
|
+
sh "mv #{gem_file} pkg"
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "Generate #{gemspec_file}"
|
86
|
+
task :gemspec => :validate do
|
87
|
+
# read spec file and split out manifest section
|
88
|
+
spec = File.read(gemspec_file)
|
89
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
90
|
+
|
91
|
+
# replace name version and date
|
92
|
+
replace_header(head, :name)
|
93
|
+
replace_header(head, :version)
|
94
|
+
replace_header(head, :date)
|
95
|
+
#comment this out if your rubyforge_project has a different name
|
96
|
+
replace_header(head, :rubyforge_project)
|
97
|
+
|
98
|
+
# determine file list from git ls-files
|
99
|
+
files = `git ls-files`.
|
100
|
+
split("\n").
|
101
|
+
sort.
|
102
|
+
reject { |file| file =~ /^\./ }.
|
103
|
+
reject { |file| file =~ /^(rdoc|pkg)/ }.
|
104
|
+
map { |file| " #{file}" }.
|
105
|
+
join("\n")
|
106
|
+
|
107
|
+
# piece file back together and write
|
108
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
109
|
+
spec = [head, manifest, tail].join(" # = MANIFEST =\n")
|
110
|
+
File.open(gemspec_file, 'w') { |io| io.write(spec) }
|
111
|
+
puts "Updated #{gemspec_file}"
|
112
|
+
end
|
113
|
+
|
114
|
+
desc "Validate #{gemspec_file}"
|
115
|
+
task :validate do
|
116
|
+
libfiles = Dir['lib/*'] - ["lib/#{name}.rb", "lib/#{name}"]
|
117
|
+
unless libfiles.empty?
|
118
|
+
puts "Directory `lib` should only contain a `#{name}.rb` file and `#{name}` dir."
|
119
|
+
exit!
|
120
|
+
end
|
121
|
+
unless Dir['VERSION*'].empty?
|
122
|
+
puts "A `VERSION` file at root level violates Gem best practices."
|
123
|
+
exit!
|
124
|
+
end
|
125
|
+
end
|
data/lib/sweetjs.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require "execjs"
|
4
|
+
require "multi_json"
|
5
|
+
|
6
|
+
class SweetJS
|
7
|
+
VERSION = "0.1.0"
|
8
|
+
REQUIRES = %w(underscore escodegen sweet)
|
9
|
+
|
10
|
+
Error = ExecJS::Error
|
11
|
+
|
12
|
+
def self.compile(source)
|
13
|
+
self.new.compile(source)
|
14
|
+
end
|
15
|
+
|
16
|
+
def context
|
17
|
+
@context ||= build_context
|
18
|
+
end
|
19
|
+
|
20
|
+
def build_context
|
21
|
+
source = (<<-JS)
|
22
|
+
var require = (function() {
|
23
|
+
var modules = {};
|
24
|
+
var require = function(module) {
|
25
|
+
return modules[module];
|
26
|
+
};
|
27
|
+
JS
|
28
|
+
|
29
|
+
REQUIRES.each do |file|
|
30
|
+
source << (<<-JS)
|
31
|
+
|
32
|
+
////////////////////////////////////////////////////////////
|
33
|
+
// #{ file }.js START
|
34
|
+
|
35
|
+
modules["#{file}"] = function() {
|
36
|
+
var exports = {}, module = {};
|
37
|
+
module.exports = exports;
|
38
|
+
|
39
|
+
#{ read_source_file(file) }
|
40
|
+
|
41
|
+
return exports;
|
42
|
+
}.call({});
|
43
|
+
|
44
|
+
// #{ file }.js END
|
45
|
+
JS
|
46
|
+
end
|
47
|
+
source << (<<-JS)
|
48
|
+
return require;
|
49
|
+
}.call(this));
|
50
|
+
JS
|
51
|
+
ExecJS.compile(source)
|
52
|
+
end
|
53
|
+
|
54
|
+
def read_source_file(name)
|
55
|
+
File.open(File.expand_path("../sweetjs/#{name}.js", __FILE__), "r:UTF-8").read
|
56
|
+
end
|
57
|
+
|
58
|
+
def compile(source)
|
59
|
+
source = source.respond_to?(:read) ? source.read : source.to_s
|
60
|
+
js = []
|
61
|
+
js << "var sweet = require('sweet');"
|
62
|
+
js << "var escodegen = require('escodegen');"
|
63
|
+
js << "var source = #{json_encode(source)};"
|
64
|
+
js << "var result = escodegen.generate(sweet.parse(source));"
|
65
|
+
js << "return result;"
|
66
|
+
context.exec js.join("\n")
|
67
|
+
end
|
68
|
+
|
69
|
+
if MultiJson.respond_to? :dump
|
70
|
+
def json_encode(obj)
|
71
|
+
MultiJson.dump(obj)
|
72
|
+
end
|
73
|
+
else
|
74
|
+
def json_encode(obj)
|
75
|
+
MultiJson.encode(obj)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,1963 @@
|
|
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*/
|
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
|
+
extra,
|
75
|
+
parse,
|
76
|
+
sourceMap;
|
77
|
+
|
78
|
+
Syntax = {
|
79
|
+
AssignmentExpression: 'AssignmentExpression',
|
80
|
+
ArrayExpression: 'ArrayExpression',
|
81
|
+
BlockStatement: 'BlockStatement',
|
82
|
+
BinaryExpression: 'BinaryExpression',
|
83
|
+
BreakStatement: 'BreakStatement',
|
84
|
+
CallExpression: 'CallExpression',
|
85
|
+
CatchClause: 'CatchClause',
|
86
|
+
ConditionalExpression: 'ConditionalExpression',
|
87
|
+
ContinueStatement: 'ContinueStatement',
|
88
|
+
DoWhileStatement: 'DoWhileStatement',
|
89
|
+
DebuggerStatement: 'DebuggerStatement',
|
90
|
+
EmptyStatement: 'EmptyStatement',
|
91
|
+
ExpressionStatement: 'ExpressionStatement',
|
92
|
+
ForStatement: 'ForStatement',
|
93
|
+
ForInStatement: 'ForInStatement',
|
94
|
+
FunctionDeclaration: 'FunctionDeclaration',
|
95
|
+
FunctionExpression: 'FunctionExpression',
|
96
|
+
Identifier: 'Identifier',
|
97
|
+
IfStatement: 'IfStatement',
|
98
|
+
Literal: 'Literal',
|
99
|
+
LabeledStatement: 'LabeledStatement',
|
100
|
+
LogicalExpression: 'LogicalExpression',
|
101
|
+
MemberExpression: 'MemberExpression',
|
102
|
+
NewExpression: 'NewExpression',
|
103
|
+
ObjectExpression: 'ObjectExpression',
|
104
|
+
Program: 'Program',
|
105
|
+
Property: 'Property',
|
106
|
+
ReturnStatement: 'ReturnStatement',
|
107
|
+
SequenceExpression: 'SequenceExpression',
|
108
|
+
SwitchStatement: 'SwitchStatement',
|
109
|
+
SwitchCase: 'SwitchCase',
|
110
|
+
ThisExpression: 'ThisExpression',
|
111
|
+
ThrowStatement: 'ThrowStatement',
|
112
|
+
TryStatement: 'TryStatement',
|
113
|
+
UnaryExpression: 'UnaryExpression',
|
114
|
+
UpdateExpression: 'UpdateExpression',
|
115
|
+
VariableDeclaration: 'VariableDeclaration',
|
116
|
+
VariableDeclarator: 'VariableDeclarator',
|
117
|
+
WhileStatement: 'WhileStatement',
|
118
|
+
WithStatement: 'WithStatement'
|
119
|
+
};
|
120
|
+
|
121
|
+
Precedence = {
|
122
|
+
Sequence: 0,
|
123
|
+
Assignment: 1,
|
124
|
+
Conditional: 2,
|
125
|
+
LogicalOR: 3,
|
126
|
+
LogicalAND: 4,
|
127
|
+
BitwiseOR: 5,
|
128
|
+
BitwiseXOR: 6,
|
129
|
+
BitwiseAND: 7,
|
130
|
+
Equality: 8,
|
131
|
+
Relational: 9,
|
132
|
+
BitwiseSHIFT: 10,
|
133
|
+
Additive: 11,
|
134
|
+
Multiplicative: 12,
|
135
|
+
Unary: 13,
|
136
|
+
Postfix: 14,
|
137
|
+
Call: 15,
|
138
|
+
New: 16,
|
139
|
+
Member: 17,
|
140
|
+
Primary: 18
|
141
|
+
};
|
142
|
+
|
143
|
+
BinaryPrecedence = {
|
144
|
+
'||': Precedence.LogicalOR,
|
145
|
+
'&&': Precedence.LogicalAND,
|
146
|
+
'|': Precedence.BitwiseOR,
|
147
|
+
'^': Precedence.BitwiseXOR,
|
148
|
+
'&': Precedence.BitwiseAND,
|
149
|
+
'==': Precedence.Equality,
|
150
|
+
'!=': Precedence.Equality,
|
151
|
+
'===': Precedence.Equality,
|
152
|
+
'!==': Precedence.Equality,
|
153
|
+
'<': Precedence.Relational,
|
154
|
+
'>': Precedence.Relational,
|
155
|
+
'<=': Precedence.Relational,
|
156
|
+
'>=': Precedence.Relational,
|
157
|
+
'in': Precedence.Relational,
|
158
|
+
'instanceof': Precedence.Relational,
|
159
|
+
'<<': Precedence.BitwiseSHIFT,
|
160
|
+
'>>': Precedence.BitwiseSHIFT,
|
161
|
+
'>>>': Precedence.BitwiseSHIFT,
|
162
|
+
'+': Precedence.Additive,
|
163
|
+
'-': Precedence.Additive,
|
164
|
+
'*': Precedence.Multiplicative,
|
165
|
+
'%': Precedence.Multiplicative,
|
166
|
+
'/': Precedence.Multiplicative
|
167
|
+
};
|
168
|
+
|
169
|
+
Regex = {
|
170
|
+
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]')
|
171
|
+
};
|
172
|
+
|
173
|
+
function getDefaultOptions() {
|
174
|
+
// default options
|
175
|
+
return {
|
176
|
+
indent: null,
|
177
|
+
base: null,
|
178
|
+
parse: null,
|
179
|
+
comment: false,
|
180
|
+
format: {
|
181
|
+
indent: {
|
182
|
+
style: ' ',
|
183
|
+
base: 0,
|
184
|
+
adjustMultilineComment: false
|
185
|
+
},
|
186
|
+
json: false,
|
187
|
+
renumber: false,
|
188
|
+
hexadecimal: false,
|
189
|
+
quotes: 'single',
|
190
|
+
escapeless: false,
|
191
|
+
compact: false,
|
192
|
+
parentheses: true,
|
193
|
+
semicolons: true,
|
194
|
+
safeConcatenation: false
|
195
|
+
},
|
196
|
+
sourceMap: null,
|
197
|
+
sourceMapWithCode: false
|
198
|
+
};
|
199
|
+
}
|
200
|
+
|
201
|
+
function stringToArray(str) {
|
202
|
+
var length = str.length,
|
203
|
+
result = [],
|
204
|
+
i;
|
205
|
+
for (i = 0; i < length; i += 1) {
|
206
|
+
result[i] = str.charAt(i);
|
207
|
+
}
|
208
|
+
return result;
|
209
|
+
}
|
210
|
+
|
211
|
+
function stringRepeat(str, num) {
|
212
|
+
var result = '';
|
213
|
+
|
214
|
+
for (num |= 0; num > 0; num >>>= 1, str += str) {
|
215
|
+
if (num & 1) {
|
216
|
+
result += str;
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
return result;
|
221
|
+
}
|
222
|
+
|
223
|
+
isArray = Array.isArray;
|
224
|
+
if (!isArray) {
|
225
|
+
isArray = function isArray(array) {
|
226
|
+
return Object.prototype.toString.call(array) === '[object Array]';
|
227
|
+
};
|
228
|
+
}
|
229
|
+
|
230
|
+
// Fallback for the non SourceMap environment
|
231
|
+
function SourceNodeMock(line, column, filename, chunk) {
|
232
|
+
var result = [];
|
233
|
+
|
234
|
+
function flatten(input) {
|
235
|
+
var i, iz;
|
236
|
+
if (isArray(input)) {
|
237
|
+
for (i = 0, iz = input.length; i < iz; ++i) {
|
238
|
+
flatten(input[i]);
|
239
|
+
}
|
240
|
+
} else if (input instanceof SourceNodeMock) {
|
241
|
+
result.push(input);
|
242
|
+
} else if (typeof input === 'string' && input) {
|
243
|
+
result.push(input);
|
244
|
+
}
|
245
|
+
}
|
246
|
+
|
247
|
+
flatten(chunk);
|
248
|
+
this.children = result;
|
249
|
+
}
|
250
|
+
|
251
|
+
SourceNodeMock.prototype.toString = function toString() {
|
252
|
+
var res = '', i, iz, node;
|
253
|
+
for (i = 0, iz = this.children.length; i < iz; ++i) {
|
254
|
+
node = this.children[i];
|
255
|
+
if (node instanceof SourceNodeMock) {
|
256
|
+
res += node.toString();
|
257
|
+
} else {
|
258
|
+
res += node;
|
259
|
+
}
|
260
|
+
}
|
261
|
+
return res;
|
262
|
+
};
|
263
|
+
|
264
|
+
SourceNodeMock.prototype.replaceRight = function replaceRight(pattern, replacement) {
|
265
|
+
var last = this.children[this.children.length - 1];
|
266
|
+
if (last instanceof SourceNodeMock) {
|
267
|
+
last.replaceRight(pattern, replacement);
|
268
|
+
} else if (typeof last === 'string') {
|
269
|
+
this.children[this.children.length - 1] = last.replace(pattern, replacement);
|
270
|
+
} else {
|
271
|
+
this.children.push(''.replace(pattern, replacement));
|
272
|
+
}
|
273
|
+
return this;
|
274
|
+
};
|
275
|
+
|
276
|
+
SourceNodeMock.prototype.join = function join(sep) {
|
277
|
+
var i, iz, result;
|
278
|
+
result = [];
|
279
|
+
iz = this.children.length;
|
280
|
+
if (iz > 0) {
|
281
|
+
for (i = 0, iz -= 1; i < iz; ++i) {
|
282
|
+
result.push(this.children[i], sep);
|
283
|
+
}
|
284
|
+
result.push(this.children[iz]);
|
285
|
+
this.children = result;
|
286
|
+
}
|
287
|
+
return this;
|
288
|
+
};
|
289
|
+
|
290
|
+
function endsWithLineTerminator(str) {
|
291
|
+
var ch = str.charAt(str.length - 1);
|
292
|
+
return ch === '\r' || ch === '\n';
|
293
|
+
}
|
294
|
+
|
295
|
+
function shallowCopy(obj) {
|
296
|
+
var ret = {}, key;
|
297
|
+
for (key in obj) {
|
298
|
+
if (obj.hasOwnProperty(key)) {
|
299
|
+
ret[key] = obj[key];
|
300
|
+
}
|
301
|
+
}
|
302
|
+
return ret;
|
303
|
+
}
|
304
|
+
|
305
|
+
function deepCopy(obj) {
|
306
|
+
var ret = {}, key, val;
|
307
|
+
for (key in obj) {
|
308
|
+
if (obj.hasOwnProperty(key)) {
|
309
|
+
val = obj[key];
|
310
|
+
if (typeof val === 'object' && val !== null) {
|
311
|
+
ret[key] = deepCopy(val);
|
312
|
+
} else {
|
313
|
+
ret[key] = val;
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|
317
|
+
return ret;
|
318
|
+
}
|
319
|
+
|
320
|
+
function updateDeeply(target, override) {
|
321
|
+
var key, val;
|
322
|
+
|
323
|
+
function isHashObject(target) {
|
324
|
+
return typeof target === 'object' && target instanceof Object && !(target instanceof RegExp);
|
325
|
+
}
|
326
|
+
|
327
|
+
for (key in override) {
|
328
|
+
if (override.hasOwnProperty(key)) {
|
329
|
+
val = override[key];
|
330
|
+
if (isHashObject(val)) {
|
331
|
+
if (isHashObject(target[key])) {
|
332
|
+
updateDeeply(target[key], val);
|
333
|
+
} else {
|
334
|
+
target[key] = updateDeeply({}, val);
|
335
|
+
}
|
336
|
+
} else {
|
337
|
+
target[key] = val;
|
338
|
+
}
|
339
|
+
}
|
340
|
+
}
|
341
|
+
return target;
|
342
|
+
}
|
343
|
+
|
344
|
+
function generateNumber(value) {
|
345
|
+
var result, point, temp, exponent, pos;
|
346
|
+
|
347
|
+
if (value !== value) {
|
348
|
+
throw new Error('Numeric literal whose value is NaN');
|
349
|
+
}
|
350
|
+
if (value < 0 || (value === 0 && 1 / value < 0)) {
|
351
|
+
throw new Error('Numeric literal whose value is negative');
|
352
|
+
}
|
353
|
+
|
354
|
+
if (value === 1 / 0) {
|
355
|
+
return json ? 'null' : renumber ? '1e400' : '1e+400';
|
356
|
+
}
|
357
|
+
|
358
|
+
result = '' + value;
|
359
|
+
if (!renumber || result.length < 3) {
|
360
|
+
return result;
|
361
|
+
}
|
362
|
+
|
363
|
+
point = result.indexOf('.');
|
364
|
+
if (!json && result.charAt(0) === '0' && point === 1) {
|
365
|
+
point = 0;
|
366
|
+
result = result.slice(1);
|
367
|
+
}
|
368
|
+
temp = result;
|
369
|
+
result = result.replace('e+', 'e');
|
370
|
+
exponent = 0;
|
371
|
+
if ((pos = temp.indexOf('e')) > 0) {
|
372
|
+
exponent = +temp.slice(pos + 1);
|
373
|
+
temp = temp.slice(0, pos);
|
374
|
+
}
|
375
|
+
if (point >= 0) {
|
376
|
+
exponent -= temp.length - point - 1;
|
377
|
+
temp = +(temp.slice(0, point) + temp.slice(point + 1)) + '';
|
378
|
+
}
|
379
|
+
pos = 0;
|
380
|
+
while (temp.charAt(temp.length + pos - 1) === '0') {
|
381
|
+
pos -= 1;
|
382
|
+
}
|
383
|
+
if (pos !== 0) {
|
384
|
+
exponent -= pos;
|
385
|
+
temp = temp.slice(0, pos);
|
386
|
+
}
|
387
|
+
if (exponent !== 0) {
|
388
|
+
temp += 'e' + exponent;
|
389
|
+
}
|
390
|
+
if ((temp.length < result.length ||
|
391
|
+
(hexadecimal && value > 1e12 && Math.floor(value) === value && (temp = '0x' + value.toString(16)).length < result.length)) &&
|
392
|
+
+temp === value) {
|
393
|
+
result = temp;
|
394
|
+
}
|
395
|
+
|
396
|
+
return result;
|
397
|
+
}
|
398
|
+
|
399
|
+
function escapeAllowedCharacter(ch, next) {
|
400
|
+
var code = ch.charCodeAt(0), hex = code.toString(16), result = '\\';
|
401
|
+
|
402
|
+
switch (ch) {
|
403
|
+
case '\b':
|
404
|
+
result += 'b';
|
405
|
+
break;
|
406
|
+
case '\f':
|
407
|
+
result += 'f';
|
408
|
+
break;
|
409
|
+
case '\t':
|
410
|
+
result += 't';
|
411
|
+
break;
|
412
|
+
default:
|
413
|
+
if (json || code > 0xff) {
|
414
|
+
result += 'u' + '0000'.slice(hex.length) + hex;
|
415
|
+
} else if (ch === '\u0000' && '0123456789'.indexOf(next) < 0) {
|
416
|
+
result += '0';
|
417
|
+
} else if (ch === '\v') {
|
418
|
+
result += 'v';
|
419
|
+
} else {
|
420
|
+
result += 'x' + '00'.slice(hex.length) + hex;
|
421
|
+
}
|
422
|
+
break;
|
423
|
+
}
|
424
|
+
|
425
|
+
return result;
|
426
|
+
}
|
427
|
+
|
428
|
+
function escapeDisallowedCharacter(ch) {
|
429
|
+
var result = '\\';
|
430
|
+
switch (ch) {
|
431
|
+
case '\\':
|
432
|
+
result += '\\';
|
433
|
+
break;
|
434
|
+
case '\n':
|
435
|
+
result += 'n';
|
436
|
+
break;
|
437
|
+
case '\r':
|
438
|
+
result += 'r';
|
439
|
+
break;
|
440
|
+
case '\u2028':
|
441
|
+
result += 'u2028';
|
442
|
+
break;
|
443
|
+
case '\u2029':
|
444
|
+
result += 'u2029';
|
445
|
+
break;
|
446
|
+
default:
|
447
|
+
throw new Error('Incorrectly classified character');
|
448
|
+
}
|
449
|
+
|
450
|
+
return result;
|
451
|
+
}
|
452
|
+
|
453
|
+
function escapeString(str) {
|
454
|
+
var result = '', i, len, ch, next, singleQuotes = 0, doubleQuotes = 0, single;
|
455
|
+
|
456
|
+
if (typeof str[0] === 'undefined') {
|
457
|
+
str = stringToArray(str);
|
458
|
+
}
|
459
|
+
|
460
|
+
for (i = 0, len = str.length; i < len; i += 1) {
|
461
|
+
ch = str[i];
|
462
|
+
if (ch === '\'') {
|
463
|
+
singleQuotes += 1;
|
464
|
+
} else if (ch === '"') {
|
465
|
+
doubleQuotes += 1;
|
466
|
+
} else if (ch === '/' && json) {
|
467
|
+
result += '\\';
|
468
|
+
} else if ('\\\n\r\u2028\u2029'.indexOf(ch) >= 0) {
|
469
|
+
result += escapeDisallowedCharacter(ch);
|
470
|
+
continue;
|
471
|
+
} else if ((json && ch < ' ') || !(json || escapeless || (ch >= ' ' && ch <= '~'))) {
|
472
|
+
result += escapeAllowedCharacter(ch, str[i + 1]);
|
473
|
+
continue;
|
474
|
+
}
|
475
|
+
result += ch;
|
476
|
+
}
|
477
|
+
|
478
|
+
single = !(quotes === 'double' || (quotes === 'auto' && doubleQuotes < singleQuotes));
|
479
|
+
str = result;
|
480
|
+
result = single ? '\'' : '"';
|
481
|
+
|
482
|
+
if (typeof str[0] === 'undefined') {
|
483
|
+
str = stringToArray(str);
|
484
|
+
}
|
485
|
+
|
486
|
+
for (i = 0, len = str.length; i < len; i += 1) {
|
487
|
+
ch = str[i];
|
488
|
+
if ((ch === '\'' && single) || (ch === '"' && !single)) {
|
489
|
+
result += '\\';
|
490
|
+
}
|
491
|
+
result += ch;
|
492
|
+
}
|
493
|
+
|
494
|
+
return result + (single ? '\'' : '"');
|
495
|
+
}
|
496
|
+
|
497
|
+
function isWhiteSpace(ch) {
|
498
|
+
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);
|
499
|
+
}
|
500
|
+
|
501
|
+
function isLineTerminator(ch) {
|
502
|
+
return '\n\r\u2028\u2029'.indexOf(ch) >= 0;
|
503
|
+
}
|
504
|
+
|
505
|
+
function isIdentifierPart(ch) {
|
506
|
+
return (ch === '$') || (ch === '_') || (ch === '\\') ||
|
507
|
+
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
|
508
|
+
((ch >= '0') && (ch <= '9')) ||
|
509
|
+
((ch.charCodeAt(0) >= 0x80) && Regex.NonAsciiIdentifierPart.test(ch));
|
510
|
+
}
|
511
|
+
|
512
|
+
function join(left, right) {
|
513
|
+
var leftSource = toSourceNode(left).toString(),
|
514
|
+
rightSource = toSourceNode(right).toString(),
|
515
|
+
leftChar = leftSource.charAt(leftSource.length - 1),
|
516
|
+
rightChar = rightSource.charAt(0);
|
517
|
+
|
518
|
+
if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
|
519
|
+
return [left, ' ', right];
|
520
|
+
} else if (isWhiteSpace(leftChar) || isLineTerminator(leftChar) || isWhiteSpace(rightChar) || isLineTerminator(rightChar)) {
|
521
|
+
return [left, right];
|
522
|
+
}
|
523
|
+
return [left, space, right];
|
524
|
+
}
|
525
|
+
|
526
|
+
function addIndent(stmt) {
|
527
|
+
return [base, stmt];
|
528
|
+
}
|
529
|
+
|
530
|
+
function withIndent(fn) {
|
531
|
+
var previousBase;
|
532
|
+
previousBase = base;
|
533
|
+
base += indent;
|
534
|
+
var result = fn.call(this, base);
|
535
|
+
base = previousBase;
|
536
|
+
return result;
|
537
|
+
}
|
538
|
+
|
539
|
+
function calculateSpaces(str) {
|
540
|
+
var i;
|
541
|
+
for (i = str.length - 1; i >= 0; i -= 1) {
|
542
|
+
if (isLineTerminator(str.charAt(i))) {
|
543
|
+
break;
|
544
|
+
}
|
545
|
+
}
|
546
|
+
return (str.length - 1) - i;
|
547
|
+
}
|
548
|
+
|
549
|
+
function toSourceNode(generated, node) {
|
550
|
+
if (node == null) {
|
551
|
+
if (generated instanceof SourceNode) {
|
552
|
+
return generated;
|
553
|
+
} else {
|
554
|
+
node = {};
|
555
|
+
}
|
556
|
+
}
|
557
|
+
if (node.loc == null) {
|
558
|
+
return new SourceNode(null, null, sourceMap, generated);
|
559
|
+
}
|
560
|
+
return new SourceNode(node.loc.start.line, node.loc.start.column, sourceMap, generated);
|
561
|
+
}
|
562
|
+
|
563
|
+
function adjustMultilineComment(value, specialBase) {
|
564
|
+
var array, i, len, line, j, ch, spaces, previousBase;
|
565
|
+
|
566
|
+
array = value.split(/\r\n|[\r\n]/);
|
567
|
+
spaces = Number.MAX_VALUE;
|
568
|
+
|
569
|
+
// first line doesn't have indentation
|
570
|
+
for (i = 1, len = array.length; i < len; i += 1) {
|
571
|
+
line = array[i];
|
572
|
+
j = 0;
|
573
|
+
while (j < line.length && isWhiteSpace(line[j])) {
|
574
|
+
j += 1;
|
575
|
+
}
|
576
|
+
if (spaces > j) {
|
577
|
+
spaces = j;
|
578
|
+
}
|
579
|
+
}
|
580
|
+
|
581
|
+
if (typeof specialBase !== 'undefined') {
|
582
|
+
// pattern like
|
583
|
+
// {
|
584
|
+
// var t = 20; /*
|
585
|
+
// * this is comment
|
586
|
+
// */
|
587
|
+
// }
|
588
|
+
previousBase = base;
|
589
|
+
if (array[1][spaces] === '*') {
|
590
|
+
specialBase += ' ';
|
591
|
+
}
|
592
|
+
base = specialBase;
|
593
|
+
} else {
|
594
|
+
if (spaces & 1) {
|
595
|
+
// /*
|
596
|
+
// *
|
597
|
+
// */
|
598
|
+
// If spaces are odd number, above pattern is considered.
|
599
|
+
// We waste 1 space.
|
600
|
+
spaces -= 1;
|
601
|
+
}
|
602
|
+
previousBase = base;
|
603
|
+
}
|
604
|
+
|
605
|
+
for (i = 1, len = array.length; i < len; i += 1) {
|
606
|
+
array[i] = toSourceNode(addIndent(array[i].slice(spaces))).join('');
|
607
|
+
}
|
608
|
+
|
609
|
+
base = previousBase;
|
610
|
+
|
611
|
+
return array.join('\n');
|
612
|
+
}
|
613
|
+
|
614
|
+
function generateComment(comment, specialBase) {
|
615
|
+
if (comment.type === 'Line') {
|
616
|
+
if (endsWithLineTerminator(comment.value)) {
|
617
|
+
return '//' + comment.value;
|
618
|
+
} else {
|
619
|
+
// Always use LineTerminator
|
620
|
+
return '//' + comment.value + '\n';
|
621
|
+
}
|
622
|
+
}
|
623
|
+
if (extra.format.indent.adjustMultilineComment && /[\n\r]/.test(comment.value)) {
|
624
|
+
return adjustMultilineComment('/*' + comment.value + '*/', specialBase);
|
625
|
+
}
|
626
|
+
return '/*' + comment.value + '*/';
|
627
|
+
}
|
628
|
+
|
629
|
+
function addCommentsToStatement(stmt, result) {
|
630
|
+
var i, len, comment, save, node, tailingToStatement, specialBase, fragment;
|
631
|
+
|
632
|
+
if (stmt.leadingComments && stmt.leadingComments.length > 0) {
|
633
|
+
save = result;
|
634
|
+
|
635
|
+
comment = stmt.leadingComments[0];
|
636
|
+
result = [];
|
637
|
+
if (safeConcatenation && stmt.type === Syntax.Program && stmt.body.length === 0) {
|
638
|
+
result.push('\n');
|
639
|
+
}
|
640
|
+
result.push(generateComment(comment));
|
641
|
+
if (!endsWithLineTerminator(toSourceNode(result).toString())) {
|
642
|
+
result.push('\n');
|
643
|
+
}
|
644
|
+
|
645
|
+
for (i = 1, len = stmt.leadingComments.length; i < len; i += 1) {
|
646
|
+
comment = stmt.leadingComments[i];
|
647
|
+
fragment = [generateComment(comment)];
|
648
|
+
if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
|
649
|
+
fragment.push('\n');
|
650
|
+
}
|
651
|
+
result.push(addIndent(fragment));
|
652
|
+
}
|
653
|
+
|
654
|
+
result.push(addIndent(save));
|
655
|
+
}
|
656
|
+
|
657
|
+
if (stmt.trailingComments) {
|
658
|
+
tailingToStatement = !endsWithLineTerminator(toSourceNode(result).toString());
|
659
|
+
specialBase = stringRepeat(' ', calculateSpaces(toSourceNode([base, result, indent]).toString()));
|
660
|
+
for (i = 0, len = stmt.trailingComments.length; i < len; i += 1) {
|
661
|
+
comment = stmt.trailingComments[i];
|
662
|
+
if (tailingToStatement) {
|
663
|
+
// We assume target like following script
|
664
|
+
//
|
665
|
+
// var t = 20; /**
|
666
|
+
// * This is comment of t
|
667
|
+
// */
|
668
|
+
if (i === 0) {
|
669
|
+
// first case
|
670
|
+
result.push(indent);
|
671
|
+
} else {
|
672
|
+
result.push(specialBase);
|
673
|
+
}
|
674
|
+
result.push(generateComment(comment, specialBase));
|
675
|
+
} else {
|
676
|
+
result.push(addIndent(generateComment(comment)));
|
677
|
+
}
|
678
|
+
if (i !== len - 1 && !endsWithLineTerminator(toSourceNode(result).toString())) {
|
679
|
+
result.push('\n');
|
680
|
+
}
|
681
|
+
}
|
682
|
+
}
|
683
|
+
|
684
|
+
return result;
|
685
|
+
}
|
686
|
+
|
687
|
+
function parenthesize(text, current, should) {
|
688
|
+
if (current < should) {
|
689
|
+
return ['(', text, ')'];
|
690
|
+
}
|
691
|
+
return text;
|
692
|
+
}
|
693
|
+
|
694
|
+
function maybeBlock(stmt, semicolonOptional) {
|
695
|
+
var result, noLeadingComment;
|
696
|
+
|
697
|
+
noLeadingComment = !extra.comment || !stmt.leadingComments;
|
698
|
+
|
699
|
+
if (stmt.type === Syntax.BlockStatement && noLeadingComment) {
|
700
|
+
return [space, generateStatement(stmt)];
|
701
|
+
}
|
702
|
+
|
703
|
+
if (stmt.type === Syntax.EmptyStatement && noLeadingComment) {
|
704
|
+
return ';';
|
705
|
+
}
|
706
|
+
|
707
|
+
withIndent(function () {
|
708
|
+
result = [newline, addIndent(generateStatement(stmt, { semicolonOptional: semicolonOptional }))];
|
709
|
+
});
|
710
|
+
|
711
|
+
return result;
|
712
|
+
}
|
713
|
+
|
714
|
+
function maybeBlockSuffix(stmt, result) {
|
715
|
+
var ends = endsWithLineTerminator(toSourceNode(result).toString());
|
716
|
+
if (stmt.type === Syntax.BlockStatement && (!extra.comment || !stmt.leadingComments) && !ends) {
|
717
|
+
return [result, space];
|
718
|
+
}
|
719
|
+
if (ends) {
|
720
|
+
return [result, base];
|
721
|
+
}
|
722
|
+
return [result, newline, base];
|
723
|
+
}
|
724
|
+
|
725
|
+
function generateFunctionBody(node) {
|
726
|
+
var result, i, len;
|
727
|
+
result = ['('];
|
728
|
+
for (i = 0, len = node.params.length; i < len; i += 1) {
|
729
|
+
result.push(node.params[i].name);
|
730
|
+
if (i + 1 < len) {
|
731
|
+
result.push(',' + space);
|
732
|
+
}
|
733
|
+
}
|
734
|
+
result.push(')', maybeBlock(node.body));
|
735
|
+
return result;
|
736
|
+
}
|
737
|
+
|
738
|
+
function generateExpression(expr, option) {
|
739
|
+
var result, precedence, currentPrecedence, i, len, raw, fragment, multiline, leftChar, leftSource, rightChar, rightSource, allowIn, allowCall, allowUnparenthesizedNew;
|
740
|
+
|
741
|
+
precedence = option.precedence;
|
742
|
+
allowIn = option.allowIn;
|
743
|
+
allowCall = option.allowCall;
|
744
|
+
|
745
|
+
switch (expr.type) {
|
746
|
+
case Syntax.SequenceExpression:
|
747
|
+
result = [];
|
748
|
+
allowIn |= (Precedence.Sequence < precedence);
|
749
|
+
for (i = 0, len = expr.expressions.length; i < len; i += 1) {
|
750
|
+
result.push(generateExpression(expr.expressions[i], {
|
751
|
+
precedence: Precedence.Assignment,
|
752
|
+
allowIn: allowIn,
|
753
|
+
allowCall: true
|
754
|
+
}));
|
755
|
+
if (i + 1 < len) {
|
756
|
+
result.push(',' + space);
|
757
|
+
}
|
758
|
+
}
|
759
|
+
result = parenthesize(result, Precedence.Sequence, precedence);
|
760
|
+
break;
|
761
|
+
|
762
|
+
case Syntax.AssignmentExpression:
|
763
|
+
allowIn |= (Precedence.Assignment < precedence);
|
764
|
+
result = parenthesize(
|
765
|
+
[
|
766
|
+
generateExpression(expr.left, {
|
767
|
+
precedence: Precedence.Call,
|
768
|
+
allowIn: allowIn,
|
769
|
+
allowCall: true
|
770
|
+
}),
|
771
|
+
space + expr.operator + space,
|
772
|
+
generateExpression(expr.right, {
|
773
|
+
precedence: Precedence.Assignment,
|
774
|
+
allowIn: allowIn,
|
775
|
+
allowCall: true
|
776
|
+
})
|
777
|
+
],
|
778
|
+
Precedence.Assignment,
|
779
|
+
precedence
|
780
|
+
);
|
781
|
+
break;
|
782
|
+
|
783
|
+
case Syntax.ConditionalExpression:
|
784
|
+
allowIn |= (Precedence.Conditional < precedence);
|
785
|
+
result = parenthesize(
|
786
|
+
[
|
787
|
+
generateExpression(expr.test, {
|
788
|
+
precedence: Precedence.LogicalOR,
|
789
|
+
allowIn: allowIn,
|
790
|
+
allowCall: true
|
791
|
+
}),
|
792
|
+
space + '?' + space,
|
793
|
+
generateExpression(expr.consequent, {
|
794
|
+
precedence: Precedence.Assignment,
|
795
|
+
allowIn: allowIn,
|
796
|
+
allowCall: true
|
797
|
+
}),
|
798
|
+
space + ':' + space,
|
799
|
+
generateExpression(expr.alternate, {
|
800
|
+
precedence: Precedence.Assignment,
|
801
|
+
allowIn: allowIn,
|
802
|
+
allowCall: true
|
803
|
+
})
|
804
|
+
],
|
805
|
+
Precedence.Conditional,
|
806
|
+
precedence
|
807
|
+
);
|
808
|
+
break;
|
809
|
+
|
810
|
+
case Syntax.LogicalExpression:
|
811
|
+
case Syntax.BinaryExpression:
|
812
|
+
currentPrecedence = BinaryPrecedence[expr.operator];
|
813
|
+
|
814
|
+
allowIn |= (currentPrecedence < precedence);
|
815
|
+
|
816
|
+
result = join(
|
817
|
+
generateExpression(expr.left, {
|
818
|
+
precedence: currentPrecedence,
|
819
|
+
allowIn: allowIn,
|
820
|
+
allowCall: true
|
821
|
+
}),
|
822
|
+
expr.operator
|
823
|
+
);
|
824
|
+
|
825
|
+
fragment = generateExpression(expr.right, {
|
826
|
+
precedence: currentPrecedence + 1,
|
827
|
+
allowIn: allowIn,
|
828
|
+
allowCall: true
|
829
|
+
});
|
830
|
+
|
831
|
+
if (expr.operator === '/' && fragment.toString().charAt(0) === '/') {
|
832
|
+
// If '/' concats with '/', it is interpreted as comment start
|
833
|
+
result.push(' ', fragment);
|
834
|
+
} else {
|
835
|
+
result = join(result, fragment);
|
836
|
+
}
|
837
|
+
|
838
|
+
if (expr.operator === 'in' && !allowIn) {
|
839
|
+
result = ['(', result, ')'];
|
840
|
+
} else {
|
841
|
+
result = parenthesize(result, currentPrecedence, precedence);
|
842
|
+
}
|
843
|
+
|
844
|
+
break;
|
845
|
+
|
846
|
+
case Syntax.CallExpression:
|
847
|
+
result = [generateExpression(expr.callee, {
|
848
|
+
precedence: Precedence.Call,
|
849
|
+
allowIn: true,
|
850
|
+
allowCall: true,
|
851
|
+
allowUnparenthesizedNew: false
|
852
|
+
})];
|
853
|
+
|
854
|
+
result.push('(');
|
855
|
+
for (i = 0, len = expr['arguments'].length; i < len; i += 1) {
|
856
|
+
result.push(generateExpression(expr['arguments'][i], {
|
857
|
+
precedence: Precedence.Assignment,
|
858
|
+
allowIn: true,
|
859
|
+
allowCall: true
|
860
|
+
}));
|
861
|
+
if (i + 1 < len) {
|
862
|
+
result.push(',' + space);
|
863
|
+
}
|
864
|
+
}
|
865
|
+
result.push(')');
|
866
|
+
|
867
|
+
if (!allowCall) {
|
868
|
+
result = ['(', result, ')'];
|
869
|
+
} else {
|
870
|
+
result = parenthesize(result, Precedence.Call, precedence);
|
871
|
+
}
|
872
|
+
break;
|
873
|
+
|
874
|
+
case Syntax.NewExpression:
|
875
|
+
len = expr['arguments'].length;
|
876
|
+
allowUnparenthesizedNew = option.allowUnparenthesizedNew === undefined || option.allowUnparenthesizedNew;
|
877
|
+
|
878
|
+
result = join(
|
879
|
+
'new',
|
880
|
+
generateExpression(expr.callee, {
|
881
|
+
precedence: Precedence.New,
|
882
|
+
allowIn: true,
|
883
|
+
allowCall: false,
|
884
|
+
allowUnparenthesizedNew: allowUnparenthesizedNew && !parentheses && len === 0
|
885
|
+
})
|
886
|
+
);
|
887
|
+
|
888
|
+
if (!allowUnparenthesizedNew || parentheses || len > 0) {
|
889
|
+
result.push('(');
|
890
|
+
for (i = 0; i < len; i += 1) {
|
891
|
+
result.push(generateExpression(expr['arguments'][i], {
|
892
|
+
precedence: Precedence.Assignment,
|
893
|
+
allowIn: true,
|
894
|
+
allowCall: true
|
895
|
+
}));
|
896
|
+
if (i + 1 < len) {
|
897
|
+
result.push(',' + space);
|
898
|
+
}
|
899
|
+
}
|
900
|
+
result.push(')');
|
901
|
+
}
|
902
|
+
|
903
|
+
result = parenthesize(result, Precedence.New, precedence);
|
904
|
+
break;
|
905
|
+
|
906
|
+
case Syntax.MemberExpression:
|
907
|
+
result = [generateExpression(expr.object, {
|
908
|
+
precedence: Precedence.Call,
|
909
|
+
allowIn: true,
|
910
|
+
allowCall: allowCall,
|
911
|
+
allowUnparenthesizedNew: false
|
912
|
+
})];
|
913
|
+
|
914
|
+
if (expr.computed) {
|
915
|
+
result.push('[', generateExpression(expr.property, {
|
916
|
+
precedence: Precedence.Sequence,
|
917
|
+
allowIn: true,
|
918
|
+
allowCall: allowCall
|
919
|
+
}), ']');
|
920
|
+
} else {
|
921
|
+
if (expr.object.type === Syntax.Literal && typeof expr.object.value === 'number') {
|
922
|
+
if (result.indexOf('.') < 0) {
|
923
|
+
if (!/[eExX]/.test(result) && !(result.length >= 2 && result[0] === '0')) {
|
924
|
+
result.push('.');
|
925
|
+
}
|
926
|
+
}
|
927
|
+
}
|
928
|
+
result.push('.' + expr.property.name);
|
929
|
+
}
|
930
|
+
|
931
|
+
result = parenthesize(result, Precedence.Member, precedence);
|
932
|
+
break;
|
933
|
+
|
934
|
+
case Syntax.UnaryExpression:
|
935
|
+
fragment = generateExpression(expr.argument, {
|
936
|
+
precedence: Precedence.Unary,
|
937
|
+
allowIn: true,
|
938
|
+
allowCall: true
|
939
|
+
});
|
940
|
+
|
941
|
+
if (space === '') {
|
942
|
+
result = join(expr.operator, fragment);
|
943
|
+
} else {
|
944
|
+
result = [expr.operator];
|
945
|
+
if (expr.operator.length > 2) {
|
946
|
+
// delete, void, typeof
|
947
|
+
// get `typeof []`, not `typeof[]`
|
948
|
+
result = join(result, fragment);
|
949
|
+
} else {
|
950
|
+
// Prevent inserting spaces between operator and argument if it is unnecessary
|
951
|
+
// like, `!cond`
|
952
|
+
leftSource = toSourceNode(result).toString();
|
953
|
+
leftChar = leftSource.charAt(leftSource.length - 1);
|
954
|
+
rightChar = fragment.toString().charAt(0);
|
955
|
+
|
956
|
+
if (((leftChar === '+' || leftChar === '-') && leftChar === rightChar) || (isIdentifierPart(leftChar) && isIdentifierPart(rightChar))) {
|
957
|
+
result.push(' ', fragment);
|
958
|
+
} else {
|
959
|
+
result.push(fragment);
|
960
|
+
}
|
961
|
+
}
|
962
|
+
}
|
963
|
+
result = parenthesize(result, Precedence.Unary, precedence);
|
964
|
+
break;
|
965
|
+
|
966
|
+
case Syntax.UpdateExpression:
|
967
|
+
if (expr.prefix) {
|
968
|
+
result = parenthesize(
|
969
|
+
[
|
970
|
+
expr.operator,
|
971
|
+
generateExpression(expr.argument, {
|
972
|
+
precedence: Precedence.Unary,
|
973
|
+
allowIn: true,
|
974
|
+
allowCall: true
|
975
|
+
})
|
976
|
+
],
|
977
|
+
Precedence.Unary,
|
978
|
+
precedence
|
979
|
+
);
|
980
|
+
} else {
|
981
|
+
result = parenthesize(
|
982
|
+
[
|
983
|
+
generateExpression(expr.argument, {
|
984
|
+
precedence: Precedence.Postfix,
|
985
|
+
allowIn: true,
|
986
|
+
allowCall: true
|
987
|
+
}),
|
988
|
+
expr.operator
|
989
|
+
],
|
990
|
+
Precedence.Postfix,
|
991
|
+
precedence
|
992
|
+
);
|
993
|
+
}
|
994
|
+
break;
|
995
|
+
|
996
|
+
case Syntax.FunctionExpression:
|
997
|
+
result = 'function';
|
998
|
+
if (expr.id) {
|
999
|
+
result += ' ' + expr.id.name;
|
1000
|
+
} else {
|
1001
|
+
result += space;
|
1002
|
+
}
|
1003
|
+
result = [result, generateFunctionBody(expr)];
|
1004
|
+
break;
|
1005
|
+
|
1006
|
+
case Syntax.ArrayExpression:
|
1007
|
+
if (!expr.elements.length) {
|
1008
|
+
result = '[]';
|
1009
|
+
break;
|
1010
|
+
}
|
1011
|
+
multiline = expr.elements.length > 1;
|
1012
|
+
result = ['[', multiline ? newline : ''];
|
1013
|
+
withIndent(function (indent) {
|
1014
|
+
for (i = 0, len = expr.elements.length; i < len; i += 1) {
|
1015
|
+
if (!expr.elements[i]) {
|
1016
|
+
if(multiline) {
|
1017
|
+
result.push(indent);
|
1018
|
+
}
|
1019
|
+
if (i + 1 === len) {
|
1020
|
+
result.push(',');
|
1021
|
+
}
|
1022
|
+
} else {
|
1023
|
+
result.push(multiline ? indent: '', generateExpression(expr.elements[i], {
|
1024
|
+
precedence: Precedence.Assignment,
|
1025
|
+
allowIn: true,
|
1026
|
+
allowCall: true
|
1027
|
+
}));
|
1028
|
+
}
|
1029
|
+
if (i + 1 < len) {
|
1030
|
+
result.push(',' + (multiline ? newline : space));
|
1031
|
+
}
|
1032
|
+
}
|
1033
|
+
});
|
1034
|
+
if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
|
1035
|
+
result.push(newline);
|
1036
|
+
}
|
1037
|
+
result.push(multiline ? base : '', ']');
|
1038
|
+
break;
|
1039
|
+
|
1040
|
+
case Syntax.Property:
|
1041
|
+
if (expr.kind === 'get' || expr.kind === 'set') {
|
1042
|
+
result = [
|
1043
|
+
expr.kind + ' ',
|
1044
|
+
generateExpression(expr.key, {
|
1045
|
+
precedence: Precedence.Sequence,
|
1046
|
+
allowIn: true,
|
1047
|
+
allowCall: true
|
1048
|
+
}),
|
1049
|
+
generateFunctionBody(expr.value)
|
1050
|
+
];
|
1051
|
+
} else {
|
1052
|
+
result = [
|
1053
|
+
generateExpression(expr.key, {
|
1054
|
+
precedence: Precedence.Sequence,
|
1055
|
+
allowIn: true,
|
1056
|
+
allowCall: true
|
1057
|
+
}),
|
1058
|
+
':' + space,
|
1059
|
+
generateExpression(expr.value, {
|
1060
|
+
precedence: Precedence.Assignment,
|
1061
|
+
allowIn: true,
|
1062
|
+
allowCall: true
|
1063
|
+
})
|
1064
|
+
];
|
1065
|
+
}
|
1066
|
+
break;
|
1067
|
+
|
1068
|
+
case Syntax.ObjectExpression:
|
1069
|
+
if (!expr.properties.length) {
|
1070
|
+
result = '{}';
|
1071
|
+
break;
|
1072
|
+
}
|
1073
|
+
multiline = expr.properties.length > 1;
|
1074
|
+
result = ['{', multiline ? newline : ''];
|
1075
|
+
|
1076
|
+
withIndent(function (indent) {
|
1077
|
+
for (i = 0, len = expr.properties.length; i < len; i += 1) {
|
1078
|
+
result.push(multiline ? indent : '', generateExpression(expr.properties[i], {
|
1079
|
+
precedence: Precedence.Sequence,
|
1080
|
+
allowIn: true,
|
1081
|
+
allowCall: true
|
1082
|
+
}));
|
1083
|
+
if (i + 1 < len) {
|
1084
|
+
result.push(',' + (multiline ? newline : space));
|
1085
|
+
}
|
1086
|
+
}
|
1087
|
+
});
|
1088
|
+
|
1089
|
+
if (multiline && !endsWithLineTerminator(toSourceNode(result).toString())) {
|
1090
|
+
result.push(newline);
|
1091
|
+
}
|
1092
|
+
result.push(multiline ? base : '', '}');
|
1093
|
+
break;
|
1094
|
+
|
1095
|
+
case Syntax.ThisExpression:
|
1096
|
+
result = 'this';
|
1097
|
+
break;
|
1098
|
+
|
1099
|
+
case Syntax.Identifier:
|
1100
|
+
result = expr.name;
|
1101
|
+
break;
|
1102
|
+
|
1103
|
+
case Syntax.Literal:
|
1104
|
+
if (expr.hasOwnProperty('raw') && parse) {
|
1105
|
+
try {
|
1106
|
+
raw = parse(expr.raw).body[0].expression;
|
1107
|
+
if (raw.type === Syntax.Literal) {
|
1108
|
+
if (raw.value === expr.value) {
|
1109
|
+
result = expr.raw;
|
1110
|
+
break;
|
1111
|
+
}
|
1112
|
+
}
|
1113
|
+
} catch (e) {
|
1114
|
+
// not use raw property
|
1115
|
+
}
|
1116
|
+
}
|
1117
|
+
|
1118
|
+
if (expr.value === null) {
|
1119
|
+
result = 'null';
|
1120
|
+
break;
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
if (typeof expr.value === 'string') {
|
1124
|
+
result = escapeString(expr.value);
|
1125
|
+
break;
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
if (typeof expr.value === 'number') {
|
1129
|
+
result = generateNumber(expr.value);
|
1130
|
+
break;
|
1131
|
+
}
|
1132
|
+
|
1133
|
+
result = expr.value.toString();
|
1134
|
+
break;
|
1135
|
+
|
1136
|
+
default:
|
1137
|
+
throw new Error('Unknown expression type: ' + expr.type);
|
1138
|
+
}
|
1139
|
+
|
1140
|
+
return toSourceNode(result, expr);
|
1141
|
+
}
|
1142
|
+
|
1143
|
+
function generateStatement(stmt, option) {
|
1144
|
+
var i, len, result, node, allowIn, fragment, semicolon;
|
1145
|
+
|
1146
|
+
allowIn = true;
|
1147
|
+
semicolon = ';';
|
1148
|
+
if (option) {
|
1149
|
+
allowIn = option.allowIn === undefined || option.allowIn;
|
1150
|
+
if (!semicolons && option.semicolonOptional === true) {
|
1151
|
+
semicolon = '';
|
1152
|
+
}
|
1153
|
+
}
|
1154
|
+
|
1155
|
+
switch (stmt.type) {
|
1156
|
+
case Syntax.BlockStatement:
|
1157
|
+
result = ['{', newline];
|
1158
|
+
|
1159
|
+
withIndent(function () {
|
1160
|
+
for (i = 0, len = stmt.body.length; i < len; i += 1) {
|
1161
|
+
fragment = addIndent(generateStatement(stmt.body[i], {semicolonOptional: i === len - 1}));
|
1162
|
+
result.push(fragment);
|
1163
|
+
if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
|
1164
|
+
result.push(newline);
|
1165
|
+
}
|
1166
|
+
}
|
1167
|
+
});
|
1168
|
+
|
1169
|
+
result.push(addIndent('}'));
|
1170
|
+
break;
|
1171
|
+
|
1172
|
+
case Syntax.BreakStatement:
|
1173
|
+
if (stmt.label) {
|
1174
|
+
result = 'break ' + stmt.label.name + semicolon;
|
1175
|
+
} else {
|
1176
|
+
result = 'break' + semicolon;
|
1177
|
+
}
|
1178
|
+
break;
|
1179
|
+
|
1180
|
+
case Syntax.ContinueStatement:
|
1181
|
+
if (stmt.label) {
|
1182
|
+
result = 'continue ' + stmt.label.name + semicolon;
|
1183
|
+
} else {
|
1184
|
+
result = 'continue' + semicolon;
|
1185
|
+
}
|
1186
|
+
break;
|
1187
|
+
|
1188
|
+
case Syntax.DoWhileStatement:
|
1189
|
+
// Because `do 42 while (cond)` is Syntax Error. We need semicolon.
|
1190
|
+
result = join('do', maybeBlock(stmt.body));
|
1191
|
+
result = maybeBlockSuffix(stmt.body, result);
|
1192
|
+
result = join(result, [
|
1193
|
+
'while' + space + '(',
|
1194
|
+
generateExpression(stmt.test, {
|
1195
|
+
precedence: Precedence.Sequence,
|
1196
|
+
allowIn: true,
|
1197
|
+
allowCall: true
|
1198
|
+
}),
|
1199
|
+
')' + semicolon
|
1200
|
+
]);
|
1201
|
+
break;
|
1202
|
+
|
1203
|
+
case Syntax.CatchClause:
|
1204
|
+
withIndent(function () {
|
1205
|
+
result = [
|
1206
|
+
'catch' + space + '(',
|
1207
|
+
generateExpression(stmt.param, {
|
1208
|
+
precedence: Precedence.Sequence,
|
1209
|
+
allowIn: true,
|
1210
|
+
allowCall: true
|
1211
|
+
}),
|
1212
|
+
')'
|
1213
|
+
];
|
1214
|
+
});
|
1215
|
+
result.push(maybeBlock(stmt.body));
|
1216
|
+
break;
|
1217
|
+
|
1218
|
+
case Syntax.DebuggerStatement:
|
1219
|
+
result = 'debugger' + semicolon;
|
1220
|
+
break;
|
1221
|
+
|
1222
|
+
case Syntax.EmptyStatement:
|
1223
|
+
result = ';';
|
1224
|
+
break;
|
1225
|
+
|
1226
|
+
case Syntax.ExpressionStatement:
|
1227
|
+
result = [generateExpression(stmt.expression, {
|
1228
|
+
precedence: Precedence.Sequence,
|
1229
|
+
allowIn: true,
|
1230
|
+
allowCall: true
|
1231
|
+
})];
|
1232
|
+
// 12.4 '{', 'function' is not allowed in this position.
|
1233
|
+
// wrap expression with parentheses
|
1234
|
+
if (result.toString().charAt(0) === '{' || (result.toString().slice(0, 8) === 'function' && " (".indexOf(result.toString().charAt(8)) >= 0)) {
|
1235
|
+
result = ['(', result, ')' + semicolon];
|
1236
|
+
} else {
|
1237
|
+
result.push(semicolon);
|
1238
|
+
}
|
1239
|
+
break;
|
1240
|
+
|
1241
|
+
case Syntax.VariableDeclarator:
|
1242
|
+
if (stmt.init) {
|
1243
|
+
result = [
|
1244
|
+
stmt.id.name + space + '=' + space,
|
1245
|
+
generateExpression(stmt.init, {
|
1246
|
+
precedence: Precedence.Assignment,
|
1247
|
+
allowIn: allowIn,
|
1248
|
+
allowCall: true
|
1249
|
+
})
|
1250
|
+
];
|
1251
|
+
} else {
|
1252
|
+
result = stmt.id.name;
|
1253
|
+
}
|
1254
|
+
break;
|
1255
|
+
|
1256
|
+
case Syntax.VariableDeclaration:
|
1257
|
+
result = [stmt.kind];
|
1258
|
+
// special path for
|
1259
|
+
// var x = function () {
|
1260
|
+
// };
|
1261
|
+
if (stmt.declarations.length === 1 && stmt.declarations[0].init &&
|
1262
|
+
stmt.declarations[0].init.type === Syntax.FunctionExpression) {
|
1263
|
+
result.push(' ', generateStatement(stmt.declarations[0], {
|
1264
|
+
allowIn: allowIn
|
1265
|
+
}));
|
1266
|
+
} else {
|
1267
|
+
// VariableDeclarator is typed as Statement,
|
1268
|
+
// but joined with comma (not LineTerminator).
|
1269
|
+
// So if comment is attached to target node, we should specialize.
|
1270
|
+
withIndent(function () {
|
1271
|
+
node = stmt.declarations[0];
|
1272
|
+
if (extra.comment && node.leadingComments) {
|
1273
|
+
result.push('\n', addIndent(generateStatement(node, {
|
1274
|
+
allowIn: allowIn
|
1275
|
+
})));
|
1276
|
+
} else {
|
1277
|
+
result.push(' ', generateStatement(node, {
|
1278
|
+
allowIn: allowIn
|
1279
|
+
}));
|
1280
|
+
}
|
1281
|
+
|
1282
|
+
for (i = 1, len = stmt.declarations.length; i < len; i += 1) {
|
1283
|
+
node = stmt.declarations[i];
|
1284
|
+
if (extra.comment && node.leadingComments) {
|
1285
|
+
result.push(',' + newline, addIndent(generateStatement(node, {
|
1286
|
+
allowIn: allowIn
|
1287
|
+
})));
|
1288
|
+
} else {
|
1289
|
+
result.push(',' + space, generateStatement(node, {
|
1290
|
+
allowIn: allowIn
|
1291
|
+
}));
|
1292
|
+
}
|
1293
|
+
}
|
1294
|
+
});
|
1295
|
+
}
|
1296
|
+
result.push(semicolon);
|
1297
|
+
break;
|
1298
|
+
|
1299
|
+
case Syntax.ThrowStatement:
|
1300
|
+
result = [join(
|
1301
|
+
'throw',
|
1302
|
+
generateExpression(stmt.argument, {
|
1303
|
+
precedence: Precedence.Sequence,
|
1304
|
+
allowIn: true,
|
1305
|
+
allowCall: true
|
1306
|
+
})
|
1307
|
+
), semicolon];
|
1308
|
+
break;
|
1309
|
+
|
1310
|
+
case Syntax.TryStatement:
|
1311
|
+
result = ['try', maybeBlock(stmt.block)];
|
1312
|
+
result = maybeBlockSuffix(stmt.block, result);
|
1313
|
+
for (i = 0, len = stmt.handlers.length; i < len; i += 1) {
|
1314
|
+
result = join(result, generateStatement(stmt.handlers[i]));
|
1315
|
+
if (stmt.finalizer || i + 1 !== len) {
|
1316
|
+
result = maybeBlockSuffix(stmt.handlers[i].body, result);
|
1317
|
+
}
|
1318
|
+
}
|
1319
|
+
if (stmt.finalizer) {
|
1320
|
+
result = join(result, ['finally', maybeBlock(stmt.finalizer)]);
|
1321
|
+
}
|
1322
|
+
break;
|
1323
|
+
|
1324
|
+
case Syntax.SwitchStatement:
|
1325
|
+
withIndent(function () {
|
1326
|
+
result = [
|
1327
|
+
'switch' + space + '(',
|
1328
|
+
generateExpression(stmt.discriminant, {
|
1329
|
+
precedence: Precedence.Sequence,
|
1330
|
+
allowIn: true,
|
1331
|
+
allowCall: true
|
1332
|
+
}),
|
1333
|
+
')' + space + '{' + newline
|
1334
|
+
];
|
1335
|
+
});
|
1336
|
+
if (stmt.cases) {
|
1337
|
+
for (i = 0, len = stmt.cases.length; i < len; i += 1) {
|
1338
|
+
fragment = addIndent(generateStatement(stmt.cases[i], {semicolonOptional: i === len - 1}));
|
1339
|
+
result.push(fragment);
|
1340
|
+
if (!endsWithLineTerminator(toSourceNode(fragment).toString())) {
|
1341
|
+
result.push(newline);
|
1342
|
+
}
|
1343
|
+
}
|
1344
|
+
}
|
1345
|
+
result.push(addIndent('}'));
|
1346
|
+
break;
|
1347
|
+
|
1348
|
+
case Syntax.SwitchCase:
|
1349
|
+
withIndent(function () {
|
1350
|
+
if (stmt.test) {
|
1351
|
+
result = [
|
1352
|
+
join('case', generateExpression(stmt.test, {
|
1353
|
+
precedence: Precedence.Sequence,
|
1354
|
+
allowIn: true,
|
1355
|
+
allowCall: true
|
1356
|
+
})),
|
1357
|
+
':'
|
1358
|
+
];
|
1359
|
+
} else {
|
1360
|
+
result = ['default:'];
|
1361
|
+
}
|
1362
|
+
|
1363
|
+
i = 0;
|
1364
|
+
len = stmt.consequent.length;
|
1365
|
+
if (len && stmt.consequent[0].type === Syntax.BlockStatement) {
|
1366
|
+
fragment = maybeBlock(stmt.consequent[0]);
|
1367
|
+
result.push(fragment);
|
1368
|
+
i = 1;
|
1369
|
+
}
|
1370
|
+
|
1371
|
+
if (i !== len && !endsWithLineTerminator(toSourceNode(result).toString())) {
|
1372
|
+
result.push(newline);
|
1373
|
+
}
|
1374
|
+
|
1375
|
+
for (; i < len; i += 1) {
|
1376
|
+
fragment = addIndent(generateStatement(stmt.consequent[i], {semicolonOptional: i === len - 1 && semicolon === ''}));
|
1377
|
+
result.push(fragment);
|
1378
|
+
if (i + 1 !== len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
|
1379
|
+
result.push(newline);
|
1380
|
+
}
|
1381
|
+
}
|
1382
|
+
});
|
1383
|
+
break;
|
1384
|
+
|
1385
|
+
case Syntax.IfStatement:
|
1386
|
+
withIndent(function () {
|
1387
|
+
result = [
|
1388
|
+
'if'+ space + '(',
|
1389
|
+
generateExpression(stmt.test, {
|
1390
|
+
precedence: Precedence.Sequence,
|
1391
|
+
allowIn: true,
|
1392
|
+
allowCall: true
|
1393
|
+
}),
|
1394
|
+
')'
|
1395
|
+
];
|
1396
|
+
});
|
1397
|
+
if (stmt.alternate) {
|
1398
|
+
result.push(maybeBlock(stmt.consequent));
|
1399
|
+
result = maybeBlockSuffix(stmt.consequent, result);
|
1400
|
+
if (stmt.alternate.type === Syntax.IfStatement) {
|
1401
|
+
result = join(result, ['else ', generateStatement(stmt.alternate, {semicolonOptional: semicolon === ''})]);
|
1402
|
+
} else {
|
1403
|
+
result = join(result, join('else', maybeBlock(stmt.alternate, semicolon === '')));
|
1404
|
+
}
|
1405
|
+
} else {
|
1406
|
+
result.push(maybeBlock(stmt.consequent, semicolon === ''));
|
1407
|
+
}
|
1408
|
+
break;
|
1409
|
+
|
1410
|
+
case Syntax.ForStatement:
|
1411
|
+
withIndent(function () {
|
1412
|
+
result = ['for' + space + '('];
|
1413
|
+
if (stmt.init) {
|
1414
|
+
if (stmt.init.type === Syntax.VariableDeclaration) {
|
1415
|
+
result.push(generateStatement(stmt.init, {allowIn: false}));
|
1416
|
+
} else {
|
1417
|
+
result.push(generateExpression(stmt.init, {
|
1418
|
+
precedence: Precedence.Sequence,
|
1419
|
+
allowIn: false,
|
1420
|
+
allowCall: true
|
1421
|
+
}), ';');
|
1422
|
+
}
|
1423
|
+
} else {
|
1424
|
+
result.push(';');
|
1425
|
+
}
|
1426
|
+
|
1427
|
+
if (stmt.test) {
|
1428
|
+
result.push(space, generateExpression(stmt.test, {
|
1429
|
+
precedence: Precedence.Sequence,
|
1430
|
+
allowIn: true,
|
1431
|
+
allowCall: true
|
1432
|
+
}), ';');
|
1433
|
+
} else {
|
1434
|
+
result.push(';');
|
1435
|
+
}
|
1436
|
+
|
1437
|
+
if (stmt.update) {
|
1438
|
+
result.push(space, generateExpression(stmt.update, {
|
1439
|
+
precedence: Precedence.Sequence,
|
1440
|
+
allowIn: true,
|
1441
|
+
allowCall: true
|
1442
|
+
}), ')');
|
1443
|
+
} else {
|
1444
|
+
result.push(')');
|
1445
|
+
}
|
1446
|
+
});
|
1447
|
+
|
1448
|
+
result.push(maybeBlock(stmt.body, semicolon === ''));
|
1449
|
+
break;
|
1450
|
+
|
1451
|
+
case Syntax.ForInStatement:
|
1452
|
+
result = ['for' + space + '('];
|
1453
|
+
withIndent(function () {
|
1454
|
+
if (stmt.left.type === Syntax.VariableDeclaration) {
|
1455
|
+
withIndent(function () {
|
1456
|
+
result.push(stmt.left.kind + ' ', generateStatement(stmt.left.declarations[0], {
|
1457
|
+
allowIn: false
|
1458
|
+
}));
|
1459
|
+
});
|
1460
|
+
} else {
|
1461
|
+
result.push(generateExpression(stmt.left, {
|
1462
|
+
precedence: Precedence.Call,
|
1463
|
+
allowIn: true,
|
1464
|
+
allowCall: true
|
1465
|
+
}));
|
1466
|
+
}
|
1467
|
+
|
1468
|
+
result = join(result, 'in');
|
1469
|
+
result = [join(
|
1470
|
+
result,
|
1471
|
+
generateExpression(stmt.right, {
|
1472
|
+
precedence: Precedence.Sequence,
|
1473
|
+
allowIn: true,
|
1474
|
+
allowCall: true
|
1475
|
+
})
|
1476
|
+
), ')'];
|
1477
|
+
});
|
1478
|
+
result.push(maybeBlock(stmt.body, semicolon === ''));
|
1479
|
+
break;
|
1480
|
+
|
1481
|
+
case Syntax.LabeledStatement:
|
1482
|
+
result = [stmt.label.name + ':', maybeBlock(stmt.body, semicolon === '')];
|
1483
|
+
break;
|
1484
|
+
|
1485
|
+
case Syntax.Program:
|
1486
|
+
len = stmt.body.length;
|
1487
|
+
result = [safeConcatenation && len > 0 ? '\n' : ''];
|
1488
|
+
for (i = 0; i < len; i += 1) {
|
1489
|
+
fragment = addIndent(generateStatement(stmt.body[i], {semicolonOptional: !safeConcatenation && i === len - 1}));
|
1490
|
+
result.push(fragment);
|
1491
|
+
if (i + 1 < len && !endsWithLineTerminator(toSourceNode(fragment).toString())) {
|
1492
|
+
result.push(newline);
|
1493
|
+
}
|
1494
|
+
}
|
1495
|
+
break;
|
1496
|
+
|
1497
|
+
case Syntax.FunctionDeclaration:
|
1498
|
+
result = ['function ' + stmt.id.name, generateFunctionBody(stmt)];
|
1499
|
+
break;
|
1500
|
+
|
1501
|
+
case Syntax.ReturnStatement:
|
1502
|
+
if (stmt.argument) {
|
1503
|
+
result = [join(
|
1504
|
+
'return',
|
1505
|
+
generateExpression(stmt.argument, {
|
1506
|
+
precedence: Precedence.Sequence,
|
1507
|
+
allowIn: true,
|
1508
|
+
allowCall: true
|
1509
|
+
})
|
1510
|
+
), semicolon];
|
1511
|
+
} else {
|
1512
|
+
result = ['return' + semicolon];
|
1513
|
+
}
|
1514
|
+
break;
|
1515
|
+
|
1516
|
+
case Syntax.WhileStatement:
|
1517
|
+
withIndent(function () {
|
1518
|
+
result = [
|
1519
|
+
'while' + space + '(',
|
1520
|
+
generateExpression(stmt.test, {
|
1521
|
+
precedence: Precedence.Sequence,
|
1522
|
+
allowIn: true,
|
1523
|
+
allowCall: true
|
1524
|
+
}),
|
1525
|
+
')'
|
1526
|
+
];
|
1527
|
+
});
|
1528
|
+
result.push(maybeBlock(stmt.body, semicolon === ''));
|
1529
|
+
break;
|
1530
|
+
|
1531
|
+
case Syntax.WithStatement:
|
1532
|
+
withIndent(function () {
|
1533
|
+
result = [
|
1534
|
+
'with' + space + '(',
|
1535
|
+
generateExpression(stmt.object, {
|
1536
|
+
precedence: Precedence.Sequence,
|
1537
|
+
allowIn: true,
|
1538
|
+
allowCall: true
|
1539
|
+
}),
|
1540
|
+
')'
|
1541
|
+
];
|
1542
|
+
});
|
1543
|
+
result.push(maybeBlock(stmt.body, semicolon === ''));
|
1544
|
+
break;
|
1545
|
+
|
1546
|
+
default:
|
1547
|
+
throw new Error('Unknown statement type: ' + stmt.type);
|
1548
|
+
}
|
1549
|
+
|
1550
|
+
// Attach comments
|
1551
|
+
|
1552
|
+
if (extra.comment) {
|
1553
|
+
result = addCommentsToStatement(stmt, result);
|
1554
|
+
}
|
1555
|
+
|
1556
|
+
var fragment = toSourceNode(result).toString();
|
1557
|
+
if (stmt.type === Syntax.Program && !safeConcatenation && newline === '' && fragment.charAt(fragment.length - 1) === '\n') {
|
1558
|
+
result = toSourceNode(result).replaceRight(/\s+$/, '');
|
1559
|
+
}
|
1560
|
+
|
1561
|
+
return toSourceNode(result, stmt);
|
1562
|
+
}
|
1563
|
+
|
1564
|
+
function generate(node, options) {
|
1565
|
+
var defaultOptions = getDefaultOptions(), result, pair;
|
1566
|
+
|
1567
|
+
if (options != null) {
|
1568
|
+
// Obsolete options
|
1569
|
+
//
|
1570
|
+
// `options.indent`
|
1571
|
+
// `options.base`
|
1572
|
+
//
|
1573
|
+
// Instead of them, we can use `option.format.indent`.
|
1574
|
+
if (typeof options.indent === 'string') {
|
1575
|
+
defaultOptions.format.indent.style = options.indent;
|
1576
|
+
}
|
1577
|
+
if (typeof options.base === 'number') {
|
1578
|
+
defaultOptions.format.indent.base = options.base;
|
1579
|
+
}
|
1580
|
+
options = updateDeeply(defaultOptions, options);
|
1581
|
+
indent = options.format.indent.style;
|
1582
|
+
if (typeof options.base === 'string') {
|
1583
|
+
base = options.base;
|
1584
|
+
} else {
|
1585
|
+
base = stringRepeat(indent, options.format.indent.base);
|
1586
|
+
}
|
1587
|
+
} else {
|
1588
|
+
options = defaultOptions;
|
1589
|
+
indent = options.format.indent.style;
|
1590
|
+
base = stringRepeat(indent, options.format.indent.base);
|
1591
|
+
}
|
1592
|
+
json = options.format.json;
|
1593
|
+
renumber = options.format.renumber;
|
1594
|
+
hexadecimal = json ? false : options.format.hexadecimal;
|
1595
|
+
quotes = json ? 'double' : options.format.quotes;
|
1596
|
+
escapeless = options.format.escapeless;
|
1597
|
+
if (options.format.compact) {
|
1598
|
+
newline = space = indent = base = '';
|
1599
|
+
} else {
|
1600
|
+
newline = '\n';
|
1601
|
+
space = ' ';
|
1602
|
+
}
|
1603
|
+
parentheses = options.format.parentheses;
|
1604
|
+
semicolons = options.format.semicolons;
|
1605
|
+
safeConcatenation = options.format.safeConcatenation;
|
1606
|
+
parse = json ? null : options.parse;
|
1607
|
+
sourceMap = options.sourceMap;
|
1608
|
+
extra = options;
|
1609
|
+
|
1610
|
+
if (sourceMap) {
|
1611
|
+
if (typeof process !== 'undefined') {
|
1612
|
+
// We assume environment is node.js
|
1613
|
+
SourceNode = require('source-map').SourceNode;
|
1614
|
+
} else {
|
1615
|
+
SourceNode = global.sourceMap.SourceNode;
|
1616
|
+
}
|
1617
|
+
} else {
|
1618
|
+
SourceNode = SourceNodeMock;
|
1619
|
+
}
|
1620
|
+
|
1621
|
+
switch (node.type) {
|
1622
|
+
case Syntax.BlockStatement:
|
1623
|
+
case Syntax.BreakStatement:
|
1624
|
+
case Syntax.CatchClause:
|
1625
|
+
case Syntax.ContinueStatement:
|
1626
|
+
case Syntax.DoWhileStatement:
|
1627
|
+
case Syntax.DebuggerStatement:
|
1628
|
+
case Syntax.EmptyStatement:
|
1629
|
+
case Syntax.ExpressionStatement:
|
1630
|
+
case Syntax.ForStatement:
|
1631
|
+
case Syntax.ForInStatement:
|
1632
|
+
case Syntax.FunctionDeclaration:
|
1633
|
+
case Syntax.IfStatement:
|
1634
|
+
case Syntax.LabeledStatement:
|
1635
|
+
case Syntax.Program:
|
1636
|
+
case Syntax.ReturnStatement:
|
1637
|
+
case Syntax.SwitchStatement:
|
1638
|
+
case Syntax.SwitchCase:
|
1639
|
+
case Syntax.ThrowStatement:
|
1640
|
+
case Syntax.TryStatement:
|
1641
|
+
case Syntax.VariableDeclaration:
|
1642
|
+
case Syntax.VariableDeclarator:
|
1643
|
+
case Syntax.WhileStatement:
|
1644
|
+
case Syntax.WithStatement:
|
1645
|
+
result = generateStatement(node);
|
1646
|
+
break;
|
1647
|
+
|
1648
|
+
case Syntax.AssignmentExpression:
|
1649
|
+
case Syntax.ArrayExpression:
|
1650
|
+
case Syntax.BinaryExpression:
|
1651
|
+
case Syntax.CallExpression:
|
1652
|
+
case Syntax.ConditionalExpression:
|
1653
|
+
case Syntax.FunctionExpression:
|
1654
|
+
case Syntax.Identifier:
|
1655
|
+
case Syntax.Literal:
|
1656
|
+
case Syntax.LogicalExpression:
|
1657
|
+
case Syntax.MemberExpression:
|
1658
|
+
case Syntax.NewExpression:
|
1659
|
+
case Syntax.ObjectExpression:
|
1660
|
+
case Syntax.Property:
|
1661
|
+
case Syntax.SequenceExpression:
|
1662
|
+
case Syntax.ThisExpression:
|
1663
|
+
case Syntax.UnaryExpression:
|
1664
|
+
case Syntax.UpdateExpression:
|
1665
|
+
result = generateExpression(node, {
|
1666
|
+
precedence: Precedence.Sequence,
|
1667
|
+
allowIn: true,
|
1668
|
+
allowCall: true
|
1669
|
+
});
|
1670
|
+
break;
|
1671
|
+
|
1672
|
+
default:
|
1673
|
+
throw new Error('Unknown node type: ' + node.type);
|
1674
|
+
}
|
1675
|
+
|
1676
|
+
if (!sourceMap) {
|
1677
|
+
return result.toString();
|
1678
|
+
}
|
1679
|
+
|
1680
|
+
pair = result.toStringWithSourceMap({file: options.sourceMap});
|
1681
|
+
|
1682
|
+
if (options.sourceMapWithCode) {
|
1683
|
+
return pair;
|
1684
|
+
}
|
1685
|
+
return pair.map.toString();
|
1686
|
+
}
|
1687
|
+
|
1688
|
+
// simple visitor implementation
|
1689
|
+
|
1690
|
+
VisitorKeys = {
|
1691
|
+
AssignmentExpression: ['left', 'right'],
|
1692
|
+
ArrayExpression: ['elements'],
|
1693
|
+
BlockStatement: ['body'],
|
1694
|
+
BinaryExpression: ['left', 'right'],
|
1695
|
+
BreakStatement: ['label'],
|
1696
|
+
CallExpression: ['callee', 'arguments'],
|
1697
|
+
CatchClause: ['param', 'body'],
|
1698
|
+
ConditionalExpression: ['test', 'consequent', 'alternate'],
|
1699
|
+
ContinueStatement: ['label'],
|
1700
|
+
DoWhileStatement: ['body', 'test'],
|
1701
|
+
DebuggerStatement: [],
|
1702
|
+
EmptyStatement: [],
|
1703
|
+
ExpressionStatement: ['expression'],
|
1704
|
+
ForStatement: ['init', 'test', 'update', 'body'],
|
1705
|
+
ForInStatement: ['left', 'right', 'body'],
|
1706
|
+
FunctionDeclaration: ['id', 'params', 'body'],
|
1707
|
+
FunctionExpression: ['id', 'params', 'body'],
|
1708
|
+
Identifier: [],
|
1709
|
+
IfStatement: ['test', 'consequent', 'alternate'],
|
1710
|
+
Literal: [],
|
1711
|
+
LabeledStatement: ['label', 'body'],
|
1712
|
+
LogicalExpression: ['left', 'right'],
|
1713
|
+
MemberExpression: ['object', 'property'],
|
1714
|
+
NewExpression: ['callee', 'arguments'],
|
1715
|
+
ObjectExpression: ['properties'],
|
1716
|
+
Program: ['body'],
|
1717
|
+
Property: ['key', 'value'],
|
1718
|
+
ReturnStatement: ['argument'],
|
1719
|
+
SequenceExpression: ['expressions'],
|
1720
|
+
SwitchStatement: ['discriminant', 'cases'],
|
1721
|
+
SwitchCase: ['test', 'consequent'],
|
1722
|
+
ThisExpression: [],
|
1723
|
+
ThrowStatement: ['argument'],
|
1724
|
+
TryStatement: ['block', 'handlers', 'finalizer'],
|
1725
|
+
UnaryExpression: ['argument'],
|
1726
|
+
UpdateExpression: ['argument'],
|
1727
|
+
VariableDeclaration: ['declarations'],
|
1728
|
+
VariableDeclarator: ['id', 'init'],
|
1729
|
+
WhileStatement: ['test', 'body'],
|
1730
|
+
WithStatement: ['object', 'body']
|
1731
|
+
};
|
1732
|
+
|
1733
|
+
VisitorOption = {
|
1734
|
+
Break: 1,
|
1735
|
+
Skip: 2
|
1736
|
+
};
|
1737
|
+
|
1738
|
+
function traverse(top, visitor) {
|
1739
|
+
var worklist, leavelist, node, ret, current, current2, candidates, candidate, marker = {};
|
1740
|
+
|
1741
|
+
worklist = [ top ];
|
1742
|
+
leavelist = [ null ];
|
1743
|
+
|
1744
|
+
while (worklist.length) {
|
1745
|
+
node = worklist.pop();
|
1746
|
+
|
1747
|
+
if (node === marker) {
|
1748
|
+
node = leavelist.pop();
|
1749
|
+
if (visitor.leave) {
|
1750
|
+
ret = visitor.leave(node, leavelist[leavelist.length - 1]);
|
1751
|
+
} else {
|
1752
|
+
ret = undefined;
|
1753
|
+
}
|
1754
|
+
if (ret === VisitorOption.Break) {
|
1755
|
+
return;
|
1756
|
+
}
|
1757
|
+
} else if (node) {
|
1758
|
+
if (visitor.enter) {
|
1759
|
+
ret = visitor.enter(node, leavelist[leavelist.length - 1]);
|
1760
|
+
} else {
|
1761
|
+
ret = undefined;
|
1762
|
+
}
|
1763
|
+
|
1764
|
+
if (ret === VisitorOption.Break) {
|
1765
|
+
return;
|
1766
|
+
}
|
1767
|
+
|
1768
|
+
worklist.push(marker);
|
1769
|
+
leavelist.push(node);
|
1770
|
+
|
1771
|
+
if (ret !== VisitorOption.Skip) {
|
1772
|
+
candidates = VisitorKeys[node.type];
|
1773
|
+
current = candidates.length;
|
1774
|
+
while ((current -= 1) >= 0) {
|
1775
|
+
candidate = node[candidates[current]];
|
1776
|
+
if (candidate) {
|
1777
|
+
if (isArray(candidate)) {
|
1778
|
+
current2 = candidate.length;
|
1779
|
+
while ((current2 -= 1) >= 0) {
|
1780
|
+
if (candidate[current2]) {
|
1781
|
+
worklist.push(candidate[current2]);
|
1782
|
+
}
|
1783
|
+
}
|
1784
|
+
} else {
|
1785
|
+
worklist.push(candidate);
|
1786
|
+
}
|
1787
|
+
}
|
1788
|
+
}
|
1789
|
+
}
|
1790
|
+
}
|
1791
|
+
}
|
1792
|
+
}
|
1793
|
+
|
1794
|
+
// based on LLVM libc++ upper_bound / lower_bound
|
1795
|
+
// MIT License
|
1796
|
+
|
1797
|
+
function upperBound(array, func) {
|
1798
|
+
var diff, len, i, current;
|
1799
|
+
|
1800
|
+
len = array.length;
|
1801
|
+
i = 0;
|
1802
|
+
|
1803
|
+
while (len) {
|
1804
|
+
diff = len >>> 1;
|
1805
|
+
current = i + diff;
|
1806
|
+
if (func(array[current])) {
|
1807
|
+
len = diff;
|
1808
|
+
} else {
|
1809
|
+
i = current + 1;
|
1810
|
+
len -= diff + 1;
|
1811
|
+
}
|
1812
|
+
}
|
1813
|
+
return i;
|
1814
|
+
}
|
1815
|
+
|
1816
|
+
function lowerBound(array, func) {
|
1817
|
+
var diff, len, i, current;
|
1818
|
+
|
1819
|
+
len = array.length;
|
1820
|
+
i = 0;
|
1821
|
+
|
1822
|
+
while (len) {
|
1823
|
+
diff = len >>> 1;
|
1824
|
+
current = i + diff;
|
1825
|
+
if (func(array[current])) {
|
1826
|
+
i = current + 1;
|
1827
|
+
len -= diff + 1;
|
1828
|
+
} else {
|
1829
|
+
len = diff;
|
1830
|
+
}
|
1831
|
+
}
|
1832
|
+
return i;
|
1833
|
+
}
|
1834
|
+
|
1835
|
+
function extendCommentRange(comment, tokens) {
|
1836
|
+
var target, token;
|
1837
|
+
|
1838
|
+
target = upperBound(tokens, function search(token) {
|
1839
|
+
return token.range[0] > comment.range[0];
|
1840
|
+
});
|
1841
|
+
|
1842
|
+
comment.extendedRange = [comment.range[0], comment.range[1]];
|
1843
|
+
|
1844
|
+
if (target !== tokens.length) {
|
1845
|
+
comment.extendedRange[1] = tokens[target].range[0];
|
1846
|
+
}
|
1847
|
+
|
1848
|
+
target -= 1;
|
1849
|
+
if (target >= 0) {
|
1850
|
+
if (target < tokens.length) {
|
1851
|
+
comment.extendedRange[0] = tokens[target].range[1];
|
1852
|
+
} else if (token.length) {
|
1853
|
+
comment.extendedRange[1] = tokens[tokens.length - 1].range[0];
|
1854
|
+
}
|
1855
|
+
}
|
1856
|
+
|
1857
|
+
return comment;
|
1858
|
+
}
|
1859
|
+
|
1860
|
+
function attachComments(tree, providedComments, tokens) {
|
1861
|
+
// At first, we should calculate extended comment ranges.
|
1862
|
+
var comments = [], comment, len, i;
|
1863
|
+
|
1864
|
+
if (!tree.range) {
|
1865
|
+
throw new Error('attachComments needs range information');
|
1866
|
+
}
|
1867
|
+
|
1868
|
+
// tokens array is empty, we attach comments to tree as 'leadingComments'
|
1869
|
+
if (!tokens.length) {
|
1870
|
+
if (providedComments.length) {
|
1871
|
+
for (i = 0, len = providedComments.length; i < len; i += 1) {
|
1872
|
+
comment = deepCopy(providedComments[i]);
|
1873
|
+
comment.extendedRange = [0, tree.range[0]];
|
1874
|
+
comments.push(comment);
|
1875
|
+
}
|
1876
|
+
tree.leadingComments = comments;
|
1877
|
+
}
|
1878
|
+
return tree;
|
1879
|
+
}
|
1880
|
+
|
1881
|
+
for (i = 0, len = providedComments.length; i < len; i += 1) {
|
1882
|
+
comments.push(extendCommentRange(deepCopy(providedComments[i]), tokens));
|
1883
|
+
}
|
1884
|
+
|
1885
|
+
// This is based on John Freeman's implementation.
|
1886
|
+
traverse(tree, {
|
1887
|
+
cursor: 0,
|
1888
|
+
enter: function (node) {
|
1889
|
+
var comment;
|
1890
|
+
|
1891
|
+
while (this.cursor < comments.length) {
|
1892
|
+
comment = comments[this.cursor];
|
1893
|
+
if (comment.extendedRange[1] > node.range[0]) {
|
1894
|
+
break;
|
1895
|
+
}
|
1896
|
+
|
1897
|
+
if (comment.extendedRange[1] === node.range[0]) {
|
1898
|
+
if (!node.leadingComments) {
|
1899
|
+
node.leadingComments = [];
|
1900
|
+
}
|
1901
|
+
node.leadingComments.push(comment);
|
1902
|
+
comments.splice(this.cursor, 1);
|
1903
|
+
} else {
|
1904
|
+
this.cursor += 1;
|
1905
|
+
}
|
1906
|
+
}
|
1907
|
+
|
1908
|
+
// already out of owned node
|
1909
|
+
if (this.cursor === comments.length) {
|
1910
|
+
return VisitorOption.Break;
|
1911
|
+
}
|
1912
|
+
|
1913
|
+
if (comments[this.cursor].extendedRange[0] > node.range[1]) {
|
1914
|
+
return VisitorOption.Skip;
|
1915
|
+
}
|
1916
|
+
}
|
1917
|
+
});
|
1918
|
+
|
1919
|
+
traverse(tree, {
|
1920
|
+
cursor: 0,
|
1921
|
+
leave: function (node) {
|
1922
|
+
var comment;
|
1923
|
+
|
1924
|
+
while (this.cursor < comments.length) {
|
1925
|
+
comment = comments[this.cursor];
|
1926
|
+
if (node.range[1] < comment.extendedRange[0]) {
|
1927
|
+
break;
|
1928
|
+
}
|
1929
|
+
|
1930
|
+
if (node.range[1] === comment.extendedRange[0]) {
|
1931
|
+
if (!node.trailingComments) {
|
1932
|
+
node.trailingComments = [];
|
1933
|
+
}
|
1934
|
+
node.trailingComments.push(comment);
|
1935
|
+
comments.splice(this.cursor, 1);
|
1936
|
+
} else {
|
1937
|
+
this.cursor += 1;
|
1938
|
+
}
|
1939
|
+
}
|
1940
|
+
|
1941
|
+
// already out of owned node
|
1942
|
+
if (this.cursor === comments.length) {
|
1943
|
+
return VisitorOption.Break;
|
1944
|
+
}
|
1945
|
+
|
1946
|
+
if (comments[this.cursor].extendedRange[0] > node.range[1]) {
|
1947
|
+
return VisitorOption.Skip;
|
1948
|
+
}
|
1949
|
+
}
|
1950
|
+
});
|
1951
|
+
|
1952
|
+
return tree;
|
1953
|
+
}
|
1954
|
+
|
1955
|
+
// Sync with package.json.
|
1956
|
+
exports.version = '0.0.10-dev';
|
1957
|
+
|
1958
|
+
exports.generate = generate;
|
1959
|
+
exports.traverse = traverse;
|
1960
|
+
exports.attachComments = attachComments;
|
1961
|
+
|
1962
|
+
}, this));
|
1963
|
+
/* vim: set sw=4 ts=4 et tw=80 : */
|