opal 1.6.1 → 1.7.0

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 (212) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/build.yml +17 -0
  3. data/CHANGELOG.md +35 -1
  4. data/Gemfile +1 -0
  5. data/HACKING.md +47 -26
  6. data/benchmark/benchmarks +415 -103
  7. data/benchmark/bm_call_overhead.yml +28 -0
  8. data/benchmark/run.rb +61 -40
  9. data/docs/cdp_common.json +3364 -0
  10. data/docs/cdp_common.md +18 -0
  11. data/docs/{headless_chrome.md → headless_browsers.md} +31 -12
  12. data/lib/opal/ast/builder.rb +1 -1
  13. data/lib/opal/builder.rb +6 -1
  14. data/lib/opal/builder_processors.rb +5 -3
  15. data/lib/opal/cache.rb +1 -7
  16. data/lib/opal/cli_options.rb +72 -58
  17. data/lib/opal/cli_runners/chrome.rb +47 -9
  18. data/lib/opal/cli_runners/chrome_cdp_interface.rb +238 -112
  19. data/lib/opal/cli_runners/compiler.rb +146 -13
  20. data/lib/opal/cli_runners/deno.rb +32 -0
  21. data/lib/opal/cli_runners/firefox.rb +350 -0
  22. data/lib/opal/cli_runners/firefox_cdp_interface.rb +212 -0
  23. data/lib/opal/cli_runners/node_modules/.bin/chrome-remote-interface.cmd +17 -0
  24. data/lib/opal/cli_runners/node_modules/.bin/chrome-remote-interface.ps1 +28 -0
  25. data/lib/opal/cli_runners/node_modules/.package-lock.json +41 -0
  26. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/LICENSE +1 -1
  27. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/README.md +322 -182
  28. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/bin/client.js +99 -114
  29. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/chrome-remote-interface.js +1 -11
  30. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/index.js +16 -11
  31. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/api.js +41 -33
  32. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/chrome.js +224 -214
  33. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/devtools.js +71 -191
  34. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/external-request.js +26 -6
  35. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/protocol.json +20788 -9049
  36. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/lib/websocket-wrapper.js +10 -3
  37. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/package.json +59 -123
  38. data/lib/opal/cli_runners/node_modules/chrome-remote-interface/webpack.config.js +25 -32
  39. data/lib/opal/cli_runners/node_modules/commander/History.md +298 -0
  40. data/lib/opal/cli_runners/node_modules/commander/LICENSE +22 -0
  41. data/lib/opal/cli_runners/node_modules/commander/Readme.md +217 -61
  42. data/lib/opal/cli_runners/node_modules/commander/index.js +431 -145
  43. data/lib/opal/cli_runners/node_modules/commander/package.json +16 -79
  44. data/lib/opal/cli_runners/node_modules/ws/README.md +334 -98
  45. data/lib/opal/cli_runners/node_modules/ws/browser.js +8 -0
  46. data/lib/opal/cli_runners/node_modules/ws/index.js +5 -10
  47. data/lib/opal/cli_runners/node_modules/ws/lib/buffer-util.js +129 -0
  48. data/lib/opal/cli_runners/node_modules/ws/lib/constants.js +10 -0
  49. data/lib/opal/cli_runners/node_modules/ws/lib/event-target.js +184 -0
  50. data/lib/opal/cli_runners/node_modules/ws/lib/extension.js +223 -0
  51. data/lib/opal/cli_runners/node_modules/ws/lib/limiter.js +55 -0
  52. data/lib/opal/cli_runners/node_modules/ws/lib/permessage-deflate.js +518 -0
  53. data/lib/opal/cli_runners/node_modules/ws/lib/receiver.js +607 -0
  54. data/lib/opal/cli_runners/node_modules/ws/lib/sender.js +409 -0
  55. data/lib/opal/cli_runners/node_modules/ws/lib/stream.js +180 -0
  56. data/lib/opal/cli_runners/node_modules/ws/lib/validation.js +104 -0
  57. data/lib/opal/cli_runners/node_modules/ws/lib/websocket-server.js +447 -0
  58. data/lib/opal/cli_runners/node_modules/ws/lib/websocket.js +1195 -0
  59. data/lib/opal/cli_runners/node_modules/ws/package.json +40 -106
  60. data/lib/opal/cli_runners/package-lock.json +62 -0
  61. data/lib/opal/cli_runners/package.json +1 -1
  62. data/lib/opal/cli_runners.rb +26 -4
  63. data/lib/opal/nodes/args/prepare_post_args.rb +2 -2
  64. data/lib/opal/nodes/def.rb +8 -8
  65. data/lib/opal/nodes/iter.rb +12 -12
  66. data/lib/opal/nodes/logic.rb +1 -1
  67. data/lib/opal/nodes/masgn.rb +2 -2
  68. data/lib/opal/parser/with_ruby_lexer.rb +1 -1
  69. data/lib/opal/paths.rb +14 -0
  70. data/lib/opal/rewriter.rb +2 -0
  71. data/lib/opal/rewriters/forward_args.rb +52 -4
  72. data/lib/opal/rewriters/targeted_patches.rb +94 -0
  73. data/lib/opal/version.rb +1 -1
  74. data/opal/corelib/basic_object.rb +1 -1
  75. data/opal/corelib/boolean.rb +2 -2
  76. data/opal/corelib/class.rb +11 -0
  77. data/opal/corelib/constants.rb +3 -3
  78. data/opal/corelib/enumerable.rb +4 -0
  79. data/opal/corelib/enumerator.rb +1 -1
  80. data/opal/corelib/hash.rb +2 -2
  81. data/opal/corelib/helpers.rb +1 -1
  82. data/opal/corelib/kernel.rb +3 -3
  83. data/opal/corelib/method.rb +1 -1
  84. data/opal/corelib/module.rb +29 -8
  85. data/opal/corelib/proc.rb +7 -5
  86. data/opal/corelib/runtime.js +141 -78
  87. data/opal/corelib/set.rb +252 -0
  88. data/opal/corelib/string.rb +2 -1
  89. data/opal/corelib/time.rb +2 -2
  90. data/opal/opal.rb +1 -0
  91. data/opal.gemspec +1 -0
  92. data/spec/filters/bugs/array.rb +22 -13
  93. data/spec/filters/bugs/base64.rb +5 -5
  94. data/spec/filters/bugs/basicobject.rb +16 -8
  95. data/spec/filters/bugs/bigdecimal.rb +161 -160
  96. data/spec/filters/bugs/binding.rb +10 -10
  97. data/spec/filters/bugs/class.rb +8 -8
  98. data/spec/filters/bugs/complex.rb +2 -1
  99. data/spec/filters/bugs/date.rb +79 -81
  100. data/spec/filters/bugs/datetime.rb +29 -29
  101. data/spec/filters/bugs/delegate.rb +1 -3
  102. data/spec/filters/bugs/encoding.rb +69 -69
  103. data/spec/filters/bugs/enumerable.rb +22 -20
  104. data/spec/filters/bugs/enumerator.rb +88 -85
  105. data/spec/filters/bugs/exception.rb +46 -40
  106. data/spec/filters/bugs/file.rb +32 -32
  107. data/spec/filters/bugs/float.rb +26 -21
  108. data/spec/filters/bugs/freeze.rb +88 -0
  109. data/spec/filters/bugs/hash.rb +39 -38
  110. data/spec/filters/bugs/integer.rb +57 -44
  111. data/spec/filters/bugs/io.rb +1 -1
  112. data/spec/filters/bugs/kernel.rb +349 -269
  113. data/spec/filters/bugs/language.rb +220 -188
  114. data/spec/filters/bugs/main.rb +5 -3
  115. data/spec/filters/bugs/marshal.rb +38 -38
  116. data/spec/filters/bugs/math.rb +2 -1
  117. data/spec/filters/bugs/method.rb +73 -62
  118. data/spec/filters/bugs/module.rb +163 -143
  119. data/spec/filters/bugs/numeric.rb +6 -6
  120. data/spec/filters/bugs/objectspace.rb +16 -16
  121. data/spec/filters/bugs/openstruct.rb +1 -1
  122. data/spec/filters/bugs/pack_unpack.rb +51 -51
  123. data/spec/filters/bugs/pathname.rb +7 -7
  124. data/spec/filters/bugs/proc.rb +63 -63
  125. data/spec/filters/bugs/random.rb +7 -6
  126. data/spec/filters/bugs/range.rb +12 -9
  127. data/spec/filters/bugs/rational.rb +8 -7
  128. data/spec/filters/bugs/regexp.rb +49 -48
  129. data/spec/filters/bugs/ruby-32.rb +56 -0
  130. data/spec/filters/bugs/set.rb +30 -30
  131. data/spec/filters/bugs/singleton.rb +4 -4
  132. data/spec/filters/bugs/string.rb +187 -99
  133. data/spec/filters/bugs/stringio.rb +7 -0
  134. data/spec/filters/bugs/stringscanner.rb +68 -68
  135. data/spec/filters/bugs/struct.rb +11 -9
  136. data/spec/filters/bugs/symbol.rb +1 -1
  137. data/spec/filters/bugs/time.rb +78 -63
  138. data/spec/filters/bugs/trace_point.rb +4 -4
  139. data/spec/filters/bugs/unboundmethod.rb +32 -17
  140. data/spec/filters/bugs/warnings.rb +8 -12
  141. data/spec/filters/unsupported/array.rb +24 -107
  142. data/spec/filters/unsupported/basicobject.rb +12 -12
  143. data/spec/filters/unsupported/bignum.rb +27 -52
  144. data/spec/filters/unsupported/class.rb +1 -2
  145. data/spec/filters/unsupported/delegator.rb +3 -3
  146. data/spec/filters/unsupported/enumerable.rb +2 -9
  147. data/spec/filters/unsupported/enumerator.rb +2 -11
  148. data/spec/filters/unsupported/file.rb +1 -1
  149. data/spec/filters/unsupported/float.rb +28 -47
  150. data/spec/filters/unsupported/hash.rb +8 -14
  151. data/spec/filters/unsupported/integer.rb +75 -91
  152. data/spec/filters/unsupported/kernel.rb +17 -35
  153. data/spec/filters/unsupported/language.rb +11 -19
  154. data/spec/filters/unsupported/marshal.rb +22 -41
  155. data/spec/filters/unsupported/matchdata.rb +28 -52
  156. data/spec/filters/unsupported/math.rb +1 -1
  157. data/spec/filters/unsupported/privacy.rb +229 -285
  158. data/spec/filters/unsupported/range.rb +1 -5
  159. data/spec/filters/unsupported/regexp.rb +40 -66
  160. data/spec/filters/unsupported/set.rb +2 -2
  161. data/spec/filters/unsupported/singleton.rb +4 -4
  162. data/spec/filters/unsupported/string.rb +305 -508
  163. data/spec/filters/unsupported/struct.rb +3 -4
  164. data/spec/filters/unsupported/symbol.rb +15 -18
  165. data/spec/filters/unsupported/thread.rb +1 -7
  166. data/spec/filters/unsupported/time.rb +159 -202
  167. data/spec/filters/unsupported/usage_of_files.rb +170 -259
  168. data/spec/lib/builder_spec.rb +4 -4
  169. data/spec/lib/rewriters/forward_args_spec.rb +32 -12
  170. data/spec/mspec-opal/runner.rb +2 -0
  171. data/spec/ruby_specs +4 -0
  172. data/stdlib/deno/base.rb +28 -0
  173. data/stdlib/deno/file.rb +340 -0
  174. data/stdlib/{headless_chrome.rb → headless_browser/base.rb} +1 -1
  175. data/stdlib/headless_browser/file.rb +15 -0
  176. data/stdlib/headless_browser.rb +4 -0
  177. data/stdlib/native.rb +1 -1
  178. data/stdlib/nodejs/file.rb +5 -0
  179. data/stdlib/opal/platform.rb +8 -6
  180. data/stdlib/opal-platform.rb +14 -8
  181. data/stdlib/set.rb +1 -258
  182. data/tasks/benchmarking.rake +62 -19
  183. data/tasks/performance.rake +1 -1
  184. data/tasks/testing.rake +5 -3
  185. data/test/nodejs/test_file.rb +29 -10
  186. data/test/opal/http_server.rb +28 -11
  187. data/test/opal/unsupported_and_bugs.rb +2 -1
  188. metadata +89 -50
  189. data/lib/opal/cli_runners/node_modules/ultron/LICENSE +0 -22
  190. data/lib/opal/cli_runners/node_modules/ultron/index.js +0 -138
  191. data/lib/opal/cli_runners/node_modules/ultron/package.json +0 -112
  192. data/lib/opal/cli_runners/node_modules/ws/SECURITY.md +0 -33
  193. data/lib/opal/cli_runners/node_modules/ws/lib/BufferUtil.fallback.js +0 -56
  194. data/lib/opal/cli_runners/node_modules/ws/lib/BufferUtil.js +0 -15
  195. data/lib/opal/cli_runners/node_modules/ws/lib/ErrorCodes.js +0 -28
  196. data/lib/opal/cli_runners/node_modules/ws/lib/EventTarget.js +0 -158
  197. data/lib/opal/cli_runners/node_modules/ws/lib/Extensions.js +0 -69
  198. data/lib/opal/cli_runners/node_modules/ws/lib/PerMessageDeflate.js +0 -339
  199. data/lib/opal/cli_runners/node_modules/ws/lib/Receiver.js +0 -520
  200. data/lib/opal/cli_runners/node_modules/ws/lib/Sender.js +0 -438
  201. data/lib/opal/cli_runners/node_modules/ws/lib/Validation.fallback.js +0 -9
  202. data/lib/opal/cli_runners/node_modules/ws/lib/Validation.js +0 -17
  203. data/lib/opal/cli_runners/node_modules/ws/lib/WebSocket.js +0 -705
  204. data/lib/opal/cli_runners/node_modules/ws/lib/WebSocketServer.js +0 -336
  205. data/spec/filters/bugs/boolean.rb +0 -3
  206. data/spec/filters/bugs/matrix.rb +0 -3
  207. data/spec/filters/unsupported/fixnum.rb +0 -15
  208. data/spec/filters/unsupported/freeze.rb +0 -102
  209. data/spec/filters/unsupported/pathname.rb +0 -4
  210. data/spec/filters/unsupported/proc.rb +0 -4
  211. data/spec/filters/unsupported/random.rb +0 -5
  212. data/spec/filters/unsupported/taint.rb +0 -162
@@ -30,8 +30,8 @@ RSpec.describe Opal::Builder do
30
30
 
31
31
  it 'compiles them as empty files' do
32
32
  source = 'require "foo"'
33
- expect(ruby_processor).to receive('new').with(source, anything, anything).once.and_call_original
34
- expect(ruby_processor).to receive('new').with('', anything, anything).once.and_call_original
33
+ expect(ruby_processor).to receive('new').with(source, anything, anything, anything).once.and_call_original
34
+ expect(ruby_processor).to receive('new').with('', anything, anything, anything).once.and_call_original
35
35
 
36
36
  builder.build_str(source, 'bar.rb')
37
37
  end
@@ -53,8 +53,8 @@ RSpec.describe Opal::Builder do
53
53
 
54
54
  it 'compiles them as empty files' do
55
55
  source = 'puts 5'
56
- expect(ruby_processor).to receive('new').with(anything, './base64.rb', anything).once.and_call_original
57
- expect(ruby_processor).to receive('new').with(source, anything, anything).once.and_call_original
56
+ expect(ruby_processor).to receive('new').with(anything, './base64.rb', anything, anything).once.and_call_original
57
+ expect(ruby_processor).to receive('new').with(source, anything, anything, anything).once.and_call_original
58
58
 
59
59
  builder.build_str(source, 'bar.rb')
60
60
  end
@@ -15,6 +15,8 @@ RSpec.describe Opal::Rewriters::ForwardArgs do
15
15
  end.yield_self { |children| s(ast.type, *children) }
16
16
  when :fwd_rest
17
17
  "$fwd_rest"
18
+ when :fwd_kwrest
19
+ "$fwd_kwrest"
18
20
  when :fwd_block
19
21
  "$fwd_block"
20
22
  else
@@ -32,6 +34,36 @@ RSpec.describe Opal::Rewriters::ForwardArgs do
32
34
  end
33
35
  ENDDEST
34
36
 
37
+ include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
38
+ def forward_star(*)
39
+ other(*)
40
+ end
41
+ ENDSOURCE
42
+ def forward_star(*fwd_rest)
43
+ other(*fwd_rest)
44
+ end
45
+ ENDDEST
46
+
47
+ include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
48
+ def forward_kwstar(**)
49
+ other(**)
50
+ end
51
+ ENDSOURCE
52
+ def forward_kwstar(**fwd_kwrest)
53
+ other(**fwd_kwrest)
54
+ end
55
+ ENDDEST
56
+
57
+ include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
58
+ def forward_block(&)
59
+ other(&)
60
+ end
61
+ ENDSOURCE
62
+ def forward_block(&fwd_block)
63
+ other(&fwd_block)
64
+ end
65
+ ENDDEST
66
+
35
67
  include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(ast_of(<<~ENDDEST))
36
68
  def forward(first_arg, ...)
37
69
  other(first_arg, second_arg, ...)
@@ -45,16 +77,4 @@ RSpec.describe Opal::Rewriters::ForwardArgs do
45
77
  other(*fwd_rest, &fwd_block)
46
78
  end
47
79
  ENDDEST
48
-
49
- # Not supported by the parser (nor by the rewriter which would have to rearrange the arguments)
50
-
51
- # include_examples 'it rewrites source-to-AST', <<~ENDSOURCE, correct_names.(parse(<<~ENDDEST))
52
- # def forward(a:, ...)
53
- # other(...)
54
- # end
55
- # ENDSOURCE
56
- # def forward(*fwd_rest, a:, &fwd_block)
57
- # other(*fwd_rest, &fwd_block)
58
- # end
59
- # ENDDEST
60
80
  end
@@ -79,6 +79,8 @@ class OSpecFormatter
79
79
  'browser' => BrowserFormatter,
80
80
  'server' => BrowserFormatter,
81
81
  'chrome' => DottedFormatter,
82
+ 'firefox' => DottedFormatter,
83
+ 'deno' => NodeJSFormatter,
82
84
  'node' => NodeJSFormatter,
83
85
  'nodejs' => NodeJSFormatter,
84
86
  'gjs' => ColoredDottedFormatter,
data/spec/ruby_specs CHANGED
@@ -37,6 +37,8 @@ ruby/core/comparable
37
37
  ruby/core/complex
38
38
  !ruby/core/complex/marshal_dump_spec
39
39
 
40
+ ruby/core/data
41
+
40
42
  ruby/core/enumerable
41
43
  ruby/core/enumerator
42
44
  ruby/core/enumerator/arithmetic_sequence
@@ -126,6 +128,8 @@ ruby/core/rational
126
128
  ruby/core/regexp
127
129
  ruby/core/random
128
130
 
131
+ ruby/core/refinement
132
+
129
133
  ruby/core/string
130
134
  !ruby/core/string/crypt_spec
131
135
  !ruby/core/string/scrub_spec
@@ -0,0 +1,28 @@
1
+ module Deno
2
+ VERSION = `Deno.version.deno`
3
+ end
4
+
5
+ `Opal.exit = Deno.exit`
6
+
7
+ ARGV = `Deno.args.slice(2)`
8
+ ARGV.shift if ARGV.first == '--'
9
+
10
+ STDOUT.write_proc = ->(string) { `Deno.stdout.write(new TextEncoder().encode(string))` }
11
+ STDERR.write_proc = ->(string) { `Deno.stderr.write(new TextEncoder().encode(string))` }
12
+
13
+ STDIN.read_proc = %x{function(_count) {
14
+ // Ignore count, return as much as we can get
15
+ var buf = new Uint8Array(65536), count;
16
+ try {
17
+ count = Deno.stdin.readSync(buf);
18
+ }
19
+ catch (e) { // Windows systems may raise EOF
20
+ return nil;
21
+ }
22
+ if (count == 0) return nil;
23
+ return buf.toString('utf8', 0, count);
24
+ }}
25
+
26
+ STDIN.tty = true
27
+ STDOUT.tty = true
28
+ STDERR.tty = true
@@ -0,0 +1,340 @@
1
+ `/* global Deno */`
2
+ require 'corelib/file'
3
+
4
+ %x{
5
+ var warnings = {}, errno_codes = #{Errno.constants};
6
+
7
+ function handle_unsupported_feature(message) {
8
+ switch (Opal.config.unsupported_features_severity) {
9
+ case 'error':
10
+ #{Kernel.raise NotImplementedError, `message`}
11
+ break;
12
+ case 'warning':
13
+ warn(message)
14
+ break;
15
+ default: // ignore
16
+ // noop
17
+ }
18
+ }
19
+ function warn(string) {
20
+ if (warnings[string]) {
21
+ return;
22
+ }
23
+ warnings[string] = true;
24
+ #{warn(`string`)};
25
+ }
26
+ function is_utf8(bytes) {
27
+ var i = 0;
28
+ while (i < bytes.length) {
29
+ if ((// ASCII
30
+ bytes[i] === 0x09 ||
31
+ bytes[i] === 0x0A ||
32
+ bytes[i] === 0x0D ||
33
+ (0x20 <= bytes[i] && bytes[i] <= 0x7E)
34
+ )
35
+ ) {
36
+ i += 1;
37
+ continue;
38
+ }
39
+
40
+ if ((// non-overlong 2-byte
41
+ (0xC2 <= bytes[i] && bytes[i] <= 0xDF) &&
42
+ (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF)
43
+ )
44
+ ) {
45
+ i += 2;
46
+ continue;
47
+ }
48
+
49
+ if ((// excluding overlongs
50
+ bytes[i] === 0xE0 &&
51
+ (0xA0 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
52
+ (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
53
+ ) ||
54
+ (// straight 3-byte
55
+ ((0xE1 <= bytes[i] && bytes[i] <= 0xEC) ||
56
+ bytes[i] === 0xEE ||
57
+ bytes[i] === 0xEF) &&
58
+ (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
59
+ (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
60
+ ) ||
61
+ (// excluding surrogates
62
+ bytes[i] === 0xED &&
63
+ (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x9F) &&
64
+ (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF)
65
+ )
66
+ ) {
67
+ i += 3;
68
+ continue;
69
+ }
70
+
71
+ if ((// planes 1-3
72
+ bytes[i] === 0xF0 &&
73
+ (0x90 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
74
+ (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
75
+ (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
76
+ ) ||
77
+ (// planes 4-15
78
+ (0xF1 <= bytes[i] && bytes[i] <= 0xF3) &&
79
+ (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0xBF) &&
80
+ (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
81
+ (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
82
+ ) ||
83
+ (// plane 16
84
+ bytes[i] === 0xF4 &&
85
+ (0x80 <= bytes[i + 1] && bytes[i + 1] <= 0x8F) &&
86
+ (0x80 <= bytes[i + 2] && bytes[i + 2] <= 0xBF) &&
87
+ (0x80 <= bytes[i + 3] && bytes[i + 3] <= 0xBF)
88
+ )
89
+ ) {
90
+ i += 4;
91
+ continue;
92
+ }
93
+
94
+ return false;
95
+ }
96
+
97
+ return true;
98
+ }
99
+ function executeIOAction(action) {
100
+ try {
101
+ return action();
102
+ } catch (error) {
103
+ if (errno_codes.indexOf(error.code) >= 0) {
104
+ var error_class = #{Errno.const_get(`error.code`)}
105
+ #{Kernel.raise `error_class`.new(`error.message`)}
106
+ }
107
+ #{Kernel.raise `error`}
108
+ }
109
+ }
110
+ }
111
+
112
+ class File < IO
113
+ `var __utf8TextDecoder__ = new TextDecoder('utf8')`
114
+ `var __textEncoder__ = new TextEncoder()`
115
+
116
+ def self.read(path)
117
+ `return executeIOAction(function(){return Deno.readFileSync(#{path}).toString()})`
118
+ end
119
+
120
+ def self.write(path, data)
121
+ `executeIOAction(function(){return Deno.writeFileSync(#{path}, __textEncoder__.encode(#{data}));})`
122
+ data.size
123
+ end
124
+
125
+ def self.delete(path)
126
+ `executeIOAction(function(){return Deno.removeSync(#{path})})`
127
+ end
128
+
129
+ class << self
130
+ alias unlink delete
131
+ end
132
+
133
+ def self.exist?(path)
134
+ path = path.path if path.respond_to? :path
135
+ `return executeIOAction(function(){return Deno.statSync(#{path})})`
136
+ end
137
+
138
+ def self.realpath(pathname, dir_string = nil, cache = nil, &block)
139
+ pathname = join(dir_string, pathname) if dir_string
140
+ if block_given?
141
+ `
142
+ Deno.realpath(#{pathname}, #{cache}, function(error, realpath){
143
+ if (error) Opal.IOError.$new(error.message)
144
+ else #{block.call(`realpath`)}
145
+ })
146
+ `
147
+ else
148
+ `return executeIOAction(function(){return Deno.realpathSync(#{pathname}, #{cache})})`
149
+ end
150
+ end
151
+
152
+ def self.join(*paths)
153
+ # by itself, `path.posix.join` normalizes leading // to /.
154
+ # restore the leading / on UNC paths (i.e., paths starting with //).
155
+ paths = paths.map(&:to_s)
156
+ prefix = paths.first&.start_with?('//') ? '/' : ''
157
+ path = prefix
158
+ paths.each do |pth|
159
+ path << if pth.end_with?('/') || pth.start_with?('/')
160
+ pth
161
+ else
162
+ '/' + pth
163
+ end
164
+ end
165
+ path
166
+ end
167
+
168
+ def self.directory?(path)
169
+ return false unless exist? path
170
+ result = `executeIOAction(function(){return !!Deno.lstatSync(path).isDirectory})`
171
+ unless result
172
+ realpath = realpath(path)
173
+ if realpath != path
174
+ result = `executeIOAction(function(){return !!Deno.lstatSync(realpath).isDirectory})`
175
+ end
176
+ end
177
+ result
178
+ end
179
+
180
+ def self.file?(path)
181
+ return false unless exist? path
182
+ result = `executeIOAction(function(){return !!Deno.lstatSync(path).isFile})`
183
+ unless result
184
+ realpath = realpath(path)
185
+ if realpath != path
186
+ result = `executeIOAction(function(){return !!Deno.lstatSync(realpath).isFile})`
187
+ end
188
+ end
189
+ result
190
+ end
191
+
192
+ def self.readable?(path)
193
+ return false unless exist? path
194
+ %{
195
+ try {
196
+ Deno.openSync(path, {read: true}).close();
197
+ return true;
198
+ } catch (error) {
199
+ return false;
200
+ }
201
+ }
202
+ end
203
+
204
+ def self.size(path)
205
+ `return executeIOAction(function(){return Deno.lstatSync(path).size})`
206
+ end
207
+
208
+ def self.open(path, mode = 'r')
209
+ file = new(path, mode)
210
+ if block_given?
211
+ begin
212
+ yield(file)
213
+ ensure
214
+ file.close
215
+ end
216
+ else
217
+ file
218
+ end
219
+ end
220
+
221
+ def self.stat(path)
222
+ path = path.path if path.respond_to? :path
223
+ File::Stat.new(path)
224
+ end
225
+
226
+ def self.mtime(path)
227
+ `return executeIOAction(function(){return Deno.statSync(#{path}).mtime})`
228
+ end
229
+
230
+ def self.symlink?(path)
231
+ `return executeIOAction(function(){return Deno.lstatSync(#{path}).isSymLink})`
232
+ end
233
+
234
+ def self.absolute_path(path, basedir = nil)
235
+ raise 'File::absolute_path is currently unsupported in Deno!'
236
+ end
237
+
238
+ # Instance Methods
239
+
240
+ def initialize(path, flags = 'r')
241
+ @binary_flag = flags.include?('b')
242
+ # Node does not recognize this flag
243
+ flags = flags.delete('b')
244
+ # encoding flag is unsupported
245
+ encoding_option_rx = /:(.*)/
246
+ if encoding_option_rx.match?(flags)
247
+ `handle_unsupported_feature("Encoding option (:encoding) is unsupported by Node.js openSync method and will be removed.")`
248
+ flags = flags.sub(encoding_option_rx, '')
249
+ end
250
+ @path = path
251
+
252
+ fd = `executeIOAction(function(){return Deno.openSync(path, flags)})`
253
+ super(fd, flags)
254
+ end
255
+
256
+ attr_reader :path
257
+
258
+ def sysread(bytes)
259
+ if @eof
260
+ raise EOFError, 'end of file reached'
261
+ else
262
+ if @binary_flag
263
+ %x{
264
+ var buf = executeIOAction(function(){return Deno.readFileSync(#{@path})})
265
+ var content
266
+ if (is_utf8(buf)) {
267
+ content = buf.toString('utf8')
268
+ } else {
269
+ // coerce to utf8
270
+ content = __utf8TextDecoder__.decode(__textEncoder__.encode(buf.toString('binary')))
271
+ }
272
+ }
273
+ res = `content`
274
+ else
275
+ res = `executeIOAction(function(){return Deno.readFileSync(#{@path}).toString('utf8')})`
276
+ end
277
+ @eof = true
278
+ @lineno = res.size
279
+ res
280
+ end
281
+ end
282
+
283
+ def write(string)
284
+ `executeIOAction(function(){return #{@fd}.writeSync(__textEncoder__.encode(#{string}))})`
285
+ end
286
+
287
+ def flush
288
+ # not supported by deno
289
+ end
290
+
291
+ def close
292
+ `executeIOAction(function(){return #{@fd}.close()})`
293
+ super
294
+ end
295
+
296
+ def mtime
297
+ `return executeIOAction(function(){return Deno.statSync(#{@path}).mtime})`
298
+ end
299
+ end
300
+
301
+ class File::Stat
302
+ def initialize(path)
303
+ @path = path
304
+ end
305
+
306
+ def file?
307
+ `return executeIOAction(function(){return Deno.statSync(#{@path}).isFile})`
308
+ end
309
+
310
+ def directory?
311
+ `return executeIOAction(function(){return Deno.statSync(#{@path}).isDirectory})`
312
+ end
313
+
314
+ def mtime
315
+ `return executeIOAction(function(){return Deno.statSync(#{@path}).mtime})`
316
+ end
317
+
318
+ def readable?
319
+ %x{
320
+ return executeIOAction(function(){
321
+ Deno.openSync(path, {read: true}).close();
322
+ return true;
323
+ })
324
+ }
325
+ end
326
+
327
+ def writable?
328
+ %x{
329
+ return executeIOAction(function(){
330
+ Deno.openSync(path, {write: true}).close();
331
+ return true;
332
+ })
333
+ }
334
+ end
335
+
336
+ def executable?
337
+ # accessible only over unstable API
338
+ false
339
+ end
340
+ end
@@ -9,7 +9,7 @@
9
9
 
10
10
  if (window.OPAL_EXIT_CODE === "noexit") {
11
11
  window.OPAL_EXIT_CODE = code;
12
- window.alert("opalheadlesschromeexit");
12
+ window.alert("opalheadlessbrowserexit");
13
13
  }
14
14
  }
15
15
  }
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ class File
4
+ def self.write(path, data)
5
+ # This is only to enable CDP runners to write the benchmark results
6
+ %x{
7
+ var http = new XMLHttpRequest();
8
+ http.open("POST", "/File.write");
9
+ http.setRequestHeader("Content-Type", "application/json");
10
+ // Failure is not an option
11
+ http.send(JSON.stringify({filename: #{path}, data: #{data}, secret: window.OPAL_CDP_SHARED_SECRET}));
12
+ }
13
+ data.length
14
+ end
15
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'headless_browser/base'
4
+ require 'headless_browser/file'
data/stdlib/native.rb CHANGED
@@ -615,7 +615,7 @@ end
615
615
  class Class
616
616
  def native_alias(new_jsid, existing_mid)
617
617
  %x{
618
- var aliased = #{self}.prototype['$' + #{existing_mid}];
618
+ var aliased = #{self}.prototype[Opal.jsid(#{existing_mid})];
619
619
  if (!aliased) {
620
620
  #{raise NameError.new("undefined method `#{existing_mid}' for class `#{inspect}'", existing_mid)};
621
621
  }
@@ -135,6 +135,11 @@ class File < IO
135
135
  data.size
136
136
  end
137
137
 
138
+ def self.symlink(path, new_path)
139
+ `executeIOAction(function(){return __fs__.symlinkSync(#{path}, #{new_path})})`
140
+ 0
141
+ end
142
+
138
143
  def self.delete(path)
139
144
  `executeIOAction(function(){return __fs__.unlinkSync(#{path})})`
140
145
  end
@@ -1,10 +1,12 @@
1
1
  require 'opal-platform'
2
2
 
3
3
  case OPAL_PLATFORM
4
- when 'nashorn' then require 'nashorn'
5
- when 'gjs' then require 'gjs'
6
- when 'quickjs' then require 'quickjs'
7
- when 'nodejs' then require 'nodejs/base'
8
- when 'headless-chrome' then require 'headless_chrome'
9
- when 'opal-miniracer' then require 'opal/miniracer'
4
+ when 'nashorn' then require 'nashorn'
5
+ when 'gjs' then require 'gjs'
6
+ when 'quickjs' then require 'quickjs'
7
+ when 'deno' then require 'deno/base'
8
+ when 'nodejs' then require 'nodejs/base'
9
+ when 'headless-chrome' then require 'headless_browser/base'
10
+ when 'headless-firefox' then require 'headless_browser/base'
11
+ when 'opal-miniracer' then require 'opal/miniracer'
10
12
  end
@@ -1,19 +1,25 @@
1
- `/* global Java, GjsFileImporter */`
1
+ `/* global Java, GjsFileImporter, Deno */`
2
2
 
3
- browser = `typeof(document) !== "undefined"`
4
- node = `typeof(process) !== "undefined" && process.versions && process.versions.node`
5
- nashorn = `typeof(Java) !== "undefined" && Java.type`
6
- headless_chrome = `typeof(opalheadlesschrome) !== 'undefined'`
7
- gjs = `typeof(window) !== "undefined" && typeof(GjsFileImporter) !== 'undefined'`
8
- quickjs = `typeof(window) === "undefined" && typeof(__loadScript) !== 'undefined'`
9
- opal_miniracer = `typeof(opalminiracer) !== 'undefined'`
3
+ browser = `typeof(document) !== "undefined"`
4
+ deno = `typeof(Deno) === "object" && typeof(Deno.version) === "object"`
5
+ node = `typeof(process) !== "undefined" && process.versions && process.versions.node`
6
+ nashorn = `typeof(Java) !== "undefined" && Java.type`
7
+ headless_chrome = `typeof(opalheadlesschrome) !== "undefined"`
8
+ headless_firefox = `typeof(opalheadlessfirefox) !== "undefined"`
9
+ gjs = `typeof(window) !== "undefined" && typeof(GjsFileImporter) !== "undefined"`
10
+ quickjs = `typeof(window) === "undefined" && typeof(__loadScript) !== "undefined"`
11
+ opal_miniracer = `typeof(opalminiracer) !== "undefined"`
10
12
 
11
13
  OPAL_PLATFORM = if nashorn
12
14
  'nashorn'
15
+ elsif deno
16
+ 'deno'
13
17
  elsif node
14
18
  'nodejs'
15
19
  elsif headless_chrome
16
20
  'headless-chrome'
21
+ elsif headless_firefox
22
+ 'headless-firefox'
17
23
  elsif gjs
18
24
  'gjs'
19
25
  elsif quickjs