opal 1.2.0 → 1.3.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- 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'
|