43
43
44
44
"use strict" ;
45
45
46
- function find_builtins ( reserved ) {
46
+ var builtins = function ( ) {
47
+ var names = [ ] ;
47
48
// NaN will be included due to Number.NaN
48
49
[
49
50
"null" ,
@@ -67,19 +68,21 @@ function find_builtins(reserved) {
67
68
] . forEach ( function ( ctor ) {
68
69
Object . getOwnPropertyNames ( ctor ) . map ( add ) ;
69
70
if ( ctor . prototype ) {
71
+ Object . getOwnPropertyNames ( new ctor ( ) ) . map ( add ) ;
70
72
Object . getOwnPropertyNames ( ctor . prototype ) . map ( add ) ;
71
73
}
72
74
} ) ;
75
+ return makePredicate ( names ) ;
73
76
74
77
function add ( name ) {
75
- push_uniq ( reserved , name ) ;
78
+ names . push ( name ) ;
76
79
}
77
- }
80
+ } ( ) ;
78
81
79
82
function reserve_quoted_keys ( ast , reserved ) {
80
83
ast . walk ( new TreeWalker ( function ( node ) {
81
- if ( node instanceof AST_ObjectKeyVal && node . quote ) {
82
- add ( node . key ) ;
84
+ if ( node instanceof AST_ObjectKeyVal ) {
85
+ if ( node . quote ) add ( node . key ) ;
83
86
} else if ( node instanceof AST_Sub ) {
84
87
addStrings ( node . property , add ) ;
85
88
}
@@ -91,17 +94,14 @@ function reserve_quoted_keys(ast, reserved) {
91
94
}
92
95
93
96
function addStrings ( node , add ) {
94
- node . walk ( new TreeWalker ( function ( node ) {
95
- if ( node instanceof AST_Sequence ) {
96
- addStrings ( node . tail_node ( ) , add ) ;
97
- } else if ( node instanceof AST_String ) {
98
- add ( node . value ) ;
99
- } else if ( node instanceof AST_Conditional ) {
100
- addStrings ( node . consequent , add ) ;
101
- addStrings ( node . alternative , add ) ;
102
- }
103
- return true ;
104
- } ) ) ;
97
+ if ( node instanceof AST_Conditional ) {
98
+ addStrings ( node . consequent , add ) ;
99
+ addStrings ( node . alternative , add ) ;
100
+ } else if ( node instanceof AST_Sequence ) {
101
+ addStrings ( node . tail_node ( ) , add ) ;
102
+ } else if ( node instanceof AST_String ) {
103
+ add ( node . value ) ;
104
+ }
105
105
}
106
106
107
107
function mangle_properties ( ast , options ) {
@@ -115,16 +115,17 @@ function mangle_properties(ast, options) {
115
115
reserved : null ,
116
116
} , true ) ;
117
117
118
- var reserved = options . reserved ;
119
- if ( ! Array . isArray ( reserved ) ) reserved = [ ] ;
120
- if ( ! options . builtins ) find_builtins ( reserved ) ;
118
+ var reserved = Object . create ( options . builtins ? null : builtins ) ;
119
+ if ( Array . isArray ( options . reserved ) ) options . reserved . forEach ( function ( name ) {
120
+ reserved [ name ] = true ;
121
+ } ) ;
121
122
122
123
var cname = - 1 ;
123
124
var cache ;
124
125
if ( options . cache ) {
125
126
cache = options . cache . props ;
126
- cache . each ( function ( mangled_name ) {
127
- push_uniq ( reserved , mangled_name ) ;
127
+ cache . each ( function ( name ) {
128
+ reserved [ name ] = true ;
128
129
} ) ;
129
130
} else {
130
131
cache = new Dictionary ( ) ;
@@ -139,62 +140,93 @@ function mangle_properties(ast, options) {
139
140
var debug_suffix ;
140
141
if ( debug ) debug_suffix = options . debug === true ? "" : options . debug ;
141
142
142
- var names_to_mangle = [ ] ;
143
- var unmangleable = [ ] ;
143
+ var names_to_mangle = Object . create ( null ) ;
144
+ var unmangleable = Object . create ( reserved ) ;
144
145
145
146
// step 1: find candidates to mangle
146
147
ast . walk ( new TreeWalker ( function ( node ) {
147
- if ( node instanceof AST_ObjectKeyVal ) {
148
+ if ( node instanceof AST_Binary ) {
149
+ if ( node . operator == "in" ) addStrings ( node . left , add ) ;
150
+ } else if ( node . TYPE == "Call" ) {
151
+ var exp = node . expression ;
152
+ if ( exp instanceof AST_Dot ) switch ( exp . property ) {
153
+ case "defineProperty" :
154
+ case "getOwnPropertyDescriptor" :
155
+ if ( node . args . length < 2 ) break ;
156
+ exp = exp . expression ;
157
+ if ( ! ( exp instanceof AST_SymbolRef ) ) break ;
158
+ if ( exp . name != "Object" ) break ;
159
+ if ( ! exp . definition ( ) . undeclared ) break ;
160
+ addStrings ( node . args [ 1 ] , add ) ;
161
+ break ;
162
+ case "hasOwnProperty" :
163
+ if ( node . args . length < 1 ) break ;
164
+ addStrings ( node . args [ 0 ] , add ) ;
165
+ break ;
166
+ }
167
+ } else if ( node instanceof AST_Dot ) {
168
+ add ( node . property ) ;
169
+ } else if ( node instanceof AST_ObjectKeyVal ) {
148
170
add ( node . key ) ;
149
171
} else if ( node instanceof AST_ObjectProperty ) {
150
172
// setter or getter, since KeyVal is handled above
151
173
add ( node . key . name ) ;
152
- } else if ( node instanceof AST_Dot ) {
153
- add ( node . property ) ;
154
174
} else if ( node instanceof AST_Sub ) {
155
175
addStrings ( node . property , add ) ;
156
- } else if ( node instanceof AST_Call
157
- && node . expression . print_to_string ( ) == "Object.defineProperty" ) {
158
- addStrings ( node . args [ 1 ] , add ) ;
159
176
}
160
177
} ) ) ;
161
178
162
- // step 2: transform the tree, renaming properties
163
- return ast . transform ( new TreeTransformer ( function ( node ) {
164
- if ( node instanceof AST_ObjectKeyVal ) {
179
+ // step 2: renaming properties
180
+ ast . walk ( new TreeWalker ( function ( node ) {
181
+ if ( node instanceof AST_Binary ) {
182
+ if ( node . operator == "in" ) mangleStrings ( node . left ) ;
183
+ } else if ( node . TYPE == "Call" ) {
184
+ var exp = node . expression ;
185
+ if ( exp instanceof AST_Dot ) switch ( exp . property ) {
186
+ case "defineProperty" :
187
+ case "getOwnPropertyDescriptor" :
188
+ if ( node . args . length < 2 ) break ;
189
+ exp = exp . expression ;
190
+ if ( ! ( exp instanceof AST_SymbolRef ) ) break ;
191
+ if ( exp . name != "Object" ) break ;
192
+ if ( ! exp . definition ( ) . undeclared ) break ;
193
+ mangleStrings ( node . args [ 1 ] ) ;
194
+ break ;
195
+ case "hasOwnProperty" :
196
+ if ( node . args . length < 1 ) break ;
197
+ mangleStrings ( node . args [ 0 ] ) ;
198
+ break ;
199
+ }
200
+ } else if ( node instanceof AST_Dot ) {
201
+ node . property = mangle ( node . property ) ;
202
+ } else if ( node instanceof AST_ObjectKeyVal ) {
165
203
node . key = mangle ( node . key ) ;
166
204
} else if ( node instanceof AST_ObjectProperty ) {
167
205
// setter or getter
168
206
node . key . name = mangle ( node . key . name ) ;
169
- } else if ( node instanceof AST_Dot ) {
170
- node . property = mangle ( node . property ) ;
171
- } else if ( ! options . keep_quoted && node instanceof AST_Sub ) {
172
- node . property = mangleStrings ( node . property ) ;
173
- } else if ( node instanceof AST_Call
174
- && node . expression . print_to_string ( ) == "Object.defineProperty" ) {
175
- node . args [ 1 ] = mangleStrings ( node . args [ 1 ] ) ;
207
+ } else if ( node instanceof AST_Sub ) {
208
+ if ( ! options . keep_quoted ) mangleStrings ( node . property ) ;
176
209
}
177
210
} ) ) ;
178
211
179
212
// only function declarations after this line
180
213
181
214
function can_mangle ( name ) {
182
- if ( unmangleable . indexOf ( name ) >= 0 ) return false ;
183
- if ( reserved . indexOf ( name ) >= 0 ) return false ;
215
+ if ( unmangleable [ name ] ) return false ;
184
216
if ( options . only_cache ) return cache . has ( name ) ;
185
217
if ( / ^ - ? [ 0 - 9 ] + ( \. [ 0 - 9 ] + ) ? ( e [ + - ] [ 0 - 9 ] + ) ? $ / . test ( name ) ) return false ;
186
218
return true ;
187
219
}
188
220
189
221
function should_mangle ( name ) {
222
+ if ( reserved [ name ] ) return false ;
190
223
if ( regex && ! regex . test ( name ) ) return false ;
191
- if ( reserved . indexOf ( name ) >= 0 ) return false ;
192
- return cache . has ( name ) || names_to_mangle . indexOf ( name ) >= 0 ;
224
+ return cache . has ( name ) || names_to_mangle [ name ] ;
193
225
}
194
226
195
227
function add ( name ) {
196
- if ( can_mangle ( name ) ) push_uniq ( names_to_mangle , name ) ;
197
- if ( ! should_mangle ( name ) ) push_uniq ( unmangleable , name ) ;
228
+ if ( can_mangle ( name ) ) names_to_mangle [ name ] = true ;
229
+ if ( ! should_mangle ( name ) ) unmangleable [ name ] = true ;
198
230
}
199
231
200
232
function mangle ( name ) {
@@ -218,17 +250,13 @@ function mangle_properties(ast, options) {
218
250
}
219
251
220
252
function mangleStrings ( node ) {
221
- return node . transform ( new TreeTransformer ( function ( node ) {
222
- if ( node instanceof AST_Sequence ) {
223
- var last = node . expressions . length - 1 ;
224
- node . expressions [ last ] = mangleStrings ( node . expressions [ last ] ) ;
225
- } else if ( node instanceof AST_String ) {
226
- node . value = mangle ( node . value ) ;
227
- } else if ( node instanceof AST_Conditional ) {
228
- node . consequent = mangleStrings ( node . consequent ) ;
229
- node . alternative = mangleStrings ( node . alternative ) ;
230
- }
231
- return node ;
232
- } ) ) ;
253
+ if ( node instanceof AST_Sequence ) {
254
+ mangleStrings ( node . expressions . tail_node ( ) ) ;
255
+ } else if ( node instanceof AST_String ) {
256
+ node . value = mangle ( node . value ) ;
257
+ } else if ( node instanceof AST_Conditional ) {
258
+ mangleStrings ( node . consequent ) ;
259
+ mangleStrings ( node . alternative ) ;
260
+ }
233
261
}
234
262
}
0 commit comments