opal 0.8.1 → 0.9.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
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