Module: __JS__::Opal

Defined in:
opal/opal/corelib/runtime.js.rb

Overview

This module is just a placeholder for showing the documentation of the internal JavaScript runtime. The methods you'll find defined below are actually JavaScript functions attached to the Opal global object

Class Method Summary collapse

Class Method Details

._bridgeObject

Bridges from donator to a target.



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'opal/opal/corelib/runtime.js.rb', line 215

def self._bridge(*)
<<-JAVASCRIPT
   function _bridge(target, donator) {
     var id, methods, method, i, bridged;
   
     if (typeof(target) === "function") {
       id      = donator.$__id__();
       methods = donator.$instance_methods();
   
       for (i = methods.length - 1; i >= 0; i--) {
         method = '$' + methods[i];
   
         bridge_method(target, donator, method, donator.$$proto[method]);
       }
   
       if (!bridges[id]) {
         bridges[id] = [];
       }
   
       bridges[id].push(target);
     }
     else {
       bridged = bridges[target.$__id__()];
   
       if (bridged) {
         for (i = bridged.length - 1; i >= 0; i--) {
           _bridge(bridged[i], donator);
         }
   
         bridges[donator.$__id__()] = bridged.slice();
       }
     }
   }
JAVASCRIPT
end

.boot_class_allocObject

Boot a base class (makes instances).



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
# File 'opal/opal/corelib/runtime.js.rb', line 253

def self.boot_class_alloc(*)
<<-JAVASCRIPT
   function boot_class_alloc(id, constructor, superklass) {
     if (superklass) {
       var alloc_proxy = function() {};
       alloc_proxy.prototype  = superklass.$$proto || superklass.prototype;
       constructor.prototype = new alloc_proxy();
     }
   
     if (id) {
       constructor.displayName = id+'_alloc';
     }
   
     constructor.prototype.constructor = constructor;
   
     return constructor;
   }
JAVASCRIPT
end

.boot_class_objectObject

The class object itself (as in Class.new)

Parameters:

  • superklass ((Opal) Class)

    Another class object (as in Class.new)

  • alloc (constructor)

    The constructor that holds the prototype that will be used for instances of the newly constructed class.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'opal/opal/corelib/runtime.js.rb', line 12

def self.boot_class_object(*)
<<-JAVASCRIPT
   function boot_class_object(id, superklass, alloc) {
     // Grab the superclass prototype and use it to build an intermediary object
     // in the prototype chain.
     function Superclass_alloc_proxy() {};
     Superclass_alloc_proxy.prototype = superklass.constructor.prototype;
     function SingletonClass_alloc() {}
     SingletonClass_alloc.prototype = new Superclass_alloc_proxy();
   
     if (id) {
       SingletonClass_alloc.displayName = "SingletonClass_alloc("+id+")";
     }
   
     // The built class is the only instance of its singleton_class
     var klass = new SingletonClass_alloc();
   
     setup_module_or_class_object(klass, SingletonClass_alloc, superklass, alloc.prototype);
   
     // @property $$alloc This is the constructor of instances of the current
     //                   class. Its prototype will be used for method lookup
     klass.$$alloc = alloc;
   
     // @property $$proto.$$class Make available to instances a reference to the
     //                           class they belong to.
     klass.$$proto.$$class = klass;
   
     return klass;
   }
JAVASCRIPT
end

.boot_core_class_objectObject

Builds the class object for core classes:

  • make the class object have a singleton class
  • make the singleton class inherit from its parent singleton class

Parameters:

  • id (String)

    the name of the class

  • alloc (Function)

    the constructor for the core class instances

  • superclass (Class alloc)

    the constructor of the superclass



282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'opal/opal/corelib/runtime.js.rb', line 282

def self.boot_core_class_object(*)
<<-JAVASCRIPT
   function boot_core_class_object(id, alloc, superclass) {
     var superclass_constructor = function() {};
         superclass_constructor.prototype = superclass.prototype;
   
     var singleton_class = function() {};
         singleton_class.prototype = new superclass_constructor();
   
     singleton_class.displayName = "#<Class:"+id+">";
   
     // the singleton_class acts as the class object constructor
     var klass = new singleton_class();
   
     setup_module_or_class_object(klass, singleton_class, superclass, alloc.prototype);
   
     klass.$$alloc     = alloc;
     klass.$$name      = id;
     klass.displayName = id;
   
     // Give all instances a ref to their class
     alloc.prototype.$$class = klass;
   
     Opal[id] = klass;
     Opal.constants.push(id);
   
     return klass;
   }
JAVASCRIPT
end

.boot_module_objectObject

Internal function to create a new module instance. This simply sets up the prototype hierarchy and method tables.



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'opal/opal/corelib/runtime.js.rb', line 107

def self.boot_module_object(*)
<<-JAVASCRIPT
   function boot_module_object() {
     var mtor = function() {};
     mtor.prototype = Module_alloc.prototype;
   
     function module_constructor() {}
     module_constructor.prototype = new mtor();
   
     var module = new module_constructor();
     var module_prototype = {};
   
     setup_module_or_class_object(module, module_constructor, Module, module_prototype);
   
     return module;
   }
JAVASCRIPT
end

.bridge_methodObject

Bridges a single method.



183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'opal/opal/corelib/runtime.js.rb', line 183

def self.bridge_method(*)
<<-JAVASCRIPT
   function bridge_method(target, from, name, body) {
     var ancestors, i, ancestor, length;
   
     ancestors = target.$$bridge.$ancestors();
   
     // order important here, we have to check for method presence in
     // ancestors from the bridged class to the last ancestor
     for (i = 0, length = ancestors.length; i < length; i++) {
       ancestor = ancestors[i];
   
       if ($hasOwn.call(ancestor.$$proto, name) &&
           ancestor.$$proto[name] &&
           !ancestor.$$proto[name].$$donated &&
           !ancestor.$$proto[name].$$stub &&
           ancestor !== from) {
         break;
       }
   
       if (ancestor === from) {
         target.prototype[name] = body
         break;
       }
     }
   
   }
JAVASCRIPT
end

.build_class_singleton_classRubyClass

Build the singleton class for an existing class.

NOTE: Actually in MRI a class' singleton class inherits from its superclass' singleton class which in turn inherits from Class.

Parameters:

  • klass (RubyClass)

Returns:

  • (RubyClass)


135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'opal/opal/corelib/runtime.js.rb', line 135

def self.build_class_singleton_class(*)
<<-JAVASCRIPT
   function build_class_singleton_class(klass) {
     var meta = new Opal.Class.$$alloc();
   
     meta.$$class = Opal.Class;
     meta.$$proto = klass.constructor.prototype;
   
     meta.$$is_singleton = true;
     meta.$$singleton_of = klass;
     meta.$$inc          = [];
     meta.$$scope        = klass.$$scope;
   
     return klass.$$meta = meta;
   }
JAVASCRIPT
end

.build_object_singleton_classRubyClass

Build the singleton class for a Ruby (non class) Object.

Parameters:

  • object (RubyObject)

Returns:

  • (RubyClass)


159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'opal/opal/corelib/runtime.js.rb', line 159

def self.build_object_singleton_class(*)
<<-JAVASCRIPT
   function build_object_singleton_class(object) {
     var orig_class = object.$$class,
         class_id   = "#<Class:#<" + orig_class.$$name + ":" + orig_class.$$id + ">>";
   
     var Singleton = function() {};
     var meta = Opal.boot_class(orig_class, Singleton);
     meta.$$name   = class_id;
   
     meta.$$proto  = object;
     meta.$$class  = orig_class.$$class;
     meta.$$scope  = orig_class.$$scope;
     meta.$$parent = orig_class;
     meta.$$is_singleton = true;
     meta.$$singleton_of = object;
   
     return object.$$meta = meta;
   }
JAVASCRIPT
end

Donate methods for a module.



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
# File 'opal/opal/corelib/runtime.js.rb', line 334

def self.donate(*)
<<-JAVASCRIPT
   function donate(module, jsid) {
     var included_in = module.$$dep,
         body = module.$$proto[jsid],
         i, length, includee, dest, current,
         klass_includees, j, jj, current_owner_index, module_index;
   
     if (!included_in) {
       return;
     }
   
     for (i = 0, length = included_in.length; i < length; i++) {
       includee = included_in[i];
       dest = includee.$$proto;
       current = dest[jsid];
   
       if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
         // target class has already defined the same method name - do nothing
       }
       else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
         // target class includes another module that has defined this method
         klass_includees = includee.$$inc;
   
         for (j = 0, jj = klass_includees.length; j < jj; j++) {
           if (klass_includees[j] === current.$$donated) {
             current_owner_index = j;
           }
           if (klass_includees[j] === module) {
             module_index = j;
           }
         }
   
         // only redefine method on class if the module was included AFTER
         // the module which defined the current method body. Also make sure
         // a module can overwrite a method it defined before
         if (current_owner_index <= module_index) {
           dest[jsid] = body;
           dest[jsid].$$donated = module;
         }
       }
       else {
         // neither a class, or module included by class, has defined method
         dest[jsid] = body;
         dest[jsid].$$donated = module;
       }
   
       if (includee.$$dep) {
         donate(includee, jsid);
       }
     }
   };
JAVASCRIPT
end

When a source module is included into the target module, we must also copy its constants to the target.



317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'opal/opal/corelib/runtime.js.rb', line 317

def self.donate_constants(*)
<<-JAVASCRIPT
   function donate_constants(source_mod, target_mod) {
     var source_constants = source_mod.$$scope.constants,
         target_scope     = target_mod.$$scope,
         target_constants = target_scope.constants;
   
     for (var i = 0, length = source_constants.length; i < length; i++) {
       target_constants.push(source_constants[i]);
       target_scope[source_constants[i]] = source_mod.$$scope[source_constants[i]];
     }
   };
JAVASCRIPT
end

.setup_module_or_class_objectObject

Adds common/required properties to a module or class object (as in Module.new / Class.new)

Parameters:

  • module

    The module or class that needs to be prepared

  • constructor

    The constructor of the module or class itself, usually it's already assigned by using new. Some ipothesis on why it's needed can be found below.

  • superklass

    The superclass of the class/module object, for modules is Module (of Module in JS context)

  • prototype

    The prototype on which the class/module methods will be stored.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'opal/opal/corelib/runtime.js.rb', line 60

def self.setup_module_or_class_object(*)
<<-JAVASCRIPT
   function setup_module_or_class_object(module, constructor, superklass, prototype) {
     // @property $$id Each class is assigned a unique `id` that helps
     //                comparation and implementation of `#object_id`
     module.$$id = Opal.uid();
   
     // @property $$proto This is the prototype on which methods will be defined
     module.$$proto = prototype;
   
     // @property constructor keeps a ref to the constructor, but apparently the
     //                       constructor is already set on:
     //
     //                          `var module = new constructor` is called.
     //
     //                       Maybe there are some browsers not abiding (IE6?)
     module.constructor = constructor;
   
     if (superklass === Module) {
       // @property $$is_module Clearly mark this as a module
       module.$$is_module = true;
       module.$$class     = Module;
     }
     else {
       // @property $$is_class Clearly mark this as a class
       module.$$is_class = true;
       module.$$class    = Class;
     }
   
     // @property $$super the superclass, doesn't get changed by module inclusions
     module.$$super = superklass;
   
     // @property $$parent direct parent class or module
     //                    starts with the superclass, after module inclusion is
     //                    the last included module
     module.$$parent = superklass;
   
     // @property $$inc included modules
     module.$$inc = [];
   }
JAVASCRIPT
end

.stub_forObject

Generate the method_missing stub for a given method name.

Parameters:

  • method_name (String)

    The js-name of the method to stub (e.g. "$foo")



394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
# File 'opal/opal/corelib/runtime.js.rb', line 394

def self.stub_for(*)
<<-JAVASCRIPT
   function stub_for(method_name) {
     function method_missing_stub() {
       // Copy any given block onto the method_missing dispatcher
       this.$method_missing.$$p = method_missing_stub.$$p;
   
       // Set block property to null ready for the next call (stop false-positives)
       method_missing_stub.$$p = null;
   
       // call method missing with correct args (remove '$' prefix on method name)
       return this.$method_missing.apply(this, [method_name.slice(1)].concat($slice.call(arguments)));
     }
   
     method_missing_stub.$$stub = true;
   
     return method_missing_stub;
   }
JAVASCRIPT
end