opal 1.5.1 → 1.6.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +4 -0
- data/.github/workflows/build.yml +17 -3
- data/HACKING.md +23 -0
- data/README.md +3 -3
- data/UNRELEASED.md +47 -0
- data/benchmark/run.rb +1 -0
- data/docs/compiled_ruby.md +8 -0
- data/docs/compiler.md +1 -1
- data/docs/compiler_directives.md +1 -1
- data/docs/getting_started.md +17 -0
- data/docs/headless_chrome.md +1 -1
- data/docs/index.md +123 -0
- data/docs/jquery.md +5 -5
- data/docs/templates.md +37 -37
- data/docs/unsupported_features.md +0 -4
- data/lib/opal/builder.rb +59 -39
- data/lib/opal/builder_processors.rb +24 -0
- data/lib/opal/builder_scheduler/prefork.rb +262 -0
- data/lib/opal/builder_scheduler/sequential.rb +13 -0
- data/lib/opal/builder_scheduler.rb +29 -0
- data/lib/opal/cache/file_cache.rb +13 -2
- data/lib/opal/cli.rb +36 -19
- data/lib/opal/cli_options.rb +4 -0
- data/lib/opal/cli_runners/chrome.rb +17 -13
- data/lib/opal/cli_runners/chrome_cdp_interface.rb +19 -2
- data/lib/opal/cli_runners/compiler.rb +1 -1
- data/lib/opal/cli_runners/gjs.rb +3 -1
- data/lib/opal/cli_runners/mini_racer.rb +5 -3
- data/lib/opal/cli_runners/nodejs.rb +3 -3
- data/lib/opal/cli_runners/server.rb +13 -28
- data/lib/opal/cli_runners/system_runner.rb +5 -3
- data/lib/opal/cli_runners.rb +7 -6
- data/lib/opal/compiler.rb +25 -2
- data/lib/opal/config.rb +10 -0
- data/lib/opal/eof_content.rb +5 -2
- data/lib/opal/nodes/args/ensure_kwargs_are_kwargs.rb +2 -6
- data/lib/opal/nodes/args/extract_kwarg.rb +3 -4
- data/lib/opal/nodes/args/extract_kwargs.rb +3 -1
- data/lib/opal/nodes/args/extract_kwoptarg.rb +1 -1
- data/lib/opal/nodes/args/extract_kwrestarg.rb +4 -1
- data/lib/opal/nodes/args/extract_optarg.rb +1 -1
- data/lib/opal/nodes/args/extract_post_arg.rb +1 -1
- data/lib/opal/nodes/args/extract_post_optarg.rb +1 -1
- data/lib/opal/nodes/args/extract_restarg.rb +2 -2
- data/lib/opal/nodes/args/initialize_iterarg.rb +1 -1
- data/lib/opal/nodes/args/initialize_shadowarg.rb +1 -1
- data/lib/opal/nodes/args/prepare_post_args.rb +4 -2
- data/lib/opal/nodes/base.rb +14 -3
- data/lib/opal/nodes/call.rb +13 -16
- data/lib/opal/nodes/class.rb +3 -1
- data/lib/opal/nodes/closure.rb +250 -0
- data/lib/opal/nodes/def.rb +7 -11
- data/lib/opal/nodes/definitions.rb +4 -2
- data/lib/opal/nodes/if.rb +12 -2
- data/lib/opal/nodes/iter.rb +11 -17
- data/lib/opal/nodes/logic.rb +15 -63
- data/lib/opal/nodes/module.rb +3 -1
- data/lib/opal/nodes/rescue.rb +23 -15
- data/lib/opal/nodes/scope.rb +7 -1
- data/lib/opal/nodes/top.rb +27 -4
- data/lib/opal/nodes/while.rb +42 -26
- data/lib/opal/nodes.rb +1 -0
- data/lib/opal/os.rb +59 -0
- data/lib/opal/rewriter.rb +2 -0
- data/lib/opal/rewriters/returnable_logic.rb +14 -0
- data/lib/opal/rewriters/thrower_finder.rb +90 -0
- data/lib/opal/simple_server.rb +12 -6
- data/lib/opal/source_map/file.rb +4 -3
- data/lib/opal/source_map/map.rb +9 -1
- data/lib/opal/util.rb +1 -1
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/array.rb +68 -3
- data/opal/corelib/basic_object.rb +1 -0
- data/opal/corelib/comparable.rb +1 -1
- data/opal/corelib/complex.rb +1 -0
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/enumerable.rb +4 -2
- data/opal/corelib/enumerator/chain.rb +4 -0
- data/opal/corelib/enumerator/generator.rb +5 -3
- data/opal/corelib/enumerator/lazy.rb +3 -1
- data/opal/corelib/enumerator/yielder.rb +2 -4
- data/opal/corelib/enumerator.rb +3 -1
- data/opal/corelib/error/errno.rb +3 -1
- data/opal/corelib/error.rb +13 -2
- data/opal/corelib/hash.rb +39 -1
- data/opal/corelib/io.rb +1 -1
- data/opal/corelib/kernel.rb +56 -5
- data/opal/corelib/module.rb +60 -4
- data/opal/corelib/proc.rb +8 -5
- data/opal/corelib/rational.rb +1 -0
- data/opal/corelib/regexp.rb +15 -1
- data/opal/corelib/runtime.js +307 -238
- data/opal/corelib/string/encoding.rb +0 -6
- data/opal/corelib/string.rb +28 -7
- data/opal/corelib/time.rb +5 -2
- data/opal/corelib/unsupported.rb +2 -14
- data/opal.gemspec +2 -2
- data/spec/filters/bugs/delegate.rb +11 -0
- data/spec/filters/bugs/kernel.rb +1 -3
- data/spec/filters/bugs/language.rb +3 -23
- data/spec/filters/bugs/method.rb +0 -1
- data/spec/filters/bugs/module.rb +0 -3
- data/spec/filters/bugs/proc.rb +0 -3
- data/spec/filters/bugs/set.rb +4 -16
- data/spec/filters/bugs/unboundmethod.rb +0 -2
- data/spec/filters/unsupported/array.rb +0 -58
- data/spec/filters/unsupported/freeze.rb +8 -192
- data/spec/filters/unsupported/hash.rb +0 -25
- data/spec/filters/unsupported/kernel.rb +0 -1
- data/spec/filters/unsupported/privacy.rb +17 -0
- data/spec/lib/builder_spec.rb +14 -0
- data/spec/lib/cli_runners/server_spec.rb +2 -3
- data/spec/lib/cli_spec.rb +15 -1
- data/spec/lib/compiler_spec.rb +1 -1
- data/spec/opal/core/language/DATA/characters_support_crlf_spec.rb +9 -0
- data/spec/opal/core/language/DATA/multiple___END___crlf_spec.rb +10 -0
- data/spec/opal/core/language/if_spec.rb +13 -0
- data/spec/opal/core/language/safe_navigator_spec.rb +10 -0
- data/spec/opal/core/module_spec.rb +8 -0
- data/spec/ruby_specs +2 -1
- data/stdlib/await.rb +44 -7
- data/stdlib/delegate.rb +427 -6
- data/stdlib/headless_chrome.rb +6 -2
- data/stdlib/nodejs/file.rb +2 -1
- data/stdlib/opal-parser.rb +1 -1
- data/stdlib/opal-platform.rb +1 -1
- data/stdlib/opal-replutils.rb +5 -3
- data/stdlib/promise.rb +3 -0
- data/stdlib/rbconfig.rb +4 -1
- data/stdlib/ruby2_keywords.rb +60 -0
- data/stdlib/set.rb +21 -0
- data/tasks/performance.rake +41 -35
- data/tasks/releasing.rake +1 -0
- data/tasks/testing/mspec_special_calls.rb +1 -0
- data/tasks/testing.rake +13 -12
- data/test/nodejs/test_await.rb +39 -1
- data/test/nodejs/test_file.rb +3 -2
- metadata +37 -22
- data/docs/faq.md +0 -17
- data/lib/opal/rewriters/break_finder.rb +0 -36
- data/spec/opal/core/kernel/freeze_spec.rb +0 -15
data/lib/opal/nodes/top.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'pathname'
|
4
|
+
require 'json'
|
4
5
|
require 'opal/version'
|
5
6
|
require 'opal/nodes/scope'
|
6
7
|
|
@@ -32,7 +33,9 @@ module Opal
|
|
32
33
|
in_scope do
|
33
34
|
line '"use strict";' if compiler.use_strict?
|
34
35
|
|
35
|
-
body_code =
|
36
|
+
body_code = in_closure(Closure::JS_FUNCTION | Closure::TOP) do
|
37
|
+
stmt(stmts)
|
38
|
+
end
|
36
39
|
body_code = [body_code] unless body_code.is_a?(Array)
|
37
40
|
|
38
41
|
if compiler.eval?
|
@@ -60,12 +63,18 @@ module Opal
|
|
60
63
|
definition
|
61
64
|
closing
|
62
65
|
end
|
66
|
+
|
67
|
+
add_file_source_embed if compiler.enable_file_source_embed?
|
68
|
+
end
|
69
|
+
|
70
|
+
def module_name
|
71
|
+
Opal::Compiler.module_name(compiler.file).inspect
|
63
72
|
end
|
64
73
|
|
65
74
|
def definition
|
66
75
|
if compiler.requirable?
|
67
|
-
unshift "Opal.modules[#{
|
68
|
-
elsif compiler.esm?
|
76
|
+
unshift "Opal.modules[#{module_name}] = "
|
77
|
+
elsif compiler.esm? && !compiler.no_export?
|
69
78
|
unshift 'export default '
|
70
79
|
end
|
71
80
|
end
|
@@ -85,6 +94,14 @@ module Opal
|
|
85
94
|
def closing
|
86
95
|
if compiler.requirable?
|
87
96
|
line "};\n"
|
97
|
+
|
98
|
+
if compiler.load?
|
99
|
+
# Opal.load normalizes the path, so that we can't
|
100
|
+
# require absolute paths from CLI. For other cases
|
101
|
+
# we can expect the module names to be normalized
|
102
|
+
# already.
|
103
|
+
line "Opal.load_normalized(#{module_name});"
|
104
|
+
end
|
88
105
|
elsif compiler.eval?
|
89
106
|
line "})(Opal, self);"
|
90
107
|
else
|
@@ -109,7 +126,7 @@ module Opal
|
|
109
126
|
end
|
110
127
|
|
111
128
|
def add_used_helpers
|
112
|
-
compiler.helpers.to_a.
|
129
|
+
compiler.helpers.to_a.reverse_each { |h| prepend_scope_temp "$#{h} = Opal.#{h}" }
|
113
130
|
end
|
114
131
|
|
115
132
|
def compile_method_stubs
|
@@ -131,6 +148,12 @@ module Opal
|
|
131
148
|
def version_comment
|
132
149
|
"/* Generated by Opal #{Opal::VERSION} */"
|
133
150
|
end
|
151
|
+
|
152
|
+
def add_file_source_embed
|
153
|
+
filename = compiler.file
|
154
|
+
source = compiler.source
|
155
|
+
unshift "Opal.file_sources[#{filename.to_json}] = #{source.to_json};\n"
|
156
|
+
end
|
134
157
|
end
|
135
158
|
end
|
136
159
|
end
|
data/lib/opal/nodes/while.rb
CHANGED
@@ -12,20 +12,27 @@ module Opal
|
|
12
12
|
def compile
|
13
13
|
test_code = js_truthy(test)
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
@redo_var = scope.new_temp if uses_redo?
|
16
|
+
|
17
|
+
compiler.in_while do
|
18
|
+
while_loop[:closure] = true if wrap_in_closure?
|
19
|
+
while_loop[:redo_var] = @redo_var
|
20
|
+
|
21
|
+
in_closure(Closure::LOOP | Closure::JS_LOOP | (wrap_in_closure? ? Closure::JS_FUNCTION : 0)) do
|
22
|
+
in_closure(Closure::LOOP_INSIDE | Closure::JS_LOOP_INSIDE) do
|
23
|
+
line(indent { stmt(body) })
|
24
|
+
end
|
19
25
|
|
20
|
-
body_code = indent { stmt(body) }
|
21
26
|
if uses_redo?
|
22
|
-
compile_with_redo(test_code
|
27
|
+
compile_with_redo(test_code)
|
23
28
|
else
|
24
|
-
compile_without_redo(test_code
|
29
|
+
compile_without_redo(test_code)
|
25
30
|
end
|
26
31
|
end
|
27
32
|
end
|
28
33
|
|
34
|
+
scope.queue_temp(@redo_var) if uses_redo?
|
35
|
+
|
29
36
|
if wrap_in_closure?
|
30
37
|
if scope.await_encountered
|
31
38
|
wrap '(await (async function() {', '; return nil; })())'
|
@@ -37,26 +44,27 @@ module Opal
|
|
37
44
|
|
38
45
|
private
|
39
46
|
|
40
|
-
def compile_with_redo(test_code
|
41
|
-
|
42
|
-
compile_while(
|
43
|
-
[redo_var, " || ", test_code],
|
44
|
-
["#{redo_var} = false;", body_code]
|
45
|
-
)
|
47
|
+
def compile_with_redo(test_code)
|
48
|
+
compile_while(test_code, "#{@redo_var} = false;")
|
46
49
|
end
|
47
50
|
|
48
|
-
def compile_without_redo(test_code
|
49
|
-
compile_while(
|
51
|
+
def compile_without_redo(test_code)
|
52
|
+
compile_while(test_code)
|
50
53
|
end
|
51
54
|
|
52
|
-
def compile_while(test_code,
|
53
|
-
|
54
|
-
|
55
|
+
def compile_while(test_code, redo_code = nil)
|
56
|
+
unshift redo_code if redo_code
|
57
|
+
unshift while_open, test_code, while_close
|
58
|
+
unshift redo_code if redo_code
|
55
59
|
line '}'
|
56
60
|
end
|
57
61
|
|
58
62
|
def while_open
|
59
|
-
|
63
|
+
if uses_redo?
|
64
|
+
redo_part = "#{@redo_var} || "
|
65
|
+
end
|
66
|
+
|
67
|
+
"while (#{redo_part}"
|
60
68
|
end
|
61
69
|
|
62
70
|
def while_close
|
@@ -64,7 +72,7 @@ module Opal
|
|
64
72
|
end
|
65
73
|
|
66
74
|
def uses_redo?
|
67
|
-
|
75
|
+
@sexp.meta[:has_redo]
|
68
76
|
end
|
69
77
|
|
70
78
|
def wrap_in_closure?
|
@@ -78,7 +86,11 @@ module Opal
|
|
78
86
|
private
|
79
87
|
|
80
88
|
def while_open
|
81
|
-
|
89
|
+
if uses_redo?
|
90
|
+
redo_part = "#{@redo_var} || "
|
91
|
+
end
|
92
|
+
|
93
|
+
"while (#{redo_part}!("
|
82
94
|
end
|
83
95
|
|
84
96
|
def while_close
|
@@ -91,10 +103,10 @@ module Opal
|
|
91
103
|
|
92
104
|
private
|
93
105
|
|
94
|
-
def compile_while(test_code,
|
95
|
-
|
96
|
-
|
97
|
-
line "} ", while_open,
|
106
|
+
def compile_while(test_code, redo_code = nil)
|
107
|
+
unshift redo_code if redo_code
|
108
|
+
unshift "do {"
|
109
|
+
line "} ", while_open, test_code, while_close
|
98
110
|
end
|
99
111
|
|
100
112
|
def while_close
|
@@ -108,7 +120,11 @@ module Opal
|
|
108
120
|
private
|
109
121
|
|
110
122
|
def while_open
|
111
|
-
|
123
|
+
if uses_redo?
|
124
|
+
redo_part = "#{@redo_var} || "
|
125
|
+
end
|
126
|
+
|
127
|
+
"while (#{redo_part}!("
|
112
128
|
end
|
113
129
|
|
114
130
|
def while_close
|
data/lib/opal/nodes.rb
CHANGED
data/lib/opal/os.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Opal
|
4
|
+
module OS
|
5
|
+
module_function
|
6
|
+
|
7
|
+
def windows?
|
8
|
+
/bccwin|cygwin|djgpp|mingw|mswin|wince/.match?(RbConfig::CONFIG['host_os'])
|
9
|
+
end
|
10
|
+
|
11
|
+
def macos?
|
12
|
+
/darwin|mac os/.match?(RbConfig::CONFIG['host_os'])
|
13
|
+
end
|
14
|
+
|
15
|
+
def shellescape(str)
|
16
|
+
if windows?
|
17
|
+
'"' + str.gsub('"', '""') + '"'
|
18
|
+
else
|
19
|
+
str.shellescape
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def env_sep
|
24
|
+
windows? ? ';' : ':'
|
25
|
+
end
|
26
|
+
|
27
|
+
def path_sep
|
28
|
+
windows? ? '\\' : '/'
|
29
|
+
end
|
30
|
+
|
31
|
+
def cmd_sep
|
32
|
+
windows? ? ' & ' : ' ; '
|
33
|
+
end
|
34
|
+
|
35
|
+
def dev_null
|
36
|
+
windows? ? 'NUL' : '/dev/null'
|
37
|
+
end
|
38
|
+
|
39
|
+
def bash_c(*commands)
|
40
|
+
cmd = if windows?
|
41
|
+
[
|
42
|
+
'bundle',
|
43
|
+
'exec',
|
44
|
+
'cmd',
|
45
|
+
'/c',
|
46
|
+
]
|
47
|
+
else
|
48
|
+
[
|
49
|
+
'bundle',
|
50
|
+
'exec',
|
51
|
+
'bash',
|
52
|
+
'-c',
|
53
|
+
]
|
54
|
+
end
|
55
|
+
|
56
|
+
cmd << commands.join(cmd_sep)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/opal/rewriter.rb
CHANGED
@@ -15,6 +15,7 @@ require 'opal/rewriters/inline_args'
|
|
15
15
|
require 'opal/rewriters/numblocks'
|
16
16
|
require 'opal/rewriters/returnable_logic'
|
17
17
|
require 'opal/rewriters/forward_args'
|
18
|
+
require 'opal/rewriters/thrower_finder'
|
18
19
|
|
19
20
|
module Opal
|
20
21
|
class Rewriter
|
@@ -66,6 +67,7 @@ module Opal
|
|
66
67
|
use Rewriters::DumpArgs
|
67
68
|
use Rewriters::MlhsArgs
|
68
69
|
use Rewriters::InlineArgs
|
70
|
+
use Rewriters::ThrowerFinder
|
69
71
|
|
70
72
|
def initialize(sexp)
|
71
73
|
@sexp = sexp
|
@@ -21,6 +21,9 @@ module Opal
|
|
21
21
|
|
22
22
|
def on_if(node)
|
23
23
|
test, = *node.children
|
24
|
+
|
25
|
+
check_control_flow!(test)
|
26
|
+
|
24
27
|
# The if_test metadata signifies that we don't care about the return value except if it's
|
25
28
|
# truthy or falsy. And those tests will be carried out by the respective $truthy helper calls.
|
26
29
|
test.meta[:if_test] = true if test
|
@@ -41,6 +44,8 @@ module Opal
|
|
41
44
|
def on_or(node)
|
42
45
|
lhs, rhs = *node.children
|
43
46
|
|
47
|
+
check_control_flow!(lhs)
|
48
|
+
|
44
49
|
if node.meta[:if_test]
|
45
50
|
# Let's forward the if_test to the lhs and rhs - since we don't care about the exact return
|
46
51
|
# value of our or, we neither do care about a return value of our lhs or rhs.
|
@@ -58,6 +63,8 @@ module Opal
|
|
58
63
|
def on_and(node)
|
59
64
|
lhs, rhs = *node.children
|
60
65
|
|
66
|
+
check_control_flow!(lhs)
|
67
|
+
|
61
68
|
if node.meta[:if_test]
|
62
69
|
lhs.meta[:if_test] = rhs.meta[:if_test] = true
|
63
70
|
out = process(node.updated(:if, [lhs, rhs, s(:false)]))
|
@@ -81,6 +88,13 @@ module Opal
|
|
81
88
|
|
82
89
|
private
|
83
90
|
|
91
|
+
def check_control_flow!(node)
|
92
|
+
case node.type
|
93
|
+
when :break, :next, :redo, :retry, :return
|
94
|
+
error 'void value expression'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
84
98
|
def build_if_from_when(node, lhs, lhs_tmp, whens, els)
|
85
99
|
first_when, *next_whens = *whens
|
86
100
|
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Layout/EmptyLineBetweenDefs, Style/SingleLineMethods
|
4
|
+
module Opal
|
5
|
+
module Rewriters
|
6
|
+
# ThrowerFinder attempts to track the presence of throwers, like
|
7
|
+
# break, redo, so we can make an informed guess in the early
|
8
|
+
# compilation phase before traversing other nodes whether we
|
9
|
+
# want to track a closure. Tracking a closure is often a deoptimizing
|
10
|
+
# step, so we want to get that knowledge earlier.
|
11
|
+
class ThrowerFinder < Opal::Rewriters::Base
|
12
|
+
def initialize
|
13
|
+
@break_stack = []
|
14
|
+
@redo_stack = []
|
15
|
+
@retry_stack = []
|
16
|
+
@rescue_else_stack = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def on_break(node)
|
20
|
+
tracking(:break, @break_stack)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def on_redo(node)
|
25
|
+
tracking(:redo, @redo_stack)
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
def on_retry(node)
|
30
|
+
tracking(:retry, @retry_stack)
|
31
|
+
super
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_iter(node)
|
35
|
+
pushing([@break_stack, node]) { super }
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_loop(node, &block)
|
39
|
+
pushing([@redo_stack, node], [@break_stack, nil], &block)
|
40
|
+
end
|
41
|
+
|
42
|
+
def on_for(node); on_loop(node) { super }; end
|
43
|
+
def on_while(node); on_loop(node) { super }; end
|
44
|
+
def on_while_post(node); on_loop(node) { super }; end
|
45
|
+
def on_until(node); on_loop(node) { super }; end
|
46
|
+
def on_until_post(node); on_loop(node) { super }; end
|
47
|
+
|
48
|
+
# ignore throwers inside defined
|
49
|
+
def on_defined(node)
|
50
|
+
pushing(
|
51
|
+
[@redo_stack, nil],
|
52
|
+
[@break_stack, nil],
|
53
|
+
[@retry_stack, nil]
|
54
|
+
) { super }
|
55
|
+
end
|
56
|
+
|
57
|
+
# In Opal we handle rescue-else either in ensure or in
|
58
|
+
# rescue. If ensure is present, we handle it in ensure.
|
59
|
+
# Otherwise we handle it in rescue. ensure is always
|
60
|
+
# above a rescue. This logic is about tracking if a given
|
61
|
+
# ensure node should expect a rescue-else inside a
|
62
|
+
# rescue node.
|
63
|
+
def on_ensure(node)
|
64
|
+
pushing([@rescue_else_stack, node]) { super }
|
65
|
+
end
|
66
|
+
|
67
|
+
def on_rescue(node)
|
68
|
+
if node.children[1..-1].detect { |sexp| sexp && sexp.type != :resbody }
|
69
|
+
tracking(:rescue_else, @rescue_else_stack)
|
70
|
+
end
|
71
|
+
|
72
|
+
pushing([@rescue_else_stack, nil], [@retry_stack, node]) { super }
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def pushing(*stacks)
|
78
|
+
stacks.each { |stack, node| stack.push(node) }
|
79
|
+
result = yield
|
80
|
+
stacks.map(&:first).each(&:pop)
|
81
|
+
result
|
82
|
+
end
|
83
|
+
|
84
|
+
def tracking(breaker, stack)
|
85
|
+
stack.last.meta[:"has_#{breaker}"] = true if stack.last
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
# rubocop:enable Layout/EmptyLineBetweenDefs, Style/SingleLineMethods
|
data/lib/opal/simple_server.rb
CHANGED
@@ -11,6 +11,8 @@ require 'opal/deprecations'
|
|
11
11
|
#
|
12
12
|
# @example (CLI)
|
13
13
|
# rackup -ropal -ropal/simple_server -b 'Opal.append_path("app"); run Opal::SimpleServer.new'
|
14
|
+
# ... or use the Server runner ...
|
15
|
+
# opal -Rserver app.rb
|
14
16
|
class Opal::SimpleServer
|
15
17
|
require 'set'
|
16
18
|
require 'erb'
|
@@ -54,13 +56,16 @@ class Opal::SimpleServer
|
|
54
56
|
]
|
55
57
|
end
|
56
58
|
|
57
|
-
def
|
59
|
+
def builder(path)
|
58
60
|
builder = Opal::Builder.new
|
59
61
|
builder.build(path.gsub(/(\.(?:rb|js|opal))*\z/, ''))
|
62
|
+
end
|
63
|
+
|
64
|
+
def fetch_asset(path)
|
65
|
+
builder = self.builder(path)
|
60
66
|
{
|
61
67
|
data: builder.to_s,
|
62
|
-
map: builder.source_map
|
63
|
-
source: builder.source_for(path),
|
68
|
+
map: builder.source_map
|
64
69
|
}
|
65
70
|
end
|
66
71
|
|
@@ -86,10 +91,11 @@ class Opal::SimpleServer
|
|
86
91
|
<!doctype html>
|
87
92
|
<html>
|
88
93
|
<head>
|
89
|
-
<meta charset="
|
90
|
-
#{javascript_include_tag(main)}
|
94
|
+
<meta charset="utf-8">
|
91
95
|
</head>
|
92
|
-
<body
|
96
|
+
<body>
|
97
|
+
#{javascript_include_tag(main)}
|
98
|
+
</body>
|
93
99
|
</html>
|
94
100
|
HTML
|
95
101
|
end
|
data/lib/opal/source_map/file.rb
CHANGED
@@ -51,7 +51,7 @@ class Opal::SourceMap::File
|
|
51
51
|
# file: "out.js", # This is optional
|
52
52
|
sourceRoot: source_root,
|
53
53
|
sources: [file],
|
54
|
-
sourcesContent: [source.
|
54
|
+
sourcesContent: [source.encoding == Encoding::UTF_8 ? source : source.encode('UTF-8', undef: :replace)],
|
55
55
|
names: names,
|
56
56
|
mappings: Opal::SourceMap::VLQ.encode_mappings(relative_mappings),
|
57
57
|
# x_com_opalrb_original_lines: source.count("\n"),
|
@@ -182,8 +182,9 @@ class Opal::SourceMap::File
|
|
182
182
|
def fragments_by_line
|
183
183
|
raw_mappings = [[]]
|
184
184
|
fragments.flat_map do |fragment|
|
185
|
-
fragment_code
|
186
|
-
|
185
|
+
fragment_code = fragment.code
|
186
|
+
splitter = /\r/.match?(fragment_code) ? /\r?\n/ : "\n"
|
187
|
+
fragment_lines = fragment_code.split(splitter, -1) # a negative limit won't suppress trailing null values
|
187
188
|
fragment_lines.each.with_index do |fragment_line, index|
|
188
189
|
raw_segment = [fragment_line, fragment]
|
189
190
|
if index.zero? && !fragment_line.size.zero?
|
data/lib/opal/source_map/map.rb
CHANGED
@@ -9,7 +9,15 @@ module Opal::SourceMap::Map
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def to_json
|
12
|
-
to_h
|
12
|
+
map = to_h
|
13
|
+
map.to_json
|
14
|
+
rescue Encoding::UndefinedConversionError
|
15
|
+
map[:sections].each do |i|
|
16
|
+
i.to_json
|
17
|
+
rescue Encoding::UndefinedConversionError
|
18
|
+
map[:sections].delete(i)
|
19
|
+
end
|
20
|
+
map.to_json
|
13
21
|
end
|
14
22
|
|
15
23
|
def as_json(*)
|
data/lib/opal/util.rb
CHANGED
@@ -15,7 +15,7 @@ module Opal
|
|
15
15
|
# @param str [String] string to minify
|
16
16
|
# @return [String]
|
17
17
|
def uglify(source, mangle: false)
|
18
|
-
sh "bin/yarn -s run terser -c #{'-m' if mangle}", data: source
|
18
|
+
sh "#{'ruby ' if Gem.win_platform?}bin/yarn -s run terser -c #{'-m' if mangle}", data: source
|
19
19
|
end
|
20
20
|
|
21
21
|
# Gzip code to check file size.
|
data/lib/opal/version.rb
CHANGED