opal 1.2.0 → 1.3.0.alpha1

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 (159) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintrc.await.js +6 -0
  3. data/.eslintrc.js +34 -0
  4. data/.github/workflows/build.yml +8 -0
  5. data/.rubocop.yml +9 -0
  6. data/CHANGELOG.md +4 -0
  7. data/README.md +1 -1
  8. data/Rakefile +1 -0
  9. data/UNRELEASED.md +64 -38
  10. data/docs/async.md +109 -0
  11. data/docs/roda-sprockets.md +0 -2
  12. data/exe/opal +2 -0
  13. data/exe/opal-repl +2 -2
  14. data/lib/opal/builder.rb +5 -1
  15. data/lib/opal/builder_processors.rb +7 -2
  16. data/lib/opal/cache/file_cache.rb +119 -0
  17. data/lib/opal/cache.rb +71 -0
  18. data/lib/opal/cli.rb +35 -1
  19. data/lib/opal/cli_options.rb +21 -0
  20. data/lib/opal/cli_runners/chrome.rb +21 -14
  21. data/lib/opal/cli_runners/chrome_cdp_interface.js +30285 -0
  22. data/lib/opal/cli_runners/{chrome.js → chrome_cdp_interface.rb} +27 -6
  23. data/lib/opal/cli_runners/compiler.rb +2 -1
  24. data/lib/opal/cli_runners/gjs.rb +27 -0
  25. data/lib/opal/cli_runners/mini_racer.rb +36 -0
  26. data/lib/opal/cli_runners/source-map-support-browser.js +276 -91
  27. data/lib/opal/cli_runners/source-map-support-node.js +276 -91
  28. data/lib/opal/cli_runners/source-map-support.js +60 -18
  29. data/lib/opal/cli_runners.rb +2 -0
  30. data/lib/opal/compiler.rb +99 -10
  31. data/lib/opal/fragment.rb +77 -14
  32. data/lib/opal/nodes/args/extract_kwrestarg.rb +6 -4
  33. data/lib/opal/nodes/args/extract_restarg.rb +10 -12
  34. data/lib/opal/nodes/args.rb +28 -0
  35. data/lib/opal/nodes/base.rb +29 -5
  36. data/lib/opal/nodes/call.rb +123 -2
  37. data/lib/opal/nodes/case.rb +7 -1
  38. data/lib/opal/nodes/class.rb +12 -2
  39. data/lib/opal/nodes/def.rb +3 -23
  40. data/lib/opal/nodes/definitions.rb +21 -4
  41. data/lib/opal/nodes/helpers.rb +2 -2
  42. data/lib/opal/nodes/if.rb +39 -9
  43. data/lib/opal/nodes/iter.rb +15 -3
  44. data/lib/opal/nodes/lambda.rb +3 -1
  45. data/lib/opal/nodes/literal.rb +13 -7
  46. data/lib/opal/nodes/logic.rb +2 -2
  47. data/lib/opal/nodes/module.rb +12 -2
  48. data/lib/opal/nodes/rescue.rb +59 -34
  49. data/lib/opal/nodes/scope.rb +88 -6
  50. data/lib/opal/nodes/super.rb +52 -25
  51. data/lib/opal/nodes/top.rb +13 -7
  52. data/lib/opal/nodes/while.rb +7 -1
  53. data/lib/opal/parser/patch.rb +2 -1
  54. data/lib/opal/repl.rb +137 -49
  55. data/lib/opal/rewriters/binary_operator_assignment.rb +10 -10
  56. data/lib/opal/rewriters/block_to_iter.rb +3 -3
  57. data/lib/opal/rewriters/for_rewriter.rb +7 -7
  58. data/lib/opal/rewriters/js_reserved_words.rb +5 -3
  59. data/lib/opal/source_map/file.rb +7 -4
  60. data/lib/opal/source_map/map.rb +17 -3
  61. data/lib/opal/version.rb +1 -1
  62. data/opal/corelib/array.rb +2 -2
  63. data/opal/corelib/binding.rb +46 -0
  64. data/opal/corelib/boolean.rb +54 -4
  65. data/opal/corelib/class.rb +2 -0
  66. data/opal/corelib/constants.rb +2 -2
  67. data/opal/corelib/error.rb +98 -12
  68. data/opal/corelib/io.rb +250 -38
  69. data/opal/corelib/kernel/format.rb +5 -2
  70. data/opal/corelib/kernel.rb +44 -23
  71. data/opal/corelib/main.rb +5 -0
  72. data/opal/corelib/method.rb +1 -0
  73. data/opal/corelib/module.rb +28 -0
  74. data/opal/corelib/number.rb +12 -1
  75. data/opal/corelib/random/seedrandom.js.rb +2 -2
  76. data/opal/corelib/regexp.rb +47 -3
  77. data/opal/corelib/runtime.js +152 -12
  78. data/opal/corelib/string/encoding.rb +17 -17
  79. data/opal/corelib/string.rb +2 -0
  80. data/opal/corelib/struct.rb +10 -3
  81. data/opal/corelib/trace_point.rb +57 -0
  82. data/opal/opal/full.rb +2 -0
  83. data/package.json +3 -2
  84. data/spec/filters/bugs/array.rb +0 -1
  85. data/spec/filters/bugs/basicobject.rb +0 -1
  86. data/spec/filters/bugs/binding.rb +27 -0
  87. data/spec/filters/bugs/enumerator.rb +132 -0
  88. data/spec/filters/bugs/exception.rb +70 -93
  89. data/spec/filters/bugs/float.rb +0 -1
  90. data/spec/filters/bugs/kernel.rb +3 -9
  91. data/spec/filters/bugs/language.rb +15 -58
  92. data/spec/filters/bugs/main.rb +16 -0
  93. data/spec/filters/bugs/matrix.rb +39 -0
  94. data/spec/filters/bugs/method.rb +0 -2
  95. data/spec/filters/bugs/module.rb +36 -79
  96. data/spec/filters/bugs/proc.rb +0 -1
  97. data/spec/filters/bugs/regexp.rb +0 -16
  98. data/spec/filters/bugs/trace_point.rb +12 -0
  99. data/spec/filters/bugs/warnings.rb +0 -4
  100. data/spec/filters/unsupported/freeze.rb +2 -0
  101. data/spec/filters/unsupported/privacy.rb +4 -0
  102. data/spec/lib/compiler_spec.rb +7 -1
  103. data/spec/lib/repl_spec.rb +4 -2
  104. data/spec/lib/source_map/file_spec.rb +1 -1
  105. data/spec/mspec-opal/formatters.rb +18 -4
  106. data/spec/mspec-opal/runner.rb +2 -2
  107. data/spec/opal/core/boolean_spec.rb +44 -0
  108. data/spec/opal/core/hash_spec.rb +8 -0
  109. data/spec/opal/core/number/to_s_spec.rb +11 -0
  110. data/spec/opal/stdlib/json/ext_spec.rb +3 -3
  111. data/spec/opal/stdlib/logger/logger_spec.rb +10 -1
  112. data/spec/ruby_specs +18 -0
  113. data/stdlib/await.rb +83 -0
  114. data/stdlib/base64.rb +4 -4
  115. data/stdlib/bigdecimal/bignumber.js.rb +4 -2
  116. data/stdlib/bigdecimal.rb +1 -0
  117. data/stdlib/gjs/io.rb +33 -0
  118. data/stdlib/gjs/kernel.rb +5 -0
  119. data/stdlib/gjs.rb +2 -0
  120. data/stdlib/js.rb +4 -0
  121. data/stdlib/json.rb +3 -3
  122. data/stdlib/logger.rb +1 -1
  123. data/stdlib/nashorn/file.rb +2 -0
  124. data/stdlib/nodejs/env.rb +7 -0
  125. data/stdlib/nodejs/file.rb +6 -41
  126. data/stdlib/nodejs/io.rb +21 -5
  127. data/stdlib/nodejs/js-yaml-3-6-1.js +2 -2
  128. data/stdlib/opal/miniracer.rb +6 -0
  129. data/stdlib/opal/platform.rb +4 -0
  130. data/stdlib/opal/repl_js.rb +5 -0
  131. data/stdlib/opal/replutils.rb +271 -0
  132. data/stdlib/opal-parser.rb +24 -11
  133. data/stdlib/opal-platform.rb +8 -0
  134. data/stdlib/promise/v2.rb +16 -4
  135. data/stdlib/promise.rb +14 -0
  136. data/stdlib/stringio.rb +13 -110
  137. data/stdlib/thread.rb +29 -0
  138. data/tasks/building.rake +10 -4
  139. data/tasks/linting-parse-eslint-results.js +39 -0
  140. data/tasks/linting.rake +38 -28
  141. data/tasks/performance/asciidoctor_test.rb.erb +6 -0
  142. data/tasks/performance/optimization_status.rb +77 -0
  143. data/tasks/performance.rake +149 -0
  144. data/tasks/testing.rake +9 -1
  145. data/test/nodejs/test_await.rb +169 -0
  146. data/test/opal/promisev2/test_error.rb +9 -3
  147. data/test/opal/unsupported_and_bugs.rb +5 -0
  148. data/vendored-minitest/minitest/benchmark.rb +9 -7
  149. data/vendored-minitest/minitest/test.rb +14 -12
  150. data/vendored-minitest/minitest.rb +19 -16
  151. data/yarn.lock +686 -117
  152. metadata +60 -23
  153. data/.jshintrc +0 -41
  154. data/spec/filters/unsupported/refinements.rb +0 -8
  155. data/vendored-minitest/minitest/hell.rb +0 -11
  156. data/vendored-minitest/minitest/parallel.rb +0 -65
  157. data/vendored-minitest/minitest/pride.rb +0 -4
  158. data/vendored-minitest/minitest/pride_plugin.rb +0 -142
  159. data/vendored-minitest/minitest/unit.rb +0 -45
data/tasks/linting.rake CHANGED
@@ -1,42 +1,52 @@
1
1
  import 'tasks/building.rake'
2
- desc "Build *corelib* and *stdlib* and lint the result"
3
- task :jshint do
4
- dir = 'tmp/lint'
5
- puts
6
- puts "= Checking distributed files..."
7
- unless ENV['SKIP_BUILD']
2
+
3
+
4
+ namespace :lint do
5
+ desc "Build *corelib* and *stdlib* and lint the result"
6
+ task :eslint do
7
+ require 'json'
8
+ require 'pathname'
9
+
10
+ result_path = "tmp/lint/result.json"
11
+ dir = ENV['DIR'] ||= 'tmp/lint'
12
+ ENV['FORMATS'] = 'js,map'
8
13
  rm_rf dir if File.exist? dir
9
- ENV['DIR'] = dir
14
+
10
15
  Rake::Task[:dist].invoke
11
- end
12
16
 
13
- Dir["#{dir}/*.js"].each {|path|
14
- # opal-builder and opal-parser take so long travis stalls
15
- next if path =~ /.min.js\z|opal-builder|opal-parser/
16
-
17
- sh "yarn -s run jshint --verbose #{path}"
18
- }
19
- puts
20
- puts "= Checking corelib files separately..."
21
- js_paths = []
22
- Dir['opal/{opal,corelib}/*.rb'].each do |path|
23
- js_path = "#{dir}/#{path.tr('/', '-')}.js"
24
- Bundler::SharedHelpers.set_bundle_environment
25
- File.write js_path, Opal.compile(File.read(path), file: path, dynamic_require_severity: :ignore)
26
- js_paths << js_path
27
- end
28
- js_paths.each do |js_path|
29
- sh "yarn -s run jshint --verbose #{js_path}"
17
+ files = Dir["#{dir}/*.js"]
18
+ es8, es3 = files.partition { |i| i.include? "await" }
19
+
20
+ [es3, es8].each do |files|
21
+ config = (files == es8) ? ["-c", __dir__+"/../.eslintrc.await.js"] : []
22
+
23
+ sh "yarn", "run", "eslint", *config, *files, "--format", "json", "--output-file", result_path do |ok, _|
24
+ if ok
25
+ puts "Successful."
26
+ else
27
+ sh 'node tasks/linting-parse-eslint-results.js'
28
+ # results = JSON.parse File.read(result_path), symbolize_names: true
29
+ # results.each do |data|
30
+ # next if data[:messages].empty?
31
+ #
32
+ # relative_path = Pathname(data[:filePath]).relative_path_from(Pathname(dir).expand_path)
33
+ # puts "* #{relative_path}"
34
+ # data[:messages].each do |message|
35
+ # puts " - #{relative_path}:#{message[:line]}:#{message[:column]}-#{message[:endLine]}:#{message[:endColumn]} #{message[:message]}"
36
+ # end
37
+ # end
38
+ end
39
+ end
40
+ end
30
41
  end
31
- sh 'yarn -s run jshint --verbose opal/corelib/runtime.js'
32
42
  end
33
43
 
34
44
  require 'rubocop/rake_task'
35
45
  desc 'Run RuboCop on lib/, opal/ and stdlib/ directories'
36
- RuboCop::RakeTask.new(:rubocop) do |task|
46
+ RuboCop::RakeTask.new('lint:rubocop') do |task|
37
47
  task.options << '--extra-details'
38
48
  task.options << '--display-style-guide'
39
49
  task.options << '--parallel'
40
50
  end
41
51
 
42
- task :lint => [:jshint, :rubocop]
52
+ task :lint => %w[lint:eslint lint:rubocop]
@@ -0,0 +1,6 @@
1
+ JAVASCRIPT_IO_MODULE="nodejs" if RUBY_ENGINE == 'opal'
2
+ require "asciidoctor"
3
+ puts Asciidoctor.convert(DATA.read)
4
+
5
+ __END__
6
+ <%= File.read('asciidoctor/benchmark/sample-data/mdbasics.adoc') %>
@@ -0,0 +1,77 @@
1
+ klasses = [
2
+ Array,
3
+ Class,
4
+ # Complex,
5
+ # Dir,
6
+ Enumerable,
7
+ Enumerator,
8
+ Exception,
9
+ Hash,
10
+ # Kernel,
11
+ Math,
12
+ Method,
13
+ Module,
14
+ Object,
15
+ Proc,
16
+ Range,
17
+ Rational,
18
+ Regexp,
19
+ Struct,
20
+ String,
21
+ Time
22
+ ]
23
+
24
+ %x{
25
+ function getOptimizationStatus(fn) {
26
+ var optstatus = %GetOptimizationStatus(fn);
27
+
28
+ return (optstatus & (1 << 6)) ? "[INTERPRETED]" : "[COMPILED]";
29
+ }
30
+
31
+ function triggerOptAndGetStatus(fn) {
32
+ // using try/catch to avoid having to call functions properly
33
+ try {
34
+ // Fill type-info
35
+ fn();
36
+ // 2 calls are needed to go from uninitialized -> pre-monomorphic -> monomorphic
37
+ fn();
38
+ }
39
+ catch (e) {}
40
+ %OptimizeFunctionOnNextCall(fn);
41
+ try {
42
+ fn();
43
+ }
44
+ catch (e) {}
45
+ return getOptimizationStatus(fn);
46
+ }
47
+ }
48
+
49
+ optimization_status = Hash[klasses.map do |klass|
50
+ methods = klass.instance_methods
51
+ methods -= Object.instance_methods unless klass == Object
52
+ methods -= [:product, :exit, :exit!, :at_exit]
53
+ opt_status = Hash[methods.map do |method|
54
+ method_func = `#{klass.instance_method(method)}.method`
55
+ [method, `triggerOptAndGetStatus(#{method_func})`]
56
+ end]
57
+ by_status_grouped = opt_status.group_by {|method, status| status }
58
+ as_hash = Hash[by_status_grouped.map do |status, stuff|
59
+ list = stuff.map {|val| val[0]}
60
+ [status, list]
61
+ end]
62
+ [klass, as_hash]
63
+ end]
64
+
65
+ puts '----Report----'
66
+ optimization_status.sort_by {|klass,_| klass.name}.each do |klass, statuses|
67
+ puts "---------------"
68
+ puts "Class #{klass}:"
69
+ puts "---------------"
70
+ statuses.sort_by {|stat,_| stat }.each do |status, methods|
71
+ methods.sort.each do |m|
72
+ puts " #{status} #{m}"
73
+ end
74
+ end
75
+ end
76
+
77
+ puts 'done!'
@@ -0,0 +1,149 @@
1
+ # A set of tasks to track performance regressions by the CI
2
+
3
+ require 'opal/util'
4
+
5
+ # Runs a block N times and returns a mean number of seconds it took to run it.
6
+ mean_time = proc do |tries: 31, &block|
7
+ tries.times.map do
8
+ t = Time.now
9
+ block.()
10
+ Time.now - t
11
+ end.sort[tries/2]
12
+ end
13
+
14
+ failed = false
15
+
16
+ # Mark a failure
17
+ failure = proc do |reason|
18
+ failed ||= []
19
+ failed << reason
20
+ end
21
+
22
+ compare_values = proc do |name, current, previous|
23
+ current = current.to_f
24
+ previous = previous.to_f
25
+
26
+ change = ((current - previous).to_f / previous) * 100
27
+
28
+ puts ("%30s: %.3f -> %.3f (change: %+.2f%%)" % [name, previous, current, change]).gsub('.000','')
29
+
30
+ if change > 5.0
31
+ failure.("#{name} increased by more than 5%")
32
+ end
33
+ end
34
+
35
+ ASCIIDOCTOR_REPO_BASE = ENV['ASCIIDOCTOR_REPO_BASE'] || 'https://github.com/asciidoctor'
36
+
37
+ # Selected asciidoctor versions were working on Aug 19 2021, feel free to update.
38
+ ASCIIDOCTOR_PREPARE = [
39
+ "bundle",
40
+ "exec",
41
+ "bash",
42
+ "-c",
43
+ <<~BASH
44
+ mkdir -p tmp/performance
45
+ pushd tmp/performance
46
+ git clone #{ASCIIDOCTOR_REPO_BASE}/asciidoctor >/dev/null 2>&1
47
+ pushd asciidoctor; git checkout 869e8236 >/dev/null 2>&1; popd
48
+ git clone #{ASCIIDOCTOR_REPO_BASE}/asciidoctor.js >/dev/null 2>&1
49
+ pushd asciidoctor.js; git checkout 053fa0d3 >/dev/null 2>&1; popd
50
+ erb ../../tasks/performance/asciidoctor_test.rb.erb > asciidoctor_test.rb
51
+ popd
52
+ BASH
53
+ ]
54
+
55
+ ASCIIDOCTOR_BUILD_OPAL = "bin/opal --no-cache -c " \
56
+ "-Itmp/performance/asciidoctor/lib " \
57
+ "-Itmp/performance/asciidoctor.js/packages/core/lib " \
58
+ "tmp/performance/asciidoctor_test.rb > tmp/performance/asciidoctor_test.js"
59
+ ASCIIDOCTOR_RUN_RUBY = "bundle exec ruby -Itmp/performance/asciidoctor/lib tmp/performance/asciidoctor_test.rb"
60
+ ASCIIDOCTOR_RUN_OPAL = "node tmp/performance/asciidoctor_test.js"
61
+
62
+ # Generate V8 function optimization status report for corelib methods
63
+ NODE_OPTSTATUS = "env NODE_OPTS=--allow-natives-syntax bin/opal tasks/performance/optimization_status.rb"
64
+
65
+ performance_stat = ->(name) {
66
+ stat = {}
67
+
68
+ # Run on current
69
+ puts "\n* Checking optimization status with #{name}..."
70
+ sh("#{NODE_OPTSTATUS} > tmp/performance/optstatus_#{name}")
71
+
72
+ puts "\n* Building AsciiDoctor with #{name}..."
73
+ stat[:compiler_time] = mean_time.(tries: 3) { sh(ASCIIDOCTOR_BUILD_OPAL) }
74
+
75
+ puts "\n* Running AsciiDoctor with #{name}..."
76
+ stat[:run_time] = mean_time.(tries: 31) { sh("#{ASCIIDOCTOR_RUN_OPAL} > tmp/performance/opal_result_#{name}.html") }
77
+ stat[:correct] = File.read("tmp/performance/opal_result_#{name}.html") == File.read("tmp/performance/ruby_result.html")
78
+ stat[:size] = File.size("tmp/performance/asciidoctor_test.js")
79
+
80
+ puts "\n* Minifying AsciiDoctor with #{name}..."
81
+ stat[:min_size] = Opal::Util.uglify(File.read("tmp/performance/asciidoctor_test.js")).bytesize rescue Float::INFINITY
82
+
83
+ stat
84
+ }
85
+
86
+ namespace :performance do
87
+ task :compare do
88
+ this_ref = `git describe --tags`.chomp
89
+ ref = 'master'
90
+ ref = ENV['GITHUB_BASE_REF'] if ENV['GITHUB_BASE_REF'] && !ENV['GITHUB_BASE_REF'].empty?
91
+
92
+ # Prepare
93
+ puts "\n* Preparing asciidoctor..."
94
+ sh(*ASCIIDOCTOR_PREPARE)
95
+
96
+ puts "\n* Running AsciiDoctor with CRuby..."
97
+ sh("#{ASCIIDOCTOR_RUN_RUBY} > tmp/performance/ruby_result.html")
98
+
99
+ current = performance_stat.(:current)
100
+
101
+ # Prepare previous
102
+ sh("git checkout --recurse-submodules #{ref} && bundle install >/dev/null 2>&1")
103
+
104
+ previous = performance_stat.(:previous)
105
+
106
+ # Restore current
107
+ sh("git checkout --recurse-submodules - && bundle install >/dev/null 2>&1")
108
+
109
+ # Summary
110
+ puts "\n=== Summary ==="
111
+ puts "Summary of performance changes between (previous) #{ref} and (current) #{this_ref}:"
112
+
113
+ diff = `diff --report-identical-files -F '^Class' -Naur tmp/performance/optstatus_previous tmp/performance/optstatus_current`
114
+ diff_lines = diff.split("\n")
115
+
116
+ puts
117
+ puts "Comparison of V8 function optimization status:"
118
+ puts diff
119
+
120
+ if diff_lines.grep(/^-\s+\[COMPILED\]/).count > 0
121
+ failure.("Some methods are no longer compiled on V8")
122
+ end
123
+
124
+ puts
125
+ puts "Comparison of the Asciidoctor (a real-life Opal application) compile and run:"
126
+
127
+ failure.("Wrong result on the current branch") unless current[:correct]
128
+ failure.("Wrong result on the previous branch - ignore it") unless previous[:correct]
129
+
130
+ compare_values.("Compile time", current[:compiler_time], previous[:compiler_time])
131
+ compare_values.("Run time", current[:run_time], previous[:run_time])
132
+ compare_values.("Bundle size", current[:size], previous[:size])
133
+ compare_values.("Minified bundle size", current[:min_size], previous[:min_size])
134
+
135
+ if failed
136
+ puts "--- Failures ---"
137
+ failed.each do |f|
138
+ puts " - #{f}"
139
+ end
140
+ puts
141
+ puts "This run failed - some performance checks did not pass. Don't worry, this is"
142
+ puts "informative, not fatal. It may be worth to rerun the task, rebase the branch,"
143
+ puts "or consult those results with a pull request reviewer."
144
+ fail
145
+ end
146
+ end
147
+ end
148
+
149
+ task :performance => ['performance:compare']
data/tasks/testing.rake CHANGED
@@ -284,7 +284,7 @@ Use PATTERN environment variable to manually set the glob for specs:
284
284
  bundle exec rake mspec_nodejs PATTERN=spec/ruby/core/numeric/**_spec.rb
285
285
  DESC
286
286
 
287
- platforms = %w[nodejs server chrome]
287
+ platforms = %w[nodejs server chrome gjs]
288
288
  mspec_suites = %w[ruby opal]
289
289
  minitest_suites = %w[cruby]
290
290
 
@@ -331,6 +331,13 @@ platforms.each do |platform|
331
331
  opal/test_openuri.rb
332
332
  opal/unsupported_and_bugs.rb
333
333
  opal/test_matrix.rb
334
+ opal/promisev2/test_always.rb
335
+ opal/promisev2/test_error.rb
336
+ opal/promisev2/test_rescue.rb
337
+ opal/promisev2/test_then.rb
338
+ opal/promisev2/test_trace.rb
339
+ opal/promisev2/test_value.rb
340
+ opal/promisev2/test_when.rb
334
341
  ]
335
342
  end
336
343
  Testing::HTTPServer.new.with_server do |session|
@@ -363,6 +370,7 @@ task :minitest_node_nodejs do
363
370
  nodejs/test_io.rb
364
371
  nodejs/test_opal_builder.rb
365
372
  nodejs/test_string.rb
373
+ nodejs/test_await.rb
366
374
  ]
367
375
 
368
376
  filename = "tmp/minitest_node_nodejs.rb"
@@ -0,0 +1,169 @@
1
+ # frozen_string_literal: true
2
+ # await: true
3
+
4
+ require "test/unit"
5
+
6
+ class TestAwait < Test::Unit::TestCase
7
+ stdheader = <<~RUBY
8
+ # await: true
9
+ require "await"
10
+ RUBY
11
+
12
+ tests = {
13
+ test_await_in_top: [<<~RUBY, 6],
14
+ #{stdheader}
15
+ $taval = 5
16
+ sleep(0.001).__await__
17
+ $taval = 6
18
+ RUBY
19
+ test_await_in_method: [<<~RUBY, 7],
20
+ #{stdheader}
21
+ $taval = 5
22
+ def xx_taim
23
+ sleep(0.001).__await__
24
+ $taval = 7
25
+ end
26
+ xx_taim.__await__
27
+ RUBY
28
+ test_await_in_block: [<<~RUBY, 0],
29
+ #{stdheader}
30
+ $taval = 5
31
+ xx_taib = proc do
32
+ sleep(0.001).__await__
33
+ $taval = 0
34
+ end
35
+ xx_taib.().__await__
36
+ RUBY
37
+ test_await_in_instance_method: [<<~RUBY, 3],
38
+ #{stdheader}
39
+ $taval = 5
40
+ class XXTaiim
41
+ def xx_taiim
42
+ sleep(0.001).__await__
43
+ $taval = 3
44
+ end
45
+ end
46
+ XXTaiim.new.xx_taiim.__await__
47
+ RUBY
48
+ test_await_in_class_method: [<<~RUBY, 4],
49
+ #{stdheader}
50
+ $taval = 5
51
+ class XXTaicm
52
+ def self.xx_taicm
53
+ sleep(0.001).__await__
54
+ $taval = 4
55
+ end
56
+ end
57
+ XXTaicm.xx_taicm.__await__
58
+ RUBY
59
+ test_await_on_promise: [<<~RUBY, 8],
60
+ #{stdheader}
61
+ $taval = PromiseV2.value(8).__await__
62
+ RUBY
63
+ test_await_in_while: [<<~RUBY, 9],
64
+ #{stdheader}
65
+ $taval = 5
66
+ begin
67
+ sleep(0.001).__await__
68
+ $taval = 9
69
+ end while false
70
+ RUBY
71
+ test_await_in_while_expr: [<<~RUBY, -9],
72
+ #{stdheader}
73
+ $taval = 5
74
+ x = if true
75
+ begin
76
+ sleep(0.001).__await__
77
+ $taval = -9
78
+ end while false
79
+ end
80
+ RUBY
81
+ test_await_in_case: [<<~RUBY, 88],
82
+ #{stdheader}
83
+ $taval = 5
84
+ case true
85
+ when true
86
+ sleep(0.001).__await__
87
+ $taval = 88
88
+ end
89
+ RUBY
90
+ test_await_in_case_expr: [<<~RUBY, 99],
91
+ #{stdheader}
92
+ $taval = 5
93
+ x = case true
94
+ when true
95
+ sleep(0.001).__await__
96
+ $taval = 99
97
+ end
98
+ RUBY
99
+ test_await_in_rescue: [<<~RUBY, 10],
100
+ #{stdheader}
101
+ $taval = 5
102
+ begin
103
+ sleep(0.001).__await__
104
+ nomethoderror
105
+ rescue
106
+ sleep(0.001).__await__
107
+ $taval = 10
108
+ end
109
+ RUBY
110
+ test_await_in_ensure: [<<~RUBY, 11],
111
+ #{stdheader}
112
+ $taval = 5
113
+ begin
114
+ sleep(0.001).__await__
115
+ nomethoderror
116
+ rescue
117
+ sleep(0.001).__await__
118
+ ensure
119
+ sleep(0.001).__await__
120
+ $taval = 11
121
+ end
122
+ RUBY
123
+ test_await_in_ensure_expr: [<<~RUBY, -11],
124
+ #{stdheader}
125
+ $taval = 5
126
+ x = begin
127
+ sleep(0.001).__await__
128
+ nomethoderror
129
+ rescue
130
+ sleep(0.001).__await__
131
+ ensure
132
+ sleep(0.001).__await__
133
+ $taval = -11
134
+ end
135
+ RUBY
136
+ test_await_in_module: [<<~RUBY, 12],
137
+ #{stdheader}
138
+ $taval = 5
139
+ module XYTaim
140
+ sleep(0.001).__await__
141
+ $taval = 12
142
+ end
143
+ RUBY
144
+ test_await_in_class: [<<~RUBY, 13],
145
+ #{stdheader}
146
+ $taval = 5
147
+ class XYTaic
148
+ sleep(0.001).__await__
149
+ $taval = 13
150
+ end
151
+ RUBY
152
+ test_await_in_and: [<<~RUBY, 14],
153
+ #{stdheader}
154
+ ($taval = 5) && (PromiseV2.value(4).__await__) && ($taval = 14)
155
+ RUBY
156
+ test_await_in_plus: [<<~RUBY, 15],
157
+ #{stdheader}
158
+ $taval = 5
159
+ $taval = PromiseV2.value(5).__await__ + 10
160
+ RUBY
161
+ }
162
+
163
+ tests.each do |name,(code,expect)|
164
+ define_method name do
165
+ eval(code).__await__
166
+ assert_equal(expect, $taval)
167
+ end
168
+ end
169
+ end
@@ -3,14 +3,20 @@ require 'promise/v2'
3
3
 
4
4
  class TestPromiseError < Test::Unit::TestCase
5
5
  def test_rejects_the_promise_with_the_given_error
6
- assert_equal(PromiseV2.error(23).error, 23)
6
+ prom = PromiseV2.error(23)
7
+ assert_equal(prom.error, 23)
8
+ prom.rescue{} # Needed, otherwise we have an uncaught exception
7
9
  end
8
10
 
9
11
  def test_marks_the_promise_as_realized
10
- assert_equal(PromiseV2.error(23).realized?, true)
12
+ prom = PromiseV2.error(23)
13
+ assert_equal(prom.realized?, true)
14
+ prom.rescue{} # Needed, otherwise we have an uncaught exception
11
15
  end
12
16
 
13
17
  def test_marks_the_promise_as_rejected
14
- assert_equal(PromiseV2.error(23).rejected?, true)
18
+ prom = PromiseV2.error(23)
19
+ assert_equal(prom.rejected?, true)
20
+ prom.rescue{}
15
21
  end
16
22
  end
@@ -37,3 +37,8 @@ class TestCall
37
37
  unsupported :test_safe_call_block_call_brace
38
38
  unsupported :test_safe_call_block_call_command
39
39
  end
40
+
41
+ class TestBenchmark
42
+ # sleep is unsupported if not awaited
43
+ unsupported :test_realtime_output
44
+ end
@@ -1,3 +1,5 @@
1
+ # await: *await*
2
+
1
3
  require 'minitest/unit'
2
4
  require 'minitest/spec'
3
5
 
@@ -88,10 +90,10 @@ module Minitest
88
90
 
89
91
  times = []
90
92
 
91
- range.each do |x|
93
+ range.each_await do |x|
92
94
  GC.start
93
95
  t0 = Time.now
94
- instance_exec(x, &work)
96
+ instance_exec(x, &work).await
95
97
  t = Time.now - t0
96
98
 
97
99
  io.print "\t%9.6f" % t
@@ -132,7 +134,7 @@ module Minitest
132
134
  [a, b, rr]
133
135
  end
134
136
 
135
- assert_performance validation, &work
137
+ assert_performance(validation, &work).await
136
138
  end
137
139
 
138
140
  ##
@@ -152,7 +154,7 @@ module Minitest
152
154
  # end
153
155
 
154
156
  def assert_performance_exponential threshold = 0.99, &work
155
- assert_performance validation_for_fit(:exponential, threshold), &work
157
+ assert_performance(validation_for_fit(:exponential, threshold), &work).await
156
158
  end
157
159
 
158
160
  ##
@@ -172,7 +174,7 @@ module Minitest
172
174
  # end
173
175
 
174
176
  def assert_performance_logarithmic threshold = 0.99, &work
175
- assert_performance validation_for_fit(:logarithmic, threshold), &work
177
+ assert_performance(validation_for_fit(:logarithmic, threshold), &work).await
176
178
  end
177
179
 
178
180
  ##
@@ -192,7 +194,7 @@ module Minitest
192
194
  # end
193
195
 
194
196
  def assert_performance_linear threshold = 0.99, &work
195
- assert_performance validation_for_fit(:linear, threshold), &work
197
+ assert_performance(validation_for_fit(:linear, threshold), &work).await
196
198
  end
197
199
 
198
200
  ##
@@ -212,7 +214,7 @@ module Minitest
212
214
  # end
213
215
 
214
216
  def assert_performance_power threshold = 0.99, &work
215
- assert_performance validation_for_fit(:power, threshold), &work
217
+ assert_performance(validation_for_fit(:power, threshold), &work).await
216
218
  end
217
219
 
218
220
  ##
@@ -1,3 +1,5 @@
1
+ # await: *await*
2
+
1
3
  require "minitest" unless defined? Minitest::Runnable
2
4
 
3
5
  module Minitest
@@ -105,16 +107,16 @@ module Minitest
105
107
  capture_exceptions do
106
108
  before_setup; setup; after_setup
107
109
 
108
- self.send self.name
109
- end
110
+ self.send(self.name).await
111
+ end.await
110
112
 
111
- TEARDOWN_METHODS.each do |hook|
113
+ TEARDOWN_METHODS.each_await do |hook|
112
114
  capture_exceptions do
113
- self.send hook
114
- end
115
- end
116
- end
117
- end
115
+ self.send(hook).await
116
+ end.await
117
+ end.await
118
+ end.await
119
+ end.await
118
120
 
119
121
  self # per contract
120
122
  end
@@ -202,7 +204,7 @@ module Minitest
202
204
  end # LifecycleHooks
203
205
 
204
206
  def capture_exceptions # :nodoc:
205
- yield
207
+ yield.await
206
208
  rescue *PASSTHROUGH_EXCEPTIONS
207
209
  raise
208
210
  rescue Assertion => e
@@ -253,7 +255,7 @@ module Minitest
253
255
  def time_it # :nodoc:
254
256
  t0 = Time.now
255
257
 
256
- yield
258
+ yield.await
257
259
  ensure
258
260
  self.time = Time.now - t0
259
261
  end
@@ -273,7 +275,7 @@ module Minitest
273
275
  warn "\nCurrent: %s#%s %.2fs" % [self.class, self.name, Time.now - t0]
274
276
  end
275
277
 
276
- self.class.on_signal "INFO", handler, &block
278
+ self.class.on_signal("INFO", handler, &block).await
277
279
  end
278
280
 
279
281
  include LifecycleHooks
@@ -282,4 +284,4 @@ module Minitest
282
284
  end # Test
283
285
  end
284
286
 
285
- require "minitest/unit" unless defined?(MiniTest) # compatibility layer only
287
+ # require "minitest/unit" unless defined?(MiniTest) # compatibility layer only