opal 1.2.0 → 1.3.0.alpha1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.await.js +6 -0
  3. data/.eslintrc.js +34 -0
  4. data/.github/workflows/build.yml +8 -0
  5. data/.rubocop.yml +9 -0
  6. data/CHANGELOG.md +4 -0
  7. data/README.md +1 -1
  8. data/Rakefile +1 -0
  9. data/UNRELEASED.md +64 -38
  10. data/docs/async.md +109 -0
  11. data/docs/roda-sprockets.md +0 -2
  12. data/exe/opal +2 -0
  13. data/exe/opal-repl +2 -2
  14. data/lib/opal/builder.rb +5 -1
  15. data/lib/opal/builder_processors.rb +7 -2
  16. data/lib/opal/cache/file_cache.rb +119 -0
  17. data/lib/opal/cache.rb +71 -0
  18. data/lib/opal/cli.rb +35 -1
  19. data/lib/opal/cli_options.rb +21 -0
  20. data/lib/opal/cli_runners/chrome.rb +21 -14
  21. data/lib/opal/cli_runners/chrome_cdp_interface.js +30285 -0
  22. data/lib/opal/cli_runners/{chrome.js → chrome_cdp_interface.rb} +27 -6
  23. data/lib/opal/cli_runners/compiler.rb +2 -1
  24. data/lib/opal/cli_runners/gjs.rb +27 -0
  25. data/lib/opal/cli_runners/mini_racer.rb +36 -0
  26. data/lib/opal/cli_runners/source-map-support-browser.js +276 -91
  27. data/lib/opal/cli_runners/source-map-support-node.js +276 -91
  28. data/lib/opal/cli_runners/source-map-support.js +60 -18
  29. data/lib/opal/cli_runners.rb +2 -0
  30. data/lib/opal/compiler.rb +99 -10
  31. data/lib/opal/fragment.rb +77 -14
  32. data/lib/opal/nodes/args/extract_kwrestarg.rb +6 -4
  33. data/lib/opal/nodes/args/extract_restarg.rb +10 -12
  34. data/lib/opal/nodes/args.rb +28 -0
  35. data/lib/opal/nodes/base.rb +29 -5
  36. data/lib/opal/nodes/call.rb +123 -2
  37. data/lib/opal/nodes/case.rb +7 -1
  38. data/lib/opal/nodes/class.rb +12 -2
  39. data/lib/opal/nodes/def.rb +3 -23
  40. data/lib/opal/nodes/definitions.rb +21 -4
  41. data/lib/opal/nodes/helpers.rb +2 -2
  42. data/lib/opal/nodes/if.rb +39 -9
  43. data/lib/opal/nodes/iter.rb +15 -3
  44. data/lib/opal/nodes/lambda.rb +3 -1
  45. data/lib/opal/nodes/literal.rb +13 -7
  46. data/lib/opal/nodes/logic.rb +2 -2
  47. data/lib/opal/nodes/module.rb +12 -2
  48. data/lib/opal/nodes/rescue.rb +59 -34
  49. data/lib/opal/nodes/scope.rb +88 -6
  50. data/lib/opal/nodes/super.rb +52 -25
  51. data/lib/opal/nodes/top.rb +13 -7
  52. data/lib/opal/nodes/while.rb +7 -1
  53. data/lib/opal/parser/patch.rb +2 -1
  54. data/lib/opal/repl.rb +137 -49
  55. data/lib/opal/rewriters/binary_operator_assignment.rb +10 -10
  56. data/lib/opal/rewriters/block_to_iter.rb +3 -3
  57. data/lib/opal/rewriters/for_rewriter.rb +7 -7
  58. data/lib/opal/rewriters/js_reserved_words.rb +5 -3
  59. data/lib/opal/source_map/file.rb +7 -4
  60. data/lib/opal/source_map/map.rb +17 -3
  61. data/lib/opal/version.rb +1 -1
  62. data/opal/corelib/array.rb +2 -2
  63. data/opal/corelib/binding.rb +46 -0
  64. data/opal/corelib/boolean.rb +54 -4
  65. data/opal/corelib/class.rb +2 -0
  66. data/opal/corelib/constants.rb +2 -2
  67. data/opal/corelib/error.rb +98 -12
  68. data/opal/corelib/io.rb +250 -38
  69. data/opal/corelib/kernel/format.rb +5 -2
  70. data/opal/corelib/kernel.rb +44 -23
  71. data/opal/corelib/main.rb +5 -0
  72. data/opal/corelib/method.rb +1 -0
  73. data/opal/corelib/module.rb +28 -0
  74. data/opal/corelib/number.rb +12 -1
  75. data/opal/corelib/random/seedrandom.js.rb +2 -2
  76. data/opal/corelib/regexp.rb +47 -3
  77. data/opal/corelib/runtime.js +152 -12
  78. data/opal/corelib/string/encoding.rb +17 -17
  79. data/opal/corelib/string.rb +2 -0
  80. data/opal/corelib/struct.rb +10 -3
  81. data/opal/corelib/trace_point.rb +57 -0
  82. data/opal/opal/full.rb +2 -0
  83. data/package.json +3 -2
  84. data/spec/filters/bugs/array.rb +0 -1
  85. data/spec/filters/bugs/basicobject.rb +0 -1
  86. data/spec/filters/bugs/binding.rb +27 -0
  87. data/spec/filters/bugs/enumerator.rb +132 -0
  88. data/spec/filters/bugs/exception.rb +70 -93
  89. data/spec/filters/bugs/float.rb +0 -1
  90. data/spec/filters/bugs/kernel.rb +3 -9
  91. data/spec/filters/bugs/language.rb +15 -58
  92. data/spec/filters/bugs/main.rb +16 -0
  93. data/spec/filters/bugs/matrix.rb +39 -0
  94. data/spec/filters/bugs/method.rb +0 -2
  95. data/spec/filters/bugs/module.rb +36 -79
  96. data/spec/filters/bugs/proc.rb +0 -1
  97. data/spec/filters/bugs/regexp.rb +0 -16
  98. data/spec/filters/bugs/trace_point.rb +12 -0
  99. data/spec/filters/bugs/warnings.rb +0 -4
  100. data/spec/filters/unsupported/freeze.rb +2 -0
  101. data/spec/filters/unsupported/privacy.rb +4 -0
  102. data/spec/lib/compiler_spec.rb +7 -1
  103. data/spec/lib/repl_spec.rb +4 -2
  104. data/spec/lib/source_map/file_spec.rb +1 -1
  105. data/spec/mspec-opal/formatters.rb +18 -4
  106. data/spec/mspec-opal/runner.rb +2 -2
  107. data/spec/opal/core/boolean_spec.rb +44 -0
  108. data/spec/opal/core/hash_spec.rb +8 -0
  109. data/spec/opal/core/number/to_s_spec.rb +11 -0
  110. data/spec/opal/stdlib/json/ext_spec.rb +3 -3
  111. data/spec/opal/stdlib/logger/logger_spec.rb +10 -1
  112. data/spec/ruby_specs +18 -0
  113. data/stdlib/await.rb +83 -0
  114. data/stdlib/base64.rb +4 -4
  115. data/stdlib/bigdecimal/bignumber.js.rb +4 -2
  116. data/stdlib/bigdecimal.rb +1 -0
  117. data/stdlib/gjs/io.rb +33 -0
  118. data/stdlib/gjs/kernel.rb +5 -0
  119. data/stdlib/gjs.rb +2 -0
  120. data/stdlib/js.rb +4 -0
  121. data/stdlib/json.rb +3 -3
  122. data/stdlib/logger.rb +1 -1
  123. data/stdlib/nashorn/file.rb +2 -0
  124. data/stdlib/nodejs/env.rb +7 -0
  125. data/stdlib/nodejs/file.rb +6 -41
  126. data/stdlib/nodejs/io.rb +21 -5
  127. data/stdlib/nodejs/js-yaml-3-6-1.js +2 -2
  128. data/stdlib/opal/miniracer.rb +6 -0
  129. data/stdlib/opal/platform.rb +4 -0
  130. data/stdlib/opal/repl_js.rb +5 -0
  131. data/stdlib/opal/replutils.rb +271 -0
  132. data/stdlib/opal-parser.rb +24 -11
  133. data/stdlib/opal-platform.rb +8 -0
  134. data/stdlib/promise/v2.rb +16 -4
  135. data/stdlib/promise.rb +14 -0
  136. data/stdlib/stringio.rb +13 -110
  137. data/stdlib/thread.rb +29 -0
  138. data/tasks/building.rake +10 -4
  139. data/tasks/linting-parse-eslint-results.js +39 -0
  140. data/tasks/linting.rake +38 -28
  141. data/tasks/performance/asciidoctor_test.rb.erb +6 -0
  142. data/tasks/performance/optimization_status.rb +77 -0
  143. data/tasks/performance.rake +149 -0
  144. data/tasks/testing.rake +9 -1
  145. data/test/nodejs/test_await.rb +169 -0
  146. data/test/opal/promisev2/test_error.rb +9 -3
  147. data/test/opal/unsupported_and_bugs.rb +5 -0
  148. data/vendored-minitest/minitest/benchmark.rb +9 -7
  149. data/vendored-minitest/minitest/test.rb +14 -12
  150. data/vendored-minitest/minitest.rb +19 -16
  151. data/yarn.lock +686 -117
  152. metadata +60 -23
  153. data/.jshintrc +0 -41
  154. data/spec/filters/unsupported/refinements.rb +0 -8
  155. data/vendored-minitest/minitest/hell.rb +0 -11
  156. data/vendored-minitest/minitest/parallel.rb +0 -65
  157. data/vendored-minitest/minitest/pride.rb +0 -4
  158. data/vendored-minitest/minitest/pride_plugin.rb +0 -142
  159. data/vendored-minitest/minitest/unit.rb +0 -45
@@ -1,5 +1,5 @@
1
1
  class Exception < `Error`
2
- # `var Kernel$raise = #{Kernel}.$raise`
2
+ `Opal.defineProperty(self.$$prototype, '$$is_exception', true)`
3
3
  `var stack_trace_limit`
4
4
 
5
5
  def self.new(*args)
@@ -8,6 +8,7 @@ class Exception < `Error`
8
8
  var error = new self.$$constructor(message);
9
9
  error.name = self.$$name;
10
10
  error.message = message;
11
+ error.cause = #{$!};
11
12
  Opal.send(error, error.$initialize, args);
12
13
 
13
14
  // Error.captureStackTrace() will use .name and .toString to build the
@@ -33,6 +34,37 @@ class Exception < `Error`
33
34
  `self.message = (args.length > 0) ? args[0] : nil`
34
35
  end
35
36
 
37
+ %x{
38
+ // Convert backtrace from any format to Ruby format
39
+ function correct_backtrace(backtrace) {
40
+ var new_bt = [], m;
41
+
42
+ for (var i = 0; i < backtrace.length; i++) {
43
+ var loc = backtrace[i];
44
+ if (!loc || !loc.$$is_string) {
45
+ /* Do nothing */
46
+ }
47
+ /* Chromium format */
48
+ else if ((m = loc.match(/^ at (.*?) \((.*?)\)$/))) {
49
+ new_bt.push(m[2] + ":in `" + m[1] + "'");
50
+ }
51
+ else if ((m = loc.match(/^ at (.*?)$/))) {
52
+ new_bt.push(m[1] + ":in `undefined'");
53
+ }
54
+ /* Node format */
55
+ else if ((m = loc.match(/^ from (.*?)$/))) {
56
+ new_bt.push(m[1]);
57
+ }
58
+ /* Mozilla/Apple format */
59
+ else if ((m = loc.match(/^(.*?)@(.*?)$/))) {
60
+ new_bt.push(m[2] + ':in `' + m[1] + "'");
61
+ }
62
+ }
63
+
64
+ return new_bt;
65
+ }
66
+ }
67
+
36
68
  def backtrace
37
69
  %x{
38
70
  if (self.backtrace) {
@@ -42,17 +74,31 @@ class Exception < `Error`
42
74
 
43
75
  var backtrace = self.stack;
44
76
 
45
- if (typeof(backtrace) === 'string') {
46
- return backtrace.split("\n").slice(0, 15);
77
+ if (backtrace.$$is_string) {
78
+ return self.backtrace = correct_backtrace(backtrace.split("\n").slice(0, 15));
47
79
  }
48
80
  else if (backtrace) {
49
- return backtrace.slice(0, 15);
81
+ return self.backtrace = correct_backtrace(backtrace.slice(0, 15));
50
82
  }
51
83
 
52
84
  return [];
53
85
  }
54
86
  end
55
87
 
88
+ def backtrace_locations
89
+ %x{
90
+ if (self.backtrace_locations) return self.backtrace_locations;
91
+ self.backtrace_locations = #{backtrace&.map do |loc|
92
+ ::Thread::Backtrace::Location.new(loc)
93
+ end}
94
+ return self.backtrace_locations;
95
+ }
96
+ end
97
+
98
+ def cause
99
+ `self.cause || nil`
100
+ end
101
+
56
102
  def exception(str = nil)
57
103
  %x{
58
104
  if (str === nil || self === str) {
@@ -61,7 +107,9 @@ class Exception < `Error`
61
107
 
62
108
  var cloned = #{clone};
63
109
  cloned.message = str;
110
+ if (self.backtrace) cloned.backtrace = self.backtrace.$dup();
64
111
  cloned.stack = self.stack;
112
+ cloned.cause = self.cause;
65
113
  return cloned;
66
114
  }
67
115
  end
@@ -71,6 +119,37 @@ class Exception < `Error`
71
119
  to_s
72
120
  end
73
121
 
122
+ def full_message(highlight: $stderr.tty?, order: :top)
123
+ raise ArgumentError, "expected true or false as highlight: #{highlight}" unless [true, false].include? highlight
124
+ raise ArgumentError, "expected :top or :bottom as order: #{order}" unless %i[top bottom].include? order
125
+
126
+ if highlight
127
+ bold_underline = "\e[1;4m"
128
+ bold = "\e[1m"
129
+ reset = "\e[m"
130
+ else
131
+ bold_underline = bold = reset = ''
132
+ end
133
+
134
+ bt = backtrace.dup
135
+ bt = caller if !bt || bt.empty?
136
+ first = bt.shift
137
+
138
+ msg = "#{first}: "
139
+ msg += "#{bold}#{to_s} (#{bold_underline}#{self.class}#{reset}#{bold})#{reset}\n"
140
+
141
+ msg += bt.map { |loc| "\tfrom #{loc}\n" }.join
142
+
143
+ msg += cause.full_message(highlight: highlight) if cause
144
+
145
+ if order == :bottom
146
+ msg = msg.split("\n").reverse.join("\n")
147
+ msg = "#{bold}Traceback#{reset} (most recent call last):\n" + msg
148
+ end
149
+
150
+ msg
151
+ end
152
+
74
153
  def inspect
75
154
  as_str = to_s
76
155
  as_str.empty? ? self.class.to_s : "#<#{self.class.to_s}: #{to_s}>"
@@ -85,7 +164,7 @@ class Exception < `Error`
85
164
  self.stack = '';
86
165
  } else if (backtrace.$$is_string) {
87
166
  self.backtrace = [backtrace];
88
- self.stack = backtrace;
167
+ self.stack = ' from ' + backtrace;
89
168
  } else {
90
169
  if (backtrace.$$is_array) {
91
170
  for (i = 0, ii = backtrace.length; i < ii; i++) {
@@ -103,7 +182,7 @@ class Exception < `Error`
103
182
  }
104
183
 
105
184
  self.backtrace = backtrace;
106
- self.stack = backtrace.join('\n');
185
+ self.stack = #{`backtrace`.map { |i| ' from ' + i }}.join("\n");
107
186
  }
108
187
 
109
188
  return backtrace;
@@ -125,8 +204,9 @@ class NotImplementedError < ScriptError; end
125
204
  class SystemExit < Exception; end
126
205
  class NoMemoryError < Exception; end
127
206
  class SignalException < Exception; end
128
- class Interrupt < Exception; end
207
+ class Interrupt < SignalException; end
129
208
  class SecurityError < Exception; end
209
+ class SystemStackError < Exception; end
130
210
 
131
211
  class StandardError < Exception; end
132
212
  class EncodingError < StandardError; end
@@ -138,13 +218,19 @@ class FrozenError < RuntimeError; end
138
218
  class LocalJumpError < StandardError; end
139
219
  class TypeError < StandardError; end
140
220
  class ArgumentError < StandardError; end
221
+ class UncaughtThrowError < ArgumentError; end
141
222
  class IndexError < StandardError; end
142
223
  class StopIteration < IndexError; end
224
+ class ClosedQueueError < StopIteration; end
143
225
  class KeyError < IndexError; end
144
226
  class RangeError < StandardError; end
145
227
  class FloatDomainError < RangeError; end
146
228
  class IOError < StandardError; end
229
+ class EOFError < IOError; end
147
230
  class SystemCallError < StandardError; end
231
+ class RegexpError < StandardError; end
232
+ class ThreadError < StandardError; end
233
+ class FiberError < StandardError; end
148
234
 
149
235
  module Errno
150
236
  class EINVAL < SystemCallError
@@ -157,13 +243,13 @@ module Errno
157
243
  end
158
244
 
159
245
  class UncaughtThrowError < ArgumentError
160
- attr_reader :sym, :arg
246
+ attr_reader :tag, :value
161
247
 
162
- def initialize(args)
163
- @sym = args[0]
164
- @arg = args[1] if args.length > 1
248
+ def initialize(tag, value = nil)
249
+ @tag = tag
250
+ @value = value
165
251
 
166
- super("uncaught throw #{@sym.inspect}")
252
+ super("uncaught throw #{@tag.inspect}")
167
253
  end
168
254
  end
169
255
 
data/opal/corelib/io.rb CHANGED
@@ -2,16 +2,30 @@ class IO
2
2
  SEEK_SET = 0
3
3
  SEEK_CUR = 1
4
4
  SEEK_END = 2
5
+ SEEK_DATA = 3
6
+ SEEK_HOLE = 4
5
7
 
6
- def tty?
7
- @tty
8
+ READABLE = 1
9
+ WRITABLE = 4
10
+
11
+ def initialize(fd, flags = 'r')
12
+ @fd = fd
13
+ @flags = flags
14
+ @eof = false
15
+
16
+ if flags.include?('r') && !flags.match?(/[wa+]/)
17
+ @closed = :write
18
+ elsif flags.match?(/[wa]/) && !flags.match?(/[r+]/)
19
+ @closed = :read
20
+ end
8
21
  end
9
22
 
10
- def closed?
11
- @closed
23
+ def tty?
24
+ `self.tty == true`
12
25
  end
13
26
 
14
27
  attr_accessor :write_proc
28
+ attr_accessor :read_proc
15
29
 
16
30
  def write(string)
17
31
  `self.write_proc(string)`
@@ -20,63 +34,261 @@ class IO
20
34
 
21
35
  attr_accessor :sync, :tty
22
36
 
37
+ attr_reader :eof
38
+ alias eof? eof
39
+
23
40
  def flush
24
41
  # noop
25
42
  end
26
43
 
27
- module Writable
28
- def <<(string)
29
- write(string)
30
- self
31
- end
44
+ def <<(string)
45
+ write(string)
46
+ self
47
+ end
32
48
 
33
- def print(*args)
34
- %x{
35
- for (var i = 0, ii = args.length; i < ii; i++) {
36
- args[i] = #{String(`args[i]`)}
37
- }
38
- self.$write(args.join(#{$,}));
49
+ def print(*args)
50
+ %x{
51
+ for (var i = 0, ii = args.length; i < ii; i++) {
52
+ args[i] = #{String(`args[i]`)}
39
53
  }
40
- nil
41
- end
54
+ self.$write(args.join(#{$,}));
55
+ }
56
+ nil
57
+ end
42
58
 
43
- def puts(*args)
44
- %x{
45
- for (var i = 0, ii = args.length; i < ii; i++) {
46
- args[i] = #{String(`args[i]`).chomp}
47
- }
48
- self.$write(args.concat([nil]).join(#{$/}));
59
+ def puts(*args)
60
+ %x{
61
+ for (var i = 0, ii = args.length; i < ii; i++) {
62
+ args[i] = #{String(`args[i]`).chomp}
49
63
  }
50
- nil
64
+ self.$write(args.concat([nil]).join(#{$/}));
65
+ }
66
+ nil
67
+ end
68
+
69
+ # Reading
70
+
71
+ def getc
72
+ @read_buffer ||= ''
73
+ parts = ''
74
+
75
+ # Will execure at most twice - one time reading from a buffer
76
+ # second time
77
+ begin
78
+ @read_buffer += parts
79
+ if @read_buffer != ''
80
+ ret = @read_buffer[0]
81
+ @read_buffer = @read_buffer[1..-1]
82
+ return ret
83
+ end
84
+ end while parts = sysread_noraise(1)
85
+
86
+ nil
87
+ end
88
+
89
+ def getbyte
90
+ getc&.ord
91
+ end
92
+
93
+ def readbyte
94
+ readchar.ord
95
+ end
96
+
97
+ def readchar
98
+ getc || raise(EOFError, 'end of file reached')
99
+ end
100
+
101
+ def readline(*args)
102
+ gets(*args) || raise(EOFError, 'end of file reached')
103
+ end
104
+
105
+ def gets(sep = false, limit = nil, opts = {})
106
+ if `sep.$$is_number` && !limit
107
+ sep, limit, opts = false, sep, limit
108
+ end
109
+ if `sep.$$is_hash` && !limit && opts == {}
110
+ sep, limit, opts = false, nil, sep
111
+ elsif `limit.$$is_hash` && opts == {}
112
+ sep, limit, opts = sep, nil, limit
113
+ end
114
+
115
+ orig_sep = sep
116
+
117
+ sep = $/ if sep == false
118
+ sep = /\r?\n\r?\n/ if sep == ''
119
+ sep ||= ''
120
+ sep = sep.to_str unless orig_sep == ''
121
+
122
+ # Try to deduce length of a regexp
123
+ seplen = `orig_sep == '' ? 2 : sep.length`
124
+
125
+ sep = / / if sep == ' ' # WTF is this, String#split(" ") matches all whitespaces???
126
+
127
+ @read_buffer ||= ''
128
+ data = ''
129
+ ret = nil
130
+
131
+ begin
132
+ @read_buffer += data
133
+ if sep != '' && (`sep.$$is_regexp` ? @read_buffer.match?(sep) : @read_buffer.include?(sep))
134
+ orig_buffer = @read_buffer
135
+ ret, @read_buffer = @read_buffer.split(sep, 2)
136
+ ret += orig_buffer[ret.length, seplen] if ret != orig_buffer
137
+ break
138
+ end
139
+ end while data = sysread_noraise(sep == '' ? 65_536 : 1)
140
+
141
+ unless ret
142
+ ret, @read_buffer = (@read_buffer || ''), ''
143
+ ret = nil if ret == ''
144
+ end
145
+
146
+ if ret
147
+ if limit
148
+ ret = ret[0...limit]
149
+ @read_buffer = ret[limit..-1] + @read_buffer
150
+ end
151
+ ret = ret.sub(/\r?\n\z/, '') if opts[:chomp]
152
+ ret = ret.sub(/\A[\r\n]+/, '') if orig_sep == ''
51
153
  end
154
+
155
+ $_ = ret if orig_sep == false
156
+ ret
52
157
  end
53
158
 
54
- module Readable
55
- def readbyte
56
- getbyte
159
+ # This method is to be overloaded, or read_proc can be changed
160
+ def sysread(integer)
161
+ `self.read_proc(integer)` || begin
162
+ @eof = true
163
+ raise EOFError, 'end of file reached'
57
164
  end
165
+ end
166
+
167
+ # @private
168
+ def sysread_noraise(integer)
169
+ sysread(integer)
170
+ rescue EOFError
171
+ nil
172
+ end
58
173
 
59
- def readchar
60
- getc
174
+ def readpartial(integer)
175
+ @read_buffer ||= ''
176
+ part = sysread(integer)
177
+ ret, @read_buffer = @read_buffer + (part || ''), ''
178
+ ret = nil if ret == ''
179
+ ret
180
+ end
181
+
182
+ def read(integer = nil)
183
+ @read_buffer ||= ''
184
+ parts = ''
185
+ ret = nil
186
+
187
+ begin
188
+ @read_buffer += parts
189
+ if integer && @read_buffer.length > integer
190
+ ret, @read_buffer = @read_buffer[0...integer], @read_buffer[integer..-1]
191
+ return ret
192
+ end
193
+ end while parts = sysread_noraise(integer || 65_536)
194
+
195
+ ret, @read_buffer = @read_buffer, ''
196
+ ret
197
+ end
198
+
199
+ # Eaches
200
+
201
+ def readlines(separator = $/)
202
+ each_line(separator).to_a
203
+ end
204
+
205
+ def each(sep = $/, *args, &block)
206
+ return enum_for :each, sep, *args unless block_given?
207
+
208
+ while (s = gets(sep, *args))
209
+ yield(s)
210
+ end
211
+
212
+ self
213
+ end
214
+
215
+ alias each_line each
216
+
217
+ def each_byte(&block)
218
+ return enum_for :each_byte unless block_given?
219
+
220
+ while (s = getbyte)
221
+ yield(s)
222
+ end
223
+
224
+ self
225
+ end
226
+
227
+ def each_char(&block)
228
+ return enum_for :each_char unless block_given?
229
+
230
+ while (s = getc)
231
+ yield(s)
232
+ end
233
+
234
+ self
235
+ end
236
+
237
+ # Closedness
238
+
239
+ def close
240
+ @closed = :both
241
+ end
242
+
243
+ def close_read
244
+ if @closed == :write
245
+ @closed = :both
246
+ else
247
+ @closed = :read
248
+ end
249
+ end
250
+
251
+ def close_write
252
+ if @closed == :read
253
+ @closed = :both
254
+ else
255
+ @closed = :write
61
256
  end
257
+ end
258
+
259
+ def closed?
260
+ @closed == :both
261
+ end
62
262
 
63
- def readline(sep = $/)
64
- raise NotImplementedError
263
+ def closed_read?
264
+ @closed == :read || @closed == :both
265
+ end
266
+
267
+ def closed_write?
268
+ @closed == :write || @closed == :both
269
+ end
270
+
271
+ # @private
272
+ def check_writable
273
+ if closed_write?
274
+ raise IOError, 'not opened for writing'
65
275
  end
276
+ end
66
277
 
67
- def readpartial(integer, outbuf = nil)
68
- raise NotImplementedError
278
+ # @private
279
+ def check_readable
280
+ if closed_read?
281
+ raise IOError, 'not opened for reading'
69
282
  end
70
283
  end
71
284
  end
72
285
 
73
- STDERR = $stderr = IO.new
74
- STDIN = $stdin = IO.new
75
- STDOUT = $stdout = IO.new
286
+ STDIN = $stdin = IO.new(0, 'r')
287
+ STDOUT = $stdout = IO.new(1, 'w')
288
+ STDERR = $stderr = IO.new(2, 'w')
76
289
 
77
290
  `var console = Opal.global.console`
78
291
  STDOUT.write_proc = `typeof(process) === 'object' && typeof(process.stdout) === 'object' ? function(s){process.stdout.write(s)} : function(s){console.log(s)}`
79
292
  STDERR.write_proc = `typeof(process) === 'object' && typeof(process.stderr) === 'object' ? function(s){process.stderr.write(s)} : function(s){console.warn(s)}`
80
293
 
81
- STDOUT.extend(IO::Writable)
82
- STDERR.extend(IO::Writable)
294
+ STDIN.read_proc = `function(s) { var p = prompt(); if (p !== null) return p + "\n"; return nil; }`
@@ -66,8 +66,8 @@ module Kernel
66
66
 
67
67
  function GET_NEXT_ARG() {
68
68
  switch (pos_arg_num) {
69
- case -1: #{raise ArgumentError, "unnumbered(#{`seq_arg_num`}) mixed with numbered"}
70
- case -2: #{raise ArgumentError, "unnumbered(#{`seq_arg_num`}) mixed with named"}
69
+ case -1: #{raise ArgumentError, "unnumbered(#{`seq_arg_num`}) mixed with numbered"} // raise
70
+ case -2: #{raise ArgumentError, "unnumbered(#{`seq_arg_num`}) mixed with named"} // raise
71
71
  }
72
72
  pos_arg_num = seq_arg_num++;
73
73
  return GET_NTH_ARG(pos_arg_num - 1);
@@ -135,6 +135,7 @@ module Kernel
135
135
  switch (format_string.charAt(i)) {
136
136
  case '%':
137
137
  begin_slice = i;
138
+ // no-break
138
139
  case '':
139
140
  case '\n':
140
141
  case '\0':
@@ -240,6 +241,7 @@ module Kernel
240
241
  }
241
242
  hash_parameter_key += format_string.charAt(i);
242
243
  }
244
+ // raise
243
245
 
244
246
  case '*':
245
247
  i++;
@@ -482,6 +484,7 @@ module Kernel
482
484
  case 'A':
483
485
  // Not implemented because there are no specs for this field type.
484
486
  #{raise NotImplementedError, '`A` and `a` format field types are not implemented in Opal yet'}
487
+ // raise
485
488
 
486
489
  case 'c':
487
490
  arg = GET_ARG();