opal 0.5.0 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +0 -2
  3. data/README.md +1 -1
  4. data/Rakefile +11 -8
  5. data/lib/opal.rb +1 -1
  6. data/lib/opal/version.rb +1 -1
  7. data/opal.gemspec +1 -1
  8. data/{corelib → opal/core}/array.rb +47 -40
  9. data/{corelib → opal/core}/basic_object.rb +4 -0
  10. data/{corelib → opal/core}/boolean.rb +2 -6
  11. data/{corelib → opal/core}/class.rb +0 -0
  12. data/{corelib → opal/core}/comparable.rb +0 -0
  13. data/{corelib → opal/core}/encoding.rb +0 -0
  14. data/{corelib → opal/core}/enumerable.rb +160 -38
  15. data/opal/core/enumerator.rb +416 -0
  16. data/{corelib → opal/core}/error.rb +0 -0
  17. data/{corelib → opal/core}/hash.rb +38 -48
  18. data/{corelib → opal/core}/io.rb +13 -9
  19. data/{corelib → opal/core}/kernel.rb +75 -49
  20. data/{corelib → opal/core}/main.rb +0 -0
  21. data/{corelib → opal/core}/match_data.rb +0 -4
  22. data/{corelib → opal/core}/method.rb +0 -0
  23. data/{corelib → opal/core}/module.rb +24 -3
  24. data/{corelib → opal/core}/nil_class.rb +0 -4
  25. data/{corelib → opal/core}/numeric.rb +3 -4
  26. data/{corelib → opal/core}/proc.rb +0 -4
  27. data/{corelib → opal/core}/range.rb +0 -0
  28. data/{corelib → opal/core}/regexp.rb +0 -4
  29. data/{corelib → opal/core}/runtime.js +0 -0
  30. data/{corelib → opal/core}/string.rb +4 -6
  31. data/{corelib → opal/core}/struct.rb +3 -21
  32. data/{corelib → opal/core}/time.rb +0 -4
  33. data/opal/opal.rb +121 -0
  34. data/spec/corelib/array/select_spec.rb +14 -0
  35. data/spec/filters/20.rb +4 -0
  36. data/spec/filters/bugs/enumerable.rb +1 -48
  37. data/spec/filters/unsupported/enumerator.rb +13 -0
  38. data/spec/opal/compiler/irb_spec.rb +1 -0
  39. data/spec/rubyspecs +1 -0
  40. data/spec/{corelib → stdlib}/native/alias_native_spec.rb +6 -4
  41. data/spec/{corelib → stdlib}/native/each_spec.rb +3 -1
  42. data/spec/{corelib → stdlib}/native/element_reference_spec.rb +3 -1
  43. data/spec/stdlib/native/ext_spec.rb +19 -0
  44. data/spec/{corelib → stdlib}/native/initialize_spec.rb +4 -4
  45. data/spec/{corelib → stdlib}/native/method_missing_spec.rb +13 -1
  46. data/spec/{corelib → stdlib}/native/new_spec.rb +3 -1
  47. data/stdlib/enumerator.rb +1 -0
  48. data/stdlib/json.rb +1 -1
  49. data/stdlib/native.rb +483 -0
  50. metadata +52 -47
  51. data/corelib/enumerator.rb +0 -55
  52. data/corelib/native.rb +0 -270
  53. data/corelib/opal.rb +0 -88
  54. data/spec/corelib/native/ext_spec.rb +0 -5
  55. data/spec/filters/bugs/enumerator.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: fdf74450cbd2b81a0d8ba44700ef6e0e77b5ca45
4
- data.tar.gz: 01e6a0e881a43bdaa1eb4db93c0e1989ca1d4568
3
+ metadata.gz: 8fd073f86d2b6572a34ed96ac1e8bc35e14be214
4
+ data.tar.gz: 5f55dcc5f1e555bc2d53afababdfedd8a1fc480e
5
5
  SHA512:
6
- metadata.gz: 90d5d6913908ef1d38f69d029d6033fbcd0d2214035a3cf34ebe5c5d8725e2bd37689009dbbd28e99ca27f9069cfe09b44445a0a3710e3d0e71f0d1ce00dd72b
7
- data.tar.gz: bca3fd06513433d71ff656a473acf3269caa301a55589fdccea45cc463d9f865b6d558bbc1f427552f46586172f6f053cf6396cb5bbe193aa2e5b113783d0a86
6
+ metadata.gz: 8db2e2f1545e635e7822d52fe6a009ac2d50d335bd7a2855e0ac44f5eff366171106eec3d783ef3600924d60d28c042d634056119b594f54fa44d1f600952776
7
+ data.tar.gz: ba90ff768744ca87c6d5a54070292d6d6877dfbf4c3c21bdaa3fe73d13258acfaeea85bf8900251b42d325ce78a7b80b1479606cd1ec504516dd7bb4595f86f3
data/Gemfile CHANGED
@@ -1,8 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
  gemspec
3
3
 
4
- gem 'opal-sprockets', :github => 'opal/opal-sprockets'
5
-
6
4
  # Stick with older racc until
7
5
  # https://github.com/tenderlove/racc/issues/32
8
6
  # is solved.
data/README.md CHANGED
@@ -71,7 +71,7 @@ visit `http://localhost:9292/` in any web browser.
71
71
  What code is supposed to run where?
72
72
 
73
73
  * `lib/` code runs inside your ruby env. It compiles ruby to javascript.
74
- * `corelib/` is the runtime/corelib for our implementation (runs in browser)
74
+ * `opal/` is the runtime/corelib for our implementation (runs in browser)
75
75
  * `stdlib/` is our implementation of ruby stdlib. It is optional (for browser).
76
76
 
77
77
  ### lib
data/Rakefile CHANGED
@@ -54,9 +54,12 @@ task :dist do
54
54
  env = Opal::Environment.new
55
55
 
56
56
  Dir.mkdir 'build' unless File.directory? 'build'
57
+ libs = Dir['{opal,stdlib}/*.rb'].map { |lib| File.basename(lib, '.rb') }
58
+ width = libs.map(&:size).max
57
59
 
58
- %w[opal opal-parser].each do |lib|
59
- puts "* building #{lib}..."
60
+ libs.each do |lib|
61
+ print "* building #{lib}...".ljust(width+'* building ... '.size)
62
+ $stdout.flush
60
63
 
61
64
  src = env[lib].to_s
62
65
  min = uglify src
@@ -66,11 +69,11 @@ task :dist do
66
69
  File.open("build/#{lib}.min.js", 'w+') { |f| f << min } if min
67
70
  File.open("build/#{lib}.min.js.gz", 'w+') { |f| f << gzp } if gzp
68
71
 
69
- print "done. (development: #{src.size}B"
70
- print ", minified: #{min.size}B" if min
71
- print ", gzipped: #{gzp.size}Bx" if gzp
72
+ print "done. ("
73
+ print "development: #{('%.2f' % (src.size/1000.0)).rjust(6)}KB"
74
+ print ", minified: #{('%.2f' % (min.size/1000.0)).rjust(6)}KB" if min
75
+ print ", gzipped: #{('%.2f' % (gzp.size/1000.0)).rjust(6)}KB" if gzp
72
76
  puts ")."
73
- puts
74
77
  end
75
78
  end
76
79
 
@@ -81,7 +84,7 @@ end
81
84
 
82
85
  # Used for uglifying source to minify
83
86
  def uglify(str)
84
- IO.popen('uglifyjs', 'r+') do |i|
87
+ IO.popen('uglifyjs 2> /dev/null', 'r+') do |i|
85
88
  i.puts str
86
89
  i.close_write
87
90
  return i.read
@@ -93,7 +96,7 @@ end
93
96
 
94
97
  # Gzip code to check file size
95
98
  def gzip(str)
96
- IO.popen('gzip -f', 'r+') do |i|
99
+ IO.popen('gzip -f 2> /dev/null', 'r+') do |i|
97
100
  i.puts str
98
101
  i.close_write
99
102
  return i.read
data/lib/opal.rb CHANGED
@@ -16,7 +16,7 @@ module Opal
16
16
  end
17
17
 
18
18
  def self.core_dir
19
- File.expand_path('../../corelib', __FILE__.untaint)
19
+ File.expand_path('../../opal', __FILE__.untaint)
20
20
  end
21
21
 
22
22
  def self.std_dir
data/lib/opal/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Opal
2
- VERSION = '0.5.0'
2
+ VERSION = '0.5.2'
3
3
  end
data/opal.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |s|
22
22
  s.add_development_dependency 'mspec', '1.5.20'
23
23
  s.add_development_dependency 'rake'
24
24
  s.add_development_dependency 'racc'
25
- s.add_development_dependency 'opal-sprockets', '~> 0.2.1'
25
+ s.add_development_dependency 'opal-sprockets', '~> 0.3.0'
26
26
  s.add_development_dependency 'rspec', '~> 2.14'
27
27
  s.add_development_dependency 'octokit', '~> 2.4.0'
28
28
  end
@@ -353,27 +353,42 @@ class Array
353
353
  end
354
354
 
355
355
  def cycle(n = nil, &block)
356
- return if `self.length === 0 || n === 0`
356
+ return if empty? || n == 0
357
+
357
358
  return enum_for :cycle, n unless block
358
359
 
359
- if `n === nil`
360
- while true
361
- if `#{(value = each(&block))} !== self`
362
- return value
363
- end
364
- end
360
+ if n.nil?
361
+ %x{
362
+ while (true) {
363
+ for (var i = 0, length = self.length; i < length; i++) {
364
+ var value = $opal.$yield1(block, self[i]);
365
+
366
+ if (value === $breaker) {
367
+ return $breaker.$v;
368
+ }
369
+ }
370
+ }
371
+ }
365
372
  else
366
- cycles = Opal.coerce_to n, Integer, :to_int
373
+ n = Opal.coerce_to! n, Integer, :to_int
367
374
 
368
- unless Integer === cycles
369
- raise TypeError, "can't convert #{n.class} into Integer (#{n.class}#to_int gives #{cycles.class}"
370
- end
375
+ %x{
376
+ if (n <= 0) {
377
+ return self;
378
+ }
371
379
 
372
- while cycles > 0
373
- each(&block)
380
+ while (n > 0) {
381
+ for (var i = 0, length = self.length; i < length; i++) {
382
+ var value = $opal.$yield1(block, self[i]);
374
383
 
375
- cycles -= 1
376
- end
384
+ if (value === $breaker) {
385
+ return $breaker.$v;
386
+ }
387
+ }
388
+
389
+ n--;
390
+ }
391
+ }
377
392
  end
378
393
 
379
394
  self
@@ -459,6 +474,12 @@ class Array
459
474
  end
460
475
 
461
476
  def concat(other)
477
+ if Array === other
478
+ other = other.to_a
479
+ else
480
+ other = Opal.coerce_to other, Array, :to_ary
481
+ end
482
+
462
483
  %x{
463
484
  for (var i = 0, length = other.length; i < length; i++) {
464
485
  self.push(other[i]);
@@ -592,7 +613,12 @@ class Array
592
613
  return defaults;
593
614
  }
594
615
 
595
- #{ raise IndexError, "Array#fetch" };
616
+ if (self.length === 0) {
617
+ #{raise IndexError, "index #{`original`} outside of array bounds: 0...0"}
618
+ }
619
+ else {
620
+ #{raise IndexError, "index #{`original`} outside of array bounds: -#{`self.length`}...#{`self.length`}"};
621
+ }
596
622
  }
597
623
  end
598
624
 
@@ -707,17 +733,17 @@ class Array
707
733
  for (var i = 0, length = self.length; i < length; i++) {
708
734
  var item = self[i];
709
735
 
710
- if (#{`item`.respond_to?(:to_ary)}) {
736
+ if (#{`item`.respond_to? :to_ary}) {
711
737
  item = #{`item`.to_ary};
712
738
 
713
739
  if (level == null) {
714
- result = result.concat(#{`item`.flatten});
740
+ result.push.apply(result, #{`item`.flatten.to_a});
715
741
  }
716
- else if (level === 0) {
742
+ else if (level == 0) {
717
743
  result.push(item);
718
744
  }
719
745
  else {
720
- result = result.concat(#{`item`.flatten(`level - 1`)});
746
+ result.push.apply(result, #{`item`.flatten(`level - 1`).to_a});
721
747
  }
722
748
  }
723
749
  else {
@@ -1056,7 +1082,7 @@ class Array
1056
1082
  for (var i = 0, length = self.length, item, value; i < length; i++) {
1057
1083
  item = self[i];
1058
1084
 
1059
- if ((value = block(item)) === $breaker) {
1085
+ if ((value = $opal.$yield1(block, item)) === $breaker) {
1060
1086
  return $breaker.$v;
1061
1087
  }
1062
1088
 
@@ -1222,25 +1248,6 @@ class Array
1222
1248
 
1223
1249
  alias to_ary to_a
1224
1250
 
1225
- def to_n
1226
- %x{
1227
- var result = [], obj
1228
-
1229
- for (var i = 0, len = self.length; i < len; i++) {
1230
- obj = self[i];
1231
-
1232
- if (#{`obj`.respond_to? :to_n}) {
1233
- result.push(#{`obj`.to_n});
1234
- }
1235
- else {
1236
- result.push(obj);
1237
- }
1238
- }
1239
-
1240
- return result;
1241
- }
1242
- end
1243
-
1244
1251
  alias to_s inspect
1245
1252
 
1246
1253
  def transpose
@@ -6,6 +6,10 @@ class BasicObject
6
6
  `self === other`
7
7
  end
8
8
 
9
+ def __id__
10
+ `self._id || (self._id = Opal.uid())`
11
+ end
12
+
9
13
  def __send__(symbol, *args, &block)
10
14
  %x{
11
15
  var func = self['$' + symbol]
@@ -28,14 +28,10 @@ class Boolean
28
28
  def to_s
29
29
  `(self == true) ? 'true' : 'false'`
30
30
  end
31
-
32
- def to_n
33
- `self.valueOf()`
34
- end
35
31
  end
36
32
 
37
- TrueClass = Boolean
33
+ TrueClass = Boolean
38
34
  FalseClass = Boolean
39
35
 
40
- TRUE = true
36
+ TRUE = true
41
37
  FALSE = false
File without changes
File without changes
File without changes
@@ -122,6 +122,71 @@ module Enumerable
122
122
  }
123
123
  end
124
124
 
125
+ def cycle(n = nil, &block)
126
+ return enum_for :cycle, n unless block
127
+
128
+ unless n.nil?
129
+ n = Opal.coerce_to! n, Integer, :to_int
130
+
131
+ return if `n <= 0`
132
+ end
133
+
134
+ %x{
135
+ var result,
136
+ all = [];
137
+
138
+ self.$each._p = function() {
139
+ var param = #{Opal.destructure(`arguments`)},
140
+ value = $opal.$yield1(block, param);
141
+
142
+ if (value === $breaker) {
143
+ result = $breaker.$v;
144
+ return $breaker;
145
+ }
146
+
147
+ all.push(param);
148
+ }
149
+
150
+ self.$each();
151
+
152
+ if (result !== undefined) {
153
+ return result;
154
+ }
155
+
156
+ if (all.length === 0) {
157
+ return nil;
158
+ }
159
+ }
160
+
161
+ if n.nil?
162
+ %x{
163
+ while (true) {
164
+ for (var i = 0, length = all.length; i < length; i++) {
165
+ var value = $opal.$yield1(block, all[i]);
166
+
167
+ if (value === $breaker) {
168
+ return $breaker.$v;
169
+ }
170
+ }
171
+ }
172
+ }
173
+ else
174
+ %x{
175
+ while (n > 1) {
176
+ for (var i = 0, length = all.length; i < length; i++) {
177
+ var value = $opal.$yield1(block, all[i]);
178
+
179
+ if (value === $breaker) {
180
+ return $breaker.$v;
181
+ }
182
+ }
183
+
184
+ n--;
185
+ }
186
+ }
187
+ end
188
+ end
189
+
125
190
  def detect(ifnone = undefined, &block)
126
191
  return enum_for :detect, ifnone unless block_given?
127
192
 
@@ -170,7 +235,7 @@ module Enumerable
170
235
  current = 0;
171
236
 
172
237
  self.$each._p = function() {
173
- if (number < current) {
238
+ if (number <= current) {
174
239
  result.push(#{Opal.destructure(`arguments`)});
175
240
  }
176
241
 
@@ -187,22 +252,28 @@ module Enumerable
187
252
  return enum_for :drop_while unless block_given?
188
253
 
189
254
  %x{
190
- var result = [];
255
+ var result = [],
256
+ dropping = true;
191
257
 
192
258
  self.$each._p = function() {
193
- var param = #{Opal.destructure(`arguments`)},
194
- value = $opal.$yield1(block, param);
259
+ var param = #{Opal.destructure(`arguments`)};
195
260
 
196
- if (value === $breaker) {
197
- result = $breaker.$v;
198
- return $breaker;
199
- }
261
+ if (dropping) {
262
+ var value = $opal.$yield1(block, param);
200
263
 
201
- if (#{Opal.truthy?(`value`)}) {
202
- return;
203
- }
264
+ if (value === $breaker) {
265
+ result = $breaker.$v;
266
+ return $breaker;
267
+ }
204
268
 
205
- result.push(param);
269
+ if (#{Opal.falsy?(`value`)}) {
270
+ dropping = false;
271
+ result.push(param);
272
+ }
273
+ }
274
+ else {
275
+ result.push(param);
276
+ }
206
277
  };
207
278
 
208
279
  self.$each();
@@ -214,6 +285,10 @@ module Enumerable
214
285
  def each_slice(n, &block)
215
286
  n = Opal.coerce_to n, Integer, :to_int
216
287
 
288
+ if `n <= 0`
289
+ raise ArgumentError, 'invalid slice size'
290
+ end
291
+
217
292
  return enum_for :each_slice, n unless block_given?
218
293
 
219
294
  %x{
@@ -252,8 +327,8 @@ module Enumerable
252
327
  nil
253
328
  end
254
329
 
255
- def each_with_index(&block)
256
- return enum_for :each_with_index unless block_given?
330
+ def each_with_index(*args, &block)
331
+ return enum_for :each_with_index, *args unless block_given?
257
332
 
258
333
  %x{
259
334
  var result,
@@ -271,14 +346,14 @@ module Enumerable
271
346
  index++;
272
347
  };
273
348
 
274
- self.$each();
349
+ self.$each.apply(self, args);
275
350
 
276
351
  if (result !== undefined) {
277
352
  return result;
278
353
  }
279
354
  }
280
355
 
281
- nil
356
+ self
282
357
  end
283
358
 
284
359
  def each_with_object(object, &block)
@@ -307,7 +382,7 @@ module Enumerable
307
382
  object
308
383
  end
309
384
 
310
- def entries
385
+ def entries(*args)
311
386
  %x{
312
387
  var result = [];
313
388
 
@@ -315,7 +390,7 @@ module Enumerable
315
390
  result.push(#{Opal.destructure(`arguments`)});
316
391
  };
317
392
 
318
- self.$each();
393
+ self.$each.apply(self, args);
319
394
 
320
395
  return result;
321
396
  }
@@ -393,35 +468,47 @@ module Enumerable
393
468
  end
394
469
 
395
470
  def first(number = undefined)
396
- %x{
397
- if (number == null) {
398
- var result = nil;
471
+ if `number === undefined`
472
+ result = nil
399
473
 
474
+ %x{
400
475
  self.$each._p = function() {
401
476
  result = #{Opal.destructure(`arguments`)};
477
+
402
478
  return $breaker;
403
479
  };
480
+
481
+ self.$each();
404
482
  }
405
- else {
483
+ else
484
+ result = []
485
+ number = Opal.coerce_to number, Integer, :to_int
486
+
487
+ if `number < 0`
488
+ raise ArgumentError, 'attempt to take negative size'
489
+ end
490
+
491
+ if `number == 0`
492
+ return []
493
+ end
494
+
495
+ %x{
406
496
  var current = 0,
407
- result = [],
408
497
  number = #{Opal.coerce_to number, Integer, :to_int};
409
498
 
410
499
  self.$each._p = function() {
411
- if (number <= current) {
412
- return $breaker;
413
- }
414
-
415
500
  result.push(#{Opal.destructure(`arguments`)});
416
501
 
417
- current++;
502
+ if (number <= ++current) {
503
+ return $breaker;
504
+ }
418
505
  };
419
- }
420
506
 
421
- self.$each();
507
+ self.$each();
508
+ }
509
+ end
422
510
 
423
- return result;
424
- }
511
+ result
425
512
  end
426
513
 
427
514
  def grep(pattern, &block)
@@ -465,7 +552,7 @@ module Enumerable
465
552
  def group_by(&block)
466
553
  return enum_for :group_by unless block_given?
467
554
 
468
- hash = Hash.new { |h, k| h[k] = [] }
555
+ hash = Hash.new
469
556
 
470
557
  %x{
471
558
  var result;
@@ -479,7 +566,7 @@ module Enumerable
479
566
  return $breaker;
480
567
  }
481
568
 
482
- #{hash[`value`] << `param`};
569
+ #{(hash[`value`] ||= []) << `param`};
483
570
  }
484
571
 
485
572
  self.$each();
@@ -493,14 +580,29 @@ module Enumerable
493
580
  end
494
581
 
495
582
  def include?(obj)
496
- any? { |v| v == obj }
583
+ %x{
584
+ var result = false;
585
+
586
+ self.$each._p = function() {
587
+ var param = #{Opal.destructure(`arguments`)};
588
+
589
+ if (#{`param` == obj}) {
590
+ result = true;
591
+ return $breaker;
592
+ }
593
+ }
594
+
595
+ self.$each();
596
+
597
+ return result;
598
+ }
497
599
  end
498
600
 
499
601
  def inject(object = undefined, sym = undefined, &block)
500
602
  %x{
501
603
  var result = object;
502
604
 
503
- if (block !== nil) {
605
+ if (block !== nil && sym === undefined) {
504
606
  self.$each._p = function() {
505
607
  var value = #{Opal.destructure(`arguments`)};
506
608
 
@@ -547,6 +649,18 @@ module Enumerable
547
649
  }
548
650
  end
549
651
 
652
+ def lazy
653
+ Enumerator::Lazy.new(self, enumerator_size) {|enum, *args|
654
+ enum.yield(*args)
655
+ }
656
+ end
657
+
658
+ def enumerator_size
659
+ respond_to?(:size) ? size : nil
660
+ end
661
+
662
+ private :enumerator_size
663
+
550
664
  alias map collect
551
665
 
552
666
  def max(&block)
@@ -569,6 +683,10 @@ module Enumerable
569
683
  return $breaker;
570
684
  }
571
685
 
686
+ if (value === nil) {
687
+ #{raise ArgumentError, "comparison failed"};
688
+ }
689
+
572
690
  if (value > 0) {
573
691
  result = param;
574
692
  }
@@ -583,7 +701,7 @@ module Enumerable
583
701
  return;
584
702
  }
585
703
 
586
- if (#{`param` <=> `result`} > 0) {
704
+ if (#{Opal.compare(`param`, `result`)} > 0) {
587
705
  result = param;
588
706
  }
589
707
  };
@@ -651,6 +769,10 @@ module Enumerable
651
769
  return $breaker;
652
770
  }
653
771
 
772
+ if (value === nil) {
773
+ #{raise ArgumentError, "comparison failed"};
774
+ }
775
+
654
776
  if (value < 0) {
655
777
  result = param;
656
778
  }
@@ -665,7 +787,7 @@ module Enumerable
665
787
  return;
666
788
  }
667
789
 
668
- if (#{`param` <=> `result`} < 0) {
790
+ if (#{Opal.compare(`param`, `result`)} < 0) {
669
791
  result = param;
670
792
  }
671
793
  };