binaryen 1.1.6.7 → 1.1.6.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e208c99114153cd5edae8ca1125d26eeecb8f2b5f91e218ccc63f807827ee4fe
4
- data.tar.gz: 6839fedb4b0c710fc1aa852909f3a24daf1729a2f1531e6c3c47b7594f2819d3
3
+ metadata.gz: 18c535d2045e224d5ba46b3117e7eced2ff502b0cb338c6e7307113f011cb5fa
4
+ data.tar.gz: 8d1a5f09b94e86221e142d0773c8b23ea0a1987275a322a175daf84db2b2e01b
5
5
  SHA512:
6
- metadata.gz: 21ec4f01eacfa0d38b08acae723f5f6bf662f42047950354c3260b9d461b774ba91749b82b162a74b83ef0e70aa4b6541fcbbbb70111cd30b11b969955a2cfec
7
- data.tar.gz: 5dbbf03fe6f8325cdaa1e78c81bfb7feef07d1887d53a647202f56dc58e5ac1b628a2057f0e5cce083bd2868894e622054f1a999d476a568ef04a5c1558a2d72
6
+ metadata.gz: dea3bf6b7f13d19fc83dc18632092306650ae3b077f2221fa62c0f35beaee50a4acf54ff50f114049da1bdf4b4485076f19e3039e9ec714b158468fb07286850
7
+ data.tar.gz: ac18a83b7221afaa90c2643ccad41af25f1be1bac141011afb056cc16a824e98c7c75832fe03b7f18b703184479faff1fe9bff127eb255cec321d50904a2e35e
@@ -1,50 +1,108 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "English"
4
- require "shellwords"
5
- require "timeout"
6
3
  require "posix/spawn"
4
+ require "timeout"
5
+ require "tempfile"
7
6
 
8
7
  module Binaryen
9
- # Wrapper around a binaryen executable command with a timeout and streaming IO.
10
- #
11
- # @example Running wasm-opt
12
- #
13
- # ```ruby
14
- # command = Binaryen::Command.new("wasm-opt", timeout: 10)
15
- # optimized_wasm = command.run("-O4", stdin: "(module)")
16
- # ```
17
8
  class Command
18
- MAX_OUTPUT_SIZE = 256 * 1024 * 1024
9
+ include POSIX::Spawn
10
+ DEFAULT_MAX_OUTPUT_SIZE = 256 * 1024 * 1024
11
+ DEFAULT_TIMEOUT = 10
19
12
  DEFAULT_ARGS_FOR_COMMAND = {
20
13
  "wasm-opt" => ["--output=-"],
21
14
  }.freeze
22
15
 
23
- def initialize(cmd, timeout: 10, ignore_missing: false)
16
+ def initialize(cmd, timeout: DEFAULT_TIMEOUT, max_output_size: DEFAULT_MAX_OUTPUT_SIZE, ignore_missing: false)
24
17
  @cmd = command_path(cmd, ignore_missing) || raise(ArgumentError, "command not found: #{cmd}")
25
18
  @timeout = timeout
26
19
  @default_args = DEFAULT_ARGS_FOR_COMMAND.fetch(cmd, [])
20
+ @max_output_size = max_output_size
27
21
  end
28
22
 
29
23
  def run(*arguments, stdin: nil, stderr: nil)
30
24
  args = [@cmd] + arguments + @default_args
31
- child = POSIX::Spawn::Child.new(*args, input: stdin, timeout: @timeout, max: MAX_OUTPUT_SIZE)
32
- stderr&.write(child.err)
33
- status = child.status
34
25
 
35
- raise Binaryen::NonZeroExitStatus, "command exited with status #{status.exitstatus}" unless status.success?
36
-
37
- child.out
38
- rescue POSIX::Spawn::MaximumOutputExceeded => e
39
- raise Binaryen::MaximumOutputExceeded, e.message
40
- rescue POSIX::Spawn::TimeoutExceeded => e
41
- raise Timeout::Error, e.message
26
+ if stdin
27
+ with_stdin_tempfile(stdin) { |path| spawn_command(*args, path, stderr: stderr) }
28
+ else
29
+ spawn_command(*args, stderr: stderr)
30
+ end
42
31
  end
43
32
 
44
33
  private
45
34
 
35
+ def with_stdin_tempfile(content)
36
+ Tempfile.open("binaryen-stdin") do |f|
37
+ f.binmode
38
+ f.write(content)
39
+ f.close
40
+ yield f.path
41
+ end
42
+ end
43
+
46
44
  def command_path(cmd, ignore_missing)
47
45
  Dir[File.join(Binaryen.bindir, cmd)].first || (ignore_missing && cmd)
48
46
  end
47
+
48
+ def spawn_command(*args, stderr: nil)
49
+ out = "".b
50
+ data_buffer = "".b
51
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
52
+ pid, stdin, stdout, stderr_stream = popen4(*args)
53
+ stdin.close
54
+ @pid = pid
55
+ readers = [stdout, stderr_stream]
56
+
57
+ while readers.any?
58
+ elapsed_time = Process.clock_gettime(Process::CLOCK_MONOTONIC) - start_time
59
+ remaining_time = @timeout - elapsed_time
60
+ ready = IO.select(readers, nil, nil, remaining_time)
61
+ raise Timeout::Error, "command timed out after #{@timeout} seconds" if ready.nil?
62
+
63
+ ready[0].each do |io|
64
+ max_amount_to_read = @max_output_size - out.bytesize + 1
65
+ data = io.read_nonblock(max_amount_to_read, data_buffer, exception: false)
66
+
67
+ if data == :wait_readable
68
+ # If the IO object is not ready for reading, read_nonblock returns :wait_readable.
69
+ # This isn't an error, but a notification.
70
+ next
71
+ elsif data.nil?
72
+ # At EOF, read_nonblock returns nil instead of raising EOFError.
73
+ readers.delete(io)
74
+ io.close
75
+ elsif io == stdout
76
+ out << data_buffer
77
+ elsif io == stderr_stream && stderr
78
+ stderr << data_buffer
79
+ end
80
+ rescue Errno::EINTR
81
+ # This means that the read was interrupted by a signal, which is not an error. So we just retry.
82
+ end
83
+
84
+ if out.bytesize > @max_output_size
85
+ Process.kill("TERM", @pid)
86
+ raise Binaryen::MaximumOutputExceeded, "maximum output size exceeded (#{@max_output_size} bytes)"
87
+ end
88
+
89
+ if remaining_time < 0
90
+ Process.kill("TERM", @pid)
91
+ raise Timeout::Error, "command timed out after #{@timeout} seconds"
92
+ end
93
+ end
94
+
95
+ _, status = Process.waitpid2(pid, Process::WUNTRACED)
96
+
97
+ raise Binaryen::NonZeroExitStatus, "command exited with status #{status.exitstatus}" unless status.success?
98
+
99
+ out
100
+ ensure
101
+ [stdin, stdout, stderr_stream].each do |io|
102
+ io.close
103
+ rescue
104
+ nil
105
+ end
106
+ end
49
107
  end
50
108
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Binaryen
4
- VERSION = "1.1.6.7"
4
+ VERSION = "1.1.6.9"
5
5
  BINARYEN_VERSION = "version_116"
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: binaryen
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.6.7
4
+ version: 1.1.6.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify Inc.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-12-18 00:00:00.000000000 Z
11
+ date: 2024-01-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: posix-spawn
@@ -106,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  - !ruby/object:Gem::Version
107
107
  version: '0'
108
108
  requirements: []
109
- rubygems_version: 3.4.22
109
+ rubygems_version: 3.5.4
110
110
  signing_key:
111
111
  specification_version: 4
112
112
  summary: Vendors binaryen libraries, headers, and executables for use in Ruby