minjs 0.3.0 → 0.4.0
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/Rakefile +7 -0
- data/exe/minjs +2 -1
- data/lib/minjs.rb +1 -5
- data/lib/minjs/compressor.rb +3 -1140
- data/lib/minjs/compressor/compressor.rb +1146 -0
- data/lib/minjs/ctype.rb +71 -28
- data/lib/minjs/ecma262.rb +9 -4
- data/lib/minjs/ecma262/base.rb +89 -8
- data/lib/minjs/ecma262/env.rb +39 -16
- data/lib/minjs/ecma262/{exp.rb → expression.rb} +988 -281
- data/lib/minjs/ecma262/{lit.rb → literal.rb} +429 -48
- data/lib/minjs/ecma262/punctuator.rb +141 -0
- data/lib/minjs/ecma262/{st.rb → statement.rb} +328 -76
- data/lib/minjs/lex.rb +8 -1009
- data/lib/minjs/{exceptions.rb → lex/exceptions.rb} +3 -1
- data/lib/minjs/lex/expression.rb +1092 -0
- data/lib/minjs/{func.rb → lex/function.rb} +43 -23
- data/lib/minjs/lex/parser.rb +1147 -0
- data/lib/minjs/lex/program.rb +56 -0
- data/lib/minjs/{statement.rb → lex/statement.rb} +136 -126
- data/lib/minjs/minjs_compressor.rb +1 -1
- data/lib/minjs/version.rb +2 -1
- data/minjs.gemspec +1 -1
- metadata +28 -11
- data/lib/minjs/ecma262/punc.rb +0 -92
- data/lib/minjs/expression.rb +0 -833
- data/lib/minjs/program.rb +0 -32
@@ -2,90 +2,145 @@
|
|
2
2
|
require 'set'
|
3
3
|
module Minjs
|
4
4
|
module ECMA262
|
5
|
+
# Base class of ECMA262 Literal
|
5
6
|
class Literal < Base
|
7
|
+
#true if literal is white space
|
6
8
|
def ws?
|
7
9
|
false
|
8
10
|
end
|
9
11
|
|
12
|
+
#true if literal is line terminator
|
10
13
|
def lt?
|
11
14
|
false
|
12
15
|
end
|
13
16
|
|
14
|
-
|
15
|
-
|
17
|
+
# Returns this node has side effect or not.
|
18
|
+
# @return [Boolean]
|
19
|
+
def side_effect?
|
20
|
+
true
|
16
21
|
end
|
17
22
|
|
23
|
+
# @return [Fixnum] expression priority
|
18
24
|
def priority
|
19
25
|
PRIORITY_PRIMARY
|
20
26
|
end
|
21
27
|
end
|
22
28
|
|
29
|
+
# Class of psedo element.
|
30
|
+
#
|
31
|
+
# This class means element is division punctuator or regular expression literal,
|
32
|
+
# but lexical parser cannot determine which of them.
|
33
|
+
#
|
23
34
|
class DivOrRegexpLiteral < Literal
|
35
|
+
# Traverses this children and itself with given block.
|
36
|
+
#
|
37
|
+
# @see Base#traverse
|
24
38
|
def traverse(parent, &block)
|
25
39
|
end
|
26
40
|
|
41
|
+
# compare object
|
27
42
|
def ==(obj)
|
28
43
|
self.class == obj.class and self.val == obj.val
|
29
44
|
end
|
30
45
|
|
31
|
-
def to_js(options = {})
|
32
|
-
"??"
|
33
|
-
end
|
34
|
-
|
35
46
|
@@instance = self.new()
|
47
|
+
|
48
|
+
# get instance
|
36
49
|
def self.get
|
37
50
|
@@instance
|
38
51
|
end
|
52
|
+
private_class_method :new
|
39
53
|
end
|
40
54
|
|
55
|
+
# DivOrRegexpLiteral
|
41
56
|
LIT_DIV_OR_REGEXP_LITERAL = DivOrRegexpLiteral.get
|
42
57
|
|
58
|
+
# Class of ECMA262 WhiteSpace element
|
59
|
+
#
|
60
|
+
# Every WhiteSpace characters in source elements is
|
61
|
+
# converted to this class object.
|
62
|
+
#
|
63
|
+
# This class is singleton and representation string is \u0020.
|
64
|
+
#
|
65
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.2
|
43
66
|
class WhiteSpace < Literal
|
67
|
+
# Traverses this children and itself with given block.
|
68
|
+
#
|
69
|
+
# @see Base#traverse
|
44
70
|
def traverse(parent, &block)
|
45
71
|
end
|
46
72
|
|
73
|
+
#true if literal is white space
|
47
74
|
def ws?
|
48
75
|
true
|
49
76
|
end
|
50
77
|
|
78
|
+
# compare object
|
51
79
|
def ==(obj)
|
52
80
|
self.class == obj.class
|
53
81
|
end
|
54
82
|
|
83
|
+
# Returns a ECMAScript string containg the representation of element.
|
84
|
+
# @see Base#to_js
|
55
85
|
def to_js(options = {})
|
56
86
|
" "
|
57
87
|
end
|
58
88
|
|
59
89
|
@@instance = self.new()
|
90
|
+
|
91
|
+
# get instance
|
60
92
|
def self.get
|
61
93
|
@@instance
|
62
94
|
end
|
95
|
+
private_class_method :new
|
63
96
|
end
|
64
97
|
|
65
|
-
|
98
|
+
# Class of ECMA262 LineTerminator element
|
99
|
+
#
|
100
|
+
# Every LineTerminator characters in source elements is
|
101
|
+
# converted to this class object.
|
102
|
+
#
|
103
|
+
# This class is singleton and representation string is \u000A.
|
104
|
+
#
|
105
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.3
|
106
|
+
class LineTerminator < Literal
|
107
|
+
# Traverses this children and itself with given block.
|
108
|
+
#
|
109
|
+
# @see Base#traverse
|
66
110
|
def traverse(parent, &block)
|
67
111
|
end
|
68
112
|
|
113
|
+
#true if literal is line terminator
|
69
114
|
def lt?
|
70
115
|
true
|
71
116
|
end
|
72
117
|
|
118
|
+
# compare object
|
73
119
|
def ==(obj)
|
74
120
|
self.class == obj.class
|
75
121
|
end
|
76
122
|
|
123
|
+
# Returns a ECMAScript string containg the representation of element.
|
124
|
+
# @see Base#to_js
|
77
125
|
def to_js(options = {})
|
78
126
|
"\n"
|
79
127
|
end
|
80
128
|
|
81
129
|
@@instance = self.new()
|
130
|
+
|
131
|
+
# get instance
|
82
132
|
def self.get
|
83
133
|
@@instance
|
84
134
|
end
|
135
|
+
private_class_method :new
|
85
136
|
end
|
86
137
|
|
87
|
-
|
138
|
+
# line feed ("\n") element
|
139
|
+
LIT_LINE_TERMINATOR = LineTerminator.get
|
88
140
|
|
141
|
+
# Class of ECMA262 'this' element
|
142
|
+
#
|
143
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 11.1.1
|
89
144
|
class This < Literal
|
90
145
|
attr_reader :context
|
91
146
|
|
@@ -93,82 +148,133 @@ module Minjs
|
|
93
148
|
@context = context
|
94
149
|
end
|
95
150
|
|
151
|
+
# duplicate object
|
152
|
+
# @see Base#deep_dup
|
96
153
|
def deep_dup
|
97
154
|
self.class.new(@context)
|
98
155
|
end
|
99
156
|
|
157
|
+
# Traverses this children and itself with given block.
|
158
|
+
#
|
159
|
+
# @see Base#traverse
|
100
160
|
def traverse(parent, &block)
|
101
|
-
yield
|
102
|
-
end
|
103
|
-
|
104
|
-
def to_s
|
105
|
-
"this"
|
161
|
+
yield parent, self
|
106
162
|
end
|
107
163
|
|
164
|
+
# compare object
|
108
165
|
def ==(obj)
|
109
166
|
self.class == obj.class
|
110
167
|
end
|
111
168
|
|
169
|
+
# Returns a ECMAScript string containg the representation of element.
|
170
|
+
# @see Base#to_js
|
112
171
|
def to_js(options = {})
|
113
172
|
"this"
|
114
173
|
end
|
115
174
|
|
175
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
116
176
|
def left_hand_side_exp?
|
117
177
|
true
|
118
178
|
end
|
119
179
|
end
|
120
180
|
|
181
|
+
# Class of ECMA262 Null element
|
182
|
+
#
|
183
|
+
# Every Null literal in source elements is
|
184
|
+
# converted to this class object.
|
185
|
+
#
|
186
|
+
# This class is singleton
|
187
|
+
#
|
188
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.8.1
|
121
189
|
class Null < Literal
|
122
190
|
def initialize(val)
|
123
191
|
@val = :null
|
124
192
|
end
|
125
193
|
|
194
|
+
# duplicate object
|
195
|
+
# @see Base#deep_dup
|
126
196
|
def deep_dup
|
127
197
|
self #not dup
|
128
198
|
end
|
129
199
|
|
200
|
+
# Traverses this children and itself with given block.
|
201
|
+
#
|
202
|
+
# @see Base#traverse
|
130
203
|
def traverse(parent, &block)
|
131
|
-
yield
|
132
|
-
end
|
133
|
-
|
134
|
-
def to_s
|
135
|
-
"null"
|
204
|
+
yield parent, self
|
136
205
|
end
|
137
206
|
|
207
|
+
# compare object
|
138
208
|
def ==(obj)
|
139
209
|
self.class == obj.class
|
140
210
|
end
|
141
211
|
|
212
|
+
# Returns a ECMAScript string containg the representation of element.
|
213
|
+
# @see Base#to_js
|
142
214
|
def to_js(options = {})
|
143
215
|
"null"
|
144
216
|
end
|
145
217
|
|
218
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
146
219
|
def left_hand_side_exp?
|
147
220
|
true
|
148
221
|
end
|
149
222
|
|
150
223
|
@@instance = self.new(nil)
|
224
|
+
|
225
|
+
# get instance
|
151
226
|
def self.get
|
152
227
|
@@instance
|
153
228
|
end
|
154
229
|
|
230
|
+
# Returns results of ToBoolean()
|
231
|
+
#
|
232
|
+
# Returns _true_ or _false_ if trivial,
|
233
|
+
# otherwise nil.
|
234
|
+
#
|
235
|
+
# @return [Boolean]
|
236
|
+
#
|
237
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.2
|
155
238
|
def to_ecma262_boolean
|
156
239
|
false
|
157
240
|
end
|
158
241
|
|
242
|
+
# Returns results of ToString()
|
243
|
+
#
|
244
|
+
# Returns string if value is trivial,
|
245
|
+
# otherwise nil.
|
246
|
+
#
|
247
|
+
# @return [Numeric]
|
248
|
+
#
|
249
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.8
|
159
250
|
def to_ecma262_string
|
160
251
|
"null"
|
161
252
|
end
|
162
253
|
|
254
|
+
# Returns results of ToNumber()
|
255
|
+
#
|
256
|
+
# Returns number if value is trivial,
|
257
|
+
# otherwise nil.
|
258
|
+
#
|
259
|
+
# @return [Numeric]
|
260
|
+
#
|
261
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.3
|
163
262
|
def to_ecma262_number
|
164
263
|
0
|
165
264
|
end
|
166
265
|
|
266
|
+
# return results of 'typeof' operator.
|
267
|
+
#
|
268
|
+
# @return [Symbol] :boolean
|
167
269
|
def ecma262_typeof
|
168
270
|
:boolean
|
169
271
|
end
|
272
|
+
private_class_method :new
|
170
273
|
end
|
171
274
|
|
275
|
+
# Class of ECMA262 Boolean element
|
276
|
+
#
|
277
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.8.2
|
172
278
|
class Boolean < Literal
|
173
279
|
attr_reader :val
|
174
280
|
|
@@ -180,23 +286,32 @@ module Minjs
|
|
180
286
|
end
|
181
287
|
end
|
182
288
|
|
289
|
+
# duplicate object
|
290
|
+
# @see Base#deep_dup
|
183
291
|
def deep_dup
|
184
292
|
self #//not dup
|
185
293
|
end
|
186
294
|
|
295
|
+
# Traverses this children and itself with given block.
|
296
|
+
#
|
297
|
+
# @see Base#traverse
|
187
298
|
def traverse(parent, &block)
|
188
|
-
yield
|
299
|
+
yield parent, self
|
189
300
|
end
|
190
301
|
|
302
|
+
# compare object
|
191
303
|
def ==(obj)
|
192
304
|
self.class == obj.class and
|
193
305
|
@val == obj.val
|
194
306
|
end
|
195
307
|
|
308
|
+
# Returns a ECMAScript string containg the representation of element.
|
309
|
+
# @see Base#to_js
|
196
310
|
def to_js(options = {})
|
197
311
|
@val.to_s
|
198
312
|
end
|
199
313
|
|
314
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
200
315
|
def left_hand_side_exp?
|
201
316
|
true
|
202
317
|
end
|
@@ -205,6 +320,14 @@ module Minjs
|
|
205
320
|
@val == :true
|
206
321
|
end
|
207
322
|
|
323
|
+
# Returns results of ToString()
|
324
|
+
#
|
325
|
+
# Returns string if value is trivial,
|
326
|
+
# otherwise nil.
|
327
|
+
#
|
328
|
+
# @return [Numeric]
|
329
|
+
#
|
330
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.8
|
208
331
|
def to_ecma262_string
|
209
332
|
if @val == :false
|
210
333
|
"false"
|
@@ -213,6 +336,14 @@ module Minjs
|
|
213
336
|
end
|
214
337
|
end
|
215
338
|
|
339
|
+
# Returns results of ToBoolean()
|
340
|
+
#
|
341
|
+
# Returns _true_ or _false_ if trivial,
|
342
|
+
# otherwise nil.
|
343
|
+
#
|
344
|
+
# @return [Boolean]
|
345
|
+
#
|
346
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.2
|
216
347
|
def to_ecma262_boolean
|
217
348
|
if @val == :false
|
218
349
|
false
|
@@ -221,6 +352,14 @@ module Minjs
|
|
221
352
|
end
|
222
353
|
end
|
223
354
|
|
355
|
+
# Returns results of ToNumber()
|
356
|
+
#
|
357
|
+
# Returns number if value is trivial,
|
358
|
+
# otherwise nil.
|
359
|
+
#
|
360
|
+
# @return [Numeric]
|
361
|
+
#
|
362
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.3
|
224
363
|
def to_ecma262_number
|
225
364
|
if @val == :false
|
226
365
|
0
|
@@ -229,12 +368,17 @@ module Minjs
|
|
229
368
|
end
|
230
369
|
end
|
231
370
|
|
371
|
+
# return results of 'typeof' operator.
|
372
|
+
#
|
373
|
+
# @return [Symbol] :boolean
|
232
374
|
def ecma262_typeof
|
233
375
|
:boolean
|
234
376
|
end
|
235
377
|
|
236
378
|
@@true = self.new(:true)
|
237
379
|
@@false = self.new(:false)
|
380
|
+
|
381
|
+
# get instance
|
238
382
|
def self.get(val)
|
239
383
|
if val.to_sym == :true || val == true
|
240
384
|
@@true
|
@@ -243,7 +387,17 @@ module Minjs
|
|
243
387
|
end
|
244
388
|
end
|
245
389
|
end
|
390
|
+
# *true* literal
|
391
|
+
LITERAL_TRUE = Boolean.new(:true)
|
392
|
+
# *false* literal
|
393
|
+
LITERAL_FALSE = Boolean.new(:false)
|
394
|
+
Boolean.class_eval {
|
395
|
+
private_class_method :new
|
396
|
+
}
|
246
397
|
|
398
|
+
# Class of ECMA262 String element
|
399
|
+
#
|
400
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.8.4
|
247
401
|
class ECMA262String < Literal
|
248
402
|
include Ctype
|
249
403
|
attr_reader :val
|
@@ -252,18 +406,26 @@ module Minjs
|
|
252
406
|
@val = val
|
253
407
|
end
|
254
408
|
|
409
|
+
# duplicate object
|
410
|
+
# @see Base#deep_dup
|
255
411
|
def deep_dup
|
256
412
|
self.class.new(@val)
|
257
413
|
end
|
258
414
|
|
415
|
+
# Traverses this children and itself with given block.
|
416
|
+
#
|
417
|
+
# @see Base#traverse
|
259
418
|
def traverse(parent)
|
260
|
-
yield
|
419
|
+
yield parent, self
|
261
420
|
end
|
262
421
|
|
422
|
+
# compare object
|
263
423
|
def ==(obj)
|
264
424
|
self.class == obj.class and @val == obj.val
|
265
425
|
end
|
266
426
|
|
427
|
+
# Returns a ECMAScript string containg the representation of element.
|
428
|
+
# @see Base#to_js
|
267
429
|
def to_js(options = {})
|
268
430
|
dq = @val.to_s.each_codepoint.select{|x| x == 0x22}.length
|
269
431
|
sq = @val.to_s.each_codepoint.select{|x| x == 0x27}.length
|
@@ -309,10 +471,19 @@ module Minjs
|
|
309
471
|
end
|
310
472
|
end
|
311
473
|
|
474
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
312
475
|
def left_hand_side_exp?
|
313
476
|
true
|
314
477
|
end
|
315
478
|
|
479
|
+
# Returns results of ToBoolean()
|
480
|
+
#
|
481
|
+
# Returns _true_ or _false_ if trivial,
|
482
|
+
# otherwise nil.
|
483
|
+
#
|
484
|
+
# @return [Boolean]
|
485
|
+
#
|
486
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.2
|
316
487
|
def to_ecma262_boolean
|
317
488
|
if @val.length == 0
|
318
489
|
false
|
@@ -321,10 +492,25 @@ module Minjs
|
|
321
492
|
end
|
322
493
|
end
|
323
494
|
|
495
|
+
# Returns results of ToString()
|
496
|
+
#
|
497
|
+
# Returns string if value is trivial,
|
498
|
+
# otherwise nil.
|
499
|
+
#
|
500
|
+
# @return [Numeric]
|
501
|
+
#
|
502
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.8
|
324
503
|
def to_ecma262_string
|
325
504
|
@val.dup
|
326
505
|
end
|
327
|
-
#
|
506
|
+
# Returns results of ToNumber()
|
507
|
+
#
|
508
|
+
# Returns number if value is trivial,
|
509
|
+
# otherwise nil.
|
510
|
+
#
|
511
|
+
# @return [Numeric]
|
512
|
+
#
|
513
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.3
|
328
514
|
def to_ecma262_number
|
329
515
|
begin
|
330
516
|
pos1 = pos0 = pos = 0
|
@@ -425,13 +611,21 @@ module Minjs
|
|
425
611
|
ret
|
426
612
|
end
|
427
613
|
|
614
|
+
# return results of 'typeof' operator.
|
615
|
+
#
|
616
|
+
# @return [Symbol] :string
|
428
617
|
def ecma262_typeof
|
429
618
|
:string
|
430
619
|
end
|
620
|
+
|
621
|
+
# Returns this node has side effect or not.
|
622
|
+
# @return [Boolean]
|
623
|
+
def side_effect?
|
624
|
+
return false
|
625
|
+
end
|
431
626
|
end
|
432
627
|
|
433
|
-
#
|
434
|
-
# 8.5 The Number Type
|
628
|
+
# Class of ECMA262 Numeric element
|
435
629
|
#
|
436
630
|
# ECMA262 say:
|
437
631
|
#
|
@@ -444,6 +638,7 @@ module Minjs
|
|
444
638
|
# To simplify the implementation,
|
445
639
|
# Minjs assumes that ruby has IEEE754 dobule precision.
|
446
640
|
#
|
641
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.8.3
|
447
642
|
class ECMA262Numeric < Literal
|
448
643
|
attr_reader :integer, :decimal, :exp, :number
|
449
644
|
|
@@ -522,18 +717,26 @@ module Minjs
|
|
522
717
|
end
|
523
718
|
end
|
524
719
|
|
720
|
+
# duplicate object
|
721
|
+
# @see Base#deep_dup
|
525
722
|
def deep_dup
|
526
723
|
self.class.new(@number)
|
527
724
|
end
|
528
725
|
|
726
|
+
# Traverses this children and itself with given block.
|
727
|
+
#
|
728
|
+
# @see Base#traverse
|
529
729
|
def traverse(parent, &block)
|
530
|
-
yield
|
730
|
+
yield parent, self
|
531
731
|
end
|
532
732
|
|
733
|
+
# compare object
|
533
734
|
def ==(obj)
|
534
735
|
self.class == obj.class and self.to_ecma262_string == obj.to_ecma262_string
|
535
736
|
end
|
536
737
|
|
738
|
+
# Returns a ECMAScript string containg the representation of element.
|
739
|
+
# @see Base#to_js
|
537
740
|
def to_js(options = {})
|
538
741
|
if nan?
|
539
742
|
return "NaN"
|
@@ -572,33 +775,44 @@ module Minjs
|
|
572
775
|
t.length <= t0.length ? t : t0
|
573
776
|
end
|
574
777
|
|
778
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
575
779
|
def left_hand_side_exp?
|
576
780
|
true
|
577
781
|
end
|
578
782
|
|
783
|
+
# to integer
|
579
784
|
def to_i
|
580
785
|
to_ecma262_string.to_i
|
581
786
|
end
|
582
787
|
|
788
|
+
# to float
|
583
789
|
def to_f
|
584
790
|
to_ecma262_string.to_f
|
585
791
|
end
|
586
792
|
|
793
|
+
# True if number is NaN
|
587
794
|
def nan?
|
588
795
|
@number.kind_of? Float and @number.nan?
|
589
796
|
end
|
590
797
|
|
798
|
+
# True if number is Infinity
|
591
799
|
def infinity?
|
592
800
|
@number == Float::INFINITY || @number == -Float::INFINITY
|
593
801
|
end
|
594
802
|
|
803
|
+
# True if number not Infinity nor NaN
|
595
804
|
def number?
|
596
805
|
!nan? and !infinity?
|
597
806
|
end
|
598
807
|
|
808
|
+
# Returns results of ToString()
|
599
809
|
#
|
600
|
-
#
|
810
|
+
# Returns string if value is trivial,
|
811
|
+
# otherwise nil.
|
601
812
|
#
|
813
|
+
# @return [Numeric]
|
814
|
+
#
|
815
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.8
|
602
816
|
def to_ecma262_string
|
603
817
|
if nan?
|
604
818
|
"NaN"
|
@@ -637,6 +851,14 @@ module Minjs
|
|
637
851
|
end
|
638
852
|
end
|
639
853
|
|
854
|
+
# Returns results of ToBoolean()
|
855
|
+
#
|
856
|
+
# Returns _true_ or _false_ if value is trivial,
|
857
|
+
# otherwise nil.
|
858
|
+
#
|
859
|
+
# @return [Boolean]
|
860
|
+
#
|
861
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.2
|
640
862
|
def to_ecma262_boolean
|
641
863
|
if @val == :nan or to_ecma262_string == "0"
|
642
864
|
false
|
@@ -645,6 +867,20 @@ module Minjs
|
|
645
867
|
end
|
646
868
|
end
|
647
869
|
|
870
|
+
# Returns this node has side effect or not.
|
871
|
+
# @return [Boolean]
|
872
|
+
def side_effect?
|
873
|
+
return false
|
874
|
+
end
|
875
|
+
|
876
|
+
# Returns results of ToNumber()
|
877
|
+
#
|
878
|
+
# Returns number if value is trivial,
|
879
|
+
# otherwise nil.
|
880
|
+
#
|
881
|
+
# @return [Numeric]
|
882
|
+
#
|
883
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.3
|
648
884
|
def to_ecma262_number
|
649
885
|
if nan?
|
650
886
|
nil
|
@@ -657,21 +893,29 @@ module Minjs
|
|
657
893
|
end
|
658
894
|
end
|
659
895
|
|
896
|
+
# return results of 'typeof' operator.
|
897
|
+
#
|
898
|
+
# @return [Symbol] :number
|
660
899
|
def ecma262_typeof
|
661
900
|
:number
|
662
901
|
end
|
663
902
|
|
664
|
-
def ecma262_eval(type)
|
665
|
-
case type
|
666
|
-
when :boolean
|
667
|
-
to_ecma262_boolean
|
668
|
-
else
|
669
|
-
nil
|
670
|
-
end
|
671
|
-
end
|
903
|
+
# def ecma262_eval(type)
|
904
|
+
# case type
|
905
|
+
# when :boolean
|
906
|
+
# to_ecma262_boolean
|
907
|
+
# else
|
908
|
+
# nil
|
909
|
+
# end
|
910
|
+
# end
|
672
911
|
end
|
912
|
+
|
913
|
+
#NaN element
|
673
914
|
NUMERIC_NAN = ECMA262Numeric.new(:nan)
|
674
915
|
|
916
|
+
# Class of ECMA262 RegExp element
|
917
|
+
#
|
918
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.8.5
|
675
919
|
class ECMA262RegExp < Literal
|
676
920
|
attr_reader :body, :flags
|
677
921
|
|
@@ -680,34 +924,51 @@ module Minjs
|
|
680
924
|
@flags = flags
|
681
925
|
end
|
682
926
|
|
927
|
+
# duplicate object
|
928
|
+
# @see Base#deep_dup
|
683
929
|
def deep_dup
|
684
930
|
self.class.new(@body, @flags)
|
685
931
|
end
|
686
932
|
|
933
|
+
# Traverses this children and itself with given block.
|
934
|
+
#
|
935
|
+
# @see Base#traverse
|
687
936
|
def traverse(parent)
|
688
|
-
yield
|
937
|
+
yield parent, self
|
689
938
|
end
|
690
939
|
|
940
|
+
# Returns results of ToBoolean()
|
941
|
+
#
|
942
|
+
# Returns _true_ or _false_ if trivial,
|
943
|
+
# otherwise nil.
|
944
|
+
#
|
945
|
+
# @return [Boolean]
|
946
|
+
#
|
947
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.2
|
691
948
|
def to_ecma262_boolean
|
692
949
|
true
|
693
950
|
end
|
694
951
|
|
952
|
+
# compare object
|
695
953
|
def ==(obj)
|
696
954
|
self.class == obj.class and @body == obj.body and @flags == obj.flags
|
697
955
|
end
|
698
956
|
|
957
|
+
# Returns a ECMAScript string containg the representation of element.
|
958
|
+
# @see Base#to_js
|
699
959
|
def to_js(options = {})
|
700
960
|
"/#{@body}/#{@flags}"
|
701
961
|
end
|
702
962
|
|
963
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
703
964
|
def left_hand_side_exp?
|
704
965
|
true
|
705
966
|
end
|
706
967
|
end
|
707
968
|
|
708
|
-
|
709
|
-
|
710
|
-
|
969
|
+
# Class of ECMA262 Array element
|
970
|
+
#
|
971
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 11.1.4
|
711
972
|
class ECMA262Array < Literal
|
712
973
|
attr_reader :val
|
713
974
|
|
@@ -715,34 +976,54 @@ module Minjs
|
|
715
976
|
@val = val # val is Array
|
716
977
|
end
|
717
978
|
|
979
|
+
# duplicate object
|
980
|
+
# @see Base#deep_dup
|
718
981
|
def deep_dup
|
719
982
|
self.class.new(@val.collect{|x| x ? x.deep_dup : nil})
|
720
983
|
end
|
721
984
|
|
985
|
+
# Traverses this children and itself with given block.
|
986
|
+
#
|
987
|
+
# @see Base#traverse
|
722
988
|
def traverse(parent, &block)
|
723
|
-
yield
|
989
|
+
yield parent, self
|
724
990
|
@val.each do |k|
|
725
991
|
k.traverse(parent, &block) if k
|
726
992
|
end
|
727
993
|
end
|
728
994
|
|
995
|
+
# compare object
|
729
996
|
def ==(obj)
|
730
997
|
self.class == obj.class and @val == obj.val
|
731
998
|
end
|
732
999
|
|
1000
|
+
# Returns a ECMAScript string containg the representation of element.
|
1001
|
+
# @see Base#to_js
|
733
1002
|
def to_js(options = {})
|
734
1003
|
"[" + @val.collect{|x| x.to_s}.join(",") + "]"
|
735
1004
|
end
|
736
1005
|
|
1006
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
737
1007
|
def left_hand_side_exp?
|
738
1008
|
true
|
739
1009
|
end
|
740
1010
|
|
1011
|
+
# Returns results of ToBoolean()
|
1012
|
+
#
|
1013
|
+
# Returns _true_ or _false_ if trivial,
|
1014
|
+
# otherwise nil.
|
1015
|
+
#
|
1016
|
+
# @return [Boolean]
|
1017
|
+
#
|
1018
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.2
|
741
1019
|
def to_ecma262_boolean
|
742
1020
|
true
|
743
1021
|
end
|
744
1022
|
end
|
745
1023
|
|
1024
|
+
# Class of ECMA262 Array element
|
1025
|
+
#
|
1026
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 11.1.5
|
746
1027
|
class ECMA262Object < Literal
|
747
1028
|
include Ctype
|
748
1029
|
attr_reader :val
|
@@ -752,22 +1033,30 @@ module Minjs
|
|
752
1033
|
@val = val
|
753
1034
|
end
|
754
1035
|
|
1036
|
+
# duplicate object
|
1037
|
+
# @see Base#deep_dup
|
755
1038
|
def deep_dup
|
756
1039
|
self.class.new(@val.collect{|x, y| [x.deep_dup, y ? y.deep_dup : y]})
|
757
1040
|
end
|
758
1041
|
|
1042
|
+
# Traverses this children and itself with given block.
|
1043
|
+
#
|
1044
|
+
# @see Base#traverse
|
759
1045
|
def traverse(parent, &block)
|
760
|
-
yield
|
1046
|
+
yield parent, self
|
761
1047
|
@val.each do |k, v|
|
762
1048
|
k.traverse(parent, &block)
|
763
1049
|
v.traverse(parent, &block)
|
764
1050
|
end
|
765
1051
|
end
|
766
1052
|
|
1053
|
+
# compare object
|
767
1054
|
def ==(obj)
|
768
1055
|
self.class == obj.class and @val == obj.val
|
769
1056
|
end
|
770
1057
|
|
1058
|
+
# Returns a ECMAScript string containg the representation of element.
|
1059
|
+
# @see Base#to_js
|
771
1060
|
def to_js(options = {})
|
772
1061
|
concat(options, "{" + @val.collect{|x, y|
|
773
1062
|
if y.kind_of? StFunc and (y.getter? || y.setter?)
|
@@ -788,37 +1077,59 @@ module Minjs
|
|
788
1077
|
}.join(","), "}")
|
789
1078
|
end
|
790
1079
|
|
1080
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
791
1081
|
def left_hand_side_exp?
|
792
1082
|
true
|
793
1083
|
end
|
794
1084
|
|
1085
|
+
# Returns results of ToBoolean()
|
1086
|
+
#
|
1087
|
+
# Returns _true_ or _false_ if trivial,
|
1088
|
+
# otherwise nil.
|
1089
|
+
#
|
1090
|
+
# @return [Boolean]
|
1091
|
+
#
|
1092
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 9.2
|
795
1093
|
def to_ecma262_boolean
|
796
1094
|
true
|
797
1095
|
end
|
798
1096
|
end
|
799
1097
|
|
1098
|
+
# Class of ECMA262 SingleLineComment Element
|
1099
|
+
#
|
1100
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.4
|
800
1101
|
class SingleLineComment < Literal
|
801
1102
|
def initialize(comment)
|
802
1103
|
@comment = comment
|
803
1104
|
end
|
804
1105
|
|
1106
|
+
# Traverses this children and itself with given block.
|
1107
|
+
#
|
1108
|
+
# @see Base#traverse
|
805
1109
|
def traverse(parent, &block)
|
806
1110
|
end
|
807
1111
|
|
1112
|
+
# compare object
|
808
1113
|
def ==(obj)
|
809
1114
|
self.class == obj.class and
|
810
1115
|
@comment == obj.comment
|
811
1116
|
end
|
812
1117
|
|
1118
|
+
# Returns a ECMAScript string containg the representation of element.
|
1119
|
+
# @see Base#to_js
|
813
1120
|
def to_js(options)
|
814
1121
|
"//#{@comment}"
|
815
1122
|
end
|
816
1123
|
|
1124
|
+
#true if literal is white space
|
817
1125
|
def ws?
|
818
1126
|
true
|
819
1127
|
end
|
820
1128
|
end
|
821
1129
|
|
1130
|
+
# Class of ECMA262 MultiLineComment Element
|
1131
|
+
#
|
1132
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.4
|
822
1133
|
class MultiLineComment < Literal
|
823
1134
|
attr_reader :comment, :has_lf
|
824
1135
|
include Ctype
|
@@ -827,21 +1138,33 @@ module Minjs
|
|
827
1138
|
@comment = comment
|
828
1139
|
end
|
829
1140
|
|
1141
|
+
# Traverses this children and itself with given block.
|
1142
|
+
#
|
1143
|
+
# @see Base#traverse
|
830
1144
|
def traverse(parent, &block)
|
831
1145
|
end
|
832
1146
|
|
1147
|
+
# compare object
|
833
1148
|
def ==(obj)
|
834
1149
|
self.class == obj.class and @comment == obj.comment
|
835
1150
|
end
|
836
1151
|
|
1152
|
+
# Returns a ECMAScript string containg the representation of element.
|
1153
|
+
# @see Base#to_js
|
837
1154
|
def to_js(options)
|
838
1155
|
"/*#{@comment}*/"
|
839
1156
|
end
|
840
1157
|
|
1158
|
+
#true if literal is white space
|
841
1159
|
def ws?
|
842
1160
|
!lt?
|
843
1161
|
end
|
844
1162
|
|
1163
|
+
#true if literal is line terminator
|
1164
|
+
#
|
1165
|
+
# If MultiLineComment has one more LineTerminator,
|
1166
|
+
# This comment is kind of line terminator.
|
1167
|
+
# otherwise, this comment is kind of white space.
|
845
1168
|
def lt?
|
846
1169
|
@comment.codepoints.each{|char|
|
847
1170
|
return true if line_terminator?(char)
|
@@ -850,6 +1173,9 @@ module Minjs
|
|
850
1173
|
end
|
851
1174
|
end
|
852
1175
|
|
1176
|
+
# Class of ECMA262 IdentifierName Element
|
1177
|
+
#
|
1178
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.6
|
853
1179
|
class IdentifierName < Literal
|
854
1180
|
attr_accessor :context
|
855
1181
|
attr_reader :val
|
@@ -861,6 +1187,7 @@ module Minjs
|
|
861
1187
|
@val = val.to_sym
|
862
1188
|
end
|
863
1189
|
|
1190
|
+
# get instance
|
864
1191
|
def self.get(context, val)
|
865
1192
|
if reserved?(val)
|
866
1193
|
@@sym[val] ||= self.new(context, val)
|
@@ -869,44 +1196,68 @@ module Minjs
|
|
869
1196
|
end
|
870
1197
|
end
|
871
1198
|
|
1199
|
+
# reserved word list
|
1200
|
+
#
|
1201
|
+
# @see http://www.ecma-international.org/ecma-262 ECMA262 7.6.1
|
872
1202
|
RESERVED_WORD = Set.new [
|
873
|
-
|
874
|
-
:
|
875
|
-
:
|
876
|
-
:
|
877
|
-
:
|
878
|
-
:
|
879
|
-
:
|
1203
|
+
#keywords
|
1204
|
+
:break, :do, :instanceof, :typeof,
|
1205
|
+
:case, :else, :new, :var,
|
1206
|
+
:catch, :finally, :return, :void,
|
1207
|
+
:continue, :for, :switch, :while,
|
1208
|
+
:debugger, :function, :this, :with,
|
1209
|
+
:default, :if, :throw,
|
1210
|
+
:delete, :in, :try,
|
1211
|
+
#future reserved words
|
1212
|
+
:class, :enum, :extends, :super,
|
1213
|
+
:const, :export, :import,
|
1214
|
+
#future reserved words(strict mode) (TODO)
|
1215
|
+
#:implements, :let, :private, :public, :yield,
|
1216
|
+
#:interface, :package, :protected, :static,
|
880
1217
|
:null, :false, :true
|
881
1218
|
]
|
1219
|
+
|
1220
|
+
# Returns true if this literal is reserved word.
|
882
1221
|
def reserved?
|
883
1222
|
RESERVED_WORD.include?(val)
|
884
1223
|
end
|
885
1224
|
|
1225
|
+
# Returns true if *val* is reserved word.
|
1226
|
+
# @param val [String] value
|
886
1227
|
def self.reserved?(val)
|
887
1228
|
RESERVED_WORD.include?(val)
|
888
1229
|
end
|
889
1230
|
|
1231
|
+
# Traverses this children and itself with given block.
|
1232
|
+
#
|
1233
|
+
# @see Base#traverse
|
890
1234
|
def traverse(parent)
|
891
|
-
yield
|
1235
|
+
yield parent, self
|
892
1236
|
end
|
893
1237
|
|
1238
|
+
# duplicate object
|
1239
|
+
# @see Base#deep_dup
|
894
1240
|
def deep_dup
|
895
1241
|
self.class.new(@context, @val)
|
896
1242
|
end
|
897
1243
|
|
1244
|
+
# compare object
|
898
1245
|
def ==(obj)
|
899
1246
|
self.class == obj.class and self.val == obj.val
|
900
1247
|
end
|
901
1248
|
|
1249
|
+
# Returns a ECMAScript string containg the representation of element.
|
1250
|
+
# @see Base#to_js
|
902
1251
|
def to_js(options = {})
|
903
1252
|
val.to_s
|
904
1253
|
end
|
905
1254
|
|
1255
|
+
# @return [Boolean] true if expression is kind of LeftHandSideExpression.
|
906
1256
|
def left_hand_side_exp?
|
907
1257
|
true
|
908
1258
|
end
|
909
1259
|
|
1260
|
+
# @return [EnvRecord] binding environment
|
910
1261
|
def binding_env(type = :var)
|
911
1262
|
return nil if context.nil?
|
912
1263
|
if type == :var
|
@@ -926,37 +1277,67 @@ module Minjs
|
|
926
1277
|
end
|
927
1278
|
end
|
928
1279
|
|
1280
|
+
# reserved word "this"
|
929
1281
|
ID_THIS = IdentifierName.get(nil, :this)
|
1282
|
+
# reserved word "var"
|
930
1283
|
ID_VAR = IdentifierName.get(nil, :var)
|
1284
|
+
# reserved word "in"
|
931
1285
|
ID_IN = IdentifierName.get(nil, :in)
|
1286
|
+
# reserved word "instanceof"
|
932
1287
|
ID_INSTANCEOF = IdentifierName.get(nil, :instanceof)
|
1288
|
+
# reserved word "function"
|
933
1289
|
ID_FUNCTION = IdentifierName.get(nil, :function)
|
1290
|
+
# reserved word "null"
|
934
1291
|
ID_NULL = IdentifierName.get(nil, :null)
|
1292
|
+
# reserved word "true"
|
935
1293
|
ID_TRUE = IdentifierName.get(nil, :true)
|
1294
|
+
# reserved word "false"
|
936
1295
|
ID_FALSE = IdentifierName.get(nil, :false)
|
1296
|
+
# reserved word "new"
|
937
1297
|
ID_NEW = IdentifierName.get(nil, :new)
|
1298
|
+
# reserved word "delete"
|
938
1299
|
ID_DELETE = IdentifierName.get(nil, :delete)
|
1300
|
+
# reserved word "void"
|
939
1301
|
ID_VOID = IdentifierName.get(nil, :void)
|
1302
|
+
# reserved word "typeof"
|
940
1303
|
ID_TYPEOF = IdentifierName.get(nil, :typeof)
|
1304
|
+
# reserved word "if"
|
941
1305
|
ID_IF = IdentifierName.get(nil, :if)
|
1306
|
+
# reserved word "else"
|
942
1307
|
ID_ELSE = IdentifierName.get(nil, :else)
|
1308
|
+
# reserved word "for"
|
943
1309
|
ID_FOR = IdentifierName.get(nil, :for)
|
1310
|
+
# reserved word "while"
|
944
1311
|
ID_WHILE = IdentifierName.get(nil, :while)
|
1312
|
+
# reserved word "do"
|
945
1313
|
ID_DO = IdentifierName.get(nil, :do)
|
1314
|
+
# reserved word "continue"
|
946
1315
|
ID_CONTINUE = IdentifierName.get(nil, :continue)
|
1316
|
+
# reserved word "break"
|
947
1317
|
ID_BREAK = IdentifierName.get(nil, :break)
|
1318
|
+
# reserved word "return"
|
948
1319
|
ID_RETURN = IdentifierName.get(nil, :return)
|
1320
|
+
# reserved word "with"
|
949
1321
|
ID_WITH = IdentifierName.get(nil, :with)
|
1322
|
+
# reserved word "switch"
|
950
1323
|
ID_SWITCH = IdentifierName.get(nil, :switch)
|
1324
|
+
# reserved word "throw"
|
951
1325
|
ID_THROW = IdentifierName.get(nil, :throw)
|
1326
|
+
# reserved word "try"
|
952
1327
|
ID_TRY = IdentifierName.get(nil, :try)
|
1328
|
+
# reserved word "catch"
|
953
1329
|
ID_CATCH = IdentifierName.get(nil, :catch)
|
1330
|
+
# reserved word "finally"
|
954
1331
|
ID_FINALLY = IdentifierName.get(nil, :finally)
|
1332
|
+
# reserved word "debugger"
|
955
1333
|
ID_DEBUGGER = IdentifierName.get(nil, :debugger)
|
1334
|
+
# reserved word "case"
|
956
1335
|
ID_CASE = IdentifierName.get(nil, :case)
|
1336
|
+
# reserved word "default"
|
957
1337
|
ID_DEFAULT = IdentifierName.get(nil, :default)
|
958
|
-
#
|
1338
|
+
# get (non-reserved word)
|
959
1339
|
ID_GET = IdentifierName.get(nil, :get)
|
1340
|
+
# set (non-reserved word)
|
960
1341
|
ID_SET = IdentifierName.get(nil, :set)
|
961
1342
|
|
962
1343
|
end
|