opal 0.8.1 → 0.9.0.beta1
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.
- 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/lib/opal/parser/grammar.y
CHANGED
@@ -8,14 +8,14 @@ token kCLASS kMODULE kDEF kUNDEF kBEGIN kRESCUE kENSURE kEND kIF kUNLESS
|
|
8
8
|
k__FILE__ k__ENCODING__ tIDENTIFIER tFID tGVAR tIVAR tCONSTANT
|
9
9
|
tLABEL tCVAR tNTH_REF tBACK_REF tSTRING_CONTENT tINTEGER tFLOAT
|
10
10
|
tREGEXP_END tUPLUS tUMINUS tUMINUS_NUM tPOW tCMP tEQ tEQQ tNEQ tGEQ tLEQ tANDOP
|
11
|
-
tOROP tMATCH tNMATCH tDOT tDOT2 tDOT3 tAREF tASET tLSHFT tRSHFT
|
11
|
+
tOROP tMATCH tNMATCH tJSDOT tDOT tDOT2 tDOT3 tAREF tASET tLSHFT tRSHFT
|
12
12
|
tCOLON2 tCOLON3 tOP_ASGN tASSOC tLPAREN tLPAREN2 tRPAREN tLPAREN_ARG
|
13
13
|
ARRAY_BEG tRBRACK tLBRACE tLBRACE_ARG tSTAR tSTAR2 tAMPER tAMPER2
|
14
14
|
tTILDE tPERCENT tDIVIDE tPLUS tMINUS tLT tGT tPIPE tBANG tCARET
|
15
15
|
tLCURLY tRCURLY tBACK_REF2 tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG
|
16
16
|
tWORDS_BEG tAWORDS_BEG tSTRING_DBEG tSTRING_DVAR tSTRING_END tSTRING
|
17
17
|
tSYMBOL tNL tEH tCOLON tCOMMA tSPACE tSEMI tLAMBDA tLAMBEG
|
18
|
-
tLBRACK2 tLBRACK tDSTAR
|
18
|
+
tLBRACK2 tLBRACK tJSLBRACK tDSTAR
|
19
19
|
|
20
20
|
prechigh
|
21
21
|
right tBANG tTILDE tUPLUS
|
@@ -150,6 +150,7 @@ rule
|
|
150
150
|
result = new_op_asgn val[1], val[0], val[2]
|
151
151
|
}
|
152
152
|
| primary_value tLBRACK2 aref_args tRBRACK tOP_ASGN command_call
|
153
|
+
| primary_value tJSLBRACK aref_args tRBRACK tOP_ASGN command_call
|
153
154
|
| primary_value tDOT tIDENTIFIER tOP_ASGN command_call
|
154
155
|
{
|
155
156
|
result = s(:op_asgn2, val[0], op_to_setter(val[2]), value(val[3]).to_sym, val[4])
|
@@ -208,6 +209,7 @@ rule
|
|
208
209
|
}
|
209
210
|
|
210
211
|
block_command: block_call
|
212
|
+
| block_call tJSDOT operation2 command_args
|
211
213
|
| block_call tDOT operation2 command_args
|
212
214
|
| block_call tCOLON2 operation2 command_args
|
213
215
|
|
@@ -218,6 +220,11 @@ rule
|
|
218
220
|
result = new_call(nil, val[0], val[1])
|
219
221
|
}
|
220
222
|
| operation command_args cmd_brace_block
|
223
|
+
| primary_value tJSDOT operation2 command_args =tLOWEST
|
224
|
+
{
|
225
|
+
result = new_js_call(val[0], val[2], val[3])
|
226
|
+
}
|
227
|
+
| primary_value tJSDOT operation2 command_args cmd_brace_block
|
221
228
|
| primary_value tDOT operation2 command_args =tLOWEST
|
222
229
|
{
|
223
230
|
result = new_call(val[0], val[2], val[3])
|
@@ -327,6 +334,10 @@ rule
|
|
327
334
|
{
|
328
335
|
result = new_assignable val[0]
|
329
336
|
}
|
337
|
+
| primary_value tJSLBRACK aref_args tRBRACK
|
338
|
+
{
|
339
|
+
result = new_js_attrasgn(val[0], val[2])
|
340
|
+
}
|
330
341
|
| primary_value tLBRACK2 aref_args tRBRACK
|
331
342
|
{
|
332
343
|
result = new_attrasgn(val[0], :[]=, val[2])
|
@@ -428,6 +439,10 @@ rule
|
|
428
439
|
{
|
429
440
|
result = new_op_asgn1(val[0], val[2], val[4], val[5])
|
430
441
|
}
|
442
|
+
| primary_value tJSLBRACK aref_args tRBRACK tOP_ASGN arg
|
443
|
+
{
|
444
|
+
raise ".JS[...] #{val[4]} is not supported"
|
445
|
+
}
|
431
446
|
| primary_value tDOT tIDENTIFIER tOP_ASGN arg
|
432
447
|
{
|
433
448
|
result = s(:op_asgn2, val[0], op_to_setter(val[2]), value(val[3]).to_sym, val[4])
|
@@ -537,8 +552,7 @@ rule
|
|
537
552
|
}
|
538
553
|
| arg tNEQ arg
|
539
554
|
{
|
540
|
-
result =
|
541
|
-
val[0], ['==', []], val[2]))
|
555
|
+
result = new_binary_call(val[0], val[1], val[2])
|
542
556
|
}
|
543
557
|
| arg tMATCH arg
|
544
558
|
{
|
@@ -546,8 +560,7 @@ rule
|
|
546
560
|
}
|
547
561
|
| arg tNMATCH arg
|
548
562
|
{
|
549
|
-
result =
|
550
|
-
val[0], ['=~', []], val[2]))
|
563
|
+
result = new_binary_call(val[0], val[1], val[2])
|
551
564
|
}
|
552
565
|
| tBANG arg
|
553
566
|
{
|
@@ -657,6 +670,7 @@ rule
|
|
657
670
|
{
|
658
671
|
result = val[0]
|
659
672
|
result << new_hash(nil, val[2], nil)
|
673
|
+
result << val[3] if val[3]
|
660
674
|
}
|
661
675
|
| block_arg
|
662
676
|
{
|
@@ -769,6 +783,10 @@ rule
|
|
769
783
|
{
|
770
784
|
result = new_call val[0], [:[], []], val[2]
|
771
785
|
}
|
786
|
+
| primary_value tJSLBRACK aref_args tRBRACK
|
787
|
+
{
|
788
|
+
result = new_js_call val[0], [:[], []], val[2]
|
789
|
+
}
|
772
790
|
| tLBRACK aref_args tRBRACK
|
773
791
|
{
|
774
792
|
result = new_array(val[0], val[1], val[2])
|
@@ -1098,6 +1116,7 @@ opt_block_args_tail: tCOMMA block_args_tail
|
|
1098
1116
|
val[0] << val[1]
|
1099
1117
|
result = val[0]
|
1100
1118
|
}
|
1119
|
+
| block_call tJSDOT operation2 opt_paren_args
|
1101
1120
|
| block_call tDOT operation2 opt_paren_args
|
1102
1121
|
| block_call tCOLON2 operation2 opt_paren_args
|
1103
1122
|
|
@@ -1109,6 +1128,10 @@ opt_block_args_tail: tCOMMA block_args_tail
|
|
1109
1128
|
{
|
1110
1129
|
result = new_call(val[0], val[2], val[3])
|
1111
1130
|
}
|
1131
|
+
| primary_value tJSDOT operation2 opt_paren_args
|
1132
|
+
{
|
1133
|
+
result = new_js_call(val[0], val[2], val[3])
|
1134
|
+
}
|
1112
1135
|
| primary_value tDOT paren_args
|
1113
1136
|
{
|
1114
1137
|
result = new_call(val[0], [:call, []], val[2])
|
data/lib/opal/parser/lexer.rb
CHANGED
@@ -987,6 +987,16 @@ module Opal
|
|
987
987
|
@lex_state = :expr_beg
|
988
988
|
return :tDOT2
|
989
989
|
|
990
|
+
elsif @lex_state != :expr_fname && scan(/\.JS\[/)
|
991
|
+
@lex_state = :expr_beg
|
992
|
+
cond_push 0
|
993
|
+
cmdarg_push 0
|
994
|
+
return :tJSLBRACK
|
995
|
+
|
996
|
+
elsif @lex_state != :expr_fname && scan(/\.JS\./)
|
997
|
+
@lex_state = :expr_dot
|
998
|
+
return :tJSDOT
|
999
|
+
|
990
1000
|
elsif scan(/\./)
|
991
1001
|
@lex_state = :expr_dot unless @lex_state == :expr_fname
|
992
1002
|
return :tDOT
|
@@ -1031,16 +1041,16 @@ module Opal
|
|
1031
1041
|
self.set_arg_state
|
1032
1042
|
return :tCARET
|
1033
1043
|
|
1034
|
-
elsif check(
|
1035
|
-
if scan(
|
1044
|
+
elsif check(/</)
|
1045
|
+
if scan(/<<\=/)
|
1036
1046
|
@lex_state = :expr_beg
|
1037
1047
|
return new_op_asgn('<<')
|
1038
1048
|
|
1039
|
-
elsif scan(
|
1049
|
+
elsif scan(/<</)
|
1040
1050
|
if after_operator?
|
1041
1051
|
@lex_state = :expr_arg
|
1042
1052
|
return :tLSHFT
|
1043
|
-
elsif !after_operator? && !end? && (!arg? || @space_seen)
|
1053
|
+
elsif !after_operator? && !end? && (!arg? || @space_seen) && @lex_state != :expr_class
|
1044
1054
|
if token = heredoc_identifier
|
1045
1055
|
return token
|
1046
1056
|
end
|
@@ -1050,7 +1060,7 @@ module Opal
|
|
1050
1060
|
end
|
1051
1061
|
@lex_state = :expr_beg
|
1052
1062
|
return :tLSHFT
|
1053
|
-
elsif scan(
|
1063
|
+
elsif scan(/<\=\>/)
|
1054
1064
|
if after_operator?
|
1055
1065
|
@lex_state = :expr_arg
|
1056
1066
|
else
|
@@ -1062,11 +1072,11 @@ module Opal
|
|
1062
1072
|
end
|
1063
1073
|
|
1064
1074
|
return :tCMP
|
1065
|
-
elsif scan(
|
1075
|
+
elsif scan(/<\=/)
|
1066
1076
|
self.set_arg_state
|
1067
1077
|
return :tLEQ
|
1068
1078
|
|
1069
|
-
elsif scan(
|
1079
|
+
elsif scan(/</)
|
1070
1080
|
self.set_arg_state
|
1071
1081
|
return :tLT
|
1072
1082
|
end
|
@@ -1228,7 +1238,7 @@ module Opal
|
|
1228
1238
|
elsif check(/[0-9]/)
|
1229
1239
|
return process_numeric
|
1230
1240
|
|
1231
|
-
elsif scan(/(\w)+
|
1241
|
+
elsif scan(/(\w)+(\?|(\!(?!=)))?/)
|
1232
1242
|
return process_identifier scanner.matched, cmd_start
|
1233
1243
|
end
|
1234
1244
|
|
data/lib/opal/sprockets.rb
CHANGED
@@ -1,3 +1,88 @@
|
|
1
1
|
require 'opal/sprockets/processor'
|
2
2
|
require 'opal/sprockets/erb'
|
3
3
|
require 'opal/sprockets/server'
|
4
|
+
|
5
|
+
module Opal
|
6
|
+
module Sprockets
|
7
|
+
# Public: Bootstraps modules loaded by sprockets on `Opal.modules` marking any
|
8
|
+
# non-Opal asset as already loaded.
|
9
|
+
#
|
10
|
+
# name - The name of the main asset to be loaded (with or without ext)
|
11
|
+
# sprockets - A Sprockets::Environment instance
|
12
|
+
#
|
13
|
+
# Example
|
14
|
+
#
|
15
|
+
# Opal::Sprockets.load_asset(Rails.application.assets, 'application')
|
16
|
+
#
|
17
|
+
# Will output the following JavaScript:
|
18
|
+
#
|
19
|
+
# if (typeof(Opal) !== 'undefined') {
|
20
|
+
# Opal.mark_as_loaded("opal");
|
21
|
+
# Opal.mark_as_loaded("jquery.self");
|
22
|
+
# Opal.load("application");
|
23
|
+
# }
|
24
|
+
#
|
25
|
+
# Returns a String containing JavaScript code.
|
26
|
+
def self.load_asset(name, sprockets)
|
27
|
+
asset = sprockets[name.sub(/(\.(js|rb|opal))*#{REGEXP_END}/, '.js')]
|
28
|
+
return '' if asset.nil?
|
29
|
+
|
30
|
+
opal_extnames = sprockets.engines.map do |ext, engine|
|
31
|
+
ext if engine <= ::Opal::Processor
|
32
|
+
end.compact
|
33
|
+
|
34
|
+
module_name = -> asset { asset.logical_path.sub(/\.js#{REGEXP_END}/, '') }
|
35
|
+
path_extnames = -> path { File.basename(path).scan(/\.[^.]+/) }
|
36
|
+
mark_loaded = -> paths { "Opal.loaded([#{paths.map(&:inspect).join(',')}]);" }
|
37
|
+
processed_by_opal = -> asset { (path_extnames[asset.pathname] & opal_extnames).any? }
|
38
|
+
stubbed_files = ::Opal::Processor.stubbed_files
|
39
|
+
|
40
|
+
non_opal_assets = ([asset]+asset.dependencies)
|
41
|
+
.select { |asset| not(processed_by_opal[asset]) }
|
42
|
+
.map { |asset| module_name[asset] }
|
43
|
+
|
44
|
+
loaded = ['opal'] + non_opal_assets + stubbed_files.to_a
|
45
|
+
|
46
|
+
if processed_by_opal[asset]
|
47
|
+
load_asset_code = "Opal.load(#{module_name[asset].inspect});"
|
48
|
+
end
|
49
|
+
|
50
|
+
|
51
|
+
"if (typeof(Opal) !== 'undefined') { "\
|
52
|
+
"#{mark_loaded[loaded]} "\
|
53
|
+
"#{load_asset_code} "\
|
54
|
+
"}"
|
55
|
+
end
|
56
|
+
|
57
|
+
# Public: Generate a `<script>` tag for Opal assets.
|
58
|
+
#
|
59
|
+
# name - The name of the asset to be loaded
|
60
|
+
# options - (default: {}):
|
61
|
+
# :sprockets - A Sprockets::Environment instance
|
62
|
+
# :prefix - The prefix String at which is mounted Sprockets
|
63
|
+
# :debug - Wether to enable debug mode along with sourcemaps support
|
64
|
+
#
|
65
|
+
# Returns a string of HTML code containing `<script>` tags.
|
66
|
+
def self.javascript_include_tag(name, options = {})
|
67
|
+
sprockets = options.fetch(:sprockets)
|
68
|
+
prefix = options.fetch(:prefix)
|
69
|
+
debug = options.fetch(:debug)
|
70
|
+
|
71
|
+
asset = sprockets[name]
|
72
|
+
raise "Cannot find asset: #{name}" if asset.nil?
|
73
|
+
scripts = []
|
74
|
+
|
75
|
+
if debug
|
76
|
+
asset.to_a.map do |dependency|
|
77
|
+
scripts << %{<script src="#{prefix}/#{dependency.logical_path}?body=1"></script>}
|
78
|
+
end
|
79
|
+
else
|
80
|
+
scripts << %{<script src="#{prefix}/#{name}.js"></script>}
|
81
|
+
end
|
82
|
+
|
83
|
+
scripts << %{<script>#{::Opal::Sprockets.load_asset(name, sprockets)}</script>}
|
84
|
+
|
85
|
+
scripts.join "\n"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -8,12 +8,12 @@ require 'opal/sprockets/source_map_server'
|
|
8
8
|
$OPAL_SOURCE_MAPS = {}
|
9
9
|
|
10
10
|
module Opal
|
11
|
-
# The Processor class is used to make ruby files (with rb or opal
|
12
|
-
# available to any sprockets based server. Processor will then
|
13
|
-
# ruby source file to build.
|
11
|
+
# Internal: The Processor class is used to make ruby files (with .rb or .opal
|
12
|
+
# extensions) available to any sprockets based server. Processor will then
|
13
|
+
# get passed any ruby source file to build.
|
14
14
|
class Processor < TiltTemplate
|
15
|
-
#
|
16
|
-
#
|
15
|
+
# Deprecated: Support legacy accessors to default options,
|
16
|
+
# now moved to Opal::Config
|
17
17
|
Opal::Config.default_config.keys.each do |config_option|
|
18
18
|
define_singleton_method(config_option) { Opal::Config.config[config_option] }
|
19
19
|
define_singleton_method("#{config_option}=") { |value| Opal::Config.config[config_option] = value }
|
@@ -36,7 +36,8 @@ module Opal
|
|
36
36
|
# In Sprockets 3 logical_path has an odd behavior when the filename is "index"
|
37
37
|
# thus we need to bake our own logical_path
|
38
38
|
filename = context.respond_to?(:filename) ? context.filename : context.pathname.to_s
|
39
|
-
|
39
|
+
root_path_regexp = Regexp.escape(context.root_path)
|
40
|
+
logical_path = filename.gsub(%r{^#{root_path_regexp}/?(.*?)#{sprockets_extnames_regexp}}, '\1')
|
40
41
|
|
41
42
|
compiler_options = self.compiler_options.merge(file: logical_path)
|
42
43
|
|
@@ -78,6 +79,8 @@ module Opal
|
|
78
79
|
end
|
79
80
|
end
|
80
81
|
|
82
|
+
# Internal: Add files required with `require_tree` as asset dependencies.
|
83
|
+
#
|
81
84
|
# Mimics (v2) Sprockets::DirectiveProcessor#process_require_tree_directive
|
82
85
|
def process_required_trees(required_trees, context)
|
83
86
|
return if required_trees.empty?
|
@@ -122,36 +125,9 @@ module Opal
|
|
122
125
|
end
|
123
126
|
end
|
124
127
|
|
128
|
+
# Deprecated: Moved to Opal::Sprockets.load_asset(sprockets, name)
|
125
129
|
def self.load_asset_code(sprockets, name)
|
126
|
-
|
127
|
-
return '' if asset.nil?
|
128
|
-
|
129
|
-
opal_extnames = sprockets.engines.map do |ext, engine|
|
130
|
-
ext if engine <= ::Opal::Processor
|
131
|
-
end.compact
|
132
|
-
|
133
|
-
module_name = -> asset { asset.logical_path.sub(/\.js#{REGEXP_END}/, '') }
|
134
|
-
path_extnames = -> path { File.basename(path).scan(/\.[^.]+/) }
|
135
|
-
mark_as_loaded = -> path { "Opal.mark_as_loaded(#{path.inspect});" }
|
136
|
-
processed_by_opal = -> asset { (path_extnames[asset.pathname] & opal_extnames).any? }
|
137
|
-
|
138
|
-
non_opal_assets = ([asset]+asset.dependencies)
|
139
|
-
.select { |asset| not(processed_by_opal[asset]) }
|
140
|
-
.map { |asset| module_name[asset] }
|
141
|
-
|
142
|
-
mark_as_loaded = (['opal'] + non_opal_assets + stubbed_files.to_a)
|
143
|
-
.map { |path| mark_as_loaded[path] }
|
144
|
-
|
145
|
-
if processed_by_opal[asset]
|
146
|
-
load_asset_code = "Opal.load(#{module_name[asset].inspect});"
|
147
|
-
end
|
148
|
-
|
149
|
-
<<-JS
|
150
|
-
if (typeof(Opal) !== 'undefined') {
|
151
|
-
#{mark_as_loaded.join("\n")}
|
152
|
-
#{load_asset_code}
|
153
|
-
}
|
154
|
-
JS
|
130
|
+
::Opal::Sprockets.load_asset(name, sprockets)
|
155
131
|
end
|
156
132
|
|
157
133
|
def self.stubbed_files
|
@@ -117,6 +117,7 @@ module Opal
|
|
117
117
|
raise "index does not exist: #{@index_path}" unless File.exist?(@index_path)
|
118
118
|
Tilt.new(@index_path).render(self)
|
119
119
|
else
|
120
|
+
raise "Main asset path not configured (set 'main' within Opal::Server.new block)" if @server.main.nil?
|
120
121
|
source
|
121
122
|
end
|
122
123
|
end
|
@@ -124,21 +125,7 @@ module Opal
|
|
124
125
|
def javascript_include_tag name
|
125
126
|
sprockets = @server.sprockets
|
126
127
|
prefix = @server.prefix
|
127
|
-
|
128
|
-
raise "Cannot find asset: #{name}" if asset.nil?
|
129
|
-
scripts = []
|
130
|
-
|
131
|
-
if @server.debug
|
132
|
-
asset.to_a.map do |dependency|
|
133
|
-
scripts << %{<script src="#{prefix}/#{dependency.logical_path}?body=1"></script>}
|
134
|
-
end
|
135
|
-
else
|
136
|
-
scripts << %{<script src="#{prefix}/#{name}.js"></script>}
|
137
|
-
end
|
138
|
-
|
139
|
-
scripts << %{<script>#{Opal::Processor.load_asset_code(sprockets, name)}</script>}
|
140
|
-
|
141
|
-
scripts.join "\n"
|
128
|
+
::Opal::Sprockets.javascript_include_tag(name, sprockets: @server.sprockets, prefix: @server.prefix, debug: @server.debug)
|
142
129
|
end
|
143
130
|
|
144
131
|
def source
|
@@ -146,6 +133,7 @@ module Opal
|
|
146
133
|
<!DOCTYPE html>
|
147
134
|
<html>
|
148
135
|
<head>
|
136
|
+
<meta charset="utf-8">
|
149
137
|
<title>Opal Server</title>
|
150
138
|
</head>
|
151
139
|
<body>
|
data/lib/opal/version.rb
CHANGED
data/opal.gemspec
CHANGED
@@ -9,16 +9,16 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.author = 'Adam Beynon'
|
10
10
|
s.email = 'adam.beynon@gmail.com'
|
11
11
|
s.homepage = 'http://opalrb.org'
|
12
|
-
s.summary = 'Ruby runtime and core library for
|
13
|
-
s.description = 'Ruby runtime and core library for
|
12
|
+
s.summary = 'Ruby runtime and core library for JavaScript'
|
13
|
+
s.description = 'Ruby runtime and core library for JavaScript.'
|
14
14
|
s.license = 'MIT'
|
15
15
|
|
16
16
|
s.files = `git ls-files`.split("\n")
|
17
|
-
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
18
18
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
19
19
|
s.require_paths = ['lib']
|
20
20
|
|
21
|
-
required_ruby_version = '>= 1.9.3'
|
21
|
+
s.required_ruby_version = '>= 1.9.3'
|
22
22
|
|
23
23
|
s.add_dependency 'sourcemap', '~> 0.1.0'
|
24
24
|
s.add_dependency 'sprockets', '~> 3.1'
|
data/opal/README.md
CHANGED
@@ -4,3 +4,12 @@ This is the Opal corelib implementation API documentation.
|
|
4
4
|
The whole corelib is loaded upon `require 'opal'`.
|
5
5
|
|
6
6
|
The `runtime.js` documentation is [available here](runtime.js.html)
|
7
|
+
|
8
|
+
# Cherry-picking
|
9
|
+
|
10
|
+
Note that `require 'opal'` will load all of the corelib, which is likely to
|
11
|
+
have a ton of stuff you don't need.
|
12
|
+
|
13
|
+
If you're concerned about runtime size, you can `require 'opal/base'` and
|
14
|
+
require anything you need, or `require 'opal/mini'` to have a working Ruby
|
15
|
+
without *useless* stuff.
|
data/opal/corelib/array.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'corelib/enumerable'
|
2
|
+
require 'corelib/numeric'
|
2
3
|
|
3
|
-
class Array
|
4
|
+
class Array < `Array`
|
4
5
|
include Enumerable
|
5
6
|
|
6
7
|
# Mark all javascript arrays as being valid ruby arrays
|
@@ -10,18 +11,17 @@ class Array
|
|
10
11
|
objects
|
11
12
|
end
|
12
13
|
|
13
|
-
def initialize(
|
14
|
-
self.class.new(*args)
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.new(size = nil, obj = nil, &block)
|
14
|
+
def initialize(size = nil, obj = nil, &block)
|
18
15
|
if `arguments.length > 2`
|
19
16
|
raise ArgumentError, "wrong number of arguments (#{`arguments.length`} for 0..2)"
|
20
17
|
end
|
21
18
|
|
22
|
-
|
23
|
-
|
24
|
-
|
19
|
+
%x{
|
20
|
+
if (arguments.length === 0) {
|
21
|
+
self.splice(0, self.length);
|
22
|
+
return self;
|
23
|
+
}
|
24
|
+
}
|
25
25
|
|
26
26
|
if `arguments.length === 1`
|
27
27
|
if Array === size
|
@@ -38,29 +38,34 @@ class Array
|
|
38
38
|
end
|
39
39
|
|
40
40
|
%x{
|
41
|
-
|
41
|
+
self.splice(0, self.length);
|
42
|
+
var i, value;
|
42
43
|
|
43
44
|
if (block === nil) {
|
44
|
-
for (
|
45
|
-
|
45
|
+
for (i = 0; i < size; i++) {
|
46
|
+
self.push(obj);
|
46
47
|
}
|
47
48
|
}
|
48
49
|
else {
|
49
|
-
for (
|
50
|
+
for (i = 0, value; i < size; i++) {
|
50
51
|
value = block(i);
|
51
52
|
|
52
53
|
if (value === $breaker) {
|
53
54
|
return $breaker.$v;
|
54
55
|
}
|
55
56
|
|
56
|
-
|
57
|
+
self[i] = value;
|
57
58
|
}
|
58
59
|
}
|
59
60
|
|
60
|
-
return
|
61
|
+
return self;
|
61
62
|
}
|
62
63
|
end
|
63
64
|
|
65
|
+
def self.new(*args, &block)
|
66
|
+
[].initialize(*args, &block)
|
67
|
+
end
|
68
|
+
|
64
69
|
def self.try_convert(obj)
|
65
70
|
Opal.coerce_to? obj, Array, :to_ary
|
66
71
|
end
|
@@ -73,21 +78,16 @@ class Array
|
|
73
78
|
end
|
74
79
|
|
75
80
|
%x{
|
76
|
-
var result = [],
|
77
|
-
seen = {};
|
78
|
-
|
79
|
-
for (var i = 0, length = self.length; i < length; i++) {
|
80
|
-
var item = self[i];
|
81
|
+
var result = [], hash = #{{}}, i, length, item;
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
for (i = 0, length = other.length; i < length; i++) {
|
84
|
+
Opal.hash_put(hash, other[i], true);
|
85
|
+
}
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
}
|
87
|
+
for (i = 0, length = self.length; i < length; i++) {
|
88
|
+
item = self[i];
|
89
|
+
if (Opal.hash_delete(hash, item) !== undefined) {
|
90
|
+
result.push(item);
|
91
91
|
}
|
92
92
|
}
|
93
93
|
|
@@ -103,32 +103,22 @@ class Array
|
|
103
103
|
end
|
104
104
|
|
105
105
|
%x{
|
106
|
-
var
|
107
|
-
seen = {};
|
106
|
+
var hash = #{{}}, i, length, item;
|
108
107
|
|
109
|
-
for (
|
110
|
-
|
111
|
-
|
112
|
-
if (!seen[item]) {
|
113
|
-
seen[item] = true;
|
114
|
-
result.push(item);
|
115
|
-
}
|
108
|
+
for (i = 0, length = self.length; i < length; i++) {
|
109
|
+
Opal.hash_put(hash, self[i], true);
|
116
110
|
}
|
117
111
|
|
118
|
-
for (
|
119
|
-
|
120
|
-
|
121
|
-
if (!seen[item]) {
|
122
|
-
seen[item] = true;
|
123
|
-
result.push(item);
|
124
|
-
}
|
112
|
+
for (i = 0, length = other.length; i < length; i++) {
|
113
|
+
Opal.hash_put(hash, other[i], true);
|
125
114
|
}
|
126
|
-
|
115
|
+
|
116
|
+
return hash.$keys();
|
127
117
|
}
|
128
118
|
end
|
129
119
|
|
130
120
|
def *(other)
|
131
|
-
return
|
121
|
+
return join(other.to_str) if other.respond_to? :to_str
|
132
122
|
|
133
123
|
unless other.respond_to? :to_int
|
134
124
|
raise TypeError, "no implicit conversion of #{other.class} into Integer"
|
@@ -172,17 +162,15 @@ class Array
|
|
172
162
|
return clone if `other.length === 0`
|
173
163
|
|
174
164
|
%x{
|
175
|
-
var
|
176
|
-
result = [];
|
165
|
+
var result = [], hash = #{{}}, i, length, item;
|
177
166
|
|
178
|
-
for (
|
179
|
-
|
167
|
+
for (i = 0, length = other.length; i < length; i++) {
|
168
|
+
Opal.hash_put(hash, other[i], true);
|
180
169
|
}
|
181
170
|
|
182
|
-
for (
|
183
|
-
|
184
|
-
|
185
|
-
if (!seen[item]) {
|
171
|
+
for (i = 0, length = self.length; i < length; i++) {
|
172
|
+
item = self[i];
|
173
|
+
if (Opal.hash_get(hash, item) === undefined) {
|
186
174
|
result.push(item);
|
187
175
|
}
|
188
176
|
}
|
@@ -211,11 +199,9 @@ class Array
|
|
211
199
|
return 0;
|
212
200
|
}
|
213
201
|
|
214
|
-
|
215
|
-
return (self.length > other.length) ? 1 : -1;
|
216
|
-
}
|
202
|
+
var count = Math.min(self.length, other.length);
|
217
203
|
|
218
|
-
for (var i = 0
|
204
|
+
for (var i = 0; i < count; i++) {
|
219
205
|
var tmp = #{`self[i]` <=> `other[i]`};
|
220
206
|
|
221
207
|
if (tmp !== 0) {
|
@@ -223,7 +209,7 @@ class Array
|
|
223
209
|
}
|
224
210
|
}
|
225
211
|
|
226
|
-
return
|
212
|
+
return #{`self.length` <=> `other.length`};
|
227
213
|
}
|
228
214
|
end
|
229
215
|
|
@@ -277,12 +263,14 @@ class Array
|
|
277
263
|
end
|
278
264
|
|
279
265
|
def [](index, length = undefined)
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
266
|
+
%x{
|
267
|
+
var size = self.length,
|
268
|
+
exclude, from, to;
|
269
|
+
|
270
|
+
if (index.$$is_range) {
|
271
|
+
exclude = index.exclude;
|
272
|
+
from = #{Opal.coerce_to `index.begin`, Integer, :to_int};
|
273
|
+
to = #{Opal.coerce_to `index.end`, Integer, :to_int};
|
286
274
|
|
287
275
|
if (from < 0) {
|
288
276
|
from += size;
|
@@ -310,11 +298,8 @@ class Array
|
|
310
298
|
|
311
299
|
return self.slice(from, to);
|
312
300
|
}
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
%x{
|
317
|
-
var size = self.length;
|
301
|
+
else {
|
302
|
+
index = #{Opal.coerce_to(index, Integer, :to_int)};
|
318
303
|
|
319
304
|
if (index < 0) {
|
320
305
|
index += size;
|
@@ -341,10 +326,14 @@ class Array
|
|
341
326
|
return self.slice(index, index + length);
|
342
327
|
}
|
343
328
|
}
|
344
|
-
|
329
|
+
}
|
345
330
|
end
|
346
331
|
|
347
332
|
def []=(index, value, extra = undefined)
|
333
|
+
%x{
|
334
|
+
var i, size = self.length;
|
335
|
+
}
|
336
|
+
|
348
337
|
if Range === index
|
349
338
|
if Array === value
|
350
339
|
data = value.to_a
|
@@ -355,8 +344,7 @@ class Array
|
|
355
344
|
end
|
356
345
|
|
357
346
|
%x{
|
358
|
-
var
|
359
|
-
exclude = index.exclude,
|
347
|
+
var exclude = index.exclude,
|
360
348
|
from = #{Opal.coerce_to `index.begin`, Integer, :to_int},
|
361
349
|
to = #{Opal.coerce_to `index.end`, Integer, :to_int};
|
362
350
|
|
@@ -377,7 +365,7 @@ class Array
|
|
377
365
|
}
|
378
366
|
|
379
367
|
if (from > size) {
|
380
|
-
for (
|
368
|
+
for (i = size; i < from; i++) {
|
381
369
|
self[i] = nil;
|
382
370
|
}
|
383
371
|
}
|
@@ -408,10 +396,10 @@ class Array
|
|
408
396
|
end
|
409
397
|
|
410
398
|
%x{
|
411
|
-
var
|
412
|
-
|
413
|
-
|
414
|
-
|
399
|
+
var old;
|
400
|
+
|
401
|
+
index = #{Opal.coerce_to index, Integer, :to_int};
|
402
|
+
length = #{Opal.coerce_to length, Integer, :to_int};
|
415
403
|
|
416
404
|
if (index < 0) {
|
417
405
|
old = index;
|
@@ -427,7 +415,7 @@ class Array
|
|
427
415
|
}
|
428
416
|
|
429
417
|
if (index > size) {
|
430
|
-
for (
|
418
|
+
for (i = size; i < index; i++) {
|
431
419
|
self[i] = nil;
|
432
420
|
}
|
433
421
|
}
|
@@ -515,15 +503,24 @@ class Array
|
|
515
503
|
end
|
516
504
|
|
517
505
|
def cycle(n = nil, &block)
|
506
|
+
return enum_for(:cycle, n) {
|
507
|
+
if n == nil
|
508
|
+
Float::INFINITY
|
509
|
+
else
|
510
|
+
n = Opal.coerce_to!(n, Integer, :to_int)
|
511
|
+
n > 0 ? self.enumerator_size * n : 0
|
512
|
+
end
|
513
|
+
} unless block_given?
|
514
|
+
|
518
515
|
return if empty? || n == 0
|
519
516
|
|
520
|
-
|
517
|
+
%x{
|
518
|
+
var i, length, value;
|
521
519
|
|
522
|
-
|
523
|
-
%x{
|
520
|
+
if (n === nil) {
|
524
521
|
while (true) {
|
525
|
-
for (
|
526
|
-
|
522
|
+
for (i = 0, length = self.length; i < length; i++) {
|
523
|
+
value = Opal.yield1(block, self[i]);
|
527
524
|
|
528
525
|
if (value === $breaker) {
|
529
526
|
return $breaker.$v;
|
@@ -531,17 +528,15 @@ class Array
|
|
531
528
|
}
|
532
529
|
}
|
533
530
|
}
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
%x{
|
531
|
+
else {
|
532
|
+
n = #{Opal.coerce_to!(n, Integer, :to_int)};
|
538
533
|
if (n <= 0) {
|
539
534
|
return self;
|
540
535
|
}
|
541
536
|
|
542
537
|
while (n > 0) {
|
543
|
-
for (
|
544
|
-
|
538
|
+
for (i = 0, length = self.length; i < length; i++) {
|
539
|
+
value = Opal.yield1(block, self[i]);
|
545
540
|
|
546
541
|
if (value === $breaker) {
|
547
542
|
return $breaker.$v;
|
@@ -551,7 +546,7 @@ class Array
|
|
551
546
|
n--;
|
552
547
|
}
|
553
548
|
}
|
554
|
-
|
549
|
+
}
|
555
550
|
|
556
551
|
self
|
557
552
|
end
|
@@ -564,6 +559,7 @@ class Array
|
|
564
559
|
|
565
560
|
def clone
|
566
561
|
copy = []
|
562
|
+
copy.copy_singleton_methods(self)
|
567
563
|
copy.initialize_clone(self)
|
568
564
|
copy
|
569
565
|
end
|
@@ -579,7 +575,7 @@ class Array
|
|
579
575
|
end
|
580
576
|
|
581
577
|
def collect(&block)
|
582
|
-
return enum_for
|
578
|
+
return enum_for(:collect){self.size} unless block_given?
|
583
579
|
|
584
580
|
%x{
|
585
581
|
var result = [];
|
@@ -599,7 +595,7 @@ class Array
|
|
599
595
|
end
|
600
596
|
|
601
597
|
def collect!(&block)
|
602
|
-
return enum_for
|
598
|
+
return enum_for(:collect!){self.size} unless block_given?
|
603
599
|
|
604
600
|
%x{
|
605
601
|
for (var i = 0, length = self.length; i < length; i++) {
|
@@ -616,9 +612,23 @@ class Array
|
|
616
612
|
self
|
617
613
|
end
|
618
614
|
|
615
|
+
%x{
|
616
|
+
function binomial_coefficient(n, k) {
|
617
|
+
if (n === k || k === 0) {
|
618
|
+
return 1;
|
619
|
+
}
|
620
|
+
|
621
|
+
if (k > 0 && n > k) {
|
622
|
+
return binomial_coefficient(n - 1, k - 1) + binomial_coefficient(n - 1, k);
|
623
|
+
}
|
624
|
+
|
625
|
+
return 0;
|
626
|
+
}
|
627
|
+
}
|
628
|
+
|
619
629
|
def combination(n)
|
620
630
|
num = Opal.coerce_to! n, Integer, :to_int
|
621
|
-
return enum_for
|
631
|
+
return enum_for(:combination, num){ `binomial_coefficient(#{self}.length, num)` } unless block_given?
|
622
632
|
|
623
633
|
%x{
|
624
634
|
var i, length, stack, chosen, lev, done, next;
|
@@ -755,7 +765,7 @@ class Array
|
|
755
765
|
end
|
756
766
|
|
757
767
|
def delete_if(&block)
|
758
|
-
return enum_for
|
768
|
+
return enum_for(:delete_if){self.size} unless block_given?
|
759
769
|
|
760
770
|
%x{
|
761
771
|
for (var i = 0, length = self.length, value; i < length; i++) {
|
@@ -785,10 +795,8 @@ class Array
|
|
785
795
|
}
|
786
796
|
end
|
787
797
|
|
788
|
-
alias dup clone
|
789
|
-
|
790
798
|
def each(&block)
|
791
|
-
return enum_for
|
799
|
+
return enum_for(:each){self.size} unless block_given?
|
792
800
|
|
793
801
|
%x{
|
794
802
|
for (var i = 0, length = self.length; i < length; i++) {
|
@@ -804,7 +812,7 @@ class Array
|
|
804
812
|
end
|
805
813
|
|
806
814
|
def each_index(&block)
|
807
|
-
return enum_for
|
815
|
+
return enum_for(:each_index){self.size} unless block_given?
|
808
816
|
|
809
817
|
%x{
|
810
818
|
for (var i = 0, length = self.length; i < length; i++) {
|
@@ -900,6 +908,10 @@ class Array
|
|
900
908
|
end
|
901
909
|
|
902
910
|
def fill(*args, &block)
|
911
|
+
%x{
|
912
|
+
var i, length, value;
|
913
|
+
}
|
914
|
+
|
903
915
|
if block
|
904
916
|
if `args.length > 2`
|
905
917
|
raise ArgumentError, "wrong number of arguments (#{args.length} for 0..2)"
|
@@ -949,7 +961,7 @@ class Array
|
|
949
961
|
|
950
962
|
if `left > #@length`
|
951
963
|
%x{
|
952
|
-
for (
|
964
|
+
for (i = #@length; i < right; i++) {
|
953
965
|
self[i] = nil;
|
954
966
|
}
|
955
967
|
}
|
@@ -961,8 +973,8 @@ class Array
|
|
961
973
|
|
962
974
|
if block
|
963
975
|
%x{
|
964
|
-
for (
|
965
|
-
|
976
|
+
for (length = #@length; left < right; left++) {
|
977
|
+
value = block(left);
|
966
978
|
|
967
979
|
if (value === $breaker) {
|
968
980
|
return $breaker.$v;
|
@@ -973,7 +985,7 @@ class Array
|
|
973
985
|
}
|
974
986
|
else
|
975
987
|
%x{
|
976
|
-
for (
|
988
|
+
for (length = #@length; left < right; left++) {
|
977
989
|
self[left] = #{obj};
|
978
990
|
}
|
979
991
|
}
|
@@ -1000,14 +1012,13 @@ class Array
|
|
1000
1012
|
|
1001
1013
|
def flatten(level = undefined)
|
1002
1014
|
%x{
|
1003
|
-
var object_id = #{`self`.object_id};
|
1004
|
-
|
1005
1015
|
function _flatten(array, level) {
|
1006
|
-
var
|
1007
|
-
result = [],
|
1016
|
+
var result = [],
|
1008
1017
|
i, length,
|
1009
1018
|
item, ary;
|
1010
1019
|
|
1020
|
+
array = #{`array`.to_a};
|
1021
|
+
|
1011
1022
|
for (i = 0, length = array.length; i < length; i++) {
|
1012
1023
|
item = array[i];
|
1013
1024
|
|
@@ -1027,7 +1038,7 @@ class Array
|
|
1027
1038
|
#{raise TypeError};
|
1028
1039
|
}
|
1029
1040
|
|
1030
|
-
if (
|
1041
|
+
if (ary === self) {
|
1031
1042
|
#{raise ArgumentError};
|
1032
1043
|
}
|
1033
1044
|
|
@@ -1077,17 +1088,42 @@ class Array
|
|
1077
1088
|
|
1078
1089
|
def hash
|
1079
1090
|
%x{
|
1080
|
-
var
|
1081
|
-
|
1082
|
-
|
1083
|
-
|
1084
|
-
|
1085
|
-
|
1086
|
-
|
1087
|
-
|
1091
|
+
var top = (Opal.hash_ids == undefined),
|
1092
|
+
result = ['A'],
|
1093
|
+
hash_id = self.$object_id(),
|
1094
|
+
item, i, key;
|
1095
|
+
|
1096
|
+
try {
|
1097
|
+
if (top) {
|
1098
|
+
Opal.hash_ids = {};
|
1099
|
+
}
|
1100
|
+
|
1101
|
+
if (Opal.hash_ids.hasOwnProperty(hash_id)) {
|
1102
|
+
return 'self';
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
for (key in Opal.hash_ids) {
|
1106
|
+
if (Opal.hash_ids.hasOwnProperty(key)) {
|
1107
|
+
item = Opal.hash_ids[key];
|
1108
|
+
if (#{eql?(`item`)}) {
|
1109
|
+
return 'self';
|
1110
|
+
}
|
1111
|
+
}
|
1112
|
+
}
|
1113
|
+
|
1114
|
+
Opal.hash_ids[hash_id] = self;
|
1115
|
+
|
1116
|
+
for (i = 0; i < self.length; i++) {
|
1117
|
+
item = self[i];
|
1118
|
+
result.push(item.$hash());
|
1119
|
+
}
|
1120
|
+
|
1121
|
+
return result.join(',');
|
1122
|
+
} finally {
|
1123
|
+
if (top) {
|
1124
|
+
delete Opal.hash_ids;
|
1088
1125
|
}
|
1089
1126
|
}
|
1090
|
-
return hash.join(',');
|
1091
1127
|
}
|
1092
1128
|
end
|
1093
1129
|
|
@@ -1105,15 +1141,17 @@ class Array
|
|
1105
1141
|
|
1106
1142
|
def index(object=undefined, &block)
|
1107
1143
|
%x{
|
1144
|
+
var i, length, value;
|
1145
|
+
|
1108
1146
|
if (object != null) {
|
1109
|
-
for (
|
1147
|
+
for (i = 0, length = self.length; i < length; i++) {
|
1110
1148
|
if (#{`self[i]` == object}) {
|
1111
1149
|
return i;
|
1112
1150
|
}
|
1113
1151
|
}
|
1114
1152
|
}
|
1115
1153
|
else if (block !== nil) {
|
1116
|
-
for (
|
1154
|
+
for (i = 0, length = self.length; i < length; i++) {
|
1117
1155
|
if ((value = block(self[i])) === $breaker) {
|
1118
1156
|
return $breaker.$v;
|
1119
1157
|
}
|
@@ -1185,13 +1223,13 @@ class Array
|
|
1185
1223
|
|
1186
1224
|
%x{
|
1187
1225
|
var result = [];
|
1188
|
-
var
|
1226
|
+
var i, length, item, tmp;
|
1189
1227
|
|
1190
|
-
for (
|
1191
|
-
|
1228
|
+
for (i = 0, length = self.length; i < length; i++) {
|
1229
|
+
item = self[i];
|
1192
1230
|
|
1193
1231
|
if (#{Opal.respond_to? `item`, :to_str}) {
|
1194
|
-
|
1232
|
+
tmp = #{`item`.to_str};
|
1195
1233
|
|
1196
1234
|
if (tmp !== nil) {
|
1197
1235
|
result.push(#{`tmp`.to_s});
|
@@ -1201,9 +1239,9 @@ class Array
|
|
1201
1239
|
}
|
1202
1240
|
|
1203
1241
|
if (#{Opal.respond_to? `item`, :to_ary}) {
|
1204
|
-
|
1242
|
+
tmp = #{`item`.to_ary};
|
1205
1243
|
|
1206
|
-
if (
|
1244
|
+
if (tmp === self) {
|
1207
1245
|
#{raise ArgumentError};
|
1208
1246
|
}
|
1209
1247
|
|
@@ -1215,7 +1253,7 @@ class Array
|
|
1215
1253
|
}
|
1216
1254
|
|
1217
1255
|
if (#{Opal.respond_to? `item`, :to_s}) {
|
1218
|
-
|
1256
|
+
tmp = #{`item`.to_s};
|
1219
1257
|
|
1220
1258
|
if (tmp !== nil) {
|
1221
1259
|
result.push(tmp);
|
@@ -1237,7 +1275,7 @@ class Array
|
|
1237
1275
|
end
|
1238
1276
|
|
1239
1277
|
def keep_if(&block)
|
1240
|
-
return enum_for
|
1278
|
+
return enum_for(:keep_if){self.size} unless block_given?
|
1241
1279
|
|
1242
1280
|
%x{
|
1243
1281
|
for (var i = 0, length = self.length, value; i < length; i++) {
|
@@ -1284,7 +1322,73 @@ class Array
|
|
1284
1322
|
alias map collect
|
1285
1323
|
|
1286
1324
|
alias map! collect!
|
1325
|
+
|
1326
|
+
def permutation(num = undefined, &block)
|
1327
|
+
return enum_for(:permutation, num){self.size} unless block_given?
|
1328
|
+
|
1329
|
+
%x{
|
1330
|
+
var permute, offensive, output;
|
1331
|
+
|
1332
|
+
if (num === undefined) {
|
1333
|
+
num = self.length;
|
1334
|
+
}
|
1335
|
+
else {
|
1336
|
+
num = #{ Opal.coerce_to num, Integer, :to_int }
|
1337
|
+
}
|
1338
|
+
|
1339
|
+
if (num < 0 || self.length < num) {
|
1340
|
+
// no permutations, yield nothing
|
1341
|
+
}
|
1342
|
+
else if (num === 0) {
|
1343
|
+
// exactly one permutation: the zero-length array
|
1344
|
+
#{ yield [] }
|
1345
|
+
}
|
1346
|
+
else if (num === 1) {
|
1347
|
+
// this is a special, easy case
|
1348
|
+
for (var i = 0; i < self.length; i++) {
|
1349
|
+
#{ yield `[self[i]]` }
|
1350
|
+
}
|
1351
|
+
}
|
1352
|
+
else {
|
1353
|
+
// this is the general case
|
1354
|
+
#{ perm = Array.new(num) }
|
1355
|
+
#{ used = Array.new(`self.length`, false) }
|
1356
|
+
|
1357
|
+
permute = function(num, perm, index, used, blk) {
|
1358
|
+
self = this;
|
1359
|
+
for(var i = 0; i < self.length; i++){
|
1360
|
+
if(#{ !used[`i`] }) {
|
1361
|
+
perm[index] = i;
|
1362
|
+
if(index < num - 1) {
|
1363
|
+
used[i] = true;
|
1364
|
+
permute.call(self, num, perm, index + 1, used, blk);
|
1365
|
+
used[i] = false;
|
1366
|
+
}
|
1367
|
+
else {
|
1368
|
+
output = [];
|
1369
|
+
for (var j = 0; j < perm.length; j++) {
|
1370
|
+
output.push(self[perm[j]]);
|
1371
|
+
}
|
1372
|
+
Opal.yield1(blk, output);
|
1373
|
+
}
|
1374
|
+
}
|
1375
|
+
}
|
1376
|
+
}
|
1377
|
+
|
1378
|
+
if (#{block_given?}) {
|
1379
|
+
// offensive (both definitions) copy.
|
1380
|
+
offensive = self.slice();
|
1381
|
+
permute.call(offensive, num, perm, 0, used, block);
|
1382
|
+
}
|
1383
|
+
else {
|
1384
|
+
permute.call(self, num, perm, 0, used, block);
|
1385
|
+
}
|
1386
|
+
}
|
1387
|
+
}
|
1287
1388
|
|
1389
|
+
self
|
1390
|
+
end
|
1391
|
+
|
1288
1392
|
def pop(count = undefined)
|
1289
1393
|
if `count === undefined`
|
1290
1394
|
return if `self.length === 0`
|
@@ -1383,7 +1487,7 @@ class Array
|
|
1383
1487
|
end
|
1384
1488
|
|
1385
1489
|
def reject(&block)
|
1386
|
-
return enum_for
|
1490
|
+
return enum_for(:reject){self.size} unless block_given?
|
1387
1491
|
|
1388
1492
|
%x{
|
1389
1493
|
var result = [];
|
@@ -1402,7 +1506,7 @@ class Array
|
|
1402
1506
|
end
|
1403
1507
|
|
1404
1508
|
def reject!(&block)
|
1405
|
-
return enum_for
|
1509
|
+
return enum_for(:reject!){self.size} unless block_given?
|
1406
1510
|
|
1407
1511
|
original = length
|
1408
1512
|
delete_if(&block)
|
@@ -1436,7 +1540,7 @@ class Array
|
|
1436
1540
|
end
|
1437
1541
|
|
1438
1542
|
def reverse_each(&block)
|
1439
|
-
return enum_for
|
1543
|
+
return enum_for(:reverse_each){self.size} unless block_given?
|
1440
1544
|
|
1441
1545
|
reverse.each &block
|
1442
1546
|
self
|
@@ -1444,19 +1548,26 @@ class Array
|
|
1444
1548
|
|
1445
1549
|
def rindex(object = undefined, &block)
|
1446
1550
|
%x{
|
1551
|
+
var i, value;
|
1552
|
+
|
1447
1553
|
if (object != null) {
|
1448
|
-
for (
|
1554
|
+
for (i = self.length - 1; i >= 0; i--) {
|
1555
|
+
if (i >= self.length) {
|
1556
|
+
break;
|
1557
|
+
}
|
1449
1558
|
if (#{`self[i]` == `object`}) {
|
1450
1559
|
return i;
|
1451
1560
|
}
|
1452
1561
|
}
|
1453
1562
|
}
|
1454
1563
|
else if (block !== nil) {
|
1455
|
-
for (
|
1564
|
+
for (i = self.length - 1; i >= 0; i--) {
|
1565
|
+
if (i >= self.length) {
|
1566
|
+
break;
|
1567
|
+
}
|
1456
1568
|
if ((value = block(self[i])) === $breaker) {
|
1457
1569
|
return $breaker.$v;
|
1458
1570
|
}
|
1459
|
-
|
1460
1571
|
if (value !== false && value !== nil) {
|
1461
1572
|
return i;
|
1462
1573
|
}
|
@@ -1492,8 +1603,6 @@ class Array
|
|
1492
1603
|
end
|
1493
1604
|
|
1494
1605
|
def rotate!(cnt=1)
|
1495
|
-
raise RuntimeError, "can't modify frozen Array" if frozen?
|
1496
|
-
|
1497
1606
|
%x{
|
1498
1607
|
if (self.length === 0 || self.length === 1) {
|
1499
1608
|
return self;
|
@@ -1504,21 +1613,133 @@ class Array
|
|
1504
1613
|
replace ary
|
1505
1614
|
end
|
1506
1615
|
|
1507
|
-
|
1508
|
-
|
1509
|
-
|
1616
|
+
class SampleRandom
|
1617
|
+
def initialize(rng)
|
1618
|
+
@rng = rng
|
1619
|
+
end
|
1510
1620
|
|
1511
|
-
|
1512
|
-
|
1513
|
-
|
1514
|
-
|
1515
|
-
|
1516
|
-
|
1621
|
+
def rand(size)
|
1622
|
+
random = Opal.coerce_to @rng.rand(size), Integer, :to_int
|
1623
|
+
raise RangeError, "random value must be >= 0" if `random < 0`
|
1624
|
+
raise RangeError, "random value must be less than Array size" unless `random < size`
|
1625
|
+
|
1626
|
+
random
|
1517
1627
|
end
|
1518
1628
|
end
|
1519
1629
|
|
1630
|
+
def sample(count = undefined, options = undefined)
|
1631
|
+
return at Kernel.rand(`self.length`) if `count === undefined`
|
1632
|
+
|
1633
|
+
if `options === undefined`
|
1634
|
+
if (o = Opal.coerce_to? count, Hash, :to_hash)
|
1635
|
+
options = o
|
1636
|
+
count = nil
|
1637
|
+
else
|
1638
|
+
options = nil
|
1639
|
+
count = Opal.coerce_to count, Integer, :to_int
|
1640
|
+
end
|
1641
|
+
else
|
1642
|
+
count = Opal.coerce_to count, Integer, :to_int
|
1643
|
+
options = Opal.coerce_to options, Hash, :to_hash
|
1644
|
+
end
|
1645
|
+
|
1646
|
+
if count and `count < 0`
|
1647
|
+
raise ArgumentError, "count must be greater than 0"
|
1648
|
+
end
|
1649
|
+
|
1650
|
+
rng = options[:random] if options
|
1651
|
+
if rng and rng.respond_to? :rand
|
1652
|
+
rng = SampleRandom.new rng
|
1653
|
+
else
|
1654
|
+
rng = Kernel
|
1655
|
+
end
|
1656
|
+
|
1657
|
+
return `self[#{rng.rand(`self.length`)}]` unless count
|
1658
|
+
|
1659
|
+
%x{
|
1660
|
+
|
1661
|
+
var abandon, spin, result, i, j, k, targetIndex, oldValue;
|
1662
|
+
|
1663
|
+
if (count > self.length) {
|
1664
|
+
count = self.length;
|
1665
|
+
}
|
1666
|
+
|
1667
|
+
switch (count) {
|
1668
|
+
case 0:
|
1669
|
+
return [];
|
1670
|
+
break;
|
1671
|
+
case 1:
|
1672
|
+
return [self[#{rng.rand(`self.length`)}]];
|
1673
|
+
break;
|
1674
|
+
case 2:
|
1675
|
+
i = #{rng.rand(`self.length`)};
|
1676
|
+
j = #{rng.rand(`self.length`)};
|
1677
|
+
if (i === j) {
|
1678
|
+
j = i === 0 ? i + 1 : i - 1;
|
1679
|
+
}
|
1680
|
+
return [self[i], self[j]];
|
1681
|
+
break;
|
1682
|
+
default:
|
1683
|
+
if (self.length / count > 3) {
|
1684
|
+
abandon = false;
|
1685
|
+
spin = 0;
|
1686
|
+
|
1687
|
+
result = #{ Array.new(count) };
|
1688
|
+
i = 1;
|
1689
|
+
|
1690
|
+
result[0] = #{rng.rand(`self.length`)};
|
1691
|
+
while (i < count) {
|
1692
|
+
k = #{rng.rand(`self.length`)};
|
1693
|
+
j = 0;
|
1694
|
+
|
1695
|
+
while (j < i) {
|
1696
|
+
while (k === result[j]) {
|
1697
|
+
spin++;
|
1698
|
+
if (spin > 100) {
|
1699
|
+
abandon = true;
|
1700
|
+
break;
|
1701
|
+
}
|
1702
|
+
k = #{rng.rand(`self.length`)};
|
1703
|
+
}
|
1704
|
+
if (abandon) { break; }
|
1705
|
+
|
1706
|
+
j++;
|
1707
|
+
}
|
1708
|
+
|
1709
|
+
if (abandon) { break; }
|
1710
|
+
|
1711
|
+
result[i] = k;
|
1712
|
+
|
1713
|
+
i++;
|
1714
|
+
}
|
1715
|
+
|
1716
|
+
if (!abandon) {
|
1717
|
+
i = 0;
|
1718
|
+
while (i < count) {
|
1719
|
+
result[i] = self[result[i]];
|
1720
|
+
i++;
|
1721
|
+
}
|
1722
|
+
|
1723
|
+
return result;
|
1724
|
+
}
|
1725
|
+
}
|
1726
|
+
|
1727
|
+
result = self.slice();
|
1728
|
+
|
1729
|
+
for (var c = 0; c < count; c++) {
|
1730
|
+
targetIndex = #{rng.rand(`self.length`)};
|
1731
|
+
oldValue = result[c];
|
1732
|
+
result[c] = result[targetIndex];
|
1733
|
+
result[targetIndex] = oldValue;
|
1734
|
+
}
|
1735
|
+
|
1736
|
+
return count === self.length ? result : #{`result`[0, count]};
|
1737
|
+
}
|
1738
|
+
}
|
1739
|
+
end
|
1740
|
+
|
1520
1741
|
def select(&block)
|
1521
|
-
return enum_for
|
1742
|
+
return enum_for(:select){self.size} unless block_given?
|
1522
1743
|
|
1523
1744
|
%x{
|
1524
1745
|
var result = [];
|
@@ -1540,7 +1761,7 @@ class Array
|
|
1540
1761
|
end
|
1541
1762
|
|
1542
1763
|
def select!(&block)
|
1543
|
-
return enum_for
|
1764
|
+
return enum_for(:select!){self.size} unless block_given?
|
1544
1765
|
|
1545
1766
|
%x{
|
1546
1767
|
var original = self.length;
|
@@ -1568,22 +1789,49 @@ class Array
|
|
1568
1789
|
|
1569
1790
|
alias size length
|
1570
1791
|
|
1571
|
-
def shuffle
|
1572
|
-
|
1792
|
+
def shuffle(rng = undefined)
|
1793
|
+
dup.shuffle!(rng)
|
1573
1794
|
end
|
1574
1795
|
|
1575
|
-
def shuffle!
|
1796
|
+
def shuffle!(rng = undefined)
|
1576
1797
|
%x{
|
1577
|
-
|
1578
|
-
|
1579
|
-
|
1798
|
+
var randgen, i = self.length, j, tmp;
|
1799
|
+
|
1800
|
+
if (rng !== undefined) {
|
1801
|
+
rng = #{Opal.coerce_to?(rng, Hash, :to_hash)};
|
1802
|
+
|
1803
|
+
if (rng !== nil) {
|
1804
|
+
rng = #{rng[:random]};
|
1805
|
+
|
1806
|
+
if (rng !== nil && #{rng.respond_to?(:rand)}) {
|
1807
|
+
randgen = rng;
|
1808
|
+
}
|
1809
|
+
}
|
1810
|
+
}
|
1811
|
+
|
1812
|
+
while (i) {
|
1813
|
+
if (randgen) {
|
1814
|
+
j = randgen.$rand(i).$to_int();
|
1815
|
+
|
1816
|
+
if (j < 0) {
|
1817
|
+
#{raise RangeError, "random number too small #{`j`}"}
|
1818
|
+
}
|
1819
|
+
|
1820
|
+
if (j >= i) {
|
1821
|
+
#{raise RangeError, "random number too big #{`j`}"}
|
1822
|
+
}
|
1823
|
+
}
|
1824
|
+
else {
|
1825
|
+
j = Math.floor(Math.random() * i);
|
1826
|
+
}
|
1580
1827
|
|
1828
|
+
tmp = self[--i];
|
1581
1829
|
self[i] = self[j];
|
1582
1830
|
self[j] = tmp;
|
1583
1831
|
}
|
1584
|
-
}
|
1585
1832
|
|
1586
|
-
|
1833
|
+
return self;
|
1834
|
+
}
|
1587
1835
|
end
|
1588
1836
|
|
1589
1837
|
alias slice []
|
@@ -1610,7 +1858,7 @@ class Array
|
|
1610
1858
|
return self unless `self.length > 1`
|
1611
1859
|
|
1612
1860
|
%x{
|
1613
|
-
if (
|
1861
|
+
if (block === nil) {
|
1614
1862
|
block = function(a, b) {
|
1615
1863
|
return #{`a` <=> `b`};
|
1616
1864
|
};
|
@@ -1713,7 +1961,7 @@ class Array
|
|
1713
1961
|
}
|
1714
1962
|
key = ary[0];
|
1715
1963
|
val = ary[1];
|
1716
|
-
hash
|
1964
|
+
Opal.hash_put(hash, key, val);
|
1717
1965
|
}
|
1718
1966
|
|
1719
1967
|
return hash;
|
@@ -1750,47 +1998,51 @@ class Array
|
|
1750
1998
|
result
|
1751
1999
|
end
|
1752
2000
|
|
1753
|
-
def uniq
|
2001
|
+
def uniq(&block)
|
1754
2002
|
%x{
|
1755
|
-
var
|
1756
|
-
seen = {};
|
2003
|
+
var hash = #{{}}, i, length, item, key;
|
1757
2004
|
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
2005
|
+
if (block === nil) {
|
2006
|
+
for (i = 0, length = self.length; i < length; i++) {
|
2007
|
+
item = self[i];
|
2008
|
+
if (Opal.hash_get(hash, item) === undefined) {
|
2009
|
+
Opal.hash_put(hash, item, item);
|
2010
|
+
}
|
2011
|
+
}
|
2012
|
+
}
|
2013
|
+
else {
|
2014
|
+
for (i = 0, length = self.length; i < length; i++) {
|
2015
|
+
item = self[i];
|
2016
|
+
key = Opal.yield1(block, item);
|
2017
|
+
if (Opal.hash_get(hash, key) === undefined) {
|
2018
|
+
Opal.hash_put(hash, key, item);
|
2019
|
+
}
|
1766
2020
|
}
|
1767
2021
|
}
|
1768
2022
|
|
1769
|
-
return
|
2023
|
+
return hash.$values();
|
1770
2024
|
}
|
1771
2025
|
end
|
1772
2026
|
|
1773
|
-
def uniq!
|
2027
|
+
def uniq!(&block)
|
1774
2028
|
%x{
|
1775
|
-
var
|
1776
|
-
seen = {};
|
2029
|
+
var original_length = self.length, hash = #{{}}, i, length, item, key;
|
1777
2030
|
|
1778
|
-
for (
|
2031
|
+
for (i = 0, length = original_length; i < length; i++) {
|
1779
2032
|
item = self[i];
|
1780
|
-
|
2033
|
+
key = (block === nil ? item : Opal.yield1(block, item));
|
1781
2034
|
|
1782
|
-
if (
|
1783
|
-
|
2035
|
+
if (Opal.hash_get(hash, key) === undefined) {
|
2036
|
+
Opal.hash_put(hash, key, item);
|
2037
|
+
continue;
|
1784
2038
|
}
|
1785
|
-
else {
|
1786
|
-
self.splice(i, 1);
|
1787
2039
|
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
2040
|
+
self.splice(i, 1);
|
2041
|
+
length--;
|
2042
|
+
i--;
|
1791
2043
|
}
|
1792
2044
|
|
1793
|
-
return self.length ===
|
2045
|
+
return self.length === original_length ? nil : self;
|
1794
2046
|
}
|
1795
2047
|
end
|
1796
2048
|
|