opal 0.5.2 → 0.5.4
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/README.md +2 -0
- data/lib/opal.rb +0 -5
- data/lib/opal/compiler.rb +24 -44
- data/lib/opal/nodes/base.rb +5 -8
- data/lib/opal/nodes/call.rb +4 -0
- data/lib/opal/nodes/class.rb +6 -7
- data/lib/opal/nodes/def.rb +4 -4
- data/lib/opal/nodes/definitions.rb +0 -14
- data/lib/opal/nodes/iter.rb +51 -38
- data/lib/opal/nodes/literal.rb +21 -24
- data/lib/opal/nodes/module.rb +4 -4
- data/lib/opal/nodes/runtime_helpers.rb +45 -0
- data/lib/opal/nodes/scope.rb +280 -0
- data/lib/opal/nodes/singleton_class.rb +4 -5
- data/lib/opal/nodes/super.rb +1 -1
- data/lib/opal/nodes/top.rb +9 -7
- data/lib/opal/nodes/yield.rb +14 -3
- data/lib/opal/parser.rb +4 -18
- data/lib/opal/parser/grammar.rb +3745 -3667
- data/lib/opal/parser/grammar.y +1692 -1778
- data/lib/opal/parser/keywords.rb +35 -35
- data/lib/opal/parser/lexer.rb +356 -325
- data/lib/opal/parser/sexp.rb +1 -1
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +1 -0
- data/opal/core/array.rb +320 -81
- data/opal/core/enumerable.rb +46 -5
- data/opal/core/hash.rb +6 -64
- data/opal/core/helpers.rb +67 -0
- data/opal/core/method.rb +1 -1
- data/opal/core/module.rb +4 -4
- data/opal/core/range.rb +1 -12
- data/opal/core/regexp.rb +2 -8
- data/opal/core/runtime.js +74 -3
- data/opal/core/string.rb +99 -74
- data/opal/opal.rb +3 -72
- data/spec/filters/bugs/array.rb +2 -30
- data/spec/filters/bugs/basic_object.rb +0 -1
- data/spec/filters/bugs/string.rb +26 -21
- data/spec/filters/unsupported/enumerator.rb +3 -0
- data/spec/filters/unsupported/float.rb +1 -0
- data/spec/filters/unsupported/immutable_strings.rb +15 -0
- data/spec/filters/unsupported/tainted.rb +58 -30
- data/spec/filters/unsupported/trusted.rb +35 -15
- data/spec/opal/parser/class_spec.rb +4 -4
- data/spec/opal/parser/def_spec.rb +4 -4
- data/spec/opal/parser/lvar_spec.rb +6 -6
- data/spec/opal/parser/module_spec.rb +4 -4
- data/spec/opal/parser/sclass_spec.rb +2 -2
- data/spec/stdlib/native/exposure_spec.rb +33 -0
- data/stdlib/buffer.rb +1 -1
- data/stdlib/buffer/view.rb +1 -1
- data/stdlib/native.rb +193 -174
- data/stdlib/opal-parser.rb +0 -6
- data/stdlib/pp.rb +9 -0
- data/tasks/mspec.rake +3 -1
- metadata +9 -9
- data/lib/opal/nodes/base_scope.rb +0 -11
- data/lib/opal/target_scope.rb +0 -281
- data/spec/filters/20.rb +0 -4
- data/spec/filters/unsupported/array_subclasses.rb +0 -37
data/lib/opal/parser/sexp.rb
CHANGED
data/lib/opal/version.rb
CHANGED
data/opal.gemspec
CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.homepage = 'http://opalrb.org'
|
12
12
|
s.summary = 'Ruby runtime and core library for javascript'
|
13
13
|
s.description = 'Ruby runtime and core library for javascript.'
|
14
|
+
s.license = 'MIT'
|
14
15
|
|
15
16
|
s.files = `git ls-files`.split("\n")
|
16
17
|
s.executables = ['opal']
|
data/opal/core/array.rb
CHANGED
@@ -4,6 +4,21 @@ class Array
|
|
4
4
|
# Mark all javascript arrays as being valid ruby arrays
|
5
5
|
`def._isArray = true`
|
6
6
|
|
7
|
+
def self.inherited(klass)
|
8
|
+
replace = Class.new(Array::Wrapper)
|
9
|
+
|
10
|
+
%x{
|
11
|
+
klass._proto = replace._proto;
|
12
|
+
klass._proto._klass = klass;
|
13
|
+
klass._alloc = replace._alloc;
|
14
|
+
klass.__parent = #{Array::Wrapper};
|
15
|
+
|
16
|
+
klass.$allocate = replace.$allocate;
|
17
|
+
klass.$new = replace.$new;
|
18
|
+
klass["$[]"] = replace["$[]"];
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
7
22
|
def self.[](*objects)
|
8
23
|
objects
|
9
24
|
end
|
@@ -70,7 +85,7 @@ class Array
|
|
70
85
|
if Array === other
|
71
86
|
other = other.to_a
|
72
87
|
else
|
73
|
-
other = Opal.coerce_to
|
88
|
+
other = Opal.coerce_to(other, Array, :to_ary).to_a
|
74
89
|
end
|
75
90
|
|
76
91
|
%x{
|
@@ -124,7 +139,7 @@ class Array
|
|
124
139
|
if Array === other
|
125
140
|
other = other.to_a
|
126
141
|
else
|
127
|
-
other = Opal.coerce_to
|
142
|
+
other = Opal.coerce_to(other, Array, :to_ary).to_a
|
128
143
|
end
|
129
144
|
|
130
145
|
`self.concat(other)`
|
@@ -134,7 +149,7 @@ class Array
|
|
134
149
|
if Array === other
|
135
150
|
other = other.to_a
|
136
151
|
else
|
137
|
-
other = Opal.coerce_to
|
152
|
+
other = Opal.coerce_to(other, Array, :to_ary).to_a
|
138
153
|
end
|
139
154
|
|
140
155
|
return [] if `self.length === 0`
|
@@ -170,7 +185,7 @@ class Array
|
|
170
185
|
if Array === other
|
171
186
|
other = other.to_a
|
172
187
|
elsif other.respond_to? :to_ary
|
173
|
-
other = other.to_ary
|
188
|
+
other = other.to_ary.to_a
|
174
189
|
else
|
175
190
|
return
|
176
191
|
end
|
@@ -197,15 +212,18 @@ class Array
|
|
197
212
|
end
|
198
213
|
|
199
214
|
def ==(other)
|
200
|
-
return
|
215
|
+
return true if `self === other`
|
216
|
+
|
217
|
+
unless Array === other
|
218
|
+
return false unless other.respond_to? :to_ary
|
219
|
+
return other == self
|
220
|
+
end
|
201
221
|
|
202
222
|
other = other.to_a
|
203
223
|
|
204
|
-
|
205
|
-
if (self.length !== other.length) {
|
206
|
-
return false;
|
207
|
-
}
|
224
|
+
return false unless `self.length === other.length`
|
208
225
|
|
226
|
+
%x{
|
209
227
|
for (var i = 0, length = self.length; i < length; i++) {
|
210
228
|
var a = self[i],
|
211
229
|
b = other[i];
|
@@ -214,7 +232,7 @@ class Array
|
|
214
232
|
continue;
|
215
233
|
}
|
216
234
|
|
217
|
-
if (
|
235
|
+
if (!#{`a` == `b`}) {
|
218
236
|
return false;
|
219
237
|
}
|
220
238
|
}
|
@@ -224,104 +242,187 @@ class Array
|
|
224
242
|
end
|
225
243
|
|
226
244
|
def [](index, length = undefined)
|
227
|
-
|
228
|
-
|
245
|
+
if Range === index
|
246
|
+
%x{
|
247
|
+
var size = self.length,
|
248
|
+
exclude = index.exclude,
|
249
|
+
from = #{Opal.coerce_to `index.begin`, Integer, :to_int},
|
250
|
+
to = #{Opal.coerce_to `index.end`, Integer, :to_int};
|
229
251
|
|
230
|
-
|
231
|
-
|
232
|
-
var exclude = index.exclude;
|
233
|
-
length = index.end;
|
234
|
-
index = index.begin;
|
252
|
+
if (from < 0) {
|
253
|
+
from += size;
|
235
254
|
|
236
|
-
if (
|
255
|
+
if (from < 0) {
|
237
256
|
return nil;
|
238
257
|
}
|
258
|
+
}
|
239
259
|
|
240
|
-
|
241
|
-
length += size;
|
242
|
-
}
|
260
|
+
#{Opal.fits_fixnum!(`from`)};
|
243
261
|
|
244
|
-
|
245
|
-
return
|
262
|
+
if (from > size) {
|
263
|
+
return nil;
|
246
264
|
}
|
247
|
-
|
248
|
-
|
265
|
+
|
266
|
+
if (to < 0) {
|
267
|
+
to += size;
|
268
|
+
|
269
|
+
if (to < 0) {
|
270
|
+
return [];
|
271
|
+
}
|
249
272
|
}
|
250
|
-
}
|
251
273
|
|
252
|
-
|
253
|
-
index += size;
|
254
|
-
}
|
274
|
+
#{Opal.fits_fixnum!(`to`)};
|
255
275
|
|
256
|
-
|
257
|
-
|
258
|
-
return nil;
|
276
|
+
if (!exclude) {
|
277
|
+
to += 1;
|
259
278
|
}
|
260
279
|
|
261
|
-
return self.slice(
|
280
|
+
return self.slice(from, to);
|
262
281
|
}
|
263
|
-
|
264
|
-
|
265
|
-
|
282
|
+
else
|
283
|
+
index = Opal.coerce_to index, Integer, :to_int
|
284
|
+
|
285
|
+
%x{
|
286
|
+
var size = self.length;
|
287
|
+
|
288
|
+
if (index < 0) {
|
289
|
+
index += size;
|
290
|
+
|
291
|
+
if (index < 0) {
|
292
|
+
return nil;
|
293
|
+
}
|
266
294
|
}
|
267
295
|
|
268
|
-
|
296
|
+
#{Opal.fits_fixnum!(`index`)};
|
297
|
+
|
298
|
+
if (length === undefined) {
|
299
|
+
if (index >= size || index < 0) {
|
300
|
+
return nil;
|
301
|
+
}
|
302
|
+
|
303
|
+
return self[index];
|
304
|
+
}
|
305
|
+
else {
|
306
|
+
length = #{Opal.coerce_to length, Integer, :to_int};
|
307
|
+
|
308
|
+
#{Opal.fits_fixnum!(`length`)};
|
309
|
+
|
310
|
+
if (length < 0 || index > size || index < 0) {
|
311
|
+
return nil;
|
312
|
+
}
|
313
|
+
|
314
|
+
return self.slice(index, index + length);
|
315
|
+
}
|
269
316
|
}
|
270
|
-
|
317
|
+
end
|
271
318
|
end
|
272
319
|
|
273
320
|
def []=(index, value, extra = undefined)
|
274
|
-
|
275
|
-
|
321
|
+
if Range === index
|
322
|
+
if Array === value
|
323
|
+
data = value.to_a
|
324
|
+
elsif value.respond_to? :to_ary
|
325
|
+
data = value.to_ary.to_a
|
326
|
+
else
|
327
|
+
data = [value]
|
328
|
+
end
|
276
329
|
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
330
|
+
%x{
|
331
|
+
var size = self.length,
|
332
|
+
exclude = index.exclude,
|
333
|
+
from = #{Opal.coerce_to `index.begin`, Integer, :to_int},
|
334
|
+
to = #{Opal.coerce_to `index.end`, Integer, :to_int};
|
335
|
+
|
336
|
+
if (from < 0) {
|
337
|
+
from += size;
|
283
338
|
|
284
|
-
if (
|
285
|
-
|
339
|
+
if (from < 0) {
|
340
|
+
#{raise RangeError, "#{index.inspect} out of range"};
|
286
341
|
}
|
342
|
+
}
|
343
|
+
|
344
|
+
#{Opal.fits_fixnum!(`from`)};
|
345
|
+
|
346
|
+
if (to < 0) {
|
347
|
+
to += size;
|
348
|
+
}
|
287
349
|
|
288
|
-
|
350
|
+
#{Opal.fits_fixnum!(`to`)};
|
289
351
|
|
290
|
-
|
352
|
+
if (!exclude) {
|
353
|
+
to += 1;
|
354
|
+
}
|
355
|
+
|
356
|
+
if (from > size) {
|
357
|
+
for (var i = size; i < index; i++) {
|
358
|
+
self[i] = nil;
|
359
|
+
}
|
360
|
+
}
|
361
|
+
|
362
|
+
if (to < 0) {
|
363
|
+
self.splice.apply(self, [from, 0].concat(data));
|
291
364
|
}
|
292
365
|
else {
|
293
|
-
|
366
|
+
self.splice.apply(self, [from, to - from].concat(data));
|
294
367
|
}
|
295
|
-
}
|
296
368
|
|
297
|
-
|
298
|
-
index += size;
|
369
|
+
return value;
|
299
370
|
}
|
371
|
+
else
|
372
|
+
if `extra === undefined`
|
373
|
+
length = 1
|
374
|
+
else
|
375
|
+
length = value
|
376
|
+
value = extra
|
377
|
+
|
378
|
+
if Array === value
|
379
|
+
data = value.to_a
|
380
|
+
elsif value.respond_to? :to_ary
|
381
|
+
data = value.to_ary.to_a
|
382
|
+
else
|
383
|
+
data = [value]
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
%x{
|
388
|
+
var size = self.length,
|
389
|
+
index = #{Opal.coerce_to index, Integer, :to_int},
|
390
|
+
length = #{Opal.coerce_to length, Integer, :to_int},
|
391
|
+
old;
|
392
|
+
|
393
|
+
if (index < 0) {
|
394
|
+
old = index;
|
395
|
+
index += size;
|
396
|
+
|
397
|
+
if (index < 0) {
|
398
|
+
#{raise IndexError, "index #{`old`} too small for array; minimum #{`-self.length`}"};
|
399
|
+
}
|
400
|
+
}
|
300
401
|
|
301
|
-
|
302
|
-
|
303
|
-
|
402
|
+
#{Opal.fits_fixnum!(`index`)};
|
403
|
+
|
404
|
+
if (length < 0) {
|
405
|
+
#{raise IndexError, "negative length (#{length})"}
|
304
406
|
}
|
305
407
|
|
408
|
+
#{Opal.fits_fixnum!(`length`)};
|
409
|
+
|
306
410
|
if (index > size) {
|
307
|
-
for (var i = size;
|
411
|
+
for (var i = size; i < index; i++) {
|
308
412
|
self[i] = nil;
|
309
413
|
}
|
310
414
|
}
|
311
415
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
if (index > size) {
|
318
|
-
for (var i = size; i < index; i++) {
|
319
|
-
self[i] = nil;
|
416
|
+
if (extra === undefined) {
|
417
|
+
self[index] = value;
|
418
|
+
}
|
419
|
+
else {
|
420
|
+
self.splice.apply(self, [index, length].concat(data));
|
320
421
|
}
|
321
|
-
}
|
322
422
|
|
323
|
-
|
324
|
-
|
423
|
+
return value;
|
424
|
+
}
|
425
|
+
end
|
325
426
|
end
|
326
427
|
|
327
428
|
def assoc(object)
|
@@ -401,7 +502,19 @@ class Array
|
|
401
502
|
end
|
402
503
|
|
403
504
|
def clone
|
404
|
-
|
505
|
+
copy = []
|
506
|
+
copy.initialize_clone(self)
|
507
|
+
copy
|
508
|
+
end
|
509
|
+
|
510
|
+
def dup
|
511
|
+
copy = []
|
512
|
+
copy.initialize_dup(self)
|
513
|
+
copy
|
514
|
+
end
|
515
|
+
|
516
|
+
def initialize_copy(other)
|
517
|
+
replace other
|
405
518
|
end
|
406
519
|
|
407
520
|
def collect(&block)
|
@@ -477,7 +590,7 @@ class Array
|
|
477
590
|
if Array === other
|
478
591
|
other = other.to_a
|
479
592
|
else
|
480
|
-
other = Opal.coerce_to
|
593
|
+
other = Opal.coerce_to(other, Array, :to_ary).to_a
|
481
594
|
end
|
482
595
|
|
483
596
|
%x{
|
@@ -593,6 +706,32 @@ class Array
|
|
593
706
|
`self.length === 0`
|
594
707
|
end
|
595
708
|
|
709
|
+
def eql?(other)
|
710
|
+
return true if `self === other`
|
711
|
+
return false unless Array === other
|
712
|
+
|
713
|
+
other = other.to_a
|
714
|
+
|
715
|
+
return false unless `self.length === other.length`
|
716
|
+
|
717
|
+
%x{
|
718
|
+
for (var i = 0, length = self.length; i < length; i++) {
|
719
|
+
var a = self[i],
|
720
|
+
b = other[i];
|
721
|
+
|
722
|
+
if (a._isArray && b._isArray && (a === self)) {
|
723
|
+
continue;
|
724
|
+
}
|
725
|
+
|
726
|
+
if (!#{`a`.eql? `b`}) {
|
727
|
+
return false;
|
728
|
+
}
|
729
|
+
}
|
730
|
+
}
|
731
|
+
|
732
|
+
true
|
733
|
+
end
|
734
|
+
|
596
735
|
def fetch(index, defaults = undefined, &block)
|
597
736
|
%x{
|
598
737
|
var original = index;
|
@@ -670,11 +809,8 @@ class Array
|
|
670
809
|
right = @length
|
671
810
|
end
|
672
811
|
|
673
|
-
|
674
|
-
|
675
|
-
elsif `right >= 536870910`
|
676
|
-
raise ArgumentError, "argument too big"
|
677
|
-
end
|
812
|
+
Opal.fits_fixnum!(right)
|
813
|
+
Opal.fits_array!(right)
|
678
814
|
|
679
815
|
if `left > #@length`
|
680
816
|
%x{
|
@@ -1009,6 +1145,12 @@ class Array
|
|
1009
1145
|
end
|
1010
1146
|
|
1011
1147
|
def replace(other)
|
1148
|
+
if Array === other
|
1149
|
+
other = other.to_a
|
1150
|
+
else
|
1151
|
+
other = Opal.coerce_to(other, Array, :to_ary).to_a
|
1152
|
+
end
|
1153
|
+
|
1012
1154
|
%x{
|
1013
1155
|
self.splice(0, self.length);
|
1014
1156
|
self.push.apply(self, other);
|
@@ -1260,7 +1402,7 @@ class Array
|
|
1260
1402
|
if Array === row
|
1261
1403
|
row = row.to_a
|
1262
1404
|
else
|
1263
|
-
row = Opal.coerce_to
|
1405
|
+
row = Opal.coerce_to(row, Array, :to_ary).to_a
|
1264
1406
|
end
|
1265
1407
|
|
1266
1408
|
max ||= `row.length`
|
@@ -1282,18 +1424,18 @@ class Array
|
|
1282
1424
|
%x{
|
1283
1425
|
var result = [],
|
1284
1426
|
seen = {};
|
1285
|
-
|
1427
|
+
|
1286
1428
|
for (var i = 0, length = self.length, item, hash; i < length; i++) {
|
1287
1429
|
item = self[i];
|
1288
1430
|
hash = item;
|
1289
|
-
|
1431
|
+
|
1290
1432
|
if (!seen[hash]) {
|
1291
1433
|
seen[hash] = true;
|
1292
|
-
|
1434
|
+
|
1293
1435
|
result.push(item);
|
1294
1436
|
}
|
1295
1437
|
}
|
1296
|
-
|
1438
|
+
|
1297
1439
|
return result;
|
1298
1440
|
}
|
1299
1441
|
end
|
@@ -1364,3 +1506,100 @@ class Array
|
|
1364
1506
|
}
|
1365
1507
|
end
|
1366
1508
|
end
|
1509
|
+
|
1510
|
+
class Array::Wrapper
|
1511
|
+
def self.allocate(array = [])
|
1512
|
+
obj = super()
|
1513
|
+
`obj.literal = array`
|
1514
|
+
obj
|
1515
|
+
end
|
1516
|
+
|
1517
|
+
def self.new(*args, &block)
|
1518
|
+
obj = allocate
|
1519
|
+
obj.initialize(*args, &block)
|
1520
|
+
obj
|
1521
|
+
end
|
1522
|
+
|
1523
|
+
def self.[](*objects)
|
1524
|
+
allocate(objects)
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
def initialize(*args, &block)
|
1528
|
+
@literal = Array.new(*args, &block)
|
1529
|
+
end
|
1530
|
+
|
1531
|
+
def method_missing(*args, &block)
|
1532
|
+
result = @literal.__send__(*args, &block)
|
1533
|
+
|
1534
|
+
if `result === #@literal`
|
1535
|
+
self
|
1536
|
+
else
|
1537
|
+
result
|
1538
|
+
end
|
1539
|
+
end
|
1540
|
+
|
1541
|
+
def initialize_copy(other)
|
1542
|
+
@literal = `other.literal`.clone
|
1543
|
+
end
|
1544
|
+
|
1545
|
+
def respond_to?(name, *)
|
1546
|
+
super || @literal.respond_to?(name)
|
1547
|
+
end
|
1548
|
+
|
1549
|
+
def ==(other)
|
1550
|
+
@literal == other
|
1551
|
+
end
|
1552
|
+
|
1553
|
+
def eql?(other)
|
1554
|
+
@literal.eql?(other)
|
1555
|
+
end
|
1556
|
+
|
1557
|
+
def to_a
|
1558
|
+
@literal
|
1559
|
+
end
|
1560
|
+
|
1561
|
+
def to_ary
|
1562
|
+
self
|
1563
|
+
end
|
1564
|
+
|
1565
|
+
def inspect
|
1566
|
+
@literal.inspect
|
1567
|
+
end
|
1568
|
+
|
1569
|
+
# wrapped results
|
1570
|
+
def *(other)
|
1571
|
+
%x{
|
1572
|
+
var result = #{@literal * other};
|
1573
|
+
|
1574
|
+
if (result._isArray) {
|
1575
|
+
return #{self.class.allocate(`result`)}
|
1576
|
+
}
|
1577
|
+
else {
|
1578
|
+
return result;
|
1579
|
+
}
|
1580
|
+
}
|
1581
|
+
end
|
1582
|
+
|
1583
|
+
def [](index, length = undefined)
|
1584
|
+
%x{
|
1585
|
+
var result = #{@literal.slice(index, length)};
|
1586
|
+
|
1587
|
+
if (result._isArray && (index._isRange || length !== undefined)) {
|
1588
|
+
return #{self.class.allocate(`result`)}
|
1589
|
+
}
|
1590
|
+
else {
|
1591
|
+
return result;
|
1592
|
+
}
|
1593
|
+
}
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
alias slice []
|
1597
|
+
|
1598
|
+
def uniq
|
1599
|
+
self.class.allocate(@literal.uniq)
|
1600
|
+
end
|
1601
|
+
|
1602
|
+
def flatten(level = undefined)
|
1603
|
+
self.class.allocate(@literal.flatten(level))
|
1604
|
+
end
|
1605
|
+
end
|