opal 0.11.4 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (379) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +42 -10
  3. data/.rubocop.yml +398 -0
  4. data/.rubocop_todo.yml +44 -0
  5. data/.travis.yml +28 -34
  6. data/CHANGELOG.md +363 -142
  7. data/CONTRIBUTING.md +3 -5
  8. data/Gemfile +17 -12
  9. data/Guardfile +0 -1
  10. data/HACKING.md +1 -35
  11. data/LICENSE +2 -2
  12. data/README.md +42 -13
  13. data/Rakefile +1 -4
  14. data/UNRELEASED.md +133 -0
  15. data/benchmark-ips/README.md +6 -0
  16. data/benchmark-ips/bm_block_vs_yield.rb +21 -0
  17. data/benchmark-ips/bm_js_symbols_vs_strings.rb +28 -0
  18. data/benchmark-ips/bm_while_true_vs_loop.rb +19 -0
  19. data/bin/console +14 -0
  20. data/bin/opal +0 -1
  21. data/bin/opal-benchmark-ips +8 -0
  22. data/bin/opal-mspec +9 -1
  23. data/bin/opal-repl +2 -1
  24. data/bin/rake +7 -0
  25. data/bin/setup +8 -0
  26. data/docs/compiled_ruby.md +89 -8
  27. data/docs/compiler.md +3 -20
  28. data/docs/jquery.md +44 -11
  29. data/docs/promises.md +1 -1
  30. data/docs/rails.md +16 -12
  31. data/docs/sinatra.md +15 -8
  32. data/docs/using_sprockets.md +16 -11
  33. data/examples/rack/config.ru +1 -0
  34. data/examples/sinatra/Gemfile +1 -0
  35. data/examples/sinatra/config.ru +2 -11
  36. data/exe/opal-repl +3 -11
  37. data/lib/opal.rb +1 -0
  38. data/lib/opal/ast/builder.rb +4 -1
  39. data/lib/opal/ast/node.rb +1 -0
  40. data/lib/opal/builder.rb +84 -63
  41. data/lib/opal/builder_processors.rb +41 -56
  42. data/lib/opal/cli.rb +33 -49
  43. data/lib/opal/cli_options.rb +27 -17
  44. data/lib/opal/cli_runners.rb +73 -16
  45. data/lib/opal/cli_runners/applescript.rb +4 -4
  46. data/lib/opal/cli_runners/chrome.rb +29 -17
  47. data/lib/opal/cli_runners/nashorn.rb +5 -4
  48. data/lib/opal/cli_runners/nodejs.rb +8 -6
  49. data/lib/opal/cli_runners/server.rb +12 -11
  50. data/lib/opal/compiler.rb +85 -103
  51. data/lib/opal/config.rb +3 -3
  52. data/lib/opal/deprecations.rb +2 -1
  53. data/lib/opal/eof_content.rb +2 -2
  54. data/lib/opal/erb.rb +8 -7
  55. data/lib/opal/errors.rb +72 -1
  56. data/lib/opal/fragment.rb +23 -3
  57. data/lib/opal/hike.rb +305 -0
  58. data/lib/opal/nodes.rb +5 -10
  59. data/lib/opal/nodes/arglist.rb +7 -6
  60. data/lib/opal/nodes/args.rb +36 -0
  61. data/lib/opal/nodes/args/arg.rb +22 -0
  62. data/lib/opal/nodes/args/arity_check.rb +151 -0
  63. data/lib/opal/nodes/args/ensure_kwargs_are_kwargs.rb +28 -0
  64. data/lib/opal/nodes/args/extract_block_arg.rb +34 -0
  65. data/lib/opal/nodes/args/extract_kwarg.rb +32 -0
  66. data/lib/opal/nodes/args/extract_kwargs.rb +28 -0
  67. data/lib/opal/nodes/args/extract_kwoptarg.rb +35 -0
  68. data/lib/opal/nodes/args/extract_kwrestarg.rb +35 -0
  69. data/lib/opal/nodes/args/extract_optarg.rb +35 -0
  70. data/lib/opal/nodes/args/extract_post_arg.rb +28 -0
  71. data/lib/opal/nodes/args/extract_post_optarg.rb +41 -0
  72. data/lib/opal/nodes/args/extract_restarg.rb +40 -0
  73. data/lib/opal/nodes/args/fake_arg.rb +26 -0
  74. data/lib/opal/nodes/args/initialize_iterarg.rb +28 -0
  75. data/lib/opal/nodes/args/initialize_shadowarg.rb +24 -0
  76. data/lib/opal/nodes/args/parameters.rb +63 -0
  77. data/lib/opal/nodes/args/prepare_post_args.rb +22 -0
  78. data/lib/opal/nodes/array.rb +9 -8
  79. data/lib/opal/nodes/base.rb +20 -11
  80. data/lib/opal/nodes/call.rb +24 -25
  81. data/lib/opal/nodes/call_special.rb +4 -3
  82. data/lib/opal/nodes/case.rb +24 -26
  83. data/lib/opal/nodes/class.rb +4 -5
  84. data/lib/opal/nodes/constants.rb +8 -7
  85. data/lib/opal/nodes/csend.rb +2 -3
  86. data/lib/opal/nodes/def.rb +28 -74
  87. data/lib/opal/nodes/defined.rb +36 -36
  88. data/lib/opal/nodes/definitions.rb +10 -7
  89. data/lib/opal/nodes/defs.rb +8 -16
  90. data/lib/opal/nodes/hash.rb +5 -4
  91. data/lib/opal/nodes/helpers.rb +8 -8
  92. data/lib/opal/nodes/if.rb +10 -8
  93. data/lib/opal/nodes/iter.rb +16 -103
  94. data/lib/opal/nodes/lambda.rb +18 -0
  95. data/lib/opal/nodes/literal.rb +29 -63
  96. data/lib/opal/nodes/logic.rb +25 -24
  97. data/lib/opal/nodes/masgn.rb +8 -6
  98. data/lib/opal/nodes/module.rb +4 -4
  99. data/lib/opal/nodes/node_with_args.rb +14 -208
  100. data/lib/opal/nodes/rescue.rb +32 -32
  101. data/lib/opal/nodes/runtime_helpers.rb +5 -4
  102. data/lib/opal/nodes/scope.rb +18 -29
  103. data/lib/opal/nodes/singleton_class.rb +3 -3
  104. data/lib/opal/nodes/super.rb +12 -18
  105. data/lib/opal/nodes/top.rb +10 -8
  106. data/lib/opal/nodes/variables.rb +6 -6
  107. data/lib/opal/nodes/while.rb +7 -6
  108. data/lib/opal/nodes/x_string.rb +139 -0
  109. data/lib/opal/nodes/yield.rb +10 -7
  110. data/lib/opal/parser.rb +9 -46
  111. data/lib/opal/parser/default_config.rb +50 -0
  112. data/lib/opal/parser/patch.rb +26 -0
  113. data/lib/opal/parser/source_buffer.rb +11 -0
  114. data/lib/opal/parser/with_c_lexer.rb +14 -0
  115. data/lib/opal/parser/with_ruby_lexer.rb +6 -0
  116. data/lib/opal/path_reader.rb +6 -5
  117. data/lib/opal/paths.rb +9 -6
  118. data/lib/opal/regexp_anchors.rb +6 -5
  119. data/lib/opal/rewriter.rb +7 -0
  120. data/lib/opal/rewriters/arguments.rb +58 -0
  121. data/lib/opal/rewriters/base.rb +32 -12
  122. data/lib/opal/rewriters/binary_operator_assignment.rb +20 -20
  123. data/lib/opal/rewriters/block_to_iter.rb +2 -1
  124. data/lib/opal/rewriters/break_finder.rb +2 -0
  125. data/lib/opal/rewriters/dot_js_syntax.rb +3 -2
  126. data/lib/opal/rewriters/dump_args.rb +28 -0
  127. data/lib/opal/rewriters/explicit_writer_return.rb +4 -3
  128. data/lib/opal/rewriters/for_rewriter.rb +12 -12
  129. data/lib/opal/rewriters/hashes/key_duplicates_rewriter.rb +2 -1
  130. data/lib/opal/rewriters/inline_args.rb +220 -0
  131. data/lib/opal/rewriters/js_reserved_words.rb +21 -17
  132. data/lib/opal/rewriters/logical_operator_assignment.rb +24 -14
  133. data/lib/opal/rewriters/mlhs_args.rb +128 -0
  134. data/lib/opal/rewriters/opal_engine_check.rb +11 -6
  135. data/lib/opal/rewriters/rubyspec/filters_rewriter.rb +3 -2
  136. data/lib/opal/server.rb +1 -0
  137. data/lib/opal/simple_server.rb +15 -23
  138. data/lib/opal/source_map.rb +7 -70
  139. data/lib/opal/source_map/file.rb +199 -0
  140. data/lib/opal/source_map/index.rb +83 -0
  141. data/lib/opal/source_map/map.rb +26 -0
  142. data/lib/opal/source_map/vlq.rb +98 -0
  143. data/lib/opal/util.rb +7 -5
  144. data/lib/opal/version.rb +2 -1
  145. data/lib/tilt/opal.rb +3 -3
  146. data/opal.gemspec +18 -9
  147. data/opal/corelib/array.rb +135 -117
  148. data/opal/corelib/array/pack.rb +446 -0
  149. data/opal/corelib/basic_object.rb +23 -9
  150. data/opal/corelib/boolean.rb +3 -3
  151. data/opal/corelib/class.rb +4 -10
  152. data/opal/corelib/comparable.rb +36 -23
  153. data/opal/corelib/complex.rb +108 -14
  154. data/opal/corelib/constants.rb +4 -4
  155. data/opal/corelib/enumerable.rb +132 -135
  156. data/opal/corelib/enumerator.rb +47 -50
  157. data/opal/corelib/error.rb +65 -8
  158. data/opal/corelib/file.rb +37 -32
  159. data/opal/corelib/hash.rb +90 -21
  160. data/opal/corelib/helpers.rb +7 -6
  161. data/opal/corelib/kernel.rb +53 -586
  162. data/opal/corelib/kernel/format.rb +544 -0
  163. data/opal/corelib/marshal.rb +1 -13
  164. data/opal/corelib/marshal/read_buffer.rb +20 -23
  165. data/opal/corelib/marshal/write_buffer.rb +23 -15
  166. data/opal/corelib/math.rb +12 -16
  167. data/opal/corelib/method.rb +5 -3
  168. data/opal/corelib/module.rb +80 -109
  169. data/opal/corelib/nil.rb +2 -2
  170. data/opal/corelib/number.rb +177 -43
  171. data/opal/corelib/numeric.rb +22 -16
  172. data/opal/corelib/pack_unpack/format_string_parser.rb +135 -0
  173. data/opal/corelib/proc.rb +3 -4
  174. data/opal/corelib/process.rb +1 -1
  175. data/opal/corelib/random.rb +24 -16
  176. data/opal/corelib/random/MersenneTwister.js +137 -0
  177. data/opal/corelib/random/math_random.js.rb +9 -0
  178. data/opal/corelib/random/mersenne_twister.js.rb +13 -0
  179. data/opal/corelib/random/seedrandom.js.rb +12 -0
  180. data/opal/corelib/range.rb +25 -26
  181. data/opal/corelib/rational.rb +57 -17
  182. data/opal/corelib/regexp.rb +39 -43
  183. data/opal/corelib/runtime.js +806 -683
  184. data/opal/corelib/string.rb +213 -112
  185. data/opal/corelib/string/encoding.rb +14 -17
  186. data/opal/corelib/string/unpack.rb +793 -0
  187. data/opal/corelib/struct.rb +40 -24
  188. data/opal/corelib/time.rb +14 -15
  189. data/opal/corelib/unsupported.rb +26 -4
  190. data/opal/opal.rb +2 -1
  191. data/opal/opal/full.rb +2 -0
  192. data/stdlib/base64.rb +1 -1
  193. data/stdlib/bigdecimal.rb +11 -13
  194. data/stdlib/buffer.rb +9 -8
  195. data/stdlib/buffer/array.rb +46 -48
  196. data/stdlib/buffer/view.rb +85 -47
  197. data/stdlib/console.rb +18 -18
  198. data/stdlib/date.rb +85 -66
  199. data/stdlib/delegate.rb +2 -2
  200. data/stdlib/e2mmap.rb +176 -0
  201. data/stdlib/encoding.rb +1 -1
  202. data/stdlib/erb.rb +1 -1
  203. data/stdlib/forwardable.rb +14 -14
  204. data/stdlib/json.rb +1 -2
  205. data/stdlib/logger.rb +112 -0
  206. data/stdlib/math.rb +1 -1
  207. data/stdlib/matrix.rb +2169 -0
  208. data/stdlib/matrix/eigenvalue_decomposition.rb +883 -0
  209. data/stdlib/matrix/lup_decomposition.rb +219 -0
  210. data/stdlib/nashorn/file.rb +7 -9
  211. data/stdlib/native.rb +69 -63
  212. data/stdlib/nodejs.rb +3 -0
  213. data/stdlib/nodejs/dir.rb +25 -4
  214. data/stdlib/nodejs/env.rb +40 -0
  215. data/stdlib/nodejs/file.rb +184 -34
  216. data/stdlib/nodejs/fileutils.rb +4 -4
  217. data/stdlib/nodejs/io.rb +4 -46
  218. data/stdlib/nodejs/irb.rb +27 -29
  219. data/stdlib/nodejs/kernel.rb +2 -11
  220. data/stdlib/nodejs/node_modules/balanced-match/.npmignore +5 -0
  221. data/stdlib/nodejs/node_modules/balanced-match/LICENSE.md +21 -0
  222. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match → balanced-match}/README.md +13 -2
  223. data/stdlib/nodejs/node_modules/balanced-match/index.js +59 -0
  224. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match → balanced-match}/package.json +46 -42
  225. data/stdlib/nodejs/node_modules/brace-expansion/LICENSE +21 -0
  226. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion → brace-expansion}/README.md +9 -1
  227. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion → brace-expansion}/index.js +12 -2
  228. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion → brace-expansion}/package.json +48 -48
  229. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map → concat-map}/.travis.yml +0 -0
  230. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map → concat-map}/LICENSE +0 -0
  231. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map → concat-map}/README.markdown +0 -0
  232. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map → concat-map}/example/map.js +0 -0
  233. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map → concat-map}/index.js +0 -0
  234. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map → concat-map}/package.json +47 -42
  235. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map → concat-map}/test/map.js +0 -0
  236. data/stdlib/nodejs/node_modules/fs.realpath/LICENSE +43 -0
  237. data/stdlib/nodejs/node_modules/fs.realpath/README.md +33 -0
  238. data/stdlib/nodejs/node_modules/fs.realpath/index.js +66 -0
  239. data/stdlib/nodejs/node_modules/fs.realpath/old.js +303 -0
  240. data/stdlib/nodejs/node_modules/fs.realpath/package.json +59 -0
  241. data/stdlib/nodejs/node_modules/glob/README.md +57 -46
  242. data/stdlib/nodejs/node_modules/glob/changelog.md +67 -0
  243. data/stdlib/nodejs/node_modules/glob/common.js +91 -28
  244. data/stdlib/nodejs/node_modules/glob/glob.js +196 -55
  245. data/stdlib/nodejs/node_modules/glob/package.json +55 -51
  246. data/stdlib/nodejs/node_modules/glob/sync.js +116 -39
  247. data/stdlib/nodejs/node_modules/{glob/node_modules/inflight → inflight}/LICENSE +0 -0
  248. data/stdlib/nodejs/node_modules/{glob/node_modules/inflight → inflight}/README.md +0 -0
  249. data/stdlib/nodejs/node_modules/inflight/inflight.js +54 -0
  250. data/stdlib/nodejs/node_modules/inflight/package.json +58 -0
  251. data/stdlib/nodejs/node_modules/{glob/node_modules/inherits → inherits}/LICENSE +0 -0
  252. data/stdlib/nodejs/node_modules/{glob/node_modules/inherits → inherits}/README.md +0 -0
  253. data/stdlib/nodejs/node_modules/inherits/inherits.js +7 -0
  254. data/stdlib/nodejs/node_modules/{glob/node_modules/inherits → inherits}/inherits_browser.js +0 -0
  255. data/stdlib/nodejs/node_modules/inherits/package.json +61 -0
  256. data/stdlib/nodejs/node_modules/{glob/node_modules/inflight/node_modules/wrappy → minimatch}/LICENSE +0 -0
  257. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch → minimatch}/README.md +2 -9
  258. data/stdlib/nodejs/node_modules/{glob/node_modules/minimatch → minimatch}/minimatch.js +284 -206
  259. data/stdlib/nodejs/node_modules/minimatch/package.json +63 -0
  260. data/stdlib/nodejs/node_modules/{glob/node_modules/once/node_modules/wrappy → once}/LICENSE +0 -0
  261. data/stdlib/nodejs/node_modules/{glob/node_modules/once → once}/README.md +28 -0
  262. data/stdlib/nodejs/node_modules/once/once.js +42 -0
  263. data/stdlib/nodejs/node_modules/once/package.json +67 -0
  264. data/stdlib/nodejs/node_modules/path-is-absolute/index.js +20 -0
  265. data/stdlib/nodejs/node_modules/path-is-absolute/license +21 -0
  266. data/stdlib/nodejs/node_modules/path-is-absolute/package.json +75 -0
  267. data/stdlib/nodejs/node_modules/path-is-absolute/readme.md +59 -0
  268. data/stdlib/nodejs/node_modules/unxhr/LICENSE +22 -0
  269. data/stdlib/nodejs/node_modules/unxhr/README.md +41 -0
  270. data/stdlib/nodejs/node_modules/unxhr/lib/XMLHttpRequest.js +598 -0
  271. data/stdlib/nodejs/node_modules/unxhr/lib/browser.js +2 -0
  272. data/stdlib/nodejs/node_modules/unxhr/lib/request.js +63 -0
  273. data/stdlib/nodejs/node_modules/unxhr/package.json +75 -0
  274. data/stdlib/nodejs/node_modules/wrappy/LICENSE +15 -0
  275. data/stdlib/nodejs/node_modules/{glob/node_modules/inflight/node_modules/wrappy → wrappy}/README.md +0 -0
  276. data/stdlib/nodejs/node_modules/wrappy/package.json +59 -0
  277. data/stdlib/nodejs/node_modules/{glob/node_modules/inflight/node_modules/wrappy → wrappy}/wrappy.js +0 -0
  278. data/stdlib/nodejs/open-uri.rb +26 -0
  279. data/stdlib/nodejs/package-lock.json +88 -0
  280. data/stdlib/nodejs/package.json +2 -1
  281. data/stdlib/nodejs/pathname.rb +20 -0
  282. data/stdlib/nodejs/require.rb +3 -3
  283. data/stdlib/nodejs/stacktrace.rb +1 -1
  284. data/stdlib/nodejs/yaml.rb +1 -1
  285. data/stdlib/opal-builder.rb +1 -0
  286. data/stdlib/opal-parser.rb +4 -1
  287. data/stdlib/opal-platform.rb +8 -10
  288. data/stdlib/opal-source-maps.rb +0 -1
  289. data/stdlib/open-uri.rb +349 -0
  290. data/stdlib/ostruct.rb +19 -17
  291. data/stdlib/pathname.rb +22 -22
  292. data/stdlib/pp.rb +5 -5
  293. data/stdlib/promise.rb +30 -26
  294. data/stdlib/rbconfig/sizeof.rb +50 -0
  295. data/stdlib/securerandom.rb +1 -1
  296. data/stdlib/set.rb +21 -23
  297. data/stdlib/singleton.rb +3 -4
  298. data/stdlib/stringio.rb +33 -0
  299. data/stdlib/strscan.rb +55 -55
  300. data/stdlib/template.rb +1 -2
  301. data/stdlib/thread.rb +6 -7
  302. data/tasks/benchmarking.rake +1 -1
  303. data/tasks/building.rake +4 -12
  304. data/tasks/linting.rake +17 -2
  305. data/tasks/releasing.rake +84 -0
  306. data/tasks/testing.rake +57 -15
  307. data/tasks/testing/mspec_special_calls.rb +23 -4
  308. data/vendored-minitest/minitest.rb +1 -1
  309. metadata +169 -168
  310. data/bin/opal-build +0 -3
  311. data/exe/opal-mspec +0 -10
  312. data/lib/opal/nodes/args/initialize_kwargs.rb +0 -29
  313. data/lib/opal/nodes/args/kwarg.rb +0 -31
  314. data/lib/opal/nodes/args/kwoptarg.rb +0 -34
  315. data/lib/opal/nodes/args/kwrestarg.rb +0 -39
  316. data/lib/opal/nodes/args/mlhsarg.rb +0 -78
  317. data/lib/opal/nodes/args/normarg.rb +0 -29
  318. data/lib/opal/nodes/args/optarg.rb +0 -25
  319. data/lib/opal/nodes/args/post_args.rb +0 -201
  320. data/lib/opal/nodes/args/post_kwargs.rb +0 -32
  321. data/lib/opal/nodes/args/restarg.rb +0 -38
  322. data/lib/opal/nodes/inline_args.rb +0 -60
  323. data/opal/corelib/string/inheritance.rb +0 -123
  324. data/stdlib/nodejs/node_modules/glob/node_modules/inflight/.eslintrc +0 -17
  325. data/stdlib/nodejs/node_modules/glob/node_modules/inflight/inflight.js +0 -44
  326. data/stdlib/nodejs/node_modules/glob/node_modules/inflight/node_modules/wrappy/package.json +0 -52
  327. data/stdlib/nodejs/node_modules/glob/node_modules/inflight/node_modules/wrappy/test/basic.js +0 -51
  328. data/stdlib/nodejs/node_modules/glob/node_modules/inflight/package.json +0 -61
  329. data/stdlib/nodejs/node_modules/glob/node_modules/inflight/test.js +0 -97
  330. data/stdlib/nodejs/node_modules/glob/node_modules/inherits/inherits.js +0 -1
  331. data/stdlib/nodejs/node_modules/glob/node_modules/inherits/package.json +0 -51
  332. data/stdlib/nodejs/node_modules/glob/node_modules/inherits/test.js +0 -25
  333. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/.npmignore +0 -1
  334. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/.travis.yml +0 -4
  335. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/LICENSE +0 -23
  336. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/benchmark.js +0 -15
  337. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/browser.js +0 -1181
  338. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/.npmignore +0 -2
  339. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/.travis.yml +0 -3
  340. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/example.js +0 -8
  341. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/.npmignore +0 -2
  342. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/.travis.yml +0 -4
  343. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/Makefile +0 -6
  344. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/example.js +0 -5
  345. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/index.js +0 -38
  346. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match/test/balanced.js +0 -56
  347. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/bash-comparison.js +0 -32
  348. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/bash-results.txt +0 -1075
  349. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/cases.txt +0 -182
  350. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/dollar.js +0 -9
  351. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/empty-option.js +0 -10
  352. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/generate.sh +0 -24
  353. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/negative-increment.js +0 -15
  354. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/nested.js +0 -16
  355. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/order.js +0 -10
  356. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/pad.js +0 -13
  357. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/same-type.js +0 -7
  358. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/test/sequence.js +0 -50
  359. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/package.json +0 -60
  360. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/test/basic.js +0 -399
  361. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/test/brace-expand.js +0 -45
  362. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/test/defaults.js +0 -274
  363. data/stdlib/nodejs/node_modules/glob/node_modules/minimatch/test/extglob-ending-with-state-char.js +0 -8
  364. data/stdlib/nodejs/node_modules/glob/node_modules/once/LICENSE +0 -27
  365. data/stdlib/nodejs/node_modules/glob/node_modules/once/node_modules/wrappy/README.md +0 -36
  366. data/stdlib/nodejs/node_modules/glob/node_modules/once/node_modules/wrappy/package.json +0 -52
  367. data/stdlib/nodejs/node_modules/glob/node_modules/once/node_modules/wrappy/test/basic.js +0 -51
  368. data/stdlib/nodejs/node_modules/glob/node_modules/once/node_modules/wrappy/wrappy.js +0 -33
  369. data/stdlib/nodejs/node_modules/glob/node_modules/once/once.js +0 -21
  370. data/stdlib/nodejs/node_modules/glob/node_modules/once/package.json +0 -60
  371. data/stdlib/nodejs/node_modules/glob/node_modules/once/test/once.js +0 -23
  372. data/stdlib/nodejs/rubygems.rb +0 -68
  373. data/stdlib/source_map.rb +0 -5
  374. data/stdlib/source_map/map.rb +0 -220
  375. data/stdlib/source_map/mapping.rb +0 -26
  376. data/stdlib/source_map/offset.rb +0 -88
  377. data/stdlib/source_map/version.rb +0 -3
  378. data/stdlib/source_map/vlq.rb +0 -99
  379. data/stdlib/sourcemap.rb +0 -1
@@ -6,7 +6,7 @@ class Rational < Numeric
6
6
  den = den.to_i
7
7
 
8
8
  if den == 0
9
- raise ZeroDivisionError, "divided by 0"
9
+ raise ZeroDivisionError, 'divided by 0'
10
10
  elsif den < 0
11
11
  num = -num
12
12
  den = -den
@@ -21,7 +21,7 @@ class Rational < Numeric
21
21
 
22
22
  def self.convert(num, den)
23
23
  if num.nil? || den.nil?
24
- raise TypeError, "cannot convert nil into Rational"
24
+ raise TypeError, 'cannot convert nil into Rational'
25
25
  end
26
26
 
27
27
  if Integer === num && Integer === den
@@ -45,8 +45,6 @@ class Rational < Numeric
45
45
  end
46
46
  end
47
47
 
48
- attr_reader :numerator, :denominator
49
-
50
48
  def initialize(num, den)
51
49
  @num = num
52
50
  @den = den
@@ -189,31 +187,31 @@ class Rational < Numeric
189
187
  case other
190
188
  when Integer
191
189
  if self == 0 && other < 0
192
- return Float::INFINITY
190
+ Float::INFINITY
193
191
  elsif other > 0
194
- Rational(@num ** other, @den ** other)
192
+ Rational(@num**other, @den**other)
195
193
  elsif other < 0
196
- Rational(@den ** -other, @num ** -other)
194
+ Rational(@den**-other, @num**-other)
197
195
  else
198
196
  Rational(1, 1)
199
197
  end
200
198
 
201
199
  when Float
202
- to_f ** other
200
+ to_f**other
203
201
 
204
202
  when Rational
205
203
  if other == 0
206
204
  Rational(1, 1)
207
205
  elsif other.denominator == 1
208
206
  if other < 0
209
- Rational(@den ** other.numerator.abs, @num ** other.numerator.abs)
207
+ Rational(@den**other.numerator.abs, @num**other.numerator.abs)
210
208
  else
211
- Rational(@num ** other.numerator, @den ** other.numerator)
209
+ Rational(@num**other.numerator, @den**other.numerator)
212
210
  end
213
211
  elsif self == 0 && other < 0
214
- raise ZeroDivisionError, "divided by 0"
212
+ raise ZeroDivisionError, 'divided by 0'
215
213
  else
216
- to_f ** other
214
+ to_f**other
217
215
  end
218
216
 
219
217
  else
@@ -244,11 +242,11 @@ class Rational < Numeric
244
242
  end
245
243
 
246
244
  def hash
247
- "Rational:#@num:#@den"
245
+ "Rational:#{@num}:#{@den}"
248
246
  end
249
247
 
250
248
  def inspect
251
- "(#{to_s})"
249
+ "(#{self})"
252
250
  end
253
251
 
254
252
  alias quo /
@@ -329,7 +327,7 @@ class Rational < Numeric
329
327
  end
330
328
 
331
329
  def to_s
332
- "#@num/#@den"
330
+ "#{@num}/#{@den}"
333
331
  end
334
332
 
335
333
  def truncate(precision = 0)
@@ -341,9 +339,9 @@ class Rational < Numeric
341
339
  end
342
340
 
343
341
  def with_precision(method, precision)
344
- raise TypeError, "not an Integer" unless Integer === precision
342
+ raise TypeError, 'not an Integer' unless Integer === precision
345
343
 
346
- p = 10 ** precision
344
+ p = 10**precision
347
345
  s = self * p
348
346
 
349
347
  if precision < 1
@@ -359,3 +357,45 @@ module Kernel
359
357
  Rational.convert(numerator, denominator)
360
358
  end
361
359
  end
360
+
361
+ class String
362
+ def to_r
363
+ %x{
364
+ var str = self.trimLeft(),
365
+ re = /^[+-]?[\d_]+(\.[\d_]+)?/,
366
+ match = str.match(re),
367
+ numerator, denominator;
368
+
369
+ function isFloat() {
370
+ return re.test(str);
371
+ }
372
+
373
+ function cutFloat() {
374
+ var match = str.match(re);
375
+ var number = match[0];
376
+ str = str.slice(number.length);
377
+ return number.replace(/_/g, '');
378
+ }
379
+
380
+ if (isFloat()) {
381
+ numerator = parseFloat(cutFloat());
382
+
383
+ if (str[0] === '/') {
384
+ // rational real part
385
+ str = str.slice(1);
386
+
387
+ if (isFloat()) {
388
+ denominator = parseFloat(cutFloat());
389
+ return #{Rational(`numerator`, `denominator`)};
390
+ } else {
391
+ return #{Rational(`numerator`, 1)};
392
+ }
393
+ } else {
394
+ return #{Rational(`numerator`, 1)};
395
+ }
396
+ } else {
397
+ return #{Rational(0, 1)};
398
+ }
399
+ }
400
+ end
401
+ end
@@ -2,9 +2,10 @@ class RegexpError < StandardError; end
2
2
 
3
3
  class Regexp < `RegExp`
4
4
  IGNORECASE = 1
5
+ EXTENDED = 2
5
6
  MULTILINE = 4
6
7
 
7
- `def.$$is_regexp = true`
8
+ `Opal.defineProperty(self.$$prototype, '$$is_regexp', true)`
8
9
 
9
10
  class << self
10
11
  def allocate
@@ -17,7 +18,7 @@ class Regexp < `RegExp`
17
18
  `Opal.escape_regexp(string)`
18
19
  end
19
20
 
20
- def last_match(n=nil)
21
+ def last_match(n = nil)
21
22
  if n.nil?
22
23
  $~
23
24
  else
@@ -33,6 +34,10 @@ class Regexp < `RegExp`
33
34
  if (parts.length == 0) {
34
35
  return /(?!)/;
35
36
  }
37
+ // return fast if there's only one element
38
+ if (parts.length == 1 && parts[0].$$is_regexp) {
39
+ return parts[0];
40
+ }
36
41
  // cover the 2 arrays passed as arguments case
37
42
  is_first_part_array = parts[0].$$is_array;
38
43
  if (parts.length > 1 && is_first_part_array) {
@@ -98,7 +103,7 @@ class Regexp < `RegExp`
98
103
  end
99
104
 
100
105
  def ==(other)
101
- `other.constructor == RegExp && self.toString() === other.toString()`
106
+ `other instanceof RegExp && self.toString() === other.toString()`
102
107
  end
103
108
 
104
109
  def ===(string)
@@ -156,11 +161,18 @@ class Regexp < `RegExp`
156
161
  }
157
162
 
158
163
  if (pos === undefined) {
159
- pos = 0;
160
- } else {
161
- pos = #{Opal.coerce_to(pos, Integer, :to_int)};
164
+ if (string === nil) return #{$~ = nil};
165
+ var m = self.exec(#{Opal.coerce_to(string, String, :to_str)});
166
+ if (m) {
167
+ #{$~ = MatchData.new(`self`, `m`)};
168
+ return block === nil ? #{$~} : #{yield $~};
169
+ } else {
170
+ return #{$~ = nil};
171
+ }
162
172
  }
163
173
 
174
+ pos = #{Opal.coerce_to(pos, Integer, :to_int)};
175
+
164
176
  if (string === nil) {
165
177
  return #{$~ = nil};
166
178
  }
@@ -174,16 +186,8 @@ class Regexp < `RegExp`
174
186
  }
175
187
  }
176
188
 
177
- var source = self.source;
178
- var flags = 'g';
179
- // m flag + a . in Ruby will match white space, but in JS, it only matches beginning/ending of lines, so we get the equivalent here
180
- if (self.multiline) {
181
- source = source.replace('.', "[\\s\\S]");
182
- flags += 'm';
183
- }
184
-
185
189
  // global RegExp maintains state, so not using self/this
186
- var md, re = new RegExp(source, flags + (self.ignoreCase ? 'i' : ''));
190
+ var md, re = Opal.global_regexp(self);
187
191
 
188
192
  while (true) {
189
193
  md = re.exec(string);
@@ -191,8 +195,8 @@ class Regexp < `RegExp`
191
195
  return #{$~ = nil};
192
196
  }
193
197
  if (md.index >= pos) {
194
- #{$~ = MatchData.new(`re`, `md`)}
195
- return block === nil ? #{$~} : #{block.call($~)};
198
+ #{$~ = MatchData.new(`re`, `md`)};
199
+ return block === nil ? #{$~} : #{yield $~};
196
200
  }
197
201
  re.lastIndex = md.index + 1;
198
202
  }
@@ -206,11 +210,11 @@ class Regexp < `RegExp`
206
210
  }
207
211
 
208
212
  if (pos === undefined) {
209
- pos = 0;
210
- } else {
211
- pos = #{Opal.coerce_to(pos, Integer, :to_int)};
213
+ return string === nil ? false : self.test(#{Opal.coerce_to(string, String, :to_str)});
212
214
  }
213
215
 
216
+ pos = #{Opal.coerce_to(pos, Integer, :to_int)};
217
+
214
218
  if (string === nil) {
215
219
  return false;
216
220
  }
@@ -224,16 +228,8 @@ class Regexp < `RegExp`
224
228
  }
225
229
  }
226
230
 
227
- var source = self.source;
228
- var flags = 'g';
229
- // m flag + a . in Ruby will match white space, but in JS, it only matches beginning/ending of lines, so we get the equivalent here
230
- if (self.multiline) {
231
- source = source.replace('.', "[\\s\\S]");
232
- flags += 'm';
233
- }
234
-
235
231
  // global RegExp maintains state, so not using self/this
236
- var md, re = new RegExp(source, flags + (self.ignoreCase ? 'i' : ''));
232
+ var md, re = Opal.global_regexp(self);
237
233
 
238
234
  md = re.exec(string);
239
235
  if (md === null || md.index < pos) {
@@ -294,10 +290,10 @@ class MatchData
294
290
  var group = match_groups[i];
295
291
 
296
292
  if (group == null) {
297
- #@matches.push(nil);
293
+ #{@matches}.push(nil);
298
294
  }
299
295
  else {
300
- #@matches.push(group);
296
+ #{@matches}.push(group);
301
297
  }
302
298
  }
303
299
  }
@@ -320,10 +316,10 @@ class MatchData
320
316
  return false unless MatchData === other
321
317
 
322
318
  `self.string == other.string` &&
323
- `self.regexp.toString() == other.regexp.toString()` &&
324
- `self.pre_match == other.pre_match` &&
325
- `self.post_match == other.post_match` &&
326
- `self.begin == other.begin`
319
+ `self.regexp.toString() == other.regexp.toString()` &&
320
+ `self.pre_match == other.pre_match` &&
321
+ `self.post_match == other.post_match` &&
322
+ `self.begin == other.begin`
327
323
  end
328
324
 
329
325
  alias eql? ==
@@ -347,15 +343,15 @@ class MatchData
347
343
  end
348
344
 
349
345
  def captures
350
- `#@matches.slice(1)`
346
+ `#{@matches}.slice(1)`
351
347
  end
352
348
 
353
349
  def inspect
354
350
  %x{
355
- var str = "#<MatchData " + #{`#@matches[0]`.inspect};
351
+ var str = "#<MatchData " + #{`#{@matches}[0]`.inspect};
356
352
 
357
- for (var i = 1, length = #@matches.length; i < length; i++) {
358
- str += " " + i + ":" + #{`#@matches[i]`.inspect};
353
+ for (var i = 1, length = #{@matches}.length; i < length; i++) {
354
+ str += " " + i + ":" + #{`#{@matches}[i]`.inspect};
359
355
  }
360
356
 
361
357
  return str + ">";
@@ -363,7 +359,7 @@ class MatchData
363
359
  end
364
360
 
365
361
  def length
366
- `#@matches.length`
362
+ `#{@matches}.length`
367
363
  end
368
364
 
369
365
  alias size length
@@ -373,7 +369,7 @@ class MatchData
373
369
  end
374
370
 
375
371
  def to_s
376
- `#@matches[0]`
372
+ `#{@matches}[0]`
377
373
  end
378
374
 
379
375
  def values_at(*args)
@@ -391,14 +387,14 @@ class MatchData
391
387
  index = #{Opal.coerce_to!(`args[i]`, Integer, :to_int)};
392
388
 
393
389
  if (index < 0) {
394
- index += #@matches.length;
390
+ index += #{@matches}.length;
395
391
  if (index < 0) {
396
392
  values.push(nil);
397
393
  continue;
398
394
  }
399
395
  }
400
396
 
401
- values.push(#@matches[index]);
397
+ values.push(#{@matches}[index]);
402
398
  }
403
399
 
404
400
  return values;
@@ -51,27 +51,9 @@
51
51
  // The actual Class class
52
52
  var Class;
53
53
 
54
- // Constructor for instances of BasicObject
55
- function BasicObject_alloc(){}
56
-
57
- // Constructor for instances of Object
58
- function Object_alloc(){}
59
-
60
- // Constructor for instances of Class
61
- function Class_alloc(){}
62
-
63
- // Constructor for instances of Module
64
- function Module_alloc(){}
65
-
66
- // Constructor for instances of NilClass (nil)
67
- function NilClass_alloc(){}
68
-
69
54
  // The Opal object that is exposed globally
70
55
  var Opal = this.Opal = {};
71
56
 
72
- // All bridged classes - keep track to donate methods from Object
73
- var BridgedClasses = {};
74
-
75
57
  // This is a useful reference to global object inside ruby files
76
58
  Opal.global = global_object;
77
59
  global_object.Opal = Opal;
@@ -84,8 +66,11 @@
84
66
  }
85
67
 
86
68
  // Minify common function calls
87
- var $hasOwn = Object.hasOwnProperty;
88
- var $slice = Opal.slice = Array.prototype.slice;
69
+ var $hasOwn = Object.hasOwnProperty;
70
+ var $bind = Function.prototype.bind;
71
+ var $setPrototype = Object.setPrototypeOf;
72
+ var $slice = Array.prototype.slice;
73
+ var $splice = Array.prototype.splice;
89
74
 
90
75
  // Nil object id is always 4
91
76
  var nil_id = 4;
@@ -103,7 +88,11 @@
103
88
  // Retrieve or assign the id of an object
104
89
  Opal.id = function(obj) {
105
90
  if (obj.$$is_number) return (obj * 2)+1;
106
- return obj.$$id || (obj.$$id = Opal.uid());
91
+ if (obj.$$id != null) {
92
+ return obj.$$id;
93
+ };
94
+ $defineProperty(obj, '$$id', Opal.uid());
95
+ return obj.$$id;
107
96
  };
108
97
 
109
98
  // Globals table
@@ -138,6 +127,30 @@
138
127
  }
139
128
  }
140
129
 
130
+ function $defineProperty(object, name, initialValue) {
131
+ if (typeof(object) === "string") {
132
+ // Special case for:
133
+ // s = "string"
134
+ // def s.m; end
135
+ // String class is the only class that:
136
+ // + compiles to JS primitive
137
+ // + allows method definition directly on instances
138
+ // numbers, true, false and nil do not support it.
139
+ object[name] = initialValue;
140
+ } else {
141
+ Object.defineProperty(object, name, {
142
+ value: initialValue,
143
+ enumerable: false,
144
+ configurable: true,
145
+ writable: true
146
+ });
147
+ }
148
+ }
149
+
150
+ Opal.defineProperty = $defineProperty;
151
+
152
+ Opal.slice = $slice;
153
+
141
154
 
142
155
  // Truth
143
156
  // -----
@@ -220,7 +233,7 @@
220
233
 
221
234
  if (cref === '::') cref = _Object;
222
235
 
223
- if (!cref.$$is_a_module) {
236
+ if (!cref.$$is_module && !cref.$$is_class) {
224
237
  throw new Opal.TypeError(cref.toString() + " is not a class/module");
225
238
  }
226
239
 
@@ -237,12 +250,13 @@
237
250
 
238
251
  if (cref === '::') cref = _Object;
239
252
 
240
- if (!cref.$$is_a_module) {
253
+ if (!cref.$$is_module && !cref.$$is_class) {
241
254
  throw new Opal.TypeError(cref.toString() + " is not a class/module");
242
255
  }
243
256
 
244
257
  if ((cache = cref.$$const_cache) == null) {
245
- cache = cref.$$const_cache = Object.create(null);
258
+ $defineProperty(cref, '$$const_cache', Object.create(null));
259
+ cache = cref.$$const_cache;
246
260
  }
247
261
  cached = cache[name];
248
262
 
@@ -266,7 +280,8 @@
266
280
  var cref = nesting[0], result, current_version = Opal.const_cache_version, cache, cached;
267
281
 
268
282
  if ((cache = nesting.$$const_cache) == null) {
269
- cache = nesting.$$const_cache = Object.create(null);
283
+ $defineProperty(nesting, '$$const_cache', Object.create(null));
284
+ cache = nesting.$$const_cache;
270
285
  }
271
286
  cached = cache[name];
272
287
 
@@ -297,11 +312,19 @@
297
312
  cref.$$const = (cref.$$const || Object.create(null));
298
313
  cref.$$const[name] = value;
299
314
 
315
+ // Add a short helper to navigate constants manually.
316
+ // @example
317
+ // Opal.$$.Regexp.$$.IGNORECASE
318
+ cref.$$ = cref.$$const;
319
+
300
320
  Opal.const_cache_version++;
301
321
 
302
322
  // Expose top level constants onto the Opal object
303
323
  if (cref === _Object) Opal[name] = value;
304
324
 
325
+ // Name new class directly onto current scope (Opal.Foo.Baz = klass)
326
+ $defineProperty(cref, name, value);
327
+
305
328
  return value;
306
329
  };
307
330
 
@@ -364,38 +387,81 @@
364
387
  // simply so that classes show up with nicely formatted names inside debuggers
365
388
  // in the web browser (or node/sprockets).
366
389
  //
367
- // The `base` is the current `self` value where the class is being created
390
+ // The `scope` is the current `self` value where the class is being created
368
391
  // from. We use this to get the scope for where the class should be created.
369
- // If `base` is an object (not a class/module), we simple get its class and
370
- // use that as the base instead.
392
+ // If `scope` is an object (not a class/module), we simple get its class and
393
+ // use that as the scope instead.
371
394
  //
372
- // @param base [Object] where the class is being created
395
+ // @param scope [Object] where the class is being created
373
396
  // @param superclass [Class,null] superclass of the new class (may be null)
374
397
  // @param id [String] the name of the class to be created
375
398
  // @param constructor [JS.Function] function to use as constructor
376
399
  //
377
400
  // @return new [Class] or existing ruby class
378
401
  //
379
- Opal.klass = function(base, superclass, name, constructor) {
380
- var klass, bridged, alloc;
402
+ Opal.allocate_class = function(name, superclass) {
403
+ var klass, constructor;
404
+
405
+ if (superclass != null && superclass.$$bridge) {
406
+ // Inheritance from bridged classes requires
407
+ // calling original JS constructors
408
+ constructor = function() {
409
+ var args = $slice.call(arguments),
410
+ self = new ($bind.apply(superclass.$$constructor, [null].concat(args)))();
381
411
 
382
- if (base == null) {
383
- base = _Object;
412
+ // and replacing a __proto__ manually
413
+ $setPrototype(self, klass.$$prototype);
414
+ return self;
415
+ }
416
+ } else {
417
+ constructor = function(){};
384
418
  }
385
419
 
386
- // If base is an object, use its class
387
- if (!base.$$is_class && !base.$$is_module) {
388
- base = base.$$class;
420
+ if (name) {
421
+ $defineProperty(constructor, 'displayName', '::'+name);
389
422
  }
390
423
 
391
- // If the superclass is a function then we're bridging a native JS class
392
- if (typeof(superclass) === 'function') {
393
- bridged = superclass;
394
- superclass = _Object;
424
+ klass = constructor;
425
+
426
+ $defineProperty(klass, '$$name', name);
427
+ $defineProperty(klass, '$$constructor', constructor);
428
+ $defineProperty(klass, '$$prototype', constructor.prototype);
429
+ $defineProperty(klass, '$$const', {});
430
+ $defineProperty(klass, '$$is_class', true);
431
+ $defineProperty(klass, '$$is_a_module', true);
432
+ $defineProperty(klass, '$$super', superclass);
433
+ $defineProperty(klass, '$$cvars', {});
434
+ $defineProperty(klass, '$$own_included_modules', []);
435
+ $defineProperty(klass, '$$own_prepended_modules', []);
436
+ $defineProperty(klass, '$$ancestors', []);
437
+ $defineProperty(klass, '$$ancestors_cache_version', null);
438
+
439
+ $defineProperty(klass.$$prototype, '$$class', klass);
440
+
441
+ // By default if there are no singleton class methods
442
+ // __proto__ is Class.prototype
443
+ // Later singleton methods generate a singleton_class
444
+ // and inject it into ancestors chain
445
+ if (Opal.Class) {
446
+ $setPrototype(klass, Opal.Class.prototype);
395
447
  }
396
448
 
449
+ if (superclass != null) {
450
+ $setPrototype(klass.$$prototype, superclass.$$prototype);
451
+
452
+ if (superclass.$$meta) {
453
+ // If superclass has metaclass then we have explicitely inherit it.
454
+ Opal.build_class_singleton_class(klass);
455
+ }
456
+ };
457
+
458
+ return klass;
459
+ }
460
+
461
+
462
+ function find_existing_class(scope, name) {
397
463
  // Try to find the class in the current scope
398
- klass = const_get_name(base, name);
464
+ var klass = const_get_name(scope, name);
399
465
 
400
466
  // If the class exists in the scope, then we must use that
401
467
  if (klass) {
@@ -404,271 +470,149 @@
404
470
  throw Opal.TypeError.$new(name + " is not a class");
405
471
  }
406
472
 
407
- // Make sure existing class has same superclass
408
- if (superclass && klass.$$super !== superclass) {
409
- throw Opal.TypeError.$new("superclass mismatch for class " + name);
410
- }
411
-
412
473
  return klass;
413
474
  }
475
+ }
414
476
 
415
- // Class doesnt exist, create a new one with given superclass...
416
-
417
- // Not specifying a superclass means we can assume it to be Object
418
- if (superclass == null) {
419
- superclass = _Object;
477
+ function ensureSuperclassMatch(klass, superclass) {
478
+ if (klass.$$super !== superclass) {
479
+ throw Opal.TypeError.$new("superclass mismatch for class " + klass.$$name);
420
480
  }
481
+ }
421
482
 
422
- // If bridged the JS class will also be the alloc function
423
- alloc = bridged || Opal.boot_class_alloc(name, constructor, superclass);
424
-
425
- // Create the class object (instance of Class)
426
- klass = Opal.setup_class_object(name, alloc, superclass.$$name, superclass.constructor);
427
-
428
- // @property $$super the superclass, doesn't get changed by module inclusions
429
- klass.$$super = superclass;
483
+ Opal.klass = function(scope, superclass, name) {
484
+ var bridged;
430
485
 
431
- // @property $$parent direct parent class
432
- // starts with the superclass, after klass inclusion is
433
- // the last included klass
434
- klass.$$parent = superclass;
486
+ if (scope == null) {
487
+ // Global scope
488
+ scope = _Object;
489
+ } else if (!scope.$$is_class && !scope.$$is_module) {
490
+ // Scope is an object, use its class
491
+ scope = scope.$$class;
492
+ }
435
493
 
436
- Opal.const_set(base, name, klass);
494
+ // If the superclass is not an Opal-generated class then we're bridging a native JS class
495
+ if (superclass != null && !superclass.hasOwnProperty('$$is_class')) {
496
+ bridged = superclass;
497
+ superclass = _Object;
498
+ }
437
499
 
438
- // Name new class directly onto current scope (Opal.Foo.Baz = klass)
439
- base[name] = klass;
500
+ var klass = find_existing_class(scope, name);
440
501
 
441
- if (bridged) {
442
- Opal.bridge(klass, alloc);
443
- }
444
- else {
445
- // Call .inherited() hook with new class on the superclass
446
- if (superclass.$inherited) {
447
- superclass.$inherited(klass);
502
+ if (klass) {
503
+ if (superclass) {
504
+ // Make sure existing class has same superclass
505
+ ensureSuperclassMatch(klass, superclass);
448
506
  }
507
+ return klass;
449
508
  }
450
509
 
451
- return klass;
452
- };
510
+ // Class doesn't exist, create a new one with given superclass...
453
511
 
454
- // Boot a base class (makes instances).
455
- //
456
- // @param name [String,null] the class name
457
- // @param constructor [JS.Function] the class' instances constructor/alloc function
458
- // @param superclass [Class,null] the superclass object
459
- // @return [JS.Function] the consturctor holding the prototype for the class' instances
460
- Opal.boot_class_alloc = function(name, constructor, superclass) {
461
- if (superclass) {
462
- var alloc_proxy = function() {};
463
- alloc_proxy.prototype = superclass.$$proto || superclass.prototype;
464
- constructor.prototype = new alloc_proxy();
465
- }
466
-
467
- if (name) {
468
- constructor.displayName = name+'_alloc';
512
+ // Not specifying a superclass means we can assume it to be Object
513
+ if (superclass == null) {
514
+ superclass = _Object;
469
515
  }
470
516
 
471
- constructor.prototype.constructor = constructor;
472
-
473
- return constructor;
474
- };
475
-
476
- Opal.setup_module_or_class = function(module) {
477
- // @property $$id Each class/module is assigned a unique `id` that helps
478
- // comparation and implementation of `#object_id`
479
- module.$$id = Opal.uid();
480
-
481
- // @property $$is_a_module Will be true for Module and its subclasses
482
- // instances (namely: Class).
483
- module.$$is_a_module = true;
484
-
485
- // @property $$inc included modules
486
- module.$$inc = [];
487
-
488
- // initialize the name with nil
489
- module.$$name = nil;
490
-
491
- // Initialize the constants table
492
- module.$$const = Object.create(null);
493
-
494
- // @property $$cvars class variables defined in the current module
495
- module.$$cvars = Object.create(null);
496
- }
497
-
498
-
499
-
500
- // Adds common/required properties to class object (as in `Class.new`)
501
- //
502
- // @param name [String,null] The name of the class
503
- //
504
- // @param alloc [JS.Function] The constructor of the class' instances
505
- //
506
- // @param superclass_name [String,null]
507
- // The name of the super class, this is
508
- // usefule to build the `.displayName` of the singleton class
509
- //
510
- // @param superclass_alloc [JS.Function]
511
- // The constructor of the superclass from which the singleton_class is
512
- // derived.
513
- //
514
- // @return [Class]
515
- Opal.setup_class_object = function(name, alloc, superclass_name, superclass_alloc) {
516
- // Grab the superclass prototype and use it to build an intermediary object
517
- // in the prototype chain.
518
- var superclass_alloc_proxy = function() {};
519
- superclass_alloc_proxy.prototype = superclass_alloc.prototype;
520
- superclass_alloc_proxy.displayName = superclass_name;
521
-
522
- var singleton_class_alloc = function() {}
523
- singleton_class_alloc.prototype = new superclass_alloc_proxy();
524
-
525
- // The built class is the only instance of its singleton_class
526
- var klass = new singleton_class_alloc();
527
-
528
- Opal.setup_module_or_class(klass);
529
-
530
- // @property $$alloc This is the constructor of instances of the current
531
- // class. Its prototype will be used for method lookup
532
- klass.$$alloc = alloc;
533
-
534
- klass.$$name = name || nil;
535
-
536
- // Set a displayName for the singleton_class
537
- singleton_class_alloc.displayName = "#<Class:"+(name || ("#<Class:"+klass.$$id+">"))+">";
538
-
539
- // @property $$proto This is the prototype on which methods will be defined
540
- klass.$$proto = alloc.prototype;
541
-
542
- // @property $$proto.$$class Make available to instances a reference to the
543
- // class they belong to.
544
- klass.$$proto.$$class = klass;
545
-
546
- // @property constructor keeps a ref to the constructor, but apparently the
547
- // constructor is already set on:
548
- //
549
- // `var klass = new constructor` is called.
550
- //
551
- // Maybe there are some browsers not abiding (IE6?)
552
- klass.constructor = singleton_class_alloc;
517
+ // Create the class object (instance of Class)
518
+ klass = Opal.allocate_class(name, superclass);
519
+ Opal.const_set(scope, name, klass);
553
520
 
554
- // @property $$is_class Clearly mark this as a class
555
- klass.$$is_class = true;
521
+ // Call .inherited() hook with new class on the superclass
522
+ if (superclass.$inherited) {
523
+ superclass.$inherited(klass);
524
+ }
556
525
 
557
- // @property $$class Classes are instances of the class Class
558
- klass.$$class = Class;
526
+ if (bridged) {
527
+ Opal.bridge(bridged, klass);
528
+ }
559
529
 
560
530
  return klass;
561
- };
531
+ }
562
532
 
563
- // Define new module (or return existing module). The given `base` is basically
533
+ // Define new module (or return existing module). The given `scope` is basically
564
534
  // the current `self` value the `module` statement was defined in. If this is
565
- // a ruby module or class, then it is used, otherwise if the base is a ruby
566
- // object then that objects real ruby class is used (e.g. if the base is the
567
- // main object, then the top level `Object` class is used as the base).
535
+ // a ruby module or class, then it is used, otherwise if the scope is a ruby
536
+ // object then that objects real ruby class is used (e.g. if the scope is the
537
+ // main object, then the top level `Object` class is used as the scope).
568
538
  //
569
- // If a module of the given name is already defined in the base, then that
539
+ // If a module of the given name is already defined in the scope, then that
570
540
  // instance is just returned.
571
541
  //
572
- // If there is a class of the given name in the base, then an error is
573
- // generated instead (cannot have a class and module of same name in same base).
542
+ // If there is a class of the given name in the scope, then an error is
543
+ // generated instead (cannot have a class and module of same name in same scope).
574
544
  //
575
- // Otherwise, a new module is created in the base with the given name, and that
545
+ // Otherwise, a new module is created in the scope with the given name, and that
576
546
  // new instance is returned back (to be referenced at runtime).
577
547
  //
578
- // @param base [Module, Class] class or module this definition is inside
548
+ // @param scope [Module, Class] class or module this definition is inside
579
549
  // @param id [String] the name of the new (or existing) module
580
550
  //
581
551
  // @return [Module]
582
- Opal.module = function(base, name) {
583
- var module;
584
-
585
- if (base == null) {
586
- base = _Object;
552
+ Opal.allocate_module = function(name) {
553
+ var constructor = function(){};
554
+ if (name) {
555
+ $defineProperty(constructor, 'displayName', name+'.$$constructor');
587
556
  }
588
557
 
589
- if (!base.$$is_class && !base.$$is_module) {
590
- base = base.$$class;
591
- }
558
+ var module = constructor;
592
559
 
593
- module = const_get_name(base, name);
594
- if (module == null && base === _Object) module = const_lookup_ancestors(_Object, name);
560
+ if (name)
561
+ $defineProperty(constructor, 'displayName', name+'.constructor');
562
+
563
+ $defineProperty(module, '$$name', name);
564
+ $defineProperty(module, '$$prototype', constructor.prototype);
565
+ $defineProperty(module, '$$const', {});
566
+ $defineProperty(module, '$$is_module', true);
567
+ $defineProperty(module, '$$is_a_module', true);
568
+ $defineProperty(module, '$$cvars', {});
569
+ $defineProperty(module, '$$iclasses', []);
570
+ $defineProperty(module, '$$own_included_modules', []);
571
+ $defineProperty(module, '$$own_prepended_modules', []);
572
+ $defineProperty(module, '$$ancestors', [module]);
573
+ $defineProperty(module, '$$ancestors_cache_version', null);
574
+
575
+ $setPrototype(module, Opal.Module.prototype);
576
+
577
+ return module;
578
+ }
579
+
580
+ function find_existing_module(scope, name) {
581
+ var module = const_get_name(scope, name);
582
+ if (module == null && scope === _Object) module = const_lookup_ancestors(_Object, name);
595
583
 
596
584
  if (module) {
597
585
  if (!module.$$is_module && module !== _Object) {
598
586
  throw Opal.TypeError.$new(name + " is not a module");
599
587
  }
600
588
  }
601
- else {
602
- module = Opal.module_allocate(Module);
603
- Opal.const_set(base, name, module);
604
- }
605
589
 
606
590
  return module;
607
- };
608
-
609
- // The implementation for Module#initialize
610
- // @param module [Module]
611
- // @param block [Proc,nil]
612
- // @return nil
613
- Opal.module_initialize = function(module, block) {
614
- if (block !== nil) {
615
- var block_self = block.$$s;
616
- block.$$s = null;
617
- block.call(module);
618
- block.$$s = block_self;
619
- }
620
- return nil;
621
- };
622
-
623
- // Internal function to create a new module instance. This simply sets up
624
- // the prototype hierarchy and method tables.
625
- //
626
- Opal.module_allocate = function(superclass) {
627
- var mtor = function() {};
628
- mtor.prototype = superclass.$$alloc.prototype;
629
-
630
- var module_constructor = function() {};
631
- module_constructor.prototype = new mtor();
632
-
633
- var module = new module_constructor();
634
- var module_prototype = {};
635
-
636
- Opal.setup_module_or_class(module);
637
-
638
- // initialize dependency tracking
639
- module.$$included_in = [];
640
-
641
- // Set the display name of the singleton prototype holder
642
- module_constructor.displayName = "#<Class:#<Module:"+module.$$id+">>"
591
+ }
643
592
 
644
- // @property $$proto This is the prototype on which methods will be defined
645
- module.$$proto = module_prototype;
593
+ Opal.module = function(scope, name) {
594
+ var module;
646
595
 
647
- // @property constructor
648
- // keeps a ref to the constructor, but apparently the
649
- // constructor is already set on:
650
- //
651
- // `var module = new constructor` is called.
652
- //
653
- // Maybe there are some browsers not abiding (IE6?)
654
- module.constructor = module_constructor;
596
+ if (scope == null) {
597
+ // Global scope
598
+ scope = _Object;
599
+ } else if (!scope.$$is_class && !scope.$$is_module) {
600
+ // Scope is an object, use its class
601
+ scope = scope.$$class;
602
+ }
655
603
 
656
- // @property $$is_module Clearly mark this as a module
657
- module.$$is_module = true;
658
- module.$$class = Module;
604
+ module = find_existing_module(scope, name);
659
605
 
660
- // @property $$super
661
- // the superclass, doesn't get changed by module inclusions
662
- module.$$super = superclass;
606
+ if (module) {
607
+ return module;
608
+ }
663
609
 
664
- // @property $$parent
665
- // direct parent class or module
666
- // starts with the superclass, after module inclusion is
667
- // the last included module
668
- module.$$parent = superclass;
610
+ // Module doesnt exist, create a new one...
611
+ module = Opal.allocate_module(name);
612
+ Opal.const_set(scope, name, module);
669
613
 
670
614
  return module;
671
- };
615
+ }
672
616
 
673
617
  // Return the singleton class for the passed object.
674
618
  //
@@ -686,11 +630,13 @@
686
630
  return object.$$meta;
687
631
  }
688
632
 
689
- if (object.$$is_class || object.$$is_module) {
633
+ if (object.hasOwnProperty('$$is_class')) {
690
634
  return Opal.build_class_singleton_class(object);
635
+ } else if (object.hasOwnProperty('$$is_module')) {
636
+ return Opal.build_module_singletin_class(object);
637
+ } else {
638
+ return Opal.build_object_singleton_class(object);
691
639
  }
692
-
693
- return Opal.build_object_singleton_class(object);
694
640
  };
695
641
 
696
642
  // Build the singleton class for an existing class. Class object are built
@@ -702,54 +648,146 @@
702
648
  //
703
649
  // @param klass [Class]
704
650
  // @return [Class]
705
- Opal.build_class_singleton_class = function(object) {
706
- var alloc, superclass, klass;
651
+ Opal.build_class_singleton_class = function(klass) {
652
+ var superclass, meta;
707
653
 
708
- if (object.$$meta) {
709
- return object.$$meta;
654
+ if (klass.$$meta) {
655
+ return klass.$$meta;
710
656
  }
711
657
 
712
- // The constructor and prototype of the singleton_class instances is the
713
- // current class constructor and prototype.
714
- alloc = object.constructor;
715
-
716
658
  // The singleton_class superclass is the singleton_class of its superclass;
717
659
  // but BasicObject has no superclass (its `$$super` is null), thus we
718
660
  // fallback on `Class`.
719
- superclass = object === BasicObject ? Class : Opal.build_class_singleton_class(object.$$super);
661
+ superclass = klass === BasicObject ? Class : Opal.get_singleton_class(klass.$$super);
720
662
 
721
- klass = Opal.setup_class_object(null, alloc, superclass.$$name, superclass.constructor);
722
- klass.$$super = superclass;
723
- klass.$$parent = superclass;
663
+ meta = Opal.allocate_class(null, superclass, function(){});
724
664
 
725
- klass.$$is_singleton = true;
726
- klass.$$singleton_of = object;
665
+ $defineProperty(meta, '$$is_singleton', true);
666
+ $defineProperty(meta, '$$singleton_of', klass);
667
+ $defineProperty(klass, '$$meta', meta);
668
+ $setPrototype(klass, meta.$$prototype);
669
+ // Restoring ClassName.class
670
+ $defineProperty(klass, '$$class', Opal.Class);
727
671
 
728
- return object.$$meta = klass;
672
+ return meta;
729
673
  };
730
674
 
675
+ Opal.build_module_singletin_class = function(mod) {
676
+ if (mod.$$meta) {
677
+ return mod.$$meta;
678
+ }
679
+
680
+ var meta = Opal.allocate_class(null, Opal.Module, function(){});
681
+
682
+ $defineProperty(meta, '$$is_singleton', true);
683
+ $defineProperty(meta, '$$singleton_of', mod);
684
+ $defineProperty(mod, '$$meta', meta);
685
+ $setPrototype(mod, meta.$$prototype);
686
+ // Restoring ModuleName.class
687
+ $defineProperty(mod, '$$class', Opal.Module);
688
+
689
+ return meta;
690
+ }
691
+
731
692
  // Build the singleton class for a Ruby (non class) Object.
732
693
  //
733
694
  // @param object [Object]
734
695
  // @return [Class]
735
696
  Opal.build_object_singleton_class = function(object) {
736
697
  var superclass = object.$$class,
737
- name = "#<Class:#<" + superclass.$$name + ":" + superclass.$$id + ">>";
698
+ klass = Opal.allocate_class(nil, superclass, function(){});
738
699
 
739
- var alloc = Opal.boot_class_alloc(name, function(){}, superclass)
740
- var klass = Opal.setup_class_object(name, alloc, superclass.$$name, superclass.constructor);
700
+ $defineProperty(klass, '$$is_singleton', true);
701
+ $defineProperty(klass, '$$singleton_of', object);
741
702
 
742
- klass.$$super = superclass;
743
- klass.$$parent = superclass;
744
- klass.$$class = superclass.$$class;
745
- klass.$$proto = object;
703
+ delete klass.$$prototype.$$class;
746
704
 
747
- klass.$$is_singleton = true;
748
- klass.$$singleton_of = object;
705
+ $defineProperty(object, '$$meta', klass);
749
706
 
750
- return object.$$meta = klass;
707
+ $setPrototype(object, object.$$meta.$$prototype);
708
+
709
+ return klass;
751
710
  };
752
711
 
712
+ Opal.is_method = function(prop) {
713
+ return (prop[0] === '$' && prop[1] !== '$');
714
+ }
715
+
716
+ Opal.instance_methods = function(mod) {
717
+ var exclude = [], results = [], ancestors = Opal.ancestors(mod);
718
+
719
+ for (var i = 0, l = ancestors.length; i < l; i++) {
720
+ var ancestor = ancestors[i],
721
+ proto = ancestor.$$prototype;
722
+
723
+ if (proto.hasOwnProperty('$$dummy')) {
724
+ proto = proto.$$define_methods_on;
725
+ }
726
+
727
+ var props = Object.getOwnPropertyNames(proto);
728
+
729
+ for (var j = 0, ll = props.length; j < ll; j++) {
730
+ var prop = props[j];
731
+
732
+ if (Opal.is_method(prop)) {
733
+ var method_name = prop.slice(1),
734
+ method = proto[prop];
735
+
736
+ if (method.$$stub && exclude.indexOf(method_name) === -1) {
737
+ exclude.push(method_name);
738
+ }
739
+
740
+ if (!method.$$stub && results.indexOf(method_name) === -1 && exclude.indexOf(method_name) === -1) {
741
+ results.push(method_name);
742
+ }
743
+ }
744
+ }
745
+ }
746
+
747
+ return results;
748
+ }
749
+
750
+ Opal.own_instance_methods = function(mod) {
751
+ var results = [],
752
+ proto = mod.$$prototype;
753
+
754
+ if (proto.hasOwnProperty('$$dummy')) {
755
+ proto = proto.$$define_methods_on;
756
+ }
757
+
758
+ var props = Object.getOwnPropertyNames(proto);
759
+
760
+ for (var i = 0, length = props.length; i < length; i++) {
761
+ var prop = props[i];
762
+
763
+ if (Opal.is_method(prop)) {
764
+ var method = proto[prop];
765
+
766
+ if (!method.$$stub) {
767
+ var method_name = prop.slice(1);
768
+ results.push(method_name);
769
+ }
770
+ }
771
+ }
772
+
773
+ return results;
774
+ }
775
+
776
+ Opal.methods = function(obj) {
777
+ return Opal.instance_methods(Opal.get_singleton_class(obj));
778
+ }
779
+
780
+ Opal.own_methods = function(obj) {
781
+ return Opal.own_instance_methods(Opal.get_singleton_class(obj));
782
+ }
783
+
784
+ Opal.receiver_methods = function(obj) {
785
+ var mod = Opal.get_singleton_class(obj);
786
+ var singleton_methods = Opal.own_instance_methods(mod);
787
+ var instance_methods = Opal.own_instance_methods(mod.$$super);
788
+ return singleton_methods.concat(instance_methods);
789
+ }
790
+
753
791
  // Returns an object containing all pairs of names/values
754
792
  // for all class variables defined in provided +module+
755
793
  // and its ancestors.
@@ -796,109 +834,50 @@
796
834
  return value;
797
835
  }
798
836
 
799
- // Bridges a single method.
800
- //
801
- // @param target [JS::Function] the constructor of the bridged class
802
- // @param from [Module] the module/class we are importing the method from
803
- // @param name [String] the method name in JS land (i.e. starting with $)
804
- // @param body [JS::Function] the body of the method
805
- Opal.bridge_method = function(target_constructor, from, name, body) {
806
- var ancestors, i, ancestor, length;
807
-
808
- ancestors = target_constructor.$$bridge.$ancestors();
837
+ function isRoot(proto) {
838
+ return proto.hasOwnProperty('$$iclass') && proto.hasOwnProperty('$$root');
839
+ }
809
840
 
810
- // order important here, we have to check for method presence in
811
- // ancestors from the bridged class to the last ancestor
812
- for (i = 0, length = ancestors.length; i < length; i++) {
813
- ancestor = ancestors[i];
841
+ function own_included_modules(module) {
842
+ var result = [], mod, proto = Object.getPrototypeOf(module.$$prototype);
814
843
 
815
- if ($hasOwn.call(ancestor.$$proto, name) &&
816
- ancestor.$$proto[name] &&
817
- !ancestor.$$proto[name].$$donated &&
818
- !ancestor.$$proto[name].$$stub &&
819
- ancestor !== from) {
844
+ while (proto) {
845
+ if (proto.hasOwnProperty('$$class')) {
846
+ // superclass
820
847
  break;
821
848
  }
822
-
823
- if (ancestor === from) {
824
- target_constructor.prototype[name] = body
825
- break;
849
+ mod = protoToModule(proto);
850
+ if (mod) {
851
+ result.push(mod);
826
852
  }
853
+ proto = Object.getPrototypeOf(proto);
827
854
  }
828
- };
829
855
 
830
- // Bridges from *donator* to a *target*.
831
- //
832
- // @param target [Module] the potentially associated with bridged classes module
833
- // @param donator [Module] the module/class source of the methods that should be bridged
834
- Opal.bridge_methods = function(target, donator) {
835
- var i,
836
- bridged = BridgedClasses[target.$__id__()],
837
- donator_id = donator.$__id__();
838
-
839
- if (bridged) {
840
- BridgedClasses[donator_id] = bridged.slice();
841
-
842
- for (i = bridged.length - 1; i >= 0; i--) {
843
- Opal_bridge_methods_to_constructor(bridged[i], donator)
844
- }
845
- }
846
- };
847
-
848
- // Actually bridge methods to the bridged (shared) prototype.
849
- function Opal_bridge_methods_to_constructor(target_constructor, donator) {
850
- var i,
851
- method,
852
- methods = donator.$instance_methods();
853
-
854
- for (i = methods.length - 1; i >= 0; i--) {
855
- method = '$' + methods[i];
856
- Opal.bridge_method(target_constructor, donator, method, donator.$$proto[method]);
857
- }
858
- }
859
-
860
- // Associate the target as a bridged class for the current "donator"
861
- function Opal_add_bridged_constructor(target_constructor, donator) {
862
- var donator_id = donator.$__id__();
863
-
864
- if (!BridgedClasses[donator_id]) {
865
- BridgedClasses[donator_id] = [];
866
- }
867
- BridgedClasses[donator_id].push(target_constructor);
856
+ return result;
868
857
  }
869
858
 
870
- // Walks the dependency tree detecting the presence of the base among its
871
- // own dependencies.
872
- //
873
- // @param [Integer] base_id The id of the base module (eg. the "includer")
874
- // @param [Array<Module>] deps The array of dependencies (eg. the included module, included.$$deps)
875
- // @param [String] prop The property that holds dependencies (eg. "$$deps")
876
- // @param [JS::Object] seen A JS object holding the cache of already visited objects
877
- // @return [Boolean] true if a cyclic dependency is present
878
- Opal.has_cyclic_dep = function has_cyclic_dep(base_id, deps, prop, seen) {
879
- var i, dep_id, dep;
880
-
881
- for (i = deps.length - 1; i >= 0; i--) {
882
- dep = deps[i];
883
- dep_id = dep.$$id;
859
+ function own_prepended_modules(module) {
860
+ var result = [], mod, proto = Object.getPrototypeOf(module.$$prototype);
884
861
 
885
- if (seen[dep_id]) {
886
- continue;
887
- }
888
- seen[dep_id] = true;
862
+ if (module.$$prototype.hasOwnProperty('$$dummy')) {
863
+ while (proto) {
864
+ if (proto === module.$$prototype.$$define_methods_on) {
865
+ break;
866
+ }
889
867
 
890
- if (dep_id === base_id) {
891
- return true;
892
- }
868
+ mod = protoToModule(proto);
869
+ if (mod) {
870
+ result.push(mod);
871
+ }
893
872
 
894
- if (has_cyclic_dep(base_id, dep[prop], prop, seen)) {
895
- return true;
873
+ proto = Object.getPrototypeOf(proto);
896
874
  }
897
875
  }
898
876
 
899
- return false;
877
+ return result;
900
878
  }
901
879
 
880
+
902
881
  // The actual inclusion of a module into a class.
903
882
  //
904
883
  // ## Class `$$parent` and `iclass`
@@ -918,47 +897,240 @@
918
897
  // @param includer [Module] the target class to include module into
919
898
  // @return [null]
920
899
  Opal.append_features = function(module, includer) {
921
- var iclass, donator, prototype, methods, id, i;
900
+ var module_ancestors = Opal.ancestors(module);
901
+ var iclasses = [];
922
902
 
923
- // check if this module is already included in the class
924
- for (i = includer.$$inc.length - 1; i >= 0; i--) {
925
- if (includer.$$inc[i] === module) {
926
- return;
903
+ if (module_ancestors.indexOf(includer) !== -1) {
904
+ throw Opal.ArgumentError.$new('cyclic include detected');
905
+ }
906
+
907
+ for (var i = 0, length = module_ancestors.length; i < length; i++) {
908
+ var ancestor = module_ancestors[i], iclass = create_iclass(ancestor);
909
+ $defineProperty(iclass, '$$included', true);
910
+ iclasses.push(iclass);
911
+ }
912
+ var includer_ancestors = Opal.ancestors(includer),
913
+ chain = chain_iclasses(iclasses),
914
+ start_chain_after,
915
+ end_chain_on;
916
+
917
+ if (includer_ancestors.indexOf(module) === -1) {
918
+ // first time include
919
+
920
+ // includer -> chain.first -> ...chain... -> chain.last -> includer.parent
921
+ start_chain_after = includer.$$prototype;
922
+ end_chain_on = Object.getPrototypeOf(includer.$$prototype);
923
+ } else {
924
+ // The module has been already included,
925
+ // we don't need to put it into the ancestors chain again,
926
+ // but this module may have new included modules.
927
+ // If it's true we need to copy them.
928
+ //
929
+ // The simplest way is to replace ancestors chain from
930
+ // parent
931
+ // |
932
+ // `module` iclass (has a $$root flag)
933
+ // |
934
+ // ...previos chain of module.included_modules ...
935
+ // |
936
+ // "next ancestor" (has a $$root flag or is a real class)
937
+ //
938
+ // to
939
+ // parent
940
+ // |
941
+ // `module` iclass (has a $$root flag)
942
+ // |
943
+ // ...regenerated chain of module.included_modules
944
+ // |
945
+ // "next ancestor" (has a $$root flag or is a real class)
946
+ //
947
+ // because there are no intermediate classes between `parent` and `next ancestor`.
948
+ // It doesn't break any prototypes of other objects as we don't change class references.
949
+
950
+ var proto = includer.$$prototype, parent = proto, module_iclass = Object.getPrototypeOf(parent);
951
+
952
+ while (module_iclass != null) {
953
+ if (isRoot(module_iclass) && module_iclass.$$module === module) {
954
+ break;
955
+ }
956
+
957
+ parent = module_iclass;
958
+ module_iclass = Object.getPrototypeOf(module_iclass);
927
959
  }
960
+
961
+ var next_ancestor = Object.getPrototypeOf(module_iclass);
962
+
963
+ // skip non-root iclasses (that were recursively included)
964
+ while (next_ancestor.hasOwnProperty('$$iclass') && !isRoot(next_ancestor)) {
965
+ next_ancestor = Object.getPrototypeOf(next_ancestor);
966
+ }
967
+
968
+ start_chain_after = parent;
969
+ end_chain_on = next_ancestor;
928
970
  }
929
971
 
930
- // Check that the base module is not also a dependency, classes can't be
931
- // dependencies so we have a special case for them.
932
- if (!includer.$$is_class && Opal.has_cyclic_dep(includer.$$id, [module], '$$inc', {})) {
933
- throw Opal.ArgumentError.$new('cyclic include detected')
972
+ $setPrototype(start_chain_after, chain.first);
973
+ $setPrototype(chain.last, end_chain_on);
974
+
975
+ // recalculate own_included_modules cache
976
+ includer.$$own_included_modules = own_included_modules(includer);
977
+
978
+ Opal.const_cache_version++;
979
+ }
980
+
981
+ Opal.prepend_features = function(module, prepender) {
982
+ // Here we change the ancestors chain from
983
+ //
984
+ // prepender
985
+ // |
986
+ // parent
987
+ //
988
+ // to:
989
+ //
990
+ // dummy(prepender)
991
+ // |
992
+ // iclass(module)
993
+ // |
994
+ // iclass(prepender)
995
+ // |
996
+ // parent
997
+ var module_ancestors = Opal.ancestors(module);
998
+ var iclasses = [];
999
+
1000
+ if (module_ancestors.indexOf(prepender) !== -1) {
1001
+ throw Opal.ArgumentError.$new('cyclic prepend detected');
1002
+ }
1003
+
1004
+ for (var i = 0, length = module_ancestors.length; i < length; i++) {
1005
+ var ancestor = module_ancestors[i], iclass = create_iclass(ancestor);
1006
+ $defineProperty(iclass, '$$prepended', true);
1007
+ iclasses.push(iclass);
1008
+ }
1009
+
1010
+ var chain = chain_iclasses(iclasses),
1011
+ dummy_prepender = prepender.$$prototype,
1012
+ previous_parent = Object.getPrototypeOf(dummy_prepender),
1013
+ prepender_iclass,
1014
+ start_chain_after,
1015
+ end_chain_on;
1016
+
1017
+ if (dummy_prepender.hasOwnProperty('$$dummy')) {
1018
+ // The module already has some prepended modules
1019
+ // which means that we don't need to make it "dummy"
1020
+ prepender_iclass = dummy_prepender.$$define_methods_on;
1021
+ } else {
1022
+ // Making the module "dummy"
1023
+ prepender_iclass = create_dummy_iclass(prepender);
1024
+ flush_methods_in(prepender);
1025
+ $defineProperty(dummy_prepender, '$$dummy', true);
1026
+ $defineProperty(dummy_prepender, '$$define_methods_on', prepender_iclass);
1027
+
1028
+ // Converting
1029
+ // dummy(prepender) -> previous_parent
1030
+ // to
1031
+ // dummy(prepender) -> iclass(prepender) -> previous_parent
1032
+ $setPrototype(dummy_prepender, prepender_iclass);
1033
+ $setPrototype(prepender_iclass, previous_parent);
1034
+ }
1035
+
1036
+ var prepender_ancestors = Opal.ancestors(prepender);
1037
+
1038
+ if (prepender_ancestors.indexOf(module) === -1) {
1039
+ // first time prepend
1040
+
1041
+ start_chain_after = dummy_prepender;
1042
+
1043
+ // next $$root or prepender_iclass or non-$$iclass
1044
+ end_chain_on = Object.getPrototypeOf(dummy_prepender);
1045
+ while (end_chain_on != null) {
1046
+ if (
1047
+ end_chain_on.hasOwnProperty('$$root') ||
1048
+ end_chain_on === prepender_iclass ||
1049
+ !end_chain_on.hasOwnProperty('$$iclass')
1050
+ ) {
1051
+ break;
1052
+ }
1053
+
1054
+ end_chain_on = Object.getPrototypeOf(end_chain_on);
1055
+ }
1056
+ } else {
1057
+ throw Opal.RuntimeError.$new("Prepending a module multiple times is not supported");
934
1058
  }
935
1059
 
1060
+ $setPrototype(start_chain_after, chain.first);
1061
+ $setPrototype(chain.last, end_chain_on);
1062
+
1063
+ // recalculate own_prepended_modules cache
1064
+ prepender.$$own_prepended_modules = own_prepended_modules(prepender);
1065
+
936
1066
  Opal.const_cache_version++;
937
- includer.$$inc.push(module);
938
- module.$$included_in.push(includer);
939
- Opal.bridge_methods(includer, module);
940
-
941
- // iclass
942
- iclass = {
943
- $$name: module.$$name,
944
- $$proto: module.$$proto,
945
- $$parent: includer.$$parent,
946
- $$module: module,
947
- $$iclass: true
948
- };
1067
+ }
949
1068
 
950
- includer.$$parent = iclass;
1069
+ function flush_methods_in(module) {
1070
+ var proto = module.$$prototype,
1071
+ props = Object.getOwnPropertyNames(proto);
1072
+
1073
+ for (var i = 0; i < props.length; i++) {
1074
+ var prop = props[i];
1075
+ if (Opal.is_method(prop)) {
1076
+ delete proto[prop];
1077
+ }
1078
+ }
1079
+ }
951
1080
 
952
- methods = module.$instance_methods();
1081
+ function create_iclass(module) {
1082
+ var iclass = create_dummy_iclass(module);
953
1083
 
954
- for (i = methods.length - 1; i >= 0; i--) {
955
- Opal.update_includer(module, includer, '$' + methods[i])
1084
+ if (module.$$is_module) {
1085
+ module.$$iclasses.push(iclass);
956
1086
  }
957
- };
958
1087
 
959
- // Table that holds all methods that have been defined on all objects
960
- // It is used for defining method stubs for new coming native classes
961
- Opal.stubs = {};
1088
+ return iclass;
1089
+ }
1090
+
1091
+ // Dummy iclass doesn't receive updates when the module gets a new method.
1092
+ function create_dummy_iclass(module) {
1093
+ var iclass = {},
1094
+ proto = module.$$prototype;
1095
+
1096
+ if (proto.hasOwnProperty('$$dummy')) {
1097
+ proto = proto.$$define_methods_on;
1098
+ }
1099
+
1100
+ var props = Object.getOwnPropertyNames(proto),
1101
+ length = props.length, i;
1102
+
1103
+ for (i = 0; i < length; i++) {
1104
+ var prop = props[i];
1105
+ $defineProperty(iclass, prop, proto[prop]);
1106
+ }
1107
+
1108
+ $defineProperty(iclass, '$$iclass', true);
1109
+ $defineProperty(iclass, '$$module', module);
1110
+
1111
+ return iclass;
1112
+ }
1113
+
1114
+ function chain_iclasses(iclasses) {
1115
+ var length = iclasses.length, first = iclasses[0];
1116
+
1117
+ $defineProperty(first, '$$root', true);
1118
+
1119
+ if (length === 1) {
1120
+ return { first: first, last: first };
1121
+ }
1122
+
1123
+ var previous = first;
1124
+
1125
+ for (var i = 1; i < length; i++) {
1126
+ var current = iclasses[i];
1127
+ $setPrototype(previous, current);
1128
+ previous = current;
1129
+ }
1130
+
1131
+
1132
+ return { first: iclasses[0], last: iclasses[length - 1] };
1133
+ }
962
1134
 
963
1135
  // For performance, some core Ruby classes are toll-free bridged to their
964
1136
  // native JavaScript counterparts (e.g. a Ruby Array is a JavaScript Array).
@@ -966,7 +1138,7 @@
966
1138
  // This method is used to setup a native constructor (e.g. Array), to have
967
1139
  // its prototype act like a normal Ruby class. Firstly, a new Ruby class is
968
1140
  // created using the native constructor so that its prototype is set as the
969
- // target for th new class. Note: all bridged classes are set to inherit
1141
+ // target for the new class. Note: all bridged classes are set to inherit
970
1142
  // from Object.
971
1143
  //
972
1144
  // Example:
@@ -977,132 +1149,93 @@
977
1149
  // @param constructor [JS.Function] native JavaScript constructor to use
978
1150
  // @return [Class] returns the passed Ruby class
979
1151
  //
980
- Opal.bridge = function(klass, constructor) {
981
- if (constructor.$$bridge) {
1152
+ Opal.bridge = function(native_klass, klass) {
1153
+ if (native_klass.hasOwnProperty('$$bridge')) {
982
1154
  throw Opal.ArgumentError.$new("already bridged");
983
1155
  }
984
1156
 
985
- Opal.stub_subscribers.push(constructor.prototype);
986
-
987
- // Populate constructor with previously stored stubs
988
- for (var method_name in Opal.stubs) {
989
- if (!(method_name in constructor.prototype)) {
990
- constructor.prototype[method_name] = Opal.stub_for(method_name);
991
- }
992
- }
993
-
994
- constructor.prototype.$$class = klass;
995
- constructor.$$bridge = klass;
1157
+ var klass_to_inject, klass_reference;
996
1158
 
997
- var ancestors = klass.$ancestors();
1159
+ klass_to_inject = klass.$$super || Opal.Object;
1160
+ klass_reference = klass;
1161
+ var original_prototype = klass.$$prototype;
998
1162
 
999
- // order important here, we have to bridge from the last ancestor to the
1000
- // bridged class
1001
- for (var i = ancestors.length - 1; i >= 0; i--) {
1002
- Opal_add_bridged_constructor(constructor, ancestors[i]);
1003
- Opal_bridge_methods_to_constructor(constructor, ancestors[i]);
1004
- }
1163
+ // constructor is a JS function with a prototype chain like:
1164
+ // - constructor
1165
+ // - super
1166
+ //
1167
+ // What we need to do is to inject our class (with its prototype chain)
1168
+ // between constructor and super. For example, after injecting ::Object
1169
+ // into JS String we get:
1170
+ //
1171
+ // - constructor (window.String)
1172
+ // - Opal.Object
1173
+ // - Opal.Kernel
1174
+ // - Opal.BasicObject
1175
+ // - super (window.Object)
1176
+ // - null
1177
+ //
1178
+ $defineProperty(native_klass, '$$bridge', klass);
1179
+ $setPrototype(native_klass.prototype, (klass.$$super || Opal.Object).$$prototype);
1180
+ $defineProperty(klass, '$$prototype', native_klass.prototype);
1005
1181
 
1006
- for (var name in BasicObject_alloc.prototype) {
1007
- var method = BasicObject_alloc.prototype[method];
1182
+ $defineProperty(klass.$$prototype, '$$class', klass);
1183
+ $defineProperty(klass, '$$constructor', native_klass);
1184
+ $defineProperty(klass, '$$bridge', true);
1185
+ };
1008
1186
 
1009
- if (method && method.$$stub && !(name in constructor.prototype)) {
1010
- constructor.prototype[name] = method;
1011
- }
1187
+ function protoToModule(proto) {
1188
+ if (proto.hasOwnProperty('$$dummy')) {
1189
+ return;
1190
+ } else if (proto.hasOwnProperty('$$iclass')) {
1191
+ return proto.$$module;
1192
+ } else if (proto.hasOwnProperty('$$class')) {
1193
+ return proto.$$class;
1012
1194
  }
1195
+ }
1013
1196
 
1014
- return klass;
1015
- };
1016
-
1017
- // Update `jsid` method cache of all classes / modules including `module`.
1018
- Opal.update_includer = function(module, includer, jsid) {
1019
- var dest, current, body,
1020
- klass_includees, j, jj, current_owner_index, module_index;
1197
+ function own_ancestors(module) {
1198
+ return module.$$own_prepended_modules.concat([module]).concat(module.$$own_included_modules);
1199
+ }
1021
1200
 
1022
- body = module.$$proto[jsid];
1023
- dest = includer.$$proto;
1024
- current = dest[jsid];
1201
+ // The Array of ancestors for a given module/class
1202
+ Opal.ancestors = function(module) {
1203
+ if (!module) { return []; }
1025
1204
 
1026
- if (dest.hasOwnProperty(jsid) && !current.$$donated && !current.$$stub) {
1027
- // target class has already defined the same method name - do nothing
1205
+ if (module.$$ancestors_cache_version === Opal.const_cache_version) {
1206
+ return module.$$ancestors;
1028
1207
  }
1029
- else if (dest.hasOwnProperty(jsid) && !current.$$stub) {
1030
- // target class includes another module that has defined this method
1031
- klass_includees = includer.$$inc;
1032
1208
 
1033
- for (j = 0, jj = klass_includees.length; j < jj; j++) {
1034
- if (klass_includees[j] === current.$$donated) {
1035
- current_owner_index = j;
1036
- }
1037
- if (klass_includees[j] === module) {
1038
- module_index = j;
1039
- }
1040
- }
1209
+ var result = [], i, mods, length;
1041
1210
 
1042
- // only redefine method on class if the module was included AFTER
1043
- // the module which defined the current method body. Also make sure
1044
- // a module can overwrite a method it defined before
1045
- if (current_owner_index <= module_index) {
1046
- dest[jsid] = body;
1047
- dest[jsid].$$donated = module;
1048
- }
1049
- }
1050
- else {
1051
- // neither a class, or module included by class, has defined method
1052
- dest[jsid] = body;
1053
- dest[jsid].$$donated = module;
1211
+ for (i = 0, mods = own_ancestors(module), length = mods.length; i < length; i++) {
1212
+ result.push(mods[i]);
1054
1213
  }
1055
1214
 
1056
- // if the includer is a module, recursively update all of its includres.
1057
- if (includer.$$included_in) {
1058
- Opal.update_includers(includer, jsid);
1215
+ if (module.$$super) {
1216
+ for (i = 0, mods = Opal.ancestors(module.$$super), length = mods.length; i < length; i++) {
1217
+ result.push(mods[i]);
1218
+ }
1059
1219
  }
1060
- };
1061
-
1062
- // Update `jsid` method cache of all classes / modules including `module`.
1063
- Opal.update_includers = function(module, jsid) {
1064
- var i, ii, includee, included_in;
1065
1220
 
1066
- included_in = module.$$included_in;
1067
-
1068
- if (!included_in) {
1069
- return;
1070
- }
1221
+ module.$$ancestors_cache_version = Opal.const_cache_version;
1222
+ module.$$ancestors = result;
1071
1223
 
1072
- for (i = 0, ii = included_in.length; i < ii; i++) {
1073
- includee = included_in[i];
1074
- Opal.update_includer(module, includee, jsid);
1075
- }
1076
- };
1224
+ return result;
1225
+ }
1077
1226
 
1078
- // The Array of ancestors for a given module/class
1079
- Opal.ancestors = function(module_or_class) {
1080
- var parent = module_or_class,
1081
- result = [],
1082
- modules, i, ii, j, jj;
1083
-
1084
- while (parent) {
1085
- result.push(parent);
1086
- for (i = parent.$$inc.length-1; i >= 0; i--) {
1087
- modules = Opal.ancestors(parent.$$inc[i]);
1088
-
1089
- for(j = 0, jj = modules.length; j < jj; j++) {
1090
- result.push(modules[j]);
1091
- }
1092
- }
1227
+ Opal.included_modules = function(module) {
1228
+ var result = [], mod = null, proto = Object.getPrototypeOf(module.$$prototype);
1093
1229
 
1094
- // only the actual singleton class gets included in its ancestry
1095
- // after that, traverse the normal class hierarchy
1096
- if (parent.$$is_singleton && parent.$$singleton_of.$$is_module) {
1097
- parent = parent.$$singleton_of.$$super;
1098
- }
1099
- else {
1100
- parent = parent.$$is_class ? parent.$$super : null;
1230
+ for (; proto && Object.getPrototypeOf(proto); proto = Object.getPrototypeOf(proto)) {
1231
+ mod = protoToModule(proto);
1232
+ if (mod && mod.$$is_module && proto.$$iclass && proto.$$included) {
1233
+ result.push(mod);
1101
1234
  }
1102
1235
  }
1103
1236
 
1104
1237
  return result;
1105
- };
1238
+ }
1106
1239
 
1107
1240
 
1108
1241
  // Method Missing
@@ -1136,37 +1269,17 @@
1136
1269
  // @param stubs [Array] an array of method stubs to add
1137
1270
  // @return [undefined]
1138
1271
  Opal.add_stubs = function(stubs) {
1139
- var subscriber, subscribers = Opal.stub_subscribers,
1140
- i, ilength = stubs.length,
1141
- j, jlength = subscribers.length,
1142
- method_name, stub,
1143
- opal_stubs = Opal.stubs;
1144
-
1145
- for (i = 0; i < ilength; i++) {
1146
- method_name = stubs[i];
1147
-
1148
- if(!opal_stubs.hasOwnProperty(method_name)) {
1149
- // Save method name to populate other subscribers with this stub
1150
- opal_stubs[method_name] = true;
1151
- stub = Opal.stub_for(method_name);
1272
+ var proto = Opal.BasicObject.$$prototype;
1152
1273
 
1153
- for (j = 0; j < jlength; j++) {
1154
- subscriber = subscribers[j];
1274
+ for (var i = 0, length = stubs.length; i < length; i++) {
1275
+ var stub = stubs[i], existing_method = proto[stub];
1155
1276
 
1156
- if (!(method_name in subscriber)) {
1157
- subscriber[method_name] = stub;
1158
- }
1159
- }
1277
+ if (existing_method == null || existing_method.$$stub) {
1278
+ Opal.add_stub_for(proto, stub);
1160
1279
  }
1161
1280
  }
1162
1281
  };
1163
1282
 
1164
- // Keep a list of prototypes that want method_missing stubs to be added.
1165
- //
1166
- // @default [Prototype List] BasicObject_alloc.prototype
1167
- //
1168
- Opal.stub_subscribers = [BasicObject_alloc.prototype];
1169
-
1170
1283
  // Add a method_missing stub function to the given prototype for the
1171
1284
  // given name.
1172
1285
  //
@@ -1175,7 +1288,7 @@
1175
1288
  // @return [undefined]
1176
1289
  Opal.add_stub_for = function(prototype, stub) {
1177
1290
  var method_missing_stub = Opal.stub_for(stub);
1178
- prototype[stub] = method_missing_stub;
1291
+ $defineProperty(prototype, stub, method_missing_stub);
1179
1292
  };
1180
1293
 
1181
1294
  // Generate the method_missing stub for a given method name.
@@ -1215,7 +1328,7 @@
1215
1328
  // @raise [ArgumentError]
1216
1329
  Opal.ac = function(actual, expected, object, meth) {
1217
1330
  var inspect = '';
1218
- if (object.$$is_class || object.$$is_module) {
1331
+ if (object.$$is_a_module) {
1219
1332
  inspect += object.$$name + '.';
1220
1333
  }
1221
1334
  else {
@@ -1240,23 +1353,35 @@
1240
1353
 
1241
1354
  // Super dispatcher
1242
1355
  Opal.find_super_dispatcher = function(obj, mid, current_func, defcheck, defs) {
1243
- var dispatcher, super_method;
1356
+ var jsid = '$' + mid, ancestors, super_method;
1357
+
1358
+ if (obj.hasOwnProperty('$$meta')) {
1359
+ ancestors = Opal.ancestors(obj.$$meta);
1360
+ } else {
1361
+ ancestors = Opal.ancestors(obj.$$class);
1362
+ }
1363
+
1364
+ var current_index = ancestors.indexOf(current_func.$$owner);
1365
+
1366
+ for (var i = current_index + 1; i < ancestors.length; i++) {
1367
+ var ancestor = ancestors[i],
1368
+ proto = ancestor.$$prototype;
1244
1369
 
1245
- if (defs) {
1246
- if (obj.$$is_class || obj.$$is_module) {
1247
- dispatcher = defs.$$super;
1370
+ if (proto.hasOwnProperty('$$dummy')) {
1371
+ proto = proto.$$define_methods_on;
1248
1372
  }
1249
- else {
1250
- dispatcher = obj.$$class.$$proto;
1373
+
1374
+ if (proto.hasOwnProperty(jsid)) {
1375
+ var method = proto[jsid];
1376
+
1377
+ if (!method.$$stub) {
1378
+ super_method = method;
1379
+ }
1380
+ break;
1251
1381
  }
1252
1382
  }
1253
- else {
1254
- dispatcher = Opal.find_obj_super_dispatcher(obj, mid, current_func);
1255
- }
1256
-
1257
- super_method = dispatcher['$' + mid];
1258
1383
 
1259
- if (!defcheck && super_method.$$stub && Opal.Kernel.$method_missing === obj.$method_missing) {
1384
+ if (!defcheck && super_method == null && Opal.Kernel.$method_missing === obj.$method_missing) {
1260
1385
  // method_missing hasn't been explicitly defined
1261
1386
  throw Opal.NoMethodError.$new('super: no superclass method `'+mid+"' for "+obj, mid);
1262
1387
  }
@@ -1283,67 +1408,6 @@
1283
1408
  return Opal.find_super_dispatcher(obj, call_jsid, current_func, defcheck);
1284
1409
  };
1285
1410
 
1286
- Opal.find_obj_super_dispatcher = function(obj, mid, current_func) {
1287
- var klass = obj.$$meta || obj.$$class;
1288
-
1289
- // first we need to find the class/module current_func is located on
1290
- klass = Opal.find_owning_class(klass, current_func);
1291
-
1292
- if (!klass) {
1293
- throw new Error("could not find current class for super()");
1294
- }
1295
-
1296
- return Opal.find_super_func(klass, '$' + mid, current_func);
1297
- };
1298
-
1299
- Opal.find_owning_class = function(klass, current_func) {
1300
- var owner = current_func.$$owner;
1301
-
1302
- while (klass) {
1303
- // repeating for readability
1304
-
1305
- if (klass.$$iclass && klass.$$module === current_func.$$donated) {
1306
- // this klass was the last one the module donated to
1307
- // case is also hit with multiple module includes
1308
- break;
1309
- }
1310
- else if (klass.$$iclass && klass.$$module === owner) {
1311
- // module has donated to other classes but klass isn't one of those
1312
- break;
1313
- }
1314
- else if (owner.$$is_singleton && klass === owner.$$singleton_of.$$class) {
1315
- // cases like stdlib `Singleton::included` that use a singleton of a singleton
1316
- break;
1317
- }
1318
- else if (klass === owner) {
1319
- // no modules, pure class inheritance
1320
- break;
1321
- }
1322
-
1323
- klass = klass.$$parent;
1324
- }
1325
-
1326
- return klass;
1327
- };
1328
-
1329
- Opal.find_super_func = function(owning_klass, jsid, current_func) {
1330
- var klass = owning_klass.$$parent;
1331
-
1332
- // now we can find the super
1333
- while (klass) {
1334
- var working = klass.$$proto[jsid];
1335
-
1336
- if (working && working !== current_func) {
1337
- // ok
1338
- break;
1339
- }
1340
-
1341
- klass = klass.$$parent;
1342
- }
1343
-
1344
- return klass.$$proto;
1345
- };
1346
-
1347
1411
  // Used to return as an expression. Sometimes, we can't simply return from
1348
1412
  // a javascript function as if we were a method, as the return is used as
1349
1413
  // an expression, or even inside a block which must "return" to the outer
@@ -1436,7 +1500,7 @@
1436
1500
  };
1437
1501
 
1438
1502
  Opal.is_a = function(object, klass) {
1439
- if (object.$$meta === klass || object.$$class === klass) {
1503
+ if (klass != null && object.$$meta === klass || object.$$class === klass) {
1440
1504
  return true;
1441
1505
  }
1442
1506
 
@@ -1538,7 +1602,7 @@
1538
1602
  Opal.extract_kwargs = function(parameters) {
1539
1603
  var kwargs = parameters[parameters.length - 1];
1540
1604
  if (kwargs != null && kwargs['$respond_to?']('to_hash', true)) {
1541
- Array.prototype.splice.call(parameters, parameters.length - 1, 1);
1605
+ $splice.call(parameters, parameters.length - 1, 1);
1542
1606
  return kwargs.$to_hash();
1543
1607
  }
1544
1608
  else {
@@ -1601,13 +1665,20 @@
1601
1665
  var body = (typeof(method) === 'string') ? recv['$'+method] : method;
1602
1666
 
1603
1667
  if (body != null) {
1604
- body.$$p = block;
1668
+ if (typeof block === 'function') {
1669
+ body.$$p = block;
1670
+ }
1605
1671
  return body.apply(recv, args);
1606
1672
  }
1607
1673
 
1608
1674
  return recv.$method_missing.apply(recv, [method].concat(args));
1609
1675
  }
1610
1676
 
1677
+ Opal.lambda = function(block) {
1678
+ block.$$is_lambda = true;
1679
+ return block;
1680
+ }
1681
+
1611
1682
  // Used to define methods on an object. This is a helper method, used by the
1612
1683
  // compiled source to define methods on special case objects when the compiler
1613
1684
  // can not determine the destination object, or the object is a Module
@@ -1645,8 +1716,13 @@
1645
1716
  // @return [null]
1646
1717
  //
1647
1718
  Opal.def = function(obj, jsid, body) {
1719
+ // Special case for a method definition in the
1720
+ // top-level namespace
1721
+ if (obj === Opal.top) {
1722
+ Opal.defn(Opal.Object, jsid, body)
1723
+ }
1648
1724
  // if instance_eval is invoked on a module/class, it sets inst_eval_mod
1649
- if (!obj.$$eval && (obj.$$is_class || obj.$$is_module)) {
1725
+ else if (!obj.$$eval && obj.$$is_a_module) {
1650
1726
  Opal.defn(obj, jsid, body);
1651
1727
  }
1652
1728
  else {
@@ -1655,59 +1731,55 @@
1655
1731
  };
1656
1732
 
1657
1733
  // Define method on a module or class (see Opal.def).
1658
- Opal.defn = function(obj, jsid, body) {
1659
- obj.$$proto[jsid] = body;
1660
- // for super dispatcher, etc.
1661
- body.$$owner = obj;
1662
- if (body.displayName == null) body.displayName = jsid.substr(1);
1734
+ Opal.defn = function(module, jsid, body) {
1735
+ body.displayName = jsid;
1736
+ body.$$owner = module;
1663
1737
 
1664
- // is it a module?
1665
- if (obj.$$is_module) {
1666
- Opal.update_includers(obj, jsid);
1738
+ var proto = module.$$prototype;
1739
+ if (proto.hasOwnProperty('$$dummy')) {
1740
+ proto = proto.$$define_methods_on;
1741
+ }
1742
+ $defineProperty(proto, jsid, body);
1667
1743
 
1668
- if (obj.$$module_function) {
1669
- Opal.defs(obj, jsid, body);
1744
+ if (module.$$is_module) {
1745
+ if (module.$$module_function) {
1746
+ Opal.defs(module, jsid, body)
1670
1747
  }
1671
- }
1672
1748
 
1673
- // is it a bridged class?
1674
- var bridged = obj.$__id__ && !obj.$__id__.$$stub && BridgedClasses[obj.$__id__()];
1675
- if (bridged) {
1676
- for (var i = bridged.length - 1; i >= 0; i--) {
1677
- Opal.bridge_method(bridged[i], obj, jsid, body);
1749
+ for (var i = 0, iclasses = module.$$iclasses, length = iclasses.length; i < length; i++) {
1750
+ var iclass = iclasses[i];
1751
+ $defineProperty(iclass, jsid, body);
1678
1752
  }
1679
1753
  }
1680
1754
 
1681
- // method_added/singleton_method_added hooks
1682
- var singleton_of = obj.$$singleton_of;
1683
- if (obj.$method_added && !obj.$method_added.$$stub && !singleton_of) {
1684
- obj.$method_added(jsid.substr(1));
1755
+ var singleton_of = module.$$singleton_of;
1756
+ if (module.$method_added && !module.$method_added.$$stub && !singleton_of) {
1757
+ module.$method_added(jsid.substr(1));
1685
1758
  }
1686
1759
  else if (singleton_of && singleton_of.$singleton_method_added && !singleton_of.$singleton_method_added.$$stub) {
1687
1760
  singleton_of.$singleton_method_added(jsid.substr(1));
1688
1761
  }
1689
-
1690
- return nil;
1691
- };
1762
+ }
1692
1763
 
1693
1764
  // Define a singleton method on the given object (see Opal.def).
1694
1765
  Opal.defs = function(obj, jsid, body) {
1766
+ if (obj.$$is_string || obj.$$is_number) {
1767
+ throw Opal.TypeError.$new("can't define singleton");
1768
+ }
1695
1769
  Opal.defn(Opal.get_singleton_class(obj), jsid, body)
1696
1770
  };
1697
1771
 
1698
1772
  // Called from #remove_method.
1699
1773
  Opal.rdef = function(obj, jsid) {
1700
- // TODO: remove from BridgedClasses as well
1701
-
1702
- if (!$hasOwn.call(obj.$$proto, jsid)) {
1774
+ if (!$hasOwn.call(obj.$$prototype, jsid)) {
1703
1775
  throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
1704
1776
  }
1705
1777
 
1706
- delete obj.$$proto[jsid];
1778
+ delete obj.$$prototype[jsid];
1707
1779
 
1708
1780
  if (obj.$$is_singleton) {
1709
- if (obj.$$proto.$singleton_method_removed && !obj.$$proto.$singleton_method_removed.$$stub) {
1710
- obj.$$proto.$singleton_method_removed(jsid.substr(1));
1781
+ if (obj.$$prototype.$singleton_method_removed && !obj.$$prototype.$singleton_method_removed.$$stub) {
1782
+ obj.$$prototype.$singleton_method_removed(jsid.substr(1));
1711
1783
  }
1712
1784
  }
1713
1785
  else {
@@ -1719,15 +1791,15 @@
1719
1791
 
1720
1792
  // Called from #undef_method.
1721
1793
  Opal.udef = function(obj, jsid) {
1722
- if (!obj.$$proto[jsid] || obj.$$proto[jsid].$$stub) {
1794
+ if (!obj.$$prototype[jsid] || obj.$$prototype[jsid].$$stub) {
1723
1795
  throw Opal.NameError.$new("method '" + jsid.substr(1) + "' not defined in " + obj.$name());
1724
1796
  }
1725
1797
 
1726
- Opal.add_stub_for(obj.$$proto, jsid);
1798
+ Opal.add_stub_for(obj.$$prototype, jsid);
1727
1799
 
1728
1800
  if (obj.$$is_singleton) {
1729
- if (obj.$$proto.$singleton_method_undefined && !obj.$$proto.$singleton_method_undefined.$$stub) {
1730
- obj.$$proto.$singleton_method_undefined(jsid.substr(1));
1801
+ if (obj.$$prototype.$singleton_method_undefined && !obj.$$prototype.$singleton_method_undefined.$$stub) {
1802
+ obj.$$prototype.$singleton_method_undefined(jsid.substr(1));
1731
1803
  }
1732
1804
  }
1733
1805
  else {
@@ -1737,10 +1809,14 @@
1737
1809
  }
1738
1810
  };
1739
1811
 
1812
+ function is_method_body(body) {
1813
+ return (typeof(body) === "function" && !body.$$stub);
1814
+ }
1815
+
1740
1816
  Opal.alias = function(obj, name, old) {
1741
1817
  var id = '$' + name,
1742
1818
  old_id = '$' + old,
1743
- body = obj.$$proto['$' + old],
1819
+ body = obj.$$prototype['$' + old],
1744
1820
  alias;
1745
1821
 
1746
1822
  // When running inside #instance_eval the alias refers to class methods.
@@ -1748,7 +1824,7 @@
1748
1824
  return Opal.alias(Opal.get_singleton_class(obj), name, old);
1749
1825
  }
1750
1826
 
1751
- if (typeof(body) !== "function" || body.$$stub) {
1827
+ if (!is_method_body(body)) {
1752
1828
  var ancestor = obj.$$super;
1753
1829
 
1754
1830
  while (typeof(body) !== "function" && ancestor) {
@@ -1756,7 +1832,12 @@
1756
1832
  ancestor = ancestor.$$super;
1757
1833
  }
1758
1834
 
1759
- if (typeof(body) !== "function" || body.$$stub) {
1835
+ if (!is_method_body(body) && obj.$$is_module) {
1836
+ // try to look into Object
1837
+ body = Opal.Object.$$prototype[old_id]
1838
+ }
1839
+
1840
+ if (!is_method_body(body)) {
1760
1841
  throw Opal.NameError.$new("undefined method `" + old + "' for class `" + obj.$name() + "'")
1761
1842
  }
1762
1843
  }
@@ -1765,7 +1846,7 @@
1765
1846
  // to keep the max depth at 1.
1766
1847
  if (body.$$alias_of) body = body.$$alias_of;
1767
1848
 
1768
- // We need a wrapper because otherwise method $$owner and other properties
1849
+ // We need a wrapper because otherwise properties
1769
1850
  // would be ovrewritten on the original body.
1770
1851
  alias = function() {
1771
1852
  var block = alias.$$p, args, i, ii;
@@ -1796,7 +1877,7 @@
1796
1877
 
1797
1878
  Opal.alias_native = function(obj, name, native_name) {
1798
1879
  var id = '$' + name,
1799
- body = obj.$$proto[native_name];
1880
+ body = obj.$$prototype[native_name];
1800
1881
 
1801
1882
  if (typeof(body) !== "function" || body.$$stub) {
1802
1883
  throw Opal.NameError.$new("undefined native method `" + native_name + "' for class `" + obj.$name() + "'")
@@ -2023,7 +2104,7 @@
2023
2104
  return arguments[0];
2024
2105
  }
2025
2106
 
2026
- hash = new Opal.Hash.$$alloc();
2107
+ hash = new Opal.Hash();
2027
2108
  Opal.hash_init(hash);
2028
2109
 
2029
2110
  if (arguments_length === 1 && arguments[0].$$is_array) {
@@ -2077,7 +2158,7 @@
2077
2158
  // function.
2078
2159
  //
2079
2160
  Opal.hash2 = function(keys, smap) {
2080
- var hash = new Opal.Hash.$$alloc();
2161
+ var hash = new Opal.Hash();
2081
2162
 
2082
2163
  hash.$$smap = smap;
2083
2164
  hash.$$map = Object.create(null);
@@ -2090,7 +2171,7 @@
2090
2171
  // range excludes the last value.
2091
2172
  //
2092
2173
  Opal.range = function(first, last, exc) {
2093
- var range = new Opal.Range.$$alloc();
2174
+ var range = new Opal.Range();
2094
2175
  range.begin = first;
2095
2176
  range.end = last;
2096
2177
  range.excl = exc;
@@ -2135,15 +2216,53 @@
2135
2216
  .replace(/[\r]/g, '\\r')
2136
2217
  .replace(/[\f]/g, '\\f')
2137
2218
  .replace(/[\t]/g, '\\t');
2138
- }
2219
+ };
2139
2220
 
2221
+ // Create a global Regexp from a RegExp object and cache the result
2222
+ // on the object itself ($$g attribute).
2223
+ //
2224
+ Opal.global_regexp = function(pattern) {
2225
+ if (pattern.global) {
2226
+ return pattern; // RegExp already has the global flag
2227
+ }
2228
+ if (pattern.$$g == null) {
2229
+ pattern.$$g = new RegExp(pattern.source, (pattern.multiline ? 'gm' : 'g') + (pattern.ignoreCase ? 'i' : ''));
2230
+ } else {
2231
+ pattern.$$g.lastIndex = null; // reset lastIndex property
2232
+ }
2233
+ return pattern.$$g;
2234
+ };
2235
+
2236
+ // Create a global multiline Regexp from a RegExp object and cache the result
2237
+ // on the object itself ($$gm or $$g attribute).
2238
+ //
2239
+ Opal.global_multiline_regexp = function(pattern) {
2240
+ var result;
2241
+ if (pattern.multiline) {
2242
+ if (pattern.global) {
2243
+ return pattern; // RegExp already has the global and multiline flag
2244
+ }
2245
+ // we are using the $$g attribute because the Regexp is already multiline
2246
+ if (pattern.$$g != null) {
2247
+ result = pattern.$$g;
2248
+ } else {
2249
+ result = pattern.$$g = new RegExp(pattern.source, 'gm' + (pattern.ignoreCase ? 'i' : ''));
2250
+ }
2251
+ } else if (pattern.$$gm != null) {
2252
+ result = pattern.$$gm;
2253
+ } else {
2254
+ result = pattern.$$gm = new RegExp(pattern.source, 'gm' + (pattern.ignoreCase ? 'i' : ''));
2255
+ }
2256
+ result.lastIndex = null; // reset lastIndex property
2257
+ return result;
2258
+ };
2140
2259
 
2141
2260
  // Require system
2142
2261
  // --------------
2143
2262
 
2144
2263
  Opal.modules = {};
2145
2264
  Opal.loaded_features = ['corelib/runtime'];
2146
- Opal.current_dir = '.'
2265
+ Opal.current_dir = '.';
2147
2266
  Opal.require_table = {'corelib/runtime': true};
2148
2267
 
2149
2268
  Opal.normalize = function(path) {
@@ -2173,7 +2292,7 @@
2173
2292
  path = Opal.normalize(paths[i]);
2174
2293
 
2175
2294
  if (Opal.require_table[path]) {
2176
- return;
2295
+ continue;
2177
2296
  }
2178
2297
 
2179
2298
  Opal.loaded_features.push(path);
@@ -2196,7 +2315,11 @@
2196
2315
  var message = 'cannot load such file -- ' + path;
2197
2316
 
2198
2317
  if (severity === "error") {
2199
- Opal.LoadError ? Opal.LoadError.$new(message) : function(){throw message}();
2318
+ if (Opal.LoadError) {
2319
+ throw Opal.LoadError.$new(message)
2320
+ } else {
2321
+ throw message
2322
+ }
2200
2323
  }
2201
2324
  else if (severity === "warning") {
2202
2325
  console.warn('WARNING: LoadError: ' + message);
@@ -2219,18 +2342,20 @@
2219
2342
 
2220
2343
  // Initialization
2221
2344
  // --------------
2345
+ function $BasicObject() {};
2346
+ function $Object() {};
2347
+ function $Module() {};
2348
+ function $Class() {};
2222
2349
 
2223
- // Constructors for *instances* of core objects
2224
- Opal.boot_class_alloc('BasicObject', BasicObject_alloc);
2225
- Opal.boot_class_alloc('Object', Object_alloc, BasicObject_alloc);
2226
- Opal.boot_class_alloc('Module', Module_alloc, Object_alloc);
2227
- Opal.boot_class_alloc('Class', Class_alloc, Module_alloc);
2350
+ Opal.BasicObject = BasicObject = Opal.allocate_class('BasicObject', null, $BasicObject);
2351
+ Opal.Object = _Object = Opal.allocate_class('Object', Opal.BasicObject, $Object);
2352
+ Opal.Module = Module = Opal.allocate_class('Module', Opal.Object, $Module);
2353
+ Opal.Class = Class = Opal.allocate_class('Class', Opal.Module, $Class);
2228
2354
 
2229
- // Constructors for *classes* of core objects
2230
- Opal.BasicObject = BasicObject = Opal.setup_class_object('BasicObject', BasicObject_alloc, 'Class', Class_alloc);
2231
- Opal.Object = _Object = Opal.setup_class_object('Object', Object_alloc, 'BasicObject', BasicObject.constructor);
2232
- Opal.Module = Module = Opal.setup_class_object('Module', Module_alloc, 'Object', _Object.constructor);
2233
- Opal.Class = Class = Opal.setup_class_object('Class', Class_alloc, 'Module', Module.constructor);
2355
+ $setPrototype(Opal.BasicObject, Opal.Class.$$prototype);
2356
+ $setPrototype(Opal.Object, Opal.Class.$$prototype);
2357
+ $setPrototype(Opal.Module, Opal.Class.$$prototype);
2358
+ $setPrototype(Opal.Class, Opal.Class.$$prototype);
2234
2359
 
2235
2360
  // BasicObject can reach itself, avoid const_set to skip the $$base_module logic
2236
2361
  BasicObject.$$const["BasicObject"] = BasicObject;
@@ -2241,26 +2366,14 @@
2241
2366
  Opal.const_set(_Object, "Module", Module);
2242
2367
  Opal.const_set(_Object, "Class", Class);
2243
2368
 
2244
-
2245
- // Fix booted classes to use their metaclass
2369
+ // Fix booted classes to have correct .class value
2246
2370
  BasicObject.$$class = Class;
2247
2371
  _Object.$$class = Class;
2248
2372
  Module.$$class = Class;
2249
2373
  Class.$$class = Class;
2250
2374
 
2251
- // Fix superclasses of booted classes
2252
- BasicObject.$$super = null;
2253
- _Object.$$super = BasicObject;
2254
- Module.$$super = _Object;
2255
- Class.$$super = Module;
2256
-
2257
- BasicObject.$$parent = null;
2258
- _Object.$$parent = BasicObject;
2259
- Module.$$parent = _Object;
2260
- Class.$$parent = Module;
2261
-
2262
2375
  // Forward .toString() to #to_s
2263
- _Object.$$proto.toString = function() {
2376
+ $defineProperty(_Object.$$prototype, 'toString', function() {
2264
2377
  var to_s = this.$to_s();
2265
2378
  if (to_s.$$is_string && typeof(to_s) === 'object') {
2266
2379
  // a string created using new String('string')
@@ -2268,22 +2381,32 @@
2268
2381
  } else {
2269
2382
  return to_s;
2270
2383
  }
2271
- };
2384
+ });
2272
2385
 
2273
2386
  // Make Kernel#require immediately available as it's needed to require all the
2274
2387
  // other corelib files.
2275
- _Object.$$proto.$require = Opal.require;
2388
+ $defineProperty(_Object.$$prototype, '$require', Opal.require);
2389
+
2390
+ // Add a short helper to navigate constants manually.
2391
+ // @example
2392
+ // Opal.$$.Regexp.$$.IGNORECASE
2393
+ Opal.$$ = _Object.$$;
2394
+
2395
+ // Instantiate the main object
2396
+ Opal.top = new _Object();
2397
+ Opal.top.$to_s = Opal.top.$inspect = function() { return 'main' };
2276
2398
 
2277
- // Instantiate the top object
2278
- Opal.top = new _Object.$$alloc();
2279
2399
 
2280
2400
  // Nil
2281
- Opal.klass(_Object, _Object, 'NilClass', NilClass_alloc);
2282
- nil = Opal.nil = new NilClass_alloc();
2401
+ function $NilClass() {};
2402
+ Opal.NilClass = Opal.allocate_class('NilClass', Opal.Object, $NilClass);
2403
+ Opal.const_set(_Object, 'NilClass', Opal.NilClass);
2404
+ nil = Opal.nil = new Opal.NilClass();
2283
2405
  nil.$$id = nil_id;
2284
2406
  nil.call = nil.apply = function() { throw Opal.LocalJumpError.$new('no block given'); };
2407
+
2408
+ // Errors
2285
2409
  Opal.breaker = new Error('unexpected break (old)');
2286
2410
  Opal.returner = new Error('unexpected return');
2287
-
2288
2411
  TypeError.$$super = Error;
2289
2412
  }).call(this);