minjs 0.4.0 → 0.4.1
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/compressor.rb +100 -70
- data/lib/minjs/ecma262/base.rb +7 -9
- data/lib/minjs/ecma262/env.rb +16 -22
- data/lib/minjs/ecma262/literal.rb +47 -51
- data/lib/minjs/ecma262/statement.rb +100 -39
- data/lib/minjs/lex/expression.rb +235 -238
- data/lib/minjs/lex/function.rb +40 -50
- data/lib/minjs/lex/parser.rb +1 -6
- data/lib/minjs/lex/program.rb +12 -12
- data/lib/minjs/lex/statement.rb +169 -175
- data/lib/minjs/version.rb +1 -1
- data/minjs.gemspec +3 -3
- metadata +15 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2378eb52a7085927e5c4068a9396d656e14dcf0
|
4
|
+
data.tar.gz: b3a936cdae1ebc77424d0a2330ee78bdf4b56922
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 86114b8ef9ef2ca9eb0ec5b15b532b49b138f3052b1ef10aaa6fa9433cbbdaa1837905b1b59a816eed0b6ab6182270a165d7aeb8e93c150fc71bc0ab6ae72d96
|
7
|
+
data.tar.gz: 458383c20b91c43c8a64c9c70896d54cfdbe34cdeaea3e129393a2ba7a371236cc10ec0cce8d0e7f4d6d537e1c3aa5a3d0ea261c9d2eafa5d9f1b5607c5a54eb
|
@@ -88,7 +88,7 @@ module Minjs::Compressor
|
|
88
88
|
# @return self
|
89
89
|
def parse(data)
|
90
90
|
@lex = Minjs::Lex::Parser.new(data, :logger => @logger)
|
91
|
-
@
|
91
|
+
@global_var_env = ECMA262::LexEnv.new(outer: nil)
|
92
92
|
@heading_comments = []
|
93
93
|
|
94
94
|
while a = (@lex.comment || @lex.line_terminator || @lex.white_space)
|
@@ -98,7 +98,8 @@ module Minjs::Compressor
|
|
98
98
|
!(@heading_comments[-2].kind_of?(ECMA262::SingleLineComment))
|
99
99
|
@heading_comments.pop
|
100
100
|
end
|
101
|
-
@prog = @lex.program(@
|
101
|
+
@prog = @lex.program(@global_var_env)
|
102
|
+
@prog.exe_context = ECMA262::ExeContext.new
|
102
103
|
|
103
104
|
remove_empty_statement
|
104
105
|
@lex.clear_cache
|
@@ -203,12 +204,12 @@ module Minjs::Compressor
|
|
203
204
|
node.traverse(nil) {|parent, st|
|
204
205
|
if st.kind_of? ECMA262::Prog
|
205
206
|
vars = nil
|
206
|
-
|
207
|
+
var_env = st.var_env
|
207
208
|
#
|
208
209
|
# collect all of var variable in this function
|
209
210
|
#
|
210
211
|
var_vars = {}
|
211
|
-
|
212
|
+
var_env.record.binding.each do|k, v|
|
212
213
|
if v and v[:_parameter_list].nil? and !v[:value].kind_of?(ECMA262::StFunc)
|
213
214
|
var_vars[k] = true
|
214
215
|
end
|
@@ -218,7 +219,7 @@ module Minjs::Compressor
|
|
218
219
|
# if variable has initializer
|
219
220
|
#
|
220
221
|
st.traverse(parent){|parent2, st2|
|
221
|
-
if st2.kind_of? ECMA262::StVar and st2.
|
222
|
+
if st2.kind_of? ECMA262::StVar and st2.var_env == var_env
|
222
223
|
exp = nil
|
223
224
|
st2.vars.each do |name, initializer|
|
224
225
|
if initializer
|
@@ -234,18 +235,18 @@ module Minjs::Compressor
|
|
234
235
|
else
|
235
236
|
parent2.replace(st2, ECMA262::StEmpty.new())
|
236
237
|
end
|
237
|
-
elsif st2.kind_of? ECMA262::StForVar and st2.
|
238
|
+
elsif st2.kind_of? ECMA262::StForVar and st2.var_env == var_env
|
238
239
|
parent2.replace(st2, st2.to_st_for)
|
239
|
-
elsif st2.kind_of? ECMA262::StForInVar and st2.
|
240
|
+
elsif st2.kind_of? ECMA262::StForInVar and st2.var_env == var_env
|
240
241
|
parent2.replace(st2, st2.to_st_for_in)
|
241
242
|
end
|
242
243
|
}
|
243
244
|
if var_vars.length > 0
|
244
245
|
elems = st.source_elements.source_elements
|
245
246
|
v = ECMA262::StVar.new(
|
246
|
-
|
247
|
+
var_env,
|
247
248
|
var_vars.collect do |k, v|
|
248
|
-
[ECMA262::IdentifierName.get(
|
249
|
+
[ECMA262::IdentifierName.get(k)]
|
249
250
|
end
|
250
251
|
)
|
251
252
|
|
@@ -341,7 +342,7 @@ module Minjs::Compressor
|
|
341
342
|
remove_empty_statement
|
342
343
|
then_to_block
|
343
344
|
node.traverse(nil) {|parent, st|
|
344
|
-
if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf)
|
345
|
+
if st.kind_of? ECMA262::StBlock and !parent.kind_of?(ECMA262::StTry) and !parent.kind_of?(ECMA262::StIf) and !parent.kind_of?(ECMA262::StTryCatch)
|
345
346
|
if st.to_statement?
|
346
347
|
parent.replace(st, st.to_statement)
|
347
348
|
end
|
@@ -569,20 +570,20 @@ module Minjs::Compressor
|
|
569
570
|
|
570
571
|
# Compresses variable name as short as possible.
|
571
572
|
#
|
572
|
-
# This method collects and counts all variables under
|
573
|
+
# This method collects and counts all variables under the function/catch,
|
573
574
|
# then trying to rename var_vars(see bellow) to
|
574
575
|
# new name.
|
575
576
|
#
|
576
577
|
# outer_vars::
|
577
|
-
# Variables which locate out of this function(or global variable)
|
578
|
+
# Variables which locate out of this function/catch(or global variable)
|
578
579
|
# Them name cannot be renamed
|
579
580
|
# nesting_vars::
|
580
|
-
# Variables which locate in the function of this function.
|
581
|
+
# Variables which locate in the function/catch of this function/catch.
|
581
582
|
# Them name cannot be renamed
|
582
583
|
# var_vars::
|
583
|
-
# Variables which have same scope in this function.
|
584
|
+
# Variables which have same scope in this function/catch.
|
584
585
|
# all_vars::
|
585
|
-
# All variables under this function.
|
586
|
+
# All variables under this function/catch.
|
586
587
|
#
|
587
588
|
# 1. If the new name is not in all_vars, the name can be renamed to it.
|
588
589
|
# 2. If the new name belongs to var_vars, the name cannot be renamed.
|
@@ -592,9 +593,15 @@ module Minjs::Compressor
|
|
592
593
|
#
|
593
594
|
#
|
594
595
|
def compress_var(node = @prog)
|
596
|
+
scopes = []
|
595
597
|
func_scopes = []
|
596
598
|
catch_scopes = []
|
597
599
|
with_scopes = []
|
600
|
+
|
601
|
+
node.traverse(nil) {|parent, st|
|
602
|
+
st.parent = parent
|
603
|
+
}
|
604
|
+
|
598
605
|
#
|
599
606
|
# ECMA262 10.2:
|
600
607
|
#
|
@@ -607,8 +614,10 @@ module Minjs::Compressor
|
|
607
614
|
node.traverse(nil) {|parent, st|
|
608
615
|
if st.kind_of? ECMA262::StFunc
|
609
616
|
func_scopes.push([parent, st])
|
610
|
-
|
617
|
+
scopes.push([parent, st])
|
618
|
+
elsif st.kind_of? ECMA262::StTryCatch
|
611
619
|
catch_scopes.push([parent, st])
|
620
|
+
scopes.push([parent, st])
|
612
621
|
elsif st.kind_of? ECMA262::StWith
|
613
622
|
with_scopes.push([parent, st])
|
614
623
|
end
|
@@ -653,42 +662,53 @@ module Minjs::Compressor
|
|
653
662
|
#console.log(eee); //=>global
|
654
663
|
#test();
|
655
664
|
#
|
656
|
-
|
657
|
-
if st.catch
|
658
|
-
catch_context = ECMA262::Context.new
|
659
|
-
catch_context.lex_env = st.context.lex_env.new_declarative_env()
|
660
|
-
catch_context.var_env = st.context.var_env
|
661
|
-
catch_context.lex_env.record.create_mutable_binding(st.catch[0], nil)
|
662
|
-
catch_context.lex_env.record.set_mutable_binding(st.catch[0], :undefined, nil)
|
663
|
-
st.catch[0].context = catch_context
|
665
|
+
scopes.reverse!
|
664
666
|
|
665
|
-
|
666
|
-
|
667
|
-
|
667
|
+
# outer
|
668
|
+
scopes = scopes.collect {|parent, st|
|
669
|
+
if st.kind_of? ECMA262::StFunc or st.kind_of? ECMA262::StTryCatch
|
670
|
+
outer = st.parent
|
671
|
+
while outer
|
672
|
+
if outer.kind_of? ECMA262::StFunc or outer.kind_of? ECMA262::StTryCatch
|
673
|
+
break
|
668
674
|
end
|
669
|
-
|
670
|
-
|
675
|
+
outer = outer.parent
|
676
|
+
end
|
671
677
|
end
|
678
|
+
if outer.nil?
|
679
|
+
outer = @prog
|
680
|
+
end
|
681
|
+
[parent, st, outer]
|
672
682
|
}
|
673
|
-
|
674
|
-
#
|
675
|
-
|
676
|
-
# with_context.var_env = st.context.var_env
|
677
|
-
# st.statement.traverse(st) {|st2|
|
678
|
-
# if st2.kind_of? ECMA262::IdentifierName and st2.binding_env == st.context.var_env
|
679
|
-
# st2.context = with_context
|
680
|
-
# with_context.lex_env.record.create_mutable_binding(st2, nil)
|
681
|
-
# with_context.lex_env.record.set_mutable_binding(st2, :undefined, nil)
|
682
|
-
# end
|
683
|
-
# }
|
684
|
-
# }
|
685
|
-
func_scopes.reverse!
|
686
|
-
func_scopes.each {|parent, st|
|
683
|
+
|
684
|
+
# exe_context
|
685
|
+
scopes.each {|parent, st, outer|
|
687
686
|
if st.kind_of? ECMA262::StFunc
|
688
|
-
|
689
|
-
|
690
|
-
|
687
|
+
st.exe_context = st.enter(outer.exe_context)
|
688
|
+
st.traverse(nil) {|parent2, st2|
|
689
|
+
if st2.kind_of? ECMA262::IdentifierName
|
690
|
+
if st.decl? and st2 .eql? st.name
|
691
|
+
;
|
692
|
+
elsif st.var_env.record.binding[st2.to_s.to_sym]
|
693
|
+
st2.exe_context = st.exe_context
|
694
|
+
end
|
695
|
+
end
|
696
|
+
}
|
697
|
+
elsif st.kind_of? ECMA262::StTryCatch
|
698
|
+
st.exe_context = st.enter(outer.exe_context)
|
699
|
+
st.traverse(nil) {|parent2, st2|
|
700
|
+
if st2.kind_of? ECMA262::IdentifierName
|
701
|
+
if st2 == st.arg
|
702
|
+
st2.exe_context = st.exe_context
|
703
|
+
end
|
704
|
+
end
|
705
|
+
}
|
691
706
|
end
|
707
|
+
}
|
708
|
+
|
709
|
+
scopes.each {|parent, st|
|
710
|
+
exe_context = st.exe_context
|
711
|
+
|
692
712
|
var_sym = :a
|
693
713
|
all_vars = {}
|
694
714
|
var_vars = {}
|
@@ -700,30 +720,28 @@ module Minjs::Compressor
|
|
700
720
|
st.traverse(parent) {|parent2, st2|
|
701
721
|
if st2.kind_of? ECMA262::IdentifierName
|
702
722
|
var_name = st2.val.to_sym
|
703
|
-
#st2_var_env = st2.binding_env
|
704
|
-
st2_lex_env = st2.binding_env(:lex)
|
705
723
|
all_vars[var_name] ||= 0
|
706
724
|
all_vars[var_name] += 1
|
707
|
-
if
|
725
|
+
if st2.exe_context == nil #global
|
708
726
|
outer_vars[var_name] ||= 0
|
709
727
|
outer_vars[var_name] += 1
|
710
|
-
elsif
|
728
|
+
elsif st2.exe_context.lex_env == @prog.exe_context.lex_env
|
711
729
|
outer_vars[var_name] ||= 0
|
712
730
|
outer_vars[var_name] += 1
|
713
|
-
elsif
|
731
|
+
elsif st2.exe_context.lex_env == exe_context.lex_env
|
714
732
|
var_vars[var_name] ||= 0
|
715
733
|
var_vars[var_name] += 1
|
716
734
|
var_vars_list.push(st2)
|
717
735
|
else
|
718
|
-
e = st2.
|
736
|
+
e = st2.exe_context.lex_env
|
719
737
|
while e
|
720
|
-
e
|
721
|
-
if e == context.lex_env
|
738
|
+
if e == exe_context.lex_env
|
722
739
|
nesting_vars[var_name] ||= 0
|
723
740
|
nesting_vars[var_name] += 1
|
724
741
|
nesting_vars_list.push(st2)
|
725
742
|
break
|
726
743
|
end
|
744
|
+
e = e.outer
|
727
745
|
if e.nil?
|
728
746
|
outer_vars[var_name] ||= 0
|
729
747
|
outer_vars[var_name] += 1
|
@@ -733,6 +751,19 @@ module Minjs::Compressor
|
|
733
751
|
end
|
734
752
|
end
|
735
753
|
}
|
754
|
+
|
755
|
+
# puts "*" * 30
|
756
|
+
# puts st.to_js
|
757
|
+
# puts "*" * 30
|
758
|
+
# puts "all_vars"
|
759
|
+
# puts all_vars
|
760
|
+
# puts "outer_vars"
|
761
|
+
# puts outer_vars
|
762
|
+
# puts "var_vars"
|
763
|
+
# puts var_vars
|
764
|
+
# puts "nesting_vars"
|
765
|
+
# puts nesting_vars
|
766
|
+
|
736
767
|
unless var_vars[:eval]
|
737
768
|
eval_flag = false
|
738
769
|
st.traverse(parent) {|parent2, st2|
|
@@ -769,7 +800,7 @@ module Minjs::Compressor
|
|
769
800
|
while true
|
770
801
|
#condition b
|
771
802
|
if outer_vars[var_sym]
|
772
|
-
|
803
|
+
#STDERR.puts "outer_vars has #{var_sym}"
|
773
804
|
elsif var_vars[var_sym]
|
774
805
|
#STDERR.puts "var_vars has #{var_sym}(#{var_vars[var_sym]})"
|
775
806
|
#condigion c
|
@@ -783,8 +814,7 @@ module Minjs::Compressor
|
|
783
814
|
if nesting_vars[var_sym]
|
784
815
|
#STDERR.puts "nesting_vars has #{var_sym}"
|
785
816
|
nesting_vars_list.each do |x|
|
786
|
-
#raise 'error' if x.binding_env(
|
787
|
-
raise 'error' if x.binding_env(:lex).nil?
|
817
|
+
#raise 'error' if x.binding_env(x.exe_context.var_env).nil?
|
788
818
|
end
|
789
819
|
|
790
820
|
var_sym2 = "XXX#{var_sym.to_s}".to_sym
|
@@ -792,13 +822,12 @@ module Minjs::Compressor
|
|
792
822
|
var_sym2 = next_sym(var_sym2)
|
793
823
|
end
|
794
824
|
#STDERR.puts "#{var_sym}->#{var_sym2}"
|
825
|
+
|
795
826
|
rl = {}
|
796
827
|
nesting_vars_list.each do |x|
|
797
828
|
if x.val.to_sym == var_sym
|
798
|
-
_var_env = x.binding_env(
|
799
|
-
_lex_env = x.binding_env(:lex)
|
829
|
+
_var_env = x.binding_env(x.exe_context.var_env)
|
800
830
|
rl[_var_env] = true
|
801
|
-
rl[_lex_env] = true
|
802
831
|
end
|
803
832
|
end
|
804
833
|
rl.keys.each do |_env|
|
@@ -814,26 +843,24 @@ module Minjs::Compressor
|
|
814
843
|
@val = var_sym2
|
815
844
|
}
|
816
845
|
end
|
817
|
-
#raise 'error' if x.binding_env(:var).nil?
|
818
|
-
raise x.to_js if x.binding_env(:lex).nil?
|
819
846
|
end
|
820
847
|
end
|
821
848
|
rename_table[name] = var_sym
|
822
849
|
var_sym = next_sym(var_sym)
|
823
850
|
}
|
824
851
|
var_vars_list.each {|st2|
|
825
|
-
raise
|
852
|
+
#raise 'error' if st2.binding_env(st2.exe_context.var_env).nil?
|
826
853
|
}
|
827
854
|
|
828
855
|
rename_table.each do |name, new_name|
|
829
856
|
if name != new_name
|
830
|
-
if
|
831
|
-
|
832
|
-
|
857
|
+
if exe_context.var_env.record.binding[name]
|
858
|
+
exe_context.var_env.record.binding[new_name] = exe_context.var_env.record.binding[name]
|
859
|
+
exe_context.var_env.record.binding.delete(name)
|
833
860
|
end
|
834
|
-
if
|
835
|
-
|
836
|
-
|
861
|
+
if exe_context.lex_env.record.binding[name]
|
862
|
+
exe_context.lex_env.record.binding[new_name] = exe_context.lex_env.record.binding[name]
|
863
|
+
exe_context.lex_env.record.binding.delete(name)
|
837
864
|
end
|
838
865
|
end
|
839
866
|
end
|
@@ -843,11 +870,14 @@ module Minjs::Compressor
|
|
843
870
|
if rename_table[@val]
|
844
871
|
@val = rename_table[@val]
|
845
872
|
#raise 'error' if st2.binding_env(:var).nil?
|
846
|
-
raise st2.to_js if st2.binding_env(:lex).nil?
|
873
|
+
#raise st2.to_js if st2.binding_env(:lex).nil?
|
847
874
|
end
|
848
875
|
}
|
849
876
|
}
|
850
877
|
}
|
878
|
+
node.traverse(nil) {|parent, st|
|
879
|
+
st.parent = nil
|
880
|
+
}
|
851
881
|
self
|
852
882
|
end
|
853
883
|
|
data/lib/minjs/ecma262/base.rb
CHANGED
@@ -2,6 +2,8 @@ module Minjs
|
|
2
2
|
module ECMA262
|
3
3
|
#ECMA262 Elements
|
4
4
|
class Base
|
5
|
+
attr_accessor :parent
|
6
|
+
|
5
7
|
# Returns a ECMAScript string containg the representation of element.
|
6
8
|
# @param options [Hash] options for Base#concat
|
7
9
|
# @return [String] ECMAScript string.
|
@@ -9,11 +11,6 @@ module Minjs
|
|
9
11
|
self.class.to_s + "??"
|
10
12
|
end
|
11
13
|
|
12
|
-
# to string
|
13
|
-
def to_s
|
14
|
-
to_js({})
|
15
|
-
end
|
16
|
-
|
17
14
|
# concatenate some of ECMA262 elements and convert it to ECMAScript
|
18
15
|
#
|
19
16
|
# @param args ECMA262 element
|
@@ -321,17 +318,18 @@ module Minjs
|
|
321
318
|
# @see http://www.ecma-international.org/ecma-262 ECMA262 14
|
322
319
|
class Prog < Base
|
323
320
|
attr_reader :source_elements
|
324
|
-
attr_reader :
|
321
|
+
attr_reader :var_env
|
322
|
+
attr_accessor :exe_context
|
325
323
|
|
326
|
-
def initialize(
|
324
|
+
def initialize(var_env, source_elements)
|
327
325
|
@source_elements = source_elements
|
328
|
-
@
|
326
|
+
@var_env = var_env
|
329
327
|
end
|
330
328
|
|
331
329
|
# duplicate object
|
332
330
|
# @see Base#deep_dup
|
333
331
|
def deep_dup
|
334
|
-
self.class.new(
|
332
|
+
self.class.new(var_env, source_elements.deep_dup)
|
335
333
|
end
|
336
334
|
|
337
335
|
# Replaces children object
|
data/lib/minjs/ecma262/env.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# coding: utf-8
|
1
2
|
module Minjs
|
2
3
|
module ECMA262
|
3
4
|
# class of Environment Record
|
@@ -30,7 +31,7 @@ module Minjs
|
|
30
31
|
n = n.val
|
31
32
|
end
|
32
33
|
@binding[n][:value] = v
|
33
|
-
@binding[n].merge!(options)
|
34
|
+
@binding[n].merge!(options || {})
|
34
35
|
end
|
35
36
|
end
|
36
37
|
|
@@ -50,16 +51,19 @@ module Minjs
|
|
50
51
|
#
|
51
52
|
# @see http://www.ecma-international.org/ecma-262 ECMA262 10.2
|
52
53
|
class LexEnv
|
53
|
-
|
54
|
+
attr_accessor :record
|
54
55
|
attr_reader :outer
|
55
56
|
attr_reader :type
|
56
57
|
|
57
58
|
def initialize(options = {})
|
58
59
|
@outer = options[:outer]
|
59
|
-
|
60
|
+
@type = (options[:type] || :declarative)
|
61
|
+
if options[:record]
|
60
62
|
@record = ObjectEnvRecord.new
|
61
|
-
|
63
|
+
elsif options[:type] == :declarative
|
62
64
|
@record = DeclarativeEnvRecord.new
|
65
|
+
elsif options[:type] == :object or true
|
66
|
+
@record = ObjectEnvRecord.new
|
63
67
|
end
|
64
68
|
end
|
65
69
|
|
@@ -70,6 +74,13 @@ module Minjs
|
|
70
74
|
e = LexEnv.new(outer: (outer || self), type: :declarative)
|
71
75
|
end
|
72
76
|
|
77
|
+
# NewDeclarativeEnvironment(E)
|
78
|
+
#
|
79
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 10.2.2.2
|
80
|
+
def self.new_declarative_env(e)
|
81
|
+
env = LexEnv.new(outer: e, type: :declarative)
|
82
|
+
end
|
83
|
+
|
73
84
|
# NewObjectEnvironment(O, E)
|
74
85
|
#
|
75
86
|
# @see http://www.ecma-international.org/ecma-262 ECMA262 10.2.2.3
|
@@ -93,32 +104,15 @@ module Minjs
|
|
93
104
|
# Class of Execution Contexts
|
94
105
|
#
|
95
106
|
# @see http://www.ecma-international.org/ecma-262 ECMA262 10.3
|
96
|
-
class
|
107
|
+
class ExeContext
|
97
108
|
attr_accessor :lex_env
|
98
109
|
attr_accessor :var_env
|
99
110
|
attr_accessor :this_binding
|
100
|
-
|
101
111
|
def initialize(options = {})
|
102
112
|
@var_env = LexEnv.new(options)
|
103
113
|
@lex_env = LexEnv.new(options)
|
104
|
-
#TODO
|
105
114
|
@this_binding = nil
|
106
|
-
# ExObject.new(
|
107
|
-
# {
|
108
|
-
# attr: {
|
109
|
-
# writable: true,
|
110
|
-
# enumerable: false,
|
111
|
-
# configurable: true
|
112
|
-
# }
|
113
|
-
# }
|
114
|
-
# )
|
115
|
-
end
|
116
|
-
|
117
|
-
# debug
|
118
|
-
def debug
|
119
|
-
@var_env.debug
|
120
115
|
end
|
121
|
-
|
122
116
|
end
|
123
117
|
end
|
124
118
|
end
|