opal 0.3.37 → 0.3.38

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