opal 0.10.0.beta2 → 0.10.0.beta3
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/CHANGELOG.md +9 -1
- data/lib/opal/compiler.rb +15 -9
- data/lib/opal/fragment.rb +8 -1
- data/lib/opal/nodes/args/restarg.rb +6 -1
- data/lib/opal/nodes/base.rb +1 -1
- data/lib/opal/nodes/call.rb +4 -0
- data/lib/opal/nodes/def.rb +20 -25
- data/lib/opal/nodes/hash.rb +89 -17
- data/lib/opal/nodes/iter.rb +30 -2
- data/lib/opal/nodes/logic.rb +54 -4
- data/lib/opal/nodes/node_with_args.rb +72 -0
- data/lib/opal/parser.rb +16 -0
- data/lib/opal/parser/grammar.rb +2555 -2562
- data/lib/opal/parser/grammar.y +28 -20
- data/lib/opal/parser/lexer.rb +4 -4
- data/lib/opal/regexp_anchors.rb +13 -5
- data/lib/opal/source_map.rb +2 -1
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +4 -0
- data/opal/corelib/basic_object.rb +3 -1
- data/opal/corelib/constants.rb +1 -1
- data/opal/corelib/file.rb +196 -4
- data/opal/corelib/hash.rb +7 -7
- data/opal/corelib/kernel.rb +7 -4
- data/opal/corelib/marshal.rb +31 -0
- data/opal/corelib/marshal/read_buffer.rb +427 -0
- data/opal/corelib/marshal/write_buffer.rb +383 -0
- data/opal/corelib/method.rb +8 -0
- data/opal/corelib/module.rb +21 -0
- data/opal/corelib/number.rb +19 -5
- data/opal/corelib/proc.rb +33 -6
- data/opal/corelib/range.rb +6 -0
- data/opal/corelib/regexp.rb +5 -1
- data/opal/corelib/runtime.js +69 -17
- data/opal/corelib/string.rb +8 -0
- data/opal/corelib/string/inheritance.rb +4 -0
- data/opal/corelib/struct.rb +5 -0
- data/opal/corelib/unsupported.rb +0 -18
- data/opal/opal/full.rb +1 -0
- data/spec/filters/bugs/basicobject.rb +0 -2
- data/spec/filters/bugs/compiler_opal.rb +5 -0
- data/spec/filters/bugs/enumerable.rb +1 -0
- data/spec/filters/bugs/enumerator.rb +0 -2
- data/spec/filters/bugs/exception.rb +0 -1
- data/spec/filters/bugs/kernel.rb +0 -5
- data/spec/filters/bugs/language.rb +7 -27
- data/spec/filters/bugs/marshal.rb +43 -0
- data/spec/filters/bugs/method.rb +0 -56
- data/spec/filters/bugs/module.rb +0 -1
- data/spec/filters/bugs/proc.rb +0 -46
- data/spec/filters/bugs/regexp.rb +1 -0
- data/spec/filters/bugs/unboundmethod.rb +0 -13
- data/spec/filters/unsupported/bignum.rb +5 -0
- data/spec/filters/unsupported/freeze.rb +2 -0
- data/spec/filters/unsupported/marshal.rb +46 -0
- data/spec/filters/unsupported/symbol.rb +5 -0
- data/spec/lib/compiler/call_spec.rb +29 -29
- data/spec/lib/compiler_spec.rb +7 -1
- data/spec/opal/core/kernel/instance_variables_spec.rb +40 -0
- data/spec/opal/core/language/ternary_operator_spec.rb +6 -0
- data/spec/opal/core/marshal/dump_spec.rb +53 -0
- data/spec/opal/core/marshal/load_spec.rb +7 -0
- data/spec/opal/core/source_map_spec.rb +35 -1
- data/spec/opal/javascript_api_spec.rb +16 -0
- data/spec/opal/stdlib/source_map_spec.rb +8 -0
- data/spec/ruby_specs +7 -4
- data/spec/support/match_helpers.rb +57 -0
- data/spec/support/mspec_rspec_adapter.rb +1 -1
- data/stdlib/opal-parser.rb +3 -1
- data/stdlib/pathname.rb +105 -7
- data/stdlib/racc/parser.rb +551 -138
- data/stdlib/source_map/vlq.rb +3 -2
- data/tasks/testing.rake +4 -2
- metadata +22 -2
data/opal/corelib/kernel.rb
CHANGED
@@ -178,9 +178,10 @@ module Kernel
|
|
178
178
|
|
179
179
|
def exit(status = true)
|
180
180
|
$__at_exit__ ||= []
|
181
|
-
|
181
|
+
|
182
|
+
while $__at_exit__.size > 0
|
182
183
|
block = $__at_exit__.pop
|
183
|
-
block
|
184
|
+
block.call
|
184
185
|
end
|
185
186
|
|
186
187
|
status = 0 if `status === true` # it's in JS because it can be null/undef
|
@@ -968,10 +969,12 @@ module Kernel
|
|
968
969
|
`Opal.load(#{file})`
|
969
970
|
end
|
970
971
|
|
971
|
-
def loop
|
972
|
+
def loop
|
973
|
+
return enum_for :loop unless block_given?
|
974
|
+
|
972
975
|
%x{
|
973
976
|
while (true) {
|
974
|
-
|
977
|
+
#{yield}
|
975
978
|
}
|
976
979
|
}
|
977
980
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'corelib/marshal/read_buffer'
|
2
|
+
require 'corelib/marshal/write_buffer'
|
3
|
+
|
4
|
+
module Marshal
|
5
|
+
MAJOR_VERSION = 4
|
6
|
+
MINOR_VERSION = 8
|
7
|
+
|
8
|
+
# For simulating binary strings
|
9
|
+
#
|
10
|
+
class BinaryString < String
|
11
|
+
def encoding
|
12
|
+
Encoding::BINARY
|
13
|
+
end
|
14
|
+
|
15
|
+
def +(other)
|
16
|
+
BinaryString.new(super)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class << self
|
21
|
+
def dump(object)
|
22
|
+
WriteBuffer.new(object).write
|
23
|
+
end
|
24
|
+
|
25
|
+
def load(marshaled)
|
26
|
+
ReadBuffer.new(marshaled).read
|
27
|
+
end
|
28
|
+
|
29
|
+
alias restore load
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,427 @@
|
|
1
|
+
module Marshal
|
2
|
+
class ReadBuffer
|
3
|
+
%x{
|
4
|
+
function stringToBytes(string) {
|
5
|
+
var i,
|
6
|
+
singleByte,
|
7
|
+
l = string.length,
|
8
|
+
result = [];
|
9
|
+
|
10
|
+
for (i = 0; i < l; i++) {
|
11
|
+
singleByte = string.charCodeAt(i);
|
12
|
+
result.push(singleByte);
|
13
|
+
}
|
14
|
+
return result;
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
attr_reader :version, :buffer, :index, :user_class, :extended, :object_cache, :symbols_cache
|
19
|
+
|
20
|
+
def initialize(input)
|
21
|
+
@buffer = `stringToBytes(#{input.to_s})`
|
22
|
+
@index = 0
|
23
|
+
major = read_byte
|
24
|
+
minor = read_byte
|
25
|
+
if major != MAJOR_VERSION || minor != MINOR_VERSION
|
26
|
+
raise TypeError, "incompatible marshal file format (can't be read)"
|
27
|
+
end
|
28
|
+
@version = "#{major}.#{minor}"
|
29
|
+
@object_cache = []
|
30
|
+
@symbols_cache = []
|
31
|
+
@extended = []
|
32
|
+
@ivars = []
|
33
|
+
end
|
34
|
+
|
35
|
+
def length
|
36
|
+
@buffer.length
|
37
|
+
end
|
38
|
+
|
39
|
+
def read(cache: true, ivar_index: nil)
|
40
|
+
code = read_char
|
41
|
+
# The first character indicates the type of the object
|
42
|
+
result = case code
|
43
|
+
when '0'
|
44
|
+
nil
|
45
|
+
when 'T'
|
46
|
+
true
|
47
|
+
when 'F'
|
48
|
+
false
|
49
|
+
when 'i'
|
50
|
+
read_fixnum
|
51
|
+
when 'e'
|
52
|
+
read_extended
|
53
|
+
object = read
|
54
|
+
apply_extends(object)
|
55
|
+
object
|
56
|
+
when 'C'
|
57
|
+
read_user_class
|
58
|
+
read
|
59
|
+
when 'o'
|
60
|
+
read_object
|
61
|
+
when 'd'
|
62
|
+
raise NotImplementedError, 'Data type cannot be demarshaled'
|
63
|
+
when 'u'
|
64
|
+
raise NotImplementedError, 'UserDef type cannot be demarshaled yet' # read_userdef
|
65
|
+
when 'U'
|
66
|
+
read_usrmarshal
|
67
|
+
when 'f'
|
68
|
+
read_float
|
69
|
+
when 'l'
|
70
|
+
read_bignum
|
71
|
+
when '"'
|
72
|
+
read_string(cache: cache)
|
73
|
+
when '/'
|
74
|
+
read_regexp
|
75
|
+
when '['
|
76
|
+
read_array
|
77
|
+
when '{'
|
78
|
+
read_hash
|
79
|
+
when '}'
|
80
|
+
raise NotImplementedError, 'Hashdef type cannot be demarshaled yet' # read_hashdef
|
81
|
+
when 'S'
|
82
|
+
read_struct
|
83
|
+
when 'M'
|
84
|
+
raise NotImplementedError, 'ModuleOld type cannot be demarshaled yet' # read_module_old
|
85
|
+
when 'c'
|
86
|
+
read_class
|
87
|
+
when 'm'
|
88
|
+
read_module
|
89
|
+
when ':'
|
90
|
+
read_symbol
|
91
|
+
when ';'
|
92
|
+
symbols_cache[read_fixnum]
|
93
|
+
when 'I'
|
94
|
+
ivar_index = @ivars.length
|
95
|
+
@ivars << true
|
96
|
+
object = read(cache: cache, ivar_index: ivar_index)
|
97
|
+
set_ivars(object) if @ivars.pop
|
98
|
+
object
|
99
|
+
when '@'
|
100
|
+
object_cache[read_fixnum]
|
101
|
+
else
|
102
|
+
raise ArgumentError, "dump format error"
|
103
|
+
end
|
104
|
+
result
|
105
|
+
end
|
106
|
+
|
107
|
+
def read_byte
|
108
|
+
if @index >= length
|
109
|
+
raise ArgumentError, "marshal data too short"
|
110
|
+
end
|
111
|
+
result = @buffer[@index]
|
112
|
+
@index += 1
|
113
|
+
result
|
114
|
+
end
|
115
|
+
|
116
|
+
def read_char
|
117
|
+
`String.fromCharCode(#{read_byte})`
|
118
|
+
end
|
119
|
+
|
120
|
+
def set_ivars(obj)
|
121
|
+
data = read_hash(cache: false)
|
122
|
+
|
123
|
+
data.each do |ivar, value|
|
124
|
+
case ivar
|
125
|
+
when :E then # encodings are not supported
|
126
|
+
when :encoding # encodings are not supported
|
127
|
+
else
|
128
|
+
if ivar.start_with?('@')
|
129
|
+
obj.instance_variable_set(ivar, value)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if obj.respond_to?(:marshal_load)
|
135
|
+
obj.marshal_load(data)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Reads and returns a fixnum from an input stream
|
140
|
+
#
|
141
|
+
def read_fixnum
|
142
|
+
%x{
|
143
|
+
var x, i, c = (#{read_byte} ^ 128) - 128;
|
144
|
+
if (c === 0) {
|
145
|
+
return 0;
|
146
|
+
}
|
147
|
+
|
148
|
+
if (c > 0) {
|
149
|
+
if (4 < c && c < 128) {
|
150
|
+
return c - 5;
|
151
|
+
}
|
152
|
+
x = 0;
|
153
|
+
for (i = 0; i < c; i++) {
|
154
|
+
x |= (#{read_byte} << (8*i));
|
155
|
+
}
|
156
|
+
} else {
|
157
|
+
if (-129 < c && c < -4) {
|
158
|
+
return c + 5;
|
159
|
+
}
|
160
|
+
|
161
|
+
c = -c;
|
162
|
+
x = -1;
|
163
|
+
|
164
|
+
for (i = 0; i < c; i++) {
|
165
|
+
x &= ~(0xff << (8*i));
|
166
|
+
x |= (#{read_byte} << (8*i));
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
return x;
|
171
|
+
}
|
172
|
+
end
|
173
|
+
|
174
|
+
# Reads and returns a string from an input stream
|
175
|
+
# Sometimes string shouldn't be cached using
|
176
|
+
# an internal object cache, for a:
|
177
|
+
# + class/module name
|
178
|
+
# + float
|
179
|
+
# + regexp
|
180
|
+
#
|
181
|
+
def read_string(cache: true)
|
182
|
+
length = read_fixnum
|
183
|
+
%x{
|
184
|
+
var i, result = '';
|
185
|
+
|
186
|
+
for (i = 0; i < length; i++) {
|
187
|
+
result += #{read_char};
|
188
|
+
}
|
189
|
+
|
190
|
+
if (cache) {
|
191
|
+
self.object_cache.push(result);
|
192
|
+
}
|
193
|
+
|
194
|
+
return result;
|
195
|
+
}
|
196
|
+
end
|
197
|
+
|
198
|
+
# Reads and returns a symbol from an input stream
|
199
|
+
#
|
200
|
+
def read_symbol
|
201
|
+
length = read_fixnum
|
202
|
+
%x{
|
203
|
+
var i, result = '';
|
204
|
+
|
205
|
+
for (i = 0; i < length; i++) {
|
206
|
+
result += #{read_char};
|
207
|
+
}
|
208
|
+
|
209
|
+
self.symbols_cache.push(result);
|
210
|
+
|
211
|
+
return result;
|
212
|
+
}
|
213
|
+
end
|
214
|
+
|
215
|
+
# Reads and returns an array from an input stream
|
216
|
+
#
|
217
|
+
def read_array
|
218
|
+
result = []
|
219
|
+
@object_cache << result
|
220
|
+
length = read_fixnum
|
221
|
+
%x{
|
222
|
+
if (length > 0) {
|
223
|
+
|
224
|
+
while (result.length < length) {
|
225
|
+
result.push(#{read});
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
return result;
|
230
|
+
}
|
231
|
+
end
|
232
|
+
|
233
|
+
# Reads and returns a hash from an input stream
|
234
|
+
# Sometimes hash shouldn't be cached using
|
235
|
+
# an internal object cache, for a:
|
236
|
+
# + hash of instance variables
|
237
|
+
# + hash of struct attributes
|
238
|
+
#
|
239
|
+
def read_hash(cache: true)
|
240
|
+
result = {}
|
241
|
+
|
242
|
+
if cache
|
243
|
+
@object_cache << result
|
244
|
+
end
|
245
|
+
|
246
|
+
length = read_fixnum
|
247
|
+
%x{
|
248
|
+
if (length > 0) {
|
249
|
+
var key, value, i;
|
250
|
+
for (i = 0; i < #{length}; i++) {
|
251
|
+
key = #{read};
|
252
|
+
value = #{read};
|
253
|
+
#{result[`key`] = `value`};
|
254
|
+
}
|
255
|
+
}
|
256
|
+
return result;
|
257
|
+
}
|
258
|
+
end
|
259
|
+
|
260
|
+
# Returns a constant by passed const_name,
|
261
|
+
# re-raises Marshal-specific error when it's missing
|
262
|
+
#
|
263
|
+
def safe_const_get(const_name)
|
264
|
+
begin
|
265
|
+
Object.const_get(const_name)
|
266
|
+
rescue NameError
|
267
|
+
raise ArgumentError, "undefined class/module #{const_name}"
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
# Reads and saves a user class from an input stream
|
272
|
+
# Used for cases like String/Array subclasses
|
273
|
+
#
|
274
|
+
def read_user_class
|
275
|
+
@user_class = read(cache: false)
|
276
|
+
end
|
277
|
+
|
278
|
+
# Constantizes and resets saved user class
|
279
|
+
#
|
280
|
+
def get_user_class
|
281
|
+
klass = safe_const_get(@user_class)
|
282
|
+
@user_class = nil
|
283
|
+
klass
|
284
|
+
end
|
285
|
+
|
286
|
+
# Reads and returns a Class from an input stream
|
287
|
+
#
|
288
|
+
def read_class
|
289
|
+
klass_name = read_string(cache: false)
|
290
|
+
result = safe_const_get(klass_name)
|
291
|
+
unless result.class == Class
|
292
|
+
raise ArgumentError, "#{klass_name} does not refer to a Class"
|
293
|
+
end
|
294
|
+
@object_cache << result
|
295
|
+
result
|
296
|
+
end
|
297
|
+
|
298
|
+
# Reads and returns a Module from an input stream
|
299
|
+
#
|
300
|
+
def read_module
|
301
|
+
mod_name = read_string(cache: false)
|
302
|
+
result = safe_const_get(mod_name)
|
303
|
+
unless result.class == Module
|
304
|
+
raise ArgumentError, "#{mod_name} does not refer to a Module"
|
305
|
+
end
|
306
|
+
@object_cache << result
|
307
|
+
result
|
308
|
+
end
|
309
|
+
|
310
|
+
# Reads and returns an abstract object from an input stream
|
311
|
+
#
|
312
|
+
def read_object
|
313
|
+
klass_name = read(cache: false)
|
314
|
+
klass = safe_const_get(klass_name)
|
315
|
+
result = if @ivars.last
|
316
|
+
data = read_hash(cache: false)
|
317
|
+
load_object(klass, data)
|
318
|
+
else
|
319
|
+
object = klass.allocate
|
320
|
+
set_ivars(object)
|
321
|
+
object
|
322
|
+
end
|
323
|
+
@object_cache << result
|
324
|
+
result
|
325
|
+
end
|
326
|
+
|
327
|
+
# Loads an instance of passed klass using
|
328
|
+
# default marshal hooks
|
329
|
+
#
|
330
|
+
def load_object(klass, args)
|
331
|
+
return klass._load(args) if klass.respond_to?(:_load)
|
332
|
+
instance = klass.allocate
|
333
|
+
instance.marshal_load(args) if instance.respond_to?(:marshal_load)
|
334
|
+
instance
|
335
|
+
end
|
336
|
+
|
337
|
+
# Reads and returns a Struct from an input stream
|
338
|
+
#
|
339
|
+
def read_struct
|
340
|
+
klass_name = read(cache: false)
|
341
|
+
klass = safe_const_get(klass_name)
|
342
|
+
args = read_hash(cache: false)
|
343
|
+
result = load_object(klass, args)
|
344
|
+
@object_cache << result
|
345
|
+
result
|
346
|
+
end
|
347
|
+
|
348
|
+
# Reads and saves a Module from an input stream
|
349
|
+
# that was extending marshalled object
|
350
|
+
#
|
351
|
+
def read_extended
|
352
|
+
@extended << read
|
353
|
+
end
|
354
|
+
|
355
|
+
# Applies all saved extending modules
|
356
|
+
# on the passed object
|
357
|
+
#
|
358
|
+
def apply_extends(object)
|
359
|
+
@extended.each do |e|
|
360
|
+
mod = safe_const_get(e)
|
361
|
+
object.extend(mod)
|
362
|
+
end
|
363
|
+
@extended = []
|
364
|
+
end
|
365
|
+
|
366
|
+
# Reads and returns Bignum from an input stream
|
367
|
+
#
|
368
|
+
def read_bignum
|
369
|
+
sign = read_char == '-' ? -1 : 1
|
370
|
+
size = read_fixnum * 2
|
371
|
+
result = 0
|
372
|
+
(0...size).each do |exp|
|
373
|
+
result += (read_char.ord) * 2 ** (exp * 8)
|
374
|
+
end
|
375
|
+
result = result.to_i * sign
|
376
|
+
@object_cache << result
|
377
|
+
result
|
378
|
+
end
|
379
|
+
|
380
|
+
# Reads and returns Float from an input stream
|
381
|
+
#
|
382
|
+
def read_float
|
383
|
+
s = read_string(cache: false)
|
384
|
+
result = if s == "nan"
|
385
|
+
0.0 / 0
|
386
|
+
elsif s == "inf"
|
387
|
+
1.0 / 0
|
388
|
+
elsif s == "-inf"
|
389
|
+
-1.0 / 0
|
390
|
+
else
|
391
|
+
s.to_f
|
392
|
+
end
|
393
|
+
@object_cache << result
|
394
|
+
result
|
395
|
+
end
|
396
|
+
|
397
|
+
# Reads and returns Regexp from an input stream
|
398
|
+
#
|
399
|
+
def read_regexp
|
400
|
+
args = [read_string(cache: false), read_byte]
|
401
|
+
|
402
|
+
result = if @user_class
|
403
|
+
load_object(get_user_class, args)
|
404
|
+
else
|
405
|
+
load_object(Regexp, args)
|
406
|
+
end
|
407
|
+
@object_cache << result
|
408
|
+
result
|
409
|
+
end
|
410
|
+
|
411
|
+
# Reads and returns an abstract object from an input stream
|
412
|
+
# when the class of this object has custom marshalling rules
|
413
|
+
#
|
414
|
+
def read_usrmarshal
|
415
|
+
klass_name = read
|
416
|
+
klass = safe_const_get(klass_name)
|
417
|
+
result = klass.allocate
|
418
|
+
@object_cache << result
|
419
|
+
data = read
|
420
|
+
unless result.respond_to?(:marshal_load)
|
421
|
+
raise TypeError, "instance of #{klass} needs to have method `marshal_load'"
|
422
|
+
end
|
423
|
+
result.marshal_load(data)
|
424
|
+
result
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|