opal 1.7.0 → 1.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/build.yml +12 -4
- data/CHANGELOG.md +29 -1
- data/exe/opal +5 -7
- data/lib/opal/builder.rb +13 -13
- data/lib/opal/builder_processors.rb +8 -2
- data/lib/opal/builder_scheduler/prefork.rb +60 -6
- data/lib/opal/cli.rb +59 -43
- data/lib/opal/cli_runners/compiler.rb +7 -6
- data/lib/opal/cli_runners/safari.rb +208 -0
- data/lib/opal/cli_runners.rb +1 -0
- data/lib/opal/nodes/literal.rb +16 -0
- data/lib/opal/version.rb +1 -1
- data/opal/corelib/constants.rb +2 -2
- data/spec/filters/platform/.keep +0 -0
- data/spec/filters/platform/firefox/exception.rb +8 -0
- data/spec/filters/platform/firefox/kernel.rb +3 -0
- data/spec/filters/platform/safari/exception.rb +8 -0
- data/spec/filters/platform/safari/float.rb +4 -0
- data/spec/filters/platform/safari/kernel.rb +3 -0
- data/spec/filters/platform/safari/literal_regexp.rb +6 -0
- data/spec/lib/builder_spec.rb +32 -0
- data/spec/lib/cli_spec.rb +18 -6
- data/spec/lib/fixtures/build_order/file1.js +1 -0
- data/spec/lib/fixtures/build_order/file2.js +1 -0
- data/spec/lib/fixtures/build_order/file3.js +1 -0
- data/spec/lib/fixtures/build_order/file4.js +1 -0
- data/spec/lib/fixtures/build_order/file5.rb.erb +4 -0
- data/spec/lib/fixtures/build_order/file51.js +1 -0
- data/spec/lib/fixtures/build_order/file6.rb +10 -0
- data/spec/lib/fixtures/build_order/file61.rb +1 -0
- data/spec/lib/fixtures/build_order/file62.rb +4 -0
- data/spec/lib/fixtures/build_order/file63.rb +4 -0
- data/spec/lib/fixtures/build_order/file64.rb +1 -0
- data/spec/lib/fixtures/build_order/file7.rb +1 -0
- data/spec/lib/fixtures/build_order.rb +9 -0
- data/spec/lib/rake_dist_spec.rb +69 -0
- data/spec/mspec-opal/runner.rb +1 -0
- data/spec/opal/core/io/read_spec.rb +12 -3
- data/stdlib/opal/platform.rb +1 -0
- data/stdlib/opal-platform.rb +3 -0
- data/stdlib/time.rb +21 -1
- data/tasks/building.rake +1 -1
- data/tasks/testing.rake +3 -4
- metadata +29 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3867be8330f4fc45cb5ea9a759c3a1fd39880c5ea92e3c054cbfb2e8776d3f45
|
4
|
+
data.tar.gz: 9bae6c750966bc7e9551f5c4e6d21ce751ee66fc69862bae5b98b85299de7343
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56d87d05c1c043e165b30181b26a7c761d24d9168474fdcece06ca23ee5b4133d8d58722d9e3446f63db666d15acdc2bbcaf870b237f11673d7c6d810149dd1e
|
7
|
+
data.tar.gz: c7f9ced16e1b43ca58c75d7405319c6a5c8d008fa43db6cc1281d235bae1bce090a617d21234c3807ae5d3663b9b268799a87fb4da30f2afc8587a16d5185f7d
|
data/.github/workflows/build.yml
CHANGED
@@ -24,12 +24,12 @@ jobs:
|
|
24
24
|
- name: mspec-chrome
|
25
25
|
ruby: '3.0'
|
26
26
|
command: bin/rake mspec_chrome
|
27
|
-
- name:
|
27
|
+
- name: mspec-firefox
|
28
28
|
env:
|
29
29
|
# when changing version, also change it below
|
30
30
|
MOZILLA_FIREFOX_BINARY: '/opt/hostedtoolcache/firefox/106.0.4/x64/firefox'
|
31
31
|
ruby: '3.0'
|
32
|
-
command: xvfb-run bin/rake
|
32
|
+
command: xvfb-run bin/rake mspec_firefox
|
33
33
|
- name: minitest
|
34
34
|
ruby: '3.0'
|
35
35
|
command: bin/rake minitest
|
@@ -59,13 +59,17 @@ jobs:
|
|
59
59
|
command: bundle exec rake mspec_chrome
|
60
60
|
ruby: '3.0'
|
61
61
|
os: windows-latest
|
62
|
-
- name: windows-
|
62
|
+
- name: windows-mspec-firefox
|
63
63
|
env:
|
64
64
|
# when changing version, also change it below and above
|
65
65
|
MOZILLA_FIREFOX_BINARY: 'C:/Program Files/Firefox_106.0.4/firefox.exe'
|
66
66
|
ruby: '3.0'
|
67
|
-
command: bundle exec rake
|
67
|
+
command: bundle exec rake mspec_firefox
|
68
68
|
os: windows-latest
|
69
|
+
- name: macos-mspec-safari
|
70
|
+
command: bundle exec rake mspec_safari
|
71
|
+
ruby: '3.0'
|
72
|
+
os: 'macos-latest'
|
69
73
|
- name: windows-minitest
|
70
74
|
command: bundle exec rake minitest
|
71
75
|
ruby: '3.0'
|
@@ -74,6 +78,10 @@ jobs:
|
|
74
78
|
command: bundle exec rake rspec
|
75
79
|
ruby: '3.0'
|
76
80
|
os: windows-latest
|
81
|
+
- name: macos
|
82
|
+
command: bundle exec rake rspec
|
83
|
+
ruby: '3.0'
|
84
|
+
os: 'macos-latest'
|
77
85
|
- name: lint
|
78
86
|
command: bin/rake lint
|
79
87
|
ruby: '3.0'
|
data/CHANGELOG.md
CHANGED
@@ -16,7 +16,7 @@ Changes are grouped as follows:
|
|
16
16
|
|
17
17
|
|
18
18
|
|
19
|
-
## [1.7.
|
19
|
+
## [1.7.1](https://github.com/opal/opal/compare/v1.7.0...v1.7.1) - 2023-01-06
|
20
20
|
|
21
21
|
|
22
22
|
<!--
|
@@ -29,6 +29,34 @@ Changes are grouped as follows:
|
|
29
29
|
### Fixed
|
30
30
|
-->
|
31
31
|
|
32
|
+
|
33
|
+
### Added
|
34
|
+
|
35
|
+
- Add safari runner ([#2513](https://github.com/opal/opal/pull/2513))
|
36
|
+
|
37
|
+
### Fixed
|
38
|
+
|
39
|
+
- Fix CLI file reading for macOS ([#2510](https://github.com/opal/opal/pull/2510))
|
40
|
+
- Make Date/Time.parse on Firefox more compatible with Chrome and Ruby ([#2506](https://github.com/opal/opal/pull/2506))
|
41
|
+
- Safari/WebKit can now parse code compiled with lookbehind regexps, failing at runtime instead ([#2511](https://github.com/opal/opal/pull/2511))
|
42
|
+
- Fix `--watch` ignoring some directories (e.g. `tmp`) ([#2509](https://github.com/opal/opal/pull/2509))
|
43
|
+
- Fix rake dist not generating libraries correctly for the CDN ([#2515](https://github.com/opal/opal/pull/2515))
|
44
|
+
- Prefork: output processed files in a correct, deterministic order ([#2516](https://github.com/opal/opal/pull/2516))
|
45
|
+
- Fix the handling of ARGV for the opal executable ([#2518](https://github.com/opal/opal/pull/2518))
|
46
|
+
|
47
|
+
### Internal
|
48
|
+
|
49
|
+
- Platform specific spec filters ([#2508](https://github.com/opal/opal/pull/2508))
|
50
|
+
- Run Firefox specs by default ([#2507](https://github.com/opal/opal/pull/2507))
|
51
|
+
- Run Safari specs by default ([#2513](https://github.com/opal/opal/pull/2513))
|
52
|
+
- [mspec_opal] Avoid lookbehind Regexp for compatibility with various javascript engines ([#2512](https://github.com/opal/opal/pull/2512))
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
|
57
|
+
## [1.7.0](https://github.com/opal/opal/compare/v1.6.1...v1.7.0) - 2022-12-26
|
58
|
+
|
59
|
+
|
32
60
|
### Added
|
33
61
|
|
34
62
|
- Update benchmarking and CLI runners, added support for Deno and Firefox (#2490, #2492, #2494, #2495, #2497, #2491, #2496)
|
data/exe/opal
CHANGED
@@ -2,8 +2,6 @@
|
|
2
2
|
|
3
3
|
# Error codes are taken from /usr/include/sysexits.h
|
4
4
|
|
5
|
-
OriginalARGV = ARGV.dup
|
6
|
-
|
7
5
|
require 'opal/cli_options'
|
8
6
|
options = Opal::CLIOptions.new
|
9
7
|
begin
|
@@ -15,11 +13,7 @@ end
|
|
15
13
|
|
16
14
|
require 'opal/cli'
|
17
15
|
options_hash = options.options
|
18
|
-
options_hash.merge!(
|
19
|
-
file: ARGF.file,
|
20
|
-
filename: ARGF.filename,
|
21
|
-
argv: ARGV.dup
|
22
|
-
) unless options_hash[:lib_only]
|
16
|
+
options_hash.merge!(argv: ARGV.dup) unless options_hash[:lib_only]
|
23
17
|
cli = Opal::CLI.new options_hash
|
24
18
|
|
25
19
|
begin
|
@@ -28,4 +22,8 @@ begin
|
|
28
22
|
rescue Opal::CliRunners::RunnerError => e
|
29
23
|
$stderr.puts e.message
|
30
24
|
exit 72
|
25
|
+
rescue SignalException => e
|
26
|
+
raise unless e.message == 'SIGUSR2'
|
27
|
+
|
28
|
+
exec($0, *ARGV)
|
31
29
|
end
|
data/lib/opal/builder.rb
CHANGED
@@ -197,6 +197,19 @@ module Opal
|
|
197
197
|
processed.map(&:abs_path).compact.select { |fn| File.exist?(fn) }
|
198
198
|
end
|
199
199
|
|
200
|
+
def expand_ext(path)
|
201
|
+
abs_path = path_reader.expand(path)
|
202
|
+
|
203
|
+
if abs_path
|
204
|
+
File.join(
|
205
|
+
File.dirname(path),
|
206
|
+
File.basename(abs_path)
|
207
|
+
)
|
208
|
+
else
|
209
|
+
path
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
200
213
|
private
|
201
214
|
|
202
215
|
def process_requires(rel_path, requires, autoloads, options)
|
@@ -261,19 +274,6 @@ module Opal
|
|
261
274
|
end
|
262
275
|
end
|
263
276
|
|
264
|
-
def expand_ext(path)
|
265
|
-
abs_path = path_reader.expand(path)
|
266
|
-
|
267
|
-
if abs_path
|
268
|
-
File.join(
|
269
|
-
File.dirname(path),
|
270
|
-
File.basename(abs_path)
|
271
|
-
)
|
272
|
-
else
|
273
|
-
path
|
274
|
-
end
|
275
|
-
end
|
276
|
-
|
277
277
|
def expand_path(path)
|
278
278
|
return if stub?(path)
|
279
279
|
(path_reader.expand(path) || File.expand_path(path)).to_s
|
@@ -148,7 +148,10 @@ module Opal
|
|
148
148
|
|
149
149
|
def compiled
|
150
150
|
@compiled ||= begin
|
151
|
-
|
151
|
+
erb = ::ERB.new(@source.to_s)
|
152
|
+
erb.filename = @abs_path
|
153
|
+
|
154
|
+
@source = erb.result
|
152
155
|
|
153
156
|
compiler = compiler_for(@source, file: @filename)
|
154
157
|
compiler.compile
|
@@ -163,7 +166,10 @@ module Opal
|
|
163
166
|
handles :erb
|
164
167
|
|
165
168
|
def source
|
166
|
-
|
169
|
+
erb = ::ERB.new(@source.to_s)
|
170
|
+
erb.filename = @abs_path
|
171
|
+
|
172
|
+
result = erb.result
|
167
173
|
module_name = ::Opal::Compiler.module_name(@filename)
|
168
174
|
"Opal.modules[#{module_name.inspect}] = function() {#{result}};"
|
169
175
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'etc'
|
4
|
+
require 'set'
|
4
5
|
|
5
6
|
module Opal
|
6
7
|
class BuilderScheduler
|
@@ -13,12 +14,64 @@ module Opal
|
|
13
14
|
io = @in_fork
|
14
15
|
io.send(:new_requires, rel_path, requires, autoloads, options)
|
15
16
|
else
|
16
|
-
prefork_reactor(rel_path, requires, autoloads, options)
|
17
|
+
processed = prefork_reactor(rel_path, requires, autoloads, options)
|
18
|
+
|
19
|
+
processed = OrderCorrector.correct_order(processed, requires, builder)
|
20
|
+
|
21
|
+
builder.processed.append(*processed)
|
17
22
|
end
|
18
23
|
end
|
19
24
|
|
20
25
|
private
|
21
26
|
|
27
|
+
# Prefork is not deterministic. This module corrects an order of processed
|
28
|
+
# files so that it would be exactly the same as if building sequentially.
|
29
|
+
# While for Ruby files it usually isn't a problem, because the real order
|
30
|
+
# stems from how `Opal.modules` array is accessed, the JavaScript files
|
31
|
+
# are executed verbatim and their order may be important. Also, having
|
32
|
+
# deterministic output is always a good thing.
|
33
|
+
module OrderCorrector
|
34
|
+
module_function
|
35
|
+
|
36
|
+
def correct_order(processed, requires, builder)
|
37
|
+
# Let's build a hash that maps a filename to an array of files it requires
|
38
|
+
requires_hash = processed.to_h do |i|
|
39
|
+
[i.filename, expand_requires(i.requires, builder)]
|
40
|
+
end
|
41
|
+
# Let's build an array with a correct order of requires
|
42
|
+
order_array = build_require_order_array(expand_requires(requires, builder), requires_hash)
|
43
|
+
# If a key is duplicated, remove the last duplicate
|
44
|
+
order_array = order_array.uniq
|
45
|
+
# Create a hash from this array: [a,b,c] => [a => 0, b => 1, c => 2]
|
46
|
+
order_hash = order_array.each_with_index.to_h
|
47
|
+
# Let's return a processed array that has elements in the order provided
|
48
|
+
processed.sort_by do |asset|
|
49
|
+
# If a filename isn't present somehow in our hash, let's put it at the end
|
50
|
+
order_hash[asset.filename] || order_array.length
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Expand a requires array, so that the requires filenames will be
|
55
|
+
# matching BuilderProcessor#. Builder needs to be passed so that
|
56
|
+
# we can access an `expand_ext` function from its context.
|
57
|
+
def expand_requires(requires, builder)
|
58
|
+
requires.map { |i| builder.expand_ext(i) }
|
59
|
+
end
|
60
|
+
|
61
|
+
def build_require_order_array(requires, requires_hash, built_for = Set.new)
|
62
|
+
array = []
|
63
|
+
requires.each do |name|
|
64
|
+
next if built_for.include?(name)
|
65
|
+
built_for << name
|
66
|
+
|
67
|
+
asset_requires = requires_hash[name]
|
68
|
+
array += build_require_order_array(asset_requires, requires_hash, built_for) if asset_requires
|
69
|
+
array << name
|
70
|
+
end
|
71
|
+
array
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
22
75
|
class ForkSet < Array
|
23
76
|
def initialize(count, &block)
|
24
77
|
super([])
|
@@ -192,6 +245,8 @@ module Opal
|
|
192
245
|
def prefork_reactor(rel_path, requires, autoloads, options)
|
193
246
|
prefork
|
194
247
|
|
248
|
+
processed = []
|
249
|
+
|
195
250
|
first = rel_path
|
196
251
|
queue = requires.map { |i| [rel_path, i, autoloads, options] }
|
197
252
|
|
@@ -206,7 +261,7 @@ module Opal
|
|
206
261
|
idles.each do |io|
|
207
262
|
break if queue.empty?
|
208
263
|
|
209
|
-
rel_path, req, autoloads, options = *queue.
|
264
|
+
rel_path, req, autoloads, options = *queue.shift
|
210
265
|
|
211
266
|
next if builder.already_processed.include?(req)
|
212
267
|
awaiting += 1
|
@@ -225,11 +280,8 @@ module Opal
|
|
225
280
|
asset, = *args
|
226
281
|
if !asset
|
227
282
|
# Do nothing, we received a nil which is expected.
|
228
|
-
elsif asset.filename == 'corelib/runtime.js'
|
229
|
-
# Opal runtime should go first... the rest can go their way.
|
230
|
-
builder.processed.unshift(asset)
|
231
283
|
else
|
232
|
-
|
284
|
+
processed << asset
|
233
285
|
end
|
234
286
|
built += 1
|
235
287
|
awaiting -= 1
|
@@ -252,6 +304,8 @@ module Opal
|
|
252
304
|
|
253
305
|
break if awaiting == 0 && queue.empty?
|
254
306
|
end
|
307
|
+
|
308
|
+
processed
|
255
309
|
ensure
|
256
310
|
$stderr.print "\r\e[K\r" if $stderr.tty?
|
257
311
|
@forks.close
|
data/lib/opal/cli.rb
CHANGED
@@ -3,18 +3,25 @@
|
|
3
3
|
require 'opal/requires'
|
4
4
|
require 'opal/builder'
|
5
5
|
require 'opal/cli_runners'
|
6
|
+
require 'stringio'
|
6
7
|
|
7
8
|
module Opal
|
8
9
|
class CLI
|
9
10
|
attr_reader :options, :file, :compiler_options, :evals, :load_paths, :argv,
|
10
11
|
:output, :requires, :rbrequires, :gems, :stubs, :verbose, :runner_options,
|
11
|
-
:preload, :
|
12
|
-
:no_cache
|
12
|
+
:preload, :debug, :no_exit, :lib_only, :missing_require_severity,
|
13
|
+
:filename, :stdin, :no_cache
|
13
14
|
|
14
15
|
class << self
|
15
16
|
attr_accessor :stdout
|
16
17
|
end
|
17
18
|
|
19
|
+
class Evals < StringIO
|
20
|
+
def to_path
|
21
|
+
'-e'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
18
25
|
def initialize(options = nil)
|
19
26
|
options ||= {}
|
20
27
|
|
@@ -25,7 +32,6 @@ module Opal
|
|
25
32
|
@options = options
|
26
33
|
@sexp = options.delete(:sexp)
|
27
34
|
@repl = options.delete(:repl)
|
28
|
-
@file = options.delete(:file)
|
29
35
|
@no_exit = options.delete(:no_exit)
|
30
36
|
@lib_only = options.delete(:lib_only)
|
31
37
|
@argv = options.delete(:argv) { [] }
|
@@ -37,10 +43,10 @@ module Opal
|
|
37
43
|
@output = options.delete(:output) { self.class.stdout || $stdout }
|
38
44
|
@verbose = options.delete(:verbose) { false }
|
39
45
|
@debug = options.delete(:debug) { false }
|
40
|
-
@filename = options.delete(:filename) { @file && @file.path }
|
41
46
|
@requires = options.delete(:requires) { [] }
|
42
47
|
@rbrequires = options.delete(:rbrequires) { [] }
|
43
48
|
@no_cache = options.delete(:no_cache) { false }
|
49
|
+
@stdin = options.delete(:stdin) { $stdin }
|
44
50
|
|
45
51
|
@debug_source_map = options.delete(:debug_source_map) { false }
|
46
52
|
|
@@ -55,9 +61,20 @@ module Opal
|
|
55
61
|
[key, value]
|
56
62
|
end.compact.to_h
|
57
63
|
|
58
|
-
|
59
|
-
|
60
|
-
|
64
|
+
if @lib_only
|
65
|
+
raise ArgumentError, 'no libraries to compile' if @requires.empty?
|
66
|
+
raise ArgumentError, "can't accept evals, file, or extra arguments in `library only` mode" if @argv.any? || @evals.any?
|
67
|
+
elsif @evals.any?
|
68
|
+
@filename = '-e'
|
69
|
+
@file = Evals.new(@evals.join("\n"))
|
70
|
+
elsif @argv.first && @argv.first != '-'
|
71
|
+
@filename = @argv.shift
|
72
|
+
@file = File.open(@filename)
|
73
|
+
else
|
74
|
+
@filename = @argv.shift || '-'
|
75
|
+
@file = @stdin
|
76
|
+
end
|
77
|
+
|
61
78
|
raise ArgumentError, "unknown options: #{options.inspect}" unless @options.empty?
|
62
79
|
end
|
63
80
|
|
@@ -93,7 +110,7 @@ module Opal
|
|
93
110
|
require 'opal/repl'
|
94
111
|
|
95
112
|
repl = REPL.new
|
96
|
-
repl.run(
|
113
|
+
repl.run(argv)
|
97
114
|
end
|
98
115
|
|
99
116
|
attr_reader :exit_status
|
@@ -127,7 +144,8 @@ module Opal
|
|
127
144
|
builder.build_str '$DEBUG = true', '(flags)', no_export: true if debug
|
128
145
|
|
129
146
|
# --eval / stdin / file
|
130
|
-
|
147
|
+
source = evals_or_file_source
|
148
|
+
builder.build_str(source, filename) if source
|
131
149
|
|
132
150
|
# --no-exit
|
133
151
|
builder.build_str '::Kernel.exit', '(exit)', no_export: true unless no_exit
|
@@ -136,27 +154,27 @@ module Opal
|
|
136
154
|
end
|
137
155
|
|
138
156
|
def show_sexp
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
157
|
+
source = evals_or_file_source or return # rubocop:disable Style/AndOr
|
158
|
+
|
159
|
+
buffer = ::Opal::Parser::SourceBuffer.new(filename)
|
160
|
+
buffer.source = source
|
161
|
+
sexp = Opal::Parser.default_parser.parse(buffer)
|
162
|
+
output.puts sexp.inspect
|
145
163
|
end
|
146
164
|
|
147
165
|
def debug_source_map
|
148
|
-
|
149
|
-
compiler = Opal::Compiler.new(contents, file: filename, **compiler_options)
|
166
|
+
source = evals_or_file_source or return # rubocop:disable Style/AndOr
|
150
167
|
|
151
|
-
|
168
|
+
compiler = Opal::Compiler.new(source, file: filename, **compiler_options)
|
152
169
|
|
153
|
-
|
154
|
-
source_map = compiler.source_map.to_json
|
170
|
+
compiler.compile
|
155
171
|
|
156
|
-
|
172
|
+
result = compiler.result
|
173
|
+
source_map = compiler.source_map.to_json
|
157
174
|
|
158
|
-
|
159
|
-
|
175
|
+
b64 = [result, source_map, contents].map { |i| Base64.strict_encode64(i) }.join(',')
|
176
|
+
|
177
|
+
output.puts "https://sokra.github.io/source-map-visualization/#base64,#{b64}"
|
160
178
|
end
|
161
179
|
|
162
180
|
def compiler_option_names
|
@@ -177,29 +195,27 @@ module Opal
|
|
177
195
|
|
178
196
|
# Internal: Yields a string of source code and the proper filename for either
|
179
197
|
# evals, stdin or a filepath.
|
180
|
-
def
|
181
|
-
# --library
|
182
|
-
return if
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
save = true
|
191
|
-
else
|
192
|
-
begin
|
193
|
-
file.rewind
|
194
|
-
rescue Errno::ESPIPE
|
195
|
-
save = true
|
196
|
-
end
|
198
|
+
def evals_or_file_source
|
199
|
+
return if lib_only # --library
|
200
|
+
return @cached_content if @cached_content
|
201
|
+
|
202
|
+
unless file.tty?
|
203
|
+
begin
|
204
|
+
file.rewind
|
205
|
+
can_read_again = true
|
206
|
+
rescue Errno::ESPIPE # rubocop:disable Lint/HandleExceptions
|
207
|
+
# noop
|
197
208
|
end
|
209
|
+
end
|
198
210
|
|
199
|
-
|
200
|
-
|
201
|
-
|
211
|
+
if @cached_content.nil? || can_read_again
|
212
|
+
# On MacOS file.read is not enough to pick up changes, probably due to some
|
213
|
+
# cache or buffer, unclear if coming from ruby or the OS.
|
214
|
+
content = File.file?(file) ? File.read(file) : file.read
|
202
215
|
end
|
216
|
+
|
217
|
+
@cached_content ||= content unless can_read_again
|
218
|
+
content
|
203
219
|
end
|
204
220
|
end
|
205
221
|
end
|
@@ -52,22 +52,20 @@ class Opal::CliRunners::Compiler
|
|
52
52
|
end
|
53
53
|
|
54
54
|
def fail_unrewindable!
|
55
|
-
|
55
|
+
abort <<~ERROR
|
56
56
|
You have specified --watch, but for watch to work, you must specify an
|
57
57
|
--output file.
|
58
58
|
ERROR
|
59
|
-
exit 1
|
60
59
|
end
|
61
60
|
|
62
61
|
def fail_no_listen!
|
63
|
-
|
62
|
+
abort <<~ERROR
|
64
63
|
--watch mode requires the `listen` gem present. Please try to run:
|
65
64
|
|
66
65
|
gem install listen
|
67
66
|
|
68
67
|
Or if you are using bundler, add listen to your Gemfile.
|
69
68
|
ERROR
|
70
|
-
exit 1
|
71
69
|
end
|
72
70
|
|
73
71
|
def watch_compile
|
@@ -88,10 +86,13 @@ class Opal::CliRunners::Compiler
|
|
88
86
|
$stderr.puts "* Opal v#{Opal::VERSION} successfully compiled your program in --watch mode"
|
89
87
|
|
90
88
|
sleep
|
89
|
+
rescue Interrupt
|
90
|
+
$stderr.puts '* Stopping watcher...'
|
91
|
+
@code_listener.stop
|
91
92
|
end
|
92
93
|
|
93
94
|
def reexec
|
94
|
-
|
95
|
+
Process.kill('USR2', Process.pid)
|
95
96
|
end
|
96
97
|
|
97
98
|
def on_code_change(modified)
|
@@ -133,7 +134,7 @@ class Opal::CliRunners::Compiler
|
|
133
134
|
def watch_files
|
134
135
|
@directories = files_to_directories
|
135
136
|
|
136
|
-
Listen.to(*@directories) do |modified, added, removed|
|
137
|
+
Listen.to(*@directories, ignore!: []) do |modified, added, removed|
|
137
138
|
our_modified = @files & (modified + added + removed)
|
138
139
|
on_code_change(our_modified) unless our_modified.empty?
|
139
140
|
end
|