(function(undefined) { if (typeof(this.Opal) !== 'undefined') { console.warn('Opal already loaded. Loading twice can cause troubles, please fix your setup.'); return this.Opal; } // The Opal object that is exposed globally var Opal = this.Opal = {}; // All bridged classes - keep track to donate methods from Object var bridged_classes = Opal.bridged_classes = []; // TopScope is used for inheriting constants from the top scope var TopScope = function(){}; // Opal just acts as the top scope TopScope.prototype = Opal; // To inherit scopes Opal.constructor = TopScope; // List top scope constants Opal.constants = []; // This is a useful reference to global object inside ruby files Opal.global = this; // Minify common function calls var $hasOwn = Opal.hasOwnProperty; var $slice = Opal.slice = Array.prototype.slice; // Generates unique id for every ruby object var unique_id = 0; // Return next unique id Opal.uid = function() { return unique_id++; }; // Table holds all class variables Opal.cvars = {}; // Globals table Opal.gvars = {}; // Get constants Opal.get = function(name) { var constant = this[name]; if (constant == null) { return this.base.$const_missing(name); } return constant; }; /* * 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. */ function create_scope(base, klass, id) { var const_alloc = function() {}; var const_scope = const_alloc.prototype = new base.constructor(); klass.$$scope = const_scope; klass.$$base_module = base.base; const_scope.base = klass; const_scope.constructor = const_alloc; const_scope.constants = []; if (id) { klass.$$orig_scope = base; base[id] = base.constructor[id] = klass; base.constants.push(id); } } Opal.create_scope = create_scope; /* * 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 [Object] base where the class is being created * @param [Class] superklass superclass of the new class (may be null) * @param [String] id the name of the class to be created * @param [Function] constructor function to use as constructor * @return [Class] new or existing ruby class */ Opal.klass = function(base, superklass, id, constructor) { // If base is an object, use its class if (!base.$$is_class) { base = base.$$class; } // Not specifying a superclass means we can assume it to be Object if (superklass === null) { superklass = ObjectClass; } var klass = base.$$scope[id]; // If a constant exists in the scope, then we must use that if ($hasOwn.call(base.$$scope, id) && 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 !== ObjectClass) { throw Opal.TypeError.$new("superclass mismatch for class " + id); } } else if (typeof(superklass) === 'function') { // passed native constructor as superklass, so bridge it as ruby class return bridge_class(id, superklass); } else { // if class doesnt exist, create a new one with given superclass klass = boot_class(superklass, constructor); // name class using base (e.g. Foo or Foo::Baz) klass.$$name = id; // every class gets its own constant scope, inherited from current scope create_scope(base.$$scope, klass, id); // Name new class directly onto current scope (Opal.Foo.Baz = klass) base[id] = base.$$scope[id] = klass; // Copy all parent constants to child, unless parent is Object if (superklass !== ObjectClass && superklass !== BasicObjectClass) { Opal.donate_constants(superklass, klass); } // call .inherited() hook with new class on the superclass if (superklass.$inherited) { superklass.$inherited(klass); } } return klass; }; // Create generic class with given superclass. function boot_class(superklass, constructor) { var alloc = boot_class_alloc(null, constructor, superklass) return boot_class_object(superklass, alloc); } // Make `boot_class` available to the JS-API Opal.boot = boot_class; /* * The class object itself (as in `Class.new`) * * @param [(Opal) Class] superklass Another class object (as in `Class.new`) * @param [constructor] alloc The constructor that holds the prototype * that will be used for instances of the * newly constructed class. */ function boot_class_object(superklass, alloc) { var singleton_class = function() {}; singleton_class.prototype = superklass.constructor.prototype; function OpalClass() {} OpalClass.prototype = new singleton_class(); var klass = new OpalClass(); setup_module_or_class_object(klass, OpalClass, 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; } /* * 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 `ModuleClass` 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 = unique_id++; // @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; // @property $$is_class Clearly mark this as a class-like module.$$is_class = true; // @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 $$methods keeps track of methods defined on the class // but seems to be used just by `define_basic_object_method` // and for donating (Ruby) Object methods to bridged classes // TODO: check if it can be removed module.$$methods = []; // @property $$inc included modules module.$$inc = []; } // Define new module (or return existing module) Opal.module = function(base, id) { var module; if (!base.$$is_class) { base = base.$$class; } if ($hasOwn.call(base.$$scope, id)) { module = base.$$scope[id]; if (!module.$$is_mod && module !== ObjectClass) { throw Opal.TypeError.$new(id + " is not a module"); } } else { module = boot_module_object(); module.$$name = id; 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; }; /* * 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 = ModuleClass.constructor.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, ModuleClass, module_prototype); module.$$is_mod = true; module.$$dep = []; return module; } /* * Get (or prepare) the singleton class for the passed object. * * @param object [Ruby Object] */ Opal.get_singleton_class = function(object) { if (object.$$meta) { return object.$$meta; } if (object.$$is_class) { return build_class_singleton_class(object); } return build_object_singleton_class(object); }; /* * 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; */ 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.$$inc = []; meta.$$methods = []; meta.$$scope = klass.$$scope; return klass.$$meta = meta; } /* * Build the singleton class for a Ruby (non class) Object. */ function build_object_singleton_class(object) { var orig_class = object.$$class, class_id = "#>"; var Singleton = function () {}; var meta = Opal.boot(orig_class, Singleton); meta.$$name = class_id; meta.$$proto = object; meta.$$class = orig_class.$$class; meta.$$scope = orig_class.$$scope; meta.$$parent = orig_class; return object.$$meta = meta; } /* * The actual inclusion of a module into a class. */ Opal.append_features = function(module, klass) { var included = klass.$$inc; // check if this module is already included in the klass for (var j = 0, jj = included.length; j < jj; j++) { if (included[j] === module) { return; } } included.push(module); module.$$dep.push(klass); // iclass var iclass = { $$name: module.$$name, $$proto: module.$$proto, $$parent: klass.$$parent, $$module: module, $$iclass: true }; klass.$$parent = iclass; var donator = module.$$proto, prototype = klass.$$proto, methods = module.$$methods; for (var i = 0, length = methods.length; i < length; i++) { var method = methods[i], current; if ( prototype.hasOwnProperty(method) && !(current = prototype[method]).$$donated && !current.$$stub ) { // 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 } else { prototype[method] = donator[method]; prototype[method].$$donated = true; } } if (klass.$$dep) { Opal.donate(klass, methods.slice(), true); } Opal.donate_constants(module, klass); }; // Boot a base class (makes instances). function boot_class_alloc(id, constructor, superklass) { if (superklass) { var ctor = function() {}; ctor.prototype = superklass.$$proto || superklass.prototype; if (id) { ctor.displayName = id; } constructor.prototype = new ctor(); } constructor.prototype.constructor = constructor; return constructor; } /* * 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 = "#"; // 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; // Give all instances a ref to their class alloc.prototype.$$class = klass; Opal[id] = klass; Opal.constants.push(id); return klass; } /* * 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. * * Bridged classes are tracked in `bridged_classes` array so that methods * defined on Object can be "donated" to all bridged classes. This allows * us to fake the inheritance of a native prototype from our Object * prototype. * * Example: * * bridge_class("Proc", Function); * * @param [String] name the name of the ruby class to create * @param [Function] constructor native javascript constructor to use * @return [Class] returns new ruby class */ function bridge_class(name, constructor) { var klass = boot_class_object(ObjectClass, constructor); klass.$$name = name; create_scope(Opal, klass, name); bridged_classes.push(klass); var object_methods = BasicObjectClass.$$methods.concat(ObjectClass.$$methods); for (var i = 0, len = object_methods.length; i < len; i++) { var meth = object_methods[i]; constructor.prototype[meth] = ObjectClass.$$proto[meth]; } add_stubs_subscriber(constructor.prototype); return klass; } /* * constant assign */ Opal.casgn = function(base_module, name, value) { var scope = base_module.$$scope; if (value.$$is_class && value.$$name === nil) { value.$$name = name; } if (value.$$is_class) { value.$$base_module = base_module; } scope.constants.push(name); return scope[name] = value; }; /* * constant decl */ Opal.cdecl = function(base_scope, name, value) { base_scope.constants.push(name); return base_scope[name] = value; }; /* * constant get */ Opal.cget = function(base_scope, path) { if (path == null) { path = base_scope; base_scope = Opal.Object; } var result = base_scope; path = path.split('::'); while (path.length !== 0) { result = result.$const_get(path.shift()); } return result; }; /* * When a source module is included into the target module, we must also copy * its constants to the target. */ Opal.donate_constants = function(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]]; } }; /* * 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 subscribers = Opal.stub_subscribers; var subscriber; for (var i = 0, length = stubs.length; i < length; i++) { var method_name = stubs[i], stub = stub_for(method_name); for (var j = 0; j < subscribers.length; j++) { subscriber = subscribers[j]; if (!(method_name in subscriber)) { subscriber[method_name] = stub; } } } }; /* * Add a prototype to the subscribers list, and (TODO) add previously stubbed * methods. * * @param [Prototype] */ function add_stubs_subscriber(prototype) { // TODO: Add previously stubbed methods too. Opal.stub_subscribers.push(prototype); } /* * Keep a list of prototypes that want method_missing stubs to be added. * * @default [Prototype List] BasicObject.prototype */ Opal.stub_subscribers = [BasicObject.prototype]; /* * 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") */ function add_stub_for(prototype, stub) { var method_missing_stub = stub_for(stub); prototype[stub] = method_missing_stub; } /* * 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; } // Expose for other parts of Opal to use Opal.add_stub_for = add_stub_for; // Arity count error dispatcher Opal.ac = function(actual, expected, object, meth) { var inspect = (object.$$is_class ? object.$$name + '.' : object.$$class.$$name + '#') + meth; var msg = '[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')'; throw Opal.ArgumentError.$new(msg); }; // Super dispatcher Opal.find_super_dispatcher = function(obj, jsid, current_func, iter, defs) { var dispatcher; if (defs) { dispatcher = obj.$$is_class ? defs.$$super : obj.$$class.$$proto; } else { if (obj.$$is_class) { dispatcher = obj.$$super; } else { dispatcher = find_obj_super_dispatcher(obj, jsid, current_func); } } dispatcher = dispatcher['$' + jsid]; dispatcher.$$p = iter; return dispatcher; }; // 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); } }; function find_obj_super_dispatcher(obj, jsid, current_func) { var klass = obj.$$meta || obj.$$class; jsid = '$' + jsid; while (klass) { if (klass.$$proto[jsid] === current_func) { // ok break; } klass = klass.$$parent; } // if we arent in a class, we couldnt find current? if (!klass) { throw new Error("could not find current class for super()"); } klass = klass.$$parent; // else, let's find the next one while (klass) { var working = klass.$$proto[jsid]; if (working && working !== current_func) { // ok break; } klass = klass.$$parent; } return klass.$$proto; }; /* * 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; }; // 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); } }; // 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); }; // 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; }; Opal.is_a = function(object, klass) { if (object.$$meta === klass) { return true; } var search = object.$$class; while (search) { if (search === klass) { return true; } for (var i = 0, length = search.$$inc.length; i < length; i++) { if (search.$$inc[i] == klass) { return true; } } search = search.$$super; } return false; }; // Helper to convert the given object to an array Opal.to_ary = function(value) { if (value.$$is_array) { return value; } else if (value.$to_ary && !value.$to_ary.$$stub) { return value.$to_ary(); } return [value]; }; /* * 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.block_send = function(recv, mid, block) { var args = $slice.call(arguments, 3), func = recv['$' + mid]; if (func) { func.$$p = block; return func.apply(recv, args); } return recv.$method_missing.apply(recv, [mid].concat(args)); }; /* * Donate methods for a class/module */ Opal.donate = function(klass, defined, indirect) { var methods = klass.$$methods, included_in = klass.$$dep; // if (!indirect) { klass.$$methods = methods.concat(defined); // } if (included_in) { for (var i = 0, length = included_in.length; i < length; i++) { var includee = included_in[i]; var dest = includee.$$proto; for (var j = 0, jj = defined.length; j < jj; j++) { var method = defined[j]; dest[method] = klass.$$proto[method]; dest[method].$$donated = true; } if (includee.$$dep) { Opal.donate(includee, defined, true); } } } }; Opal.defn = function(obj, jsid, body) { if (obj.$$is_mod) { obj.$$proto[jsid] = body; Opal.donate(obj, [jsid]); if (obj.$$module_function) { obj[jsid] = body; } } else if (obj.$$is_class) { obj.$$proto[jsid] = body; if (obj === BasicObjectClass) { define_basic_object_method(jsid, body); } else if (obj === ObjectClass) { Opal.donate(obj, [jsid]); } } else { obj[jsid] = body; } return nil; }; /* * Define a singleton method on the given object. */ Opal.defs = function(obj, jsid, body) { if (obj.$$is_class || obj.$$is_mod) { obj.constructor.prototype[jsid] = body; } else { obj[jsid] = body; } }; function define_basic_object_method(jsid, body) { BasicObjectClass.$$methods.push(jsid); for (var i = 0, len = bridged_classes.length; i < len; i++) { bridged_classes[i].$$proto[jsid] = body; } } Opal.hash = function() { if (arguments.length == 1 && arguments[0].$$class == Opal.Hash) { return arguments[0]; } var hash = new Opal.Hash.$$alloc(), keys = [], _map = {}, smap = {}, key, obj, length, khash; hash.map = _map; hash.smap = smap; hash.keys = keys; if (arguments.length == 1) { if (arguments[0].$$is_array) { var args = arguments[0]; for (var i = 0, ii = args.length; i < ii; i++) { var pair = args[i]; if (pair.length !== 2) { throw Opal.ArgumentError.$new("value not of length 2: " + pair.$inspect()); } key = pair[0]; obj = pair[1]; if (key.$$is_string) { khash = key; map = smap; } else { khash = key.$hash(); map = _map; } if (map[khash] == null) { keys.push(key); } map[khash] = obj; } } else { obj = arguments[0]; for (key in obj) { khash = key.$hash(); map[khash] = obj[khash]; keys.push(key); } } } else { length = arguments.length; if (length % 2 !== 0) { throw Opal.ArgumentError.$new("odd number of arguments for Hash"); } for (var j = 0; j < length; j++) { key = arguments[j]; obj = arguments[++j]; if (key.$$is_string) { khash = key; map = smap; } else { khash = key.$hash(); map = _map; } if (map[khash] == null) { keys.push(key); } map[khash] = obj; } } return hash; }; /* * 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, map) { var hash = new Opal.Hash.$$alloc(); hash.keys = keys; hash.map = {}; hash.smap = map; return hash; }; /* * 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; }; // Require system // -------------- (function(Opal) { var loaded_features = ['corelib/runtime.js'], require_table = {'corelib/runtime.js': true}, modules = {}; var current_dir = '.'; function mark_as_loaded(filename) { if (require_table[filename]) { return false; } loaded_features.push(filename); require_table[filename] = true; return true; } function normalize_loadable_path(path) { var parts, part, new_parts = [], SEPARATOR = '/'; if (current_dir !== '.') { path = current_dir.replace(/\/*$/, '/') + path; } parts = path.split(SEPARATOR); for (var i = 0, ii = parts.length; i < ii; i++) { part = parts[i]; if (part == '') continue; (part === '..') ? new_parts.pop() : new_parts.push(part) } return new_parts.join(SEPARATOR); } function load(path) { mark_as_loaded(path); var module = modules[path]; if (module) { module(Opal); } else { var severity = Opal.dynamic_require_severity || 'warning'; var message = 'cannot load such file -- ' + path; if (severity === "error") { Opal.LoadError ? Opal.LoadError.$new(message) : function(){throw message}(); } else if (severity === "warning") { console.warn('WARNING: LoadError: ' + message); } } return true; } function require(path) { if (require_table[path]) { return false; } return load(path); } Opal.modules = modules; Opal.loaded_features = loaded_features; Opal.normalize_loadable_path = normalize_loadable_path; Opal.mark_as_loaded = mark_as_loaded; Opal.load = load; Opal.require = require; })(Opal); // Initialization // -------------- // The actual class for BasicObject var BasicObjectClass; // The actual Object class var ObjectClass; // The actual Module class var ModuleClass; // The actual Class class var ClassClass; // Constructor for instances of BasicObject function BasicObject(){} // Constructor for instances of Object function Object(){} // Constructor for instances of Class function Class(){} // Constructor for instances of Module function Module(){} // Constructor for instances of NilClass (nil) function NilClass(){} // Constructors for *instances* of core objects boot_class_alloc('BasicObject', BasicObject); boot_class_alloc('Object', Object, BasicObject); boot_class_alloc('Module', Module, Object); boot_class_alloc('Class', Class, Module); // Constructors for *classes* of core objects BasicObjectClass = boot_core_class_object('BasicObject', BasicObject, Class); ObjectClass = boot_core_class_object('Object', Object, BasicObjectClass.constructor); ModuleClass = boot_core_class_object('Module', Module, ObjectClass.constructor); ClassClass = boot_core_class_object('Class', Class, ModuleClass.constructor); // Fix booted classes to use their metaclass BasicObjectClass.$$class = ClassClass; ObjectClass.$$class = ClassClass; ModuleClass.$$class = ClassClass; ClassClass.$$class = ClassClass; // Fix superclasses of booted classes BasicObjectClass.$$super = null; ObjectClass.$$super = BasicObjectClass; ModuleClass.$$super = ObjectClass; ClassClass.$$super = ModuleClass; BasicObjectClass.$$parent = null; ObjectClass.$$parent = BasicObjectClass; ModuleClass.$$parent = ObjectClass; ClassClass.$$parent = ModuleClass; // Internally, Object acts like a module as it is "included" into bridged // classes. In other words, we donate methods from Object into our bridged // classes as their prototypes don't inherit from our root Object, so they // act like module includes. ObjectClass.$$dep = bridged_classes; Opal.base = ObjectClass; BasicObjectClass.$$scope = ObjectClass.$$scope = Opal; BasicObjectClass.$$orig_scope = ObjectClass.$$orig_scope = Opal; Opal.Kernel = ObjectClass; ModuleClass.$$scope = ObjectClass.$$scope; ModuleClass.$$orig_scope = ObjectClass.$$orig_scope; ClassClass.$$scope = ObjectClass.$$scope; ClassClass.$$orig_scope = ObjectClass.$$orig_scope; ObjectClass.$$proto.toString = function() { return this.$to_s(); }; ObjectClass.$$proto.$require = Opal.require; Opal.top = new ObjectClass.$$alloc(); // Nil var nil_id = Opal.uid(); // nil id is traditionally 4 Opal.klass(ObjectClass, ObjectClass, 'NilClass', NilClass); var nil = Opal.nil = new NilClass(); nil.$$id = nil_id; nil.call = nil.apply = function() { throw Opal.LocalJumpError.$new('no block given'); }; Opal.breaker = new Error('unexpected break'); Opal.returner = new Error('unexpected return'); bridge_class('Array', Array); bridge_class('Boolean', Boolean); bridge_class('Numeric', Number); bridge_class('String', String); bridge_class('Proc', Function); bridge_class('Exception', Error); bridge_class('Regexp', RegExp); bridge_class('Time', Date); TypeError.$$super = Error; }).call(this); if (typeof(global) !== 'undefined') { global.Opal = this.Opal; Opal.global = global; } if (typeof(window) !== 'undefined') { window.Opal = this.Opal; Opal.global = window; }