opal 0.3.37 → 0.3.38

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 (51) hide show
  1. data/CHANGELOG.md +11 -0
  2. data/Gemfile +0 -8
  3. data/README.md +7 -6
  4. data/bin/opal +18 -10
  5. data/config.ru +8 -21
  6. data/lib/assets/javascripts/opal-parser.js.erb +3 -60
  7. data/lib/assets/javascripts/opal/array.rb +87 -43
  8. data/lib/assets/javascripts/opal/basic_object.rb +4 -0
  9. data/lib/assets/javascripts/opal/boolean.rb +5 -3
  10. data/lib/assets/javascripts/opal/class.rb +19 -4
  11. data/lib/assets/javascripts/opal/comparable.rb +1 -1
  12. data/lib/assets/javascripts/opal/enumerable.rb +32 -0
  13. data/lib/assets/javascripts/opal/error.rb +1 -1
  14. data/lib/assets/javascripts/opal/hash.rb +166 -103
  15. data/lib/assets/javascripts/opal/json.rb +3 -2
  16. data/lib/assets/javascripts/opal/kernel.rb +9 -1
  17. data/lib/assets/javascripts/opal/native.rb +29 -0
  18. data/lib/assets/javascripts/opal/nil_class.rb +9 -1
  19. data/lib/assets/javascripts/opal/numeric.rb +6 -4
  20. data/lib/assets/javascripts/opal/parser.js +57 -0
  21. data/lib/assets/javascripts/opal/proc.rb +5 -5
  22. data/lib/assets/javascripts/opal/regexp.rb +1 -1
  23. data/lib/assets/javascripts/opal/runtime.js +13 -0
  24. data/lib/assets/javascripts/opal/string.rb +14 -3
  25. data/lib/assets/javascripts/opal/time.rb +1 -1
  26. data/lib/opal.rb +1 -1
  27. data/lib/opal/parser.rb +39 -13
  28. data/lib/opal/processor.rb +13 -2
  29. data/lib/opal/version.rb +1 -1
  30. data/opal.gemspec +3 -0
  31. data/spec/core/array/fill_spec.rb +26 -0
  32. data/spec/core/array/try_convert_spec.rb +15 -0
  33. data/spec/core/enumerable/each_slice_spec.rb +24 -0
  34. data/spec/core/enumerable/group_by_spec.rb +16 -0
  35. data/spec/core/module/const_get_spec.rb +34 -0
  36. data/spec/core/module/undef_method_spec.rb +67 -0
  37. data/spec/core/nil/to_h_spec.rb +10 -0
  38. data/spec/core/proc/element_reference_spec.rb +21 -0
  39. data/spec/{core → core_ext}/array/to_json_spec.rb +0 -0
  40. data/spec/core_ext/method_missing_spec.rb +43 -0
  41. data/spec/core_ext/native/fixtures/classes.rb +5 -0
  42. data/spec/core_ext/native/initialize_spec.rb +8 -0
  43. data/spec/core_ext/native/method_missing_spec.rb +7 -0
  44. data/spec/core_ext/native/to_native_spec.rb +7 -0
  45. data/spec/grammar/parser_spec.rb +1 -1
  46. data/spec/language/super_spec.rb +20 -0
  47. data/spec/language/variables_spec.rb +69 -0
  48. data/spec/spec_helper.rb +9 -5
  49. metadata +66 -8
  50. data/lib/assets/javascripts/opal/core.rb +0 -36
  51. data/spec/autorun.rb +0 -3
@@ -216,6 +216,28 @@ module Enumerable
216
216
  }
217
217
  end
218
218
 
219
+ def each_slice(n, &block)
220
+ %x{
221
+ var all = [];
222
+
223
+ #{self}.$each(function(obj) {
224
+ all.push(obj);
225
+
226
+ if (all.length == n) {
227
+ block(all.slice(0));
228
+ all = [];
229
+ }
230
+ });
231
+
232
+ // our "last" group, if smaller than n then wont have been yielded
233
+ if (all.length > 0) {
234
+ block(all.slice(0));
235
+ }
236
+
237
+ return nil;
238
+ }
239
+ end
240
+
219
241
  def each_with_index(&block)
220
242
  %x{
221
243
  var index = 0;
@@ -376,6 +398,16 @@ module Enumerable
376
398
  }
377
399
  end
378
400
 
401
+ def group_by(&block)
402
+ hash = Hash.new { |h, k| h[k] = [] }
403
+
404
+ each do |el|
405
+ hash[block.call(el)] << el
406
+ end
407
+
408
+ hash
409
+ end
410
+
379
411
  alias map collect
380
412
 
381
413
  alias select find_all
@@ -40,4 +40,4 @@ NoMethodError = Exception
40
40
  ArgumentError = Exception
41
41
  IndexError = Exception
42
42
  KeyError = Exception
43
- RangeError = Exception
43
+ RangeError = Exception
@@ -23,18 +23,23 @@ class Hash
23
23
 
24
24
  return hash;
25
25
  };
26
+ }
26
27
 
27
- // hash2 is a faster creator for hashes that just use symbols and
28
- // strings as keys. The map and keys array can be constructed at
29
- // compile time, so they are just added here by the constructor
30
- // function
31
- __hash2 = Opal.hash2 = function(map) {
28
+ # hash2 is a faster creator for hashes that just use symbols and
29
+ # strings as keys. The map and keys array can be constructed at
30
+ # compile time, so they are just added here by the constructor
31
+ # function
32
+ %x{
33
+ __hash2 = Opal.hash2 = function(keys, map) {
32
34
  var hash = new Hash;
35
+ hash.keys = keys;
33
36
  hash.map = map;
34
37
  return hash;
35
- }
38
+ };
36
39
  }
37
40
 
41
+ `var __hasOwn = {}.hasOwnProperty`
42
+
38
43
  def self.[](*objs)
39
44
  `__hash.apply(null, objs)`
40
45
  end
@@ -45,9 +50,10 @@ class Hash
45
50
 
46
51
  def self.from_native(obj)
47
52
  %x{
48
- var hash = __hash(), map = hash.map;
53
+ var hash = __hash(), map = hash.map, keys = hash.keys;
49
54
 
50
55
  for (var key in obj) {
56
+ keys.push(key);
51
57
  map[key] = obj[key];
52
58
  }
53
59
 
@@ -76,15 +82,19 @@ class Hash
76
82
  return true;
77
83
  }
78
84
 
79
- if (other.map == null) {
85
+ if (!other.map || !other.keys) {
86
+ return false;
87
+ }
88
+
89
+ if (#{self}.keys.length !== other.keys.length) {
80
90
  return false;
81
91
  }
82
92
 
83
93
  var map = #{self}.map,
84
94
  map2 = other.map;
85
95
 
86
- for (var key in map) {
87
- var obj = map[key], obj2 = map2[key];
96
+ for (var i = 0, length = #{self}.keys.length; i < length; i++) {
97
+ var key = #{self}.keys[i], obj = map[key], obj2 = map2[key];
88
98
 
89
99
  if (#{`obj` != `obj2`}) {
90
100
  return false;
@@ -97,10 +107,10 @@ class Hash
97
107
 
98
108
  def [](key)
99
109
  %x{
100
- var obj = #{self}.map[key];
110
+ var bucket = #{self}.map[key];
101
111
 
102
- if (obj != null) {
103
- return obj;
112
+ if (bucket != null) {
113
+ return bucket;
104
114
  }
105
115
 
106
116
  var proc = #{@proc};
@@ -115,18 +125,27 @@ class Hash
115
125
 
116
126
  def []=(key, value)
117
127
  %x{
118
- #{self}.map[key] = value;
128
+ var map = #{self}.map;
129
+
130
+ if (!__hasOwn.call(map, key)) {
131
+ #{self}.keys.push(key);
132
+ }
133
+
134
+ map[key] = value;
135
+
119
136
  return value;
120
137
  }
121
138
  end
122
139
 
123
140
  def assoc(object)
124
141
  %x{
125
- var map = #{self}.map;
142
+ var keys = #{self}.keys, key;
143
+
144
+ for (var i = 0, length = keys.length; i < length; i++) {
145
+ key = keys[i];
126
146
 
127
- for (var key in map) {
128
147
  if (#{`key` == object}) {
129
- return [key, map[key]];
148
+ return [key, #{self}.map[key]];
130
149
  }
131
150
  }
132
151
 
@@ -137,6 +156,7 @@ class Hash
137
156
  def clear
138
157
  %x{
139
158
  #{self}.map = {};
159
+ #{self}.keys = [];
140
160
  return #{self};
141
161
  }
142
162
  end
@@ -145,10 +165,12 @@ class Hash
145
165
  %x{
146
166
  var result = __hash(),
147
167
  map = #{self}.map,
148
- map2 = result.map;
168
+ map2 = result.map,
169
+ keys2 = result.keys;
149
170
 
150
- for (var key in map) {
151
- map2[key] = map[key];
171
+ for (var i = 0, length = #{self}.keys.length; i < length; i++) {
172
+ keys2.push(#{self}.keys[i]);
173
+ map2[#{self}.keys[i]] = map[#{self}.keys[i]];
152
174
  }
153
175
 
154
176
  return result;
@@ -173,10 +195,12 @@ class Hash
173
195
 
174
196
  def delete(key)
175
197
  %x{
176
- var map = #{self}.map, result = map[key];
198
+ var map = #{self}.map, result = map[key];
177
199
 
178
200
  if (result != null) {
179
201
  delete map[key];
202
+ #{self}.keys.$delete(key);
203
+
180
204
  return result;
181
205
  }
182
206
 
@@ -186,15 +210,21 @@ class Hash
186
210
 
187
211
  def delete_if(&block)
188
212
  %x{
189
- var map = #{self}.map, value;
213
+ var map = #{self}.map, keys = #{self}.keys, value;
190
214
 
191
- for (var key in map) {
192
- if ((value = block(key, map[key])) === __breaker) {
215
+ for (var i = 0, length = keys.length; i < length; i++) {
216
+ var key = keys[i], obj = map[key];
217
+
218
+ if ((value = block(key, obj)) === __breaker) {
193
219
  return __breaker.$v;
194
220
  }
195
221
 
196
222
  if (value !== false && value !== nil) {
197
- delete map[key]
223
+ keys.splice(i, 1);
224
+ delete map[key];
225
+
226
+ length--;
227
+ i--;
198
228
  }
199
229
  }
200
230
 
@@ -206,9 +236,11 @@ class Hash
206
236
 
207
237
  def each(&block)
208
238
  %x{
209
- var map = #{self}.map;
239
+ var map = #{self}.map, keys = #{self}.keys;
240
+
241
+ for (var i = 0, length = keys.length; i < length; i++) {
242
+ var key = keys[i];
210
243
 
211
- for (var key in map) {
212
244
  if (block(key, map[key]) === __breaker) {
213
245
  return __breaker.$v;
214
246
  }
@@ -220,9 +252,11 @@ class Hash
220
252
 
221
253
  def each_key(&block)
222
254
  %x{
223
- var map = #{self}.map;
255
+ var keys = #{self}.keys;
256
+
257
+ for (var i = 0, length = keys.length; i < length; i++) {
258
+ var key = keys[i];
224
259
 
225
- for (var key in map) {
226
260
  if (block(key) === __breaker) {
227
261
  return __breaker.$v;
228
262
  }
@@ -236,10 +270,10 @@ class Hash
236
270
 
237
271
  def each_value(&block)
238
272
  %x{
239
- var map = #{self}.map;
273
+ var map = #{self}.map, keys = #{self}.keys;
240
274
 
241
- for (var key in map) {
242
- if (block(map[key]) === __breaker) {
275
+ for (var i = 0, length = keys.length; i < length; i++) {
276
+ if (block(map[keys[i]]) === __breaker) {
243
277
  return __breaker.$v;
244
278
  }
245
279
  }
@@ -250,11 +284,7 @@ class Hash
250
284
 
251
285
  def empty?
252
286
  %x{
253
- for (var key in #{self}.map) {
254
- return false;
255
- }
256
-
257
- return true;
287
+ return #{self}.keys.length === 0;
258
288
  }
259
289
  end
260
290
 
@@ -288,10 +318,10 @@ class Hash
288
318
 
289
319
  def flatten(level=undefined)
290
320
  %x{
291
- var map = #{self}.map, result = [];
321
+ var map = #{self}.map, keys = #{self}.keys, result = [];
292
322
 
293
- for (var key in map) {
294
- var value = map[key];
323
+ for (var i = 0, length = keys.length; i < length; i++) {
324
+ var key = keys[i], value = map[key];
295
325
 
296
326
  result.push(key);
297
327
 
@@ -318,10 +348,8 @@ class Hash
318
348
 
319
349
  def has_value?(value)
320
350
  %x{
321
- var map = #{self}.map;
322
-
323
- for (var key in map) {
324
- if (#{`map[key]` == value}) {
351
+ for (var assoc in #{self}.map) {
352
+ if (#{`#{self}.map[assoc]` == value}) {
325
353
  return true;
326
354
  }
327
355
  }
@@ -338,9 +366,11 @@ class Hash
338
366
 
339
367
  def index(object)
340
368
  %x{
341
- var map = #{self}.map;
369
+ var map = #{self}.map, keys = #{self}.keys;
370
+
371
+ for (var i = 0, length = keys.length; i < length; i++) {
372
+ var key = keys[i];
342
373
 
343
- for (var key in map) {
344
374
  if (#{object == `map[key]`}) {
345
375
  return key;
346
376
  }
@@ -355,13 +385,13 @@ class Hash
355
385
  var result = [], map = #{self}.map, val;
356
386
 
357
387
  for (var i = 0, length = keys.length; i < length; i++) {
358
- val = map[keys[i]];
388
+ var key = keys[i], val = map[key];
359
389
 
360
390
  if (val != null) {
361
391
  result.push(val);
362
392
  }
363
393
  else {
364
- result.push(#{@none});
394
+ result.push(#{self}.none);
365
395
  }
366
396
  }
367
397
 
@@ -373,9 +403,10 @@ class Hash
373
403
 
374
404
  def inspect
375
405
  %x{
376
- var inspect = [], map = #{self}.map;
406
+ var inspect = [], keys = #{self}.keys, map = #{self}.map;
377
407
 
378
- for (var key in map) {
408
+ for (var i = 0, length = keys.length; i < length; i++) {
409
+ var key = keys[i];
379
410
  inspect.push(#{`key`.inspect} + '=>' + #{`map[key]`.inspect});
380
411
  }
381
412
 
@@ -385,10 +416,13 @@ class Hash
385
416
 
386
417
  def invert
387
418
  %x{
388
- var result = __hash(), map = #{self}.map, map2 = result.map;
419
+ var result = __hash(), keys = #{self}.keys, map = #{self}.map,
420
+ keys2 = result.keys, map2 = result.map;
389
421
 
390
- for (var key in map) {
391
- var obj = map[key];
422
+ for (var i = 0, length = keys.length; i < length; i++) {
423
+ var key = keys[i], obj = map[key];
424
+
425
+ keys2.push(obj);
392
426
  map2[obj] = key;
393
427
  }
394
428
 
@@ -398,17 +432,21 @@ class Hash
398
432
 
399
433
  def keep_if(&block)
400
434
  %x{
401
- var map = #{self}.map, value;
435
+ var map = #{self}.map, keys = #{self}.keys, value;
402
436
 
403
- for (var key in map) {
404
- var obj = map[key];
437
+ for (var i = 0, length = keys.length; i < length; i++) {
438
+ var key = keys[i], obj = map[key];
405
439
 
406
440
  if ((value = block(key, obj)) === __breaker) {
407
441
  return __breaker.$v;
408
442
  }
409
443
 
410
444
  if (value === false || value === nil) {
445
+ keys.splice(i, 1);
411
446
  delete map[key];
447
+
448
+ length--;
449
+ i--;
412
450
  }
413
451
  }
414
452
 
@@ -422,25 +460,13 @@ class Hash
422
460
 
423
461
  def keys
424
462
  %x{
425
- var result = [], map = #{self}.map;
426
-
427
- for (var key in map) {
428
- result.push(key);
429
- }
430
-
431
- return result;
463
+ return #{self}.keys.slice(0);
432
464
  }
433
465
  end
434
466
 
435
467
  def length
436
468
  %x{
437
- var length = 0, map = #{self}.map;
438
-
439
- for (var key in map) {
440
- length++;
441
- }
442
-
443
- return length;
469
+ return #{self}.keys.length;
444
470
  }
445
471
  end
446
472
 
@@ -448,22 +474,35 @@ class Hash
448
474
 
449
475
  def merge(other, &block)
450
476
  %x{
451
- var map = #{self}.map, result = __hash(), map2 = result.map;
477
+ var keys = #{self}.keys, map = #{self}.map,
478
+ result = __hash(), keys2 = result.keys, map2 = result.map;
452
479
 
453
- for (var key in map) {
480
+ for (var i = 0, length = keys.length; i < length; i++) {
481
+ var key = keys[i];
482
+
483
+ keys2.push(key);
454
484
  map2[key] = map[key];
455
485
  }
456
486
 
457
- map = other.map;
487
+ var keys = other.keys, map = other.map;
458
488
 
459
489
  if (block === nil) {
460
- for (key in map) {
490
+ for (var i = 0, length = keys.length; i < length; i++) {
491
+ var key = keys[i];
492
+
493
+ if (map2[key] == null) {
494
+ keys2.push(key);
495
+ }
496
+
461
497
  map2[key] = map[key];
462
498
  }
463
499
  }
464
500
  else {
465
- for (key in map) {
501
+ for (var i = 0, length = keys.length; i < length; i++) {
502
+ var key = keys[i];
503
+
466
504
  if (map2[key] == null) {
505
+ keys2.push(key);
467
506
  map2[key] = map[key];
468
507
  }
469
508
  else {
@@ -478,16 +517,26 @@ class Hash
478
517
 
479
518
  def merge!(other, &block)
480
519
  %x{
481
- var map = #{self}.map, map2 = other.map;
520
+ var keys = #{self}.keys, map = #{self}.map,
521
+ keys2 = other.keys, map2 = other.map;
482
522
 
483
523
  if (block === nil) {
484
- for (var key in map2) {
524
+ for (var i = 0, length = keys2.length; i < length; i++) {
525
+ var key = keys2[i];
526
+
527
+ if (map[key] == null) {
528
+ keys.push(key);
529
+ }
530
+
485
531
  map[key] = map2[key];
486
532
  }
487
533
  }
488
534
  else {
489
- for (key in map2) {
535
+ for (var i = 0, length = keys2.length; i < length; i++) {
536
+ var key = keys2[i];
537
+
490
538
  if (map[key] == null) {
539
+ keys.push(key);
491
540
  map[key] = map2[key];
492
541
  }
493
542
  else {
@@ -502,10 +551,10 @@ class Hash
502
551
 
503
552
  def rassoc(object)
504
553
  %x{
505
- var map = #{self}.map;
554
+ var keys = #{self}.keys, map = #{self}.map;
506
555
 
507
- for (var key in map) {
508
- var obj = map[key];
556
+ for (var i = 0, length = keys.length; i < length; i++) {
557
+ var key = keys[i], obj = map[key];
509
558
 
510
559
  if (#{`obj` == object}) {
511
560
  return [key, obj];
@@ -518,16 +567,18 @@ class Hash
518
567
 
519
568
  def reject(&block)
520
569
  %x{
521
- var map = #{self}.map, result = __hash(), map2 = result.map;
570
+ var keys = #{self}.keys, map = #{self}.map,
571
+ result = __hash(), map2 = result.map, keys2 = result.keys;
522
572
 
523
- for (var key in map) {
524
- var obj = map[key], value;
573
+ for (var i = 0, length = keys.length; i < length; i++) {
574
+ var key = keys[i], obj = map[key], value;
525
575
 
526
576
  if ((value = block(key, obj)) === __breaker) {
527
577
  return __breaker.$v;
528
578
  }
529
579
 
530
580
  if (value === false || value === nil) {
581
+ keys2.push(key);
531
582
  map2[key] = obj;
532
583
  }
533
584
  }
@@ -538,10 +589,12 @@ class Hash
538
589
 
539
590
  def replace(other)
540
591
  %x{
541
- var map = #{self}.map = {}, map2 = other.map;
592
+ var map = #{self}.map = {}, keys = #{self}.keys = [];
542
593
 
543
- for (var key in map2) {
544
- map[key] = map2[key];
594
+ for (var i = 0, length = other.keys.length; i < length; i++) {
595
+ var key = other.keys[i];
596
+ keys.push(key);
597
+ map[key] = other.map[key];
545
598
  }
546
599
 
547
600
  return #{self};
@@ -550,16 +603,18 @@ class Hash
550
603
 
551
604
  def select(&block)
552
605
  %x{
553
- var map = #{self}.map, result = __hash(), map2 = result.map;
606
+ var keys = #{self}.keys, map = #{self}.map,
607
+ result = __hash(), map2 = result.map, keys2 = result.keys;
554
608
 
555
- for (var key in map) {
556
- var obj = map[key], value;
609
+ for (var i = 0, length = keys.length; i < length; i++) {
610
+ var key = keys[i], obj = map[key], value;
557
611
 
558
612
  if ((value = block(key, obj)) === __breaker) {
559
613
  return __breaker.$v;
560
614
  }
561
615
 
562
616
  if (value !== false && value !== nil) {
617
+ keys2.push(key);
563
618
  map2[key] = obj;
564
619
  }
565
620
  }
@@ -570,18 +625,21 @@ class Hash
570
625
 
571
626
  def select!(&block)
572
627
  %x{
573
- var map = #{self}.map, value, result = nil;
628
+ var map = #{self}.map, keys = #{self}.keys, value, result = nil;
574
629
 
575
- for (var key in map) {
576
- var obj = map[key];
630
+ for (var i = 0, length = keys.length; i < length; i++) {
631
+ var key = keys[i], obj = map[key];
577
632
 
578
633
  if ((value = block(key, obj)) === __breaker) {
579
634
  return __breaker.$v;
580
635
  }
581
636
 
582
637
  if (value === false || value === nil) {
638
+ keys.splice(i, 1);
583
639
  delete map[key];
584
640
 
641
+ length--;
642
+ i--;
585
643
  result = #{self}
586
644
  }
587
645
  }
@@ -592,11 +650,14 @@ class Hash
592
650
 
593
651
  def shift
594
652
  %x{
595
- var map = #{self}.map;
653
+ var keys = #{self}.keys, map = #{self}.map;
654
+
655
+ if (keys.length) {
656
+ var key = keys[0], obj = map[key];
596
657
 
597
- for (var key in map) {
598
- var obj = map[key];
599
658
  delete map[key];
659
+ keys.splice(0, 1);
660
+
600
661
  return [key, obj];
601
662
  }
602
663
 
@@ -608,9 +669,10 @@ class Hash
608
669
 
609
670
  def to_a
610
671
  %x{
611
- var map = #{self}.map, result = [];
672
+ var keys = #{self}.keys, map = #{self}.map, result = [];
612
673
 
613
- for (var key in map) {
674
+ for (var i = 0, length = keys.length; i < length; i++) {
675
+ var key = keys[i];
614
676
  result.push([key, map[key]]);
615
677
  }
616
678
 
@@ -624,9 +686,10 @@ class Hash
624
686
 
625
687
  def to_json
626
688
  %x{
627
- var inspect = [], map = #{self}.map;
689
+ var inspect = [], keys = #{self}.keys, map = #{self}.map;
628
690
 
629
- for (var key in map) {
691
+ for (var i = 0, length = keys.length; i < length; i++) {
692
+ var key = keys[i];
630
693
  inspect.push(#{`key`.to_json} + ': ' + #{`map[key]`.to_json});
631
694
  }
632
695
 
@@ -636,10 +699,10 @@ class Hash
636
699
 
637
700
  def to_native
638
701
  %x{
639
- var result = {}, map = #{self}.map;
702
+ var result = {}, keys = #{self}.keys, map = #{self}.map, bucket, value;
640
703
 
641
- for (var key in map) {
642
- var obj = map[key];
704
+ for (var i = 0, length = keys.length; i < length; i++) {
705
+ var key = keys[i], obj = map[key];
643
706
 
644
707
  if (obj.$to_native) {
645
708
  result[key] = #{`obj`.to_native};