opal 0.3.19 → 0.3.20
Sign up to get free protection for your applications and to get access to all the features.
- 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');
|