opal 0.8.1 → 0.9.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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