opal 0.3.19 → 0.3.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +3 -1
- data/Gemfile +3 -2
- data/README.md +304 -48
- data/Rakefile +1 -2
- data/core/alpha.rb +2 -1
- data/core/array.rb +92 -96
- data/core/basic_object.rb +1 -10
- data/core/boolean.rb +6 -18
- data/core/class.rb +9 -10
- data/core/comparable.rb +1 -1
- data/core/enumerable.rb +11 -11
- data/core/enumerator.rb +2 -10
- data/core/error.rb +16 -31
- data/core/hash.rb +32 -36
- data/core/json.rb +50 -0
- data/core/kernel.rb +48 -57
- data/core/load_order +3 -5
- data/core/module.rb +37 -35
- data/core/nil_class.rb +4 -0
- data/core/numeric.rb +10 -30
- data/core/proc.rb +1 -1
- data/core/range.rb +3 -4
- data/core/regexp.rb +21 -6
- data/core/runtime.js +278 -370
- data/core/string.rb +21 -37
- data/core/struct.rb +11 -3
- data/core/time.rb +44 -37
- data/lib/opal.rb +3 -3
- data/lib/opal/builder.rb +48 -27
- data/lib/opal/builder_task.rb +3 -20
- data/lib/opal/grammar.rb +18 -13
- data/lib/opal/grammar.y +7 -4
- data/lib/opal/parser.rb +290 -199
- data/lib/opal/scope.rb +187 -176
- data/lib/opal/version.rb +1 -1
- data/test/core/kernel/define_singleton_method_spec.rb +21 -0
- data/test/core/time/at_spec.rb +7 -0
- data/test/core/time/day_spec.rb +5 -0
- data/test/core/time/friday_spec.rb +9 -0
- data/test/core/time/hour_spec.rb +5 -0
- data/test/core/time/min_spec.rb +5 -0
- data/test/core/time/monday_spec.rb +9 -0
- data/test/core/time/month_spec.rb +5 -0
- data/test/core/time/now_spec.rb +5 -0
- data/test/core/time/saturday_spec.rb +9 -0
- data/test/index.html +2 -1
- data/test/language/singleton_class_spec.rb +0 -16
- data/test/opal/array/to_json_spec.rb +7 -0
- data/test/opal/boolean/singleton_class_spec.rb +9 -0
- data/test/opal/boolean/to_json_spec.rb +9 -0
- data/test/opal/hash/to_json_spec.rb +9 -0
- data/test/opal/json/parse_spec.rb +31 -0
- data/test/opal/kernel/to_json_spec.rb +5 -0
- data/test/opal/nil/to_json_spec.rb +5 -0
- data/test/opal/numeric/to_json_spec.rb +6 -0
- data/test/opal/runtime/call_spec.rb +16 -0
- data/test/opal/runtime/defined_spec.rb +11 -0
- data/test/opal/runtime/super_spec.rb +16 -0
- data/test/opal/string/to_json_spec.rb +6 -0
- data/test/spec_helper.rb +1 -3
- metadata +48 -15
- data/core/dir.rb +0 -89
- data/core/file.rb +0 -85
- data/core/match_data.rb +0 -35
- data/core/rational.rb +0 -16
- data/test/core/file/expand_path_spec.rb +0 -20
data/core/regexp.rb
CHANGED
@@ -20,10 +20,11 @@ class Regexp < `RegExp`
|
|
20
20
|
var result = this.exec(string);
|
21
21
|
|
22
22
|
if (result) {
|
23
|
-
|
24
|
-
|
23
|
+
result.$to_s = match_to_s;
|
24
|
+
result.$inspect = match_inspect;
|
25
|
+
result._real = result._klass = #{ MatchData };
|
25
26
|
|
26
|
-
#{$~ = `
|
27
|
+
#{$~ = `result`};
|
27
28
|
}
|
28
29
|
else {
|
29
30
|
#{$~ = nil};
|
@@ -44,10 +45,11 @@ class Regexp < `RegExp`
|
|
44
45
|
var result = this.exec(pattern);
|
45
46
|
|
46
47
|
if (result) {
|
47
|
-
|
48
|
-
|
48
|
+
result.$to_s = match_to_s;
|
49
|
+
result.$inspect = match_inspect;
|
50
|
+
result._real = result._klass = #{ MatchData };
|
49
51
|
|
50
|
-
return #{$~ = `
|
52
|
+
return #{$~ = `result`};
|
51
53
|
}
|
52
54
|
else {
|
53
55
|
return #{$~ = nil};
|
@@ -58,4 +60,17 @@ class Regexp < `RegExp`
|
|
58
60
|
def to_s
|
59
61
|
`this.source`
|
60
62
|
end
|
63
|
+
|
64
|
+
%x{
|
65
|
+
function match_inspect() {
|
66
|
+
return "<#MatchData " + this[0].$inspect() + ">";
|
67
|
+
}
|
68
|
+
|
69
|
+
function match_to_s() {
|
70
|
+
return this[0];
|
71
|
+
}
|
72
|
+
}
|
61
73
|
end
|
74
|
+
|
75
|
+
class MatchData
|
76
|
+
end
|
data/core/runtime.js
CHANGED
@@ -1,14 +1,35 @@
|
|
1
|
-
//
|
2
|
-
var
|
3
|
-
var top_const_scope = top_const_alloc.prototype;
|
4
|
-
top_const_scope.alloc = top_const_alloc;
|
1
|
+
// The Opal object that is exposed globally
|
2
|
+
var Opal = this.Opal = {};
|
5
3
|
|
6
|
-
|
4
|
+
// Very root class
|
5
|
+
function BasicObject(){}
|
7
6
|
|
7
|
+
// Core Object class
|
8
|
+
function Object(){}
|
9
|
+
|
10
|
+
// Class' class
|
11
|
+
function Class(){}
|
12
|
+
|
13
|
+
// Modules are just classes that cannot be instantiated
|
14
|
+
var Module = Class;
|
15
|
+
|
16
|
+
// the class of nil
|
17
|
+
function NilClass(){}
|
18
|
+
|
19
|
+
// TopScope is used for inheriting constants from the top scope
|
20
|
+
var TopScope = function(){};
|
21
|
+
|
22
|
+
// Opal just acts as the top scope
|
23
|
+
TopScope.prototype = Opal;
|
24
|
+
|
25
|
+
// To inherit scopes
|
26
|
+
Opal.alloc = TopScope;
|
27
|
+
|
28
|
+
// This is a useful reference to global object inside ruby files
|
8
29
|
Opal.global = this;
|
9
30
|
|
10
31
|
// Minify common function calls
|
11
|
-
var __hasOwn =
|
32
|
+
var __hasOwn = Opal.hasOwnProperty;
|
12
33
|
var __slice = Opal.slice = Array.prototype.slice;
|
13
34
|
|
14
35
|
// Generates unique id for every ruby object
|
@@ -20,35 +41,80 @@ Opal.cvars = {};
|
|
20
41
|
// Globals table
|
21
42
|
Opal.gvars = {};
|
22
43
|
|
23
|
-
|
44
|
+
// Runtime method used to either define a new class, or re-open an old
|
45
|
+
// class. The base may be an object (rather than a class), which is
|
46
|
+
// always the case when defining classes in the top level as the top
|
47
|
+
// level is just the 'main' Object instance.
|
48
|
+
//
|
49
|
+
// The given ruby code:
|
50
|
+
//
|
51
|
+
// class Foo
|
52
|
+
// 42
|
53
|
+
// end
|
54
|
+
//
|
55
|
+
// class Bar < Foo
|
56
|
+
// 3.142
|
57
|
+
// end
|
58
|
+
//
|
59
|
+
// Would be compiled to something like:
|
60
|
+
//
|
61
|
+
// var __klass = Opal.klass;
|
62
|
+
//
|
63
|
+
// __klass(this, null, 'Foo', function() {
|
64
|
+
// return 42;
|
65
|
+
// });
|
66
|
+
//
|
67
|
+
// __klass(this, __scope.Foo, 'Bar', function() {
|
68
|
+
// return 3.142;
|
69
|
+
// });
|
70
|
+
//
|
71
|
+
// @param [RubyObject] base the scope in which to define the class
|
72
|
+
// @param [RubyClass] superklass the superklass, may be null
|
73
|
+
// @param [String] id the name for the class
|
74
|
+
// @param [Function] body the class body
|
75
|
+
// @return returns last value from running body
|
76
|
+
Opal.klass = function(base, superklass, id, constructor) {
|
24
77
|
var klass;
|
25
78
|
if (base._isObject) {
|
26
79
|
base = base._real;
|
27
80
|
}
|
28
81
|
|
29
82
|
if (superklass === null) {
|
30
|
-
superklass =
|
83
|
+
superklass = Object;
|
31
84
|
}
|
32
85
|
|
33
86
|
if (__hasOwn.call(base._scope, id)) {
|
34
87
|
klass = base._scope[id];
|
35
88
|
}
|
36
|
-
else if (!superklass._klass || !superklass._proto) {
|
37
|
-
klass = bridge_class(superklass, id);
|
38
|
-
}
|
39
89
|
else {
|
40
|
-
|
90
|
+
if (!superklass._methods) {
|
91
|
+
var bridged = superklass;
|
92
|
+
superklass = Object;
|
93
|
+
klass = bridge_class(bridged);
|
94
|
+
}
|
95
|
+
else {
|
96
|
+
klass = boot_class(superklass, constructor);
|
97
|
+
}
|
98
|
+
|
99
|
+
klass._name = (base === Object ? id : base._name + '::' + id);
|
100
|
+
|
101
|
+
var const_alloc = function() {};
|
102
|
+
var const_scope = const_alloc.prototype = new base._scope.alloc();
|
103
|
+
klass._scope = const_scope;
|
104
|
+
const_scope.alloc = const_alloc;
|
105
|
+
|
106
|
+
base[id] = base._scope[id] = klass;
|
107
|
+
|
108
|
+
if (superklass.$inherited) {
|
109
|
+
superklass.$inherited(klass);
|
110
|
+
}
|
41
111
|
}
|
42
112
|
|
43
|
-
return
|
113
|
+
return klass;
|
44
114
|
};
|
45
115
|
|
46
|
-
|
47
|
-
|
48
|
-
return body.call(klass);
|
49
|
-
}
|
50
|
-
|
51
|
-
Opal.module = function(base, id, body) {
|
116
|
+
// Define new module (or return existing module)
|
117
|
+
Opal.module = function(base, id, constructor) {
|
52
118
|
var klass;
|
53
119
|
if (base._isObject) {
|
54
120
|
base = base._real;
|
@@ -58,10 +124,8 @@ Opal.module = function(base, id, body) {
|
|
58
124
|
klass = base._scope[id];
|
59
125
|
}
|
60
126
|
else {
|
61
|
-
klass = boot_module();
|
62
|
-
klass._name = (base ===
|
63
|
-
|
64
|
-
make_metaclass(klass, RubyModule);
|
127
|
+
klass = boot_module(constructor, id);
|
128
|
+
klass._name = (base === Object ? id : base._name + '::' + id);
|
65
129
|
|
66
130
|
klass._isModule = true;
|
67
131
|
klass.$included_in = [];
|
@@ -71,268 +135,161 @@ Opal.module = function(base, id, body) {
|
|
71
135
|
klass._scope = const_scope;
|
72
136
|
const_scope.alloc = const_alloc;
|
73
137
|
|
74
|
-
base._scope[id] = klass;
|
138
|
+
base[id] = base._scope[id] = klass;
|
75
139
|
}
|
76
140
|
|
77
|
-
return
|
141
|
+
return klass;
|
78
142
|
}
|
79
143
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
method will all the defined methods. They are then passed onto
|
85
|
-
the includee classes.
|
86
|
-
|
87
|
-
The second purpose is to store an array of all the methods defined
|
88
|
-
directly in this class or module. This makes features such as
|
89
|
-
#methods and #instance_methods work. It is also used internally to
|
90
|
-
create subclasses of Arrays, as an annoyance with javascript is that
|
91
|
-
arrays cannot be subclassed (or they can't without problems arrising
|
92
|
-
with tracking the array length). Therefore, when a new instance of a
|
93
|
-
subclass is created, behind the scenes we copy all the methods from
|
94
|
-
the subclass onto an array prototype.
|
95
|
-
|
96
|
-
If the includee is also included into other modules or classes, then
|
97
|
-
this method will also set up donations for that module. If this is
|
98
|
-
the case, then 'indirect' will be set to true as we don't want those
|
99
|
-
modules/classes to think they had that method set on themselves. This
|
100
|
-
stops `Object` thinking it defines `#sprintf` when it is actually
|
101
|
-
`Kernel` that defines that method. Indirect is false by default when
|
102
|
-
called by generated code in the compiler output.
|
103
|
-
|
104
|
-
@param [RubyClass] klass the class or module that defined methods
|
105
|
-
@param [Array<String>] methods an array of jsid method names defined
|
106
|
-
@param [Boolean] indirect whether this is an indirect method define
|
107
|
-
*/
|
108
|
-
Opal.donate = function(klass, methods, indirect) {
|
109
|
-
var included_in = klass.$included_in, includee, method,
|
110
|
-
table = klass._proto, dest;
|
111
|
-
|
112
|
-
if (!indirect) {
|
113
|
-
klass._methods = klass._methods.concat(methods);
|
114
|
-
}
|
115
|
-
|
116
|
-
if (included_in) {
|
117
|
-
for (var i = 0, length = included_in.length; i < length; i++) {
|
118
|
-
includee = included_in[i];
|
119
|
-
dest = includee._proto;
|
120
|
-
|
121
|
-
for (var j = 0, jj = methods.length; j < jj; j++) {
|
122
|
-
method = methods[j];
|
123
|
-
dest[method] = table[method];
|
124
|
-
}
|
125
|
-
|
126
|
-
if (includee.$included_in) {
|
127
|
-
Opal.donate(includee, methods, true);
|
128
|
-
}
|
129
|
-
}
|
130
|
-
}
|
131
|
-
};
|
132
|
-
|
133
|
-
var mid_to_jsid = Opal.mid_to_jsid = function(mid) {
|
134
|
-
if (method_names[mid]) {
|
135
|
-
return method_names[mid];
|
136
|
-
}
|
137
|
-
|
138
|
-
return '$' + mid.replace('!', '$b').replace('?', '$p').replace('=', '$e');
|
139
|
-
};
|
140
|
-
|
141
|
-
var jsid_to_mid = Opal.jsid_to_mid = function(jsid) {
|
142
|
-
if (reverse_method_names[jsid]) {
|
143
|
-
return reverse_method_names[jsid];
|
144
|
-
}
|
145
|
-
|
146
|
-
jsid = jsid.substr(1); // remove '$'
|
147
|
-
|
148
|
-
return jsid.replace('$b', '!').replace('$p', '?').replace('$e', '=');
|
144
|
+
// Convert a ruby method name into a javascript identifier
|
145
|
+
var mid_to_jsid = function(mid) {
|
146
|
+
return method_names[mid] ||
|
147
|
+
('$' + mid.replace('!', '$b').replace('?', '$p').replace('=', '$e'));
|
149
148
|
};
|
150
149
|
|
150
|
+
// Utility function to raise a "no block given" error
|
151
151
|
var no_block_given = function() {
|
152
152
|
throw new Error('no block given');
|
153
153
|
};
|
154
154
|
|
155
|
-
//
|
156
|
-
|
157
|
-
|
158
|
-
this._id = unique_id++;
|
159
|
-
};
|
155
|
+
// An array of all classes inside Opal. Used for donating methods from
|
156
|
+
// Module and Class.
|
157
|
+
var classes = Opal.classes = [];
|
160
158
|
|
159
|
+
// Boot a base class (makes instances).
|
160
|
+
var boot_defclass = function(id, constructor, superklass) {
|
161
161
|
if (superklass) {
|
162
162
|
var ctor = function() {};
|
163
163
|
ctor.prototype = superklass.prototype;
|
164
164
|
|
165
|
-
|
165
|
+
constructor.prototype = new ctor();
|
166
166
|
}
|
167
167
|
|
168
|
-
|
169
|
-
cls.prototype._isObject = true;
|
168
|
+
var prototype = constructor.prototype;
|
170
169
|
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
function boot_makemeta(id, klass, superklass) {
|
176
|
-
var meta = function() {
|
177
|
-
this._id = unique_id++;
|
178
|
-
};
|
170
|
+
prototype.constructor = constructor;
|
171
|
+
prototype._isObject = true;
|
172
|
+
prototype._klass = constructor;
|
173
|
+
prototype._real = constructor;
|
179
174
|
|
180
|
-
|
181
|
-
|
175
|
+
constructor._included_in = [];
|
176
|
+
constructor._isClass = true;
|
177
|
+
constructor._name = id;
|
178
|
+
constructor._super = superklass;
|
179
|
+
constructor._methods = [];
|
180
|
+
constructor._smethods = [];
|
181
|
+
constructor._isObject = false;
|
182
|
+
constructor._subclasses = [];
|
182
183
|
|
183
|
-
|
184
|
+
constructor._donate = __donate;
|
185
|
+
constructor._sdonate = __sdonate;
|
184
186
|
|
185
|
-
|
186
|
-
proto.$included_in = [];
|
187
|
-
proto._alloc = klass;
|
188
|
-
proto._isClass = true;
|
189
|
-
proto._name = id;
|
190
|
-
proto._super = superklass;
|
191
|
-
proto.constructor = meta;
|
192
|
-
proto._methods = [];
|
193
|
-
proto._isObject = false;
|
187
|
+
Opal[id] = constructor;
|
194
188
|
|
195
|
-
|
196
|
-
klass.prototype._klass = result;
|
197
|
-
klass.prototype._real = result;
|
189
|
+
classes.push(constructor);
|
198
190
|
|
199
|
-
|
200
|
-
|
201
|
-
top_const_scope[id] = result;
|
202
|
-
|
203
|
-
return result;
|
204
|
-
}
|
191
|
+
return constructor;
|
192
|
+
};
|
205
193
|
|
206
194
|
// Create generic class with given superclass.
|
207
|
-
|
208
|
-
// instances
|
209
|
-
var cls = function() {
|
210
|
-
this._id = unique_id++;
|
211
|
-
};
|
212
|
-
|
195
|
+
var boot_class = function(superklass, constructor) {
|
213
196
|
var ctor = function() {};
|
214
|
-
ctor.prototype = superklass.
|
215
|
-
|
216
|
-
cls.prototype = new ctor();
|
217
|
-
|
218
|
-
var proto = cls.prototype;
|
219
|
-
proto.constructor = cls;
|
220
|
-
proto._isObject = true;
|
221
|
-
|
222
|
-
// class itself
|
223
|
-
var meta = function() {
|
224
|
-
this._id = unique_id++;
|
225
|
-
};
|
226
|
-
|
227
|
-
var mtor = function() {};
|
228
|
-
mtor.prototype = superklass.constructor.prototype;
|
229
|
-
|
230
|
-
meta.prototype = new mtor();
|
197
|
+
ctor.prototype = superklass.prototype;
|
231
198
|
|
232
|
-
|
233
|
-
|
234
|
-
proto._isClass = true;
|
235
|
-
proto.constructor = meta;
|
236
|
-
proto._super = superklass;
|
237
|
-
proto._methods = [];
|
199
|
+
constructor.prototype = new ctor();
|
200
|
+
var prototype = constructor.prototype;
|
238
201
|
|
239
|
-
|
240
|
-
|
241
|
-
|
202
|
+
prototype._klass = constructor;
|
203
|
+
prototype._real = constructor;
|
204
|
+
prototype.constructor = constructor;
|
242
205
|
|
243
|
-
|
206
|
+
constructor._included_in = [];
|
207
|
+
constructor._isClass = true;
|
208
|
+
constructor._super = superklass;
|
209
|
+
constructor._methods = [];
|
210
|
+
constructor._isObject = false;
|
211
|
+
constructor._klass = Class;
|
212
|
+
constructor._real = Class;
|
213
|
+
constructor._donate = __donate
|
214
|
+
constructor._sdonate = __sdonate;
|
215
|
+
constructor._subclasses = [];
|
244
216
|
|
245
|
-
|
246
|
-
}
|
217
|
+
constructor.$eqq$ = module_eqq;
|
247
218
|
|
248
|
-
|
249
|
-
// where module "instance" methods go. will never be instantiated so it
|
250
|
-
// can be a regular object
|
251
|
-
var module_cons = function(){};
|
252
|
-
var module_inst = module_cons.prototype;
|
219
|
+
superklass._subclasses.push(constructor);
|
253
220
|
|
254
|
-
|
255
|
-
var meta = function() {
|
256
|
-
this._id = unique_id++;
|
257
|
-
};
|
221
|
+
var smethods;
|
258
222
|
|
259
|
-
|
260
|
-
mtor.prototype = RubyModule.constructor.prototype;
|
261
|
-
meta.prototype = new mtor();
|
223
|
+
smethods = superklass._smethods.slice();
|
262
224
|
|
263
|
-
|
225
|
+
constructor._smethods = smethods;
|
226
|
+
for (var i = 0, length = smethods.length; i < length; i++) {
|
227
|
+
var m = smethods[i];
|
228
|
+
constructor[m] = superklass[m];
|
229
|
+
}
|
264
230
|
|
265
|
-
|
266
|
-
proto._isModule = true;
|
267
|
-
proto.constructor = meta;
|
268
|
-
proto._super = null;
|
269
|
-
proto._methods = [];
|
231
|
+
classes.push(constructor);
|
270
232
|
|
271
|
-
|
272
|
-
|
233
|
+
return constructor;
|
234
|
+
};
|
273
235
|
|
274
|
-
|
275
|
-
}
|
236
|
+
var boot_module = function(constructor, id) {
|
237
|
+
var ctor = function() {};
|
238
|
+
ctor.prototype = Module.prototype;
|
276
239
|
|
277
|
-
|
278
|
-
|
279
|
-
if (klass._isClass) {
|
280
|
-
if (klass._isSingleton) {
|
281
|
-
throw RubyException.$new('too much meta: return klass?');
|
282
|
-
}
|
283
|
-
else {
|
284
|
-
var class_id = "#<Class:" + klass._name + ">",
|
285
|
-
meta = boot_class(superklass);
|
240
|
+
constructor.prototype = new ctor();
|
241
|
+
var prototype = constructor.prototype;
|
286
242
|
|
287
|
-
|
288
|
-
meta._alloc.prototype = klass.constructor.prototype;
|
289
|
-
meta._proto = meta._alloc.prototype;
|
290
|
-
meta._isSingleton = true;
|
291
|
-
meta._klass = RubyClass;
|
292
|
-
meta._real = RubyClass;
|
243
|
+
prototype.constructor = constructor;
|
293
244
|
|
294
|
-
|
245
|
+
constructor._isModule = true;
|
246
|
+
constructor._name = id;
|
247
|
+
constructor._methods = [];
|
248
|
+
constructor._smethods = [];
|
249
|
+
constructor._klass = Module;
|
250
|
+
constructor._donate = __donate;
|
251
|
+
constructor._sdonate = function(){};
|
295
252
|
|
296
|
-
|
297
|
-
meta.__attached__ = klass;
|
253
|
+
classes.push(constructor);
|
298
254
|
|
299
|
-
|
300
|
-
|
255
|
+
var smethods = constructor._smethods = Module._methods.slice();
|
256
|
+
for (var i = 0, length = smethods.length; i < length; i++) {
|
257
|
+
var m = smethods[i];
|
258
|
+
constructor[m] = Object[m];
|
301
259
|
}
|
302
|
-
else {
|
303
|
-
var orig_class = klass._klass,
|
304
|
-
class_id = "#<Class:#<" + orig_class._name + ":" + orig_class._id + ">>";
|
305
260
|
|
306
|
-
|
307
|
-
|
261
|
+
return constructor;
|
262
|
+
};
|
308
263
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
meta._alloc.prototype = klass;
|
313
|
-
klass._klass = meta;
|
314
|
-
meta.__attached__ = klass;
|
315
|
-
meta._klass = orig_class._real._klass
|
264
|
+
var bridge_class = function(constructor) {
|
265
|
+
constructor.prototype._klass = constructor;
|
266
|
+
constructor.prototype._real = constructor;
|
316
267
|
|
317
|
-
|
318
|
-
|
319
|
-
|
268
|
+
constructor._included_in = [];
|
269
|
+
constructor._isClass = true;
|
270
|
+
constructor._super = Object;
|
271
|
+
constructor._klass = Class;
|
272
|
+
constructor._methods = [];
|
273
|
+
constructor._smethods = [];
|
274
|
+
constructor._isObject = false;
|
275
|
+
constructor._subclasses = [];
|
320
276
|
|
321
|
-
function
|
322
|
-
|
323
|
-
prototype = constructor.prototype;
|
277
|
+
constructor._donate = function(){};
|
278
|
+
constructor._sdonate = __sdonate;
|
324
279
|
|
325
|
-
|
326
|
-
klass._proto = prototype;
|
280
|
+
constructor.$eqq$ = module_eqq;
|
327
281
|
|
328
|
-
|
282
|
+
var smethods = constructor._smethods = Module._methods.slice();
|
283
|
+
for (var i = 0, length = smethods.length; i < length; i++) {
|
284
|
+
var m = smethods[i];
|
285
|
+
constructor[m] = Object[m];
|
286
|
+
}
|
329
287
|
|
330
|
-
|
331
|
-
|
332
|
-
prototype._isObject = true;
|
288
|
+
bridgedClasses.push(constructor);
|
289
|
+
classes.push(constructor);
|
333
290
|
|
334
291
|
var allocator = function(initializer) {
|
335
|
-
var result, kls = this, methods = kls._methods, proto = kls.
|
292
|
+
var result, kls = this, methods = kls._methods, proto = kls.prototype;
|
336
293
|
|
337
294
|
if (initializer == null) {
|
338
295
|
result = new constructor
|
@@ -341,7 +298,7 @@ function bridge_class(constructor, id) {
|
|
341
298
|
result = new constructor(initializer);
|
342
299
|
}
|
343
300
|
|
344
|
-
if (kls ===
|
301
|
+
if (kls === constructor) {
|
345
302
|
return result;
|
346
303
|
}
|
347
304
|
|
@@ -356,71 +313,32 @@ function bridge_class(constructor, id) {
|
|
356
313
|
return result;
|
357
314
|
};
|
358
315
|
|
359
|
-
|
316
|
+
var table = Object.prototype, methods = Object._methods;
|
360
317
|
|
361
|
-
var
|
362
|
-
|
363
|
-
|
364
|
-
table = donator._proto;
|
365
|
-
methods = donator._methods;
|
366
|
-
|
367
|
-
for (var i = 0, length = methods.length; i < length; i++) {
|
368
|
-
var method = methods[i];
|
369
|
-
prototype[method] = table[method];
|
370
|
-
}
|
371
|
-
|
372
|
-
donator = donator._super;
|
318
|
+
for (var i = 0, length = methods.length; i < length; i++) {
|
319
|
+
var m = methods[i];
|
320
|
+
constructor.prototype[m] = table[m];
|
373
321
|
}
|
374
322
|
|
375
|
-
|
376
|
-
}
|
323
|
+
constructor.$allocate = allocator;
|
377
324
|
|
378
|
-
|
379
|
-
Actually define a new class with the name `id`. The superklass is
|
380
|
-
required, and Object is currently the root class. The base is the
|
381
|
-
parent scope of this class. For example, defining a root `Foo`
|
382
|
-
class would have `Object` as the parent. Defining `Foo::Bar` would
|
383
|
-
use `Foo` as the parent.
|
384
|
-
|
385
|
-
@param [RubyClass] base the base class/module for this new class
|
386
|
-
@param [String] id the name for this class
|
387
|
-
@param [RubyClass] superklass the super class
|
388
|
-
@return [RubyClass] returns new class with given attributes
|
389
|
-
*/
|
390
|
-
function define_class(base, id, superklass) {
|
391
|
-
var klass = boot_class(superklass);
|
392
|
-
klass._name = (base === RubyObject ? id : base._name + '::' + id);
|
393
|
-
|
394
|
-
make_metaclass(klass, superklass._klass);
|
395
|
-
|
396
|
-
var const_alloc = function() {};
|
397
|
-
var const_scope = const_alloc.prototype = new base._scope.alloc();
|
398
|
-
klass._scope = const_scope;
|
399
|
-
const_scope.alloc = const_alloc;
|
400
|
-
|
401
|
-
base._scope[id] = klass;
|
402
|
-
|
403
|
-
if (superklass.$inherited) {
|
404
|
-
superklass.$inherited(klass);
|
405
|
-
}
|
325
|
+
constructor._smethods.push('$allocate');
|
406
326
|
|
407
|
-
return
|
408
|
-
}
|
327
|
+
return constructor;
|
328
|
+
};
|
409
329
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
*/
|
423
|
-
function define_iclass(klass, module) {
|
330
|
+
// An IClass is a fake class created when a module is included into a
|
331
|
+
// class or another module. It is a "copy" of the module that is then
|
332
|
+
// injected into the hierarchy so it appears internally that the iclass
|
333
|
+
// is the super of the class instead of the old super class. This is
|
334
|
+
// actually hidden from the ruby side of things, but allows internal
|
335
|
+
// features such as super() etc to work. All useful properties from the
|
336
|
+
// module are copied onto this iclass.
|
337
|
+
//
|
338
|
+
// @param [RubyClass] klass the klass which is including the module
|
339
|
+
// @param [RubyModule] module the module which is being included
|
340
|
+
// @return [RubyIClass] returns newly created iclass
|
341
|
+
var define_iclass = function(klass, module) {
|
424
342
|
var iclass = {
|
425
343
|
_proto: module._proto,
|
426
344
|
_super: klass._super,
|
@@ -433,112 +351,102 @@ function define_iclass(klass, module) {
|
|
433
351
|
klass._super = iclass;
|
434
352
|
|
435
353
|
return iclass;
|
436
|
-
}
|
437
|
-
|
438
|
-
/**
|
439
|
-
This is a map of all file ids to their bodies. The file id is the
|
440
|
-
id used to require a file, and it does not have an extension name.
|
354
|
+
};
|
441
355
|
|
442
|
-
|
443
|
-
|
444
|
-
var factories = Opal.factories = {};
|
356
|
+
// Initialization
|
357
|
+
// --------------
|
445
358
|
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
__FILE__ variable. This should never be accessed manually.
|
359
|
+
boot_defclass('BasicObject', BasicObject);
|
360
|
+
boot_defclass('Object', Object, BasicObject);
|
361
|
+
boot_defclass('Class', Class, Object);
|
450
362
|
|
451
|
-
|
452
|
-
*/
|
453
|
-
Opal.file = "";
|
363
|
+
Class.prototype = Function.prototype;
|
454
364
|
|
455
|
-
|
456
|
-
Register the body for the given file id name. This will then allow
|
457
|
-
the file to be loaded with require().
|
365
|
+
BasicObject._klass = Object._klass = Class._klass = Class;
|
458
366
|
|
459
|
-
|
460
|
-
|
461
|
-
*/
|
462
|
-
Opal.define = function(id, body) {
|
463
|
-
factories[id] = body;
|
367
|
+
Module._donate = function(defined) {
|
368
|
+
// ...
|
464
369
|
};
|
465
370
|
|
466
|
-
|
467
|
-
|
371
|
+
// Implementation of Module#===
|
372
|
+
function module_eqq(object) {
|
373
|
+
if (object == null) {
|
374
|
+
return false;
|
375
|
+
}
|
468
376
|
|
469
|
-
|
470
|
-
@return [Boolean] if file has already been required
|
471
|
-
*/
|
472
|
-
Opal.require = function(id) {
|
473
|
-
var body = factories[id];
|
377
|
+
var search = object._klass;
|
474
378
|
|
475
|
-
|
476
|
-
|
477
|
-
|
379
|
+
while (search) {
|
380
|
+
if (search === this) {
|
381
|
+
return true;
|
382
|
+
}
|
478
383
|
|
479
|
-
|
480
|
-
return false;
|
384
|
+
search = search._super;
|
481
385
|
}
|
482
386
|
|
483
|
-
|
387
|
+
return false;
|
388
|
+
}
|
484
389
|
|
485
|
-
|
486
|
-
|
390
|
+
// Donator for all 'normal' classes and modules
|
391
|
+
function __donate(defined, indirect) {
|
392
|
+
var methods = this._methods, included_in = this.$included_in;
|
487
393
|
|
488
|
-
|
489
|
-
|
394
|
+
if (!indirect) {
|
395
|
+
this._methods = methods.concat(defined);
|
396
|
+
}
|
490
397
|
|
491
|
-
|
492
|
-
|
398
|
+
if (included_in) {
|
399
|
+
for (var i = 0, length = included_in.length; i < length; i++) {
|
400
|
+
var includee = included_in[i];
|
401
|
+
var dest = includee.prototype;
|
493
402
|
|
494
|
-
|
495
|
-
var
|
496
|
-
|
497
|
-
|
498
|
-
var BootClass = boot_defclass(BootModule);
|
403
|
+
for (var j = 0, jj = defined.length; j < jj; j++) {
|
404
|
+
var method = defined[j];
|
405
|
+
dest[method] = this.prototype[method];
|
406
|
+
}
|
499
407
|
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
var RubyClass = boot_makemeta('Class', BootClass, RubyModule.constructor);
|
408
|
+
if (includee.$included_in) {
|
409
|
+
includee._donate(defined, true);
|
410
|
+
}
|
411
|
+
}
|
505
412
|
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
413
|
+
}
|
414
|
+
}
|
415
|
+
|
416
|
+
// Donator for singleton (class) methods
|
417
|
+
function __sdonate(defined) {
|
418
|
+
var smethods = this._smethods, subclasses = this._subclasses;
|
419
|
+
|
420
|
+
this._smethods = smethods.concat(defined);
|
511
421
|
|
512
|
-
|
513
|
-
|
514
|
-
RubyObject._super = RubyBasicObject;
|
515
|
-
RubyModule._super = RubyObject;
|
516
|
-
RubyClass._super = RubyModule;
|
422
|
+
for (var i = 0, length = subclasses.length; i < length; i++) {
|
423
|
+
var s = subclasses[i];
|
517
424
|
|
518
|
-
var
|
519
|
-
|
425
|
+
for (var j = 0, jj = defined.length; j < jj; j++) {
|
426
|
+
}
|
427
|
+
}
|
428
|
+
}
|
520
429
|
|
521
|
-
|
430
|
+
var bridgedClasses = Object.$included_in = [];
|
431
|
+
BasicObject.$included_in = bridgedClasses;
|
522
432
|
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
RubyModule._scope = module_const_scope;
|
433
|
+
BasicObject._scope = Object._scope = Opal;
|
434
|
+
Opal.Module = Opal.Class;
|
435
|
+
Opal.Kernel = Object;
|
527
436
|
|
528
437
|
var class_const_alloc = function(){};
|
529
|
-
var class_const_scope = new
|
438
|
+
var class_const_scope = new TopScope();
|
530
439
|
class_const_scope.alloc = class_const_alloc;
|
531
|
-
|
440
|
+
Class._scope = class_const_scope;
|
532
441
|
|
533
|
-
|
442
|
+
Object.prototype.toString = function() {
|
534
443
|
return this.$to_s();
|
535
444
|
};
|
536
445
|
|
537
|
-
Opal.top = new
|
446
|
+
Opal.top = new Object;
|
538
447
|
|
539
|
-
|
540
|
-
Opal.nil = new
|
448
|
+
Opal.klass(Object, Object, 'NilClass', NilClass)
|
449
|
+
Opal.nil = new NilClass;
|
541
450
|
Opal.nil.call = Opal.nil.apply = no_block_given;
|
542
451
|
|
543
|
-
|
544
|
-
breaker.$t = function() { throw this; };
|
452
|
+
Opal.breaker = new Error('unexpected break');
|