opal 0.2.2 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. data/.gitignore +5 -10
  2. data/LICENSE +75 -0
  3. data/README.md +55 -3
  4. data/Rakefile +62 -139
  5. data/bin/opal +7 -10
  6. data/gems/core/README.md +5 -0
  7. data/gems/core/Rakefile +7 -0
  8. data/gems/core/core.gemspec +13 -0
  9. data/gems/core/lib/core.rb +33 -0
  10. data/gems/core/lib/core/array.rb +1470 -0
  11. data/gems/core/lib/core/basic_object.rb +15 -0
  12. data/gems/core/lib/core/class.rb +31 -0
  13. data/gems/core/lib/core/dir.rb +26 -0
  14. data/gems/core/lib/core/error.rb +43 -0
  15. data/gems/core/lib/core/false_class.rb +21 -0
  16. data/gems/core/lib/core/file.rb +54 -0
  17. data/gems/core/lib/core/hash.rb +725 -0
  18. data/gems/core/lib/core/kernel.rb +240 -0
  19. data/gems/core/lib/core/module.rb +98 -0
  20. data/gems/core/lib/core/nil_class.rb +41 -0
  21. data/gems/core/lib/core/numeric.rb +370 -0
  22. data/gems/core/lib/core/proc.rb +11 -0
  23. data/gems/core/lib/core/range.rb +17 -0
  24. data/gems/core/lib/core/regexp.rb +18 -0
  25. data/gems/core/lib/core/string.rb +328 -0
  26. data/gems/core/lib/core/symbol.rb +15 -0
  27. data/gems/core/lib/core/top_self.rb +8 -0
  28. data/gems/core/lib/core/true_class.rb +20 -0
  29. data/gems/core/lib/core/vm.rb +16 -0
  30. data/{opals/opal/opal → gems/core}/spec/core/array/append_spec.rb +0 -0
  31. data/{opals/opal/opal → gems/core}/spec/core/array/assoc_spec.rb +0 -0
  32. data/{opals/opal/opal → gems/core}/spec/core/array/at_spec.rb +0 -0
  33. data/{opals/opal/opal → gems/core}/spec/core/array/clear_spec.rb +1 -1
  34. data/{opals/opal/opal → gems/core}/spec/core/array/collect_bang_spec.rb +0 -0
  35. data/{opals/opal/opal → gems/core}/spec/core/array/collect_spec.rb +0 -0
  36. data/gems/core/spec/core/array/compact_spec.rb +41 -0
  37. data/{opals/opal/opal → gems/core}/spec/core/array/concat_spec.rb +0 -0
  38. data/{opals/opal/opal → gems/core}/spec/core/array/constructor_spec.rb +0 -0
  39. data/{opals/opal/opal → gems/core}/spec/core/array/each_spec.rb +0 -0
  40. data/{opals/opal/opal → gems/core}/spec/core/array/element_reference_spec.rb +0 -0
  41. data/{opals/opal/opal → gems/core}/spec/core/array/first_spec.rb +1 -1
  42. data/{opals/opal/opal → gems/core}/spec/core/array/include_spec.rb +0 -0
  43. data/gems/core/spec/core/array/join_spec.rb +6 -0
  44. data/gems/core/spec/core/array/last_spec.rb +51 -0
  45. data/gems/core/spec/core/array/length_spec.rb +6 -0
  46. data/{opals/opal/opal → gems/core}/spec/core/array/map_spec.rb +2 -0
  47. data/gems/core/spec/core/array/reverse_spec.rb +6 -0
  48. data/{opals/opal/opal → gems/core}/spec/core/builtin_constants/builtin_constants_spec.rb +0 -0
  49. data/{opals/opal/opal → gems/core}/spec/core/false/and_spec.rb +0 -0
  50. data/{opals/opal/opal → gems/core}/spec/core/false/inspect_spec.rb +0 -0
  51. data/{opals/opal/opal → gems/core}/spec/core/false/or_spec.rb +0 -0
  52. data/{opals/opal/opal → gems/core}/spec/core/false/to_s_spec.rb +0 -0
  53. data/{opals/opal/opal → gems/core}/spec/core/false/xor_spec.rb +0 -0
  54. data/{opals/opal/opal → gems/core}/spec/core/file/join_spec.rb +1 -1
  55. data/gems/core/spec/core/hash/assoc_spec.rb +32 -0
  56. data/{opals/opal/opal → gems/core}/spec/core/kernel/instance_eval_spec.rb +0 -0
  57. data/{opals/opal/opal → gems/core}/spec/core/kernel/loop_spec.rb +0 -0
  58. data/{opals/opal/opal → gems/core}/spec/core/kernel/raise_spec.rb +0 -0
  59. data/{opals/opal/opal → gems/core}/spec/core/module/attr_accessor_spec.rb +0 -0
  60. data/{opals/opal/opal → gems/core}/spec/core/number/lt_spec.rb +0 -0
  61. data/gems/core/spec/core/string/sub_spec.rb +24 -0
  62. data/{opals/opal/opal → gems/core}/spec/core/true/and_spec.rb +0 -0
  63. data/{opals/opal/opal → gems/core}/spec/core/true/inspect_spec.rb +0 -0
  64. data/{opals/opal/opal → gems/core}/spec/core/true/or_spec.rb +0 -0
  65. data/{opals/opal/opal → gems/core}/spec/core/true/to_s_spec.rb +0 -0
  66. data/{opals/opal/opal → gems/core}/spec/core/true/xor_spec.rb +0 -0
  67. data/{opals/opal/opal → gems/core}/spec/language/and_spec.rb +2 -3
  68. data/{opals/opal/opal → gems/core}/spec/language/array_spec.rb +21 -5
  69. data/gems/core/spec/language/block_spec.rb +38 -0
  70. data/{opals/opal/opal → gems/core}/spec/language/break_spec.rb +0 -0
  71. data/gems/core/spec/language/case_spec.rb +103 -0
  72. data/{opals/opal/opal → gems/core}/spec/language/def_spec.rb +11 -1
  73. data/{opals/opal/opal → gems/core}/spec/language/eigenclass_spec.rb +0 -0
  74. data/gems/core/spec/language/file_spec.rb +13 -0
  75. data/gems/core/spec/language/fixtures/block.rb +21 -0
  76. data/gems/core/spec/language/fixtures/super.rb +293 -0
  77. data/{opals/opal/opal → gems/core}/spec/language/hash_spec.rb +0 -0
  78. data/{opals/opal/opal → gems/core}/spec/language/if_spec.rb +0 -0
  79. data/{opals/opal/opal → gems/core}/spec/language/loop_spec.rb +0 -0
  80. data/gems/core/spec/language/metaclass_spec.rb +21 -0
  81. data/{opals/opal/opal → gems/core}/spec/language/method_spec.rb +60 -0
  82. data/{opals/opal/opal → gems/core}/spec/language/next_spec.rb +0 -0
  83. data/{opals/opal/opal → gems/core}/spec/language/or_spec.rb +0 -0
  84. data/{opals/opal/opal → gems/core}/spec/language/redo_spec.rb +0 -0
  85. data/gems/core/spec/language/regexp_spec.rb +26 -0
  86. data/{opals/opal/opal → gems/core}/spec/language/rescue_spec.rb +0 -0
  87. data/{opals/opal/opal → gems/core}/spec/language/return_spec.rb +0 -0
  88. data/{opals/opal/opal → gems/core}/spec/language/string_spec.rb +0 -0
  89. data/gems/core/spec/language/super_spec.rb +32 -0
  90. data/{opals/opal/opal → gems/core}/spec/language/until_spec.rb +47 -47
  91. data/gems/core/spec/language/variables_spec.rb +155 -0
  92. data/{opals/opal/opal → gems/core}/spec/language/while_spec.rb +47 -47
  93. data/{opals/opal/opal → gems/core}/spec/spec_helper.rb +1 -1
  94. data/gems/core_fs/README.md +19 -0
  95. data/gems/dev/Rakefile +5 -0
  96. data/gems/dev/lib/dev.js +99 -0
  97. data/gems/dev/lib/dev/generator.js +1264 -0
  98. data/gems/dev/lib/dev/parser.js +979 -0
  99. data/gems/dev/lib/dev/ruby_parser.js +1088 -0
  100. data/gems/dev/lib/dev/ruby_parser.y +1267 -0
  101. data/gems/dev/lib/dev/string_scanner.js +38 -0
  102. data/gems/dev/tools/racc2js/README.md +39 -0
  103. data/gems/dev/tools/racc2js/math_parser.js +222 -0
  104. data/gems/dev/tools/racc2js/math_parser.rb +133 -0
  105. data/gems/dev/tools/racc2js/math_parser.y +28 -0
  106. data/gems/dev/tools/racc2js/parser.js +218 -0
  107. data/gems/dev/tools/racc2js/racc2js.rb +153 -0
  108. data/gems/json/README.md +4 -0
  109. data/gems/json/json.gemspec +14 -0
  110. data/gems/json/lib/json.rb +64 -0
  111. data/gems/json/lib/json/ext.rb +51 -0
  112. data/{opals/opal/browser/lib/browser/json_parse.js → gems/json/lib/json/json2.js} +197 -37
  113. data/gems/ospec/README.md +0 -0
  114. data/gems/ospec/lib/ospec.rb +6 -0
  115. data/gems/ospec/lib/ospec/autorun.rb +3 -0
  116. data/gems/ospec/lib/ospec/dsl.rb +15 -0
  117. data/gems/ospec/lib/ospec/example.rb +11 -0
  118. data/gems/ospec/lib/ospec/example/before_and_after_hooks.rb +56 -0
  119. data/gems/ospec/lib/ospec/example/errors.rb +17 -0
  120. data/gems/ospec/lib/ospec/example/example_group.rb +12 -0
  121. data/gems/ospec/lib/ospec/example/example_group_factory.rb +21 -0
  122. data/gems/ospec/lib/ospec/example/example_group_hierarchy.rb +20 -0
  123. data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/example/example_group_methods.rb +26 -68
  124. data/gems/ospec/lib/ospec/example/example_group_proxy.rb +14 -0
  125. data/gems/ospec/lib/ospec/example/example_methods.rb +46 -0
  126. data/gems/ospec/lib/ospec/example/example_proxy.rb +18 -0
  127. data/gems/ospec/lib/ospec/expectations.rb +19 -0
  128. data/gems/ospec/lib/ospec/expectations/errors.rb +8 -0
  129. data/gems/ospec/lib/ospec/expectations/fail_with.rb +8 -0
  130. data/gems/ospec/lib/ospec/expectations/handler.rb +27 -0
  131. data/gems/ospec/lib/ospec/matchers.rb +24 -0
  132. data/{opals/opal/Rakefile → gems/ospec/lib/ospec/matchers/be.rb} +0 -0
  133. data/gems/ospec/lib/ospec/matchers/generated_descriptions.rb +20 -0
  134. data/gems/ospec/lib/ospec/matchers/operator_matcher.rb +52 -0
  135. data/gems/ospec/lib/ospec/runner.rb +40 -0
  136. data/gems/ospec/lib/ospec/runner/example_group_runner.rb +44 -0
  137. data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/formatter/html_formatter.rb +31 -40
  138. data/gems/ospec/lib/ospec/runner/formatter/terminal_formatter.rb +48 -0
  139. data/gems/ospec/lib/ospec/runner/options.rb +36 -0
  140. data/{opals/opal/spec/lib/spec → gems/ospec/lib/ospec}/runner/reporter.rb +23 -55
  141. data/gems/ospec/ospec.gemspec +0 -0
  142. data/gems/rquery/README.md +9 -0
  143. data/gems/rquery/lib/rquery.rb +10 -0
  144. data/gems/rquery/lib/rquery/ajax.rb +4 -0
  145. data/gems/rquery/lib/rquery/css.rb +96 -0
  146. data/gems/rquery/lib/rquery/document.rb +25 -0
  147. data/gems/rquery/lib/rquery/element.rb +292 -0
  148. data/gems/rquery/lib/rquery/event.rb +108 -0
  149. data/gems/rquery/lib/rquery/jquery.js +8177 -0
  150. data/gems/rquery/lib/rquery/request.rb +138 -0
  151. data/gems/rquery/lib/rquery/response.rb +49 -0
  152. data/gems/rquery/rquery.gemspec +16 -0
  153. data/lib/opal.js +1597 -0
  154. data/lib/opal.rb +6 -69
  155. data/lib/opal/builder.rb +115 -0
  156. data/lib/opal/bundle.rb +131 -0
  157. data/lib/opal/command.rb +11 -0
  158. data/lib/opal/context.rb +69 -0
  159. data/lib/opal/context/console.rb +12 -0
  160. data/lib/opal/context/file_system.rb +19 -0
  161. data/lib/opal/context/loader.rb +117 -0
  162. data/lib/opal/gem.rb +153 -0
  163. data/lib/opal/ruby/nodes.rb +1302 -0
  164. data/lib/opal/ruby/parser.rb +780 -0
  165. data/lib/opal/ruby/ruby_parser.rb +5170 -0
  166. data/lib/opal/ruby/ruby_parser.y +1298 -0
  167. data/opal.gemspec +11 -256
  168. metadata +179 -240
  169. data/.gitmodules +0 -6
  170. data/Opalfile +0 -384
  171. data/VERSION +0 -1
  172. data/demos/apps/browser_demo/index.html +0 -11
  173. data/demos/apps/browser_demo/lib/browser_demo.rb +0 -31
  174. data/demos/apps/simple_opal/Opalfile +0 -13
  175. data/demos/apps/simple_opal/index.html +0 -11
  176. data/demos/apps/simple_opal/lib/app_controller.rb +0 -62
  177. data/demos/apps/simple_opal/lib/main_window.rb +0 -146
  178. data/demos/browser/request/index.html +0 -52
  179. data/demos/browser/request/request.rb +0 -48
  180. data/gen/browser/__PROJECT_NAME__/Rakefile +0 -12
  181. data/gen/browser/__PROJECT_NAME__/index.html +0 -11
  182. data/gen/browser/__PROJECT_NAME__/javascripts/opal.debug.js +0 -4687
  183. data/gen/browser/__PROJECT_NAME__/javascripts/opal.min.js +0 -175
  184. data/gen/browser/__PROJECT_NAME__/lib/__PROJECT_NAME__.rb +0 -1
  185. data/lib/opal/builders/base.rb +0 -50
  186. data/lib/opal/builders/css.rb +0 -46
  187. data/lib/opal/builders/javascript.rb +0 -44
  188. data/lib/opal/builders/opal.rb +0 -79
  189. data/lib/opal/builders/ruby.rb +0 -50
  190. data/lib/opal/builders/ruby/generate.rb +0 -1851
  191. data/lib/opal/builders/ruby/nodes.rb +0 -210
  192. data/lib/opal/builders/ruby/ruby.rb +0 -916
  193. data/lib/opal/builders/ruby/ruby_parser.rb +0 -6008
  194. data/lib/opal/builders/ruby/ruby_parser.rb.y +0 -1451
  195. data/lib/opal/models/build_item.rb +0 -104
  196. data/lib/opal/models/hash_struct.rb +0 -40
  197. data/lib/opal/models/project.rb +0 -252
  198. data/lib/opal/models/struct_accessors.rb +0 -58
  199. data/lib/opal/models/target.rb +0 -176
  200. data/lib/opal/opal/build.rb +0 -169
  201. data/lib/opal/opal/env/console.rb +0 -66
  202. data/lib/opal/opal/env/fs.rb +0 -98
  203. data/lib/opal/opal/env/object.rb +0 -48
  204. data/lib/opal/opal/environment.rb +0 -139
  205. data/lib/opal/opal/gen.rb +0 -62
  206. data/lib/opal/opal/opal.rb +0 -75
  207. data/lib/opal/opal/repl.rb +0 -38
  208. data/lib/opal/opalfile/dsl.rb +0 -62
  209. data/lib/opal/opalfile/opalfile.rb +0 -133
  210. data/lib/opal/opalfile/task.rb +0 -96
  211. data/lib/opal/opalfile/task_manager.rb +0 -63
  212. data/lib/opal/opalfile/task_scope.rb +0 -52
  213. data/lib/opal/rack/app_server.rb +0 -119
  214. data/lib/opal/rake/opal_task.rb +0 -34
  215. data/opals/opal/README.md +0 -37
  216. data/opals/opal/browser/Opalfile +0 -11
  217. data/opals/opal/browser/README.md +0 -146
  218. data/opals/opal/browser/SIZZLE_LICESNSE.txt +0 -148
  219. data/opals/opal/browser/lib/browser.rb +0 -118
  220. data/opals/opal/browser/lib/browser/builder.rb +0 -41
  221. data/opals/opal/browser/lib/browser/canvas_context.rb +0 -115
  222. data/opals/opal/browser/lib/browser/dimensions.rb +0 -50
  223. data/opals/opal/browser/lib/browser/document.rb +0 -146
  224. data/opals/opal/browser/lib/browser/element.rb +0 -487
  225. data/opals/opal/browser/lib/browser/element/attributes.rb +0 -88
  226. data/opals/opal/browser/lib/browser/element/css.rb +0 -290
  227. data/opals/opal/browser/lib/browser/element/form.rb +0 -146
  228. data/opals/opal/browser/lib/browser/event/dom_events.rb +0 -81
  229. data/opals/opal/browser/lib/browser/event/event.rb +0 -177
  230. data/opals/opal/browser/lib/browser/event/trigger_events.rb +0 -53
  231. data/opals/opal/browser/lib/browser/geometry.rb +0 -97
  232. data/opals/opal/browser/lib/browser/json.rb +0 -32
  233. data/opals/opal/browser/lib/browser/request/request.rb +0 -201
  234. data/opals/opal/browser/lib/browser/sizzle.js +0 -1068
  235. data/opals/opal/browser/lib/browser/string.rb +0 -42
  236. data/opals/opal/browser/lib/browser/touch.rb +0 -37
  237. data/opals/opal/browser/lib/browser/vml_context.js +0 -33
  238. data/opals/opal/browser/lib/browser/window.rb +0 -36
  239. data/opals/opal/browser/spec/browser/browser_detection_spec.rb +0 -7
  240. data/opals/opal/browser/spec/document/aref_spec.rb +0 -110
  241. data/opals/opal/browser/spec/document/ready_spec.rb +0 -16
  242. data/opals/opal/browser/spec/element/body_spec.rb +0 -11
  243. data/opals/opal/browser/spec/element/clear_spec.rb +0 -26
  244. data/opals/opal/browser/spec/element/empty_spec.rb +0 -29
  245. data/opals/opal/browser/spec/element/has_class_spec.rb +0 -40
  246. data/opals/opal/browser/spec/element/hidden_spec.rb +0 -23
  247. data/opals/opal/browser/spec/element/hide_spec.rb +0 -31
  248. data/opals/opal/browser/spec/element/remove_spec.rb +0 -25
  249. data/opals/opal/browser/spec/element/show_spec.rb +0 -31
  250. data/opals/opal/browser/spec/element/style_spec.rb +0 -69
  251. data/opals/opal/browser/spec/element/toggle_spec.rb +0 -31
  252. data/opals/opal/browser/spec/element/visible_spec.rb +0 -23
  253. data/opals/opal/browser/spec/spec_helper.rb +0 -1
  254. data/opals/opal/opal/Opalfile +0 -14
  255. data/opals/opal/opal/spec/core/array/compact_spec.rb +0 -15
  256. data/opals/opal/opal/spec/fixtures/super.rb +0 -70
  257. data/opals/opal/opal/spec/language/____temp_remove_this.rb +0 -12
  258. data/opals/opal/opal/spec/language/block_spec.rb +0 -18
  259. data/opals/opal/opal/spec/language/case_spec.rb +0 -103
  260. data/opals/opal/opal/spec/language/metaclass_spec.rb +0 -21
  261. data/opals/opal/opal/spec/language/super_spec.rb +0 -26
  262. data/opals/opal/runtime/Opalfile +0 -78
  263. data/opals/opal/runtime/README.md +0 -12
  264. data/opals/opal/runtime/docs/debugging.md +0 -51
  265. data/opals/opal/runtime/lib/array.rb +0 -1516
  266. data/opals/opal/runtime/lib/basic_object.rb +0 -49
  267. data/opals/opal/runtime/lib/class.rb +0 -54
  268. data/opals/opal/runtime/lib/dir.rb +0 -36
  269. data/opals/opal/runtime/lib/error.rb +0 -49
  270. data/opals/opal/runtime/lib/false_class.rb +0 -52
  271. data/opals/opal/runtime/lib/file.rb +0 -79
  272. data/opals/opal/runtime/lib/hash.rb +0 -791
  273. data/opals/opal/runtime/lib/io.rb +0 -39
  274. data/opals/opal/runtime/lib/kernel.rb +0 -288
  275. data/opals/opal/runtime/lib/match_data.rb +0 -36
  276. data/opals/opal/runtime/lib/module.rb +0 -109
  277. data/opals/opal/runtime/lib/nil_class.rb +0 -69
  278. data/opals/opal/runtime/lib/number.rb +0 -398
  279. data/opals/opal/runtime/lib/proc.rb +0 -77
  280. data/opals/opal/runtime/lib/range.rb +0 -63
  281. data/opals/opal/runtime/lib/regexp.rb +0 -111
  282. data/opals/opal/runtime/lib/ruby.rb +0 -30
  283. data/opals/opal/runtime/lib/string.rb +0 -328
  284. data/opals/opal/runtime/lib/symbol.rb +0 -40
  285. data/opals/opal/runtime/lib/top_self.rb +0 -33
  286. data/opals/opal/runtime/lib/true_class.rb +0 -45
  287. data/opals/opal/runtime/runtime/browser.js +0 -287
  288. data/opals/opal/runtime/runtime/debug.js +0 -180
  289. data/opals/opal/runtime/runtime/opal.js +0 -1008
  290. data/opals/opal/runtime/runtime/post_opal.js +0 -1
  291. data/opals/opal/runtime/runtime/pre_opal.js +0 -2
  292. data/opals/opal/runtime/runtime/server_side.js +0 -50
  293. data/opals/opal/spec/LICENSE.txt +0 -26
  294. data/opals/opal/spec/Opalfile +0 -5
  295. data/opals/opal/spec/bin/spec.rb +0 -43
  296. data/opals/opal/spec/lib/spec.rb +0 -33
  297. data/opals/opal/spec/lib/spec/dsl.rb +0 -41
  298. data/opals/opal/spec/lib/spec/example.rb +0 -35
  299. data/opals/opal/spec/lib/spec/example/before_and_after_hooks.rb +0 -81
  300. data/opals/opal/spec/lib/spec/example/errors.rb +0 -42
  301. data/opals/opal/spec/lib/spec/example/example_group.rb +0 -37
  302. data/opals/opal/spec/lib/spec/example/example_group_factory.rb +0 -43
  303. data/opals/opal/spec/lib/spec/example/example_group_hierarchy.rb +0 -45
  304. data/opals/opal/spec/lib/spec/example/example_group_proxy.rb +0 -41
  305. data/opals/opal/spec/lib/spec/example/example_methods.rb +0 -73
  306. data/opals/opal/spec/lib/spec/example/example_proxy.rb +0 -48
  307. data/opals/opal/spec/lib/spec/expectations.rb +0 -46
  308. data/opals/opal/spec/lib/spec/expectations/errors.rb +0 -35
  309. data/opals/opal/spec/lib/spec/expectations/fail_with.rb +0 -37
  310. data/opals/opal/spec/lib/spec/expectations/handler.rb +0 -48
  311. data/opals/opal/spec/lib/spec/matchers.rb +0 -50
  312. data/opals/opal/spec/lib/spec/matchers/be.rb +0 -26
  313. data/opals/opal/spec/lib/spec/matchers/generated_descriptions.rb +0 -47
  314. data/opals/opal/spec/lib/spec/matchers/operator_matcher.rb +0 -66
  315. data/opals/opal/spec/lib/spec/runner.rb +0 -48
  316. data/opals/opal/spec/lib/spec/runner/example_group_runner.rb +0 -71
  317. data/opals/opal/spec/lib/spec/runner/formatter/terminal_formatter.rb +0 -82
  318. data/opals/opal/spec/lib/spec/runner/options.rb +0 -63
  319. data/opals/opal/spec/resources/index.html +0 -25
  320. data/opals/opal/spec/resources/spec.css +0 -132
  321. data/spec/cherry_kit/iseq_spec.rb +0 -38
  322. data/spec/spec_helper.rb +0 -16
  323. data/spec/vienna_spec.rb +0 -7
  324. data/yard/index.html +0 -43
  325. data/yard/style.css +0 -765
@@ -0,0 +1,138 @@
1
+ # The Request class wraps the native XMLHttpRequest object in the
2
+ # browser and makes use of jQuery's ajax facilities to make requests.
3
+ class Request
4
+
5
+ # Default options used by all Requests. Unless an option here is
6
+ # overrideen, then these defaults will be used on each request. This
7
+ # is not a full list of all options that can be used; these are just
8
+ # the bare essentials and useful defaults.
9
+ DEFAULT_OPTIONS = {
10
+ :url => '',
11
+ :type => 'GET'
12
+ }
13
+
14
+ # Creates a new Request object. The passed options are merged with
15
+ # DEFAULT_OPTIONS and will be used as the base options for each
16
+ # request. Request specific options may be passed to {#send}, and
17
+ # these will be used in preference to the options passed here.
18
+ #
19
+ # Most of the options that can be set also have their own designated
20
+ # getters and setters as instance methods on this class. This allows
21
+ # for options to be set in a more independant manner instead of
22
+ # collecting all options into the initialization hash.
23
+ #
24
+ # @param [Hash] options request options
25
+ # @return [Request] returns new request instance
26
+ def initialize(options = {})
27
+ @options = DEFAULT_OPTIONS.merge options
28
+ @complete_action = nil
29
+ @failure_action = nil
30
+ @success_action = nil
31
+ end
32
+
33
+ # Creates attribute reader and writers for the given options that will
34
+ # set/retrieve the values from the options hash belonging to this
35
+ # instance. Each of these options may also be overriden by the final
36
+ # values sent to {#send}, or one of its aliases: {#get}, {#post},
37
+ # {#put} or {#delete}.
38
+ #
39
+ # @param [String, Symbol] names option names to set
40
+ def self.option_accessor(*names)
41
+ names.each do |name|
42
+ # define option getter
43
+ define_method(name) { @options[name] }
44
+ # define option setter
45
+ define_method("#{name}=") { |value| @options[name] = value }
46
+ end
47
+ end
48
+
49
+ # By default all requests will be sent async, to avoid locking up the
50
+ # browser. Set this to `false` to send requests in a sync fashion.
51
+ # This defaults to `true` to send by async by default.
52
+ option_accessor :async
53
+
54
+ # Gets the type of the request, which is "GET" by default. This value
55
+ # may be "GET" or "POST", as they are well supported by the browser,
56
+ # but "PUT" and "DELETE" may also be used, but they are not supported
57
+ # within the browser.
58
+ option_accessor :type
59
+
60
+ # Holds the string representing the URL to which the request is sent.
61
+ # By default this is an empty string, so it needs to be set to get any
62
+ # useful requests back.
63
+ option_accessor :url
64
+
65
+ # Sets the username to use when accessing the HTTP authentication
66
+ # requests.
67
+ option_accessor :username
68
+
69
+ # Sets the relevant password used in the HTTP authentication requests.
70
+ option_accessor :password
71
+
72
+ # Sends the request with the specified options. These options are
73
+ # merged with the options given to {#initialize}. There are also
74
+ # aliases for this method for automatically setting the request
75
+ # type; {#put}, {#post}, {#get} and {#delete} will automatically
76
+ # set the correct request type to avoid the need to set it in the
77
+ # options.
78
+ #
79
+ # @param [Hash] options the request options
80
+ # @return [Request] returns the receiver
81
+ def send(options = {})
82
+ `options = #{@options.merge options};
83
+
84
+ // native options object
85
+ var opts = {};
86
+
87
+ // we must have a url
88
+ opts.url = #{options[:url]}
89
+
90
+ // request type
91
+ opts.type = #{options[:type]}
92
+
93
+ // success callback
94
+ if (#{@success_action} != nil) {
95
+ opts.success = function(data, textStatus, jqXHR) {
96
+ var response = #{Response.new `jqXHR`};
97
+ #{@success_action.call `response`};
98
+ };
99
+ }
100
+
101
+ $.ajax(opts);
102
+
103
+ return self;`
104
+ end
105
+
106
+ def get(options = {})
107
+ options[:type] = 'GET'
108
+ send options
109
+ end
110
+
111
+ def post(options = {})
112
+ options[:type] = 'POST'
113
+ send options
114
+ end
115
+
116
+ def put(options = {})
117
+ options[:type] = 'PUT'
118
+ send options
119
+ end
120
+
121
+ def delete(options = {})
122
+ options[:type] = 'DELETE'
123
+ send options
124
+ end
125
+
126
+ # Register a block that will be called if the request succeeds.
127
+ def success(&block)
128
+ @success_action = block
129
+ end
130
+
131
+ # Register a block that will be called if the request fails
132
+
133
+ def failure(&block)
134
+ @failure_action = block
135
+ end
136
+ end
137
+
138
+
@@ -0,0 +1,49 @@
1
+ # Instances of Response are automatically created by Request, so you do
2
+ # not need to make them yourself. This is the object that will be passed
3
+ # to each of the callbacks for a Request object. For this reason, this
4
+ # object will be created if the request succeeds, or indeed fails.
5
+ class Response
6
+ # Private initializer. This handles a native jquery requets object, so
7
+ # this should all probably be private.
8
+ def initialize(request)
9
+ `self.$xhr = request`
10
+ end
11
+
12
+ # Returns the numeric status code for the response.
13
+ #
14
+ # @return [Numeric]
15
+ def status
16
+ `return self.$xhr.status;`
17
+ end
18
+
19
+ # Returns the string status message for the response.
20
+ #
21
+ # @return [String]
22
+ def status_text
23
+ `return self.$xhr.statusText;`
24
+ end
25
+
26
+ # Returns the response text from the request.
27
+ #
28
+ # @return [String]
29
+ def text
30
+ `return self.$xhr.responseText;`
31
+ end
32
+
33
+ # Returns `true` if the response represents a successfull request,
34
+ # `false` otherwise.
35
+ #
36
+ # @return [true, false]
37
+ def success?
38
+ `return (self.$xhr.status >= 200 && self.$xhr.status < 300) ? Qtrue : Qfalse;`
39
+ end
40
+
41
+ # Returns `false` if the response was the result of an unsuccessful
42
+ # request, `true` otherwise.
43
+ #
44
+ # @return [true, false]
45
+ def failure?
46
+ !success?
47
+ end
48
+ end
49
+
@@ -0,0 +1,16 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "rquery"
5
+ s.version = "0.0.1"
6
+ s.authors = ["Adam Beynon"]
7
+ s.email = ["adam@adambeynon.com"]
8
+ s.homepage = "http://github.com/adambeynon/opal"
9
+ s.summary = "Rquery DOM library for ruby/opal"
10
+
11
+ s.files = Dir.glob("{bin,lib}/**/*") + %w[README.md]
12
+ s.require_path = "lib"
13
+
14
+ s.add_dependency "json"
15
+ end
16
+
@@ -0,0 +1,1597 @@
1
+ /**
2
+ Incase we are in browser, wrap body to avoid global vars. Just opal can become
3
+ a top level var. We treat opal as our exports in nodejs, as we reassign them
4
+ at the bottom of this file.
5
+ */
6
+ var opal = {};
7
+
8
+ (function() {
9
+
10
+ // So we can minimize
11
+ var Op = opal;
12
+
13
+ /**
14
+ Core runtime classes, objects and literals.
15
+ */
16
+ var cBasicObject, cObject, cModule, cClass,
17
+ mKernel, cNilClass, cTrueClass, cFalseClass,
18
+ cFile, cProc, cNumeric, cArray,
19
+ cHash, cString, cSymbol, cRange,
20
+ cRegexp, cMatch, Qself, Qnil,
21
+ Qfalse, Qtrue;
22
+
23
+ /**
24
+ Exception classes. Some of these are used by runtime so they are here for
25
+ convenience.
26
+ */
27
+ var eException, eStandardError, eLocalJumpError, eNameError,
28
+ eNoMethodError, eArgError, eScriptError, eLoadError,
29
+ eRuntimeError, eTypeError, eIndexError, eKeyError,
30
+ eRangeError;
31
+
32
+ /**
33
+ Standard jump exceptions to save re-creating them everytime they are needed
34
+ */
35
+ var rb_vm_return_instance,
36
+ rb_vm_loop_return_instance,
37
+ rb_vm_next_instance,
38
+ rb_vm_break_instance;
39
+
40
+ // ..........................................................
41
+ // VIRTUAL MACHINE
42
+ //
43
+
44
+ /**
45
+ This is the VM param that gets given to all files in opal. This contains
46
+ just the VM methods for opal, to keep the global opal namespace cleaner as
47
+ it is used just for external access.
48
+ */
49
+ Op.vm = {};
50
+
51
+ // for minimizng
52
+ var Vm = Op.vm;
53
+ Vm.opal = Op;
54
+
55
+ /**
56
+ Core object type flags. Added as local variables, and onto Opal prototype.
57
+ */
58
+ var T_CLASS = Vm.T_CLASS = 1,
59
+ T_MODULE = Vm.T_MODULE = 2,
60
+ T_OBJECT = Vm.T_OBJECT = 4,
61
+ T_BOOLEAN = Vm.T_BOOLEAN = 8,
62
+ T_STRING = Vm.T_STRING = 16,
63
+ T_ARRAY = Vm.T_ARRAY = 32,
64
+ T_NUMBER = Vm.T_NUMBER = 64,
65
+ T_PROC = Vm.T_PROC = 128,
66
+ T_SYMBOL = Vm.T_SYMBOL = 256,
67
+ T_HASH = Vm.T_HASH = 512,
68
+ T_RANGE = Vm.T_RANGE = 1024,
69
+ T_ICLASS = Vm.T_ICLASS = 2056,
70
+ FL_SINGLETON = Vm.FL_SINGLETON = 4112;
71
+
72
+ /**
73
+ For setting up method_missing methods. Each ruby file that has been compiled
74
+ with call this method with an array of all method_ids that it makes use of.
75
+ These only need to be from method calls. This allows us to make sure this
76
+ method exists on the base prototype, and is set to simply call method_missing
77
+ for the receiver. This adds overhead to the beginning of each file being
78
+ loaded, but is more more efficient than having to check for method_missing on
79
+ every method call in the file for the entirety of its lifetime.
80
+
81
+ @param {Array<String>} method_ids An array of method_ids to register
82
+ */
83
+ Vm.mm = function(method_ids) {
84
+ var prototype = cBasicObject.$m_prototype_tbl;
85
+
86
+ for (var i = 0, ii = method_ids.length; i < ii; i++) {
87
+ var method_id = method_ids[i];
88
+ // only add fake method if not already defined
89
+ if (!prototype.hasOwnProperty(method_id)) {
90
+ // our fake method implementation
91
+ var imp = (function(method_id) {
92
+ return function(self) {
93
+ var args = [].slice.call(arguments, 1);
94
+ args.unshift(Vm.Y(method_id));
95
+ args.unshift(self);
96
+ return self.$m.method_missing.apply(null, args);
97
+ };
98
+ })(method_id);
99
+ // mark as a fake method to help respond_to? and send, etc.
100
+ imp.$rbMM = true;
101
+ prototype[method_id] = imp;
102
+ }
103
+ }
104
+ };
105
+
106
+ /**
107
+ Define methods. Public method for defining a method on the given base.
108
+
109
+ @param {RObject} base The base to define method on
110
+ @param {String} method_id Ruby mid
111
+ @param {Function} body The method implementation
112
+ @param {Boolean} singleton Singleton or Normal method. true for singleton
113
+ */
114
+
115
+ Vm.dm = function(base, method_id, body, singleton) {
116
+ if (singleton) {
117
+ define_singleton_method(base, method_id, body);
118
+ } else {
119
+ // should this instead do a rb_singleton_method?? probably..
120
+ if (base.$flags & T_OBJECT) {
121
+ base = base.$klass;
122
+ }
123
+
124
+ define_method(base, method_id, body);
125
+ }
126
+
127
+ return Qnil;
128
+ };
129
+
130
+ /**
131
+ Define classes. This is the public API for defining classes, shit classes
132
+ and modules.
133
+
134
+ @param {RObject} base
135
+ @param {RClass} super_class
136
+ @param {String} id
137
+ @param {Function} body
138
+ @param {Number} flag
139
+ */
140
+ Vm.dc = function(base, super_class, id, body, flag) {
141
+ var klass;
142
+
143
+ switch (flag) {
144
+ case 0:
145
+ if (base.$flags & T_OBJECT) {
146
+ base = class_real(base.$klass);
147
+ }
148
+
149
+ if (super_class == Qnil) {
150
+ super_class = cObject;
151
+ }
152
+
153
+ klass = define_class_under(base, id, super_class);
154
+ break;
155
+
156
+ case 1:
157
+ klass = singleton_class(base);
158
+ break;
159
+
160
+ case 2:
161
+ if (base.$flags & T_OBJECT) {
162
+ base = class_real(base.$klass);
163
+ }
164
+ klass = define_module_under(base, id);
165
+ break;
166
+
167
+ default:
168
+ raise(eException, "define_class got a unknown flag " + flag);
169
+ }
170
+
171
+ return body.call(klass);
172
+ };
173
+
174
+ /**
175
+ Returns a new RHash instance constructed from the given arguments of
176
+ alternate key, value pairs.
177
+ */
178
+ Vm.H = function() {
179
+ return new RHash(Array.prototype.slice.call(arguments));
180
+ };
181
+
182
+ /**
183
+ Returns a new ruby symbol with the given intern value. Symbols are made
184
+ using the new String() constructor, and just have its klass and method
185
+ table reassigned. This makes dealing with strings/symbols internally
186
+ easier as both can be used as a string within opal.
187
+
188
+ @param {String} intern Symbol value
189
+ @return {RSymbol} symbol
190
+ */
191
+ Vm.Y = function(intern) {
192
+ if (symbol_table.hasOwnProperty(intern)) {
193
+ return symbol_table[intern];
194
+ }
195
+
196
+ var res = new String(intern);
197
+ res.$klass = cSymbol;
198
+ res.$m = cSymbol.$m_tbl;
199
+ symbol_table[intern] = res;
200
+ return res;
201
+ };
202
+
203
+ /**
204
+ Returns a new ruby range. 'G' for range... yeah.
205
+
206
+ @param {RObject} beg The start item for the range
207
+ @param {RObject} end The finish item for the range
208
+ @param {true, false} exclude_end Whether or not the range excludes the last item
209
+ @return {RRange} Returns the new range instance
210
+ */
211
+ Vm.G = function(beg, end, exclude_end) {
212
+ return new RRange(beg, end, exclude_end);
213
+ };
214
+
215
+ /**
216
+ Ruby break statement with the given value. When no break value is needed, nil
217
+ should be passed here. An undefined/null value is not valid and will cause an
218
+ internal error.
219
+
220
+ @param {RObject} value The break value.
221
+ */
222
+ Vm.B = function(value) {
223
+ rb_vm_break_instance.$value = value;
224
+ throw rb_vm_break_instance;
225
+ };
226
+
227
+ /**
228
+ Ruby return, with the given value. The func is the reference function which
229
+ represents the method that this statement must return from.
230
+ */
231
+ Vm.R = function(value, func) {
232
+ rb_vm_return_instance.$value = value;
233
+ rb_vm_return_instance.$func = func;
234
+ throw rb_vm_return_instance;
235
+ };
236
+
237
+ /**
238
+ Block passing. This holds the current block info for the runtime.
239
+
240
+ f: function
241
+ p: block
242
+ y: yield error
243
+
244
+ */
245
+ Vm.P = {
246
+ f: null,
247
+ p: null,
248
+ y: function() {
249
+ throw new Error("LocalJumpError - opal.P.y - no block given");
250
+ }
251
+ };
252
+
253
+ /**
254
+ Define a toll free bridged class.
255
+
256
+ @param {Object} prototype Native prototype to extend
257
+ @param {Number} flags The flags for instances of class
258
+ @param {String} id Class id
259
+ @param {RClass} super_klass
260
+ */
261
+ Vm.bridged_class = function(prototype, flags, id, super_klass) {
262
+ return bridge_class(prototype, flags || T_OBJECT, id, super_klass);
263
+ };
264
+
265
+ /**
266
+ Sets the constant value `val` on the given `klass` as `id`.
267
+
268
+ @param {RClass} klass
269
+ @param {String} id
270
+ @param {Object} val
271
+ @return {Object} returns the set value
272
+ */
273
+ function const_set(klass, id, val) {
274
+ klass.$c_prototype[id] = val;
275
+ return val;
276
+ }
277
+
278
+ /**
279
+ Lookup a constant named `id` on the `klass`. This will throw an error if
280
+ the constant cannot be found.
281
+
282
+ @param {RClass} klass
283
+ @param {String} id
284
+ */
285
+ function const_get(klass, id) {
286
+ if (klass.$c[id]) {
287
+ return (klass.$c[id]);
288
+ }
289
+
290
+ var parent = klass.$parent;
291
+
292
+ while (parent && parent != cObject) {
293
+ if (parent.$c[id]) {
294
+ return parent.$c[id];
295
+ }
296
+
297
+ parent = parent.$parent;
298
+ }
299
+
300
+ raise(eNameError, 'uninitialized constant ' + id);
301
+ };
302
+
303
+ /**
304
+ Returns true or false depending whether a constant named `id` is defined
305
+ on the receiver `klass`.
306
+
307
+ @param {RClass} klass
308
+ @param {String} id
309
+ @return {true, false}
310
+ */
311
+ function const_defined(klass, id) {
312
+ if (klass.$c[id]) {
313
+ return true;
314
+ }
315
+
316
+ return false;
317
+ };
318
+
319
+ /**
320
+ Set an instance variable on the receiver.
321
+ */
322
+ function ivar_set(obj, id, val) {
323
+ obj[id] = val;
324
+ return val;
325
+ };
326
+
327
+ /**
328
+ Return an instance variable set on the receiver, or nil if one does not
329
+ exist.
330
+ */
331
+ function ivar_get(obj, id) {
332
+ return obj.hasOwnProperty(id) ? obj[id] : Qnil;
333
+ };
334
+
335
+ /**
336
+ Determines whether and instance variable has been set on the receiver.
337
+ */
338
+ function ivar_defined(obj, id) {
339
+ return obj.hasOwnProperty(id) ? true : false;
340
+ };
341
+
342
+ /**
343
+ This table holds all the global variables accessible from ruby.
344
+
345
+ Entries are mapped by their global id => an object that contains the
346
+ given keys:
347
+
348
+ - name
349
+ - value
350
+ - getter
351
+ - setter
352
+ */
353
+ var global_tbl = {};
354
+
355
+ /**
356
+ Defines a hooked/global variable.
357
+
358
+ @param {String} name The global name (e.g. '$:')
359
+ @param {Function} getter The getter function to return the variable
360
+ @param {Function} setter The setter function used for setting the var
361
+ @return {null}
362
+ */
363
+ function define_hooked_variable(name, getter, setter) {
364
+ var entry = {
365
+ "name": name,
366
+ "value": Qnil,
367
+ "getter": getter,
368
+ "setter": setter
369
+ };
370
+
371
+ global_tbl[name] = entry;
372
+ };
373
+
374
+ /**
375
+ A default read only getter for a global variable. This will simply throw a
376
+ name error with the given id. This can be used for variables that should
377
+ not be altered.
378
+ */
379
+ function gvar_readonly_setter(id, value) {
380
+ raise(eNameError, id + " is a read-only variable");
381
+ };
382
+
383
+ /**
384
+ Retrieve a global variable. This will use the assigned getter.
385
+ */
386
+ function gvar_get(id) {
387
+ var entry = global_tbl[id];
388
+ if (!entry) { return Qnil; }
389
+ return entry.getter(id);
390
+ };
391
+
392
+ /**
393
+ Set a global. If not already set, then we assign basic getters and setters.
394
+ */
395
+ function gvar_set(id, value) {
396
+ var entry = global_tbl[id];
397
+ if (entry) { return entry.setter(id, value); }
398
+
399
+ define_hooked_variable(id,
400
+
401
+ function(id) {
402
+ return global_tbl[id].value;
403
+ },
404
+
405
+ function(id, value) {
406
+ return (global_tbl[id].value = value);
407
+ }
408
+ );
409
+
410
+ return gvar_set(id, value);
411
+ };
412
+
413
+ /**
414
+ Every object has a unique id. This count is used as the next id for the
415
+ next created object. Therefore, first ruby object has id 0, next has 1 etc.
416
+ */
417
+ var hash_yield = 0;
418
+
419
+ /**
420
+ Yield the next object id, updating the count, and returning it.
421
+ */
422
+ function yield_hash() {
423
+ return hash_yield++;
424
+ };
425
+
426
+ /**
427
+ The root class. Every class in opal is an instance of RClass.
428
+
429
+ @constructor
430
+ @param {RClass} klass
431
+ @param {RClass} super_klass
432
+ */
433
+ var RClass = Vm.RClass = function(klass, super_klass) {
434
+ this.$id = yield_hash();
435
+ this.$super = super_klass;
436
+
437
+ if (super_klass) {
438
+ var ctor = function() {};
439
+ ctor.prototype = super_klass.$m_prototype_tbl;
440
+
441
+ var m_ctor = function() {};
442
+ m_ctor.prototype = new ctor();
443
+
444
+ this.$m_tbl = new m_ctor();
445
+ this.$m_prototype_tbl = m_ctor.prototype;
446
+
447
+ var cctor = function() {};
448
+ cctor.prototype = super_klass.$c_prototype;
449
+
450
+ var c_ctor = function() {};
451
+ c_ctor.prototype = new cctor();
452
+
453
+ this.$c = new c_ctor();
454
+ this.$c_prototype = c_ctor.prototype;
455
+ }
456
+ else {
457
+ var m_ctor = function() {};
458
+ this.$m_tbl = new m_ctor();
459
+ this.$m_prototype_tbl = m_ctor.prototype;
460
+
461
+ var c_ctor = function() {};
462
+ this.$c = new c_ctor();
463
+ this.$c_prototype = c_ctor.prototype;
464
+ }
465
+
466
+ this.$method_table = {};
467
+ return this;
468
+ };
469
+
470
+ // RClass protoype for minimizing
471
+ var Rp = RClass.prototype;
472
+
473
+ /**
474
+ Flags. Every RClass instance is simply a T_CLASS, so mark as so.
475
+ */
476
+ Rp.$flags = T_CLASS;
477
+
478
+ /**
479
+ RTest/truthiness - every RClass instance is true.
480
+ */
481
+ Rp.$r = true;
482
+
483
+ /**
484
+ The root object. Every object in opal (apart from toll free bridged classes
485
+ like array, string etc) are an instance of RObject.
486
+
487
+ @param {RClass} klass
488
+ */
489
+ var RObject = Vm.RObject = function(klass) {
490
+ this.$id = yield_hash();
491
+ this.$klass = klass;
492
+ this.$m = klass.$m_tbl;
493
+ return this;
494
+ };
495
+
496
+ // For minimizing
497
+ var Bp = RObject.prototype;
498
+
499
+ /**
500
+ Flags - every RObject instance is simply a T_OBJECT
501
+ */
502
+ Bp.$flags = T_OBJECT;
503
+
504
+ /**
505
+ RTest - every RObject instance is true.
506
+ */
507
+ Bp.$r = true;
508
+
509
+ /**
510
+ The hash of a class or object in ruby is simply it's id, as all objects and
511
+ classes have unique ids.
512
+ */
513
+ Bp.$hash = Rp.$hash = function() {
514
+ return this.$id;
515
+ };
516
+
517
+ /**
518
+ Internal method for defining a method.
519
+
520
+ @param {RClass} klass The klass to define the method on
521
+ @param {String} name The method id
522
+ @param {Function} body Method implementation
523
+ @return {Qnil}
524
+ */
525
+ function define_method(klass, name, body) {
526
+ klass.$m_prototype_tbl[name] = body;
527
+ klass.$method_table[name] = body;
528
+
529
+ if (klass.$included_in) {
530
+ for (var i = 0; i < klass.$included_in.length; i++) {
531
+ klass.$included_in[i].$m_prototype_tbl[name] = body;
532
+ klass.$included_in[i].$method_table[name] = body;
533
+ }
534
+ }
535
+
536
+ if (!body.$rbName) {
537
+ body.$rbName = name;
538
+ }
539
+
540
+ return Qnil;
541
+ };
542
+
543
+ Vm.define_method = define_method;
544
+
545
+ function define_singleton_method(klass, name, body) {
546
+ define_method(singleton_class(klass), name, body);
547
+ };
548
+
549
+ function define_alias(base, new_name, old_name) {
550
+ define_method(base, new_name, base.$m_tbl[old_name]);
551
+ return Qnil;
552
+ };
553
+
554
+ /**
555
+ Implementation for Class#allocate
556
+ */
557
+ function obj_alloc(klass) {
558
+ var result = new RObject(klass, T_OBJECT);
559
+ return result;
560
+ };
561
+
562
+ /**
563
+ Raise the exception class with the given string message.
564
+ */
565
+ function raise(exc, str) {
566
+ if (str === undefined) {
567
+ str = exc;
568
+ exc = eException;
569
+ }
570
+ var exception = exc.$m.allocate(exc);
571
+ exception.message = str;
572
+ vm_raise(exception);
573
+ };
574
+
575
+ /**
576
+ Raise an exception instance (DO NOT pass strings to this)
577
+ */
578
+ function vm_raise(exc) {
579
+ throw exc;
580
+ };
581
+
582
+ Vm.raise = vm_raise;
583
+
584
+ /**
585
+ Throw an argument error when the wrong number of arguments were given to a
586
+ method.
587
+
588
+ @param {Number} given The number of arguments actually given
589
+ @param {Number} expected The number of arguments we expected to have
590
+ */
591
+ function arg_error(given, expected) {
592
+ raise(eArgError,
593
+ "wrong number of arguments(" + given + " for " + expected + ")");
594
+ };
595
+
596
+ /**
597
+ Call a super method.
598
+
599
+ callee is the function that actually called super(). We use this to find
600
+ the right place in the tree to find the method that actually called super.
601
+ This is actually done in super_find.
602
+ */
603
+ Vm.S = function(callee, self, args) {
604
+ var mid = callee.$rbName;
605
+ var func = super_find(self.$klass, callee, callee.$rbName);
606
+
607
+ if (!func) {
608
+ raise(eNoMethodError, "super: no superclass method for " + mid);
609
+ raise(eNoMethodError, "super: no super class method `" + mid + "`" +
610
+ " for " + self.$m.inspect(self));
611
+ }
612
+
613
+ var args_to_send = [self, mid].concat(args);
614
+ return func.apply(null, args_to_send);
615
+ };
616
+
617
+ /**
618
+ Actually find super impl to call. Returns null if cannot find it.
619
+ */
620
+ function super_find(klass, callee, mid) {
621
+ var cur_method;
622
+
623
+ while (klass) {
624
+ if (klass.$method_table[mid]) {
625
+ if (klass.$method_table[mid] == callee) {
626
+ break;
627
+ }
628
+ }
629
+ klass = klass.$super;
630
+ }
631
+
632
+ if (!klass) { return null; }
633
+
634
+ klass = klass.$super;
635
+
636
+ while (klass) {
637
+ if (klass.$method_table[mid]) {
638
+ return klass.$method_table[mid];
639
+ }
640
+
641
+ klass = klass.$super;
642
+ }
643
+
644
+ return null;
645
+ };
646
+
647
+ /**
648
+ VM method to get a contant from the given base.
649
+
650
+ @global
651
+ */
652
+ rb_vm_cg = function(base, id) {
653
+ if (base.$flags & T_OBJECT) {
654
+ base = class_real(base.$klass);
655
+ }
656
+ return const_get(base, id);
657
+ };
658
+
659
+ /**
660
+ VM method to set a contant in base.
661
+
662
+ @global
663
+ */
664
+ rb_vm_cs = function(base, id, val) {
665
+ if (base.$flags & T_OBJECT) {
666
+ base = class_real(base.$klass);
667
+ }
668
+ return const_set(base, id, val);
669
+ };
670
+
671
+ /**
672
+ Get global by id
673
+ */
674
+ Vm.gg = function(id) {
675
+ return gvar_get(id);
676
+ };
677
+
678
+ /**
679
+ Set global by id
680
+ */
681
+ Vm.gs = function(id, value) {
682
+ return gvar_set(id, value);
683
+ };
684
+
685
+ /**
686
+ Getter method for getting the load path for opal.
687
+
688
+ @param {String} id The globals id being retrieved.
689
+ @return {Array} Load paths
690
+ */
691
+ function load_path_getter(id) {
692
+ return opal.loader.paths;
693
+ };
694
+
695
+ /**
696
+ Getter method to get all loaded features.
697
+
698
+ @param {String} id Feature global id
699
+ @return {Array} Loaded features
700
+ */
701
+ function loaded_feature_getter(id) {
702
+ return loaded_features;
703
+ };
704
+
705
+ /**
706
+ Main init method. This is called once this file has fully loaded. It setups
707
+ all the core objects and classes and required runtime features.
708
+ */
709
+ function init() {
710
+
711
+ var metaclass;
712
+
713
+ Vm.BasicObject = cBasicObject = boot_defrootclass('BasicObject');
714
+ Vm.Object = cObject = boot_defclass('Object', cBasicObject);
715
+ Vm.Module = cModule = boot_defclass('Module', cObject);
716
+ Vm.Class = cClass = boot_defclass('Class', cModule);
717
+
718
+ const_set(cObject, 'BasicObject', cBasicObject);
719
+
720
+ metaclass = make_metaclass(cBasicObject, cClass);
721
+ metaclass = make_metaclass(cObject, metaclass);
722
+ metaclass = make_metaclass(cModule, metaclass);
723
+ metaclass = make_metaclass(cClass, metaclass);
724
+
725
+ boot_defmetametaclass(cModule, metaclass);
726
+ boot_defmetametaclass(cObject, metaclass);
727
+ boot_defmetametaclass(cBasicObject, metaclass);
728
+
729
+ define_method(cBasicObject, "!", obj_not);
730
+ define_method(cBasicObject, "!=", obj_not_equal);
731
+
732
+ mKernel = define_module('Kernel');
733
+
734
+ include_module(cObject, mKernel);
735
+
736
+ define_method(cClass, "allocate", obj_alloc);
737
+ define_method(cClass, "new", class_new_instance);
738
+ define_method(cClass, "initialize", class_initialize);
739
+ define_singleton_method(cClass, "new", class_s_new);
740
+
741
+ define_method(mKernel, "puts", obj_puts);
742
+
743
+ Qself = obj_alloc(cObject);
744
+ Vm.top = Qself;
745
+
746
+ cNilClass = define_class('NilClass', cObject);
747
+ Vm.Qnil = Qnil = obj_alloc(cNilClass);
748
+ Qnil.$r = false;
749
+
750
+ cTrueClass = define_class('TrueClass', cObject);
751
+ Vm.Qtrue = Qtrue = obj_alloc(cTrueClass);
752
+
753
+ cFalseClass = define_class('FalseClass', cObject);
754
+ Vm.Qfalse = Qfalse = obj_alloc(cFalseClass);
755
+ Qfalse.$r = false;
756
+
757
+ cArray = bridge_class(Array.prototype,
758
+ T_OBJECT | T_ARRAY, 'Array', cObject);
759
+
760
+ Array.prototype.$hash = function() {
761
+ return (this.$id || (this.$id = yield_hash()));
762
+ };
763
+
764
+ cNumeric = bridge_class(Number.prototype,
765
+ T_OBJECT | T_NUMBER, 'Numeric', cObject);
766
+
767
+ cHash = bridge_class(RHash.prototype,
768
+ T_OBJECT | T_HASH, 'Hash', cObject);
769
+
770
+ RHash.prototype.$hash = function() {
771
+ return (this.$id || (this.$id = yield_hash()));
772
+ };
773
+
774
+ define_singleton_method(cHash, '[]', hash_s_create);
775
+
776
+ cRegexp = bridge_class(RegExp.prototype, T_OBJECT,
777
+ 'Regexp', cObject);
778
+
779
+ define_hooked_variable('$:', load_path_getter, gvar_readonly_setter);
780
+ define_hooked_variable('$LOAD_PATH', load_path_getter, gvar_readonly_setter);
781
+
782
+ const_set(cObject, 'ARGV', []);
783
+
784
+ eException = bridge_class(Error.prototype, T_OBJECT, 'Exception', cObject);
785
+
786
+ eStandardError = define_class("StandardError", eException);
787
+ eRuntimeError = define_class("RuntimeError", eException);
788
+ eLocalJumpError = define_class("LocalJumpError", eStandardError);
789
+ eTypeError = define_class("TypeError", eStandardError);
790
+ eNameError = define_class("NameError", eStandardError);
791
+ eNoMethodError = define_class('NoMethodError', eNameError);
792
+ eArgError = define_class('ArgumentError', eStandardError);
793
+ eScriptError = define_class('ScriptError', eException);
794
+ eLoadError = define_class('LoadError', eScriptError);
795
+
796
+ eIndexError = define_class("IndexError", eStandardError);
797
+ eKeyError = define_class("KeyError", eIndexError);
798
+ eRangeError = define_class("RangeError", eStandardError);
799
+
800
+ rb_vm_break_instance = new Error('unexpected break');
801
+ rb_vm_break_instance.$klass = eLocalJumpError;
802
+ rb_vm_break_instance.$keyword = 2;
803
+
804
+ rb_vm_return_instance = new Error('unexpected return');
805
+ rb_vm_return_instance.$klass = eLocalJumpError;
806
+ rb_vm_return_instance.$keyword = 1;
807
+
808
+ rb_vm_next_instance = new Error('unexpected next');
809
+ rb_vm_next_instance.$klass = eLocalJumpError;
810
+ rb_vm_next_instance.$keyword = 3;
811
+
812
+ cString = bridge_class(String.prototype,
813
+ T_OBJECT | T_STRING, 'String', cObject);
814
+
815
+ cSymbol = define_class('Symbol', cObject);
816
+
817
+ cProc = bridge_class(Function.prototype,
818
+ T_OBJECT | T_PROC, 'Proc', cObject);
819
+
820
+ Function.prototype.$hash = function() {
821
+ return (this.$id || (this.$id = yield_hash()));
822
+ };
823
+
824
+ cRange = bridge_class(RRange.prototype, T_OBJECT | T_RANGE,
825
+ 'Range', cObject);
826
+
827
+ RRange.prototype.$hash = function() {
828
+ return (this.$id || (this.$id = yield_hash()));
829
+ };
830
+
831
+ const_set(cObject, 'RUBY_PLATFORM', 'opal');
832
+ };
833
+
834
+ /**
835
+ Define a top level module with the given id
836
+ */
837
+ function define_module(id) {
838
+ return define_module_under(cObject, id);
839
+ };
840
+
841
+ function define_module_under(base, id) {
842
+ var module;
843
+
844
+ if (const_defined(base, id)) {
845
+ module = const_get(base, id);
846
+ if (module.$flags & T_MODULE) {
847
+ return module;
848
+ }
849
+
850
+ throw id + " is not a module.";
851
+ }
852
+
853
+ module = define_module_id(id);
854
+ const_set(base, id, module);
855
+ module.$parent = base;
856
+ return module;
857
+ };
858
+
859
+ function define_module_id(id) {
860
+ var module = define_class_id(id, cModule);
861
+ module.$flags = T_MODULE;
862
+ name_class(module, id);
863
+ return module;
864
+ };
865
+
866
+ function mod_create() {
867
+ return class_boot(cModule);
868
+ };
869
+
870
+ function include_module(klass, module) {
871
+
872
+ if (!klass.$included_modules) {
873
+ klass.$included_modules = [];
874
+ }
875
+
876
+ if (klass.$included_modules.indexOf(module) != -1) {
877
+ return;
878
+ }
879
+ klass.$included_modules.push(module);
880
+
881
+ if (!module.$included_in) {
882
+ module.$included_in = [];
883
+ }
884
+
885
+ module.$included_in.push(klass);
886
+
887
+ for (var method in module.$method_table) {
888
+ if (module.$method_table.hasOwnProperty(method)) {
889
+ define_method(klass, method, module.$method_table[method]);
890
+ }
891
+ }
892
+ };
893
+
894
+ Vm.include_module = include_module;
895
+
896
+ function extend_module(klass, module) {
897
+ if (!klass.$extended_modules) {
898
+ klass.$extended_modules = [];
899
+ }
900
+
901
+ if (klass.$extended_modules.indexOf(module) != -1) {
902
+ return;
903
+ }
904
+ klass.$extended_modules.push(module);
905
+
906
+ if (!module.$extended_in) {
907
+ module.$extended_in = [];
908
+ }
909
+
910
+ module.$extended_in.push(klass);
911
+
912
+ var meta = klass.$klass;
913
+
914
+ for (var method in module.$method_table) {
915
+ if (module.$method_table.hasOwnProperty(method)) {
916
+ define_method(meta, method, module.$method_table[method]);
917
+ }
918
+ }
919
+ };
920
+
921
+ Vm.extend_module = extend_module;
922
+
923
+ /**
924
+ Boot a base class (only used for very core object classes)
925
+ */
926
+ function boot_defclass(id, super_klass) {
927
+ var result = class_boot(super_klass);
928
+ name_class(result, id);
929
+ const_set((cObject || result), id, result);
930
+ return result;
931
+ };
932
+
933
+ /**
934
+ Like boot_defclass, but for root object only (i.e. basicobject)
935
+ */
936
+ function boot_defrootclass(id) {
937
+ var result = new RClass(null, null);
938
+ result.$flags = T_CLASS;
939
+ name_class(result, id);
940
+ const_set((cObject || result), id, result);
941
+ return result;
942
+ };
943
+
944
+ function class_boot(super_class) {
945
+ if (super_class) {
946
+ var ctor = function() {};
947
+ ctor.prototype = super_class.constructor.prototype;
948
+
949
+ var result = function() {
950
+ RClass.call(this, null, super_class);
951
+ return this;
952
+ };
953
+ result.prototype = new ctor();
954
+
955
+ var klass = new result();
956
+ klass.$klass = cClass;
957
+ return klass;
958
+ }
959
+ else {
960
+ var result = new RClass(null, null);
961
+ return result;
962
+ }
963
+ };
964
+
965
+ /**
966
+ @global
967
+ */
968
+ function class_real(klass) {
969
+ while (klass.$flags & FL_SINGLETON) { klass = klass.$super; }
970
+ return klass;
971
+ };
972
+
973
+ Vm.class_real = class_real;
974
+
975
+ /**
976
+ Name the class with the given id.
977
+ */
978
+ function name_class(klass, id) {
979
+ klass.__classid__ = id;
980
+ };
981
+
982
+ /**
983
+ Make metaclass for the given class
984
+ */
985
+ function make_metaclass(klass, super_class) {
986
+ if ((klass.$flags & T_CLASS) && (klass.$flags & FL_SINGLETON)) {
987
+ return make_metametaclass(klass);
988
+ }
989
+ else {
990
+ var meta = class_boot(super_class);
991
+ meta.$flags |= FL_SINGLETON;
992
+ klass.$klass = meta;
993
+ klass.$m = meta.$m_tbl;
994
+ meta.$c = klass.$c;
995
+ singleton_class_attached(meta, klass);
996
+
997
+ return meta;
998
+ }
999
+ };
1000
+
1001
+ function singleton_class_attached(klass, obj) {
1002
+ if (klass.$flags & FL_SINGLETON) {
1003
+ ivar_set(klass, '__attached__', obj);
1004
+ }
1005
+ };
1006
+
1007
+ function make_metametaclass(metaclass) {
1008
+ var metametaclass, super_of_metaclass;
1009
+
1010
+ if (metaclass.$klass == metaclass) {
1011
+ metametaclass = class_boot(null);
1012
+ metametaclass.$klass = metametaclass;
1013
+ }
1014
+ else {
1015
+ metametaclass = class_boot(null);
1016
+ metametaclass.$klass = metaclass.$klass.$klass == metaclass.$klass
1017
+ ? make_metametaclass(metaclass.$klass)
1018
+ : metaclass.$klass.$klass;
1019
+ }
1020
+
1021
+ metametaclass.$flags |= FL_SINGLETON;
1022
+
1023
+ singleton_class_attached(metametaclass, metaclass);
1024
+ metaclass.$klass = metametaclass;
1025
+ metaclass.$m = metametaclass.$m_tbl;
1026
+ super_of_metaclass = metaclass.$super;
1027
+
1028
+ metametaclass.$super = ivar_get(super_of_metaclass.$klass, '__attached__')
1029
+ == super_of_metaclass
1030
+ ? super_of_metaclass.$klass
1031
+ : make_metametaclass(super_of_metaclass);
1032
+
1033
+ return metametaclass;
1034
+ };
1035
+
1036
+ function boot_defmetametaclass(klass, metametaclass) {
1037
+ klass.$klass.$klass = metametaclass;
1038
+ };
1039
+
1040
+ /**
1041
+ Define toll free bridged class
1042
+ */
1043
+ function bridge_class(prototype, flags, id, super_class) {
1044
+ var klass = define_class(id, super_class);
1045
+
1046
+ prototype.$klass = klass;
1047
+ prototype.$m = klass.$m_tbl;
1048
+ prototype.$flags = flags;
1049
+ prototype.$r = true;
1050
+
1051
+ prototype.$hash = function() {
1052
+ return flags + '_' + this;
1053
+ };
1054
+
1055
+ return klass;
1056
+ };
1057
+
1058
+ /**
1059
+ Define a new class (normal way), with the given id and superclass. Will be
1060
+ top level.
1061
+ */
1062
+ function define_class(id, super_klass) {
1063
+ return define_class_under(cObject, id, super_klass);
1064
+ };
1065
+
1066
+ function define_class_under(base, id, super_klass) {
1067
+ var klass;
1068
+
1069
+ if (const_defined(base, id)) {
1070
+ return const_get(base, id);
1071
+ }
1072
+
1073
+ klass = define_class_id(id, super_klass);
1074
+
1075
+ name_class(klass, id);
1076
+ const_set(base, id, klass);
1077
+ klass.$parent = base;
1078
+ return klass;
1079
+ };
1080
+
1081
+ /**
1082
+ Actually create class
1083
+ */
1084
+ function define_class_id(id, super_klass) {
1085
+ var klass;
1086
+
1087
+ if (!super_klass) {
1088
+ super_klass = cObject;
1089
+ }
1090
+ klass = class_create(super_klass);
1091
+ name_class(klass, id);
1092
+ make_metaclass(klass, super_klass.$klass);
1093
+ return klass;
1094
+ };
1095
+
1096
+ function class_create(super_klass) {
1097
+ return class_boot(super_klass);
1098
+ };
1099
+
1100
+ /**
1101
+ Get singleton class of obj
1102
+ */
1103
+ function singleton_class(obj) {
1104
+ var obj;
1105
+
1106
+ if ((obj.$klass.$flags & FL_SINGLETON)&& ivar_get(obj.$klass, '__attached__') == obj) {
1107
+ klass = obj.$klass;
1108
+ }
1109
+ else {
1110
+ var class_id = obj.$klass.__classid__;
1111
+ klass = make_metaclass(obj, obj.$klass);
1112
+ }
1113
+
1114
+ return klass;
1115
+ };
1116
+
1117
+ function RHash(args) {
1118
+ var k, v;
1119
+ this.$keys = [];
1120
+ this.$assocs = {};
1121
+ this.$default = Qnil;
1122
+
1123
+ for (var i = 0; i < args.length; i++) {
1124
+ k = args[i];
1125
+ v = args[i+1];
1126
+ i++;
1127
+ this.$keys.push(k);
1128
+ this.$assocs[k.$hash()] = v;
1129
+ }
1130
+ return this;
1131
+ };
1132
+
1133
+ /**
1134
+ Symbol table. All symbols are stored here.
1135
+ */
1136
+ var symbol_table = { };
1137
+
1138
+ /**
1139
+ Range ruby object
1140
+ */
1141
+ function RRange(beg, end, exclude_end) {
1142
+ this.$beg = beg;
1143
+ this.$end = end;
1144
+ this.$exc = exclude_end;
1145
+ return this;
1146
+ };
1147
+
1148
+ /**
1149
+ Creates a new hash populated with the given objects. Equivalent to the
1150
+ literal `{ key => value, ... }`.
1151
+
1152
+ @example
1153
+ Hash["a", 100, "b", 200]
1154
+ # => {"a" =>100, "b"=>200}
1155
+
1156
+ @return [Hash]
1157
+ */
1158
+ function hash_s_create(obj, mid) {
1159
+ return opalhash.apply(null, Array.prototype.slice.call(arguments, 2));
1160
+ };
1161
+
1162
+ function class_s_new(cls, sup) {
1163
+ var klass = define_class_id("AnonClass", sup || cObject);
1164
+ return klass;
1165
+ };
1166
+
1167
+ function class_new_instance(cls) {
1168
+ var obj = cls.$m.allocate(cls);
1169
+ var args = Array.prototype.slice.call(arguments, 1);
1170
+ args.unshift(obj);
1171
+
1172
+ if (Vm.P.f == arguments.callee) {
1173
+ VM.P.f = obj.$m.initialize;
1174
+ }
1175
+
1176
+ obj.$m.initialize.apply(obj, args);
1177
+ return obj;
1178
+ };
1179
+
1180
+ function class_initialize(cla, mid, sup) {
1181
+ var klass = define_class_id('', sup || cObject);
1182
+ return klass;
1183
+ };
1184
+
1185
+ /**
1186
+ Prints each argument in turn to the browser console. Currently there is no
1187
+ use of `$stdout`, so it is hardcoded into this method to write to the
1188
+ console directly.
1189
+
1190
+ @param {Object} args objects to print using `inspect`
1191
+ @return {nil}
1192
+ */
1193
+ function obj_puts(obj) {
1194
+ var args = Array.prototype.slice.call(arguments, 1);
1195
+
1196
+ for (var i = 0; i < args.length; i++) {
1197
+ console.log((args[i].$m.to_s(args[i])).toString());
1198
+ }
1199
+
1200
+ return Qnil;
1201
+ };
1202
+
1203
+ /**
1204
+ @example
1205
+ !obj # => true or false
1206
+ */
1207
+ function obj_not(obj, mid) {
1208
+ return obj.$r ? Qfalse : Qtrue;
1209
+ };
1210
+
1211
+ /**
1212
+ @example
1213
+ obj != obj2 # => true or false
1214
+ */
1215
+ function obj_not_equal(obj1, mid, obj2) {
1216
+ var res = obj1.$m['=='](obj1, obj2);
1217
+ return res.$r ? Qfalse : Qtrue;
1218
+ };
1219
+
1220
+ // ..........................................................
1221
+ // FILESYSTEM
1222
+ //
1223
+
1224
+ // added to main opal namespace, and Fs for minimizing here.
1225
+ var Fs = Op.fs = {};
1226
+
1227
+ /**
1228
+ Regular expression used for splitting filenames into their dirname,
1229
+ basename and extension. This is unix style only, as filenames inside
1230
+ opal in the browser will only ever have this style of filename. The gem
1231
+ fs support will depend on the platform being run.
1232
+ **/
1233
+ var PATH_RE = /^(.+\/(?!$)|\/)?((?:.+?)?(\.[^.]*)?)$/;
1234
+
1235
+ /**
1236
+ Holds the current working directory for the application. This is '/' by
1237
+ default, but is usually set to the base directory of the main gem.
1238
+
1239
+ @type {String}
1240
+ */
1241
+ Fs.cwd = '/';
1242
+
1243
+ /**
1244
+ Join the given args using the default seperator. The path returned is not
1245
+ expanded.
1246
+
1247
+ @param {arguments<String<} args The arguments to join
1248
+ @return {String}
1249
+ */
1250
+ var file_join = Fs.join = function() {
1251
+ var parts = [].slice.call(arguments, 0);
1252
+ return parts.join('/');
1253
+ };
1254
+
1255
+ /**
1256
+ Normalize the path by removing '..' and '.' parts, remove '//' etc to
1257
+ return a nice normalized path.
1258
+
1259
+ @param {String} path The path needing normalization
1260
+ @param {String} base Optional base to normalize to
1261
+ @return {String} Normalized path
1262
+ */
1263
+ var file_expand_path = Fs.expand_path = function(path, base) {
1264
+ path = file_join(base || Fs.cwd, path);
1265
+
1266
+ var parts = path.split('/'), result = [], part;
1267
+
1268
+ // initial /
1269
+ if (parts[0] === '') result.push('');
1270
+
1271
+ for (var i = 0, ii = parts.length; i < ii; i++) {
1272
+ part = parts[i];
1273
+
1274
+ if (part == '..') {
1275
+ result.pop();
1276
+ }
1277
+ else if (part == '.' || part == '') {
1278
+
1279
+ }
1280
+ else {
1281
+ result.push(part);
1282
+ }
1283
+ }
1284
+
1285
+ return result.join('/');
1286
+ };
1287
+
1288
+ /**
1289
+ Returns all of the components of the given `file_name` except for the last
1290
+ one.
1291
+
1292
+ @param {String} file_name
1293
+ @return {String}
1294
+ */
1295
+ var file_dirname = Fs.dirname = function(file_name) {
1296
+ var dirname = PATH_RE.exec(file_name)[1];
1297
+
1298
+ if (!dirname) return '.';
1299
+ else if (dirname === '/') return dirname;
1300
+ else return dirname.substring(0, dirname.length - 1);
1301
+ };
1302
+
1303
+ /**
1304
+ Returns the file extension of the given `file_name`.
1305
+
1306
+ @param {String} file_name
1307
+ @return {String}
1308
+ */
1309
+ Fs.extname = function(file_name) {
1310
+ var extname = PATH_RE.exec(file_name)[3];
1311
+
1312
+ if (!extname || extname === '.') return '';
1313
+ else return extname;
1314
+ };
1315
+
1316
+
1317
+ // ..........................................................
1318
+ // LOADER
1319
+ //
1320
+
1321
+ /**
1322
+ Require a module.
1323
+
1324
+ @param {String} id The module id
1325
+ @return {Object} returns the exports
1326
+ */
1327
+ Op.require = function(id, parent) {
1328
+ var resolved = Op.loader.resolve_module(id, null);
1329
+ var cached = Op.cache[resolved];
1330
+
1331
+ if (cached) {
1332
+ return true;
1333
+ }
1334
+
1335
+ Op.cache[resolved] = true;
1336
+ // try/catch?
1337
+ load_file(Op.loader, resolved);
1338
+
1339
+ return true;
1340
+ };
1341
+
1342
+ // Virtual machine must also be able to require..
1343
+ Vm.require = Op.require;
1344
+
1345
+ /**
1346
+ Register a package with the given package info.
1347
+
1348
+ This will probably (definately??) always be done only in the browser.
1349
+
1350
+ @param {String} name The package name
1351
+ @param {Object} info The package info
1352
+ */
1353
+ Op.register = function(name, info) {
1354
+
1355
+ // make sure we get a string name
1356
+ if (typeof name !== 'string') {
1357
+ throw new Error("Cannot register a package without a proper name");
1358
+ }
1359
+
1360
+ // registering a single module/file
1361
+ if (typeof info === 'string' || typeof info === 'function') {
1362
+ register_module(name, info);
1363
+ }
1364
+ // make sure info is a proper package
1365
+ else if (typeof info === 'object') {
1366
+ register_package(name, info);
1367
+ }
1368
+ // else, we have an error.. we can only register packages or modules
1369
+ else {
1370
+ throw new Error("Invalid package.json data for '" + name + "'");
1371
+ }
1372
+ };
1373
+
1374
+ /**
1375
+ Private method to actually register the package. This is private to
1376
+ avoid external interferance. This will be called from {opal#register}.
1377
+
1378
+ @param {String} name The package name
1379
+ @param {Object} info The package information
1380
+ */
1381
+ var register_package = function(name, info) {
1382
+ var factories = Op.loader.factories,
1383
+ paths = Op.loader.paths;
1384
+
1385
+ // register all files
1386
+ var files = info.files || {};
1387
+
1388
+ // root dir for package is /package_name
1389
+ var root_dir = '/' + name;
1390
+
1391
+ // assume './lib' dir for lib files (for now.. should be dynamic)
1392
+ var lib_dir = './lib';
1393
+
1394
+ // add lib dir to paths
1395
+ paths.unshift(file_expand_path(file_join(root_dir, lib_dir)));
1396
+
1397
+ for (var file in files) {
1398
+ if (files.hasOwnProperty(file)) {
1399
+ // full path to file; we use the root dir
1400
+ var file_path = file_expand_path(file_join(root_dir, file));
1401
+
1402
+ factories[file_path] = files[file];
1403
+ }
1404
+ }
1405
+
1406
+ ////////////////////////////////////////
1407
+ // Autobooting. Basically, autoload opal.
1408
+ //
1409
+ if (name === 'opal') {
1410
+ Op.require(name);
1411
+ }
1412
+ };
1413
+
1414
+ /**
1415
+ Private method to register a single module. These modules are added to the
1416
+ very top level dir: /module_name.js
1417
+ */
1418
+ var register_module = function(name, factory) {
1419
+ // name gets preceeded with a '/' for root files
1420
+ var factory_name = '/' + name;
1421
+
1422
+ Op.loader.factories[factory_name] = factory;
1423
+ };
1424
+
1425
+
1426
+ // valid extensions for loading
1427
+ var load_extensions = {};
1428
+
1429
+ load_extensions['.js'] = function(loader, filename) {
1430
+ var source = loader.module_contents(filename);
1431
+ return execute_file(loader, source, filename);
1432
+ };
1433
+
1434
+ load_extensions['.rb'] = function(loader, filename) {
1435
+ var source = loader.ruby_module_contents(filename);
1436
+ return execute_file(loader, source, filename);
1437
+ };
1438
+
1439
+ /**
1440
+ The loader is the core machinery used for loading and executing modules
1441
+ within opal. An instance of opal will have a .loader property, which
1442
+ is an instance of this Loader class. A Loader is responsible for finding,
1443
+ opening and reading the contents of modules on disk. Within the browser,
1444
+ which is the default environment, a loader will use XHR requests or cached
1445
+ modules from JSON to load the required modules.
1446
+
1447
+ Within the browser, the loader, currently, just looks at its opal
1448
+ instance for registered files and packages and uses them as needed.
1449
+ opal also has 'built in' packages from commonjs, like 'system' etc, so
1450
+ all loaders must check opal first for registered packages.
1451
+
1452
+ @param {opal} opal The opal instance for this loader
1453
+ */
1454
+ var Loader = function(opal) {
1455
+ this.opal = opal;
1456
+ this.paths = [''];
1457
+
1458
+ this.factories = {};
1459
+
1460
+
1461
+ return this;
1462
+ };
1463
+
1464
+ // Loader prototype
1465
+ var Lp = Loader.prototype;
1466
+
1467
+ /**
1468
+ The paths property is an array of disk paths in which to search for
1469
+ required modules. In the browser this functionality isn't really used.
1470
+
1471
+ This array is created within the constructor method for uniqueness
1472
+ between instances for correct sandboxing.
1473
+ */
1474
+ Lp.paths = null;
1475
+
1476
+ /**
1477
+ factories of registered packages, paths => function/string. This is
1478
+ generic, but in reality only the browser uses this, and it is treated
1479
+ as the mini filesystem. Not just factories can go here, anything can!
1480
+ Images, text, json, whatever.
1481
+ */
1482
+ Lp.factories = {};
1483
+
1484
+ /**
1485
+ Valid factory format for use in require();
1486
+ */
1487
+ Lp.valid_extensions = ['.js', '.rb'];
1488
+
1489
+ /**
1490
+ Resolves the path to the module, which can then be used to load. This
1491
+ method will throw an error if the module cannot be found. If this method
1492
+ returns a successful filename, then subsequent methods like load_module
1493
+ should be successful and should not throw errors.
1494
+
1495
+ @param {String} id The id to look for
1496
+ @param {Module} parent The module that has requested the id
1497
+ */
1498
+ Lp.resolve_module = function(id, parent) {
1499
+ var resolved = this.find_module(id, this.paths);
1500
+
1501
+ if (!resolved) {
1502
+ throw new Error("Cannot find module '" + id + "'");
1503
+ }
1504
+
1505
+ return resolved;
1506
+ };
1507
+
1508
+ Lp.find_module = function(id, paths) {
1509
+ var extensions = this.valid_extensions, factories = this.factories, candidate;
1510
+
1511
+ for (var i = 0, ii = paths.length; i < ii; i++) {
1512
+ for (var j = 0, jj = extensions.length; j < jj; j++) {
1513
+ candidate = file_join(paths[i], id + extensions[j]);
1514
+
1515
+ console.log(candidate);
1516
+ if (factories[candidate]) {
1517
+ return candidate;
1518
+ }
1519
+ }
1520
+ }
1521
+
1522
+ return null;
1523
+ };
1524
+
1525
+ /**
1526
+ Module contents
1527
+ */
1528
+ Lp.module_contents = function(filename) {
1529
+ return this.factories[filename];
1530
+ };
1531
+
1532
+ /**
1533
+ Actually load the file with the given resolved filename. This filename has
1534
+ been checked, and is known to exist.
1535
+ */
1536
+ function load_file(loader, filename) {
1537
+ var extension = load_extensions[PATH_RE.exec(filename)[3] || '.js'];
1538
+
1539
+ if (!extension) {
1540
+ throw new Error("Loader.load - Bad extension for resolved path");
1541
+ }
1542
+
1543
+ extension(loader, filename);
1544
+ };
1545
+
1546
+ /**
1547
+ Run content, which by now must be javascript. If the content is a string,
1548
+ then it is simply evaluated. Within the browser it might be a function, so
1549
+ we call it, passing our standard args.
1550
+
1551
+ The arguments we pass are standardised as:
1552
+
1553
+ VM - Our opal vm variable which exposes runtime methods
1554
+ Qself - the top level ruby object, which is the 'self' for files
1555
+ filename - the Filename to run the file as for __FILE__
1556
+
1557
+ @param {String, Function} content The javascript content to be run.
1558
+ @param {String} filename Filename to run content as.
1559
+ */
1560
+ function execute_file(loader, content, filename) {
1561
+
1562
+ var args = [Vm, Qself, filename];
1563
+
1564
+ if (typeof content === 'function') {
1565
+ return content.apply(Op, args);
1566
+
1567
+ } else if (typeof content === 'string') {
1568
+ var func = loader.wrap(content, filename);
1569
+ return func.apply(Op, args);
1570
+
1571
+ } else {
1572
+ throw new Error(
1573
+ "Loader.execute - bad content sent for '" + filename + "'");
1574
+ }
1575
+ };
1576
+
1577
+ // ..........................................................
1578
+ // FINAL INITILIZATION
1579
+ //
1580
+
1581
+ // init ruby runtime
1582
+ init();
1583
+
1584
+ // browser based loader - overriden by v8 context
1585
+ Op.loader = new Loader(Op);
1586
+
1587
+ // cache of filenames already evaluated
1588
+ Op.cache = {};
1589
+
1590
+ })();
1591
+
1592
+ // if in a commonjs system already (node etc), exports become our opal
1593
+ // object. Otherwise, in the browser, we just get a top level opal var
1594
+ if ((typeof require !== 'undefined') && (typeof module !== 'undefined')) {
1595
+ module.exports = opal;
1596
+ }
1597
+