minjs 0.1.5 → 0.1.7
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 +255 -25
- data/lib/minjs/ecma262/base.rb +0 -67
- data/lib/minjs/ecma262/env.rb +4 -1
- data/lib/minjs/ecma262/exp.rb +371 -80
- data/lib/minjs/ecma262/lit.rb +58 -2
- data/lib/minjs/ecma262/st.rb +123 -43
- data/lib/minjs/func.rb +6 -0
- data/lib/minjs/literal.rb +2 -2
- data/lib/minjs/minjs_compressor.rb +2 -2
- data/lib/minjs/statement.rb +20 -14
- 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: 6a8187931f76664dfc06d3ff52d9c41f984d0faa
|
4
|
+
data.tar.gz: 6f03506bef8148d713bff2ef74c377d6305876fd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 33a3e964e04dca6ade14ee7ec3b10cc07c3b0fb73c0a99176dd240914987a3f2d786a93e69ef42a0843ac2b4a4f7edf89d796ad5c1f46dd3ac6ecefef3038119
|
7
|
+
data.tar.gz: 17cd44a4d705ac698f535b2ec2cf909f77da132ce33ac995933a7956af264b5dc9eb5d2434c2363d0043e301c681bc4d0670bad871059b24a445ae4dd4a86005
|
data/lib/minjs/compressor.rb
CHANGED
@@ -61,6 +61,9 @@ module Minjs
|
|
61
61
|
@logger.info '* block_to_statement'
|
62
62
|
block_to_statement
|
63
63
|
|
64
|
+
@logger.info '* reduce_if'
|
65
|
+
reduce_if
|
66
|
+
|
64
67
|
@logger.info '* if_to_cond'
|
65
68
|
if_to_cond
|
66
69
|
|
@@ -196,7 +199,7 @@ module Minjs
|
|
196
199
|
]
|
197
200
|
}
|
198
201
|
st.traverse(parent) {|st2, parent2|
|
199
|
-
if st2.kind_of? ECMA262::StVar and st2.context == @context
|
202
|
+
if st2.kind_of? ECMA262::StVar and st2.context.var_env == @context.var_env
|
200
203
|
st2.instance_eval{
|
201
204
|
blk = []
|
202
205
|
@vars.each do |vl|
|
@@ -207,9 +210,9 @@ module Minjs
|
|
207
210
|
end
|
208
211
|
parent2.replace(st2, ECMA262::StBlock.new(ECMA262::StatementList.new(blk)))
|
209
212
|
}
|
210
|
-
elsif st2.kind_of? ECMA262::StForVar and st2.context == @context
|
213
|
+
elsif st2.kind_of? ECMA262::StForVar and st2.context.var_env == @context.var_env
|
211
214
|
parent2.replace(st2, st2.to_st_for)
|
212
|
-
elsif st2.kind_of? ECMA262::StForInVar and st2.context == @context
|
215
|
+
elsif st2.kind_of? ECMA262::StForInVar and st2.context.var_env == @context.var_env
|
213
216
|
parent2.replace(st2, st2.to_st_for_in)
|
214
217
|
end
|
215
218
|
}
|
@@ -220,12 +223,14 @@ module Minjs
|
|
220
223
|
end
|
221
224
|
}
|
222
225
|
remove_block_in_block
|
226
|
+
self
|
223
227
|
end
|
224
228
|
|
225
229
|
def remove_paren(node = @prog)
|
226
230
|
node.traverse(nil) {|st, parent|
|
227
231
|
if st.respond_to? :remove_paren
|
228
232
|
st.remove_paren
|
233
|
+
st.add_paren
|
229
234
|
end
|
230
235
|
}
|
231
236
|
self
|
@@ -246,19 +251,68 @@ module Minjs
|
|
246
251
|
}
|
247
252
|
break if !_retry
|
248
253
|
end
|
254
|
+
self
|
249
255
|
end
|
250
256
|
|
251
257
|
def block_to_statement(node = @prog)
|
252
258
|
node.traverse(nil) {|st, parent|
|
253
|
-
if st.kind_of? ECMA262::
|
254
|
-
|
255
|
-
|
259
|
+
if st.kind_of? ECMA262::StIf
|
260
|
+
#
|
261
|
+
# To determine removing "if block" is available or not is difficult.
|
262
|
+
# For example, next codes block must not be removed, because
|
263
|
+
# "else" cluase combined to second "if" statement.
|
264
|
+
#
|
265
|
+
#
|
266
|
+
# if(a){ //<= this block must not be removed
|
267
|
+
# while(true)
|
268
|
+
# if(b){
|
269
|
+
# ;
|
270
|
+
# }
|
271
|
+
# }
|
272
|
+
# else{
|
273
|
+
# ;
|
274
|
+
# }
|
275
|
+
|
276
|
+
# The "else" cluase's block can be removed without condition.
|
277
|
+
if st.else_st and st.else_st.kind_of? ECMA262::StBlock and st.else_st.to_statement?
|
278
|
+
st.replace(st.else_st, st.else_st.to_statement)
|
279
|
+
end
|
280
|
+
#
|
281
|
+
# if "if" statement has no "else" clause, its block can be removed.
|
282
|
+
#
|
283
|
+
if st.else_st.nil? and st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
|
284
|
+
st.replace(st.then_st, st.then_st.to_statement)
|
285
|
+
#
|
286
|
+
# if "if" statement has "else" clause, check "then" branch.
|
287
|
+
# If branch has no "if" statement or
|
288
|
+
# has "if-else" statement, its block can be removed.
|
289
|
+
#
|
290
|
+
elsif st.else_st and st.then_st.kind_of? ECMA262::StBlock and st.then_st.to_statement?
|
291
|
+
deblock = true
|
292
|
+
last_st = st.then_st.last_statement.map{|x|
|
293
|
+
if x.kind_of? ECMA262::StIf and x.else_st.nil?
|
294
|
+
deblock = false
|
295
|
+
end
|
296
|
+
}
|
297
|
+
if deblock
|
298
|
+
st.replace(st.then_st, st.then_st.to_statement)
|
299
|
+
end
|
256
300
|
end
|
257
301
|
end
|
258
302
|
}
|
303
|
+
node.traverse(nil) {|st, parent|
|
304
|
+
if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf)
|
305
|
+
if st.to_statement?
|
306
|
+
parent.replace(st, st.to_statement)
|
307
|
+
end
|
308
|
+
end
|
309
|
+
}
|
259
310
|
self
|
260
311
|
end
|
261
312
|
|
313
|
+
def if_block_to_statemet(node = @prog)
|
314
|
+
end
|
315
|
+
|
262
316
|
def if_to_cond(node = nil)
|
263
317
|
node = @prog if node.nil?
|
264
318
|
node.traverse(nil) {|st, parent|
|
@@ -304,6 +358,7 @@ module Minjs
|
|
304
358
|
end
|
305
359
|
}
|
306
360
|
remove_paren
|
361
|
+
self
|
307
362
|
end
|
308
363
|
|
309
364
|
def compress_var(node = @prog)
|
@@ -311,13 +366,29 @@ module Minjs
|
|
311
366
|
#traverse all statemtns and expression
|
312
367
|
#
|
313
368
|
node.traverse(nil) {|st, parent|
|
314
|
-
|
315
|
-
|
369
|
+
var_sym = :a
|
370
|
+
if st.kind_of? ECMA262::StTry and st.catch
|
371
|
+
_context = st.catch_context
|
372
|
+
_parent = st
|
373
|
+
_st = st.catch[1]
|
374
|
+
elsif st.kind_of? ECMA262::StFunc #and st.context.var_env.outer
|
375
|
+
_context = st.context
|
376
|
+
_parent = parent
|
377
|
+
_st = st
|
378
|
+
else
|
379
|
+
_parent = nil
|
380
|
+
_context = nil
|
381
|
+
_st = nil
|
382
|
+
end
|
383
|
+
if _parent and _context and _st
|
316
384
|
#
|
317
|
-
# collect all variables under this function
|
385
|
+
# collect all variables under this function/catch
|
318
386
|
#
|
319
387
|
vars = {}
|
320
|
-
st.
|
388
|
+
if st.kind_of? ECMA262::StTry
|
389
|
+
vars[st.catch[0].val.to_sym] = 1
|
390
|
+
end
|
391
|
+
_st.traverse(_parent) {|st2|
|
321
392
|
if st2.kind_of? ECMA262::IdentifierName
|
322
393
|
vars[st2.val.to_sym] ||= 0
|
323
394
|
vars[st2.val.to_sym] += 1
|
@@ -327,22 +398,35 @@ module Minjs
|
|
327
398
|
# collect all var variables under this function
|
328
399
|
#
|
329
400
|
var_vars = {}
|
330
|
-
st.
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
st2.
|
336
|
-
|
401
|
+
if st.kind_of? ECMA262::StFunc
|
402
|
+
_context.var_env.record.binding.each do|k, v|
|
403
|
+
var_vars[k] = (vars[k] || 1)
|
404
|
+
end
|
405
|
+
_st.traverse(parent) {|st2|
|
406
|
+
if st2.kind_of? ECMA262::StFunc
|
407
|
+
st2.context.var_env.record.binding.each do|k, v|
|
408
|
+
var_vars[k] = (vars[k] || 1)
|
409
|
+
end
|
337
410
|
end
|
411
|
+
}
|
412
|
+
end
|
413
|
+
#
|
414
|
+
# collect all lexical variables under this catch clause
|
415
|
+
#
|
416
|
+
# currently, only catch's args is lex_var
|
417
|
+
#
|
418
|
+
lex_vars = {}
|
419
|
+
if st.kind_of? ECMA262::StTry
|
420
|
+
_context.lex_env.record.binding.each do|k, v|
|
421
|
+
lex_vars[k] = (vars[k] || 1)
|
338
422
|
end
|
339
|
-
|
423
|
+
end
|
340
424
|
#
|
341
|
-
# check `eval' function is exist under this function
|
425
|
+
# check `eval' function is exist under this function/catch
|
342
426
|
#
|
343
427
|
unless var_vars[:eval]
|
344
428
|
eval_flag = false
|
345
|
-
|
429
|
+
_st.traverse(_parent) {|st2|
|
346
430
|
if st2.kind_of? ECMA262::ExpCall and st2.name.to_js({}) == "eval"
|
347
431
|
eval_flag = true
|
348
432
|
break
|
@@ -370,8 +454,10 @@ module Minjs
|
|
370
454
|
#
|
371
455
|
# rename `name' to `var_sym'
|
372
456
|
#
|
373
|
-
|
374
|
-
if st2.kind_of? ECMA262::IdentifierName and st2.context
|
457
|
+
_st.traverse(_parent){|st2|
|
458
|
+
if st2.kind_of? ECMA262::IdentifierName and st2.context.nil?
|
459
|
+
;# TODO, currently special identifier such as 'this' has no context
|
460
|
+
elsif st2.kind_of? ECMA262::IdentifierName and st2.context.var_env.outer == nil # global scope
|
375
461
|
;
|
376
462
|
elsif st2.kind_of? ECMA262::IdentifierName and st2.val == name
|
377
463
|
st2.instance_eval{
|
@@ -385,6 +471,38 @@ module Minjs
|
|
385
471
|
end
|
386
472
|
var_sym = next_sym(var_sym)
|
387
473
|
}
|
474
|
+
lex_vars.each {|name, count|
|
475
|
+
if name.nil?
|
476
|
+
next
|
477
|
+
end
|
478
|
+
while(vars[var_sym])
|
479
|
+
var_sym = next_sym(var_sym)
|
480
|
+
end
|
481
|
+
if name.to_s.bytesize > var_sym.to_s.bytesize
|
482
|
+
#
|
483
|
+
# rename `name' to `var_sym'
|
484
|
+
#
|
485
|
+
_st.traverse(_parent){|st2|
|
486
|
+
if st2.kind_of? ECMA262::IdentifierName and st2.context.nil?
|
487
|
+
;# TODO, currently special identifier such as 'this' has no context
|
488
|
+
elsif st2.kind_of? ECMA262::IdentifierName and st2.context.lex_env.outer == nil # global scope
|
489
|
+
;
|
490
|
+
elsif st2.kind_of? ECMA262::IdentifierName and st2.val == name
|
491
|
+
st2.instance_eval{
|
492
|
+
@val = var_sym
|
493
|
+
}
|
494
|
+
end
|
495
|
+
}
|
496
|
+
if st.kind_of? ECMA262::StTry
|
497
|
+
if st.catch[0].kind_of? ECMA262::IdentifierName
|
498
|
+
st.catch[0].instance_eval{
|
499
|
+
@val = var_sym
|
500
|
+
}
|
501
|
+
end
|
502
|
+
end
|
503
|
+
end
|
504
|
+
var_sym = next_sym(var_sym)
|
505
|
+
}
|
388
506
|
end
|
389
507
|
}
|
390
508
|
self
|
@@ -396,22 +514,27 @@ module Minjs
|
|
396
514
|
st.reduce(parent)
|
397
515
|
end
|
398
516
|
}
|
517
|
+
self
|
399
518
|
end
|
400
519
|
|
401
520
|
def simple_replacement(node = @prog)
|
402
521
|
node.traverse(nil) {|st, parent|
|
522
|
+
#
|
403
523
|
#true => !0
|
404
524
|
#false => !1
|
525
|
+
#
|
405
526
|
if st.kind_of? ECMA262::Boolean
|
406
527
|
if st.true?
|
407
528
|
parent.replace(st, ECMA262::ExpParen.new(ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new(0))))
|
408
529
|
else
|
409
530
|
parent.replace(st, ECMA262::ExpParen.new(ECMA262::ExpLogicalNot.new(ECMA262::ECMA262Numeric.new(1))))
|
410
531
|
end
|
532
|
+
#
|
411
533
|
#if(true){<then>}else{<else>} => then
|
534
|
+
#
|
412
535
|
elsif st.kind_of? ECMA262::StIf
|
413
|
-
if st.cond.
|
414
|
-
if st.cond.
|
536
|
+
if st.cond.respond_to? :to_ecma262_boolean
|
537
|
+
if st.cond.to_ecma262_boolean
|
415
538
|
parent.replace(st, st.then_st)
|
416
539
|
elsif st.else_st
|
417
540
|
parent.replace(st, st.else_st)
|
@@ -419,8 +542,19 @@ module Minjs
|
|
419
542
|
parent.replace(st, ECMA262::StEmpty.new())
|
420
543
|
end
|
421
544
|
end
|
545
|
+
#
|
546
|
+
# while(true) => for(;;)
|
547
|
+
# while(false) => remove
|
548
|
+
#
|
549
|
+
elsif st.kind_of? ECMA262::StWhile and st.exp.respond_to? :to_ecma262_boolean
|
550
|
+
if st.exp.to_ecma262_boolean
|
551
|
+
parent.replace(st, ECMA262::StFor.new(nil,nil,nil, st.statement))
|
552
|
+
else
|
553
|
+
parent.replace(st, ECMA262::StEmpty.new)
|
554
|
+
end
|
422
555
|
end
|
423
556
|
}
|
557
|
+
self
|
424
558
|
end
|
425
559
|
|
426
560
|
def return_to_exp(node = @prog)
|
@@ -446,7 +580,7 @@ module Minjs
|
|
446
580
|
# var a; a=1
|
447
581
|
# => var a=1
|
448
582
|
#
|
449
|
-
def
|
583
|
+
def assignment_after_var_old(node = @prog)
|
450
584
|
node.traverse(nil) {|st, parent|
|
451
585
|
if st.kind_of? ECMA262::StExp and parent.kind_of? ECMA262::SourceElements
|
452
586
|
if st.exp.kind_of? ECMA262::ExpAssign
|
@@ -476,6 +610,102 @@ module Minjs
|
|
476
610
|
end
|
477
611
|
end
|
478
612
|
}
|
613
|
+
self
|
614
|
+
end
|
615
|
+
#
|
616
|
+
# reduce_if
|
617
|
+
#
|
618
|
+
# 1) rewrite nested "if" statemet such as:
|
619
|
+
# if(a)
|
620
|
+
# if(b) ...;
|
621
|
+
#
|
622
|
+
# to:
|
623
|
+
#
|
624
|
+
# if(a && b) ...;
|
625
|
+
#
|
626
|
+
# NOTE:
|
627
|
+
# both if must not have "else" clause
|
628
|
+
#
|
629
|
+
def reduce_if(node = @prog)
|
630
|
+
node.traverse(nil) {|st, parent|
|
631
|
+
if st.kind_of? ECMA262::StIf
|
632
|
+
if st.else_st.nil? and
|
633
|
+
st.then_st.kind_of? ECMA262::StIf and st.then_st.else_st.nil?
|
634
|
+
st.replace(st.cond, ECMA262::ExpLogicalAnd.new(st.cond, st.then_st.cond))
|
635
|
+
st.replace(st.then_st, st.then_st.then_st)
|
636
|
+
end
|
637
|
+
end
|
638
|
+
}
|
639
|
+
self
|
640
|
+
end
|
641
|
+
|
642
|
+
def assignment_after_var(node = @prog)
|
643
|
+
def rewrite_var(var_st, name, initializer)
|
644
|
+
var_st.normalization
|
645
|
+
i = 0
|
646
|
+
var_st.vars.each do |_name, _initializer|
|
647
|
+
if _name == name and _initializer.nil?
|
648
|
+
var_st.vars[i] = [name, initializer]
|
649
|
+
var_st.normalization
|
650
|
+
return true
|
651
|
+
end
|
652
|
+
i += 1
|
653
|
+
end
|
654
|
+
false
|
655
|
+
end
|
656
|
+
node.traverse(nil) {|st, parent|
|
657
|
+
if st.kind_of? ECMA262::StVar and parent.kind_of? ECMA262::SourceElements
|
658
|
+
#
|
659
|
+
# index of 'var statement' is 0, after calling reorder_var
|
660
|
+
#
|
661
|
+
catch(:break){
|
662
|
+
idx = 1
|
663
|
+
while true
|
664
|
+
st2 = parent[idx]
|
665
|
+
if st2.kind_of? ECMA262::StEmpty
|
666
|
+
idx +=1
|
667
|
+
next
|
668
|
+
elsif st2.kind_of? ECMA262::StExp and st2.exp.kind_of? ECMA262::ExpAssign
|
669
|
+
if rewrite_var(st, st2.exp.val, st2.exp.val2)
|
670
|
+
parent.replace(st2, ECMA262::StEmpty.new())
|
671
|
+
else
|
672
|
+
throw :break
|
673
|
+
end
|
674
|
+
idx += 1
|
675
|
+
next
|
676
|
+
elsif st2.kind_of? ECMA262::StFor and st2.exp1.kind_of? ECMA262::ExpAssign
|
677
|
+
if rewrite_var(st, st2.exp1.val, st2.exp1.val2)
|
678
|
+
st2.replace(st2.exp1, nil)
|
679
|
+
else
|
680
|
+
throw :break
|
681
|
+
end
|
682
|
+
throw :break
|
683
|
+
elsif st2.kind_of? ECMA262::StExp and st2.exp.kind_of? ECMA262::ExpComma
|
684
|
+
exp_parent = st2
|
685
|
+
exp = st2.exp
|
686
|
+
|
687
|
+
while exp.val.kind_of? ECMA262::ExpComma
|
688
|
+
exp_parent = exp
|
689
|
+
exp = exp.val
|
690
|
+
end
|
691
|
+
|
692
|
+
if exp.val.kind_of? ECMA262::ExpAssign
|
693
|
+
if rewrite_var(st, exp.val.val, exp.val.val2)
|
694
|
+
exp_parent.replace(exp, exp.val2)
|
695
|
+
else
|
696
|
+
throw :break
|
697
|
+
end
|
698
|
+
else
|
699
|
+
throw :break
|
700
|
+
end
|
701
|
+
else
|
702
|
+
throw :break
|
703
|
+
end
|
704
|
+
end
|
705
|
+
}
|
706
|
+
end
|
707
|
+
}
|
708
|
+
self
|
479
709
|
end
|
480
710
|
end
|
481
711
|
end
|
data/lib/minjs/ecma262/base.rb
CHANGED
@@ -203,73 +203,6 @@ module Minjs
|
|
203
203
|
def to_js(options = {})
|
204
204
|
concat options, @source_elements
|
205
205
|
end
|
206
|
-
=begin
|
207
|
-
def grouping
|
208
|
-
remove_empty_statement
|
209
|
-
nsl = []
|
210
|
-
sl = []
|
211
|
-
g = []
|
212
|
-
@source_elements.each do |st|
|
213
|
-
if st.to_exp?
|
214
|
-
g.push(st)
|
215
|
-
else
|
216
|
-
if g.length > 0
|
217
|
-
sl.push(g)
|
218
|
-
end
|
219
|
-
sl.push([st])
|
220
|
-
g = []
|
221
|
-
end
|
222
|
-
end
|
223
|
-
if g.length > 0
|
224
|
-
sl.push(g)
|
225
|
-
end
|
226
|
-
|
227
|
-
sl.each do |g|
|
228
|
-
if g.length == 1
|
229
|
-
nsl.push(g[0])
|
230
|
-
else
|
231
|
-
i = 1
|
232
|
-
t = g[0].to_exp
|
233
|
-
while i < g.length
|
234
|
-
t = ExpComma.new(t, g[i].to_exp)
|
235
|
-
i += 1
|
236
|
-
end
|
237
|
-
nsl.push(StExp.new(t))
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
@source_elements = nsl
|
242
|
-
end
|
243
|
-
|
244
|
-
def replace(from, to)
|
245
|
-
idx = @source_elements.index(from)
|
246
|
-
if idx
|
247
|
-
@source_elements[idx] = to
|
248
|
-
end
|
249
|
-
end
|
250
|
-
|
251
|
-
def remove(st)
|
252
|
-
@source_elements.delete(st)
|
253
|
-
end
|
254
|
-
|
255
|
-
def remove_empty_statement
|
256
|
-
@source_elements.reject!{|x|
|
257
|
-
x.class == StEmpty
|
258
|
-
}
|
259
|
-
end
|
260
|
-
|
261
|
-
def each(&block)
|
262
|
-
@source_elements.each(&block)
|
263
|
-
end
|
264
|
-
|
265
|
-
def [](i)
|
266
|
-
@source_elements[i]
|
267
|
-
end
|
268
|
-
|
269
|
-
def index(st)
|
270
|
-
@source_elements.index(st)
|
271
|
-
end
|
272
|
-
=end
|
273
206
|
end
|
274
207
|
end
|
275
208
|
end
|
data/lib/minjs/ecma262/env.rb
CHANGED
@@ -8,12 +8,14 @@ module Minjs
|
|
8
8
|
@binding = {}
|
9
9
|
@options = {}
|
10
10
|
end
|
11
|
+
|
11
12
|
def create_mutable_binding(n, d, options = {})
|
12
13
|
if n.kind_of? IdentifierName
|
13
14
|
n = n.val
|
14
15
|
end
|
15
16
|
@binding[n] = {:value => nil}
|
16
17
|
end
|
18
|
+
|
17
19
|
def set_mutable_binding(n, v, s, options = {})
|
18
20
|
if n.kind_of? IdentifierName
|
19
21
|
n = n.val
|
@@ -54,7 +56,8 @@ module Minjs
|
|
54
56
|
attr_accessor :this_binding
|
55
57
|
|
56
58
|
def initialize(options = {})
|
57
|
-
@var_env =
|
59
|
+
@var_env = LexEnv.new(options)
|
60
|
+
@lex_env = LexEnv.new(options)
|
58
61
|
@this_binding = ExObject.new(
|
59
62
|
{
|
60
63
|
attr: {
|