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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bc96268e7c234e02e983299ec4e04de40283cd5dec33a944aca6567bddaf927
|
4
|
+
data.tar.gz: 34a0a446e2c6a8564cb1ec9523a88acfaf667f2b35d77aebde437e5658eb8b95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 470926fc4eb90e7effc90cc193fdf80746f26ecffff79ddd602c7c275e2e17638206a230079370f3fd30923f00988bd497f1ec38914ae50fa49a90ff76ab14a6
|
7
|
+
data.tar.gz: 83fa53a8d529538c321dad65ba704e4ec3fd4ab92e8de57a2865fb1da38a205008729eddd5444e1f7c15ef19cc11f228e0cad9d692e32c558cf346fac62c1c66
|
data/.gitattributes
CHANGED
@@ -1 +1,5 @@
|
|
1
1
|
UNRELEASED.md merge=union
|
2
|
+
spec/opal/core/language/DATA/characters_support_crlf_spec.rb text eol=crlf
|
3
|
+
spec/opal/core/language/DATA/characters_support_spec.rb text eol=lf
|
4
|
+
spec/opal/core/language/DATA/multiple___END___crlf_spec.rb text eol=crlf
|
5
|
+
spec/opal/core/language/DATA/multiple___END___spec.rb text eol=lf
|
data/.github/workflows/build.yml
CHANGED
@@ -8,6 +8,9 @@ on:
|
|
8
8
|
- "*/ci-check"
|
9
9
|
pull_request: {}
|
10
10
|
|
11
|
+
permissions:
|
12
|
+
contents: read
|
13
|
+
|
11
14
|
jobs:
|
12
15
|
rake:
|
13
16
|
name: ${{ matrix.combo.name || matrix.combo.ruby }}
|
@@ -42,9 +45,20 @@ jobs:
|
|
42
45
|
- name: smoke-test
|
43
46
|
ruby: '3.0'
|
44
47
|
command: bin/rake smoke_test
|
48
|
+
- name: windows-mspec-nodejs
|
49
|
+
command: bundle exec rake mspec_nodejs
|
50
|
+
ruby: '3.0'
|
51
|
+
os: windows-latest
|
52
|
+
- name: windows-mspec-chrome
|
53
|
+
command: bundle exec rake mspec_chrome
|
54
|
+
ruby: '3.0'
|
55
|
+
os: windows-latest
|
56
|
+
- name: windows-minitest
|
57
|
+
command: bundle exec rake minitest
|
58
|
+
ruby: '3.0'
|
59
|
+
os: windows-latest
|
45
60
|
- name: windows
|
46
|
-
|
47
|
-
command: bundle exec rake rspec minitest_nodejs
|
61
|
+
command: bundle exec rake rspec
|
48
62
|
ruby: '3.0'
|
49
63
|
os: windows-latest
|
50
64
|
- name: lint
|
@@ -58,7 +72,7 @@ jobs:
|
|
58
72
|
permissive: true
|
59
73
|
fetchdepth: '0'
|
60
74
|
command: bin/rake performance:compare
|
61
|
-
os: ryzen
|
75
|
+
# os: ryzen
|
62
76
|
|
63
77
|
# Currently failing:
|
64
78
|
# - ruby: truffleruby
|
data/HACKING.md
CHANGED
@@ -185,6 +185,29 @@ Array#permutation_returns_an_Enumerator_which_works_as_expected_even_when_the_ar
|
|
185
185
|
Array#permutation_generates_from_a_defensive_copy,_ignoring_mutations 0.038
|
186
186
|
```
|
187
187
|
|
188
|
+
### AsciiDoctor Benchmark and git branch performance comparison
|
189
|
+
|
190
|
+
It is testing the performance for the real life application AsciiDoctor, compiling it, running it and asset size.
|
191
|
+
It prints a nice summary to compare the current branch with the master branch.
|
192
|
+
On Windows make sure to have the Ruby DevKit enabled with `ridk enable`.
|
193
|
+
|
194
|
+
Run the task on any system with: `bundle exec rake performance:compare`
|
195
|
+
|
196
|
+
Example output:
|
197
|
+
```
|
198
|
+
=== Summary ===
|
199
|
+
Summary of performance changes between (previous) master and (current) v1.5.1-48-gc470e969:
|
200
|
+
|
201
|
+
Comparison of V8 function optimization status:
|
202
|
+
Dateien tmp/performance/optstatus_previous und tmp/performance/optstatus_current sind identisch.
|
203
|
+
|
204
|
+
Comparison of the Asciidoctor (a real-life Opal application) compile and run:
|
205
|
+
Compile time: 9.367 (±2.21%) -> 9.579 (±17.53%) (change: +2.26%)
|
206
|
+
Run time: 2.049 (±9.25%) -> 2.147 (±19.70%) (change: +4.80%)
|
207
|
+
Bundle size: 4740.27 kB -> 4740.27 kB (change: +0.00%)
|
208
|
+
Minified bundle size: 995.10 kB -> 995.10 kB (change: +0.00%)
|
209
|
+
Mangled & minified: 706.32 kB -> 706.32 kB (change: +0.00%)
|
210
|
+
```
|
188
211
|
|
189
212
|
## Parser
|
190
213
|
|
data/README.md
CHANGED
@@ -18,14 +18,14 @@
|
|
18
18
|
<a href="#sponsors"><img src="https://opencollective.com/opal/sponsors/badge.svg" alt="Sponsors on Open Collective" title="" /></a>
|
19
19
|
<a href="https://slack.opalrb.com/"><img src="https://img.shields.io/badge/slack-join%20chat-46BC99?logo=slack&style=flat" alt="Slack" title="Join Chat" /></a>
|
20
20
|
<a href="https://opalrb.com/docs"><img src="https://img.shields.io/badge/docs-updated-blue.svg" alt="Documentation" title="" /></a>
|
21
|
-
|
21
|
+
|
22
22
|
<br>
|
23
23
|
<strong>Code:</strong><br>
|
24
24
|
<a href="https://badge.fury.io/rb/opal"><img src="https://img.shields.io/gem/v/opal.svg?style=flat" alt="Gem Version" title="" /></a>
|
25
25
|
<a href="https://github.com/opal/opal/actions?query=workflow%3Abuild"><img src="https://github.com/opal/opal/workflows/build/badge.svg" alt="Build Status" /></a>
|
26
26
|
<a href="https://codeclimate.com/github/opal/opal"><img src="https://img.shields.io/codeclimate/maintainability-percentage/opal/opal.svg" alt="Code Climate" title="" /></a>
|
27
27
|
<a href="https://coveralls.io/github/opal/opal?branch=master"><img src="https://coveralls.io/repos/opal/opal/badge.svg?branch=master&service=github" alt="Coverage Status" title="" /></a>
|
28
|
-
|
28
|
+
|
29
29
|
<br>
|
30
30
|
<strong>Sponsors:</strong>
|
31
31
|
<br/><a href="https://nebulab.it?utm_source=github&utm_medium=badge"><img src="https://img.shields.io/static/v1?label=Nebulab&message=Open+Source+Fridays&color=%235dbefd&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAYAAAByDd+UAAAACXBIWXMAABYlAAAWJQFJUiTwAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMQSURBVHgBrZZNTxNRFIbfczsgIMQiLBCRFDaGhUr9A9iiIa5EEneIwE/AlRsNv8KlIKwFl35RTUBX8rFBdiVKAgqmXSCY0M71nJl+zJTOdKh9k6Yzc8/cZ86555x7CQE0mji5hSyGlQoNaOgIPwrnhtIArWszu4EQFudjdR8rzUV+gw8/ZMZB9IwvIwimJJGafhmjWZwFOJ7QkYzWCwTdj+qUDJGKz8Rou3RAlT4YS+hHWW2u/QdM1MNzrI6+zwyXDrg8FANStIDaSXOIJ5whLgAljOIZiglRK6U4vDfz4S2ElGGJWsEaQkCTUbhtNbV+lb+xgFY2Bs9ET0h/GzBxlfAkqnCUKY5xKfVLbsi1/R126lcF6WgCYp2ES42EBp6tvQFY+alLTUlrUxizJEVNWiVwBkVagGg7oe+CDclLYOfrgMdfTBz8PfWa1lkzbsDEsH/5FyF9YUK0zQ1xwpoZtsm9pwxMRLyA9wyi0A2Jcjl1NNqeeEFEimxYPkmWd014ikIDnDTeBb53DOweaRxnvWGyhnmYfPZWGt487sNi6lsK67/lZ1oZGOtUaD3nhtU7etXXfe0VzrzCBgLKCR68rNDX6oaJlvd0xXnklbSfgSTL/QghXF8EP980cVKyVL/Ys9UDVFJa8Tdt+1lYmcmJM3Vd4UEvWeslRf32h9ubrVRl77gBrCto85OfUU+LXTMGx+JuN2Hoin3/Zkfjj6ObBAknV+KG4jpc9BqXMEpiCMz6Z9ZQ12kvJZxb6co4Zr1W83esY8F2OYsIe+eEyfTiVXczCl7uM2wliHfMEJaRc3Wa++mLUotrF4EW7h6f94Dvh6aVFM60Fy8Xkya+BfBOjh5yUWhqY0vmKi9q1GnVxZ7sHKIWSs7FQ71yUagkRTTCfymnVY1gsgHHC5z8hbUjaz0Fr8ZanXhX0pPOw5SrV8wNGjNscMrTKpXKaj05f9twVYHnMZGPHEuwTwEBNi+3NGiNt6GRcsfEIAfhp2cAV3cQLtXoOz7q8+ZJRLx3kmxn4dy7aas1SrfiBpKraV/9A+PSJLDAXLUvAAAAAElFTkSuQmCC" alt="Nebulab: Open Source Fridays" /></a>
|
@@ -99,7 +99,7 @@ or to build an entire app including dependencies declared with `require`:
|
|
99
99
|
```ruby
|
100
100
|
builder = Opal::Builder.new
|
101
101
|
builder.build_str('require "opal"; puts "wow"', '(inline)')
|
102
|
-
File.
|
102
|
+
File.binwrite 'app.js', builder.to_s # must use binary mode for writing
|
103
103
|
```
|
104
104
|
|
105
105
|
|
data/UNRELEASED.md
CHANGED
@@ -7,3 +7,50 @@
|
|
7
7
|
### Performance
|
8
8
|
### Fixed
|
9
9
|
-->
|
10
|
+
|
11
|
+
### Changed
|
12
|
+
|
13
|
+
- No longer truncate stacktraces to 15 lines (#2440)
|
14
|
+
|
15
|
+
### Performance
|
16
|
+
|
17
|
+
- Improve method block performance for runtime (#2449)
|
18
|
+
- Uninline non-typical argument handling (#2419)
|
19
|
+
- Logic optimization of runtime.js (#2415)
|
20
|
+
- Windows support for `performance:compare` CI check (#2450)
|
21
|
+
- Improve block performance for even more cases (#2465)
|
22
|
+
|
23
|
+
### Added
|
24
|
+
|
25
|
+
- Added support for `#freeze` and `#frozen?` (#2444, #2468)
|
26
|
+
- Add CLI support for ESM, at least for Chrome, NodeJS, QuickJS and GJS (#2435)
|
27
|
+
- Support exit in Chrome CLI Runner, both sync and async (#2439)
|
28
|
+
- Make sure the Server CLI Runner can pick up changes in sources (#2436)
|
29
|
+
- Delegate and ruby2_keywords (#2446)
|
30
|
+
- Source code can now be embedded in the compiled file to improve development/debugging, e.g. RSpec reports, `Proc#source_location` (#2440)
|
31
|
+
- Added `Kernel#caller_locations` (#2440)
|
32
|
+
- `Opal::Builder::Prefork` for blazingly fast multicore compilation times (#2263, #2462, #2454, #2469, #2475)
|
33
|
+
- Add `Opal::BuilderProcessors::RubyERBProcessor` (#2470)
|
34
|
+
|
35
|
+
### Fixed
|
36
|
+
|
37
|
+
- Closure tracking support fixes a whole array of bugs handling `break` / `next` / `retry` / … (#2357)
|
38
|
+
- Fix an edge case of if in the most complex form not returning (#2433)
|
39
|
+
- `String#length` is now available when using `opal/mini` (#2438)
|
40
|
+
- Auto-await produced invalid code (#2440)
|
41
|
+
- Fix `Enumerable#collect_concat` and `#flat_map` implementation (#2440)
|
42
|
+
- Improved await support for PromiseV1 (#2440)
|
43
|
+
- Compilation error occurs while compiling `being/end` returning a `case/when` (#2459)
|
44
|
+
- Ensure UTF-8 encoding of `.sourcesContent` of source maps (#2451)
|
45
|
+
- Benchmarks require string/unpack (#2453)
|
46
|
+
- Fix compilation of a call: `gets&.chomp` (#2473)
|
47
|
+
- Fix specs on Windows (#2460)
|
48
|
+
- Make opal CLI tool work again with pipes (#2474)
|
49
|
+
|
50
|
+
### Internal
|
51
|
+
|
52
|
+
- GitHub Workflows security hardening (#2432)
|
53
|
+
- Retry if file cache write operation exits with Zlib::BufError (#2463)
|
54
|
+
- Eliminate redundant `var constructor` in `allocate_class` (#2452)
|
55
|
+
- Fix `performance:compare` asset size calculation (#2457)
|
56
|
+
- Fix a few specs after the Opal RSpec 1.0 (alpha) release (#2471, #2472)
|
data/benchmark/run.rb
CHANGED
data/docs/compiled_ruby.md
CHANGED
@@ -617,6 +617,14 @@ myHash.$to_n(); // provided by the Native module
|
|
617
617
|
|
618
618
|
NOTE: Be aware `Hash#to_n` produces a duplicate copy of the hash.
|
619
619
|
|
620
|
+
|
621
|
+
### Freezing Objects
|
622
|
+
|
623
|
+
Starting with Opal 1.6.0 freezing objects is supported in general but a few differences to Ruby apply.
|
624
|
+
Contrary to Ruby, where #freeze is often used to optimize performance, there is no performance benefit when freezing objects in Opal, instead its main use case is to prevent modification of objects.
|
625
|
+
There are a few edge cases, where accessing frozen objects in Opal behaves different from Ruby. In those cases a modification attempt will fail silently, with no "FrozenError" exception thrown.
|
626
|
+
|
627
|
+
|
620
628
|
## Advanced Compilation
|
621
629
|
|
622
630
|
### Method Missing
|
data/docs/compiler.md
CHANGED
data/docs/compiler_directives.md
CHANGED
data/docs/getting_started.md
CHANGED
@@ -45,3 +45,20 @@ Opal.append_path '../my_lib'
|
|
45
45
|
Now, any ruby files in this directory can be discovered.
|
46
46
|
|
47
47
|
|
48
|
+
## FAQ
|
49
|
+
|
50
|
+
### Why does Opal exist?
|
51
|
+
|
52
|
+
To try and keep ruby relevant in a world where client-side applications are making javascript the primary development platform.
|
53
|
+
|
54
|
+
### How compatible is Opal?
|
55
|
+
|
56
|
+
We run opal against the [ruby spec](https://github.com/ruby/spec) as our primary testing setup. We try to make Opal as compatible as possible, whilst also taking into account restrictions of JavaScript when applicable. Opal supports the majority of ruby syntax features, as well as a very large part of the corelib implementation. We support method\_missing, modules, classes, instance\_exec, blocks, procs and lots lots more. Opal can compile and run RSpec unmodified, as well as self hosting the compiler at runtime.
|
57
|
+
|
58
|
+
### What version of ruby does Opal target?
|
59
|
+
|
60
|
+
We are running tests under ruby 3.0.0 conditions, but are mostly compatible with 2.6 level features.
|
61
|
+
|
62
|
+
### Why doesn't Opal support mutable strings?
|
63
|
+
|
64
|
+
All strings in Opal are immutable because ruby strings just get compiled directly into javascript strings, which are immutable. Wrapping ruby strings as a custom JavaScript object would add a lot of overhead as well as making interaction between ruby and javascript libraries more difficult.
|
data/docs/headless_chrome.md
CHANGED
data/docs/index.md
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
# Opal Guides for v1.6.dev
|
2
|
+
|
3
|
+
These guides are designed to make you immediately productive with Opal, and to help you understand how all of the pieces fit together.
|
4
|
+
|
5
|
+
The guides for earlier releases are [available here](/docs).
|
6
|
+
|
7
|
+
---
|
8
|
+
|
9
|
+
## Start here
|
10
|
+
|
11
|
+
#### [Getting Started with Opal](etting_started.html)
|
12
|
+
|
13
|
+
Everything you need to know to install Opal and create your first application.
|
14
|
+
|
15
|
+
---
|
16
|
+
|
17
|
+
## Using JavaScript Features from Ruby
|
18
|
+
|
19
|
+
#### [Async](async.html)
|
20
|
+
|
21
|
+
Learn more about JavaScript `async`/`await` support in Opal and how you can use it to avoid explicit callbacks and promises.
|
22
|
+
|
23
|
+
#### [Promises](promises.html)
|
24
|
+
|
25
|
+
How to interact and leverage the power of JavaScript promises from Ruby.
|
26
|
+
|
27
|
+
#### [Source Maps](source_maps.html)
|
28
|
+
|
29
|
+
How to enable and consume source-maps for your Opal application and be able to debug your Ruby scripts right inside the browser.
|
30
|
+
|
31
|
+
---
|
32
|
+
|
33
|
+
## Using Ruby Features
|
34
|
+
|
35
|
+
#### [Working with ERB and Haml Templates](templates.html)
|
36
|
+
|
37
|
+
How to work with template libraries in Opal, be it to share the templates with the server or to write your own.
|
38
|
+
|
39
|
+
---
|
40
|
+
|
41
|
+
## Working with Frameworks
|
42
|
+
|
43
|
+
#### [Rails](rails.html)
|
44
|
+
|
45
|
+
How to use `opal-rails` to use Opal as the JavaScript compiler.
|
46
|
+
|
47
|
+
#### [Static Applications](static_applications.html)
|
48
|
+
|
49
|
+
The most basic setup for a static Opal powered website that can be hosted anywhere.
|
50
|
+
|
51
|
+
#### [Sinatra](sinatra.html)
|
52
|
+
|
53
|
+
Serve Opal applications through Sinatra and `opal-sprockets`.
|
54
|
+
|
55
|
+
#### [Roda + Sprockets](roda-sprockets.html)
|
56
|
+
|
57
|
+
Setup Roda + Sprockets to start serving Opal applications from Roda.
|
58
|
+
|
59
|
+
---
|
60
|
+
|
61
|
+
## Interacting with Other Libraries
|
62
|
+
|
63
|
+
#### [jQuery](jquery.html)
|
64
|
+
|
65
|
+
This guide covers the `opal-jquery` wrapper around the popular library.
|
66
|
+
|
67
|
+
#### [RSpec](rspec.html)
|
68
|
+
|
69
|
+
Write specs for your Opal code RSpec and run them on Node.js or in a browser.
|
70
|
+
|
71
|
+
#### [Using Sprockets](using_sprockets.html)
|
72
|
+
|
73
|
+
Configure the long-lasting asset handler to work with Opal.
|
74
|
+
|
75
|
+
---
|
76
|
+
|
77
|
+
## Digging Deeper
|
78
|
+
|
79
|
+
#### [Configuring Gems](configuring_gems.html)
|
80
|
+
|
81
|
+
How to make your gem work in Opal and differentiate code for the JavaScript environment.
|
82
|
+
|
83
|
+
#### [Compiler](compiler.html)
|
84
|
+
|
85
|
+
A very general overview of how the Opal compiler works.
|
86
|
+
|
87
|
+
#### [Compiled Ruby](compiled_ruby.html)
|
88
|
+
|
89
|
+
This guide documents how each part of Ruby is mapped to JavaScript internally.
|
90
|
+
|
91
|
+
#### [Compiler File Loading Directives](compiler_directives.html)
|
92
|
+
|
93
|
+
The Opal compiler supports some special directives that can optimize or
|
94
|
+
enhance the output of compiled Ruby code to suit the Ruby environment.
|
95
|
+
|
96
|
+
#### [Using the Opal parser inside a JavaScript environment](opal_parser.html)
|
97
|
+
|
98
|
+
This guide documents how to parse and run Ruby scripts within a browser or any supported JavaScript environment
|
99
|
+
|
100
|
+
#### [Encoding](encoding.html)
|
101
|
+
|
102
|
+
(WIP) How to handle encoding within Opal in the browser and in the code.
|
103
|
+
|
104
|
+
#### [Running code in a Headless Chrome](headless_chrome.html)
|
105
|
+
|
106
|
+
How to run your Opal application in a headless Chrome from the CLI instead of Node.js.
|
107
|
+
|
108
|
+
#### [Unsupported Features](unsupported_features.html)
|
109
|
+
|
110
|
+
Some things that are very difficult, impossible, or outright incompatible with a JavaScript environment.
|
111
|
+
|
112
|
+
---
|
113
|
+
|
114
|
+
## Releases
|
115
|
+
|
116
|
+
#### [Upgrading Opal](upgrading.html)
|
117
|
+
|
118
|
+
This guide provides steps to be followed when you upgrade your applications to a newer version of Opal.
|
119
|
+
|
120
|
+
#### [Releasing Instructions](releasing.html)
|
121
|
+
|
122
|
+
(WIP) A step-by-step guide on who to release a new version of Opal.
|
123
|
+
|
data/docs/jquery.md
CHANGED
@@ -58,7 +58,7 @@ builder.build('opal')
|
|
58
58
|
builder.build('opal-jquery')
|
59
59
|
builder.build('./app/application.rb')
|
60
60
|
|
61
|
-
File.
|
61
|
+
File.binwrite('application.js', builder.to_s) # must use binary mode for writing
|
62
62
|
```
|
63
63
|
|
64
64
|
then simply load the compiled file in your html:
|
@@ -67,7 +67,7 @@ then simply load the compiled file in your html:
|
|
67
67
|
<!DOCTYPE html>
|
68
68
|
<html>
|
69
69
|
<head>
|
70
|
-
<script src='https://code.jquery.com/jquery-3.3.1.min.js' integrity='sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=' crossorigin='anonymous'></script>
|
70
|
+
<script src='https://code.jquery.com/jquery-3.3.1.min.js' integrity='sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=' crossorigin='anonymous'></script>
|
71
71
|
<script type='text/javascript' src='./application.js'></script>
|
72
72
|
</head>
|
73
73
|
<body></body>
|
@@ -75,11 +75,11 @@ then simply load the compiled file in your html:
|
|
75
75
|
```
|
76
76
|
|
77
77
|
NOTE: opal-jquery expects a jquery library to be loaded. This example loads it
|
78
|
-
remotely from jquery.com, but a locally downloaded copy works just as well, or-
|
78
|
+
remotely from jquery.com, but a locally downloaded copy works just as well, or-
|
79
79
|
if you're using rails- jquery may be included automatically.
|
80
80
|
|
81
|
-
This example builds opal, opal-jquery and the application into a single `.js` file,
|
82
|
-
but you may build them separately, if you so choose. Just remember to include
|
81
|
+
This example builds opal, opal-jquery and the application into a single `.js` file,
|
82
|
+
but you may build them separately, if you so choose. Just remember to include
|
83
83
|
each respective script in your html!
|
84
84
|
|
85
85
|
### How does opal-jquery work
|
data/docs/templates.md
CHANGED
@@ -42,6 +42,43 @@ Template['login']
|
|
42
42
|
# => #<Template: 'login'>
|
43
43
|
```
|
44
44
|
|
45
|
+
## ERB Templates
|
46
|
+
|
47
|
+
Support for `erb` templates is built in directly to the opal gem and stdlib.
|
48
|
+
There is one caveat though when working with sprockets - it must have the
|
49
|
+
`.opalerb` file extension, instead of `.erb`. This is because sprockets has a
|
50
|
+
built in handler for `.erb` files.
|
51
|
+
|
52
|
+
If we have the same user class as above, create an `app/views/user.opalerb`
|
53
|
+
file:
|
54
|
+
|
55
|
+
```erb
|
56
|
+
<!-- app/views/user.opalerb -->
|
57
|
+
<div class="row">
|
58
|
+
<div class="col-md-3"><%= self.name %></div>
|
59
|
+
</div>
|
60
|
+
```
|
61
|
+
|
62
|
+
Again, you must then require the template (without the `.opalerb` extension):
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
# app/application.rb
|
66
|
+
require 'opal'
|
67
|
+
require 'views/user'
|
68
|
+
```
|
69
|
+
|
70
|
+
And then you can access and render the template:
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# app/application.rb
|
74
|
+
|
75
|
+
template = Template['views/user']
|
76
|
+
user = User.new('Ford Prefect')
|
77
|
+
|
78
|
+
puts template.render(user)
|
79
|
+
# => "<div class="row">...</div>"
|
80
|
+
```
|
81
|
+
|
45
82
|
## Haml templates
|
46
83
|
|
47
84
|
`opal-haml` allows `.haml` templates to be compiled, just like opal compiles
|
@@ -111,40 +148,3 @@ check it out, you should see it compiled into something like the following:
|
|
111
148
|
</div>
|
112
149
|
</div>
|
113
150
|
```
|
114
|
-
|
115
|
-
## ERB Templates
|
116
|
-
|
117
|
-
Support for `erb` templates is built in directly to the opal gem and stdlib.
|
118
|
-
There is one caveat though when working with sprockets - it must have the
|
119
|
-
`.opalerb` file extension, instead of `.erb`. This is because sprockets has a
|
120
|
-
built in handler for `.erb` files.
|
121
|
-
|
122
|
-
If we have the same user class as above, create an `app/views/user.opalerb`
|
123
|
-
file:
|
124
|
-
|
125
|
-
```erb
|
126
|
-
<!-- app/views/user.opalerb -->
|
127
|
-
<div class="row">
|
128
|
-
<div class="col-md-3"><%= self.name %></div>
|
129
|
-
</div>
|
130
|
-
```
|
131
|
-
|
132
|
-
Again, you must then require the template (without the `.opalerb` extension):
|
133
|
-
|
134
|
-
```ruby
|
135
|
-
# app/application.rb
|
136
|
-
require 'opal'
|
137
|
-
require 'views/user'
|
138
|
-
```
|
139
|
-
|
140
|
-
And then you can access and render the template:
|
141
|
-
|
142
|
-
```ruby
|
143
|
-
# app/application.rb
|
144
|
-
|
145
|
-
template = Template['views/user']
|
146
|
-
user = User.new('Ford Prefect')
|
147
|
-
|
148
|
-
puts template.render(user)
|
149
|
-
# => "<div class="row">...</div>"
|
150
|
-
```
|
@@ -24,10 +24,6 @@ Encodings only have a very small implementation inside Opal.
|
|
24
24
|
|
25
25
|
JavaScript does not have a native `Thread` implementation, so they are not present inside Opal. There is a placeholder `Thread` class just to provide some small level of compatibility with libraries that expect it. It does not have any function.
|
26
26
|
|
27
|
-
#### Frozen Objects ####
|
28
|
-
|
29
|
-
Opal does not currently support frozen objects, but has placeholder methods to prevent other libraries breaking when expecting these methods. Opal could support frozen objects in the future once a similar implementation becomes available across JavaScript runtimes.
|
30
|
-
|
31
27
|
#### Private, Public and Protected methods ####
|
32
28
|
|
33
29
|
All methods in Opal are defined as `public` to avoid additional runtime overhead. `Module#private` and `Module#protected` exist as just placeholder methods and are no-op methods.
|
data/lib/opal/builder.rb
CHANGED
@@ -4,6 +4,7 @@ require 'opal/path_reader'
|
|
4
4
|
require 'opal/paths'
|
5
5
|
require 'opal/config'
|
6
6
|
require 'opal/cache'
|
7
|
+
require 'opal/builder_scheduler'
|
7
8
|
require 'set'
|
8
9
|
|
9
10
|
module Opal
|
@@ -55,8 +56,6 @@ module Opal
|
|
55
56
|
processor_extensions.each { |ext| extensions << ext }
|
56
57
|
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
59
|
class MissingRequire < LoadError
|
61
60
|
end
|
62
61
|
|
@@ -76,6 +75,11 @@ module Opal
|
|
76
75
|
@compiler_options ||= Opal::Config.compiler_options
|
77
76
|
@missing_require_severity ||= Opal::Config.missing_require_severity
|
78
77
|
@cache ||= Opal.cache
|
78
|
+
@scheduler ||= Opal.builder_scheduler
|
79
|
+
|
80
|
+
if @scheduler.respond_to? :new
|
81
|
+
@scheduler = @scheduler.new(self)
|
82
|
+
end
|
79
83
|
|
80
84
|
@processed = []
|
81
85
|
end
|
@@ -99,11 +103,10 @@ module Opal
|
|
99
103
|
rel_path = expand_ext(rel_path)
|
100
104
|
asset = processor_for(source, rel_path, abs_path, false, options)
|
101
105
|
requires = preload + asset.requires + tree_requires(asset, abs_path)
|
102
|
-
|
106
|
+
# Don't automatically load modules required by the module
|
107
|
+
process_requires(rel_path, requires, asset.autoloads, options.merge(load: false))
|
103
108
|
processed << asset
|
104
109
|
self
|
105
|
-
rescue MissingRequire => error
|
106
|
-
raise error, "A file required by #{rel_path.inspect} wasn't found.\n#{error.message}", error.backtrace
|
107
110
|
end
|
108
111
|
|
109
112
|
def build_require(path, options = {})
|
@@ -134,6 +137,39 @@ module Opal
|
|
134
137
|
path_reader.append_paths(*paths)
|
135
138
|
end
|
136
139
|
|
140
|
+
def process_require_threadsafely(rel_path, autoloads, options)
|
141
|
+
return if prerequired.include?(rel_path)
|
142
|
+
|
143
|
+
autoload = autoloads.include? rel_path
|
144
|
+
|
145
|
+
source = stub?(rel_path) ? '' : read(rel_path, autoload)
|
146
|
+
|
147
|
+
# The handling is delegated to the runtime
|
148
|
+
return if source.nil?
|
149
|
+
|
150
|
+
abs_path = expand_path(rel_path)
|
151
|
+
rel_path = expand_ext(rel_path)
|
152
|
+
asset = processor_for(source, rel_path, abs_path, autoload, options.merge(requirable: true))
|
153
|
+
process_requires(
|
154
|
+
rel_path,
|
155
|
+
asset.requires + tree_requires(asset, abs_path),
|
156
|
+
asset.autoloads,
|
157
|
+
options
|
158
|
+
)
|
159
|
+
asset
|
160
|
+
end
|
161
|
+
|
162
|
+
def process_require(rel_path, autoloads, options)
|
163
|
+
return if already_processed.include?(rel_path)
|
164
|
+
already_processed << rel_path
|
165
|
+
asset = process_require_threadsafely(rel_path, autoloads, options)
|
166
|
+
processed << asset if asset
|
167
|
+
end
|
168
|
+
|
169
|
+
def already_processed
|
170
|
+
@already_processed ||= Set.new
|
171
|
+
end
|
172
|
+
|
137
173
|
include UseGem
|
138
174
|
|
139
175
|
attr_reader :processed
|
@@ -141,8 +177,26 @@ module Opal
|
|
141
177
|
attr_accessor :processors, :path_reader, :stubs, :prerequired, :preload,
|
142
178
|
:compiler_options, :missing_require_severity, :cache
|
143
179
|
|
180
|
+
def esm?
|
181
|
+
@compiler_options[:esm]
|
182
|
+
end
|
183
|
+
|
184
|
+
# Output extension, to be used by runners. At least Node.JS switches
|
185
|
+
# to ESM mode only if the extension is "mjs"
|
186
|
+
def output_extension
|
187
|
+
if esm?
|
188
|
+
'mjs'
|
189
|
+
else
|
190
|
+
'js'
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
144
194
|
private
|
145
195
|
|
196
|
+
def process_requires(rel_path, requires, autoloads, options)
|
197
|
+
@scheduler.process_requires(rel_path, requires, autoloads, options)
|
198
|
+
end
|
199
|
+
|
146
200
|
def tree_requires(asset, asset_path)
|
147
201
|
dirname = asset_path.to_s.empty? ? Pathname.pwd : Pathname(asset_path).expand_path.dirname
|
148
202
|
abs_base_paths = path_reader.paths.map { |p| File.expand_path(p) }
|
@@ -201,30 +255,6 @@ module Opal
|
|
201
255
|
end
|
202
256
|
end
|
203
257
|
|
204
|
-
def process_require(rel_path, autoloads, options)
|
205
|
-
return if prerequired.include?(rel_path)
|
206
|
-
return if already_processed.include?(rel_path)
|
207
|
-
already_processed << rel_path
|
208
|
-
|
209
|
-
autoload = autoloads.include? rel_path
|
210
|
-
|
211
|
-
source = stub?(rel_path) ? '' : read(rel_path, autoload)
|
212
|
-
|
213
|
-
# The handling is delegated to the runtime
|
214
|
-
return if source.nil?
|
215
|
-
|
216
|
-
abs_path = expand_path(rel_path)
|
217
|
-
rel_path = expand_ext(rel_path)
|
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
|
-
)
|
225
|
-
processed << asset
|
226
|
-
end
|
227
|
-
|
228
258
|
def expand_ext(path)
|
229
259
|
abs_path = path_reader.expand(path)
|
230
260
|
|
@@ -243,16 +273,6 @@ module Opal
|
|
243
273
|
(path_reader.expand(path) || File.expand_path(path)).to_s
|
244
274
|
end
|
245
275
|
|
246
|
-
def process_requires(rel_path, requires, autoloads, options)
|
247
|
-
requires.map { |r| process_require(r, autoloads, options) }
|
248
|
-
rescue MissingRequire => error
|
249
|
-
raise error, "A file required by #{rel_path.inspect} wasn't found.\n#{error.message}", error.backtrace
|
250
|
-
end
|
251
|
-
|
252
|
-
def already_processed
|
253
|
-
@already_processed ||= Set.new
|
254
|
-
end
|
255
|
-
|
256
276
|
def stub?(path)
|
257
277
|
stubs.include?(path)
|
258
278
|
end
|