minjs 0.1.3 → 0.1.5
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.
- checksums.yaml +4 -4
- data/lib/minjs/compressor.rb +130 -121
- data/lib/minjs/ctype.rb +2 -0
- data/lib/minjs/ecma262/base.rb +172 -34
- data/lib/minjs/ecma262/exp.rb +644 -388
- data/lib/minjs/ecma262/lit.rb +39 -3
- data/lib/minjs/ecma262/st.rb +388 -157
- data/lib/minjs/exceptions.rb +1 -1
- data/lib/minjs/expression.rb +88 -76
- data/lib/minjs/func.rb +1 -2
- data/lib/minjs/lex.rb +7 -7
- data/lib/minjs/minjs_compressor.rb +8 -4
- data/lib/minjs/program.rb +1 -1
- data/lib/minjs/statement.rb +32 -15
- data/lib/minjs/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82f88a2a64ab93ccafd2abd3e699e8d5fa7682d0
|
4
|
+
data.tar.gz: 3e9aec62b059e22695c0111169b75c5bd3fc1141
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b58b34b47810cec665a86a8d831f7a222a558eb0ed21996de5332caddd13a3e15000544bc9a7867ed0a3341535eb55bebe8af4092e73dc9d0b8f34e143cf2b88
|
7
|
+
data.tar.gz: 93c25a509a9bf2c6864433f4ef955b64887bb35471be4d4fe1b68fdcaf736341e9c04634150adf8136097a2ada5d2f6815298ac1257b62a8192512d716f0754b
|
data/lib/minjs/compressor.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# coding: utf-8
|
2
3
|
require 'minjs/lex'
|
3
4
|
require 'minjs/ecma262'
|
4
5
|
require 'minjs/literal'
|
@@ -7,6 +8,7 @@ require 'minjs/expression'
|
|
7
8
|
require 'minjs/func'
|
8
9
|
require 'minjs/program'
|
9
10
|
require 'minjs/exceptions'
|
11
|
+
require 'logger'
|
10
12
|
|
11
13
|
module Minjs
|
12
14
|
class Compressor
|
@@ -19,14 +21,17 @@ module Minjs
|
|
19
21
|
attr_reader :prog
|
20
22
|
|
21
23
|
def initialize(options = {})
|
22
|
-
@
|
23
|
-
if
|
24
|
-
@
|
24
|
+
@logger = options[:logger]
|
25
|
+
if !@logger
|
26
|
+
@logger = Logger.new(STDERR)
|
27
|
+
@logger.level = (options[:debug_level] || Logger::WARN)
|
28
|
+
@logger.formatter = proc{|severity, datetime, progname, message|
|
29
|
+
"#{message}\n"
|
30
|
+
}
|
25
31
|
end
|
26
32
|
end
|
27
33
|
|
28
34
|
def debug
|
29
|
-
#@global_context.debug
|
30
35
|
puts @prog.to_js()
|
31
36
|
end
|
32
37
|
|
@@ -35,29 +40,50 @@ module Minjs
|
|
35
40
|
end
|
36
41
|
|
37
42
|
def compress(data, options = {})
|
43
|
+
@logger.info '* parse'
|
38
44
|
parse(data)
|
39
45
|
|
46
|
+
@logger.info '* reorder_function_decl'
|
40
47
|
reorder_function_decl
|
48
|
+
|
49
|
+
@logger.info '* simple_replacement'
|
41
50
|
simple_replacement
|
51
|
+
|
52
|
+
@logger.info '* reorder_var'
|
42
53
|
reorder_var
|
54
|
+
|
55
|
+
@logger.info '* assignment_after_var'
|
43
56
|
assignment_after_var
|
57
|
+
|
58
|
+
@logger.info '* grouping_statement'
|
44
59
|
grouping_statement
|
45
|
-
|
60
|
+
|
61
|
+
@logger.info '* block_to_statement'
|
62
|
+
block_to_statement
|
63
|
+
|
64
|
+
@logger.info '* if_to_cond'
|
46
65
|
if_to_cond
|
66
|
+
|
67
|
+
@logger.info '* compress_var'
|
47
68
|
compress_var
|
69
|
+
|
70
|
+
@logger.info '* reduce_exp'
|
48
71
|
reduce_exp
|
72
|
+
|
73
|
+
@logger.info '* remove_paren'
|
49
74
|
remove_paren
|
50
|
-
|
51
|
-
|
75
|
+
|
76
|
+
@logger.info '* return_to_exp'
|
77
|
+
return_to_exp
|
78
|
+
|
52
79
|
@heading_comments.reverse.each do |c|
|
53
|
-
@prog.source_elements.unshift(c)
|
80
|
+
@prog.source_elements.source_elements.unshift(c)
|
54
81
|
end
|
55
|
-
|
56
82
|
to_js(options)
|
57
83
|
end
|
58
84
|
|
59
85
|
def parse(data)
|
60
|
-
@lex = Minjs::Lex.new(data)
|
86
|
+
@lex = Minjs::Lex.new(data, :logger => @logger)
|
61
87
|
@global_context = ECMA262::Context.new
|
62
88
|
|
63
89
|
@heading_comments = []
|
@@ -71,9 +97,9 @@ module Minjs
|
|
71
97
|
@prog
|
72
98
|
end
|
73
99
|
|
74
|
-
def traverse(&block)
|
75
|
-
@prog.traverse(nil, &block)
|
76
|
-
end
|
100
|
+
# def traverse(&block)
|
101
|
+
# @prog.traverse(nil, &block)
|
102
|
+
# end
|
77
103
|
|
78
104
|
def next_sym(s)
|
79
105
|
def c2i(c)
|
@@ -131,34 +157,37 @@ module Minjs
|
|
131
157
|
|
132
158
|
end
|
133
159
|
|
134
|
-
def grouping_statement
|
135
|
-
|
136
|
-
if st.kind_of? ECMA262::
|
137
|
-
st.grouping
|
138
|
-
elsif st.kind_of? ECMA262::StList
|
160
|
+
def grouping_statement(node = @prog)
|
161
|
+
node.traverse(nil) {|st, parent|
|
162
|
+
if st.kind_of? ECMA262::StatementList
|
139
163
|
st.grouping
|
140
164
|
end
|
141
165
|
}
|
166
|
+
remove_paren
|
167
|
+
self
|
142
168
|
end
|
143
169
|
|
144
|
-
def reorder_function_decl
|
145
|
-
|
146
|
-
if st.kind_of? ECMA262::StFunc and parent.kind_of? ECMA262::
|
170
|
+
def reorder_function_decl(node = @prog)
|
171
|
+
node.traverse(nil) {|st, parent|
|
172
|
+
if st.kind_of? ECMA262::StFunc and parent.kind_of? ECMA262::StatementList and st.decl?
|
147
173
|
if parent.index(st)
|
148
174
|
parent.remove(st)
|
149
175
|
parent.source_elements.unshift(st)
|
150
176
|
end
|
151
177
|
end
|
152
178
|
}
|
179
|
+
self
|
153
180
|
end
|
154
181
|
|
155
|
-
def reorder_var
|
156
|
-
|
157
|
-
self.traverse {|st, parent|
|
182
|
+
def reorder_var(node = @prog)
|
183
|
+
node.traverse(nil) {|st, parent|
|
158
184
|
if st.kind_of? ECMA262::Prog
|
159
185
|
vars = nil
|
160
186
|
context = nil
|
161
187
|
st.instance_eval{
|
188
|
+
#
|
189
|
+
# collect all of var variable in this function
|
190
|
+
#
|
162
191
|
vars = @context.var_env.record.binding.find_all {|k, v|
|
163
192
|
v and v[:_parameter_list].nil? and !v[:value].kind_of?(ECMA262::StFunc)
|
164
193
|
}.collect{|x|
|
@@ -173,12 +202,10 @@ module Minjs
|
|
173
202
|
@vars.each do |vl|
|
174
203
|
if vl[1]
|
175
204
|
blk.push(ECMA262::StExp.new(ECMA262::ExpAssign.new(vl[0], vl[1])))
|
176
|
-
#parent2.replace(st2, ECMA262::StExp.new(ECMA262::ExpAssign.new(vl[0], vl[1])))
|
177
205
|
else
|
178
|
-
#parent2.replace(st2, ECMA262::StEmpty.new())
|
179
206
|
end
|
180
207
|
end
|
181
|
-
parent2.replace(st2, ECMA262::StBlock.new(ECMA262::
|
208
|
+
parent2.replace(st2, ECMA262::StBlock.new(ECMA262::StatementList.new(blk)))
|
182
209
|
}
|
183
210
|
elsif st2.kind_of? ECMA262::StForVar and st2.context == @context
|
184
211
|
parent2.replace(st2, st2.to_st_for)
|
@@ -187,7 +214,7 @@ module Minjs
|
|
187
214
|
end
|
188
215
|
}
|
189
216
|
if vars.length > 0
|
190
|
-
@source_elements.unshift ECMA262::StVar.new(@context, vars)
|
217
|
+
@source_elements.source_elements.unshift ECMA262::StVar.new(@context, vars)
|
191
218
|
end
|
192
219
|
}
|
193
220
|
end
|
@@ -195,38 +222,20 @@ module Minjs
|
|
195
222
|
remove_block_in_block
|
196
223
|
end
|
197
224
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
#
|
203
|
-
# ECMA262 say:
|
204
|
-
# expression statement cannot start with "function"
|
205
|
-
#
|
206
|
-
if parent.priority(st) > st.val.priority(nil)
|
207
|
-
if st.val.to_js.match(/^function/)
|
208
|
-
;
|
209
|
-
elsif st.val.to_js.match(/^{/)
|
210
|
-
;
|
211
|
-
else
|
212
|
-
parent.replace(st, st.val)
|
213
|
-
end
|
214
|
-
end
|
225
|
+
def remove_paren(node = @prog)
|
226
|
+
node.traverse(nil) {|st, parent|
|
227
|
+
if st.respond_to? :remove_paren
|
228
|
+
st.remove_paren
|
215
229
|
end
|
216
230
|
}
|
217
231
|
self
|
218
232
|
end
|
219
233
|
|
220
|
-
def remove_block_in_block
|
234
|
+
def remove_block_in_block(node = @prog)
|
221
235
|
while true
|
222
236
|
_retry = false
|
223
|
-
|
224
|
-
if parent.kind_of? ECMA262::
|
225
|
-
idx = parent.index(st)
|
226
|
-
parent.source_elements[idx..idx] = st.statement_list.statement_list
|
227
|
-
_retry = true
|
228
|
-
break
|
229
|
-
elsif parent.kind_of? ECMA262::StList and st.kind_of? ECMA262::StBlock
|
237
|
+
node.traverse(nil) {|st, parent|
|
238
|
+
if parent.kind_of? ECMA262::StatementList and st.kind_of? ECMA262::StBlock
|
230
239
|
idx = parent.index(st)
|
231
240
|
parent.statement_list[idx..idx] = st.statement_list.statement_list
|
232
241
|
_retry = true
|
@@ -239,66 +248,69 @@ module Minjs
|
|
239
248
|
end
|
240
249
|
end
|
241
250
|
|
242
|
-
def
|
243
|
-
|
244
|
-
if st.kind_of? ECMA262::StBlock and
|
245
|
-
if
|
246
|
-
|
247
|
-
t = st.to_exp({})
|
248
|
-
parent.replace(st, ECMA262::StExp.new(t))
|
251
|
+
def block_to_statement(node = @prog)
|
252
|
+
node.traverse(nil) {|st, parent|
|
253
|
+
if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry)
|
254
|
+
if st.to_statement?
|
255
|
+
parent.replace(st, st.to_statement)
|
249
256
|
end
|
250
257
|
end
|
251
258
|
}
|
259
|
+
self
|
252
260
|
end
|
253
261
|
|
254
|
-
def
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
262
|
+
def if_to_cond(node = nil)
|
263
|
+
node = @prog if node.nil?
|
264
|
+
node.traverse(nil) {|st, parent|
|
265
|
+
#
|
266
|
+
#feature
|
267
|
+
#
|
268
|
+
# if(a)return a;
|
269
|
+
# return b;
|
270
|
+
# => if(a)return a;else return b;
|
271
|
+
#
|
272
|
+
|
273
|
+
if st.kind_of? ECMA262::StIf and parent.kind_of? ECMA262::StatementList
|
274
|
+
i = parent.index(st)
|
275
|
+
if parent[i+1].nil? and !parent.kind_of?(ECMA262::SourceElements)
|
276
|
+
next
|
277
|
+
end
|
278
|
+
if parent[i+1].nil? or parent[i+1].to_return?
|
279
|
+
s = st
|
280
|
+
while s.kind_of? ECMA262::StIf and s.else_st and s.then_st.to_return?
|
281
|
+
s = s.else_st
|
282
|
+
end
|
283
|
+
if s and s.kind_of? ECMA262::StIf and s.then_st.to_return?
|
284
|
+
if parent[i+1]
|
285
|
+
s.replace(s.else_st, parent[i+1])
|
286
|
+
parent.replace(parent[i+1], ECMA262::StEmpty.new)
|
287
|
+
else
|
288
|
+
s.replace(s.else_st, ECMA262::StReturn.new(ECMA262::ExpVoid.new(ECMA262::ECMA262Numeric.new(0))))
|
289
|
+
end
|
290
|
+
end
|
260
291
|
end
|
261
292
|
end
|
262
293
|
}
|
263
|
-
|
264
|
-
|
265
|
-
def if_to_cond
|
266
|
-
self.traverse {|st, parent|
|
294
|
+
node.traverse(nil) {|st, parent|
|
267
295
|
if st.kind_of? ECMA262::StIf and st.to_exp?
|
268
296
|
if t = ECMA262::StExp.new(st.to_exp({}))
|
269
297
|
parent.replace(st, t)
|
270
298
|
end
|
271
|
-
# feature...
|
272
|
-
=begin
|
273
299
|
elsif st.kind_of? ECMA262::StIf and st.to_return?
|
274
|
-
|
275
|
-
|
276
|
-
# return a;
|
277
|
-
# return b;
|
278
|
-
#
|
279
|
-
# => if(...)return a;else return b;
|
280
|
-
#
|
281
|
-
if parent.kind_of? ECMA262::StList and st.else_st.nil? and (nxt = parent[parent.index(st) + 1]).kind_of? ECMA262::StReturn
|
282
|
-
st.replace(st.else_st, nxt)
|
283
|
-
parent.replace(nxt, ECMA262::StEmpty.new())
|
284
|
-
parent.replace(st, st.to_return)
|
285
|
-
#
|
286
|
-
# if(...)
|
287
|
-
# return a;
|
288
|
-
# else
|
289
|
-
# return b;
|
290
|
-
#
|
291
|
-
else
|
300
|
+
t = st.to_return
|
301
|
+
if t.to_js().length < st.to_js().length
|
292
302
|
parent.replace(st, st.to_return)
|
293
303
|
end
|
294
|
-
=end
|
295
304
|
end
|
296
305
|
}
|
306
|
+
remove_paren
|
297
307
|
end
|
298
308
|
|
299
|
-
def compress_var
|
309
|
+
def compress_var(node = @prog)
|
310
|
+
#
|
300
311
|
#traverse all statemtns and expression
|
301
|
-
|
312
|
+
#
|
313
|
+
node.traverse(nil) {|st, parent|
|
302
314
|
if st.kind_of? ECMA262::StFunc and st.context.var_env.outer
|
303
315
|
var_sym = :a
|
304
316
|
#
|
@@ -307,7 +319,8 @@ module Minjs
|
|
307
319
|
vars = {}
|
308
320
|
st.traverse(parent) {|st2|
|
309
321
|
if st2.kind_of? ECMA262::IdentifierName
|
310
|
-
vars[st2.val.to_sym]
|
322
|
+
vars[st2.val.to_sym] ||= 0
|
323
|
+
vars[st2.val.to_sym] += 1
|
311
324
|
end
|
312
325
|
}
|
313
326
|
#
|
@@ -315,12 +328,12 @@ module Minjs
|
|
315
328
|
#
|
316
329
|
var_vars = {}
|
317
330
|
st.context.var_env.record.binding.each do|k, v|
|
318
|
-
var_vars[k] =
|
331
|
+
var_vars[k] = vars[k]
|
319
332
|
end
|
320
333
|
st.traverse(parent) {|st2|
|
321
334
|
if st2.kind_of? ECMA262::StFunc
|
322
335
|
st2.context.var_env.record.binding.each do|k, v|
|
323
|
-
var_vars[k] =
|
336
|
+
var_vars[k] = vars[k]
|
324
337
|
end
|
325
338
|
end
|
326
339
|
}
|
@@ -340,9 +353,13 @@ module Minjs
|
|
340
353
|
end
|
341
354
|
end
|
342
355
|
#
|
356
|
+
# sort var_vars
|
357
|
+
#
|
358
|
+
var_vars = var_vars.sort {|(k1,v1), (k2,v2)| v2 <=> v1}
|
359
|
+
#
|
343
360
|
# check var_vars
|
344
361
|
#
|
345
|
-
var_vars.each {|name,
|
362
|
+
var_vars.each {|name, count|
|
346
363
|
if name.nil?
|
347
364
|
next
|
348
365
|
end
|
@@ -357,7 +374,9 @@ module Minjs
|
|
357
374
|
if st2.kind_of? ECMA262::IdentifierName and st2.context and st2.context.var_env == st.context.var_env.outer
|
358
375
|
;
|
359
376
|
elsif st2.kind_of? ECMA262::IdentifierName and st2.val == name
|
360
|
-
st2.
|
377
|
+
st2.instance_eval{
|
378
|
+
@val = var_sym
|
379
|
+
}
|
361
380
|
elsif st2.kind_of? ECMA262::StFunc
|
362
381
|
st2.context.var_env.record.binding[var_sym] = st2.context.var_env.record.binding[name]
|
363
382
|
st2.context.var_env.record.binding.delete(name)
|
@@ -368,18 +387,19 @@ module Minjs
|
|
368
387
|
}
|
369
388
|
end
|
370
389
|
}
|
390
|
+
self
|
371
391
|
end
|
372
392
|
|
373
|
-
def reduce_exp
|
374
|
-
|
393
|
+
def reduce_exp(node = @prog)
|
394
|
+
node.traverse(nil) {|st, parent|
|
375
395
|
if st.kind_of? ECMA262::Exp
|
376
396
|
st.reduce(parent)
|
377
397
|
end
|
378
398
|
}
|
379
399
|
end
|
380
400
|
|
381
|
-
def simple_replacement
|
382
|
-
|
401
|
+
def simple_replacement(node = @prog)
|
402
|
+
node.traverse(nil) {|st, parent|
|
383
403
|
#true => !0
|
384
404
|
#false => !1
|
385
405
|
if st.kind_of? ECMA262::Boolean
|
@@ -403,23 +423,10 @@ module Minjs
|
|
403
423
|
}
|
404
424
|
end
|
405
425
|
|
406
|
-
def return_to_exp
|
407
|
-
|
426
|
+
def return_to_exp(node = @prog)
|
427
|
+
node.traverse(nil) {|st, parent|
|
408
428
|
if st.kind_of? ECMA262::StReturn
|
409
|
-
if parent.kind_of? ECMA262::
|
410
|
-
parent.remove_empty_statement
|
411
|
-
#
|
412
|
-
# a=1;return b; => return a=1,b;
|
413
|
-
#
|
414
|
-
# check statement:
|
415
|
-
# last one is return and its previous is expression or not
|
416
|
-
if parent.source_elements[-1] == st and (prev=parent.source_elements[-2]).class == ECMA262::StExp
|
417
|
-
if st.exp
|
418
|
-
st.replace(st.exp, ECMA262::ExpComma.new(prev.exp, st.exp))
|
419
|
-
parent.replace(prev, ECMA262::StEmpty.new())
|
420
|
-
end
|
421
|
-
end
|
422
|
-
elsif parent.kind_of? ECMA262::StList
|
429
|
+
if parent.kind_of? ECMA262::StatementList
|
423
430
|
parent.remove_empty_statement
|
424
431
|
if parent.statement_list[-1] == st and (prev=parent.statement_list[-2]).class == ECMA262::StExp
|
425
432
|
if st.exp
|
@@ -427,19 +434,21 @@ module Minjs
|
|
427
434
|
parent.replace(prev, ECMA262::StEmpty.new())
|
428
435
|
end
|
429
436
|
end
|
437
|
+
parent.remove_empty_statement
|
430
438
|
end
|
431
439
|
end
|
432
440
|
}
|
433
441
|
block_to_statement
|
434
442
|
if_to_cond
|
443
|
+
self
|
435
444
|
end
|
436
445
|
#
|
437
446
|
# var a; a=1
|
438
447
|
# => var a=1
|
439
448
|
#
|
440
|
-
def assignment_after_var
|
441
|
-
|
442
|
-
if st.kind_of? ECMA262::StExp and parent.kind_of? ECMA262::
|
449
|
+
def assignment_after_var(node = @prog)
|
450
|
+
node.traverse(nil) {|st, parent|
|
451
|
+
if st.kind_of? ECMA262::StExp and parent.kind_of? ECMA262::SourceElements
|
443
452
|
if st.exp.kind_of? ECMA262::ExpAssign
|
444
453
|
idx = parent.index(st)
|
445
454
|
while idx > 0
|
data/lib/minjs/ctype.rb
CHANGED
@@ -14,6 +14,7 @@ module Minjs
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def identifier_start?(c)
|
17
|
+
return false if c.nil?
|
17
18
|
c == 0x24 || c == 0x5f ||
|
18
19
|
(c >= 0x41 && c <= 0x5a) ||
|
19
20
|
(c >= 0x61 && c <= 0x7a) ||
|
@@ -563,6 +564,7 @@ module Minjs
|
|
563
564
|
end
|
564
565
|
|
565
566
|
def identifier_part?(c)
|
567
|
+
return false if c.nil?
|
566
568
|
identifier_start?(c) ||
|
567
569
|
(c >= 0x30 && c <= 0x39) ||
|
568
570
|
(c >= 0x5f && c <= 0x5f) ||
|