opal 0.9.4 → 0.10.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitattributes +1 -0
- data/.gitignore +2 -3
- data/.gitmodules +5 -2
- data/.jshintrc +1 -8
- data/.rspec +1 -1
- data/.travis.yml +15 -23
- data/CHANGELOG.md +511 -326
- data/CODE_OF_CONDUCT.md +13 -15
- data/CONTRIBUTING.md +26 -216
- data/Gemfile +20 -12
- data/Guardfile +2 -2
- data/HACKING.md +230 -0
- data/README.md +6 -7
- data/bin/opal-mspec +1 -1
- data/config.ru +2 -2
- data/docs/faq.md +1 -1
- data/docs/source_maps.md +1 -1
- data/lib/opal.rb +1 -0
- data/lib/opal/builder.rb +1 -1
- data/lib/opal/cli.rb +30 -28
- data/lib/opal/cli_options.rb +3 -0
- data/lib/opal/cli_runners.rb +14 -1
- data/lib/opal/cli_runners/{apple_script.rb → applescript.rb} +3 -3
- data/lib/opal/cli_runners/nashorn.rb +2 -2
- data/lib/opal/cli_runners/nodejs.rb +2 -2
- data/lib/opal/cli_runners/phantom.js +24 -0
- data/lib/opal/cli_runners/phantomjs.rb +10 -10
- data/lib/opal/cli_runners/server.rb +3 -3
- data/lib/opal/compiler.rb +43 -4
- data/lib/opal/config.rb +3 -1
- data/lib/opal/errors.rb +13 -0
- data/lib/opal/fragment.rb +0 -13
- data/lib/opal/nodes.rb +10 -0
- data/lib/opal/nodes/args/initialize_kwargs.rb +28 -0
- data/lib/opal/nodes/args/kwarg.rb +29 -0
- data/lib/opal/nodes/args/kwoptarg.rb +29 -0
- data/lib/opal/nodes/args/kwrestarg.rb +39 -0
- data/lib/opal/nodes/args/mlhsarg.rb +79 -0
- data/lib/opal/nodes/args/normarg.rb +26 -0
- data/lib/opal/nodes/args/optarg.rb +27 -0
- data/lib/opal/nodes/args/post_args.rb +200 -0
- data/lib/opal/nodes/args/post_kwargs.rb +31 -0
- data/lib/opal/nodes/args/restarg.rb +33 -0
- data/lib/opal/nodes/base.rb +12 -0
- data/lib/opal/nodes/call.rb +92 -33
- data/lib/opal/nodes/def.rb +26 -169
- data/lib/opal/nodes/hash.rb +10 -4
- data/lib/opal/nodes/helpers.rb +6 -3
- data/lib/opal/nodes/inline_args.rb +61 -0
- data/lib/opal/nodes/iter.rb +73 -82
- data/lib/opal/nodes/logic.rb +12 -2
- data/lib/opal/nodes/masgn.rb +1 -2
- data/lib/opal/nodes/node_with_args.rb +141 -0
- data/lib/opal/nodes/rescue.rb +121 -43
- data/lib/opal/nodes/scope.rb +24 -5
- data/lib/opal/nodes/super.rb +122 -54
- data/lib/opal/nodes/top.rb +0 -12
- data/lib/opal/nodes/yield.rb +2 -13
- data/lib/opal/parser.rb +67 -39
- data/lib/opal/parser/grammar.rb +3319 -2961
- data/lib/opal/parser/grammar.y +234 -46
- data/lib/opal/parser/lexer.rb +105 -17
- data/lib/opal/parser/sexp.rb +4 -0
- data/lib/opal/paths.rb +4 -0
- data/lib/opal/regexp_anchors.rb +19 -1
- data/lib/opal/sprockets.rb +21 -18
- data/lib/opal/sprockets/environment.rb +0 -8
- data/lib/opal/sprockets/processor.rb +13 -16
- data/lib/opal/sprockets/server.rb +6 -12
- data/lib/opal/version.rb +1 -1
- data/opal.gemspec +1 -0
- data/opal/corelib/array.rb +209 -131
- data/opal/corelib/basic_object.rb +7 -3
- data/opal/corelib/class.rb +11 -17
- data/opal/corelib/constants.rb +2 -2
- data/opal/corelib/enumerable.rb +178 -355
- data/opal/corelib/enumerator.rb +3 -46
- data/opal/corelib/error.rb +2 -2
- data/opal/corelib/file.rb +13 -1
- data/opal/corelib/hash.rb +26 -56
- data/opal/corelib/helpers.rb +10 -0
- data/opal/corelib/kernel.rb +6 -3
- data/opal/corelib/module.rb +62 -31
- data/opal/corelib/number.rb +7 -16
- data/opal/corelib/proc.rb +24 -9
- data/opal/corelib/range.rb +4 -13
- data/opal/corelib/runtime.js +515 -378
- data/opal/corelib/string.rb +21 -49
- data/opal/corelib/struct.rb +50 -35
- data/opal/corelib/unsupported.rb +18 -30
- data/opal/opal.rb +0 -1
- data/opal/opal/mini.rb +1 -0
- data/spec/README.md +6 -4
- data/spec/filters/bugs/array.rb +0 -42
- data/spec/filters/bugs/basicobject.rb +0 -2
- data/spec/filters/bugs/bigdecimal.rb +160 -0
- data/spec/filters/bugs/class.rb +0 -5
- data/spec/filters/bugs/date.rb +1 -48
- data/spec/filters/bugs/enumerable.rb +4 -12
- data/spec/filters/bugs/enumerator.rb +0 -1
- data/spec/filters/bugs/exception.rb +4 -3
- data/spec/filters/bugs/float.rb +4 -2
- data/spec/filters/bugs/kernel.rb +25 -10
- data/spec/filters/bugs/language.rb +119 -68
- data/spec/filters/bugs/method.rb +135 -0
- data/spec/filters/bugs/module.rb +13 -28
- data/spec/filters/bugs/proc.rb +18 -8
- data/spec/filters/bugs/range.rb +0 -3
- data/spec/filters/bugs/rational.rb +4 -0
- data/spec/filters/bugs/regexp.rb +68 -36
- data/spec/filters/bugs/string.rb +1 -1
- data/spec/filters/bugs/struct.rb +0 -12
- data/spec/filters/bugs/time.rb +1 -0
- data/spec/filters/bugs/unboundmethod.rb +2 -1
- data/spec/filters/unsupported/freeze.rb +3 -1
- data/spec/filters/unsupported/language.rb +0 -7
- data/spec/filters/unsupported/privacy.rb +7 -6
- data/spec/filters/unsupported/string.rb +10 -0
- data/spec/filters/unsupported/struct.rb +3 -0
- data/spec/filters/unsupported/symbol.rb +9 -0
- data/spec/filters/unsupported/taint.rb +0 -3
- data/spec/filters/unsupported/thread.rb +1 -0
- data/spec/lib/cli_runners/phantomjs_spec.rb +39 -0
- data/spec/lib/cli_spec.rb +42 -1
- data/spec/lib/compiler/call_spec.rb +700 -0
- data/spec/lib/compiler_spec.rb +46 -28
- data/spec/lib/config_spec.rb +13 -0
- data/spec/lib/parser/call_spec.rb +18 -0
- data/spec/lib/parser/def_spec.rb +29 -0
- data/spec/lib/parser/iter_spec.rb +15 -15
- data/spec/lib/parser/lambda_spec.rb +153 -12
- data/spec/lib/parser/string_spec.rb +5 -0
- data/spec/lib/parser/undef_spec.rb +1 -1
- data/spec/lib/parser/variables_spec.rb +24 -0
- data/spec/lib/paths_spec.rb +12 -5
- data/spec/lib/spec_helper.rb +5 -0
- data/spec/lib/sprockets/processor_spec.rb +6 -5
- data/spec/lib/sprockets_spec.rb +8 -0
- data/spec/mspec-opal/formatters.rb +188 -0
- data/spec/mspec-opal/runner.rb +193 -0
- data/spec/opal/core/enumerator/with_index_spec.rb +6 -0
- data/spec/opal/core/kernel/define_singleton_method_spec.rb +1 -1
- data/spec/opal/core/kernel/instance_variables_spec.rb +14 -0
- data/spec/opal/core/kernel/loop_spec.rb +1 -1
- data/spec/opal/core/kernel/raise_spec.rb +1 -1
- data/spec/opal/core/language/heredoc_spec.rb +42 -0
- data/spec/opal/core/language/rescue_spec.rb +18 -0
- data/spec/opal/core/language_spec.rb +22 -0
- data/spec/opal/core/module/const_defined_spec.rb +1 -2
- data/spec/opal/core/module/name_spec.rb +6 -0
- data/spec/opal/core/runtime/bridged_classes_spec.rb +14 -2
- data/spec/opal/core/runtime/rescue_spec.rb +12 -2
- data/spec/opal/core/runtime/super_spec.rb +1 -0
- data/spec/opal/core/string_spec.rb +21 -0
- data/spec/opal/stdlib/js_spec.rb +1 -1
- data/spec/opal/stdlib/native/hash_spec.rb +7 -0
- data/spec/opal/stdlib/promise/always_spec.rb +24 -5
- data/spec/opal/stdlib/promise/rescue_spec.rb +15 -6
- data/spec/opal/stdlib/promise/then_spec.rb +13 -5
- data/spec/opal/stdlib/promise/trace_spec.rb +5 -6
- data/spec/opal/stdlib/strscan/scan_spec.rb +1 -1
- data/spec/ruby_specs +122 -0
- data/spec/spec_helper.rb +3 -15
- data/stdlib/base64.rb +51 -121
- data/stdlib/bigdecimal.rb +231 -0
- data/stdlib/bigdecimal/bignumber.js.rb +11 -0
- data/stdlib/bigdecimal/kernel.rb +5 -0
- data/stdlib/date.rb +252 -10
- data/stdlib/native.rb +38 -38
- data/stdlib/nodejs/dir.rb +8 -6
- data/stdlib/nodejs/file.rb +28 -3
- data/stdlib/nodejs/node_modules/.bin/js-yaml +1 -0
- data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esparse +1 -0
- data/stdlib/nodejs/node_modules/js-yaml/node_modules/.bin/esvalidate +1 -0
- data/stdlib/nodejs/require.rb +1 -1
- data/stdlib/nodejs/yaml.rb +3 -2
- data/stdlib/opal-parser.rb +7 -2
- data/stdlib/pathname.rb +23 -1
- data/stdlib/phantomjs.rb +10 -0
- data/stdlib/promise.rb +38 -23
- data/tasks/building.rake +3 -3
- data/tasks/testing.rake +27 -14
- data/tasks/testing/mspec_special_calls.rb +1 -1
- data/tasks/testing/sprockets-phantomjs.js +4 -0
- data/test/opal/test_keyword.rb +110 -110
- data/test/opal/unsupported_and_bugs.rb +30 -0
- data/vendored-minitest/minitest/assertions.rb +1 -1
- metadata +65 -15
- data/.spectator +0 -2
- data/.spectator-mspec +0 -3
- data/opal/corelib/array/inheritance.rb +0 -127
- data/spec/rubyspecs +0 -139
data/opal/corelib/number.rb
CHANGED
@@ -209,16 +209,13 @@ class Number < Numeric
|
|
209
209
|
bit = Opal.coerce_to! bit, Integer, :to_int
|
210
210
|
|
211
211
|
%x{
|
212
|
-
if (#{bit} <
|
212
|
+
if (#{bit} < 0) {
|
213
213
|
return 0;
|
214
214
|
}
|
215
|
-
|
216
|
-
|
217
|
-
return (((~self) + 1) >> #{bit}) % 2;
|
218
|
-
}
|
219
|
-
else {
|
220
|
-
return (self >> #{bit}) % 2;
|
215
|
+
if (#{bit} >= 32) {
|
216
|
+
return #{ self } < 0 ? 1 : 0;
|
221
217
|
}
|
218
|
+
return (self >> #{bit}) & 1;
|
222
219
|
}
|
223
220
|
end
|
224
221
|
|
@@ -345,9 +342,7 @@ class Number < Numeric
|
|
345
342
|
#{raise ArgumentError, "comparison of #{self.class} with #{stop.class} failed"}
|
346
343
|
}
|
347
344
|
for (var i = self; i >= stop; i--) {
|
348
|
-
|
349
|
-
return $breaker.$v;
|
350
|
-
}
|
345
|
+
block(i);
|
351
346
|
}
|
352
347
|
}
|
353
348
|
|
@@ -595,9 +590,7 @@ class Number < Numeric
|
|
595
590
|
|
596
591
|
%x{
|
597
592
|
for (var i = 0; i < self; i++) {
|
598
|
-
|
599
|
-
return $breaker.$v;
|
600
|
-
}
|
593
|
+
block(i);
|
601
594
|
}
|
602
595
|
}
|
603
596
|
|
@@ -659,9 +652,7 @@ class Number < Numeric
|
|
659
652
|
#{raise ArgumentError, "comparison of #{self.class} with #{stop.class} failed"}
|
660
653
|
}
|
661
654
|
for (var i = self; i <= stop; i++) {
|
662
|
-
|
663
|
-
return $breaker.$v;
|
664
|
-
}
|
655
|
+
block(i);
|
665
656
|
}
|
666
657
|
}
|
667
658
|
|
data/opal/corelib/proc.rb
CHANGED
@@ -16,17 +16,32 @@ class Proc < `Function`
|
|
16
16
|
self.$$p = block;
|
17
17
|
}
|
18
18
|
|
19
|
-
var result;
|
20
|
-
|
21
|
-
if (
|
22
|
-
|
19
|
+
var result, $brk = self.$$brk;
|
20
|
+
|
21
|
+
if ($brk) {
|
22
|
+
try {
|
23
|
+
if (self.$$is_lambda) {
|
24
|
+
result = self.apply(null, args);
|
25
|
+
}
|
26
|
+
else {
|
27
|
+
result = Opal.yieldX(self, args);
|
28
|
+
}
|
29
|
+
} catch (err) {
|
30
|
+
if (err === $brk) {
|
31
|
+
return $brk.$v
|
32
|
+
}
|
33
|
+
else {
|
34
|
+
throw err
|
35
|
+
}
|
36
|
+
}
|
23
37
|
}
|
24
38
|
else {
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
39
|
+
if (self.$$is_lambda) {
|
40
|
+
result = self.apply(null, args);
|
41
|
+
}
|
42
|
+
else {
|
43
|
+
result = Opal.yieldX(self, args);
|
44
|
+
}
|
30
45
|
}
|
31
46
|
|
32
47
|
return result;
|
data/opal/corelib/range.rb
CHANGED
@@ -39,7 +39,7 @@ class Range
|
|
39
39
|
return enum_for :each unless block_given?
|
40
40
|
|
41
41
|
%x{
|
42
|
-
var i, limit
|
42
|
+
var i, limit;
|
43
43
|
|
44
44
|
if (#@begin.$$is_number && #@end.$$is_number) {
|
45
45
|
if (#@begin % 1 !== 0 || #@end % 1 !== 0) {
|
@@ -47,24 +47,15 @@ class Range
|
|
47
47
|
}
|
48
48
|
|
49
49
|
for (i = #@begin, limit = #@end + #{@exclude ? 0 : 1}; i < limit; i++) {
|
50
|
-
|
51
|
-
if (value === $breaker) { return $breaker.$v; }
|
50
|
+
block(i);
|
52
51
|
}
|
53
52
|
|
54
53
|
return self;
|
55
54
|
}
|
56
55
|
|
57
56
|
if (#@begin.$$is_string && #@end.$$is_string) {
|
58
|
-
|
59
|
-
|
60
|
-
// The following is a bit hackish: we know that
|
61
|
-
// String#upto normally returns self, but may
|
62
|
-
// return a different value if there's a `break`
|
63
|
-
// statement in the supplied block. We need to
|
64
|
-
// propagate this `break` value here, so we
|
65
|
-
// test for equality with `@begin` string to
|
66
|
-
// determine the return value:
|
67
|
-
return value === #@begin ? self : value;
|
57
|
+
#{@begin.upto(@end, @exclude, &block)}
|
58
|
+
return self;
|
68
59
|
}
|
69
60
|
}
|
70
61
|
|
data/opal/corelib/runtime.js
CHANGED
@@ -1,4 +1,18 @@
|
|
1
1
|
(function(undefined) {
|
2
|
+
// @note
|
3
|
+
// A few conventions for the documentation of this file:
|
4
|
+
// 1. Always use "//" (in contrast with "/**/")
|
5
|
+
// 2. The syntax used is Yardoc (yardoc.org), which is intended for Ruby (se below)
|
6
|
+
// 3. `@param` and `@return` types should be preceded by `JS.` when referring to
|
7
|
+
// JavaScript constructors (e.g. `JS.Function`) otherwise Ruby is assumed.
|
8
|
+
// 4. `nil` and `null` being unambiguous refer to the respective
|
9
|
+
// objects/values in Ruby and JavaScript
|
10
|
+
// 5. This is still WIP :) so please give feedback and suggestions on how
|
11
|
+
// to improve or for alternative solutions
|
12
|
+
//
|
13
|
+
// The way the code is digested before going through Yardoc is a secret kept
|
14
|
+
// in the docs repo (https://github.com/opal/docs/tree/master).
|
15
|
+
|
2
16
|
if (typeof(this.Opal) !== 'undefined') {
|
3
17
|
console.warn('Opal already loaded. Loading twice can cause troubles, please fix your setup.');
|
4
18
|
return this.Opal;
|
@@ -55,6 +69,12 @@
|
|
55
69
|
// This is a useful reference to global object inside ruby files
|
56
70
|
Opal.global = this;
|
57
71
|
|
72
|
+
// Configure runtime behavior with regards to require and unsupported fearures
|
73
|
+
Opal.config = {
|
74
|
+
missing_require_severity: 'error', // error, warning, ignore
|
75
|
+
unsupported_features_severity: 'warning' // error, warning, ignore
|
76
|
+
}
|
77
|
+
|
58
78
|
// Minify common function calls
|
59
79
|
var $hasOwn = Opal.hasOwnProperty;
|
60
80
|
var $slice = Opal.slice = Array.prototype.slice;
|
@@ -85,6 +105,16 @@
|
|
85
105
|
// keeps track of exceptions for $!
|
86
106
|
Opal.exceptions = [];
|
87
107
|
|
108
|
+
// @private
|
109
|
+
// Pops an exception from the stack and updates `$!`.
|
110
|
+
Opal.pop_exception = function() {
|
111
|
+
Opal.gvars["!"] = Opal.exceptions.pop() || nil;
|
112
|
+
}
|
113
|
+
|
114
|
+
|
115
|
+
// Constants
|
116
|
+
// ---------
|
117
|
+
|
88
118
|
// Get a constant on the given scope. Every class and module in Opal has a
|
89
119
|
// scope used to store, and inherit, constants. For example, the top level
|
90
120
|
// `Object` in ruby has a scope accessible as `Opal.Object.$$scope`.
|
@@ -97,8 +127,8 @@
|
|
97
127
|
// class/module's `#const_method` is called, which by default will raise an
|
98
128
|
// error.
|
99
129
|
//
|
100
|
-
// @param [String]
|
101
|
-
// @return [
|
130
|
+
// @param name [String] the name of the constant to lookup
|
131
|
+
// @return [Object]
|
102
132
|
//
|
103
133
|
Opal.get = function(name) {
|
104
134
|
var constant = this[name];
|
@@ -133,7 +163,88 @@
|
|
133
163
|
Opal.cdecl(base_scope, id, klass);
|
134
164
|
const_alloc.displayName = id+"_scope_alloc";
|
135
165
|
}
|
136
|
-
}
|
166
|
+
};
|
167
|
+
|
168
|
+
// Constant assignment, see also `Opal.cdecl`
|
169
|
+
//
|
170
|
+
// @param base_module [Module, Class] the constant namespace
|
171
|
+
// @param name [String] the name of the constant
|
172
|
+
// @param value [Object] the value of the constant
|
173
|
+
//
|
174
|
+
// @example Assigning a namespaced constant
|
175
|
+
// self::FOO = 'bar'
|
176
|
+
//
|
177
|
+
// @example Assigning with Module#const_set
|
178
|
+
// Foo.const_set :BAR, 123
|
179
|
+
//
|
180
|
+
Opal.casgn = function(base_module, name, value) {
|
181
|
+
function update(klass, name) {
|
182
|
+
klass.$$name = name;
|
183
|
+
|
184
|
+
for (name in klass.$$scope) {
|
185
|
+
var value = klass.$$scope[name];
|
186
|
+
|
187
|
+
if (value.$$name === nil && (value.$$is_class || value.$$is_module)) {
|
188
|
+
update(value, name)
|
189
|
+
}
|
190
|
+
}
|
191
|
+
}
|
192
|
+
|
193
|
+
var scope = base_module.$$scope;
|
194
|
+
|
195
|
+
if (value.$$is_class || value.$$is_module) {
|
196
|
+
// Only checking _Object prevents setting a const on an anonymous class
|
197
|
+
// that has a superclass that's not Object
|
198
|
+
if (value.$$is_class || value.$$base_module === _Object) {
|
199
|
+
value.$$base_module = base_module;
|
200
|
+
}
|
201
|
+
|
202
|
+
if (value.$$name === nil && value.$$base_module.$$name !== nil) {
|
203
|
+
update(value, name);
|
204
|
+
}
|
205
|
+
}
|
206
|
+
|
207
|
+
scope.constants.push(name);
|
208
|
+
scope[name] = value;
|
209
|
+
|
210
|
+
// If we dynamically declare a constant in a module,
|
211
|
+
// we should populate all the classes that include this module
|
212
|
+
// with the same constant
|
213
|
+
if (base_module.$$is_module && base_module.$$dep) {
|
214
|
+
for (var i = 0; i < base_module.$$dep.length; i++) {
|
215
|
+
var dep = base_module.$$dep[i];
|
216
|
+
Opal.casgn(dep, name, value);
|
217
|
+
}
|
218
|
+
}
|
219
|
+
|
220
|
+
return value;
|
221
|
+
};
|
222
|
+
|
223
|
+
// Constant declaration
|
224
|
+
//
|
225
|
+
// @example
|
226
|
+
// FOO = :bar
|
227
|
+
//
|
228
|
+
// @param base_scope [$$scope] the current scope
|
229
|
+
// @param name [String] the name of the constant
|
230
|
+
// @param value [Object] the value of the constant
|
231
|
+
Opal.cdecl = function(base_scope, name, value) {
|
232
|
+
if ((value.$$is_class || value.$$is_module) && value.$$orig_scope == null) {
|
233
|
+
value.$$name = name;
|
234
|
+
value.$$orig_scope = base_scope;
|
235
|
+
// Here we should explicitly set a base module
|
236
|
+
// (a module where the constant was initially defined)
|
237
|
+
value.$$base_module = base_scope.base;
|
238
|
+
base_scope.constructor[name] = value;
|
239
|
+
}
|
240
|
+
|
241
|
+
base_scope.constants.push(name);
|
242
|
+
return base_scope[name] = value;
|
243
|
+
};
|
244
|
+
|
245
|
+
|
246
|
+
// Modules & Classes
|
247
|
+
// -----------------
|
137
248
|
|
138
249
|
// A `class Foo; end` expression in ruby is compiled to call this runtime
|
139
250
|
// method which either returns an existing class of the given name, or creates
|
@@ -141,8 +252,8 @@
|
|
141
252
|
//
|
142
253
|
// If a constant with the given name exists, then we check to make sure that
|
143
254
|
// it is a class and also that the superclasses match. If either of these
|
144
|
-
// fail, then we raise a `TypeError`. Note,
|
145
|
-
// not specified in the ruby code.
|
255
|
+
// fail, then we raise a `TypeError`. Note, `superclass` may be null if one
|
256
|
+
// was not specified in the ruby code.
|
146
257
|
//
|
147
258
|
// We pass a constructor to this method of the form `function ClassName() {}`
|
148
259
|
// simply so that classes show up with nicely formatted names inside debuggers
|
@@ -154,13 +265,13 @@
|
|
154
265
|
// use that as the base instead.
|
155
266
|
//
|
156
267
|
// @param base [Object] where the class is being created
|
157
|
-
// @param
|
268
|
+
// @param superclass [Class,null] superclass of the new class (may be null)
|
158
269
|
// @param id [String] the name of the class to be created
|
159
|
-
// @param constructor [Function] function to use as constructor
|
270
|
+
// @param constructor [JS.Function] function to use as constructor
|
160
271
|
//
|
161
272
|
// @return new [Class] or existing ruby class
|
162
273
|
//
|
163
|
-
Opal.klass = function(base,
|
274
|
+
Opal.klass = function(base, superclass, name, constructor) {
|
164
275
|
var klass, bridged, alloc;
|
165
276
|
|
166
277
|
// If base is an object, use its class
|
@@ -169,24 +280,24 @@
|
|
169
280
|
}
|
170
281
|
|
171
282
|
// If the superclass is a function then we're bridging a native JS class
|
172
|
-
if (typeof(
|
173
|
-
bridged =
|
174
|
-
|
283
|
+
if (typeof(superclass) === 'function') {
|
284
|
+
bridged = superclass;
|
285
|
+
superclass = _Object;
|
175
286
|
}
|
176
287
|
|
177
288
|
// Try to find the class in the current scope
|
178
|
-
klass = base.$$scope[
|
289
|
+
klass = base.$$scope[name];
|
179
290
|
|
180
291
|
// If the class exists in the scope, then we must use that
|
181
292
|
if (klass && klass.$$orig_scope === base.$$scope) {
|
182
293
|
// Make sure the existing constant is a class, or raise error
|
183
294
|
if (!klass.$$is_class) {
|
184
|
-
throw Opal.TypeError.$new(
|
295
|
+
throw Opal.TypeError.$new(name + " is not a class");
|
185
296
|
}
|
186
297
|
|
187
298
|
// Make sure existing class has same superclass
|
188
|
-
if (
|
189
|
-
throw Opal.TypeError.$new("superclass mismatch for class " +
|
299
|
+
if (superclass && klass.$$super !== superclass) {
|
300
|
+
throw Opal.TypeError.$new("superclass mismatch for class " + name);
|
190
301
|
}
|
191
302
|
|
192
303
|
return klass;
|
@@ -195,141 +306,134 @@
|
|
195
306
|
// Class doesnt exist, create a new one with given superclass...
|
196
307
|
|
197
308
|
// Not specifying a superclass means we can assume it to be Object
|
198
|
-
if (
|
199
|
-
|
309
|
+
if (superclass == null) {
|
310
|
+
superclass = _Object;
|
200
311
|
}
|
201
312
|
|
202
313
|
// If bridged the JS class will also be the alloc function
|
203
|
-
alloc = bridged || boot_class_alloc(
|
314
|
+
alloc = bridged || Opal.boot_class_alloc(name, constructor, superclass);
|
204
315
|
|
205
316
|
// Create the class object (instance of Class)
|
206
|
-
klass =
|
317
|
+
klass = Opal.setup_class_object(name, alloc, superclass.$$name, superclass.constructor);
|
207
318
|
|
208
|
-
//
|
209
|
-
klass.$$
|
210
|
-
klass.displayName = id;
|
319
|
+
// @property $$super the superclass, doesn't get changed by module inclusions
|
320
|
+
klass.$$super = superclass;
|
211
321
|
|
212
|
-
//
|
213
|
-
klass
|
322
|
+
// @property $$parent direct parent class
|
323
|
+
// starts with the superclass, after klass inclusion is
|
324
|
+
// the last included klass
|
325
|
+
klass.$$parent = superclass;
|
214
326
|
|
215
327
|
// Every class gets its own constant scope, inherited from current scope
|
216
|
-
Opal.create_scope(base.$$scope, klass,
|
217
|
-
|
218
|
-
// Name new class directly onto current scope (Opal.Foo.Baz = klass)
|
219
|
-
base[id] = base.$$scope[id] = klass;
|
328
|
+
Opal.create_scope(base.$$scope, klass, name);
|
220
329
|
|
221
330
|
if (bridged) {
|
222
331
|
Opal.bridge(klass, alloc);
|
223
332
|
}
|
224
333
|
else {
|
225
334
|
// Copy all parent constants to child, unless parent is Object
|
226
|
-
if (
|
227
|
-
donate_constants(
|
335
|
+
if (superclass !== _Object && superclass !== BasicObject) {
|
336
|
+
Opal.donate_constants(superclass, klass);
|
228
337
|
}
|
229
338
|
|
230
339
|
// Call .inherited() hook with new class on the superclass
|
231
|
-
if (
|
232
|
-
|
340
|
+
if (superclass.$inherited) {
|
341
|
+
superclass.$inherited(klass);
|
233
342
|
}
|
234
343
|
}
|
235
344
|
|
236
345
|
return klass;
|
237
346
|
};
|
238
347
|
|
239
|
-
//
|
240
|
-
|
241
|
-
|
348
|
+
// Boot a base class (makes instances).
|
349
|
+
//
|
350
|
+
// @param name [String,null] the class name
|
351
|
+
// @param constructor [JS.Function] the class' instances constructor/alloc function
|
352
|
+
// @param superclass [Class,null] the superclass object
|
353
|
+
// @return [JS.Function] the consturctor holding the prototype for the class' instances
|
354
|
+
Opal.boot_class_alloc = function(name, constructor, superclass) {
|
355
|
+
if (superclass) {
|
356
|
+
var alloc_proxy = function() {};
|
357
|
+
alloc_proxy.prototype = superclass.$$proto || superclass.prototype;
|
358
|
+
constructor.prototype = new alloc_proxy();
|
359
|
+
}
|
360
|
+
|
361
|
+
if (name) {
|
362
|
+
constructor.displayName = name+'_alloc';
|
363
|
+
}
|
242
364
|
|
243
|
-
|
244
|
-
}
|
365
|
+
constructor.prototype.constructor = constructor;
|
245
366
|
|
246
|
-
|
367
|
+
return constructor;
|
368
|
+
};
|
369
|
+
|
370
|
+
// Adds common/required properties to class object (as in `Class.new`)
|
371
|
+
//
|
372
|
+
// @param name [String,null] The name of the class
|
373
|
+
//
|
374
|
+
// @param alloc [JS.Function] The constructor of the class' instances
|
375
|
+
//
|
376
|
+
// @param superclass_name [String,null]
|
377
|
+
// The name of the super class, this is
|
378
|
+
// usefule to build the `.displayName` of the singleton class
|
247
379
|
//
|
248
|
-
// @param
|
249
|
-
//
|
250
|
-
//
|
251
|
-
//
|
252
|
-
|
380
|
+
// @param superclass_alloc [JS.Function]
|
381
|
+
// The constructor of the superclass from which the singleton_class is
|
382
|
+
// derived.
|
383
|
+
//
|
384
|
+
// @return [Class]
|
385
|
+
Opal.setup_class_object = function(name, alloc, superclass_name, superclass_alloc) {
|
253
386
|
// Grab the superclass prototype and use it to build an intermediary object
|
254
387
|
// in the prototype chain.
|
255
|
-
function
|
256
|
-
|
257
|
-
|
258
|
-
SingletonClass_alloc.prototype = new Superclass_alloc_proxy();
|
388
|
+
var superclass_alloc_proxy = function() {};
|
389
|
+
superclass_alloc_proxy.prototype = superclass_alloc.prototype;
|
390
|
+
superclass_alloc_proxy.displayName = superclass_name;
|
259
391
|
|
260
|
-
|
261
|
-
|
262
|
-
}
|
392
|
+
var singleton_class_alloc = function() {}
|
393
|
+
singleton_class_alloc.prototype = new superclass_alloc_proxy();
|
263
394
|
|
264
395
|
// The built class is the only instance of its singleton_class
|
265
|
-
var klass = new
|
266
|
-
|
267
|
-
setup_module_or_class_object(klass, SingletonClass_alloc, superklass, alloc.prototype);
|
396
|
+
var klass = new singleton_class_alloc();
|
268
397
|
|
269
398
|
// @property $$alloc This is the constructor of instances of the current
|
270
399
|
// class. Its prototype will be used for method lookup
|
271
400
|
klass.$$alloc = alloc;
|
272
401
|
|
273
|
-
|
274
|
-
// class they belong to.
|
275
|
-
klass.$$proto.$$class = klass;
|
402
|
+
klass.$$name = name || nil;
|
276
403
|
|
277
|
-
return klass;
|
278
|
-
}
|
279
|
-
|
280
|
-
// Adds common/required properties to a module or class object
|
281
|
-
// (as in `Module.new` / `Class.new`)
|
282
|
-
//
|
283
|
-
// @param module The module or class that needs to be prepared
|
284
|
-
//
|
285
|
-
// @param constructor The constructor of the module or class itself,
|
286
|
-
// usually it's already assigned by using `new`. Some
|
287
|
-
// ipothesis on why it's needed can be found below.
|
288
|
-
//
|
289
|
-
// @param superklass The superclass of the class/module object, for modules
|
290
|
-
// is `Module` (of `Module` in JS context)
|
291
|
-
//
|
292
|
-
// @param prototype The prototype on which the class/module methods will
|
293
|
-
// be stored.
|
294
|
-
//
|
295
|
-
function setup_module_or_class_object(module, constructor, superklass, prototype) {
|
296
404
|
// @property $$id Each class is assigned a unique `id` that helps
|
297
405
|
// comparation and implementation of `#object_id`
|
298
|
-
|
406
|
+
klass.$$id = Opal.uid();
|
407
|
+
|
408
|
+
// Set a displayName for the singleton_class
|
409
|
+
singleton_class_alloc.displayName = "#<Class:"+(name || ("#<Class:"+klass.$$id+">"))+">";
|
299
410
|
|
300
411
|
// @property $$proto This is the prototype on which methods will be defined
|
301
|
-
|
412
|
+
klass.$$proto = alloc.prototype;
|
413
|
+
|
414
|
+
// @property $$proto.$$class Make available to instances a reference to the
|
415
|
+
// class they belong to.
|
416
|
+
klass.$$proto.$$class = klass;
|
302
417
|
|
303
418
|
// @property constructor keeps a ref to the constructor, but apparently the
|
304
419
|
// constructor is already set on:
|
305
420
|
//
|
306
|
-
// `var
|
421
|
+
// `var klass = new constructor` is called.
|
307
422
|
//
|
308
423
|
// Maybe there are some browsers not abiding (IE6?)
|
309
|
-
|
310
|
-
|
311
|
-
if (superklass === Module) {
|
312
|
-
// @property $$is_module Clearly mark this as a module
|
313
|
-
module.$$is_module = true;
|
314
|
-
module.$$class = Module;
|
315
|
-
}
|
316
|
-
else {
|
317
|
-
// @property $$is_class Clearly mark this as a class
|
318
|
-
module.$$is_class = true;
|
319
|
-
module.$$class = Class;
|
320
|
-
}
|
424
|
+
klass.constructor = singleton_class_alloc;
|
321
425
|
|
322
|
-
// @property $$
|
323
|
-
|
426
|
+
// @property $$is_class Clearly mark this as a class
|
427
|
+
klass.$$is_class = true;
|
324
428
|
|
325
|
-
// @property $$
|
326
|
-
|
327
|
-
// the last included module
|
328
|
-
module.$$parent = superklass;
|
429
|
+
// @property $$class Classes are instances of the class Class
|
430
|
+
klass.$$class = Class;
|
329
431
|
|
330
432
|
// @property $$inc included modules
|
331
|
-
|
332
|
-
|
433
|
+
klass.$$inc = [];
|
434
|
+
|
435
|
+
return klass;
|
436
|
+
};
|
333
437
|
|
334
438
|
// Define new module (or return existing module). The given `base` is basically
|
335
439
|
// the current `self` value the `module` statement was defined in. If this is
|
@@ -347,48 +451,49 @@
|
|
347
451
|
// new instance is returned back (to be referenced at runtime).
|
348
452
|
//
|
349
453
|
// @param base [Module, Class] class or module this definition is inside
|
350
|
-
// @param id
|
351
|
-
// @return [Module]
|
454
|
+
// @param id [String] the name of the new (or existing) module
|
352
455
|
//
|
353
|
-
|
456
|
+
// @return [Module]
|
457
|
+
Opal.module = function(base, name) {
|
354
458
|
var module;
|
355
459
|
|
356
460
|
if (!base.$$is_class && !base.$$is_module) {
|
357
461
|
base = base.$$class;
|
358
462
|
}
|
359
463
|
|
360
|
-
if ($hasOwn.call(base.$$scope,
|
361
|
-
module = base.$$scope[
|
464
|
+
if ($hasOwn.call(base.$$scope, name)) {
|
465
|
+
module = base.$$scope[name];
|
362
466
|
|
363
467
|
if (!module.$$is_module && module !== _Object) {
|
364
|
-
throw Opal.TypeError.$new(
|
468
|
+
throw Opal.TypeError.$new(name + " is not a module");
|
365
469
|
}
|
366
470
|
}
|
367
471
|
else {
|
368
|
-
module =
|
369
|
-
|
370
|
-
// name module using base (e.g. Foo or Foo::Baz)
|
371
|
-
module.$$name = id;
|
372
|
-
|
373
|
-
// mark the object as a module
|
374
|
-
module.$$is_module = true;
|
375
|
-
|
376
|
-
// initialize dependency tracking
|
377
|
-
module.$$dep = [];
|
378
|
-
|
379
|
-
Opal.create_scope(base.$$scope, module, id);
|
380
|
-
|
381
|
-
// Name new module directly onto current scope (Opal.Foo.Baz = module)
|
382
|
-
base[id] = base.$$scope[id] = module;
|
472
|
+
module = Opal.module_allocate();
|
473
|
+
Opal.create_scope(base.$$scope, module, name);
|
383
474
|
}
|
384
475
|
|
385
476
|
return module;
|
386
477
|
};
|
387
478
|
|
479
|
+
// The implementation for Module#initialize
|
480
|
+
// @param module [Module]
|
481
|
+
// @param block [Proc,nil]
|
482
|
+
// @return nil
|
483
|
+
Opal.module_initialize = function(module, block) {
|
484
|
+
if (block !== nil) {
|
485
|
+
var block_self = block.$$s;
|
486
|
+
block.$$s = null;
|
487
|
+
block.call(module);
|
488
|
+
block.$$s = block_self;
|
489
|
+
}
|
490
|
+
return nil;
|
491
|
+
};
|
492
|
+
|
388
493
|
// Internal function to create a new module instance. This simply sets up
|
389
494
|
// the prototype hierarchy and method tables.
|
390
495
|
//
|
391
|
-
function
|
496
|
+
Opal.module_allocate = function() {
|
392
497
|
var mtor = function() {};
|
393
498
|
mtor.prototype = Module_alloc.prototype;
|
394
499
|
|
@@ -397,14 +502,55 @@
|
|
397
502
|
|
398
503
|
var module = new module_constructor();
|
399
504
|
var module_prototype = {};
|
505
|
+
var superclass = Module;
|
506
|
+
|
507
|
+
// @property $$id Each class is assigned a unique `id` that helps
|
508
|
+
// comparation and implementation of `#object_id`
|
509
|
+
module.$$id = Opal.uid();
|
400
510
|
|
401
|
-
|
511
|
+
// Set the display name of the singleton prototype holder
|
512
|
+
module_constructor.displayName = "#<Class:#<Module:"+module.$$id+">>"
|
402
513
|
|
403
|
-
|
404
|
-
|
514
|
+
// @property $$proto This is the prototype on which methods will be defined
|
515
|
+
module.$$proto = module_prototype;
|
516
|
+
|
517
|
+
// @property constructor
|
518
|
+
// keeps a ref to the constructor, but apparently the
|
519
|
+
// constructor is already set on:
|
520
|
+
//
|
521
|
+
// `var module = new constructor` is called.
|
522
|
+
//
|
523
|
+
// Maybe there are some browsers not abiding (IE6?)
|
524
|
+
module.constructor = module_constructor;
|
525
|
+
|
526
|
+
// @property $$is_module Clearly mark this as a module
|
527
|
+
module.$$is_module = true;
|
528
|
+
module.$$class = Module;
|
529
|
+
|
530
|
+
// @property $$super
|
531
|
+
// the superclass, doesn't get changed by module inclusions
|
532
|
+
module.$$super = superclass;
|
405
533
|
|
406
|
-
|
407
|
-
|
534
|
+
// @property $$parent
|
535
|
+
// direct parent class or module
|
536
|
+
// starts with the superclass, after module inclusion is
|
537
|
+
// the last included module
|
538
|
+
module.$$parent = superclass;
|
539
|
+
|
540
|
+
// @property $$inc included modules
|
541
|
+
module.$$inc = [];
|
542
|
+
|
543
|
+
// mark the object as a module
|
544
|
+
module.$$is_module = true;
|
545
|
+
|
546
|
+
// initialize dependency tracking
|
547
|
+
module.$$dep = [];
|
548
|
+
|
549
|
+
// initialize the name with nil
|
550
|
+
module.$$name = nil;
|
551
|
+
|
552
|
+
return module;
|
553
|
+
};
|
408
554
|
|
409
555
|
// Return the singleton class for the passed object.
|
410
556
|
//
|
@@ -415,68 +561,83 @@
|
|
415
561
|
// Otherwise, a new singleton object for the class or object is created, set on
|
416
562
|
// the object at `$$meta` for future use, and then returned.
|
417
563
|
//
|
418
|
-
// @param [
|
419
|
-
// @return [
|
420
|
-
//
|
564
|
+
// @param object [Object] the ruby object
|
565
|
+
// @return [Class] the singleton class for object
|
421
566
|
Opal.get_singleton_class = function(object) {
|
422
567
|
if (object.$$meta) {
|
423
568
|
return object.$$meta;
|
424
569
|
}
|
425
570
|
|
426
571
|
if (object.$$is_class || object.$$is_module) {
|
427
|
-
return build_class_singleton_class(object);
|
572
|
+
return Opal.build_class_singleton_class(object);
|
428
573
|
}
|
429
574
|
|
430
|
-
return build_object_singleton_class(object);
|
575
|
+
return Opal.build_object_singleton_class(object);
|
431
576
|
};
|
432
577
|
|
433
|
-
// Build the singleton class for an existing class.
|
578
|
+
// Build the singleton class for an existing class. Class object are built
|
579
|
+
// with their singleton class already in the prototype chain and inheriting
|
580
|
+
// from their superclass object (up to `Class` itself).
|
434
581
|
//
|
435
582
|
// NOTE: Actually in MRI a class' singleton class inherits from its
|
436
583
|
// superclass' singleton class which in turn inherits from Class.
|
437
584
|
//
|
438
|
-
// @param [
|
439
|
-
// @return [
|
440
|
-
|
441
|
-
|
442
|
-
var meta = new Opal.Class.$$alloc();
|
585
|
+
// @param klass [Class]
|
586
|
+
// @return [Class]
|
587
|
+
Opal.build_class_singleton_class = function(object) {
|
588
|
+
var alloc, superclass, klass;
|
443
589
|
|
444
|
-
meta
|
445
|
-
|
590
|
+
if (object.$$meta) {
|
591
|
+
return object.$$meta;
|
592
|
+
}
|
446
593
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
meta.$$scope = klass.$$scope;
|
594
|
+
// The constructor and prototype of the singleton_class instances is the
|
595
|
+
// current class constructor and prototype.
|
596
|
+
alloc = object.constructor;
|
451
597
|
|
452
|
-
|
453
|
-
|
598
|
+
// The singleton_class superclass is the singleton_class of its superclass;
|
599
|
+
// but BasicObject has no superclass (its `$$super` is null), thus we
|
600
|
+
// fallback on `Class`.
|
601
|
+
superclass = object === BasicObject ? Class : Opal.build_class_singleton_class(object.$$super);
|
602
|
+
|
603
|
+
klass = Opal.setup_class_object(null, alloc, superclass.$$name, superclass.constructor);
|
604
|
+
klass.$$super = superclass;
|
605
|
+
klass.$$parent = superclass;
|
606
|
+
|
607
|
+
// The singleton_class retains the same scope as the original class
|
608
|
+
Opal.create_scope(object.$$scope, klass);
|
609
|
+
|
610
|
+
klass.$$is_singleton = true;
|
611
|
+
klass.$$singleton_of = object;
|
612
|
+
|
613
|
+
return object.$$meta = klass;
|
614
|
+
};
|
454
615
|
|
455
616
|
// Build the singleton class for a Ruby (non class) Object.
|
456
617
|
//
|
457
|
-
// @param [
|
458
|
-
// @return [
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
class_id = "#<Class:#<" + orig_class.$$name + ":" + orig_class.$$id + ">>";
|
618
|
+
// @param object [Object]
|
619
|
+
// @return [Class]
|
620
|
+
Opal.build_object_singleton_class = function(object) {
|
621
|
+
var superclass = object.$$class,
|
622
|
+
name = "#<Class:#<" + superclass.$$name + ":" + superclass.$$id + ">>";
|
463
623
|
|
464
|
-
var
|
465
|
-
var
|
466
|
-
meta.$$name = class_id;
|
624
|
+
var alloc = Opal.boot_class_alloc(name, function(){}, superclass)
|
625
|
+
var klass = Opal.setup_class_object(name, alloc, superclass.$$name, superclass.constructor);
|
467
626
|
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
meta.$$singleton_of = object;
|
627
|
+
klass.$$super = superclass;
|
628
|
+
klass.$$parent = superclass;
|
629
|
+
klass.$$class = superclass.$$class;
|
630
|
+
klass.$$scope = superclass.$$scope;
|
631
|
+
klass.$$proto = object;
|
474
632
|
|
475
|
-
|
476
|
-
|
633
|
+
klass.$$is_singleton = true;
|
634
|
+
klass.$$singleton_of = object;
|
635
|
+
|
636
|
+
return object.$$meta = klass;
|
637
|
+
};
|
477
638
|
|
478
639
|
// Bridges a single method.
|
479
|
-
function
|
640
|
+
Opal.bridge_method = function(target, from, name, body) {
|
480
641
|
var ancestors, i, ancestor, length;
|
481
642
|
|
482
643
|
ancestors = target.$$bridge.$ancestors();
|
@@ -500,10 +661,10 @@
|
|
500
661
|
}
|
501
662
|
}
|
502
663
|
|
503
|
-
}
|
664
|
+
};
|
504
665
|
|
505
666
|
// Bridges from *donator* to a *target*.
|
506
|
-
function
|
667
|
+
Opal._bridge = function(target, donator) {
|
507
668
|
var id, methods, method, i, bridged;
|
508
669
|
|
509
670
|
if (typeof(target) === "function") {
|
@@ -513,7 +674,7 @@
|
|
513
674
|
for (i = methods.length - 1; i >= 0; i--) {
|
514
675
|
method = '$' + methods[i];
|
515
676
|
|
516
|
-
bridge_method(target, donator, method, donator.$$proto[method]);
|
677
|
+
Opal.bridge_method(target, donator, method, donator.$$proto[method]);
|
517
678
|
}
|
518
679
|
|
519
680
|
if (!bridges[id]) {
|
@@ -527,13 +688,13 @@
|
|
527
688
|
|
528
689
|
if (bridged) {
|
529
690
|
for (i = bridged.length - 1; i >= 0; i--) {
|
530
|
-
_bridge(bridged[i], donator);
|
691
|
+
Opal._bridge(bridged[i], donator);
|
531
692
|
}
|
532
693
|
|
533
694
|
bridges[donator.$__id__()] = bridged.slice();
|
534
695
|
}
|
535
696
|
}
|
536
|
-
}
|
697
|
+
};
|
537
698
|
|
538
699
|
// The actual inclusion of a module into a class.
|
539
700
|
//
|
@@ -550,10 +711,9 @@
|
|
550
711
|
// a proxy to the actual module, so the `super` chain can then search it for
|
551
712
|
// the required method.
|
552
713
|
//
|
553
|
-
// @param [
|
554
|
-
// @param [
|
714
|
+
// @param module [Module] the module to include
|
715
|
+
// @param klass [Class] the target class to include module into
|
555
716
|
// @return [null]
|
556
|
-
//
|
557
717
|
Opal.append_features = function(module, klass) {
|
558
718
|
var iclass, donator, prototype, methods, id, i;
|
559
719
|
|
@@ -566,7 +726,7 @@
|
|
566
726
|
|
567
727
|
klass.$$inc.push(module);
|
568
728
|
module.$$dep.push(klass);
|
569
|
-
_bridge(klass, module);
|
729
|
+
Opal._bridge(klass, module);
|
570
730
|
|
571
731
|
// iclass
|
572
732
|
iclass = {
|
@@ -599,60 +759,12 @@
|
|
599
759
|
prototype[id].$$donated = module;
|
600
760
|
}
|
601
761
|
|
602
|
-
donate_constants(module, klass);
|
762
|
+
Opal.donate_constants(module, klass);
|
603
763
|
};
|
604
764
|
|
605
|
-
//
|
606
|
-
|
607
|
-
|
608
|
-
var alloc_proxy = function() {};
|
609
|
-
alloc_proxy.prototype = superklass.$$proto || superklass.prototype;
|
610
|
-
constructor.prototype = new alloc_proxy();
|
611
|
-
}
|
612
|
-
|
613
|
-
if (id) {
|
614
|
-
constructor.displayName = id+'_alloc';
|
615
|
-
}
|
616
|
-
|
617
|
-
constructor.prototype.constructor = constructor;
|
618
|
-
|
619
|
-
return constructor;
|
620
|
-
}
|
621
|
-
|
622
|
-
// Builds the class object for core classes:
|
623
|
-
// - make the class object have a singleton class
|
624
|
-
// - make the singleton class inherit from its parent singleton class
|
625
|
-
//
|
626
|
-
// @param id [String] the name of the class
|
627
|
-
// @param alloc [Function] the constructor for the core class instances
|
628
|
-
// @param superclass [Class alloc] the constructor of the superclass
|
629
|
-
//
|
630
|
-
function boot_core_class_object(id, alloc, superclass) {
|
631
|
-
var superclass_constructor = function() {};
|
632
|
-
superclass_constructor.prototype = superclass.prototype;
|
633
|
-
|
634
|
-
var singleton_class = function() {};
|
635
|
-
singleton_class.prototype = new superclass_constructor();
|
636
|
-
|
637
|
-
singleton_class.displayName = "#<Class:"+id+">";
|
638
|
-
|
639
|
-
// the singleton_class acts as the class object constructor
|
640
|
-
var klass = new singleton_class();
|
641
|
-
|
642
|
-
setup_module_or_class_object(klass, singleton_class, superclass, alloc.prototype);
|
643
|
-
|
644
|
-
klass.$$alloc = alloc;
|
645
|
-
klass.$$name = id;
|
646
|
-
klass.displayName = id;
|
647
|
-
|
648
|
-
// Give all instances a ref to their class
|
649
|
-
alloc.prototype.$$class = klass;
|
650
|
-
|
651
|
-
Opal[id] = klass;
|
652
|
-
Opal.constants.push(id);
|
653
|
-
|
654
|
-
return klass;
|
655
|
-
}
|
765
|
+
// Table that holds all methods that have been defined on all objects
|
766
|
+
// It is used for defining method stubs for new coming native classes
|
767
|
+
Opal.stubs = {};
|
656
768
|
|
657
769
|
// For performance, some core Ruby classes are toll-free bridged to their
|
658
770
|
// native JavaScript counterparts (e.g. a Ruby Array is a JavaScript Array).
|
@@ -667,8 +779,8 @@
|
|
667
779
|
//
|
668
780
|
// Opal.bridge(self, Function);
|
669
781
|
//
|
670
|
-
// @param [Class]
|
671
|
-
// @param [Function]
|
782
|
+
// @param klass [Class] the Ruby class to bridge
|
783
|
+
// @param constructor [JS.Function] native JavaScript constructor to use
|
672
784
|
// @return [Class] returns the passed Ruby class
|
673
785
|
//
|
674
786
|
Opal.bridge = function(klass, constructor) {
|
@@ -678,6 +790,13 @@
|
|
678
790
|
|
679
791
|
Opal.stub_subscribers.push(constructor.prototype);
|
680
792
|
|
793
|
+
// Populate constructor with previously stored stubs
|
794
|
+
for (var method_name in Opal.stubs) {
|
795
|
+
if (!(method_name in constructor.prototype)) {
|
796
|
+
constructor.prototype[method_name] = Opal.stub_for(method_name);
|
797
|
+
}
|
798
|
+
}
|
799
|
+
|
681
800
|
constructor.prototype.$$class = klass;
|
682
801
|
constructor.$$bridge = klass;
|
683
802
|
|
@@ -686,7 +805,7 @@
|
|
686
805
|
// order important here, we have to bridge from the last ancestor to the
|
687
806
|
// bridged class
|
688
807
|
for (var i = ancestors.length - 1; i >= 0; i--) {
|
689
|
-
_bridge(constructor, ancestors[i]);
|
808
|
+
Opal._bridge(constructor, ancestors[i]);
|
690
809
|
}
|
691
810
|
|
692
811
|
for (var name in BasicObject_alloc.prototype) {
|
@@ -698,68 +817,12 @@
|
|
698
817
|
}
|
699
818
|
|
700
819
|
return klass;
|
701
|
-
}
|
702
|
-
|
703
|
-
|
704
|
-
// Constant assignment, see also `Opal.cdecl`
|
705
|
-
//
|
706
|
-
// @param base_module [Module, Class] the constant namespace
|
707
|
-
// @param name [String] the name of the constant
|
708
|
-
// @param value [Object] the value of the constant
|
709
|
-
//
|
710
|
-
// @example Assigning a namespaced constant
|
711
|
-
// self::FOO = 'bar'
|
712
|
-
//
|
713
|
-
// @example Assigning with Module#const_set
|
714
|
-
// Foo.const_set :BAR, 123
|
715
|
-
//
|
716
|
-
Opal.casgn = function(base_module, name, value) {
|
717
|
-
function update(klass, name) {
|
718
|
-
klass.$$name = name;
|
719
|
-
|
720
|
-
for (name in klass.$$scope) {
|
721
|
-
var value = klass.$$scope[name];
|
722
|
-
|
723
|
-
if (value.$$name === nil && (value.$$is_class || value.$$is_module)) {
|
724
|
-
update(value, name)
|
725
|
-
}
|
726
|
-
}
|
727
|
-
}
|
728
|
-
|
729
|
-
var scope = base_module.$$scope;
|
730
|
-
|
731
|
-
if (value.$$is_class || value.$$is_module) {
|
732
|
-
// Only checking _Object prevents setting a const on an anonymous class
|
733
|
-
// that has a superclass that's not Object
|
734
|
-
if (value.$$is_class || value.$$base_module === _Object) {
|
735
|
-
value.$$base_module = base_module;
|
736
|
-
}
|
737
|
-
|
738
|
-
if (value.$$name === nil && value.$$base_module.$$name !== nil) {
|
739
|
-
update(value, name);
|
740
|
-
}
|
741
|
-
}
|
742
|
-
|
743
|
-
scope.constants.push(name);
|
744
|
-
return scope[name] = value;
|
745
|
-
};
|
746
|
-
|
747
|
-
// constant decl
|
748
|
-
Opal.cdecl = function(base_scope, name, value) {
|
749
|
-
if ((value.$$is_class || value.$$is_module) && value.$$orig_scope == null) {
|
750
|
-
value.$$name = name;
|
751
|
-
value.$$orig_scope = base_scope;
|
752
|
-
base_scope.constructor[name] = value;
|
753
|
-
}
|
754
|
-
|
755
|
-
base_scope.constants.push(name);
|
756
|
-
return base_scope[name] = value;
|
757
820
|
};
|
758
821
|
|
759
822
|
// When a source module is included into the target module, we must also copy
|
760
823
|
// its constants to the target.
|
761
824
|
//
|
762
|
-
function
|
825
|
+
Opal.donate_constants = function(source_mod, target_mod) {
|
763
826
|
var source_constants = source_mod.$$scope.constants,
|
764
827
|
target_scope = target_mod.$$scope,
|
765
828
|
target_constants = target_scope.constants;
|
@@ -771,7 +834,7 @@
|
|
771
834
|
};
|
772
835
|
|
773
836
|
// Donate methods for a module.
|
774
|
-
function
|
837
|
+
Opal.donate = function(module, jsid) {
|
775
838
|
var included_in = module.$$dep,
|
776
839
|
body = module.$$proto[jsid],
|
777
840
|
i, length, includee, dest, current,
|
@@ -817,11 +880,37 @@
|
|
817
880
|
}
|
818
881
|
|
819
882
|
if (includee.$$dep) {
|
820
|
-
donate(includee, jsid);
|
883
|
+
Opal.donate(includee, jsid);
|
884
|
+
}
|
885
|
+
}
|
886
|
+
};
|
887
|
+
|
888
|
+
// The Array of ancestors for a given module/class
|
889
|
+
Opal.ancestors = function(module_or_class) {
|
890
|
+
var parent = module_or_class,
|
891
|
+
result = [],
|
892
|
+
modules;
|
893
|
+
|
894
|
+
while (parent) {
|
895
|
+
result.push(parent);
|
896
|
+
for (var i=0; i < parent.$$inc.length; i++) {
|
897
|
+
modules = Opal.ancestors(parent.$$inc[i]);
|
898
|
+
|
899
|
+
for(var j = 0; j < modules.length; j++) {
|
900
|
+
result.push(modules[j]);
|
901
|
+
}
|
821
902
|
}
|
903
|
+
|
904
|
+
parent = parent.$$is_class ? parent.$$super : null;
|
822
905
|
}
|
906
|
+
|
907
|
+
return result;
|
823
908
|
};
|
824
909
|
|
910
|
+
|
911
|
+
// Method Missing
|
912
|
+
// --------------
|
913
|
+
|
825
914
|
// Methods stubs are used to facilitate method_missing in opal. A stub is a
|
826
915
|
// placeholder function which just calls `method_missing` on the receiver.
|
827
916
|
// If no method with the given name is actually defined on an object, then it
|
@@ -847,8 +936,8 @@
|
|
847
936
|
// that other internal methods can detect if a method is just a stub or not.
|
848
937
|
// `Kernel#respond_to?` uses this property to detect a methods presence.
|
849
938
|
//
|
850
|
-
// @param [Array]
|
851
|
-
//
|
939
|
+
// @param stubs [Array] an array of method stubs to add
|
940
|
+
// @return [undefined]
|
852
941
|
Opal.add_stubs = function(stubs) {
|
853
942
|
var subscriber, subscribers = Opal.stub_subscribers,
|
854
943
|
i, ilength = stubs.length,
|
@@ -857,7 +946,9 @@
|
|
857
946
|
|
858
947
|
for (i = 0; i < ilength; i++) {
|
859
948
|
method_name = stubs[i];
|
860
|
-
|
949
|
+
// Save method name to populate other subscribers with this stub
|
950
|
+
Opal.stubs[method_name] = true;
|
951
|
+
stub = Opal.stub_for(method_name);
|
861
952
|
|
862
953
|
for (j = 0; j < jlength; j++) {
|
863
954
|
subscriber = subscribers[j];
|
@@ -878,19 +969,19 @@
|
|
878
969
|
// Add a method_missing stub function to the given prototype for the
|
879
970
|
// given name.
|
880
971
|
//
|
881
|
-
// @param [Prototype]
|
882
|
-
// @param [String] stub
|
883
|
-
//
|
972
|
+
// @param prototype [Prototype] the target prototype
|
973
|
+
// @param stub [String] stub name to add (e.g. "$foo")
|
974
|
+
// @return [undefined]
|
884
975
|
Opal.add_stub_for = function(prototype, stub) {
|
885
|
-
var method_missing_stub = stub_for(stub);
|
976
|
+
var method_missing_stub = Opal.stub_for(stub);
|
886
977
|
prototype[stub] = method_missing_stub;
|
887
|
-
}
|
978
|
+
};
|
888
979
|
|
889
980
|
// Generate the method_missing stub for a given method name.
|
890
981
|
//
|
891
|
-
// @param [String]
|
892
|
-
//
|
893
|
-
function
|
982
|
+
// @param method_name [String] The js-name of the method to stub (e.g. "$foo")
|
983
|
+
// @return [undefined]
|
984
|
+
Opal.stub_for = function(method_name) {
|
894
985
|
function method_missing_stub() {
|
895
986
|
// Copy any given block onto the method_missing dispatcher
|
896
987
|
this.$method_missing.$$p = method_missing_stub.$$p;
|
@@ -905,7 +996,11 @@
|
|
905
996
|
method_missing_stub.$$stub = true;
|
906
997
|
|
907
998
|
return method_missing_stub;
|
908
|
-
}
|
999
|
+
};
|
1000
|
+
|
1001
|
+
|
1002
|
+
// Methods
|
1003
|
+
// -------
|
909
1004
|
|
910
1005
|
// Arity count error dispatcher
|
911
1006
|
Opal.ac = function(actual, expected, object, meth) {
|
@@ -921,25 +1016,8 @@
|
|
921
1016
|
throw Opal.ArgumentError.$new('[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')');
|
922
1017
|
};
|
923
1018
|
|
924
|
-
// The Array of ancestors for a given module/class
|
925
|
-
Opal.ancestors = function(module_or_class) {
|
926
|
-
var parent = module_or_class,
|
927
|
-
result = [];
|
928
|
-
|
929
|
-
while (parent) {
|
930
|
-
result.push(parent);
|
931
|
-
for (var i=0; i < parent.$$inc.length; i++) {
|
932
|
-
result = result.concat(Opal.ancestors(parent.$$inc[i]));
|
933
|
-
}
|
934
|
-
|
935
|
-
parent = parent.$$is_class ? parent.$$super : null;
|
936
|
-
}
|
937
|
-
|
938
|
-
return result;
|
939
|
-
}
|
940
|
-
|
941
1019
|
// Super dispatcher
|
942
|
-
Opal.find_super_dispatcher = function(obj, jsid, current_func,
|
1020
|
+
Opal.find_super_dispatcher = function(obj, jsid, current_func, defcheck, defs) {
|
943
1021
|
var dispatcher;
|
944
1022
|
|
945
1023
|
if (defs) {
|
@@ -955,33 +1033,47 @@
|
|
955
1033
|
dispatcher = obj.$$super;
|
956
1034
|
}
|
957
1035
|
else {
|
958
|
-
dispatcher = find_obj_super_dispatcher(obj, jsid, current_func);
|
1036
|
+
dispatcher = Opal.find_obj_super_dispatcher(obj, jsid, current_func);
|
959
1037
|
}
|
960
1038
|
}
|
961
1039
|
|
962
1040
|
dispatcher = dispatcher['$' + jsid];
|
963
|
-
|
1041
|
+
|
1042
|
+
if (!defcheck && dispatcher.$$stub && Opal.Kernel.$method_missing === obj.$method_missing) {
|
1043
|
+
// method_missing hasn't been explicitly defined
|
1044
|
+
throw Opal.NoMethodError.$new('super: no superclass method `'+jsid+"' for "+obj, jsid);
|
1045
|
+
}
|
964
1046
|
|
965
1047
|
return dispatcher;
|
966
1048
|
};
|
967
1049
|
|
968
1050
|
// Iter dispatcher for super in a block
|
969
|
-
Opal.find_iter_super_dispatcher = function(obj, jsid, current_func,
|
970
|
-
|
971
|
-
|
1051
|
+
Opal.find_iter_super_dispatcher = function(obj, jsid, current_func, defcheck, implicit) {
|
1052
|
+
var call_jsid = jsid;
|
1053
|
+
|
1054
|
+
if (!current_func) {
|
1055
|
+
throw Opal.RuntimeError.$new("super called outside of method");
|
972
1056
|
}
|
973
|
-
|
974
|
-
|
1057
|
+
|
1058
|
+
if (implicit && current_func.$$define_meth) {
|
1059
|
+
throw Opal.RuntimeError.$new("implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly");
|
975
1060
|
}
|
1061
|
+
|
1062
|
+
if (current_func.$$def) {
|
1063
|
+
call_jsid = current_func.$$jsid;
|
1064
|
+
}
|
1065
|
+
|
1066
|
+
return Opal.find_super_dispatcher(obj, call_jsid, current_func, defcheck);
|
976
1067
|
};
|
977
1068
|
|
978
|
-
function
|
1069
|
+
Opal.find_obj_super_dispatcher = function(obj, jsid, current_func) {
|
979
1070
|
var klass = obj.$$meta || obj.$$class;
|
980
1071
|
jsid = '$' + jsid;
|
981
1072
|
|
1073
|
+
// first we need to find the class/module current_func is defined/donated on
|
982
1074
|
while (klass) {
|
983
|
-
|
984
|
-
|
1075
|
+
// when a module has been included in a class, look for that
|
1076
|
+
if ((klass.$$iclass && klass.$$module === current_func.$$owner) || klass === current_func.$$owner) {
|
985
1077
|
break;
|
986
1078
|
}
|
987
1079
|
|
@@ -995,7 +1087,7 @@
|
|
995
1087
|
|
996
1088
|
klass = klass.$$parent;
|
997
1089
|
|
998
|
-
//
|
1090
|
+
// now we can find the super
|
999
1091
|
while (klass) {
|
1000
1092
|
var working = klass.$$proto[jsid];
|
1001
1093
|
|
@@ -1022,6 +1114,18 @@
|
|
1022
1114
|
throw Opal.returner;
|
1023
1115
|
};
|
1024
1116
|
|
1117
|
+
// Used to break out of a block.
|
1118
|
+
Opal.brk = function(val, breaker) {
|
1119
|
+
breaker.$v = val;
|
1120
|
+
throw breaker;
|
1121
|
+
};
|
1122
|
+
|
1123
|
+
// Builds a new unique breaker, this is to avoid multiple nested breaks to get
|
1124
|
+
// in the way of each other.
|
1125
|
+
Opal.new_brk = function() {
|
1126
|
+
return new Error('unexpected break');
|
1127
|
+
};
|
1128
|
+
|
1025
1129
|
// handles yield calls for 1 yielded arg
|
1026
1130
|
Opal.yield1 = function(block, arg) {
|
1027
1131
|
if (typeof(block) !== "function") {
|
@@ -1081,20 +1185,20 @@
|
|
1081
1185
|
return true;
|
1082
1186
|
}
|
1083
1187
|
|
1084
|
-
var
|
1188
|
+
var i, length, ancestors = Opal.ancestors(object.$$class);
|
1085
1189
|
|
1086
|
-
|
1087
|
-
if (
|
1190
|
+
for (i = 0, length = ancestors.length; i < length; i++) {
|
1191
|
+
if (ancestors[i] === klass) {
|
1088
1192
|
return true;
|
1089
1193
|
}
|
1194
|
+
}
|
1090
1195
|
|
1091
|
-
|
1092
|
-
if (search.$$inc[i] === klass) {
|
1093
|
-
return true;
|
1094
|
-
}
|
1095
|
-
}
|
1196
|
+
ancestors = Opal.ancestors(object.$$meta);
|
1096
1197
|
|
1097
|
-
|
1198
|
+
for (i = 0, length = ancestors.length; i < length; i++) {
|
1199
|
+
if (ancestors[i] === klass) {
|
1200
|
+
return true;
|
1201
|
+
}
|
1098
1202
|
}
|
1099
1203
|
|
1100
1204
|
return false;
|
@@ -1102,13 +1206,13 @@
|
|
1102
1206
|
|
1103
1207
|
// Helpers for implementing multiple assignment
|
1104
1208
|
// Our code for extracting the values and assigning them only works if the
|
1105
|
-
// return value is a JS array
|
1209
|
+
// return value is a JS array.
|
1106
1210
|
// So if we get an Array subclass, extract the wrapped JS array from it
|
1107
1211
|
|
1212
|
+
// Used for: a, b = something (no splat)
|
1108
1213
|
Opal.to_ary = function(value) {
|
1109
|
-
// Used for: a, b = something (no splat)
|
1110
1214
|
if (value.$$is_array) {
|
1111
|
-
return
|
1215
|
+
return value;
|
1112
1216
|
}
|
1113
1217
|
else if (value['$respond_to?']('to_ary', true)) {
|
1114
1218
|
var ary = value.$to_ary();
|
@@ -1116,7 +1220,7 @@
|
|
1116
1220
|
return [value];
|
1117
1221
|
}
|
1118
1222
|
else if (ary.$$is_array) {
|
1119
|
-
return
|
1223
|
+
return ary;
|
1120
1224
|
}
|
1121
1225
|
else {
|
1122
1226
|
throw Opal.TypeError.$new("Can't convert " + value.$$class +
|
@@ -1128,11 +1232,11 @@
|
|
1128
1232
|
}
|
1129
1233
|
};
|
1130
1234
|
|
1235
|
+
// Used for: a, b = *something (with splat)
|
1131
1236
|
Opal.to_a = function(value) {
|
1132
|
-
// Used for: a, b = *something (with splat)
|
1133
1237
|
if (value.$$is_array) {
|
1134
1238
|
// A splatted array must be copied
|
1135
|
-
return
|
1239
|
+
return value.slice();
|
1136
1240
|
}
|
1137
1241
|
else if (value['$respond_to?']('to_a', true)) {
|
1138
1242
|
var ary = value.$to_a();
|
@@ -1140,7 +1244,7 @@
|
|
1140
1244
|
return [value];
|
1141
1245
|
}
|
1142
1246
|
else if (ary.$$is_array) {
|
1143
|
-
return
|
1247
|
+
return ary;
|
1144
1248
|
}
|
1145
1249
|
else {
|
1146
1250
|
throw Opal.TypeError.$new("Can't convert " + value.$$class +
|
@@ -1152,6 +1256,24 @@
|
|
1152
1256
|
}
|
1153
1257
|
};
|
1154
1258
|
|
1259
|
+
// Used for extracting keyword arguments from arguments passed to
|
1260
|
+
// JS function. If provided +arguments+ list doesn't have a Hash
|
1261
|
+
// as a last item, returns a blank Hash.
|
1262
|
+
//
|
1263
|
+
// @param parameters [Array]
|
1264
|
+
// @return [Hash]
|
1265
|
+
//
|
1266
|
+
Opal.extract_kwargs = function(parameters) {
|
1267
|
+
var kwargs = parameters[parameters.length - 1];
|
1268
|
+
if (kwargs != null && kwargs['$respond_to?']('to_hash', true)) {
|
1269
|
+
Array.prototype.splice.call(parameters, parameters.length - 1, 1);
|
1270
|
+
return kwargs.$to_hash();
|
1271
|
+
}
|
1272
|
+
else {
|
1273
|
+
return Opal.hash2([], {});
|
1274
|
+
}
|
1275
|
+
}
|
1276
|
+
|
1155
1277
|
// Used to get a list of rest keyword arguments. Method takes the given
|
1156
1278
|
// keyword args, i.e. the hash literal passed to the method containing all
|
1157
1279
|
// keyword arguemnts passed to method, as well as the used args which are
|
@@ -1181,6 +1303,7 @@
|
|
1181
1303
|
|
1182
1304
|
// Call a ruby method on a ruby object with some arguments:
|
1183
1305
|
//
|
1306
|
+
// @example
|
1184
1307
|
// var my_array = [1, 2, 3, 4]
|
1185
1308
|
// Opal.send(my_array, 'length') # => 4
|
1186
1309
|
// Opal.send(my_array, 'reverse!') # => [4, 3, 2, 1]
|
@@ -1190,9 +1313,9 @@
|
|
1190
1313
|
//
|
1191
1314
|
// The result of either call with be returned.
|
1192
1315
|
//
|
1193
|
-
// @param [Object]
|
1194
|
-
// @param [String]
|
1195
|
-
//
|
1316
|
+
// @param recv [Object] the ruby object
|
1317
|
+
// @param mid [String] ruby method to call
|
1318
|
+
// @return [Object] forwards the return value of the method (or of method_missing)
|
1196
1319
|
Opal.send = function(recv, mid) {
|
1197
1320
|
var args = $slice.call(arguments, 2),
|
1198
1321
|
func = recv['$' + mid];
|
@@ -1247,16 +1370,18 @@
|
|
1247
1370
|
// defined on the object as a singleton method. This would be the case when
|
1248
1371
|
// a method is defined inside an `instance_eval` block.
|
1249
1372
|
//
|
1250
|
-
// @param [
|
1251
|
-
// @param [String]
|
1252
|
-
// @param [Function]
|
1373
|
+
// @param obj [Object, Class] the actual obj to define method for
|
1374
|
+
// @param jsid [String] the javascript friendly method name (e.g. '$foo')
|
1375
|
+
// @param body [JS.Function] the literal javascript function used as method
|
1253
1376
|
// @return [null]
|
1254
1377
|
//
|
1255
1378
|
Opal.defn = function(obj, jsid, body) {
|
1256
1379
|
obj.$$proto[jsid] = body;
|
1380
|
+
// for super dispatcher, etc.
|
1381
|
+
body.$$owner = obj;
|
1257
1382
|
|
1258
1383
|
if (obj.$$is_module) {
|
1259
|
-
donate(obj, jsid);
|
1384
|
+
Opal.donate(obj, jsid);
|
1260
1385
|
|
1261
1386
|
if (obj.$$module_function) {
|
1262
1387
|
Opal.defs(obj, jsid, body);
|
@@ -1268,24 +1393,22 @@
|
|
1268
1393
|
|
1269
1394
|
if (bridged) {
|
1270
1395
|
for (var i = bridged.length - 1; i >= 0; i--) {
|
1271
|
-
bridge_method(bridged[i], obj, jsid, body);
|
1396
|
+
Opal.bridge_method(bridged[i], obj, jsid, body);
|
1272
1397
|
}
|
1273
1398
|
}
|
1274
1399
|
}
|
1275
1400
|
|
1276
|
-
|
1401
|
+
var singleton_of = obj.$$singleton_of;
|
1402
|
+
if (obj.$method_added && !obj.$method_added.$$stub && !singleton_of) {
|
1277
1403
|
obj.$method_added(jsid.substr(1));
|
1278
1404
|
}
|
1279
|
-
|
1280
|
-
var singleton_of = obj.$$singleton_of;
|
1281
|
-
if (singleton_of && singleton_of.$singleton_method_added && !singleton_of.$singleton_method_added.$$stub) {
|
1405
|
+
else if (singleton_of && singleton_of.$singleton_method_added && !singleton_of.$singleton_method_added.$$stub) {
|
1282
1406
|
singleton_of.$singleton_method_added(jsid.substr(1));
|
1283
1407
|
}
|
1284
1408
|
|
1285
1409
|
return nil;
|
1286
1410
|
};
|
1287
1411
|
|
1288
|
-
|
1289
1412
|
// Define a singleton method on the given object.
|
1290
1413
|
Opal.defs = function(obj, jsid, body) {
|
1291
1414
|
Opal.defn(Opal.get_singleton_class(obj), jsid, body)
|
@@ -1384,15 +1507,19 @@
|
|
1384
1507
|
return obj;
|
1385
1508
|
};
|
1386
1509
|
|
1510
|
+
|
1511
|
+
// Hashes
|
1512
|
+
// ------
|
1513
|
+
|
1387
1514
|
Opal.hash_init = function(hash) {
|
1388
|
-
hash.$$map = {};
|
1389
1515
|
hash.$$smap = {};
|
1516
|
+
hash.$$map = {};
|
1390
1517
|
hash.$$keys = [];
|
1391
1518
|
};
|
1392
1519
|
|
1393
1520
|
Opal.hash_clone = function(from_hash, to_hash) {
|
1394
|
-
to_hash
|
1395
|
-
to_hash
|
1521
|
+
to_hash.$$none = from_hash.$$none;
|
1522
|
+
to_hash.$$proc = from_hash.$$proc;
|
1396
1523
|
|
1397
1524
|
for (var i = 0, keys = from_hash.$$keys, length = keys.length, key, value; i < length; i++) {
|
1398
1525
|
key = from_hash.$$keys[i];
|
@@ -1650,9 +1777,9 @@
|
|
1650
1777
|
Opal.hash2 = function(keys, smap) {
|
1651
1778
|
var hash = new Opal.Hash.$$alloc();
|
1652
1779
|
|
1780
|
+
hash.$$smap = smap;
|
1653
1781
|
hash.$$map = {};
|
1654
1782
|
hash.$$keys = keys;
|
1655
|
-
hash.$$smap = smap;
|
1656
1783
|
|
1657
1784
|
return hash;
|
1658
1785
|
};
|
@@ -1690,6 +1817,7 @@
|
|
1690
1817
|
return name;
|
1691
1818
|
};
|
1692
1819
|
|
1820
|
+
|
1693
1821
|
// Require system
|
1694
1822
|
// --------------
|
1695
1823
|
|
@@ -1698,7 +1826,7 @@
|
|
1698
1826
|
Opal.current_dir = '.'
|
1699
1827
|
Opal.require_table = {'corelib/runtime': true};
|
1700
1828
|
|
1701
|
-
function
|
1829
|
+
Opal.normalize = function(path) {
|
1702
1830
|
var parts, part, new_parts = [], SEPARATOR = '/';
|
1703
1831
|
|
1704
1832
|
if (Opal.current_dir !== '.') {
|
@@ -1715,13 +1843,13 @@
|
|
1715
1843
|
}
|
1716
1844
|
|
1717
1845
|
return new_parts.join(SEPARATOR);
|
1718
|
-
}
|
1846
|
+
};
|
1719
1847
|
|
1720
1848
|
Opal.loaded = function(paths) {
|
1721
1849
|
var i, l, path;
|
1722
1850
|
|
1723
1851
|
for (i = 0, l = paths.length; i < l; i++) {
|
1724
|
-
path = normalize(paths[i]);
|
1852
|
+
path = Opal.normalize(paths[i]);
|
1725
1853
|
|
1726
1854
|
if (Opal.require_table[path]) {
|
1727
1855
|
return;
|
@@ -1730,10 +1858,10 @@
|
|
1730
1858
|
Opal.loaded_features.push(path);
|
1731
1859
|
Opal.require_table[path] = true;
|
1732
1860
|
}
|
1733
|
-
}
|
1861
|
+
};
|
1734
1862
|
|
1735
1863
|
Opal.load = function(path) {
|
1736
|
-
path = normalize(path);
|
1864
|
+
path = Opal.normalize(path);
|
1737
1865
|
|
1738
1866
|
Opal.loaded([path]);
|
1739
1867
|
|
@@ -1743,7 +1871,7 @@
|
|
1743
1871
|
module(Opal);
|
1744
1872
|
}
|
1745
1873
|
else {
|
1746
|
-
var severity = Opal.
|
1874
|
+
var severity = Opal.config.missing_require_severity;
|
1747
1875
|
var message = 'cannot load such file -- ' + path;
|
1748
1876
|
|
1749
1877
|
if (severity === "error") {
|
@@ -1755,32 +1883,38 @@
|
|
1755
1883
|
}
|
1756
1884
|
|
1757
1885
|
return true;
|
1758
|
-
}
|
1886
|
+
};
|
1759
1887
|
|
1760
1888
|
Opal.require = function(path) {
|
1761
|
-
path = normalize(path);
|
1889
|
+
path = Opal.normalize(path);
|
1762
1890
|
|
1763
1891
|
if (Opal.require_table[path]) {
|
1764
1892
|
return false;
|
1765
1893
|
}
|
1766
1894
|
|
1767
1895
|
return Opal.load(path);
|
1768
|
-
}
|
1896
|
+
};
|
1897
|
+
|
1769
1898
|
|
1770
1899
|
// Initialization
|
1771
1900
|
// --------------
|
1772
1901
|
|
1773
1902
|
// Constructors for *instances* of core objects
|
1774
|
-
boot_class_alloc('BasicObject', BasicObject_alloc);
|
1775
|
-
boot_class_alloc('Object', Object_alloc, BasicObject_alloc);
|
1776
|
-
boot_class_alloc('Module', Module_alloc, Object_alloc);
|
1777
|
-
boot_class_alloc('Class', Class_alloc, Module_alloc);
|
1903
|
+
Opal.boot_class_alloc('BasicObject', BasicObject_alloc);
|
1904
|
+
Opal.boot_class_alloc('Object', Object_alloc, BasicObject_alloc);
|
1905
|
+
Opal.boot_class_alloc('Module', Module_alloc, Object_alloc);
|
1906
|
+
Opal.boot_class_alloc('Class', Class_alloc, Module_alloc);
|
1778
1907
|
|
1779
1908
|
// Constructors for *classes* of core objects
|
1780
|
-
BasicObject =
|
1781
|
-
_Object =
|
1782
|
-
Module =
|
1783
|
-
Class =
|
1909
|
+
Opal.BasicObject = BasicObject = Opal.setup_class_object('BasicObject', BasicObject_alloc, 'Class', Class_alloc);
|
1910
|
+
Opal.Object = _Object = Opal.setup_class_object('Object', Object_alloc, 'BasicObject', BasicObject.constructor);
|
1911
|
+
Opal.Module = Module = Opal.setup_class_object('Module', Module_alloc, 'Object', _Object.constructor);
|
1912
|
+
Opal.Class = Class = Opal.setup_class_object('Class', Class_alloc, 'Module', Module.constructor);
|
1913
|
+
|
1914
|
+
Opal.constants.push("BasicObject");
|
1915
|
+
Opal.constants.push("Object");
|
1916
|
+
Opal.constants.push("Module");
|
1917
|
+
Opal.constants.push("Class");
|
1784
1918
|
|
1785
1919
|
// Fix booted classes to use their metaclass
|
1786
1920
|
BasicObject.$$class = Class;
|
@@ -1808,12 +1942,16 @@
|
|
1808
1942
|
Class.$$scope = _Object.$$scope;
|
1809
1943
|
Class.$$orig_scope = _Object.$$orig_scope;
|
1810
1944
|
|
1945
|
+
// Forward .toString() to #to_s
|
1811
1946
|
_Object.$$proto.toString = function() {
|
1812
1947
|
return this.$to_s();
|
1813
1948
|
};
|
1814
1949
|
|
1950
|
+
// Make Kernel#require immediately available as it's needed to require all the
|
1951
|
+
// other corelib files.
|
1815
1952
|
_Object.$$proto.$require = Opal.require;
|
1816
1953
|
|
1954
|
+
// Instantiate the top object
|
1817
1955
|
Opal.top = new _Object.$$alloc();
|
1818
1956
|
|
1819
1957
|
// Nil
|
@@ -1821,8 +1959,7 @@
|
|
1821
1959
|
nil = Opal.nil = new NilClass_alloc();
|
1822
1960
|
nil.$$id = nil_id;
|
1823
1961
|
nil.call = nil.apply = function() { throw Opal.LocalJumpError.$new('no block given'); };
|
1824
|
-
|
1825
|
-
Opal.breaker = new Error('unexpected break');
|
1962
|
+
Opal.breaker = new Error('unexpected break (old)');
|
1826
1963
|
Opal.returner = new Error('unexpected return');
|
1827
1964
|
|
1828
1965
|
TypeError.$$super = Error;
|