opal 0.3.29 → 0.3.30
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.
- data/core/date.rb +34 -0
- data/core/hash.rb +98 -157
- data/core/json.rb +1 -2
- data/core/kernel.rb +157 -1
- data/core/load_order +2 -1
- data/core/proc.rb +3 -1
- data/core/string.rb +6 -7
- data/core/time.rb +4 -0
- data/lib/opal.rb +1 -0
- data/lib/opal/erb.rb +13 -0
- data/lib/opal/lexer.rb +9 -9
- data/lib/opal/parser.rb +22 -18
- data/lib/opal/scope.rb +1 -1
- data/lib/opal/version.rb +1 -1
- data/spec/core/date/new_spec.rb +8 -0
- data/spec/core/date/to_s_spec.rb +5 -0
- data/spec/core/date/today_spec.rb +5 -0
- data/spec/core/kernel/format_spec.rb +122 -0
- data/spec/core/kernel/method_spec.rb +31 -0
- data/spec/core/kernel/printf_spec.rb +9 -0
- data/spec/core/kernel/sprintf_spec.rb +5 -0
- data/spec/core/string/format_spec.rb +9 -0
- data/spec/grammar/begin_spec.rb +4 -0
- data/spec/grammar/call_spec.rb +22 -1
- data/spec/parser/erb_spec.rb +32 -0
- data/spec/parser/simple_spec.rb +4 -1
- data/spec/spec_helper.rb +4 -0
- metadata +23 -3
data/core/json.rb
CHANGED
@@ -38,12 +38,11 @@ module JSON
|
|
38
38
|
return arr;
|
39
39
|
}
|
40
40
|
else {
|
41
|
-
var hash = #{ {} }, v, map = hash.map
|
41
|
+
var hash = #{ {} }, v, map = hash.map;
|
42
42
|
|
43
43
|
for (var k in value) {
|
44
44
|
if (__hasOwn.call(value, k)) {
|
45
45
|
v = to_opal(value[k]);
|
46
|
-
keys.push(k);
|
47
46
|
map[k] = v;
|
48
47
|
}
|
49
48
|
}
|
data/core/kernel.rb
CHANGED
@@ -11,6 +11,23 @@ module Kernel
|
|
11
11
|
`#{self} == other`
|
12
12
|
end
|
13
13
|
|
14
|
+
def method(name)
|
15
|
+
%x{
|
16
|
+
var recv = #{self},
|
17
|
+
meth = recv['$' + name],
|
18
|
+
func = function() {
|
19
|
+
return meth.apply(recv, __slice.call(arguments, 0));
|
20
|
+
};
|
21
|
+
|
22
|
+
if (!meth) {
|
23
|
+
#{ raise NameError };
|
24
|
+
}
|
25
|
+
|
26
|
+
func._klass = #{Method};
|
27
|
+
return func;
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
14
31
|
def methods(all = true)
|
15
32
|
%x{
|
16
33
|
var methods = [];
|
@@ -83,6 +100,135 @@ module Kernel
|
|
83
100
|
}
|
84
101
|
end
|
85
102
|
|
103
|
+
def format(format, *args)
|
104
|
+
%x{
|
105
|
+
var idx = 0;
|
106
|
+
return format.replace(/%(\\d+\\$)?([-+ 0]*)(\\d*|\\*(\\d+\\$)?)(?:\\.(\\d*|\\*(\\d+\\$)?))?([cspdiubBoxXfgeEG])|(%%)/g, function(str, idx_str, flags, width_str, w_idx_str, prec_str, p_idx_str, spec, escaped) {
|
107
|
+
if (escaped) {
|
108
|
+
return '%';
|
109
|
+
}
|
110
|
+
|
111
|
+
var width,
|
112
|
+
prec,
|
113
|
+
is_integer_spec = ("diubBoxX".indexOf(spec) != -1),
|
114
|
+
is_float_spec = ("eEfgG".indexOf(spec) != -1),
|
115
|
+
prefix = '',
|
116
|
+
obj;
|
117
|
+
|
118
|
+
if (width_str === undefined) {
|
119
|
+
width = undefined;
|
120
|
+
} else if (width_str.charAt(0) == '*') {
|
121
|
+
var w_idx = idx++;
|
122
|
+
if (w_idx_str) {
|
123
|
+
w_idx = parseInt(w_idx_str, 10) - 1;
|
124
|
+
}
|
125
|
+
width = #{`args[w_idx]`.to_i};
|
126
|
+
} else {
|
127
|
+
width = parseInt(width_str, 10);
|
128
|
+
}
|
129
|
+
if (prec_str === undefined) {
|
130
|
+
prec = is_float_spec ? 6 : undefined;
|
131
|
+
} else if (prec_str.charAt(0) == '*') {
|
132
|
+
var p_idx = idx++;
|
133
|
+
if (p_idx_str) {
|
134
|
+
p_idx = parseInt(p_idx_str, 10) - 1;
|
135
|
+
}
|
136
|
+
prec = #{`args[p_idx]`.to_i};
|
137
|
+
} else {
|
138
|
+
prec = parseInt(prec_str, 10);
|
139
|
+
}
|
140
|
+
if (idx_str) {
|
141
|
+
idx = parseInt(idx_str, 10) - 1;
|
142
|
+
}
|
143
|
+
switch (spec) {
|
144
|
+
case 'c':
|
145
|
+
obj = args[idx];
|
146
|
+
if (obj._isString) {
|
147
|
+
str = obj.charAt(0);
|
148
|
+
} else {
|
149
|
+
str = String.fromCharCode(#{`obj`.to_i});
|
150
|
+
}
|
151
|
+
break;
|
152
|
+
case 's':
|
153
|
+
str = #{`args[idx]`.to_s};
|
154
|
+
if (prec !== undefined) {
|
155
|
+
str = str.substr(0, prec);
|
156
|
+
}
|
157
|
+
break;
|
158
|
+
case 'p':
|
159
|
+
str = #{`args[idx]`.inspect};
|
160
|
+
if (prec !== undefined) {
|
161
|
+
str = str.substr(0, prec);
|
162
|
+
}
|
163
|
+
break;
|
164
|
+
case 'd':
|
165
|
+
case 'i':
|
166
|
+
case 'u':
|
167
|
+
str = #{`args[idx]`.to_i}.toString();
|
168
|
+
break;
|
169
|
+
case 'b':
|
170
|
+
case 'B':
|
171
|
+
str = #{`args[idx]`.to_i}.toString(2);
|
172
|
+
break;
|
173
|
+
case 'o':
|
174
|
+
str = #{`args[idx]`.to_i}.toString(8);
|
175
|
+
break;
|
176
|
+
case 'x':
|
177
|
+
case 'X':
|
178
|
+
str = #{`args[idx]`.to_i}.toString(16);
|
179
|
+
break;
|
180
|
+
case 'e':
|
181
|
+
case 'E':
|
182
|
+
str = #{`args[idx]`.to_f}.toExponential(prec);
|
183
|
+
break;
|
184
|
+
case 'f':
|
185
|
+
str = #{`args[idx]`.to_f}.toFixed(prec);
|
186
|
+
break;
|
187
|
+
case 'g':
|
188
|
+
case 'G':
|
189
|
+
str = #{`args[idx]`.to_f}.toPrecision(prec);
|
190
|
+
break;
|
191
|
+
}
|
192
|
+
idx++;
|
193
|
+
if (is_integer_spec || is_float_spec) {
|
194
|
+
if (str.charAt(0) == '-') {
|
195
|
+
prefix = '-';
|
196
|
+
str = str.substr(1);
|
197
|
+
} else {
|
198
|
+
if (flags.indexOf('+') != -1) {
|
199
|
+
prefix = '+';
|
200
|
+
} else if (flags.indexOf(' ') != -1) {
|
201
|
+
prefix = ' ';
|
202
|
+
}
|
203
|
+
}
|
204
|
+
}
|
205
|
+
if (is_integer_spec && prec !== undefined) {
|
206
|
+
if (str.length < prec) {
|
207
|
+
str = #{'0' * `prec - str.length`} + str;
|
208
|
+
}
|
209
|
+
}
|
210
|
+
var total_len = prefix.length + str.length;
|
211
|
+
if (width !== undefined && total_len < width) {
|
212
|
+
if (flags.indexOf('-') != -1) {
|
213
|
+
str = str + #{' ' * `width - total_len`};
|
214
|
+
} else {
|
215
|
+
var pad_char = ' ';
|
216
|
+
if (flags.indexOf('0') != -1) {
|
217
|
+
str = #{'0' * `width - total_len`} + str;
|
218
|
+
} else {
|
219
|
+
prefix = #{' ' * `width - total_len`} + prefix;
|
220
|
+
}
|
221
|
+
}
|
222
|
+
}
|
223
|
+
var result = prefix + str;
|
224
|
+
if ('XEG'.indexOf(spec) != -1) {
|
225
|
+
result = result.toUpperCase();
|
226
|
+
}
|
227
|
+
return result;
|
228
|
+
});
|
229
|
+
}
|
230
|
+
end
|
231
|
+
|
86
232
|
def hash
|
87
233
|
`#{self}._id`
|
88
234
|
end
|
@@ -184,6 +330,14 @@ module Kernel
|
|
184
330
|
`#{self}._id || (#{self}._id = unique_id++)`
|
185
331
|
end
|
186
332
|
|
333
|
+
def printf(*args)
|
334
|
+
if args.length > 0
|
335
|
+
fmt = args.shift
|
336
|
+
print format(fmt, *args)
|
337
|
+
end
|
338
|
+
nil
|
339
|
+
end
|
340
|
+
|
187
341
|
def proc(&block)
|
188
342
|
%x{
|
189
343
|
if (block === nil) {
|
@@ -277,6 +431,8 @@ module Kernel
|
|
277
431
|
}
|
278
432
|
end
|
279
433
|
|
434
|
+
alias sprintf format
|
435
|
+
|
280
436
|
def tap(&block)
|
281
437
|
yield self
|
282
438
|
self
|
@@ -293,4 +449,4 @@ module Kernel
|
|
293
449
|
def to_s
|
294
450
|
`return "#<" + #{self}._klass._name + ":" + #{self}._id + ">";`
|
295
451
|
end
|
296
|
-
end
|
452
|
+
end
|
data/core/load_order
CHANGED
data/core/proc.rb
CHANGED
data/core/string.rb
CHANGED
@@ -16,12 +16,11 @@ class String < `String`
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def %(data)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
}
|
19
|
+
if data.is_a?(Array)
|
20
|
+
format(self, *data)
|
21
|
+
else
|
22
|
+
format(self, data)
|
23
|
+
end
|
25
24
|
end
|
26
25
|
|
27
26
|
def *(count)
|
@@ -517,4 +516,4 @@ class String < `String`
|
|
517
516
|
alias_native :upcase, :toUpperCase
|
518
517
|
end
|
519
518
|
|
520
|
-
Symbol = String
|
519
|
+
Symbol = String
|
data/core/time.rb
CHANGED
@@ -56,6 +56,8 @@ class Time < `Date`
|
|
56
56
|
|
57
57
|
alias_native :hour, :getHours
|
58
58
|
|
59
|
+
alias_native :inspect, :toString
|
60
|
+
|
59
61
|
alias mday day
|
60
62
|
|
61
63
|
alias_native :min, :getMinutes
|
@@ -92,6 +94,8 @@ class Time < `Date`
|
|
92
94
|
`parseInt(#{self}.getTime() / 1000)`
|
93
95
|
end
|
94
96
|
|
97
|
+
alias to_s inspect
|
98
|
+
|
95
99
|
def tuesday?
|
96
100
|
`#{self}.getDay() === 2`
|
97
101
|
end
|
data/lib/opal.rb
CHANGED
data/lib/opal/erb.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Opal
|
2
|
+
def self.parse_erb(str, name = '(erb)')
|
3
|
+
body = str.gsub('"', '\\"').gsub(/<%=([\s\S]+?)%>/) do
|
4
|
+
inner = $1.gsub(/\\'/, "'").gsub(/\\"/, '"')
|
5
|
+
"\")\nout.<<(#{ inner })\nout.<<(\""
|
6
|
+
end.gsub(/<%([\s\S]+?)%>/) do
|
7
|
+
"\")\n#{ $1 }\nout.<<(\""
|
8
|
+
end
|
9
|
+
|
10
|
+
code = "Template.new('#{name}') do\nout = []\nout.<<(\"#{ body }\")\nout.join\nend\n"
|
11
|
+
"// #{ name } (erb)\n#{ Opal.parse(code) }\n"
|
12
|
+
end
|
13
|
+
end
|
data/lib/opal/lexer.rb
CHANGED
@@ -183,13 +183,8 @@ module Opal
|
|
183
183
|
|
184
184
|
if rest
|
185
185
|
res << rest
|
186
|
-
|
187
|
-
|
188
|
-
rescue ArgumentError => e
|
189
|
-
# Rescue from empty symbol error on Ruby 1.8
|
190
|
-
raise unless e.message =~ /empty/
|
191
|
-
''
|
192
|
-
end
|
186
|
+
rest_str = rest.to_s[1..-1]
|
187
|
+
@scope.add_local rest_str.to_sym unless rest_str.empty?
|
193
188
|
end
|
194
189
|
|
195
190
|
if block
|
@@ -732,6 +727,8 @@ module Opal
|
|
732
727
|
@string_parse = { :beg => '/', :end => '/', :interpolate => true, :regexp => true }
|
733
728
|
return :REGEXP_BEG, scanner.matched
|
734
729
|
end
|
730
|
+
else
|
731
|
+
@lex_state = :expr_beg
|
735
732
|
end
|
736
733
|
|
737
734
|
return '/', '/'
|
@@ -1151,7 +1148,7 @@ module Opal
|
|
1151
1148
|
|
1152
1149
|
elsif scanner.check(/[0-9]/)
|
1153
1150
|
@lex_state = :expr_end
|
1154
|
-
if scanner.scan(/[\d_]+\.[\d_]+\b/)
|
1151
|
+
if scanner.scan(/[\d_]+\.[\d_]+\b|[\d_]+(\.[\d_]+)?[eE][-+]?[\d_]+\b/)
|
1155
1152
|
return [:FLOAT, scanner.matched.gsub(/_/, '').to_f]
|
1156
1153
|
elsif scanner.scan(/[\d_]+\b/)
|
1157
1154
|
return [:INTEGER, scanner.matched.gsub(/_/, '').to_i]
|
@@ -1276,7 +1273,10 @@ module Opal
|
|
1276
1273
|
|
1277
1274
|
when 'rescue'
|
1278
1275
|
return :IDENTIFIER, matched if [:expr_dot, :expr_fname].include? @lex_state
|
1279
|
-
|
1276
|
+
if @lex_state == :expr_beg
|
1277
|
+
@lex_state = :expr_mid
|
1278
|
+
return :RESCUE, matched
|
1279
|
+
end
|
1280
1280
|
@lex_state = :expr_beg
|
1281
1281
|
return :RESCUE_MOD, matched
|
1282
1282
|
|
data/lib/opal/parser.rb
CHANGED
@@ -179,14 +179,14 @@ module Opal
|
|
179
179
|
code = @indent + process(s(:scope, sexp), :stmt)
|
180
180
|
}
|
181
181
|
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
182
|
+
@scope.add_temp "__opal = Opal"
|
183
|
+
@scope.add_temp "self = __opal.top"
|
184
|
+
@scope.add_temp "__scope = __opal"
|
185
|
+
@scope.add_temp "nil = __opal.nil"
|
186
|
+
@scope.add_temp "def = #{current_self}._klass.prototype" if @scope.defines_defn
|
187
|
+
@helpers.keys.each { |h| @scope.add_temp "__#{h} = __opal.#{h}" }
|
188
188
|
|
189
|
-
code =
|
189
|
+
code = INDENT + @scope.to_vars + "\n" + code
|
190
190
|
end
|
191
191
|
|
192
192
|
"(function() {\n#{ code }\n})();"
|
@@ -497,15 +497,19 @@ module Opal
|
|
497
497
|
meth, recv, arg = sexp
|
498
498
|
mid = mid_to_jsid meth.to_s
|
499
499
|
|
500
|
-
|
501
|
-
with_temp do |
|
502
|
-
|
503
|
-
|
500
|
+
if @parser_uses_optimized_operators
|
501
|
+
with_temp do |a|
|
502
|
+
with_temp do |b|
|
503
|
+
l = process recv, :expr
|
504
|
+
r = process arg, :expr
|
504
505
|
|
505
|
-
|
506
|
-
|
506
|
+
"(%s = %s, %s = %s, typeof(%s) === 'number' ? %s %s %s : %s%s(%s))" %
|
507
|
+
[a, l, b, r, a, a, meth.to_s, b, a, mid, b]
|
508
|
+
end
|
507
509
|
end
|
508
510
|
end
|
511
|
+
|
512
|
+
"#{process recv, :recv}#{mid}(#{process arg, :expr})"
|
509
513
|
end
|
510
514
|
|
511
515
|
def js_block_given(sexp, level)
|
@@ -1233,7 +1237,7 @@ module Opal
|
|
1233
1237
|
map = hash_keys.map { |k| "#{k}: #{hash_obj[k]}"}
|
1234
1238
|
|
1235
1239
|
@helpers[:hash2] = true
|
1236
|
-
"__hash2(
|
1240
|
+
"__hash2({#{map.join(', ')}})"
|
1237
1241
|
else
|
1238
1242
|
@helpers[:hash] = true
|
1239
1243
|
"__hash(#{sexp.map { |p| process p, :expr }.join ', '})"
|
@@ -1871,18 +1875,18 @@ module Opal
|
|
1871
1875
|
|
1872
1876
|
def process_rescue(exp, level)
|
1873
1877
|
body = exp.first.first == :resbody ? s(:nil) : exp.shift
|
1874
|
-
body = process body, level
|
1878
|
+
body = indent { process body, level }
|
1875
1879
|
|
1876
1880
|
parts = []
|
1877
1881
|
until exp.empty?
|
1878
|
-
part = process exp.shift, level
|
1882
|
+
part = indent { process exp.shift, level }
|
1879
1883
|
part = "else " + part unless parts.empty?
|
1880
1884
|
parts << part
|
1881
1885
|
end
|
1882
1886
|
# if no rescue statement captures our error, we should rethrow
|
1883
|
-
parts << "else { throw $err; }"
|
1887
|
+
parts << indent { "else { throw $err; }" }
|
1884
1888
|
|
1885
|
-
code = "try {#@space#{body}#@space} catch ($err) {#@space#{parts.join @space}#{@space}}"
|
1889
|
+
code = "try {#@space#{INDENT}#{body}#@space} catch ($err) {#@space#{parts.join @space}#{@space}}"
|
1886
1890
|
code = "(function() { #{code} }).call(#{current_self})" if level == :expr
|
1887
1891
|
|
1888
1892
|
code
|
data/lib/opal/scope.rb
CHANGED
data/lib/opal/version.rb
CHANGED