opal 1.3.0.alpha1 → 1.3.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +3 -1
  3. data/UNRELEASED.md +29 -6
  4. data/examples/rack/Gemfile +1 -0
  5. data/examples/rack/Gemfile.lock +11 -7
  6. data/examples/rack-esm/.gitignore +1 -0
  7. data/examples/rack-esm/Gemfile +5 -0
  8. data/examples/rack-esm/app/application.rb +27 -0
  9. data/examples/rack-esm/app/user.rb +24 -0
  10. data/examples/rack-esm/config.ru +25 -0
  11. data/examples/rack-esm/index.html.erb +11 -0
  12. data/examples/sinatra/Gemfile.lock +21 -19
  13. data/lib/opal/builder.rb +39 -23
  14. data/lib/opal/builder_processors.rb +6 -1
  15. data/lib/opal/cache/file_cache.rb +7 -6
  16. data/lib/opal/cli_runners/chrome.rb +20 -15
  17. data/lib/opal/cli_runners/chrome_cdp_interface.rb +1 -1
  18. data/lib/opal/cli_runners/nodejs.rb +3 -2
  19. data/lib/opal/cli_runners/quickjs.rb +28 -0
  20. data/lib/opal/cli_runners.rb +1 -0
  21. data/lib/opal/compiler.rb +8 -2
  22. data/lib/opal/config.rb +5 -0
  23. data/lib/opal/nodes/call.rb +45 -26
  24. data/lib/opal/nodes/helpers.rb +1 -1
  25. data/lib/opal/nodes/top.rb +5 -8
  26. data/lib/opal/rewriters/rubyspec/filters_rewriter.rb +16 -0
  27. data/lib/opal/simple_server.rb +7 -2
  28. data/lib/opal/util.rb +1 -1
  29. data/lib/opal/version.rb +1 -1
  30. data/opal/corelib/complex/base.rb +15 -0
  31. data/opal/corelib/complex.rb +3 -15
  32. data/opal/corelib/constants.rb +2 -2
  33. data/opal/corelib/error.rb +1 -1
  34. data/opal/corelib/helpers.rb +10 -0
  35. data/opal/corelib/io.rb +4 -0
  36. data/opal/corelib/kernel.rb +21 -5
  37. data/opal/corelib/main.rb +4 -0
  38. data/opal/corelib/method.rb +4 -0
  39. data/opal/corelib/module.rb +39 -16
  40. data/opal/corelib/pattern_matching/base.rb +35 -0
  41. data/opal/corelib/pattern_matching.rb +2 -36
  42. data/opal/corelib/process/base.rb +9 -0
  43. data/opal/corelib/process.rb +1 -11
  44. data/opal/corelib/random.rb +4 -0
  45. data/opal/corelib/rational/base.rb +11 -0
  46. data/opal/corelib/rational.rb +3 -10
  47. data/opal/corelib/regexp.rb +1 -1
  48. data/opal/corelib/runtime.js +38 -3
  49. data/opal/opal/full.rb +5 -4
  50. data/opal/opal.rb +12 -11
  51. data/package.json +1 -1
  52. data/spec/filters/bugs/bigdecimal.rb +0 -1
  53. data/spec/filters/bugs/enumerator.rb +5 -0
  54. data/spec/filters/bugs/float.rb +3 -0
  55. data/spec/filters/bugs/kernel.rb +2 -9
  56. data/spec/filters/bugs/language.rb +0 -1
  57. data/spec/filters/bugs/marshal.rb +3 -0
  58. data/spec/filters/bugs/method.rb +1 -2
  59. data/spec/filters/bugs/module.rb +0 -6
  60. data/spec/filters/bugs/rational.rb +1 -0
  61. data/spec/filters/bugs/regexp.rb +0 -1
  62. data/spec/lib/compiler_spec.rb +2 -2
  63. data/spec/mspec-opal/runner.rb +1 -0
  64. data/stdlib/benchmark.rb +14 -0
  65. data/stdlib/buffer.rb +4 -0
  66. data/stdlib/nashorn/file.rb +2 -0
  67. data/stdlib/native.rb +63 -58
  68. data/stdlib/nodejs/argf.rb +110 -0
  69. data/stdlib/nodejs/env.rb +12 -0
  70. data/stdlib/nodejs/file.rb +10 -0
  71. data/stdlib/nodejs/kernel.rb +56 -0
  72. data/stdlib/nodejs.rb +1 -0
  73. data/stdlib/opal/platform.rb +2 -0
  74. data/stdlib/opal-platform.rb +5 -2
  75. data/stdlib/pathname.rb +4 -0
  76. data/stdlib/quickjs/io.rb +22 -0
  77. data/stdlib/quickjs/kernel.rb +5 -0
  78. data/stdlib/quickjs.rb +2 -0
  79. data/stdlib/securerandom.rb +2 -0
  80. data/tasks/performance.rake +2 -1
  81. data/tasks/testing.rake +1 -1
  82. metadata +36 -8
  83. data/lib/opal/cli_runners/chrome_cdp_interface.js +0 -30285
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cf895e8ef63c69f90e6e099aa2f4c671649411893b980bdb03b55268da2e0a34
4
- data.tar.gz: 5fc847637cea4a857bcc78ad1a491d5c898fdc051d779644f39e282e6c2aba66
3
+ metadata.gz: 16782d65a3f9ab801bc44d034562757ea7dc22085099087d310850fce8fe08d4
4
+ data.tar.gz: fcf2a3d06b0ea2177e48bc3047efdd4049d8c3a237b53f506fa8a199506cb1c3
5
5
  SHA512:
6
- metadata.gz: 0eb66e6cb09d52075f7afd1ab8d10b67fdab302a503269f95b152440991b8d1f9bc3fc759e0265503350e6c4cd3c1453afca9d7d971bbdae46a367f15f5f8230
7
- data.tar.gz: e0ce987c98345a13101dc3d9311ce1bb41435777edf41ab14aac96cf5821c1e6076236de25216c443fa806567af6f1a32de2f8d7d9e1e67e4ba165547c938e95
6
+ metadata.gz: 46ebb7477fd100fcd133eedbc284c967be2b9938fa1c6da6bfb82c22c41f99202f577880514c15e3ce31e57c411ef7b213c4bae07b2500a2c30bff34d0bd296c
7
+ data.tar.gz: 44ebb97f64ad9586b9b10eb3d2a8d60a2d8f78a8dd4c8766a13c9ecc80548272f2014c4b8aa96b3fba31c34147d094a7fc2832ab18818480e4736d0addd0839f
@@ -54,6 +54,7 @@ jobs:
54
54
  permissive: true
55
55
  fetchdepth: '0'
56
56
  command: bin/rake performance:compare
57
+ os: ryzen
57
58
 
58
59
  # Currently failing:
59
60
  # - ruby: truffleruby
@@ -66,7 +67,8 @@ jobs:
66
67
  - uses: actions/checkout@v2
67
68
  with:
68
69
  fetch-depth: ${{ fromJSON(matrix.combo.fetchdepth || '1') }}
69
- - uses: ruby/setup-ruby@v1
70
+ - if: ${{ matrix.combo.os != 'ryzen' }}
71
+ uses: ruby/setup-ruby@v1
70
72
  with:
71
73
  ruby-version: ${{ matrix.combo.ruby }}
72
74
  # NOTE: Bundler 2.2.0 fails to install libv8
data/UNRELEASED.md CHANGED
@@ -10,13 +10,12 @@
10
10
  - Implement the Flip-Flop operators (#2261)
11
11
  - Add `JS[]` to access properties on the global object (#2259)
12
12
  - Add `ENV.fetch` to the Nodejs implementation of `ENV` (#2259)
13
- - Opal::Cache, an optional compiler cache (enabled by default) (#2242, #2278)
13
+ - Opal::Cache, an optional compiler cache (enabled by default) (#2242, #2278, #2329)
14
14
  - Alias for gvars, alias on main (#2270)
15
15
  - Support for GJS (GNOME's JavaScript runtime) runner (#2280)
16
16
  - Scope variables support for `eval()` (#2256)
17
17
  - Add support for `Kernel#binding` (#2256)
18
18
  - A (mostly) correct support for refinements (#2256)
19
- - [CI] Performance regression check (#2276, #2282)
20
19
  - Add support for ECMAScript modules with an `--esm` CLI option (#2286)
21
20
  - Implement `Regexp#names` and add named captures support (#2272)
22
21
  - REPL improvements: (#2285)
@@ -26,15 +25,15 @@
26
25
  - Add `IO#gets` and `IO#read_proc` along with other supporting methods (#2309)
27
26
  - Support `#gets` on most platforms, including browsers (via `prompt`)
28
27
  - Move the REPL to a `--repl` CLI option of the main executable
29
- - Completely refactor IO, now supporting
28
+ - Completely refactor IO, now supporting
30
29
  - Add a runner for MiniRacer (as `miniracer`)
31
- - Support Windows on the Chrome runner
30
+ - Support Windows on the Chrome runner
32
31
  - Support Windows on the REPL
33
32
  - Platforms an IO implementations should either set `IO#read_proc` or overwrite `IO#sysread`
34
33
  - [experimental] Add support for JavaScript async/await (#2221)
35
34
  - Enable the feature by adding a magic comment: `# await: true`
36
35
  - The magic comment can be also used to mark specific method patterns to be awaited
37
- (e.g. `# await: *_await, sleep` will make any method ending in `_await` or named `sleep` to be awaited)
36
+ (e.g. `# await: *_await, sleep` will make any method ending in `_await` or named `sleep` to be awaited)
38
37
  - Add `Kernel#__await__` as a bridge to the `await` keyword (inspired by CoffeeScript await support)
39
38
  - Require `opal/await` to get additional support
40
39
  - Read more on the newly added documentation page
@@ -42,6 +41,21 @@
42
41
  - Add `PromiseV1` as an alias to the original (legacy) Promise class
43
42
  - Add `#to_v1` and `#to_v2` to both classes
44
43
  - `Promise#to_n` will convert it to a native Promise (v2)
44
+ - Add `Opal::Config.esm` to enable/disable ES modules (#2316)
45
+ - If Config.esm is enabled, SimpleServer does type="module"
46
+ - Add new rack-esm example
47
+ - Add a QuickJS (https://bellard.org/quickjs/) runner (#2331)
48
+ - Add `IO#fileno`, `Method#curry`, `Buffer#to_s`, `Pathname.pwd` (#2332)
49
+ - Add NodeJS support for `ARGF`, `ENV.{inspect,to_h,to_hash,merge}`, `File.{delete,unlink}`, `Kernel#system`, <code>Kernel#`</code>, `Process::Status` (#2332)
50
+ - Introduce `__dir__` support (#2323)
51
+ - Full autoload support (#2323)
52
+ - Now compatible with `opal-zeitwerk` and `isomorfeus`
53
+ - Allow toplevel autoloads
54
+ - Allow dynamic autoloads (e.g. can be hooked to fetch a URL upon autoload with a custom loader)
55
+ - Allow overwriting `require` (e.g. like rubygems does)
56
+ - Allow autoloading trees with `require_tree "./foo", autoload: true`
57
+ - Add Module#autoload?
58
+ - Autoload parts of the corelib (#2323)
45
59
 
46
60
  ### Fixed
47
61
 
@@ -58,6 +72,13 @@
58
72
  - Don't try to return the JS `debugger` statement, just return `nil` (#2307)
59
73
  - Retain the `-` while stringifying `-0.0` (#2304)
60
74
  - Fix super support for rest args and re-assignments with implicit arguments (#2315)
75
+ - Fix calling `Regexp#last_match` when `$~` is nil (#2328)
76
+ - Windows support for chrome runner (#2324)
77
+ - Use correct node separator for NODE_PATH on Windows
78
+ - Pass dir and emulate exec a bit on Windows
79
+ - Use Gem.win_platform?, match supported platform to ruby, simplify run
80
+ - NodeJS: Drop the first `--` argument in `ARGV` (#2332)
81
+ - Fix `Object#require` not pointing to `Kernel#require` (#2323)
61
82
 
62
83
  ### Changed
63
84
 
@@ -65,7 +86,7 @@
65
86
  - Renamed internal `super` related helpers,
66
87
  `find_super_dispatcher` is now `find_super`, `find_iter_super_dispatcher` is now `find_block_super` (#2090)
67
88
  - The `opal-repl` CLI now requires files to be passed with `--require` (or `-r`) instead of the bare filename (#2309)
68
-
89
+ - `Process` is now a Module, not a Class - just like in MRI (#2332)
69
90
 
70
91
  ### Deprecated
71
92
 
@@ -74,3 +95,5 @@
74
95
  ### Internal
75
96
 
76
97
  - Switch from jshint to ESLint (#2289)
98
+ - Switch from UglifyJS to Terser (#2318)
99
+ - [CI] Performance regression check (#2276, #2282)
@@ -2,3 +2,4 @@ source 'https://rubygems.org'
2
2
 
3
3
  gem 'rack'
4
4
  gem 'opal', :path => '../../'
5
+ gem 'puma'
@@ -1,24 +1,28 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- opal (1.0.0)
4
+ opal (1.3.0.dev)
5
5
  ast (>= 2.3.0)
6
- parser (~> 2.6)
6
+ parser (~> 3.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- ast (2.4.0)
12
- parser (2.6.4.1)
13
- ast (~> 2.4.0)
14
- rack (2.0.7)
11
+ ast (2.4.2)
12
+ nio4r (2.5.8)
13
+ parser (3.0.2.0)
14
+ ast (~> 2.4.1)
15
+ puma (5.5.0)
16
+ nio4r (~> 2.0)
17
+ rack (2.2.3)
15
18
 
16
19
  PLATFORMS
17
20
  ruby
18
21
 
19
22
  DEPENDENCIES
20
23
  opal!
24
+ puma
21
25
  rack
22
26
 
23
27
  BUNDLED WITH
24
- 1.17.3
28
+ 2.1.4
@@ -0,0 +1 @@
1
+ tmp
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'rack'
4
+ gem 'opal', :path => '../../'
5
+ gem 'puma'
@@ -0,0 +1,27 @@
1
+ require 'opal'
2
+ require 'user'
3
+ require 'opal/platform'
4
+
5
+ module MyApp
6
+ class Application
7
+ def initialize
8
+ @user = User.new('Bob')
9
+ end
10
+
11
+ def title
12
+ "#{@user.name} is #{:not unless @user.authenticated?} authenticated"
13
+ end
14
+ end
15
+ end
16
+
17
+ $app = MyApp::Application.new
18
+
19
+ require 'native'
20
+
21
+ $$[:document][:title] = "#{$app.title}"
22
+
23
+ bill = User.new('Bill')
24
+
25
+ $$.alert "The user is named #{bill.name}."
26
+
27
+ bill.authenticated?
@@ -0,0 +1,24 @@
1
+ class User
2
+ def initialize(name)
3
+ puts "wow"
4
+ @name = name
5
+ end
6
+
7
+ attr_reader :name
8
+
9
+ def authenticated?
10
+ if admin? or special_permission?
11
+ true
12
+ else
13
+ raise "not authenticated"
14
+ end
15
+ end
16
+
17
+ def admin?
18
+ @name == 'Bob'
19
+ end
20
+
21
+ def special_permission?
22
+ false
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ require 'bundler'
2
+ Bundler.require
3
+
4
+ # Instructions: bundle in this directory
5
+ # then run `bundle exec rackup` to start the server
6
+ # and browse to http://localhost:9292
7
+
8
+ # a very small application that just tries to authenticate a user and fails
9
+ # it just writes to the console in the browser (no visible html)
10
+
11
+ # with gems like opal-jquery or opal-browser you could manipulate the dom directly
12
+
13
+ # the directory where the code is (add to opal load path )
14
+ Opal.append_path 'app'
15
+
16
+ # Enable ESM
17
+ Opal::Config.esm = true
18
+
19
+ run Opal::SimpleServer.new { |s|
20
+ # the name of the ruby file to load. To use more files they must be required from here (see app)
21
+ s.main = 'application'
22
+ # need to set the index explicitly for opal server to pick it up
23
+ s.index_path = 'index.html.erb'
24
+ }
25
+
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>opal-sprockets demo</title>
6
+
7
+ <%= javascript_include_tag 'application' %>
8
+ </head>
9
+ <body>
10
+ </body>
11
+ </html>
@@ -1,34 +1,36 @@
1
1
  PATH
2
2
  remote: ../..
3
3
  specs:
4
- opal (1.0.0)
4
+ opal (1.3.0.dev)
5
5
  ast (>= 2.3.0)
6
- parser (~> 2.6)
6
+ parser (~> 3.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- ast (2.4.0)
12
- concurrent-ruby (1.1.5)
13
- mustermann (1.0.3)
14
- nio4r (2.5.2)
15
- opal-sprockets (0.4.8.1.0.3.7)
16
- opal (~> 1.0.0)
17
- sprockets (~> 3.7)
11
+ ast (2.4.2)
12
+ concurrent-ruby (1.1.9)
13
+ mustermann (1.1.1)
14
+ ruby2_keywords (~> 0.0.1)
15
+ nio4r (2.5.8)
16
+ opal-sprockets (1.0.2)
17
+ opal (>= 1.0, < 2.0)
18
+ sprockets (~> 4.0)
18
19
  tilt (>= 1.4)
19
- parser (2.6.5.0)
20
- ast (~> 2.4.0)
21
- puma (4.2.1)
20
+ parser (3.0.2.0)
21
+ ast (~> 2.4.1)
22
+ puma (5.5.0)
22
23
  nio4r (~> 2.0)
23
- rack (2.0.7)
24
- rack-protection (2.0.7)
24
+ rack (2.2.3)
25
+ rack-protection (2.1.0)
25
26
  rack
26
- sinatra (2.0.7)
27
+ ruby2_keywords (0.0.5)
28
+ sinatra (2.1.0)
27
29
  mustermann (~> 1.0)
28
- rack (~> 2.0)
29
- rack-protection (= 2.0.7)
30
+ rack (~> 2.2)
31
+ rack-protection (= 2.1.0)
30
32
  tilt (~> 2.0)
31
- sprockets (3.7.2)
33
+ sprockets (4.0.2)
32
34
  concurrent-ruby (~> 1.0)
33
35
  rack (> 1, < 3)
34
36
  tilt (2.0.10)
@@ -43,4 +45,4 @@ DEPENDENCIES
43
45
  sinatra
44
46
 
45
47
  BUNDLED WITH
46
- 1.17.3
48
+ 2.1.4
data/lib/opal/builder.rb CHANGED
@@ -28,6 +28,10 @@ module Opal
28
28
  # ## `#required_trees`
29
29
  # An array of string containing the logic paths of required directories
30
30
  #
31
+ # ## `#autoloads`
32
+ # An array of entities that are autoloaded and their compile-time load failure can
33
+ # be safely ignored
34
+ #
31
35
  # ## `#to_s`
32
36
  # The processed source
33
37
  #
@@ -86,16 +90,16 @@ module Opal
86
90
 
87
91
  # Retrieve the source for a given path the same way #build would do.
88
92
  def source_for(path)
89
- read(path)
93
+ read(path, false)
90
94
  end
91
95
 
92
96
  def build_str(source, rel_path, options = {})
93
97
  return if source.nil?
94
98
  abs_path = expand_path(rel_path)
95
99
  rel_path = expand_ext(rel_path)
96
- asset = processor_for(source, rel_path, abs_path, options)
100
+ asset = processor_for(source, rel_path, abs_path, false, options)
97
101
  requires = preload + asset.requires + tree_requires(asset, abs_path)
98
- requires.map { |r| process_require(r, options) }
102
+ requires.map { |r| process_require(r, asset.autoloads, options) }
99
103
  processed << asset
100
104
  self
101
105
  rescue MissingRequire => error
@@ -103,7 +107,7 @@ module Opal
103
107
  end
104
108
 
105
109
  def build_require(path, options = {})
106
- process_require(path, options)
110
+ process_require(path, [], options)
107
111
  end
108
112
 
109
113
  def initialize_copy(other)
@@ -158,21 +162,24 @@ module Opal
158
162
  end
159
163
  end
160
164
 
161
- def processor_for(source, rel_path, abs_path, options)
162
- processor = processors.find { |p| p.match? abs_path } ||
163
- raise(ProcessorNotFound, "can't find processor for rel_path: " \
164
- "#{rel_path.inspect}, "\
165
- "abs_path: #{abs_path.inspect}, "\
166
- "source: #{source.inspect}, "\
167
- "processors: #{processors.inspect}"
168
- )
165
+ def processor_for(source, rel_path, abs_path, autoload, options)
166
+ processor = processors.find { |p| p.match? abs_path }
167
+
168
+ if !processor && !autoload
169
+ raise(ProcessorNotFound, "can't find processor for rel_path: " \
170
+ "#{rel_path.inspect}, "\
171
+ "abs_path: #{abs_path.inspect}, "\
172
+ "source: #{source.inspect}, "\
173
+ "processors: #{processors.inspect}"
174
+ )
175
+ end
169
176
 
170
177
  options = options.merge(cache: cache)
171
178
 
172
179
  processor.new(source, rel_path, @compiler_options.merge(options))
173
180
  end
174
181
 
175
- def read(path)
182
+ def read(path, autoload)
176
183
  path_reader.read(path) || begin
177
184
  print_list = ->(list) { "- #{list.join("\n- ")}\n" }
178
185
  message = "can't find file: #{path.inspect} in:\n" +
@@ -182,30 +189,39 @@ module Opal
182
189
  "\nAnd the following processors:\n" +
183
190
  print_list[processors]
184
191
 
185
- case missing_require_severity
186
- when :error then raise MissingRequire, message
187
- when :warning then warn message
188
- when :ignore then # noop
192
+ unless autoload
193
+ case missing_require_severity
194
+ when :error then raise MissingRequire, message
195
+ when :warning then warn message
196
+ when :ignore then # noop
197
+ end
189
198
  end
190
199
 
191
200
  nil
192
201
  end
193
202
  end
194
203
 
195
- def process_require(rel_path, options)
204
+ def process_require(rel_path, autoloads, options)
196
205
  return if prerequired.include?(rel_path)
197
206
  return if already_processed.include?(rel_path)
198
207
  already_processed << rel_path
199
208
 
200
- source = stub?(rel_path) ? '' : read(rel_path)
209
+ autoload = autoloads.include? rel_path
210
+
211
+ source = stub?(rel_path) ? '' : read(rel_path, autoload)
201
212
 
202
213
  # The handling is delegated to the runtime
203
214
  return if source.nil?
204
215
 
205
216
  abs_path = expand_path(rel_path)
206
217
  rel_path = expand_ext(rel_path)
207
- asset = processor_for(source, rel_path, abs_path, options.merge(requirable: true))
208
- process_requires(rel_path, asset.requires + tree_requires(asset, abs_path), options)
218
+ asset = processor_for(source, rel_path, abs_path, autoload, options.merge(requirable: true))
219
+ process_requires(
220
+ rel_path,
221
+ asset.requires + tree_requires(asset, abs_path),
222
+ asset.autoloads,
223
+ options
224
+ )
209
225
  processed << asset
210
226
  end
211
227
 
@@ -227,8 +243,8 @@ module Opal
227
243
  (path_reader.expand(path) || File.expand_path(path)).to_s
228
244
  end
229
245
 
230
- def process_requires(rel_path, requires, options)
231
- requires.map { |r| process_require(r, options) }
246
+ def process_requires(rel_path, requires, autoloads, options)
247
+ requires.map { |r| process_require(r, autoloads, options) }
232
248
  rescue MissingRequire => error
233
249
  raise error, "A file required by #{rel_path.inspect} wasn't found.\n#{error.message}", error.backtrace
234
250
  end
@@ -12,8 +12,9 @@ module Opal
12
12
  @cache = @options.delete(:cache) { Opal.cache }
13
13
  @requires = []
14
14
  @required_trees = []
15
+ @autoloads = []
15
16
  end
16
- attr_reader :source, :filename, :options, :requires, :required_trees
17
+ attr_reader :source, :filename, :options, :requires, :required_trees, :autoloads
17
18
 
18
19
  def to_s
19
20
  source.to_s
@@ -103,6 +104,10 @@ module Opal
103
104
  compiled.required_trees
104
105
  end
105
106
 
107
+ def autoloads
108
+ compiled.autoloads
109
+ end
110
+
106
111
  # Also catch a files with missing extensions and nil.
107
112
  def self.match?(other)
108
113
  super || File.extname(other.to_s) == ''
@@ -42,8 +42,9 @@ module Opal
42
42
  # were used least recently.
43
43
  private def tidy_up_cache
44
44
  entries = Dir[@dir + '/*.rbm.gz']
45
+ entries_stats = entries.map { |entry| [entry, File.stat(entry)] }
45
46
 
46
- size_sum = entries.map { |i| File.size(i) }.sum
47
+ size_sum = entries_stats.map { |_entry, stat| stat.size }.sum
47
48
  return unless size_sum > @max_size
48
49
 
49
50
  # First, we try to get the oldest files first.
@@ -51,13 +52,13 @@ module Opal
51
52
  # recently used files first. Filesystems with relatime or noatime
52
53
  # will get this wrong, but it doesn't matter that much, because
53
54
  # the previous sort got things "maybe right".
54
- entries = entries.sort_by { |i| [File.mtime(i), File.atime(i)] }
55
+ entries_stats = entries_stats.sort_by { |_entry, stat| [stat.mtime, stat.atime] }
55
56
 
56
- entries.each do |i|
57
- size_sum -= File.size(i)
58
- File.unlink(i)
57
+ entries_stats.each do |entry, stat|
58
+ size_sum -= stat.size
59
+ File.unlink(entry)
59
60
 
60
- # We don't need to work this out anymore - we reached out goal.
61
+ # We don't need to work this out anymore - we reached our goal.
61
62
  break unless size_sum > @max_size
62
63
  end
63
64
  rescue Errno::ENOENT
@@ -8,7 +8,7 @@ require 'tmpdir'
8
8
  module Opal
9
9
  module CliRunners
10
10
  class Chrome
11
- SCRIPT_PATH = File.expand_path('chrome_cdp_interface.js', __dir__).freeze
11
+ SCRIPT_PATH = File.expand_path('chrome_cdp_interface.rb', __dir__).freeze
12
12
 
13
13
  DEFAULT_CHROME_HOST = 'localhost'
14
14
  DEFAULT_CHROME_PORT = 9222
@@ -36,23 +36,24 @@ module Opal
36
36
  def run
37
37
  mktmpdir do |dir|
38
38
  with_chrome_server do
39
- # This has to be moved to some generator.
40
- system(%{bundle exec opal -r opal/cli_runners/source-map-support-node } +
41
- %{-cE #{__dir__}/chrome_cdp_interface.rb > "#{SCRIPT_PATH}"}
42
- )
43
-
44
39
  prepare_files_in(dir)
45
40
 
41
+ env = {
42
+ 'CHROME_HOST' => chrome_host,
43
+ 'CHROME_PORT' => chrome_port.to_s,
44
+ 'NODE_PATH' => File.join(__dir__, 'node_modules')
45
+ }
46
+
46
47
  cmd = [
47
- 'env',
48
- "CHROME_HOST=#{chrome_host}",
49
- "CHROME_PORT=#{chrome_port}",
50
- 'node',
48
+ 'bundle', 'exec', 'opal',
49
+ '--no-exit',
50
+ '-I', __dir__,
51
+ '-r', 'source-map-support-node',
51
52
  SCRIPT_PATH,
52
53
  dir,
53
54
  ]
54
55
 
55
- Kernel.exec(*cmd)
56
+ Kernel.exec(env, *cmd)
56
57
  end
57
58
  end
58
59
  end
@@ -108,7 +109,7 @@ module Opal
108
109
  raise 'Chrome server can be started only on localhost' if chrome_host != DEFAULT_CHROME_HOST
109
110
 
110
111
  # Disable web security with "--disable-web-security" flag to be able to do XMLHttpRequest (see test_openuri.rb)
111
- chrome_server_cmd = %{"#{chrome_executable}" \
112
+ chrome_server_cmd = %{#{chrome_executable.shellescape} \
112
113
  --headless \
113
114
  --disable-web-security \
114
115
  --remote-debugging-port=#{chrome_port} \
@@ -129,7 +130,11 @@ module Opal
129
130
  puts 'Make sure that you have it installed and that its version is > 59'
130
131
  exit(1)
131
132
  ensure
132
- Process.kill('HUP', chrome_pid) if chrome_pid
133
+ if Gem.win_platform? && chrome_pid
134
+ Process.kill('KILL', chrome_pid) unless system("taskkill /f /t /pid #{chrome_pid} >NUL 2>NUL")
135
+ elsif chrome_pid
136
+ Process.kill('HUP', chrome_pid)
137
+ end
133
138
  end
134
139
 
135
140
  def chrome_server_running?
@@ -143,7 +148,7 @@ module Opal
143
148
  def chrome_executable
144
149
  ENV['GOOGLE_CHROME_BINARY'] ||
145
150
  case RbConfig::CONFIG['host_os']
146
- when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
151
+ when /bccwin|cygwin|djgpp|mingw|mswin|wince/
147
152
  [
148
153
  'C:/Program Files/Google/Chrome Dev/Application/chrome.exe',
149
154
  'C:/Program Files/Google/Chrome/Application/chrome.exe'
@@ -152,7 +157,7 @@ module Opal
152
157
  return path
153
158
  end
154
159
  when /darwin|mac os/
155
- '/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome'
160
+ '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
156
161
  when /linux/
157
162
  %w[
158
163
  google-chrome-stable
@@ -10,7 +10,7 @@ require 'opal/platform'
10
10
  var CDP = require("chrome-remote-interface");
11
11
  var fs = require("fs");
12
12
 
13
- var dir = #{ARGV[0]}
13
+ var dir = #{ARGV.last}
14
14
 
15
15
  var options = {
16
16
  host: #{ENV['CHROME_HOST'] || 'localhost'},
@@ -32,9 +32,10 @@ module Opal
32
32
 
33
33
  # Ensure stdlib node_modules is among NODE_PATHs
34
34
  def self.node_modules
35
- ENV['NODE_PATH'].to_s.split(':').tap do |paths|
35
+ npsep = Gem.win_platform? ? ';' : ':'
36
+ ENV['NODE_PATH'].to_s.split(npsep).tap do |paths|
36
37
  paths << NODE_PATH unless paths.include? NODE_PATH
37
- end.join(':')
38
+ end.join(npsep)
38
39
  end
39
40
 
40
41
  class MissingNodeJS < RunnerError
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'opal/paths'
4
+ require 'opal/cli_runners/system_runner'
5
+ require 'shellwords'
6
+
7
+ module Opal
8
+ module CliRunners
9
+ # QuickJS is Fabrice Bellard's minimalistic JavaScript engine
10
+ # https://github.com/bellard/quickjs
11
+ class Quickjs
12
+ def self.call(data)
13
+ exe = ENV['QJS_PATH'] || 'qjs'
14
+
15
+ opts = Shellwords.shellwords(ENV['QJS_OPTS'] || '')
16
+
17
+ SystemRunner.call(data) do |tempfile|
18
+ [exe, '--std', *opts, tempfile.path, *data[:argv]]
19
+ end
20
+ rescue Errno::ENOENT
21
+ raise MissingQuickjs, 'Please install QuickJS to be able to run Opal scripts.'
22
+ end
23
+
24
+ class MissingQuickjs < RunnerError
25
+ end
26
+ end
27
+ end
28
+ end
@@ -66,6 +66,7 @@ module Opal
66
66
  register_runner :nashorn, :Nashorn, 'opal/cli_runners/nashorn'
67
67
  register_runner :nodejs, :Nodejs, 'opal/cli_runners/nodejs'
68
68
  register_runner :gjs, :Gjs, 'opal/cli_runners/gjs'
69
+ register_runner :quickjs, :Quickjs, 'opal/cli_runners/quickjs'
69
70
  register_runner :miniracer, :MiniRacer, 'opal/cli_runners/mini_racer'
70
71
  register_runner :server, :Server, 'opal/cli_runners/server'
71
72