opal 0.8.1 → 0.9.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -2
- data/.gitmodules +3 -3
- data/.jshintrc +17 -20
- data/.travis.yml +22 -11
- data/CHANGELOG.md +51 -1
- data/CODE_OF_CONDUCT.md +15 -0
- data/CONTRIBUTING.md +125 -9
- data/Gemfile +1 -1
- data/Guardfile +2 -2
- data/README.md +95 -29
- data/Rakefile +1 -1
- data/benchmark/benchmarks +103 -0
- data/benchmark/bm_array_flatten.rb +9 -0
- data/benchmark/bm_array_intersection_numbers.rb +7 -0
- data/benchmark/bm_array_intersection_objects.rb +7 -0
- data/benchmark/bm_array_intersection_strings.rb +7 -0
- data/benchmark/bm_array_join_ary.rb +9 -0
- data/benchmark/bm_array_minus_numbers.rb +7 -0
- data/benchmark/bm_array_minus_objects.rb +7 -0
- data/benchmark/bm_array_minus_strings.rb +7 -0
- data/benchmark/bm_array_union_numbers.rb +7 -0
- data/benchmark/bm_array_union_objects.rb +7 -0
- data/benchmark/bm_array_union_strings.rb +7 -0
- data/benchmark/bm_array_uniq_bang_numbers.rb +5 -0
- data/benchmark/bm_array_uniq_bang_objects.rb +5 -0
- data/benchmark/bm_array_uniq_bang_strings.rb +5 -0
- data/benchmark/bm_array_uniq_numbers.rb +5 -0
- data/benchmark/bm_array_uniq_objects.rb +5 -0
- data/benchmark/bm_array_uniq_strings.rb +5 -0
- data/benchmark/bm_dispatch_bind_table.rb +57 -0
- data/benchmark/bm_dispatch_code_gen.rb +65 -0
- data/benchmark/bm_dispatch_code_gen_if.rb +64 -0
- data/benchmark/bm_dispatch_hardcoded.rb +44 -0
- data/benchmark/bm_dispatch_send.rb +38 -0
- data/benchmark/bm_dispatch_send_table.rb +57 -0
- data/benchmark/bm_hash_assoc_object.rb +11 -0
- data/benchmark/bm_hash_assoc_string.rb +9 -0
- data/benchmark/bm_hash_clone_object.rb +9 -0
- data/benchmark/bm_hash_clone_string.rb +9 -0
- data/benchmark/bm_hash_delete_object.rb +11 -0
- data/benchmark/bm_hash_delete_string.rb +9 -0
- data/benchmark/bm_hash_each_key_object.rb +9 -0
- data/benchmark/bm_hash_each_key_string.rb +9 -0
- data/benchmark/bm_hash_each_object.rb +9 -0
- data/benchmark/bm_hash_each_string.rb +9 -0
- data/benchmark/bm_hash_each_value_object.rb +9 -0
- data/benchmark/bm_hash_each_value_string.rb +9 -0
- data/benchmark/bm_hash_element_reference_object.rb +11 -0
- data/benchmark/bm_hash_element_reference_string.rb +9 -0
- data/benchmark/bm_hash_element_set_object.rb +5 -0
- data/benchmark/bm_hash_element_set_string.rb +5 -0
- data/benchmark/bm_hash_equal_value_object.rb +14 -0
- data/benchmark/bm_hash_equal_value_string.rb +11 -0
- data/benchmark/bm_hash_fetch_object.rb +11 -0
- data/benchmark/bm_hash_fetch_string.rb +9 -0
- data/benchmark/bm_hash_flatten_object.rb +9 -0
- data/benchmark/bm_hash_flatten_string.rb +9 -0
- data/benchmark/bm_hash_has_key_object.rb +11 -0
- data/benchmark/bm_hash_has_key_string.rb +9 -0
- data/benchmark/bm_hash_has_value_object.rb +9 -0
- data/benchmark/bm_hash_has_value_string.rb +9 -0
- data/benchmark/bm_hash_hash_object.rb +9 -0
- data/benchmark/bm_hash_hash_string.rb +9 -0
- data/benchmark/bm_hash_inspect_object.rb +9 -0
- data/benchmark/bm_hash_inspect_string.rb +9 -0
- data/benchmark/bm_hash_invert_object.rb +9 -0
- data/benchmark/bm_hash_invert_string.rb +9 -0
- data/benchmark/bm_hash_keep_if_object.rb +9 -0
- data/benchmark/bm_hash_keep_if_string.rb +9 -0
- data/benchmark/bm_hash_key_object.rb +9 -0
- data/benchmark/bm_hash_key_string.rb +9 -0
- data/benchmark/bm_hash_keys_object.rb +9 -0
- data/benchmark/bm_hash_keys_string.rb +9 -0
- data/benchmark/bm_hash_literal_mixed_large.rb +3 -0
- data/benchmark/bm_hash_literal_mixed_small.rb +3 -0
- data/benchmark/bm_hash_literal_object_large.rb +4 -0
- data/benchmark/bm_hash_literal_object_small.rb +3 -0
- data/benchmark/bm_hash_literal_string_large.rb +4 -0
- data/benchmark/bm_hash_literal_string_small.rb +3 -0
- data/benchmark/bm_hash_merge_object.rb +22 -0
- data/benchmark/bm_hash_merge_string.rb +18 -0
- data/benchmark/bm_hash_rassoc_object.rb +9 -0
- data/benchmark/bm_hash_rassoc_string.rb +9 -0
- data/benchmark/bm_hash_rehash_object.rb +9 -0
- data/benchmark/bm_hash_rehash_string.rb +9 -0
- data/benchmark/bm_hash_reject_bang_object.rb +9 -0
- data/benchmark/bm_hash_reject_bang_string.rb +9 -0
- data/benchmark/bm_hash_reject_object.rb +9 -0
- data/benchmark/bm_hash_reject_string.rb +9 -0
- data/benchmark/bm_hash_replace_object.rb +18 -0
- data/benchmark/bm_hash_replace_string.rb +14 -0
- data/benchmark/bm_hash_select_bang_object.rb +9 -0
- data/benchmark/bm_hash_select_bang_string.rb +9 -0
- data/benchmark/bm_hash_select_object.rb +9 -0
- data/benchmark/bm_hash_select_string.rb +9 -0
- data/benchmark/bm_hash_shift_object.rb +10 -0
- data/benchmark/bm_hash_shift_string.rb +10 -0
- data/benchmark/bm_hash_to_a_object.rb +9 -0
- data/benchmark/bm_hash_to_a_string.rb +9 -0
- data/benchmark/bm_hash_to_h_object.rb +10 -0
- data/benchmark/bm_hash_to_h_string.rb +10 -0
- data/benchmark/bm_hash_values_object.rb +9 -0
- data/benchmark/bm_hash_values_string.rb +9 -0
- data/benchmark/run.rb +48 -0
- data/bin/opal-mspec +1 -1
- data/bin/opal-repl +4 -4
- data/docs/compiled_ruby.md +214 -56
- data/docs/configuring_gems.md +2 -2
- data/docs/faq.md +2 -2
- data/docs/getting_started.md +19 -2
- data/docs/jquery.md +5 -5
- data/docs/opal_parser.md +53 -0
- data/docs/unsupported_features.md +2 -2
- data/docs/upgrading.md +22 -0
- data/docs/using_sprockets.md +15 -0
- data/examples/rack/config.ru +13 -0
- data/examples/sinatra/config.ru +4 -5
- data/lib/mspec/opal/runner.rb +54 -11
- data/lib/opal.rb +1 -1
- data/lib/opal/builder.rb +1 -1
- data/lib/opal/builder_processors.rb +1 -1
- data/lib/opal/cli.rb +17 -13
- data/lib/opal/cli_options.rb +1 -1
- data/lib/opal/compiler.rb +12 -0
- data/lib/opal/config.rb +4 -0
- data/lib/opal/nodes/arglist.rb +5 -7
- data/lib/opal/nodes/call.rb +6 -1
- data/lib/opal/nodes/call_special.rb +74 -0
- data/lib/opal/nodes/def.rb +35 -28
- data/lib/opal/nodes/definitions.rb +3 -5
- data/lib/opal/nodes/for.rb +13 -0
- data/lib/opal/nodes/helpers.rb +15 -1
- data/lib/opal/nodes/if.rb +5 -5
- data/lib/opal/nodes/iter.rb +6 -1
- data/lib/opal/nodes/literal.rb +1 -1
- data/lib/opal/nodes/logic.rb +2 -2
- data/lib/opal/nodes/masgn.rb +1 -2
- data/lib/opal/nodes/module.rb +2 -1
- data/lib/opal/nodes/rescue.rb +10 -1
- data/lib/opal/nodes/scope.rb +8 -2
- data/lib/opal/nodes/singleton_class.rb +1 -1
- data/lib/opal/nodes/top.rb +11 -0
- data/lib/opal/nodes/variables.rb +4 -4
- data/lib/opal/parser.rb +21 -3
- data/lib/opal/parser/grammar.rb +3115 -2961
- data/lib/opal/parser/grammar.y +29 -6
- data/lib/opal/parser/lexer.rb +18 -8
- data/lib/opal/sprockets.rb +85 -0
- data/lib/opal/sprockets/processor.rb +11 -35
- data/lib/opal/sprockets/server.rb +3 -15
- data/lib/opal/version.rb +2 -2
- data/opal.gemspec +4 -4
- data/opal/README.md +9 -0
- data/opal/corelib/array.rb +433 -181
- data/opal/corelib/basic_object.rb +48 -4
- data/opal/corelib/boolean.rb +15 -6
- data/opal/corelib/class.rb +6 -5
- data/opal/corelib/comparable.rb +12 -0
- data/opal/corelib/complex.rb +282 -0
- data/opal/corelib/constants.rb +9 -0
- data/opal/corelib/enumerable.rb +83 -34
- data/opal/corelib/enumerator.rb +3 -1
- data/opal/corelib/error.rb +49 -10
- data/opal/corelib/file.rb +1 -0
- data/opal/corelib/hash.rb +353 -577
- data/opal/corelib/helpers.rb +20 -0
- data/opal/corelib/kernel.rb +114 -59
- data/opal/corelib/math.rb +470 -0
- data/opal/corelib/method.rb +11 -2
- data/opal/corelib/module.rb +96 -96
- data/opal/corelib/{nil_class.rb → nil.rb} +20 -1
- data/opal/corelib/number.rb +751 -0
- data/opal/corelib/numeric.rb +77 -437
- data/opal/corelib/proc.rb +81 -1
- data/opal/corelib/process.rb +27 -0
- data/opal/corelib/rational.rb +358 -0
- data/opal/corelib/regexp.rb +156 -27
- data/opal/corelib/runtime.js +724 -335
- data/opal/corelib/string.rb +93 -104
- data/opal/corelib/string/encoding.rb +177 -0
- data/opal/corelib/string/inheritance.rb +2 -0
- data/opal/corelib/struct.rb +105 -18
- data/opal/corelib/time.rb +267 -146
- data/opal/corelib/unsupported.rb +216 -0
- data/opal/corelib/variables.rb +0 -6
- data/opal/opal.rb +8 -22
- data/opal/opal/base.rb +9 -0
- data/opal/opal/mini.rb +17 -0
- data/spec/README.md +1 -1
- data/spec/filters/bugs/array.rb +38 -136
- data/spec/filters/bugs/{basic_object.rb → basicobject.rb} +14 -15
- data/spec/filters/bugs/class.rb +6 -12
- data/spec/filters/bugs/complex.rb +3 -0
- data/spec/filters/bugs/date.rb +162 -10
- data/spec/filters/bugs/enumerable.rb +31 -58
- data/spec/filters/bugs/enumerator.rb +42 -0
- data/spec/filters/bugs/exception.rb +66 -10
- data/spec/filters/bugs/float.rb +17 -0
- data/spec/filters/bugs/hash.rb +11 -97
- data/spec/filters/bugs/inheritance.rb +5 -0
- data/spec/filters/bugs/integer.rb +28 -0
- data/spec/filters/bugs/kernel.rb +304 -12
- data/spec/filters/bugs/language.rb +133 -399
- data/spec/filters/bugs/language_opal.rb +88 -0
- data/spec/filters/bugs/module.rb +203 -62
- data/spec/filters/bugs/numeric.rb +32 -0
- data/spec/filters/bugs/proc.rb +39 -0
- data/spec/filters/bugs/range.rb +148 -0
- data/spec/filters/bugs/regexp.rb +168 -0
- data/spec/filters/bugs/set.rb +46 -3
- data/spec/filters/bugs/singleton.rb +1 -2
- data/spec/filters/bugs/string.rb +59 -90
- data/spec/filters/bugs/strscan.rb +80 -0
- data/spec/filters/bugs/struct.rb +10 -20
- data/spec/filters/bugs/time.rb +17 -184
- data/spec/filters/bugs/unboundmethod.rb +22 -0
- data/spec/filters/unsupported/array.rb +163 -0
- data/spec/filters/unsupported/basicobject.rb +14 -0
- data/spec/filters/unsupported/bignum.rb +46 -0
- data/spec/filters/unsupported/class.rb +4 -0
- data/spec/filters/unsupported/delegator.rb +5 -0
- data/spec/filters/unsupported/enumerable.rb +11 -0
- data/spec/filters/unsupported/enumerator.rb +8 -9
- data/spec/filters/unsupported/fixnum.rb +14 -0
- data/spec/filters/unsupported/float.rb +41 -7
- data/spec/filters/unsupported/freeze.rb +45 -0
- data/spec/filters/unsupported/hash.rb +50 -0
- data/spec/filters/unsupported/integer.rb +3 -0
- data/spec/filters/unsupported/kernel.rb +31 -0
- data/spec/filters/unsupported/language.rb +17 -0
- data/spec/filters/unsupported/matchdata.rb +30 -0
- data/spec/filters/unsupported/math.rb +3 -0
- data/spec/filters/unsupported/module.rb +5 -3
- data/spec/filters/unsupported/pathname.rb +3 -0
- data/spec/filters/unsupported/privacy.rb +136 -0
- data/spec/filters/unsupported/proc.rb +3 -0
- data/spec/filters/unsupported/regexp.rb +59 -0
- data/spec/filters/unsupported/set.rb +4 -0
- data/spec/filters/unsupported/{marshal.rb → singleton.rb} +4 -2
- data/spec/filters/unsupported/{mutable_strings.rb → string.rb} +456 -336
- data/spec/filters/unsupported/struct.rb +3 -0
- data/spec/filters/unsupported/symbol.rb +5 -0
- data/spec/filters/unsupported/taint.rb +16 -0
- data/spec/filters/unsupported/thread.rb +5 -0
- data/spec/filters/unsupported/time.rb +197 -16
- data/spec/lib/cli_spec.rb +14 -4
- data/spec/lib/compiler_spec.rb +9 -1
- data/spec/lib/parser/call_spec.rb +18 -0
- data/spec/lib/parser/not_spec.rb +2 -8
- data/spec/lib/sprockets_spec.rb +24 -0
- data/spec/opal/core/array/intersection_spec.rb +38 -0
- data/spec/opal/core/array/minus_spec.rb +38 -0
- data/spec/opal/core/array/union_spec.rb +38 -0
- data/spec/opal/core/array/uniq_spec.rb +49 -0
- data/spec/opal/core/exception_spec.rb +7 -0
- data/spec/opal/core/fixtures/require_tree_with_dot/file 1.rb +1 -0
- data/spec/opal/core/fixtures/require_tree_with_dot/file 2.rb +1 -0
- data/spec/opal/core/fixtures/require_tree_with_dot/file 3.rb +1 -0
- data/spec/opal/core/fixtures/require_tree_with_dot/index.rb +3 -0
- data/spec/opal/core/hash/internals_spec.rb +332 -0
- data/spec/opal/core/helpers_spec.rb +14 -0
- data/spec/opal/core/kernel/freeze_spec.rb +1 -1
- data/spec/opal/core/kernel/raise_spec.rb +13 -0
- data/spec/opal/core/kernel/require_tree_spec.rb +9 -0
- data/spec/opal/core/language/class_spec.rb +55 -0
- data/spec/opal/core/language/fixtures/send.rb +1 -0
- data/spec/opal/core/language/keyword_arguments_spec.rb +11 -0
- data/spec/opal/core/language/send_spec.rb +5 -0
- data/spec/opal/core/method/to_proc_spec.rb +28 -0
- data/spec/opal/core/module/name_spec.rb +0 -17
- data/spec/opal/core/runtime/bridged_classes_spec.rb +2 -2
- data/spec/opal/core/runtime/eval_spec.rb +1 -1
- data/spec/opal/core/runtime/method_missing_spec.rb +6 -0
- data/spec/opal/core/runtime_spec.rb +51 -0
- data/spec/opal/stdlib/js_spec.rb +66 -0
- data/spec/opal/stdlib/native/hash_spec.rb +36 -0
- data/spec/rubyspecs +152 -273
- data/spec/spec_helper.rb +10 -11
- data/stdlib/base64.rb +9 -9
- data/stdlib/benchmark.rb +551 -4
- data/stdlib/console.rb +94 -0
- data/stdlib/date.rb +1 -1
- data/stdlib/encoding.rb +1 -170
- data/stdlib/js.rb +56 -0
- data/stdlib/json.rb +9 -14
- data/stdlib/math.rb +1 -370
- data/stdlib/native.rb +133 -63
- data/stdlib/nodejs/file.rb +5 -0
- data/stdlib/nodejs/fileutils.rb +13 -6
- data/stdlib/nodejs/node_modules/js-yaml/node_modules/argparse/README.md +1 -1
- data/stdlib/opal-parser.rb +1 -2
- data/stdlib/ostruct.rb +65 -6
- data/stdlib/pp.rb +2 -4
- data/stdlib/rbconfig.rb +1 -3
- data/stdlib/strscan.rb +164 -28
- data/tasks/benchmarking.rake +88 -0
- data/tasks/testing.rake +181 -55
- data/{lib/mspec/opal/special_calls.rb → tasks/testing/mspec_special_calls.rb} +1 -1
- data/{lib/mspec/opal/sprockets.js → tasks/testing/phantomjs1-sprockets.js} +17 -6
- data/test/opal/test_keyword.rb +590 -0
- data/vendored-minitest/minitest.rb +2 -2
- data/vendored-minitest/test/unit.rb +5 -0
- metadata +229 -62
- data/benchmarks/operators.rb +0 -11
- data/benchmarks/prova.js.rb +0 -13
- data/docs/libraries.md +0 -36
- data/lib/mspec/opal/new.html.erb +0 -1
- data/lib/mspec/opal/rake_task.rb +0 -248
- data/opal/corelib/match_data.rb +0 -128
- data/spec/filters/bugs/math.rb +0 -95
- data/spec/filters/bugs/nil.rb +0 -7
- data/spec/filters/bugs/opal.rb +0 -9
- data/spec/filters/bugs/regular_expressions.rb +0 -41
- data/spec/filters/bugs/stringscanner.rb +0 -33
- data/spec/filters/unsupported/encoding.rb +0 -102
- data/spec/filters/unsupported/frozen.rb +0 -92
- data/spec/filters/unsupported/hash_compare_by_identity.rb +0 -16
- data/spec/filters/unsupported/integer_size.rb +0 -59
- data/spec/filters/unsupported/method_added.rb +0 -10
- data/spec/filters/unsupported/private_constants.rb +0 -30
- data/spec/filters/unsupported/private_methods.rb +0 -55
- data/spec/filters/unsupported/random.rb +0 -4
- data/spec/filters/unsupported/rational_numbers.rb +0 -4
- data/spec/filters/unsupported/regular_expressions.rb +0 -137
- data/spec/filters/unsupported/ruby_exe.rb +0 -5
- data/spec/filters/unsupported/symbols.rb +0 -17
- data/spec/filters/unsupported/tainted.rb +0 -180
- data/spec/filters/unsupported/trusted.rb +0 -88
- data/stdlib/process.rb +0 -10
- data/tasks/documenting.rake +0 -37
data/docs/configuring_gems.md
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
|
3
3
|
To configure a gem to run in Opal the gem will need a couple of things:
|
4
4
|
|
5
|
-
1. The opal gem running on a server (so the ruby code can get compiled to .
|
6
|
-
2. The
|
5
|
+
1. The opal gem running on a server (so the ruby code can get compiled to JavaScript).
|
6
|
+
2. The Opal search path has to know to look for your gem when it is required.
|
7
7
|
|
8
8
|
This is done by having the following 2 lines in your outermost .rb file:
|
9
9
|
|
data/docs/faq.md
CHANGED
@@ -6,7 +6,7 @@ To try and keep ruby relevant in a world where client-side apps are making javas
|
|
6
6
|
|
7
7
|
### How compatible is Opal?
|
8
8
|
|
9
|
-
We run opal against [rubyspec](https://github.com/rubyspec/rubyspec) as our primary testing setup. We try to make Opal as compatible as possible, whilst also taking into account restrictions of
|
9
|
+
We run opal against [rubyspec](https://github.com/rubyspec/rubyspec) 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.
|
10
10
|
|
11
11
|
### What version of ruby does Opal target?
|
12
12
|
|
@@ -14,4 +14,4 @@ We are running tests under ruby 2.0.0 conditions, but are mostly compatible with
|
|
14
14
|
|
15
15
|
### Why doesn't Opal support mutable strings?
|
16
16
|
|
17
|
-
All strings in Opal are immutable because ruby strings just get compiled direclty into javascript strings, which are immutable. Wrapping ruby strings as a custom
|
17
|
+
All strings in Opal are immutable because ruby strings just get compiled direclty 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/getting_started.md
CHANGED
@@ -25,6 +25,23 @@ Opal.compile("[1, 2, 3].each { |a| puts a }")
|
|
25
25
|
# => "(function() { ... })()"
|
26
26
|
```
|
27
27
|
|
28
|
-
`opal` includes sprockets support
|
28
|
+
`opal` includes sprockets support for compiling Ruby (and ERB) assets, and treating them as first class JavaScript citizens. It works in a similar way to CoffeeScript, where JavaScript files can simply require Ruby sources, and Ruby sources can require JavaScript and other Ruby files.
|
29
|
+
|
30
|
+
This relies on the Opal load path. Any gem containing opal code registers that directory to the Opal load path. Opal will then use all Opal load paths when running sprockets instances. For rails applications, `opal-rails` does this automatically. For building a simple application, we have to do this manually.
|
31
|
+
|
32
|
+
|
33
|
+
### Adding lookup paths
|
34
|
+
|
35
|
+
Opal uses a load path which works with sprockets to create a set of locations which opal can require files
|
36
|
+
from. If you want to add a directory to this load path, you can add it to the global environment.
|
37
|
+
|
38
|
+
In the `Opal` module, a property `paths` is used to hold the load paths which
|
39
|
+
`Opal` uses to require files from. You can add a directory to this:
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
Opal.append_path '../my_lib'
|
43
|
+
```
|
44
|
+
|
45
|
+
Now, any ruby files in this directory can be discovered.
|
46
|
+
|
29
47
|
|
30
|
-
This relies on the opal load path. Any gem containing opal code registers that directory to the opal load path. opal will then use all opal load paths when running sprockets instances. For rails applications, opal-rails does this automatically. For building a simple application, we have to do this manually.
|
data/docs/jquery.md
CHANGED
@@ -42,11 +42,11 @@ require 'opal-jquery'
|
|
42
42
|
alert "Hello from jquery + opal"
|
43
43
|
```
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
NOTE: this file requires two important dependencies, `jquery` and `opal-jquery`.
|
46
|
+
You need to bring your own `jquery.js` file as the gem does not include one. If
|
47
|
+
you are using the asset pipeline with rails, then this should be available
|
48
|
+
already, otherwise download a copy and place it into `app/` or whichever directory
|
49
|
+
you are compiling assets from. You can alternatively require a zepto instance.
|
50
50
|
|
51
51
|
The `#alert` method is provided by `opal-jquery`. If the message displays, then
|
52
52
|
`jquery` support should be working.
|
data/docs/opal_parser.md
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
# Parsing Ruby from JavaScript with `opal-parser`
|
2
|
+
|
3
|
+
Generally is best to precompile Ruby source files to JavaScript server-side but sometimes may become useful to be able to compile Ruby to JavaScript directly from JS.
|
4
|
+
|
5
|
+
Opal is able to compile its – pure Ruby – compiler to JavaScript (how cool is that!). The whole compiler chain is available in the `stdlib` as `opal-parser`.
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
require 'opal-parser'
|
9
|
+
```
|
10
|
+
|
11
|
+
|
12
|
+
## Features
|
13
|
+
|
14
|
+
### `Kernel#eval`
|
15
|
+
|
16
|
+
`opal-parser` provides a partial implementation of `Kernel#eval` that only support the first parameter (String) and refuse any passed `binding`, `lineno` or `filename`.
|
17
|
+
|
18
|
+
Example:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
require 'opal-parser'
|
22
|
+
eval "puts 'hello world!'"
|
23
|
+
```
|
24
|
+
|
25
|
+
|
26
|
+
### `Kernel#require_remote`
|
27
|
+
|
28
|
+
Will fetch a remote URL (by means of a sync `XMLHttpRequest`) and evaluate its contents as Ruby code.
|
29
|
+
|
30
|
+
Example:
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require 'opal-parser'
|
34
|
+
require_remote 'http://pastie.org/pastes/10444960/text'
|
35
|
+
HelloWorld.new.say_hello!
|
36
|
+
```
|
37
|
+
|
38
|
+
|
39
|
+
### `Opal.compile()` and `Opal.eval()` (JavaScript)
|
40
|
+
|
41
|
+
After requiring `opal-parser` both `Opal.compile()` and `Opal.eval()` functions are added to the JavaScript API.
|
42
|
+
|
43
|
+
`Opal.compile(string, options)` (JavaScript) will forward the call to `Opal.compile` (Ruby) converting options from a plain JS object to a Ruby Hash.
|
44
|
+
`Opal.eval(string)` will compile the given code to JavaScript and then pass it to the [native `eval()` function][eval].
|
45
|
+
|
46
|
+
|
47
|
+
### Support for `<script type="text/ruby">`
|
48
|
+
|
49
|
+
When `opal-parser` is required it will search the page for any `<script>` tag with type `text/ruby`.
|
50
|
+
If an `src` attribute is present will fetch and eval the file with `Kernel#require_remote` otherwise it will get the script tags contents and eval them with `Kernel#eval`.
|
51
|
+
|
52
|
+
|
53
|
+
[eval]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
|
@@ -12,11 +12,11 @@ Encodings only have a very small implementation inside Opal.
|
|
12
12
|
|
13
13
|
#### Threads ####
|
14
14
|
|
15
|
-
|
15
|
+
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.
|
16
16
|
|
17
17
|
#### Frozen Objects ####
|
18
18
|
|
19
|
-
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
|
19
|
+
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.
|
20
20
|
|
21
21
|
#### `method_added` and `method_removed` hooks ####
|
22
22
|
|
data/docs/upgrading.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Upgrading from v0.8 to v0.9
|
2
|
+
|
3
|
+
## `Opal::Processor.load_asset_code` deprecated
|
4
|
+
|
5
|
+
`Opal::Processor.load_asset_code(sprockets, name)` has been deprecated in favor of `Opal::Sprockets.load_asset(name, sprockets)`.
|
6
|
+
|
7
|
+
## `$console.log` instead of `pp`
|
8
|
+
|
9
|
+
Previously `pp` would have forwarded the object to JS own `console.log` but now just prints calling `.inspect` on it similarly to what `p` does.
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'pp'
|
13
|
+
pp a: 1, b: {c: 3}
|
14
|
+
```
|
15
|
+
|
16
|
+
Now:
|
17
|
+
|
18
|
+
```ruby
|
19
|
+
require 'console'
|
20
|
+
$console.log a: 1, b: {c: 3}
|
21
|
+
```
|
22
|
+
|
data/docs/using_sprockets.md
CHANGED
@@ -70,3 +70,18 @@ Run `bundle exec rackup` and visit the page `http://localhost:9292` in any
|
|
70
70
|
browser. Observe the console to see the printed statement.
|
71
71
|
|
72
72
|
You can just change `app/application.rb` and refresh the page to see any changes.
|
73
|
+
|
74
|
+
|
75
|
+
## Using an existing `sprockets` instance
|
76
|
+
|
77
|
+
We only need to append Opal paths to the existing sprockets instance.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
require 'sprockets'
|
81
|
+
environment = Sprockets::Environment.new
|
82
|
+
|
83
|
+
require 'opal'
|
84
|
+
Opal.paths.each do |path|
|
85
|
+
environment.append_path path
|
86
|
+
end
|
87
|
+
```
|
data/examples/rack/config.ru
CHANGED
@@ -1,7 +1,20 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
Bundler.require
|
3
3
|
|
4
|
+
# Instructions: bundle in this directory
|
5
|
+
# then run bundle exec rackup to start the server
|
6
|
+
# and browse to 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
|
+
|
4
13
|
run Opal::Server.new { |s|
|
14
|
+
# the name of the ruby file to load. To use more files they must be required from here (see app)
|
5
15
|
s.main = 'application'
|
16
|
+
# the directory where the code is (add to opal load path )
|
6
17
|
s.append_path 'app'
|
18
|
+
# need to set the index explicitly for opal server to pick it up
|
19
|
+
s.index_path = 'index.html.erb'
|
7
20
|
}
|
data/examples/sinatra/config.ru
CHANGED
@@ -7,6 +7,7 @@ opal = Opal::Server.new {|s|
|
|
7
7
|
}
|
8
8
|
|
9
9
|
sprockets = opal.sprockets
|
10
|
+
prefix = '/assets'
|
10
11
|
maps_prefix = '/__OPAL_SOURCE_MAPS__'
|
11
12
|
maps_app = Opal::SourceMapServer.new(sprockets, maps_prefix)
|
12
13
|
|
@@ -17,19 +18,17 @@ map maps_prefix do
|
|
17
18
|
run maps_app
|
18
19
|
end
|
19
20
|
|
20
|
-
map
|
21
|
+
map prefix do
|
21
22
|
run sprockets
|
22
23
|
end
|
23
24
|
|
24
25
|
get '/' do
|
25
|
-
opal_boot_code = Opal::Processor.load_asset_code(sprockets, 'application')
|
26
|
-
|
27
26
|
<<-HTML
|
28
27
|
<!doctype html>
|
29
28
|
<html>
|
30
29
|
<head>
|
31
|
-
<
|
32
|
-
|
30
|
+
<meta charset="utf-8">
|
31
|
+
#{::Opal::Sprockets.javascript_include_tag('application', sprockets: sprockets, prefix: prefix, debug: true)}
|
33
32
|
</head>
|
34
33
|
</html>
|
35
34
|
HTML
|
data/lib/mspec/opal/runner.rb
CHANGED
@@ -5,6 +5,7 @@ class OSpecFilter
|
|
5
5
|
|
6
6
|
def initialize
|
7
7
|
@filters = Set.new
|
8
|
+
@seen = Set.new
|
8
9
|
end
|
9
10
|
|
10
11
|
def register
|
@@ -12,6 +13,7 @@ class OSpecFilter
|
|
12
13
|
end
|
13
14
|
|
14
15
|
def ===(description)
|
16
|
+
@seen << description
|
15
17
|
@filters.include? description
|
16
18
|
end
|
17
19
|
|
@@ -22,12 +24,58 @@ class OSpecFilter
|
|
22
24
|
def fails(description)
|
23
25
|
@filters << description
|
24
26
|
end
|
27
|
+
|
28
|
+
def unused_filters_message(list: false)
|
29
|
+
unused = @filters - @seen
|
30
|
+
return if unused.size == 0
|
31
|
+
|
32
|
+
if list
|
33
|
+
puts
|
34
|
+
puts "Unused filters:"
|
35
|
+
unused.each {|u| puts "- #{u}"}
|
36
|
+
puts
|
37
|
+
else
|
38
|
+
warn "\nThere are #{unused.size} unused filters, re-run with ENV['LIST_UNUSED_FILTERS'] = true to list them\n\n"
|
39
|
+
end
|
40
|
+
end
|
25
41
|
end
|
26
42
|
|
27
43
|
class Object
|
28
44
|
def opal_filter(description, &block)
|
29
45
|
OSpecFilter.main.register_filters(description, block)
|
30
46
|
end
|
47
|
+
|
48
|
+
# Copyed from MSpec, with changes.
|
49
|
+
def with_timezone(name, offset = nil, daylight_saving_zone = "")
|
50
|
+
zone = name.dup
|
51
|
+
|
52
|
+
if offset
|
53
|
+
# TZ convention is backwards
|
54
|
+
offset = -offset
|
55
|
+
|
56
|
+
zone += offset.to_s
|
57
|
+
zone += ":00:00"
|
58
|
+
end
|
59
|
+
zone += daylight_saving_zone
|
60
|
+
|
61
|
+
# WAS:
|
62
|
+
#
|
63
|
+
# old = ENV["TZ"]
|
64
|
+
# ENV["TZ"] = zone
|
65
|
+
#
|
66
|
+
# begin
|
67
|
+
# yield
|
68
|
+
# ensure
|
69
|
+
# ENV["TZ"] = old
|
70
|
+
# end
|
71
|
+
#
|
72
|
+
if ENV["TZ"] == zone
|
73
|
+
yield
|
74
|
+
else
|
75
|
+
1.should == 1 # MSpec will get mad if the example has no expectations.
|
76
|
+
warn "Skipped spec for TZ=#{zone} as it's not supported"
|
77
|
+
end
|
78
|
+
end
|
31
79
|
end
|
32
80
|
|
33
81
|
class BrowserFormatter
|
@@ -171,10 +219,6 @@ class NodeJSFormatter < BrowserFormatter
|
|
171
219
|
end
|
172
220
|
end
|
173
221
|
|
174
|
-
def finish_with_code(code)
|
175
|
-
`global.OPAL_SPEC_CODE = code;`
|
176
|
-
end
|
177
|
-
|
178
222
|
def finish_with_code(code)
|
179
223
|
puts "\n\n"
|
180
224
|
exit(code)
|
@@ -227,9 +271,10 @@ class OSpecRunner
|
|
227
271
|
MSpec.actions :start
|
228
272
|
end
|
229
273
|
|
230
|
-
def bm!(repeat)
|
274
|
+
def bm!(repeat, bm_filepath)
|
231
275
|
`self.bm = {}`
|
232
|
-
|
276
|
+
`self.bm_filepath = bm_filepath`
|
277
|
+
MSpec.repeat = repeat
|
233
278
|
MSpec.register :before, self
|
234
279
|
MSpec.register :after, self
|
235
280
|
end
|
@@ -252,17 +297,15 @@ class OSpecRunner
|
|
252
297
|
|
253
298
|
def did_finish
|
254
299
|
%x{
|
255
|
-
var obj = self.bm, key, val,
|
300
|
+
var obj = self.bm, key, val, report = '';
|
256
301
|
if (obj) {
|
257
302
|
for (key in obj) {
|
258
303
|
if (obj.hasOwnProperty(key)) {
|
259
304
|
val = obj[key];
|
260
|
-
|
305
|
+
report += key.replace(/\s/g, '_') + ' ' + ((val.stopped - val.started) / 1000) + '\n';
|
261
306
|
}
|
262
307
|
}
|
263
|
-
|
264
|
-
file = #{Time.now.strftime('tmp/bm_%Y-%m-%d_%H-%M-%S-%L.json')};
|
265
|
-
#{File.open(`file`, 'w') {|f| f.write(`json`)}}
|
308
|
+
require('fs').writeFileSync(self.bm_filepath, report);
|
266
309
|
}
|
267
310
|
}
|
268
311
|
MSpec.actions :finish
|
data/lib/opal.rb
CHANGED
data/lib/opal/builder.rb
CHANGED
@@ -143,7 +143,7 @@ module Opal
|
|
143
143
|
def process_requires(filename, requires, options)
|
144
144
|
requires.map { |r| process_require(r, options) }
|
145
145
|
rescue MissingRequire => error
|
146
|
-
raise error, "A file required by #{filename.inspect} wasn't found.\n#{error.message}"
|
146
|
+
raise error, "A file required by #{filename.inspect} wasn't found.\n#{error.message}", error.backtrace
|
147
147
|
end
|
148
148
|
|
149
149
|
def already_processed
|
data/lib/opal/cli.rb
CHANGED
@@ -105,12 +105,8 @@ module Opal
|
|
105
105
|
builder.build(local_require)
|
106
106
|
end
|
107
107
|
|
108
|
-
|
109
|
-
builder.build_str(
|
110
|
-
else
|
111
|
-
if file and (filename != '-' or evals.empty?)
|
112
|
-
builder.build_str(file.read, filename)
|
113
|
-
end
|
108
|
+
evals_or_file do |contents, filename|
|
109
|
+
builder.build_str(contents, filename)
|
114
110
|
end
|
115
111
|
|
116
112
|
builder.build_str 'Kernel.exit', '(exit)' unless no_exit
|
@@ -127,14 +123,10 @@ module Opal
|
|
127
123
|
end
|
128
124
|
|
129
125
|
def show_sexp
|
130
|
-
|
131
|
-
sexp = Opal::Parser.new.parse(
|
132
|
-
|
133
|
-
if file and (file.path != '-' or evals.empty?)
|
134
|
-
sexp = Opal::Parser.new.parse(file.read, file.path)
|
135
|
-
end
|
126
|
+
evals_or_file do |contents, filename|
|
127
|
+
sexp = Opal::Parser.new.parse(contents, filename)
|
128
|
+
puts sexp.inspect
|
136
129
|
end
|
137
|
-
puts sexp.inspect
|
138
130
|
end
|
139
131
|
|
140
132
|
def map
|
@@ -154,6 +146,18 @@ module Opal
|
|
154
146
|
]
|
155
147
|
end
|
156
148
|
|
149
|
+
# Internal: Yelds a string of source code and the proper filename for either
|
150
|
+
# evals, stdin or a filepath.
|
151
|
+
def evals_or_file
|
152
|
+
if evals.any?
|
153
|
+
yield evals.join("\n"), '-e'
|
154
|
+
else
|
155
|
+
if file and (filename != '-' or evals.empty?)
|
156
|
+
yield file.read, filename
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
157
161
|
def puts(*args)
|
158
162
|
output.puts(*args)
|
159
163
|
end
|
data/lib/opal/cli_options.rb
CHANGED
@@ -119,7 +119,7 @@ module Opal
|
|
119
119
|
dynamic_require_levels = %w[error warning ignore]
|
120
120
|
on('-D', '--dynamic-require LEVEL', dynamic_require_levels,
|
121
121
|
'Set level of dynamic require severity.',
|
122
|
-
"(
|
122
|
+
"(default: error, values: #{dynamic_require_levels.join(', ')})") do |level|
|
123
123
|
options[:dynamic_require_severity] = level.to_sym
|
124
124
|
end
|
125
125
|
|