runtime.js

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 = {};

bridges = {}

All bridged classes - keep track to donate methods from Object

var bridges = {};

TopScope = function(){}

TopScope is used for inheriting constants from the top scope

var TopScope = function(){};

TopScope.prototype = Opal

Opal just acts as the top scope

TopScope.prototype = Opal;

Opal.constructor = TopScope

To inherit scopes

Opal.constructor = TopScope;

Opal.constants = []

List top scope constants

Opal.constants = [];

Opal.global = this

This is a useful reference to global object inside ruby files

Opal.global = this;

$hasOwn = Opal.hasOwnProperty

Minify common function calls

var $hasOwn = Opal.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.cvars = {}

Table holds all class variables

Opal.cvars = {};

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 phantom 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.get = function(name)

Get a constant on the given scope. Every class and module in Opal has a scope used to store, and inherit, constants. For example, the top level Object in ruby has a scope accessible as Opal.Object.$$scope.

To get the Array class using this scope, you could use:

Opal.Object.$$scope.get("Array")

If a constant with the given name cannot be found, then a dispatch to the class/module's #const_method is called, which by default will raise an error.

@param [String] name the name of the constant to lookup @return [RubyObject]

Opal.get = function(name) {
  var constant = this[name];

  if (constant == null) {
    return this.base.$const_get(name);
  }

  return constant;
};

Opal.create_scope = function(base_scope, klass, id)

Create a new constants scope for the given class with the given base. Constants are looked up through their parents, so the base scope will be the outer scope of the new klass.

@param base_scope [$$scope] the scope in which the new scope should be created @param klass [Class] @param id [String, null] the name of the newly created scope

Opal.create_scope = function(base_scope, klass, id) {
  var const_alloc = function() {};
  var const_scope = const_alloc.prototype = new base_scope.constructor();

  klass.$$scope       = const_scope;
  klass.$$base_module = base_scope.base;

  const_scope.base        = klass;
  const_scope.constructor = const_alloc;
  const_scope.constants   = [];

  if (id) {
    Opal.cdecl(base_scope, id, klass);
    const_alloc.displayName = id+"_scope_alloc";
  }
}

Opal.klass = function(base, superklass, id, 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, superklass 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 superklass [Class,null] superclass of the new class (may be null) @param id [String] the name of the class to be created @param constructor [Function] function to use as constructor

@return new [Class] or existing ruby class

Opal.klass = function(base, superklass, id, constructor) {
  var klass, bridged, alloc;

  // 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(superklass) === 'function') {
    bridged = superklass;
    superklass = _Object;
  }

  // Try to find the class in the current scope
  klass = base.$$scope[id];

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

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

    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 (superklass == null) {
    superklass = _Object;
  }

  // If bridged the JS class will also be the alloc function
  alloc = bridged || boot_class_alloc(id, constructor, superklass);

  // Create the class object (instance of Class)
  klass = boot_class_object(id, superklass, alloc);

  // Name the class
  klass.$$name = id;
  klass.displayName = id;

  // Mark the object as a class
  klass.$$is_class = true;

  // Every class gets its own constant scope, inherited from current scope
  Opal.create_scope(base.$$scope, klass, id);

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

  if (bridged) {
    Opal.bridge(klass, alloc);
  }
  else {
    // Copy all parent constants to child, unless parent is Object
    if (superklass !== _Object && superklass !== BasicObject) {
      donate_constants(superklass, klass);
    }

    // Call .inherited() hook with new class on the superclass
    if (superklass.$inherited) {
      superklass.$inherited(klass);
    }
  }

  return klass;
};

Opal.boot_class = function(superklass, constructor)

Create generic class with given superclass.

Opal.boot_class = function(superklass, constructor) {
  var alloc = boot_class_alloc(null, constructor, superklass)

  return boot_class_object(null, superklass, alloc);
}

function boot_class_object(id, superklass, alloc)

The class object itself (as in Class.new)

@param superklass [(Opal) Class] Another class object (as in Class.new) @param alloc [constructor] The constructor that holds the prototype that will be used for instances of the newly constructed class.

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;
}

function setup_module_or_class_object(module, constructor, superklass, prototype)

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

@param module The module or class that needs to be prepared

@param 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.

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

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

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 = [];
}

Opal.module = function(base, id)

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, id) {
  var module;

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

  if ($hasOwn.call(base.$$scope, id)) {
    module = base.$$scope[id];

    if (!module.$$is_module && module !== _Object) {
      throw Opal.TypeError.$new(id + " is not a module");
    }
  }
  else {
    module = boot_module_object();

    // name module using base (e.g. Foo or Foo::Baz)
    module.$$name = id;

    // mark the object as a module
    module.$$is_module = true;

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

    Opal.create_scope(base.$$scope, module, id);

    // Name new module directly onto current scope (Opal.Foo.Baz = module)
    base[id] = base.$$scope[id] = module;
  }

  return module;
};

function boot_module_object()

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

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;
}

Opal.boot_module_object = boot_module_object

Make boot_module_object available to the JS-API

Opal.boot_module_object = boot_module_object;

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 [RubyObject] object the ruby object @return [RubyClass] 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 build_class_singleton_class(object);
  }

  return build_object_singleton_class(object);
};

function build_class_singleton_class(klass)

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.

@param [RubyClass] klass @return [RubyClass]

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;
}

function build_object_singleton_class(object)

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

@param [RubyObject] object @return [RubyClass]

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;
}

function bridge_method(target, from, name, body)

Bridges a single method.

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;
    }
  }

}

function _bridge(target, donator)

Bridges from donator to a target.

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();
    }
  }
}

Opal.append_features = function(module, klass)

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 [RubyModule] module the module to include @param [RubyClass] klass the target class to include module into @return [null]

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

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

  klass.$$inc.push(module);
  module.$$dep.push(klass);
  _bridge(klass, module);

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

  klass.$$parent = iclass;

  donator   = module.$$proto;
  prototype = klass.$$proto;
  methods   = module.$instance_methods();

  for (i = methods.length - 1; i >= 0; i--) {
    id = '$' + methods[i];

    // if the target class already has a method of the same name defined
    // and that method was NOT donated, then it must be a method defined
    // by the class so we do not want to override it
    if ( prototype.hasOwnProperty(id) &&
        !prototype[id].$$donated &&
        !prototype[id].$$stub) {
      continue;
    }

    prototype[id] = donator[id];
    prototype[id].$$donated = module;
  }

  donate_constants(module, klass);
};

function boot_class_alloc(id, constructor, superklass)

Boot a base class (makes instances).

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;
}

function boot_core_class_object(id, alloc, superclass)

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

@param id [String] the name of the class @param alloc [Function] the constructor for the core class instances @param superclass [Class alloc] the constructor of the superclass

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;
}

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 [Class] klass the Ruby class to bridge @param [Function] constructor 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);

  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--) {
    _bridge(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.casgn = function(base_module, name, value)

Constant assignment, see also Opal.cdecl

@param base_module [Module, Class] the constant namespace @param name [String] the name of the constant @param value [Object] the value of the constant

@example Assigning a namespaced constant self::FOO = 'bar'

@example Assigning with Module#const_set Foo.const_set :BAR, 123

Opal.casgn = function(base_module, name, value) {
  function update(klass, name) {
    klass.$$name = name;

    for (name in klass.$$scope) {
      var value = klass.$$scope[name];

      if (value.$$name === nil && (value.$$is_class || value.$$is_module)) {
        update(value, name)
      }
    }
  }

  var scope = base_module.$$scope;

  if (value.$$is_class || value.$$is_module) {
    // Only checking _Object prevents setting a const on an anonymous class
    // that has a superclass that's not Object
    if (value.$$is_class || value.$$base_module === _Object) {
      value.$$base_module = base_module;
    }

    if (value.$$name === nil && value.$$base_module.$$name !== nil) {
      update(value, name);
    }
  }

  scope.constants.push(name);
  return scope[name] = value;
};

Opal.cdecl = function(base_scope, name, value)

constant decl

Opal.cdecl = function(base_scope, name, value) {
  if ((value.$$is_class || value.$$is_module) && value.$$orig_scope == null) {
    value.$$name = name;
    value.$$orig_scope = base_scope;
    base_scope.constructor[name] = value;
  }

  base_scope.constants.push(name);
  return base_scope[name] = value;
};

function donate_constants(source_mod, target_mod)

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

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]];
  }
};

function donate(module, jsid)

Donate methods for a module.

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);
    }
  }
};

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 [Array] stubs an array of method stubs to add

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

  for (i = 0; i < ilength; i++) {
    method_name = stubs[i];
    stub = 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 [String] stub stub name to add (e.g. "$foo")

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

function stub_for(method_name)

Generate the method_missing stub for a given method name.

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

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;
}

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

Arity count error dispatcher

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.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 = [];

  while (parent) {
    result.push(parent);
    for (var i=0; i < parent.$$inc.length; i++) {
      result = result.concat(Opal.ancestors(parent.$$inc[i]));
    }

    parent = parent.$$is_class ? parent.$$super : null;
  }

  return result;
}

Opal.find_super_dispatcher = function(obj, jsid, current_func, iter, defs)

Super dispatcher

Opal.find_super_dispatcher = function(obj, jsid, current_func, iter, defs) {
  var dispatcher;

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

  dispatcher = dispatcher['$' + jsid];
  dispatcher.$$p = iter;

  return dispatcher;
};

Opal.find_iter_super_dispatcher = function(obj, jsid, current_func, iter, defs)

Iter dispatcher for super in a block

Opal.find_iter_super_dispatcher = function(obj, jsid, current_func, iter, defs) {
  if (current_func.$$def) {
    return Opal.find_super_dispatcher(obj, current_func.$$jsid, current_func, iter, defs);
  }
  else {
    return Opal.find_super_dispatcher(obj, jsid, current_func, iter, defs);
  }
};

break

ok

break;

if (!klass)

if we arent in a class, we couldnt find current?

if (!klass) {

while (klass)

else, let's find the next one

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.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");
  }

  if (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) {
    args = $slice.call(args);
  }

  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['$==='](exception)) {
      return candidate;
    }
  }

  return null;
};

``

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


if (value.$$is_array)

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

if (value.$$is_array) {

if (value.$$is_array)

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

if (value.$$is_array) {

return (value.constructor === Array) ? value.slice() : value.literal.slice()

A splatted array must be copied

return (value.constructor === Array) ? value.slice() : value.literal.slice();

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, mid)

Call a ruby method on a ruby object with some arguments:

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

A missing method will be forwarded to the object via method_missing.

The result of either call with be returned.

@param [Object] recv the ruby object @param [String] mid ruby method to call

Opal.send = function(recv, mid) {
  var args = $slice.call(arguments, 2),
      func = recv['$' + mid];

  if (func) {
    return func.apply(recv, args);
  }

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

Opal.defn = 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 [RubyObject or Class] obj the actual obj to define method for @param [String] jsid the javascript friendly method name (e.g. '$foo') @param [Function] body the literal javascript function used as method @return [null]

Opal.defn = function(obj, jsid, body) {
  obj.$$proto[jsid] = body;

  if (obj.$$is_module) {
    donate(obj, jsid);

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

  if (obj.$__id__ && !obj.$__id__.$$stub) {
    var bridged = bridges[obj.$__id__()];

    if (bridged) {
      for (var i = bridged.length - 1; i >= 0; i--) {
        bridge_method(bridged[i], obj, jsid, body);
      }
    }
  }

  if (obj.$method_added && !obj.$method_added.$$stub) {
    obj.$method_added(jsid.substr(1));
  }

  var singleton_of = obj.$$singleton_of;
  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.

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

if (!obj.$$eval && (obj.$$is_class || obj.$$is_module))

if instance_eval is invoked on a module/class, it sets inst_eval_mod

if (!obj.$$eval && (obj.$$is_class || obj.$$is_module)) {

Opal.rdef = function(obj, jsid)

Called from #remove_method.

Opal.rdef = function(obj, jsid) {
  // TODO: remove from bridges 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)

instance_eval is being run on a class/module, so that need to alias class methods

if (obj.$$eval) {

Opal.hash2 = function(keys, smap)

hash2 is a faster 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.$$map  = {};
  hash.$$keys = keys;
  hash.$$smap = smap;

  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.exclude = exc;

  return range;
};

name === "constructor" ||

properties

name === "constructor" ||

name === "hasOwnProperty" ||

methods

name === "hasOwnProperty" ||

``

Require system


``

Initialization


boot_class_alloc('BasicObject', BasicObject_alloc)

Constructors for instances of core objects

boot_class_alloc('BasicObject', BasicObject_alloc);

BasicObject = boot_core_class_object('BasicObject', BasicObject_alloc, Class_alloc)

Constructors for classes of core objects

BasicObject = boot_core_class_object('BasicObject', BasicObject_alloc, Class_alloc);

BasicObject.$$class = Class

Fix booted classes to use their metaclass

BasicObject.$$class = Class;

BasicObject.$$super = null

Fix superclasses of booted classes

BasicObject.$$super = null;

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

Nil

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