opal 0.8.1 → 0.9.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (331) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -2
  3. data/.gitmodules +3 -3
  4. data/.jshintrc +17 -20
  5. data/.travis.yml +22 -11
  6. data/CHANGELOG.md +51 -1
  7. data/CODE_OF_CONDUCT.md +15 -0
  8. data/CONTRIBUTING.md +125 -9
  9. data/Gemfile +1 -1
  10. data/Guardfile +2 -2
  11. data/README.md +95 -29
  12. data/Rakefile +1 -1
  13. data/benchmark/benchmarks +103 -0
  14. data/benchmark/bm_array_flatten.rb +9 -0
  15. data/benchmark/bm_array_intersection_numbers.rb +7 -0
  16. data/benchmark/bm_array_intersection_objects.rb +7 -0
  17. data/benchmark/bm_array_intersection_strings.rb +7 -0
  18. data/benchmark/bm_array_join_ary.rb +9 -0
  19. data/benchmark/bm_array_minus_numbers.rb +7 -0
  20. data/benchmark/bm_array_minus_objects.rb +7 -0
  21. data/benchmark/bm_array_minus_strings.rb +7 -0
  22. data/benchmark/bm_array_union_numbers.rb +7 -0
  23. data/benchmark/bm_array_union_objects.rb +7 -0
  24. data/benchmark/bm_array_union_strings.rb +7 -0
  25. data/benchmark/bm_array_uniq_bang_numbers.rb +5 -0
  26. data/benchmark/bm_array_uniq_bang_objects.rb +5 -0
  27. data/benchmark/bm_array_uniq_bang_strings.rb +5 -0
  28. data/benchmark/bm_array_uniq_numbers.rb +5 -0
  29. data/benchmark/bm_array_uniq_objects.rb +5 -0
  30. data/benchmark/bm_array_uniq_strings.rb +5 -0
  31. data/benchmark/bm_dispatch_bind_table.rb +57 -0
  32. data/benchmark/bm_dispatch_code_gen.rb +65 -0
  33. data/benchmark/bm_dispatch_code_gen_if.rb +64 -0
  34. data/benchmark/bm_dispatch_hardcoded.rb +44 -0
  35. data/benchmark/bm_dispatch_send.rb +38 -0
  36. data/benchmark/bm_dispatch_send_table.rb +57 -0
  37. data/benchmark/bm_hash_assoc_object.rb +11 -0
  38. data/benchmark/bm_hash_assoc_string.rb +9 -0
  39. data/benchmark/bm_hash_clone_object.rb +9 -0
  40. data/benchmark/bm_hash_clone_string.rb +9 -0
  41. data/benchmark/bm_hash_delete_object.rb +11 -0
  42. data/benchmark/bm_hash_delete_string.rb +9 -0
  43. data/benchmark/bm_hash_each_key_object.rb +9 -0
  44. data/benchmark/bm_hash_each_key_string.rb +9 -0
  45. data/benchmark/bm_hash_each_object.rb +9 -0
  46. data/benchmark/bm_hash_each_string.rb +9 -0
  47. data/benchmark/bm_hash_each_value_object.rb +9 -0
  48. data/benchmark/bm_hash_each_value_string.rb +9 -0
  49. data/benchmark/bm_hash_element_reference_object.rb +11 -0
  50. data/benchmark/bm_hash_element_reference_string.rb +9 -0
  51. data/benchmark/bm_hash_element_set_object.rb +5 -0
  52. data/benchmark/bm_hash_element_set_string.rb +5 -0
  53. data/benchmark/bm_hash_equal_value_object.rb +14 -0
  54. data/benchmark/bm_hash_equal_value_string.rb +11 -0
  55. data/benchmark/bm_hash_fetch_object.rb +11 -0
  56. data/benchmark/bm_hash_fetch_string.rb +9 -0
  57. data/benchmark/bm_hash_flatten_object.rb +9 -0
  58. data/benchmark/bm_hash_flatten_string.rb +9 -0
  59. data/benchmark/bm_hash_has_key_object.rb +11 -0
  60. data/benchmark/bm_hash_has_key_string.rb +9 -0
  61. data/benchmark/bm_hash_has_value_object.rb +9 -0
  62. data/benchmark/bm_hash_has_value_string.rb +9 -0
  63. data/benchmark/bm_hash_hash_object.rb +9 -0
  64. data/benchmark/bm_hash_hash_string.rb +9 -0
  65. data/benchmark/bm_hash_inspect_object.rb +9 -0
  66. data/benchmark/bm_hash_inspect_string.rb +9 -0
  67. data/benchmark/bm_hash_invert_object.rb +9 -0
  68. data/benchmark/bm_hash_invert_string.rb +9 -0
  69. data/benchmark/bm_hash_keep_if_object.rb +9 -0
  70. data/benchmark/bm_hash_keep_if_string.rb +9 -0
  71. data/benchmark/bm_hash_key_object.rb +9 -0
  72. data/benchmark/bm_hash_key_string.rb +9 -0
  73. data/benchmark/bm_hash_keys_object.rb +9 -0
  74. data/benchmark/bm_hash_keys_string.rb +9 -0
  75. data/benchmark/bm_hash_literal_mixed_large.rb +3 -0
  76. data/benchmark/bm_hash_literal_mixed_small.rb +3 -0
  77. data/benchmark/bm_hash_literal_object_large.rb +4 -0
  78. data/benchmark/bm_hash_literal_object_small.rb +3 -0
  79. data/benchmark/bm_hash_literal_string_large.rb +4 -0
  80. data/benchmark/bm_hash_literal_string_small.rb +3 -0
  81. data/benchmark/bm_hash_merge_object.rb +22 -0
  82. data/benchmark/bm_hash_merge_string.rb +18 -0
  83. data/benchmark/bm_hash_rassoc_object.rb +9 -0
  84. data/benchmark/bm_hash_rassoc_string.rb +9 -0
  85. data/benchmark/bm_hash_rehash_object.rb +9 -0
  86. data/benchmark/bm_hash_rehash_string.rb +9 -0
  87. data/benchmark/bm_hash_reject_bang_object.rb +9 -0
  88. data/benchmark/bm_hash_reject_bang_string.rb +9 -0
  89. data/benchmark/bm_hash_reject_object.rb +9 -0
  90. data/benchmark/bm_hash_reject_string.rb +9 -0
  91. data/benchmark/bm_hash_replace_object.rb +18 -0
  92. data/benchmark/bm_hash_replace_string.rb +14 -0
  93. data/benchmark/bm_hash_select_bang_object.rb +9 -0
  94. data/benchmark/bm_hash_select_bang_string.rb +9 -0
  95. data/benchmark/bm_hash_select_object.rb +9 -0
  96. data/benchmark/bm_hash_select_string.rb +9 -0
  97. data/benchmark/bm_hash_shift_object.rb +10 -0
  98. data/benchmark/bm_hash_shift_string.rb +10 -0
  99. data/benchmark/bm_hash_to_a_object.rb +9 -0
  100. data/benchmark/bm_hash_to_a_string.rb +9 -0
  101. data/benchmark/bm_hash_to_h_object.rb +10 -0
  102. data/benchmark/bm_hash_to_h_string.rb +10 -0
  103. data/benchmark/bm_hash_values_object.rb +9 -0
  104. data/benchmark/bm_hash_values_string.rb +9 -0
  105. data/benchmark/run.rb +48 -0
  106. data/bin/opal-mspec +1 -1
  107. data/bin/opal-repl +4 -4
  108. data/docs/compiled_ruby.md +214 -56
  109. data/docs/configuring_gems.md +2 -2
  110. data/docs/faq.md +2 -2
  111. data/docs/getting_started.md +19 -2
  112. data/docs/jquery.md +5 -5
  113. data/docs/opal_parser.md +53 -0
  114. data/docs/unsupported_features.md +2 -2
  115. data/docs/upgrading.md +22 -0
  116. data/docs/using_sprockets.md +15 -0
  117. data/examples/rack/config.ru +13 -0
  118. data/examples/sinatra/config.ru +4 -5
  119. data/lib/mspec/opal/runner.rb +54 -11
  120. data/lib/opal.rb +1 -1
  121. data/lib/opal/builder.rb +1 -1
  122. data/lib/opal/builder_processors.rb +1 -1
  123. data/lib/opal/cli.rb +17 -13
  124. data/lib/opal/cli_options.rb +1 -1
  125. data/lib/opal/compiler.rb +12 -0
  126. data/lib/opal/config.rb +4 -0
  127. data/lib/opal/nodes/arglist.rb +5 -7
  128. data/lib/opal/nodes/call.rb +6 -1
  129. data/lib/opal/nodes/call_special.rb +74 -0
  130. data/lib/opal/nodes/def.rb +35 -28
  131. data/lib/opal/nodes/definitions.rb +3 -5
  132. data/lib/opal/nodes/for.rb +13 -0
  133. data/lib/opal/nodes/helpers.rb +15 -1
  134. data/lib/opal/nodes/if.rb +5 -5
  135. data/lib/opal/nodes/iter.rb +6 -1
  136. data/lib/opal/nodes/literal.rb +1 -1
  137. data/lib/opal/nodes/logic.rb +2 -2
  138. data/lib/opal/nodes/masgn.rb +1 -2
  139. data/lib/opal/nodes/module.rb +2 -1
  140. data/lib/opal/nodes/rescue.rb +10 -1
  141. data/lib/opal/nodes/scope.rb +8 -2
  142. data/lib/opal/nodes/singleton_class.rb +1 -1
  143. data/lib/opal/nodes/top.rb +11 -0
  144. data/lib/opal/nodes/variables.rb +4 -4
  145. data/lib/opal/parser.rb +21 -3
  146. data/lib/opal/parser/grammar.rb +3115 -2961
  147. data/lib/opal/parser/grammar.y +29 -6
  148. data/lib/opal/parser/lexer.rb +18 -8
  149. data/lib/opal/sprockets.rb +85 -0
  150. data/lib/opal/sprockets/processor.rb +11 -35
  151. data/lib/opal/sprockets/server.rb +3 -15
  152. data/lib/opal/version.rb +2 -2
  153. data/opal.gemspec +4 -4
  154. data/opal/README.md +9 -0
  155. data/opal/corelib/array.rb +433 -181
  156. data/opal/corelib/basic_object.rb +48 -4
  157. data/opal/corelib/boolean.rb +15 -6
  158. data/opal/corelib/class.rb +6 -5
  159. data/opal/corelib/comparable.rb +12 -0
  160. data/opal/corelib/complex.rb +282 -0
  161. data/opal/corelib/constants.rb +9 -0
  162. data/opal/corelib/enumerable.rb +83 -34
  163. data/opal/corelib/enumerator.rb +3 -1
  164. data/opal/corelib/error.rb +49 -10
  165. data/opal/corelib/file.rb +1 -0
  166. data/opal/corelib/hash.rb +353 -577
  167. data/opal/corelib/helpers.rb +20 -0
  168. data/opal/corelib/kernel.rb +114 -59
  169. data/opal/corelib/math.rb +470 -0
  170. data/opal/corelib/method.rb +11 -2
  171. data/opal/corelib/module.rb +96 -96
  172. data/opal/corelib/{nil_class.rb → nil.rb} +20 -1
  173. data/opal/corelib/number.rb +751 -0
  174. data/opal/corelib/numeric.rb +77 -437
  175. data/opal/corelib/proc.rb +81 -1
  176. data/opal/corelib/process.rb +27 -0
  177. data/opal/corelib/rational.rb +358 -0
  178. data/opal/corelib/regexp.rb +156 -27
  179. data/opal/corelib/runtime.js +724 -335
  180. data/opal/corelib/string.rb +93 -104
  181. data/opal/corelib/string/encoding.rb +177 -0
  182. data/opal/corelib/string/inheritance.rb +2 -0
  183. data/opal/corelib/struct.rb +105 -18
  184. data/opal/corelib/time.rb +267 -146
  185. data/opal/corelib/unsupported.rb +216 -0
  186. data/opal/corelib/variables.rb +0 -6
  187. data/opal/opal.rb +8 -22
  188. data/opal/opal/base.rb +9 -0
  189. data/opal/opal/mini.rb +17 -0
  190. data/spec/README.md +1 -1
  191. data/spec/filters/bugs/array.rb +38 -136
  192. data/spec/filters/bugs/{basic_object.rb → basicobject.rb} +14 -15
  193. data/spec/filters/bugs/class.rb +6 -12
  194. data/spec/filters/bugs/complex.rb +3 -0
  195. data/spec/filters/bugs/date.rb +162 -10
  196. data/spec/filters/bugs/enumerable.rb +31 -58
  197. data/spec/filters/bugs/enumerator.rb +42 -0
  198. data/spec/filters/bugs/exception.rb +66 -10
  199. data/spec/filters/bugs/float.rb +17 -0
  200. data/spec/filters/bugs/hash.rb +11 -97
  201. data/spec/filters/bugs/inheritance.rb +5 -0
  202. data/spec/filters/bugs/integer.rb +28 -0
  203. data/spec/filters/bugs/kernel.rb +304 -12
  204. data/spec/filters/bugs/language.rb +133 -399
  205. data/spec/filters/bugs/language_opal.rb +88 -0
  206. data/spec/filters/bugs/module.rb +203 -62
  207. data/spec/filters/bugs/numeric.rb +32 -0
  208. data/spec/filters/bugs/proc.rb +39 -0
  209. data/spec/filters/bugs/range.rb +148 -0
  210. data/spec/filters/bugs/regexp.rb +168 -0
  211. data/spec/filters/bugs/set.rb +46 -3
  212. data/spec/filters/bugs/singleton.rb +1 -2
  213. data/spec/filters/bugs/string.rb +59 -90
  214. data/spec/filters/bugs/strscan.rb +80 -0
  215. data/spec/filters/bugs/struct.rb +10 -20
  216. data/spec/filters/bugs/time.rb +17 -184
  217. data/spec/filters/bugs/unboundmethod.rb +22 -0
  218. data/spec/filters/unsupported/array.rb +163 -0
  219. data/spec/filters/unsupported/basicobject.rb +14 -0
  220. data/spec/filters/unsupported/bignum.rb +46 -0
  221. data/spec/filters/unsupported/class.rb +4 -0
  222. data/spec/filters/unsupported/delegator.rb +5 -0
  223. data/spec/filters/unsupported/enumerable.rb +11 -0
  224. data/spec/filters/unsupported/enumerator.rb +8 -9
  225. data/spec/filters/unsupported/fixnum.rb +14 -0
  226. data/spec/filters/unsupported/float.rb +41 -7
  227. data/spec/filters/unsupported/freeze.rb +45 -0
  228. data/spec/filters/unsupported/hash.rb +50 -0
  229. data/spec/filters/unsupported/integer.rb +3 -0
  230. data/spec/filters/unsupported/kernel.rb +31 -0
  231. data/spec/filters/unsupported/language.rb +17 -0
  232. data/spec/filters/unsupported/matchdata.rb +30 -0
  233. data/spec/filters/unsupported/math.rb +3 -0
  234. data/spec/filters/unsupported/module.rb +5 -3
  235. data/spec/filters/unsupported/pathname.rb +3 -0
  236. data/spec/filters/unsupported/privacy.rb +136 -0
  237. data/spec/filters/unsupported/proc.rb +3 -0
  238. data/spec/filters/unsupported/regexp.rb +59 -0
  239. data/spec/filters/unsupported/set.rb +4 -0
  240. data/spec/filters/unsupported/{marshal.rb → singleton.rb} +4 -2
  241. data/spec/filters/unsupported/{mutable_strings.rb → string.rb} +456 -336
  242. data/spec/filters/unsupported/struct.rb +3 -0
  243. data/spec/filters/unsupported/symbol.rb +5 -0
  244. data/spec/filters/unsupported/taint.rb +16 -0
  245. data/spec/filters/unsupported/thread.rb +5 -0
  246. data/spec/filters/unsupported/time.rb +197 -16
  247. data/spec/lib/cli_spec.rb +14 -4
  248. data/spec/lib/compiler_spec.rb +9 -1
  249. data/spec/lib/parser/call_spec.rb +18 -0
  250. data/spec/lib/parser/not_spec.rb +2 -8
  251. data/spec/lib/sprockets_spec.rb +24 -0
  252. data/spec/opal/core/array/intersection_spec.rb +38 -0
  253. data/spec/opal/core/array/minus_spec.rb +38 -0
  254. data/spec/opal/core/array/union_spec.rb +38 -0
  255. data/spec/opal/core/array/uniq_spec.rb +49 -0
  256. data/spec/opal/core/exception_spec.rb +7 -0
  257. data/spec/opal/core/fixtures/require_tree_with_dot/file 1.rb +1 -0
  258. data/spec/opal/core/fixtures/require_tree_with_dot/file 2.rb +1 -0
  259. data/spec/opal/core/fixtures/require_tree_with_dot/file 3.rb +1 -0
  260. data/spec/opal/core/fixtures/require_tree_with_dot/index.rb +3 -0
  261. data/spec/opal/core/hash/internals_spec.rb +332 -0
  262. data/spec/opal/core/helpers_spec.rb +14 -0
  263. data/spec/opal/core/kernel/freeze_spec.rb +1 -1
  264. data/spec/opal/core/kernel/raise_spec.rb +13 -0
  265. data/spec/opal/core/kernel/require_tree_spec.rb +9 -0
  266. data/spec/opal/core/language/class_spec.rb +55 -0
  267. data/spec/opal/core/language/fixtures/send.rb +1 -0
  268. data/spec/opal/core/language/keyword_arguments_spec.rb +11 -0
  269. data/spec/opal/core/language/send_spec.rb +5 -0
  270. data/spec/opal/core/method/to_proc_spec.rb +28 -0
  271. data/spec/opal/core/module/name_spec.rb +0 -17
  272. data/spec/opal/core/runtime/bridged_classes_spec.rb +2 -2
  273. data/spec/opal/core/runtime/eval_spec.rb +1 -1
  274. data/spec/opal/core/runtime/method_missing_spec.rb +6 -0
  275. data/spec/opal/core/runtime_spec.rb +51 -0
  276. data/spec/opal/stdlib/js_spec.rb +66 -0
  277. data/spec/opal/stdlib/native/hash_spec.rb +36 -0
  278. data/spec/rubyspecs +152 -273
  279. data/spec/spec_helper.rb +10 -11
  280. data/stdlib/base64.rb +9 -9
  281. data/stdlib/benchmark.rb +551 -4
  282. data/stdlib/console.rb +94 -0
  283. data/stdlib/date.rb +1 -1
  284. data/stdlib/encoding.rb +1 -170
  285. data/stdlib/js.rb +56 -0
  286. data/stdlib/json.rb +9 -14
  287. data/stdlib/math.rb +1 -370
  288. data/stdlib/native.rb +133 -63
  289. data/stdlib/nodejs/file.rb +5 -0
  290. data/stdlib/nodejs/fileutils.rb +13 -6
  291. data/stdlib/nodejs/node_modules/js-yaml/node_modules/argparse/README.md +1 -1
  292. data/stdlib/opal-parser.rb +1 -2
  293. data/stdlib/ostruct.rb +65 -6
  294. data/stdlib/pp.rb +2 -4
  295. data/stdlib/rbconfig.rb +1 -3
  296. data/stdlib/strscan.rb +164 -28
  297. data/tasks/benchmarking.rake +88 -0
  298. data/tasks/testing.rake +181 -55
  299. data/{lib/mspec/opal/special_calls.rb → tasks/testing/mspec_special_calls.rb} +1 -1
  300. data/{lib/mspec/opal/sprockets.js → tasks/testing/phantomjs1-sprockets.js} +17 -6
  301. data/test/opal/test_keyword.rb +590 -0
  302. data/vendored-minitest/minitest.rb +2 -2
  303. data/vendored-minitest/test/unit.rb +5 -0
  304. metadata +229 -62
  305. data/benchmarks/operators.rb +0 -11
  306. data/benchmarks/prova.js.rb +0 -13
  307. data/docs/libraries.md +0 -36
  308. data/lib/mspec/opal/new.html.erb +0 -1
  309. data/lib/mspec/opal/rake_task.rb +0 -248
  310. data/opal/corelib/match_data.rb +0 -128
  311. data/spec/filters/bugs/math.rb +0 -95
  312. data/spec/filters/bugs/nil.rb +0 -7
  313. data/spec/filters/bugs/opal.rb +0 -9
  314. data/spec/filters/bugs/regular_expressions.rb +0 -41
  315. data/spec/filters/bugs/stringscanner.rb +0 -33
  316. data/spec/filters/unsupported/encoding.rb +0 -102
  317. data/spec/filters/unsupported/frozen.rb +0 -92
  318. data/spec/filters/unsupported/hash_compare_by_identity.rb +0 -16
  319. data/spec/filters/unsupported/integer_size.rb +0 -59
  320. data/spec/filters/unsupported/method_added.rb +0 -10
  321. data/spec/filters/unsupported/private_constants.rb +0 -30
  322. data/spec/filters/unsupported/private_methods.rb +0 -55
  323. data/spec/filters/unsupported/random.rb +0 -4
  324. data/spec/filters/unsupported/rational_numbers.rb +0 -4
  325. data/spec/filters/unsupported/regular_expressions.rb +0 -137
  326. data/spec/filters/unsupported/ruby_exe.rb +0 -5
  327. data/spec/filters/unsupported/symbols.rb +0 -17
  328. data/spec/filters/unsupported/tainted.rb +0 -180
  329. data/spec/filters/unsupported/trusted.rb +0 -88
  330. data/stdlib/process.rb +0 -10
  331. data/tasks/documenting.rake +0 -37
data/stdlib/pp.rb CHANGED
@@ -19,10 +19,8 @@ class PP
19
19
  p(*args)
20
20
  end
21
21
  else
22
- def pp(obj, out=`console`, width=79)
23
- if `#{out} === console`
24
- `console.log(obj)`
25
- elsif String === out
22
+ def pp(obj, out=$stdout, width=79)
23
+ if String === out
26
24
  out + obj.inspect + "\n"
27
25
  else
28
26
  out << obj.inspect + "\n"
data/stdlib/rbconfig.rb CHANGED
@@ -15,6 +15,4 @@ module RbConfig
15
15
  end
16
16
 
17
17
  # required for mspec it would appear
18
- RUBY_NAME = 'opal'
19
- RUBY_EXE = 'opal'
20
- RUBY_PATCHLEVEL = "327"
18
+ RUBY_EXE = 'bundle exec bin/opal'
data/stdlib/strscan.rb CHANGED
@@ -7,7 +7,7 @@ class StringScanner
7
7
  @pos = 0
8
8
  @matched = nil
9
9
  @working = string
10
- @match = []
10
+ @match = []
11
11
  end
12
12
 
13
13
  attr_reader :string
@@ -15,15 +15,17 @@ class StringScanner
15
15
  def beginning_of_line?
16
16
  `#@pos === 0 || #@string.charAt(#@pos - 1) === "\n"`
17
17
  end
18
+
18
19
  alias bol? beginning_of_line?
19
20
 
20
- def scan(regex)
21
+ def scan(pattern)
22
+ pattern = anchor(pattern)
23
+
21
24
  %x{
22
- var regex = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1)),
23
- result = regex.exec(#@working);
25
+ var result = pattern.exec(#@working);
24
26
 
25
27
  if (result == null) {
26
- return #{self}.matched = nil;
28
+ return #@matched = nil;
27
29
  }
28
30
  else if (typeof(result) === 'object') {
29
31
  #@prev_pos = #@pos;
@@ -46,6 +48,38 @@ class StringScanner
46
48
  }
47
49
  end
48
50
 
51
+ def scan_until(pattern)
52
+ pattern = anchor(pattern)
53
+
54
+ %x{
55
+ var pos = #@pos,
56
+ working = #@working,
57
+ result;
58
+
59
+ while (true) {
60
+ result = pattern.exec(working);
61
+ pos += 1;
62
+ working = working.substr(1);
63
+
64
+ if (result == null) {
65
+ if (working.length === 0) {
66
+ return #@matched = nil;
67
+ }
68
+
69
+ continue;
70
+ }
71
+
72
+ #@matched = #@string.substr(#@pos, pos - #@pos - 1 + result[0].length);
73
+ #@prev_pos = pos - 1;
74
+ #@pos = pos;
75
+ #@working = working.substr(result[0].length);
76
+
77
+ return #@matched;
78
+ }
79
+ }
80
+ end
81
+
82
+
49
83
  def [](idx)
50
84
  %x{
51
85
  var match = #@match;
@@ -66,16 +100,36 @@ class StringScanner
66
100
  }
67
101
  end
68
102
 
69
- def check(regex)
103
+ def check(pattern)
104
+ pattern = anchor(pattern)
105
+
70
106
  %x{
71
- var regexp = new RegExp('^' + regex.toString().substring(1, regex.toString().length - 1)),
72
- result = regexp.exec(#@working);
107
+ var result = pattern.exec(#@working);
73
108
 
74
109
  if (result == null) {
75
- return #{self}.matched = nil;
110
+ return #@matched = nil;
111
+ }
112
+
113
+ return #@matched = result[0];
114
+ }
115
+ end
116
+
117
+ def check_until(pattern)
118
+ %x{
119
+ var prev_pos = #@prev_pos,
120
+ pos = #@pos;
121
+
122
+ var result = #{scan_until(pattern)};
123
+
124
+ if (result !== nil) {
125
+ #@matched = result.substr(-1);
126
+ #@working = #@string.substr(pos);
76
127
  }
77
128
 
78
- return #{self}.matched = result[0];
129
+ #@prev_pos = prev_pos;
130
+ #@pos = pos;
131
+
132
+ return result;
79
133
  }
80
134
  end
81
135
 
@@ -87,37 +141,72 @@ class StringScanner
87
141
  `#@working.length === 0`
88
142
  end
89
143
 
90
- def skip(re)
144
+ def exist?(pattern)
91
145
  %x{
92
- re = new RegExp('^' + re.source)
93
- var result = re.exec(#@working);
146
+ var result = pattern.exec(#@working);
94
147
 
95
148
  if (result == null) {
96
- return #{self}.matched = nil;
149
+ return nil;
150
+ }
151
+ else if (result.index == 0) {
152
+ return 0;
153
+ }
154
+ else {
155
+ return result.index + 1;
156
+ }
157
+ }
158
+ end
159
+
160
+ def skip(pattern)
161
+ pattern = anchor(pattern)
162
+
163
+ %x{
164
+ var result = pattern.exec(#@working);
165
+
166
+ if (result == null) {
167
+ return #@matched = nil;
97
168
  }
98
169
  else {
99
170
  var match_str = result[0];
100
171
  var match_len = match_str.length;
101
- #{self}.matched = match_str;
102
- self.prev_pos = self.pos;
103
- #{self}.pos += match_len;
104
- #{self}.working = #{self}.working.substring(match_len);
172
+
173
+ #@matched = match_str;
174
+ #@prev_pos = #@pos;
175
+ #@pos += match_len;
176
+ #@working = #@working.substring(match_len);
177
+
105
178
  return match_len;
106
179
  }
107
180
  }
108
181
  end
109
182
 
110
- def get_byte()
183
+ def skip_until(pattern)
184
+ %x{
185
+ var result = #{scan_until(pattern)};
186
+
187
+ if (result === nil) {
188
+ return nil;
189
+ }
190
+ else {
191
+ #@matched = result.substr(-1);
192
+
193
+ return result.length;
194
+ }
195
+ }
196
+ end
197
+
198
+ def get_byte
111
199
  %x{
112
200
  var result = nil;
113
- if (#{self}.pos < #{self}.string.length) {
114
- self.prev_pos = self.pos;
115
- #{self}.pos += 1;
116
- result = #{self}.matched = #{self}.working.substring(0, 1);
117
- #{self}.working = #{self}.working.substring(1);
201
+
202
+ if (#@pos < #@string.length) {
203
+ #@prev_pos = #@pos;
204
+ #@pos += 1;
205
+ result = #@matched = #@working.substring(0, 1);
206
+ #@working = #@working.substring(1);
118
207
  }
119
208
  else {
120
- #{self}.matched = nil;
209
+ #@matched = nil;
121
210
  }
122
211
 
123
212
  return result;
@@ -127,6 +216,23 @@ class StringScanner
127
216
  # not exactly, but for now...
128
217
  alias getch get_byte
129
218
 
219
+ def match?(pattern)
220
+ pattern = anchor(pattern)
221
+
222
+ %x{
223
+ var result = pattern.exec(#@working);
224
+
225
+ if (result == null) {
226
+ return nil;
227
+ }
228
+ else {
229
+ #@prev_pos = #@pos;
230
+
231
+ return result[0].length;
232
+ }
233
+ }
234
+ end
235
+
130
236
  def pos=(pos)
131
237
  %x{
132
238
  if (pos < 0) {
@@ -134,10 +240,30 @@ class StringScanner
134
240
  }
135
241
  }
136
242
 
137
- @pos = pos
243
+ @pos = pos
138
244
  @working = `#{@string}.slice(pos)`
139
245
  end
140
246
 
247
+ def post_match
248
+ %x{
249
+ if (#@matched === nil) {
250
+ return nil;
251
+ }
252
+
253
+ return #@string.substr(#@pos);
254
+ }
255
+ end
256
+
257
+ def pre_match
258
+ %x{
259
+ if (#@matched === nil) {
260
+ return nil;
261
+ }
262
+
263
+ return #@string.substr(0, #@prev_pos);
264
+ }
265
+ end
266
+
141
267
  def reset
142
268
  @working = @string
143
269
  @matched = nil
@@ -152,15 +278,25 @@ class StringScanner
152
278
  `#@working.length !== 0`
153
279
  end
154
280
 
281
+ def rest_size
282
+ rest.size
283
+ end
284
+
155
285
  def terminate
156
286
  @match = nil
157
287
  self.pos = @string.length
158
288
  end
159
289
 
160
290
  def unscan
161
- @pos = @prev_pos
291
+ @pos = @prev_pos
162
292
  @prev_pos = nil
163
- @match = nil
293
+ @match = nil
294
+
164
295
  self
165
296
  end
297
+
298
+ private
299
+ def anchor(pattern)
300
+ `new RegExp('^' + pattern.toString().substr(1, pattern.toString().length - 2))`
301
+ end
166
302
  end
@@ -0,0 +1,88 @@
1
+ namespace :bench do
2
+ directory "tmp/bench"
3
+
4
+ desc "Benchmark Opal"
5
+ task :opal => "tmp/bench" do |t, args|
6
+ files = Array(args[:files]) + args.extras
7
+ index = 0
8
+ begin
9
+ index += 1
10
+ report = "tmp/bench/Opal#{index}"
11
+ end while File.exist?(report)
12
+ sh "bundle exec opal benchmark/run.rb #{files.join(" ")} | tee #{report}"
13
+ end
14
+
15
+ desc "Benchmark Ruby"
16
+ task :ruby => "tmp/bench" do |t, args|
17
+ files = Array(args[:files]) + args.extras
18
+ index = 0
19
+ begin
20
+ index += 1
21
+ report = "tmp/bench/Ruby#{index}"
22
+ end while File.exist?(report)
23
+ sh "bundle exec ruby benchmark/run.rb #{files.join(" ")} | tee #{report}"
24
+ end
25
+
26
+ desc "Delete all benchmark results"
27
+ task :clear do
28
+ sh "rm tmp/bench/*"
29
+ end
30
+
31
+ desc "Combined report of all benchmark results"
32
+ task :report do |t, args|
33
+ files = Array(args[:files]) + args.extras
34
+ if files.empty?
35
+ files = Dir["tmp/bench/*"]
36
+ else
37
+ files = files.map{|file| "tmp/bench/#{ file }"}
38
+ end
39
+ reports = []
40
+ benchmark_names = []
41
+
42
+ files.each do |file|
43
+ report_name = File.basename(file, File.extname(file))
44
+ report_results = {}
45
+ File.read(file).each_line do |line|
46
+ benchmark_name, benchmark_result = line.split(" ")
47
+ report_results[benchmark_name] = benchmark_result
48
+ benchmark_names << benchmark_name
49
+ end
50
+ reports << [report_name, report_results]
51
+ end
52
+
53
+ benchmark_names.uniq!
54
+
55
+ header = ["Benchmark"]
56
+ reports.each do |report_name, _|
57
+ header << report_name
58
+ end
59
+
60
+ table = [header]
61
+ benchmark_names.each do |benchmark_name|
62
+ row = [benchmark_name]
63
+ reports.each do |_, report_results|
64
+ if report_results[benchmark_name]
65
+ row << format("%0.3f", report_results[benchmark_name])
66
+ else
67
+ row << ""
68
+ end
69
+ end
70
+ table << row
71
+ end
72
+
73
+ fmt = ""
74
+ table.transpose.each_with_index do |column, index|
75
+ column_width = column.max_by{|string| string.length}.length
76
+ if index.zero?
77
+ fmt << "%-#{ column_width }s"
78
+ else
79
+ fmt << " %#{ column_width }s"
80
+ end
81
+ end
82
+ fmt << "\n"
83
+
84
+ table.each do |row|
85
+ printf fmt, *row
86
+ end
87
+ end
88
+ end
data/tasks/testing.rake CHANGED
@@ -1,70 +1,181 @@
1
+ require_relative './testing/mspec_special_calls'
2
+
1
3
  require 'rspec/core/rake_task'
2
4
  RSpec::Core::RakeTask.new(:rspec) do |t|
3
5
  t.pattern = 'spec/lib/**/*_spec.rb'
4
6
  end
5
7
 
6
- require 'mspec/opal/rake_task'
7
- MSpec::Opal::RakeTask.new(:mspec_phantom) do |config|
8
- config.pattern = ENV['MSPEC_PATTERN'] if ENV['MSPEC_PATTERN']
9
- config.basedir = ENV['MSPEC_BASEDIR'] if ENV['MSPEC_BASEDIR']
10
- end
8
+ module Testing
9
+ extend self
10
+
11
+ def stubs
12
+ %w[
13
+ mspec/helpers/tmp
14
+ mspec/helpers/environment
15
+ mspec/guards/block_device
16
+ mspec/guards/endian
17
+ ]
18
+ end
19
+
20
+ def specs(env = ENV)
21
+ suite = env['SUITE']
22
+ pattern = env['PATTERN']
23
+ whitelist_pattern = !!env['RUBYSPECS']
24
+
25
+ excepting = []
26
+ rubyspecs = File.read('spec/rubyspecs').lines.reject do |l|
27
+ l.strip!
28
+ l.start_with?('#') || l.empty? || (l.start_with?('!') && excepting.push(l.sub('!', 'spec/') + '.rb'))
29
+ end.flat_map do |path|
30
+ path = "spec/#{path}"
31
+ File.directory?(path) ? Dir[path+'/*.rb'] : "#{path}.rb"
32
+ end - excepting
33
+
34
+ opalspecs = Dir['spec/{opal,lib/parser}/**/*_spec.rb'] + ['spec/lib/lexer_spec.rb']
35
+ userspecs = Dir[pattern] if pattern
36
+ userspecs &= rubyspecs if whitelist_pattern
37
+
38
+ opalspec_filters = Dir['spec/filters/**/*_opal.rb']
39
+ rubyspec_filters = Dir['spec/filters/**/*.rb'] - opalspec_filters
40
+
41
+ specs = []
42
+ add_specs = ->(name, new_specs) do
43
+ puts "Adding #{new_specs.size.to_s.rjust(3)} files (#{name})"
44
+ specs += new_specs
45
+ end
46
+
47
+ # Filters must be added first
48
+ suite_filters = suite == 'opal' ? opalspec_filters : rubyspec_filters
49
+ add_specs["#{suite} filters", suite_filters]
50
+
51
+ if pattern
52
+ add_specs["PATTERN=#{pattern}", userspecs]
53
+ elsif suite == 'opal'
54
+ add_specs['spec/opal', opalspecs]
55
+ elsif suite == 'rubyspec'
56
+ add_specs['spec/rubyspec', rubyspecs]
57
+ else
58
+ warn 'Please provide at lease one of the following ENV vars:'
59
+ warn 'PATTERN # e.g. env PATTERN="spec/rubyspec/core/numeric/**_spec.rb"'
60
+ warn 'SUITE # can be either SUITE=opal or SUITE=rubyspec'
61
+ exit 1
62
+ end
63
+
64
+ specs
65
+ end
11
66
 
12
- desc <<-DESC
13
- Run the MSpec test suite on node
67
+ def write_file(filename, specs, bm_filepath = nil)
68
+ requires = specs.map{|s| "require '#{s.sub(/^spec\//,'')}'"}
14
69
 
70
+ if bm_filepath
71
+ enter_benchmarking_mode = "OSpecRunner.main.bm!(#{Integer(ENV['BM'])}, '#{bm_filepath}')"
72
+ end
73
+
74
+ File.write filename, <<-RUBY
75
+ require 'spec_helper'
76
+ #{enter_benchmarking_mode}
77
+ #{requires.join("\n ")}
78
+ OSpecFilter.main.unused_filters_message(list: #{!!ENV['LIST_UNUSED_FILTERS']})
79
+ OSpecRunner.main.did_finish
80
+ RUBY
81
+ end
82
+
83
+ def bm_filepath
84
+ mkdir_p 'tmp/bench'
85
+ index = 0
86
+ begin
87
+ index += 1
88
+ bm_filepath = "tmp/bench/Spec#{index}"
89
+ end while File.exist?(bm_filepath)
90
+ end
91
+ end
92
+
93
+ pattern_usage = <<-DESC
15
94
  Use PATTERN and env var to manually set the glob for specs:
16
95
 
17
96
  # Will run all specs matching the specified pattern.
18
97
  # (Note: the rubyspecs filters will still apply)
19
- rake mspec_node PATTERN=spec/corelib/core/module/class_variable*
98
+ env PATTERN="spec/rubyspec/core/module/class_variable*_spec.rb" rake mspec_node
99
+ env PATTERN="spec/rubyspec/core/numeric/**_spec.rb" rake mspec_node
20
100
  DESC
21
- task :mspec_node do
22
- excepting = []
23
- rubyspecs = File.read('spec/rubyspecs').lines.reject do |l|
24
- l.strip!; l.start_with?('#') || l.empty? || (l.start_with?('!') && excepting.push(l.sub('!', 'spec/') + '.rb'))
25
- end.flat_map do |path|
26
- path = "spec/#{path}"
27
- File.directory?(path) ? Dir[path+'/*.rb'] : "#{path}.rb"
28
- end - excepting
29
-
30
- filters = Dir['spec/filters/**/*.rb']
31
- shared = Dir['spec/{opal,lib/parser}/**/*_spec.rb'] + ['spec/lib/lexer_spec.rb']
32
-
33
- specs = []
34
- add_specs = ->(name, new_specs) { p [new_specs.size, name]; specs + new_specs}
35
-
36
- specs = add_specs.(:filters, filters)
37
- pattern = ENV['PATTERN']
38
- whitelist_pattern = !!ENV['RUBYSPECS']
39
-
40
- if pattern
41
- custom = Dir[pattern]
42
- custom &= rubyspecs if whitelist_pattern
43
- specs = add_specs.(:custom, custom)
44
- else
45
- specs = add_specs.(:shared, shared)
46
- specs = add_specs.(:rubyspecs, rubyspecs)
101
+
102
+ %w[rubyspec opal].each do |suite|
103
+ desc "Run the MSpec/#{suite} test suite on Phantom.js" + pattern_usage
104
+ task :"mspec_#{suite}_phantom" do
105
+ filename = File.expand_path('tmp/mspec_phantom.rb')
106
+ runner = "#{__dir__}/testing/phantomjs1-sprockets.js"
107
+ port = 9999
108
+ url = "http://localhost:#{port}/"
109
+
110
+ mkdir_p File.dirname(filename)
111
+ Testing.write_file filename, Testing.specs(ENV.to_hash.merge 'SUITE' => suite)
112
+
113
+ Testing.stubs.each {|s| ::Opal::Processor.stub_file s }
114
+
115
+ Opal::Config.arity_check_enabled = true
116
+ Opal::Config.freezing_stubs_enabled = false
117
+ Opal::Config.tainting_stubs_enabled = false
118
+ Opal::Config.dynamic_require_severity = :error
119
+
120
+ Opal.use_gem 'mspec'
121
+ Opal.append_path 'spec'
122
+ Opal.append_path 'lib'
123
+ Opal.append_path File.dirname(filename)
124
+
125
+ app = Opal::Server.new { |s| s.main = File.basename(filename) }
126
+ server = Thread.new { Rack::Server.start(app: app, Port: port) }
127
+ sleep 1
128
+
129
+ begin
130
+ sh 'phantomjs', runner, url
131
+ ensure
132
+ server.kill if server.alive?
133
+ end
47
134
  end
48
135
 
49
- requires = specs.map{|s| "require '#{s.sub(/^spec\//,'')}'"}
50
- include_paths = '-Ispec -Ilib'
136
+ desc "Run the MSpec test suite on Node.js" + pattern_usage
137
+ task :"mspec_#{suite}_node" do
138
+ include_paths = '-Ispec -Ilib'
51
139
 
52
- filename = 'tmp/mspec_node.rb'
53
- js_filename = 'tmp/mspec_node.js'
54
- mkdir_p File.dirname(filename)
55
- enter_benchmarking_mode = ENV['BM'] && "OSpecRunner.main.bm!(#{Integer(ENV['BM'])})"
56
- File.write filename, <<-RUBY
57
- require 'spec_helper'
58
- #{enter_benchmarking_mode}
59
- #{requires.join("\n ")}
60
- OSpecRunner.main.did_finish
61
- RUBY
62
-
63
- stubs = '-smspec/helpers/tmp -smspec/helpers/environment -smspec/guards/block_device -smspec/guards/endian'
64
-
65
- sh "ruby -rbundler/setup -rmspec/opal/special_calls "\
66
- "bin/opal -gmspec #{include_paths} #{stubs} -rnodejs -Dwarning -A #{filename} -c > #{js_filename}"
67
- sh "NODE_PATH=stdlib/nodejs/node_modules node #{js_filename}"
140
+ filename = 'tmp/mspec_node.rb'
141
+ js_filename = 'tmp/mspec_node.js'
142
+ mkdir_p File.dirname(filename)
143
+ bm_filepath = Testing.bm_filepath if ENV['BM']
144
+ Testing.write_file filename, Testing.specs(ENV.to_hash.merge 'SUITE' => suite), bm_filepath
145
+
146
+ stubs = Testing.stubs.map{|s| "-s#{s}"}.join(' ')
147
+
148
+ sh "ruby -rbundler/setup -r#{__dir__}/testing/mspec_special_calls "\
149
+ "bin/opal -gmspec #{include_paths} #{stubs} -rnodejs/io -rnodejs/kernel -Dwarning -A #{filename} -c > #{js_filename}"
150
+ sh "NODE_PATH=stdlib/nodejs/node_modules node #{js_filename}"
151
+
152
+ if bm_filepath
153
+ puts "Benchmark results have been written to #{bm_filepath}"
154
+ puts "To view the results, run bundle exec rake bench:report"
155
+ end
156
+ end
157
+ end
158
+
159
+ task :jshint do
160
+ js_filename = 'tmp/jshint.js'
161
+ mkdir_p 'tmp'
162
+
163
+ if ENV['SUITE'] == 'core'
164
+ sh "ruby -rbundler/setup bin/opal -ce '23' > #{js_filename}"
165
+ sh "jshint --verbose #{js_filename}"
166
+ elsif ENV['SUITE'] == 'stdlib'
167
+ sh "rake dist"
168
+
169
+ Dir["build/*.js"].each {|path|
170
+ unless path =~ /(opal.*js)|.min.js/
171
+ sh "jshint --verbose #{path}"
172
+ end
173
+ }
174
+ else
175
+ warn 'Please provide at lease one of the following ENV vars:'
176
+ warn 'SUITE # can be either SUITE=core or SUITE=stdlib'
177
+ exit 1
178
+ end
68
179
  end
69
180
 
70
181
  task :cruby_tests do
@@ -72,10 +183,12 @@ task :cruby_tests do
72
183
  files = Dir[ENV['FILES'] || 'test/test_*.rb']
73
184
  include_paths = '-Itest -I. -Itmp -Ilib'
74
185
  else
75
- include_paths = '-Itest/cruby/test'
186
+ include_paths = '-Itest/cruby/test -Itest'
76
187
  test_dir = Pathname("#{__dir__}/../test/cruby/test")
77
188
  files = %w[
189
+ benchmark/test_benchmark.rb
78
190
  ruby/test_call.rb
191
+ opal/test_keyword.rb
79
192
  ].flat_map do |path|
80
193
  if path.end_with?('.rb')
81
194
  path
@@ -99,10 +212,23 @@ task :cruby_tests do
99
212
  puts "== Running: #{files.join ", "}"
100
213
 
101
214
  sh "ruby -rbundler/setup "\
102
- "bin/opal #{include_paths} #{stubs} -rnodejs -Dwarning -A #{filename} -c > #{js_filename}"
215
+ "bin/opal #{include_paths} #{stubs} -rnodejs -ropal-parser -Dwarning -A #{filename} -c > #{js_filename}"
103
216
  sh "NODE_PATH=stdlib/nodejs/node_modules node #{js_filename}"
104
217
  end
105
218
 
106
- task :mspec => [:mspec_node, :mspec_phantom]
219
+ task :mspec => [:mspec_rubyspec_node, :mspec_rubyspec_phantom, :mspec_opal_node, :mspec_opal_phantom]
107
220
  task :minitest => [:cruby_tests]
108
221
  task :test_all => [:rspec, :mspec, :minitest]
222
+
223
+
224
+ if (current_suite = ENV['SUITE'])
225
+ # Legacy tasks, only if ENV['SUITE'] is set
226
+ desc "Deprecated: use mspec_rubyspec_phantom or mspec_opal_phantom instead"
227
+ task :mspec_phantom => :"mspec_#{current_suite}_phantom"
228
+
229
+ desc "Deprecated: use mspec_rubyspec_node or mspec_opal_node instead"
230
+ task :mspec_node => :"mspec_#{current_suite}_node"
231
+ else
232
+ task :mspec_phantom => [:mspec_opal_phantom, :mspec_rubyspec_phantom]
233
+ task :mspec_node => [:mspec_opal_node, :mspec_rubyspec_node]
234
+ end