opal 1.8.1 → 1.8.3.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +30 -41
  3. data/.rubocop.yml +3 -1
  4. data/CHANGELOG.md +14 -2
  5. data/Gemfile +1 -0
  6. data/UNRELEASED.md +13 -3
  7. data/docs/compiled_ruby.md +14 -14
  8. data/docs/releasing.md +4 -2
  9. data/exe/opal-build +1 -1
  10. data/lib/opal/compiler.rb +1 -1
  11. data/lib/opal/nodes/call_special.rb +1 -1
  12. data/lib/opal/nodes/literal.rb +1 -1
  13. data/lib/opal/nodes/rescue.rb +1 -1
  14. data/lib/opal/nodes/scope.rb +1 -1
  15. data/lib/opal/version.rb +1 -1
  16. data/opal/corelib/array.rb +1 -1
  17. data/opal/corelib/basic_object.rb +1 -1
  18. data/opal/corelib/constants.rb +3 -3
  19. data/opal/corelib/error.rb +16 -1
  20. data/opal/corelib/hash.rb +1 -1
  21. data/opal/corelib/io.rb +1 -1
  22. data/opal/corelib/module.rb +1 -1
  23. data/opal/corelib/object_space.rb +1 -1
  24. data/opal/corelib/runtime.js +2 -2
  25. data/opal/corelib/string/encoding.rb +6 -6
  26. data/opal/corelib/string.rb +3 -3
  27. data/opal.gemspec +2 -1
  28. data/spec/lib/compiler_spec.rb +16 -6
  29. data/spec/lib/fixtures/build_order/file5.rb.erb +1 -1
  30. data/spec/lib/rewriters/hashes/key_duplicates_rewriter_spec.rb +1 -1
  31. data/spec/lib/spec_helper.rb +11 -0
  32. data/spec/opal/core/array/include_spec.rb +12 -0
  33. data/spec/opal/core/runtime/rescue_spec.rb +5 -5
  34. data/spec/opal/core/string_spec.rb +35 -0
  35. data/spec/opal/stdlib/native/hash_spec.rb +2 -2
  36. data/spec/opal/stdlib/opal_raw_spec.rb +74 -0
  37. data/spec/support/source_map_helper.rb +1 -3
  38. data/stdlib/bigdecimal.rb +14 -14
  39. data/stdlib/date/date_time.rb +1 -1
  40. data/stdlib/deno/file.rb +1 -1
  41. data/stdlib/js.rb +7 -66
  42. data/stdlib/native.rb +3 -3
  43. data/stdlib/nodejs/file.rb +7 -7
  44. data/stdlib/opal/raw.rb +73 -0
  45. data/stdlib/optparse.rb +6 -6
  46. data/stdlib/shellwords.rb +1 -1
  47. data/tasks/testing.rake +13 -2
  48. metadata +27 -10
  49. data/spec/opal/stdlib/js_spec.rb +0 -74
@@ -8,7 +8,7 @@ RSpec.describe Opal::Rewriters::Hashes::KeyDuplicatesRewriter do
8
8
  shared_examples 'it warns' do |code, key_to_warn|
9
9
  context "for #{code} code" do
10
10
  it "warns about #{key_to_warn.inspect} being overwritten" do
11
- expect(Kernel).to receive(:warn).with("warning: key #{key_to_warn.inspect} is duplicated and overwritten")
11
+ expect(Kernel).to receive(:warn).with("warning: key #{key_to_warn.inspect} is duplicated and overwritten") { nil }
12
12
 
13
13
  ast = parse_without_rewriting(code)
14
14
  rewrite(ast)
@@ -5,15 +5,26 @@ if ENV['CHECK_COVERAGE']
5
5
  Coveralls.wear!
6
6
  end
7
7
 
8
+ if ENV['CHECK_COVERAGE_SIMPLECOV']
9
+ require 'simplecov'
10
+ SimpleCov.start
11
+ end
12
+
8
13
  require 'opal'
9
14
 
10
15
  ENV['OPAL_DISABLE_PREFORK_LOGS'] = '1'
11
16
 
17
+ $diagnostic_messages = []
18
+ Opal::Parser.default_parser_class.diagnostics_consumer = ->(diagnostic) do
19
+ $diagnostic_messages << diagnostic.render
20
+ end
21
+
12
22
  # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
13
23
  RSpec.configure do |config|
14
24
  config.before { Opal.reset_paths! unless RUBY_PLATFORM == 'opal' }
15
25
  config.before { Opal::Config.reset! if defined? Opal::Config }
16
26
  config.before { Opal::Processor.reset_cache_key! if defined? Opal::Processor }
27
+ config.before { $diagnostic_messages.clear }
17
28
 
18
29
  # rspec-expectations config goes here. You can use an alternate
19
30
  # assertion/expectation library such as wrong or the stdlib/minitest
@@ -0,0 +1,12 @@
1
+ # backtick_javascript: true
2
+
3
+ describe "Array#include" do
4
+ it "should respect nil values" do
5
+ nileq = Object.new
6
+ def nileq.==(other)
7
+ nil
8
+ end
9
+
10
+ [nileq].should_not include("no match expected")
11
+ end
12
+ end
@@ -1,12 +1,12 @@
1
1
  # backtick_javascript: true
2
2
 
3
3
  describe "The rescue keyword" do
4
- context 'JS::Error' do
4
+ context 'Opal::Raw::Error' do
5
5
  it 'handles raw js throws' do
6
6
  begin
7
7
  `throw { message: 'foo' }`
8
8
  nil
9
- rescue JS::Error => e
9
+ rescue Opal::Raw::Error => e
10
10
  e.JS[:message]
11
11
  end.should == 'foo'
12
12
  end
@@ -14,7 +14,7 @@ describe "The rescue keyword" do
14
14
  it 'handles other Opal error' do
15
15
  begin
16
16
  raise 'bar'
17
- rescue JS::Error => e
17
+ rescue Opal::Raw::Error => e
18
18
  e.message
19
19
  end.should == 'bar'
20
20
  end
@@ -23,7 +23,7 @@ describe "The rescue keyword" do
23
23
  begin
24
24
  `throw { message: 'baz' }`
25
25
  nil
26
- rescue JS::Error, RuntimeError => e
26
+ rescue Opal::Raw::Error, RuntimeError => e
27
27
  e.JS[:message]
28
28
  end.should == 'baz'
29
29
  end
@@ -31,7 +31,7 @@ describe "The rescue keyword" do
31
31
  it 'can be combined with other classes to catch Opal errors' do
32
32
  begin
33
33
  raise 'quux'
34
- rescue JS::Error, RuntimeError => e
34
+ rescue Opal::Raw::Error, RuntimeError => e
35
35
  e.message
36
36
  end.should == 'quux'
37
37
  end
@@ -26,3 +26,38 @@ describe 'Encoding' do
26
26
  end
27
27
  end
28
28
  end
29
+
30
+ describe 'strip methods' do
31
+ def strip_cases(before, after, method)
32
+ before = before ? 1 : 0
33
+ after = after ? 1 : 0
34
+
35
+ it 'strip spaces' do
36
+ "#{" " * before}ABC#{" " * after}".send(method).should == "ABC"
37
+ end
38
+
39
+ it 'strips NUL bytes' do
40
+ "#{"\0" * before}ABC#{"\0" * after}".send(method).should == "ABC"
41
+ end
42
+
43
+ it "doesn't strip NBSPs" do
44
+ "#{"\u{a0}" * before}ABC#{"\u{a0}" * after}".send(method).should != "ABC"
45
+ end
46
+
47
+ it "strips all other supported whitespace characters" do
48
+ "#{"\r\n\t\v\f" * before}ABC#{"\r\n\t\v\f" * after}".send(method).should == "ABC"
49
+ end
50
+ end
51
+
52
+ describe '#lstrip' do
53
+ strip_cases true, false, :lstrip
54
+ end
55
+
56
+ describe '#rstrip' do
57
+ strip_cases false, true, :rstrip
58
+ end
59
+
60
+ describe '#strip' do
61
+ strip_cases true, true, :strip
62
+ end
63
+ end
@@ -82,14 +82,14 @@ describe Hash do
82
82
  it 'converts a hash with native objects as values' do
83
83
  obj = { 'a_key' => `{ key: 1 }` }
84
84
  native = obj.to_n
85
- `#{native}.get('a_key').key`.should == 1
85
+ `#{native}.a_key.key`.should == 1
86
86
  end
87
87
 
88
88
  it 'passes Ruby objects that cannot be converted' do
89
89
  object = Object.new
90
90
  hash = { foo: object }
91
91
  native = hash.to_n
92
- expect(`#{native}.get('foo')`).to eq object
92
+ expect(`#{native}.foo`).to eq object
93
93
  end
94
94
  end
95
95
  end
@@ -0,0 +1,74 @@
1
+ # backtick_javascript: true
2
+
3
+ require 'spec_helper'
4
+ require 'opal/raw'
5
+
6
+ describe 'javascript operations using Opal::Raw module' do
7
+ it 'Opal::Raw.typeof uses typeof to return underlying javascript type' do
8
+ [1, `null`, `undefined`, Object.new, [], ""].each do |v|
9
+ Opal::Raw.typeof(v).should == `typeof #{v}`
10
+ end
11
+ end
12
+
13
+ it 'Opal::Raw.new uses new to create new instance' do
14
+ f = `function(){}`
15
+ f.JS[:prototype].JS[:color] = 'black'
16
+ Opal::Raw.new(f).JS[:color].should == 'black'
17
+ end
18
+
19
+ it 'Opal::Raw.new handles blocks' do
20
+ f = `function(a){this.a = a}`
21
+ Opal::Raw.new(f){1}.JS.a.should == 1
22
+ end
23
+
24
+ it 'Opal::Raw.instanceof uses instanceof to check if value is an instance of a function' do
25
+ f = `function(){}`
26
+ Opal::Raw.instanceof(Opal::Raw.new(f), f).should == true
27
+ Opal::Raw.instanceof(Opal::Raw.new(f), `function(){}`).should == false
28
+ end
29
+
30
+ it 'Opal::Raw.delete uses delete to remove properties from objects' do
31
+ f = `{a:1}`
32
+ f.JS[:a].should == 1
33
+ Opal::Raw.delete(f, :a)
34
+ `#{f.JS[:a]} === undefined`.should == true
35
+ end
36
+
37
+ it 'Opal::Raw.in uses in to check for properties in objects' do
38
+ f = `{a:1}`
39
+ Opal::Raw.in(:a, f).should == true
40
+ Opal::Raw.in(:b, f).should == false
41
+ end
42
+
43
+ it 'Opal::Raw.void returns undefined' do
44
+ f = 1
45
+ `#{Opal::Raw.void(f += 1)} === undefined`.should == true
46
+ f.should == 2
47
+ end
48
+
49
+ it 'Opal::Raw.call calls global javascript methods' do
50
+ Opal::Raw.call(:parseFloat, '1.0').should == 1
51
+ Opal::Raw.call(:parseInt, '1').should == 1
52
+ Opal::Raw.call(:eval, "({a:1})").JS[:a].should == 1
53
+ end
54
+
55
+ it 'Opal::Raw.method_missing calls global javascript methods' do
56
+ Opal::Raw.parseFloat('1.0').should == 1
57
+ Opal::Raw.parseInt('1').should == 1
58
+ end
59
+
60
+ it 'Opal::Raw.call calls global javascript methods with blocks' do
61
+ begin
62
+ Opal::Raw.global.JS[:_test_global_function] = lambda{|pr| pr.call + 1}
63
+ Opal::Raw._test_global_function{1}.should == 2
64
+ ensure
65
+ Opal::Raw.delete(Opal::Raw.global, :_test_global_function)
66
+ end
67
+ end
68
+
69
+ it 'JS.<METHOD> supports complex method calls' do
70
+ obj = `{ foo: function(){return "foo"} }`
71
+ args = [1,2,3]
72
+ obj.JS.foo(*args).should == :foo
73
+ end
74
+ end
@@ -48,7 +48,7 @@ module SourceMapHelper
48
48
 
49
49
  def find_section_in_map_index(index_map)
50
50
  sections = index_map.to_h[:sections]
51
- section, section_index = sections.each.with_index.find do |map, index|
51
+ section, _section_index = sections.each.with_index.find do |map, index|
52
52
  next_map = sections[index + 1] or next true # if there's no next map the current one is good
53
53
 
54
54
  (
@@ -58,8 +58,6 @@ module SourceMapHelper
58
58
  )
59
59
  end
60
60
 
61
- next_section = sections[section_index + 1]
62
-
63
61
  section or raise "no map found for #{inspect} among available sections: #{sections.map { |s| s[:offset] }}"
64
62
  end
65
63
 
data/stdlib/bigdecimal.rb CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  class BigDecimal < Numeric; end
4
4
 
5
- require 'js'
5
+ require 'opal/raw'
6
6
  require 'bigdecimal/bignumber'
7
7
 
8
8
  module Kernel
@@ -57,7 +57,7 @@ class BigDecimal < Numeric
57
57
  attr_reader :bignumber
58
58
 
59
59
  def initialize(initial, digits = 0)
60
- @bignumber = JS.new(BigNumber, initial)
60
+ @bignumber = Opal::Raw.new(BigNumber, initial)
61
61
  end
62
62
 
63
63
  def ==(other)
@@ -102,7 +102,7 @@ class BigDecimal < Numeric
102
102
  end
103
103
 
104
104
  def abs
105
- self.class.new(bignumber.JS.abs)
105
+ BigDecimal(bignumber.JS.abs)
106
106
  end
107
107
 
108
108
  def add(other, digits = 0)
@@ -122,7 +122,7 @@ class BigDecimal < Numeric
122
122
  result = result.JS.toDigits(digits, self.class.mode(ROUND_MODE))
123
123
  end
124
124
 
125
- self.class.new(result)
125
+ BigDecimal(result)
126
126
  end
127
127
 
128
128
  def ceil(n = nil)
@@ -133,9 +133,9 @@ class BigDecimal < Numeric
133
133
  if n.nil?
134
134
  bignumber.JS.round(0, ROUND_CEILING).JS.toNumber
135
135
  elsif n >= 0
136
- self.class.new(bignumber.JS.round(n, ROUND_CEILING))
136
+ BigDecimal(bignumber.JS.round(n, ROUND_CEILING))
137
137
  else
138
- self.class.new(bignumber.JS.round(0, ROUND_CEILING))
138
+ BigDecimal(bignumber.JS.round(0, ROUND_CEILING))
139
139
  end
140
140
  end
141
141
 
@@ -144,7 +144,7 @@ class BigDecimal < Numeric
144
144
  when self.class
145
145
  [other, self]
146
146
  when Number
147
- [self.class.new(other), self]
147
+ [BigDecimal(other), self]
148
148
  else
149
149
  raise TypeError, "#{other.class} can't be coerced into #{self.class}"
150
150
  end
@@ -168,10 +168,10 @@ class BigDecimal < Numeric
168
168
  raise FloatDomainError, "Computation results to 'Infinity'"
169
169
  end
170
170
 
171
- return self.class.new(bignumber.JS.dividedToIntegerBy(other.bignumber))
171
+ return BigDecimal(bignumber.JS.dividedToIntegerBy(other.bignumber))
172
172
  end
173
173
 
174
- self.class.new(bignumber.JS.dividedBy(other.bignumber).JS.round(digits, self.class.mode(ROUND_MODE)))
174
+ BigDecimal(bignumber.JS.dividedBy(other.bignumber).JS.round(digits, self.class.mode(ROUND_MODE)))
175
175
  end
176
176
 
177
177
  def finite?
@@ -185,17 +185,17 @@ class BigDecimal < Numeric
185
185
 
186
186
  def minus(other)
187
187
  other, _ = coerce(other)
188
- self.class.new(bignumber.JS.minus(other.bignumber))
188
+ BigDecimal(bignumber.JS.minus(other.bignumber))
189
189
  end
190
190
 
191
191
  def mult(other, digits = nil)
192
192
  other, _ = coerce(other)
193
193
 
194
194
  if digits.nil?
195
- return self.class.new(bignumber.JS.times(other.bignumber))
195
+ return BigDecimal(bignumber.JS.times(other.bignumber))
196
196
  end
197
197
 
198
- self.class.new(bignumber.JS.times(other.bignumber).JS.round(digits, self.class.mode(ROUND_MODE)))
198
+ BigDecimal(bignumber.JS.times(other.bignumber).JS.round(digits, self.class.mode(ROUND_MODE)))
199
199
  end
200
200
 
201
201
  def nan?
@@ -204,7 +204,7 @@ class BigDecimal < Numeric
204
204
 
205
205
  def quo(other)
206
206
  other, _ = coerce(other)
207
- self.class.new(bignumber.JS.dividedBy(other.bignumber))
207
+ BigDecimal(bignumber.JS.dividedBy(other.bignumber))
208
208
  end
209
209
 
210
210
  def sign
@@ -218,7 +218,7 @@ class BigDecimal < Numeric
218
218
 
219
219
  def sub(other, precision)
220
220
  other, _ = coerce(other)
221
- self.class.new(bignumber.JS.minus(other.bignumber))
221
+ BigDecimal(bignumber.JS.minus(other.bignumber))
222
222
  end
223
223
 
224
224
  def to_f
@@ -29,7 +29,7 @@ class DateTime < Date
29
29
  alias second sec
30
30
 
31
31
  def sec_fraction
32
- @date.usec / 1_000_000r
32
+ @date.usec/1_000_000r
33
33
  end
34
34
 
35
35
  alias second_fraction sec_fraction
data/stdlib/deno/file.rb CHANGED
@@ -193,7 +193,7 @@ class File < IO
193
193
 
194
194
  def self.readable?(path)
195
195
  return false unless exist? path
196
- %{
196
+ %x{
197
197
  try {
198
198
  Deno.openSync(path, {read: true}).close();
199
199
  return true;
data/stdlib/js.rb CHANGED
@@ -1,71 +1,12 @@
1
1
  # backtick_javascript: true
2
2
 
3
- # The JS module provides syntax sugar for calling native javascript
4
- # operators (e.g. typeof, instanceof, new, delete) and global functions
5
- # (e.g. parseFloat, parseInt).
6
- module JS
7
- # Use delete to remove a property from an object.
8
- def delete(object, property)
9
- `delete #{object}[#{property}]`
10
- end
11
-
12
- # The global object
13
- def global
14
- `Opal.global`
15
- end
16
-
17
- # Use in to check for a property in an object.
18
- def in(property, object)
19
- `#{property} in #{object}`
20
- end
21
-
22
- # Use instanceof to return whether value is an instance of the function.
23
- def instanceof(value, func)
24
- `#{value} instanceof #{func}`
25
- end
26
-
27
- # Use new to create a new instance of the prototype of the function.
28
- if `typeof Function.prototype.bind == 'function'`
29
- def new(func, *args, &block)
30
- args.insert(0, `this`)
31
- args << block if block
32
- `new (#{func}.bind.apply(#{func}, #{args}))()`
33
- end
34
- else
35
- def new(func, *args, &block)
36
- args << block if block
37
- f = `function(){return func.apply(this, args)}`
38
- f.JS[:prototype] = func.JS[:prototype]
39
- `new f()`
40
- end
41
- end
3
+ require 'opal/raw'
42
4
 
43
- # Use typeof to return the underlying javascript type of value.
44
- # Note that for undefined values, this will not work exactly like
45
- # the javascript typeof operator, as the argument is evaluated before
46
- # the function call.
47
- def typeof(value)
48
- `typeof #{value}`
49
- end
5
+ warn '[Opal] JS module has been renamed to Opal::Raw and will change semantics in Opal 2.1. ' \
6
+ 'In addition, you will need to require "opal/raw" instead of "js". ' \
7
+ 'To ensure forward compatibility, please update your calls.'
50
8
 
51
- # Use void to return undefined.
52
- def void(expr)
53
- # Could use `undefined` here, but this is closer to the intent of the method
54
- `void #{expr}`
55
- end
56
-
57
- # Call the global javascript function with the given arguments.
58
- def call(func, *args, &block)
59
- g = global
60
- args << block if block
61
- g.JS[func].JS.apply(g, args)
62
- end
63
-
64
- def [](name)
65
- `Opal.global[#{name}]`
66
- end
67
-
68
- alias method_missing call
69
-
70
- extend self
9
+ module JS
10
+ extend Opal::Raw
11
+ include Opal::Raw
71
12
  end
data/stdlib/native.rb CHANGED
@@ -587,14 +587,14 @@ unless Hash.method_defined? :_initialize
587
587
  }
588
588
  end
589
589
 
590
- # @return a JavaScript Map but calling #to_n on
590
+ # @return a JavaScript object, in turn also calling #to_n on
591
591
  # all keys and values.
592
592
  def to_n
593
593
  %x{
594
- var result = new Map();
594
+ var result = {};
595
595
 
596
596
  Opal.hash_each(self, false, function(key, value) {
597
- result.set(#{Native.try_convert(`key`, `key`)} , #{Native.try_convert(`value`, `value`)});
597
+ result[#{Native.try_convert(`key`, `key`)}] = #{Native.try_convert(`value`, `value`)};
598
598
  return [false, false];
599
599
  });
600
600
 
@@ -203,14 +203,14 @@ class File < IO
203
203
 
204
204
  def self.readable?(path)
205
205
  return false unless exist? path
206
- %{
207
- try {
208
- __fs__.accessSync(path, __fs__.R_OK);
209
- return true;
210
- } catch (error) {
211
- return false;
212
- }
206
+ %x{
207
+ try {
208
+ __fs__.accessSync(path, __fs__.R_OK);
209
+ return true;
210
+ } catch (error) {
211
+ return false;
213
212
  }
213
+ }
214
214
  end
215
215
 
216
216
  def self.size(path)
@@ -0,0 +1,73 @@
1
+ # backtick_javascript: true
2
+
3
+ # The Opal::Raw module provides syntax sugar for calling native javascript
4
+ # operators (e.g. typeof, instanceof, new, delete) and global functions
5
+ # (e.g. parseFloat, parseInt).
6
+ module ::Opal
7
+ module Raw
8
+ # Use delete to remove a property from an object.
9
+ def delete(object, property)
10
+ `delete #{object}[#{property}]`
11
+ end
12
+
13
+ # The global object
14
+ def global
15
+ `Opal.global`
16
+ end
17
+
18
+ # Use in to check for a property in an object.
19
+ def in(property, object)
20
+ `#{property} in #{object}`
21
+ end
22
+
23
+ # Use instanceof to return whether value is an instance of the function.
24
+ def instanceof(value, func)
25
+ `#{value} instanceof #{func}`
26
+ end
27
+
28
+ # Use new to create a new instance of the prototype of the function.
29
+ if `typeof Function.prototype.bind == 'function'`
30
+ def new(func, *args, &block)
31
+ args.insert(0, `this`)
32
+ args << block if block
33
+ `new (#{func}.bind.apply(#{func}, #{args}))()`
34
+ end
35
+ else
36
+ def new(func, *args, &block)
37
+ args << block if block
38
+ f = `function(){return func.apply(this, args)}`
39
+ f.JS[:prototype] = func.JS[:prototype]
40
+ `new f()`
41
+ end
42
+ end
43
+
44
+ # Use typeof to return the underlying javascript type of value.
45
+ # Note that for undefined values, this will not work exactly like
46
+ # the javascript typeof operator, as the argument is evaluated before
47
+ # the function call.
48
+ def typeof(value)
49
+ `typeof #{value}`
50
+ end
51
+
52
+ # Use void to return undefined.
53
+ def void(expr)
54
+ # Could use `undefined` here, but this is closer to the intent of the method
55
+ `void #{expr}`
56
+ end
57
+
58
+ # Call the global javascript function with the given arguments.
59
+ def call(func, *args, &block)
60
+ g = global
61
+ args << block if block
62
+ g.JS[func].JS.apply(g, args)
63
+ end
64
+
65
+ def [](name)
66
+ `Opal.global[#{name}]`
67
+ end
68
+
69
+ alias method_missing call
70
+
71
+ extend self # rubocop:disable Style/ModuleFunction
72
+ end
73
+ end
data/stdlib/optparse.rb CHANGED
@@ -1932,7 +1932,7 @@ XXX
1932
1932
  octal = "0(?:[0-7]+(?:_[0-7]+)*|#{binary}|#{hex})?"
1933
1933
  integer = "#{octal}|#{decimal}"
1934
1934
 
1935
- accept(Integer, %r"\A[-+]?(?:#{integer})\z"io) do |s,|
1935
+ accept(Integer, %r"\A[-+]?(?:#{integer})\z"i) do |s,|
1936
1936
  if s
1937
1937
  begin
1938
1938
  Integer(s)
@@ -1946,7 +1946,7 @@ XXX
1946
1946
  # Float number format, and converts to Float.
1947
1947
  #
1948
1948
  float = "(?:#{decimal}(?=(.)?)(?:\\.(?:#{decimal})?)?|\\.#{decimal})(?:E[-+]?#{decimal})?"
1949
- floatpat = %r"\A[-+]?#{float}\z"io
1949
+ floatpat = %r"\A[-+]?#{float}\z"i
1950
1950
  accept(Float, floatpat) { |s,| s.to_f if s }
1951
1951
 
1952
1952
  #
@@ -1954,7 +1954,7 @@ XXX
1954
1954
  # for float format, and Rational for rational format.
1955
1955
  #
1956
1956
  real = "[-+]?(?:#{octal}|#{float})"
1957
- accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/io) do |s, d, f, n,|
1957
+ accept(Numeric, /\A(#{real})(?:\/(#{real}))?\z/i) do |s, d, f, n,|
1958
1958
  if n
1959
1959
  Rational(d, n)
1960
1960
  elsif f
@@ -1967,7 +1967,7 @@ XXX
1967
1967
  #
1968
1968
  # Decimal integer format, to be converted to Integer.
1969
1969
  #
1970
- DecimalInteger = /\A[-+]?#{decimal}\z/io
1970
+ DecimalInteger = /\A[-+]?#{decimal}\z/i
1971
1971
  accept(DecimalInteger, DecimalInteger) do |s,|
1972
1972
  if s
1973
1973
  begin
@@ -1982,7 +1982,7 @@ XXX
1982
1982
  # Ruby/C like octal/hexadecimal/binary integer format, to be converted to
1983
1983
  # Integer.
1984
1984
  #
1985
- OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/io
1985
+ OctalInteger = /\A[-+]?(?:[0-7]+(?:_[0-7]+)*|0(?:#{binary}|#{hex}))\z/i
1986
1986
  accept(OctalInteger, OctalInteger) do |s,|
1987
1987
  if s
1988
1988
  begin
@@ -2084,7 +2084,7 @@ XXX
2084
2084
 
2085
2085
  def self.filter_backtrace(array)
2086
2086
  unless $DEBUG
2087
- array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:"o.method(:=~))
2087
+ array.delete_if(&%r"\A#{Regexp.quote(__FILE__)}:".method(:=~))
2088
2088
  end
2089
2089
  array
2090
2090
  end
data/stdlib/shellwords.rb CHANGED
@@ -98,7 +98,7 @@ module Shellwords
98
98
  # characters when considered special:
99
99
  #
100
100
  # $ ` " \ <newline>
101
- field += (word || sq || (dq && dq.gsub(/\\([$`"\\\n])/, '\\1')) || esc.gsub(/\\(.)/, '\\1'))
101
+ field += word || sq || (dq && dq.gsub(/\\([$`"\\\n])/, '\\1')) || esc.gsub(/\\(.)/, '\\1')
102
102
  if sep
103
103
  words << field
104
104
  field = String.new
data/tasks/testing.rake CHANGED
@@ -1,6 +1,7 @@
1
1
  require_relative "#{__dir__}/../lib/opal/os"
2
2
  require_relative "#{__dir__}/../lib/opal/cli_runners"
3
3
 
4
+ require 'timeout'
4
5
  require 'rspec/core/rake_task'
5
6
 
6
7
  OS = Opal::OS unless defined? OS
@@ -196,9 +197,14 @@ module Testing
196
197
  begin
197
198
  server = Process.spawn "bundle exec rackup --host #{host} --port #{port}"
198
199
  puts 'Waiting for server…'
199
- sleep 0.1 until system "curl -s 'http://#{host}:#{port}/' > /dev/null"
200
+ Timeout.timeout(30) do
201
+ sleep 0.1 until system "curl -s 'http://#{host}:#{port}/' > /dev/null"
202
+ end
200
203
  puts 'Server ready.'
201
204
  yield self
205
+ rescue Timeout::Error
206
+ puts 'Failed to start rack server'
207
+ exit(1)
202
208
  ensure
203
209
  Process.kill(:TERM, server)
204
210
  Process.wait(server)
@@ -252,9 +258,14 @@ module Testing
252
258
  begin
253
259
  server = Process.spawn 'ruby test/opal/http_server.rb'
254
260
  puts 'Waiting for server…'
255
- sleep 0.1 until sinatra_server_running?
261
+ Timeout.timeout(30) do
262
+ sleep 0.1 until sinatra_server_running?
263
+ end
256
264
  puts 'Server ready.'
257
265
  yield self
266
+ rescue Timeout::Error
267
+ puts 'Failed to start Sinatra server'
268
+ exit(1)
258
269
  ensure
259
270
  if OS.windows?
260
271
  # https://blog.simplificator.com/2016/01/18/how-to-kill-processes-on-windows-using-ruby/