opal 0.3.19 → 0.3.20

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. data/.gitignore +3 -1
  2. data/Gemfile +3 -2
  3. data/README.md +304 -48
  4. data/Rakefile +1 -2
  5. data/core/alpha.rb +2 -1
  6. data/core/array.rb +92 -96
  7. data/core/basic_object.rb +1 -10
  8. data/core/boolean.rb +6 -18
  9. data/core/class.rb +9 -10
  10. data/core/comparable.rb +1 -1
  11. data/core/enumerable.rb +11 -11
  12. data/core/enumerator.rb +2 -10
  13. data/core/error.rb +16 -31
  14. data/core/hash.rb +32 -36
  15. data/core/json.rb +50 -0
  16. data/core/kernel.rb +48 -57
  17. data/core/load_order +3 -5
  18. data/core/module.rb +37 -35
  19. data/core/nil_class.rb +4 -0
  20. data/core/numeric.rb +10 -30
  21. data/core/proc.rb +1 -1
  22. data/core/range.rb +3 -4
  23. data/core/regexp.rb +21 -6
  24. data/core/runtime.js +278 -370
  25. data/core/string.rb +21 -37
  26. data/core/struct.rb +11 -3
  27. data/core/time.rb +44 -37
  28. data/lib/opal.rb +3 -3
  29. data/lib/opal/builder.rb +48 -27
  30. data/lib/opal/builder_task.rb +3 -20
  31. data/lib/opal/grammar.rb +18 -13
  32. data/lib/opal/grammar.y +7 -4
  33. data/lib/opal/parser.rb +290 -199
  34. data/lib/opal/scope.rb +187 -176
  35. data/lib/opal/version.rb +1 -1
  36. data/test/core/kernel/define_singleton_method_spec.rb +21 -0
  37. data/test/core/time/at_spec.rb +7 -0
  38. data/test/core/time/day_spec.rb +5 -0
  39. data/test/core/time/friday_spec.rb +9 -0
  40. data/test/core/time/hour_spec.rb +5 -0
  41. data/test/core/time/min_spec.rb +5 -0
  42. data/test/core/time/monday_spec.rb +9 -0
  43. data/test/core/time/month_spec.rb +5 -0
  44. data/test/core/time/now_spec.rb +5 -0
  45. data/test/core/time/saturday_spec.rb +9 -0
  46. data/test/index.html +2 -1
  47. data/test/language/singleton_class_spec.rb +0 -16
  48. data/test/opal/array/to_json_spec.rb +7 -0
  49. data/test/opal/boolean/singleton_class_spec.rb +9 -0
  50. data/test/opal/boolean/to_json_spec.rb +9 -0
  51. data/test/opal/hash/to_json_spec.rb +9 -0
  52. data/test/opal/json/parse_spec.rb +31 -0
  53. data/test/opal/kernel/to_json_spec.rb +5 -0
  54. data/test/opal/nil/to_json_spec.rb +5 -0
  55. data/test/opal/numeric/to_json_spec.rb +6 -0
  56. data/test/opal/runtime/call_spec.rb +16 -0
  57. data/test/opal/runtime/defined_spec.rb +11 -0
  58. data/test/opal/runtime/super_spec.rb +16 -0
  59. data/test/opal/string/to_json_spec.rb +6 -0
  60. data/test/spec_helper.rb +1 -3
  61. metadata +48 -15
  62. data/core/dir.rb +0 -89
  63. data/core/file.rb +0 -85
  64. data/core/match_data.rb +0 -35
  65. data/core/rational.rb +0 -16
  66. data/test/core/file/expand_path_spec.rb +0 -20
@@ -20,10 +20,11 @@ class Regexp < `RegExp`
20
20
  var result = this.exec(string);
21
21
 
22
22
  if (result) {
23
- var match = new #{MatchData}._alloc();
24
- match.$data = result;
23
+ result.$to_s = match_to_s;
24
+ result.$inspect = match_inspect;
25
+ result._real = result._klass = #{ MatchData };
25
26
 
26
- #{$~ = `match`};
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
- var match = new #{MatchData}._alloc();
48
- match.$data = result;
48
+ result.$to_s = match_to_s;
49
+ result.$inspect = match_inspect;
50
+ result._real = result._klass = #{ MatchData };
49
51
 
50
- return #{$~ = `match`};
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
@@ -1,14 +1,35 @@
1
- // Top level Object scope (used by object and top_self).
2
- var top_const_alloc = function(){};
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
- var Opal = this.Opal = top_const_scope;
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 = Object.prototype.hasOwnProperty;
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
- Opal.klass = function(base, superklass, id, body) {
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 = RubyObject;
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
- klass = define_class(base, id, superklass);
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 body.call(klass);
113
+ return klass;
44
114
  };
45
115
 
46
- Opal.sklass = function(shift, body) {
47
- var klass = shift.$singleton_class();
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 === RubyObject ? id : base._name + '::' + id);
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 body.call(klass);
141
+ return klass;
78
142
  }
79
143
 
80
- /**
81
- This function serves two purposes. The first is to allow methods
82
- defined in modules to be included into classes that have included
83
- them. This is done at the end of a module body by calling this
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
- // Boot a base class (makes instances).
156
- function boot_defclass(superklass) {
157
- var cls = function() {
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
- cls.prototype = new ctor();
165
+ constructor.prototype = new ctor();
166
166
  }
167
167
 
168
- cls.prototype.constructor = cls;
169
- cls.prototype._isObject = true;
168
+ var prototype = constructor.prototype;
170
169
 
171
- return cls;
172
- }
173
-
174
- // Boot actual (meta classes) of core objects.
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
- var ctor = function() {};
181
- ctor.prototype = superklass.prototype;
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
- meta.prototype = new ctor();
184
+ constructor._donate = __donate;
185
+ constructor._sdonate = __sdonate;
184
186
 
185
- var proto = meta.prototype;
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
- var result = new meta();
196
- klass.prototype._klass = result;
197
- klass.prototype._real = result;
189
+ classes.push(constructor);
198
190
 
199
- result._proto = klass.prototype;
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
- function boot_class(superklass) {
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._alloc.prototype;
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
- proto = meta.prototype;
233
- proto._alloc = cls;
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
- var result = new meta();
240
- cls.prototype._klass = result;
241
- cls.prototype._real = result;
202
+ prototype._klass = constructor;
203
+ prototype._real = constructor;
204
+ prototype.constructor = constructor;
242
205
 
243
- result._proto = cls.prototype;
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
- return result;
246
- }
217
+ constructor.$eqq$ = module_eqq;
247
218
 
248
- function boot_module() {
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
- // Module itself
255
- var meta = function() {
256
- this._id = unique_id++;
257
- };
221
+ var smethods;
258
222
 
259
- var mtor = function(){};
260
- mtor.prototype = RubyModule.constructor.prototype;
261
- meta.prototype = new mtor();
223
+ smethods = superklass._smethods.slice();
262
224
 
263
- var proto = meta.prototype;
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
- proto._alloc = module_cons;
266
- proto._isModule = true;
267
- proto.constructor = meta;
268
- proto._super = null;
269
- proto._methods = [];
231
+ classes.push(constructor);
270
232
 
271
- var module = new meta();
272
- module._proto = module_inst;
233
+ return constructor;
234
+ };
273
235
 
274
- return module;
275
- }
236
+ var boot_module = function(constructor, id) {
237
+ var ctor = function() {};
238
+ ctor.prototype = Module.prototype;
276
239
 
277
- // Make metaclass for the given class
278
- function make_metaclass(klass, superklass) {
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
- meta._name = class_id;
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
- klass._klass = meta;
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
- meta._scope = klass._scope;
297
- meta.__attached__ = klass;
253
+ classes.push(constructor);
298
254
 
299
- return meta;
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
- var meta = boot_class(orig_class);
307
- meta._name = class_id;
261
+ return constructor;
262
+ };
308
263
 
309
- meta._isSingleton = true;
310
- meta._proto = klass;
311
- // FIXME: this should be removed. _proto should always point to this.
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
- return meta;
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 bridge_class(constructor, id) {
322
- var klass = define_class(RubyObject, id, RubyObject),
323
- prototype = constructor.prototype;
277
+ constructor._donate = function(){};
278
+ constructor._sdonate = __sdonate;
324
279
 
325
- klass._alloc = constructor;
326
- klass._proto = prototype;
280
+ constructor.$eqq$ = module_eqq;
327
281
 
328
- bridged_classes.push(klass);
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
- prototype._klass = klass;
331
- prototype._real = klass;
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._proto;
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 === klass) {
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
- klass.constructor.prototype.$allocate = allocator;
316
+ var table = Object.prototype, methods = Object._methods;
360
317
 
361
- var donator = RubyObject, table, methods;
362
-
363
- while (donator) {
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
- return klass;
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 klass;
408
- }
327
+ return constructor;
328
+ };
409
329
 
410
- /**
411
- An IClass is a fake class created when a module is included into a
412
- class or another module. It is a "copy" of the module that is then
413
- injected into the hierarchy so it appears internally that the iclass
414
- is the super of the class instead of the old super class. This is
415
- actually hidden from the ruby side of things, but allows internal
416
- features such as super() etc to work. All useful properties from the
417
- module are copied onto this iclass.
418
-
419
- @param [RubyClass] klass the klass which is including the module
420
- @param [RubyModule] module the module which is being included
421
- @return [RubyIClass] returns newly created iclass
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
- @type { String: Function }
443
- */
444
- var factories = Opal.factories = {};
356
+ // Initialization
357
+ // --------------
445
358
 
446
- /**
447
- This holds the name of the current file being executed by opal. This
448
- gets set in require() below and it allows the file to get the
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
- @type {String}
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
- @param [String] id the file id
460
- @param [Function] body the body representing the file
461
- */
462
- Opal.define = function(id, body) {
463
- factories[id] = body;
367
+ Module._donate = function(defined) {
368
+ // ...
464
369
  };
465
370
 
466
- /**
467
- Require a specific file by id.
371
+ // Implementation of Module#===
372
+ function module_eqq(object) {
373
+ if (object == null) {
374
+ return false;
375
+ }
468
376
 
469
- @param [String] id file id to require
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
- if (!body) {
476
- throw new Error("No file: '" + id + "'");
477
- }
379
+ while (search) {
380
+ if (search === this) {
381
+ return true;
382
+ }
478
383
 
479
- if (body._loaded) {
480
- return false;
384
+ search = search._super;
481
385
  }
482
386
 
483
- Opal.file = id;
387
+ return false;
388
+ }
484
389
 
485
- body._loaded = true;
486
- body.call(Opal.top);
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
- return true;
489
- };
394
+ if (!indirect) {
395
+ this._methods = methods.concat(defined);
396
+ }
490
397
 
491
- // Initialization
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
- // The *instances* of core objects
495
- var BootBasicObject = boot_defclass();
496
- var BootObject = boot_defclass(BootBasicObject);
497
- var BootModule = boot_defclass(BootObject);
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
- // The *classes' of core objects
501
- var RubyBasicObject = boot_makemeta('BasicObject', BootBasicObject, BootClass);
502
- var RubyObject = boot_makemeta('Object', BootObject, RubyBasicObject.constructor);
503
- var RubyModule = boot_makemeta('Module', BootModule, RubyObject.constructor);
504
- var RubyClass = boot_makemeta('Class', BootClass, RubyModule.constructor);
408
+ if (includee.$included_in) {
409
+ includee._donate(defined, true);
410
+ }
411
+ }
505
412
 
506
- // Fix boot classes to use meta class
507
- RubyBasicObject._klass = RubyClass;
508
- RubyObject._klass = RubyClass;
509
- RubyModule._klass = RubyClass;
510
- RubyClass._klass = RubyClass;
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
- // fix superclasses
513
- RubyBasicObject._super = null;
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 bridged_classes = RubyObject.$included_in = [];
519
- RubyBasicObject.$included_in = bridged_classes;
425
+ for (var j = 0, jj = defined.length; j < jj; j++) {
426
+ }
427
+ }
428
+ }
520
429
 
521
- RubyObject._scope = RubyBasicObject._scope = top_const_scope;
430
+ var bridgedClasses = Object.$included_in = [];
431
+ BasicObject.$included_in = bridgedClasses;
522
432
 
523
- var module_const_alloc = function(){};
524
- var module_const_scope = new top_const_alloc();
525
- module_const_scope.alloc = module_const_alloc;
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 top_const_alloc();
438
+ var class_const_scope = new TopScope();
530
439
  class_const_scope.alloc = class_const_alloc;
531
- RubyClass._scope = class_const_scope;
440
+ Class._scope = class_const_scope;
532
441
 
533
- RubyObject._proto.toString = function() {
442
+ Object.prototype.toString = function() {
534
443
  return this.$to_s();
535
444
  };
536
445
 
537
- Opal.top = new RubyObject._alloc();
446
+ Opal.top = new Object;
538
447
 
539
- var RubyNilClass = define_class(RubyObject, 'NilClass', RubyObject);
540
- Opal.nil = new RubyNilClass._alloc();
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
- var breaker = Opal.breaker = new Error('unexpected break');
544
- breaker.$t = function() { throw this; };
452
+ Opal.breaker = new Error('unexpected break');