opal 1.8.1 → 1.8.3.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/
|