opal 0.9.0.beta2 → 0.9.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/.jshintrc +2 -1
  3. data/.travis.yml +8 -4
  4. data/CHANGELOG.md +270 -251
  5. data/CONTRIBUTING.md +41 -0
  6. data/README.md +8 -8
  7. data/Rakefile +1 -1
  8. data/lib/opal/cli.rb +1 -0
  9. data/lib/opal/cli_options.rb +2 -2
  10. data/lib/opal/cli_runners.rb +1 -0
  11. data/lib/opal/cli_runners/nashorn.rb +58 -0
  12. data/lib/opal/cli_runners/phantom.js +11 -9
  13. data/lib/opal/compiler.rb +2 -0
  14. data/lib/opal/erb.rb +2 -1
  15. data/lib/opal/nodes/def.rb +15 -6
  16. data/lib/opal/nodes/helpers.rb +1 -1
  17. data/lib/opal/nodes/literal.rb +1 -1
  18. data/lib/opal/nodes/masgn.rb +79 -29
  19. data/lib/opal/nodes/module.rb +1 -1
  20. data/lib/opal/nodes/top.rb +6 -2
  21. data/lib/opal/parser.rb +1 -0
  22. data/lib/opal/parser/grammar.rb +3160 -3083
  23. data/lib/opal/parser/grammar.y +39 -11
  24. data/lib/opal/parser/lexer.rb +15 -13
  25. data/lib/opal/parser/sexp.rb +5 -0
  26. data/lib/opal/version.rb +1 -1
  27. data/opal/corelib/array.rb +21 -6
  28. data/opal/corelib/basic_object.rb +17 -4
  29. data/opal/corelib/class.rb +1 -1
  30. data/opal/corelib/constants.rb +2 -2
  31. data/opal/corelib/enumerator.rb +2 -0
  32. data/opal/corelib/hash.rb +50 -50
  33. data/opal/corelib/helpers.rb +1 -1
  34. data/opal/corelib/io.rb +9 -6
  35. data/opal/corelib/kernel.rb +37 -9
  36. data/opal/corelib/module.rb +6 -17
  37. data/opal/corelib/nil.rb +4 -0
  38. data/opal/corelib/number.rb +0 -4
  39. data/opal/corelib/runtime.js +637 -662
  40. data/opal/corelib/struct.rb +7 -3
  41. data/spec/filters/bugs/array.rb +4 -9
  42. data/spec/filters/bugs/basicobject.rb +1 -15
  43. data/spec/filters/bugs/date.rb +4 -26
  44. data/spec/filters/bugs/enumerable.rb +26 -1
  45. data/spec/filters/bugs/enumerator.rb +4 -4
  46. data/spec/filters/bugs/exception.rb +1 -7
  47. data/spec/filters/bugs/float.rb +14 -0
  48. data/spec/filters/bugs/hash.rb +0 -2
  49. data/spec/filters/bugs/integer.rb +1 -1
  50. data/spec/filters/bugs/kernel.rb +47 -66
  51. data/spec/filters/bugs/language.rb +1 -2
  52. data/spec/filters/bugs/module.rb +11 -14
  53. data/spec/filters/bugs/numeric.rb +3 -3
  54. data/spec/filters/bugs/proc.rb +0 -1
  55. data/spec/filters/bugs/range.rb +2 -3
  56. data/spec/filters/bugs/regexp.rb +15 -17
  57. data/spec/filters/bugs/set.rb +2 -2
  58. data/spec/filters/bugs/string.rb +29 -5
  59. data/spec/filters/bugs/{strscan.rb → stringscanner.rb} +9 -10
  60. data/spec/filters/bugs/struct.rb +0 -4
  61. data/spec/filters/bugs/time.rb +2 -3
  62. data/spec/filters/bugs/unboundmethod.rb +3 -0
  63. data/spec/filters/unsupported/freeze.rb +2 -1
  64. data/spec/filters/unsupported/taint.rb +2 -0
  65. data/spec/lib/parser/aref_spec.rb +10 -0
  66. data/spec/lib/parser/lambda_spec.rb +14 -0
  67. data/spec/lib/parser/op_asgn_spec.rb +17 -0
  68. data/spec/lib/parser/return_spec.rb +5 -0
  69. data/spec/lib/parser/unary_spec.rb +4 -0
  70. data/spec/lib/sprockets/erb_spec.rb +1 -1
  71. data/spec/mspec/opal/formatters.rb +159 -0
  72. data/{lib → spec}/mspec/opal/runner.rb +0 -160
  73. data/spec/opal/core/hash/internals_spec.rb +162 -162
  74. data/spec/opal/core/kernel/at_exit_spec.rb +70 -0
  75. data/spec/opal/core/kernel/extend_spec.rb +1 -1
  76. data/spec/opal/core/kernel/instance_variables_spec.rb +56 -0
  77. data/spec/opal/core/language/equal_spec.rb +8 -0
  78. data/spec/opal/core/language/predefined_spec.rb +1 -1
  79. data/spec/opal/core/language/ternary_operator_spec.rb +14 -0
  80. data/spec/opal/core/language/versions/{hash_1.9.rb → hash_1_9_spec.rb} +5 -0
  81. data/spec/opal/core/module/fixtures/classes.rb +11 -1
  82. data/spec/opal/core/module/method_lookup_spec.rb +13 -0
  83. data/spec/opal/core/runtime/super_spec.rb +10 -0
  84. data/spec/opal/stdlib/native/new_spec.rb +84 -0
  85. data/spec/opal/stdlib/strscan/scan_spec.rb +11 -0
  86. data/spec/rubyspecs +6 -9
  87. data/spec/spec_helper.rb +9 -21
  88. data/stdlib/date.rb +121 -1
  89. data/stdlib/js.rb +13 -5
  90. data/stdlib/json.rb +3 -3
  91. data/stdlib/nashorn.rb +5 -0
  92. data/stdlib/nashorn/file.rb +13 -0
  93. data/stdlib/nashorn/io.rb +2 -0
  94. data/stdlib/native.rb +12 -4
  95. data/stdlib/nodejs/io.rb +5 -2
  96. data/stdlib/opal/platform.rb +19 -0
  97. data/stdlib/phantomjs.rb +4 -0
  98. data/stdlib/strscan.rb +1 -1
  99. data/tasks/building.rake +2 -1
  100. data/tasks/testing.rake +29 -34
  101. data/tasks/testing/{phantomjs1-sprockets.js → sprockets-phantomjs.js} +2 -20
  102. data/vendored-minitest/minitest/test.rb +7 -15
  103. metadata +32 -9
  104. data/lib/mspec/opal/main.rb.erb +0 -9
@@ -112,5 +112,5 @@ module Opal
112
112
  end
113
113
 
114
114
  name
115
- end
115
+ end
116
116
  end
data/opal/corelib/io.rb CHANGED
@@ -18,7 +18,11 @@ class IO
18
18
  string.size
19
19
  end
20
20
 
21
- attr_accessor :sync
21
+ attr_accessor :sync, :tty
22
+
23
+ def flush
24
+ # noop
25
+ end
22
26
 
23
27
  module Writable
24
28
  def <<(string)
@@ -65,9 +69,8 @@ STDERR = $stderr = IO.new
65
69
  STDIN = $stdin = IO.new
66
70
  STDOUT = $stdout = IO.new
67
71
 
72
+ STDOUT.write_proc = `typeof(process) === 'object' ? function(s){process.stdout.write(s)} : function(s){console.log(s)}`
73
+ STDERR.write_proc = `typeof(process) === 'object' ? function(s){process.stderr.write(s)} : function(s){console.warn(s)}`
68
74
 
69
- $stdout.write_proc = `typeof(process) === 'object' ? function(s){process.stdout.write(s)} : function(s){console.log(s)}`
70
- $stderr.write_proc = `typeof(process) === 'object' ? function(s){process.stderr.write(s)} : function(s){console.warn(s)}`
71
-
72
- $stdout.extend(IO::Writable)
73
- $stderr.extend(IO::Writable)
75
+ STDOUT.extend(IO::Writable)
76
+ STDERR.extend(IO::Writable)
@@ -105,7 +105,7 @@ module Kernel
105
105
  def copy_instance_variables(other)
106
106
  %x{
107
107
  for (var name in other) {
108
- if (name.charAt(0) !== '$') {
108
+ if (other.hasOwnProperty(name) && name.charAt(0) !== '$') {
109
109
  self[name] = other[name];
110
110
  }
111
111
  }
@@ -177,7 +177,12 @@ module Kernel
177
177
  end
178
178
 
179
179
  def exit(status = true)
180
- $__at_exit__.reverse.each(&:call) if $__at_exit__
180
+ $__at_exit__ ||= []
181
+ loop do
182
+ block = $__at_exit__.pop
183
+ block ? block.call : break
184
+ end
185
+
181
186
  status = 0 if `status === true` # it's in JS because it can be null/undef
182
187
  `Opal.exit(status);`
183
188
  nil
@@ -190,6 +195,10 @@ module Kernel
190
195
  for (var i = mods.length - 1; i >= 0; i--) {
191
196
  var mod = mods[i];
192
197
 
198
+ if (!mod.$$is_module) {
199
+ #{raise TypeError, "wrong argument type #{`mod`.class} (expected Module)"};
200
+ }
201
+
193
202
  #{`mod`.append_features `singleton`};
194
203
  #{`mod`.extended self};
195
204
  }
@@ -740,7 +749,7 @@ module Kernel
740
749
  end
741
750
 
742
751
  def hash
743
- "#{self.class}:#{self.class.__id__}:#{__id__}"
752
+ __id__
744
753
  end
745
754
 
746
755
  def initialize_copy(other)
@@ -770,7 +779,7 @@ module Kernel
770
779
  name = Opal.instance_variable_name!(name)
771
780
 
772
781
  %x{
773
- var ivar = self[name.substr(1)];
782
+ var ivar = self[Opal.ivar(name.substr(1))];
774
783
 
775
784
  return ivar == null ? nil : ivar;
776
785
  }
@@ -779,18 +788,37 @@ module Kernel
779
788
  def instance_variable_set(name, value)
780
789
  name = Opal.instance_variable_name!(name)
781
790
 
782
- `self[name.substr(1)] = value`
791
+ `self[Opal.ivar(name.substr(1))] = value`
792
+ end
793
+
794
+ def remove_instance_variable(name)
795
+ name = Opal.instance_variable_name!(name)
796
+
797
+ %x{
798
+ var key = Opal.ivar(name.substr(1)),
799
+ val;
800
+ if (self.hasOwnProperty(key)) {
801
+ val = self[key];
802
+ delete self[key];
803
+ return val;
804
+ }
805
+ }
806
+
807
+ raise NameError, "instance variable #{name} not defined"
783
808
  end
784
809
 
785
810
  def instance_variables
786
811
  %x{
787
- var result = [];
812
+ var result = [], ivar;
788
813
 
789
814
  for (var name in self) {
790
- if (name.charAt(0) !== '$') {
791
- if (name !== '$$class' && name !== '$$id') {
792
- result.push('@' + name);
815
+ if (self.hasOwnProperty(name) && name.charAt(0) !== '$') {
816
+ if (name.substr(-1) === '$') {
817
+ ivar = name.slice(0, name.length - 1);
818
+ } else {
819
+ ivar = name;
793
820
  }
821
+ result.push('@' + ivar);
794
822
  }
795
823
  }
796
824
 
@@ -1,8 +1,7 @@
1
1
  class Module
2
2
  def self.new(&block)
3
3
  %x{
4
- function AnonModule(){}
5
- var klass = Opal.boot(Opal.Module, AnonModule);
4
+ var klass = Opal.boot_module_object();
6
5
  klass.$$name = nil;
7
6
  klass.$$class = Opal.Module;
8
7
  klass.$$dep = []
@@ -67,21 +66,7 @@ class Module
67
66
  end
68
67
 
69
68
  def ancestors
70
- %x{
71
- var parent = self,
72
- result = [];
73
-
74
- while (parent) {
75
- result.push(parent);
76
- for (var i=0; i < parent.$$inc.length; i++) {
77
- result = result.concat(parent.$$inc[i].$ancestors());
78
- }
79
-
80
- parent = parent.$$is_class ? parent.$$super : null;
81
- }
82
-
83
- return result;
84
- }
69
+ `Opal.ancestors(self)`
85
70
  end
86
71
 
87
72
  def append_features(klass)
@@ -347,6 +332,10 @@ class Module
347
332
  continue;
348
333
  }
349
334
 
335
+ if (!mod.$$is_module) {
336
+ #{raise TypeError, "wrong argument type #{`mod`.class} (expected Module)"};
337
+ }
338
+
350
339
  #{`mod`.append_features self};
351
340
  #{`mod`.included self};
352
341
  }
data/opal/corelib/nil.rb CHANGED
@@ -71,6 +71,10 @@ class NilClass
71
71
  def to_r
72
72
  Rational(0, 1)
73
73
  end
74
+
75
+ def instance_variables
76
+ []
77
+ end
74
78
  end
75
79
 
76
80
  NIL = nil
@@ -392,10 +392,6 @@ class Number < Numeric
392
392
  [gcd, lcm]
393
393
  end
394
394
 
395
- def hash
396
- `'Numeric:'+self.toString()`
397
- end
398
-
399
395
  def integer?
400
396
  `self % 1 === 0`
401
397
  end
@@ -4,6 +4,36 @@
4
4
  return this.Opal;
5
5
  }
6
6
 
7
+ var nil;
8
+
9
+ // The actual class for BasicObject
10
+ var BasicObject;
11
+
12
+ // The actual Object class.
13
+ // The leading underscore is to avoid confusion with window.Object()
14
+ var _Object;
15
+
16
+ // The actual Module class
17
+ var Module;
18
+
19
+ // The actual Class class
20
+ var Class;
21
+
22
+ // Constructor for instances of BasicObject
23
+ function BasicObject_alloc(){}
24
+
25
+ // Constructor for instances of Object
26
+ function Object_alloc(){}
27
+
28
+ // Constructor for instances of Class
29
+ function Class_alloc(){}
30
+
31
+ // Constructor for instances of Module
32
+ function Module_alloc(){}
33
+
34
+ // Constructor for instances of NilClass (nil)
35
+ function NilClass_alloc(){}
36
+
7
37
  // The Opal object that is exposed globally
8
38
  var Opal = this.Opal = {};
9
39
 
@@ -51,26 +81,25 @@
51
81
  // Exit function, this should be replaced by platform specific implementation
52
82
  // (See nodejs and phantom for examples)
53
83
  Opal.exit = function(status) { if (Opal.gvars.DEBUG) console.log('Exited with status '+status); };
54
-
84
+
55
85
  // keeps track of exceptions for $!
56
86
  Opal.exceptions = [];
57
87
 
58
- /**
59
- Get a constant on the given scope. Every class and module in Opal has a
60
- scope used to store, and inherit, constants. For example, the top level
61
- `Object` in ruby has a scope accessible as `Opal.Object.$$scope`.
62
-
63
- To get the `Array` class using this scope, you could use:
64
-
65
- Opal.Object.$$scope.get("Array")
66
-
67
- If a constant with the given name cannot be found, then a dispatch to the
68
- class/module's `#const_method` is called, which by default will raise an
69
- error.
70
-
71
- @param [String] name the name of the constant to lookup
72
- @returns [RubyObject]
73
- */
88
+ // Get a constant on the given scope. Every class and module in Opal has a
89
+ // scope used to store, and inherit, constants. For example, the top level
90
+ // `Object` in ruby has a scope accessible as `Opal.Object.$$scope`.
91
+ //
92
+ // To get the `Array` class using this scope, you could use:
93
+ //
94
+ // Opal.Object.$$scope.get("Array")
95
+ //
96
+ // If a constant with the given name cannot be found, then a dispatch to the
97
+ // class/module's `#const_method` is called, which by default will raise an
98
+ // error.
99
+ //
100
+ // @param [String] name the name of the constant to lookup
101
+ // @return [RubyObject]
102
+ //
74
103
  Opal.get = function(name) {
75
104
  var constant = this[name];
76
105
 
@@ -81,12 +110,11 @@
81
110
  return constant;
82
111
  };
83
112
 
84
- /*
85
- * Create a new constants scope for the given class with the given
86
- * base. Constants are looked up through their parents, so the base
87
- * scope will be the outer scope of the new klass.
88
- */
89
- function create_scope(base, klass, id) {
113
+ // Create a new constants scope for the given class with the given
114
+ // base. Constants are looked up through their parents, so the base
115
+ // scope will be the outer scope of the new klass.
116
+ //
117
+ Opal.create_scope = function(base, klass, id) {
90
118
  var const_alloc = function() {};
91
119
  var const_scope = const_alloc.prototype = new base.constructor();
92
120
 
@@ -98,45 +126,51 @@
98
126
  const_scope.constants = [];
99
127
 
100
128
  if (id) {
101
- Opal.cdecl(base, id, klass)
129
+ Opal.cdecl(base, id, klass);
130
+ const_alloc.displayName = id+"_alloc";
102
131
  }
103
132
  }
104
133
 
105
- Opal.create_scope = create_scope;
106
-
107
- /*
108
- * A `class Foo; end` expression in ruby is compiled to call this runtime
109
- * method which either returns an existing class of the given name, or creates
110
- * a new class in the given `base` scope.
111
- *
112
- * If a constant with the given name exists, then we check to make sure that
113
- * it is a class and also that the superclasses match. If either of these
114
- * fail, then we raise a `TypeError`. Note, superklass may be null if one was
115
- * not specified in the ruby code.
116
- *
117
- * We pass a constructor to this method of the form `function ClassName() {}`
118
- * simply so that classes show up with nicely formatted names inside debuggers
119
- * in the web browser (or node/sprockets).
120
- *
121
- * The `base` is the current `self` value where the class is being created
122
- * from. We use this to get the scope for where the class should be created.
123
- * If `base` is an object (not a class/module), we simple get its class and
124
- * use that as the base instead.
125
- *
126
- * @param [Object] base where the class is being created
127
- * @param [Class] superklass superclass of the new class (may be null)
128
- * @param [String] id the name of the class to be created
129
- * @param [Function] constructor function to use as constructor
130
- * @return [Class] new or existing ruby class
131
- */
134
+ // A `class Foo; end` expression in ruby is compiled to call this runtime
135
+ // method which either returns an existing class of the given name, or creates
136
+ // a new class in the given `base` scope.
137
+ //
138
+ // If a constant with the given name exists, then we check to make sure that
139
+ // it is a class and also that the superclasses match. If either of these
140
+ // fail, then we raise a `TypeError`. Note, superklass may be null if one was
141
+ // not specified in the ruby code.
142
+ //
143
+ // We pass a constructor to this method of the form `function ClassName() {}`
144
+ // simply so that classes show up with nicely formatted names inside debuggers
145
+ // in the web browser (or node/sprockets).
146
+ //
147
+ // The `base` is the current `self` value where the class is being created
148
+ // from. We use this to get the scope for where the class should be created.
149
+ // If `base` is an object (not a class/module), we simple get its class and
150
+ // use that as the base instead.
151
+ //
152
+ // @param [Object] base where the class is being created
153
+ // @param [Class] superklass superclass of the new class (may be null)
154
+ // @param [String] id the name of the class to be created
155
+ // @param [Function] constructor function to use as constructor
156
+ // @return [Class] new or existing ruby class
157
+ //
132
158
  Opal.klass = function(base, superklass, id, constructor) {
159
+ var klass, bridged, alloc;
160
+
133
161
  // If base is an object, use its class
134
162
  if (!base.$$is_class && !base.$$is_module) {
135
163
  base = base.$$class;
136
164
  }
137
165
 
138
- var klass = base.$$scope[id],
139
- bridged = typeof(superklass) === 'function';
166
+ // If the superclass is a function then we're bridging a native JS class
167
+ if (typeof(superklass) === 'function') {
168
+ bridged = superklass;
169
+ superklass = _Object;
170
+ }
171
+
172
+ // Try to find the class in the current scope
173
+ klass = base.$$scope[id];
140
174
 
141
175
  // If the class exists in the scope, then we must use that
142
176
  if (klass && klass.$$orig_scope === base.$$scope) {
@@ -153,38 +187,42 @@
153
187
  return klass;
154
188
  }
155
189
 
190
+ // Class doesnt exist, create a new one with given superclass...
191
+
156
192
  // Not specifying a superclass means we can assume it to be Object
157
- if (superklass === null) {
158
- superklass = ObjectClass;
193
+ if (superklass == null) {
194
+ superklass = _Object;
159
195
  }
160
196
 
161
- // if class doesnt exist, create a new one with given superclass
162
- klass = bridged ?
163
- boot_class_object(ObjectClass, superklass) :
164
- boot_class(superklass, constructor);
197
+ // If bridged the JS class will also be the alloc function
198
+ alloc = bridged || boot_class_alloc(id, constructor, superklass);
165
199
 
166
- // name class using base (e.g. Foo or Foo::Baz)
200
+ // Create the class object (instance of Class)
201
+ klass = boot_class_object(id, superklass, alloc);
202
+
203
+ // Name the class
167
204
  klass.$$name = id;
205
+ klass.displayName = id;
168
206
 
169
- // mark the object as a class
207
+ // Mark the object as a class
170
208
  klass.$$is_class = true;
171
209
 
172
- // every class gets its own constant scope, inherited from current scope
173
- create_scope(base.$$scope, klass, id);
210
+ // Every class gets its own constant scope, inherited from current scope
211
+ Opal.create_scope(base.$$scope, klass, id);
174
212
 
175
213
  // Name new class directly onto current scope (Opal.Foo.Baz = klass)
176
214
  base[id] = base.$$scope[id] = klass;
177
215
 
178
216
  if (bridged) {
179
- Opal.bridge(klass, superklass);
217
+ Opal.bridge(klass, alloc);
180
218
  }
181
219
  else {
182
220
  // Copy all parent constants to child, unless parent is Object
183
- if (superklass !== ObjectClass && superklass !== BasicObjectClass) {
221
+ if (superklass !== _Object && superklass !== BasicObject) {
184
222
  donate_constants(superklass, klass);
185
223
  }
186
224
 
187
- // call .inherited() hook with new class on the superclass
225
+ // Call .inherited() hook with new class on the superclass
188
226
  if (superklass.$inherited) {
189
227
  superklass.$inherited(klass);
190
228
  }
@@ -194,33 +232,34 @@
194
232
  };
195
233
 
196
234
  // Create generic class with given superclass.
197
- function boot_class(superklass, constructor) {
235
+ Opal.boot_class = function(superklass, constructor) {
198
236
  var alloc = boot_class_alloc(null, constructor, superklass)
199
237
 
200
- return boot_class_object(superklass, alloc);
238
+ return boot_class_object(null, superklass, alloc);
201
239
  }
202
240
 
203
- // Make `boot_class` available to the JS-API
204
- Opal.boot = boot_class;
205
-
206
- /*
207
- * The class object itself (as in `Class.new`)
208
- *
209
- * @param [(Opal) Class] superklass Another class object (as in `Class.new`)
210
- * @param [constructor] alloc The constructor that holds the prototype
211
- * that will be used for instances of the
212
- * newly constructed class.
213
- */
214
- function boot_class_object(superklass, alloc) {
215
- var singleton_class = function() {};
216
- singleton_class.prototype = superklass.constructor.prototype;
241
+ // The class object itself (as in `Class.new`)
242
+ //
243
+ // @param superklass [(Opal) Class] Another class object (as in `Class.new`)
244
+ // @param alloc [constructor] The constructor that holds the prototype
245
+ // that will be used for instances of the
246
+ // newly constructed class.
247
+ function boot_class_object(id, superklass, alloc) {
248
+ // Grab the superclass prototype and use it to build an intermediary object
249
+ // in the prototype chain.
250
+ function Superclass_alloc_proxy() {};
251
+ Superclass_alloc_proxy.prototype = superklass.constructor.prototype;
252
+ function SingletonClass_alloc() {}
253
+ SingletonClass_alloc.prototype = new Superclass_alloc_proxy();
217
254
 
218
- function OpalClass() {}
219
- OpalClass.prototype = new singleton_class();
255
+ if (id) {
256
+ SingletonClass_alloc.displayName = "SingletonClass_alloc("+id+")";
257
+ }
220
258
 
221
- var klass = new OpalClass();
259
+ // The built class is the only instance of its singleton_class
260
+ var klass = new SingletonClass_alloc();
222
261
 
223
- setup_module_or_class_object(klass, OpalClass, superklass, alloc.prototype);
262
+ setup_module_or_class_object(klass, SingletonClass_alloc, superklass, alloc.prototype);
224
263
 
225
264
  // @property $$alloc This is the constructor of instances of the current
226
265
  // class. Its prototype will be used for method lookup
@@ -233,22 +272,21 @@
233
272
  return klass;
234
273
  }
235
274
 
236
- /*
237
- * Adds common/required properties to a module or class object
238
- * (as in `Module.new` / `Class.new`)
239
- *
240
- * @param module The module or class that needs to be prepared
241
- *
242
- * @param constructor The constructor of the module or class itself,
243
- * usually it's already assigned by using `new`. Some
244
- * ipothesis on why it's needed can be found below.
245
- *
246
- * @param superklass The superclass of the class/module object, for modules
247
- * is `Module` (of `ModuleClass` in JS context)
248
- *
249
- * @param prototype The prototype on which the class/module methods will
250
- * be stored.
251
- */
275
+ // Adds common/required properties to a module or class object
276
+ // (as in `Module.new` / `Class.new`)
277
+ //
278
+ // @param module The module or class that needs to be prepared
279
+ //
280
+ // @param constructor The constructor of the module or class itself,
281
+ // usually it's already assigned by using `new`. Some
282
+ // ipothesis on why it's needed can be found below.
283
+ //
284
+ // @param superklass The superclass of the class/module object, for modules
285
+ // is `Module` (of `Module` in JS context)
286
+ //
287
+ // @param prototype The prototype on which the class/module methods will
288
+ // be stored.
289
+ //
252
290
  function setup_module_or_class_object(module, constructor, superklass, prototype) {
253
291
  // @property $$id Each class is assigned a unique `id` that helps
254
292
  // comparation and implementation of `#object_id`
@@ -265,15 +303,15 @@
265
303
  // Maybe there are some browsers not abiding (IE6?)
266
304
  module.constructor = constructor;
267
305
 
268
- if (superklass === ModuleClass) {
306
+ if (superklass === Module) {
269
307
  // @property $$is_module Clearly mark this as a module
270
308
  module.$$is_module = true;
271
- module.$$class = ModuleClass;
309
+ module.$$class = Module;
272
310
  }
273
311
  else {
274
312
  // @property $$is_class Clearly mark this as a class
275
313
  module.$$is_class = true;
276
- module.$$class = ClassClass;
314
+ module.$$class = Class;
277
315
  }
278
316
 
279
317
  // @property $$super the superclass, doesn't get changed by module inclusions
@@ -288,26 +326,25 @@
288
326
  module.$$inc = [];
289
327
  }
290
328
 
291
- /**
292
- Define new module (or return existing module). The given `base` is basically
293
- the current `self` value the `module` statement was defined in. If this is
294
- a ruby module or class, then it is used, otherwise if the base is a ruby
295
- object then that objects real ruby class is used (e.g. if the base is the
296
- main object, then the top level `Object` class is used as the base).
297
-
298
- If a module of the given name is already defined in the base, then that
299
- instance is just returned.
300
-
301
- If there is a class of the given name in the base, then an error is
302
- generated instead (cannot have a class and module of same name in same base).
303
-
304
- Otherwise, a new module is created in the base with the given name, and that
305
- new instance is returned back (to be referenced at runtime).
306
-
307
- @param [RubyModule or Class] base class or module this definition is inside
308
- @param [String] id the name of the new (or existing) module
309
- @returns [RubyModule]
310
- */
329
+ // Define new module (or return existing module). The given `base` is basically
330
+ // the current `self` value the `module` statement was defined in. If this is
331
+ // a ruby module or class, then it is used, otherwise if the base is a ruby
332
+ // object then that objects real ruby class is used (e.g. if the base is the
333
+ // main object, then the top level `Object` class is used as the base).
334
+ //
335
+ // If a module of the given name is already defined in the base, then that
336
+ // instance is just returned.
337
+ //
338
+ // If there is a class of the given name in the base, then an error is
339
+ // generated instead (cannot have a class and module of same name in same base).
340
+ //
341
+ // Otherwise, a new module is created in the base with the given name, and that
342
+ // new instance is returned back (to be referenced at runtime).
343
+ //
344
+ // @param [RubyModule or Class] base class or module this definition is inside
345
+ // @param [String] id the name of the new (or existing) module
346
+ // @return [RubyModule]
347
+ //
311
348
  Opal.module = function(base, id) {
312
349
  var module;
313
350
 
@@ -318,7 +355,7 @@
318
355
  if ($hasOwn.call(base.$$scope, id)) {
319
356
  module = base.$$scope[id];
320
357
 
321
- if (!module.$$is_module && module !== ObjectClass) {
358
+ if (!module.$$is_module && module !== _Object) {
322
359
  throw Opal.TypeError.$new(id + " is not a module");
323
360
  }
324
361
  }
@@ -334,7 +371,7 @@
334
371
  // initialize dependency tracking
335
372
  module.$$dep = [];
336
373
 
337
- create_scope(base.$$scope, module, id);
374
+ Opal.create_scope(base.$$scope, module, id);
338
375
 
339
376
  // Name new module directly onto current scope (Opal.Foo.Baz = module)
340
377
  base[id] = base.$$scope[id] = module;
@@ -343,13 +380,12 @@
343
380
  return module;
344
381
  };
345
382
 
346
- /*
347
- * Internal function to create a new module instance. This simply sets up
348
- * the prototype hierarchy and method tables.
349
- */
383
+ // Internal function to create a new module instance. This simply sets up
384
+ // the prototype hierarchy and method tables.
385
+ //
350
386
  function boot_module_object() {
351
387
  var mtor = function() {};
352
- mtor.prototype = ModuleClass.constructor.prototype;
388
+ mtor.prototype = Module_alloc.prototype;
353
389
 
354
390
  function module_constructor() {}
355
391
  module_constructor.prototype = new mtor();
@@ -357,24 +393,26 @@
357
393
  var module = new module_constructor();
358
394
  var module_prototype = {};
359
395
 
360
- setup_module_or_class_object(module, module_constructor, ModuleClass, module_prototype);
396
+ setup_module_or_class_object(module, module_constructor, Module, module_prototype);
361
397
 
362
398
  return module;
363
399
  }
364
400
 
365
- /**
366
- Return the singleton class for the passed object.
367
-
368
- If the given object alredy has a singleton class, then it will be stored on
369
- the object as the `$$meta` property. If this exists, then it is simply
370
- returned back.
371
-
372
- Otherwise, a new singleton object for the class or object is created, set on
373
- the object at `$$meta` for future use, and then returned.
374
-
375
- @param [RubyObject] object the ruby object
376
- @returns [RubyClass] the singleton class for object
377
- */
401
+ // Make `boot_module_object` available to the JS-API
402
+ Opal.boot_module_object = boot_module_object;
403
+
404
+ // Return the singleton class for the passed object.
405
+ //
406
+ // If the given object alredy has a singleton class, then it will be stored on
407
+ // the object as the `$$meta` property. If this exists, then it is simply
408
+ // returned back.
409
+ //
410
+ // Otherwise, a new singleton object for the class or object is created, set on
411
+ // the object at `$$meta` for future use, and then returned.
412
+ //
413
+ // @param [RubyObject] object the ruby object
414
+ // @return [RubyClass] the singleton class for object
415
+ //
378
416
  Opal.get_singleton_class = function(object) {
379
417
  if (object.$$meta) {
380
418
  return object.$$meta;
@@ -387,15 +425,14 @@
387
425
  return build_object_singleton_class(object);
388
426
  };
389
427
 
390
- /**
391
- Build the singleton class for an existing class.
392
-
393
- NOTE: Actually in MRI a class' singleton class inherits from its
394
- superclass' singleton class which in turn inherits from Class.
395
-
396
- @param [RubyClass] klass
397
- @returns [RubyClass]
398
- */
428
+ // Build the singleton class for an existing class.
429
+ //
430
+ // NOTE: Actually in MRI a class' singleton class inherits from its
431
+ // superclass' singleton class which in turn inherits from Class.
432
+ //
433
+ // @param [RubyClass] klass
434
+ // @return [RubyClass]
435
+ //
399
436
  function build_class_singleton_class(klass) {
400
437
  var meta = new Opal.Class.$$alloc();
401
438
 
@@ -410,18 +447,17 @@
410
447
  return klass.$$meta = meta;
411
448
  }
412
449
 
413
- /**
414
- Build the singleton class for a Ruby (non class) Object.
415
-
416
- @param [RubyObject] object
417
- @returns [RubyClass]
418
- */
450
+ // Build the singleton class for a Ruby (non class) Object.
451
+ //
452
+ // @param [RubyObject] object
453
+ // @return [RubyClass]
454
+ //
419
455
  function build_object_singleton_class(object) {
420
456
  var orig_class = object.$$class,
421
457
  class_id = "#<Class:#<" + orig_class.$$name + ":" + orig_class.$$id + ">>";
422
458
 
423
- var Singleton = function () {};
424
- var meta = Opal.boot(orig_class, Singleton);
459
+ var Singleton = function() {};
460
+ var meta = Opal.boot_class(orig_class, Singleton);
425
461
  meta.$$name = class_id;
426
462
 
427
463
  meta.$$proto = object;
@@ -434,109 +470,85 @@
434
470
  return object.$$meta = meta;
435
471
  }
436
472
 
437
- /**
438
- The actual inclusion of a module into a class.
439
-
440
- ## Class `$$parent` and `iclass`
441
-
442
- To handle `super` calls, every class has a `$$parent`. This parent is
443
- used to resolve the next class for a super call. A normal class would
444
- have this point to its superclass. However, if a class includes a module
445
- then this would need to take into account the module. The module would
446
- also have to then point its `$$parent` to the actual superclass. We
447
- cannot modify modules like this, because it might be included in more
448
- then one class. To fix this, we actually insert an `iclass` as the class'
449
- `$$parent` which can then point to the superclass. The `iclass` acts as
450
- a proxy to the actual module, so the `super` chain can then search it for
451
- the required method.
452
-
453
- @param [RubyModule] module the module to include
454
- @param [RubyClass] klass the target class to include module into
455
- @returns [null]
456
- */
457
- function bridge() {
458
- var target, donator, from, name, body, ancestors, id, methods, method, i, ancestor, bridged, length;
459
-
460
- if (arguments.length === 4) {
461
- target = arguments[0];
462
- from = arguments[1];
463
- name = arguments[2];
464
- body = arguments[3];
465
- ancestors = target.$$bridge.$ancestors();
466
-
467
- // order important here, we have to check for method presence in
468
- // ancestors from the bridged class to the last ancestor
469
- for (i = 0, length = ancestors.length; i < length; i++) {
470
- ancestor = ancestors[i];
471
-
472
- if ($hasOwn.call(ancestor.$$proto, name) &&
473
- ancestor.$$proto[name] &&
474
- !ancestor.$$proto[name].$$donated &&
475
- !ancestor.$$proto[name].$$stub &&
476
- ancestor !== from) {
477
- break;
478
- }
473
+ // Bridges a single method.
474
+ function bridge_method(target, from, name, body) {
475
+ var ancestors, i, ancestor, length;
479
476
 
480
- if (ancestor === from) {
481
- target.prototype[name] = body
482
- break;
483
- }
477
+ ancestors = target.$$bridge.$ancestors();
478
+
479
+ // order important here, we have to check for method presence in
480
+ // ancestors from the bridged class to the last ancestor
481
+ for (i = 0, length = ancestors.length; i < length; i++) {
482
+ ancestor = ancestors[i];
483
+
484
+ if ($hasOwn.call(ancestor.$$proto, name) &&
485
+ ancestor.$$proto[name] &&
486
+ !ancestor.$$proto[name].$$donated &&
487
+ !ancestor.$$proto[name].$$stub &&
488
+ ancestor !== from) {
489
+ break;
490
+ }
491
+
492
+ if (ancestor === from) {
493
+ target.prototype[name] = body
494
+ break;
484
495
  }
485
496
  }
486
- else {
487
- target = arguments[0];
488
- donator = arguments[1];
489
497
 
490
- if (typeof(target) === "function") {
491
- id = donator.$__id__();
492
- methods = donator.$instance_methods();
498
+ }
493
499
 
494
- for (i = methods.length - 1; i >= 0; i--) {
495
- method = '$' + methods[i];
500
+ // Bridges from *donator* to a *target*.
501
+ function _bridge(target, donator) {
502
+ var id, methods, method, i, bridged;
496
503
 
497
- bridge(target, donator, method, donator.$$proto[method]);
498
- }
504
+ if (typeof(target) === "function") {
505
+ id = donator.$__id__();
506
+ methods = donator.$instance_methods();
499
507
 
500
- if (!bridges[id]) {
501
- bridges[id] = [];
502
- }
508
+ for (i = methods.length - 1; i >= 0; i--) {
509
+ method = '$' + methods[i];
503
510
 
504
- bridges[id].push(target);
511
+ bridge_method(target, donator, method, donator.$$proto[method]);
505
512
  }
506
- else {
507
- bridged = bridges[target.$__id__()];
508
513
 
509
- if (bridged) {
510
- for (i = bridged.length - 1; i >= 0; i--) {
511
- bridge(bridged[i], donator);
512
- }
514
+ if (!bridges[id]) {
515
+ bridges[id] = [];
516
+ }
513
517
 
514
- bridges[donator.$__id__()] = bridged.slice();
518
+ bridges[id].push(target);
519
+ }
520
+ else {
521
+ bridged = bridges[target.$__id__()];
522
+
523
+ if (bridged) {
524
+ for (i = bridged.length - 1; i >= 0; i--) {
525
+ _bridge(bridged[i], donator);
515
526
  }
527
+
528
+ bridges[donator.$__id__()] = bridged.slice();
516
529
  }
517
530
  }
518
531
  }
519
532
 
520
- /**
521
- The actual inclusion of a module into a class.
522
-
523
- ## Class `$$parent` and `iclass`
524
-
525
- To handle `super` calls, every class has a `$$parent`. This parent is
526
- used to resolve the next class for a super call. A normal class would
527
- have this point to its superclass. However, if a class includes a module
528
- then this would need to take into account the module. The module would
529
- also have to then point its `$$parent` to the actual superclass. We
530
- cannot modify modules like this, because it might be included in more
531
- then one class. To fix this, we actually insert an `iclass` as the class'
532
- `$$parent` which can then point to the superclass. The `iclass` acts as
533
- a proxy to the actual module, so the `super` chain can then search it for
534
- the required method.
535
-
536
- @param [RubyModule] module the module to include
537
- @param [RubyClass] klass the target class to include module into
538
- @returns [null]
539
- */
533
+ // The actual inclusion of a module into a class.
534
+ //
535
+ // ## Class `$$parent` and `iclass`
536
+ //
537
+ // To handle `super` calls, every class has a `$$parent`. This parent is
538
+ // used to resolve the next class for a super call. A normal class would
539
+ // have this point to its superclass. However, if a class includes a module
540
+ // then this would need to take into account the module. The module would
541
+ // also have to then point its `$$parent` to the actual superclass. We
542
+ // cannot modify modules like this, because it might be included in more
543
+ // then one class. To fix this, we actually insert an `iclass` as the class'
544
+ // `$$parent` which can then point to the superclass. The `iclass` acts as
545
+ // a proxy to the actual module, so the `super` chain can then search it for
546
+ // the required method.
547
+ //
548
+ // @param [RubyModule] module the module to include
549
+ // @param [RubyClass] klass the target class to include module into
550
+ // @return [null]
551
+ //
540
552
  Opal.append_features = function(module, klass) {
541
553
  var iclass, donator, prototype, methods, id, i;
542
554
 
@@ -549,7 +561,7 @@
549
561
 
550
562
  klass.$$inc.push(module);
551
563
  module.$$dep.push(klass);
552
- bridge(klass, module);
564
+ _bridge(klass, module);
553
565
 
554
566
  // iclass
555
567
  iclass = {
@@ -588,14 +600,13 @@
588
600
  // Boot a base class (makes instances).
589
601
  function boot_class_alloc(id, constructor, superklass) {
590
602
  if (superklass) {
591
- var ctor = function() {};
592
- ctor.prototype = superklass.$$proto || superklass.prototype;
593
-
594
- if (id) {
595
- ctor.displayName = id;
596
- }
603
+ var alloc_proxy = function() {};
604
+ alloc_proxy.prototype = superklass.$$proto || superklass.prototype;
605
+ constructor.prototype = new alloc_proxy();
606
+ }
597
607
 
598
- constructor.prototype = new ctor();
608
+ if (id) {
609
+ constructor.displayName = id+'_alloc';
599
610
  }
600
611
 
601
612
  constructor.prototype.constructor = constructor;
@@ -603,15 +614,14 @@
603
614
  return constructor;
604
615
  }
605
616
 
606
- /*
607
- * Builds the class object for core classes:
608
- * - make the class object have a singleton class
609
- * - make the singleton class inherit from its parent singleton class
610
- *
611
- * @param id [String] the name of the class
612
- * @param alloc [Function] the constructor for the core class instances
613
- * @param superclass [Class alloc] the constructor of the superclass
614
- */
617
+ // Builds the class object for core classes:
618
+ // - make the class object have a singleton class
619
+ // - make the singleton class inherit from its parent singleton class
620
+ //
621
+ // @param id [String] the name of the class
622
+ // @param alloc [Function] the constructor for the core class instances
623
+ // @param superclass [Class alloc] the constructor of the superclass
624
+ //
615
625
  function boot_core_class_object(id, alloc, superclass) {
616
626
  var superclass_constructor = function() {};
617
627
  superclass_constructor.prototype = superclass.prototype;
@@ -626,8 +636,9 @@
626
636
 
627
637
  setup_module_or_class_object(klass, singleton_class, superclass, alloc.prototype);
628
638
 
629
- klass.$$alloc = alloc;
630
- klass.$$name = id;
639
+ klass.$$alloc = alloc;
640
+ klass.$$name = id;
641
+ klass.displayName = id;
631
642
 
632
643
  // Give all instances a ref to their class
633
644
  alloc.prototype.$$class = klass;
@@ -638,24 +649,23 @@
638
649
  return klass;
639
650
  }
640
651
 
641
- /*
642
- * For performance, some core Ruby classes are toll-free bridged to their
643
- * native JavaScript counterparts (e.g. a Ruby Array is a JavaScript Array).
644
- *
645
- * This method is used to setup a native constructor (e.g. Array), to have
646
- * its prototype act like a normal Ruby class. Firstly, a new Ruby class is
647
- * created using the native constructor so that its prototype is set as the
648
- * target for th new class. Note: all bridged classes are set to inherit
649
- * from Object.
650
- *
651
- * Example:
652
- *
653
- * Opal.bridge(self, Function);
654
- *
655
- * @param [Class] klass the Ruby class to bridge
656
- * @param [Function] constructor native JavaScript constructor to use
657
- * @return [Class] returns the passed Ruby class
658
- */
652
+ // For performance, some core Ruby classes are toll-free bridged to their
653
+ // native JavaScript counterparts (e.g. a Ruby Array is a JavaScript Array).
654
+ //
655
+ // This method is used to setup a native constructor (e.g. Array), to have
656
+ // its prototype act like a normal Ruby class. Firstly, a new Ruby class is
657
+ // created using the native constructor so that its prototype is set as the
658
+ // target for th new class. Note: all bridged classes are set to inherit
659
+ // from Object.
660
+ //
661
+ // Example:
662
+ //
663
+ // Opal.bridge(self, Function);
664
+ //
665
+ // @param [Class] klass the Ruby class to bridge
666
+ // @param [Function] constructor native JavaScript constructor to use
667
+ // @return [Class] returns the passed Ruby class
668
+ //
659
669
  Opal.bridge = function(klass, constructor) {
660
670
  if (constructor.$$bridge) {
661
671
  throw Opal.ArgumentError.$new("already bridged");
@@ -671,11 +681,11 @@
671
681
  // order important here, we have to bridge from the last ancestor to the
672
682
  // bridged class
673
683
  for (var i = ancestors.length - 1; i >= 0; i--) {
674
- bridge(constructor, ancestors[i]);
684
+ _bridge(constructor, ancestors[i]);
675
685
  }
676
686
 
677
- for (var name in BasicObject.prototype) {
678
- var method = BasicObject.prototype[method];
687
+ for (var name in BasicObject_alloc.prototype) {
688
+ var method = BasicObject_alloc.prototype[method];
679
689
 
680
690
  if (method && method.$$stub && !(name in constructor.prototype)) {
681
691
  constructor.prototype[name] = method;
@@ -686,9 +696,8 @@
686
696
  }
687
697
 
688
698
 
689
- /*
690
- * constant assign
691
- */
699
+ // constant assign
700
+ //
692
701
  Opal.casgn = function(base_module, name, value) {
693
702
  function update(klass, name) {
694
703
  klass.$$name = name;
@@ -705,8 +714,8 @@
705
714
  var scope = base_module.$$scope;
706
715
 
707
716
  if (value.$$is_class || value.$$is_module) {
708
- // only checking ObjectClass prevents setting a const on an anonymous class that has a superclass that's not Object
709
- if (value.$$is_class || value.$$base_module === ObjectClass) {
717
+ // only checking _Object prevents setting a const on an anonymous class that has a superclass that's not Object
718
+ if (value.$$is_class || value.$$base_module === _Object) {
710
719
  value.$$base_module = base_module;
711
720
  }
712
721
 
@@ -719,9 +728,7 @@
719
728
  return scope[name] = value;
720
729
  };
721
730
 
722
- /*
723
- * constant decl
724
- */
731
+ // constant decl
725
732
  Opal.cdecl = function(base_scope, name, value) {
726
733
  if ((value.$$is_class || value.$$is_module) && value.$$orig_scope == null) {
727
734
  value.$$name = name;
@@ -733,10 +740,9 @@
733
740
  return base_scope[name] = value;
734
741
  };
735
742
 
736
- /*
737
- * When a source module is included into the target module, we must also copy
738
- * its constants to the target.
739
- */
743
+ // When a source module is included into the target module, we must also copy
744
+ // its constants to the target.
745
+ //
740
746
  function donate_constants(source_mod, target_mod) {
741
747
  var source_constants = source_mod.$$scope.constants,
742
748
  target_scope = target_mod.$$scope,
@@ -748,9 +754,7 @@
748
754
  }
749
755
  };
750
756
 
751
- /*
752
- * Donate methods for a module.
753
- */
757
+ // Donate methods for a module.
754
758
  function donate(module, jsid) {
755
759
  var included_in = module.$$dep,
756
760
  body = module.$$proto[jsid],
@@ -802,34 +806,33 @@
802
806
  }
803
807
  };
804
808
 
805
- /*
806
- * Methods stubs are used to facilitate method_missing in opal. A stub is a
807
- * placeholder function which just calls `method_missing` on the receiver.
808
- * If no method with the given name is actually defined on an object, then it
809
- * is obvious to say that the stub will be called instead, and then in turn
810
- * method_missing will be called.
811
- *
812
- * When a file in ruby gets compiled to javascript, it includes a call to
813
- * this function which adds stubs for every method name in the compiled file.
814
- * It should then be safe to assume that method_missing will work for any
815
- * method call detected.
816
- *
817
- * Method stubs are added to the BasicObject prototype, which every other
818
- * ruby object inherits, so all objects should handle method missing. A stub
819
- * is only added if the given property name (method name) is not already
820
- * defined.
821
- *
822
- * Note: all ruby methods have a `$` prefix in javascript, so all stubs will
823
- * have this prefix as well (to make this method more performant).
824
- *
825
- * Opal.add_stubs(["$foo", "$bar", "$baz="]);
826
- *
827
- * All stub functions will have a private `$$stub` property set to true so
828
- * that other internal methods can detect if a method is just a stub or not.
829
- * `Kernel#respond_to?` uses this property to detect a methods presence.
830
- *
831
- * @param [Array] stubs an array of method stubs to add
832
- */
809
+ // Methods stubs are used to facilitate method_missing in opal. A stub is a
810
+ // placeholder function which just calls `method_missing` on the receiver.
811
+ // If no method with the given name is actually defined on an object, then it
812
+ // is obvious to say that the stub will be called instead, and then in turn
813
+ // method_missing will be called.
814
+ //
815
+ // When a file in ruby gets compiled to javascript, it includes a call to
816
+ // this function which adds stubs for every method name in the compiled file.
817
+ // It should then be safe to assume that method_missing will work for any
818
+ // method call detected.
819
+ //
820
+ // Method stubs are added to the BasicObject prototype, which every other
821
+ // ruby object inherits, so all objects should handle method missing. A stub
822
+ // is only added if the given property name (method name) is not already
823
+ // defined.
824
+ //
825
+ // Note: all ruby methods have a `$` prefix in javascript, so all stubs will
826
+ // have this prefix as well (to make this method more performant).
827
+ //
828
+ // Opal.add_stubs(["$foo", "$bar", "$baz="]);
829
+ //
830
+ // All stub functions will have a private `$$stub` property set to true so
831
+ // that other internal methods can detect if a method is just a stub or not.
832
+ // `Kernel#respond_to?` uses this property to detect a methods presence.
833
+ //
834
+ // @param [Array] stubs an array of method stubs to add
835
+ //
833
836
  Opal.add_stubs = function(stubs) {
834
837
  var subscriber, subscribers = Opal.stub_subscribers,
835
838
  i, ilength = stubs.length,
@@ -850,30 +853,27 @@
850
853
  }
851
854
  };
852
855
 
853
- /*
854
- * Keep a list of prototypes that want method_missing stubs to be added.
855
- *
856
- * @default [Prototype List] BasicObject.prototype
857
- */
858
- Opal.stub_subscribers = [BasicObject.prototype];
859
-
860
- /*
861
- * Add a method_missing stub function to the given prototype for the
862
- * given name.
863
- *
864
- * @param [Prototype] prototype the target prototype
865
- * @param [String] stub stub name to add (e.g. "$foo")
866
- */
867
- function add_stub_for(prototype, stub) {
856
+ // Keep a list of prototypes that want method_missing stubs to be added.
857
+ //
858
+ // @default [Prototype List] BasicObject_alloc.prototype
859
+ //
860
+ Opal.stub_subscribers = [BasicObject_alloc.prototype];
861
+
862
+ // Add a method_missing stub function to the given prototype for the
863
+ // given name.
864
+ //
865
+ // @param [Prototype] prototype the target prototype
866
+ // @param [String] stub stub name to add (e.g. "$foo")
867
+ //
868
+ Opal.add_stub_for = function(prototype, stub) {
868
869
  var method_missing_stub = stub_for(stub);
869
870
  prototype[stub] = method_missing_stub;
870
871
  }
871
872
 
872
- /*
873
- * Generate the method_missing stub for a given method name.
874
- *
875
- * @param [String] method_name The js-name of the method to stub (e.g. "$foo")
876
- */
873
+ // Generate the method_missing stub for a given method name.
874
+ //
875
+ // @param [String] method_name The js-name of the method to stub (e.g. "$foo")
876
+ //
877
877
  function stub_for(method_name) {
878
878
  function method_missing_stub() {
879
879
  // Copy any given block onto the method_missing dispatcher
@@ -891,9 +891,6 @@
891
891
  return method_missing_stub;
892
892
  }
893
893
 
894
- // Expose for other parts of Opal to use
895
- Opal.add_stub_for = add_stub_for;
896
-
897
894
  // Arity count error dispatcher
898
895
  Opal.ac = function(actual, expected, object, meth) {
899
896
  var inspect = '';
@@ -908,6 +905,23 @@
908
905
  throw Opal.ArgumentError.$new('[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')');
909
906
  };
910
907
 
908
+ // The Array of ancestors for a given module/class
909
+ Opal.ancestors = function(module_or_class) {
910
+ var parent = module_or_class,
911
+ result = [];
912
+
913
+ while (parent) {
914
+ result.push(parent);
915
+ for (var i=0; i < parent.$$inc.length; i++) {
916
+ result = result.concat(Opal.ancestors(parent.$$inc[i]));
917
+ }
918
+
919
+ parent = parent.$$is_class ? parent.$$super : null;
920
+ }
921
+
922
+ return result;
923
+ }
924
+
911
925
  // Super dispatcher
912
926
  Opal.find_super_dispatcher = function(obj, jsid, current_func, iter, defs) {
913
927
  var dispatcher;
@@ -980,14 +994,13 @@
980
994
  return klass.$$proto;
981
995
  };
982
996
 
983
- /*
984
- * Used to return as an expression. Sometimes, we can't simply return from
985
- * a javascript function as if we were a method, as the return is used as
986
- * an expression, or even inside a block which must "return" to the outer
987
- * method. This helper simply throws an error which is then caught by the
988
- * method. This approach is expensive, so it is only used when absolutely
989
- * needed.
990
- */
997
+ // Used to return as an expression. Sometimes, we can't simply return from
998
+ // a javascript function as if we were a method, as the return is used as
999
+ // an expression, or even inside a block which must "return" to the outer
1000
+ // method. This helper simply throws an error which is then caught by the
1001
+ // method. This approach is expensive, so it is only used when absolutely
1002
+ // needed.
1003
+ //
991
1004
  Opal.ret = function(val) {
992
1005
  Opal.returner.$v = val;
993
1006
  throw Opal.returner;
@@ -1071,13 +1084,28 @@
1071
1084
  return false;
1072
1085
  };
1073
1086
 
1074
- // Helper to convert the given object to an array
1087
+ // Helpers for implementing multiple assignment
1088
+ // Our code for extracting the values and assigning them only works if the
1089
+ // return value is a JS array
1090
+ // So if we get an Array subclass, extract the wrapped JS array from it
1091
+
1075
1092
  Opal.to_ary = function(value) {
1093
+ // Used for: a, b = something (no splat)
1076
1094
  if (value.$$is_array) {
1077
- return value;
1095
+ return (value.constructor === Array) ? value : value.literal;
1078
1096
  }
1079
- else if (value.$to_ary && !value.$to_ary.$$stub) {
1080
- return value.$to_ary();
1097
+ else if (value['$respond_to?']('to_ary', true)) {
1098
+ var ary = value.$to_ary();
1099
+ if (ary === nil) {
1100
+ return [value];
1101
+ }
1102
+ else if (ary.$$is_array) {
1103
+ return (ary.constructor === Array) ? ary : ary.literal;
1104
+ }
1105
+ else {
1106
+ throw Opal.TypeError.$new("Can't convert " + value.$$class +
1107
+ " to Array (" + value.$$class + "#to_ary gives " + ary.$$class + ")");
1108
+ }
1081
1109
  }
1082
1110
  else {
1083
1111
  return [value];
@@ -1085,34 +1113,45 @@
1085
1113
  };
1086
1114
 
1087
1115
  Opal.to_a = function(value) {
1088
- if (value == null || value === nil) {
1089
- return [];
1116
+ // Used for: a, b = *something (with splat)
1117
+ if (value.$$is_array) {
1118
+ // A splatted array must be copied
1119
+ return (value.constructor === Array) ? value.slice() : value.literal.slice();
1090
1120
  }
1091
- else if (value.$to_a && !value.$to_a.$$stub) {
1092
- return value.$to_a();
1121
+ else if (value['$respond_to?']('to_a', true)) {
1122
+ var ary = value.$to_a();
1123
+ if (ary === nil) {
1124
+ return [value];
1125
+ }
1126
+ else if (ary.$$is_array) {
1127
+ return (ary.constructor === Array) ? ary : ary.literal;
1128
+ }
1129
+ else {
1130
+ throw Opal.TypeError.$new("Can't convert " + value.$$class +
1131
+ " to Array (" + value.$$class + "#to_a gives " + ary.$$class + ")");
1132
+ }
1093
1133
  }
1094
1134
  else {
1095
1135
  return [value];
1096
1136
  }
1097
1137
  };
1098
1138
 
1099
- /**
1100
- Used to get a list of rest keyword arguments. Method takes the given
1101
- keyword args, i.e. the hash literal passed to the method containing all
1102
- keyword arguemnts passed to method, as well as the used args which are
1103
- the names of required and optional arguments defined. This method then
1104
- just returns all key/value pairs which have not been used, in a new
1105
- hash literal.
1106
-
1107
- @param given_args [Hash] all kwargs given to method
1108
- @param used_args [Object<String: true>] all keys used as named kwargs
1109
- @return [Hash]
1110
- */
1139
+ // Used to get a list of rest keyword arguments. Method takes the given
1140
+ // keyword args, i.e. the hash literal passed to the method containing all
1141
+ // keyword arguemnts passed to method, as well as the used args which are
1142
+ // the names of required and optional arguments defined. This method then
1143
+ // just returns all key/value pairs which have not been used, in a new
1144
+ // hash literal.
1145
+ //
1146
+ // @param given_args [Hash] all kwargs given to method
1147
+ // @param used_args [Object<String: true>] all keys used as named kwargs
1148
+ // @return [Hash]
1149
+ //
1111
1150
  Opal.kwrestargs = function(given_args, used_args) {
1112
1151
  var keys = [],
1113
1152
  map = {},
1114
1153
  key = null,
1115
- given_map = given_args.smap;
1154
+ given_map = given_args.$$smap;
1116
1155
 
1117
1156
  for (key in given_map) {
1118
1157
  if (!used_args[key]) {
@@ -1124,21 +1163,20 @@
1124
1163
  return Opal.hash2(keys, map);
1125
1164
  };
1126
1165
 
1127
- /*
1128
- * Call a ruby method on a ruby object with some arguments:
1129
- *
1130
- * var my_array = [1, 2, 3, 4]
1131
- * Opal.send(my_array, 'length') # => 4
1132
- * Opal.send(my_array, 'reverse!') # => [4, 3, 2, 1]
1133
- *
1134
- * A missing method will be forwarded to the object via
1135
- * method_missing.
1136
- *
1137
- * The result of either call with be returned.
1138
- *
1139
- * @param [Object] recv the ruby object
1140
- * @param [String] mid ruby method to call
1141
- */
1166
+ // Call a ruby method on a ruby object with some arguments:
1167
+ //
1168
+ // var my_array = [1, 2, 3, 4]
1169
+ // Opal.send(my_array, 'length') # => 4
1170
+ // Opal.send(my_array, 'reverse!') # => [4, 3, 2, 1]
1171
+ //
1172
+ // A missing method will be forwarded to the object via
1173
+ // method_missing.
1174
+ //
1175
+ // The result of either call with be returned.
1176
+ //
1177
+ // @param [Object] recv the ruby object
1178
+ // @param [String] mid ruby method to call
1179
+ //
1142
1180
  Opal.send = function(recv, mid) {
1143
1181
  var args = $slice.call(arguments, 2),
1144
1182
  func = recv['$' + mid];
@@ -1162,43 +1200,42 @@
1162
1200
  return recv.$method_missing.apply(recv, [mid].concat(args));
1163
1201
  };
1164
1202
 
1165
- /**
1166
- Used to define methods on an object. This is a helper method, used by the
1167
- compiled source to define methods on special case objects when the compiler
1168
- can not determine the destination object, or the object is a Module
1169
- instance. This can get called by `Module#define_method` as well.
1170
-
1171
- ## Modules
1172
-
1173
- Any method defined on a module will come through this runtime helper.
1174
- The method is added to the module body, and the owner of the method is
1175
- set to be the module itself. This is used later when choosing which
1176
- method should show on a class if more than 1 included modules define
1177
- the same method. Finally, if the module is in `module_function` mode,
1178
- then the method is also defined onto the module itself.
1179
-
1180
- ## Classes
1181
-
1182
- This helper will only be called for classes when a method is being
1183
- defined indirectly; either through `Module#define_method`, or by a
1184
- literal `def` method inside an `instance_eval` or `class_eval` body. In
1185
- either case, the method is simply added to the class' prototype. A special
1186
- exception exists for `BasicObject` and `Object`. These two classes are
1187
- special because they are used in toll-free bridged classes. In each of
1188
- these two cases, extra work is required to define the methods on toll-free
1189
- bridged class' prototypes as well.
1190
-
1191
- ## Objects
1192
-
1193
- If a simple ruby object is the object, then the method is simply just
1194
- defined on the object as a singleton method. This would be the case when
1195
- a method is defined inside an `instance_eval` block.
1196
-
1197
- @param [RubyObject or Class] obj the actual obj to define method for
1198
- @param [String] jsid the javascript friendly method name (e.g. '$foo')
1199
- @param [Function] body the literal javascript function used as method
1200
- @returns [null]
1201
- */
1203
+ // Used to define methods on an object. This is a helper method, used by the
1204
+ // compiled source to define methods on special case objects when the compiler
1205
+ // can not determine the destination object, or the object is a Module
1206
+ // instance. This can get called by `Module#define_method` as well.
1207
+ //
1208
+ // ## Modules
1209
+ //
1210
+ // Any method defined on a module will come through this runtime helper.
1211
+ // The method is added to the module body, and the owner of the method is
1212
+ // set to be the module itself. This is used later when choosing which
1213
+ // method should show on a class if more than 1 included modules define
1214
+ // the same method. Finally, if the module is in `module_function` mode,
1215
+ // then the method is also defined onto the module itself.
1216
+ //
1217
+ // ## Classes
1218
+ //
1219
+ // This helper will only be called for classes when a method is being
1220
+ // defined indirectly; either through `Module#define_method`, or by a
1221
+ // literal `def` method inside an `instance_eval` or `class_eval` body. In
1222
+ // either case, the method is simply added to the class' prototype. A special
1223
+ // exception exists for `BasicObject` and `Object`. These two classes are
1224
+ // special because they are used in toll-free bridged classes. In each of
1225
+ // these two cases, extra work is required to define the methods on toll-free
1226
+ // bridged class' prototypes as well.
1227
+ //
1228
+ // ## Objects
1229
+ //
1230
+ // If a simple ruby object is the object, then the method is simply just
1231
+ // defined on the object as a singleton method. This would be the case when
1232
+ // a method is defined inside an `instance_eval` block.
1233
+ //
1234
+ // @param [RubyObject or Class] obj the actual obj to define method for
1235
+ // @param [String] jsid the javascript friendly method name (e.g. '$foo')
1236
+ // @param [Function] body the literal javascript function used as method
1237
+ // @return [null]
1238
+ //
1202
1239
  Opal.defn = function(obj, jsid, body) {
1203
1240
  obj.$$proto[jsid] = body;
1204
1241
 
@@ -1215,7 +1252,7 @@
1215
1252
 
1216
1253
  if (bridged) {
1217
1254
  for (var i = bridged.length - 1; i >= 0; i--) {
1218
- bridge(bridged[i], obj, jsid, body);
1255
+ bridge_method(bridged[i], obj, jsid, body);
1219
1256
  }
1220
1257
  }
1221
1258
  }
@@ -1232,9 +1269,8 @@
1232
1269
  return nil;
1233
1270
  };
1234
1271
 
1235
- /*
1236
- * Define a singleton method on the given object.
1237
- */
1272
+
1273
+ // Define a singleton method on the given object.
1238
1274
  Opal.defs = function(obj, jsid, body) {
1239
1275
  Opal.defn(Opal.get_singleton_class(obj), jsid, body)
1240
1276
  };
@@ -1249,9 +1285,7 @@
1249
1285
  }
1250
1286
  };
1251
1287
 
1252
- /*
1253
- * Called from #remove_method.
1254
- */
1288
+ // Called from #remove_method.
1255
1289
  Opal.rdef = function(obj, jsid) {
1256
1290
  // TODO: remove from bridges as well
1257
1291
 
@@ -1273,9 +1307,7 @@
1273
1307
  }
1274
1308
  };
1275
1309
 
1276
- /*
1277
- * Called from #undef_method.
1278
- */
1310
+ // Called from #undef_method.
1279
1311
  Opal.udef = function(obj, jsid) {
1280
1312
  if (!obj.$$proto[jsid] || obj.$$proto[jsid].$$stub) {
1281
1313
  throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
@@ -1295,33 +1327,11 @@
1295
1327
  }
1296
1328
  };
1297
1329
 
1298
- // This black magic is required to avoid clashes of internal special fields,
1299
- // like $$donated.
1300
- function wrap(body) {
1301
- function alias() {
1302
- body.$$p = alias.$$p;
1303
- body.$$s = alias.$$s;
1304
-
1305
- try {
1306
- return body.apply(this, $slice.call(arguments));
1307
- }
1308
- finally {
1309
- alias.$$s = null;
1310
- alias.$$p = null;
1311
- }
1312
- }
1313
-
1314
- alias.$$target = body;
1315
- alias.$$arity = body.length;
1316
-
1317
- return alias;
1318
- }
1319
-
1320
1330
  Opal.alias = function(obj, name, old) {
1321
1331
  var id = '$' + name,
1322
1332
  old_id = '$' + old,
1323
1333
  body = obj.$$proto['$' + old];
1324
-
1334
+
1325
1335
  // instance_eval is being run on a class/module, so that need to alias class methods
1326
1336
  if (obj.$$eval) {
1327
1337
  return Opal.alias(Opal.get_singleton_class(obj), name, old);
@@ -1340,7 +1350,7 @@
1340
1350
  }
1341
1351
  }
1342
1352
 
1343
- Opal.defn(obj, id, wrap(body));
1353
+ Opal.defn(obj, id, body);
1344
1354
 
1345
1355
  return obj;
1346
1356
  };
@@ -1353,26 +1363,26 @@
1353
1363
  throw Opal.NameError.$new("undefined native method `" + native_name + "' for class `" + obj.$name() + "'")
1354
1364
  }
1355
1365
 
1356
- Opal.defn(obj, id, wrap(body));
1366
+ Opal.defn(obj, id, body);
1357
1367
 
1358
1368
  return obj;
1359
1369
  };
1360
1370
 
1361
- Opal.hash_init = function (hash) {
1362
- hash.map = {};
1363
- hash.smap = {};
1364
- hash.keys = [];
1371
+ Opal.hash_init = function(hash) {
1372
+ hash.$$map = {};
1373
+ hash.$$smap = {};
1374
+ hash.$$keys = [];
1365
1375
  };
1366
1376
 
1367
- Opal.hash_clone = function (from_hash, to_hash) {
1377
+ Opal.hash_clone = function(from_hash, to_hash) {
1368
1378
  to_hash.none = from_hash.none;
1369
1379
  to_hash.proc = from_hash.proc;
1370
1380
 
1371
- for (var i = 0, keys = from_hash.keys, length = keys.length, key, value; i < length; i++) {
1372
- key = from_hash.keys[i];
1381
+ for (var i = 0, keys = from_hash.$$keys, length = keys.length, key, value; i < length; i++) {
1382
+ key = from_hash.$$keys[i];
1373
1383
 
1374
1384
  if (key.$$is_string) {
1375
- value = from_hash.smap[key];
1385
+ value = from_hash.$$smap[key];
1376
1386
  } else {
1377
1387
  value = key.value;
1378
1388
  key = key.key;
@@ -1382,25 +1392,25 @@
1382
1392
  }
1383
1393
  };
1384
1394
 
1385
- Opal.hash_put = function (hash, key, value) {
1395
+ Opal.hash_put = function(hash, key, value) {
1386
1396
  if (key.$$is_string) {
1387
- if (!hash.smap.hasOwnProperty(key)) {
1388
- hash.keys.push(key);
1397
+ if (!hash.$$smap.hasOwnProperty(key)) {
1398
+ hash.$$keys.push(key);
1389
1399
  }
1390
- hash.smap[key] = value;
1400
+ hash.$$smap[key] = value;
1391
1401
  return;
1392
1402
  }
1393
1403
 
1394
1404
  var key_hash = key.$hash(), bucket, last_bucket;
1395
1405
 
1396
- if (!hash.map.hasOwnProperty(key_hash)) {
1406
+ if (!hash.$$map.hasOwnProperty(key_hash)) {
1397
1407
  bucket = {key: key, key_hash: key_hash, value: value};
1398
- hash.keys.push(bucket);
1399
- hash.map[key_hash] = bucket;
1408
+ hash.$$keys.push(bucket);
1409
+ hash.$$map[key_hash] = bucket;
1400
1410
  return;
1401
1411
  }
1402
1412
 
1403
- bucket = hash.map[key_hash];
1413
+ bucket = hash.$$map[key_hash];
1404
1414
 
1405
1415
  while (bucket) {
1406
1416
  if (key === bucket.key || key['$eql?'](bucket.key)) {
@@ -1414,23 +1424,23 @@
1414
1424
 
1415
1425
  if (last_bucket) {
1416
1426
  bucket = {key: key, key_hash: key_hash, value: value};
1417
- hash.keys.push(bucket);
1427
+ hash.$$keys.push(bucket);
1418
1428
  last_bucket.next = bucket;
1419
1429
  }
1420
1430
  };
1421
1431
 
1422
- Opal.hash_get = function (hash, key) {
1432
+ Opal.hash_get = function(hash, key) {
1423
1433
  if (key.$$is_string) {
1424
- if (hash.smap.hasOwnProperty(key)) {
1425
- return hash.smap[key];
1434
+ if (hash.$$smap.hasOwnProperty(key)) {
1435
+ return hash.$$smap[key];
1426
1436
  }
1427
1437
  return;
1428
1438
  }
1429
1439
 
1430
1440
  var key_hash = key.$hash(), bucket;
1431
1441
 
1432
- if (hash.map.hasOwnProperty(key_hash)) {
1433
- bucket = hash.map[key_hash];
1442
+ if (hash.$$map.hasOwnProperty(key_hash)) {
1443
+ bucket = hash.$$map[key_hash];
1434
1444
 
1435
1445
  while (bucket) {
1436
1446
  if (key === bucket.key || key['$eql?'](bucket.key)) {
@@ -1441,11 +1451,11 @@
1441
1451
  }
1442
1452
  };
1443
1453
 
1444
- Opal.hash_delete = function (hash, key) {
1445
- var i, keys = hash.keys, length = keys.length, value;
1454
+ Opal.hash_delete = function(hash, key) {
1455
+ var i, keys = hash.$$keys, length = keys.length, value;
1446
1456
 
1447
1457
  if (key.$$is_string) {
1448
- if (!hash.smap.hasOwnProperty(key)) {
1458
+ if (!hash.$$smap.hasOwnProperty(key)) {
1449
1459
  return;
1450
1460
  }
1451
1461
 
@@ -1456,18 +1466,18 @@
1456
1466
  }
1457
1467
  }
1458
1468
 
1459
- value = hash.smap[key];
1460
- delete hash.smap[key];
1469
+ value = hash.$$smap[key];
1470
+ delete hash.$$smap[key];
1461
1471
  return value;
1462
1472
  }
1463
1473
 
1464
1474
  var key_hash = key.$hash();
1465
1475
 
1466
- if (!hash.map.hasOwnProperty(key_hash)) {
1476
+ if (!hash.$$map.hasOwnProperty(key_hash)) {
1467
1477
  return;
1468
1478
  }
1469
1479
 
1470
- var bucket = hash.map[key_hash], last_bucket;
1480
+ var bucket = hash.$$map[key_hash], last_bucket;
1471
1481
 
1472
1482
  while (bucket) {
1473
1483
  if (key === bucket.key || key['$eql?'](bucket.key)) {
@@ -1487,10 +1497,10 @@
1487
1497
  delete last_bucket.next;
1488
1498
  }
1489
1499
  else if (bucket.next) {
1490
- hash.map[key_hash] = bucket.next;
1500
+ hash.$$map[key_hash] = bucket.next;
1491
1501
  }
1492
1502
  else {
1493
- delete hash.map[key_hash];
1503
+ delete hash.$$map[key_hash];
1494
1504
  }
1495
1505
 
1496
1506
  return value;
@@ -1500,24 +1510,24 @@
1500
1510
  }
1501
1511
  };
1502
1512
 
1503
- Opal.hash_rehash = function (hash) {
1504
- for (var i = 0, length = hash.keys.length, key_hash, bucket, last_bucket; i < length; i++) {
1513
+ Opal.hash_rehash = function(hash) {
1514
+ for (var i = 0, length = hash.$$keys.length, key_hash, bucket, last_bucket; i < length; i++) {
1505
1515
 
1506
- if (hash.keys[i].$$is_string) {
1516
+ if (hash.$$keys[i].$$is_string) {
1507
1517
  continue;
1508
1518
  }
1509
1519
 
1510
- key_hash = hash.keys[i].key.$hash();
1520
+ key_hash = hash.$$keys[i].key.$hash();
1511
1521
 
1512
- if (key_hash === hash.keys[i].key_hash) {
1522
+ if (key_hash === hash.$$keys[i].key_hash) {
1513
1523
  continue;
1514
1524
  }
1515
1525
 
1516
- bucket = hash.map[hash.keys[i].key_hash];
1526
+ bucket = hash.$$map[hash.$$keys[i].key_hash];
1517
1527
  last_bucket = undefined;
1518
1528
 
1519
1529
  while (bucket) {
1520
- if (bucket === hash.keys[i]) {
1530
+ if (bucket === hash.$$keys[i]) {
1521
1531
  if (last_bucket && bucket.next) {
1522
1532
  last_bucket.next = bucket.next;
1523
1533
  }
@@ -1525,10 +1535,10 @@
1525
1535
  delete last_bucket.next;
1526
1536
  }
1527
1537
  else if (bucket.next) {
1528
- hash.map[hash.keys[i].key_hash] = bucket.next;
1538
+ hash.$$map[hash.$$keys[i].key_hash] = bucket.next;
1529
1539
  }
1530
1540
  else {
1531
- delete hash.map[hash.keys[i].key_hash];
1541
+ delete hash.$$map[hash.$$keys[i].key_hash];
1532
1542
  }
1533
1543
  break;
1534
1544
  }
@@ -1536,18 +1546,18 @@
1536
1546
  bucket = bucket.next;
1537
1547
  }
1538
1548
 
1539
- hash.keys[i].key_hash = key_hash;
1549
+ hash.$$keys[i].key_hash = key_hash;
1540
1550
 
1541
- if (!hash.map.hasOwnProperty(key_hash)) {
1542
- hash.map[key_hash] = hash.keys[i];
1551
+ if (!hash.$$map.hasOwnProperty(key_hash)) {
1552
+ hash.$$map[key_hash] = hash.$$keys[i];
1543
1553
  continue;
1544
1554
  }
1545
1555
 
1546
- bucket = hash.map[key_hash];
1556
+ bucket = hash.$$map[key_hash];
1547
1557
  last_bucket = undefined;
1548
1558
 
1549
1559
  while (bucket) {
1550
- if (bucket === hash.keys[i]) {
1560
+ if (bucket === hash.$$keys[i]) {
1551
1561
  last_bucket = undefined;
1552
1562
  break;
1553
1563
  }
@@ -1556,7 +1566,7 @@
1556
1566
  }
1557
1567
 
1558
1568
  if (last_bucket) {
1559
- last_bucket.next = hash.keys[i];
1569
+ last_bucket.next = hash.$$keys[i];
1560
1570
  }
1561
1571
  }
1562
1572
  };
@@ -1616,26 +1626,24 @@
1616
1626
  return hash;
1617
1627
  };
1618
1628
 
1619
- /*
1620
- * hash2 is a faster creator for hashes that just use symbols and
1621
- * strings as keys. The map and keys array can be constructed at
1622
- * compile time, so they are just added here by the constructor
1623
- * function
1624
- */
1629
+ // hash2 is a faster creator for hashes that just use symbols and
1630
+ // strings as keys. The map and keys array can be constructed at
1631
+ // compile time, so they are just added here by the constructor
1632
+ // function
1633
+ //
1625
1634
  Opal.hash2 = function(keys, smap) {
1626
1635
  var hash = new Opal.Hash.$$alloc();
1627
1636
 
1628
- hash.map = {};
1629
- hash.keys = keys;
1630
- hash.smap = smap;
1637
+ hash.$$map = {};
1638
+ hash.$$keys = keys;
1639
+ hash.$$smap = smap;
1631
1640
 
1632
1641
  return hash;
1633
1642
  };
1634
1643
 
1635
- /*
1636
- * Create a new range instance with first and last values, and whether the
1637
- * range excludes the last value.
1638
- */
1644
+ // Create a new range instance with first and last values, and whether the
1645
+ // range excludes the last value.
1646
+ //
1639
1647
  Opal.range = function(first, last, exc) {
1640
1648
  var range = new Opal.Range.$$alloc();
1641
1649
  range.begin = first;
@@ -1646,17 +1654,19 @@
1646
1654
  };
1647
1655
 
1648
1656
  Opal.ivar = function(name) {
1649
- if (name === "constructor" ||
1650
- name === "__proto__" ||
1651
- name === "__parent__" ||
1657
+ if (
1658
+ // properties
1659
+ name === "constructor" ||
1660
+ name === "displayName" ||
1661
+ name === "__count__" ||
1652
1662
  name === "__noSuchMethod__" ||
1653
- name === "__count__")
1654
- {
1655
- return name + "$";
1656
- }
1663
+ name === "__parent__" ||
1664
+ name === "__proto__" ||
1657
1665
 
1658
- if (name === "hasOwnProperty" ||
1659
- name === "valueOf")
1666
+ // methods
1667
+ name === "hasOwnProperty" ||
1668
+ name === "valueOf"
1669
+ )
1660
1670
  {
1661
1671
  return name + "$";
1662
1672
  }
@@ -1666,169 +1676,133 @@
1666
1676
 
1667
1677
  // Require system
1668
1678
  // --------------
1669
- (function(Opal) {
1670
- var loaded_features = ['corelib/runtime'],
1671
- require_table = {'corelib/runtime': true},
1672
- modules = {};
1673
1679
 
1674
- var current_dir = '.';
1680
+ Opal.modules = {};
1681
+ Opal.loaded_features = ['corelib/runtime'];
1682
+ Opal.current_dir = '.'
1683
+ Opal.require_table = {'corelib/runtime': true};
1675
1684
 
1676
- function normalize(path) {
1677
- var parts, part, new_parts = [], SEPARATOR = '/';
1685
+ function normalize(path) {
1686
+ var parts, part, new_parts = [], SEPARATOR = '/';
1678
1687
 
1679
- if (current_dir !== '.') {
1680
- path = current_dir.replace(/\/*$/, '/') + path;
1681
- }
1682
-
1683
- path = path.replace(/\.(rb|opal|js)$/, '');
1684
- parts = path.split(SEPARATOR);
1688
+ if (Opal.current_dir !== '.') {
1689
+ path = Opal.current_dir.replace(/\/*$/, '/') + path;
1690
+ }
1685
1691
 
1686
- for (var i = 0, ii = parts.length; i < ii; i++) {
1687
- part = parts[i];
1688
- if (part === '') continue;
1689
- (part === '..') ? new_parts.pop() : new_parts.push(part)
1690
- }
1692
+ path = path.replace(/\.(rb|opal|js)$/, '');
1693
+ parts = path.split(SEPARATOR);
1691
1694
 
1692
- return new_parts.join(SEPARATOR);
1695
+ for (var i = 0, ii = parts.length; i < ii; i++) {
1696
+ part = parts[i];
1697
+ if (part === '') continue;
1698
+ (part === '..') ? new_parts.pop() : new_parts.push(part)
1693
1699
  }
1694
1700
 
1695
- function loaded(paths) {
1696
- var i, l, path;
1701
+ return new_parts.join(SEPARATOR);
1702
+ }
1697
1703
 
1698
- for (i = 0, l = paths.length; i < l; i++) {
1699
- path = normalize(paths[i]);
1704
+ Opal.loaded = function(paths) {
1705
+ var i, l, path;
1700
1706
 
1701
- if (require_table[path]) {
1702
- return;
1703
- }
1707
+ for (i = 0, l = paths.length; i < l; i++) {
1708
+ path = normalize(paths[i]);
1704
1709
 
1705
- loaded_features.push(path);
1706
- require_table[path] = true;
1710
+ if (Opal.require_table[path]) {
1711
+ return;
1707
1712
  }
1713
+
1714
+ Opal.loaded_features.push(path);
1715
+ Opal.require_table[path] = true;
1708
1716
  }
1717
+ }
1709
1718
 
1710
- function load(path) {
1711
- path = normalize(path);
1719
+ Opal.load = function(path) {
1720
+ path = normalize(path);
1712
1721
 
1713
- loaded([path]);
1722
+ Opal.loaded([path]);
1714
1723
 
1715
- var module = modules[path];
1724
+ var module = Opal.modules[path];
1716
1725
 
1717
- if (module) {
1718
- module(Opal);
1719
- }
1720
- else {
1721
- var severity = Opal.dynamic_require_severity || 'warning';
1722
- var message = 'cannot load such file -- ' + path;
1726
+ if (module) {
1727
+ module(Opal);
1728
+ }
1729
+ else {
1730
+ var severity = Opal.dynamic_require_severity || 'warning';
1731
+ var message = 'cannot load such file -- ' + path;
1723
1732
 
1724
- if (severity === "error") {
1725
- Opal.LoadError ? Opal.LoadError.$new(message) : function(){throw message}();
1726
- }
1727
- else if (severity === "warning") {
1728
- console.warn('WARNING: LoadError: ' + message);
1729
- }
1733
+ if (severity === "error") {
1734
+ Opal.LoadError ? Opal.LoadError.$new(message) : function(){throw message}();
1735
+ }
1736
+ else if (severity === "warning") {
1737
+ console.warn('WARNING: LoadError: ' + message);
1730
1738
  }
1731
-
1732
- return true;
1733
1739
  }
1734
1740
 
1735
- function require(path) {
1736
- path = normalize(path);
1741
+ return true;
1742
+ }
1737
1743
 
1738
- if (require_table[path]) {
1739
- return false;
1740
- }
1744
+ Opal.require = function(path) {
1745
+ path = normalize(path);
1741
1746
 
1742
- return load(path);
1747
+ if (Opal.require_table[path]) {
1748
+ return false;
1743
1749
  }
1744
1750
 
1745
- Opal.modules = modules;
1746
- Opal.loaded_features = loaded_features;
1747
- Opal.loaded = loaded;
1748
-
1749
- Opal.load = load;
1750
- Opal.require = require;
1751
- })(Opal);
1751
+ return Opal.load(path);
1752
+ }
1752
1753
 
1753
1754
  // Initialization
1754
1755
  // --------------
1755
1756
 
1756
- // The actual class for BasicObject
1757
- var BasicObjectClass;
1758
-
1759
- // The actual Object class
1760
- var ObjectClass;
1761
-
1762
- // The actual Module class
1763
- var ModuleClass;
1764
-
1765
- // The actual Class class
1766
- var ClassClass;
1767
-
1768
- // Constructor for instances of BasicObject
1769
- function BasicObject(){}
1770
-
1771
- // Constructor for instances of Object
1772
- function Object(){}
1773
-
1774
- // Constructor for instances of Class
1775
- function Class(){}
1776
-
1777
- // Constructor for instances of Module
1778
- function Module(){}
1779
-
1780
- // Constructor for instances of NilClass (nil)
1781
- function NilClass(){}
1782
-
1783
1757
  // Constructors for *instances* of core objects
1784
- boot_class_alloc('BasicObject', BasicObject);
1785
- boot_class_alloc('Object', Object, BasicObject);
1786
- boot_class_alloc('Module', Module, Object);
1787
- boot_class_alloc('Class', Class, Module);
1758
+ boot_class_alloc('BasicObject', BasicObject_alloc);
1759
+ boot_class_alloc('Object', Object_alloc, BasicObject_alloc);
1760
+ boot_class_alloc('Module', Module_alloc, Object_alloc);
1761
+ boot_class_alloc('Class', Class_alloc, Module_alloc);
1788
1762
 
1789
1763
  // Constructors for *classes* of core objects
1790
- BasicObjectClass = boot_core_class_object('BasicObject', BasicObject, Class);
1791
- ObjectClass = boot_core_class_object('Object', Object, BasicObjectClass.constructor);
1792
- ModuleClass = boot_core_class_object('Module', Module, ObjectClass.constructor);
1793
- ClassClass = boot_core_class_object('Class', Class, ModuleClass.constructor);
1764
+ BasicObject = boot_core_class_object('BasicObject', BasicObject_alloc, Class_alloc);
1765
+ _Object = boot_core_class_object('Object', Object_alloc, BasicObject.constructor);
1766
+ Module = boot_core_class_object('Module', Module_alloc, _Object.constructor);
1767
+ Class = boot_core_class_object('Class', Class_alloc, Module.constructor);
1794
1768
 
1795
1769
  // Fix booted classes to use their metaclass
1796
- BasicObjectClass.$$class = ClassClass;
1797
- ObjectClass.$$class = ClassClass;
1798
- ModuleClass.$$class = ClassClass;
1799
- ClassClass.$$class = ClassClass;
1770
+ BasicObject.$$class = Class;
1771
+ _Object.$$class = Class;
1772
+ Module.$$class = Class;
1773
+ Class.$$class = Class;
1800
1774
 
1801
1775
  // Fix superclasses of booted classes
1802
- BasicObjectClass.$$super = null;
1803
- ObjectClass.$$super = BasicObjectClass;
1804
- ModuleClass.$$super = ObjectClass;
1805
- ClassClass.$$super = ModuleClass;
1806
-
1807
- BasicObjectClass.$$parent = null;
1808
- ObjectClass.$$parent = BasicObjectClass;
1809
- ModuleClass.$$parent = ObjectClass;
1810
- ClassClass.$$parent = ModuleClass;
1811
-
1812
- Opal.base = ObjectClass;
1813
- BasicObjectClass.$$scope = ObjectClass.$$scope = Opal;
1814
- BasicObjectClass.$$orig_scope = ObjectClass.$$orig_scope = Opal;
1815
-
1816
- ModuleClass.$$scope = ObjectClass.$$scope;
1817
- ModuleClass.$$orig_scope = ObjectClass.$$orig_scope;
1818
- ClassClass.$$scope = ObjectClass.$$scope;
1819
- ClassClass.$$orig_scope = ObjectClass.$$orig_scope;
1820
-
1821
- ObjectClass.$$proto.toString = function() {
1776
+ BasicObject.$$super = null;
1777
+ _Object.$$super = BasicObject;
1778
+ Module.$$super = _Object;
1779
+ Class.$$super = Module;
1780
+
1781
+ BasicObject.$$parent = null;
1782
+ _Object.$$parent = BasicObject;
1783
+ Module.$$parent = _Object;
1784
+ Class.$$parent = Module;
1785
+
1786
+ Opal.base = _Object;
1787
+ BasicObject.$$scope = _Object.$$scope = Opal;
1788
+ BasicObject.$$orig_scope = _Object.$$orig_scope = Opal;
1789
+
1790
+ Module.$$scope = _Object.$$scope;
1791
+ Module.$$orig_scope = _Object.$$orig_scope;
1792
+ Class.$$scope = _Object.$$scope;
1793
+ Class.$$orig_scope = _Object.$$orig_scope;
1794
+
1795
+ _Object.$$proto.toString = function() {
1822
1796
  return this.$to_s();
1823
1797
  };
1824
1798
 
1825
- ObjectClass.$$proto.$require = Opal.require;
1799
+ _Object.$$proto.$require = Opal.require;
1826
1800
 
1827
- Opal.top = new ObjectClass.$$alloc();
1801
+ Opal.top = new _Object.$$alloc();
1828
1802
 
1829
1803
  // Nil
1830
- Opal.klass(ObjectClass, ObjectClass, 'NilClass', NilClass);
1831
- var nil = Opal.nil = new NilClass();
1804
+ Opal.klass(_Object, _Object, 'NilClass', NilClass_alloc);
1805
+ nil = Opal.nil = new NilClass_alloc();
1832
1806
  nil.$$id = nil_id;
1833
1807
  nil.call = nil.apply = function() { throw Opal.LocalJumpError.$new('no block given'); };
1834
1808
 
@@ -1842,6 +1816,7 @@ if (typeof(global) !== 'undefined') {
1842
1816
  global.Opal = this.Opal;
1843
1817
  Opal.global = global;
1844
1818
  }
1819
+
1845
1820
  if (typeof(window) !== 'undefined') {
1846
1821
  window.Opal = this.Opal;
1847
1822
  Opal.global = window;