opal 1.3.0.alpha1 → 1.3.0.rc1

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.
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