opal 1.3.1 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (243) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.js +1 -0
  3. data/.github/workflows/build.yml +20 -21
  4. data/.rubocop.yml +5 -1
  5. data/CHANGELOG.md +119 -11
  6. data/UNRELEASED.md +4 -9
  7. data/benchmark-ips/bm_truthy.rb +30 -0
  8. data/bin/opal-mspec +1 -3
  9. data/bin/opal-repl +1 -2
  10. data/bin/remove-filters +1 -4
  11. data/docs/compiled_ruby.md +37 -22
  12. data/docs/faq.md +1 -1
  13. data/docs/headless_chrome.md +11 -21
  14. data/docs/jquery.md +1 -6
  15. data/docs/opal_parser.md +3 -1
  16. data/docs/promises.md +2 -0
  17. data/docs/releasing.md +3 -0
  18. data/docs/roda-sprockets.md +0 -1
  19. data/docs/source_maps.md +10 -11
  20. data/docs/static_applications.md +2 -2
  21. data/docs/unsupported_features.md +4 -0
  22. data/exe/opal-repl +1 -3
  23. data/lib/opal/ast/builder.rb +1 -1
  24. data/lib/opal/cli.rb +2 -2
  25. data/lib/opal/cli_runners/nodejs.rb +9 -2
  26. data/lib/opal/cli_runners/source-map-support-browser.js +80 -216
  27. data/lib/opal/cli_runners/source-map-support-node.js +80 -216
  28. data/lib/opal/cli_runners/source-map-support.js +5 -1
  29. data/lib/opal/cli_runners/system_runner.rb +10 -4
  30. data/lib/opal/compiler.rb +3 -5
  31. data/lib/opal/fragment.rb +5 -1
  32. data/lib/opal/nodes/args/extract_block_arg.rb +1 -8
  33. data/lib/opal/nodes/args/extract_kwoptarg.rb +1 -3
  34. data/lib/opal/nodes/args/extract_optarg.rb +1 -3
  35. data/lib/opal/nodes/args/extract_post_arg.rb +2 -5
  36. data/lib/opal/nodes/args/extract_post_optarg.rb +2 -7
  37. data/lib/opal/nodes/args/initialize_iterarg.rb +1 -3
  38. data/lib/opal/nodes/args/prepare_post_args.rb +5 -1
  39. data/lib/opal/nodes/base.rb +3 -2
  40. data/lib/opal/nodes/call.rb +20 -9
  41. data/lib/opal/nodes/call_special.rb +50 -0
  42. data/lib/opal/nodes/class.rb +24 -15
  43. data/lib/opal/nodes/constants.rb +23 -5
  44. data/lib/opal/nodes/def.rb +20 -23
  45. data/lib/opal/nodes/defined.rb +5 -5
  46. data/lib/opal/nodes/definitions.rb +2 -2
  47. data/lib/opal/nodes/defs.rb +2 -5
  48. data/lib/opal/nodes/helpers.rb +48 -18
  49. data/lib/opal/nodes/if.rb +113 -8
  50. data/lib/opal/nodes/iter.rb +23 -16
  51. data/lib/opal/nodes/literal.rb +18 -4
  52. data/lib/opal/nodes/logic.rb +2 -1
  53. data/lib/opal/nodes/masgn.rb +4 -9
  54. data/lib/opal/nodes/module.rb +29 -19
  55. data/lib/opal/nodes/node_with_args.rb +1 -7
  56. data/lib/opal/nodes/scope.rb +54 -15
  57. data/lib/opal/nodes/singleton_class.rb +5 -3
  58. data/lib/opal/nodes/super.rb +12 -12
  59. data/lib/opal/nodes/top.rb +34 -31
  60. data/lib/opal/nodes/variables.rb +2 -2
  61. data/lib/opal/nodes/x_string.rb +30 -28
  62. data/lib/opal/nodes.rb +0 -1
  63. data/lib/opal/parser/patch.rb +75 -0
  64. data/lib/opal/parser/with_ruby_lexer.rb +1 -1
  65. data/lib/opal/regexp_anchors.rb +7 -7
  66. data/lib/opal/requires.rb +19 -0
  67. data/lib/opal/rewriters/pattern_matching.rb +1 -1
  68. data/lib/opal/rewriters/returnable_logic.rb +102 -4
  69. data/lib/opal/util.rb +2 -2
  70. data/lib/opal/version.rb +1 -1
  71. data/lib/opal.rb +1 -17
  72. data/opal/corelib/array/pack.rb +11 -11
  73. data/opal/corelib/array.rb +193 -152
  74. data/opal/corelib/basic_object.rb +19 -15
  75. data/opal/corelib/binding.rb +7 -7
  76. data/opal/corelib/boolean.rb +12 -15
  77. data/opal/corelib/class.rb +23 -1
  78. data/opal/corelib/comparable.rb +8 -8
  79. data/opal/corelib/complex/base.rb +2 -2
  80. data/opal/corelib/complex.rb +79 -88
  81. data/opal/corelib/constants.rb +9 -9
  82. data/opal/corelib/dir.rb +4 -3
  83. data/opal/corelib/enumerable.rb +140 -127
  84. data/opal/corelib/enumerator/arithmetic_sequence.rb +177 -0
  85. data/opal/corelib/enumerator/chain.rb +42 -0
  86. data/opal/corelib/enumerator/generator.rb +35 -0
  87. data/opal/corelib/enumerator/lazy.rb +243 -0
  88. data/opal/corelib/enumerator/yielder.rb +36 -0
  89. data/opal/corelib/enumerator.rb +45 -300
  90. data/opal/corelib/error/errno.rb +47 -0
  91. data/opal/corelib/error.rb +62 -60
  92. data/opal/corelib/file.rb +26 -12
  93. data/opal/corelib/hash.rb +98 -107
  94. data/opal/corelib/helpers.rb +62 -13
  95. data/opal/corelib/io.rb +48 -35
  96. data/opal/corelib/kernel/format.rb +29 -29
  97. data/opal/corelib/kernel.rb +86 -83
  98. data/opal/corelib/main.rb +14 -12
  99. data/opal/corelib/marshal/read_buffer.rb +15 -15
  100. data/opal/corelib/marshal/write_buffer.rb +45 -44
  101. data/opal/corelib/marshal.rb +3 -3
  102. data/opal/corelib/math.rb +50 -50
  103. data/opal/corelib/method.rb +12 -8
  104. data/opal/corelib/module.rb +79 -75
  105. data/opal/corelib/nil.rb +9 -11
  106. data/opal/corelib/number.rb +113 -118
  107. data/opal/corelib/numeric.rb +37 -33
  108. data/opal/corelib/object_space.rb +11 -10
  109. data/opal/corelib/pack_unpack/format_string_parser.rb +3 -3
  110. data/opal/corelib/pattern_matching/base.rb +7 -7
  111. data/opal/corelib/pattern_matching.rb +1 -1
  112. data/opal/corelib/proc.rb +15 -16
  113. data/opal/corelib/process/base.rb +2 -2
  114. data/opal/corelib/process/status.rb +21 -0
  115. data/opal/corelib/process.rb +5 -5
  116. data/opal/corelib/random/formatter.rb +11 -11
  117. data/opal/corelib/random/math_random.js.rb +1 -1
  118. data/opal/corelib/random/mersenne_twister.rb +3 -3
  119. data/opal/corelib/random/seedrandom.js.rb +3 -3
  120. data/opal/corelib/random.rb +17 -17
  121. data/opal/corelib/range.rb +51 -35
  122. data/opal/corelib/rational/base.rb +4 -4
  123. data/opal/corelib/rational.rb +61 -62
  124. data/opal/corelib/regexp.rb +54 -45
  125. data/opal/corelib/runtime.js +247 -141
  126. data/opal/corelib/string/encoding.rb +21 -21
  127. data/opal/corelib/string/unpack.rb +19 -14
  128. data/opal/corelib/string.rb +137 -130
  129. data/opal/corelib/struct.rb +59 -46
  130. data/opal/corelib/time.rb +47 -57
  131. data/opal/corelib/trace_point.rb +2 -2
  132. data/opal/corelib/unsupported.rb +31 -120
  133. data/opal/corelib/variables.rb +3 -3
  134. data/opal/opal/base.rb +9 -8
  135. data/opal/opal/full.rb +8 -8
  136. data/opal/opal/mini.rb +17 -17
  137. data/opal/opal.rb +17 -18
  138. data/opal.gemspec +1 -1
  139. data/spec/filters/bugs/array.rb +4 -24
  140. data/spec/filters/bugs/basicobject.rb +0 -1
  141. data/spec/filters/bugs/bigdecimal.rb +0 -23
  142. data/spec/filters/bugs/binding.rb +0 -1
  143. data/spec/filters/bugs/boolean.rb +3 -0
  144. data/spec/filters/bugs/class.rb +2 -0
  145. data/spec/filters/bugs/date.rb +0 -5
  146. data/spec/filters/bugs/encoding.rb +8 -50
  147. data/spec/filters/bugs/enumerable.rb +4 -1
  148. data/spec/filters/bugs/enumerator.rb +3 -36
  149. data/spec/filters/bugs/exception.rb +0 -2
  150. data/spec/filters/bugs/file.rb +0 -2
  151. data/spec/filters/bugs/float.rb +0 -3
  152. data/spec/filters/bugs/hash.rb +5 -3
  153. data/spec/filters/bugs/integer.rb +2 -3
  154. data/spec/filters/bugs/kernel.rb +2 -31
  155. data/spec/filters/bugs/language.rb +29 -49
  156. data/spec/filters/bugs/main.rb +0 -2
  157. data/spec/filters/bugs/marshal.rb +2 -3
  158. data/spec/filters/bugs/matrix.rb +0 -36
  159. data/spec/filters/bugs/module.rb +7 -61
  160. data/spec/filters/bugs/numeric.rb +0 -7
  161. data/spec/filters/bugs/objectspace.rb +1 -1
  162. data/spec/filters/bugs/pack_unpack.rb +0 -4
  163. data/spec/filters/bugs/proc.rb +0 -9
  164. data/spec/filters/bugs/random.rb +0 -5
  165. data/spec/filters/bugs/range.rb +1 -6
  166. data/spec/filters/bugs/regexp.rb +0 -3
  167. data/spec/filters/bugs/set.rb +8 -1
  168. data/spec/filters/bugs/string.rb +9 -34
  169. data/spec/filters/bugs/stringscanner.rb +8 -7
  170. data/spec/filters/bugs/struct.rb +2 -3
  171. data/spec/filters/bugs/symbol.rb +0 -1
  172. data/spec/filters/bugs/time.rb +0 -8
  173. data/spec/filters/bugs/unboundmethod.rb +0 -8
  174. data/spec/filters/bugs/warnings.rb +1 -7
  175. data/spec/filters/unsupported/freeze.rb +24 -0
  176. data/spec/filters/unsupported/integer.rb +1 -0
  177. data/spec/filters/unsupported/kernel.rb +12 -0
  178. data/spec/filters/unsupported/privacy.rb +3 -0
  179. data/spec/filters/unsupported/string.rb +2 -0
  180. data/spec/lib/builder_spec.rb +2 -2
  181. data/spec/lib/cli_spec.rb +1 -1
  182. data/spec/lib/compiler_spec.rb +37 -37
  183. data/spec/lib/simple_server_spec.rb +2 -2
  184. data/spec/lib/source_map/file_spec.rb +1 -1
  185. data/spec/opal/compiler/irb_spec.rb +2 -2
  186. data/spec/opal/core/io/read_spec.rb +69 -0
  187. data/spec/opal/core/kernel/puts_spec.rb +90 -0
  188. data/spec/opal/core/language/super_spec.rb +21 -0
  189. data/spec/opal/core/language/xstring_spec.rb +13 -0
  190. data/spec/opal/core/language_spec.rb +14 -0
  191. data/spec/opal/core/string/gsub_spec.rb +8 -0
  192. data/spec/ruby_specs +4 -2
  193. data/spec/support/rewriters_helper.rb +1 -1
  194. data/stdlib/bigdecimal.rb +7 -11
  195. data/stdlib/buffer/view.rb +2 -2
  196. data/stdlib/buffer.rb +2 -2
  197. data/stdlib/date.rb +5 -6
  198. data/stdlib/erb.rb +1 -0
  199. data/stdlib/js.rb +2 -1
  200. data/stdlib/native.rb +7 -8
  201. data/stdlib/nodejs/argf.rb +4 -4
  202. data/stdlib/nodejs/base.rb +29 -0
  203. data/stdlib/nodejs/dir.rb +1 -1
  204. data/stdlib/nodejs/env.rb +6 -9
  205. data/stdlib/nodejs/file.rb +23 -17
  206. data/stdlib/nodejs/fileutils.rb +3 -3
  207. data/stdlib/nodejs/io.rb +2 -20
  208. data/stdlib/nodejs/irb.rb +0 -0
  209. data/stdlib/nodejs/kernel.rb +2 -37
  210. data/stdlib/nodejs.rb +1 -3
  211. data/stdlib/opal/miniracer.rb +2 -0
  212. data/stdlib/opal/platform.rb +6 -13
  213. data/stdlib/opal/replutils.rb +16 -5
  214. data/stdlib/opal-parser.rb +2 -2
  215. data/stdlib/optparse/ac.rb +54 -0
  216. data/stdlib/optparse/date.rb +14 -0
  217. data/stdlib/optparse/kwargs.rb +22 -0
  218. data/stdlib/optparse/shellwords.rb +7 -0
  219. data/stdlib/optparse/time.rb +15 -0
  220. data/stdlib/optparse/uri.rb +7 -0
  221. data/stdlib/optparse/version.rb +69 -0
  222. data/stdlib/optparse.rb +2279 -0
  223. data/stdlib/pathname.rb +5 -6
  224. data/stdlib/pp.rb +18 -2
  225. data/stdlib/promise/v2.rb +18 -29
  226. data/stdlib/promise.rb +15 -21
  227. data/stdlib/quickjs/io.rb +0 -2
  228. data/stdlib/quickjs/kernel.rb +0 -2
  229. data/stdlib/quickjs.rb +2 -0
  230. data/stdlib/set.rb +32 -32
  231. data/stdlib/shellwords.rb +240 -0
  232. data/stdlib/stringio.rb +3 -6
  233. data/stdlib/strscan.rb +5 -8
  234. data/stdlib/template.rb +2 -2
  235. data/stdlib/thread.rb +7 -9
  236. data/tasks/linting-parse-eslint-results.js +1 -0
  237. data/tasks/linting.rake +0 -10
  238. data/tasks/performance.rake +5 -2
  239. data/tasks/testing/mspec_special_calls.rb +0 -12
  240. data/tasks/testing.rake +55 -37
  241. data/test/nodejs/test_file.rb +11 -0
  242. metadata +55 -8
  243. data/lib/opal/nodes/case.rb +0 -114
@@ -0,0 +1,177 @@
1
+ class ::Enumerator
2
+ class self::ArithmeticSequence < self
3
+ `Opal.prop(self.$$prototype, '$$is_arithmetic_seq', true)`
4
+
5
+ `var inf = Infinity`
6
+
7
+ # @private
8
+ def initialize(range, step = undefined, creation_method = :step)
9
+ @creation_method = creation_method
10
+ if range.is_a? ::Array
11
+ @step_arg1, @step_arg2, @topfx, @bypfx = *range
12
+ @receiver_num = step
13
+ @step = 1
14
+
15
+ @range = if @step_arg2
16
+ @step = @step_arg2
17
+ (@receiver_num..@step_arg1)
18
+ elsif @step_arg1
19
+ (@receiver_num..@step_arg1)
20
+ else
21
+ (@receiver_num..nil)
22
+ end
23
+ else
24
+ @skipped_arg = true unless step
25
+ @range, @step = range, step || 1
26
+ end
27
+
28
+ @object = self
29
+
30
+ ::Kernel.raise ArgumentError, "step can't be 0" if @step == 0
31
+ unless @step.respond_to? :to_int
32
+ ::Kernel.raise ArgumentError, "no implicit conversion of #{@step.class} " \
33
+ 'into Integer'
34
+ end
35
+ end
36
+
37
+ attr_reader :step
38
+
39
+ def begin
40
+ @range.begin
41
+ end
42
+
43
+ def end
44
+ @range.end
45
+ end
46
+
47
+ def exclude_end?
48
+ @range.exclude_end?
49
+ end
50
+
51
+ # @private
52
+ def _lesser_than_end?(val)
53
+ end_ = self.end || `inf`
54
+ if step > 0
55
+ exclude_end? ? val < end_ : val <= end_
56
+ else
57
+ exclude_end? ? val > end_ : val >= end_
58
+ end
59
+ end
60
+
61
+ # @private
62
+ def _greater_than_begin?(val)
63
+ begin_ = self.begin || -`inf`
64
+ if step > 0
65
+ val > begin_
66
+ else
67
+ val < begin_
68
+ end
69
+ end
70
+
71
+ def first(count = undefined)
72
+ iter = self.begin || -`inf`
73
+
74
+ return _lesser_than_end?(iter) ? iter : nil unless count
75
+
76
+ out = []
77
+
78
+ while _lesser_than_end?(iter) && count > 0
79
+ out << iter
80
+ iter += step
81
+ count -= 1
82
+ end
83
+
84
+ out
85
+ end
86
+
87
+ def each(&block)
88
+ return self unless block_given?
89
+
90
+ case self.begin
91
+ when nil
92
+ ::Kernel.raise TypeError, "nil can't be coerced into Integer"
93
+ end
94
+
95
+ iter = self.begin || -`inf`
96
+
97
+ while _lesser_than_end?(iter)
98
+ yield iter
99
+ iter += step
100
+ end
101
+ self
102
+ end
103
+
104
+ def last(count = undefined)
105
+ case self.end
106
+ when `inf`, -`inf`
107
+ ::Kernel.raise ::FloatDomainError, self.end
108
+ when nil
109
+ ::Kernel.raise ::RangeError, 'cannot get the last element of endless arithmetic sequence'
110
+ end
111
+
112
+ iter = self.end - ((self.end - self.begin) % step)
113
+ iter -= step unless _lesser_than_end?(iter)
114
+
115
+ return _greater_than_begin?(iter) ? iter : nil unless count
116
+
117
+ out = []
118
+
119
+ while _greater_than_begin?(iter) && count > 0
120
+ out << iter
121
+ iter -= step
122
+ count -= 1
123
+ end
124
+
125
+ out.reverse
126
+ end
127
+
128
+ def size
129
+ step_sign = step > 0 ? 1 : -1
130
+
131
+ if !_lesser_than_end?(self.begin)
132
+ 0
133
+ elsif [-`inf`, `inf`].include?(step)
134
+ 1
135
+ elsif [-`inf` * step_sign, nil].include?(self.begin) ||
136
+ [`inf` * step_sign, nil].include?(self.end)
137
+ `inf`
138
+ else
139
+ iter = self.end - ((self.end - self.begin) % step)
140
+ iter -= step unless _lesser_than_end?(iter)
141
+ ((iter - self.begin) / step).abs.to_i + 1
142
+ end
143
+ end
144
+
145
+ def ==(other)
146
+ self.class == other.class &&
147
+ self.begin == other.begin &&
148
+ self.end == other.end &&
149
+ step == other.step &&
150
+ exclude_end? == other.exclude_end?
151
+ end
152
+
153
+ def hash
154
+ [self.begin, self.end, step, exclude_end?].hash
155
+ end
156
+
157
+ def inspect
158
+ if @receiver_num
159
+ args = if @step_arg2
160
+ "(#{@topfx}#{@step_arg1.inspect}, #{@bypfx}#{@step_arg2.inspect})"
161
+ elsif @step_arg1
162
+ "(#{@topfx}#{@step_arg1.inspect})"
163
+ end
164
+
165
+ "(#{@receiver_num.inspect}.#{@creation_method}#{args})"
166
+ else
167
+ args = unless @skipped_arg
168
+ "(#{@step})"
169
+ end
170
+ "((#{@range.inspect}).#{@creation_method}#{args})"
171
+ end
172
+ end
173
+
174
+ alias === ==
175
+ alias eql? ==
176
+ end
177
+ end
@@ -0,0 +1,42 @@
1
+ class ::Enumerator
2
+ class self::Chain < self
3
+ def initialize(*enums)
4
+ @enums = enums
5
+ @iterated = []
6
+ @object = self
7
+ end
8
+
9
+ def each(*args, &block)
10
+ return to_enum(:each, *args) { size } unless block_given?
11
+
12
+ @enums.each do |enum|
13
+ @iterated << enum
14
+ enum.each(*args, &block)
15
+ end
16
+
17
+ self
18
+ end
19
+
20
+ def size(*args)
21
+ accum = 0
22
+ @enums.each do |enum|
23
+ size = enum.size(*args)
24
+ return size if [nil, ::Float::INFINITY].include? size
25
+ accum += size
26
+ end
27
+ accum
28
+ end
29
+
30
+ def rewind
31
+ @iterated.reverse_each do |enum|
32
+ enum.rewind if enum.respond_to? :rewind
33
+ end
34
+ @iterated = []
35
+ self
36
+ end
37
+
38
+ def inspect
39
+ "#<Enumerator::Chain: #{@enums.inspect}>"
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,35 @@
1
+ # helpers: breaker
2
+
3
+ class Enumerator
4
+ class Generator
5
+ include ::Enumerable
6
+
7
+ def initialize(&block)
8
+ ::Kernel.raise ::LocalJumpError, 'no block given' unless block
9
+
10
+ @block = block
11
+ end
12
+
13
+ def each(*args, &block)
14
+ yielder = Yielder.new(&block)
15
+
16
+ %x{
17
+ try {
18
+ args.unshift(#{yielder});
19
+
20
+ Opal.yieldX(#{@block}, args);
21
+ }
22
+ catch (e) {
23
+ if (e === $breaker) {
24
+ return $breaker.$v;
25
+ }
26
+ else {
27
+ throw e;
28
+ }
29
+ }
30
+ }
31
+
32
+ self
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,243 @@
1
+ # helpers: truthy, coerce_to, yield1, yieldX
2
+
3
+ class ::Enumerator
4
+ class self::Lazy < self
5
+ class self::StopLazyError < ::Exception; end
6
+
7
+ def self.for(object, *)
8
+ lazy = super
9
+ `lazy.enumerator = object`
10
+ lazy
11
+ end
12
+
13
+ def initialize(object, size = nil, &block)
14
+ unless block_given?
15
+ ::Kernel.raise ::ArgumentError, 'tried to call lazy new without a block'
16
+ end
17
+
18
+ @enumerator = object
19
+
20
+ super size do |yielder, *each_args|
21
+ object.each(*each_args) do |*args|
22
+ %x{
23
+ args.unshift(#{yielder});
24
+
25
+ $yieldX(block, args);
26
+ }
27
+ end
28
+ rescue StopLazyError
29
+ nil
30
+ end
31
+ end
32
+
33
+ def lazy
34
+ self
35
+ end
36
+
37
+ def collect(&block)
38
+ unless block
39
+ ::Kernel.raise ::ArgumentError, 'tried to call lazy map without a block'
40
+ end
41
+
42
+ Lazy.new(self, enumerator_size) do |enum, *args|
43
+ %x{
44
+ var value = $yieldX(block, args);
45
+
46
+ #{enum.yield `value`};
47
+ }
48
+ end
49
+ end
50
+
51
+ def collect_concat(&block)
52
+ unless block
53
+ ::Kernel.raise ::ArgumentError, 'tried to call lazy map without a block'
54
+ end
55
+
56
+ Lazy.new(self, nil) do |enum, *args|
57
+ %x{
58
+ var value = $yieldX(block, args);
59
+
60
+ if (#{`value`.respond_to? :force} && #{`value`.respond_to? :each}) {
61
+ #{`value`.each { |v| enum.yield v }}
62
+ }
63
+ else {
64
+ var array = #{::Opal.try_convert `value`, ::Array, :to_ary};
65
+
66
+ if (array === nil) {
67
+ #{enum.yield `value`};
68
+ }
69
+ else {
70
+ #{`value`.each { |v| enum.yield v }};
71
+ }
72
+ }
73
+ }
74
+ end
75
+ end
76
+
77
+ def drop(n)
78
+ n = `$coerce_to(#{n}, #{::Integer}, 'to_int')`
79
+
80
+ if n < 0
81
+ ::Kernel.raise ::ArgumentError, 'attempt to drop negative size'
82
+ end
83
+
84
+ current_size = enumerator_size
85
+ set_size = if ::Integer === current_size
86
+ n < current_size ? n : current_size
87
+ else
88
+ current_size
89
+ end
90
+
91
+ dropped = 0
92
+ Lazy.new(self, set_size) do |enum, *args|
93
+ if dropped < n
94
+ dropped += 1
95
+ else
96
+ enum.yield(*args)
97
+ end
98
+ end
99
+ end
100
+
101
+ def drop_while(&block)
102
+ unless block
103
+ ::Kernel.raise ::ArgumentError, 'tried to call lazy drop_while without a block'
104
+ end
105
+
106
+ succeeding = true
107
+ Lazy.new(self, nil) do |enum, *args|
108
+ if succeeding
109
+ %x{
110
+ var value = $yieldX(block, args);
111
+
112
+ if (!$truthy(value)) {
113
+ succeeding = false;
114
+
115
+ #{enum.yield(*args)};
116
+ }
117
+ }
118
+ else
119
+ enum.yield(*args)
120
+ end
121
+ end
122
+ end
123
+
124
+ def enum_for(method = :each, *args, &block)
125
+ self.class.for(self, method, *args, &block)
126
+ end
127
+
128
+ def find_all(&block)
129
+ unless block
130
+ ::Kernel.raise ::ArgumentError, 'tried to call lazy select without a block'
131
+ end
132
+
133
+ Lazy.new(self, nil) do |enum, *args|
134
+ %x{
135
+ var value = $yieldX(block, args);
136
+
137
+ if ($truthy(value)) {
138
+ #{enum.yield(*args)};
139
+ }
140
+ }
141
+ end
142
+ end
143
+
144
+ def grep(pattern, &block)
145
+ if block
146
+ Lazy.new(self, nil) do |enum, *args|
147
+ %x{
148
+ var param = #{::Opal.destructure(args)},
149
+ value = #{pattern === `param`};
150
+
151
+ if ($truthy(value)) {
152
+ value = $yield1(block, param);
153
+
154
+ #{enum.yield `$yield1(block, param)`};
155
+ }
156
+ }
157
+ end
158
+ else
159
+ Lazy.new(self, nil) do |enum, *args|
160
+ %x{
161
+ var param = #{::Opal.destructure(args)},
162
+ value = #{pattern === `param`};
163
+
164
+ if ($truthy(value)) {
165
+ #{enum.yield `param`};
166
+ }
167
+ }
168
+ end
169
+ end
170
+ end
171
+
172
+ def reject(&block)
173
+ unless block
174
+ ::Kernel.raise ::ArgumentError, 'tried to call lazy reject without a block'
175
+ end
176
+
177
+ Lazy.new(self, nil) do |enum, *args|
178
+ %x{
179
+ var value = $yieldX(block, args);
180
+
181
+ if (!$truthy(value)) {
182
+ #{enum.yield(*args)};
183
+ }
184
+ }
185
+ end
186
+ end
187
+
188
+ def take(n)
189
+ n = `$coerce_to(#{n}, #{::Integer}, 'to_int')`
190
+
191
+ if n < 0
192
+ ::Kernel.raise ::ArgumentError, 'attempt to take negative size'
193
+ end
194
+
195
+ current_size = enumerator_size
196
+ set_size = if ::Integer === current_size
197
+ n < current_size ? n : current_size
198
+ else
199
+ current_size
200
+ end
201
+
202
+ taken = 0
203
+ Lazy.new(self, set_size) do |enum, *args|
204
+ if taken < n
205
+ enum.yield(*args)
206
+ taken += 1
207
+ else
208
+ ::Kernel.raise StopLazyError
209
+ end
210
+ end
211
+ end
212
+
213
+ def take_while(&block)
214
+ unless block
215
+ ::Kernel.raise ::ArgumentError, 'tried to call lazy take_while without a block'
216
+ end
217
+
218
+ Lazy.new(self, nil) do |enum, *args|
219
+ %x{
220
+ var value = $yieldX(block, args);
221
+
222
+ if ($truthy(value)) {
223
+ #{enum.yield(*args)};
224
+ }
225
+ else {
226
+ #{::Kernel.raise StopLazyError};
227
+ }
228
+ }
229
+ end
230
+ end
231
+
232
+ def inspect
233
+ "#<#{self.class}: #{@enumerator.inspect}>"
234
+ end
235
+
236
+ alias force to_a
237
+ alias filter find_all
238
+ alias flat_map collect_concat
239
+ alias map collect
240
+ alias select find_all
241
+ alias to_enum enum_for
242
+ end
243
+ end
@@ -0,0 +1,36 @@
1
+ # helpers: breaker
2
+
3
+ class Enumerator
4
+ class Yielder
5
+ def initialize(&block)
6
+ @block = block
7
+ # rubocop:disable Lint/Void
8
+ self
9
+ # rubocop:enable Lint/Void
10
+ end
11
+
12
+ def yield(*values)
13
+ %x{
14
+ var value = Opal.yieldX(#{@block}, values);
15
+
16
+ if (value === $breaker) {
17
+ throw $breaker;
18
+ }
19
+
20
+ return value;
21
+ }
22
+ end
23
+
24
+ def <<(value)
25
+ self.yield(value)
26
+
27
+ self
28
+ end
29
+
30
+ def to_proc
31
+ proc do |*values|
32
+ self.yield(*values)
33
+ end
34
+ end
35
+ end
36
+ end