opal 1.0.1 → 1.1.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (406) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +14 -12
  3. data/.gitattributes +1 -1
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/workflows/build.yml +90 -0
  6. data/.jshintrc +1 -1
  7. data/.overcommit.yml +35 -0
  8. data/.rubocop.yml +44 -7
  9. data/{.rubocop_todo.yml → .rubocop/todo.yml} +4 -5
  10. data/CHANGELOG.md +129 -7
  11. data/Gemfile +2 -3
  12. data/HACKING.md +2 -9
  13. data/README.md +20 -17
  14. data/UNRELEASED.md +106 -7
  15. data/benchmark-ips/bm_array_pop_1.rb +8 -0
  16. data/benchmark-ips/bm_array_shift.rb +7 -0
  17. data/benchmark-ips/class_shovel_vs_singleton_class.rb +16 -0
  18. data/bin/build-browser-source-map-support +5 -0
  19. data/bin/format-filters +54 -0
  20. data/bin/git-submodule-fast-install +49 -0
  21. data/bin/remove-filters +39 -0
  22. data/bin/setup +4 -0
  23. data/bin/yarn +11 -0
  24. data/docs/releasing.md +18 -0
  25. data/docs/roda-sprockets.md +86 -0
  26. data/docs/sinatra.md +5 -12
  27. data/examples/rack/Gemfile +1 -0
  28. data/examples/rack/app/application.rb +3 -0
  29. data/examples/rack/config.ru +5 -4
  30. data/exe/opal-repl +2 -83
  31. data/lib/opal/ast/builder.rb +1 -1
  32. data/lib/opal/builder.rb +2 -10
  33. data/lib/opal/builder_processors.rb +1 -1
  34. data/lib/opal/cli.rb +4 -1
  35. data/lib/opal/cli_options.rb +11 -3
  36. data/lib/opal/cli_runners.rb +27 -37
  37. data/lib/opal/cli_runners/applescript.rb +5 -44
  38. data/lib/opal/cli_runners/chrome.js +7 -35
  39. data/lib/opal/cli_runners/chrome.rb +77 -19
  40. data/lib/opal/cli_runners/compiler.rb +17 -0
  41. data/lib/opal/cli_runners/nashorn.rb +9 -43
  42. data/lib/opal/cli_runners/nodejs.rb +18 -47
  43. data/lib/opal/cli_runners/server.rb +18 -6
  44. data/lib/opal/cli_runners/source-map-support-browser.js +6445 -0
  45. data/lib/opal/cli_runners/source-map-support.js +639 -0
  46. data/lib/opal/cli_runners/system_runner.rb +45 -0
  47. data/lib/opal/compiler.rb +57 -29
  48. data/lib/opal/config.rb +0 -5
  49. data/lib/opal/erb.rb +1 -1
  50. data/lib/opal/magic_comments.rb +34 -0
  51. data/lib/opal/nodes/args/arity_check.rb +2 -1
  52. data/lib/opal/nodes/base.rb +1 -1
  53. data/lib/opal/nodes/call.rb +1 -4
  54. data/lib/opal/nodes/def.rb +2 -0
  55. data/lib/opal/nodes/iter.rb +1 -1
  56. data/lib/opal/nodes/literal.rb +19 -14
  57. data/lib/opal/nodes/logic.rb +5 -80
  58. data/lib/opal/nodes/masgn.rb +2 -0
  59. data/lib/opal/nodes/rescue.rb +1 -1
  60. data/lib/opal/nodes/super.rb +24 -10
  61. data/lib/opal/nodes/top.rb +5 -4
  62. data/lib/opal/parser/patch.rb +15 -0
  63. data/lib/opal/parser/with_c_lexer.rb +2 -1
  64. data/lib/opal/parser/with_ruby_lexer.rb +1 -1
  65. data/lib/opal/path_reader.rb +2 -2
  66. data/lib/opal/paths.rb +8 -5
  67. data/lib/opal/repl.rb +103 -0
  68. data/lib/opal/rewriter.rb +4 -0
  69. data/lib/opal/rewriters/for_rewriter.rb +1 -1
  70. data/lib/opal/rewriters/js_reserved_words.rb +7 -7
  71. data/lib/opal/rewriters/numblocks.rb +31 -0
  72. data/lib/opal/rewriters/returnable_logic.rb +33 -0
  73. data/lib/opal/util.rb +11 -48
  74. data/lib/opal/version.rb +1 -1
  75. data/opal.gemspec +25 -25
  76. data/opal/corelib/array.rb +160 -118
  77. data/opal/corelib/array/pack.rb +5 -3
  78. data/opal/corelib/basic_object.rb +4 -4
  79. data/opal/corelib/class.rb +2 -1
  80. data/opal/corelib/comparable.rb +49 -31
  81. data/opal/corelib/constants.rb +5 -5
  82. data/opal/corelib/enumerable.rb +108 -46
  83. data/opal/corelib/enumerator.rb +27 -12
  84. data/opal/corelib/file.rb +3 -1
  85. data/opal/corelib/hash.rb +6 -1
  86. data/opal/corelib/helpers.rb +8 -28
  87. data/opal/corelib/io.rb +12 -7
  88. data/opal/corelib/kernel.rb +45 -14
  89. data/opal/corelib/kernel/format.rb +3 -1
  90. data/opal/corelib/math.rb +8 -6
  91. data/opal/corelib/method.rb +8 -0
  92. data/opal/corelib/module.rb +17 -2
  93. data/opal/corelib/number.rb +3 -12
  94. data/opal/corelib/proc.rb +16 -0
  95. data/opal/corelib/random/mersenne_twister.rb +147 -0
  96. data/opal/corelib/range.rb +3 -13
  97. data/opal/corelib/regexp.rb +10 -6
  98. data/opal/corelib/runtime.js +208 -81
  99. data/opal/corelib/string.rb +55 -49
  100. data/opal/corelib/string/encoding.rb +109 -32
  101. data/opal/corelib/string/unpack.rb +2 -17
  102. data/opal/corelib/struct.rb +14 -1
  103. data/opal/corelib/time.rb +4 -0
  104. data/opal/opal.rb +1 -1
  105. data/opal/opal/mini.rb +1 -1
  106. data/package.json +16 -0
  107. data/spec/README.md +10 -0
  108. data/spec/filters/bugs/array.rb +76 -0
  109. data/spec/filters/bugs/base64.rb +10 -0
  110. data/spec/filters/bugs/basicobject.rb +12 -0
  111. data/spec/filters/bugs/bigdecimal.rb +248 -0
  112. data/spec/filters/bugs/class.rb +12 -0
  113. data/spec/filters/bugs/complex.rb +7 -0
  114. data/spec/filters/bugs/date.rb +104 -0
  115. data/spec/filters/bugs/encoding.rb +259 -0
  116. data/spec/filters/bugs/enumerable.rb +26 -0
  117. data/spec/filters/bugs/enumerator.rb +48 -0
  118. data/spec/filters/bugs/exception.rb +120 -0
  119. data/spec/filters/bugs/file.rb +48 -0
  120. data/spec/filters/bugs/float.rb +74 -0
  121. data/spec/filters/bugs/hash.rb +60 -0
  122. data/spec/filters/bugs/integer.rb +78 -0
  123. data/spec/filters/bugs/io.rb +9 -0
  124. data/spec/filters/bugs/kernel.rb +401 -0
  125. data/spec/filters/bugs/language.rb +451 -0
  126. data/spec/filters/bugs/marshal.rb +50 -0
  127. data/spec/filters/bugs/math.rb +4 -0
  128. data/spec/filters/bugs/method.rb +79 -0
  129. data/spec/filters/bugs/module.rb +281 -0
  130. data/spec/filters/bugs/nilclass.rb +4 -0
  131. data/spec/filters/bugs/numeric.rb +27 -0
  132. data/spec/filters/bugs/openstruct.rb +8 -0
  133. data/spec/filters/bugs/pack_unpack.rb +138 -0
  134. data/spec/filters/bugs/pathname.rb +9 -0
  135. data/spec/filters/bugs/proc.rb +80 -0
  136. data/spec/filters/bugs/random.rb +20 -0
  137. data/spec/filters/bugs/range.rb +139 -0
  138. data/spec/filters/bugs/rational.rb +12 -0
  139. data/spec/filters/bugs/regexp.rb +91 -0
  140. data/spec/filters/bugs/set.rb +51 -0
  141. data/spec/filters/bugs/singleton.rb +7 -0
  142. data/spec/filters/bugs/string.rb +341 -0
  143. data/spec/filters/bugs/stringscanner.rb +78 -0
  144. data/spec/filters/bugs/struct.rb +26 -0
  145. data/spec/filters/bugs/symbol.rb +7 -0
  146. data/spec/filters/bugs/time.rb +109 -0
  147. data/spec/filters/bugs/unboundmethod.rb +33 -0
  148. data/spec/filters/bugs/warnings.rb +30 -0
  149. data/spec/filters/unsupported/array.rb +168 -0
  150. data/spec/filters/unsupported/basicobject.rb +15 -0
  151. data/spec/filters/unsupported/bignum.rb +55 -0
  152. data/spec/filters/unsupported/class.rb +5 -0
  153. data/spec/filters/unsupported/delegator.rb +6 -0
  154. data/spec/filters/unsupported/enumerable.rb +12 -0
  155. data/spec/filters/unsupported/enumerator.rb +14 -0
  156. data/spec/filters/unsupported/file.rb +4 -0
  157. data/spec/filters/unsupported/fixnum.rb +15 -0
  158. data/spec/filters/unsupported/float.rb +47 -0
  159. data/spec/filters/unsupported/freeze.rb +259 -0
  160. data/spec/filters/unsupported/hash.rb +44 -0
  161. data/spec/filters/unsupported/integer.rb +101 -0
  162. data/spec/filters/unsupported/kernel.rb +35 -0
  163. data/spec/filters/unsupported/language.rb +25 -0
  164. data/spec/filters/unsupported/marshal.rb +44 -0
  165. data/spec/filters/unsupported/matchdata.rb +63 -0
  166. data/spec/filters/unsupported/math.rb +4 -0
  167. data/spec/filters/unsupported/pathname.rb +4 -0
  168. data/spec/filters/unsupported/privacy.rb +287 -0
  169. data/spec/filters/unsupported/proc.rb +4 -0
  170. data/spec/filters/unsupported/random.rb +5 -0
  171. data/spec/filters/unsupported/range.rb +8 -0
  172. data/spec/filters/unsupported/regexp.rb +70 -0
  173. data/spec/filters/unsupported/set.rb +5 -0
  174. data/spec/filters/unsupported/singleton.rb +7 -0
  175. data/spec/filters/unsupported/string.rb +687 -0
  176. data/spec/filters/unsupported/struct.rb +7 -0
  177. data/spec/filters/unsupported/symbol.rb +21 -0
  178. data/spec/filters/unsupported/taint.rb +162 -0
  179. data/spec/filters/unsupported/thread.rb +10 -0
  180. data/spec/filters/unsupported/time.rb +204 -0
  181. data/spec/filters/unsupported/usage_of_files.rb +262 -0
  182. data/spec/lib/builder_processors_spec.rb +44 -0
  183. data/spec/lib/builder_spec.rb +133 -0
  184. data/spec/lib/cli_runners/server_spec.rb +25 -0
  185. data/spec/lib/cli_runners_spec.rb +16 -0
  186. data/spec/lib/cli_spec.rb +256 -0
  187. data/spec/lib/compiler_spec.rb +693 -0
  188. data/spec/lib/config_spec.rb +112 -0
  189. data/spec/lib/dependency_resolver_spec.rb +43 -0
  190. data/spec/lib/deprecations_spec.rb +17 -0
  191. data/spec/lib/fixtures/complex_sprockets.js.rb.erb +4 -0
  192. data/spec/lib/fixtures/file_with_directives.js +2 -0
  193. data/spec/lib/fixtures/jst_file.js.jst +1 -0
  194. data/spec/lib/fixtures/no_requires.rb +1 -0
  195. data/spec/lib/fixtures/opal_file.rb +2 -0
  196. data/spec/lib/fixtures/require_tree_test.rb +3 -0
  197. data/spec/lib/fixtures/required_file.js +1 -0
  198. data/spec/lib/fixtures/required_tree_test/required_file1.rb +1 -0
  199. data/spec/lib/fixtures/required_tree_test/required_file2.rb +1 -0
  200. data/spec/lib/fixtures/requires.rb +7 -0
  201. data/spec/lib/fixtures/source_location_test.rb +7 -0
  202. data/spec/lib/fixtures/source_map.rb +1 -0
  203. data/spec/lib/fixtures/source_map/subfolder/other_file.rb +1 -0
  204. data/spec/lib/fixtures/sprockets_file.js.rb +3 -0
  205. data/spec/lib/fixtures/sprockets_require_tree_test.rb +3 -0
  206. data/spec/lib/path_reader_spec.rb +47 -0
  207. data/spec/lib/paths_spec.rb +18 -0
  208. data/spec/lib/repl_spec.rb +28 -0
  209. data/spec/lib/rewriters/base_spec.rb +68 -0
  210. data/spec/lib/rewriters/binary_operator_assignment_spec.rb +153 -0
  211. data/spec/lib/rewriters/block_to_iter_spec.rb +28 -0
  212. data/spec/lib/rewriters/dot_js_syntax_spec.rb +108 -0
  213. data/spec/lib/rewriters/explicit_writer_return_spec.rb +186 -0
  214. data/spec/lib/rewriters/for_rewriter_spec.rb +92 -0
  215. data/spec/lib/rewriters/hashes/key_duplicates_rewriter_spec.rb +47 -0
  216. data/spec/lib/rewriters/js_reserved_words_spec.rb +119 -0
  217. data/spec/lib/rewriters/logical_operator_assignment_spec.rb +202 -0
  218. data/spec/lib/rewriters/opal_engine_check_spec.rb +84 -0
  219. data/spec/lib/rewriters/returnable_logic_spec.rb +52 -0
  220. data/spec/lib/rewriters/rubyspec/filters_rewriter_spec.rb +59 -0
  221. data/spec/lib/simple_server_spec.rb +56 -0
  222. data/spec/lib/source_map/file_spec.rb +67 -0
  223. data/spec/lib/source_map/index_spec.rb +80 -0
  224. data/spec/lib/spec_helper.rb +105 -0
  225. data/spec/mspec-opal/formatters.rb +197 -0
  226. data/spec/mspec-opal/runner.rb +172 -0
  227. data/spec/opal/compiler/irb_spec.rb +44 -0
  228. data/spec/opal/compiler/unicode_spec.rb +10 -0
  229. data/spec/opal/core/array/dup_spec.rb +23 -0
  230. data/spec/opal/core/array/intersection_spec.rb +38 -0
  231. data/spec/opal/core/array/minus_spec.rb +38 -0
  232. data/spec/opal/core/array/union_spec.rb +38 -0
  233. data/spec/opal/core/array/uniq_spec.rb +49 -0
  234. data/spec/opal/core/class/inherited_spec.rb +18 -0
  235. data/spec/opal/core/enumerable/all_break_spec.rb +5 -0
  236. data/spec/opal/core/enumerable/any_break_spec.rb +5 -0
  237. data/spec/opal/core/enumerable/collect_break_spec.rb +13 -0
  238. data/spec/opal/core/enumerable/count_break_spec.rb +5 -0
  239. data/spec/opal/core/enumerable/detect_break_spec.rb +5 -0
  240. data/spec/opal/core/enumerable/drop_while_break_spec.rb +5 -0
  241. data/spec/opal/core/enumerable/each_slice_break_spec.rb +6 -0
  242. data/spec/opal/core/enumerable/each_with_index_break_spec.rb +5 -0
  243. data/spec/opal/core/enumerable/each_with_object_break_spec.rb +5 -0
  244. data/spec/opal/core/enumerable/find_all_break_spec.rb +5 -0
  245. data/spec/opal/core/enumerable/find_index_break_spec.rb +5 -0
  246. data/spec/opal/core/enumerable/grep_break_spec.rb +5 -0
  247. data/spec/opal/core/enumerable/max_break_spec.rb +5 -0
  248. data/spec/opal/core/enumerable/max_by_break_spec.rb +5 -0
  249. data/spec/opal/core/enumerable/min_break_spec.rb +5 -0
  250. data/spec/opal/core/enumerable/min_by_break_spec.rb +5 -0
  251. data/spec/opal/core/enumerable/none_break_spec.rb +5 -0
  252. data/spec/opal/core/enumerable/one_break_spec.rb +5 -0
  253. data/spec/opal/core/enumerable/reduce_break_spec.rb +5 -0
  254. data/spec/opal/core/enumerable/take_while_break_spec.rb +5 -0
  255. data/spec/opal/core/enumerator/with_index_spec.rb +6 -0
  256. data/spec/opal/core/exception_spec.rb +8 -0
  257. data/spec/opal/core/fixtures/require_tree_files/file 1.rb +1 -0
  258. data/spec/opal/core/fixtures/require_tree_files/file 2.rb +1 -0
  259. data/spec/opal/core/fixtures/require_tree_files/file 3.rb +1 -0
  260. data/spec/opal/core/fixtures/require_tree_files/file 4.rb +1 -0
  261. data/spec/opal/core/fixtures/require_tree_files/file 5.rb +1 -0
  262. data/spec/opal/core/fixtures/require_tree_files/nested/nested 1.rb +1 -0
  263. data/spec/opal/core/fixtures/require_tree_files/nested/nested 2.rb +1 -0
  264. data/spec/opal/core/fixtures/require_tree_files/other/other 1.rb +1 -0
  265. data/spec/opal/core/fixtures/require_tree_with_dot/file 1.rb +1 -0
  266. data/spec/opal/core/fixtures/require_tree_with_dot/file 2.rb +1 -0
  267. data/spec/opal/core/fixtures/require_tree_with_dot/file 3.rb +1 -0
  268. data/spec/opal/core/fixtures/require_tree_with_dot/index.rb +3 -0
  269. data/spec/opal/core/hash/internals_spec.rb +339 -0
  270. data/spec/opal/core/helpers_spec.rb +14 -0
  271. data/spec/opal/core/iterable_props_spec.rb +53 -0
  272. data/spec/opal/core/kernel/at_exit_spec.rb +70 -0
  273. data/spec/opal/core/kernel/freeze_spec.rb +15 -0
  274. data/spec/opal/core/kernel/instance_variables_spec.rb +110 -0
  275. data/spec/opal/core/kernel/methods_spec.rb +25 -0
  276. data/spec/opal/core/kernel/public_methods_spec.rb +25 -0
  277. data/spec/opal/core/kernel/require_tree_spec.rb +18 -0
  278. data/spec/opal/core/kernel/respond_to_spec.rb +15 -0
  279. data/spec/opal/core/language/DATA/characters_support_spec.rb +9 -0
  280. data/spec/opal/core/language/DATA/empty___END___spec.rb +7 -0
  281. data/spec/opal/core/language/DATA/multiple___END___spec.rb +10 -0
  282. data/spec/opal/core/language/arguments/mlhs_arg_spec.rb +18 -0
  283. data/spec/opal/core/language/keyword_arguments_spec.rb +9 -0
  284. data/spec/opal/core/language/numblocks_spec.rb +16 -0
  285. data/spec/opal/core/language/safe_navigator_spec.rb +7 -0
  286. data/spec/opal/core/language/while_spec.rb +31 -0
  287. data/spec/opal/core/language_spec.rb +29 -0
  288. data/spec/opal/core/marshal/dump_spec.rb +81 -0
  289. data/spec/opal/core/marshal/load_spec.rb +13 -0
  290. data/spec/opal/core/module_spec.rb +27 -0
  291. data/spec/opal/core/object_id_spec.rb +56 -0
  292. data/spec/opal/core/regexp/interpolation_spec.rb +40 -0
  293. data/spec/opal/core/regexp/match_spec.rb +78 -0
  294. data/spec/opal/core/runtime/bridged_classes_spec.rb +123 -0
  295. data/spec/opal/core/runtime/constants_spec.rb +16 -0
  296. data/spec/opal/core/runtime/eval_spec.rb +5 -0
  297. data/spec/opal/core/runtime/exit_spec.rb +29 -0
  298. data/spec/opal/core/runtime/is_a_spec.rb +48 -0
  299. data/spec/opal/core/runtime/loaded_spec.rb +20 -0
  300. data/spec/opal/core/runtime/main_methods_spec.rb +39 -0
  301. data/spec/opal/core/runtime/method_missing_spec.rb +68 -0
  302. data/spec/opal/core/runtime/rescue_spec.rb +37 -0
  303. data/spec/opal/core/runtime/string_spec.rb +25 -0
  304. data/spec/opal/core/runtime/truthy_spec.rb +61 -0
  305. data/spec/opal/core/runtime_spec.rb +58 -0
  306. data/spec/opal/core/string/each_byte_spec.rb +19 -0
  307. data/spec/opal/core/string/gsub_spec.rb +35 -0
  308. data/spec/opal/core/string/to_sym_spec.rb +9 -0
  309. data/spec/opal/core/string_spec.rb +28 -0
  310. data/spec/opal/core/struct/dup_spec.rb +11 -0
  311. data/spec/opal/core/time_spec.rb +68 -0
  312. data/spec/opal/stdlib/erb/erb_spec.rb +30 -0
  313. data/spec/opal/stdlib/erb/inline_block.opalerb +3 -0
  314. data/spec/opal/stdlib/erb/quoted.opalerb +1 -0
  315. data/spec/opal/stdlib/erb/simple.opalerb +1 -0
  316. data/spec/opal/stdlib/js_spec.rb +72 -0
  317. data/spec/opal/stdlib/json/ext_spec.rb +55 -0
  318. data/spec/opal/stdlib/json/parse_spec.rb +37 -0
  319. data/spec/opal/stdlib/logger/logger_spec.rb +308 -0
  320. data/spec/opal/stdlib/native/alias_native_spec.rb +27 -0
  321. data/spec/opal/stdlib/native/array_spec.rb +11 -0
  322. data/spec/opal/stdlib/native/date_spec.rb +12 -0
  323. data/spec/opal/stdlib/native/deprecated_include_spec.rb +8 -0
  324. data/spec/opal/stdlib/native/each_spec.rb +13 -0
  325. data/spec/opal/stdlib/native/element_reference_spec.rb +16 -0
  326. data/spec/opal/stdlib/native/exposure_spec.rb +33 -0
  327. data/spec/opal/stdlib/native/ext_spec.rb +19 -0
  328. data/spec/opal/stdlib/native/hash_spec.rb +67 -0
  329. data/spec/opal/stdlib/native/initialize_spec.rb +17 -0
  330. data/spec/opal/stdlib/native/method_missing_spec.rb +51 -0
  331. data/spec/opal/stdlib/native/native_alias_spec.rb +26 -0
  332. data/spec/opal/stdlib/native/native_class_spec.rb +18 -0
  333. data/spec/opal/stdlib/native/native_module_spec.rb +13 -0
  334. data/spec/opal/stdlib/native/native_reader_spec.rb +22 -0
  335. data/spec/opal/stdlib/native/native_writer_spec.rb +30 -0
  336. data/spec/opal/stdlib/native/new_spec.rb +92 -0
  337. data/spec/opal/stdlib/native/struct_spec.rb +12 -0
  338. data/spec/opal/stdlib/pp_spec.rb +5 -0
  339. data/spec/opal/stdlib/promise/always_spec.rb +49 -0
  340. data/spec/opal/stdlib/promise/error_spec.rb +15 -0
  341. data/spec/opal/stdlib/promise/rescue_spec.rb +53 -0
  342. data/spec/opal/stdlib/promise/then_spec.rb +79 -0
  343. data/spec/opal/stdlib/promise/trace_spec.rb +51 -0
  344. data/spec/opal/stdlib/promise/value_spec.rb +15 -0
  345. data/spec/opal/stdlib/promise/when_spec.rb +34 -0
  346. data/spec/opal/stdlib/source_map_spec.rb +8 -0
  347. data/spec/opal/stdlib/strscan/scan_spec.rb +11 -0
  348. data/spec/opal/stdlib/template/paths_spec.rb +10 -0
  349. data/spec/opal/stdlib/thread/mutex_spec.rb +40 -0
  350. data/spec/opal/stdlib/thread/thread_queue_spec.rb +32 -0
  351. data/spec/opal/stdlib/thread/thread_spec.rb +60 -0
  352. data/spec/ruby_specs +183 -0
  353. data/spec/spec_helper.rb +31 -0
  354. data/spec/support/guard_platform.rb +4 -0
  355. data/spec/support/match_helpers.rb +57 -0
  356. data/spec/support/mspec_rspec_adapter.rb +33 -0
  357. data/spec/support/rewriters_helper.rb +54 -0
  358. data/spec/support/source_map_helper.rb +190 -0
  359. data/stdlib/base64.rb +2 -2
  360. data/stdlib/bigdecimal.rb +15 -3
  361. data/stdlib/bigdecimal/bignumber.js.rb +1 -1
  362. data/stdlib/bigdecimal/util.rb +148 -0
  363. data/stdlib/delegate.rb +8 -0
  364. data/stdlib/nodejs/fileutils.rb +1 -1
  365. data/stdlib/nodejs/kernel.rb +0 -13
  366. data/stdlib/nodejs/stacktrace.rb +4 -179
  367. data/stdlib/ostruct.rb +5 -0
  368. data/stdlib/pp.rb +586 -19
  369. data/stdlib/prettyprint.rb +556 -0
  370. data/stdlib/rbconfig/sizeof.rb +2 -0
  371. data/stdlib/securerandom.rb +32 -0
  372. data/stdlib/set.rb +36 -0
  373. data/stdlib/strscan.rb +15 -0
  374. data/tasks/benchmarking.rake +1 -1
  375. data/tasks/linting.rake +3 -5
  376. data/tasks/releasing.rake +2 -5
  377. data/tasks/testing.rake +16 -11
  378. data/tasks/testing/mspec_special_calls.rb +1 -19
  379. data/test/nodejs/fixtures/cat.png +0 -0
  380. data/test/nodejs/fixtures/hello.rb +1 -0
  381. data/test/nodejs/fixtures/iso88591.txt +1 -0
  382. data/test/nodejs/fixtures/utf8.txt +1 -0
  383. data/test/nodejs/fixtures/win1258.txt +1 -0
  384. data/test/nodejs/test_dir.rb +39 -0
  385. data/test/nodejs/test_env.rb +62 -0
  386. data/test/nodejs/test_error.rb +29 -0
  387. data/test/nodejs/test_file.rb +206 -0
  388. data/test/nodejs/test_file_encoding.rb +20 -0
  389. data/test/nodejs/test_io.rb +18 -0
  390. data/test/nodejs/test_opal_builder.rb +12 -0
  391. data/test/nodejs/test_pathname.rb +16 -0
  392. data/test/opal/cat.png +0 -0
  393. data/test/opal/http_server.rb +52 -0
  394. data/test/opal/test_base64.rb +115 -0
  395. data/test/opal/test_keyword.rb +590 -0
  396. data/test/opal/test_matrix.rb +661 -0
  397. data/test/opal/test_openuri.rb +53 -0
  398. data/test/opal/unsupported_and_bugs.rb +39 -0
  399. data/yarn.lock +1355 -0
  400. metadata +899 -36
  401. data/.travis.yml +0 -109
  402. data/appveyor.yml +0 -35
  403. data/lib/opal/nodes/runtime_helpers.rb +0 -51
  404. data/opal/corelib/random/MersenneTwister.js +0 -137
  405. data/opal/corelib/random/mersenne_twister.js.rb +0 -13
  406. data/stdlib/bigdecimal/kernel.rb +0 -5
@@ -0,0 +1,59 @@
1
+ require 'lib/spec_helper'
2
+ require 'opal/rewriters/rubyspec/filters_rewriter'
3
+ require 'support/rewriters_helper'
4
+
5
+ RSpec.describe Opal::Rubyspec::FiltersRewriter do
6
+ include RewritersHelper
7
+
8
+ let(:source) do
9
+ <<-SOURCE
10
+ describe 'User#email' do
11
+ context 'when this' do
12
+ it 'does that'
13
+
14
+ it 'and does that' do
15
+ 42
16
+ end
17
+ end
18
+
19
+ it 'also does something else'
20
+ end
21
+ SOURCE
22
+ end
23
+
24
+ let(:ast) { ast_of(source) }
25
+
26
+ context 'when spec is filtered' do
27
+ around(:each) do |e|
28
+ Opal::Rubyspec::FiltersRewriter.filter 'User#email when this does that'
29
+ Opal::Rubyspec::FiltersRewriter.filter 'User#email when this and does that'
30
+ e.run
31
+ Opal::Rubyspec::FiltersRewriter.clear_filters!
32
+ end
33
+
34
+ let(:rewritten_source) do
35
+ <<-SOURCE
36
+ describe 'User#email' do
37
+ context 'when this' do
38
+ nil # <- right here
39
+ nil # <- and here
40
+ end
41
+
42
+ it 'also does something else'
43
+ end
44
+ SOURCE
45
+ end
46
+
47
+ let(:expected_ast) { ast_of(rewritten_source) }
48
+
49
+ it 'replaces it with nil' do
50
+ expect_rewritten(ast).to eq(expected_ast)
51
+ end
52
+ end
53
+
54
+ context 'when spec is not filtered' do
55
+ it 'does not rewrite it' do
56
+ expect_no_rewriting_for(ast)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,56 @@
1
+ require 'lib/spec_helper'
2
+ require 'rack/test'
3
+
4
+ RSpec.describe Opal::SimpleServer do
5
+ include Rack::Test::Methods
6
+
7
+ attr_accessor :app
8
+
9
+ before do
10
+ Opal.append_path "#{__dir__}/fixtures"
11
+ self.app = described_class.new(main: 'console')
12
+ end
13
+
14
+ it 'serves opal assets' do
15
+ response = get '/assets/console.js'
16
+ expect(response.body).to start_with(Opal::Builder.build('console').to_s)
17
+ end
18
+
19
+ it 'serves index for all non opal paths' do
20
+ %w[/ /foo /foo/bar/baz].each do |path|
21
+ response = get path
22
+ expect(response.body).to include('<html>')
23
+ expect(response.body).to include('<script')
24
+ expect(response.body).to include('src="/assets/console.js')
25
+ expect(response.headers['Content-type']).to eq('text/html')
26
+ end
27
+ end
28
+
29
+ it 'serves the source map as data uri' do
30
+ response = get '/assets/console.js'
31
+ expect(response.body).to include("\n//# sourceMappingURL=data:application/json;base64,")
32
+ base64_map = response.body.split("\n//# sourceMappingURL=data:application/json;base64,").last
33
+ expect(Base64.decode64(base64_map)).to eq(Opal::Builder.build('console').source_map.to_json)
34
+ end
35
+
36
+ it 'takes a :prefix option to set the assets prefix' do
37
+ self.app = described_class.new(main: 'opal', prefix: 'foo')
38
+ expect(get('/foo/console.js').body).to start_with(Opal::Builder.build('console').to_s)
39
+ self.app = described_class.new(main: 'opal', prefix: '/foo')
40
+ expect(get('/foo/console.js').body).to start_with(Opal::Builder.build('console').to_s)
41
+ end
42
+
43
+ it 'takes a :main option to set the main asset' do
44
+ self.app = described_class.new(main: 'foo')
45
+ expect(get('/').body).to include('src="/assets/foo.js')
46
+ end
47
+
48
+ it 'respects config set in Opal::Config' do
49
+ Opal::Config.arity_check_enabled = false
50
+ expect(get('/assets/console.js').body).not_to include('$Console_clear$1.$$parameters = []')
51
+
52
+ Opal::Config.arity_check_enabled = true
53
+ self.app = described_class.new(main: 'console')
54
+ expect(get('/assets/console.js').body).to include('$Console_clear$1.$$parameters = []')
55
+ end
56
+ end
@@ -0,0 +1,67 @@
1
+ require 'support/source_map_helper'
2
+
3
+ RSpec.describe Opal::SourceMap::File do
4
+ include SourceMapHelper
5
+
6
+ specify '#as_json' do
7
+ map = described_class.new([fragment(code: "foo")], 'foo.rb', "foo")
8
+ expect(map.as_json).to be_a(Hash)
9
+ expect(map.as_json(ignored: :options)).to be_a(Hash)
10
+ end
11
+
12
+ it 'correctly map generated code to original positions' do
13
+ fragments = [
14
+ # It doesn't matter too much to keep these fragments updated in terms of generated code,
15
+ # as long as it works as real-world usage.
16
+ fragment(line: nil, column: nil, source_map_name: nil, code: "/* Generated by Opal 0.11.1.dev */", sexp_type: :top),
17
+ fragment(line: nil, column: nil, source_map_name: nil, code: "\n", sexp_type: :top),
18
+ fragment(line: nil, column: nil, source_map_name: nil, code: "(function(Opal) {", sexp_type: :top),
19
+ fragment(line: nil, column: nil, source_map_name: nil, code: "\n ", sexp_type: :top),
20
+ fragment(line: nil, column: nil, source_map_name: nil, code: "var self = Opal.top, $nesting = [], nil = Opal.nil, $$$ = Opal.$$$, $$ = Opal.$$, $breaker = Opal.breaker, $slice = Opal.slice;\n", sexp_type: :top),
21
+ fragment(line: nil, column: nil, source_map_name: nil, code: "\n ", sexp_type: :top),
22
+ fragment(line: nil, column: nil, source_map_name: nil, code: "Opal.add_stubs(['$puts']);", sexp_type: :top),
23
+ fragment(line: nil, column: nil, source_map_name: nil, code: "\n ", sexp_type: :top),
24
+ fragment(line: 1, column: 0, source_map_name: nil, code: "\n ", sexp_type: :begin),
25
+ fragment(line: nil, column: nil, source_map_name: "self", code: "self", sexp_type: :self),
26
+ fragment(line: 1, column: 0, source_map_name: :puts, code: ".$puts", sexp_type: :send),
27
+ fragment(line: 1, column: 0, source_map_name: :puts, code: "(", sexp_type: :send),
28
+ fragment(line: 1, column: 5, source_map_name: "5", code: "5", sexp_type: :int),
29
+ fragment(line: 1, column: 0, source_map_name: :puts, code: ")", sexp_type: :send),
30
+ fragment(line: 1, column: 0, source_map_name: nil, code: ";", sexp_type: :begin),
31
+ fragment(line: 1, column: 0, source_map_name: nil, code: "\n ", sexp_type: :begin),
32
+ fragment(line: 3, column: 0, source_map_name: nil, code: "return ", sexp_type: :js_return),
33
+ fragment(line: nil, column: nil, source_map_name: "self", code: "self", sexp_type: :self),
34
+ fragment(line: 3, column: 0, source_map_name: :puts, code: ".$puts", sexp_type: :send),
35
+ fragment(line: 3, column: 0, source_map_name: :puts, code: "(", sexp_type: :send),
36
+ fragment(line: 3, column: 5, source_map_name: "6", code: "6", sexp_type: :int),
37
+ fragment(line: 3, column: 0, source_map_name: :puts, code: ")", sexp_type: :send),
38
+ fragment(line: 1, column: 0, source_map_name: nil, code: ";", sexp_type: :begin),
39
+ fragment(line: nil, column: nil, source_map_name: nil, code: "\n", sexp_type: :top),
40
+ fragment(line: nil, column: nil, source_map_name: nil, code: "})(Opal);\n", sexp_type: :top),
41
+ fragment(line: nil, column: nil, source_map_name: nil, code: "\n", sexp_type: :newline),
42
+ ]
43
+
44
+ subject = described_class.new(fragments, 'foo.rb', "puts 5\n\nputs 6")
45
+ generated_code = subject.generated_code
46
+
47
+ expect(subject.map.merge(mappings: nil)).to eq(
48
+ version: 3,
49
+ sourceRoot: '',
50
+ sources: ['foo.rb'],
51
+ sourcesContent: ["puts 5\n\nputs 6"],
52
+ names: ['puts', '5', '6'],
53
+ mappings: nil,
54
+ )
55
+
56
+ expect('$puts(5)').to be_at_line_and_column(6, 7, source: generated_code)
57
+ expect('$puts(5)').to be_at_line_and_column(6, 7, source: generated_code)
58
+ expect('5' ).to be_at_line_and_column(6, 13, source: generated_code)
59
+ expect('$puts(6)').to be_at_line_and_column(7, 14, source: generated_code)
60
+ expect('6' ).to be_at_line_and_column(7, 20, source: generated_code)
61
+
62
+ expect('puts(5)').to be_mapped_to_line_and_column(0, 0, map: subject, source: generated_code, file: 'foo.rb')
63
+ expect('5);' ).to be_mapped_to_line_and_column(0, 5, map: subject, source: generated_code, file: 'foo.rb')
64
+ expect('puts(6)').to be_mapped_to_line_and_column(2, 0, map: subject, source: generated_code, file: 'foo.rb')
65
+ expect('6);' ).to be_mapped_to_line_and_column(2, 5, map: subject, source: generated_code, file: 'foo.rb')
66
+ end
67
+ end
@@ -0,0 +1,80 @@
1
+ require 'support/source_map_helper'
2
+
3
+ RSpec.describe Opal::SourceMap::Index do
4
+ include SourceMapHelper
5
+
6
+ specify '#as_json' do
7
+ builder = Opal::Builder.new
8
+ builder.build_str('foo', 'bar.rb')
9
+ map = builder.source_map
10
+ expect(map.as_json).to be_a(Hash)
11
+ expect(map.as_json(ignored: :options)).to be_a(Hash)
12
+ end
13
+
14
+ let(:builder) do
15
+ builder = Opal::Builder.new
16
+ builder.build_str(
17
+ " jsline1();\n"+
18
+ " jsline2();\n"+
19
+ " jsline3();",
20
+ 'js_file.js'
21
+ )
22
+ builder.build_str(
23
+ " rbline1\n"+
24
+ " rbline2\n"+
25
+ " rbline3",
26
+ 'rb_file.rb'
27
+ )
28
+ builder.build_str(
29
+ "\n"+
30
+ "\n"+
31
+ "\n"+
32
+ " jsline4();\n"+
33
+ " jsline5();\n"+
34
+ " jsline6();",
35
+ 'js2_file.js'
36
+ )
37
+ builder.build_str(
38
+ "\n"+
39
+ "\n"+
40
+ "\n"+
41
+ " rbline4\n"+
42
+ " rbline5\n"+
43
+ " rbline6",
44
+ 'rb2_file.rb'
45
+ )
46
+ builder
47
+ end
48
+
49
+ let(:compiled) { builder.to_s }
50
+ let(:source_map) { builder.source_map }
51
+ let(:mappings) { source_map.send(:mappings) }
52
+
53
+ it 'points to the correct source line' do
54
+ # To debug this stuff can be useful to print out all
55
+ # the sources with #inspect_source:
56
+ #
57
+ # p :compiled
58
+ # inspect_source compiled
59
+ #
60
+ # p :generated_code
61
+ # source_map.source_maps.each do |sub_source_map|
62
+ # p generated_code: sub_source_map.file
63
+ # inspect_source sub_source_map.generated_code
64
+ # end
65
+ #
66
+
67
+ expect('jsline1(').to be_mapped_to_line_and_column(0, 4, file: 'js_file.js', map: source_map, source: compiled)
68
+ expect('jsline2(').to be_mapped_to_line_and_column(1, 4, file: 'js_file.js', map: source_map, source: compiled)
69
+ expect('jsline3(').to be_mapped_to_line_and_column(2, 4, file: 'js_file.js', map: source_map, source: compiled)
70
+ expect('$rbline1(').to be_mapped_to_line_and_column(0, 2, file: 'rb_file.rb', map: source_map, source: compiled)
71
+ expect('$rbline2(').to be_mapped_to_line_and_column(1, 2, file: 'rb_file.rb', map: source_map, source: compiled)
72
+ expect('$rbline3(').to be_mapped_to_line_and_column(2, 2, file: 'rb_file.rb', map: source_map, source: compiled)
73
+ expect('jsline4(').to be_mapped_to_line_and_column(3, 4, file: 'js2_file.js', map: source_map, source: compiled)
74
+ expect('jsline5(').to be_mapped_to_line_and_column(4, 4, file: 'js2_file.js', map: source_map, source: compiled)
75
+ expect('jsline6(').to be_mapped_to_line_and_column(5, 4, file: 'js2_file.js', map: source_map, source: compiled)
76
+ expect('$rbline4(').to be_mapped_to_line_and_column(3, 2, file: 'rb2_file.rb', map: source_map, source: compiled)
77
+ expect('$rbline5(').to be_mapped_to_line_and_column(4, 2, file: 'rb2_file.rb', map: source_map, source: compiled)
78
+ expect('$rbline6(').to be_mapped_to_line_and_column(5, 2, file: 'rb2_file.rb', map: source_map, source: compiled)
79
+ end
80
+ end
@@ -0,0 +1,105 @@
1
+ $VERBOSE = true
2
+
3
+ if ENV['CHECK_COVERAGE']
4
+ require 'coveralls'
5
+ Coveralls.wear!
6
+ end
7
+
8
+ require 'opal'
9
+
10
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
11
+ RSpec.configure do |config|
12
+ config.before { Opal.reset_paths! unless RUBY_PLATFORM == 'opal' }
13
+ config.before { Opal::Config.reset! if defined? Opal::Config }
14
+ config.before { Opal::Processor.reset_cache_key! if defined? Opal::Processor }
15
+
16
+ # rspec-expectations config goes here. You can use an alternate
17
+ # assertion/expectation library such as wrong or the stdlib/minitest
18
+ # assertions if you prefer.
19
+ config.expect_with :rspec do |expectations|
20
+ # This option will default to `true` in RSpec 4. It makes the `description`
21
+ # and `failure_message` of custom matchers include text for helper methods
22
+ # defined using `chain`, e.g.:
23
+ # be_bigger_than(2).and_smaller_than(4).description
24
+ # # => "be bigger than 2 and smaller than 4"
25
+ # ...rather than:
26
+ # # => "be bigger than 2"
27
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
28
+
29
+ expectations.syntax = [:expect, :should]
30
+ end
31
+
32
+ # rspec-mocks config goes here. You can use an alternate test double
33
+ # library (such as bogus or mocha) by changing the `mock_with` option here.
34
+ config.mock_with :rspec do |mocks|
35
+ # Prevents you from mocking or stubbing a method that does not exist on
36
+ # a real object. This is generally recommended, and will default to
37
+ # `true` in RSpec 4.
38
+ mocks.verify_partial_doubles = true
39
+
40
+ mocks.syntax = [:expect, :should]
41
+ end
42
+
43
+ # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
44
+ # have no way to turn it off -- the option exists only for backwards
45
+ # compatibility in RSpec 3). It causes shared context metadata to be
46
+ # inherited by the metadata hash of host groups and examples, rather than
47
+ # triggering implicit auto-inclusion in groups with matching metadata.
48
+ config.shared_context_metadata_behavior = :apply_to_host_groups if config.respond_to? :shared_context_metadata_behavior
49
+
50
+ # This allows you to limit a spec run to individual examples or groups
51
+ # you care about by tagging them with `:focus` metadata. When nothing
52
+ # is tagged with `:focus`, all examples get run. RSpec also provides
53
+ # aliases for `it`, `||\describe`, and `context` that include `:focus`
54
+ # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
55
+ config.filter_run_when_matching :focus if config.respond_to? :filter_run_when_matching
56
+
57
+ # Allows RSpec to persist some state between runs in order to support
58
+ # the `--only-failures` and `--next-failure` CLI options. We recommend
59
+ # you configure your source control system to ignore this file.
60
+ config.example_status_persistence_file_path = "tmp/examples.txt" if config.respond_to? :example_status_persistence_file_path
61
+
62
+ # Limits the available syntax to the non-monkey patched syntax that is
63
+ # recommended. For more details, see:
64
+ # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
65
+ # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
66
+ # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
67
+ # config.disable_monkey_patching!
68
+
69
+ # This setting enables warnings. It's recommended, but in some cases may
70
+ # be too noisy due to issues in dependencies.
71
+ # config.warnings = true
72
+
73
+ # Many RSpec users commonly either run the entire suite or an individual
74
+ # file, and it's useful to allow more verbose output when running an
75
+ # individual spec file.
76
+ if config.files_to_run.one?
77
+ # Use the documentation formatter for detailed output,
78
+ # unless a formatter has already been configured
79
+ # (e.g. via a command-line flag).
80
+ config.default_formatter = 'doc'
81
+
82
+ # Show full backtrace
83
+ config.backtrace_exclusion_patterns = []
84
+ else
85
+ # The RSpec specs are stored in spec/lib.
86
+ config.pattern = 'spec/lib/**/*_spec.rb'
87
+ end
88
+
89
+ # Print the 10 slowest examples and example groups at the
90
+ # end of the spec run, to help surface which specs are running
91
+ # particularly slow.
92
+ config.profile_examples = 10
93
+
94
+ # Run specs in random order to surface order dependencies. If you find an
95
+ # order dependency and want to debug it, you can fix the order by providing
96
+ # the seed, which is printed after each run.
97
+ # --seed 1234
98
+ config.order = :random
99
+
100
+ # Seed global randomization in this process using the `--seed` CLI option.
101
+ # Setting this allows you to use `--seed` to deterministically reproduce
102
+ # test failures related to randomization by passing the same `--seed` value
103
+ # as the one that triggered the failure.
104
+ Kernel.srand config.seed
105
+ end
@@ -0,0 +1,197 @@
1
+ class BaseOpalFormatter
2
+ def initialize(out=nil)
3
+ @exception = @failure = false
4
+ @exceptions = []
5
+ @count = 0
6
+ @examples = 0
7
+
8
+ @current_state = nil
9
+ end
10
+
11
+ def register
12
+ MSpec.register :exception, self
13
+ MSpec.register :before, self
14
+ MSpec.register :after, self
15
+ MSpec.register :start, self
16
+ MSpec.register :finish, self
17
+ MSpec.register :abort, self
18
+ MSpec.register :enter, self
19
+ end
20
+
21
+ def red(str)
22
+ `console.error(str)`
23
+ end
24
+
25
+ def green(str)
26
+ `console.info(str)`
27
+ end
28
+
29
+ def cyan(str)
30
+ `console.info(str)`
31
+ end
32
+
33
+ def log(str)
34
+ `console.log(str)`
35
+ end
36
+
37
+ def exception?
38
+ @exception
39
+ end
40
+
41
+ def failure?
42
+ @failure
43
+ end
44
+
45
+ def enter(describe); end
46
+
47
+ def before(state=nil)
48
+ @current_state = nil
49
+ @failure = @exception = false
50
+ end
51
+
52
+ def exception(exception)
53
+ @count += 1
54
+ @failure = @exception ? @failure && exception.failure? : exception.failure?
55
+ @exception = true
56
+ @exceptions << exception
57
+ end
58
+
59
+ def after(state = nil)
60
+ @current_state = state
61
+ @examples += 1
62
+ end
63
+
64
+ def start
65
+ @start_time = Time.now.to_f
66
+ end
67
+
68
+ def finish
69
+ time = Time.now.to_f - @start_time
70
+
71
+ if @exceptions.empty?
72
+ log "\nFinished"
73
+ green "#{@examples} examples, #{@count} failures (time taken: #{time})\n"
74
+
75
+ finish_with_code 0
76
+ else
77
+ log "\nFailures:"
78
+
79
+ @exceptions.each_with_index do |exception, idx|
80
+ log "\n #{idx + 1}. #{exception.description}"
81
+ red "\n #{exception.message}"
82
+ log "\n #{`#{exception.exception}.stack`}\n"
83
+ end
84
+
85
+ log "\nFinished"
86
+ red "#{@examples} examples, #{@count} failures (time taken: #{time})"
87
+
88
+ log "\n\nFilters for failed examples:\n\n"
89
+ @exceptions.map do |exception|
90
+ ["#{exception.describe} #{exception.it}", exception.message.tr("\n", " ")]
91
+ end.sort.each do |(description, message)|
92
+ red "fails #{description.inspect}"
93
+ cyan " # #{message}\n"
94
+ end
95
+ log "\n"
96
+
97
+ finish_with_code(1)
98
+ end
99
+ end
100
+
101
+ def finish_with_code(code)
102
+ exit(code)
103
+ end
104
+ end
105
+
106
+ class BrowserFormatter < BaseOpalFormatter
107
+ def initialize(*args, &block)
108
+ $passed = 0
109
+ $failed = 0
110
+ $errored = 0
111
+ super
112
+ end
113
+
114
+ def print_example(state)
115
+ unless exception?
116
+ $passed += 1
117
+ else
118
+ if failure?
119
+ $failed += 1
120
+ else
121
+ $errored += 1
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ class NodeJSFormatter < BaseOpalFormatter
128
+ def red(str)
129
+ `process.stdout.write("\u001b[31m"+#{str}+"\u001b[0m")`
130
+ end
131
+
132
+ def green(str)
133
+ `process.stdout.write("\u001b[32m"+#{str}+"\u001b[0m")`
134
+ end
135
+
136
+ def cyan(str)
137
+ `process.stdout.write("\u001b[36m"+#{str}+"\u001b[0m")`
138
+ end
139
+
140
+ def log(str)
141
+ puts str
142
+ end
143
+
144
+ def after(state)
145
+ super
146
+ print_example(state)
147
+ end
148
+
149
+ def print_example(state)
150
+ unless exception?
151
+ green('.')
152
+ else
153
+ red(failure? ? 'F' : 'E')
154
+ end
155
+ end
156
+
157
+ def finish_with_code(code)
158
+ exit(code)
159
+ end
160
+ end
161
+
162
+ class NodeJSDocFormatter < NodeJSFormatter
163
+ def before(example)
164
+ print example.description
165
+ end
166
+
167
+ def print_example(state)
168
+ (@exception && state) ? red(" ✗\n") : green(" ✓\n")
169
+ end
170
+ end
171
+
172
+ module InvertedFormatter
173
+ def initialize(out=nil)
174
+ super
175
+ @actually_passing = []
176
+ end
177
+
178
+ def register
179
+ MSpec.register :before, self
180
+ MSpec.register :exception, self
181
+ MSpec.register :after, self
182
+ MSpec.register :finish, self
183
+ end
184
+
185
+ def after(state=nil)
186
+ super
187
+ @actually_passing << @current_state unless exception?
188
+ end
189
+
190
+ def finish
191
+ puts "\n\nExpected #{@actually_passing.size} examples to fail:\n"
192
+ @actually_passing.each_with_index do |example, idx|
193
+ puts " #{idx + 1}) #{example.description.inspect}"
194
+ end
195
+ puts "\n"
196
+ end
197
+ end