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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dff56ddbe102f06b6d07d67ca3cbb7076dec2bc2
4
- data.tar.gz: 2bf1104e9aeda92155019cd2784e4313614fc958
3
+ metadata.gz: 82f88a2a64ab93ccafd2abd3e699e8d5fa7682d0
4
+ data.tar.gz: 3e9aec62b059e22695c0111169b75c5bd3fc1141
5
5
  SHA512:
6
- metadata.gz: 546ff6b86865bc79856e034b4bba733093170ccc4f514de33f390b597bb9cd0cf6608e2c00c8619ccfe2cd3e3ab3977df50fb3f022def02982b06a99f4dcee80
7
- data.tar.gz: 4ce28cc2d02368b99335fd1fe5bd69a7d03ccd72b4399fb775782e3186bf42d839df584f30468b83e6be4b9040a3c6054722ff266b79a96a177fee53c25ae9e4
6
+ metadata.gz: b58b34b47810cec665a86a8d831f7a222a558eb0ed21996de5332caddd13a3e15000544bc9a7867ed0a3341535eb55bebe8af4092e73dc9d0b8f34e143cf2b88
7
+ data.tar.gz: 93c25a509a9bf2c6864433f4ef955b64887bb35471be4d4fe1b68fdcaf736341e9c04634150adf8136097a2ada5d2f6815298ac1257b62a8192512d716f0754b
@@ -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
- @debug = false
23
- if options[:debug]
24
- @debug = true
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
- block_to_exp
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
- #feature
51
- #return_to_exp
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
- self.traverse {|st, parent|
136
- if st.kind_of? ECMA262::Prog
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
- self.traverse {|st, parent|
146
- if st.kind_of? ECMA262::StFunc and parent.kind_of? ECMA262::Prog and st.decl?
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
- #traverse all statemtns and expression
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::StList.new(blk)))
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
- #feature
199
- def remove_paren
200
- self.traverse {|st, parent|
201
- if st.kind_of? ECMA262::ExpParen
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
- self.traverse {|st, parent|
224
- if parent.kind_of? ECMA262::Prog and st.kind_of? ECMA262::StBlock
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 block_to_exp
243
- self.traverse {|st, parent|
244
- if st.kind_of? ECMA262::StBlock and st.to_exp?
245
- if parent.kind_of? ECMA262::StTry
246
- else
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 block_to_statement
255
- self.traverse {|st, parent|
256
- if st.kind_of? ECMA262::StBlock and st.to_statement?
257
- if parent.kind_of? ECMA262::StTry
258
- else
259
- parent.replace(st, st.to_statement)
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
- end
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
- # if(...)
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
- self.traverse {|st, parent|
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] = true
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] = true
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] = true
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, v|
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.val = var_sym
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
- self.traverse {|st, parent|
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
- self.traverse {|st, parent|
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
- self.traverse {|st, parent|
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::Prog
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
- self.traverse {|st, parent|
442
- if st.kind_of? ECMA262::StExp and parent.kind_of? ECMA262::Prog
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) ||