opal 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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,1470 @@
1
+ # Arrays are ordered, indexed by integers starting at 0
2
+ #
3
+ # Implementation details
4
+ # ======================
5
+ #
6
+ # For efficiency, an array instance is simply a native javascript array. There
7
+ # is no wrapping, it is simply a toll-free class
8
+ class Array
9
+ # Returns a new array populated with the given objects.
10
+ #
11
+ # @example
12
+ #
13
+ # Array['a', 'b', 'c']
14
+ # # => ['a', 'b', 'c']
15
+ #
16
+ # FIXME should support custom subclasses
17
+ #
18
+ # @param [Object] objs
19
+ # @return [Array]
20
+ def self.[](*objs)
21
+ objs
22
+ end
23
+
24
+ # FIXME should support custom subclasses
25
+ def self.allocate
26
+ []
27
+ end
28
+
29
+ def initialize(*objs)
30
+ `for (var i = 0, length = objs.length; i < length; i++) {
31
+ self.push(objs[i]);
32
+ }
33
+
34
+ return self;`
35
+ end
36
+
37
+ # Returns a formatted, printable version of the array. {#inspect} is called
38
+ # on each of the elements and appended to the string.
39
+ #
40
+ # @return [String] string representation of the receiver
41
+ def inspect
42
+ `var description = [];
43
+
44
+ for (var i = 0, length = self.length; i < length; i++) {
45
+ description.push(#{`self[i]`.inspect});
46
+ }
47
+
48
+ return '[' + description.join(', ') + ']';`
49
+ end
50
+
51
+ # Returns a simple string version of the array. {#to_s} is applied to each
52
+ # of the child elements with no seperator.
53
+ def to_s
54
+ `var description = [];
55
+
56
+ for (var i = 0, length = self.length; i < length; i++) {
57
+ description.push(#{`self[i]`.to_s});
58
+ }
59
+
60
+ return description.join('');`
61
+ end
62
+
63
+ # Append - pushes the given object onto the end of this array. This
64
+ # expression returns the array itself, so several appends may be chained
65
+ # together.
66
+ #
67
+ # @example
68
+ #
69
+ # [1, 2] << "c" << "d" << [3, 4]
70
+ # # => [1, 2, "c", "d", [3, 4]]
71
+ #
72
+ # @param [Object] obj the object to append
73
+ # @return [Array] returns the receiver
74
+ def <<(obj)
75
+ `self.push(obj);`
76
+ self
77
+ end
78
+
79
+ # Returns the number of elements in `self`. May be zero.
80
+ #
81
+ # @example
82
+ #
83
+ # [1, 2, 3, 4, 5].length
84
+ # # => 5
85
+ #
86
+ # @return [Numeric] length
87
+ def length
88
+ `return self.length;`
89
+ end
90
+
91
+ def size
92
+ `return self.length;`
93
+ end
94
+
95
+ # Yields the block once for each element in `self`, passing that element as
96
+ # a parameter.
97
+ #
98
+ # If no block is given, an enumerator is returned instead.
99
+ #
100
+ # @example
101
+ #
102
+ # a = ['a', 'b', 'c']
103
+ # a.each { |x| puts x }
104
+ # # => 'a'
105
+ # # => 'b'
106
+ # # => 'c'
107
+ #
108
+ # TODO: needs to return enumerator for no block.
109
+ #
110
+ # @return [Array] returns the receiver
111
+ def each
112
+ `for (var i = 0, length = self.length; i < length; i++) {
113
+ try {
114
+ #{yield `self[i]`};
115
+ } catch (e) {
116
+ switch (e.$keyword) {
117
+ case 2:
118
+ return e.$value;
119
+ default:
120
+ throw e;
121
+ }
122
+ }
123
+ }
124
+
125
+ return self;`
126
+ end
127
+
128
+ # Similar to {#each}, but also passes in the current element index to the
129
+ # block.
130
+ def each_with_index
131
+ `for (var i = 0, length = self.length; i < length; i++) {
132
+ try {
133
+ #{yield `self[i]`, `i`};
134
+ } catch (e) {
135
+ switch (e.$keyword) {
136
+ case 2:
137
+ return e.$value;
138
+ default:
139
+ throw e;
140
+ }
141
+ }
142
+ }
143
+
144
+ return self;`
145
+ end
146
+
147
+ # Same as {#each}, but passes the index of the element instead of the
148
+ # element itself.
149
+ #
150
+ # If no block given, an enumerator is returned instead.
151
+ #
152
+ # TODO: enumerator functionality not yet implemented.
153
+ #
154
+ # @example
155
+ #
156
+ # a = [1, 2, 3]
157
+ # a.each_index { |x| puts x }
158
+ # # => 0
159
+ # # => 1
160
+ # # => 2
161
+ #
162
+ # @return [Array] returns receiver
163
+ def each_index
164
+ `for (var i = 0, length = self.length; i < length; i++) {
165
+ try {
166
+ #{yield `i`};
167
+ } catch (e) {
168
+ switch (e.$keyword) {
169
+ case 2:
170
+ return e.$value;
171
+ default:
172
+ throw e;
173
+ }
174
+ }
175
+ }
176
+
177
+ return self;`
178
+ end
179
+
180
+ # Append - pushes the given object(s) onto the end of this array. This
181
+ # expression returns the array itself, so several appends may be chained
182
+ # together.
183
+ #
184
+ # @example
185
+ #
186
+ # a = ['a', 'b', 'c']
187
+ # a.push 'd', 'e', 'f'
188
+ # # => ['a', 'b', 'c', 'd', 'e', 'f'
189
+ #
190
+ # @param [Object] obj the object(s) to push onto the array
191
+ # @return [Array] returns the receiver
192
+ def push(*objs)
193
+ `for (var i = 0, length = objs.length; i < length; i++) {
194
+ self.push(objs[i]);
195
+ }
196
+
197
+ return self;`
198
+ end
199
+
200
+ # Returns the index of the first object in `self` such that it is `==` to
201
+ # `obj`. If a block is given instead of an argument, returns first object for
202
+ # which the block is true. Returns `nil` if no match is found. See also
203
+ # {#rindex}.
204
+ #
205
+ # @example
206
+ #
207
+ # a = ['a', 'b', 'c']
208
+ # a.index('a') # => 0
209
+ # a.index('z') # => nil
210
+ # a.index { |x| x == 'b' } # => 1
211
+ #
212
+ # @param [Object] obj the object to look for
213
+ # @return [Numeric, nil] result
214
+ def index(obj)
215
+ `for (var i = 0, length = self.length; i < length; i++) {
216
+ if (#{`self[i]` == obj}.$r) {
217
+ return i;
218
+ }
219
+ }
220
+
221
+ return nil;`
222
+ end
223
+
224
+ # Concatenation - returns a new array built by concatenating the two arrays
225
+ # together to produce a third array.
226
+ #
227
+ # @example
228
+ #
229
+ # [1, 2, 3] + [4, 5]
230
+ # # => [1, 2, 3, 4, 5]
231
+ #
232
+ # @param [Array] other the array to concat with
233
+ # @return [Array] returns new concatenated array
234
+ def +(other)
235
+ `return self.concat(other);`
236
+ end
237
+
238
+ # Difference. Creates a new array that is a copy of the original array,
239
+ # removing any items that also appear in `other`.
240
+ #
241
+ # @example
242
+ #
243
+ # [1, 2, 3, 3, 4, 4, 5] - [1, 2, 4]
244
+ # # => [3, 3, 5]
245
+ #
246
+ # @param [Array] other array to use for difference
247
+ # @return [Array] new array
248
+ def -(other)
249
+ raise "Array#- not yet implemented"
250
+ end
251
+
252
+ # Equality. Two arrays are equal if they contain the same number of elements
253
+ # and if each element is equal to (according to {Object#==} the corresponding
254
+ # element in the second array.
255
+ #
256
+ # @example
257
+ #
258
+ # ['a', 'c'] == ['a', 'c', 7] # => false
259
+ # ['a', 'c', '7'] == ['a', 'c', 7] # => true
260
+ # ['a', 'c', 7] == ['a', 'd', 'f'] # => false
261
+ #
262
+ # @param [Array] other array to compare self with
263
+ # @return [Boolean] if the arrays are equal
264
+ def ==(other)
265
+ `if (self.$hash() == other.$hash()) return Qtrue;
266
+ if (self.length != other.length) return Qfalse;
267
+
268
+ for (var i = 0; i < self.length; i++) {
269
+ if (!#{`self[i]` == `other[i]`}.$r) {
270
+ return Qfalse;
271
+ }
272
+ }
273
+
274
+ return Qtrue;`
275
+ end
276
+
277
+ # Searches through an array whose elements are also arrays, comparing `obj`
278
+ # with their first element of each contained array using {Object#==}. Returns
279
+ # the first contained array that matches (that is, the first associated array)
280
+ # or `nil` if no match is found. See also {#rassoc}.
281
+ #
282
+ # @example
283
+ #
284
+ # s1 = ['colors', 'red', 'blue', 'green']
285
+ # s2 = ['letters', 'a', 'b', 'c']
286
+ # s3 = 'foo'
287
+ # a = [s1, s2, s3]
288
+ #
289
+ # a.assoc 'letters' # => ['letters', 'a', 'b', 'c']
290
+ # a.assoc 'foo' # => nil
291
+ def assoc(obj)
292
+ `var arg;
293
+
294
+ for (var i = 0; i < self.length; i++) {
295
+ arg = self[i];
296
+
297
+ if (arg.length && #{`arg[0]` == obj}.$r) {
298
+ return arg;
299
+ }
300
+ }
301
+
302
+ return nil;`
303
+ end
304
+
305
+ # Returns the element at `index`. A negative index counts from the end of the
306
+ # receiver. Returns `nil` if the given index is out of range. See also {#[]}.
307
+ #
308
+ # @example
309
+ #
310
+ # a = ['a', 'b', 'c', 'd', 'e']
311
+ # a.at 0 # => 'a'
312
+ # a.at -1 # => 'e'
313
+ # a.at 324 # => nil
314
+ #
315
+ # @param [Numeric] index the index to get
316
+ # @return [Object, nil] returns nil or the result
317
+ def at(idx)
318
+ `if (idx < 0) idx += self.length;
319
+
320
+ if (idx < 0 || idx >= self.length) return nil;
321
+ return self[idx];`
322
+ end
323
+
324
+ # Removes all elements from the receiver.
325
+ #
326
+ # @example
327
+ #
328
+ # a = ['a', 'b', 'c', 'd', 'e']
329
+ # a.clear # => []
330
+ #
331
+ # @return [Array] returns the receiver
332
+ def clear
333
+ `self.splice(0);
334
+ return self;`
335
+ end
336
+
337
+ # Yields the block, passing in successive elements from the receiver,
338
+ # returning an array containing those elements for which the block returns a
339
+ # true value.
340
+ #
341
+ # @example
342
+ #
343
+ # a = [1, 2, 3, 4, 5, 6]
344
+ # a.select { |x| x > 4 }
345
+ # # => [5, 6]
346
+ #
347
+ # @return [Array] returns a new array of selected elements
348
+ def select
349
+ `var result = [], arg;
350
+
351
+ for (var i = 0; i < self.length; i++) {
352
+ try {
353
+ arg = self[i];
354
+ if (#{yield `arg`}.$r) {
355
+ result.push(arg);
356
+ }
357
+ } catch (e) {
358
+ switch (e.$keyword) {
359
+ case 2:
360
+ return e.$value;
361
+ default:
362
+ throw e;
363
+ }
364
+ }
365
+ }
366
+
367
+ return result;`
368
+ end
369
+
370
+ # Yields the block once for each element of the receiver. Creates a new array
371
+ # containing the values returned by the block. See also {Enumerable#collect}.
372
+ #
373
+ # @example
374
+ #
375
+ # a = ['a', 'b', 'c', 'd']
376
+ # a.collect { |x| x + '!' } # => ['a!', 'b!', 'c!', 'd!']
377
+ # a # => ['a', 'b', 'c', 'd']
378
+ #
379
+ # @return [Array] new array
380
+ def collect
381
+ `var result = [];
382
+
383
+ for (var i = 0; i < self.length; i++) {
384
+ try {
385
+ result.push(#{yield `self[i]`});
386
+ } catch (e) {
387
+ switch (e.$keyword) {
388
+ case 2:
389
+ return e.$value;
390
+ default:
391
+ throw e;
392
+ }
393
+ }
394
+ }
395
+
396
+ return result;`
397
+ end
398
+
399
+ # alias_method 'map', 'collect'
400
+
401
+ # Yields the block once for each element of `self`, replacing the element with
402
+ # the value returned by the block. See also {Enumerable#collect}.
403
+ #
404
+ # @example
405
+ #
406
+ # a = ['a', 'b', 'c', 'd']
407
+ # a.collect { |x| x + '!' }
408
+ # # => ['a!', 'b!', 'c!', 'd!']
409
+ # a
410
+ # # => ['a!', 'b!', 'c!', 'd!']
411
+ #
412
+ # @return [Array] returns the receiver
413
+ def collect!
414
+ `for (var i = 0; i < self.length; i++) {
415
+ try {
416
+ self[i] = #{yield `self[i]`};
417
+ } catch (e) {
418
+ switch (e.$keyword) {
419
+ case 2:
420
+ return e.$value;
421
+ default:
422
+ throw e;
423
+ }
424
+ }
425
+ }
426
+
427
+ return self;`
428
+ end
429
+
430
+ # Duplicate.
431
+ def dup
432
+ `return self.slice(0);`
433
+ end
434
+
435
+ # Returns a copy of the receiver with all nil elements removed
436
+ #
437
+ # @example
438
+ #
439
+ # ['a', nil, 'b', nil, 'c', nil].compact
440
+ # # => ['a', 'b', 'c']
441
+ #
442
+ # @return [Array] new Array
443
+ def compact
444
+ `var result = [], length = self.length;
445
+
446
+ for (var i = 0; i < length; i++) {
447
+ if (self[i] != nil) {
448
+ result.push(self[i]);
449
+ }
450
+ }
451
+
452
+ return result;`
453
+ end
454
+
455
+ # Removes nil elements from the receiver. Returns nil if no changes were made,
456
+ # otherwise returns self.
457
+ #
458
+ # @example
459
+ #
460
+ # ['a', nil, 'b', nil, 'c'].compact!
461
+ # # => ['a', 'b', 'c']
462
+ #
463
+ # ['a', 'b', 'c'].compact!
464
+ # # => nil
465
+ #
466
+ # @return [Array, nil] returns either the receiver or nil
467
+ def compact!
468
+ `var length = self.length;
469
+
470
+ for (var i = 0; i < length; i++) {
471
+ if (self[i] == nil) {
472
+ self.splice(i, 1);
473
+ i--;
474
+ }
475
+ }
476
+
477
+ return length == self.length ? nil : self;`
478
+ end
479
+
480
+ # Appends the elements of `other` to `self`.
481
+ #
482
+ # @example
483
+ #
484
+ # ['a', 'b'].concat ['c', 'd']
485
+ # # => ['a', 'b', 'c', 'd']
486
+ #
487
+ # @param [Array] other array to concat
488
+ # @return [Array] returns the receiver
489
+ def concat(other)
490
+ `var length = other.length;
491
+
492
+ for (var i = 0; i < length; i++) {
493
+ self.push(other[i]);
494
+ }
495
+
496
+ return self;`
497
+ end
498
+
499
+ # Returns the number of elements. If an argument is given, counts the number
500
+ # of elements which equals to `obj`. If a block is given, counts the number of
501
+ # elements yielding a true value.
502
+ #
503
+ # @example
504
+ #
505
+ # ary = [1, 2, 4, 2]
506
+ # ary.count # => 4
507
+ # ary.count(2) # =>2
508
+ #
509
+ # @param [Object] obj object to check
510
+ # @return [Numeric] count or count of obj
511
+ def count(obj)
512
+ `if (obj != undefined) {
513
+ var total = 0;
514
+
515
+ for (var i = 0; i < self.length; i++) {
516
+ if (#{`self[i]` == obj}.$r) {
517
+ total++;
518
+ }
519
+ }
520
+
521
+ return total;
522
+ } else {
523
+ return self.length;
524
+ }`
525
+ end
526
+
527
+ # Deletes items from `self` that are equal to `obj`. If any items are found,
528
+ # returns `obj`. If the item is not found, returns `nil`. If the optional code
529
+ # block is given, returns the result of block if the item is not found.
530
+ #
531
+ # @example
532
+ #
533
+ # a = ['a', 'b', 'b', 'b', 'c']
534
+ #
535
+ # a.delete 'b'
536
+ # # => 'b'
537
+ # a
538
+ # # => ['a', 'c']
539
+ #
540
+ # a.delete 'z'
541
+ # # => nil
542
+ #
543
+ # @param [Object] obj object to delete
544
+ # @return [Object, nil] returns obj or nil
545
+ def delete(obj)
546
+ `var length = self.length;
547
+
548
+ for (var i = 0; i < self.length; i++) {
549
+ if (#{`self[i]` == obj}.$r) {
550
+ self.splice(i, 1);
551
+ i--;
552
+ }
553
+ }
554
+
555
+ return length == self.length ? nil : obj;`
556
+ end
557
+
558
+ # Deletes the element at the specified index, returning that element, or nil
559
+ # if the index is out of range.
560
+ #
561
+ # @example
562
+ #
563
+ # a = ['ant', 'bat', 'cat', 'dog']
564
+ # a.delete_at 2
565
+ # # => 'cat'
566
+ # a
567
+ # # => ['ant', 'bat', 'dog']
568
+ # a.delete_at 99
569
+ # # => nil
570
+ #
571
+ # @param [Numeric] idx the index to delete
572
+ # @return [Object, nil] returns the deleted object or nil
573
+ def delete_at(idx)
574
+ `if (idx < 0) idx += self.length;
575
+ if (idx < 0 || idx >= self.length) return nil;
576
+ var res = self[idx];
577
+ self.splice(idx, 1);
578
+ return self;`
579
+ end
580
+
581
+ # Deletes every element of `self` for which `block` evaluates to true.
582
+ #
583
+ # @example
584
+ #
585
+ # a = [1, 2, 3]
586
+ # a.delete_if { |x| x >= 2 }
587
+ # # => [1]
588
+ #
589
+ # @return [Array] returns amended receiver
590
+ def delete_if
591
+ `for (var i = 0; i < self.length; i++) {
592
+ try {
593
+ if (#{yield `self[i]`}.$r) {
594
+ self.splice(i, 1);
595
+ i--;
596
+ }
597
+ } catch (e) {
598
+ switch(e.$keyword) {
599
+ case 2:
600
+ return e.$value;
601
+ default:
602
+ throw e;
603
+ }
604
+ }
605
+ }
606
+
607
+ return self;`
608
+ end
609
+
610
+ # Drop first `n` elements from receiver, and returns remaining elements in
611
+ # array.
612
+ #
613
+ # @example
614
+ #
615
+ # a = [1, 2, 3, 4, 5, 6]
616
+ # a.drop 3
617
+ # # => [4, 5, 6]
618
+ #
619
+ # @param [Number] n number of elements to drop
620
+ # @return [Array] returns new array
621
+ def drop(n)
622
+ `if (n > self.length) return [];
623
+ return self.slice(n);`
624
+ end
625
+
626
+ # Drop elements up to, but not including, the first element for which the
627
+ # block returns nil or false, and returns an array containing the remaining
628
+ # elements.
629
+ #
630
+ # @example
631
+ #
632
+ # a = [1, 2, 3, 4, 5, 6]
633
+ # a.drop_while { |i| i < 3 }
634
+ # # => [3, 4, 5, 6]
635
+ #
636
+ # @return [Array] returns a new array
637
+ def drop_while
638
+ `for (var i = 0; i < self.length; i++) {
639
+ if (!#{yield `self[i]`}.$r) {
640
+ return self.slice(i);
641
+ }
642
+ }
643
+
644
+ return [];`
645
+ end
646
+
647
+ # Returns `true` if the receiver contains no elements, `false` otherwise.
648
+ #
649
+ # @example
650
+ #
651
+ # [].empty?
652
+ # # => true
653
+ #
654
+ # @return [false, true] empty or not
655
+ def empty?
656
+ `return self.length == 0 ? Qtrue : Qfalse;`
657
+ end
658
+
659
+ # Tries to return the element as position `index`. If the index lies outside
660
+ # the array, the first form throws an IndexError exception, the second form
661
+ # returns `default`, and the third form returns the value of invoking the
662
+ # block, passing in the index. Negative values of `index` count from the end
663
+ # of the array.
664
+ #
665
+ # @example First form
666
+ #
667
+ # a = [11, 22, 33, 44]
668
+ # a.fetch 1
669
+ # # => 22
670
+ # a.fetch -1
671
+ # # => 44
672
+ #
673
+ # @example Second form
674
+ #
675
+ # a.fetch 4, 'cat'
676
+ # # => 'cat'
677
+ #
678
+ # @example Third form
679
+ #
680
+ # a.fetch 4 { |i| i * i }
681
+ # # => 16
682
+ #
683
+ # @param [Numeric] idx
684
+ # @param [Object] defaults
685
+ # @return [Object] returns result
686
+ def fetch(idx, defaults)
687
+ `var original = idx;
688
+
689
+ if (idx < 0) idx += self.length;
690
+ if (idx < 0 || idx >= self.length) {
691
+ if (defaults == undefined)
692
+ return rb_raise("Index Error: Array#fetch");
693
+ else if (__block__)
694
+ return #{yield `original`};
695
+ else
696
+ return defaults;
697
+ }
698
+
699
+ return self[idx];`
700
+ end
701
+
702
+ # Returns the first element, or the first `n` elements, of the array. If the
703
+ # array is empty, the first form returns `nil`, and the second form returns an
704
+ # empty array.
705
+ #
706
+ # @example
707
+ #
708
+ # a = ['q', 'r', 's', 't']
709
+ # a.first
710
+ # # => q
711
+ # a.first 2
712
+ # # => ['q', 'r']
713
+ #
714
+ # @param [Numeric] count number of elements
715
+ # @return [Object, Array] object or array of objects
716
+ def first(count = nil)
717
+ `if (count == nil) {
718
+ if (self.length == 0) return nil;
719
+ return self[0];
720
+ }
721
+ return self.slice(0, count);`
722
+ end
723
+
724
+ # Returns a new array that is a one-dimensional flattening of this array
725
+ # (recursively). That is, for evey element that is an array, extract its
726
+ # elements into the new array. If the optional `level` argument determines the
727
+ # level of recursion to flatten.
728
+ #
729
+ # @example
730
+ #
731
+ # s = [1, 2, 3]
732
+ # # => [a, 2, 3]
733
+ # t = [4, 5, 6, [7, 8]]
734
+ # # => [4, 5, 6, [7, 8]]
735
+ # a = [s, t, 9, 10]
736
+ # # => [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
737
+ # a.flatten
738
+ # # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
739
+ # a = [1, 2, [3, [4, 5]]]
740
+ # a.flatten 1
741
+ # # => [1, 2, 3, [4, 5]]
742
+ #
743
+ # @param [Numeric] level the level to flatten
744
+ # @return [Array] returns new array
745
+ def flatten(level = nil)
746
+ `var result = [], item;
747
+
748
+ for (var i = 0; i < self.length; i++) {
749
+ item = self[i];
750
+
751
+ if (item.hasOwnProperty('length')) {
752
+ if (level == nil)
753
+ result = result.concat(#{`item`.flatten});
754
+ else if (level == 0)
755
+ result.push(item);
756
+ else
757
+ result = result.concat(#{`item`.flatten `level - 1`});
758
+ } else {
759
+ result.push(item);
760
+ }
761
+ }
762
+
763
+ return result;`
764
+ end
765
+
766
+ # Flattens the receiver in place. Returns `nil` if no modifications were made.
767
+ # If the optional level argument determines the level of recursion to flatten.
768
+ #
769
+ # @example
770
+ #
771
+ # a = [1, 2, [3, [4, 5]]]
772
+ # a.flatten!
773
+ # # => [1, 2, 3, 4, 5]
774
+ # a.flatten!
775
+ # # => nil
776
+ # a
777
+ # # => [1, 2, 3, 4, 5]
778
+ #
779
+ # @param [Number] level to flatten to
780
+ # @return [Array] returns the receiver
781
+ def flatten!(level = nil)
782
+ `var length = self.length;
783
+ var result = #{self.flatten level};
784
+ self.splice(0);
785
+
786
+ for (var i = 0; i < result.length; i++) {
787
+ self.push(result[i]);
788
+ }
789
+
790
+ if (self.length == length)
791
+ return nil;
792
+
793
+ return self;`
794
+ end
795
+
796
+ # Returns true if the given object is present in `self`, false otherwise.
797
+ #
798
+ # @example
799
+ #
800
+ # a = ['a', 'b', 'c']
801
+ # a.include? 'b'
802
+ # # => true
803
+ # a.include? 'z'
804
+ # # => false
805
+ def include?(member)
806
+ `for (var i = 0; i < self.length; i++) {
807
+ if (#{`self[i]` == member}.$r) {
808
+ return #{true};
809
+ }
810
+ }
811
+
812
+ return #{false};`
813
+ end
814
+
815
+ # Replaces the contents of `self` with the contents of `other`, truncating or
816
+ # expanding if necessary.
817
+ #
818
+ # @example
819
+ #
820
+ # a = ['a', 'b', 'c', 'd', 'e']
821
+ # a.replace ['x', 'y', 'z']
822
+ # # => ['x', 'y', 'z']
823
+ # a
824
+ # # => ['x', 'y', 'z']
825
+ #
826
+ # @param [Array] other array to replace contents with
827
+ # @return [Array] returns the receiver
828
+ def replace(other)
829
+ `self.splice(0);
830
+
831
+ for (var i = 0; i < other.length; i++) {
832
+ self.push(other[i]);
833
+ }
834
+
835
+ return self;`
836
+ end
837
+
838
+ # Inserts the given values before the element with the given index (which may
839
+ # be negative).
840
+ #
841
+ # @example
842
+ #
843
+ # a = ['a', 'b', 'c', 'd']
844
+ # a.insert 2, 99
845
+ # # => ['a', 'b', 99, 'c', 'd']
846
+ # a.insert -2, 1, 2, 3
847
+ # # => ['a', 'b', 99, 'c', 1, 2, 3, 'd']
848
+ #
849
+ # @param [Numeric] idx the index for insertion
850
+ # @param [Object] objs objects to insert
851
+ # @return [Array] returns the receiver
852
+ def insert(idx, *objs)
853
+ `if (idx < 0) idx += self.length;
854
+
855
+ if (idx < 0 || idx >= self.length)
856
+ rb_raise("IndexError: out of range");
857
+
858
+ self.splice.apply(self, [idx, 0].concat(objs));
859
+ return self;`
860
+ end
861
+
862
+ # Returns a string created by converting each element of the array to a string
863
+ # seperated by `sep`.
864
+ #
865
+ # @example
866
+ #
867
+ # ['a', 'b', 'c'].join
868
+ # # => 'abc'
869
+ # ['a', 'b', 'c'].join '-'
870
+ # # => 'a-b-c'
871
+ #
872
+ # @param [String] sep the separator
873
+ # @return [String] joined string
874
+ def join(sep = '')
875
+ `var result = [];
876
+
877
+ for (var i = 0; i < self.length; i++) {
878
+ result.push(#{`self[i]`.to_s});
879
+ }
880
+
881
+ return result.join(sep);`
882
+ end
883
+
884
+ # Deletes every element of `self` for which the block evaluates to false.
885
+ #
886
+ # @example
887
+ #
888
+ # a = [1, 2, 3, 4, 5, 6]
889
+ # a.keep_if { |x| x < 4 }
890
+ # # => [1, 2, 3]
891
+ #
892
+ # @return [Array] returns the receiver
893
+ def keep_if
894
+ `for (var i = 0; i < self.length; i++) {
895
+ if (!#{yield `self[i]`}.$r) {
896
+ self.splice(i, 1);
897
+ i--;
898
+ }
899
+ }
900
+
901
+ return self;`
902
+ end
903
+
904
+ # Return the last element(s) of `self`. If the array is empty, the first form
905
+ # returns `nil`.
906
+ #
907
+ # @example
908
+ #
909
+ # a = ['w', 'x', 'y', 'z']
910
+ # a.last
911
+ # # => 'z'
912
+ # a.last 2
913
+ # # => ['y', 'z']
914
+ #
915
+ # @param [Number] count the number of items to get
916
+ # @return [Object, Array] result
917
+ def last(count = nil)
918
+ `if (count == nil) {
919
+ if (self.length == 0) return nil;
920
+ return self[self.length - 1];
921
+ } else {
922
+ if (count > self.length) count = self.length;
923
+ return self.slice(self.length - count, self.length);
924
+ }`
925
+ end
926
+
927
+ # Removes the last element from `self` and returns it, or `nil` if the array
928
+ # is empty. If a count is given, returns an array of the last `count`
929
+ # elements (or less).
930
+ #
931
+ # @example
932
+ #
933
+ # a = ['a', 'b', 'c', 'd']
934
+ # a.pop
935
+ # # => 'd'
936
+ # a.pop 2
937
+ # # => 'b', 'c'
938
+ # a
939
+ # # => ['a']
940
+ #
941
+ # @param [Numeric] count number to pop
942
+ # @return [Array] returns popped items
943
+ def pop(count = nil)
944
+ `if (count == nil) {
945
+ if (self.length) return self.pop();
946
+ return nil;
947
+ } else {
948
+ return self.splice(self.length - count, self.length);
949
+ }`
950
+ end
951
+
952
+ # Searches through the array whose elements are also arrays. Compares `obj`
953
+ # with the second element of each contained array using `==`. Returns the
954
+ # first contained array that matches.
955
+ #
956
+ # @example
957
+ #
958
+ # a = [[1, 'one'], [2, 'two'], [3, 'three'], ['ii', 'two']]
959
+ # a.rassoc 'two'
960
+ # # => [2, 'two']
961
+ # a.rassoc 'four'
962
+ # # => nil
963
+ #
964
+ # @param [Object] obj object to search for
965
+ # @return [Object, nil] result or nil
966
+ def rassoc(obj)
967
+ `var test;
968
+
969
+ for (var i = 0; i < self.length; i++) {
970
+ test = self[i];
971
+ if (test.hasOwnProperty('length') && test[1] != undefined) {
972
+ console.log("trying " + i);
973
+ if (#{`test[1]` == obj}.$r) return test;
974
+ }
975
+ }
976
+
977
+ return nil;`
978
+ end
979
+
980
+ # Returns a new array containing the items in `self` for which the block is
981
+ # not true. See also {#delete_if}.
982
+ #
983
+ # @example
984
+ #
985
+ # a = [1, 2, 3, 4, 5, 6]
986
+ # a.reject { |x| x > 3 }
987
+ # # => [1, 2, 3]
988
+ # a
989
+ # # => [1, 2, 3, 4, 5, 6]
990
+ #
991
+ # @return [Array] returns the receiver
992
+ def reject
993
+ `var result = [];
994
+
995
+ for (var i = 0; i < self.length; i++) {
996
+ if (!#{yield `self[i]`}.$r) {
997
+ result.push(self[i]);
998
+ }
999
+ }
1000
+
1001
+ return result;`
1002
+ end
1003
+
1004
+ # Equivalent to {#delete_if!}, deleting elements from self for which the block
1005
+ # evaluates to true, but returns nil if no changes were made.
1006
+ #
1007
+ # @example
1008
+ #
1009
+ # a = [1, 2, 3, 4, 5, 6]
1010
+ # a.reject! { |x| x > 3 }
1011
+ # # => [1, 2, 3]
1012
+ # a.reject! { |x| x > 3 }
1013
+ # # => nil
1014
+ # a
1015
+ # # => [1, 2, 3]
1016
+ #
1017
+ # @return [Array] returns receiver
1018
+ def reject!
1019
+ `var length = self.length;
1020
+
1021
+ for (var i = 0; i < self.length; i++) {
1022
+ if (#{yield `self[i]`}.$r) {
1023
+ self.splice(i, 1);
1024
+ i--;
1025
+ }
1026
+ }
1027
+
1028
+ return self.length == length ? nil : self;`
1029
+ end
1030
+
1031
+ # Returns a new array containing the receiver's elements in reverse order.
1032
+ #
1033
+ # @example
1034
+ #
1035
+ # ['a', 'b', 'c'].reverse
1036
+ # # => ['c', 'b', 'a']
1037
+ # [1].reverse
1038
+ # # => [1]
1039
+ #
1040
+ # @return [Array] return new array
1041
+ def reverse
1042
+ `var result = [];
1043
+
1044
+ for (var i = self.length - 1; i >= 0; i--) {
1045
+ result.push(self[i]);
1046
+ }
1047
+
1048
+ return result;`
1049
+ end
1050
+
1051
+ # Reverses the receiver in place.
1052
+ #
1053
+ # @example
1054
+ #
1055
+ # a = ['a', 'b', 'c']
1056
+ # a.reverse!
1057
+ # # => ['c', 'b', 'a']
1058
+ # a
1059
+ # # => ['c', 'b', 'a']
1060
+ #
1061
+ # @return [Array] returns the receiver
1062
+ def reverse!
1063
+ `var length = self.length / 2, tmp;
1064
+
1065
+ for (var i = 0; i < length; i++) {
1066
+ tmp = self[i];
1067
+ self[i] = self[self.length - (i + 1)];
1068
+ self[self.length - (i + 1)] = tmp;
1069
+ }
1070
+
1071
+ return self;`
1072
+ end
1073
+
1074
+ # Same as {#each}, but traverses the receiver in reverse order
1075
+ #
1076
+ # @example
1077
+ #
1078
+ # a = ['a', 'b', 'c']
1079
+ # a.reverse_each { |x| puts x }
1080
+ # # => 'c'
1081
+ # # => 'b'
1082
+ # # => 'a'
1083
+ #
1084
+ # @return [Array] returns the receiver
1085
+ def reverse_each
1086
+ `for (var i = self.length - 1; i >= 0; i--) {
1087
+ try {
1088
+ #{yield `self[i]`};
1089
+ } catch (e) {
1090
+ switch (e.$keyword) {
1091
+ case 2:
1092
+ return e['@exit_value'];
1093
+ default:
1094
+ throw e;
1095
+ }
1096
+ }
1097
+ }
1098
+
1099
+ return self;`
1100
+ end
1101
+
1102
+ # Returns the index of the last object in self that is == to object. If a
1103
+ # block is given instead of an argument, returns the first object for which
1104
+ # block is true, starting from the last object. Returns `nil` if no match is
1105
+ # found.
1106
+ #
1107
+ # @example
1108
+ #
1109
+ # a = ['a', 'b', 'b', 'b', 'c']
1110
+ # a.rindex 'b'
1111
+ # # => 3
1112
+ # a.rindex 'z'
1113
+ # # => nil
1114
+ # a.rindex { |x| x == 'b' }
1115
+ # # => 3
1116
+ #
1117
+ # @return [Object, nil] returns result or nil
1118
+ def rindex(obj = `undefined`)
1119
+ `if (obj != undefined) {
1120
+ for (var i = self.length - 1; i >=0; i--) {
1121
+ if (#{`self[i]` == obj}.$r) {
1122
+ return i;
1123
+ }
1124
+ }
1125
+ } else if (true || __block__) {
1126
+ rb_raise("array#rindex needs to do block action");
1127
+ }
1128
+
1129
+ return nil;`
1130
+ end
1131
+
1132
+ # Invokes the block passing in successive elements from `self`, deleting the
1133
+ # elements for which the block returns a false value. It returns `self` if
1134
+ # changes were made, otherwise it returns `nil`.
1135
+ #
1136
+ # @example
1137
+ #
1138
+ # a = [1, 2, 3, 4, 5, 6]
1139
+ # a.select! { |x| x > 4 }
1140
+ # # => [5, 6]
1141
+ # a.select! { |x| x > 4 }
1142
+ # # => nil
1143
+ # a
1144
+ # # => [5, 6]
1145
+ #
1146
+ # @return [Array] returns receiver
1147
+ def select!
1148
+ `var length = self.length;
1149
+
1150
+ for (var i = 0; i < self.length; i++) {
1151
+ if (!#{yield `self[i]`}.$r) {
1152
+ self.splice(i, 1);
1153
+ i--;
1154
+ }
1155
+ }
1156
+
1157
+ return self.length == length ? nil : self;`
1158
+ end
1159
+
1160
+ # Returns the first element of `self` and removes it (shifting all other
1161
+ # elements down by one). Returns `nil` if the array is empty.
1162
+ #
1163
+ # If a number `n` is given, returns an array of the first n elements (or
1164
+ # less), just like {#slice} does.
1165
+ #
1166
+ # @example
1167
+ #
1168
+ # a = ['a', 'b', 'c']
1169
+ # a.shift
1170
+ # # => 'a'
1171
+ # a
1172
+ # # => ['b', 'c']
1173
+ # a = ['a', 'b', 'c']
1174
+ # a.shift 2
1175
+ # # => ['a', 'b']
1176
+ # a
1177
+ # # => ['c']
1178
+ #
1179
+ # @param [Numeric] count elements to shift
1180
+ # @return [Array] result
1181
+ def shift(count = nil)
1182
+ `if (count != nil)
1183
+ return self.splice(0, count);
1184
+
1185
+ if (self.length)
1186
+ return self.shift();
1187
+
1188
+ return nil;`
1189
+ end
1190
+
1191
+ # Deletes the element(s) given by an `index` (optionally with a length) or
1192
+ # by a range. Returns the deleted object(s), or `nil` if the index is out of
1193
+ # range.
1194
+ #
1195
+ # @example
1196
+ #
1197
+ # a = ['a', 'b', 'c']
1198
+ # a.slice! 1
1199
+ # # => 'b'
1200
+ # a
1201
+ # # => ['a', 'c']
1202
+ # a.slice! -1
1203
+ # # => 'c'
1204
+ # a
1205
+ # # => ['a']
1206
+ # a.slice! 100
1207
+ # # => nil
1208
+ #
1209
+ # TODO does not yet work with ranges
1210
+ #
1211
+ # @param [Range, Number] index to begin with
1212
+ # @param [Number] length last index
1213
+ # @return [Array, nil] result
1214
+ def slice!(index, length = nil)
1215
+ `var size = self.length;
1216
+
1217
+ if (index < 0) index += size;
1218
+
1219
+ if (index >= size || index < 0) return nil;
1220
+
1221
+ if (length != nil) {
1222
+ if (length <= 0 || length > self.length) return nil;
1223
+ return self.splice(index, index + length);
1224
+ } else {
1225
+ return self.splice(index, 1)[0];
1226
+ }`
1227
+ end
1228
+
1229
+ # Returns first `count` elements from ary.
1230
+ #
1231
+ # @example
1232
+ #
1233
+ # a = [1, 2, 3, 4, 5, 6]
1234
+ # a.take 3
1235
+ # # => [1, 2, 3]
1236
+ #
1237
+ # @return [Array] array of elements
1238
+ def take(count)
1239
+ `return self.slice(0, count);`
1240
+ end
1241
+
1242
+
1243
+ # Passes elements to the block until the block returns a false value, then
1244
+ # stops iterating and returns an array of all prior elements.
1245
+ #
1246
+ # @example
1247
+ #
1248
+ # a = [1, 2, 3, 4, 5, 6]
1249
+ # a.take_while { |i| i < 3 }
1250
+ # # => [1, 2]
1251
+ #
1252
+ # @return [Array] new array with elements
1253
+ def take_while
1254
+ `var result = [];
1255
+
1256
+ for (var i = 0; i < self.length; i++) {
1257
+ try {
1258
+ if (#{yield `self[i]`}.$r) {
1259
+ result.push(self[i]);
1260
+ } else {
1261
+ break;
1262
+ }
1263
+ } catch (e) {
1264
+ switch (e.$keyword) {
1265
+ case 2:
1266
+ return e['@exit_value'];
1267
+
1268
+ default:
1269
+ throw e;
1270
+ }
1271
+ }
1272
+ }
1273
+
1274
+ return result;`
1275
+ end
1276
+
1277
+ # Returns the receiver.
1278
+ #
1279
+ # @example
1280
+ #
1281
+ # a = [1, 2, 3]
1282
+ # a.to_a
1283
+ # # => [1, 2, 3]
1284
+ #
1285
+ # @return [Array] returns the receiver
1286
+ def to_a
1287
+ self
1288
+ end
1289
+
1290
+ # Returns a new array by removing duplicate values in `self`.
1291
+ #
1292
+ # @example
1293
+ #
1294
+ # a = ['a', 'a', 'b', 'b', 'c']
1295
+ # a.uniq
1296
+ # # => ['a', 'b', 'c']
1297
+ # a
1298
+ # # => ['a', 'a', 'b', 'b', 'c']
1299
+ #
1300
+ # @return [Array]
1301
+ def uniq
1302
+ `var result = [], seen = [];
1303
+
1304
+ for (var i = 0; i < self.length; i++) {
1305
+ var test = self[i], hash = test.$hash();
1306
+ if (seen.indexOf(hash) == -1) {
1307
+ seen.push(hash);
1308
+ result.push(test);
1309
+ }
1310
+ }
1311
+
1312
+ return result;`
1313
+ end
1314
+
1315
+ # Removes duplicate elements from `self`. Returns `nil` if no changes are
1316
+ # made (that is, no duplicates are found).
1317
+ #
1318
+ # @example
1319
+ #
1320
+ # a = ['a', 'a', 'b', 'b', 'c']
1321
+ # a.uniq!
1322
+ # # => ['a', 'b', 'c']
1323
+ # a.uniq!
1324
+ # # => nil
1325
+ #
1326
+ # @return [Array] returns receiver
1327
+ def uniq!
1328
+ `var seen = [], length = self.length;
1329
+
1330
+ for (var i = 0; i < self.length; i++) {
1331
+ var test = self[i], hash = test.$hash();
1332
+ if (seen.indexOf(hash) == -1) {
1333
+ seen.push(hash);
1334
+ } else {
1335
+ self.splice(i, 1);
1336
+ i--;
1337
+ }
1338
+ }
1339
+
1340
+ return self.length == length ? nil : self;`
1341
+ end
1342
+
1343
+ # Prepends objects to the front of `self`, moving other elements upwards.
1344
+ #
1345
+ # @example
1346
+ #
1347
+ # a = ['b', 'c', 'd']
1348
+ # a.unshift 'a'
1349
+ # # => ['a', 'b', 'c', 'd']
1350
+ # a.unshift 1, 2
1351
+ # # => [1, 2, 'a', 'b', 'c', 'd']
1352
+ #
1353
+ # @param [Object] objs objects to add
1354
+ # @return [Array] returns the receiver
1355
+ def unshift(*objs)
1356
+ `for (var i = objs.length - 1; i >= 0; i--) {
1357
+ self.unshift(objs[i]);
1358
+ }
1359
+
1360
+ return self;`
1361
+ end
1362
+
1363
+ # Set intersection - Returns a new array containing elements common to the
1364
+ # two arrays, with no duplicates.
1365
+ #
1366
+ # @example
1367
+ #
1368
+ # [1, 1, 3, 5] & [1, 2, 3]
1369
+ # # => [1, 3]
1370
+ #
1371
+ # @param [Array] other second array to intersect
1372
+ # @return [Array] new intersected array
1373
+ def &(other)
1374
+ `var result = [], seen = [];
1375
+
1376
+ for (var i = 0; i < self.length; i++) {
1377
+ var test = self[i], hash = test.$hash();
1378
+
1379
+ if (seen.indexOf(hash) == -1) {
1380
+ for (var j = 0; j < other.length; j++) {
1381
+ var test_b = other[j], hash_b = test_b.$hash();
1382
+
1383
+ if ((hash == hash_b) && seen.indexOf(hash) == -1) {
1384
+ seen.push(hash);
1385
+ result.push(test);
1386
+ }
1387
+ }
1388
+ }
1389
+ }
1390
+
1391
+ return result;`
1392
+ end
1393
+
1394
+ # Repitition - When given a string argument, acts the same as {#join}.
1395
+ # Otherwise, returns a new array build by concatenating the `num` copies of
1396
+ # self.
1397
+ #
1398
+ # @example With Number
1399
+ #
1400
+ # [1, 2, 3] * 3
1401
+ # # => [1, 2, 3, 1, 2, 3, 1, 2, 3]
1402
+ #
1403
+ # @example With String
1404
+ #
1405
+ # [1, 2, 3] * ','
1406
+ # # => '1,2,3'
1407
+ #
1408
+ # @param [String, Number] num string or number used to join or concat
1409
+ # @return [String, Array] depending on argument
1410
+ def *(arg)
1411
+ `if (typeof arg == 'string') {
1412
+ return #{self.join `arg`};
1413
+ } else {
1414
+ var result = [];
1415
+ for (var i = 0; i < parseInt(arg); i++) {
1416
+ result = result.concat(self);
1417
+ }
1418
+
1419
+ return result;
1420
+ }`
1421
+ end
1422
+
1423
+ # Element Reference - Returns the element at `index`, or returns a subarray
1424
+ # at index and counting for length elements, or returns a subarray if index
1425
+ # is a range. Negative indecies count backward from the end of the array (-1
1426
+ # is the last element). Returns `nil` if the index (or starting index) are
1427
+ # out of range.
1428
+ #
1429
+ # @example
1430
+ #
1431
+ # a = ['a', 'b', 'c', 'd', 'e']
1432
+ # a[2] + a[0] + a[1] # => 'cab'
1433
+ # a[6] # => nil
1434
+ # a[1, 2] # => ['b', 'c']
1435
+ # a[1..3] # => ['b', 'c', 'd']
1436
+ # a[4..7] # => ['e']
1437
+ # a[6..10] # => nil
1438
+ # a[-3, 3] # => ['c', 'd', 'e']
1439
+ # a[5] # => nil
1440
+ # a[5, 1] # => []
1441
+ # a[5..10] # => []
1442
+ #
1443
+ # @TODO: does not yet work with ranges
1444
+ #
1445
+ # @param [Range, Numeric] index to begin
1446
+ # @param [Numeric] length last index
1447
+ # @return [Array, Object, nil] result
1448
+ def [](index, length = `undefined`)
1449
+ `var size = self.length;
1450
+
1451
+ if (index < 0) index += size;
1452
+
1453
+ if (index >= size || index < 0) return nil;
1454
+
1455
+ if (length != undefined) {
1456
+ if (length <= 0) return [];
1457
+ return self.slice(index, index + length);
1458
+ } else {
1459
+ return self[index];
1460
+ }`
1461
+ end
1462
+
1463
+ # Element reference setting.
1464
+ #
1465
+ # @TODO: need to expand functionlaity.
1466
+ def []=(index, value)
1467
+ `return self[index] = value;`
1468
+ end
1469
+ end
1470
+