opal 0.5.2 → 0.5.4

Sign up to get free protection for your applications and to get access to all the features.
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