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.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +30 -41
- data/.rubocop.yml +3 -1
- data/CHANGELOG.md +14 -2
- data/Gemfile +1 -0
- data/UNRELEASED.md +13 -3
- data/docs/compiled_ruby.md +14 -14
- data/docs/releasing.md +4 -2
- data/exe/opal-build +1 -1
- data/lib/opal/compiler.rb +1 -1
- data/lib/opal/nodes/call_special.rb +1 -1
- data/lib/opal/nodes/literal.rb +1 -1
- data/lib/opal/nodes/rescue.rb +1 -1
- data/lib/opal/nodes/scope.rb +1 -1
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +1 -1
- data/opal/corelib/basic_object.rb +1 -1
- data/opal/corelib/constants.rb +3 -3
- data/opal/corelib/error.rb +16 -1
- data/opal/corelib/hash.rb +1 -1
- data/opal/corelib/io.rb +1 -1
- data/opal/corelib/module.rb +1 -1
- data/opal/corelib/object_space.rb +1 -1
- data/opal/corelib/runtime.js +2 -2
- data/opal/corelib/string/encoding.rb +6 -6
- data/opal/corelib/string.rb +3 -3
- data/opal.gemspec +2 -1
- data/spec/lib/compiler_spec.rb +16 -6
- data/spec/lib/fixtures/build_order/file5.rb.erb +1 -1
- data/spec/lib/rewriters/hashes/key_duplicates_rewriter_spec.rb +1 -1
- data/spec/lib/spec_helper.rb +11 -0
- data/spec/opal/core/array/include_spec.rb +12 -0
- data/spec/opal/core/runtime/rescue_spec.rb +5 -5
- data/spec/opal/core/string_spec.rb +35 -0
- data/spec/opal/stdlib/native/hash_spec.rb +2 -2
- data/spec/opal/stdlib/opal_raw_spec.rb +74 -0
- data/spec/support/source_map_helper.rb +1 -3
- data/stdlib/bigdecimal.rb +14 -14
- data/stdlib/date/date_time.rb +1 -1
- data/stdlib/deno/file.rb +1 -1
- data/stdlib/js.rb +7 -66
- data/stdlib/native.rb +3 -3
- data/stdlib/nodejs/file.rb +7 -7
- data/stdlib/opal/raw.rb +73 -0
- data/stdlib/optparse.rb +6 -6
- data/stdlib/shellwords.rb +1 -1
- data/tasks/testing.rake +13 -2
- metadata +27 -10
- 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)
|
data/spec/lib/spec_helper.rb
CHANGED
@@ -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
|
@@ -1,12 +1,12 @@
|
|
1
1
|
# backtick_javascript: true
|
2
2
|
|
3
3
|
describe "The rescue keyword" do
|
4
|
-
context '
|
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
|
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
|
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
|
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
|
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}.
|
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}.
|
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,
|
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 '
|
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 =
|
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
|
-
|
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
|
-
|
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
|
-
|
136
|
+
BigDecimal(bignumber.JS.round(n, ROUND_CEILING))
|
137
137
|
else
|
138
|
-
|
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
|
-
[
|
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
|
171
|
+
return BigDecimal(bignumber.JS.dividedToIntegerBy(other.bignumber))
|
172
172
|
end
|
173
173
|
|
174
|
-
|
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
|
-
|
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
|
195
|
+
return BigDecimal(bignumber.JS.times(other.bignumber))
|
196
196
|
end
|
197
197
|
|
198
|
-
|
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
|
-
|
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
|
-
|
221
|
+
BigDecimal(bignumber.JS.minus(other.bignumber))
|
222
222
|
end
|
223
223
|
|
224
224
|
def to_f
|
data/stdlib/date/date_time.rb
CHANGED
data/stdlib/deno/file.rb
CHANGED
data/stdlib/js.rb
CHANGED
@@ -1,71 +1,12 @@
|
|
1
1
|
# backtick_javascript: true
|
2
2
|
|
3
|
-
|
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
|
-
|
44
|
-
|
45
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
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
|
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 =
|
594
|
+
var result = {};
|
595
595
|
|
596
596
|
Opal.hash_each(self, false, function(key, value) {
|
597
|
-
result
|
597
|
+
result[#{Native.try_convert(`key`, `key`)}] = #{Native.try_convert(`value`, `value`)};
|
598
598
|
return [false, false];
|
599
599
|
});
|
600
600
|
|
data/stdlib/nodejs/file.rb
CHANGED
@@ -203,14 +203,14 @@ class File < IO
|
|
203
203
|
|
204
204
|
def self.readable?(path)
|
205
205
|
return false unless exist? path
|
206
|
-
%{
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
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)
|
data/stdlib/opal/raw.rb
ADDED
@@ -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"
|
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"
|
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/
|
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/
|
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/
|
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__)}:"
|
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 +=
|
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
|
-
|
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
|
-
|
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/
|