opal 1.2.0 → 1.3.0.alpha1
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/.eslintrc.await.js +6 -0
- data/.eslintrc.js +34 -0
- data/.github/workflows/build.yml +8 -0
- data/.rubocop.yml +9 -0
- data/CHANGELOG.md +4 -0
- data/README.md +1 -1
- data/Rakefile +1 -0
- data/UNRELEASED.md +64 -38
- data/docs/async.md +109 -0
- data/docs/roda-sprockets.md +0 -2
- data/exe/opal +2 -0
- data/exe/opal-repl +2 -2
- data/lib/opal/builder.rb +5 -1
- data/lib/opal/builder_processors.rb +7 -2
- data/lib/opal/cache/file_cache.rb +119 -0
- data/lib/opal/cache.rb +71 -0
- data/lib/opal/cli.rb +35 -1
- data/lib/opal/cli_options.rb +21 -0
- data/lib/opal/cli_runners/chrome.rb +21 -14
- data/lib/opal/cli_runners/chrome_cdp_interface.js +30285 -0
- data/lib/opal/cli_runners/{chrome.js → chrome_cdp_interface.rb} +27 -6
- data/lib/opal/cli_runners/compiler.rb +2 -1
- data/lib/opal/cli_runners/gjs.rb +27 -0
- data/lib/opal/cli_runners/mini_racer.rb +36 -0
- data/lib/opal/cli_runners/source-map-support-browser.js +276 -91
- data/lib/opal/cli_runners/source-map-support-node.js +276 -91
- data/lib/opal/cli_runners/source-map-support.js +60 -18
- data/lib/opal/cli_runners.rb +2 -0
- data/lib/opal/compiler.rb +99 -10
- data/lib/opal/fragment.rb +77 -14
- data/lib/opal/nodes/args/extract_kwrestarg.rb +6 -4
- data/lib/opal/nodes/args/extract_restarg.rb +10 -12
- data/lib/opal/nodes/args.rb +28 -0
- data/lib/opal/nodes/base.rb +29 -5
- data/lib/opal/nodes/call.rb +123 -2
- data/lib/opal/nodes/case.rb +7 -1
- data/lib/opal/nodes/class.rb +12 -2
- data/lib/opal/nodes/def.rb +3 -23
- data/lib/opal/nodes/definitions.rb +21 -4
- data/lib/opal/nodes/helpers.rb +2 -2
- data/lib/opal/nodes/if.rb +39 -9
- data/lib/opal/nodes/iter.rb +15 -3
- data/lib/opal/nodes/lambda.rb +3 -1
- data/lib/opal/nodes/literal.rb +13 -7
- data/lib/opal/nodes/logic.rb +2 -2
- data/lib/opal/nodes/module.rb +12 -2
- data/lib/opal/nodes/rescue.rb +59 -34
- data/lib/opal/nodes/scope.rb +88 -6
- data/lib/opal/nodes/super.rb +52 -25
- data/lib/opal/nodes/top.rb +13 -7
- data/lib/opal/nodes/while.rb +7 -1
- data/lib/opal/parser/patch.rb +2 -1
- data/lib/opal/repl.rb +137 -49
- data/lib/opal/rewriters/binary_operator_assignment.rb +10 -10
- data/lib/opal/rewriters/block_to_iter.rb +3 -3
- data/lib/opal/rewriters/for_rewriter.rb +7 -7
- data/lib/opal/rewriters/js_reserved_words.rb +5 -3
- data/lib/opal/source_map/file.rb +7 -4
- data/lib/opal/source_map/map.rb +17 -3
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +2 -2
- data/opal/corelib/binding.rb +46 -0
- data/opal/corelib/boolean.rb +54 -4
- data/opal/corelib/class.rb +2 -0
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/error.rb +98 -12
- data/opal/corelib/io.rb +250 -38
- data/opal/corelib/kernel/format.rb +5 -2
- data/opal/corelib/kernel.rb +44 -23
- data/opal/corelib/main.rb +5 -0
- data/opal/corelib/method.rb +1 -0
- data/opal/corelib/module.rb +28 -0
- data/opal/corelib/number.rb +12 -1
- data/opal/corelib/random/seedrandom.js.rb +2 -2
- data/opal/corelib/regexp.rb +47 -3
- data/opal/corelib/runtime.js +152 -12
- data/opal/corelib/string/encoding.rb +17 -17
- data/opal/corelib/string.rb +2 -0
- data/opal/corelib/struct.rb +10 -3
- data/opal/corelib/trace_point.rb +57 -0
- data/opal/opal/full.rb +2 -0
- data/package.json +3 -2
- data/spec/filters/bugs/array.rb +0 -1
- data/spec/filters/bugs/basicobject.rb +0 -1
- data/spec/filters/bugs/binding.rb +27 -0
- data/spec/filters/bugs/enumerator.rb +132 -0
- data/spec/filters/bugs/exception.rb +70 -93
- data/spec/filters/bugs/float.rb +0 -1
- data/spec/filters/bugs/kernel.rb +3 -9
- data/spec/filters/bugs/language.rb +15 -58
- data/spec/filters/bugs/main.rb +16 -0
- data/spec/filters/bugs/matrix.rb +39 -0
- data/spec/filters/bugs/method.rb +0 -2
- data/spec/filters/bugs/module.rb +36 -79
- data/spec/filters/bugs/proc.rb +0 -1
- data/spec/filters/bugs/regexp.rb +0 -16
- data/spec/filters/bugs/trace_point.rb +12 -0
- data/spec/filters/bugs/warnings.rb +0 -4
- data/spec/filters/unsupported/freeze.rb +2 -0
- data/spec/filters/unsupported/privacy.rb +4 -0
- data/spec/lib/compiler_spec.rb +7 -1
- data/spec/lib/repl_spec.rb +4 -2
- data/spec/lib/source_map/file_spec.rb +1 -1
- data/spec/mspec-opal/formatters.rb +18 -4
- data/spec/mspec-opal/runner.rb +2 -2
- data/spec/opal/core/boolean_spec.rb +44 -0
- data/spec/opal/core/hash_spec.rb +8 -0
- data/spec/opal/core/number/to_s_spec.rb +11 -0
- data/spec/opal/stdlib/json/ext_spec.rb +3 -3
- data/spec/opal/stdlib/logger/logger_spec.rb +10 -1
- data/spec/ruby_specs +18 -0
- data/stdlib/await.rb +83 -0
- data/stdlib/base64.rb +4 -4
- data/stdlib/bigdecimal/bignumber.js.rb +4 -2
- data/stdlib/bigdecimal.rb +1 -0
- data/stdlib/gjs/io.rb +33 -0
- data/stdlib/gjs/kernel.rb +5 -0
- data/stdlib/gjs.rb +2 -0
- data/stdlib/js.rb +4 -0
- data/stdlib/json.rb +3 -3
- data/stdlib/logger.rb +1 -1
- data/stdlib/nashorn/file.rb +2 -0
- data/stdlib/nodejs/env.rb +7 -0
- data/stdlib/nodejs/file.rb +6 -41
- data/stdlib/nodejs/io.rb +21 -5
- data/stdlib/nodejs/js-yaml-3-6-1.js +2 -2
- data/stdlib/opal/miniracer.rb +6 -0
- data/stdlib/opal/platform.rb +4 -0
- data/stdlib/opal/repl_js.rb +5 -0
- data/stdlib/opal/replutils.rb +271 -0
- data/stdlib/opal-parser.rb +24 -11
- data/stdlib/opal-platform.rb +8 -0
- data/stdlib/promise/v2.rb +16 -4
- data/stdlib/promise.rb +14 -0
- data/stdlib/stringio.rb +13 -110
- data/stdlib/thread.rb +29 -0
- data/tasks/building.rake +10 -4
- data/tasks/linting-parse-eslint-results.js +39 -0
- data/tasks/linting.rake +38 -28
- data/tasks/performance/asciidoctor_test.rb.erb +6 -0
- data/tasks/performance/optimization_status.rb +77 -0
- data/tasks/performance.rake +149 -0
- data/tasks/testing.rake +9 -1
- data/test/nodejs/test_await.rb +169 -0
- data/test/opal/promisev2/test_error.rb +9 -3
- data/test/opal/unsupported_and_bugs.rb +5 -0
- data/vendored-minitest/minitest/benchmark.rb +9 -7
- data/vendored-minitest/minitest/test.rb +14 -12
- data/vendored-minitest/minitest.rb +19 -16
- data/yarn.lock +686 -117
- metadata +60 -23
- data/.jshintrc +0 -41
- data/spec/filters/unsupported/refinements.rb +0 -8
- data/vendored-minitest/minitest/hell.rb +0 -11
- data/vendored-minitest/minitest/parallel.rb +0 -65
- data/vendored-minitest/minitest/pride.rb +0 -4
- data/vendored-minitest/minitest/pride_plugin.rb +0 -142
- data/vendored-minitest/minitest/unit.rb +0 -45
data/lib/opal/repl.rb
CHANGED
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
require 'opal'
|
|
4
4
|
require 'securerandom'
|
|
5
|
+
require 'stringio'
|
|
6
|
+
require 'fileutils'
|
|
5
7
|
|
|
6
8
|
module Opal
|
|
7
9
|
class REPL
|
|
8
10
|
HISTORY_PATH = File.expand_path('~/.opal-repl-history')
|
|
9
11
|
|
|
12
|
+
attr_accessor :colorize
|
|
13
|
+
|
|
10
14
|
def initialize
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
rescue LoadError
|
|
14
|
-
abort 'opal-repl depends on mini_racer gem, which is not currently installed'
|
|
15
|
-
end
|
|
15
|
+
@argv = []
|
|
16
|
+
@colorize = true
|
|
16
17
|
|
|
17
18
|
begin
|
|
18
19
|
require 'readline'
|
|
@@ -20,80 +21,154 @@ module Opal
|
|
|
20
21
|
abort 'opal-repl depends on readline, which is not currently available'
|
|
21
22
|
end
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
begin
|
|
25
|
+
FileUtils.touch(HISTORY_PATH)
|
|
26
|
+
rescue
|
|
27
|
+
nil
|
|
28
|
+
end
|
|
25
29
|
@history = File.exist?(HISTORY_PATH)
|
|
26
30
|
end
|
|
27
31
|
|
|
28
|
-
def run(
|
|
32
|
+
def run(argv = [])
|
|
33
|
+
@argv = argv
|
|
34
|
+
|
|
35
|
+
savepoint = save_tty
|
|
29
36
|
load_opal
|
|
30
|
-
load_file(filename) if filename
|
|
31
37
|
load_history
|
|
32
38
|
run_input_loop
|
|
33
39
|
ensure
|
|
34
40
|
dump_history
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def load_file(filename)
|
|
38
|
-
raise "file does not exist: #{filename}" unless File.exist? filename
|
|
39
|
-
eval_ruby File.read(filename)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
# A polyfill so that SecureRandom works in repl correctly.
|
|
43
|
-
def random_bytes(bytes)
|
|
44
|
-
::SecureRandom.bytes(bytes).split('').map(&:ord)
|
|
41
|
+
restore_tty(savepoint)
|
|
45
42
|
end
|
|
46
43
|
|
|
47
44
|
def load_opal
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
runner = @argv.reject { |i| i == '--repl' }
|
|
46
|
+
runner += ['-e', 'require "opal/repl_js"']
|
|
47
|
+
runner = %w[bundle exec opal] + runner
|
|
48
|
+
|
|
49
|
+
@pipe = IO.popen(runner, 'r+',
|
|
50
|
+
# What I try to achieve here: let the runner ignore
|
|
51
|
+
# interrupts. Those should be handled by a supervisor.
|
|
52
|
+
pgroup: true,
|
|
53
|
+
new_pgroup: true,
|
|
54
|
+
)
|
|
58
55
|
end
|
|
59
56
|
|
|
60
57
|
def run_input_loop
|
|
61
|
-
# on SIGINT lets just return from the loop..
|
|
62
|
-
previous_trap = trap('SIGINT') { return }
|
|
63
|
-
|
|
64
58
|
while (line = readline)
|
|
65
|
-
|
|
59
|
+
eval_ruby(line)
|
|
66
60
|
end
|
|
67
|
-
|
|
61
|
+
rescue Interrupt
|
|
62
|
+
@incomplete = nil
|
|
63
|
+
retry
|
|
68
64
|
ensure
|
|
69
|
-
|
|
65
|
+
finish
|
|
70
66
|
end
|
|
71
67
|
|
|
72
|
-
|
|
68
|
+
def finish
|
|
69
|
+
@pipe.close
|
|
70
|
+
rescue
|
|
71
|
+
nil
|
|
72
|
+
end
|
|
73
73
|
|
|
74
74
|
def eval_ruby(code)
|
|
75
75
|
builder = Opal::Builder.new
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
silencer = Silencer.new
|
|
77
|
+
|
|
78
|
+
code = "#{@incomplete}#{code}"
|
|
79
|
+
if code.start_with? 'ls '
|
|
80
|
+
eval_code = code[3..-1]
|
|
81
|
+
mode = :ls
|
|
82
|
+
elsif code == 'ls'
|
|
83
|
+
eval_code = 'self'
|
|
84
|
+
mode = :ls
|
|
85
|
+
elsif code.start_with? 'show '
|
|
86
|
+
eval_code = code[5..-1]
|
|
87
|
+
mode = :show
|
|
88
|
+
else
|
|
89
|
+
eval_code = code
|
|
90
|
+
mode = :inspect
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
begin
|
|
94
|
+
silencer.silence do
|
|
95
|
+
builder.build_str(eval_code, '(irb)', irb: true, const_missing: true)
|
|
96
|
+
end
|
|
97
|
+
@incomplete = nil
|
|
98
|
+
rescue Opal::SyntaxError => e
|
|
99
|
+
if LINEBREAKS.include?(e.message)
|
|
100
|
+
@incomplete = "#{code}\n"
|
|
101
|
+
else
|
|
102
|
+
@incomplete = nil
|
|
103
|
+
if silencer.warnings.empty?
|
|
104
|
+
warn e.full_message
|
|
105
|
+
else
|
|
106
|
+
# Most likely a parser error
|
|
107
|
+
warn silencer.warnings
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
return
|
|
111
|
+
end
|
|
112
|
+
builder.processed[0...-1].each { |js_code| eval_js(:silent, js_code.to_s) }
|
|
78
113
|
last_processed_file = builder.processed.last.to_s
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
114
|
+
|
|
115
|
+
if mode == :show
|
|
116
|
+
puts last_processed_file
|
|
117
|
+
return
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
eval_js(mode, last_processed_file)
|
|
121
|
+
rescue Interrupt, SystemExit => e
|
|
122
|
+
raise e
|
|
123
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
124
|
+
puts e.full_message(highlight: true)
|
|
85
125
|
end
|
|
86
126
|
|
|
87
|
-
|
|
88
|
-
|
|
127
|
+
private
|
|
128
|
+
|
|
129
|
+
LINEBREAKS = [
|
|
130
|
+
'unexpected token $end',
|
|
131
|
+
'unterminated string meets end of file'
|
|
132
|
+
].freeze
|
|
133
|
+
|
|
134
|
+
class Silencer
|
|
135
|
+
def initialize
|
|
136
|
+
@stderr = $stderr
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def silence
|
|
140
|
+
@collector = StringIO.new
|
|
141
|
+
$stderr = @collector
|
|
142
|
+
yield
|
|
143
|
+
ensure
|
|
144
|
+
$stderr = @stderr
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def warnings
|
|
148
|
+
@collector.string
|
|
149
|
+
end
|
|
89
150
|
end
|
|
90
151
|
|
|
91
|
-
def
|
|
92
|
-
|
|
152
|
+
def eval_js(mode, code)
|
|
153
|
+
obj = { mode: mode, code: code, colors: colorize }.to_json
|
|
154
|
+
@pipe.puts obj
|
|
155
|
+
while (line = @pipe.readline)
|
|
156
|
+
break if line.chomp == '<<<ready>>>'
|
|
157
|
+
puts line
|
|
158
|
+
end
|
|
159
|
+
rescue Interrupt => e
|
|
160
|
+
# A child stopped responding... let's create a new one
|
|
161
|
+
warn "* Killing #{@pipe.pid}"
|
|
162
|
+
Process.kill('-KILL', @pipe.pid)
|
|
163
|
+
load_opal
|
|
164
|
+
raise e
|
|
165
|
+
rescue EOFError, Errno::EPIPE
|
|
166
|
+
exit $?.exitstatus
|
|
93
167
|
end
|
|
94
168
|
|
|
95
169
|
def readline
|
|
96
|
-
|
|
170
|
+
prompt = @incomplete ? '.. ' : '>> '
|
|
171
|
+
Readline.readline prompt, true
|
|
97
172
|
end
|
|
98
173
|
|
|
99
174
|
def load_history
|
|
@@ -106,5 +181,18 @@ module Opal
|
|
|
106
181
|
length = Readline::HISTORY.size > 1000 ? 1000 : Readline::HISTORY.size
|
|
107
182
|
File.write(HISTORY_PATH, Readline::HISTORY.to_a[-length..-1].join("\n"))
|
|
108
183
|
end
|
|
184
|
+
|
|
185
|
+
# How do we support Win32?
|
|
186
|
+
def save_tty
|
|
187
|
+
%x{stty -g}.chomp
|
|
188
|
+
rescue
|
|
189
|
+
nil
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def restore_tty(savepoint)
|
|
193
|
+
system('stty', savepoint)
|
|
194
|
+
rescue
|
|
195
|
+
nil
|
|
196
|
+
end
|
|
109
197
|
end
|
|
110
198
|
end
|
|
@@ -16,11 +16,11 @@ module Opal
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
GET_SET = ->(get_type, set_type) {
|
|
19
|
-
->(lhs, operation, rhs) {
|
|
20
|
-
get_node = lhs.updated(get_type)
|
|
21
|
-
set_node =
|
|
19
|
+
->(node, lhs, operation, rhs) {
|
|
20
|
+
get_node = lhs.updated(get_type) # lhs
|
|
21
|
+
set_node = node.updated(:send, [get_node, operation, rhs]) # lhs + rhs
|
|
22
22
|
|
|
23
|
-
lhs.updated(set_type, [*lhs, set_node])
|
|
23
|
+
lhs.updated(set_type, [*lhs, set_node]) # lhs = lhs + rhs
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
@@ -48,7 +48,7 @@ module Opal
|
|
|
48
48
|
# Produces `recvr.meth = recvr.meth + rhs`
|
|
49
49
|
# (lhs is a recvr.meth, op is :+)
|
|
50
50
|
class SendHandler < self
|
|
51
|
-
def self.call(lhs, operation, rhs)
|
|
51
|
+
def self.call(node, lhs, operation, rhs)
|
|
52
52
|
recvr, reader_method, *args = *lhs
|
|
53
53
|
|
|
54
54
|
# If recvr is a complex expression it must be cached.
|
|
@@ -62,11 +62,11 @@ module Opal
|
|
|
62
62
|
writer_method = :"#{reader_method}="
|
|
63
63
|
|
|
64
64
|
call_reader = lhs.updated(:send, [recvr, reader_method, *args]) # $tmp.meth
|
|
65
|
-
call_op =
|
|
65
|
+
call_op = node.updated(:send, [call_reader, operation, rhs]) # $tmp.meth + rhs
|
|
66
66
|
call_writer = lhs.updated(:send, [recvr, writer_method, *args, call_op]) # $tmp.meth = $tmp.meth + rhs
|
|
67
67
|
|
|
68
68
|
if cache_recvr
|
|
69
|
-
|
|
69
|
+
node.updated(:begin, [cache_recvr, call_writer])
|
|
70
70
|
else
|
|
71
71
|
call_writer
|
|
72
72
|
end
|
|
@@ -78,7 +78,7 @@ module Opal
|
|
|
78
78
|
# NOTE: Later output of this handler gets post-processed by this rewriter again
|
|
79
79
|
# using SendHandler to `recvr.nil? ? nil : (recvr.meth = recvr.meth + rhs)`
|
|
80
80
|
class ConditionalSendHandler < self
|
|
81
|
-
def self.call(lhs, operation, rhs)
|
|
81
|
+
def self.call(node, lhs, operation, rhs)
|
|
82
82
|
recvr, meth, *args = *lhs
|
|
83
83
|
|
|
84
84
|
recvr_tmp = new_temp
|
|
@@ -87,7 +87,7 @@ module Opal
|
|
|
87
87
|
|
|
88
88
|
recvr_is_nil = s(:send, recvr, :nil?) # recvr.nil?
|
|
89
89
|
plain_send = lhs.updated(:send, [recvr, meth, *args]) # recvr.meth
|
|
90
|
-
plain_op_asgn =
|
|
90
|
+
plain_op_asgn = node.updated(:op_asgn, [plain_send, operation, rhs]) # recvr.meth += rhs
|
|
91
91
|
|
|
92
92
|
s(:begin,
|
|
93
93
|
cache_recvr,
|
|
@@ -116,7 +116,7 @@ module Opal
|
|
|
116
116
|
|
|
117
117
|
result = HANDLERS
|
|
118
118
|
.fetch(lhs.type) { error "cannot handle LHS type: #{lhs.type}" }
|
|
119
|
-
.call(lhs, op, rhs)
|
|
119
|
+
.call(node, lhs, op, rhs)
|
|
120
120
|
|
|
121
121
|
process(result)
|
|
122
122
|
end
|
|
@@ -6,11 +6,11 @@ module Opal
|
|
|
6
6
|
module Rewriters
|
|
7
7
|
class BlockToIter < Base
|
|
8
8
|
def on_block(node)
|
|
9
|
-
recvr, args, body = *
|
|
9
|
+
recvr, args, body = *node
|
|
10
10
|
iter_node = s(:iter, args, body)
|
|
11
|
-
recvr.updated(
|
|
11
|
+
process recvr.updated(
|
|
12
12
|
nil,
|
|
13
|
-
recvr.children + [iter_node],
|
|
13
|
+
(recvr.children + [iter_node]),
|
|
14
14
|
)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -52,7 +52,7 @@ module Opal
|
|
|
52
52
|
loop_variable_assignment = case loop_variable.type
|
|
53
53
|
when :mlhs # multiple left-hand statement like in "for i,j in [[1, 2], [3, 4]]"
|
|
54
54
|
# i, j = __jstmp
|
|
55
|
-
|
|
55
|
+
loop_variable.updated(:masgn, [loop_variable, get_tmp_loop_variable])
|
|
56
56
|
else # single argument like "for i in (0..3)"
|
|
57
57
|
# i = __jstmp
|
|
58
58
|
loop_variable << get_tmp_loop_variable
|
|
@@ -60,13 +60,13 @@ module Opal
|
|
|
60
60
|
|
|
61
61
|
loop_body = prepend_to_body(loop_body, loop_variable_assignment)
|
|
62
62
|
|
|
63
|
-
node =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
63
|
+
node = node.updated(:send, [iterating_value, :each, # (0..3).each {
|
|
64
|
+
node.updated(:iter, [s(:args, s(:arg, tmp_loop_variable)), # |__jstmp|
|
|
65
|
+
process(loop_body)] # i = __jstmp; j = i + 1 }
|
|
66
|
+
)]
|
|
67
|
+
)
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
node.updated(:begin, [*outer_assigns, node])
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
class LocalVariableAssigns < Base
|
|
@@ -86,9 +86,9 @@ module Opal
|
|
|
86
86
|
super(node)
|
|
87
87
|
end
|
|
88
88
|
|
|
89
|
-
# Restarg
|
|
90
|
-
# because
|
|
91
|
-
# def m(
|
|
89
|
+
# Restarg and kwrestarg are special cases
|
|
90
|
+
# because they may have no name
|
|
91
|
+
# def m(*, **); end
|
|
92
92
|
def on_restarg(node)
|
|
93
93
|
name, _ = *node
|
|
94
94
|
|
|
@@ -99,6 +99,8 @@ module Opal
|
|
|
99
99
|
node
|
|
100
100
|
end
|
|
101
101
|
|
|
102
|
+
alias on_kwrestarg on_restarg
|
|
103
|
+
|
|
102
104
|
def on_argument(node)
|
|
103
105
|
node = super(node)
|
|
104
106
|
name, value = *node
|
data/lib/opal/source_map/file.rb
CHANGED
|
@@ -7,11 +7,12 @@ class Opal::SourceMap::File
|
|
|
7
7
|
attr_reader :file
|
|
8
8
|
attr_reader :source
|
|
9
9
|
|
|
10
|
-
def initialize(fragments, file, source)
|
|
10
|
+
def initialize(fragments, file, source, generated_code = nil)
|
|
11
11
|
@fragments = fragments
|
|
12
12
|
@file = file
|
|
13
13
|
@source = source
|
|
14
14
|
@names_map = Hash.new { |hash, name| hash[name] = hash.size }
|
|
15
|
+
@generated_code = generated_code
|
|
15
16
|
@absolute_mappings = nil
|
|
16
17
|
end
|
|
17
18
|
|
|
@@ -98,8 +99,10 @@ class Opal::SourceMap::File
|
|
|
98
99
|
# field, in which case the whole value is represented.
|
|
99
100
|
def segment_from_fragment(fragment, generated_column)
|
|
100
101
|
source_index = 0 # always 0, we're dealing with a single file
|
|
101
|
-
original_line = fragment.line - 1
|
|
102
|
-
|
|
102
|
+
original_line = (fragment.line || 0) - 1 # fragments have 1-based lines
|
|
103
|
+
original_line = 0 if original_line < 0 # line 0 (-1) for fragments in source maps will crash
|
|
104
|
+
# browsers devtools and the webpack build process
|
|
105
|
+
original_column = fragment.column || 0 # fragments have 0-based columns
|
|
103
106
|
|
|
104
107
|
if fragment.source_map_name
|
|
105
108
|
map_name_index = (@names_map[fragment.source_map_name.to_s] ||= @names_map.size)
|
|
@@ -162,7 +165,7 @@ class Opal::SourceMap::File
|
|
|
162
165
|
generated_column = 0
|
|
163
166
|
segments = []
|
|
164
167
|
raw_segments.each do |(generated_code, fragment)|
|
|
165
|
-
|
|
168
|
+
unless fragment.is_a?(Opal::Fragment) && fragment.skip_source_map?
|
|
166
169
|
segments << segment_from_fragment(fragment, generated_column)
|
|
167
170
|
end
|
|
168
171
|
generated_column += generated_code.size
|
data/lib/opal/source_map/map.rb
CHANGED
|
@@ -5,11 +5,11 @@ require 'json'
|
|
|
5
5
|
|
|
6
6
|
module Opal::SourceMap::Map
|
|
7
7
|
def to_h
|
|
8
|
-
map
|
|
8
|
+
@to_h || map
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def to_json
|
|
12
|
-
|
|
12
|
+
to_h.to_json
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def as_json(*)
|
|
@@ -17,10 +17,24 @@ module Opal::SourceMap::Map
|
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def to_s
|
|
20
|
-
|
|
20
|
+
to_h.to_s
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def to_data_uri_comment
|
|
24
24
|
"//# sourceMappingURL=data:application/json;base64,#{Base64.encode64(to_json).delete("\n")}"
|
|
25
25
|
end
|
|
26
|
+
|
|
27
|
+
# Marshaling for cache shortpath
|
|
28
|
+
def cache
|
|
29
|
+
@to_h ||= map
|
|
30
|
+
self
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def marshal_dump
|
|
34
|
+
[to_h, generated_code]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def marshal_load(value)
|
|
38
|
+
@to_h, @generated_code = value
|
|
39
|
+
end
|
|
26
40
|
end
|
data/lib/opal/version.rb
CHANGED
data/opal/corelib/array.rb
CHANGED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
class Binding
|
|
2
|
+
# @private
|
|
3
|
+
def initialize(jseval, scope_variables, receiver, source_location)
|
|
4
|
+
@jseval, @scope_variables, @receiver, @source_location = \
|
|
5
|
+
jseval, scope_variables, receiver, source_location
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def js_eval(*args)
|
|
9
|
+
@jseval.call(*args)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def local_variable_get(symbol)
|
|
13
|
+
js_eval(symbol)
|
|
14
|
+
rescue Exception
|
|
15
|
+
raise NameError, "local variable `#{symbol}' is not defined for #{inspect}"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def local_variable_set(symbol, value)
|
|
19
|
+
js_eval(symbol, value)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def local_variables
|
|
23
|
+
@scope_variables
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def local_variable_defined?(value)
|
|
27
|
+
@scope_variables.include?(value)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def eval(str, file = nil, line = nil)
|
|
31
|
+
return receiver if str == 'self'
|
|
32
|
+
|
|
33
|
+
Kernel.eval(str, self, file, line)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
attr_reader :receiver, :source_location
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
module Kernel
|
|
40
|
+
def binding
|
|
41
|
+
raise "Opal doesn't support dynamic calls to binding"
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
TOPLEVEL_BINDING = binding
|
|
46
|
+
`#{TOPLEVEL_BINDING}.source_location = ["<main>", 0]`
|
data/opal/corelib/boolean.rb
CHANGED
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
class Boolean < `Boolean`
|
|
2
2
|
`Opal.defineProperty(self.$$prototype, '$$is_boolean', true)`
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
%x{
|
|
5
|
+
var properties = ['$$class', '$$meta'];
|
|
6
|
+
|
|
7
|
+
for (var i = 0; i < properties.length; i++) {
|
|
8
|
+
Object.defineProperty(self.$$prototype, properties[i], {
|
|
9
|
+
configurable: true,
|
|
10
|
+
enumerable: false,
|
|
11
|
+
get: function() {
|
|
12
|
+
return this == true ? Opal.TrueClass :
|
|
13
|
+
this == false ? Opal.FalseClass :
|
|
14
|
+
Opal.Boolean;
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
Object.defineProperty(self.$$prototype, "$$id", {
|
|
20
|
+
configurable: true,
|
|
21
|
+
enumerable: false,
|
|
22
|
+
get: function() {
|
|
23
|
+
return this == true ? 2 :
|
|
24
|
+
this == false ? 0 :
|
|
25
|
+
nil;
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
}
|
|
4
29
|
|
|
5
30
|
class << self
|
|
6
31
|
def allocate
|
|
@@ -40,13 +65,15 @@ class Boolean < `Boolean`
|
|
|
40
65
|
alias eql? ==
|
|
41
66
|
|
|
42
67
|
def singleton_class
|
|
43
|
-
|
|
68
|
+
`self.$$meta`
|
|
44
69
|
end
|
|
45
70
|
|
|
46
71
|
def to_s
|
|
47
72
|
`(self == true) ? 'true' : 'false'`
|
|
48
73
|
end
|
|
49
74
|
|
|
75
|
+
alias inspect to_s
|
|
76
|
+
|
|
50
77
|
def dup
|
|
51
78
|
self
|
|
52
79
|
end
|
|
@@ -54,10 +81,33 @@ class Boolean < `Boolean`
|
|
|
54
81
|
def clone(freeze: true)
|
|
55
82
|
self
|
|
56
83
|
end
|
|
84
|
+
|
|
85
|
+
# See: https://github.com/opal/opal/issues/2230
|
|
86
|
+
#
|
|
87
|
+
# This is a hack that allows you to add methods to TrueClass and FalseClass.
|
|
88
|
+
# Do note, that while true and false have a correct $$class (it's either
|
|
89
|
+
# TrueClass or FalseClass), their prototype is `Boolean.$$prototype`, which
|
|
90
|
+
# basically means that when calling `true.something` we actually call
|
|
91
|
+
# `Boolean#something` instead of `TrueClass#something`. So using
|
|
92
|
+
# method_missing we dispatch it to `TrueClass/FalseClass#something` correctly.
|
|
93
|
+
#
|
|
94
|
+
# The downside is that a correct implementation would also allow us to override
|
|
95
|
+
# the methods defined on Boolean, but our implementation doesn't allow that,
|
|
96
|
+
# unless you define them on Boolean and not on TrueClass/FalseClass.
|
|
97
|
+
def method_missing(method, *args, &block)
|
|
98
|
+
`var body = self.$$class.$$prototype['$' + #{method}]`
|
|
99
|
+
super unless `typeof body !== 'undefined' && !body.$$stub`
|
|
100
|
+
`Opal.send(self, body, #{args}, #{block})`
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def respond_to_missing?(method, _include_all = false)
|
|
104
|
+
`var body = self.$$class.$$prototype['$' + #{method}]`
|
|
105
|
+
`typeof body !== 'undefined' && !body.$$stub`
|
|
106
|
+
end
|
|
57
107
|
end
|
|
58
108
|
|
|
59
|
-
TrueClass
|
|
60
|
-
FalseClass
|
|
109
|
+
class TrueClass < Boolean; end
|
|
110
|
+
class FalseClass < Boolean; end
|
|
61
111
|
|
|
62
112
|
TRUE = true
|
|
63
113
|
FALSE = false
|
data/opal/corelib/class.rb
CHANGED
data/opal/corelib/constants.rb
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
RUBY_PLATFORM = 'opal'
|
|
2
2
|
RUBY_ENGINE = 'opal'
|
|
3
3
|
RUBY_VERSION = '3.0.2'
|
|
4
|
-
RUBY_ENGINE_VERSION = '1.
|
|
5
|
-
RUBY_RELEASE_DATE = '2021-
|
|
4
|
+
RUBY_ENGINE_VERSION = '1.3.0.alpha1'
|
|
5
|
+
RUBY_RELEASE_DATE = '2021-09-29'
|
|
6
6
|
RUBY_PATCHLEVEL = 0
|
|
7
7
|
RUBY_REVISION = '0'
|
|
8
8
|
RUBY_COPYRIGHT = 'opal - Copyright (C) 2013-2021 Adam Beynon and the Opal contributors'
|