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.
Files changed (62) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -0
  3. data/lib/opal.rb +0 -5
  4. data/lib/opal/compiler.rb +24 -44
  5. data/lib/opal/nodes/base.rb +5 -8
  6. data/lib/opal/nodes/call.rb +4 -0
  7. data/lib/opal/nodes/class.rb +6 -7
  8. data/lib/opal/nodes/def.rb +4 -4
  9. data/lib/opal/nodes/definitions.rb +0 -14
  10. data/lib/opal/nodes/iter.rb +51 -38
  11. data/lib/opal/nodes/literal.rb +21 -24
  12. data/lib/opal/nodes/module.rb +4 -4
  13. data/lib/opal/nodes/runtime_helpers.rb +45 -0
  14. data/lib/opal/nodes/scope.rb +280 -0
  15. data/lib/opal/nodes/singleton_class.rb +4 -5
  16. data/lib/opal/nodes/super.rb +1 -1
  17. data/lib/opal/nodes/top.rb +9 -7
  18. data/lib/opal/nodes/yield.rb +14 -3
  19. data/lib/opal/parser.rb +4 -18
  20. data/lib/opal/parser/grammar.rb +3745 -3667
  21. data/lib/opal/parser/grammar.y +1692 -1778
  22. data/lib/opal/parser/keywords.rb +35 -35
  23. data/lib/opal/parser/lexer.rb +356 -325
  24. data/lib/opal/parser/sexp.rb +1 -1
  25. data/lib/opal/version.rb +1 -1
  26. data/opal.gemspec +1 -0
  27. data/opal/core/array.rb +320 -81
  28. data/opal/core/enumerable.rb +46 -5
  29. data/opal/core/hash.rb +6 -64
  30. data/opal/core/helpers.rb +67 -0
  31. data/opal/core/method.rb +1 -1
  32. data/opal/core/module.rb +4 -4
  33. data/opal/core/range.rb +1 -12
  34. data/opal/core/regexp.rb +2 -8
  35. data/opal/core/runtime.js +74 -3
  36. data/opal/core/string.rb +99 -74
  37. data/opal/opal.rb +3 -72
  38. data/spec/filters/bugs/array.rb +2 -30
  39. data/spec/filters/bugs/basic_object.rb +0 -1
  40. data/spec/filters/bugs/string.rb +26 -21
  41. data/spec/filters/unsupported/enumerator.rb +3 -0
  42. data/spec/filters/unsupported/float.rb +1 -0
  43. data/spec/filters/unsupported/immutable_strings.rb +15 -0
  44. data/spec/filters/unsupported/tainted.rb +58 -30
  45. data/spec/filters/unsupported/trusted.rb +35 -15
  46. data/spec/opal/parser/class_spec.rb +4 -4
  47. data/spec/opal/parser/def_spec.rb +4 -4
  48. data/spec/opal/parser/lvar_spec.rb +6 -6
  49. data/spec/opal/parser/module_spec.rb +4 -4
  50. data/spec/opal/parser/sclass_spec.rb +2 -2
  51. data/spec/stdlib/native/exposure_spec.rb +33 -0
  52. data/stdlib/buffer.rb +1 -1
  53. data/stdlib/buffer/view.rb +1 -1
  54. data/stdlib/native.rb +193 -174
  55. data/stdlib/opal-parser.rb +0 -6
  56. data/stdlib/pp.rb +9 -0
  57. data/tasks/mspec.rake +3 -1
  58. metadata +9 -9
  59. data/lib/opal/nodes/base_scope.rb +0 -11
  60. data/lib/opal/target_scope.rb +0 -281
  61. data/spec/filters/20.rb +0 -4
  62. data/spec/filters/unsupported/array_subclasses.rb +0 -37
@@ -54,7 +54,7 @@ module Opal
54
54
  alias eql? ==
55
55
 
56
56
  def inspect
57
- "s(#{@array.map { |e| e.inspect }.join ', '})"
57
+ "(#{@array.map { |e| e.inspect }.join ' '})"
58
58
  end
59
59
 
60
60
  alias to_s inspect
@@ -1,3 +1,3 @@
1
1
  module Opal
2
- VERSION = '0.5.2'
2
+ VERSION = '0.5.4'
3
3
  end
@@ -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']
@@ -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 other, Array, :to_ary
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 other, Array, :to_ary
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 other, Array, :to_ary
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 false unless Array === other
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
- %x{
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 (!(#{`a` == `b`})) {
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
- %x{
228
- var size = self.length;
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
- if (typeof index !== 'number' && !index._isNumber) {
231
- if (index._isRange) {
232
- var exclude = index.exclude;
233
- length = index.end;
234
- index = index.begin;
252
+ if (from < 0) {
253
+ from += size;
235
254
 
236
- if (index > size) {
255
+ if (from < 0) {
237
256
  return nil;
238
257
  }
258
+ }
239
259
 
240
- if (length < 0) {
241
- length += size;
242
- }
260
+ #{Opal.fits_fixnum!(`from`)};
243
261
 
244
- if (!exclude) length += 1;
245
- return self.slice(index, length);
262
+ if (from > size) {
263
+ return nil;
246
264
  }
247
- else {
248
- #{ raise "bad arg for Array#[]" };
265
+
266
+ if (to < 0) {
267
+ to += size;
268
+
269
+ if (to < 0) {
270
+ return [];
271
+ }
249
272
  }
250
- }
251
273
 
252
- if (index < 0) {
253
- index += size;
254
- }
274
+ #{Opal.fits_fixnum!(`to`)};
255
275
 
256
- if (length !== undefined) {
257
- if (length < 0 || index > size || index < 0) {
258
- return nil;
276
+ if (!exclude) {
277
+ to += 1;
259
278
  }
260
279
 
261
- return self.slice(index, index + length);
280
+ return self.slice(from, to);
262
281
  }
263
- else {
264
- if (index >= size || index < 0) {
265
- return nil;
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
- return self[index];
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
- %x{
275
- var size = self.length;
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
- if (typeof index !== 'number' && !index._isNumber) {
278
- if (index._isRange) {
279
- var exclude = index.exclude;
280
- extra = value;
281
- value = index.end;
282
- index = index.begin;
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 (value < 0) {
285
- value += size;
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
- if (!exclude) value += 1;
350
+ #{Opal.fits_fixnum!(`to`)};
289
351
 
290
- value = value - index;
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
- #{raise ArgumentError};
366
+ self.splice.apply(self, [from, to - from].concat(data));
294
367
  }
295
- }
296
368
 
297
- if (index < 0) {
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
- if (extra != null) {
302
- if (value < 0) {
303
- #{raise IndexError};
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; index > i; i++) {
411
+ for (var i = size; i < index; i++) {
308
412
  self[i] = nil;
309
413
  }
310
414
  }
311
415
 
312
- self.splice.apply(self, [index, value].concat(extra));
313
-
314
- return extra;
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
- return self[index] = value;
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
- `self.slice()`
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 other, Array, :to_ary
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
- if `right > 2147483648`
674
- raise RangeError, "bignum too big to convert into `long'"
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 row, Array, :to_ary
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