Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
J
jquery
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
夏彬
jquery
Commits
2a714934
Commit
2a714934
authored
Apr 17, 2011
by
John Resig
Committed by
timmywil
Apr 17, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Updating UglifyJS.
parent
3cb9c183
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
571 additions
and
437 deletions
+571
-437
parse-js.js
build/lib/parse-js.js
+179
-99
process.js
build/lib/process.js
+392
-338
No files found.
build/lib/parse-js.js
View file @
2a714934
...
@@ -182,8 +182,6 @@ var OPERATORS = array_to_hash([
...
@@ -182,8 +182,6 @@ var OPERATORS = array_to_hash([
">>="
,
">>="
,
"<<="
,
"<<="
,
">>>="
,
">>>="
,
"~="
,
"%="
,
"|="
,
"|="
,
"^="
,
"^="
,
"&="
,
"&="
,
...
@@ -191,7 +189,7 @@ var OPERATORS = array_to_hash([
...
@@ -191,7 +189,7 @@ var OPERATORS = array_to_hash([
"||"
"||"
]);
]);
var
WHITESPACE_CHARS
=
array_to_hash
(
characters
(
"
\n
\
r
\
t"
));
var
WHITESPACE_CHARS
=
array_to_hash
(
characters
(
"
\n
\
r
\
t
\
u200b
"
));
var
PUNC_BEFORE_EXPRESSION
=
array_to_hash
(
characters
(
"[{}(,.;:"
));
var
PUNC_BEFORE_EXPRESSION
=
array_to_hash
(
characters
(
"[{}(,.;:"
));
...
@@ -201,20 +199,47 @@ var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
...
@@ -201,20 +199,47 @@ var REGEXP_MODIFIERS = array_to_hash(characters("gmsiy"));
/* -----[ Tokenizer ]----- */
/* -----[ Tokenizer ]----- */
function
is_alphanumeric_char
(
ch
)
{
// regexps adapted from http://xregexp.com/plugins/#unicode
ch
=
ch
.
charCodeAt
(
0
);
var
UNICODE
=
{
return
(
ch
>=
48
&&
ch
<=
57
)
||
letter
:
new
RegExp
(
"[
\\
u0041-
\\
u005A
\\
u0061-
\\
u007A
\\
u00AA
\\
u00B5
\\
u00BA
\\
u00C0-
\\
u00D6
\\
u00D8-
\\
u00F6
\\
u00F8-
\\
u02C1
\\
u02C6-
\\
u02D1
\\
u02E0-
\\
u02E4
\\
u02EC
\\
u02EE
\\
u0370-
\\
u0374
\\
u0376
\\
u0377
\\
u037A-
\\
u037D
\\
u0386
\\
u0388-
\\
u038A
\\
u038C
\\
u038E-
\\
u03A1
\\
u03A3-
\\
u03F5
\\
u03F7-
\\
u0481
\\
u048A-
\\
u0523
\\
u0531-
\\
u0556
\\
u0559
\\
u0561-
\\
u0587
\\
u05D0-
\\
u05EA
\\
u05F0-
\\
u05F2
\\
u0621-
\\
u064A
\\
u066E
\\
u066F
\\
u0671-
\\
u06D3
\\
u06D5
\\
u06E5
\\
u06E6
\\
u06EE
\\
u06EF
\\
u06FA-
\\
u06FC
\\
u06FF
\\
u0710
\\
u0712-
\\
u072F
\\
u074D-
\\
u07A5
\\
u07B1
\\
u07CA-
\\
u07EA
\\
u07F4
\\
u07F5
\\
u07FA
\\
u0904-
\\
u0939
\\
u093D
\\
u0950
\\
u0958-
\\
u0961
\\
u0971
\\
u0972
\\
u097B-
\\
u097F
\\
u0985-
\\
u098C
\\
u098F
\\
u0990
\\
u0993-
\\
u09A8
\\
u09AA-
\\
u09B0
\\
u09B2
\\
u09B6-
\\
u09B9
\\
u09BD
\\
u09CE
\\
u09DC
\\
u09DD
\\
u09DF-
\\
u09E1
\\
u09F0
\\
u09F1
\\
u0A05-
\\
u0A0A
\\
u0A0F
\\
u0A10
\\
u0A13-
\\
u0A28
\\
u0A2A-
\\
u0A30
\\
u0A32
\\
u0A33
\\
u0A35
\\
u0A36
\\
u0A38
\\
u0A39
\\
u0A59-
\\
u0A5C
\\
u0A5E
\\
u0A72-
\\
u0A74
\\
u0A85-
\\
u0A8D
\\
u0A8F-
\\
u0A91
\\
u0A93-
\\
u0AA8
\\
u0AAA-
\\
u0AB0
\\
u0AB2
\\
u0AB3
\\
u0AB5-
\\
u0AB9
\\
u0ABD
\\
u0AD0
\\
u0AE0
\\
u0AE1
\\
u0B05-
\\
u0B0C
\\
u0B0F
\\
u0B10
\\
u0B13-
\\
u0B28
\\
u0B2A-
\\
u0B30
\\
u0B32
\\
u0B33
\\
u0B35-
\\
u0B39
\\
u0B3D
\\
u0B5C
\\
u0B5D
\\
u0B5F-
\\
u0B61
\\
u0B71
\\
u0B83
\\
u0B85-
\\
u0B8A
\\
u0B8E-
\\
u0B90
\\
u0B92-
\\
u0B95
\\
u0B99
\\
u0B9A
\\
u0B9C
\\
u0B9E
\\
u0B9F
\\
u0BA3
\\
u0BA4
\\
u0BA8-
\\
u0BAA
\\
u0BAE-
\\
u0BB9
\\
u0BD0
\\
u0C05-
\\
u0C0C
\\
u0C0E-
\\
u0C10
\\
u0C12-
\\
u0C28
\\
u0C2A-
\\
u0C33
\\
u0C35-
\\
u0C39
\\
u0C3D
\\
u0C58
\\
u0C59
\\
u0C60
\\
u0C61
\\
u0C85-
\\
u0C8C
\\
u0C8E-
\\
u0C90
\\
u0C92-
\\
u0CA8
\\
u0CAA-
\\
u0CB3
\\
u0CB5-
\\
u0CB9
\\
u0CBD
\\
u0CDE
\\
u0CE0
\\
u0CE1
\\
u0D05-
\\
u0D0C
\\
u0D0E-
\\
u0D10
\\
u0D12-
\\
u0D28
\\
u0D2A-
\\
u0D39
\\
u0D3D
\\
u0D60
\\
u0D61
\\
u0D7A-
\\
u0D7F
\\
u0D85-
\\
u0D96
\\
u0D9A-
\\
u0DB1
\\
u0DB3-
\\
u0DBB
\\
u0DBD
\\
u0DC0-
\\
u0DC6
\\
u0E01-
\\
u0E30
\\
u0E32
\\
u0E33
\\
u0E40-
\\
u0E46
\\
u0E81
\\
u0E82
\\
u0E84
\\
u0E87
\\
u0E88
\\
u0E8A
\\
u0E8D
\\
u0E94-
\\
u0E97
\\
u0E99-
\\
u0E9F
\\
u0EA1-
\\
u0EA3
\\
u0EA5
\\
u0EA7
\\
u0EAA
\\
u0EAB
\\
u0EAD-
\\
u0EB0
\\
u0EB2
\\
u0EB3
\\
u0EBD
\\
u0EC0-
\\
u0EC4
\\
u0EC6
\\
u0EDC
\\
u0EDD
\\
u0F00
\\
u0F40-
\\
u0F47
\\
u0F49-
\\
u0F6C
\\
u0F88-
\\
u0F8B
\\
u1000-
\\
u102A
\\
u103F
\\
u1050-
\\
u1055
\\
u105A-
\\
u105D
\\
u1061
\\
u1065
\\
u1066
\\
u106E-
\\
u1070
\\
u1075-
\\
u1081
\\
u108E
\\
u10A0-
\\
u10C5
\\
u10D0-
\\
u10FA
\\
u10FC
\\
u1100-
\\
u1159
\\
u115F-
\\
u11A2
\\
u11A8-
\\
u11F9
\\
u1200-
\\
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
\\
u1380-
\\
u138F
\\
u13A0-
\\
u13F4
\\
u1401-
\\
u166C
\\
u166F-
\\
u1676
\\
u1681-
\\
u169A
\\
u16A0-
\\
u16EA
\\
u1700-
\\
u170C
\\
u170E-
\\
u1711
\\
u1720-
\\
u1731
\\
u1740-
\\
u1751
\\
u1760-
\\
u176C
\\
u176E-
\\
u1770
\\
u1780-
\\
u17B3
\\
u17D7
\\
u17DC
\\
u1820-
\\
u1877
\\
u1880-
\\
u18A8
\\
u18AA
\\
u1900-
\\
u191C
\\
u1950-
\\
u196D
\\
u1970-
\\
u1974
\\
u1980-
\\
u19A9
\\
u19C1-
\\
u19C7
\\
u1A00-
\\
u1A16
\\
u1B05-
\\
u1B33
\\
u1B45-
\\
u1B4B
\\
u1B83-
\\
u1BA0
\\
u1BAE
\\
u1BAF
\\
u1C00-
\\
u1C23
\\
u1C4D-
\\
u1C4F
\\
u1C5A-
\\
u1C7D
\\
u1D00-
\\
u1DBF
\\
u1E00-
\\
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
\\
u2071
\\
u207F
\\
u2090-
\\
u2094
\\
u2102
\\
u2107
\\
u210A-
\\
u2113
\\
u2115
\\
u2119-
\\
u211D
\\
u2124
\\
u2126
\\
u2128
\\
u212A-
\\
u212D
\\
u212F-
\\
u2139
\\
u213C-
\\
u213F
\\
u2145-
\\
u2149
\\
u214E
\\
u2183
\\
u2184
\\
u2C00-
\\
u2C2E
\\
u2C30-
\\
u2C5E
\\
u2C60-
\\
u2C6F
\\
u2C71-
\\
u2C7D
\\
u2C80-
\\
u2CE4
\\
u2D00-
\\
u2D25
\\
u2D30-
\\
u2D65
\\
u2D6F
\\
u2D80-
\\
u2D96
\\
u2DA0-
\\
u2DA6
\\
u2DA8-
\\
u2DAE
\\
u2DB0-
\\
u2DB6
\\
u2DB8-
\\
u2DBE
\\
u2DC0-
\\
u2DC6
\\
u2DC8-
\\
u2DCE
\\
u2DD0-
\\
u2DD6
\\
u2DD8-
\\
u2DDE
\\
u2E2F
\\
u3005
\\
u3006
\\
u3031-
\\
u3035
\\
u303B
\\
u303C
\\
u3041-
\\
u3096
\\
u309D-
\\
u309F
\\
u30A1-
\\
u30FA
\\
u30FC-
\\
u30FF
\\
u3105-
\\
u312D
\\
u3131-
\\
u318E
\\
u31A0-
\\
u31B7
\\
u31F0-
\\
u31FF
\\
u3400
\\
u4DB5
\\
u4E00
\\
u9FC3
\\
uA000-
\\
uA48C
\\
uA500-
\\
uA60C
\\
uA610-
\\
uA61F
\\
uA62A
\\
uA62B
\\
uA640-
\\
uA65F
\\
uA662-
\\
uA66E
\\
uA67F-
\\
uA697
\\
uA717-
\\
uA71F
\\
uA722-
\\
uA788
\\
uA78B
\\
uA78C
\\
uA7FB-
\\
uA801
\\
uA803-
\\
uA805
\\
uA807-
\\
uA80A
\\
uA80C-
\\
uA822
\\
uA840-
\\
uA873
\\
uA882-
\\
uA8B3
\\
uA90A-
\\
uA925
\\
uA930-
\\
uA946
\\
uAA00-
\\
uAA28
\\
uAA40-
\\
uAA42
\\
uAA44-
\\
uAA4B
\\
uAC00
\\
uD7A3
\\
uF900-
\\
uFA2D
\\
uFA30-
\\
uFA6A
\\
uFA70-
\\
uFAD9
\\
uFB00-
\\
uFB06
\\
uFB13-
\\
uFB17
\\
uFB1D
\\
uFB1F-
\\
uFB28
\\
uFB2A-
\\
uFB36
\\
uFB38-
\\
uFB3C
\\
uFB3E
\\
uFB40
\\
uFB41
\\
uFB43
\\
uFB44
\\
uFB46-
\\
uFBB1
\\
uFBD3-
\\
uFD3D
\\
uFD50-
\\
uFD8F
\\
uFD92-
\\
uFDC7
\\
uFDF0-
\\
uFDFB
\\
uFE70-
\\
uFE74
\\
uFE76-
\\
uFEFC
\\
uFF21-
\\
uFF3A
\\
uFF41-
\\
uFF5A
\\
uFF66-
\\
uFFBE
\\
uFFC2-
\\
uFFC7
\\
uFFCA-
\\
uFFCF
\\
uFFD2-
\\
uFFD7
\\
uFFDA-
\\
uFFDC]"
),
(
ch
>=
65
&&
ch
<=
90
)
||
non_spacing_mark
:
new
RegExp
(
"[
\\
u0300-
\\
u036F
\\
u0483-
\\
u0487
\\
u0591-
\\
u05BD
\\
u05BF
\\
u05C1
\\
u05C2
\\
u05C4
\\
u05C5
\\
u05C7
\\
u0610-
\\
u061A
\\
u064B-
\\
u065E
\\
u0670
\\
u06D6-
\\
u06DC
\\
u06DF-
\\
u06E4
\\
u06E7
\\
u06E8
\\
u06EA-
\\
u06ED
\\
u0711
\\
u0730-
\\
u074A
\\
u07A6-
\\
u07B0
\\
u07EB-
\\
u07F3
\\
u0816-
\\
u0819
\\
u081B-
\\
u0823
\\
u0825-
\\
u0827
\\
u0829-
\\
u082D
\\
u0900-
\\
u0902
\\
u093C
\\
u0941-
\\
u0948
\\
u094D
\\
u0951-
\\
u0955
\\
u0962
\\
u0963
\\
u0981
\\
u09BC
\\
u09C1-
\\
u09C4
\\
u09CD
\\
u09E2
\\
u09E3
\\
u0A01
\\
u0A02
\\
u0A3C
\\
u0A41
\\
u0A42
\\
u0A47
\\
u0A48
\\
u0A4B-
\\
u0A4D
\\
u0A51
\\
u0A70
\\
u0A71
\\
u0A75
\\
u0A81
\\
u0A82
\\
u0ABC
\\
u0AC1-
\\
u0AC5
\\
u0AC7
\\
u0AC8
\\
u0ACD
\\
u0AE2
\\
u0AE3
\\
u0B01
\\
u0B3C
\\
u0B3F
\\
u0B41-
\\
u0B44
\\
u0B4D
\\
u0B56
\\
u0B62
\\
u0B63
\\
u0B82
\\
u0BC0
\\
u0BCD
\\
u0C3E-
\\
u0C40
\\
u0C46-
\\
u0C48
\\
u0C4A-
\\
u0C4D
\\
u0C55
\\
u0C56
\\
u0C62
\\
u0C63
\\
u0CBC
\\
u0CBF
\\
u0CC6
\\
u0CCC
\\
u0CCD
\\
u0CE2
\\
u0CE3
\\
u0D41-
\\
u0D44
\\
u0D4D
\\
u0D62
\\
u0D63
\\
u0DCA
\\
u0DD2-
\\
u0DD4
\\
u0DD6
\\
u0E31
\\
u0E34-
\\
u0E3A
\\
u0E47-
\\
u0E4E
\\
u0EB1
\\
u0EB4-
\\
u0EB9
\\
u0EBB
\\
u0EBC
\\
u0EC8-
\\
u0ECD
\\
u0F18
\\
u0F19
\\
u0F35
\\
u0F37
\\
u0F39
\\
u0F71-
\\
u0F7E
\\
u0F80-
\\
u0F84
\\
u0F86
\\
u0F87
\\
u0F90-
\\
u0F97
\\
u0F99-
\\
u0FBC
\\
u0FC6
\\
u102D-
\\
u1030
\\
u1032-
\\
u1037
\\
u1039
\\
u103A
\\
u103D
\\
u103E
\\
u1058
\\
u1059
\\
u105E-
\\
u1060
\\
u1071-
\\
u1074
\\
u1082
\\
u1085
\\
u1086
\\
u108D
\\
u109D
\\
u135F
\\
u1712-
\\
u1714
\\
u1732-
\\
u1734
\\
u1752
\\
u1753
\\
u1772
\\
u1773
\\
u17B7-
\\
u17BD
\\
u17C6
\\
u17C9-
\\
u17D3
\\
u17DD
\\
u180B-
\\
u180D
\\
u18A9
\\
u1920-
\\
u1922
\\
u1927
\\
u1928
\\
u1932
\\
u1939-
\\
u193B
\\
u1A17
\\
u1A18
\\
u1A56
\\
u1A58-
\\
u1A5E
\\
u1A60
\\
u1A62
\\
u1A65-
\\
u1A6C
\\
u1A73-
\\
u1A7C
\\
u1A7F
\\
u1B00-
\\
u1B03
\\
u1B34
\\
u1B36-
\\
u1B3A
\\
u1B3C
\\
u1B42
\\
u1B6B-
\\
u1B73
\\
u1B80
\\
u1B81
\\
u1BA2-
\\
u1BA5
\\
u1BA8
\\
u1BA9
\\
u1C2C-
\\
u1C33
\\
u1C36
\\
u1C37
\\
u1CD0-
\\
u1CD2
\\
u1CD4-
\\
u1CE0
\\
u1CE2-
\\
u1CE8
\\
u1CED
\\
u1DC0-
\\
u1DE6
\\
u1DFD-
\\
u1DFF
\\
u20D0-
\\
u20DC
\\
u20E1
\\
u20E5-
\\
u20F0
\\
u2CEF-
\\
u2CF1
\\
u2DE0-
\\
u2DFF
\\
u302A-
\\
u302F
\\
u3099
\\
u309A
\\
uA66F
\\
uA67C
\\
uA67D
\\
uA6F0
\\
uA6F1
\\
uA802
\\
uA806
\\
uA80B
\\
uA825
\\
uA826
\\
uA8C4
\\
uA8E0-
\\
uA8F1
\\
uA926-
\\
uA92D
\\
uA947-
\\
uA951
\\
uA980-
\\
uA982
\\
uA9B3
\\
uA9B6-
\\
uA9B9
\\
uA9BC
\\
uAA29-
\\
uAA2E
\\
uAA31
\\
uAA32
\\
uAA35
\\
uAA36
\\
uAA43
\\
uAA4C
\\
uAAB0
\\
uAAB2-
\\
uAAB4
\\
uAAB7
\\
uAAB8
\\
uAABE
\\
uAABF
\\
uAAC1
\\
uABE5
\\
uABE8
\\
uABED
\\
uFB1E
\\
uFE00-
\\
uFE0F
\\
uFE20-
\\
uFE26]"
),
(
ch
>=
97
&&
ch
<=
122
);
space_combining_mark
:
new
RegExp
(
"[
\\
u0903
\\
u093E-
\\
u0940
\\
u0949-
\\
u094C
\\
u094E
\\
u0982
\\
u0983
\\
u09BE-
\\
u09C0
\\
u09C7
\\
u09C8
\\
u09CB
\\
u09CC
\\
u09D7
\\
u0A03
\\
u0A3E-
\\
u0A40
\\
u0A83
\\
u0ABE-
\\
u0AC0
\\
u0AC9
\\
u0ACB
\\
u0ACC
\\
u0B02
\\
u0B03
\\
u0B3E
\\
u0B40
\\
u0B47
\\
u0B48
\\
u0B4B
\\
u0B4C
\\
u0B57
\\
u0BBE
\\
u0BBF
\\
u0BC1
\\
u0BC2
\\
u0BC6-
\\
u0BC8
\\
u0BCA-
\\
u0BCC
\\
u0BD7
\\
u0C01-
\\
u0C03
\\
u0C41-
\\
u0C44
\\
u0C82
\\
u0C83
\\
u0CBE
\\
u0CC0-
\\
u0CC4
\\
u0CC7
\\
u0CC8
\\
u0CCA
\\
u0CCB
\\
u0CD5
\\
u0CD6
\\
u0D02
\\
u0D03
\\
u0D3E-
\\
u0D40
\\
u0D46-
\\
u0D48
\\
u0D4A-
\\
u0D4C
\\
u0D57
\\
u0D82
\\
u0D83
\\
u0DCF-
\\
u0DD1
\\
u0DD8-
\\
u0DDF
\\
u0DF2
\\
u0DF3
\\
u0F3E
\\
u0F3F
\\
u0F7F
\\
u102B
\\
u102C
\\
u1031
\\
u1038
\\
u103B
\\
u103C
\\
u1056
\\
u1057
\\
u1062-
\\
u1064
\\
u1067-
\\
u106D
\\
u1083
\\
u1084
\\
u1087-
\\
u108C
\\
u108F
\\
u109A-
\\
u109C
\\
u17B6
\\
u17BE-
\\
u17C5
\\
u17C7
\\
u17C8
\\
u1923-
\\
u1926
\\
u1929-
\\
u192B
\\
u1930
\\
u1931
\\
u1933-
\\
u1938
\\
u19B0-
\\
u19C0
\\
u19C8
\\
u19C9
\\
u1A19-
\\
u1A1B
\\
u1A55
\\
u1A57
\\
u1A61
\\
u1A63
\\
u1A64
\\
u1A6D-
\\
u1A72
\\
u1B04
\\
u1B35
\\
u1B3B
\\
u1B3D-
\\
u1B41
\\
u1B43
\\
u1B44
\\
u1B82
\\
u1BA1
\\
u1BA6
\\
u1BA7
\\
u1BAA
\\
u1C24-
\\
u1C2B
\\
u1C34
\\
u1C35
\\
u1CE1
\\
u1CF2
\\
uA823
\\
uA824
\\
uA827
\\
uA880
\\
uA881
\\
uA8B4-
\\
uA8C3
\\
uA952
\\
uA953
\\
uA983
\\
uA9B4
\\
uA9B5
\\
uA9BA
\\
uA9BB
\\
uA9BD-
\\
uA9C0
\\
uAA2F
\\
uAA30
\\
uAA33
\\
uAA34
\\
uAA4D
\\
uAA7B
\\
uABE3
\\
uABE4
\\
uABE6
\\
uABE7
\\
uABE9
\\
uABEA
\\
uABEC]"
),
connector_punctuation
:
new
RegExp
(
"[
\\
u005F
\\
u203F
\\
u2040
\\
u2054
\\
uFE33
\\
uFE34
\\
uFE4D-
\\
uFE4F
\\
uFF3F]"
)
};
};
function
is_
identifier_cha
r
(
ch
)
{
function
is_
lette
r
(
ch
)
{
return
is_alphanumeric_char
(
ch
)
||
ch
==
"$"
||
ch
==
"_"
;
return
UNICODE
.
letter
.
test
(
ch
)
;
};
};
function
is_digit
(
ch
)
{
function
is_digit
(
ch
)
{
ch
=
ch
.
charCodeAt
(
0
);
ch
=
ch
.
charCodeAt
(
0
);
return
ch
>=
48
&&
ch
<=
57
;
return
ch
>=
48
&&
ch
<=
57
;
//XXX: find out if "UnicodeDigit" means something else than 0..9
};
function
is_alphanumeric_char
(
ch
)
{
return
is_digit
(
ch
)
||
is_letter
(
ch
);
};
function
is_unicode_combining_mark
(
ch
)
{
return
UNICODE
.
non_spacing_mark
.
test
(
ch
)
||
UNICODE
.
space_combining_mark
.
test
(
ch
);
};
function
is_unicode_connector_punctuation
(
ch
)
{
return
UNICODE
.
connector_punctuation
.
test
(
ch
);
};
function
is_identifier_start
(
ch
)
{
return
ch
==
"$"
||
ch
==
"_"
||
is_letter
(
ch
);
};
function
is_identifier_char
(
ch
)
{
return
is_identifier_start
(
ch
)
||
is_unicode_combining_mark
(
ch
)
||
is_digit
(
ch
)
||
is_unicode_connector_punctuation
(
ch
)
||
ch
==
"
\
u200c"
// zero-width non-joiner <ZWNJ>
||
ch
==
"
\
u200d"
// zero-width joiner <ZWJ> (in my ECMA-262 PDF, this is also 200c)
;
};
};
function
parse_js_number
(
num
)
{
function
parse_js_number
(
num
)
{
...
@@ -253,7 +278,7 @@ function is_token(token, type, val) {
...
@@ -253,7 +278,7 @@ function is_token(token, type, val) {
var
EX_EOF
=
{};
var
EX_EOF
=
{};
function
tokenizer
(
$TEXT
,
skip_comments
)
{
function
tokenizer
(
$TEXT
)
{
var
S
=
{
var
S
=
{
text
:
$TEXT
.
replace
(
/
\r\n?
|
[\n\u
2028
\u
2029
]
/g
,
"
\n
"
).
replace
(
/^
\u
FEFF/
,
''
),
text
:
$TEXT
.
replace
(
/
\r\n?
|
[\n\u
2028
\u
2029
]
/g
,
"
\n
"
).
replace
(
/^
\u
FEFF/
,
''
),
...
@@ -264,7 +289,8 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -264,7 +289,8 @@ function tokenizer($TEXT, skip_comments) {
col
:
0
,
col
:
0
,
tokcol
:
0
,
tokcol
:
0
,
newline_before
:
false
,
newline_before
:
false
,
regex_allowed
:
false
regex_allowed
:
false
,
comments_before
:
[]
};
};
function
peek
()
{
return
S
.
text
.
charAt
(
S
.
pos
);
};
function
peek
()
{
return
S
.
text
.
charAt
(
S
.
pos
);
};
...
@@ -299,7 +325,7 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -299,7 +325,7 @@ function tokenizer($TEXT, skip_comments) {
S
.
tokpos
=
S
.
pos
;
S
.
tokpos
=
S
.
pos
;
};
};
function
token
(
type
,
value
)
{
function
token
(
type
,
value
,
is_comment
)
{
S
.
regex_allowed
=
((
type
==
"operator"
&&
!
HOP
(
UNARY_POSTFIX
,
value
))
||
S
.
regex_allowed
=
((
type
==
"operator"
&&
!
HOP
(
UNARY_POSTFIX
,
value
))
||
(
type
==
"keyword"
&&
HOP
(
KEYWORDS_BEFORE_EXPRESSION
,
value
))
||
(
type
==
"keyword"
&&
HOP
(
KEYWORDS_BEFORE_EXPRESSION
,
value
))
||
(
type
==
"punc"
&&
HOP
(
PUNC_BEFORE_EXPRESSION
,
value
)));
(
type
==
"punc"
&&
HOP
(
PUNC_BEFORE_EXPRESSION
,
value
)));
...
@@ -311,6 +337,10 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -311,6 +337,10 @@ function tokenizer($TEXT, skip_comments) {
pos
:
S
.
tokpos
,
pos
:
S
.
tokpos
,
nlb
:
S
.
newline_before
nlb
:
S
.
newline_before
};
};
if
(
!
is_comment
)
{
ret
.
comments_before
=
S
.
comments_before
;
S
.
comments_before
=
[];
}
S
.
newline_before
=
false
;
S
.
newline_before
=
false
;
return
ret
;
return
ret
;
};
};
...
@@ -351,7 +381,7 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -351,7 +381,7 @@ function tokenizer($TEXT, skip_comments) {
if
(
ch
==
"+"
)
return
after_e
;
if
(
ch
==
"+"
)
return
after_e
;
after_e
=
false
;
after_e
=
false
;
if
(
ch
==
"."
)
{
if
(
ch
==
"."
)
{
if
(
!
has_dot
)
if
(
!
has_dot
&&
!
has_x
)
return
has_dot
=
true
;
return
has_dot
=
true
;
return
false
;
return
false
;
}
}
...
@@ -417,7 +447,7 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -417,7 +447,7 @@ function tokenizer($TEXT, skip_comments) {
ret = S.text.substring(S.pos, i);
ret = S.text.substring(S.pos, i);
S.pos = i;
S.pos = i;
}
}
return token("
comment1
", ret);
return token("
comment1
", ret
, true
);
};
};
function read_multiline_comment() {
function read_multiline_comment() {
...
@@ -425,14 +455,41 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -425,14 +455,41 @@ function tokenizer($TEXT, skip_comments) {
return with_eof_error("
Unterminated
multiline
comment
", function(){
return with_eof_error("
Unterminated
multiline
comment
", function(){
var i = find("
*
/", true
)
,
var i = find("
*
/", true
)
,
text
=
S
.
text
.
substring
(
S
.
pos
,
i
),
text
=
S
.
text
.
substring
(
S
.
pos
,
i
),
tok
=
token
(
"comment2"
,
text
);
tok
=
token
(
"comment2"
,
text
,
true
);
S
.
pos
=
i
+
2
;
S
.
pos
=
i
+
2
;
S
.
line
+=
text
.
split
(
"
\n
"
).
length
-
1
;
S
.
line
+=
text
.
split
(
"
\n
"
).
length
-
1
;
S
.
newline_before
=
text
.
indexOf
(
"
\n
"
)
>=
0
;
S
.
newline_before
=
text
.
indexOf
(
"
\n
"
)
>=
0
;
// https://github.com/mishoo/UglifyJS/issues/#issue/100
if
(
/^@cc_on/i
.
test
(
text
))
{
warn
(
"WARNING: at line "
+
S
.
line
);
warn
(
"*** Found
\"
conditional comment
\"
: "
+
text
);
warn
(
"*** UglifyJS DISCARDS ALL COMMENTS. This means your code might no longer work properly in Internet Explorer."
);
}
return
tok
;
return
tok
;
});
});
};
};
function
read_name
()
{
var
backslash
=
false
,
name
=
""
,
ch
;
while
((
ch
=
peek
())
!=
null
)
{
if
(
!
backslash
)
{
if
(
ch
==
"
\
\"
) backslash = true, next();
else if (is_identifier_char(ch)) name += next();
else break;
}
else {
if (ch != "
u
") parse_error("
Expecting
UnicodeEscapeSequence
--
uXXXX
");
ch = read_escaped_char();
if (!is_identifier_char(ch)) parse_error("
Unicode
char
:
" + ch.charCodeAt(0) + "
is
not
valid
in
identifier
");
name += ch;
backslash = false;
}
}
return name;
};
function read_regexp() {
function read_regexp() {
return with_eof_error("
Unterminated
regular
expression
", function(){
return with_eof_error("
Unterminated
regular
expression
", function(){
var prev_backslash = false, regexp = "", ch, in_class = false;
var prev_backslash = false, regexp = "", ch, in_class = false;
...
@@ -452,15 +509,14 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -452,15 +509,14 @@ function tokenizer($TEXT, skip_comments) {
} else {
} else {
regexp += ch;
regexp += ch;
}
}
var mods = read_while(function(ch){
var mods = read_name();
return HOP(REGEXP_MODIFIERS, ch);
});
return token("
regexp
", [ regexp, mods ]);
return token("
regexp
", [ regexp, mods ]);
});
});
};
};
function read_operator(prefix) {
function read_operator(prefix) {
function grow(op) {
function grow(op) {
if (!peek()) return op;
var bigger = op + peek();
var bigger = op + peek();
if (HOP(OPERATORS, bigger)) {
if (HOP(OPERATORS, bigger)) {
next();
next();
...
@@ -472,19 +528,18 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -472,19 +528,18 @@ function tokenizer($TEXT, skip_comments) {
return token("
operator
", grow(prefix || next()));
return token("
operator
", grow(prefix || next()));
};
};
var handle_slash = skip_comments ? function
() {
function handle_slash
() {
next();
next();
var regex_allowed = S.regex_allowed;
var regex_allowed = S.regex_allowed;
switch (peek()) {
switch (peek()) {
case "
/
": read_line_comment(); S.regex_allowed = regex_allowed; return next_token();
case "
/
":
case "
*
": read_multiline_comment(); S.regex_allowed = regex_allowed; return next_token();
S.comments_before.push(read_line_comment());
}
S.regex_allowed = regex_allowed;
return S.regex_allowed ? read_regexp() : read_operator("
/
");
return next_token();
} : function() {
case "
*
":
next();
S.comments_before.push(read_multiline_comment());
switch (peek()) {
S.regex_allowed = regex_allowed;
case "
/
": return read_line_comment();
return next_token();
case "
*
": return read_multiline_comment();
}
}
return S.regex_allowed ? read_regexp() : read_operator("
/
");
return S.regex_allowed ? read_regexp() : read_operator("
/
");
};
};
...
@@ -497,7 +552,7 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -497,7 +552,7 @@ function tokenizer($TEXT, skip_comments) {
};
};
function read_word() {
function read_word() {
var word = read_
while(is_identifier_char
);
var word = read_
name(
);
return !HOP(KEYWORDS, word)
return !HOP(KEYWORDS, word)
? token("
name
", word)
? token("
name
", word)
: HOP(OPERATORS, word)
: HOP(OPERATORS, word)
...
@@ -529,7 +584,7 @@ function tokenizer($TEXT, skip_comments) {
...
@@ -529,7 +584,7 @@ function tokenizer($TEXT, skip_comments) {
if (ch == "
.
") return handle_dot();
if (ch == "
.
") return handle_dot();
if (ch == "
/
") return handle_slash();
if (ch == "
/
") return handle_slash();
if (HOP(OPERATOR_CHARS, ch)) return read_operator();
if (HOP(OPERATOR_CHARS, ch)) return read_operator();
if (
is_identifier_char
(ch)) return read_word();
if (
ch == "
\\
" || is_identifier_start
(ch)) return read_word();
parse_error("
Unexpected
character
'" + ch + "'
");
parse_error("
Unexpected
character
'" + ch + "'
");
};
};
...
@@ -565,7 +620,7 @@ var ASSIGNMENT = (function(a, ret, i){
...
@@ -565,7 +620,7 @@ var ASSIGNMENT = (function(a, ret, i){
}
}
return ret;
return ret;
})(
})(
["
+=
", "
-=
", "
/=
", "
*=
", "
%=
", "
>>=
", "
<<=
", "
>>>=
", "
~=
", "
%=
", "
|=
", "
^=
", "
&=
"],
["
+=
", "
-=
", "
/=
", "
*=
", "
%=
", "
>>=
", "
<<=
", "
>>>=
", "
|=
", "
^=
", "
&=
"],
{ "
=
": true },
{ "
=
": true },
0
0
);
);
...
@@ -608,16 +663,16 @@ function NodeWithToken(str, start, end) {
...
@@ -608,16 +663,16 @@ function NodeWithToken(str, start, end) {
NodeWithToken.prototype.toString = function() { return this.name; };
NodeWithToken.prototype.toString = function() { return this.name; };
function parse($TEXT,
stric
t_mode, embed_tokens) {
function parse($TEXT,
exigen
t_mode, embed_tokens) {
var S = {
var S = {
input
: tokenizer($TEXT, true)
,
input
: typeof $TEXT == "
string
" ? tokenizer($TEXT, true) : $TEXT
,
token: null,
token
: null,
prev: null,
prev
: null,
peeked: null,
peeked
: null,
in_function: 0,
in_function
: 0,
in_loop: 0,
in_loop
: 0,
labels: []
labels
: []
};
};
S.token = next();
S.token = next();
...
@@ -671,7 +726,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -671,7 +726,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
function expect(punc) { return expect_token("
punc
", punc); };
function expect(punc) { return expect_token("
punc
", punc); };
function can_insert_semicolon() {
function can_insert_semicolon() {
return !
stric
t_mode && (
return !
exigen
t_mode && (
S.token.nlb || is("
eof
") || is("
punc
", "
}
")
S.token.nlb || is("
eof
") || is("
punc
", "
}
")
);
);
};
};
...
@@ -693,14 +748,14 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -693,14 +748,14 @@ function parse($TEXT, strict_mode, embed_tokens) {
};
};
function add_tokens(str, start, end) {
function add_tokens(str, start, end) {
return new NodeWithToken(str, start, end);
return
str instanceof NodeWithToken ? str :
new NodeWithToken(str, start, end);
};
};
var statement = embed_tokens ? function() {
var statement = embed_tokens ? function() {
var start = S.token;
var start = S.token;
var
stmt = $statement(
);
var
ast = $statement.apply(this, arguments
);
stmt[0] = add_tokens(stm
t[0], start, prev());
ast[0] = add_tokens(as
t[0], start, prev());
return
stm
t;
return
as
t;
} : $statement;
} : $statement;
function $statement() {
function $statement() {
...
@@ -802,7 +857,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -802,7 +857,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
function labeled_statement(label) {
function labeled_statement(label) {
S.labels.push(label);
S.labels.push(label);
var start = S.token, stat = statement();
var start = S.token, stat = statement();
if (
stric
t_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
if (
exigen
t_mode && !HOP(STATEMENTS_WITH_LABELS, stat[0]))
unexpected(start);
unexpected(start);
S.labels.pop();
S.labels.pop();
return as("
label
", label, stat);
return as("
label
", label, stat);
...
@@ -827,29 +882,42 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -827,29 +882,42 @@ function parse($TEXT, strict_mode, embed_tokens) {
function for_() {
function for_() {
expect("
(
");
expect("
(
");
var has_var = is("
keyword
", "
var
");
var init = null;
if (has_var)
if (!is("
punc
", "
;
")) {
next();
init = is("
keyword
", "
var
")
if (is("
name
") && is_token(peek(), "
operator
", "
in
")) {
? (next(), var_(true))
// for (i in foo)
: expression(true, true);
var name = S.token.value;
if (is("
operator
", "
in
"))
next(); next();
return for_in(init);
var obj = expression();
}
expect("
)
");
return regular_for(init);
return as("
for
-
in
", has_var, name, obj, in_loop(statement));
};
} else {
// classic for
function regular_for(init) {
var init = is("
punc
", "
;
") ? null : has_var ? var_() : expression();
expect("
;
");
expect("
;
");
var test = is("
punc
", "
;
") ? null : expression();
var test = is("
punc
", "
;
") ? null : expression();
expect("
;
");
expect("
;
");
var step = is("
punc
", "
)
") ? null : expression();
var step = is("
punc
", "
)
") ? null : expression();
expect("
)
");
expect("
)
");
return as("
for
", init, test, step, in_loop(statement));
return as("
for
", init, test, step, in_loop(statement));
}
};
};
function function_(in_statement) {
function for_in(init) {
var lhs = init[0] == "
var
" ? as("
name
", init[1][0]) : init;
next();
var obj = expression();
expect("
)
");
return as("
for
-
in
", init, lhs, obj, in_loop(statement));
};
var function_ = embed_tokens ? function() {
var start = prev();
var ast = $function_.apply(this, arguments);
ast[0] = add_tokens(ast[0], start, prev());
return ast;
} : $function_;
function $function_(in_statement) {
var name = is("
name
") ? prog1(S.token.value, next) : null;
var name = is("
name
") ? prog1(S.token.value, next) : null;
if (in_statement && !name)
if (in_statement && !name)
unexpected();
unexpected();
...
@@ -946,7 +1014,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -946,7 +1014,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
return
as
(
"try"
,
body
,
bcatch
,
bfinally
);
return
as
(
"try"
,
body
,
bcatch
,
bfinally
);
};
};
function
vardefs
()
{
function
vardefs
(
no_in
)
{
var
a
=
[];
var
a
=
[];
for
(;;)
{
for
(;;)
{
if
(
!
is
(
"name"
))
if
(
!
is
(
"name"
))
...
@@ -955,7 +1023,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -955,7 +1023,7 @@ function parse($TEXT, strict_mode, embed_tokens) {
next
();
next
();
if
(
is
(
"operator"
,
"="
))
{
if
(
is
(
"operator"
,
"="
))
{
next
();
next
();
a
.
push
([
name
,
expression
(
false
)
]);
a
.
push
([
name
,
expression
(
false
,
no_in
)
]);
}
else
{
}
else
{
a
.
push
([
name
]);
a
.
push
([
name
]);
}
}
...
@@ -966,8 +1034,8 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -966,8 +1034,8 @@ function parse($TEXT, strict_mode, embed_tokens) {
return
a
;
return
a
;
};
};
function
var_
()
{
function
var_
(
no_in
)
{
return
as
(
"var"
,
vardefs
());
return
as
(
"var"
,
vardefs
(
no_in
));
};
};
function
const_
()
{
function
const_
()
{
...
@@ -1022,27 +1090,30 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -1022,27 +1090,30 @@ function parse($TEXT, strict_mode, embed_tokens) {
unexpected
();
unexpected
();
};
};
function
expr_list
(
closing
,
allow_trailing_comma
)
{
function
expr_list
(
closing
,
allow_trailing_comma
,
allow_empty
)
{
var
first
=
true
,
a
=
[];
var
first
=
true
,
a
=
[];
while
(
!
is
(
"punc"
,
closing
))
{
while
(
!
is
(
"punc"
,
closing
))
{
if
(
first
)
first
=
false
;
else
expect
(
","
);
if
(
first
)
first
=
false
;
else
expect
(
","
);
if
(
allow_trailing_comma
&&
is
(
"punc"
,
closing
))
if
(
allow_trailing_comma
&&
is
(
"punc"
,
closing
))
break
;
break
;
if
(
is
(
"punc"
,
","
)
&&
allow_empty
)
{
a
.
push
([
"atom"
,
"undefined"
]);
}
else
{
a
.
push
(
expression
(
false
));
a
.
push
(
expression
(
false
));
}
}
}
next
();
next
();
return
a
;
return
a
;
};
};
function
array_
()
{
function
array_
()
{
return
as
(
"array"
,
expr_list
(
"]"
,
!
strict_mod
e
));
return
as
(
"array"
,
expr_list
(
"]"
,
!
exigent_mode
,
tru
e
));
};
};
function
object_
()
{
function
object_
()
{
var
first
=
true
,
a
=
[];
var
first
=
true
,
a
=
[];
while
(
!
is
(
"punc"
,
"}"
))
{
while
(
!
is
(
"punc"
,
"}"
))
{
if
(
first
)
first
=
false
;
else
expect
(
","
);
if
(
first
)
first
=
false
;
else
expect
(
","
);
if
(
!
stric
t_mode
&&
is
(
"punc"
,
"}"
))
if
(
!
exigen
t_mode
&&
is
(
"punc"
,
"}"
))
// allow trailing comma
// allow trailing comma
break
;
break
;
var
type
=
S
.
token
.
type
;
var
type
=
S
.
token
.
type
;
...
@@ -1105,61 +1176,65 @@ function parse($TEXT, strict_mode, embed_tokens) {
...
@@ -1105,61 +1176,65 @@ function parse($TEXT, strict_mode, embed_tokens) {
return
as
(
tag
,
op
,
expr
);
return
as
(
tag
,
op
,
expr
);
};
};
function
expr_op
(
left
,
min_prec
)
{
function
expr_op
(
left
,
min_prec
,
no_in
)
{
var
op
=
is
(
"operator"
)
?
S
.
token
.
value
:
null
;
var
op
=
is
(
"operator"
)
?
S
.
token
.
value
:
null
;
if
(
op
&&
op
==
"in"
&&
no_in
)
op
=
null
;
var
prec
=
op
!=
null
?
PRECEDENCE
[
op
]
:
null
;
var
prec
=
op
!=
null
?
PRECEDENCE
[
op
]
:
null
;
if
(
prec
!=
null
&&
prec
>
min_prec
)
{
if
(
prec
!=
null
&&
prec
>
min_prec
)
{
next
();
next
();
var
right
=
expr_op
(
expr_atom
(
true
),
prec
);
var
right
=
expr_op
(
expr_atom
(
true
),
prec
,
no_in
);
return
expr_op
(
as
(
"binary"
,
op
,
left
,
right
),
min_prec
);
return
expr_op
(
as
(
"binary"
,
op
,
left
,
right
),
min_prec
,
no_in
);
}
}
return
left
;
return
left
;
};
};
function
expr_ops
()
{
function
expr_ops
(
no_in
)
{
return
expr_op
(
expr_atom
(
true
),
0
);
return
expr_op
(
expr_atom
(
true
),
0
,
no_in
);
};
};
function
maybe_conditional
()
{
function
maybe_conditional
(
no_in
)
{
var
expr
=
expr_ops
();
var
expr
=
expr_ops
(
no_in
);
if
(
is
(
"operator"
,
"?"
))
{
if
(
is
(
"operator"
,
"?"
))
{
next
();
next
();
var
yes
=
expression
(
false
);
var
yes
=
expression
(
false
);
expect
(
":"
);
expect
(
":"
);
return
as
(
"conditional"
,
expr
,
yes
,
expression
(
false
));
return
as
(
"conditional"
,
expr
,
yes
,
expression
(
false
,
no_in
));
}
}
return
expr
;
return
expr
;
};
};
function
is_assignable
(
expr
)
{
function
is_assignable
(
expr
)
{
if
(
!
exigent_mode
)
return
true
;
switch
(
expr
[
0
])
{
switch
(
expr
[
0
])
{
case
"dot"
:
case
"dot"
:
case
"sub"
:
case
"sub"
:
case
"new"
:
case
"call"
:
return
true
;
return
true
;
case
"name"
:
case
"name"
:
return
expr
[
1
]
!=
"this"
;
return
expr
[
1
]
!=
"this"
;
}
}
};
};
function
maybe_assign
()
{
function
maybe_assign
(
no_in
)
{
var
left
=
maybe_conditional
(),
val
=
S
.
token
.
value
;
var
left
=
maybe_conditional
(
no_in
),
val
=
S
.
token
.
value
;
if
(
is
(
"operator"
)
&&
HOP
(
ASSIGNMENT
,
val
))
{
if
(
is
(
"operator"
)
&&
HOP
(
ASSIGNMENT
,
val
))
{
if
(
is_assignable
(
left
))
{
if
(
is_assignable
(
left
))
{
next
();
next
();
return
as
(
"assign"
,
ASSIGNMENT
[
val
],
left
,
maybe_assign
());
return
as
(
"assign"
,
ASSIGNMENT
[
val
],
left
,
maybe_assign
(
no_in
));
}
}
croak
(
"Invalid assignment"
);
croak
(
"Invalid assignment"
);
}
}
return
left
;
return
left
;
};
};
function
expression
(
commas
)
{
function
expression
(
commas
,
no_in
)
{
if
(
arguments
.
length
==
0
)
if
(
arguments
.
length
==
0
)
commas
=
true
;
commas
=
true
;
var
expr
=
maybe_assign
();
var
expr
=
maybe_assign
(
no_in
);
if
(
commas
&&
is
(
"punc"
,
","
))
{
if
(
commas
&&
is
(
"punc"
,
","
))
{
next
();
next
();
return
as
(
"seq"
,
expr
,
expression
());
return
as
(
"seq"
,
expr
,
expression
(
true
,
no_in
));
}
}
return
expr
;
return
expr
;
};
};
...
@@ -1222,6 +1297,8 @@ function HOP(obj, prop) {
...
@@ -1222,6 +1297,8 @@ function HOP(obj, prop) {
return
Object
.
prototype
.
hasOwnProperty
.
call
(
obj
,
prop
);
return
Object
.
prototype
.
hasOwnProperty
.
call
(
obj
,
prop
);
};
};
var
warn
=
function
()
{};
/* -----[ Exports ]----- */
/* -----[ Exports ]----- */
exports
.
tokenizer
=
tokenizer
;
exports
.
tokenizer
=
tokenizer
;
...
@@ -1237,3 +1314,6 @@ exports.KEYWORDS = KEYWORDS;
...
@@ -1237,3 +1314,6 @@ exports.KEYWORDS = KEYWORDS;
exports
.
ATOMIC_START_TOKEN
=
ATOMIC_START_TOKEN
;
exports
.
ATOMIC_START_TOKEN
=
ATOMIC_START_TOKEN
;
exports
.
OPERATORS
=
OPERATORS
;
exports
.
OPERATORS
=
OPERATORS
;
exports
.
is_alphanumeric_char
=
is_alphanumeric_char
;
exports
.
is_alphanumeric_char
=
is_alphanumeric_char
;
exports
.
set_logger
=
function
(
logger
)
{
warn
=
logger
;
};
build/lib/process.js
View file @
2a714934
...
@@ -10,14 +10,13 @@
...
@@ -10,14 +10,13 @@
Exported functions:
Exported functions:
- ast_mangle(ast, include_toplevel) -- mangles the
- ast_mangle(ast, options) -- mangles the variable/function names
variable/function names in the AST. Returns an AST. Pass true
in the AST. Returns an AST.
as second argument to mangle toplevel names too.
- ast_squeeze(ast) -- employs various optimizations to make the
- ast_squeeze(ast) -- employs various optimizations to make the
final generated code even smaller. Returns an AST.
final generated code even smaller. Returns an AST.
- gen_code(ast,
beautify
) -- generates JS code from the AST. Pass
- gen_code(ast,
options
) -- generates JS code from the AST. Pass
true (or an object, see the code for some options) as second
true (or an object, see the code for some options) as second
argument to get "pretty" (indented) code.
argument to get "pretty" (indented) code.
...
@@ -69,139 +68,135 @@ var jsp = require("./parse-js"),
...
@@ -69,139 +68,135 @@ var jsp = require("./parse-js"),
function
ast_walker
(
ast
)
{
function
ast_walker
(
ast
)
{
function
_vardefs
(
defs
)
{
function
_vardefs
(
defs
)
{
return
MAP
(
defs
,
function
(
def
){
return
[
this
[
0
],
MAP
(
defs
,
function
(
def
){
var
a
=
[
def
[
0
]
];
var
a
=
[
def
[
0
]
];
if
(
def
.
length
>
1
)
if
(
def
.
length
>
1
)
a
[
1
]
=
walk
(
def
[
1
]);
a
[
1
]
=
walk
(
def
[
1
]);
return
a
;
return
a
;
});
})
]
;
};
};
var
walkers
=
{
var
walkers
=
{
"string"
:
function
(
str
)
{
"string"
:
function
(
str
)
{
return
[
"string"
,
str
];
return
[
this
[
0
]
,
str
];
},
},
"num"
:
function
(
num
)
{
"num"
:
function
(
num
)
{
return
[
"num"
,
num
];
return
[
this
[
0
]
,
num
];
},
},
"name"
:
function
(
name
)
{
"name"
:
function
(
name
)
{
return
[
"name"
,
name
];
return
[
this
[
0
]
,
name
];
},
},
"toplevel"
:
function
(
statements
)
{
"toplevel"
:
function
(
statements
)
{
return
[
"toplevel"
,
MAP
(
statements
,
walk
)
];
return
[
this
[
0
]
,
MAP
(
statements
,
walk
)
];
},
},
"block"
:
function
(
statements
)
{
"block"
:
function
(
statements
)
{
var
out
=
[
"block"
];
var
out
=
[
this
[
0
]
];
if
(
statements
!=
null
)
if
(
statements
!=
null
)
out
.
push
(
MAP
(
statements
,
walk
));
out
.
push
(
MAP
(
statements
,
walk
));
return
out
;
return
out
;
},
},
"var"
:
function
(
defs
)
{
"var"
:
_vardefs
,
return
[
"var"
,
_vardefs
(
defs
)
];
"const"
:
_vardefs
,
},
"const"
:
function
(
defs
)
{
return
[
"const"
,
_vardefs
(
defs
)
];
},
"try"
:
function
(
t
,
c
,
f
)
{
"try"
:
function
(
t
,
c
,
f
)
{
return
[
return
[
"try"
,
this
[
0
]
,
MAP
(
t
,
walk
),
MAP
(
t
,
walk
),
c
!=
null
?
[
c
[
0
],
MAP
(
c
[
1
],
walk
)
]
:
null
,
c
!=
null
?
[
c
[
0
],
MAP
(
c
[
1
],
walk
)
]
:
null
,
f
!=
null
?
MAP
(
f
,
walk
)
:
null
f
!=
null
?
MAP
(
f
,
walk
)
:
null
];
];
},
},
"throw"
:
function
(
expr
)
{
"throw"
:
function
(
expr
)
{
return
[
"throw"
,
walk
(
expr
)
];
return
[
this
[
0
]
,
walk
(
expr
)
];
},
},
"new"
:
function
(
ctor
,
args
)
{
"new"
:
function
(
ctor
,
args
)
{
return
[
"new"
,
walk
(
ctor
),
MAP
(
args
,
walk
)
];
return
[
this
[
0
]
,
walk
(
ctor
),
MAP
(
args
,
walk
)
];
},
},
"switch"
:
function
(
expr
,
body
)
{
"switch"
:
function
(
expr
,
body
)
{
return
[
"switch"
,
walk
(
expr
),
MAP
(
body
,
function
(
branch
){
return
[
this
[
0
]
,
walk
(
expr
),
MAP
(
body
,
function
(
branch
){
return
[
branch
[
0
]
?
walk
(
branch
[
0
])
:
null
,
return
[
branch
[
0
]
?
walk
(
branch
[
0
])
:
null
,
MAP
(
branch
[
1
],
walk
)
];
MAP
(
branch
[
1
],
walk
)
];
})
];
})
];
},
},
"break"
:
function
(
label
)
{
"break"
:
function
(
label
)
{
return
[
"break"
,
label
];
return
[
this
[
0
]
,
label
];
},
},
"continue"
:
function
(
label
)
{
"continue"
:
function
(
label
)
{
return
[
"continue"
,
label
];
return
[
this
[
0
]
,
label
];
},
},
"conditional"
:
function
(
cond
,
t
,
e
)
{
"conditional"
:
function
(
cond
,
t
,
e
)
{
return
[
"conditional"
,
walk
(
cond
),
walk
(
t
),
walk
(
e
)
];
return
[
this
[
0
]
,
walk
(
cond
),
walk
(
t
),
walk
(
e
)
];
},
},
"assign"
:
function
(
op
,
lvalue
,
rvalue
)
{
"assign"
:
function
(
op
,
lvalue
,
rvalue
)
{
return
[
"assign"
,
op
,
walk
(
lvalue
),
walk
(
rvalue
)
];
return
[
this
[
0
]
,
op
,
walk
(
lvalue
),
walk
(
rvalue
)
];
},
},
"dot"
:
function
(
expr
)
{
"dot"
:
function
(
expr
)
{
return
[
"dot"
,
walk
(
expr
)
].
concat
(
slice
(
arguments
,
1
));
return
[
this
[
0
]
,
walk
(
expr
)
].
concat
(
slice
(
arguments
,
1
));
},
},
"call"
:
function
(
expr
,
args
)
{
"call"
:
function
(
expr
,
args
)
{
return
[
"call"
,
walk
(
expr
),
MAP
(
args
,
walk
)
];
return
[
this
[
0
]
,
walk
(
expr
),
MAP
(
args
,
walk
)
];
},
},
"function"
:
function
(
name
,
args
,
body
)
{
"function"
:
function
(
name
,
args
,
body
)
{
return
[
"function"
,
name
,
args
.
slice
(),
MAP
(
body
,
walk
)
];
return
[
this
[
0
]
,
name
,
args
.
slice
(),
MAP
(
body
,
walk
)
];
},
},
"defun"
:
function
(
name
,
args
,
body
)
{
"defun"
:
function
(
name
,
args
,
body
)
{
return
[
"defun"
,
name
,
args
.
slice
(),
MAP
(
body
,
walk
)
];
return
[
this
[
0
]
,
name
,
args
.
slice
(),
MAP
(
body
,
walk
)
];
},
},
"if"
:
function
(
conditional
,
t
,
e
)
{
"if"
:
function
(
conditional
,
t
,
e
)
{
return
[
"if"
,
walk
(
conditional
),
walk
(
t
),
walk
(
e
)
];
return
[
this
[
0
]
,
walk
(
conditional
),
walk
(
t
),
walk
(
e
)
];
},
},
"for"
:
function
(
init
,
cond
,
step
,
block
)
{
"for"
:
function
(
init
,
cond
,
step
,
block
)
{
return
[
"for"
,
walk
(
init
),
walk
(
cond
),
walk
(
step
),
walk
(
block
)
];
return
[
this
[
0
]
,
walk
(
init
),
walk
(
cond
),
walk
(
step
),
walk
(
block
)
];
},
},
"for-in"
:
function
(
has_
var
,
key
,
hash
,
block
)
{
"for-in"
:
function
(
v
var
,
key
,
hash
,
block
)
{
return
[
"for-in"
,
has_var
,
key
,
walk
(
hash
),
walk
(
block
)
];
return
[
this
[
0
],
walk
(
vvar
),
walk
(
key
)
,
walk
(
hash
),
walk
(
block
)
];
},
},
"while"
:
function
(
cond
,
block
)
{
"while"
:
function
(
cond
,
block
)
{
return
[
"while"
,
walk
(
cond
),
walk
(
block
)
];
return
[
this
[
0
]
,
walk
(
cond
),
walk
(
block
)
];
},
},
"do"
:
function
(
cond
,
block
)
{
"do"
:
function
(
cond
,
block
)
{
return
[
"do"
,
walk
(
cond
),
walk
(
block
)
];
return
[
this
[
0
]
,
walk
(
cond
),
walk
(
block
)
];
},
},
"return"
:
function
(
expr
)
{
"return"
:
function
(
expr
)
{
return
[
"return"
,
walk
(
expr
)
];
return
[
this
[
0
]
,
walk
(
expr
)
];
},
},
"binary"
:
function
(
op
,
left
,
right
)
{
"binary"
:
function
(
op
,
left
,
right
)
{
return
[
"binary"
,
op
,
walk
(
left
),
walk
(
right
)
];
return
[
this
[
0
]
,
op
,
walk
(
left
),
walk
(
right
)
];
},
},
"unary-prefix"
:
function
(
op
,
expr
)
{
"unary-prefix"
:
function
(
op
,
expr
)
{
return
[
"unary-prefix"
,
op
,
walk
(
expr
)
];
return
[
this
[
0
]
,
op
,
walk
(
expr
)
];
},
},
"unary-postfix"
:
function
(
op
,
expr
)
{
"unary-postfix"
:
function
(
op
,
expr
)
{
return
[
"unary-postfix"
,
op
,
walk
(
expr
)
];
return
[
this
[
0
]
,
op
,
walk
(
expr
)
];
},
},
"sub"
:
function
(
expr
,
subscript
)
{
"sub"
:
function
(
expr
,
subscript
)
{
return
[
"sub"
,
walk
(
expr
),
walk
(
subscript
)
];
return
[
this
[
0
]
,
walk
(
expr
),
walk
(
subscript
)
];
},
},
"object"
:
function
(
props
)
{
"object"
:
function
(
props
)
{
return
[
"object"
,
MAP
(
props
,
function
(
p
){
return
[
this
[
0
]
,
MAP
(
props
,
function
(
p
){
return
p
.
length
==
2
return
p
.
length
==
2
?
[
p
[
0
],
walk
(
p
[
1
])
]
?
[
p
[
0
],
walk
(
p
[
1
])
]
:
[
p
[
0
],
walk
(
p
[
1
]),
p
[
2
]
];
// get/set-ter
:
[
p
[
0
],
walk
(
p
[
1
]),
p
[
2
]
];
// get/set-ter
})
];
})
];
},
},
"regexp"
:
function
(
rx
,
mods
)
{
"regexp"
:
function
(
rx
,
mods
)
{
return
[
"regexp"
,
rx
,
mods
];
return
[
this
[
0
]
,
rx
,
mods
];
},
},
"array"
:
function
(
elements
)
{
"array"
:
function
(
elements
)
{
return
[
"array"
,
MAP
(
elements
,
walk
)
];
return
[
this
[
0
]
,
MAP
(
elements
,
walk
)
];
},
},
"stat"
:
function
(
stat
)
{
"stat"
:
function
(
stat
)
{
return
[
"stat"
,
walk
(
stat
)
];
return
[
this
[
0
]
,
walk
(
stat
)
];
},
},
"seq"
:
function
()
{
"seq"
:
function
()
{
return
[
"seq"
].
concat
(
MAP
(
slice
(
arguments
),
walk
));
return
[
this
[
0
]
].
concat
(
MAP
(
slice
(
arguments
),
walk
));
},
},
"label"
:
function
(
name
,
block
)
{
"label"
:
function
(
name
,
block
)
{
return
[
"label"
,
name
,
walk
(
block
)
];
return
[
this
[
0
]
,
name
,
walk
(
block
)
];
},
},
"with"
:
function
(
expr
,
block
)
{
"with"
:
function
(
expr
,
block
)
{
return
[
"with"
,
walk
(
expr
),
walk
(
block
)
];
return
[
this
[
0
]
,
walk
(
expr
),
walk
(
block
)
];
},
},
"atom"
:
function
(
name
)
{
"atom"
:
function
(
name
)
{
return
[
"atom"
,
name
];
return
[
this
[
0
]
,
name
];
}
}
};
};
...
@@ -260,8 +255,8 @@ function Scope(parent) {
...
@@ -260,8 +255,8 @@ function Scope(parent) {
this
.
rev_mangled
=
{};
// reverse lookup (mangled => orig.name)
this
.
rev_mangled
=
{};
// reverse lookup (mangled => orig.name)
this
.
cname
=
-
1
;
// current mangled name
this
.
cname
=
-
1
;
// current mangled name
this
.
refs
=
{};
// names referenced from this scope
this
.
refs
=
{};
// names referenced from this scope
this
.
uses_with
=
false
;
// will become TRUE if
eval
() is detected in this or any subscopes
this
.
uses_with
=
false
;
// will become TRUE if
with
() is detected in this or any subscopes
this
.
uses_eval
=
false
;
// will become TRUE if
with
() is detected in this or any subscopes
this
.
uses_eval
=
false
;
// will become TRUE if
eval
() is detected in this or any subscopes
this
.
parent
=
parent
;
// parent scope
this
.
parent
=
parent
;
// parent scope
this
.
children
=
[];
// sub-scopes
this
.
children
=
[];
// sub-scopes
if
(
parent
)
{
if
(
parent
)
{
...
@@ -382,7 +377,7 @@ function ast_add_scope(ast) {
...
@@ -382,7 +377,7 @@ function ast_add_scope(ast) {
};
};
function
_lambda
(
name
,
args
,
body
)
{
function
_lambda
(
name
,
args
,
body
)
{
return
[
this
[
0
],
define
(
name
)
,
args
,
with_new_scope
(
function
(){
return
[
this
[
0
],
this
[
0
]
==
"defun"
?
define
(
name
)
:
name
,
args
,
with_new_scope
(
function
(){
MAP
(
args
,
define
);
MAP
(
args
,
define
);
return
MAP
(
body
,
walk
);
return
MAP
(
body
,
walk
);
})];
})];
...
@@ -405,7 +400,7 @@ function ast_add_scope(ast) {
...
@@ -405,7 +400,7 @@ function ast_add_scope(ast) {
},
},
"try"
:
function
(
t
,
c
,
f
)
{
"try"
:
function
(
t
,
c
,
f
)
{
if
(
c
!=
null
)
return
[
if
(
c
!=
null
)
return
[
"try"
,
this
[
0
]
,
MAP
(
t
,
walk
),
MAP
(
t
,
walk
),
[
define
(
c
[
0
]),
MAP
(
c
[
1
],
walk
)
],
[
define
(
c
[
0
]),
MAP
(
c
[
1
],
walk
)
],
f
!=
null
?
MAP
(
f
,
walk
)
:
null
f
!=
null
?
MAP
(
f
,
walk
)
:
null
...
@@ -415,10 +410,6 @@ function ast_add_scope(ast) {
...
@@ -415,10 +410,6 @@ function ast_add_scope(ast) {
if
(
name
==
"eval"
)
if
(
name
==
"eval"
)
having_eval
.
push
(
current_scope
);
having_eval
.
push
(
current_scope
);
reference
(
name
);
reference
(
name
);
},
"for-in"
:
function
(
has_var
,
name
)
{
if
(
has_var
)
define
(
name
);
else
reference
(
name
);
}
}
},
function
(){
},
function
(){
return
walk
(
ast
);
return
walk
(
ast
);
...
@@ -461,11 +452,14 @@ function ast_add_scope(ast) {
...
@@ -461,11 +452,14 @@ function ast_add_scope(ast) {
/* -----[ mangle names ]----- */
/* -----[ mangle names ]----- */
function
ast_mangle
(
ast
,
do_toplevel
)
{
function
ast_mangle
(
ast
,
options
)
{
var
w
=
ast_walker
(),
walk
=
w
.
walk
,
scope
;
var
w
=
ast_walker
(),
walk
=
w
.
walk
,
scope
;
options
=
options
||
{};
function
get_mangled
(
name
,
newMangle
)
{
function
get_mangled
(
name
,
newMangle
)
{
if
(
!
do_toplevel
&&
!
scope
.
parent
)
return
name
;
// don't mangle toplevel
if
(
!
options
.
toplevel
&&
!
scope
.
parent
)
return
name
;
// don't mangle toplevel
if
(
options
.
except
&&
member
(
name
,
options
.
except
))
return
name
;
return
scope
.
get_mangled
(
name
,
newMangle
);
return
scope
.
get_mangled
(
name
,
newMangle
);
};
};
...
@@ -491,9 +485,9 @@ function ast_mangle(ast, do_toplevel) {
...
@@ -491,9 +485,9 @@ function ast_mangle(ast, do_toplevel) {
};
};
function
_vardefs
(
defs
)
{
function
_vardefs
(
defs
)
{
return
MAP
(
defs
,
function
(
d
){
return
[
this
[
0
],
MAP
(
defs
,
function
(
d
){
return
[
get_mangled
(
d
[
0
]),
walk
(
d
[
1
])
];
return
[
get_mangled
(
d
[
0
]),
walk
(
d
[
1
])
];
});
})
]
;
};
};
return
w
.
with_walkers
({
return
w
.
with_walkers
({
...
@@ -510,28 +504,22 @@ function ast_mangle(ast, do_toplevel) {
...
@@ -510,28 +504,22 @@ function ast_mangle(ast, do_toplevel) {
}
}
return
ast
;
return
ast
;
},
},
"var"
:
function
(
defs
)
{
"var"
:
_vardefs
,
return
[
"var"
,
_vardefs
(
defs
)
];
"const"
:
_vardefs
,
},
"const"
:
function
(
defs
)
{
return
[
"const"
,
_vardefs
(
defs
)
];
},
"name"
:
function
(
name
)
{
"name"
:
function
(
name
)
{
return
[
"name"
,
get_mangled
(
name
)
];
return
[
this
[
0
]
,
get_mangled
(
name
)
];
},
},
"try"
:
function
(
t
,
c
,
f
)
{
"try"
:
function
(
t
,
c
,
f
)
{
return
[
"try"
,
return
[
this
[
0
]
,
MAP
(
t
,
walk
),
MAP
(
t
,
walk
),
c
!=
null
?
[
get_mangled
(
c
[
0
]),
MAP
(
c
[
1
],
walk
)
]
:
null
,
c
!=
null
?
[
get_mangled
(
c
[
0
]),
MAP
(
c
[
1
],
walk
)
]
:
null
,
f
!=
null
?
MAP
(
f
,
walk
)
:
null
];
f
!=
null
?
MAP
(
f
,
walk
)
:
null
];
},
},
"toplevel"
:
function
(
body
)
{
"toplevel"
:
function
(
body
)
{
return
with_scope
(
this
.
scope
,
function
(){
var
self
=
this
;
return
[
"toplevel"
,
MAP
(
body
,
walk
)
];
return
with_scope
(
self
.
scope
,
function
(){
return
[
self
[
0
],
MAP
(
body
,
walk
)
];
});
});
},
"for-in"
:
function
(
has_var
,
name
,
obj
,
stat
)
{
return
[
"for-in"
,
has_var
,
get_mangled
(
name
),
walk
(
obj
),
walk
(
stat
)
];
}
}
},
function
()
{
},
function
()
{
return
walk
(
ast_add_scope
(
ast
));
return
walk
(
ast_add_scope
(
ast
));
...
@@ -569,28 +557,29 @@ function aborts(t) {
...
@@ -569,28 +557,29 @@ function aborts(t) {
}
}
};
};
function
negate
(
c
)
{
function
boolean_expr
(
expr
)
{
var
not_c
=
[
"unary-prefix"
,
"!"
,
c
];
return
(
(
expr
[
0
]
==
"unary-prefix"
switch
(
c
[
0
])
{
&&
member
(
expr
[
1
],
[
"!"
,
"delete"
]))
||
case
"unary-prefix"
:
return
c
[
1
]
==
"!"
?
c
[
2
]
:
not_c
;
(
expr
[
0
]
==
"binary"
case
"binary"
:
&&
member
(
expr
[
1
],
[
"in"
,
"instanceof"
,
"=="
,
"!="
,
"==="
,
"!=="
,
"<"
,
"<="
,
">="
,
">"
]))
||
var
op
=
c
[
1
],
left
=
c
[
2
],
right
=
c
[
3
];
switch
(
op
)
{
(
expr
[
0
]
==
"binary"
case
"<="
:
return
[
"binary"
,
">"
,
left
,
right
];
&&
member
(
expr
[
1
],
[
"&&"
,
"||"
])
case
"<"
:
return
[
"binary"
,
">="
,
left
,
right
];
&&
boolean_expr
(
expr
[
2
])
case
">="
:
return
[
"binary"
,
"<"
,
left
,
right
];
&&
boolean_expr
(
expr
[
3
]))
||
case
">"
:
return
[
"binary"
,
"<="
,
left
,
right
];
case
"=="
:
return
[
"binary"
,
"!="
,
left
,
right
];
(
expr
[
0
]
==
"conditional"
case
"!="
:
return
[
"binary"
,
"=="
,
left
,
right
];
&&
boolean_expr
(
expr
[
2
])
case
"==="
:
return
[
"binary"
,
"!=="
,
left
,
right
];
&&
boolean_expr
(
expr
[
3
]))
||
case
"!=="
:
return
[
"binary"
,
"==="
,
left
,
right
];
case
"&&"
:
return
best_of
(
not_c
,
[
"binary"
,
"||"
,
negate
(
left
),
negate
(
right
)
]);
(
expr
[
0
]
==
"assign"
case
"||"
:
return
best_of
(
not_c
,
[
"binary"
,
"&&"
,
negate
(
left
),
negate
(
right
)
]);
&&
expr
[
1
]
===
true
}
&&
boolean_expr
(
expr
[
3
]))
||
break
;
}
(
expr
[
0
]
==
"seq"
return
not_c
;
&&
boolean_expr
(
expr
[
expr
.
length
-
1
]))
);
};
};
function
make_conditional
(
c
,
t
,
e
)
{
function
make_conditional
(
c
,
t
,
e
)
{
...
@@ -605,16 +594,143 @@ function empty(b) {
...
@@ -605,16 +594,143 @@ function empty(b) {
return
!
b
||
(
b
[
0
]
==
"block"
&&
(
!
b
[
1
]
||
b
[
1
].
length
==
0
));
return
!
b
||
(
b
[
0
]
==
"block"
&&
(
!
b
[
1
]
||
b
[
1
].
length
==
0
));
};
};
function
is_string
(
node
)
{
return
(
node
[
0
]
==
"string"
||
node
[
0
]
==
"unary-prefix"
&&
node
[
1
]
==
"typeof"
||
node
[
0
]
==
"binary"
&&
node
[
1
]
==
"+"
&&
(
is_string
(
node
[
2
])
||
is_string
(
node
[
3
])));
};
var
when_constant
=
(
function
(){
var
$NOT_CONSTANT
=
{};
// this can only evaluate constant expressions. If it finds anything
// not constant, it throws $NOT_CONSTANT.
function
evaluate
(
expr
)
{
switch
(
expr
[
0
])
{
case
"string"
:
case
"num"
:
return
expr
[
1
];
case
"name"
:
case
"atom"
:
switch
(
expr
[
1
])
{
case
"true"
:
return
true
;
case
"false"
:
return
false
;
}
break
;
case
"unary-prefix"
:
switch
(
expr
[
1
])
{
case
"!"
:
return
!
evaluate
(
expr
[
2
]);
case
"typeof"
:
return
typeof
evaluate
(
expr
[
2
]);
case
"~"
:
return
~
evaluate
(
expr
[
2
]);
case
"-"
:
return
-
evaluate
(
expr
[
2
]);
case
"+"
:
return
+
evaluate
(
expr
[
2
]);
}
break
;
case
"binary"
:
var
left
=
expr
[
2
],
right
=
expr
[
3
];
switch
(
expr
[
1
])
{
case
"&&"
:
return
evaluate
(
left
)
&&
evaluate
(
right
);
case
"||"
:
return
evaluate
(
left
)
||
evaluate
(
right
);
case
"|"
:
return
evaluate
(
left
)
|
evaluate
(
right
);
case
"&"
:
return
evaluate
(
left
)
&
evaluate
(
right
);
case
"^"
:
return
evaluate
(
left
)
^
evaluate
(
right
);
case
"+"
:
return
evaluate
(
left
)
+
evaluate
(
right
);
case
"*"
:
return
evaluate
(
left
)
*
evaluate
(
right
);
case
"/"
:
return
evaluate
(
left
)
/
evaluate
(
right
);
case
"-"
:
return
evaluate
(
left
)
-
evaluate
(
right
);
case
"<<"
:
return
evaluate
(
left
)
<<
evaluate
(
right
);
case
">>"
:
return
evaluate
(
left
)
>>
evaluate
(
right
);
case
">>>"
:
return
evaluate
(
left
)
>>>
evaluate
(
right
);
case
"=="
:
return
evaluate
(
left
)
==
evaluate
(
right
);
case
"==="
:
return
evaluate
(
left
)
===
evaluate
(
right
);
case
"!="
:
return
evaluate
(
left
)
!=
evaluate
(
right
);
case
"!=="
:
return
evaluate
(
left
)
!==
evaluate
(
right
);
case
"<"
:
return
evaluate
(
left
)
<
evaluate
(
right
);
case
"<="
:
return
evaluate
(
left
)
<=
evaluate
(
right
);
case
">"
:
return
evaluate
(
left
)
>
evaluate
(
right
);
case
">="
:
return
evaluate
(
left
)
>=
evaluate
(
right
);
case
"in"
:
return
evaluate
(
left
)
in
evaluate
(
right
);
case
"instanceof"
:
return
evaluate
(
left
)
instanceof
evaluate
(
right
);
}
}
throw
$NOT_CONSTANT
;
};
return
function
(
expr
,
yes
,
no
)
{
try
{
var
val
=
evaluate
(
expr
),
ast
;
switch
(
typeof
val
)
{
case
"string"
:
ast
=
[
"string"
,
val
];
break
;
case
"number"
:
ast
=
[
"num"
,
val
];
break
;
case
"boolean"
:
ast
=
[
"name"
,
String
(
val
)
];
break
;
default
:
throw
new
Error
(
"Can't handle constant of type: "
+
(
typeof
val
));
}
return
yes
.
call
(
expr
,
ast
,
val
);
}
catch
(
ex
)
{
if
(
ex
===
$NOT_CONSTANT
)
{
if
(
expr
[
0
]
==
"binary"
&&
(
expr
[
1
]
==
"==="
||
expr
[
1
]
==
"!=="
)
&&
((
is_string
(
expr
[
2
])
&&
is_string
(
expr
[
3
]))
||
(
boolean_expr
(
expr
[
2
])
&&
boolean_expr
(
expr
[
3
]))))
{
expr
[
1
]
=
expr
[
1
].
substr
(
0
,
2
);
}
return
no
?
no
.
call
(
expr
,
expr
)
:
null
;
}
else
throw
ex
;
}
};
})();
function
warn_unreachable
(
ast
)
{
if
(
!
empty
(
ast
))
warn
(
"Dropping unreachable code: "
+
gen_code
(
ast
,
true
));
};
function
ast_squeeze
(
ast
,
options
)
{
function
ast_squeeze
(
ast
,
options
)
{
options
=
defaults
(
options
,
{
options
=
defaults
(
options
,
{
make_seqs
:
true
,
make_seqs
:
true
,
dead_code
:
true
,
dead_code
:
true
,
no_warnings
:
fals
e
,
keep_comps
:
tru
e
,
extra
:
false
no_warnings
:
false
});
});
var
w
=
ast_walker
(),
walk
=
w
.
walk
,
scope
;
var
w
=
ast_walker
(),
walk
=
w
.
walk
,
scope
;
function
negate
(
c
)
{
var
not_c
=
[
"unary-prefix"
,
"!"
,
c
];
switch
(
c
[
0
])
{
case
"unary-prefix"
:
return
c
[
1
]
==
"!"
&&
boolean_expr
(
c
[
2
])
?
c
[
2
]
:
not_c
;
case
"seq"
:
c
=
slice
(
c
);
c
[
c
.
length
-
1
]
=
negate
(
c
[
c
.
length
-
1
]);
return
c
;
case
"conditional"
:
return
best_of
(
not_c
,
[
"conditional"
,
c
[
1
],
negate
(
c
[
2
]),
negate
(
c
[
3
])
]);
case
"binary"
:
var
op
=
c
[
1
],
left
=
c
[
2
],
right
=
c
[
3
];
if
(
!
options
.
keep_comps
)
switch
(
op
)
{
case
"<="
:
return
[
"binary"
,
">"
,
left
,
right
];
case
"<"
:
return
[
"binary"
,
">="
,
left
,
right
];
case
">="
:
return
[
"binary"
,
"<"
,
left
,
right
];
case
">"
:
return
[
"binary"
,
"<="
,
left
,
right
];
}
switch
(
op
)
{
case
"=="
:
return
[
"binary"
,
"!="
,
left
,
right
];
case
"!="
:
return
[
"binary"
,
"=="
,
left
,
right
];
case
"==="
:
return
[
"binary"
,
"!=="
,
left
,
right
];
case
"!=="
:
return
[
"binary"
,
"==="
,
left
,
right
];
case
"&&"
:
return
best_of
(
not_c
,
[
"binary"
,
"||"
,
negate
(
left
),
negate
(
right
)
]);
case
"||"
:
return
best_of
(
not_c
,
[
"binary"
,
"&&"
,
negate
(
left
),
negate
(
right
)
]);
}
break
;
}
return
not_c
;
};
function
with_scope
(
s
,
cont
)
{
function
with_scope
(
s
,
cont
)
{
var
_scope
=
scope
;
var
_scope
=
scope
;
scope
=
s
;
scope
=
s
;
...
@@ -624,89 +740,14 @@ function ast_squeeze(ast, options) {
...
@@ -624,89 +740,14 @@ function ast_squeeze(ast, options) {
return
ret
;
return
ret
;
};
};
function
is_constant
(
node
)
{
return
node
[
0
]
==
"string"
||
node
[
0
]
==
"num"
;
};
function
find_first_execute
(
node
)
{
if
(
!
node
)
return
false
;
switch
(
node
[
0
])
{
case
"num"
:
case
"string"
:
case
"name"
:
return
node
;
case
"call"
:
case
"conditional"
:
case
"for"
:
case
"if"
:
case
"new"
:
case
"return"
:
case
"stat"
:
case
"switch"
:
case
"throw"
:
return
find_first_execute
(
node
[
1
]);
case
"binary"
:
return
find_first_execute
(
node
[
2
]);
case
"assign"
:
if
(
node
[
1
]
===
true
)
return
find_first_execute
(
node
[
3
]);
break
;
case
"var"
:
if
(
node
[
1
][
0
].
length
>
1
)
return
find_first_execute
(
node
[
1
][
0
][
1
]);
break
;
}
return
null
;
}
function
find_assign_recursive
(
p
,
v
)
{
if
(
p
[
0
]
==
"assign"
&&
p
[
1
]
!=
true
||
p
[
0
]
==
"unary-prefix"
)
{
if
(
p
[
2
][
0
]
==
"name"
&&
v
[
0
]
==
"name"
&&
p
[
2
][
1
]
==
v
[
1
])
return
true
;
return
false
;
}
if
(
p
[
0
]
!=
"assign"
||
p
[
1
]
!==
true
)
return
false
;
if
((
is_constant
(
p
[
3
])
&&
p
[
3
][
0
]
==
v
[
0
]
&&
p
[
3
][
1
]
==
v
[
1
])
||
(
p
[
3
][
0
]
==
"name"
&&
v
[
0
]
==
"name"
&&
p
[
3
][
1
]
==
v
[
1
])
||
(
p
[
2
][
0
]
==
"name"
&&
v
[
0
]
==
"name"
&&
p
[
2
][
1
]
==
v
[
1
]))
return
true
;
return
find_assign_recursive
(
p
[
3
],
v
);
};
function
rmblock
(
block
)
{
function
rmblock
(
block
)
{
if
(
block
!=
null
&&
block
[
0
]
==
"block"
&&
block
[
1
]
&&
block
[
1
].
length
==
1
)
if
(
block
!=
null
&&
block
[
0
]
==
"block"
&&
block
[
1
])
{
if
(
block
[
1
].
length
==
1
)
block
=
block
[
1
][
0
];
block
=
block
[
1
][
0
];
return
block
;
else
if
(
block
[
1
].
length
==
0
)
};
block
=
[
"block"
];
function
clone
(
obj
)
{
if
(
obj
&&
obj
.
constructor
==
Array
)
return
MAP
(
obj
,
clone
);
return
obj
;
};
function
make_seq_to_statements
(
node
)
{
if
(
node
[
0
]
!=
"seq"
)
{
switch
(
node
[
0
])
{
case
"var"
:
case
"const"
:
return
[
node
];
default
:
return
[
[
"stat"
,
node
]
];
}
}
}
return
block
;
var
ret
=
[];
for
(
var
i
=
1
;
i
<
node
.
length
;
i
++
)
ret
.
push
.
apply
(
ret
,
make_seq_to_statements
(
node
[
i
]));
return
ret
;
};
};
function
_lambda
(
name
,
args
,
body
)
{
function
_lambda
(
name
,
args
,
body
)
{
...
@@ -734,64 +775,6 @@ function ast_squeeze(ast, options) {
...
@@ -734,64 +775,6 @@ function ast_squeeze(ast, options) {
return
a
;
return
a
;
},
[]);
},
[]);
if
(
options
.
extra
)
{
// Detightening things. We do this because then we can assume that the
// statements are structured in a specific way.
statements
=
(
function
(
a
,
prev
)
{
statements
.
forEach
(
function
(
cur
)
{
switch
(
cur
[
0
])
{
case
"for"
:
if
(
cur
[
1
]
!=
null
)
{
a
.
push
.
apply
(
a
,
make_seq_to_statements
(
cur
[
1
]));
cur
[
1
]
=
null
;
}
a
.
push
(
cur
);
break
;
case
"stat"
:
var
stats
=
make_seq_to_statements
(
cur
[
1
]);
stats
.
forEach
(
function
(
s
)
{
if
(
s
[
1
][
0
]
==
"unary-postfix"
)
s
[
1
][
0
]
=
"unary-prefix"
;
});
a
.
push
.
apply
(
a
,
stats
);
break
;
default
:
a
.
push
(
cur
);
}
});
return
a
;
})([]);
statements
=
(
function
(
a
,
prev
)
{
statements
.
forEach
(
function
(
cur
)
{
if
(
!
(
prev
&&
prev
[
0
]
==
"stat"
))
{
a
.
push
(
cur
);
prev
=
cur
;
return
;
}
var
p
=
prev
[
1
];
var
c
=
find_first_execute
(
cur
);
if
(
c
&&
find_assign_recursive
(
p
,
c
))
{
var
old_cur
=
clone
(
cur
);
c
.
splice
(
0
,
c
.
length
);
c
.
push
.
apply
(
c
,
p
);
var
tmp_cur
=
best_of
(
cur
,
[
"toplevel"
,
[
prev
,
old_cur
]
]);
if
(
tmp_cur
==
cur
)
{
a
[
a
.
length
-
1
]
=
cur
;
}
else
{
cur
=
old_cur
;
a
.
push
(
cur
);
}
}
else
{
a
.
push
(
cur
);
}
prev
=
cur
;
});
return
a
;
})([]);
}
statements
=
(
function
(
a
,
prev
){
statements
=
(
function
(
a
,
prev
){
statements
.
forEach
(
function
(
cur
){
statements
.
forEach
(
function
(
cur
){
if
(
prev
&&
((
cur
[
0
]
==
"var"
&&
prev
[
0
]
==
"var"
)
||
if
(
prev
&&
((
cur
[
0
]
==
"var"
&&
prev
[
0
]
==
"var"
)
||
...
@@ -812,7 +795,7 @@ function ast_squeeze(ast, options) {
...
@@ -812,7 +795,7 @@ function ast_squeeze(ast, options) {
a
.
push
(
st
);
a
.
push
(
st
);
}
}
else
if
(
!
options
.
no_warnings
)
else
if
(
!
options
.
no_warnings
)
warn
(
"Removing unreachable code: "
+
gen_code
(
st
,
true
)
);
warn
_unreachable
(
st
);
}
}
else
{
else
{
a
.
push
(
st
);
a
.
push
(
st
);
...
@@ -835,22 +818,6 @@ function ast_squeeze(ast, options) {
...
@@ -835,22 +818,6 @@ function ast_squeeze(ast, options) {
return
a
;
return
a
;
})([]);
})([]);
if
(
options
.
extra
)
{
statements
=
(
function
(
a
,
prev
){
statements
.
forEach
(
function
(
cur
){
var
replaced
=
false
;
if
(
prev
&&
cur
[
0
]
==
"for"
&&
cur
[
1
]
==
null
&&
(
prev
[
0
]
==
"var"
||
prev
[
0
]
==
"const"
||
prev
[
0
]
==
"stat"
))
{
cur
[
1
]
=
prev
;
a
[
a
.
length
-
1
]
=
cur
;
}
else
{
a
.
push
(
cur
);
}
prev
=
cur
;
});
return
a
;
})([]);
}
if
(
block_type
==
"lambda"
)
statements
=
(
function
(
i
,
a
,
stat
){
if
(
block_type
==
"lambda"
)
statements
=
(
function
(
i
,
a
,
stat
){
while
(
i
<
statements
.
length
)
{
while
(
i
<
statements
.
length
)
{
stat
=
statements
[
i
++
];
stat
=
statements
[
i
++
];
...
@@ -874,6 +841,20 @@ function ast_squeeze(ast, options) {
...
@@ -874,6 +841,20 @@ function ast_squeeze(ast, options) {
};
};
function
make_if
(
c
,
t
,
e
)
{
function
make_if
(
c
,
t
,
e
)
{
return
when_constant
(
c
,
function
(
ast
,
val
){
if
(
val
)
{
warn_unreachable
(
e
);
return
t
;
}
else
{
warn_unreachable
(
t
);
return
e
;
}
},
function
()
{
return
make_real_if
(
c
,
t
,
e
);
});
};
function
make_real_if
(
c
,
t
,
e
)
{
c
=
walk
(
c
);
c
=
walk
(
c
);
t
=
walk
(
t
);
t
=
walk
(
t
);
e
=
walk
(
e
);
e
=
walk
(
e
);
...
@@ -901,7 +882,10 @@ function ast_squeeze(ast, options) {
...
@@ -901,7 +882,10 @@ function ast_squeeze(ast, options) {
if
(
empty
(
e
)
&&
empty
(
t
))
if
(
empty
(
e
)
&&
empty
(
t
))
return
[
"stat"
,
c
];
return
[
"stat"
,
c
];
var
ret
=
[
"if"
,
c
,
t
,
e
];
var
ret
=
[
"if"
,
c
,
t
,
e
];
if
(
t
[
0
]
==
"stat"
)
{
if
(
t
[
0
]
==
"if"
&&
empty
(
t
[
3
])
&&
empty
(
e
))
{
ret
=
best_of
(
ret
,
walk
([
"if"
,
[
"binary"
,
"&&"
,
c
,
t
[
1
]
],
t
[
2
]
]));
}
else
if
(
t
[
0
]
==
"stat"
)
{
if
(
e
)
{
if
(
e
)
{
if
(
e
[
0
]
==
"stat"
)
{
if
(
e
[
0
]
==
"stat"
)
{
ret
=
best_of
(
ret
,
[
"stat"
,
make_conditional
(
c
,
t
[
1
],
e
[
1
])
]);
ret
=
best_of
(
ret
,
[
"stat"
,
make_conditional
(
c
,
t
[
1
],
e
[
1
])
]);
...
@@ -911,7 +895,7 @@ function ast_squeeze(ast, options) {
...
@@ -911,7 +895,7 @@ function ast_squeeze(ast, options) {
ret
=
best_of
(
ret
,
[
"stat"
,
make_conditional
(
c
,
t
[
1
])
]);
ret
=
best_of
(
ret
,
[
"stat"
,
make_conditional
(
c
,
t
[
1
])
]);
}
}
}
}
else
if
(
e
&&
t
[
0
]
==
e
[
0
]
&&
(
t
[
0
]
==
"return"
||
t
[
0
]
==
"throw"
))
{
else
if
(
e
&&
t
[
0
]
==
e
[
0
]
&&
(
t
[
0
]
==
"return"
||
t
[
0
]
==
"throw"
)
&&
t
[
1
]
&&
e
[
1
]
)
{
ret
=
best_of
(
ret
,
[
t
[
0
],
make_conditional
(
c
,
t
[
1
],
e
[
1
]
)
]);
ret
=
best_of
(
ret
,
[
t
[
0
],
make_conditional
(
c
,
t
[
1
],
e
[
1
]
)
]);
}
}
else
if
(
e
&&
aborts
(
t
))
{
else
if
(
e
&&
aborts
(
t
))
{
...
@@ -936,13 +920,25 @@ function ast_squeeze(ast, options) {
...
@@ -936,13 +920,25 @@ function ast_squeeze(ast, options) {
return
ret
;
return
ret
;
};
};
function
_do_while
(
cond
,
body
)
{
return
when_constant
(
cond
,
function
(
cond
,
val
){
if
(
!
val
)
{
warn_unreachable
(
body
);
return
[
"block"
];
}
else
{
return
[
"for"
,
null
,
null
,
null
,
walk
(
body
)
];
}
});
};
return
w
.
with_walkers
({
return
w
.
with_walkers
({
"sub"
:
function
(
expr
,
subscript
)
{
"sub"
:
function
(
expr
,
subscript
)
{
if
(
subscript
[
0
]
==
"string"
)
{
if
(
subscript
[
0
]
==
"string"
)
{
var
name
=
subscript
[
1
];
var
name
=
subscript
[
1
];
if
(
is_identifier
(
name
))
{
if
(
is_identifier
(
name
))
return
[
"dot"
,
walk
(
expr
),
name
];
return
[
"dot"
,
walk
(
expr
),
name
];
}
else
if
(
/^
[
1-9
][
0-9
]
*$/
.
test
(
name
)
||
name
===
"0"
)
return
[
"sub"
,
walk
(
expr
),
[
"num"
,
parseInt
(
name
,
10
)
]
];
}
}
},
},
"if"
:
make_if
,
"if"
:
make_if
,
...
@@ -963,35 +959,23 @@ function ast_squeeze(ast, options) {
...
@@ -963,35 +959,23 @@ function ast_squeeze(ast, options) {
return
[
branch
[
0
]
?
walk
(
branch
[
0
])
:
null
,
block
];
return
[
branch
[
0
]
?
walk
(
branch
[
0
])
:
null
,
block
];
})
];
})
];
},
},
"function"
:
_lambda
,
"function"
:
function
()
{
var
ret
=
_lambda
.
apply
(
this
,
arguments
);
if
(
ret
[
1
]
&&
!
HOP
(
scope
.
refs
,
ret
[
1
]))
{
ret
[
1
]
=
null
;
}
return
ret
;
},
"defun"
:
_lambda
,
"defun"
:
_lambda
,
"block"
:
function
(
body
)
{
"block"
:
function
(
body
)
{
if
(
body
)
return
rmblock
([
"block"
,
tighten
(
MAP
(
body
,
walk
))
]);
if
(
body
)
return
rmblock
([
"block"
,
tighten
(
MAP
(
body
,
walk
))
]);
},
},
"binary"
:
function
(
op
,
left
,
right
)
{
"binary"
:
function
(
op
,
left
,
right
)
{
left
=
walk
(
left
);
return
when_constant
([
"binary"
,
op
,
walk
(
left
),
walk
(
right
)
],
function
yes
(
c
){
right
=
walk
(
right
);
return
best_of
(
walk
(
c
),
this
);
var
best
=
[
"binary"
,
op
,
left
,
right
];
},
function
no
()
{
if
(
is_constant
(
right
))
{
return
this
;
if
(
is_constant
(
left
))
{
});
var
val
=
null
;
switch
(
op
)
{
case
"+"
:
val
=
left
[
1
]
+
right
[
1
];
break
;
case
"*"
:
val
=
left
[
1
]
*
right
[
1
];
break
;
case
"/"
:
val
=
left
[
1
]
/
right
[
1
];
break
;
case
"-"
:
val
=
left
[
1
]
-
right
[
1
];
break
;
case
"<<"
:
val
=
left
[
1
]
<<
right
[
1
];
break
;
case
">>"
:
val
=
left
[
1
]
>>
right
[
1
];
break
;
case
">>>"
:
val
=
left
[
1
]
>>>
right
[
1
];
break
;
}
if
(
val
!=
null
)
{
best
=
best_of
(
best
,
[
typeof
val
==
"string"
?
"string"
:
"num"
,
val
]);
}
}
else
if
(
left
[
0
]
==
"binary"
&&
left
[
1
]
==
"+"
&&
left
[
3
][
0
]
==
"string"
)
{
best
=
best_of
(
best
,
[
"binary"
,
"+"
,
left
[
2
],
[
"string"
,
left
[
3
][
1
]
+
right
[
1
]
]
]);
}
}
return
best
;
},
},
"conditional"
:
function
(
c
,
t
,
e
)
{
"conditional"
:
function
(
c
,
t
,
e
)
{
return
make_conditional
(
walk
(
c
),
walk
(
t
),
walk
(
e
));
return
make_conditional
(
walk
(
c
),
walk
(
t
),
walk
(
e
));
...
@@ -1004,17 +988,14 @@ function ast_squeeze(ast, options) {
...
@@ -1004,17 +988,14 @@ function ast_squeeze(ast, options) {
f
!=
null
?
tighten
(
MAP
(
f
,
walk
))
:
null
f
!=
null
?
tighten
(
MAP
(
f
,
walk
))
:
null
];
];
},
},
"unary-prefix"
:
function
(
op
,
cond
)
{
"unary-prefix"
:
function
(
op
,
expr
)
{
if
(
op
==
"!"
)
{
expr
=
walk
(
expr
);
cond
=
walk
(
cond
);
var
ret
=
[
"unary-prefix"
,
op
,
expr
];
if
(
cond
[
0
]
==
"unary-prefix"
&&
cond
[
1
]
==
"!"
)
{
if
(
op
==
"!"
)
var
p
=
w
.
parent
();
ret
=
best_of
(
ret
,
negate
(
expr
));
if
(
p
[
0
]
==
"unary-prefix"
&&
p
[
1
]
==
"!"
)
return
when_constant
(
ret
,
function
(
ast
,
val
){
return
cond
[
2
];
return
walk
(
ast
);
// it's either true or false, so minifies to !0 or !1
return
[
"unary-prefix"
,
"!"
,
cond
];
},
function
()
{
return
ret
});
}
return
best_of
(
this
,
negate
(
cond
));
}
},
},
"name"
:
function
(
name
)
{
"name"
:
function
(
name
)
{
switch
(
name
)
{
switch
(
name
)
{
...
@@ -1035,7 +1016,9 @@ function ast_squeeze(ast, options) {
...
@@ -1035,7 +1016,9 @@ function ast_squeeze(ast, options) {
if
(
expr
[
0
]
==
"name"
&&
expr
[
1
]
==
"Array"
&&
args
.
length
!=
1
&&
!
scope
.
has
(
"Array"
))
{
if
(
expr
[
0
]
==
"name"
&&
expr
[
1
]
==
"Array"
&&
args
.
length
!=
1
&&
!
scope
.
has
(
"Array"
))
{
return
[
"array"
,
args
];
return
[
"array"
,
args
];
}
}
}
},
"while"
:
_do_while
,
"do"
:
_do_while
},
function
()
{
},
function
()
{
return
walk
(
ast_add_scope
(
ast
));
return
walk
(
ast_add_scope
(
ast
));
});
});
...
@@ -1046,6 +1029,7 @@ function ast_squeeze(ast, options) {
...
@@ -1046,6 +1029,7 @@ function ast_squeeze(ast, options) {
var
DOT_CALL_NO_PARENS
=
jsp
.
array_to_hash
([
var
DOT_CALL_NO_PARENS
=
jsp
.
array_to_hash
([
"name"
,
"name"
,
"array"
,
"array"
,
"object"
,
"string"
,
"string"
,
"dot"
,
"dot"
,
"sub"
,
"sub"
,
...
@@ -1053,9 +1037,9 @@ var DOT_CALL_NO_PARENS = jsp.array_to_hash([
...
@@ -1053,9 +1037,9 @@ var DOT_CALL_NO_PARENS = jsp.array_to_hash([
"regexp"
"regexp"
]);
]);
function
make_string
(
str
)
{
function
make_string
(
str
,
ascii_only
)
{
var
dq
=
0
,
sq
=
0
;
var
dq
=
0
,
sq
=
0
;
str
=
str
.
replace
(
/
[\\\b\f\n\r\t\x
22
\x
27
]
/g
,
function
(
s
){
str
=
str
.
replace
(
/
[\\\b\f\n\r\t\x
22
\x
27
\u
2028
\u
2029
]
/g
,
function
(
s
){
switch
(
s
)
{
switch
(
s
)
{
case
"
\
\"
: return "
\\\\
";
case
"
\
\"
: return "
\\\\
";
case "
\
b
": return "
\\
b
";
case "
\
b
": return "
\\
b
";
...
@@ -1063,34 +1047,56 @@ function make_string(str) {
...
@@ -1063,34 +1047,56 @@ function make_string(str) {
case "
\
n
": return "
\\
n
";
case "
\
n
": return "
\\
n
";
case "
\
r
": return "
\\
r
";
case "
\
r
": return "
\\
r
";
case "
\
t
": return "
\\
t
";
case "
\
t
": return "
\\
t
";
case "
\
u2028
": return "
\\
u2028
";
case "
\
u2029
": return "
\\
u2029
";
case '"
': ++dq; return '
"';
case '"
': ++dq; return '
"';
case "
'": ++sq; return "'
";
case "
'": ++sq; return "'
";
}
}
return s;
return s;
});
});
if (dq > sq) {
if (ascii_only) str = to_ascii(str);
return "
'" + str.replace(/
\
x27/g, "
\
\'
") + "'
";
if (dq > sq) return "
'" + str.replace(/
\
x27/g, "
\
\'
") + "'
";
} else {
else return '"
' + str.replace(/
\
x22/g, '
\\
"') + '"
';
return '"
' + str.replace(/
\
x22/g, '
\\
"') + '"
';
}
};
};
function gen_code(ast, beautify) {
function to_ascii(str) {
if (beautify) beautify = defaults(beautify, {
return str.replace(/[
\
u0080-
\
uffff]/g, function(ch) {
var code = ch.charCodeAt(0).toString(16);
while (code.length < 4) code = "0" + code;
return "
\\
u" + code;
});
};
function gen_code(ast, options) {
options = defaults(options, {
indent_start : 0,
indent_start : 0,
indent_level : 4,
indent_level : 4,
quote_keys : false,
quote_keys : false,
space_colon : false
space_colon : false,
beautify : false,
ascii_only : false
});
});
var beautify = !!options.beautify;
var indentation = 0,
var indentation = 0,
newline = beautify ? "
\
n" : "",
newline = beautify ? "
\
n" : "",
space = beautify ? " " : "";
space = beautify ? " " : "";
function encode_string(str) {
return make_string(str, options.ascii_only);
};
function make_name(name) {
name = name.toString();
if (options.ascii_only)
name = to_ascii(name);
return name;
};
function indent(line) {
function indent(line) {
if (line == null)
if (line == null)
line = "";
line = "";
if (beautify)
if (beautify)
line = repeat_string(" ",
beautify.indent_start + indentation * beautify
.indent_level) + line;
line = repeat_string(" ",
options.indent_start + indentation * options
.indent_level) + line;
return line;
return line;
};
};
...
@@ -1144,7 +1150,7 @@ function gen_code(ast, beautify) {
...
@@ -1144,7 +1150,7 @@ function gen_code(ast, beautify) {
};
};
function needs_parens(expr) {
function needs_parens(expr) {
if (expr[0] == "function") {
if (expr[0] == "function"
|| expr[0] == "object"
) {
// dot/call on a literal function requires the
// dot/call on a literal function requires the
// function literal itself to be parenthesized
// function literal itself to be parenthesized
// only if it'
s
the
first
"thing"
in
a
// only if it'
s
the
first
"thing"
in
a
...
@@ -1156,9 +1162,8 @@ function gen_code(ast, beautify) {
...
@@ -1156,9 +1162,8 @@ function gen_code(ast, beautify) {
var
a
=
slice
(
$stack
),
self
=
a
.
pop
(),
p
=
a
.
pop
();
var
a
=
slice
(
$stack
),
self
=
a
.
pop
(),
p
=
a
.
pop
();
while
(
p
)
{
while
(
p
)
{
if
(
p
[
0
]
==
"stat"
)
return
true
;
if
(
p
[
0
]
==
"stat"
)
return
true
;
if
((
p
[
0
]
==
"seq"
&&
p
[
1
]
===
self
)
||
if
(((
p
[
0
]
==
"seq"
||
p
[
0
]
==
"call"
||
p
[
0
]
==
"dot"
||
p
[
0
]
==
"sub"
||
p
[
0
]
==
"conditional"
)
&&
p
[
1
]
===
self
)
||
(
p
[
0
]
==
"call"
&&
p
[
1
]
===
self
)
||
((
p
[
0
]
==
"binary"
||
p
[
0
]
==
"assign"
||
p
[
0
]
==
"unary-postfix"
)
&&
p
[
2
]
===
self
))
{
(
p
[
0
]
==
"binary"
&&
p
[
2
]
===
self
))
{
self
=
p
;
self
=
p
;
p
=
a
.
pop
();
p
=
a
.
pop
();
}
else
{
}
else
{
...
@@ -1185,7 +1190,7 @@ function gen_code(ast, beautify) {
...
@@ -1185,7 +1190,7 @@ function gen_code(ast, beautify) {
};
};
var
generators
=
{
var
generators
=
{
"string"
:
mak
e_string
,
"string"
:
encod
e_string
,
"num"
:
make_num
,
"num"
:
make_num
,
"name"
:
make_name
,
"name"
:
make_name
,
"toplevel"
:
function
(
statements
)
{
"toplevel"
:
function
(
statements
)
{
...
@@ -1253,9 +1258,10 @@ function gen_code(ast, beautify) {
...
@@ -1253,9 +1258,10 @@ function gen_code(ast, beautify) {
},
},
"dot"
:
function
(
expr
)
{
"dot"
:
function
(
expr
)
{
var
out
=
make
(
expr
),
i
=
1
;
var
out
=
make
(
expr
),
i
=
1
;
if
(
expr
[
0
]
==
"num"
)
if
(
expr
[
0
]
==
"num"
)
{
if
(
!
/
\.
/
.
test
(
expr
[
1
]))
out
+=
"."
;
out
+=
"."
;
else
if
(
needs_parens
(
expr
))
}
else
if
(
needs_parens
(
expr
))
out
=
"("
+
out
+
")"
;
out
=
"("
+
out
+
")"
;
while
(
i
<
arguments
.
length
)
while
(
i
<
arguments
.
length
)
out
+=
"."
+
make_name
(
arguments
[
i
++
]);
out
+=
"."
+
make_name
(
arguments
[
i
++
]);
...
@@ -1288,12 +1294,11 @@ function gen_code(ast, beautify) {
...
@@ -1288,12 +1294,11 @@ function gen_code(ast, beautify) {
out
.
push
(
"("
+
args
+
")"
,
make
(
block
));
out
.
push
(
"("
+
args
+
")"
,
make
(
block
));
return
add_spaces
(
out
);
return
add_spaces
(
out
);
},
},
"for-in"
:
function
(
has_var
,
key
,
hash
,
block
)
{
"for-in"
:
function
(
vvar
,
key
,
hash
,
block
)
{
var
out
=
add_spaces
([
"for"
,
"("
]);
return
add_spaces
([
"for"
,
"("
+
if
(
has_var
)
(
vvar
?
make
(
vvar
).
replace
(
/;+$/
,
""
)
:
make
(
key
)),
out
+=
"var "
;
"in"
,
out
+=
add_spaces
([
make_name
(
key
)
+
" in "
+
make
(
hash
)
+
")"
,
make
(
block
)
]);
make
(
hash
)
+
")"
,
make
(
block
)
]);
return
out
;
},
},
"while"
:
function
(
condition
,
block
)
{
"while"
:
function
(
condition
,
block
)
{
return
add_spaces
([
"while"
,
"("
+
make
(
condition
)
+
")"
,
make
(
block
)
]);
return
add_spaces
([
"while"
,
"("
+
make
(
condition
)
+
")"
,
make
(
block
)
]);
...
@@ -1316,7 +1321,8 @@ function gen_code(ast, beautify) {
...
@@ -1316,7 +1321,8 @@ function gen_code(ast, beautify) {
left
=
"("
+
left
+
")"
;
left
=
"("
+
left
+
")"
;
}
}
if
(
member
(
rvalue
[
0
],
[
"assign"
,
"conditional"
,
"seq"
])
||
if
(
member
(
rvalue
[
0
],
[
"assign"
,
"conditional"
,
"seq"
])
||
rvalue
[
0
]
==
"binary"
&&
PRECEDENCE
[
operator
]
>=
PRECEDENCE
[
rvalue
[
1
]])
{
rvalue
[
0
]
==
"binary"
&&
PRECEDENCE
[
operator
]
>=
PRECEDENCE
[
rvalue
[
1
]]
&&
!
(
rvalue
[
1
]
==
operator
&&
member
(
operator
,
[
"&&"
,
"||"
,
"*"
])))
{
right
=
"("
+
right
+
")"
;
right
=
"("
+
right
+
")"
;
}
}
return
add_spaces
([
left
,
operator
,
right
]);
return
add_spaces
([
left
,
operator
,
right
]);
...
@@ -1350,14 +1356,15 @@ function gen_code(ast, beautify) {
...
@@ -1350,14 +1356,15 @@ function gen_code(ast, beautify) {
return
indent
(
make_function
(
p
[
0
],
p
[
1
][
2
],
p
[
1
][
3
],
p
[
2
]));
return
indent
(
make_function
(
p
[
0
],
p
[
1
][
2
],
p
[
1
][
3
],
p
[
2
]));
}
}
var
key
=
p
[
0
],
val
=
make
(
p
[
1
]);
var
key
=
p
[
0
],
val
=
make
(
p
[
1
]);
if
(
beautify
&&
beautify
.
quote_keys
)
{
if
(
options
.
quote_keys
)
{
key
=
make_string
(
key
);
key
=
encode_string
(
key
);
}
else
if
(
typeof
key
==
"number"
||
!
beautify
&&
+
key
+
""
==
key
)
{
}
else
if
((
typeof
key
==
"number"
||
!
beautify
&&
+
key
+
""
==
key
)
&&
parseFloat
(
key
)
>=
0
)
{
key
=
make_num
(
+
key
);
key
=
make_num
(
+
key
);
}
else
if
(
!
is_identifier
(
key
))
{
}
else
if
(
!
is_identifier
(
key
))
{
key
=
mak
e_string
(
key
);
key
=
encod
e_string
(
key
);
}
}
return
indent
(
add_spaces
(
beautify
&&
beautify
.
space_colon
return
indent
(
add_spaces
(
beautify
&&
options
.
space_colon
?
[
key
,
":"
,
val
]
?
[
key
,
":"
,
val
]
:
[
key
+
":"
,
val
]));
:
[
key
+
":"
,
val
]));
}).
join
(
","
+
newline
);
}).
join
(
","
+
newline
);
...
@@ -1369,6 +1376,7 @@ function gen_code(ast, beautify) {
...
@@ -1369,6 +1376,7 @@ function gen_code(ast, beautify) {
"array"
:
function
(
elements
)
{
"array"
:
function
(
elements
)
{
if
(
elements
.
length
==
0
)
return
"[]"
;
if
(
elements
.
length
==
0
)
return
"[]"
;
return
add_spaces
([
"["
,
add_commas
(
MAP
(
elements
,
function
(
el
){
return
add_spaces
([
"["
,
add_commas
(
MAP
(
elements
,
function
(
el
){
if
(
!
beautify
&&
el
[
0
]
==
"atom"
&&
el
[
1
]
==
"undefined"
)
return
""
;
return
parenthesize
(
el
,
"seq"
);
return
parenthesize
(
el
,
"seq"
);
})),
"]"
]);
})),
"]"
]);
},
},
...
@@ -1386,12 +1394,6 @@ function gen_code(ast, beautify) {
...
@@ -1386,12 +1394,6 @@ function gen_code(ast, beautify) {
},
},
"atom"
:
function
(
name
)
{
"atom"
:
function
(
name
)
{
return
make_name
(
name
);
return
make_name
(
name
);
},
"comment1"
:
function
(
text
)
{
return
"//"
+
text
+
"
\n
"
;
},
"comment2"
:
function
(
text
)
{
return
"/*"
+
text
+
"*/"
;
}
}
};
};
...
@@ -1435,17 +1437,21 @@ function gen_code(ast, beautify) {
...
@@ -1435,17 +1437,21 @@ function gen_code(ast, beautify) {
return
add_spaces
([
out
,
make_block
(
body
)
]);
return
add_spaces
([
out
,
make_block
(
body
)
]);
};
};
function
make_name
(
name
)
{
return
name
.
toString
();
};
function
make_block_statements
(
statements
)
{
function
make_block_statements
(
statements
)
{
for
(
var
a
=
[],
last
=
statements
.
length
-
1
,
i
=
0
;
i
<=
last
;
++
i
)
{
for
(
var
a
=
[],
last
=
statements
.
length
-
1
,
i
=
0
;
i
<=
last
;
++
i
)
{
var
stat
=
statements
[
i
];
var
stat
=
statements
[
i
];
var
code
=
make
(
stat
);
var
code
=
make
(
stat
);
if
(
code
!=
";"
)
{
if
(
code
!=
";"
)
{
if
(
!
beautify
&&
i
==
last
)
if
(
!
beautify
&&
i
==
last
)
{
if
((
stat
[
0
]
==
"while"
&&
empty
(
stat
[
2
]))
||
(
member
(
stat
[
0
],
[
"for"
,
"for-in"
]
)
&&
empty
(
stat
[
4
]))
||
(
stat
[
0
]
==
"if"
&&
empty
(
stat
[
2
])
&&
!
stat
[
3
])
||
(
stat
[
0
]
==
"if"
&&
stat
[
3
]
&&
empty
(
stat
[
3
])))
{
code
=
code
.
replace
(
/;*
\s
*$/
,
";"
);
}
else
{
code
=
code
.
replace
(
/;+
\s
*$/
,
""
);
code
=
code
.
replace
(
/;+
\s
*$/
,
""
);
}
}
a
.
push
(
code
);
a
.
push
(
code
);
}
}
}
}
...
@@ -1480,7 +1486,7 @@ function gen_code(ast, beautify) {
...
@@ -1480,7 +1486,7 @@ function gen_code(ast, beautify) {
function
make_1vardef
(
def
)
{
function
make_1vardef
(
def
)
{
var
name
=
def
[
0
],
val
=
def
[
1
];
var
name
=
def
[
0
],
val
=
def
[
1
];
if
(
val
!=
null
)
if
(
val
!=
null
)
name
=
add_spaces
([
name
,
"="
,
make
(
val
)
]);
name
=
add_spaces
([
make_name
(
name
),
"="
,
parenthesize
(
val
,
"seq"
)
]);
return
name
;
return
name
;
};
};
...
@@ -1500,6 +1506,49 @@ function gen_code(ast, beautify) {
...
@@ -1500,6 +1506,49 @@ function gen_code(ast, beautify) {
return
make
(
ast
);
return
make
(
ast
);
};
};
function
split_lines
(
code
,
max_line_length
)
{
var
splits
=
[
0
];
jsp
.
parse
(
function
(){
var
next_token
=
jsp
.
tokenizer
(
code
);
var
last_split
=
0
;
var
prev_token
;
function
current_length
(
tok
)
{
return
tok
.
pos
-
last_split
;
};
function
split_here
(
tok
)
{
last_split
=
tok
.
pos
;
splits
.
push
(
last_split
);
};
function
custom
(){
var
tok
=
next_token
.
apply
(
this
,
arguments
);
out
:
{
if
(
prev_token
)
{
if
(
prev_token
.
type
==
"keyword"
)
break
out
;
}
if
(
current_length
(
tok
)
>
max_line_length
)
{
switch
(
tok
.
type
)
{
case
"keyword"
:
case
"atom"
:
case
"name"
:
case
"punc"
:
split_here
(
tok
);
break
out
;
}
}
}
prev_token
=
tok
;
return
tok
;
};
custom
.
context
=
function
()
{
return
next_token
.
context
.
apply
(
this
,
arguments
);
};
return
custom
;
}());
return
splits
.
map
(
function
(
pos
,
i
){
return
code
.
substring
(
pos
,
splits
[
i
+
1
]
||
code
.
length
);
}).
join
(
"
\n
"
);
};
/* -----[ Utilities ]----- */
/* -----[ Utilities ]----- */
function
repeat_string
(
str
,
i
)
{
function
repeat_string
(
str
,
i
)
{
...
@@ -1558,5 +1607,10 @@ exports.ast_mangle = ast_mangle;
...
@@ -1558,5 +1607,10 @@ exports.ast_mangle = ast_mangle;
exports
.
ast_squeeze
=
ast_squeeze
;
exports
.
ast_squeeze
=
ast_squeeze
;
exports
.
gen_code
=
gen_code
;
exports
.
gen_code
=
gen_code
;
exports
.
ast_add_scope
=
ast_add_scope
;
exports
.
ast_add_scope
=
ast_add_scope
;
exports
.
ast_squeeze_more
=
require
(
"./squeeze-more"
).
ast_squeeze_more
;
exports
.
set_logger
=
function
(
logger
)
{
warn
=
logger
};
exports
.
set_logger
=
function
(
logger
)
{
warn
=
logger
};
exports
.
make_string
=
make_string
;
exports
.
split_lines
=
split_lines
;
exports
.
MAP
=
MAP
;
// keep this last!
exports
.
ast_squeeze_more
=
require
(
"./squeeze-more"
).
ast_squeeze_more
;
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment