opal 0.8.1 → 0.9.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (331) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/.gitmodules +3 -3
  4. data/.jshintrc +17 -20
  5. data/.travis.yml +22 -11
  6. data/CHANGELOG.md +51 -1
  7. data/CODE_OF_CONDUCT.md +15 -0
  8. data/CONTRIBUTING.md +125 -9
  9. data/Gemfile +1 -1
  10. data/Guardfile +2 -2
  11. data/README.md +95 -29
  12. data/Rakefile +1 -1
  13. data/benchmark/benchmarks +103 -0
  14. data/benchmark/bm_array_flatten.rb +9 -0
  15. data/benchmark/bm_array_intersection_numbers.rb +7 -0
  16. data/benchmark/bm_array_intersection_objects.rb +7 -0
  17. data/benchmark/bm_array_intersection_strings.rb +7 -0
  18. data/benchmark/bm_array_join_ary.rb +9 -0
  19. data/benchmark/bm_array_minus_numbers.rb +7 -0
  20. data/benchmark/bm_array_minus_objects.rb +7 -0
  21. data/benchmark/bm_array_minus_strings.rb +7 -0
  22. data/benchmark/bm_array_union_numbers.rb +7 -0
  23. data/benchmark/bm_array_union_objects.rb +7 -0
  24. data/benchmark/bm_array_union_strings.rb +7 -0
  25. data/benchmark/bm_array_uniq_bang_numbers.rb +5 -0
  26. data/benchmark/bm_array_uniq_bang_objects.rb +5 -0
  27. data/benchmark/bm_array_uniq_bang_strings.rb +5 -0
  28. data/benchmark/bm_array_uniq_numbers.rb +5 -0
  29. data/benchmark/bm_array_uniq_objects.rb +5 -0
  30. data/benchmark/bm_array_uniq_strings.rb +5 -0
  31. data/benchmark/bm_dispatch_bind_table.rb +57 -0
  32. data/benchmark/bm_dispatch_code_gen.rb +65 -0
  33. data/benchmark/bm_dispatch_code_gen_if.rb +64 -0
  34. data/benchmark/bm_dispatch_hardcoded.rb +44 -0
  35. data/benchmark/bm_dispatch_send.rb +38 -0
  36. data/benchmark/bm_dispatch_send_table.rb +57 -0
  37. data/benchmark/bm_hash_assoc_object.rb +11 -0
  38. data/benchmark/bm_hash_assoc_string.rb +9 -0
  39. data/benchmark/bm_hash_clone_object.rb +9 -0
  40. data/benchmark/bm_hash_clone_string.rb +9 -0
  41. data/benchmark/bm_hash_delete_object.rb +11 -0
  42. data/benchmark/bm_hash_delete_string.rb +9 -0
  43. data/benchmark/bm_hash_each_key_object.rb +9 -0
  44. data/benchmark/bm_hash_each_key_string.rb +9 -0
  45. data/benchmark/bm_hash_each_object.rb +9 -0
  46. data/benchmark/bm_hash_each_string.rb +9 -0
  47. data/benchmark/bm_hash_each_value_object.rb +9 -0
  48. data/benchmark/bm_hash_each_value_string.rb +9 -0
  49. data/benchmark/bm_hash_element_reference_object.rb +11 -0
  50. data/benchmark/bm_hash_element_reference_string.rb +9 -0
  51. data/benchmark/bm_hash_element_set_object.rb +5 -0
  52. data/benchmark/bm_hash_element_set_string.rb +5 -0
  53. data/benchmark/bm_hash_equal_value_object.rb +14 -0
  54. data/benchmark/bm_hash_equal_value_string.rb +11 -0
  55. data/benchmark/bm_hash_fetch_object.rb +11 -0
  56. data/benchmark/bm_hash_fetch_string.rb +9 -0
  57. data/benchmark/bm_hash_flatten_object.rb +9 -0
  58. data/benchmark/bm_hash_flatten_string.rb +9 -0
  59. data/benchmark/bm_hash_has_key_object.rb +11 -0
  60. data/benchmark/bm_hash_has_key_string.rb +9 -0
  61. data/benchmark/bm_hash_has_value_object.rb +9 -0
  62. data/benchmark/bm_hash_has_value_string.rb +9 -0
  63. data/benchmark/bm_hash_hash_object.rb +9 -0
  64. data/benchmark/bm_hash_hash_string.rb +9 -0
  65. data/benchmark/bm_hash_inspect_object.rb +9 -0
  66. data/benchmark/bm_hash_inspect_string.rb +9 -0
  67. data/benchmark/bm_hash_invert_object.rb +9 -0
  68. data/benchmark/bm_hash_invert_string.rb +9 -0
  69. data/benchmark/bm_hash_keep_if_object.rb +9 -0
  70. data/benchmark/bm_hash_keep_if_string.rb +9 -0
  71. data/benchmark/bm_hash_key_object.rb +9 -0
  72. data/benchmark/bm_hash_key_string.rb +9 -0
  73. data/benchmark/bm_hash_keys_object.rb +9 -0
  74. data/benchmark/bm_hash_keys_string.rb +9 -0
  75. data/benchmark/bm_hash_literal_mixed_large.rb +3 -0
  76. data/benchmark/bm_hash_literal_mixed_small.rb +3 -0
  77. data/benchmark/bm_hash_literal_object_large.rb +4 -0
  78. data/benchmark/bm_hash_literal_object_small.rb +3 -0
  79. data/benchmark/bm_hash_literal_string_large.rb +4 -0
  80. data/benchmark/bm_hash_literal_string_small.rb +3 -0
  81. data/benchmark/bm_hash_merge_object.rb +22 -0
  82. data/benchmark/bm_hash_merge_string.rb +18 -0
  83. data/benchmark/bm_hash_rassoc_object.rb +9 -0
  84. data/benchmark/bm_hash_rassoc_string.rb +9 -0
  85. data/benchmark/bm_hash_rehash_object.rb +9 -0
  86. data/benchmark/bm_hash_rehash_string.rb +9 -0
  87. data/benchmark/bm_hash_reject_bang_object.rb +9 -0
  88. data/benchmark/bm_hash_reject_bang_string.rb +9 -0
  89. data/benchmark/bm_hash_reject_object.rb +9 -0
  90. data/benchmark/bm_hash_reject_string.rb +9 -0
  91. data/benchmark/bm_hash_replace_object.rb +18 -0
  92. data/benchmark/bm_hash_replace_string.rb +14 -0
  93. data/benchmark/bm_hash_select_bang_object.rb +9 -0
  94. data/benchmark/bm_hash_select_bang_string.rb +9 -0
  95. data/benchmark/bm_hash_select_object.rb +9 -0
  96. data/benchmark/bm_hash_select_string.rb +9 -0
  97. data/benchmark/bm_hash_shift_object.rb +10 -0
  98. data/benchmark/bm_hash_shift_string.rb +10 -0
  99. data/benchmark/bm_hash_to_a_object.rb +9 -0
  100. data/benchmark/bm_hash_to_a_string.rb +9 -0
  101. data/benchmark/bm_hash_to_h_object.rb +10 -0
  102. data/benchmark/bm_hash_to_h_string.rb +10 -0
  103. data/benchmark/bm_hash_values_object.rb +9 -0
  104. data/benchmark/bm_hash_values_string.rb +9 -0
  105. data/benchmark/run.rb +48 -0
  106. data/bin/opal-mspec +1 -1
  107. data/bin/opal-repl +4 -4
  108. data/docs/compiled_ruby.md +214 -56
  109. data/docs/configuring_gems.md +2 -2
  110. data/docs/faq.md +2 -2
  111. data/docs/getting_started.md +19 -2
  112. data/docs/jquery.md +5 -5
  113. data/docs/opal_parser.md +53 -0
  114. data/docs/unsupported_features.md +2 -2
  115. data/docs/upgrading.md +22 -0
  116. data/docs/using_sprockets.md +15 -0
  117. data/examples/rack/config.ru +13 -0
  118. data/examples/sinatra/config.ru +4 -5
  119. data/lib/mspec/opal/runner.rb +54 -11
  120. data/lib/opal.rb +1 -1
  121. data/lib/opal/builder.rb +1 -1
  122. data/lib/opal/builder_processors.rb +1 -1
  123. data/lib/opal/cli.rb +17 -13
  124. data/lib/opal/cli_options.rb +1 -1
  125. data/lib/opal/compiler.rb +12 -0
  126. data/lib/opal/config.rb +4 -0
  127. data/lib/opal/nodes/arglist.rb +5 -7
  128. data/lib/opal/nodes/call.rb +6 -1
  129. data/lib/opal/nodes/call_special.rb +74 -0
  130. data/lib/opal/nodes/def.rb +35 -28
  131. data/lib/opal/nodes/definitions.rb +3 -5
  132. data/lib/opal/nodes/for.rb +13 -0
  133. data/lib/opal/nodes/helpers.rb +15 -1
  134. data/lib/opal/nodes/if.rb +5 -5
  135. data/lib/opal/nodes/iter.rb +6 -1
  136. data/lib/opal/nodes/literal.rb +1 -1
  137. data/lib/opal/nodes/logic.rb +2 -2
  138. data/lib/opal/nodes/masgn.rb +1 -2
  139. data/lib/opal/nodes/module.rb +2 -1
  140. data/lib/opal/nodes/rescue.rb +10 -1
  141. data/lib/opal/nodes/scope.rb +8 -2
  142. data/lib/opal/nodes/singleton_class.rb +1 -1
  143. data/lib/opal/nodes/top.rb +11 -0
  144. data/lib/opal/nodes/variables.rb +4 -4
  145. data/lib/opal/parser.rb +21 -3
  146. data/lib/opal/parser/grammar.rb +3115 -2961
  147. data/lib/opal/parser/grammar.y +29 -6
  148. data/lib/opal/parser/lexer.rb +18 -8
  149. data/lib/opal/sprockets.rb +85 -0
  150. data/lib/opal/sprockets/processor.rb +11 -35
  151. data/lib/opal/sprockets/server.rb +3 -15
  152. data/lib/opal/version.rb +2 -2
  153. data/opal.gemspec +4 -4
  154. data/opal/README.md +9 -0
  155. data/opal/corelib/array.rb +433 -181
  156. data/opal/corelib/basic_object.rb +48 -4
  157. data/opal/corelib/boolean.rb +15 -6
  158. data/opal/corelib/class.rb +6 -5
  159. data/opal/corelib/comparable.rb +12 -0
  160. data/opal/corelib/complex.rb +282 -0
  161. data/opal/corelib/constants.rb +9 -0
  162. data/opal/corelib/enumerable.rb +83 -34
  163. data/opal/corelib/enumerator.rb +3 -1
  164. data/opal/corelib/error.rb +49 -10
  165. data/opal/corelib/file.rb +1 -0
  166. data/opal/corelib/hash.rb +353 -577
  167. data/opal/corelib/helpers.rb +20 -0
  168. data/opal/corelib/kernel.rb +114 -59
  169. data/opal/corelib/math.rb +470 -0
  170. data/opal/corelib/method.rb +11 -2
  171. data/opal/corelib/module.rb +96 -96
  172. data/opal/corelib/{nil_class.rb → nil.rb} +20 -1
  173. data/opal/corelib/number.rb +751 -0
  174. data/opal/corelib/numeric.rb +77 -437
  175. data/opal/corelib/proc.rb +81 -1
  176. data/opal/corelib/process.rb +27 -0
  177. data/opal/corelib/rational.rb +358 -0
  178. data/opal/corelib/regexp.rb +156 -27
  179. data/opal/corelib/runtime.js +724 -335
  180. data/opal/corelib/string.rb +93 -104
  181. data/opal/corelib/string/encoding.rb +177 -0
  182. data/opal/corelib/string/inheritance.rb +2 -0
  183. data/opal/corelib/struct.rb +105 -18
  184. data/opal/corelib/time.rb +267 -146
  185. data/opal/corelib/unsupported.rb +216 -0
  186. data/opal/corelib/variables.rb +0 -6
  187. data/opal/opal.rb +8 -22
  188. data/opal/opal/base.rb +9 -0
  189. data/opal/opal/mini.rb +17 -0
  190. data/spec/README.md +1 -1
  191. data/spec/filters/bugs/array.rb +38 -136
  192. data/spec/filters/bugs/{basic_object.rb → basicobject.rb} +14 -15
  193. data/spec/filters/bugs/class.rb +6 -12
  194. data/spec/filters/bugs/complex.rb +3 -0
  195. data/spec/filters/bugs/date.rb +162 -10
  196. data/spec/filters/bugs/enumerable.rb +31 -58
  197. data/spec/filters/bugs/enumerator.rb +42 -0
  198. data/spec/filters/bugs/exception.rb +66 -10
  199. data/spec/filters/bugs/float.rb +17 -0
  200. data/spec/filters/bugs/hash.rb +11 -97
  201. data/spec/filters/bugs/inheritance.rb +5 -0
  202. data/spec/filters/bugs/integer.rb +28 -0
  203. data/spec/filters/bugs/kernel.rb +304 -12
  204. data/spec/filters/bugs/language.rb +133 -399
  205. data/spec/filters/bugs/language_opal.rb +88 -0
  206. data/spec/filters/bugs/module.rb +203 -62
  207. data/spec/filters/bugs/numeric.rb +32 -0
  208. data/spec/filters/bugs/proc.rb +39 -0
  209. data/spec/filters/bugs/range.rb +148 -0
  210. data/spec/filters/bugs/regexp.rb +168 -0
  211. data/spec/filters/bugs/set.rb +46 -3
  212. data/spec/filters/bugs/singleton.rb +1 -2
  213. data/spec/filters/bugs/string.rb +59 -90
  214. data/spec/filters/bugs/strscan.rb +80 -0
  215. data/spec/filters/bugs/struct.rb +10 -20
  216. data/spec/filters/bugs/time.rb +17 -184
  217. data/spec/filters/bugs/unboundmethod.rb +22 -0
  218. data/spec/filters/unsupported/array.rb +163 -0
  219. data/spec/filters/unsupported/basicobject.rb +14 -0
  220. data/spec/filters/unsupported/bignum.rb +46 -0
  221. data/spec/filters/unsupported/class.rb +4 -0
  222. data/spec/filters/unsupported/delegator.rb +5 -0
  223. data/spec/filters/unsupported/enumerable.rb +11 -0
  224. data/spec/filters/unsupported/enumerator.rb +8 -9
  225. data/spec/filters/unsupported/fixnum.rb +14 -0
  226. data/spec/filters/unsupported/float.rb +41 -7
  227. data/spec/filters/unsupported/freeze.rb +45 -0
  228. data/spec/filters/unsupported/hash.rb +50 -0
  229. data/spec/filters/unsupported/integer.rb +3 -0
  230. data/spec/filters/unsupported/kernel.rb +31 -0
  231. data/spec/filters/unsupported/language.rb +17 -0
  232. data/spec/filters/unsupported/matchdata.rb +30 -0
  233. data/spec/filters/unsupported/math.rb +3 -0
  234. data/spec/filters/unsupported/module.rb +5 -3
  235. data/spec/filters/unsupported/pathname.rb +3 -0
  236. data/spec/filters/unsupported/privacy.rb +136 -0
  237. data/spec/filters/unsupported/proc.rb +3 -0
  238. data/spec/filters/unsupported/regexp.rb +59 -0
  239. data/spec/filters/unsupported/set.rb +4 -0
  240. data/spec/filters/unsupported/{marshal.rb → singleton.rb} +4 -2
  241. data/spec/filters/unsupported/{mutable_strings.rb → string.rb} +456 -336
  242. data/spec/filters/unsupported/struct.rb +3 -0
  243. data/spec/filters/unsupported/symbol.rb +5 -0
  244. data/spec/filters/unsupported/taint.rb +16 -0
  245. data/spec/filters/unsupported/thread.rb +5 -0
  246. data/spec/filters/unsupported/time.rb +197 -16
  247. data/spec/lib/cli_spec.rb +14 -4
  248. data/spec/lib/compiler_spec.rb +9 -1
  249. data/spec/lib/parser/call_spec.rb +18 -0
  250. data/spec/lib/parser/not_spec.rb +2 -8
  251. data/spec/lib/sprockets_spec.rb +24 -0
  252. data/spec/opal/core/array/intersection_spec.rb +38 -0
  253. data/spec/opal/core/array/minus_spec.rb +38 -0
  254. data/spec/opal/core/array/union_spec.rb +38 -0
  255. data/spec/opal/core/array/uniq_spec.rb +49 -0
  256. data/spec/opal/core/exception_spec.rb +7 -0
  257. data/spec/opal/core/fixtures/require_tree_with_dot/file 1.rb +1 -0
  258. data/spec/opal/core/fixtures/require_tree_with_dot/file 2.rb +1 -0
  259. data/spec/opal/core/fixtures/require_tree_with_dot/file 3.rb +1 -0
  260. data/spec/opal/core/fixtures/require_tree_with_dot/index.rb +3 -0
  261. data/spec/opal/core/hash/internals_spec.rb +332 -0
  262. data/spec/opal/core/helpers_spec.rb +14 -0
  263. data/spec/opal/core/kernel/freeze_spec.rb +1 -1
  264. data/spec/opal/core/kernel/raise_spec.rb +13 -0
  265. data/spec/opal/core/kernel/require_tree_spec.rb +9 -0
  266. data/spec/opal/core/language/class_spec.rb +55 -0
  267. data/spec/opal/core/language/fixtures/send.rb +1 -0
  268. data/spec/opal/core/language/keyword_arguments_spec.rb +11 -0
  269. data/spec/opal/core/language/send_spec.rb +5 -0
  270. data/spec/opal/core/method/to_proc_spec.rb +28 -0
  271. data/spec/opal/core/module/name_spec.rb +0 -17
  272. data/spec/opal/core/runtime/bridged_classes_spec.rb +2 -2
  273. data/spec/opal/core/runtime/eval_spec.rb +1 -1
  274. data/spec/opal/core/runtime/method_missing_spec.rb +6 -0
  275. data/spec/opal/core/runtime_spec.rb +51 -0
  276. data/spec/opal/stdlib/js_spec.rb +66 -0
  277. data/spec/opal/stdlib/native/hash_spec.rb +36 -0
  278. data/spec/rubyspecs +152 -273
  279. data/spec/spec_helper.rb +10 -11
  280. data/stdlib/base64.rb +9 -9
  281. data/stdlib/benchmark.rb +551 -4
  282. data/stdlib/console.rb +94 -0
  283. data/stdlib/date.rb +1 -1
  284. data/stdlib/encoding.rb +1 -170
  285. data/stdlib/js.rb +56 -0
  286. data/stdlib/json.rb +9 -14
  287. data/stdlib/math.rb +1 -370
  288. data/stdlib/native.rb +133 -63
  289. data/stdlib/nodejs/file.rb +5 -0
  290. data/stdlib/nodejs/fileutils.rb +13 -6
  291. data/stdlib/nodejs/node_modules/js-yaml/node_modules/argparse/README.md +1 -1
  292. data/stdlib/opal-parser.rb +1 -2
  293. data/stdlib/ostruct.rb +65 -6
  294. data/stdlib/pp.rb +2 -4
  295. data/stdlib/rbconfig.rb +1 -3
  296. data/stdlib/strscan.rb +164 -28
  297. data/tasks/benchmarking.rake +88 -0
  298. data/tasks/testing.rake +181 -55
  299. data/{lib/mspec/opal/special_calls.rb → tasks/testing/mspec_special_calls.rb} +1 -1
  300. data/{lib/mspec/opal/sprockets.js → tasks/testing/phantomjs1-sprockets.js} +17 -6
  301. data/test/opal/test_keyword.rb +590 -0
  302. data/vendored-minitest/minitest.rb +2 -2
  303. data/vendored-minitest/test/unit.rb +5 -0
  304. metadata +229 -62
  305. data/benchmarks/operators.rb +0 -11
  306. data/benchmarks/prova.js.rb +0 -13
  307. data/docs/libraries.md +0 -36
  308. data/lib/mspec/opal/new.html.erb +0 -1
  309. data/lib/mspec/opal/rake_task.rb +0 -248
  310. data/opal/corelib/match_data.rb +0 -128
  311. data/spec/filters/bugs/math.rb +0 -95
  312. data/spec/filters/bugs/nil.rb +0 -7
  313. data/spec/filters/bugs/opal.rb +0 -9
  314. data/spec/filters/bugs/regular_expressions.rb +0 -41
  315. data/spec/filters/bugs/stringscanner.rb +0 -33
  316. data/spec/filters/unsupported/encoding.rb +0 -102
  317. data/spec/filters/unsupported/frozen.rb +0 -92
  318. data/spec/filters/unsupported/hash_compare_by_identity.rb +0 -16
  319. data/spec/filters/unsupported/integer_size.rb +0 -59
  320. data/spec/filters/unsupported/method_added.rb +0 -10
  321. data/spec/filters/unsupported/private_constants.rb +0 -30
  322. data/spec/filters/unsupported/private_methods.rb +0 -55
  323. data/spec/filters/unsupported/random.rb +0 -4
  324. data/spec/filters/unsupported/rational_numbers.rb +0 -4
  325. data/spec/filters/unsupported/regular_expressions.rb +0 -137
  326. data/spec/filters/unsupported/ruby_exe.rb +0 -5
  327. data/spec/filters/unsupported/symbols.rb +0 -17
  328. data/spec/filters/unsupported/tainted.rb +0 -180
  329. data/spec/filters/unsupported/trusted.rb +0 -88
  330. data/stdlib/process.rb +0 -10
  331. data/tasks/documenting.rake +0 -37
@@ -1,5 +1,6 @@
1
1
  class RegexpError < StandardError; end
2
- class Regexp
2
+
3
+ class Regexp < `RegExp`
3
4
  IGNORECASE = 1
4
5
  MULTILINE = 4
5
6
 
@@ -67,35 +68,30 @@ class Regexp
67
68
 
68
69
  def new(regexp, options = undefined)
69
70
  %x{
70
- // Play nice with IE8
71
- if (regexp.$$is_string && regexp.substr(regexp.length-1, 1) == "\\") {
71
+ if (regexp.$$is_regexp) {
72
+ return new RegExp(regexp);
73
+ }
74
+
75
+ regexp = #{Opal.coerce_to!(regexp, String, :to_str)};
76
+
77
+ if (regexp.charAt(regexp.length - 1) === '\\') {
72
78
  #{raise RegexpError, "too short escape sequence: /#{regexp}/"}
73
79
  }
74
-
75
- if (options == undefined || #{!options}) {
76
- options = undefined;
80
+
81
+ if (options === undefined || #{!options}) {
82
+ return new RegExp(regexp);
77
83
  }
78
-
79
- if (options != undefined) {
80
- if (regexp.$$is_regexp) {
81
- // options are already in regex
82
- options = undefined;
83
- }
84
- else if (options.$$is_number) {
85
- var result = '';
86
- if (#{IGNORECASE} & options) {
87
- result += 'i';
88
- }
89
- if (#{MULTILINE} & options) {
90
- result += 'm';
91
- }
92
- options = result;
93
- }
94
- else {
95
- options = 'i';
96
- }
97
- }
98
-
84
+
85
+ if (options.$$is_number) {
86
+ var temp = '';
87
+ if (#{IGNORECASE} & options) { temp += 'i'; }
88
+ if (#{MULTILINE} & options) { temp += 'm'; }
89
+ options = temp;
90
+ }
91
+ else {
92
+ options = 'i';
93
+ }
94
+
99
95
  return new RegExp(regexp, options);
100
96
  }
101
97
  end
@@ -199,6 +195,139 @@ class Regexp
199
195
  return result;
200
196
  }
201
197
  end
198
+
199
+ def casefold?
200
+ `self.ignoreCase`
201
+ end
202
202
 
203
203
  alias to_s source
204
204
  end
205
+
206
+ class MatchData
207
+ attr_reader :post_match, :pre_match, :regexp, :string
208
+
209
+ def initialize(regexp, match_groups)
210
+ $~ = self
211
+ @regexp = regexp
212
+ @begin = `match_groups.index`
213
+ @string = `match_groups.input`
214
+ @pre_match = `match_groups.input.slice(0, match_groups.index)`
215
+ @post_match = `match_groups.input.slice(match_groups.index + match_groups[0].length)`
216
+ @matches = []
217
+
218
+ %x{
219
+ for (var i = 0, length = match_groups.length; i < length; i++) {
220
+ var group = match_groups[i];
221
+
222
+ if (group == null) {
223
+ #@matches.push(nil);
224
+ }
225
+ else {
226
+ #@matches.push(group);
227
+ }
228
+ }
229
+ }
230
+ end
231
+
232
+ def [](*args)
233
+ @matches[*args]
234
+ end
235
+
236
+ def offset(n)
237
+ %x{
238
+ if (n !== 0) {
239
+ #{raise ArgumentError, 'MatchData#offset only supports 0th element'}
240
+ }
241
+ return [self.begin, self.begin + self.matches[n].length];
242
+ }
243
+ end
244
+
245
+ def ==(other)
246
+ return false unless MatchData === other
247
+
248
+ `self.string == other.string` &&
249
+ `self.regexp.toString() == other.regexp.toString()` &&
250
+ `self.pre_match == other.pre_match` &&
251
+ `self.post_match == other.post_match` &&
252
+ `self.begin == other.begin`
253
+ end
254
+
255
+ alias eql? ==
256
+
257
+ def begin(n)
258
+ %x{
259
+ if (n !== 0) {
260
+ #{raise ArgumentError, 'MatchData#begin only supports 0th element'}
261
+ }
262
+ return self.begin;
263
+ }
264
+ end
265
+
266
+ def end(n)
267
+ %x{
268
+ if (n !== 0) {
269
+ #{raise ArgumentError, 'MatchData#end only supports 0th element'}
270
+ }
271
+ return self.begin + self.matches[n].length;
272
+ }
273
+ end
274
+
275
+ def captures
276
+ `#@matches.slice(1)`
277
+ end
278
+
279
+ def inspect
280
+ %x{
281
+ var str = "#<MatchData " + #{`#@matches[0]`.inspect};
282
+
283
+ for (var i = 1, length = #@matches.length; i < length; i++) {
284
+ str += " " + i + ":" + #{`#@matches[i]`.inspect};
285
+ }
286
+
287
+ return str + ">";
288
+ }
289
+ end
290
+
291
+ def length
292
+ `#@matches.length`
293
+ end
294
+
295
+ alias size length
296
+
297
+ def to_a
298
+ @matches
299
+ end
300
+
301
+ def to_s
302
+ `#@matches[0]`
303
+ end
304
+
305
+ def values_at(*args)
306
+ %x{
307
+ var i, a, index, values = [];
308
+
309
+ for (i = 0; i < args.length; i++) {
310
+
311
+ if (args[i].$$is_range) {
312
+ a = #{`args[i]`.to_a};
313
+ a.unshift(i, 1);
314
+ Array.prototype.splice.apply(args, a);
315
+ }
316
+
317
+ index = #{Opal.coerce_to!(`args[i]`, Integer, :to_int)};
318
+
319
+ if (index < 0) {
320
+ index += #@matches.length;
321
+ if (index < 0) {
322
+ values.push(nil);
323
+ continue;
324
+ }
325
+ }
326
+
327
+ values.push(#@matches[index]);
328
+ }
329
+
330
+ return values;
331
+ }
332
+ end
333
+ end
@@ -8,7 +8,7 @@
8
8
  var Opal = this.Opal = {};
9
9
 
10
10
  // All bridged classes - keep track to donate methods from Object
11
- var bridged_classes = Opal.bridged_classes = [];
11
+ var bridges = {};
12
12
 
13
13
  // TopScope is used for inheriting constants from the top scope
14
14
  var TopScope = function(){};
@@ -51,6 +51,9 @@
51
51
  // Exit function, this should be replaced by platform specific implementation
52
52
  // (See nodejs and phantom for examples)
53
53
  Opal.exit = function(status) { if (Opal.gvars.DEBUG) console.log('Exited with status '+status); };
54
+
55
+ // keeps track of exceptions for $!
56
+ Opal.exceptions = [];
54
57
 
55
58
  /**
56
59
  Get a constant on the given scope. Every class and module in Opal has a
@@ -72,7 +75,7 @@
72
75
  var constant = this[name];
73
76
 
74
77
  if (constant == null) {
75
- return this.base.$const_missing(name);
78
+ return this.base.$const_get(name);
76
79
  }
77
80
 
78
81
  return constant;
@@ -95,9 +98,7 @@
95
98
  const_scope.constants = [];
96
99
 
97
100
  if (id) {
98
- klass.$$orig_scope = base;
99
- base[id] = base.constructor[id] = klass;
100
- base.constants.push(id);
101
+ Opal.cdecl(base, id, klass)
101
102
  }
102
103
  }
103
104
 
@@ -130,46 +131,54 @@
130
131
  */
131
132
  Opal.klass = function(base, superklass, id, constructor) {
132
133
  // If base is an object, use its class
133
- if (!base.$$is_class) {
134
+ if (!base.$$is_class && !base.$$is_module) {
134
135
  base = base.$$class;
135
136
  }
136
137
 
137
- // Not specifying a superclass means we can assume it to be Object
138
- if (superklass === null) {
139
- superklass = ObjectClass;
140
- }
141
-
142
- var klass = base.$$scope[id];
138
+ var klass = base.$$scope[id],
139
+ bridged = typeof(superklass) === 'function';
143
140
 
144
- // If a constant exists in the scope, then we must use that
145
- if ($hasOwn.call(base.$$scope, id) && klass.$$orig_scope === base.$$scope) {
141
+ // If the class exists in the scope, then we must use that
142
+ if (klass && klass.$$orig_scope === base.$$scope) {
146
143
  // Make sure the existing constant is a class, or raise error
147
144
  if (!klass.$$is_class) {
148
145
  throw Opal.TypeError.$new(id + " is not a class");
149
146
  }
150
147
 
151
148
  // Make sure existing class has same superclass
152
- if (superklass !== klass.$$super && superklass !== ObjectClass) {
149
+ if (superklass && klass.$$super !== superklass) {
153
150
  throw Opal.TypeError.$new("superclass mismatch for class " + id);
154
151
  }
152
+
153
+ return klass;
155
154
  }
156
- else if (typeof(superklass) === 'function') {
157
- // passed native constructor as superklass, so bridge it as ruby class
158
- return bridge_class(id, superklass, base);
155
+
156
+ // Not specifying a superclass means we can assume it to be Object
157
+ if (superklass === null) {
158
+ superklass = ObjectClass;
159
159
  }
160
- else {
161
- // if class doesnt exist, create a new one with given superclass
162
- klass = boot_class(superklass, constructor);
163
160
 
164
- // name class using base (e.g. Foo or Foo::Baz)
165
- klass.$$name = id;
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);
165
+
166
+ // name class using base (e.g. Foo or Foo::Baz)
167
+ klass.$$name = id;
166
168
 
167
- // every class gets its own constant scope, inherited from current scope
168
- create_scope(base.$$scope, klass, id);
169
+ // mark the object as a class
170
+ klass.$$is_class = true;
169
171
 
170
- // Name new class directly onto current scope (Opal.Foo.Baz = klass)
171
- base[id] = base.$$scope[id] = klass;
172
+ // every class gets its own constant scope, inherited from current scope
173
+ create_scope(base.$$scope, klass, id);
172
174
 
175
+ // Name new class directly onto current scope (Opal.Foo.Baz = klass)
176
+ base[id] = base.$$scope[id] = klass;
177
+
178
+ if (bridged) {
179
+ Opal.bridge(klass, superklass);
180
+ }
181
+ else {
173
182
  // Copy all parent constants to child, unless parent is Object
174
183
  if (superklass !== ObjectClass && superklass !== BasicObjectClass) {
175
184
  donate_constants(superklass, klass);
@@ -256,8 +265,16 @@
256
265
  // Maybe there are some browsers not abiding (IE6?)
257
266
  module.constructor = constructor;
258
267
 
259
- // @property $$is_class Clearly mark this as a class-like
260
- module.$$is_class = true;
268
+ if (superklass === ModuleClass) {
269
+ // @property $$is_module Clearly mark this as a module
270
+ module.$$is_module = true;
271
+ module.$$class = ModuleClass;
272
+ }
273
+ else {
274
+ // @property $$is_class Clearly mark this as a class
275
+ module.$$is_class = true;
276
+ module.$$class = ClassClass;
277
+ }
261
278
 
262
279
  // @property $$super the superclass, doesn't get changed by module inclusions
263
280
  module.$$super = superklass;
@@ -267,12 +284,6 @@
267
284
  // the last included module
268
285
  module.$$parent = superklass;
269
286
 
270
- // @property $$methods keeps track of methods defined on the class
271
- // but seems to be used just by `define_basic_object_method`
272
- // and for donating (Ruby) Object methods to bridged classes
273
- // TODO: check if it can be removed
274
- module.$$methods = [];
275
-
276
287
  // @property $$inc included modules
277
288
  module.$$inc = [];
278
289
  }
@@ -300,21 +311,29 @@
300
311
  Opal.module = function(base, id) {
301
312
  var module;
302
313
 
303
- if (!base.$$is_class) {
314
+ if (!base.$$is_class && !base.$$is_module) {
304
315
  base = base.$$class;
305
316
  }
306
317
 
307
318
  if ($hasOwn.call(base.$$scope, id)) {
308
319
  module = base.$$scope[id];
309
320
 
310
- if (!module.$$is_mod && module !== ObjectClass) {
321
+ if (!module.$$is_module && module !== ObjectClass) {
311
322
  throw Opal.TypeError.$new(id + " is not a module");
312
323
  }
313
324
  }
314
325
  else {
315
326
  module = boot_module_object();
327
+
328
+ // name module using base (e.g. Foo or Foo::Baz)
316
329
  module.$$name = id;
317
330
 
331
+ // mark the object as a module
332
+ module.$$is_module = true;
333
+
334
+ // initialize dependency tracking
335
+ module.$$dep = [];
336
+
318
337
  create_scope(base.$$scope, module, id);
319
338
 
320
339
  // Name new module directly onto current scope (Opal.Foo.Baz = module)
@@ -340,9 +359,6 @@
340
359
 
341
360
  setup_module_or_class_object(module, module_constructor, ModuleClass, module_prototype);
342
361
 
343
- module.$$is_mod = true;
344
- module.$$dep = [];
345
-
346
362
  return module;
347
363
  }
348
364
 
@@ -364,7 +380,7 @@
364
380
  return object.$$meta;
365
381
  }
366
382
 
367
- if (object.$$is_class) {
383
+ if (object.$$is_class || object.$$is_module) {
368
384
  return build_class_singleton_class(object);
369
385
  }
370
386
 
@@ -381,14 +397,14 @@
381
397
  @returns [RubyClass]
382
398
  */
383
399
  function build_class_singleton_class(klass) {
384
- var meta = new Opal.Class.$$alloc;
400
+ var meta = new Opal.Class.$$alloc();
385
401
 
386
402
  meta.$$class = Opal.Class;
387
403
  meta.$$proto = klass.constructor.prototype;
388
404
 
389
405
  meta.$$is_singleton = true;
406
+ meta.$$singleton_of = klass;
390
407
  meta.$$inc = [];
391
- meta.$$methods = [];
392
408
  meta.$$scope = klass.$$scope;
393
409
 
394
410
  return klass.$$meta = meta;
@@ -412,9 +428,95 @@
412
428
  meta.$$class = orig_class.$$class;
413
429
  meta.$$scope = orig_class.$$scope;
414
430
  meta.$$parent = orig_class;
431
+ meta.$$is_singleton = true;
432
+ meta.$$singleton_of = object;
433
+
415
434
  return object.$$meta = meta;
416
435
  }
417
436
 
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
+ }
479
+
480
+ if (ancestor === from) {
481
+ target.prototype[name] = body
482
+ break;
483
+ }
484
+ }
485
+ }
486
+ else {
487
+ target = arguments[0];
488
+ donator = arguments[1];
489
+
490
+ if (typeof(target) === "function") {
491
+ id = donator.$__id__();
492
+ methods = donator.$instance_methods();
493
+
494
+ for (i = methods.length - 1; i >= 0; i--) {
495
+ method = '$' + methods[i];
496
+
497
+ bridge(target, donator, method, donator.$$proto[method]);
498
+ }
499
+
500
+ if (!bridges[id]) {
501
+ bridges[id] = [];
502
+ }
503
+
504
+ bridges[id].push(target);
505
+ }
506
+ else {
507
+ bridged = bridges[target.$__id__()];
508
+
509
+ if (bridged) {
510
+ for (i = bridged.length - 1; i >= 0; i--) {
511
+ bridge(bridged[i], donator);
512
+ }
513
+
514
+ bridges[donator.$__id__()] = bridged.slice();
515
+ }
516
+ }
517
+ }
518
+ }
519
+
418
520
  /**
419
521
  The actual inclusion of a module into a class.
420
522
 
@@ -436,20 +538,21 @@
436
538
  @returns [null]
437
539
  */
438
540
  Opal.append_features = function(module, klass) {
439
- var included = klass.$$inc;
541
+ var iclass, donator, prototype, methods, id, i;
440
542
 
441
- // check if this module is already included in the klass
442
- for (var j = 0, jj = included.length; j < jj; j++) {
443
- if (included[j] === module) {
543
+ // check if this module is already included in the class
544
+ for (i = klass.$$inc.length - 1; i >= 0; i--) {
545
+ if (klass.$$inc[i] === module) {
444
546
  return;
445
547
  }
446
548
  }
447
549
 
448
- included.push(module);
550
+ klass.$$inc.push(module);
449
551
  module.$$dep.push(klass);
552
+ bridge(klass, module);
450
553
 
451
554
  // iclass
452
- var iclass = {
555
+ iclass = {
453
556
  $$name: module.$$name,
454
557
  $$proto: module.$$proto,
455
558
  $$parent: klass.$$parent,
@@ -459,28 +562,24 @@
459
562
 
460
563
  klass.$$parent = iclass;
461
564
 
462
- var donator = module.$$proto,
463
- prototype = klass.$$proto,
464
- methods = module.$$methods;
465
-
466
- for (var i = 0, length = methods.length; i < length; i++) {
467
- var method = methods[i], current;
565
+ donator = module.$$proto;
566
+ prototype = klass.$$proto;
567
+ methods = module.$instance_methods();
468
568
 
569
+ for (i = methods.length - 1; i >= 0; i--) {
570
+ id = '$' + methods[i];
469
571
 
470
- if ( prototype.hasOwnProperty(method) &&
471
- !(current = prototype[method]).$$donated && !current.$$stub ) {
472
- // if the target class already has a method of the same name defined
473
- // and that method was NOT donated, then it must be a method defined
474
- // by the class so we do not want to override it
475
- }
476
- else {
477
- prototype[method] = donator[method];
478
- prototype[method].$$donated = true;
572
+ // if the target class already has a method of the same name defined
573
+ // and that method was NOT donated, then it must be a method defined
574
+ // by the class so we do not want to override it
575
+ if ( prototype.hasOwnProperty(id) &&
576
+ !prototype[id].$$donated &&
577
+ !prototype[id].$$stub) {
578
+ continue;
479
579
  }
480
- }
481
580
 
482
- if (klass.$$dep) {
483
- donate_methods(klass, methods.slice(), true);
581
+ prototype[id] = donator[id];
582
+ prototype[id].$$donated = module;
484
583
  }
485
584
 
486
585
  donate_constants(module, klass);
@@ -540,68 +639,80 @@
540
639
  }
541
640
 
542
641
  /*
543
- * For performance, some core ruby classes are toll-free bridged to their
544
- * native javascript counterparts (e.g. a ruby Array is a javascript Array).
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).
545
644
  *
546
645
  * This method is used to setup a native constructor (e.g. Array), to have
547
- * its prototype act like a normal ruby class. Firstly, a new ruby class is
646
+ * its prototype act like a normal Ruby class. Firstly, a new Ruby class is
548
647
  * created using the native constructor so that its prototype is set as the
549
648
  * target for th new class. Note: all bridged classes are set to inherit
550
649
  * from Object.
551
650
  *
552
- * Bridged classes are tracked in `bridged_classes` array so that methods
553
- * defined on Object can be "donated" to all bridged classes. This allows
554
- * us to fake the inheritance of a native prototype from our Object
555
- * prototype.
556
- *
557
651
  * Example:
558
652
  *
559
- * bridge_class("Proc", Function);
653
+ * Opal.bridge(self, Function);
560
654
  *
561
- * @param [String] name the name of the ruby class to create
562
- * @param [Function] constructor native javascript constructor to use
563
- * @param [Object] base where the bridge class is being created. If none is supplied, the top level scope (Opal) will be used
564
- * @return [Class] returns new ruby class
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
565
658
  */
566
- function bridge_class(name, constructor, base) {
567
- var klass = boot_class_object(ObjectClass, constructor);
568
-
569
- klass.$$name = name;
570
-
571
- if (base === undefined) {
572
- base = Opal;
573
- }
574
- else {
575
- base = base.$$scope;
659
+ Opal.bridge = function(klass, constructor) {
660
+ if (constructor.$$bridge) {
661
+ throw Opal.ArgumentError.$new("already bridged");
576
662
  }
577
663
 
578
- create_scope(base, klass, name);
579
- bridged_classes.push(klass);
664
+ Opal.stub_subscribers.push(constructor.prototype);
665
+
666
+ constructor.prototype.$$class = klass;
667
+ constructor.$$bridge = klass;
580
668
 
581
- var object_methods = BasicObjectClass.$$methods.concat(ObjectClass.$$methods);
669
+ var ancestors = klass.$ancestors();
582
670
 
583
- for (var i = 0, len = object_methods.length; i < len; i++) {
584
- var meth = object_methods[i];
585
- constructor.prototype[meth] = ObjectClass.$$proto[meth];
671
+ // order important here, we have to bridge from the last ancestor to the
672
+ // bridged class
673
+ for (var i = ancestors.length - 1; i >= 0; i--) {
674
+ bridge(constructor, ancestors[i]);
586
675
  }
587
676
 
588
- add_stubs_subscriber(constructor.prototype);
677
+ for (var name in BasicObject.prototype) {
678
+ var method = BasicObject.prototype[method];
679
+
680
+ if (method && method.$$stub && !(name in constructor.prototype)) {
681
+ constructor.prototype[name] = method;
682
+ }
683
+ }
589
684
 
590
685
  return klass;
591
686
  }
592
687
 
688
+
593
689
  /*
594
690
  * constant assign
595
691
  */
596
692
  Opal.casgn = function(base_module, name, value) {
597
- var scope = base_module.$$scope;
693
+ function update(klass, name) {
694
+ klass.$$name = name;
598
695
 
599
- if (value.$$is_class && value.$$name === nil) {
600
- value.$$name = name;
696
+ for (name in klass.$$scope) {
697
+ var value = klass.$$scope[name];
698
+
699
+ if (value.$$name === nil && (value.$$is_class || value.$$is_module)) {
700
+ update(value, name)
701
+ }
702
+ }
601
703
  }
602
704
 
603
- if (value.$$is_class) {
604
- value.$$base_module = base_module;
705
+ var scope = base_module.$$scope;
706
+
707
+ 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) {
710
+ value.$$base_module = base_module;
711
+ }
712
+
713
+ if (value.$$name === nil && value.$$base_module.$$name !== nil) {
714
+ update(value, name);
715
+ }
605
716
  }
606
717
 
607
718
  scope.constants.push(name);
@@ -612,6 +723,12 @@
612
723
  * constant decl
613
724
  */
614
725
  Opal.cdecl = function(base_scope, name, value) {
726
+ if ((value.$$is_class || value.$$is_module) && value.$$orig_scope == null) {
727
+ value.$$name = name;
728
+ value.$$orig_scope = base_scope;
729
+ base_scope.constructor[name] = value;
730
+ }
731
+
615
732
  base_scope.constants.push(name);
616
733
  return base_scope[name] = value;
617
734
  };
@@ -631,6 +748,60 @@
631
748
  }
632
749
  };
633
750
 
751
+ /*
752
+ * Donate methods for a module.
753
+ */
754
+ function donate(module, jsid) {
755
+ var included_in = module.$$dep,
756
+ body = module.$$proto[jsid],
757
+ i, length, includee, dest, current,
758
+ klass_includees, j, jj, current_owner_index, module_index;
759
+
760
+ if (!included_in) {
761
+ return;
762
+ }
763
+
764
+ for (i = 0, length = included_in.length; i < length; i++) {
765
+ includee = included_in[i];
766
+ dest = includee.$$proto;
767
+ current = dest[jsid];
768
+
769
+ if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
770
+ // target class has already defined the same method name - do nothing
771
+ }
772
+ else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
773
+ // target class includes another module that has defined this method
774
+ klass_includees = includee.$$inc;
775
+
776
+ for (j = 0, jj = klass_includees.length; j < jj; j++) {
777
+ if (klass_includees[j] === current.$$donated) {
778
+ current_owner_index = j;
779
+ }
780
+ if (klass_includees[j] === module) {
781
+ module_index = j;
782
+ }
783
+ }
784
+
785
+ // only redefine method on class if the module was included AFTER
786
+ // the module which defined the current method body. Also make sure
787
+ // a module can overwrite a method it defined before
788
+ if (current_owner_index <= module_index) {
789
+ dest[jsid] = body;
790
+ dest[jsid].$$donated = module;
791
+ }
792
+ }
793
+ else {
794
+ // neither a class, or module included by class, has defined method
795
+ dest[jsid] = body;
796
+ dest[jsid].$$donated = module;
797
+ }
798
+
799
+ if (includee.$$dep) {
800
+ donate(includee, jsid);
801
+ }
802
+ }
803
+ };
804
+
634
805
  /*
635
806
  * Methods stubs are used to facilitate method_missing in opal. A stub is a
636
807
  * placeholder function which just calls `method_missing` on the receiver.
@@ -660,14 +831,18 @@
660
831
  * @param [Array] stubs an array of method stubs to add
661
832
  */
662
833
  Opal.add_stubs = function(stubs) {
663
- var subscribers = Opal.stub_subscribers;
664
- var subscriber;
834
+ var subscriber, subscribers = Opal.stub_subscribers,
835
+ i, ilength = stubs.length,
836
+ j, jlength = subscribers.length,
837
+ method_name, stub;
665
838
 
666
- for (var i = 0, length = stubs.length; i < length; i++) {
667
- var method_name = stubs[i], stub = stub_for(method_name);
839
+ for (i = 0; i < ilength; i++) {
840
+ method_name = stubs[i];
841
+ stub = stub_for(method_name);
668
842
 
669
- for (var j = 0; j < subscribers.length; j++) {
843
+ for (j = 0; j < jlength; j++) {
670
844
  subscriber = subscribers[j];
845
+
671
846
  if (!(method_name in subscriber)) {
672
847
  subscriber[method_name] = stub;
673
848
  }
@@ -675,17 +850,6 @@
675
850
  }
676
851
  };
677
852
 
678
- /*
679
- * Add a prototype to the subscribers list, and (TODO) add previously stubbed
680
- * methods.
681
- *
682
- * @param [Prototype]
683
- */
684
- function add_stubs_subscriber(prototype) {
685
- // TODO: Add previously stubbed methods too.
686
- Opal.stub_subscribers.push(prototype);
687
- }
688
-
689
853
  /*
690
854
  * Keep a list of prototypes that want method_missing stubs to be added.
691
855
  *
@@ -732,9 +896,16 @@
732
896
 
733
897
  // Arity count error dispatcher
734
898
  Opal.ac = function(actual, expected, object, meth) {
735
- var inspect = (object.$$is_class ? object.$$name + '.' : object.$$class.$$name + '#') + meth;
736
- var msg = '[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')';
737
- throw Opal.ArgumentError.$new(msg);
899
+ var inspect = '';
900
+ if (object.$$is_class || object.$$is_module) {
901
+ inspect += object.$$name + '.';
902
+ }
903
+ else {
904
+ inspect += object.$$class.$$name + '#';
905
+ }
906
+ inspect += meth;
907
+
908
+ throw Opal.ArgumentError.$new('[' + inspect + '] wrong number of arguments(' + actual + ' for ' + expected + ')');
738
909
  };
739
910
 
740
911
  // Super dispatcher
@@ -742,10 +913,15 @@
742
913
  var dispatcher;
743
914
 
744
915
  if (defs) {
745
- dispatcher = obj.$$is_class ? defs.$$super : obj.$$class.$$proto;
916
+ if (obj.$$is_class || obj.$$is_module) {
917
+ dispatcher = defs.$$super;
918
+ }
919
+ else {
920
+ dispatcher = obj.$$class.$$proto;
921
+ }
746
922
  }
747
923
  else {
748
- if (obj.$$is_class) {
924
+ if (obj.$$is_class || obj.$$is_module) {
749
925
  dispatcher = obj.$$super;
750
926
  }
751
927
  else {
@@ -837,7 +1013,7 @@
837
1013
  throw Opal.LocalJumpError.$new("no block given");
838
1014
  }
839
1015
 
840
- if (block.length > 1 && args.length == 1) {
1016
+ if (block.length > 1 && args.length === 1) {
841
1017
  if (args[0].$$is_array) {
842
1018
  return block.apply(null, args[0]);
843
1019
  }
@@ -884,7 +1060,7 @@
884
1060
  }
885
1061
 
886
1062
  for (var i = 0, length = search.$$inc.length; i < length; i++) {
887
- if (search.$$inc[i] == klass) {
1063
+ if (search.$$inc[i] === klass) {
888
1064
  return true;
889
1065
  }
890
1066
  }
@@ -903,8 +1079,21 @@
903
1079
  else if (value.$to_ary && !value.$to_ary.$$stub) {
904
1080
  return value.$to_ary();
905
1081
  }
1082
+ else {
1083
+ return [value];
1084
+ }
1085
+ };
906
1086
 
907
- return [value];
1087
+ Opal.to_a = function(value) {
1088
+ if (value == null || value === nil) {
1089
+ return [];
1090
+ }
1091
+ else if (value.$to_a && !value.$to_a.$$stub) {
1092
+ return value.$to_a();
1093
+ }
1094
+ else {
1095
+ return [value];
1096
+ }
908
1097
  };
909
1098
 
910
1099
  /**
@@ -973,103 +1162,6 @@
973
1162
  return recv.$method_missing.apply(recv, [mid].concat(args));
974
1163
  };
975
1164
 
976
- /*
977
- * Donate methods for a class/module
978
- */
979
- function donate_methods(klass, defined, indirect) {
980
- var methods = klass.$$methods, included_in = klass.$$dep;
981
-
982
- // if (!indirect) {
983
- klass.$$methods = methods.concat(defined);
984
- // }
985
-
986
- if (included_in) {
987
- for (var i = 0, length = included_in.length; i < length; i++) {
988
- var includee = included_in[i];
989
- var dest = includee.$$proto;
990
-
991
- for (var j = 0, jj = defined.length; j < jj; j++) {
992
- var method = defined[j];
993
-
994
- dest[method] = klass.$$proto[method];
995
- dest[method].$$donated = true;
996
- }
997
-
998
- if (includee.$$dep) {
999
- donate_methods(includee, defined, true);
1000
- }
1001
- }
1002
- }
1003
- };
1004
-
1005
- /**
1006
- Define the given method on the module.
1007
-
1008
- This also handles donating methods to all classes that include this
1009
- module. Method conflicts are also handled here, where a class might already
1010
- have defined a method of the same name, or another included module defined
1011
- the same method.
1012
-
1013
- @param [RubyModule] module the module method defined on
1014
- @param [String] jsid javascript friendly method name (e.g. "$foo")
1015
- @param [Function] body method body of actual function
1016
- */
1017
- function define_module_method(module, jsid, body) {
1018
- module.$$proto[jsid] = body;
1019
- body.$$owner = module;
1020
-
1021
- module.$$methods.push(jsid);
1022
-
1023
- if (module.$$module_function) {
1024
- module[jsid] = body;
1025
- }
1026
-
1027
- var included_in = module.$$dep;
1028
-
1029
- if (included_in) {
1030
- for (var i = 0, length = included_in.length; i < length; i++) {
1031
- var includee = included_in[i];
1032
- var dest = includee.$$proto;
1033
- var current = dest[jsid];
1034
-
1035
-
1036
- if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
1037
- // target class has already defined the same method name - do nothing
1038
- }
1039
- else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
1040
- // target class includes another module that has defined this method
1041
- var klass_includees = includee.$$inc;
1042
-
1043
- for (var j = 0, jj = klass_includees.length; j < jj; j++) {
1044
- if (klass_includees[j] === current.$$owner) {
1045
- var current_owner_index = j;
1046
- }
1047
- if (klass_includees[j] === module) {
1048
- var module_index = j;
1049
- }
1050
- }
1051
-
1052
- // only redefine method on class if the module was included AFTER
1053
- // the module which defined the current method body. Also make sure
1054
- // a module can overwrite a method it defined before
1055
- if (current_owner_index <= module_index) {
1056
- dest[jsid] = body;
1057
- dest[jsid].$$donated = true;
1058
- }
1059
- }
1060
- else {
1061
- // neither a class, or module included by class, has defined method
1062
- dest[jsid] = body;
1063
- dest[jsid].$$donated = true;
1064
- }
1065
-
1066
- if (includee.$$dep) {
1067
- donate_methods(includee, [jsid], true);
1068
- }
1069
- }
1070
- }
1071
- }
1072
-
1073
1165
  /**
1074
1166
  Used to define methods on an object. This is a helper method, used by the
1075
1167
  compiled source to define methods on special case objects when the compiler
@@ -1108,21 +1200,33 @@
1108
1200
  @returns [null]
1109
1201
  */
1110
1202
  Opal.defn = function(obj, jsid, body) {
1111
- if (obj.$$is_mod) {
1112
- define_module_method(obj, jsid, body);
1113
- }
1114
- else if (obj.$$is_class) {
1115
- obj.$$proto[jsid] = body;
1203
+ obj.$$proto[jsid] = body;
1116
1204
 
1117
- if (obj === BasicObjectClass) {
1118
- define_basic_object_method(jsid, body);
1205
+ if (obj.$$is_module) {
1206
+ donate(obj, jsid);
1207
+
1208
+ if (obj.$$module_function) {
1209
+ Opal.defs(obj, jsid, body);
1119
1210
  }
1120
- else if (obj === ObjectClass) {
1121
- donate_methods(obj, [jsid]);
1211
+ }
1212
+
1213
+ if (obj.$__id__ && !obj.$__id__.$$stub) {
1214
+ var bridged = bridges[obj.$__id__()];
1215
+
1216
+ if (bridged) {
1217
+ for (var i = bridged.length - 1; i >= 0; i--) {
1218
+ bridge(bridged[i], obj, jsid, body);
1219
+ }
1122
1220
  }
1123
1221
  }
1124
- else {
1125
- obj[jsid] = body;
1222
+
1223
+ if (obj.$method_added && !obj.$method_added.$$stub) {
1224
+ obj.$method_added(jsid.substr(1));
1225
+ }
1226
+
1227
+ var singleton_of = obj.$$singleton_of;
1228
+ if (singleton_of && singleton_of.$singleton_method_added && !singleton_of.$singleton_method_added.$$stub) {
1229
+ singleton_of.$singleton_method_added(jsid.substr(1));
1126
1230
  }
1127
1231
 
1128
1232
  return nil;
@@ -1132,105 +1236,381 @@
1132
1236
  * Define a singleton method on the given object.
1133
1237
  */
1134
1238
  Opal.defs = function(obj, jsid, body) {
1135
- if (obj.$$is_class || obj.$$is_mod) {
1136
- obj.constructor.prototype[jsid] = body;
1239
+ Opal.defn(Opal.get_singleton_class(obj), jsid, body)
1240
+ };
1241
+
1242
+ Opal.def = function(obj, jsid, body) {
1243
+ // if instance_eval is invoked on a module/class, it sets inst_eval_mod
1244
+ if (!obj.$$eval && (obj.$$is_class || obj.$$is_module)) {
1245
+ Opal.defn(obj, jsid, body);
1137
1246
  }
1138
1247
  else {
1139
- obj[jsid] = body;
1248
+ Opal.defs(obj, jsid, body);
1140
1249
  }
1141
1250
  };
1142
1251
 
1143
- function define_basic_object_method(jsid, body) {
1144
- BasicObjectClass.$$methods.push(jsid);
1145
- for (var i = 0, len = bridged_classes.length; i < len; i++) {
1146
- bridged_classes[i].$$proto[jsid] = body;
1252
+ /*
1253
+ * Called from #remove_method.
1254
+ */
1255
+ Opal.rdef = function(obj, jsid) {
1256
+ // TODO: remove from bridges as well
1257
+
1258
+ if (!$hasOwn.call(obj.$$proto, jsid)) {
1259
+ throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
1147
1260
  }
1148
- }
1261
+
1262
+ delete obj.$$proto[jsid];
1263
+
1264
+ if (obj.$$is_singleton) {
1265
+ if (obj.$$proto.$singleton_method_removed && !obj.$$proto.$singleton_method_removed.$$stub) {
1266
+ obj.$$proto.$singleton_method_removed(jsid.substr(1));
1267
+ }
1268
+ }
1269
+ else {
1270
+ if (obj.$method_removed && !obj.$method_removed.$$stub) {
1271
+ obj.$method_removed(jsid.substr(1));
1272
+ }
1273
+ }
1274
+ };
1149
1275
 
1150
1276
  /*
1151
- * Called to remove a method.
1277
+ * Called from #undef_method.
1152
1278
  */
1153
- Opal.undef = function(obj, jsid) {
1154
- delete obj.$$proto[jsid];
1279
+ Opal.udef = function(obj, jsid) {
1280
+ if (!obj.$$proto[jsid] || obj.$$proto[jsid].$$stub) {
1281
+ throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
1282
+ }
1283
+
1284
+ Opal.add_stub_for(obj.$$proto, jsid);
1285
+
1286
+ if (obj.$$is_singleton) {
1287
+ if (obj.$$proto.$singleton_method_undefined && !obj.$$proto.$singleton_method_undefined.$$stub) {
1288
+ obj.$$proto.$singleton_method_undefined(jsid.substr(1));
1289
+ }
1290
+ }
1291
+ else {
1292
+ if (obj.$method_undefined && !obj.$method_undefined.$$stub) {
1293
+ obj.$method_undefined(jsid.substr(1));
1294
+ }
1295
+ }
1155
1296
  };
1156
1297
 
1157
- Opal.hash = function() {
1158
- if (arguments.length == 1 && arguments[0].$$class == Opal.Hash) {
1159
- return arguments[0];
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
+ }
1160
1312
  }
1161
1313
 
1162
- var hash = new Opal.Hash.$$alloc(),
1163
- keys = [],
1164
- _map = {},
1165
- smap = {},
1166
- key, obj, length, khash, map;
1314
+ alias.$$target = body;
1315
+ alias.$$arity = body.length;
1167
1316
 
1168
- hash.map = _map;
1169
- hash.smap = smap;
1170
- hash.keys = keys;
1317
+ return alias;
1318
+ }
1171
1319
 
1172
- if (arguments.length == 1) {
1173
- if (arguments[0].$$is_array) {
1174
- var args = arguments[0];
1320
+ Opal.alias = function(obj, name, old) {
1321
+ var id = '$' + name,
1322
+ old_id = '$' + old,
1323
+ body = obj.$$proto['$' + old];
1324
+
1325
+ // instance_eval is being run on a class/module, so that need to alias class methods
1326
+ if (obj.$$eval) {
1327
+ return Opal.alias(Opal.get_singleton_class(obj), name, old);
1328
+ }
1175
1329
 
1176
- for (var i = 0, ii = args.length; i < ii; i++) {
1177
- var pair = args[i];
1330
+ if (typeof(body) !== "function" || body.$$stub) {
1331
+ var ancestor = obj.$$super;
1178
1332
 
1179
- if (pair.length !== 2) {
1180
- throw Opal.ArgumentError.$new("value not of length 2: " + pair.$inspect());
1181
- }
1333
+ while (typeof(body) !== "function" && ancestor) {
1334
+ body = ancestor[old_id];
1335
+ ancestor = ancestor.$$super;
1336
+ }
1182
1337
 
1183
- key = pair[0];
1184
- obj = pair[1];
1338
+ if (typeof(body) !== "function" || body.$$stub) {
1339
+ throw Opal.NameError.$new("undefined method `" + old + "' for class `" + obj.$name() + "'")
1340
+ }
1341
+ }
1185
1342
 
1186
- if (key.$$is_string) {
1187
- khash = key;
1188
- map = smap;
1189
- } else {
1190
- khash = key.$hash();
1191
- map = _map;
1192
- }
1343
+ Opal.defn(obj, id, wrap(body));
1193
1344
 
1194
- if (map[khash] == null) {
1195
- keys.push(key);
1196
- }
1345
+ return obj;
1346
+ };
1197
1347
 
1198
- map[khash] = obj;
1348
+ Opal.alias_native = function(obj, name, native_name) {
1349
+ var id = '$' + name,
1350
+ body = obj.$$proto[native_name];
1351
+
1352
+ if (typeof(body) !== "function" || body.$$stub) {
1353
+ throw Opal.NameError.$new("undefined native method `" + native_name + "' for class `" + obj.$name() + "'")
1354
+ }
1355
+
1356
+ Opal.defn(obj, id, wrap(body));
1357
+
1358
+ return obj;
1359
+ };
1360
+
1361
+ Opal.hash_init = function (hash) {
1362
+ hash.map = {};
1363
+ hash.smap = {};
1364
+ hash.keys = [];
1365
+ };
1366
+
1367
+ Opal.hash_clone = function (from_hash, to_hash) {
1368
+ to_hash.none = from_hash.none;
1369
+ to_hash.proc = from_hash.proc;
1370
+
1371
+ for (var i = 0, keys = from_hash.keys, length = keys.length, key, value; i < length; i++) {
1372
+ key = from_hash.keys[i];
1373
+
1374
+ if (key.$$is_string) {
1375
+ value = from_hash.smap[key];
1376
+ } else {
1377
+ value = key.value;
1378
+ key = key.key;
1379
+ }
1380
+
1381
+ Opal.hash_put(to_hash, key, value);
1382
+ }
1383
+ };
1384
+
1385
+ Opal.hash_put = function (hash, key, value) {
1386
+ if (key.$$is_string) {
1387
+ if (!hash.smap.hasOwnProperty(key)) {
1388
+ hash.keys.push(key);
1389
+ }
1390
+ hash.smap[key] = value;
1391
+ return;
1392
+ }
1393
+
1394
+ var key_hash = key.$hash(), bucket, last_bucket;
1395
+
1396
+ if (!hash.map.hasOwnProperty(key_hash)) {
1397
+ bucket = {key: key, key_hash: key_hash, value: value};
1398
+ hash.keys.push(bucket);
1399
+ hash.map[key_hash] = bucket;
1400
+ return;
1401
+ }
1402
+
1403
+ bucket = hash.map[key_hash];
1404
+
1405
+ while (bucket) {
1406
+ if (key === bucket.key || key['$eql?'](bucket.key)) {
1407
+ last_bucket = undefined;
1408
+ bucket.value = value;
1409
+ break;
1410
+ }
1411
+ last_bucket = bucket;
1412
+ bucket = bucket.next;
1413
+ }
1414
+
1415
+ if (last_bucket) {
1416
+ bucket = {key: key, key_hash: key_hash, value: value};
1417
+ hash.keys.push(bucket);
1418
+ last_bucket.next = bucket;
1419
+ }
1420
+ };
1421
+
1422
+ Opal.hash_get = function (hash, key) {
1423
+ if (key.$$is_string) {
1424
+ if (hash.smap.hasOwnProperty(key)) {
1425
+ return hash.smap[key];
1426
+ }
1427
+ return;
1428
+ }
1429
+
1430
+ var key_hash = key.$hash(), bucket;
1431
+
1432
+ if (hash.map.hasOwnProperty(key_hash)) {
1433
+ bucket = hash.map[key_hash];
1434
+
1435
+ while (bucket) {
1436
+ if (key === bucket.key || key['$eql?'](bucket.key)) {
1437
+ return bucket.value;
1199
1438
  }
1439
+ bucket = bucket.next;
1200
1440
  }
1201
- else {
1202
- obj = arguments[0];
1203
- for (key in obj) {
1204
- khash = key.$hash();
1205
- smap[khash] = obj[khash];
1206
- keys.push(key);
1441
+ }
1442
+ };
1443
+
1444
+ Opal.hash_delete = function (hash, key) {
1445
+ var i, keys = hash.keys, length = keys.length, value;
1446
+
1447
+ if (key.$$is_string) {
1448
+ if (!hash.smap.hasOwnProperty(key)) {
1449
+ return;
1450
+ }
1451
+
1452
+ for (i = 0; i < length; i++) {
1453
+ if (keys[i] === key) {
1454
+ keys.splice(i, 1);
1455
+ break;
1207
1456
  }
1208
1457
  }
1458
+
1459
+ value = hash.smap[key];
1460
+ delete hash.smap[key];
1461
+ return value;
1209
1462
  }
1210
- else {
1211
- length = arguments.length;
1212
- if (length % 2 !== 0) {
1213
- throw Opal.ArgumentError.$new("odd number of arguments for Hash");
1463
+
1464
+ var key_hash = key.$hash();
1465
+
1466
+ if (!hash.map.hasOwnProperty(key_hash)) {
1467
+ return;
1468
+ }
1469
+
1470
+ var bucket = hash.map[key_hash], last_bucket;
1471
+
1472
+ while (bucket) {
1473
+ if (key === bucket.key || key['$eql?'](bucket.key)) {
1474
+ value = bucket.value;
1475
+
1476
+ for (i = 0; i < length; i++) {
1477
+ if (keys[i] === bucket) {
1478
+ keys.splice(i, 1);
1479
+ break;
1480
+ }
1481
+ }
1482
+
1483
+ if (last_bucket && bucket.next) {
1484
+ last_bucket.next = bucket.next;
1485
+ }
1486
+ else if (last_bucket) {
1487
+ delete last_bucket.next;
1488
+ }
1489
+ else if (bucket.next) {
1490
+ hash.map[key_hash] = bucket.next;
1491
+ }
1492
+ else {
1493
+ delete hash.map[key_hash];
1494
+ }
1495
+
1496
+ return value;
1497
+ }
1498
+ last_bucket = bucket;
1499
+ bucket = bucket.next;
1500
+ }
1501
+ };
1502
+
1503
+ Opal.hash_rehash = function (hash) {
1504
+ for (var i = 0, length = hash.keys.length, key_hash, bucket, last_bucket; i < length; i++) {
1505
+
1506
+ if (hash.keys[i].$$is_string) {
1507
+ continue;
1214
1508
  }
1215
1509
 
1216
- for (var j = 0; j < length; j++) {
1217
- key = arguments[j];
1218
- obj = arguments[++j];
1510
+ key_hash = hash.keys[i].key.$hash();
1219
1511
 
1220
- if (key.$$is_string) {
1221
- khash = key;
1222
- map = smap;
1223
- } else {
1224
- khash = key.$hash();
1225
- map = _map;
1512
+ if (key_hash === hash.keys[i].key_hash) {
1513
+ continue;
1514
+ }
1515
+
1516
+ bucket = hash.map[hash.keys[i].key_hash];
1517
+ last_bucket = undefined;
1518
+
1519
+ while (bucket) {
1520
+ if (bucket === hash.keys[i]) {
1521
+ if (last_bucket && bucket.next) {
1522
+ last_bucket.next = bucket.next;
1523
+ }
1524
+ else if (last_bucket) {
1525
+ delete last_bucket.next;
1526
+ }
1527
+ else if (bucket.next) {
1528
+ hash.map[hash.keys[i].key_hash] = bucket.next;
1529
+ }
1530
+ else {
1531
+ delete hash.map[hash.keys[i].key_hash];
1532
+ }
1533
+ break;
1534
+ }
1535
+ last_bucket = bucket;
1536
+ bucket = bucket.next;
1537
+ }
1538
+
1539
+ hash.keys[i].key_hash = key_hash;
1540
+
1541
+ if (!hash.map.hasOwnProperty(key_hash)) {
1542
+ hash.map[key_hash] = hash.keys[i];
1543
+ continue;
1544
+ }
1545
+
1546
+ bucket = hash.map[key_hash];
1547
+ last_bucket = undefined;
1548
+
1549
+ while (bucket) {
1550
+ if (bucket === hash.keys[i]) {
1551
+ last_bucket = undefined;
1552
+ break;
1226
1553
  }
1554
+ last_bucket = bucket;
1555
+ bucket = bucket.next;
1556
+ }
1557
+
1558
+ if (last_bucket) {
1559
+ last_bucket.next = hash.keys[i];
1560
+ }
1561
+ }
1562
+ };
1563
+
1564
+ Opal.hash = function() {
1565
+ var arguments_length = arguments.length, args, hash, i, length, key, value;
1566
+
1567
+ if (arguments_length === 1 && arguments[0].$$is_hash) {
1568
+ return arguments[0];
1569
+ }
1570
+
1571
+ hash = new Opal.Hash.$$alloc();
1572
+ Opal.hash_init(hash);
1227
1573
 
1228
- if (map[khash] == null) {
1229
- keys.push(key);
1574
+ if (arguments_length === 1 && arguments[0].$$is_array) {
1575
+ args = arguments[0];
1576
+ length = args.length;
1577
+
1578
+ for (i = 0; i < length; i++) {
1579
+ if (args[i].length !== 2) {
1580
+ throw Opal.ArgumentError.$new("value not of length 2: " + args[i].$inspect());
1230
1581
  }
1231
1582
 
1232
- map[khash] = obj;
1583
+ key = args[i][0];
1584
+ value = args[i][1];
1585
+
1586
+ Opal.hash_put(hash, key, value);
1587
+ }
1588
+
1589
+ return hash;
1590
+ }
1591
+
1592
+ if (arguments_length === 1) {
1593
+ args = arguments[0];
1594
+ for (key in args) {
1595
+ if (args.hasOwnProperty(key)) {
1596
+ value = args[key];
1597
+
1598
+ Opal.hash_put(hash, key, value);
1599
+ }
1233
1600
  }
1601
+
1602
+ return hash;
1603
+ }
1604
+
1605
+ if (arguments_length % 2 !== 0) {
1606
+ throw Opal.ArgumentError.$new("odd number of arguments for Hash");
1607
+ }
1608
+
1609
+ for (i = 0; i < arguments_length; i += 2) {
1610
+ key = arguments[i];
1611
+ value = arguments[i + 1];
1612
+
1613
+ Opal.hash_put(hash, key, value);
1234
1614
  }
1235
1615
 
1236
1616
  return hash;
@@ -1242,12 +1622,12 @@
1242
1622
  * compile time, so they are just added here by the constructor
1243
1623
  * function
1244
1624
  */
1245
- Opal.hash2 = function(keys, map) {
1625
+ Opal.hash2 = function(keys, smap) {
1246
1626
  var hash = new Opal.Hash.$$alloc();
1247
1627
 
1248
- hash.keys = keys;
1249
1628
  hash.map = {};
1250
- hash.smap = map;
1629
+ hash.keys = keys;
1630
+ hash.smap = smap;
1251
1631
 
1252
1632
  return hash;
1253
1633
  };
@@ -1265,6 +1645,25 @@
1265
1645
  return range;
1266
1646
  };
1267
1647
 
1648
+ Opal.ivar = function(name) {
1649
+ if (name === "constructor" ||
1650
+ name === "__proto__" ||
1651
+ name === "__parent__" ||
1652
+ name === "__noSuchMethod__" ||
1653
+ name === "__count__")
1654
+ {
1655
+ return name + "$";
1656
+ }
1657
+
1658
+ if (name === "hasOwnProperty" ||
1659
+ name === "valueOf")
1660
+ {
1661
+ return name + "$";
1662
+ }
1663
+
1664
+ return name;
1665
+ };
1666
+
1268
1667
  // Require system
1269
1668
  // --------------
1270
1669
  (function(Opal) {
@@ -1274,18 +1673,7 @@
1274
1673
 
1275
1674
  var current_dir = '.';
1276
1675
 
1277
- function mark_as_loaded(filename) {
1278
- if (require_table[filename]) {
1279
- return false;
1280
- }
1281
-
1282
- loaded_features.push(filename);
1283
- require_table[filename] = true;
1284
-
1285
- return true;
1286
- }
1287
-
1288
- function normalize_loadable_path(path) {
1676
+ function normalize(path) {
1289
1677
  var parts, part, new_parts = [], SEPARATOR = '/';
1290
1678
 
1291
1679
  if (current_dir !== '.') {
@@ -1297,15 +1685,32 @@
1297
1685
 
1298
1686
  for (var i = 0, ii = parts.length; i < ii; i++) {
1299
1687
  part = parts[i];
1300
- if (part == '') continue;
1688
+ if (part === '') continue;
1301
1689
  (part === '..') ? new_parts.pop() : new_parts.push(part)
1302
1690
  }
1303
1691
 
1304
1692
  return new_parts.join(SEPARATOR);
1305
1693
  }
1306
1694
 
1695
+ function loaded(paths) {
1696
+ var i, l, path;
1697
+
1698
+ for (i = 0, l = paths.length; i < l; i++) {
1699
+ path = normalize(paths[i]);
1700
+
1701
+ if (require_table[path]) {
1702
+ return;
1703
+ }
1704
+
1705
+ loaded_features.push(path);
1706
+ require_table[path] = true;
1707
+ }
1708
+ }
1709
+
1307
1710
  function load(path) {
1308
- mark_as_loaded(path);
1711
+ path = normalize(path);
1712
+
1713
+ loaded([path]);
1309
1714
 
1310
1715
  var module = modules[path];
1311
1716
 
@@ -1328,6 +1733,8 @@
1328
1733
  }
1329
1734
 
1330
1735
  function require(path) {
1736
+ path = normalize(path);
1737
+
1331
1738
  if (require_table[path]) {
1332
1739
  return false;
1333
1740
  }
@@ -1337,9 +1744,7 @@
1337
1744
 
1338
1745
  Opal.modules = modules;
1339
1746
  Opal.loaded_features = loaded_features;
1340
-
1341
- Opal.normalize_loadable_path = normalize_loadable_path;
1342
- Opal.mark_as_loaded = mark_as_loaded;
1747
+ Opal.loaded = loaded;
1343
1748
 
1344
1749
  Opal.load = load;
1345
1750
  Opal.require = require;
@@ -1404,16 +1809,9 @@
1404
1809
  ModuleClass.$$parent = ObjectClass;
1405
1810
  ClassClass.$$parent = ModuleClass;
1406
1811
 
1407
- // Internally, Object acts like a module as it is "included" into bridged
1408
- // classes. In other words, we donate methods from Object into our bridged
1409
- // classes as their prototypes don't inherit from our root Object, so they
1410
- // act like module includes.
1411
- ObjectClass.$$dep = bridged_classes;
1412
-
1413
1812
  Opal.base = ObjectClass;
1414
1813
  BasicObjectClass.$$scope = ObjectClass.$$scope = Opal;
1415
1814
  BasicObjectClass.$$orig_scope = ObjectClass.$$orig_scope = Opal;
1416
- Opal.Kernel = ObjectClass;
1417
1815
 
1418
1816
  ModuleClass.$$scope = ObjectClass.$$scope;
1419
1817
  ModuleClass.$$orig_scope = ObjectClass.$$orig_scope;
@@ -1437,15 +1835,6 @@
1437
1835
  Opal.breaker = new Error('unexpected break');
1438
1836
  Opal.returner = new Error('unexpected return');
1439
1837
 
1440
- bridge_class('Array', Array);
1441
- bridge_class('Boolean', Boolean);
1442
- bridge_class('Numeric', Number);
1443
- bridge_class('String', String);
1444
- bridge_class('Proc', Function);
1445
- bridge_class('Exception', Error);
1446
- bridge_class('Regexp', RegExp);
1447
- bridge_class('Time', Date);
1448
-
1449
1838
  TypeError.$$super = Error;
1450
1839
  }).call(this);
1451
1840