runtime.js

``

@note A few conventions for the documentation of this file:

  1. Always use "//" (in contrast with "/**/")
  2. The syntax used is Yardoc (yardoc.org), which is intended for Ruby (se below)
  3. @param and @return types should be preceded by JS. when referring to JavaScript constructors (e.g. JS.Function) otherwise Ruby is assumed.
  4. nil and null being unambiguous refer to the respective objects/values in Ruby and JavaScript
  5. This is still WIP :) so please give feedback and suggestions on how to improve or for alternative solutions

The way the code is digested before going through Yardoc is a secret kept in the docs repo (https://github.com/opal/docs/tree/master).


if (typeof(global) !== 'undefined') { global_object = global; }

Detect the global object

if (typeof(global) !== 'undefined') { global_object = global; }

if (typeof(global_object.console) === 'object')

Setup a dummy console object if missing

if (typeof(global_object.console) === 'object') {

BasicObject

The actual class for BasicObject

var BasicObject;

_Object

The actual Object class. The leading underscore is to avoid confusion with window.Object()

var _Object;

Module

The actual Module class

var Module;

Class

The actual Class class

var Class;

function: BasicObject_alloc()

Constructor for instances of BasicObject

function BasicObject_alloc(){}

function: Object_alloc()

Constructor for instances of Object

function Object_alloc(){}

function: Class_alloc()

Constructor for instances of Class

function Class_alloc(){}

function: Module_alloc()

Constructor for instances of Module

function Module_alloc(){}

function: NilClass_alloc()

Constructor for instances of NilClass (nil)

function NilClass_alloc(){}

Opal = this.Opal = {}

The Opal object that is exposed globally

var Opal = this.Opal = {};

BridgedClasses = {}

All bridged classes - keep track to donate methods from Object

var BridgedClasses = {};

Opal.global = global_object

This is a useful reference to global object inside ruby files

Opal.global = global_object;

Opal.config =

Configure runtime behavior with regards to require and unsupported fearures

Opal.config = {

$hasOwn = Object.hasOwnProperty

Minify common function calls

var $hasOwn = Object.hasOwnProperty;

nil_id = 4

Nil object id is always 4

var nil_id = 4;

unique_id = nil_id

Generates even sequential numbers greater than 4 (nil_id) to serve as unique ids for ruby objects

var unique_id = nil_id;

Opal.uid = function()

Return next unique id

Opal.uid = function() {
  unique_id += 2;
  return unique_id;
};

Opal.id = function(obj)

Retrieve or assign the id of an object

Opal.id = function(obj) {
  if (obj.$$is_number) return (obj * 2)+1;
  return obj.$$id || (obj.$$id = Opal.uid());
};

Opal.gvars = {}

Globals table

Opal.gvars = {};

Opal.exit = function(status) { if (Opal.gvars.DEBUG) console.log('Exited with status '+status); }

Exit function, this should be replaced by platform specific implementation (See nodejs and chrome for examples)

Opal.exit = function(status) { if (Opal.gvars.DEBUG) console.log('Exited with status '+status); };

Opal.exceptions = []

keeps track of exceptions for $!

Opal.exceptions = [];

Opal.pop_exception = function()

@private Pops an exception from the stack and updates $!.

Opal.pop_exception = function() {
  Opal.gvars["!"] = Opal.exceptions.pop() || nil;
}

Opal.inspect = function(obj)

Inspect any kind of object, including non Ruby ones

Opal.inspect = function(obj) {
  if (obj === undefined) {
    return "undefined";
  }
  else if (obj === null) {
    return "null";
  }
  else if (!obj.$$class) {
    return obj.toString();
  }
  else {
    return obj.$inspect();
  }
}

``

Truth


``

Constants

For future reference:

Legend of MRI concepts/names:

  • constant reference (cref): the module/class that acts as a namespace
  • nesting: the namespaces wrapping the current scope, e.g. nesting inside module A; module B::C; end; end is [B::C, A]

function const_get_name(cref, name)

Get the constant in the scope of the current cref

function const_get_name(cref, name) {
  if (cref) return cref.$$const[name];
}

function const_lookup_nesting(nesting, name)

Walk up the nesting array looking for the constant

function const_lookup_nesting(nesting, name) {
  var i, ii, result, constant;

  if (nesting.length === 0) return;

  // If the nesting is not empty the constant is looked up in its elements
  // and in order. The ancestors of those elements are ignored.
  for (i = 0, ii = nesting.length; i < ii; i++) {
    constant = nesting[i].$$const[name];
    if (constant != null) return constant;
  }
}

function const_lookup_ancestors(cref, name)

Walk up the ancestors chain looking for the constant

function const_lookup_ancestors(cref, name) {
  var i, ii, result, ancestors;

  if (cref == null) return;

  ancestors = Opal.ancestors(cref);

  for (i = 0, ii = ancestors.length; i < ii; i++) {
    if (ancestors[i].$$const && $hasOwn.call(ancestors[i].$$const, name)) {
      return ancestors[i].$$const[name];
    }
  }
}

function const_lookup_Object(cref, name)

Walk up Object's ancestors chain looking for the constant, but only if cref is missing or a module.

function const_lookup_Object(cref, name) {
  if (cref == null || cref.$$is_module) {
    return const_lookup_ancestors(_Object, name);
  }
}

function const_missing(cref, name, skip_missing)

Call const_missing if nothing else worked

function const_missing(cref, name, skip_missing) {
  if (!skip_missing) {
    return (cref || _Object).$const_missing(name);
  }
}

Opal.const_get_local = function(cref, name, skip_missing)

Look for the constant just in the current cref or call #const_missing

Opal.const_get_local = function(cref, name, skip_missing) {
  var result;

  if (cref == null) return;

  if (cref === '::') cref = _Object;

  if (!cref.$$is_a_module) {
    throw new Opal.TypeError(cref.toString() + " is not a class/module");
  }

  result = const_get_name(cref, name);              if (result != null) return result;
  result = const_missing(cref, name, skip_missing); if (result != null) return result;
}

Opal.const_get_qualified = function(cref, name, skip_missing)

Look for the constant relative to a cref or call #const_missing (when the constant is prefixed by ::).

Opal.const_get_qualified = function(cref, name, skip_missing) {
  var result, cache, cached, current_version = Opal.const_cache_version;

  if (cref == null) return;

  if (cref === '::') cref = _Object;

  if (!cref.$$is_a_module) {
    throw new Opal.TypeError(cref.toString() + " is not a class/module");
  }

  if ((cache = cref.$$const_cache) == null) {
    cache = cref.$$const_cache = Object.create(null);
  }
  cached = cache[name];

  if (cached == null || cached[0] !== current_version) {
    ((result = const_get_name(cref, name))              != null) ||
    ((result = const_lookup_ancestors(cref, name))      != null);
    cache[name] = [current_version, result];
  } else {
    result = cached[1];
  }

  return result != null ? result : const_missing(cref, name, skip_missing);
};

Opal.const_cache_version = 1

Initialize the top level constant cache generation counter

Opal.const_cache_version = 1;

Opal.const_get_relative = function(nesting, name, skip_missing)

Look for the constant in the open using the current nesting and the nearest cref ancestors or call #const_missing (when the constant has no :: prefix).

Opal.const_get_relative = function(nesting, name, skip_missing) {
  var cref = nesting[0], result, current_version = Opal.const_cache_version, cache, cached;

  if ((cache = nesting.$$const_cache) == null) {
    cache = nesting.$$const_cache = Object.create(null);
  }
  cached = cache[name];

  if (cached == null || cached[0] !== current_version) {
    ((result = const_get_name(cref, name))              != null) ||
    ((result = const_lookup_nesting(nesting, name))     != null) ||
    ((result = const_lookup_ancestors(cref, name))      != null) ||
    ((result = const_lookup_Object(cref, name))         != null);

    cache[name] = [current_version, result];
  } else {
    result = cached[1];
  }

  return result != null ? result : const_missing(cref, name, skip_missing);
};

Opal.const_set = function(cref, name, value)

Register the constant on a cref and opportunistically set the name of unnamed classes/modules.

Opal.const_set = function(cref, name, value) {
  if (cref == null || cref === '::') cref = _Object;

  if (value.$$is_a_module) {
    if (value.$$name == null || value.$$name === nil) value.$$name = name;
    if (value.$$base_module == null) value.$$base_module = cref;
  }

  cref.$$const = (cref.$$const || Object.create(null));
  cref.$$const[name] = value;

  Opal.const_cache_version++;

  // Expose top level constants onto the Opal object
  if (cref === _Object) Opal[name] = value;

  return value;
};

Opal.constants = function(cref, inherit)

Get all the constants reachable from a given cref, by default will include inherited constants.

Opal.constants = function(cref, inherit) {
  if (inherit == null) inherit = true;

  var module, modules = [cref], module_constants, i, ii, constants = {}, constant;

  if (inherit) modules = modules.concat(Opal.ancestors(cref));
  if (inherit && cref.$$is_module) modules = modules.concat([Opal.Object]).concat(Opal.ancestors(Opal.Object));

  for (i = 0, ii = modules.length; i < ii; i++) {
    module = modules[i];

    // Don not show Objects constants unless we're querying Object itself
    if (cref !== _Object && module == _Object) break;

    for (constant in module.$$const) {
      constants[constant] = true;
    }
  }

  return Object.keys(constants);
};

Opal.const_remove = function(cref, name)

Remove a constant from a cref.

Opal.const_remove = function(cref, name) {
  Opal.const_cache_version++;

  if (cref.$$const[name] != null) {
    var old = cref.$$const[name];
    delete cref.$$const[name];
    return old;
  }

  if (cref.$$autoload != null && cref.$$autoload[name] != null) {
    delete cref.$$autoload[name];
    return nil;
  }

  throw Opal.NameError.$new("constant "+cref+"::"+cref.$name()+" not defined");
};

``

Modules & Classes


Opal.klass = function(base, superclass, name, constructor)

A class Foo; end expression in ruby is compiled to call this runtime method which either returns an existing class of the given name, or creates a new class in the given base scope.

If a constant with the given name exists, then we check to make sure that it is a class and also that the superclasses match. If either of these fail, then we raise a TypeError. Note, superclass may be null if one was not specified in the ruby code.

We pass a constructor to this method of the form function ClassName() {} simply so that classes show up with nicely formatted names inside debuggers in the web browser (or node/sprockets).

The base is the current self value where the class is being created from. We use this to get the scope for where the class should be created. If base is an object (not a class/module), we simple get its class and use that as the base instead.

@param base [Object] where the class is being created @param superclass [Class,null] superclass of the new class (may be null) @param id [String] the name of the class to be created @param constructor [JS.Function] function to use as constructor

@return new [Class] or existing ruby class

Opal.klass = function(base, superclass, name, constructor) {
  var klass, bridged, alloc;

  if (base == null) {
    base = _Object;
  }

  // If base is an object, use its class
  if (!base.$$is_class && !base.$$is_module) {
    base = base.$$class;
  }

  // If the superclass is a function then we're bridging a native JS class
  if (typeof(superclass) === 'function') {
    bridged = superclass;
    superclass = _Object;
  }

  // Try to find the class in the current scope
  klass = const_get_name(base, name);

  // If the class exists in the scope, then we must use that
  if (klass) {
    // Make sure the existing constant is a class, or raise error
    if (!klass.$$is_class) {
      throw Opal.TypeError.$new(name + " is not a class");
    }

    // Make sure existing class has same superclass
    if (superclass && klass.$$super !== superclass) {
      throw Opal.TypeError.$new("superclass mismatch for class " + name);
    }

    return klass;
  }

  // Class doesnt exist, create a new one with given superclass...

  // Not specifying a superclass means we can assume it to be Object
  if (superclass == null) {
    superclass = _Object;
  }

  // If bridged the JS class will also be the alloc function
  alloc = bridged || Opal.boot_class_alloc(name, constructor, superclass);

  // Create the class object (instance of Class)
  klass = Opal.setup_class_object(name, alloc, superclass.$$name, superclass.constructor);

  // @property $$super the superclass, doesn't get changed by module inclusions
  klass.$$super = superclass;

  // @property $$parent direct parent class
  //                    starts with the superclass, after klass inclusion is
  //                    the last included klass
  klass.$$parent = superclass;

  Opal.const_set(base, name, klass);

  // Name new class directly onto current scope (Opal.Foo.Baz = klass)
  base[name] = klass;

  if (bridged) {
    Opal.bridge(klass, alloc);
  }
  else {
    // Call .inherited() hook with new class on the superclass
    if (superclass.$inherited) {
      superclass.$inherited(klass);
    }
  }

  return klass;
};

Opal.boot_class_alloc = function(name, constructor, superclass)

Boot a base class (makes instances).

@param name [String,null] the class name @param constructor [JS.Function] the class' instances constructor/alloc function @param superclass [Class,null] the superclass object @return [JS.Function] the consturctor holding the prototype for the class' instances

Opal.boot_class_alloc = function(name, constructor, superclass) {
  if (superclass) {
    var alloc_proxy = function() {};
    alloc_proxy.prototype = superclass.$$proto || superclass.prototype;
    constructor.prototype = new alloc_proxy();
  }

  if (name) {
    constructor.displayName = name+'_alloc';
  }

  constructor.prototype.constructor = constructor;

  return constructor;
};

module.$$id = Opal.uid()

@property $$id Each class/module is assigned a unique id that helps comparation and implementation of #object_id

module.$$id = Opal.uid();

module.$$is_a_module = true

@property $$is_a_module Will be true for Module and its subclasses instances (namely: Class).

module.$$is_a_module = true;

module.$$inc = []

@property $$inc included modules

module.$$inc = [];

module.$$name = nil

initialize the name with nil

module.$$name = nil;

module.$$const = Object.create(null)

Initialize the constants table

module.$$const = Object.create(null);

module.$$cvars = Object.create(null)

@property $$cvars class variables defined in the current module

module.$$cvars = Object.create(null);

Opal.setup_class_object = function(name, alloc, superclass_name, superclass_alloc)

Adds common/required properties to class object (as in Class.new)

@param name [String,null] The name of the class

@param alloc [JS.Function] The constructor of the class' instances

@param superclass_name [String,null] The name of the super class, this is usefule to build the .displayName of the singleton class

@param superclass_alloc [JS.Function] The constructor of the superclass from which the singleton_class is derived.

@return [Class]

Opal.setup_class_object = function(name, alloc, superclass_name, superclass_alloc) {
  // Grab the superclass prototype and use it to build an intermediary object
  // in the prototype chain.
  var superclass_alloc_proxy = function() {};
      superclass_alloc_proxy.prototype = superclass_alloc.prototype;
      superclass_alloc_proxy.displayName = superclass_name;

  var singleton_class_alloc = function() {}
      singleton_class_alloc.prototype = new superclass_alloc_proxy();

  // The built class is the only instance of its singleton_class
  var klass = new singleton_class_alloc();

  Opal.setup_module_or_class(klass);

  // @property $$alloc This is the constructor of instances of the current
  //                   class. Its prototype will be used for method lookup
  klass.$$alloc = alloc;

  klass.$$name = name || nil;

  // Set a displayName for the singleton_class
  singleton_class_alloc.displayName = "#<Class:"+(name || ("#<Class:"+klass.$$id+">"))+">";

  // @property $$proto This is the prototype on which methods will be defined
  klass.$$proto = alloc.prototype;

  // @property $$proto.$$class Make available to instances a reference to the
  //                           class they belong to.
  klass.$$proto.$$class = klass;

  // @property constructor keeps a ref to the constructor, but apparently the
  //                       constructor is already set on:
  //
  //                          `var klass = new constructor` is called.
  //
  //                       Maybe there are some browsers not abiding (IE6?)
  klass.constructor = singleton_class_alloc;

  // @property $$is_class Clearly mark this as a class
  klass.$$is_class = true;

  // @property $$class Classes are instances of the class Class
  klass.$$class    = Class;

  return klass;
};

Opal.module = function(base, name)

Define new module (or return existing module). The given base is basically the current self value the module statement was defined in. If this is a ruby module or class, then it is used, otherwise if the base is a ruby object then that objects real ruby class is used (e.g. if the base is the main object, then the top level Object class is used as the base).

If a module of the given name is already defined in the base, then that instance is just returned.

If there is a class of the given name in the base, then an error is generated instead (cannot have a class and module of same name in same base).

Otherwise, a new module is created in the base with the given name, and that new instance is returned back (to be referenced at runtime).

@param base [Module, Class] class or module this definition is inside @param id [String] the name of the new (or existing) module

@return [Module]

Opal.module = function(base, name) {
  var module;

  if (base == null) {
    base = _Object;
  }

  if (!base.$$is_class && !base.$$is_module) {
    base = base.$$class;
  }

  module = const_get_name(base, name);
  if (module == null && base === _Object) module = const_lookup_ancestors(_Object, name);

  if (module) {
    if (!module.$$is_module && module !== _Object) {
      throw Opal.TypeError.$new(name + " is not a module");
    }
  }
  else {
    module = Opal.module_allocate(Module);
    Opal.const_set(base, name, module);
  }

  return module;
};

Opal.module_initialize = function(module, block)

The implementation for Module#initialize @param module [Module] @param block [Proc,nil] @return nil

Opal.module_initialize = function(module, block) {
  if (block !== nil) {
    var block_self = block.$$s;
    block.$$s = null;
    block.call(module);
    block.$$s = block_self;
  }
  return nil;
};

Opal.module_allocate = function(superclass)

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

Opal.module_allocate = function(superclass) {
  var mtor = function() {};
  mtor.prototype = superclass.$$alloc.prototype;

  var module_constructor = function() {};
  module_constructor.prototype = new mtor();

  var module = new module_constructor();
  var module_prototype = {};

  Opal.setup_module_or_class(module);

  // initialize dependency tracking
  module.$$included_in = [];

  // Set the display name of the singleton prototype holder
  module_constructor.displayName = "#<Class:#<Module:"+module.$$id+">>"

  // @property $$proto This is the prototype on which methods will be defined
  module.$$proto = module_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 = module_constructor;

  // @property $$is_module Clearly mark this as a module
  module.$$is_module = true;
  module.$$class     = Module;

  // @property $$super
  //   the superclass, doesn't get changed by module inclusions
  module.$$super = superclass;

  // @property $$parent
  //   direct parent class or module
  //   starts with the superclass, after module inclusion is
  //   the last included module
  module.$$parent = superclass;

  return module;
};

Opal.get_singleton_class = function(object)

Return the singleton class for the passed object.

If the given object alredy has a singleton class, then it will be stored on the object as the $$meta property. If this exists, then it is simply returned back.

Otherwise, a new singleton object for the class or object is created, set on the object at $$meta for future use, and then returned.

@param object [Object] the ruby object @return [Class] the singleton class for object

Opal.get_singleton_class = function(object) {
  if (object.$$meta) {
    return object.$$meta;
  }

  if (object.$$is_class || object.$$is_module) {
    return Opal.build_class_singleton_class(object);
  }

  return Opal.build_object_singleton_class(object);
};

Opal.build_class_singleton_class = function(object)

Build the singleton class for an existing class. Class object are built with their singleton class already in the prototype chain and inheriting from their superclass object (up to Class itself).

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

@param klass [Class] @return [Class]

Opal.build_class_singleton_class = function(object) {
  var alloc, superclass, klass;

  if (object.$$meta) {
    return object.$$meta;
  }

  // The constructor and prototype of the singleton_class instances is the
  // current class constructor and prototype.
  alloc = object.constructor;

  // The singleton_class superclass is the singleton_class of its superclass;
  // but BasicObject has no superclass (its `$$super` is null), thus we
  // fallback on `Class`.
  superclass = object === BasicObject ? Class : Opal.build_class_singleton_class(object.$$super);

  klass = Opal.setup_class_object(null, alloc, superclass.$$name, superclass.constructor);
  klass.$$super  = superclass;
  klass.$$parent = superclass;

  klass.$$is_singleton = true;
  klass.$$singleton_of = object;

  return object.$$meta = klass;
};

Opal.build_object_singleton_class = function(object)

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

@param object [Object] @return [Class]

Opal.build_object_singleton_class = function(object) {
  var superclass = object.$$class,
      name = "#<Class:#<" + superclass.$$name + ":" + superclass.$$id + ">>";

  var alloc = Opal.boot_class_alloc(name, function(){}, superclass)
  var klass = Opal.setup_class_object(name, alloc, superclass.$$name, superclass.constructor);

  klass.$$super  = superclass;
  klass.$$parent = superclass;
  klass.$$class  = superclass.$$class;
  klass.$$proto  = object;

  klass.$$is_singleton = true;
  klass.$$singleton_of = object;

  return object.$$meta = klass;
};

Opal.class_variables = function(module)

Returns an object containing all pairs of names/values for all class variables defined in provided +module+ and its ancestors.

@param module [Module] @return [Object]

Opal.class_variables = function(module) {
  var ancestors = Opal.ancestors(module),
      i, length = ancestors.length,
      result = {};

  for (i = length - 1; i >= 0; i--) {
    var ancestor = ancestors[i];

    for (var cvar in ancestor.$$cvars) {
      result[cvar] = ancestor.$$cvars[cvar];
    }
  }

  return result;
}

Opal.class_variable_set = function(module, name, value)

Sets class variable with specified +name+ to +value+ in provided +module+

@param module [Module] @param name [String] @param value [Object]

Opal.class_variable_set = function(module, name, value) {
  var ancestors = Opal.ancestors(module),
      i, length = ancestors.length;

  for (i = length - 2; i >= 0; i--) {
    var ancestor = ancestors[i];

    if ($hasOwn.call(ancestor.$$cvars, name)) {
      ancestor.$$cvars[name] = value;
      return value;
    }
  }

  module.$$cvars[name] = value;

  return value;
}

Opal.bridge_method = function(target_constructor, from, name, body)

Bridges a single method.

@param target [JS::Function] the constructor of the bridged class @param from [Module] the module/class we are importing the method from @param name [String] the method name in JS land (i.e. starting with $) @param body [JS::Function] the body of the method

Opal.bridge_method = function(target_constructor, from, name, body) {
  var ancestors, i, ancestor, length;

  ancestors = target_constructor.$$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_constructor.prototype[name] = body
      break;
    }
  }
};

Opal.bridge_methods = function(target, donator)

Bridges from donator to a target.

@param target [Module] the potentially associated with bridged classes module @param donator [Module] the module/class source of the methods that should be bridged

Opal.bridge_methods = function(target, donator) {
  var i,
      bridged = BridgedClasses[target.$__id__()],
      donator_id = donator.$__id__();

  if (bridged) {
    BridgedClasses[donator_id] = bridged.slice();

    for (i = bridged.length - 1; i >= 0; i--) {
      Opal_bridge_methods_to_constructor(bridged[i], donator)
    }
  }
};

function Opal_bridge_methods_to_constructor(target_constructor, donator)

Actually bridge methods to the bridged (shared) prototype.

function Opal_bridge_methods_to_constructor(target_constructor, donator) {
  var i,
      method,
      methods = donator.$instance_methods();

  for (i = methods.length - 1; i >= 0; i--) {
    method = '$' + methods[i];
    Opal.bridge_method(target_constructor, donator, method, donator.$$proto[method]);
  }
}

function Opal_add_bridged_constructor(target_constructor, donator)

Associate the target as a bridged class for the current "donator"

function Opal_add_bridged_constructor(target_constructor, donator) {
  var donator_id = donator.$__id__();

  if (!BridgedClasses[donator_id]) {
    BridgedClasses[donator_id] = [];
  }
  BridgedClasses[donator_id].push(target_constructor);
}

Opal.has_cyclic_dep = function has_cyclic_dep(base_id, deps, prop, seen)

Walks the dependency tree detecting the presence of the base among its own dependencies.

@param [Integer] base_id The id of the base module (eg. the "includer") @param [Array] deps The array of dependencies (eg. the included module, included.$$deps) @param [String] prop The property that holds dependencies (eg. "$$deps") @param [JS::Object] seen A JS object holding the cache of already visited objects @return [Boolean] true if a cyclic dependency is present

Opal.has_cyclic_dep = function has_cyclic_dep(base_id, deps, prop, seen) {
  var i, dep_id, dep;

  for (i = deps.length - 1; i >= 0; i--) {
    dep = deps[i];
    dep_id = dep.$$id;

    if (seen[dep_id]) {
      continue;
    }
    seen[dep_id] = true;

    if (dep_id === base_id) {
      return true;
    }

    if (has_cyclic_dep(base_id, dep[prop], prop, seen)) {
      return true;
    }
  }

  return false;
}

Opal.append_features = function(module, includer)

The actual inclusion of a module into a class.

Class $$parent and iclass

To handle super calls, every class has a $$parent. This parent is used to resolve the next class for a super call. A normal class would have this point to its superclass. However, if a class includes a module then this would need to take into account the module. The module would also have to then point its $$parent to the actual superclass. We cannot modify modules like this, because it might be included in more then one class. To fix this, we actually insert an iclass as the class' $$parent which can then point to the superclass. The iclass acts as a proxy to the actual module, so the super chain can then search it for the required method.

@param module [Module] the module to include @param includer [Module] the target class to include module into @return [null]

Opal.append_features = function(module, includer) {
  var iclass, donator, prototype, methods, id, i;

  // check if this module is already included in the class
  for (i = includer.$$inc.length - 1; i >= 0; i--) {
    if (includer.$$inc[i] === module) {
      return;
    }
  }

  // Check that the base module is not also a dependency, classes can't be
  // dependencies so we have a special case for them.
  if (!includer.$$is_class && Opal.has_cyclic_dep(includer.$$id, [module], '$$inc', {})) {
    throw Opal.ArgumentError.$new('cyclic include detected')
  }

  Opal.const_cache_version++;
  includer.$$inc.push(module);
  module.$$included_in.push(includer);
  Opal.bridge_methods(includer, module);

  // iclass
  iclass = {
    $$name:   module.$$name,
    $$proto:  module.$$proto,
    $$parent: includer.$$parent,
    $$module: module,
    $$iclass: true
  };

  includer.$$parent = iclass;

  methods = module.$instance_methods();

  for (i = methods.length - 1; i >= 0; i--) {
    Opal.update_includer(module, includer, '$' + methods[i])
  }
};

Opal.stubs = {}

Table that holds all methods that have been defined on all objects It is used for defining method stubs for new coming native classes

Opal.stubs = {};

Opal.bridge = function(klass, constructor)

For performance, some core Ruby classes are toll-free bridged to their native JavaScript counterparts (e.g. a Ruby Array is a JavaScript Array).

This method is used to setup a native constructor (e.g. Array), to have its prototype act like a normal Ruby class. Firstly, a new Ruby class is created using the native constructor so that its prototype is set as the target for th new class. Note: all bridged classes are set to inherit from Object.

Example:

Opal.bridge(self, Function);

@param klass [Class] the Ruby class to bridge @param constructor [JS.Function] native JavaScript constructor to use @return [Class] returns the passed Ruby class

Opal.bridge = function(klass, constructor) {
  if (constructor.$$bridge) {
    throw Opal.ArgumentError.$new("already bridged");
  }

  Opal.stub_subscribers.push(constructor.prototype);

  // Populate constructor with previously stored stubs
  for (var method_name in Opal.stubs) {
    if (!(method_name in constructor.prototype)) {
      constructor.prototype[method_name] = Opal.stub_for(method_name);
    }
  }

  constructor.prototype.$$class = klass;
  constructor.$$bridge          = klass;

  var ancestors = klass.$ancestors();

  // order important here, we have to bridge from the last ancestor to the
  // bridged class
  for (var i = ancestors.length - 1; i >= 0; i--) {
    Opal_add_bridged_constructor(constructor, ancestors[i]);
    Opal_bridge_methods_to_constructor(constructor, ancestors[i]);
  }

  for (var name in BasicObject_alloc.prototype) {
    var method = BasicObject_alloc.prototype[method];

    if (method && method.$$stub && !(name in constructor.prototype)) {
      constructor.prototype[name] = method;
    }
  }

  return klass;
};

Opal.update_includer = function(module, includer, jsid)

Update jsid method cache of all classes / modules including module.

Opal.update_includer = function(module, includer, jsid) {
  var dest, current, body,
      klass_includees, j, jj, current_owner_index, module_index;

  body    = module.$$proto[jsid];
  dest    = includer.$$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 = includer.$$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 the includer is a module, recursively update all of its includres.
  if (includer.$$included_in) {
    Opal.update_includers(includer, jsid);
  }
};

Opal.update_includers = function(module, jsid)

Update jsid method cache of all classes / modules including module.

Opal.update_includers = function(module, jsid) {
  var i, ii, includee, included_in;

  included_in = module.$$included_in;

  if (!included_in) {
    return;
  }

  for (i = 0, ii = included_in.length; i < ii; i++) {
    includee = included_in[i];
    Opal.update_includer(module, includee, jsid);
  }
};

Opal.ancestors = function(module_or_class)

The Array of ancestors for a given module/class

Opal.ancestors = function(module_or_class) {
  var parent = module_or_class,
      result = [],
      modules, i, ii, j, jj;

  while (parent) {
    result.push(parent);
    for (i = parent.$$inc.length-1; i >= 0; i--) {
      modules = Opal.ancestors(parent.$$inc[i]);

      for(j = 0, jj = modules.length; j < jj; j++) {
        result.push(modules[j]);
      }
    }

    // only the actual singleton class gets included in its ancestry
    // after that, traverse the normal class hierarchy
    if (parent.$$is_singleton && parent.$$singleton_of.$$is_module) {
      parent = parent.$$singleton_of.$$super;
    }
    else {
      parent = parent.$$is_class ? parent.$$super : null;
    }
  }

  return result;
};

``

Method Missing


Opal.add_stubs = function(stubs)

Methods stubs are used to facilitate method_missing in opal. A stub is a placeholder function which just calls method_missing on the receiver. If no method with the given name is actually defined on an object, then it is obvious to say that the stub will be called instead, and then in turn method_missing will be called.

When a file in ruby gets compiled to javascript, it includes a call to this function which adds stubs for every method name in the compiled file. It should then be safe to assume that method_missing will work for any method call detected.

Method stubs are added to the BasicObject prototype, which every other ruby object inherits, so all objects should handle method missing. A stub is only added if the given property name (method name) is not already defined.

Note: all ruby methods have a $ prefix in javascript, so all stubs will have this prefix as well (to make this method more performant).

Opal.add_stubs(["$foo", "$bar", "$baz="]);

All stub functions will have a private $$stub property set to true so that other internal methods can detect if a method is just a stub or not. Kernel#respond_to? uses this property to detect a methods presence.

@param stubs [Array] an array of method stubs to add @return [undefined]

Opal.add_stubs = function(stubs) {
  var subscriber, subscribers = Opal.stub_subscribers,
      i, ilength = stubs.length,
      j, jlength = subscribers.length,
      method_name, stub,
      opal_stubs = Opal.stubs;

  for (i = 0; i < ilength; i++) {
    method_name = stubs[i];

    if(!opal_stubs.hasOwnProperty(method_name)) {
      // Save method name to populate other subscribers with this stub
      opal_stubs[method_name] = true;
      stub = Opal.stub_for(method_name);

      for (j = 0; j < jlength; j++) {
        subscriber = subscribers[j];

        if (!(method_name in subscriber)) {
          subscriber[method_name] = stub;
        }
      }
    }
  }
};

Opal.stub_subscribers = [BasicObject_alloc.prototype]

Keep a list of prototypes that want method_missing stubs to be added.

@default [Prototype List] BasicObject_alloc.prototype

Opal.stub_subscribers = [BasicObject_alloc.prototype];

Opal.add_stub_for = function(prototype, stub)

Add a method_missing stub function to the given prototype for the given name.

@param prototype [Prototype] the target prototype @param stub [String] stub name to add (e.g. "$foo") @return [undefined]

Opal.add_stub_for = function(prototype, stub) {
  var method_missing_stub = Opal.stub_for(stub);
  prototype[stub] = method_missing_stub;
};

Opal.stub_for = function(method_name)

Generate the method_missing stub for a given method name.

@param method_name [String] The js-name of the method to stub (e.g. "$foo") @return [undefined]

Opal.stub_for = function(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)
    var args_ary = new Array(arguments.length);
    for(var i = 0, l = args_ary.length; i < l; i++) { args_ary[i] = arguments[i]; }

    return this.$method_missing.apply(this, [method_name.slice(1)].concat(args_ary));
  }

  method_missing_stub.$$stub = true;

  return method_missing_stub;
};

``

Methods


Opal.ac = function(actual, expected, object, meth)

Arity count error dispatcher for methods

@param actual [Fixnum] number of arguments given to method @param expected [Fixnum] expected number of arguments @param object [Object] owner of the method +meth+ @param meth [String] method name that got wrong number of arguments @raise [ArgumentError]

Opal.ac = function(actual, expected, object, meth) {
  var inspect = '';
  if (object.$$is_class || object.$$is_module) {
    inspect += object.$$name + '.';
  }
  else {
    inspect += object.$$class.$$name + '#';
  }
  inspect += meth;

  throw Opal.ArgumentError.$new('[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')');
};

Opal.block_ac = function(actual, expected, context)

Arity count error dispatcher for blocks

@param actual [Fixnum] number of arguments given to block @param expected [Fixnum] expected number of arguments @param context [Object] context of the block definition @raise [ArgumentError]

Opal.block_ac = function(actual, expected, context) {
  var inspect = "`block in " + context + "'";

  throw Opal.ArgumentError.$new(inspect + ': wrong number of arguments (' + actual + ' for ' + expected + ')');
};

Opal.find_super_dispatcher = function(obj, mid, current_func, defcheck, defs)

Super dispatcher

Opal.find_super_dispatcher = function(obj, mid, current_func, defcheck, defs) {
  var dispatcher, super_method;

  if (defs) {
    if (obj.$$is_class || obj.$$is_module) {
      dispatcher = defs.$$super;
    }
    else {
      dispatcher = obj.$$class.$$proto;
    }
  }
  else {
    dispatcher = Opal.find_obj_super_dispatcher(obj, mid, current_func);
  }

  super_method = dispatcher['$' + mid];

  if (!defcheck && super_method.$$stub && Opal.Kernel.$method_missing === obj.$method_missing) {
    // method_missing hasn't been explicitly defined
    throw Opal.NoMethodError.$new('super: no superclass method `'+mid+"' for "+obj, mid);
  }

  return super_method;
};

Opal.find_iter_super_dispatcher = function(obj, jsid, current_func, defcheck, implicit)

Iter dispatcher for super in a block

Opal.find_iter_super_dispatcher = function(obj, jsid, current_func, defcheck, implicit) {
  var call_jsid = jsid;

  if (!current_func) {
    throw Opal.RuntimeError.$new("super called outside of method");
  }

  if (implicit && current_func.$$define_meth) {
    throw Opal.RuntimeError.$new("implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly");
  }

  if (current_func.$$def) {
    call_jsid = current_func.$$jsid;
  }

  return Opal.find_super_dispatcher(obj, call_jsid, current_func, defcheck);
};

klass = Opal.find_owning_class(klass, current_func)

first we need to find the class/module current_func is located on

klass = Opal.find_owning_class(klass, current_func);

``

repeating for readability


break

this klass was the last one the module donated to case is also hit with multiple module includes

break;

break

module has donated to other classes but klass isn't one of those

break;

break

cases like stdlib Singleton::included that use a singleton of a singleton

break;

break

no modules, pure class inheritance

break;

while (klass)

now we can find the super

while (klass) {

break

ok

break;

Opal.ret = function(val)

Used to return as an expression. Sometimes, we can't simply return from a javascript function as if we were a method, as the return is used as an expression, or even inside a block which must "return" to the outer method. This helper simply throws an error which is then caught by the method. This approach is expensive, so it is only used when absolutely needed.

Opal.ret = function(val) {
  Opal.returner.$v = val;
  throw Opal.returner;
};

Opal.brk = function(val, breaker)

Used to break out of a block.

Opal.brk = function(val, breaker) {
  breaker.$v = val;
  throw breaker;
};

Opal.new_brk = function()

Builds a new unique breaker, this is to avoid multiple nested breaks to get in the way of each other.

Opal.new_brk = function() {
  return new Error('unexpected break');
};

Opal.yield1 = function(block, arg)

handles yield calls for 1 yielded arg

Opal.yield1 = function(block, arg) {
  if (typeof(block) !== "function") {
    throw Opal.LocalJumpError.$new("no block given");
  }

  var has_mlhs = block.$$has_top_level_mlhs_arg,
      has_trailing_comma = block.$$has_trailing_comma_in_args;

  if (block.length > 1 || ((has_mlhs || has_trailing_comma) && block.length === 1)) {
    arg = Opal.to_ary(arg);
  }

  if ((block.length > 1 || (has_trailing_comma && block.length === 1)) && arg.$$is_array) {
    return block.apply(null, arg);
  }
  else {
    return block(arg);
  }
};

Opal.yieldX = function(block, args)

handles yield for > 1 yielded arg

Opal.yieldX = function(block, args) {
  if (typeof(block) !== "function") {
    throw Opal.LocalJumpError.$new("no block given");
  }

  if (block.length > 1 && args.length === 1) {
    if (args[0].$$is_array) {
      return block.apply(null, args[0]);
    }
  }

  if (!args.$$is_array) {
    var args_ary = new Array(args.length);
    for(var i = 0, l = args_ary.length; i < l; i++) { args_ary[i] = args[i]; }

    return block.apply(null, args_ary);
  }

  return block.apply(null, args);
};

Opal.rescue = function(exception, candidates)

Finds the corresponding exception match in candidates. Each candidate can be a value, or an array of values. Returns null if not found.

Opal.rescue = function(exception, candidates) {
  for (var i = 0; i < candidates.length; i++) {
    var candidate = candidates[i];

    if (candidate.$$is_array) {
      var result = Opal.rescue(exception, candidate);

      if (result) {
        return result;
      }
    }
    else if (candidate === Opal.JS.Error) {
      return candidate;
    }
    else if (candidate['$==='](exception)) {
      return candidate;
    }
  }

  return null;
};

Opal.to_hash = function(value)

Helpers for extracting kwsplats Used for: { **h }

Opal.to_hash = function(value) {
  if (value.$$is_hash) {
    return value;
  }
  else if (value['$respond_to?']('to_hash', true)) {
    var hash = value.$to_hash();
    if (hash.$$is_hash) {
      return hash;
    }
    else {
      throw Opal.TypeError.$new("Can't convert " + value.$$class +
        " to Hash (" + value.$$class + "#to_hash gives " + hash.$$class + ")");
    }
  }
  else {
    throw Opal.TypeError.$new("no implicit conversion of " + value.$$class + " into Hash");
  }
};

``

Helpers for implementing multiple assignment Our code for extracting the values and assigning them only works if the return value is a JS array. So if we get an Array subclass, extract the wrapped JS array from it


Opal.to_ary = function(value)

Used for: a, b = something (no splat)

Opal.to_ary = function(value) {
  if (value.$$is_array) {
    return value;
  }
  else if (value['$respond_to?']('to_ary', true)) {
    var ary = value.$to_ary();
    if (ary === nil) {
      return [value];
    }
    else if (ary.$$is_array) {
      return ary;
    }
    else {
      throw Opal.TypeError.$new("Can't convert " + value.$$class +
        " to Array (" + value.$$class + "#to_ary gives " + ary.$$class + ")");
    }
  }
  else {
    return [value];
  }
};

Opal.to_a = function(value)

Used for: a, b = *something (with splat)

Opal.to_a = function(value) {
  if (value.$$is_array) {
    // A splatted array must be copied
    return value.slice();
  }
  else if (value['$respond_to?']('to_a', true)) {
    var ary = value.$to_a();
    if (ary === nil) {
      return [value];
    }
    else if (ary.$$is_array) {
      return ary;
    }
    else {
      throw Opal.TypeError.$new("Can't convert " + value.$$class +
        " to Array (" + value.$$class + "#to_a gives " + ary.$$class + ")");
    }
  }
  else {
    return [value];
  }
};

Opal.extract_kwargs = function(parameters)

Used for extracting keyword arguments from arguments passed to JS function. If provided +arguments+ list doesn't have a Hash as a last item, returns a blank Hash.

@param parameters [Array] @return [Hash]

Opal.extract_kwargs = function(parameters) {
  var kwargs = parameters[parameters.length - 1];
  if (kwargs != null && kwargs['$respond_to?']('to_hash', true)) {
    Array.prototype.splice.call(parameters, parameters.length - 1, 1);
    return kwargs.$to_hash();
  }
  else {
    return Opal.hash2([], {});
  }
}

Opal.kwrestargs = function(given_args, used_args)

Used to get a list of rest keyword arguments. Method takes the given keyword args, i.e. the hash literal passed to the method containing all keyword arguemnts passed to method, as well as the used args which are the names of required and optional arguments defined. This method then just returns all key/value pairs which have not been used, in a new hash literal.

@param given_args [Hash] all kwargs given to method @param used_args [Object] all keys used as named kwargs @return [Hash]

Opal.kwrestargs = function(given_args, used_args) {
  var keys      = [],
      map       = {},
      key       = null,
      given_map = given_args.$$smap;

  for (key in given_map) {
    if (!used_args[key]) {
      keys.push(key);
      map[key] = given_map[key];
    }
  }

  return Opal.hash2(keys, map);
};

Opal.send = function(recv, method, args, block)

Calls passed method on a ruby object with arguments and block:

Can take a method or a method name.

  1. When method name gets passed it invokes it by its name and calls 'method_missing' when object doesn't have this method. Used internally by Opal to invoke method that takes a block or a splat.
  2. When method (i.e. method body) gets passed, it doesn't trigger 'method_missing' because it doesn't know the name of the actual method. Used internally by Opal to invoke 'super'.

@example var my_array = [1, 2, 3, 4] Opal.send(my_array, 'length') # => 4 Opal.send(my_array, my_array.$length) # => 4

Opal.send(my_array, 'reverse!') # => [4, 3, 2, 1] Opal.send(my_array, my_array['$reverse!']') # => [4, 3, 2, 1]

@param recv [Object] ruby object @param method [Function, String] method body or name of the method @param args [Array] arguments that will be passed to the method call @param block [Function] ruby block @return [Object] returning value of the method call

Opal.send = function(recv, method, args, block) {
  var body = (typeof(method) === 'string') ? recv['$'+method] : method;

  if (body != null) {
    body.$$p = block;
    return body.apply(recv, args);
  }

  return recv.$method_missing.apply(recv, [method].concat(args));
}

Opal.def = function(obj, jsid, body)

Used to define methods on an object. This is a helper method, used by the compiled source to define methods on special case objects when the compiler can not determine the destination object, or the object is a Module instance. This can get called by Module#define_method as well.

Modules

Any method defined on a module will come through this runtime helper. The method is added to the module body, and the owner of the method is set to be the module itself. This is used later when choosing which method should show on a class if more than 1 included modules define the same method. Finally, if the module is in module_function mode, then the method is also defined onto the module itself.

Classes

This helper will only be called for classes when a method is being defined indirectly; either through Module#define_method, or by a literal def method inside an instance_eval or class_eval body. In either case, the method is simply added to the class' prototype. A special exception exists for BasicObject and Object. These two classes are special because they are used in toll-free bridged classes. In each of these two cases, extra work is required to define the methods on toll-free bridged class' prototypes as well.

Objects

If a simple ruby object is the object, then the method is simply just defined on the object as a singleton method. This would be the case when a method is defined inside an instance_eval block.

@param obj [Object, Class] the actual obj to define method for @param jsid [String] the JavaScript friendly method name (e.g. '$foo') @param body [JS.Function] the literal JavaScript function used as method @return [null]

Opal.def = function(obj, jsid, body) {
  // if instance_eval is invoked on a module/class, it sets inst_eval_mod
  if (!obj.$$eval && (obj.$$is_class || obj.$$is_module)) {
    Opal.defn(obj, jsid, body);
  }
  else {
    Opal.defs(obj, jsid, body);
  }
};

Opal.defn = function(obj, jsid, body)

Define method on a module or class (see Opal.def).

Opal.defn = function(obj, jsid, body) {
  obj.$$proto[jsid] = body;
  // for super dispatcher, etc.
  body.$$owner = obj;
  if (body.displayName == null) body.displayName = jsid.substr(1);

  // is it a module?
  if (obj.$$is_module) {
    Opal.update_includers(obj, jsid);

    if (obj.$$module_function) {
      Opal.defs(obj, jsid, body);
    }
  }

  // is it a bridged class?
  var bridged = obj.$__id__ && !obj.$__id__.$$stub && BridgedClasses[obj.$__id__()];
  if (bridged) {
    for (var i = bridged.length - 1; i >= 0; i--) {
      Opal.bridge_method(bridged[i], obj, jsid, body);
    }
  }

  // method_added/singleton_method_added hooks
  var singleton_of = obj.$$singleton_of;
  if (obj.$method_added && !obj.$method_added.$$stub && !singleton_of) {
    obj.$method_added(jsid.substr(1));
  }
  else if (singleton_of && singleton_of.$singleton_method_added && !singleton_of.$singleton_method_added.$$stub) {
    singleton_of.$singleton_method_added(jsid.substr(1));
  }

  return nil;
};

Opal.defs = function(obj, jsid, body)

Define a singleton method on the given object (see Opal.def).

Opal.defs = function(obj, jsid, body) {
  Opal.defn(Opal.get_singleton_class(obj), jsid, body)
};

Opal.rdef = function(obj, jsid)

Called from #remove_method.

Opal.rdef = function(obj, jsid) {
  // TODO: remove from BridgedClasses as well

  if (!$hasOwn.call(obj.$$proto, jsid)) {
    throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
  }

  delete obj.$$proto[jsid];

  if (obj.$$is_singleton) {
    if (obj.$$proto.$singleton_method_removed && !obj.$$proto.$singleton_method_removed.$$stub) {
      obj.$$proto.$singleton_method_removed(jsid.substr(1));
    }
  }
  else {
    if (obj.$method_removed && !obj.$method_removed.$$stub) {
      obj.$method_removed(jsid.substr(1));
    }
  }
};

Opal.udef = function(obj, jsid)

Called from #undef_method.

Opal.udef = function(obj, jsid) {
  if (!obj.$$proto[jsid] || obj.$$proto[jsid].$$stub) {
    throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
  }

  Opal.add_stub_for(obj.$$proto, jsid);

  if (obj.$$is_singleton) {
    if (obj.$$proto.$singleton_method_undefined && !obj.$$proto.$singleton_method_undefined.$$stub) {
      obj.$$proto.$singleton_method_undefined(jsid.substr(1));
    }
  }
  else {
    if (obj.$method_undefined && !obj.$method_undefined.$$stub) {
      obj.$method_undefined(jsid.substr(1));
    }
  }
};

if (obj.$$eval)

When running inside #instance_eval the alias refers to class methods.

if (obj.$$eval) {

if (body.$$alias_of) body = body.$$alias_of

If the body is itself an alias use the original body to keep the max depth at 1.

if (body.$$alias_of) body = body.$$alias_of;

alias = function()

We need a wrapper because otherwise method $$owner and other properties would be ovrewritten on the original body.

alias = function() {
  var block = alias.$$p, args, i, ii;

  args = new Array(arguments.length);
  for(i = 0, ii = arguments.length; i < ii; i++) {
    args[i] = arguments[i];
  }

  if (block != null) { alias.$$p = null }

  return Opal.send(this, body, args, block);
};

alias.displayName = name

Try to make the browser pick the right name

alias.displayName       = name;

``

Hashes


Opal.hash2 = function(keys, smap)

A faster Hash creator for hashes that just use symbols and strings as keys. The map and keys array can be constructed at compile time, so they are just added here by the constructor function.

Opal.hash2 = function(keys, smap) {
  var hash = new Opal.Hash.$$alloc();

  hash.$$smap = smap;
  hash.$$map  = Object.create(null);
  hash.$$keys = keys;

  return hash;
};

Opal.range = function(first, last, exc)

Create a new range instance with first and last values, and whether the range excludes the last value.

Opal.range = function(first, last, exc) {
  var range         = new Opal.Range.$$alloc();
      range.begin   = first;
      range.end     = last;
      range.excl    = exc;

  return range;
};

Opal.ivar = function(name)

Get the ivar name for a given name. Mostly adds a trailing $ to reserved names.

Opal.ivar = function(name) {
  if (
      // properties
      name === "constructor" ||
      name === "displayName" ||
      name === "__count__" ||
      name === "__noSuchMethod__" ||
      name === "__parent__" ||
      name === "__proto__" ||

      // methods
      name === "hasOwnProperty" ||
      name === "valueOf"
     )
  {
    return name + "$";
  }

  return name;
};

``

Regexps


Opal.escape_regexp = function(str)

Escape Regexp special chars letting the resulting string be used to build a new Regexp.

Opal.escape_regexp = function(str) {
  return str.replace(/([-[\]\/{}()*+?.^$\\| ])/g, '\\$1')
            .replace(/[\n]/g, '\\n')
            .replace(/[\r]/g, '\\r')
            .replace(/[\f]/g, '\\f')
            .replace(/[\t]/g, '\\t');
}

``

Require system


``

Initialization


Opal.boot_class_alloc('BasicObject', BasicObject_alloc)

Constructors for instances of core objects

Opal.boot_class_alloc('BasicObject', BasicObject_alloc);

Opal.BasicObject = BasicObject = Opal.setup_class_object('BasicObject', BasicObject_alloc, 'Class', Class_alloc)

Constructors for classes of core objects

Opal.BasicObject = BasicObject = Opal.setup_class_object('BasicObject', BasicObject_alloc, 'Class',       Class_alloc);

BasicObject.$$const["BasicObject"] = BasicObject

BasicObject can reach itself, avoid const_set to skip the $$base_module logic

BasicObject.$$const["BasicObject"] = BasicObject;

Opal.const_set(_Object, "BasicObject", BasicObject)

Assign basic constants

Opal.const_set(_Object, "BasicObject",  BasicObject);

BasicObject.$$class = Class

Fix booted classes to use their metaclass

BasicObject.$$class = Class;

BasicObject.$$super = null

Fix superclasses of booted classes

BasicObject.$$super = null;

_Object.$$proto.toString = function()

Forward .toString() to #to_s

_Object.$$proto.toString = function() {
  var to_s = this.$to_s();
  if (to_s.$$is_string && typeof(to_s) === 'object') {
    // a string created using new String('string')
    return to_s.valueOf();
  } else {
    return to_s;
  }
};

_Object.$$proto.$require = Opal.require

Make Kernel#require immediately available as it's needed to require all the other corelib files.

_Object.$$proto.$require = Opal.require;

Opal.top = new _Object.$$alloc()

Instantiate the top object

Opal.top = new _Object.$$alloc();

Opal.klass(_Object, _Object, 'NilClass', NilClass_alloc)

Nil

Opal.klass(_Object, _Object, 'NilClass', NilClass_alloc);