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/opal/corelib/regexp.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
class RegexpError < StandardError; end
|
2
|
-
|
2
|
+
|
3
|
+
class Regexp < `RegExp`
|
3
4
|
IGNORECASE = 1
|
4
5
|
MULTILINE = 4
|
5
6
|
|
@@ -67,35 +68,30 @@ class Regexp
|
|
67
68
|
|
68
69
|
def new(regexp, options = undefined)
|
69
70
|
%x{
|
70
|
-
|
71
|
-
|
71
|
+
if (regexp.$$is_regexp) {
|
72
|
+
return new RegExp(regexp);
|
73
|
+
}
|
74
|
+
|
75
|
+
regexp = #{Opal.coerce_to!(regexp, String, :to_str)};
|
76
|
+
|
77
|
+
if (regexp.charAt(regexp.length - 1) === '\\') {
|
72
78
|
#{raise RegexpError, "too short escape sequence: /#{regexp}/"}
|
73
79
|
}
|
74
|
-
|
75
|
-
if (options
|
76
|
-
|
80
|
+
|
81
|
+
if (options === undefined || #{!options}) {
|
82
|
+
return new RegExp(regexp);
|
77
83
|
}
|
78
|
-
|
79
|
-
if (options
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
if (#{MULTILINE} & options) {
|
90
|
-
result += 'm';
|
91
|
-
}
|
92
|
-
options = result;
|
93
|
-
}
|
94
|
-
else {
|
95
|
-
options = 'i';
|
96
|
-
}
|
97
|
-
}
|
98
|
-
|
84
|
+
|
85
|
+
if (options.$$is_number) {
|
86
|
+
var temp = '';
|
87
|
+
if (#{IGNORECASE} & options) { temp += 'i'; }
|
88
|
+
if (#{MULTILINE} & options) { temp += 'm'; }
|
89
|
+
options = temp;
|
90
|
+
}
|
91
|
+
else {
|
92
|
+
options = 'i';
|
93
|
+
}
|
94
|
+
|
99
95
|
return new RegExp(regexp, options);
|
100
96
|
}
|
101
97
|
end
|
@@ -199,6 +195,139 @@ class Regexp
|
|
199
195
|
return result;
|
200
196
|
}
|
201
197
|
end
|
198
|
+
|
199
|
+
def casefold?
|
200
|
+
`self.ignoreCase`
|
201
|
+
end
|
202
202
|
|
203
203
|
alias to_s source
|
204
204
|
end
|
205
|
+
|
206
|
+
class MatchData
|
207
|
+
attr_reader :post_match, :pre_match, :regexp, :string
|
208
|
+
|
209
|
+
def initialize(regexp, match_groups)
|
210
|
+
$~ = self
|
211
|
+
@regexp = regexp
|
212
|
+
@begin = `match_groups.index`
|
213
|
+
@string = `match_groups.input`
|
214
|
+
@pre_match = `match_groups.input.slice(0, match_groups.index)`
|
215
|
+
@post_match = `match_groups.input.slice(match_groups.index + match_groups[0].length)`
|
216
|
+
@matches = []
|
217
|
+
|
218
|
+
%x{
|
219
|
+
for (var i = 0, length = match_groups.length; i < length; i++) {
|
220
|
+
var group = match_groups[i];
|
221
|
+
|
222
|
+
if (group == null) {
|
223
|
+
#@matches.push(nil);
|
224
|
+
}
|
225
|
+
else {
|
226
|
+
#@matches.push(group);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
end
|
231
|
+
|
232
|
+
def [](*args)
|
233
|
+
@matches[*args]
|
234
|
+
end
|
235
|
+
|
236
|
+
def offset(n)
|
237
|
+
%x{
|
238
|
+
if (n !== 0) {
|
239
|
+
#{raise ArgumentError, 'MatchData#offset only supports 0th element'}
|
240
|
+
}
|
241
|
+
return [self.begin, self.begin + self.matches[n].length];
|
242
|
+
}
|
243
|
+
end
|
244
|
+
|
245
|
+
def ==(other)
|
246
|
+
return false unless MatchData === other
|
247
|
+
|
248
|
+
`self.string == other.string` &&
|
249
|
+
`self.regexp.toString() == other.regexp.toString()` &&
|
250
|
+
`self.pre_match == other.pre_match` &&
|
251
|
+
`self.post_match == other.post_match` &&
|
252
|
+
`self.begin == other.begin`
|
253
|
+
end
|
254
|
+
|
255
|
+
alias eql? ==
|
256
|
+
|
257
|
+
def begin(n)
|
258
|
+
%x{
|
259
|
+
if (n !== 0) {
|
260
|
+
#{raise ArgumentError, 'MatchData#begin only supports 0th element'}
|
261
|
+
}
|
262
|
+
return self.begin;
|
263
|
+
}
|
264
|
+
end
|
265
|
+
|
266
|
+
def end(n)
|
267
|
+
%x{
|
268
|
+
if (n !== 0) {
|
269
|
+
#{raise ArgumentError, 'MatchData#end only supports 0th element'}
|
270
|
+
}
|
271
|
+
return self.begin + self.matches[n].length;
|
272
|
+
}
|
273
|
+
end
|
274
|
+
|
275
|
+
def captures
|
276
|
+
`#@matches.slice(1)`
|
277
|
+
end
|
278
|
+
|
279
|
+
def inspect
|
280
|
+
%x{
|
281
|
+
var str = "#<MatchData " + #{`#@matches[0]`.inspect};
|
282
|
+
|
283
|
+
for (var i = 1, length = #@matches.length; i < length; i++) {
|
284
|
+
str += " " + i + ":" + #{`#@matches[i]`.inspect};
|
285
|
+
}
|
286
|
+
|
287
|
+
return str + ">";
|
288
|
+
}
|
289
|
+
end
|
290
|
+
|
291
|
+
def length
|
292
|
+
`#@matches.length`
|
293
|
+
end
|
294
|
+
|
295
|
+
alias size length
|
296
|
+
|
297
|
+
def to_a
|
298
|
+
@matches
|
299
|
+
end
|
300
|
+
|
301
|
+
def to_s
|
302
|
+
`#@matches[0]`
|
303
|
+
end
|
304
|
+
|
305
|
+
def values_at(*args)
|
306
|
+
%x{
|
307
|
+
var i, a, index, values = [];
|
308
|
+
|
309
|
+
for (i = 0; i < args.length; i++) {
|
310
|
+
|
311
|
+
if (args[i].$$is_range) {
|
312
|
+
a = #{`args[i]`.to_a};
|
313
|
+
a.unshift(i, 1);
|
314
|
+
Array.prototype.splice.apply(args, a);
|
315
|
+
}
|
316
|
+
|
317
|
+
index = #{Opal.coerce_to!(`args[i]`, Integer, :to_int)};
|
318
|
+
|
319
|
+
if (index < 0) {
|
320
|
+
index += #@matches.length;
|
321
|
+
if (index < 0) {
|
322
|
+
values.push(nil);
|
323
|
+
continue;
|
324
|
+
}
|
325
|
+
}
|
326
|
+
|
327
|
+
values.push(#@matches[index]);
|
328
|
+
}
|
329
|
+
|
330
|
+
return values;
|
331
|
+
}
|
332
|
+
end
|
333
|
+
end
|
data/opal/corelib/runtime.js
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
var Opal = this.Opal = {};
|
9
9
|
|
10
10
|
// All bridged classes - keep track to donate methods from Object
|
11
|
-
var
|
11
|
+
var bridges = {};
|
12
12
|
|
13
13
|
// TopScope is used for inheriting constants from the top scope
|
14
14
|
var TopScope = function(){};
|
@@ -51,6 +51,9 @@
|
|
51
51
|
// Exit function, this should be replaced by platform specific implementation
|
52
52
|
// (See nodejs and phantom for examples)
|
53
53
|
Opal.exit = function(status) { if (Opal.gvars.DEBUG) console.log('Exited with status '+status); };
|
54
|
+
|
55
|
+
// keeps track of exceptions for $!
|
56
|
+
Opal.exceptions = [];
|
54
57
|
|
55
58
|
/**
|
56
59
|
Get a constant on the given scope. Every class and module in Opal has a
|
@@ -72,7 +75,7 @@
|
|
72
75
|
var constant = this[name];
|
73
76
|
|
74
77
|
if (constant == null) {
|
75
|
-
return this.base.$
|
78
|
+
return this.base.$const_get(name);
|
76
79
|
}
|
77
80
|
|
78
81
|
return constant;
|
@@ -95,9 +98,7 @@
|
|
95
98
|
const_scope.constants = [];
|
96
99
|
|
97
100
|
if (id) {
|
98
|
-
|
99
|
-
base[id] = base.constructor[id] = klass;
|
100
|
-
base.constants.push(id);
|
101
|
+
Opal.cdecl(base, id, klass)
|
101
102
|
}
|
102
103
|
}
|
103
104
|
|
@@ -130,46 +131,54 @@
|
|
130
131
|
*/
|
131
132
|
Opal.klass = function(base, superklass, id, constructor) {
|
132
133
|
// If base is an object, use its class
|
133
|
-
if (!base.$$is_class) {
|
134
|
+
if (!base.$$is_class && !base.$$is_module) {
|
134
135
|
base = base.$$class;
|
135
136
|
}
|
136
137
|
|
137
|
-
|
138
|
-
|
139
|
-
superklass = ObjectClass;
|
140
|
-
}
|
141
|
-
|
142
|
-
var klass = base.$$scope[id];
|
138
|
+
var klass = base.$$scope[id],
|
139
|
+
bridged = typeof(superklass) === 'function';
|
143
140
|
|
144
|
-
// If
|
145
|
-
if (
|
141
|
+
// If the class exists in the scope, then we must use that
|
142
|
+
if (klass && klass.$$orig_scope === base.$$scope) {
|
146
143
|
// Make sure the existing constant is a class, or raise error
|
147
144
|
if (!klass.$$is_class) {
|
148
145
|
throw Opal.TypeError.$new(id + " is not a class");
|
149
146
|
}
|
150
147
|
|
151
148
|
// Make sure existing class has same superclass
|
152
|
-
if (superklass
|
149
|
+
if (superklass && klass.$$super !== superklass) {
|
153
150
|
throw Opal.TypeError.$new("superclass mismatch for class " + id);
|
154
151
|
}
|
152
|
+
|
153
|
+
return klass;
|
155
154
|
}
|
156
|
-
|
157
|
-
|
158
|
-
|
155
|
+
|
156
|
+
// Not specifying a superclass means we can assume it to be Object
|
157
|
+
if (superklass === null) {
|
158
|
+
superklass = ObjectClass;
|
159
159
|
}
|
160
|
-
else {
|
161
|
-
// if class doesnt exist, create a new one with given superclass
|
162
|
-
klass = boot_class(superklass, constructor);
|
163
160
|
|
164
|
-
|
165
|
-
|
161
|
+
// if class doesnt exist, create a new one with given superclass
|
162
|
+
klass = bridged ?
|
163
|
+
boot_class_object(ObjectClass, superklass) :
|
164
|
+
boot_class(superklass, constructor);
|
165
|
+
|
166
|
+
// name class using base (e.g. Foo or Foo::Baz)
|
167
|
+
klass.$$name = id;
|
166
168
|
|
167
|
-
|
168
|
-
|
169
|
+
// mark the object as a class
|
170
|
+
klass.$$is_class = true;
|
169
171
|
|
170
|
-
|
171
|
-
|
172
|
+
// every class gets its own constant scope, inherited from current scope
|
173
|
+
create_scope(base.$$scope, klass, id);
|
172
174
|
|
175
|
+
// Name new class directly onto current scope (Opal.Foo.Baz = klass)
|
176
|
+
base[id] = base.$$scope[id] = klass;
|
177
|
+
|
178
|
+
if (bridged) {
|
179
|
+
Opal.bridge(klass, superklass);
|
180
|
+
}
|
181
|
+
else {
|
173
182
|
// Copy all parent constants to child, unless parent is Object
|
174
183
|
if (superklass !== ObjectClass && superklass !== BasicObjectClass) {
|
175
184
|
donate_constants(superklass, klass);
|
@@ -256,8 +265,16 @@
|
|
256
265
|
// Maybe there are some browsers not abiding (IE6?)
|
257
266
|
module.constructor = constructor;
|
258
267
|
|
259
|
-
|
260
|
-
|
268
|
+
if (superklass === ModuleClass) {
|
269
|
+
// @property $$is_module Clearly mark this as a module
|
270
|
+
module.$$is_module = true;
|
271
|
+
module.$$class = ModuleClass;
|
272
|
+
}
|
273
|
+
else {
|
274
|
+
// @property $$is_class Clearly mark this as a class
|
275
|
+
module.$$is_class = true;
|
276
|
+
module.$$class = ClassClass;
|
277
|
+
}
|
261
278
|
|
262
279
|
// @property $$super the superclass, doesn't get changed by module inclusions
|
263
280
|
module.$$super = superklass;
|
@@ -267,12 +284,6 @@
|
|
267
284
|
// the last included module
|
268
285
|
module.$$parent = superklass;
|
269
286
|
|
270
|
-
// @property $$methods keeps track of methods defined on the class
|
271
|
-
// but seems to be used just by `define_basic_object_method`
|
272
|
-
// and for donating (Ruby) Object methods to bridged classes
|
273
|
-
// TODO: check if it can be removed
|
274
|
-
module.$$methods = [];
|
275
|
-
|
276
287
|
// @property $$inc included modules
|
277
288
|
module.$$inc = [];
|
278
289
|
}
|
@@ -300,21 +311,29 @@
|
|
300
311
|
Opal.module = function(base, id) {
|
301
312
|
var module;
|
302
313
|
|
303
|
-
if (!base.$$is_class) {
|
314
|
+
if (!base.$$is_class && !base.$$is_module) {
|
304
315
|
base = base.$$class;
|
305
316
|
}
|
306
317
|
|
307
318
|
if ($hasOwn.call(base.$$scope, id)) {
|
308
319
|
module = base.$$scope[id];
|
309
320
|
|
310
|
-
if (!module.$$
|
321
|
+
if (!module.$$is_module && module !== ObjectClass) {
|
311
322
|
throw Opal.TypeError.$new(id + " is not a module");
|
312
323
|
}
|
313
324
|
}
|
314
325
|
else {
|
315
326
|
module = boot_module_object();
|
327
|
+
|
328
|
+
// name module using base (e.g. Foo or Foo::Baz)
|
316
329
|
module.$$name = id;
|
317
330
|
|
331
|
+
// mark the object as a module
|
332
|
+
module.$$is_module = true;
|
333
|
+
|
334
|
+
// initialize dependency tracking
|
335
|
+
module.$$dep = [];
|
336
|
+
|
318
337
|
create_scope(base.$$scope, module, id);
|
319
338
|
|
320
339
|
// Name new module directly onto current scope (Opal.Foo.Baz = module)
|
@@ -340,9 +359,6 @@
|
|
340
359
|
|
341
360
|
setup_module_or_class_object(module, module_constructor, ModuleClass, module_prototype);
|
342
361
|
|
343
|
-
module.$$is_mod = true;
|
344
|
-
module.$$dep = [];
|
345
|
-
|
346
362
|
return module;
|
347
363
|
}
|
348
364
|
|
@@ -364,7 +380,7 @@
|
|
364
380
|
return object.$$meta;
|
365
381
|
}
|
366
382
|
|
367
|
-
if (object.$$is_class) {
|
383
|
+
if (object.$$is_class || object.$$is_module) {
|
368
384
|
return build_class_singleton_class(object);
|
369
385
|
}
|
370
386
|
|
@@ -381,14 +397,14 @@
|
|
381
397
|
@returns [RubyClass]
|
382
398
|
*/
|
383
399
|
function build_class_singleton_class(klass) {
|
384
|
-
var meta = new Opal.Class.$$alloc;
|
400
|
+
var meta = new Opal.Class.$$alloc();
|
385
401
|
|
386
402
|
meta.$$class = Opal.Class;
|
387
403
|
meta.$$proto = klass.constructor.prototype;
|
388
404
|
|
389
405
|
meta.$$is_singleton = true;
|
406
|
+
meta.$$singleton_of = klass;
|
390
407
|
meta.$$inc = [];
|
391
|
-
meta.$$methods = [];
|
392
408
|
meta.$$scope = klass.$$scope;
|
393
409
|
|
394
410
|
return klass.$$meta = meta;
|
@@ -412,9 +428,95 @@
|
|
412
428
|
meta.$$class = orig_class.$$class;
|
413
429
|
meta.$$scope = orig_class.$$scope;
|
414
430
|
meta.$$parent = orig_class;
|
431
|
+
meta.$$is_singleton = true;
|
432
|
+
meta.$$singleton_of = object;
|
433
|
+
|
415
434
|
return object.$$meta = meta;
|
416
435
|
}
|
417
436
|
|
437
|
+
/**
|
438
|
+
The actual inclusion of a module into a class.
|
439
|
+
|
440
|
+
## Class `$$parent` and `iclass`
|
441
|
+
|
442
|
+
To handle `super` calls, every class has a `$$parent`. This parent is
|
443
|
+
used to resolve the next class for a super call. A normal class would
|
444
|
+
have this point to its superclass. However, if a class includes a module
|
445
|
+
then this would need to take into account the module. The module would
|
446
|
+
also have to then point its `$$parent` to the actual superclass. We
|
447
|
+
cannot modify modules like this, because it might be included in more
|
448
|
+
then one class. To fix this, we actually insert an `iclass` as the class'
|
449
|
+
`$$parent` which can then point to the superclass. The `iclass` acts as
|
450
|
+
a proxy to the actual module, so the `super` chain can then search it for
|
451
|
+
the required method.
|
452
|
+
|
453
|
+
@param [RubyModule] module the module to include
|
454
|
+
@param [RubyClass] klass the target class to include module into
|
455
|
+
@returns [null]
|
456
|
+
*/
|
457
|
+
function bridge() {
|
458
|
+
var target, donator, from, name, body, ancestors, id, methods, method, i, ancestor, bridged, length;
|
459
|
+
|
460
|
+
if (arguments.length === 4) {
|
461
|
+
target = arguments[0];
|
462
|
+
from = arguments[1];
|
463
|
+
name = arguments[2];
|
464
|
+
body = arguments[3];
|
465
|
+
ancestors = target.$$bridge.$ancestors();
|
466
|
+
|
467
|
+
// order important here, we have to check for method presence in
|
468
|
+
// ancestors from the bridged class to the last ancestor
|
469
|
+
for (i = 0, length = ancestors.length; i < length; i++) {
|
470
|
+
ancestor = ancestors[i];
|
471
|
+
|
472
|
+
if ($hasOwn.call(ancestor.$$proto, name) &&
|
473
|
+
ancestor.$$proto[name] &&
|
474
|
+
!ancestor.$$proto[name].$$donated &&
|
475
|
+
!ancestor.$$proto[name].$$stub &&
|
476
|
+
ancestor !== from) {
|
477
|
+
break;
|
478
|
+
}
|
479
|
+
|
480
|
+
if (ancestor === from) {
|
481
|
+
target.prototype[name] = body
|
482
|
+
break;
|
483
|
+
}
|
484
|
+
}
|
485
|
+
}
|
486
|
+
else {
|
487
|
+
target = arguments[0];
|
488
|
+
donator = arguments[1];
|
489
|
+
|
490
|
+
if (typeof(target) === "function") {
|
491
|
+
id = donator.$__id__();
|
492
|
+
methods = donator.$instance_methods();
|
493
|
+
|
494
|
+
for (i = methods.length - 1; i >= 0; i--) {
|
495
|
+
method = '$' + methods[i];
|
496
|
+
|
497
|
+
bridge(target, donator, method, donator.$$proto[method]);
|
498
|
+
}
|
499
|
+
|
500
|
+
if (!bridges[id]) {
|
501
|
+
bridges[id] = [];
|
502
|
+
}
|
503
|
+
|
504
|
+
bridges[id].push(target);
|
505
|
+
}
|
506
|
+
else {
|
507
|
+
bridged = bridges[target.$__id__()];
|
508
|
+
|
509
|
+
if (bridged) {
|
510
|
+
for (i = bridged.length - 1; i >= 0; i--) {
|
511
|
+
bridge(bridged[i], donator);
|
512
|
+
}
|
513
|
+
|
514
|
+
bridges[donator.$__id__()] = bridged.slice();
|
515
|
+
}
|
516
|
+
}
|
517
|
+
}
|
518
|
+
}
|
519
|
+
|
418
520
|
/**
|
419
521
|
The actual inclusion of a module into a class.
|
420
522
|
|
@@ -436,20 +538,21 @@
|
|
436
538
|
@returns [null]
|
437
539
|
*/
|
438
540
|
Opal.append_features = function(module, klass) {
|
439
|
-
var
|
541
|
+
var iclass, donator, prototype, methods, id, i;
|
440
542
|
|
441
|
-
// check if this module is already included in the
|
442
|
-
for (
|
443
|
-
if (
|
543
|
+
// check if this module is already included in the class
|
544
|
+
for (i = klass.$$inc.length - 1; i >= 0; i--) {
|
545
|
+
if (klass.$$inc[i] === module) {
|
444
546
|
return;
|
445
547
|
}
|
446
548
|
}
|
447
549
|
|
448
|
-
|
550
|
+
klass.$$inc.push(module);
|
449
551
|
module.$$dep.push(klass);
|
552
|
+
bridge(klass, module);
|
450
553
|
|
451
554
|
// iclass
|
452
|
-
|
555
|
+
iclass = {
|
453
556
|
$$name: module.$$name,
|
454
557
|
$$proto: module.$$proto,
|
455
558
|
$$parent: klass.$$parent,
|
@@ -459,28 +562,24 @@
|
|
459
562
|
|
460
563
|
klass.$$parent = iclass;
|
461
564
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
for (var i = 0, length = methods.length; i < length; i++) {
|
467
|
-
var method = methods[i], current;
|
565
|
+
donator = module.$$proto;
|
566
|
+
prototype = klass.$$proto;
|
567
|
+
methods = module.$instance_methods();
|
468
568
|
|
569
|
+
for (i = methods.length - 1; i >= 0; i--) {
|
570
|
+
id = '$' + methods[i];
|
469
571
|
|
470
|
-
if
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
prototype[method] = donator[method];
|
478
|
-
prototype[method].$$donated = true;
|
572
|
+
// if the target class already has a method of the same name defined
|
573
|
+
// and that method was NOT donated, then it must be a method defined
|
574
|
+
// by the class so we do not want to override it
|
575
|
+
if ( prototype.hasOwnProperty(id) &&
|
576
|
+
!prototype[id].$$donated &&
|
577
|
+
!prototype[id].$$stub) {
|
578
|
+
continue;
|
479
579
|
}
|
480
|
-
}
|
481
580
|
|
482
|
-
|
483
|
-
|
581
|
+
prototype[id] = donator[id];
|
582
|
+
prototype[id].$$donated = module;
|
484
583
|
}
|
485
584
|
|
486
585
|
donate_constants(module, klass);
|
@@ -540,68 +639,80 @@
|
|
540
639
|
}
|
541
640
|
|
542
641
|
/*
|
543
|
-
* For performance, some core
|
544
|
-
* native
|
642
|
+
* For performance, some core Ruby classes are toll-free bridged to their
|
643
|
+
* native JavaScript counterparts (e.g. a Ruby Array is a JavaScript Array).
|
545
644
|
*
|
546
645
|
* This method is used to setup a native constructor (e.g. Array), to have
|
547
|
-
* its prototype act like a normal
|
646
|
+
* its prototype act like a normal Ruby class. Firstly, a new Ruby class is
|
548
647
|
* created using the native constructor so that its prototype is set as the
|
549
648
|
* target for th new class. Note: all bridged classes are set to inherit
|
550
649
|
* from Object.
|
551
650
|
*
|
552
|
-
* Bridged classes are tracked in `bridged_classes` array so that methods
|
553
|
-
* defined on Object can be "donated" to all bridged classes. This allows
|
554
|
-
* us to fake the inheritance of a native prototype from our Object
|
555
|
-
* prototype.
|
556
|
-
*
|
557
651
|
* Example:
|
558
652
|
*
|
559
|
-
*
|
653
|
+
* Opal.bridge(self, Function);
|
560
654
|
*
|
561
|
-
* @param [
|
562
|
-
* @param [Function] constructor native
|
563
|
-
* @
|
564
|
-
* @return [Class] returns new ruby class
|
655
|
+
* @param [Class] klass the Ruby class to bridge
|
656
|
+
* @param [Function] constructor native JavaScript constructor to use
|
657
|
+
* @return [Class] returns the passed Ruby class
|
565
658
|
*/
|
566
|
-
function
|
567
|
-
|
568
|
-
|
569
|
-
klass.$$name = name;
|
570
|
-
|
571
|
-
if (base === undefined) {
|
572
|
-
base = Opal;
|
573
|
-
}
|
574
|
-
else {
|
575
|
-
base = base.$$scope;
|
659
|
+
Opal.bridge = function(klass, constructor) {
|
660
|
+
if (constructor.$$bridge) {
|
661
|
+
throw Opal.ArgumentError.$new("already bridged");
|
576
662
|
}
|
577
663
|
|
578
|
-
|
579
|
-
|
664
|
+
Opal.stub_subscribers.push(constructor.prototype);
|
665
|
+
|
666
|
+
constructor.prototype.$$class = klass;
|
667
|
+
constructor.$$bridge = klass;
|
580
668
|
|
581
|
-
var
|
669
|
+
var ancestors = klass.$ancestors();
|
582
670
|
|
583
|
-
|
584
|
-
|
585
|
-
|
671
|
+
// order important here, we have to bridge from the last ancestor to the
|
672
|
+
// bridged class
|
673
|
+
for (var i = ancestors.length - 1; i >= 0; i--) {
|
674
|
+
bridge(constructor, ancestors[i]);
|
586
675
|
}
|
587
676
|
|
588
|
-
|
677
|
+
for (var name in BasicObject.prototype) {
|
678
|
+
var method = BasicObject.prototype[method];
|
679
|
+
|
680
|
+
if (method && method.$$stub && !(name in constructor.prototype)) {
|
681
|
+
constructor.prototype[name] = method;
|
682
|
+
}
|
683
|
+
}
|
589
684
|
|
590
685
|
return klass;
|
591
686
|
}
|
592
687
|
|
688
|
+
|
593
689
|
/*
|
594
690
|
* constant assign
|
595
691
|
*/
|
596
692
|
Opal.casgn = function(base_module, name, value) {
|
597
|
-
|
693
|
+
function update(klass, name) {
|
694
|
+
klass.$$name = name;
|
598
695
|
|
599
|
-
|
600
|
-
|
696
|
+
for (name in klass.$$scope) {
|
697
|
+
var value = klass.$$scope[name];
|
698
|
+
|
699
|
+
if (value.$$name === nil && (value.$$is_class || value.$$is_module)) {
|
700
|
+
update(value, name)
|
701
|
+
}
|
702
|
+
}
|
601
703
|
}
|
602
704
|
|
603
|
-
|
604
|
-
|
705
|
+
var scope = base_module.$$scope;
|
706
|
+
|
707
|
+
if (value.$$is_class || value.$$is_module) {
|
708
|
+
// only checking ObjectClass prevents setting a const on an anonymous class that has a superclass that's not Object
|
709
|
+
if (value.$$is_class || value.$$base_module === ObjectClass) {
|
710
|
+
value.$$base_module = base_module;
|
711
|
+
}
|
712
|
+
|
713
|
+
if (value.$$name === nil && value.$$base_module.$$name !== nil) {
|
714
|
+
update(value, name);
|
715
|
+
}
|
605
716
|
}
|
606
717
|
|
607
718
|
scope.constants.push(name);
|
@@ -612,6 +723,12 @@
|
|
612
723
|
* constant decl
|
613
724
|
*/
|
614
725
|
Opal.cdecl = function(base_scope, name, value) {
|
726
|
+
if ((value.$$is_class || value.$$is_module) && value.$$orig_scope == null) {
|
727
|
+
value.$$name = name;
|
728
|
+
value.$$orig_scope = base_scope;
|
729
|
+
base_scope.constructor[name] = value;
|
730
|
+
}
|
731
|
+
|
615
732
|
base_scope.constants.push(name);
|
616
733
|
return base_scope[name] = value;
|
617
734
|
};
|
@@ -631,6 +748,60 @@
|
|
631
748
|
}
|
632
749
|
};
|
633
750
|
|
751
|
+
/*
|
752
|
+
* Donate methods for a module.
|
753
|
+
*/
|
754
|
+
function donate(module, jsid) {
|
755
|
+
var included_in = module.$$dep,
|
756
|
+
body = module.$$proto[jsid],
|
757
|
+
i, length, includee, dest, current,
|
758
|
+
klass_includees, j, jj, current_owner_index, module_index;
|
759
|
+
|
760
|
+
if (!included_in) {
|
761
|
+
return;
|
762
|
+
}
|
763
|
+
|
764
|
+
for (i = 0, length = included_in.length; i < length; i++) {
|
765
|
+
includee = included_in[i];
|
766
|
+
dest = includee.$$proto;
|
767
|
+
current = dest[jsid];
|
768
|
+
|
769
|
+
if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
|
770
|
+
// target class has already defined the same method name - do nothing
|
771
|
+
}
|
772
|
+
else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
|
773
|
+
// target class includes another module that has defined this method
|
774
|
+
klass_includees = includee.$$inc;
|
775
|
+
|
776
|
+
for (j = 0, jj = klass_includees.length; j < jj; j++) {
|
777
|
+
if (klass_includees[j] === current.$$donated) {
|
778
|
+
current_owner_index = j;
|
779
|
+
}
|
780
|
+
if (klass_includees[j] === module) {
|
781
|
+
module_index = j;
|
782
|
+
}
|
783
|
+
}
|
784
|
+
|
785
|
+
// only redefine method on class if the module was included AFTER
|
786
|
+
// the module which defined the current method body. Also make sure
|
787
|
+
// a module can overwrite a method it defined before
|
788
|
+
if (current_owner_index <= module_index) {
|
789
|
+
dest[jsid] = body;
|
790
|
+
dest[jsid].$$donated = module;
|
791
|
+
}
|
792
|
+
}
|
793
|
+
else {
|
794
|
+
// neither a class, or module included by class, has defined method
|
795
|
+
dest[jsid] = body;
|
796
|
+
dest[jsid].$$donated = module;
|
797
|
+
}
|
798
|
+
|
799
|
+
if (includee.$$dep) {
|
800
|
+
donate(includee, jsid);
|
801
|
+
}
|
802
|
+
}
|
803
|
+
};
|
804
|
+
|
634
805
|
/*
|
635
806
|
* Methods stubs are used to facilitate method_missing in opal. A stub is a
|
636
807
|
* placeholder function which just calls `method_missing` on the receiver.
|
@@ -660,14 +831,18 @@
|
|
660
831
|
* @param [Array] stubs an array of method stubs to add
|
661
832
|
*/
|
662
833
|
Opal.add_stubs = function(stubs) {
|
663
|
-
var subscribers = Opal.stub_subscribers
|
664
|
-
|
834
|
+
var subscriber, subscribers = Opal.stub_subscribers,
|
835
|
+
i, ilength = stubs.length,
|
836
|
+
j, jlength = subscribers.length,
|
837
|
+
method_name, stub;
|
665
838
|
|
666
|
-
for (
|
667
|
-
|
839
|
+
for (i = 0; i < ilength; i++) {
|
840
|
+
method_name = stubs[i];
|
841
|
+
stub = stub_for(method_name);
|
668
842
|
|
669
|
-
for (
|
843
|
+
for (j = 0; j < jlength; j++) {
|
670
844
|
subscriber = subscribers[j];
|
845
|
+
|
671
846
|
if (!(method_name in subscriber)) {
|
672
847
|
subscriber[method_name] = stub;
|
673
848
|
}
|
@@ -675,17 +850,6 @@
|
|
675
850
|
}
|
676
851
|
};
|
677
852
|
|
678
|
-
/*
|
679
|
-
* Add a prototype to the subscribers list, and (TODO) add previously stubbed
|
680
|
-
* methods.
|
681
|
-
*
|
682
|
-
* @param [Prototype]
|
683
|
-
*/
|
684
|
-
function add_stubs_subscriber(prototype) {
|
685
|
-
// TODO: Add previously stubbed methods too.
|
686
|
-
Opal.stub_subscribers.push(prototype);
|
687
|
-
}
|
688
|
-
|
689
853
|
/*
|
690
854
|
* Keep a list of prototypes that want method_missing stubs to be added.
|
691
855
|
*
|
@@ -732,9 +896,16 @@
|
|
732
896
|
|
733
897
|
// Arity count error dispatcher
|
734
898
|
Opal.ac = function(actual, expected, object, meth) {
|
735
|
-
var inspect =
|
736
|
-
|
737
|
-
|
899
|
+
var inspect = '';
|
900
|
+
if (object.$$is_class || object.$$is_module) {
|
901
|
+
inspect += object.$$name + '.';
|
902
|
+
}
|
903
|
+
else {
|
904
|
+
inspect += object.$$class.$$name + '#';
|
905
|
+
}
|
906
|
+
inspect += meth;
|
907
|
+
|
908
|
+
throw Opal.ArgumentError.$new('[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')');
|
738
909
|
};
|
739
910
|
|
740
911
|
// Super dispatcher
|
@@ -742,10 +913,15 @@
|
|
742
913
|
var dispatcher;
|
743
914
|
|
744
915
|
if (defs) {
|
745
|
-
|
916
|
+
if (obj.$$is_class || obj.$$is_module) {
|
917
|
+
dispatcher = defs.$$super;
|
918
|
+
}
|
919
|
+
else {
|
920
|
+
dispatcher = obj.$$class.$$proto;
|
921
|
+
}
|
746
922
|
}
|
747
923
|
else {
|
748
|
-
if (obj.$$is_class) {
|
924
|
+
if (obj.$$is_class || obj.$$is_module) {
|
749
925
|
dispatcher = obj.$$super;
|
750
926
|
}
|
751
927
|
else {
|
@@ -837,7 +1013,7 @@
|
|
837
1013
|
throw Opal.LocalJumpError.$new("no block given");
|
838
1014
|
}
|
839
1015
|
|
840
|
-
if (block.length > 1 && args.length
|
1016
|
+
if (block.length > 1 && args.length === 1) {
|
841
1017
|
if (args[0].$$is_array) {
|
842
1018
|
return block.apply(null, args[0]);
|
843
1019
|
}
|
@@ -884,7 +1060,7 @@
|
|
884
1060
|
}
|
885
1061
|
|
886
1062
|
for (var i = 0, length = search.$$inc.length; i < length; i++) {
|
887
|
-
if (search.$$inc[i]
|
1063
|
+
if (search.$$inc[i] === klass) {
|
888
1064
|
return true;
|
889
1065
|
}
|
890
1066
|
}
|
@@ -903,8 +1079,21 @@
|
|
903
1079
|
else if (value.$to_ary && !value.$to_ary.$$stub) {
|
904
1080
|
return value.$to_ary();
|
905
1081
|
}
|
1082
|
+
else {
|
1083
|
+
return [value];
|
1084
|
+
}
|
1085
|
+
};
|
906
1086
|
|
907
|
-
|
1087
|
+
Opal.to_a = function(value) {
|
1088
|
+
if (value == null || value === nil) {
|
1089
|
+
return [];
|
1090
|
+
}
|
1091
|
+
else if (value.$to_a && !value.$to_a.$$stub) {
|
1092
|
+
return value.$to_a();
|
1093
|
+
}
|
1094
|
+
else {
|
1095
|
+
return [value];
|
1096
|
+
}
|
908
1097
|
};
|
909
1098
|
|
910
1099
|
/**
|
@@ -973,103 +1162,6 @@
|
|
973
1162
|
return recv.$method_missing.apply(recv, [mid].concat(args));
|
974
1163
|
};
|
975
1164
|
|
976
|
-
/*
|
977
|
-
* Donate methods for a class/module
|
978
|
-
*/
|
979
|
-
function donate_methods(klass, defined, indirect) {
|
980
|
-
var methods = klass.$$methods, included_in = klass.$$dep;
|
981
|
-
|
982
|
-
// if (!indirect) {
|
983
|
-
klass.$$methods = methods.concat(defined);
|
984
|
-
// }
|
985
|
-
|
986
|
-
if (included_in) {
|
987
|
-
for (var i = 0, length = included_in.length; i < length; i++) {
|
988
|
-
var includee = included_in[i];
|
989
|
-
var dest = includee.$$proto;
|
990
|
-
|
991
|
-
for (var j = 0, jj = defined.length; j < jj; j++) {
|
992
|
-
var method = defined[j];
|
993
|
-
|
994
|
-
dest[method] = klass.$$proto[method];
|
995
|
-
dest[method].$$donated = true;
|
996
|
-
}
|
997
|
-
|
998
|
-
if (includee.$$dep) {
|
999
|
-
donate_methods(includee, defined, true);
|
1000
|
-
}
|
1001
|
-
}
|
1002
|
-
}
|
1003
|
-
};
|
1004
|
-
|
1005
|
-
/**
|
1006
|
-
Define the given method on the module.
|
1007
|
-
|
1008
|
-
This also handles donating methods to all classes that include this
|
1009
|
-
module. Method conflicts are also handled here, where a class might already
|
1010
|
-
have defined a method of the same name, or another included module defined
|
1011
|
-
the same method.
|
1012
|
-
|
1013
|
-
@param [RubyModule] module the module method defined on
|
1014
|
-
@param [String] jsid javascript friendly method name (e.g. "$foo")
|
1015
|
-
@param [Function] body method body of actual function
|
1016
|
-
*/
|
1017
|
-
function define_module_method(module, jsid, body) {
|
1018
|
-
module.$$proto[jsid] = body;
|
1019
|
-
body.$$owner = module;
|
1020
|
-
|
1021
|
-
module.$$methods.push(jsid);
|
1022
|
-
|
1023
|
-
if (module.$$module_function) {
|
1024
|
-
module[jsid] = body;
|
1025
|
-
}
|
1026
|
-
|
1027
|
-
var included_in = module.$$dep;
|
1028
|
-
|
1029
|
-
if (included_in) {
|
1030
|
-
for (var i = 0, length = included_in.length; i < length; i++) {
|
1031
|
-
var includee = included_in[i];
|
1032
|
-
var dest = includee.$$proto;
|
1033
|
-
var current = dest[jsid];
|
1034
|
-
|
1035
|
-
|
1036
|
-
if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
|
1037
|
-
// target class has already defined the same method name - do nothing
|
1038
|
-
}
|
1039
|
-
else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
|
1040
|
-
// target class includes another module that has defined this method
|
1041
|
-
var klass_includees = includee.$$inc;
|
1042
|
-
|
1043
|
-
for (var j = 0, jj = klass_includees.length; j < jj; j++) {
|
1044
|
-
if (klass_includees[j] === current.$$owner) {
|
1045
|
-
var current_owner_index = j;
|
1046
|
-
}
|
1047
|
-
if (klass_includees[j] === module) {
|
1048
|
-
var module_index = j;
|
1049
|
-
}
|
1050
|
-
}
|
1051
|
-
|
1052
|
-
// only redefine method on class if the module was included AFTER
|
1053
|
-
// the module which defined the current method body. Also make sure
|
1054
|
-
// a module can overwrite a method it defined before
|
1055
|
-
if (current_owner_index <= module_index) {
|
1056
|
-
dest[jsid] = body;
|
1057
|
-
dest[jsid].$$donated = true;
|
1058
|
-
}
|
1059
|
-
}
|
1060
|
-
else {
|
1061
|
-
// neither a class, or module included by class, has defined method
|
1062
|
-
dest[jsid] = body;
|
1063
|
-
dest[jsid].$$donated = true;
|
1064
|
-
}
|
1065
|
-
|
1066
|
-
if (includee.$$dep) {
|
1067
|
-
donate_methods(includee, [jsid], true);
|
1068
|
-
}
|
1069
|
-
}
|
1070
|
-
}
|
1071
|
-
}
|
1072
|
-
|
1073
1165
|
/**
|
1074
1166
|
Used to define methods on an object. This is a helper method, used by the
|
1075
1167
|
compiled source to define methods on special case objects when the compiler
|
@@ -1108,21 +1200,33 @@
|
|
1108
1200
|
@returns [null]
|
1109
1201
|
*/
|
1110
1202
|
Opal.defn = function(obj, jsid, body) {
|
1111
|
-
|
1112
|
-
define_module_method(obj, jsid, body);
|
1113
|
-
}
|
1114
|
-
else if (obj.$$is_class) {
|
1115
|
-
obj.$$proto[jsid] = body;
|
1203
|
+
obj.$$proto[jsid] = body;
|
1116
1204
|
|
1117
|
-
|
1118
|
-
|
1205
|
+
if (obj.$$is_module) {
|
1206
|
+
donate(obj, jsid);
|
1207
|
+
|
1208
|
+
if (obj.$$module_function) {
|
1209
|
+
Opal.defs(obj, jsid, body);
|
1119
1210
|
}
|
1120
|
-
|
1121
|
-
|
1211
|
+
}
|
1212
|
+
|
1213
|
+
if (obj.$__id__ && !obj.$__id__.$$stub) {
|
1214
|
+
var bridged = bridges[obj.$__id__()];
|
1215
|
+
|
1216
|
+
if (bridged) {
|
1217
|
+
for (var i = bridged.length - 1; i >= 0; i--) {
|
1218
|
+
bridge(bridged[i], obj, jsid, body);
|
1219
|
+
}
|
1122
1220
|
}
|
1123
1221
|
}
|
1124
|
-
|
1125
|
-
|
1222
|
+
|
1223
|
+
if (obj.$method_added && !obj.$method_added.$$stub) {
|
1224
|
+
obj.$method_added(jsid.substr(1));
|
1225
|
+
}
|
1226
|
+
|
1227
|
+
var singleton_of = obj.$$singleton_of;
|
1228
|
+
if (singleton_of && singleton_of.$singleton_method_added && !singleton_of.$singleton_method_added.$$stub) {
|
1229
|
+
singleton_of.$singleton_method_added(jsid.substr(1));
|
1126
1230
|
}
|
1127
1231
|
|
1128
1232
|
return nil;
|
@@ -1132,105 +1236,381 @@
|
|
1132
1236
|
* Define a singleton method on the given object.
|
1133
1237
|
*/
|
1134
1238
|
Opal.defs = function(obj, jsid, body) {
|
1135
|
-
|
1136
|
-
|
1239
|
+
Opal.defn(Opal.get_singleton_class(obj), jsid, body)
|
1240
|
+
};
|
1241
|
+
|
1242
|
+
Opal.def = function(obj, jsid, body) {
|
1243
|
+
// if instance_eval is invoked on a module/class, it sets inst_eval_mod
|
1244
|
+
if (!obj.$$eval && (obj.$$is_class || obj.$$is_module)) {
|
1245
|
+
Opal.defn(obj, jsid, body);
|
1137
1246
|
}
|
1138
1247
|
else {
|
1139
|
-
obj
|
1248
|
+
Opal.defs(obj, jsid, body);
|
1140
1249
|
}
|
1141
1250
|
};
|
1142
1251
|
|
1143
|
-
|
1144
|
-
|
1145
|
-
|
1146
|
-
|
1252
|
+
/*
|
1253
|
+
* Called from #remove_method.
|
1254
|
+
*/
|
1255
|
+
Opal.rdef = function(obj, jsid) {
|
1256
|
+
// TODO: remove from bridges as well
|
1257
|
+
|
1258
|
+
if (!$hasOwn.call(obj.$$proto, jsid)) {
|
1259
|
+
throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
|
1147
1260
|
}
|
1148
|
-
|
1261
|
+
|
1262
|
+
delete obj.$$proto[jsid];
|
1263
|
+
|
1264
|
+
if (obj.$$is_singleton) {
|
1265
|
+
if (obj.$$proto.$singleton_method_removed && !obj.$$proto.$singleton_method_removed.$$stub) {
|
1266
|
+
obj.$$proto.$singleton_method_removed(jsid.substr(1));
|
1267
|
+
}
|
1268
|
+
}
|
1269
|
+
else {
|
1270
|
+
if (obj.$method_removed && !obj.$method_removed.$$stub) {
|
1271
|
+
obj.$method_removed(jsid.substr(1));
|
1272
|
+
}
|
1273
|
+
}
|
1274
|
+
};
|
1149
1275
|
|
1150
1276
|
/*
|
1151
|
-
* Called
|
1277
|
+
* Called from #undef_method.
|
1152
1278
|
*/
|
1153
|
-
Opal.
|
1154
|
-
|
1279
|
+
Opal.udef = function(obj, jsid) {
|
1280
|
+
if (!obj.$$proto[jsid] || obj.$$proto[jsid].$$stub) {
|
1281
|
+
throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
|
1282
|
+
}
|
1283
|
+
|
1284
|
+
Opal.add_stub_for(obj.$$proto, jsid);
|
1285
|
+
|
1286
|
+
if (obj.$$is_singleton) {
|
1287
|
+
if (obj.$$proto.$singleton_method_undefined && !obj.$$proto.$singleton_method_undefined.$$stub) {
|
1288
|
+
obj.$$proto.$singleton_method_undefined(jsid.substr(1));
|
1289
|
+
}
|
1290
|
+
}
|
1291
|
+
else {
|
1292
|
+
if (obj.$method_undefined && !obj.$method_undefined.$$stub) {
|
1293
|
+
obj.$method_undefined(jsid.substr(1));
|
1294
|
+
}
|
1295
|
+
}
|
1155
1296
|
};
|
1156
1297
|
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1298
|
+
// This black magic is required to avoid clashes of internal special fields,
|
1299
|
+
// like $$donated.
|
1300
|
+
function wrap(body) {
|
1301
|
+
function alias() {
|
1302
|
+
body.$$p = alias.$$p;
|
1303
|
+
body.$$s = alias.$$s;
|
1304
|
+
|
1305
|
+
try {
|
1306
|
+
return body.apply(this, $slice.call(arguments));
|
1307
|
+
}
|
1308
|
+
finally {
|
1309
|
+
alias.$$s = null;
|
1310
|
+
alias.$$p = null;
|
1311
|
+
}
|
1160
1312
|
}
|
1161
1313
|
|
1162
|
-
|
1163
|
-
|
1164
|
-
_map = {},
|
1165
|
-
smap = {},
|
1166
|
-
key, obj, length, khash, map;
|
1314
|
+
alias.$$target = body;
|
1315
|
+
alias.$$arity = body.length;
|
1167
1316
|
|
1168
|
-
|
1169
|
-
|
1170
|
-
hash.keys = keys;
|
1317
|
+
return alias;
|
1318
|
+
}
|
1171
1319
|
|
1172
|
-
|
1173
|
-
|
1174
|
-
|
1320
|
+
Opal.alias = function(obj, name, old) {
|
1321
|
+
var id = '$' + name,
|
1322
|
+
old_id = '$' + old,
|
1323
|
+
body = obj.$$proto['$' + old];
|
1324
|
+
|
1325
|
+
// instance_eval is being run on a class/module, so that need to alias class methods
|
1326
|
+
if (obj.$$eval) {
|
1327
|
+
return Opal.alias(Opal.get_singleton_class(obj), name, old);
|
1328
|
+
}
|
1175
1329
|
|
1176
|
-
|
1177
|
-
|
1330
|
+
if (typeof(body) !== "function" || body.$$stub) {
|
1331
|
+
var ancestor = obj.$$super;
|
1178
1332
|
|
1179
|
-
|
1180
|
-
|
1181
|
-
|
1333
|
+
while (typeof(body) !== "function" && ancestor) {
|
1334
|
+
body = ancestor[old_id];
|
1335
|
+
ancestor = ancestor.$$super;
|
1336
|
+
}
|
1182
1337
|
|
1183
|
-
|
1184
|
-
|
1338
|
+
if (typeof(body) !== "function" || body.$$stub) {
|
1339
|
+
throw Opal.NameError.$new("undefined method `" + old + "' for class `" + obj.$name() + "'")
|
1340
|
+
}
|
1341
|
+
}
|
1185
1342
|
|
1186
|
-
|
1187
|
-
khash = key;
|
1188
|
-
map = smap;
|
1189
|
-
} else {
|
1190
|
-
khash = key.$hash();
|
1191
|
-
map = _map;
|
1192
|
-
}
|
1343
|
+
Opal.defn(obj, id, wrap(body));
|
1193
1344
|
|
1194
|
-
|
1195
|
-
|
1196
|
-
}
|
1345
|
+
return obj;
|
1346
|
+
};
|
1197
1347
|
|
1198
|
-
|
1348
|
+
Opal.alias_native = function(obj, name, native_name) {
|
1349
|
+
var id = '$' + name,
|
1350
|
+
body = obj.$$proto[native_name];
|
1351
|
+
|
1352
|
+
if (typeof(body) !== "function" || body.$$stub) {
|
1353
|
+
throw Opal.NameError.$new("undefined native method `" + native_name + "' for class `" + obj.$name() + "'")
|
1354
|
+
}
|
1355
|
+
|
1356
|
+
Opal.defn(obj, id, wrap(body));
|
1357
|
+
|
1358
|
+
return obj;
|
1359
|
+
};
|
1360
|
+
|
1361
|
+
Opal.hash_init = function (hash) {
|
1362
|
+
hash.map = {};
|
1363
|
+
hash.smap = {};
|
1364
|
+
hash.keys = [];
|
1365
|
+
};
|
1366
|
+
|
1367
|
+
Opal.hash_clone = function (from_hash, to_hash) {
|
1368
|
+
to_hash.none = from_hash.none;
|
1369
|
+
to_hash.proc = from_hash.proc;
|
1370
|
+
|
1371
|
+
for (var i = 0, keys = from_hash.keys, length = keys.length, key, value; i < length; i++) {
|
1372
|
+
key = from_hash.keys[i];
|
1373
|
+
|
1374
|
+
if (key.$$is_string) {
|
1375
|
+
value = from_hash.smap[key];
|
1376
|
+
} else {
|
1377
|
+
value = key.value;
|
1378
|
+
key = key.key;
|
1379
|
+
}
|
1380
|
+
|
1381
|
+
Opal.hash_put(to_hash, key, value);
|
1382
|
+
}
|
1383
|
+
};
|
1384
|
+
|
1385
|
+
Opal.hash_put = function (hash, key, value) {
|
1386
|
+
if (key.$$is_string) {
|
1387
|
+
if (!hash.smap.hasOwnProperty(key)) {
|
1388
|
+
hash.keys.push(key);
|
1389
|
+
}
|
1390
|
+
hash.smap[key] = value;
|
1391
|
+
return;
|
1392
|
+
}
|
1393
|
+
|
1394
|
+
var key_hash = key.$hash(), bucket, last_bucket;
|
1395
|
+
|
1396
|
+
if (!hash.map.hasOwnProperty(key_hash)) {
|
1397
|
+
bucket = {key: key, key_hash: key_hash, value: value};
|
1398
|
+
hash.keys.push(bucket);
|
1399
|
+
hash.map[key_hash] = bucket;
|
1400
|
+
return;
|
1401
|
+
}
|
1402
|
+
|
1403
|
+
bucket = hash.map[key_hash];
|
1404
|
+
|
1405
|
+
while (bucket) {
|
1406
|
+
if (key === bucket.key || key['$eql?'](bucket.key)) {
|
1407
|
+
last_bucket = undefined;
|
1408
|
+
bucket.value = value;
|
1409
|
+
break;
|
1410
|
+
}
|
1411
|
+
last_bucket = bucket;
|
1412
|
+
bucket = bucket.next;
|
1413
|
+
}
|
1414
|
+
|
1415
|
+
if (last_bucket) {
|
1416
|
+
bucket = {key: key, key_hash: key_hash, value: value};
|
1417
|
+
hash.keys.push(bucket);
|
1418
|
+
last_bucket.next = bucket;
|
1419
|
+
}
|
1420
|
+
};
|
1421
|
+
|
1422
|
+
Opal.hash_get = function (hash, key) {
|
1423
|
+
if (key.$$is_string) {
|
1424
|
+
if (hash.smap.hasOwnProperty(key)) {
|
1425
|
+
return hash.smap[key];
|
1426
|
+
}
|
1427
|
+
return;
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
var key_hash = key.$hash(), bucket;
|
1431
|
+
|
1432
|
+
if (hash.map.hasOwnProperty(key_hash)) {
|
1433
|
+
bucket = hash.map[key_hash];
|
1434
|
+
|
1435
|
+
while (bucket) {
|
1436
|
+
if (key === bucket.key || key['$eql?'](bucket.key)) {
|
1437
|
+
return bucket.value;
|
1199
1438
|
}
|
1439
|
+
bucket = bucket.next;
|
1200
1440
|
}
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1441
|
+
}
|
1442
|
+
};
|
1443
|
+
|
1444
|
+
Opal.hash_delete = function (hash, key) {
|
1445
|
+
var i, keys = hash.keys, length = keys.length, value;
|
1446
|
+
|
1447
|
+
if (key.$$is_string) {
|
1448
|
+
if (!hash.smap.hasOwnProperty(key)) {
|
1449
|
+
return;
|
1450
|
+
}
|
1451
|
+
|
1452
|
+
for (i = 0; i < length; i++) {
|
1453
|
+
if (keys[i] === key) {
|
1454
|
+
keys.splice(i, 1);
|
1455
|
+
break;
|
1207
1456
|
}
|
1208
1457
|
}
|
1458
|
+
|
1459
|
+
value = hash.smap[key];
|
1460
|
+
delete hash.smap[key];
|
1461
|
+
return value;
|
1209
1462
|
}
|
1210
|
-
|
1211
|
-
|
1212
|
-
|
1213
|
-
|
1463
|
+
|
1464
|
+
var key_hash = key.$hash();
|
1465
|
+
|
1466
|
+
if (!hash.map.hasOwnProperty(key_hash)) {
|
1467
|
+
return;
|
1468
|
+
}
|
1469
|
+
|
1470
|
+
var bucket = hash.map[key_hash], last_bucket;
|
1471
|
+
|
1472
|
+
while (bucket) {
|
1473
|
+
if (key === bucket.key || key['$eql?'](bucket.key)) {
|
1474
|
+
value = bucket.value;
|
1475
|
+
|
1476
|
+
for (i = 0; i < length; i++) {
|
1477
|
+
if (keys[i] === bucket) {
|
1478
|
+
keys.splice(i, 1);
|
1479
|
+
break;
|
1480
|
+
}
|
1481
|
+
}
|
1482
|
+
|
1483
|
+
if (last_bucket && bucket.next) {
|
1484
|
+
last_bucket.next = bucket.next;
|
1485
|
+
}
|
1486
|
+
else if (last_bucket) {
|
1487
|
+
delete last_bucket.next;
|
1488
|
+
}
|
1489
|
+
else if (bucket.next) {
|
1490
|
+
hash.map[key_hash] = bucket.next;
|
1491
|
+
}
|
1492
|
+
else {
|
1493
|
+
delete hash.map[key_hash];
|
1494
|
+
}
|
1495
|
+
|
1496
|
+
return value;
|
1497
|
+
}
|
1498
|
+
last_bucket = bucket;
|
1499
|
+
bucket = bucket.next;
|
1500
|
+
}
|
1501
|
+
};
|
1502
|
+
|
1503
|
+
Opal.hash_rehash = function (hash) {
|
1504
|
+
for (var i = 0, length = hash.keys.length, key_hash, bucket, last_bucket; i < length; i++) {
|
1505
|
+
|
1506
|
+
if (hash.keys[i].$$is_string) {
|
1507
|
+
continue;
|
1214
1508
|
}
|
1215
1509
|
|
1216
|
-
|
1217
|
-
key = arguments[j];
|
1218
|
-
obj = arguments[++j];
|
1510
|
+
key_hash = hash.keys[i].key.$hash();
|
1219
1511
|
|
1220
|
-
|
1221
|
-
|
1222
|
-
|
1223
|
-
|
1224
|
-
|
1225
|
-
|
1512
|
+
if (key_hash === hash.keys[i].key_hash) {
|
1513
|
+
continue;
|
1514
|
+
}
|
1515
|
+
|
1516
|
+
bucket = hash.map[hash.keys[i].key_hash];
|
1517
|
+
last_bucket = undefined;
|
1518
|
+
|
1519
|
+
while (bucket) {
|
1520
|
+
if (bucket === hash.keys[i]) {
|
1521
|
+
if (last_bucket && bucket.next) {
|
1522
|
+
last_bucket.next = bucket.next;
|
1523
|
+
}
|
1524
|
+
else if (last_bucket) {
|
1525
|
+
delete last_bucket.next;
|
1526
|
+
}
|
1527
|
+
else if (bucket.next) {
|
1528
|
+
hash.map[hash.keys[i].key_hash] = bucket.next;
|
1529
|
+
}
|
1530
|
+
else {
|
1531
|
+
delete hash.map[hash.keys[i].key_hash];
|
1532
|
+
}
|
1533
|
+
break;
|
1534
|
+
}
|
1535
|
+
last_bucket = bucket;
|
1536
|
+
bucket = bucket.next;
|
1537
|
+
}
|
1538
|
+
|
1539
|
+
hash.keys[i].key_hash = key_hash;
|
1540
|
+
|
1541
|
+
if (!hash.map.hasOwnProperty(key_hash)) {
|
1542
|
+
hash.map[key_hash] = hash.keys[i];
|
1543
|
+
continue;
|
1544
|
+
}
|
1545
|
+
|
1546
|
+
bucket = hash.map[key_hash];
|
1547
|
+
last_bucket = undefined;
|
1548
|
+
|
1549
|
+
while (bucket) {
|
1550
|
+
if (bucket === hash.keys[i]) {
|
1551
|
+
last_bucket = undefined;
|
1552
|
+
break;
|
1226
1553
|
}
|
1554
|
+
last_bucket = bucket;
|
1555
|
+
bucket = bucket.next;
|
1556
|
+
}
|
1557
|
+
|
1558
|
+
if (last_bucket) {
|
1559
|
+
last_bucket.next = hash.keys[i];
|
1560
|
+
}
|
1561
|
+
}
|
1562
|
+
};
|
1563
|
+
|
1564
|
+
Opal.hash = function() {
|
1565
|
+
var arguments_length = arguments.length, args, hash, i, length, key, value;
|
1566
|
+
|
1567
|
+
if (arguments_length === 1 && arguments[0].$$is_hash) {
|
1568
|
+
return arguments[0];
|
1569
|
+
}
|
1570
|
+
|
1571
|
+
hash = new Opal.Hash.$$alloc();
|
1572
|
+
Opal.hash_init(hash);
|
1227
1573
|
|
1228
|
-
|
1229
|
-
|
1574
|
+
if (arguments_length === 1 && arguments[0].$$is_array) {
|
1575
|
+
args = arguments[0];
|
1576
|
+
length = args.length;
|
1577
|
+
|
1578
|
+
for (i = 0; i < length; i++) {
|
1579
|
+
if (args[i].length !== 2) {
|
1580
|
+
throw Opal.ArgumentError.$new("value not of length 2: " + args[i].$inspect());
|
1230
1581
|
}
|
1231
1582
|
|
1232
|
-
|
1583
|
+
key = args[i][0];
|
1584
|
+
value = args[i][1];
|
1585
|
+
|
1586
|
+
Opal.hash_put(hash, key, value);
|
1587
|
+
}
|
1588
|
+
|
1589
|
+
return hash;
|
1590
|
+
}
|
1591
|
+
|
1592
|
+
if (arguments_length === 1) {
|
1593
|
+
args = arguments[0];
|
1594
|
+
for (key in args) {
|
1595
|
+
if (args.hasOwnProperty(key)) {
|
1596
|
+
value = args[key];
|
1597
|
+
|
1598
|
+
Opal.hash_put(hash, key, value);
|
1599
|
+
}
|
1233
1600
|
}
|
1601
|
+
|
1602
|
+
return hash;
|
1603
|
+
}
|
1604
|
+
|
1605
|
+
if (arguments_length % 2 !== 0) {
|
1606
|
+
throw Opal.ArgumentError.$new("odd number of arguments for Hash");
|
1607
|
+
}
|
1608
|
+
|
1609
|
+
for (i = 0; i < arguments_length; i += 2) {
|
1610
|
+
key = arguments[i];
|
1611
|
+
value = arguments[i + 1];
|
1612
|
+
|
1613
|
+
Opal.hash_put(hash, key, value);
|
1234
1614
|
}
|
1235
1615
|
|
1236
1616
|
return hash;
|
@@ -1242,12 +1622,12 @@
|
|
1242
1622
|
* compile time, so they are just added here by the constructor
|
1243
1623
|
* function
|
1244
1624
|
*/
|
1245
|
-
Opal.hash2 = function(keys,
|
1625
|
+
Opal.hash2 = function(keys, smap) {
|
1246
1626
|
var hash = new Opal.Hash.$$alloc();
|
1247
1627
|
|
1248
|
-
hash.keys = keys;
|
1249
1628
|
hash.map = {};
|
1250
|
-
hash.
|
1629
|
+
hash.keys = keys;
|
1630
|
+
hash.smap = smap;
|
1251
1631
|
|
1252
1632
|
return hash;
|
1253
1633
|
};
|
@@ -1265,6 +1645,25 @@
|
|
1265
1645
|
return range;
|
1266
1646
|
};
|
1267
1647
|
|
1648
|
+
Opal.ivar = function(name) {
|
1649
|
+
if (name === "constructor" ||
|
1650
|
+
name === "__proto__" ||
|
1651
|
+
name === "__parent__" ||
|
1652
|
+
name === "__noSuchMethod__" ||
|
1653
|
+
name === "__count__")
|
1654
|
+
{
|
1655
|
+
return name + "$";
|
1656
|
+
}
|
1657
|
+
|
1658
|
+
if (name === "hasOwnProperty" ||
|
1659
|
+
name === "valueOf")
|
1660
|
+
{
|
1661
|
+
return name + "$";
|
1662
|
+
}
|
1663
|
+
|
1664
|
+
return name;
|
1665
|
+
};
|
1666
|
+
|
1268
1667
|
// Require system
|
1269
1668
|
// --------------
|
1270
1669
|
(function(Opal) {
|
@@ -1274,18 +1673,7 @@
|
|
1274
1673
|
|
1275
1674
|
var current_dir = '.';
|
1276
1675
|
|
1277
|
-
function
|
1278
|
-
if (require_table[filename]) {
|
1279
|
-
return false;
|
1280
|
-
}
|
1281
|
-
|
1282
|
-
loaded_features.push(filename);
|
1283
|
-
require_table[filename] = true;
|
1284
|
-
|
1285
|
-
return true;
|
1286
|
-
}
|
1287
|
-
|
1288
|
-
function normalize_loadable_path(path) {
|
1676
|
+
function normalize(path) {
|
1289
1677
|
var parts, part, new_parts = [], SEPARATOR = '/';
|
1290
1678
|
|
1291
1679
|
if (current_dir !== '.') {
|
@@ -1297,15 +1685,32 @@
|
|
1297
1685
|
|
1298
1686
|
for (var i = 0, ii = parts.length; i < ii; i++) {
|
1299
1687
|
part = parts[i];
|
1300
|
-
if (part
|
1688
|
+
if (part === '') continue;
|
1301
1689
|
(part === '..') ? new_parts.pop() : new_parts.push(part)
|
1302
1690
|
}
|
1303
1691
|
|
1304
1692
|
return new_parts.join(SEPARATOR);
|
1305
1693
|
}
|
1306
1694
|
|
1695
|
+
function loaded(paths) {
|
1696
|
+
var i, l, path;
|
1697
|
+
|
1698
|
+
for (i = 0, l = paths.length; i < l; i++) {
|
1699
|
+
path = normalize(paths[i]);
|
1700
|
+
|
1701
|
+
if (require_table[path]) {
|
1702
|
+
return;
|
1703
|
+
}
|
1704
|
+
|
1705
|
+
loaded_features.push(path);
|
1706
|
+
require_table[path] = true;
|
1707
|
+
}
|
1708
|
+
}
|
1709
|
+
|
1307
1710
|
function load(path) {
|
1308
|
-
|
1711
|
+
path = normalize(path);
|
1712
|
+
|
1713
|
+
loaded([path]);
|
1309
1714
|
|
1310
1715
|
var module = modules[path];
|
1311
1716
|
|
@@ -1328,6 +1733,8 @@
|
|
1328
1733
|
}
|
1329
1734
|
|
1330
1735
|
function require(path) {
|
1736
|
+
path = normalize(path);
|
1737
|
+
|
1331
1738
|
if (require_table[path]) {
|
1332
1739
|
return false;
|
1333
1740
|
}
|
@@ -1337,9 +1744,7 @@
|
|
1337
1744
|
|
1338
1745
|
Opal.modules = modules;
|
1339
1746
|
Opal.loaded_features = loaded_features;
|
1340
|
-
|
1341
|
-
Opal.normalize_loadable_path = normalize_loadable_path;
|
1342
|
-
Opal.mark_as_loaded = mark_as_loaded;
|
1747
|
+
Opal.loaded = loaded;
|
1343
1748
|
|
1344
1749
|
Opal.load = load;
|
1345
1750
|
Opal.require = require;
|
@@ -1404,16 +1809,9 @@
|
|
1404
1809
|
ModuleClass.$$parent = ObjectClass;
|
1405
1810
|
ClassClass.$$parent = ModuleClass;
|
1406
1811
|
|
1407
|
-
// Internally, Object acts like a module as it is "included" into bridged
|
1408
|
-
// classes. In other words, we donate methods from Object into our bridged
|
1409
|
-
// classes as their prototypes don't inherit from our root Object, so they
|
1410
|
-
// act like module includes.
|
1411
|
-
ObjectClass.$$dep = bridged_classes;
|
1412
|
-
|
1413
1812
|
Opal.base = ObjectClass;
|
1414
1813
|
BasicObjectClass.$$scope = ObjectClass.$$scope = Opal;
|
1415
1814
|
BasicObjectClass.$$orig_scope = ObjectClass.$$orig_scope = Opal;
|
1416
|
-
Opal.Kernel = ObjectClass;
|
1417
1815
|
|
1418
1816
|
ModuleClass.$$scope = ObjectClass.$$scope;
|
1419
1817
|
ModuleClass.$$orig_scope = ObjectClass.$$orig_scope;
|
@@ -1437,15 +1835,6 @@
|
|
1437
1835
|
Opal.breaker = new Error('unexpected break');
|
1438
1836
|
Opal.returner = new Error('unexpected return');
|
1439
1837
|
|
1440
|
-
bridge_class('Array', Array);
|
1441
|
-
bridge_class('Boolean', Boolean);
|
1442
|
-
bridge_class('Numeric', Number);
|
1443
|
-
bridge_class('String', String);
|
1444
|
-
bridge_class('Proc', Function);
|
1445
|
-
bridge_class('Exception', Error);
|
1446
|
-
bridge_class('Regexp', RegExp);
|
1447
|
-
bridge_class('Time', Date);
|
1448
|
-
|
1449
1838
|
TypeError.$$super = Error;
|
1450
1839
|
}).call(this);
|
1451
1840
|
|