wardite 0.7.0 → 0.8.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.
- checksums.yaml +4 -4
- data/lib/wardite/cli/cli.rb +17 -3
- data/lib/wardite/value.rb +1 -1
- data/lib/wardite/version.rb +1 -1
- data/lib/wardite/wasi/consts.rb +7 -0
- data/lib/wardite/wasi/dirent_cache.rb +87 -0
- data/lib/wardite/wasi/preopens.rb +17 -0
- data/lib/wardite/wasi.rb +453 -16
- data/lib/wardite.rb +1 -0
- data/sig/generated/wardite/cli/cli.rbs +2 -0
- data/sig/generated/wardite/wasi/consts.rbs +10 -0
- data/sig/generated/wardite/wasi/dirent_cache.rbs +42 -0
- data/sig/generated/wardite/wasi/preopens.rbs +15 -0
- data/sig/generated/wardite/wasi.rbs +98 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 20aa59cedbb81d21c2681737929bb7f29fcf70cd189ca5d0de1ff538fca57782
|
4
|
+
data.tar.gz: fed9168236c3d23e377d38e2a6bf175336def008268aa5910215667ff3fac750
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '098a4d2d2c25221667307bdf49fa207f682dd0f53e9ee33700cf18790961ce0ea627ed3f8ff7292a4cf55d70bf0c6068ed0b4b03502ec95aedd511c547dac7a0'
|
7
|
+
data.tar.gz: 9e1b69ba3cea02e033892ad4bf3fafc456d96d0f4741e8b0a9b6c55d2285cbb7d29fc0f0b2e71b1b35812c905b6281d1c4713c7b9215c5f99b42d94c88a6295b
|
data/lib/wardite/cli/cli.rb
CHANGED
@@ -11,18 +11,21 @@ module Wardite
|
|
11
11
|
attr_reader :file #: String
|
12
12
|
attr_reader :memsize #: Integer
|
13
13
|
attr_reader :wasi #: bool
|
14
|
+
attr_reader :yjit #: bool
|
14
15
|
|
15
16
|
# @rbs args: Array[String]
|
16
17
|
# @rbs return: void
|
17
18
|
def initialize(args)
|
18
19
|
@invoke = @mapdir = nil
|
19
20
|
@wasi = true # default to true
|
21
|
+
@yjit = false
|
20
22
|
@memsize = 1
|
21
23
|
options = OptionParser.new do |opts|
|
24
|
+
opts.version = Wardite::VERSION
|
22
25
|
opts.on("--invoke [fnname]", "Invoke the function") { |v|
|
23
26
|
@invoke = v
|
24
27
|
}
|
25
|
-
opts.on("--mapdir [
|
28
|
+
opts.on("--mapdir [dirs]", "Map the directory") { |v|
|
26
29
|
@mapdir = v
|
27
30
|
}
|
28
31
|
opts.on("--memsize [size_in_bytes]", "Initial memory size") { |v|
|
@@ -31,12 +34,19 @@ module Wardite
|
|
31
34
|
opts.on("--no-wasi", "Disable WASI feature") {|_v|
|
32
35
|
@wasi = false
|
33
36
|
}
|
37
|
+
opts.on("--yjit", "Enable yjit if available; setting WARDITE_YJIT_ON=1 has the same effect") {|_v|
|
38
|
+
@yjit = true
|
39
|
+
}
|
34
40
|
opts.on("FILE.wasm") { }
|
35
41
|
end
|
36
42
|
options.parse!(args)
|
37
43
|
@file = args[0] || raise("require file argument")
|
38
44
|
@args = (args[1..-1] || [])
|
39
45
|
@args.unshift if @args[0] == '--'
|
46
|
+
|
47
|
+
if (yjit || ENV["WARDITE_YJIT_ON"] == "1") && (defined? RubyVM::YJIT)
|
48
|
+
RubyVM::YJIT.enable
|
49
|
+
end
|
40
50
|
end
|
41
51
|
|
42
52
|
# @rbs return: Array[Integer | Float]
|
@@ -66,7 +76,10 @@ module Wardite
|
|
66
76
|
if invoke
|
67
77
|
invoke_function
|
68
78
|
else
|
69
|
-
|
79
|
+
if wasi
|
80
|
+
invoke_wasi
|
81
|
+
return
|
82
|
+
end
|
70
83
|
raise("requires function name to invoke")
|
71
84
|
end
|
72
85
|
end
|
@@ -91,6 +104,7 @@ module Wardite
|
|
91
104
|
if mapdir && mount_dst && mount_src
|
92
105
|
# TODO: support multiple mapdir
|
93
106
|
instance.wasi.mapdir[mount_dst] = mount_src
|
107
|
+
instance.wasi.set_preopened_dir(mount_dst, mount_src)
|
94
108
|
end
|
95
109
|
|
96
110
|
if defined? Bundler
|
@@ -99,7 +113,7 @@ module Wardite
|
|
99
113
|
end
|
100
114
|
else
|
101
115
|
instance.runtime._start
|
102
|
-
end
|
116
|
+
end
|
103
117
|
end
|
104
118
|
|
105
119
|
# @rbs return: String?
|
data/lib/wardite/value.rb
CHANGED
@@ -383,7 +383,7 @@ module Wardite
|
|
383
383
|
raise EvalError, "unsupported operation" if to != :f64
|
384
384
|
v = [value].pack("L!").unpack("d")[0]
|
385
385
|
raise EvalError, "[BUG] String#unpack is broke, really?" if !v.is_a?(Float)
|
386
|
-
|
386
|
+
F64(v)
|
387
387
|
end
|
388
388
|
|
389
389
|
# @rbs from: Symbol
|
data/lib/wardite/version.rb
CHANGED
data/lib/wardite/wasi/consts.rb
CHANGED
@@ -103,6 +103,13 @@ module Wardite
|
|
103
103
|
RIGHT_PATH_REMOVE_DIRECTORY |
|
104
104
|
RIGHT_PATH_UNLINK_FILE
|
105
105
|
|
106
|
+
LOOKUP_SYMLINK_FOLLOW = 1 << 0
|
107
|
+
|
108
|
+
O_CREAT = 1 << 0
|
109
|
+
O_DIRECTORY = 1 << 1
|
110
|
+
O_EXCL = 1 << 2
|
111
|
+
O_TRUNC = 1 << 3
|
112
|
+
|
106
113
|
# @rbs mode_str: String
|
107
114
|
# @rbs return: Integer
|
108
115
|
def self.to_ftype(mode_str)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
|
3
|
+
module Wardite
|
4
|
+
module Wasi
|
5
|
+
class Dirent
|
6
|
+
attr_reader :path #: String
|
7
|
+
attr_reader :ino #: Integer
|
8
|
+
attr_reader :type #: Integer
|
9
|
+
|
10
|
+
# @rbs path: String
|
11
|
+
# @rbs ino: Integer
|
12
|
+
# @rbs type: Integer
|
13
|
+
# @rbs return: void
|
14
|
+
def initialize(path, ino, type)
|
15
|
+
@path = path
|
16
|
+
@ino = ino
|
17
|
+
@type = type
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class DirentCache
|
22
|
+
attr_reader :entries #: Array[Dirent]
|
23
|
+
attr_accessor :eof #: bool
|
24
|
+
|
25
|
+
# @rbs path: String
|
26
|
+
# @rbs return: void
|
27
|
+
def initialize(path)
|
28
|
+
@entries = []
|
29
|
+
Dir.entries(path).sort.each do |entry|
|
30
|
+
case entry
|
31
|
+
when "."
|
32
|
+
@entries << Dirent.new(entry, File.stat(path).ino, FILETYPE_DIRECTORY)
|
33
|
+
when ".."
|
34
|
+
@entries << Dirent.new(entry, 0, FILETYPE_DIRECTORY)
|
35
|
+
else
|
36
|
+
full_path = File.join(path, entry)
|
37
|
+
type = case File.ftype(full_path)
|
38
|
+
when "directory" then FILETYPE_DIRECTORY
|
39
|
+
when "file" then FILETYPE_REGULAR_FILE
|
40
|
+
when "link" then FILETYPE_SYMBOLIC_LINK
|
41
|
+
else FILETYPE_UNKNOWN
|
42
|
+
end
|
43
|
+
@entries << Dirent.new(entry, File.stat(full_path).ino, type)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
@eof = false
|
48
|
+
end
|
49
|
+
|
50
|
+
# @rbs buf_len: Integer
|
51
|
+
# @rbs cookie: Integer
|
52
|
+
# @rbs return: [String, bool]
|
53
|
+
def fetch_entries_binary(buf_len, cookie)
|
54
|
+
# d_next is the index of the next file in the list, so it should
|
55
|
+
# always be one higher than the requested cookie.
|
56
|
+
d_next = cookie + 1
|
57
|
+
buf = ""
|
58
|
+
entries_slice = entries[cookie..-1]
|
59
|
+
return "", false if entries_slice.nil? || entries_slice.empty?
|
60
|
+
|
61
|
+
entries_slice.each do |entry|
|
62
|
+
data = make_dirent_pack1(d_next, entry.ino, entry.path.size, entry.type, entry.path)
|
63
|
+
if buf.size + data.size > buf_len
|
64
|
+
# truncated
|
65
|
+
return buf, true
|
66
|
+
end
|
67
|
+
buf += data
|
68
|
+
d_next += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
return buf, false
|
72
|
+
end
|
73
|
+
|
74
|
+
# @rbs d_next: Integer
|
75
|
+
# @rbs ino: Integer
|
76
|
+
# @rbs name_len: Integer
|
77
|
+
# @rbs type: Integer
|
78
|
+
# @rbs name: String
|
79
|
+
# @rbs return: String
|
80
|
+
def make_dirent_pack1(d_next, ino, name_len, type, name)
|
81
|
+
data = [d_next, ino, name_len, type].pack("Q! Q! I! I!")
|
82
|
+
data += name
|
83
|
+
data
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# rbs_inline: enabled
|
2
|
+
|
3
|
+
module Wardite
|
4
|
+
module Wasi
|
5
|
+
class PreopenedDir
|
6
|
+
attr_reader :path #: String
|
7
|
+
attr_reader :guest_path #: String
|
8
|
+
attr_reader :fd #: Integer
|
9
|
+
|
10
|
+
def initialize(path, guest_path, fd)
|
11
|
+
@path = path
|
12
|
+
@guest_path = guest_path
|
13
|
+
@fd = fd
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/wardite/wasi.rb
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
require "wardite/wasm_module"
|
4
4
|
require "wardite/wasi/consts"
|
5
|
+
require "wardite/wasi/preopens"
|
6
|
+
require "wardite/wasi/dirent_cache"
|
5
7
|
require "securerandom"
|
6
8
|
require "fcntl"
|
7
9
|
|
@@ -10,21 +12,136 @@ module Wardite
|
|
10
12
|
include ValueHelper
|
11
13
|
include WasmModule
|
12
14
|
|
13
|
-
attr_accessor :fd_table #:
|
15
|
+
attr_accessor :fd_table #: Hash[Integer, (IO|File|::Wardite::Wasi::PreopenedDir)]
|
16
|
+
attr_accessor :fd_count #: Integer
|
14
17
|
attr_accessor :argv #: Array[String]
|
15
18
|
attr_accessor :mapdir #: Hash[String, String]
|
19
|
+
attr_accessor :dirent_cache #: Hash[Integer, ::Wardite::Wasi::DirentCache]
|
16
20
|
|
17
21
|
# @rbs argv: Array[String]
|
18
22
|
# @rbs mapdir: Hash[String, String]
|
19
23
|
# @rbs return: void
|
20
24
|
def initialize(argv: [], mapdir: {})
|
21
|
-
@fd_table =
|
22
|
-
STDIN,
|
23
|
-
STDOUT,
|
24
|
-
STDERR,
|
25
|
-
|
25
|
+
@fd_table = {
|
26
|
+
0 => STDIN,
|
27
|
+
1 => STDOUT,
|
28
|
+
2 => STDERR,
|
29
|
+
}
|
30
|
+
@fd_count = 3
|
26
31
|
@argv = argv
|
27
32
|
@mapdir = mapdir
|
33
|
+
|
34
|
+
@dirent_cache = {}
|
35
|
+
end
|
36
|
+
|
37
|
+
# @rbs file: IO|File|::Wardite::Wasi::PreopenedDir
|
38
|
+
# @rbs return: Integer
|
39
|
+
def set_fd(file)
|
40
|
+
fd = @fd_count
|
41
|
+
@fd_table[fd] = file
|
42
|
+
@fd_count += 1
|
43
|
+
fd
|
44
|
+
end
|
45
|
+
|
46
|
+
# @rbs path: String
|
47
|
+
# @rbs guest_path: String
|
48
|
+
# @rbs return: void
|
49
|
+
def set_preopened_dir(path, guest_path)
|
50
|
+
fd = @fd_count
|
51
|
+
set_fd(::Wardite::Wasi::PreopenedDir.new(path, guest_path, fd))
|
52
|
+
end
|
53
|
+
|
54
|
+
# @rbs orig_path: String
|
55
|
+
# @rbs return: String
|
56
|
+
def resolv_path(orig_path)
|
57
|
+
@mapdir.each do |k, v|
|
58
|
+
if orig_path.start_with?(k)
|
59
|
+
return v + orig_path[k.size..-1].to_s
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
return orig_path
|
64
|
+
end
|
65
|
+
|
66
|
+
# @rbs atfd: Integer
|
67
|
+
# @rbs target: String
|
68
|
+
# @rbs return: String
|
69
|
+
def get_path_at(atfd, target)
|
70
|
+
target = resolv_path(target)
|
71
|
+
|
72
|
+
at = @fd_table[atfd]
|
73
|
+
pwd = case at
|
74
|
+
when Wasi::PreopenedDir
|
75
|
+
at.guest_path
|
76
|
+
when File
|
77
|
+
Dir.fchdir(at.fileno) do
|
78
|
+
Dir.pwd
|
79
|
+
end
|
80
|
+
else
|
81
|
+
raise ArgumentError, "invalid fd: #{atfd}"
|
82
|
+
end
|
83
|
+
|
84
|
+
ret = File.expand_path(target, pwd)
|
85
|
+
ret
|
86
|
+
end
|
87
|
+
|
88
|
+
# @rbs dirflags: Integer
|
89
|
+
# @rbs oflags: Integer
|
90
|
+
# @rbs fdflags: Integer
|
91
|
+
# @rbs rights: Integer
|
92
|
+
def interpret_open_flags(dirflags, oflags, fdflags, rights)
|
93
|
+
open_flags = 0
|
94
|
+
if dirflags & Wasi::LOOKUP_SYMLINK_FOLLOW == 0
|
95
|
+
open_flags |= File::Constants::NOFOLLOW
|
96
|
+
end
|
97
|
+
if oflags & Wasi::O_DIRECTORY != 0
|
98
|
+
# open_flags |= File::Constants::DIRECTORY
|
99
|
+
$stderr.puts "O_DIRECTORY is not supported, ignore" if ENV["WARDITE_TRACE"]
|
100
|
+
elsif oflags & Wasi::O_EXCL != 0
|
101
|
+
open_flags |= File::Constants::EXCL
|
102
|
+
end
|
103
|
+
|
104
|
+
default_mode = File::Constants::RDONLY
|
105
|
+
if oflags & Wasi::O_TRUNC != 0
|
106
|
+
open_flags |= File::Constants::TRUNC
|
107
|
+
default_mode = File::Constants::RDWR
|
108
|
+
end
|
109
|
+
if oflags & Wasi::O_CREAT != 0
|
110
|
+
open_flags |= File::Constants::CREAT
|
111
|
+
default_mode = File::Constants::RDWR
|
112
|
+
end
|
113
|
+
if fdflags & Wasi::FD_NONBLOCK != 0
|
114
|
+
open_flags |= File::Constants::NONBLOCK
|
115
|
+
end
|
116
|
+
if fdflags & Wasi::FD_APPEND != 0
|
117
|
+
open_flags |= File::Constants::APPEND
|
118
|
+
default_mode = File::Constants::RDWR
|
119
|
+
end
|
120
|
+
if fdflags & Wasi::FD_DSYNC != 0
|
121
|
+
open_flags |= File::Constants::DSYNC
|
122
|
+
end
|
123
|
+
if fdflags & Wasi::FD_RSYNC != 0
|
124
|
+
open_flags |= File::Constants::RSYNC
|
125
|
+
end
|
126
|
+
if fdflags & Wasi::FD_SYNC != 0
|
127
|
+
open_flags |= File::Constants::SYNC
|
128
|
+
end
|
129
|
+
|
130
|
+
r = Wasi::RIGHT_FD_READ
|
131
|
+
w = Wasi::RIGHT_FD_WRITE
|
132
|
+
rw = r | w
|
133
|
+
case
|
134
|
+
when (rights & rw) == rw
|
135
|
+
open_flags |= File::Constants::RDWR
|
136
|
+
when (rights & w) == w
|
137
|
+
open_flags |= File::Constants::WRONLY
|
138
|
+
when (rights & r) == r
|
139
|
+
open_flags |= File::Constants::RDONLY
|
140
|
+
else
|
141
|
+
open_flags |= default_mode
|
142
|
+
end
|
143
|
+
|
144
|
+
open_flags
|
28
145
|
end
|
29
146
|
|
30
147
|
# @rbs store: Store
|
@@ -140,17 +257,216 @@ module Wardite
|
|
140
257
|
0
|
141
258
|
end
|
142
259
|
|
260
|
+
# @rbs store: Store
|
261
|
+
# @rbs args: Array[wasmValue]
|
262
|
+
# @rbs return: Object
|
263
|
+
def path_create_directory(store, args)
|
264
|
+
fd = args[0].value.to_i
|
265
|
+
path = args[1].value.to_i
|
266
|
+
path_len = args[2].value.to_i
|
267
|
+
path_str = store.memories[0].data[path...(path+path_len)]
|
268
|
+
if !path_str
|
269
|
+
return Wasi::ENOENT
|
270
|
+
end
|
271
|
+
|
272
|
+
target = get_path_at(fd, path_str)
|
273
|
+
Dir.mkdir(target, 0700)
|
274
|
+
0
|
275
|
+
# TODO; rescue EBADF, ENOTDIR
|
276
|
+
end
|
277
|
+
|
278
|
+
# @rbs store: Store
|
279
|
+
# @rbs args: Array[wasmValue]
|
280
|
+
# @rbs return: Object
|
281
|
+
def path_filestat_get(store, args)
|
282
|
+
fd = args[0].value.to_i
|
283
|
+
flags = args[1].value.to_i
|
284
|
+
path = args[2].value.to_i
|
285
|
+
path_len = args[3].value.to_i
|
286
|
+
target = get_path_at(fd, store.memories[0].data[path...(path+path_len)].to_s)
|
287
|
+
|
288
|
+
stat = File.stat(target)
|
289
|
+
memory = store.memories[0]
|
290
|
+
binformat = [
|
291
|
+
stat.dev, stat.ino, Wasi.to_ftype(stat.ftype), stat.nlink,
|
292
|
+
stat.size, stat.atime.to_i, stat.mtime.to_i, stat.ctime.to_i
|
293
|
+
].pack("Q8")
|
294
|
+
memory.data[flags...(flags+binformat.size)] = binformat
|
295
|
+
0
|
296
|
+
rescue Errno::ENOENT
|
297
|
+
return Wasi::ENOENT
|
298
|
+
end
|
299
|
+
|
300
|
+
# @rbs store: Store
|
301
|
+
# @rbs args: Array[wasmValue]
|
302
|
+
# @rbs return: Object
|
303
|
+
def path_filestat_set_times(store, args)
|
304
|
+
fd = args[0].value.to_i
|
305
|
+
# TODO: flags support
|
306
|
+
_flags = args[1].value.to_i
|
307
|
+
path = args[2].value.to_i
|
308
|
+
path_len = args[3].value.to_i
|
309
|
+
atim = args[4].value.to_i # nanoseconds
|
310
|
+
mtim = args[5].value.to_i # nanoseconds
|
311
|
+
target = get_path_at(fd, store.memories[0].data[path...(path+path_len)].to_s)
|
312
|
+
|
313
|
+
atime = Time.at(atim.to_f / 1_000_000_000)
|
314
|
+
mtime = Time.at(mtim.to_f / 1_000_000_000)
|
315
|
+
File.utime(atime, mtime, target)
|
316
|
+
0
|
317
|
+
end
|
318
|
+
|
319
|
+
# @rbs store: Store
|
320
|
+
# @rbs args: Array[wasmValue]
|
321
|
+
# @rbs return: Object
|
322
|
+
def path_link(store, args)
|
323
|
+
old_fd = args[0].value.to_i
|
324
|
+
old_path = args[1].value.to_i
|
325
|
+
old_path_len = args[2].value.to_i
|
326
|
+
old_name = get_path_at(old_fd, store.memories[0].data[old_path...(old_path+old_path_len)].to_s)
|
327
|
+
|
328
|
+
new_fd = args[3].value.to_i
|
329
|
+
new_path = args[4].value.to_i
|
330
|
+
new_path_len = args[5].value.to_i
|
331
|
+
new_name = get_path_at(new_fd, store.memories[0].data[new_path...(new_path+new_path_len)].to_s)
|
332
|
+
|
333
|
+
File.link(old_name, new_name)
|
334
|
+
0
|
335
|
+
end
|
336
|
+
|
337
|
+
# @rbs store: Store
|
338
|
+
# @rbs args: Array[wasmValue]
|
339
|
+
# @rbs return: Object
|
340
|
+
def path_open(store, args)
|
341
|
+
dirfd = args[0].value.to_i
|
342
|
+
dirflags = args[1].value.to_i
|
343
|
+
path = args[2].value.to_i
|
344
|
+
path_len = args[3].value.to_i
|
345
|
+
oflags = args[4].value.to_i
|
346
|
+
fs_rights_base = args[5].value.to_i
|
347
|
+
_fs_rights_inheriting = args[6].value.to_i
|
348
|
+
fs_flags = args[7].value.to_i
|
349
|
+
fd_off = args[8].value.to_i
|
350
|
+
|
351
|
+
path_name = get_path_at(dirfd, store.memories[0].data[path...(path+path_len)].to_s)
|
352
|
+
open_flags = interpret_open_flags(dirflags, oflags, fs_flags, fs_rights_base)
|
353
|
+
is_dir = (oflags & Wasi::O_DIRECTORY) != 0
|
354
|
+
if is_dir && (oflags & Wasi::O_CREAT) != 0
|
355
|
+
return Wasi::EINVAL
|
356
|
+
end
|
357
|
+
|
358
|
+
file = File.open(path_name, open_flags, 0600)
|
359
|
+
fd = set_fd file
|
360
|
+
|
361
|
+
memory = store.memories[0]
|
362
|
+
memory.data[fd_off...(fd_off+4)] = [fd].pack("I!")
|
363
|
+
0
|
364
|
+
rescue Errno::ENOENT
|
365
|
+
return Wasi::ENOENT
|
366
|
+
end
|
367
|
+
|
368
|
+
# @rbs store: Store
|
369
|
+
# @rbs args: Array[wasmValue]
|
370
|
+
# @rbs return: Object
|
371
|
+
def path_readlink(store, args)
|
372
|
+
fd = args[0].value.to_i
|
373
|
+
path = args[1].value.to_i
|
374
|
+
path_len = args[2].value.to_i
|
375
|
+
buf = args[3].value.to_i
|
376
|
+
buf_len = args[4].value.to_i
|
377
|
+
result_buf = args[5].value.to_i
|
378
|
+
|
379
|
+
if buf_len <= 0 || path_len <= 0
|
380
|
+
return Wasi::EINVAL
|
381
|
+
end
|
382
|
+
target = get_path_at(fd, store.memories[0].data[path...(path+path_len)].to_s)
|
383
|
+
|
384
|
+
link_target = File.readlink(target)
|
385
|
+
if link_target.size > buf_len
|
386
|
+
return Wasi::ENAMETOOLONG
|
387
|
+
end
|
388
|
+
|
389
|
+
memory = store.memories[0]
|
390
|
+
memory.data[buf...(buf+link_target.size)] = link_target
|
391
|
+
memory.data[result_buf...(result_buf+4)] = [link_target.size].pack("I!")
|
392
|
+
0
|
393
|
+
end
|
394
|
+
|
395
|
+
# @rbs store: Store
|
396
|
+
# @rbs args: Array[wasmValue]
|
397
|
+
# @rbs return: Object
|
398
|
+
def path_remove_directory(store, args)
|
399
|
+
fd = args[0].value.to_i
|
400
|
+
path = args[1].value.to_i
|
401
|
+
path_len = args[2].value.to_i
|
402
|
+
path_str = store.memories[0].data[path...(path+path_len)].to_s
|
403
|
+
target = get_path_at(fd, path_str)
|
404
|
+
|
405
|
+
Dir.rmdir(target)
|
406
|
+
0
|
407
|
+
end
|
408
|
+
|
409
|
+
# @rbs store: Store
|
410
|
+
# @rbs args: Array[wasmValue]
|
411
|
+
# @rbs return: Object
|
412
|
+
def path_rename(store, args)
|
413
|
+
fd = args[0].value.to_i
|
414
|
+
old_path = args[1].value.to_i
|
415
|
+
old_path_len = args[2].value.to_i
|
416
|
+
|
417
|
+
new_fd = args[3].value.to_i
|
418
|
+
new_path = args[4].value.to_i
|
419
|
+
new_path_len = args[5].value.to_i
|
420
|
+
|
421
|
+
old_target = get_path_at(fd, store.memories[0].data[old_path...(old_path+old_path_len)].to_s)
|
422
|
+
new_target = get_path_at(new_fd, store.memories[0].data[new_path...(new_path+new_path_len)].to_s)
|
423
|
+
|
424
|
+
File.rename(old_target, new_target)
|
425
|
+
0
|
426
|
+
end
|
427
|
+
|
428
|
+
# @rbs store: Store
|
429
|
+
# @rbs args: Array[wasmValue]
|
430
|
+
# @rbs return: Object
|
431
|
+
def path_symlink(store, args)
|
432
|
+
old_path = args[0].value.to_i
|
433
|
+
old_path_len = args[1].value.to_i
|
434
|
+
old_name = store.memories[0].data[old_path...(old_path+old_path_len)].to_s
|
435
|
+
|
436
|
+
fd = args[2].value.to_i
|
437
|
+
new_path = args[3].value.to_i
|
438
|
+
new_path_len = args[4].value.to_i
|
439
|
+
new_name = get_path_at(fd, store.memories[0].data[new_path...(new_path+new_path_len)].to_s)
|
440
|
+
|
441
|
+
File.symlink(old_name, new_name)
|
442
|
+
0
|
443
|
+
end
|
444
|
+
|
445
|
+
# @rbs store: Store
|
446
|
+
# @rbs args: Array[wasmValue]
|
447
|
+
# @rbs return: Object
|
448
|
+
def path_unlink_file(store, args)
|
449
|
+
fd = args[0].value.to_i
|
450
|
+
path = args[1].value.to_i
|
451
|
+
path_len = args[2].value.to_i
|
452
|
+
path_str = store.memories[0].data[path...(path+path_len)].to_s
|
453
|
+
target = get_path_at(fd, path_str)
|
454
|
+
|
455
|
+
File.unlink(target)
|
456
|
+
0
|
457
|
+
end
|
458
|
+
|
143
459
|
# @rbs store: Store
|
144
460
|
# @rbs args: Array[wasmValue]
|
145
461
|
# @rbs return: Object
|
146
462
|
def fd_prestat_get(store, args)
|
147
463
|
fd = args[0].value.to_i
|
148
464
|
prestat_offset = args[1].value.to_i
|
149
|
-
if fd >=
|
465
|
+
if fd >= fd_count
|
150
466
|
return Wasi::EBADF
|
151
467
|
end
|
152
468
|
file = @fd_table[fd]
|
153
|
-
if !file.is_a?(
|
469
|
+
if !file.is_a?(Wasi::PreopenedDir)
|
154
470
|
return Wasi::EBADF
|
155
471
|
end
|
156
472
|
name = file.path
|
@@ -161,6 +477,31 @@ module Wardite
|
|
161
477
|
0
|
162
478
|
end
|
163
479
|
|
480
|
+
# @rbs store: Store
|
481
|
+
# @rbs args: Array[wasmValue]
|
482
|
+
# @rbs return: Object
|
483
|
+
def fd_prestat_dir_name(store, args)
|
484
|
+
fd = args[0].value.to_i
|
485
|
+
path = args[1].value.to_i
|
486
|
+
path_len = args[2].value.to_i
|
487
|
+
if fd >= fd_count
|
488
|
+
return Wasi::EBADF
|
489
|
+
end
|
490
|
+
file = @fd_table[fd]
|
491
|
+
if !file.is_a?(Wasi::PreopenedDir)
|
492
|
+
return Wasi::EBADF
|
493
|
+
end
|
494
|
+
name = file.path
|
495
|
+
if name.size > path_len
|
496
|
+
return Wasi::ENAMETOOLONG
|
497
|
+
end
|
498
|
+
name += ("\0" * (path_len - name.size))
|
499
|
+
|
500
|
+
memory = store.memories[0]
|
501
|
+
memory.data[path...(path+name.size)] = name
|
502
|
+
0
|
503
|
+
end
|
504
|
+
|
164
505
|
# @rbs store: Store
|
165
506
|
# @rbs args: Array[wasmValue]
|
166
507
|
# @rbs return: Object
|
@@ -177,7 +518,7 @@ module Wardite
|
|
177
518
|
raise Wardite::ArgumentError, "args too short"
|
178
519
|
end
|
179
520
|
file = self.fd_table[fd]
|
180
|
-
return Wasi::EBADF if !file
|
521
|
+
return Wasi::EBADF if !file || file.is_a?(Wasi::PreopenedDir)
|
181
522
|
memory = store.memories[0]
|
182
523
|
nwritten = 0
|
183
524
|
iovs_len.times do
|
@@ -210,7 +551,7 @@ module Wardite
|
|
210
551
|
raise Wardite::ArgumentError, "args too short"
|
211
552
|
end
|
212
553
|
file = self.fd_table[fd]
|
213
|
-
return Wasi::EBADF if !file
|
554
|
+
return Wasi::EBADF if !file || file.is_a?(Wasi::PreopenedDir)
|
214
555
|
memory = store.memories[0]
|
215
556
|
nread = 0
|
216
557
|
|
@@ -221,10 +562,10 @@ module Wardite
|
|
221
562
|
iovs += 4
|
222
563
|
buf = file.read(slen)
|
223
564
|
if !buf
|
224
|
-
|
565
|
+
break 0
|
225
566
|
end
|
226
|
-
memory.data[start...(start+
|
227
|
-
nread +=
|
567
|
+
memory.data[start...(start+buf.size)] = buf
|
568
|
+
nread += buf.size
|
228
569
|
end
|
229
570
|
|
230
571
|
memory.data[rp...(rp+4)] = [nread].pack("I!")
|
@@ -237,12 +578,16 @@ module Wardite
|
|
237
578
|
def fd_fdstat_get(store, args)
|
238
579
|
fd = args[0].value.to_i
|
239
580
|
fdstat_offset = args[1].value.to_i
|
240
|
-
if fd >=
|
581
|
+
if fd >= fd_count
|
241
582
|
return Wasi::EBADF
|
242
583
|
end
|
243
584
|
file = @fd_table[fd]
|
244
585
|
fdflags = 0
|
245
|
-
if file
|
586
|
+
if !file
|
587
|
+
return Wasi::EBADF
|
588
|
+
elsif file.is_a?(Wasi::PreopenedDir)
|
589
|
+
file = File.open(file.guest_path) # reopen directory
|
590
|
+
elsif file.is_a?(IO) && !file.is_a?(File)
|
246
591
|
fdflags |= Wasi::FD_APPEND
|
247
592
|
else
|
248
593
|
if (Fcntl::O_APPEND & file.fcntl(Fcntl::F_GETFL, 0)) != 0
|
@@ -285,10 +630,14 @@ module Wardite
|
|
285
630
|
def fd_filestat_get(store, args)
|
286
631
|
fd = args[0].value.to_i
|
287
632
|
filestat_offset = args[1].value.to_i
|
288
|
-
if fd >=
|
633
|
+
if fd >= fd_count
|
289
634
|
return Wasi::EBADF
|
290
635
|
end
|
291
636
|
file = @fd_table[fd]
|
637
|
+
if !file || file.is_a?(Wasi::PreopenedDir)
|
638
|
+
return Wasi::EBADF
|
639
|
+
end
|
640
|
+
|
292
641
|
stat = file.stat #: File::Stat
|
293
642
|
memory = store.memories[0]
|
294
643
|
binformat = [stat.dev, stat.ino, Wasi.to_ftype(stat.ftype), stat.nlink, stat.size, stat.atime.to_i, stat.mtime.to_i, stat.ctime.to_i].pack("Q8")
|
@@ -296,6 +645,94 @@ module Wardite
|
|
296
645
|
0
|
297
646
|
end
|
298
647
|
|
648
|
+
# @rbs store: Store
|
649
|
+
# @rbs args: Array[wasmValue]
|
650
|
+
# @rbs return: Object
|
651
|
+
def fd_readdir(store, args)
|
652
|
+
fd = args[0].value.to_i
|
653
|
+
buf = args[1].value.to_i
|
654
|
+
buf_len = args[2].value.to_i
|
655
|
+
cookie = args[3].value.to_i
|
656
|
+
result_buf_used = args[4].value.to_i
|
657
|
+
|
658
|
+
if buf_len < 24 # when smaller than Dirent header size: Q! Q! I! I!
|
659
|
+
return Wasi::EINVAL
|
660
|
+
end
|
661
|
+
|
662
|
+
memory = store.memories[0]
|
663
|
+
|
664
|
+
if dirent_cache[fd]&.eof
|
665
|
+
dirent_cache.delete(fd)
|
666
|
+
end
|
667
|
+
dir = @fd_table[fd]
|
668
|
+
if dir.is_a?(Wasi::PreopenedDir) || (dir.is_a?(File) && dir.stat.ftype == "directory")
|
669
|
+
dirent_cache[fd] ||= Wasi::DirentCache.new(dir.path)
|
670
|
+
else
|
671
|
+
return Wasi::EBADF
|
672
|
+
end
|
673
|
+
|
674
|
+
dirent = dirent_cache[fd]
|
675
|
+
bindata, is_truncated = dirent.fetch_entries_binary(buf_len, cookie)
|
676
|
+
|
677
|
+
bufused = bindata.size
|
678
|
+
# bufused == buf_len means more dirents exist
|
679
|
+
if is_truncated
|
680
|
+
bufused = buf_len
|
681
|
+
memory.data[buf...(buf+buf_len)] = bindata + "\0" * (buf_len - bindata.size)
|
682
|
+
else
|
683
|
+
dirent.eof = true
|
684
|
+
memory.data[buf...(buf+bindata.size)] = bindata
|
685
|
+
end
|
686
|
+
|
687
|
+
memory.data[result_buf_used...(result_buf_used+4)] = [bufused].pack("I!")
|
688
|
+
0
|
689
|
+
end
|
690
|
+
|
691
|
+
# @rbs store: Store
|
692
|
+
# @rbs args: Array[wasmValue]
|
693
|
+
def fd_tell(store, args)
|
694
|
+
fd = args[0].value.to_i
|
695
|
+
result_buf = args[1].value.to_i
|
696
|
+
if fd >= fd_count
|
697
|
+
return Wasi::EBADF
|
698
|
+
end
|
699
|
+
file = @fd_table[fd]
|
700
|
+
if !file || file.is_a?(Wasi::PreopenedDir)
|
701
|
+
return Wasi::EBADF
|
702
|
+
end
|
703
|
+
|
704
|
+
memory = store.memories[0]
|
705
|
+
memory.data[result_buf...(result_buf+4)] = [file.tell].pack("I!")
|
706
|
+
0
|
707
|
+
rescue Errno::EBADF
|
708
|
+
return Wasi::EBADF
|
709
|
+
end
|
710
|
+
|
711
|
+
# @rbs store: Store
|
712
|
+
# @rbs args: Array[wasmValue]
|
713
|
+
# @rbs return: Object
|
714
|
+
def fd_close(store, args)
|
715
|
+
fd = args[0].value.to_i
|
716
|
+
if fd >= fd_count
|
717
|
+
return Wasi::EBADF
|
718
|
+
end
|
719
|
+
file = @fd_table[fd]
|
720
|
+
if !file
|
721
|
+
return Wasi::EBADF
|
722
|
+
end
|
723
|
+
if file.is_a?(Wasi::PreopenedDir)
|
724
|
+
# do nothing for preopened dir...?
|
725
|
+
$stderr.puts "close preopened dir?: #{file.guest_path}"
|
726
|
+
@fd_table.delete(fd)
|
727
|
+
return 0
|
728
|
+
end
|
729
|
+
file.close
|
730
|
+
@fd_table.delete(fd)
|
731
|
+
0
|
732
|
+
rescue Errno::EBADF
|
733
|
+
return Wasi::EBADF
|
734
|
+
end
|
735
|
+
|
299
736
|
# @rbs store: Store
|
300
737
|
# @rbs args: Array[wasmValue]
|
301
738
|
# @rbs return: Object
|
data/lib/wardite.rb
CHANGED
@@ -354,6 +354,7 @@ module Wardite
|
|
354
354
|
# @rbs external_function: ExternalFunction
|
355
355
|
# @rbs return: wasmValue|nil
|
356
356
|
def invoke_external(external_function)
|
357
|
+
$stderr.puts "[trace] call external function: #{external_function.name}" if ENV["WARDITE_TRACE"]
|
357
358
|
local_start = stack.size - external_function.callsig.size
|
358
359
|
args = stack[local_start..]
|
359
360
|
if !args
|
@@ -130,6 +130,16 @@ module Wardite
|
|
130
130
|
|
131
131
|
RIGHT_DIR_RIGHT_BASE: untyped
|
132
132
|
|
133
|
+
LOOKUP_SYMLINK_FOLLOW: untyped
|
134
|
+
|
135
|
+
O_CREAT: untyped
|
136
|
+
|
137
|
+
O_DIRECTORY: untyped
|
138
|
+
|
139
|
+
O_EXCL: untyped
|
140
|
+
|
141
|
+
O_TRUNC: untyped
|
142
|
+
|
133
143
|
# @rbs mode_str: String
|
134
144
|
# @rbs return: Integer
|
135
145
|
def self.to_ftype: (String mode_str) -> Integer
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# Generated from lib/wardite/wasi/dirent_cache.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Wardite
|
4
|
+
module Wasi
|
5
|
+
class Dirent
|
6
|
+
attr_reader path: String
|
7
|
+
|
8
|
+
attr_reader ino: Integer
|
9
|
+
|
10
|
+
attr_reader type: Integer
|
11
|
+
|
12
|
+
# @rbs path: String
|
13
|
+
# @rbs ino: Integer
|
14
|
+
# @rbs type: Integer
|
15
|
+
# @rbs return: void
|
16
|
+
def initialize: (String path, Integer ino, Integer type) -> void
|
17
|
+
end
|
18
|
+
|
19
|
+
class DirentCache
|
20
|
+
attr_reader entries: Array[Dirent]
|
21
|
+
|
22
|
+
attr_accessor eof: bool
|
23
|
+
|
24
|
+
# @rbs path: String
|
25
|
+
# @rbs return: void
|
26
|
+
def initialize: (String path) -> void
|
27
|
+
|
28
|
+
# @rbs buf_len: Integer
|
29
|
+
# @rbs cookie: Integer
|
30
|
+
# @rbs return: [String, bool]
|
31
|
+
def fetch_entries_binary: (Integer buf_len, Integer cookie) -> [ String, bool ]
|
32
|
+
|
33
|
+
# @rbs d_next: Integer
|
34
|
+
# @rbs ino: Integer
|
35
|
+
# @rbs name_len: Integer
|
36
|
+
# @rbs type: Integer
|
37
|
+
# @rbs name: String
|
38
|
+
# @rbs return: String
|
39
|
+
def make_dirent_pack1: (Integer d_next, Integer ino, Integer name_len, Integer type, String name) -> String
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Generated from lib/wardite/wasi/preopens.rb with RBS::Inline
|
2
|
+
|
3
|
+
module Wardite
|
4
|
+
module Wasi
|
5
|
+
class PreopenedDir
|
6
|
+
attr_reader path: String
|
7
|
+
|
8
|
+
attr_reader guest_path: String
|
9
|
+
|
10
|
+
attr_reader fd: Integer
|
11
|
+
|
12
|
+
def initialize: (untyped path, untyped guest_path, untyped fd) -> untyped
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,17 +6,45 @@ module Wardite
|
|
6
6
|
|
7
7
|
include WasmModule
|
8
8
|
|
9
|
-
attr_accessor fd_table:
|
9
|
+
attr_accessor fd_table: Hash[Integer, IO | File | ::Wardite::Wasi::PreopenedDir]
|
10
|
+
|
11
|
+
attr_accessor fd_count: Integer
|
10
12
|
|
11
13
|
attr_accessor argv: Array[String]
|
12
14
|
|
13
15
|
attr_accessor mapdir: Hash[String, String]
|
14
16
|
|
17
|
+
attr_accessor dirent_cache: Hash[Integer, ::Wardite::Wasi::DirentCache]
|
18
|
+
|
15
19
|
# @rbs argv: Array[String]
|
16
20
|
# @rbs mapdir: Hash[String, String]
|
17
21
|
# @rbs return: void
|
18
22
|
def initialize: (?argv: Array[String], ?mapdir: Hash[String, String]) -> void
|
19
23
|
|
24
|
+
# @rbs file: IO|File|::Wardite::Wasi::PreopenedDir
|
25
|
+
# @rbs return: Integer
|
26
|
+
def set_fd: (IO | File | ::Wardite::Wasi::PreopenedDir file) -> Integer
|
27
|
+
|
28
|
+
# @rbs path: String
|
29
|
+
# @rbs guest_path: String
|
30
|
+
# @rbs return: void
|
31
|
+
def set_preopened_dir: (String path, String guest_path) -> void
|
32
|
+
|
33
|
+
# @rbs orig_path: String
|
34
|
+
# @rbs return: String
|
35
|
+
def resolv_path: (String orig_path) -> String
|
36
|
+
|
37
|
+
# @rbs atfd: Integer
|
38
|
+
# @rbs target: String
|
39
|
+
# @rbs return: String
|
40
|
+
def get_path_at: (Integer atfd, String target) -> String
|
41
|
+
|
42
|
+
# @rbs dirflags: Integer
|
43
|
+
# @rbs oflags: Integer
|
44
|
+
# @rbs fdflags: Integer
|
45
|
+
# @rbs rights: Integer
|
46
|
+
def interpret_open_flags: (Integer dirflags, Integer oflags, Integer fdflags, Integer rights) -> untyped
|
47
|
+
|
20
48
|
# @rbs store: Store
|
21
49
|
# @rbs args: Array[wasmValue]
|
22
50
|
# @rbs return: Object
|
@@ -42,11 +70,66 @@ module Wardite
|
|
42
70
|
# @rbs return: Object
|
43
71
|
def clock_time_get: (Store store, Array[wasmValue] args) -> Object
|
44
72
|
|
73
|
+
# @rbs store: Store
|
74
|
+
# @rbs args: Array[wasmValue]
|
75
|
+
# @rbs return: Object
|
76
|
+
def path_create_directory: (Store store, Array[wasmValue] args) -> Object
|
77
|
+
|
78
|
+
# @rbs store: Store
|
79
|
+
# @rbs args: Array[wasmValue]
|
80
|
+
# @rbs return: Object
|
81
|
+
def path_filestat_get: (Store store, Array[wasmValue] args) -> Object
|
82
|
+
|
83
|
+
# @rbs store: Store
|
84
|
+
# @rbs args: Array[wasmValue]
|
85
|
+
# @rbs return: Object
|
86
|
+
def path_filestat_set_times: (Store store, Array[wasmValue] args) -> Object
|
87
|
+
|
88
|
+
# @rbs store: Store
|
89
|
+
# @rbs args: Array[wasmValue]
|
90
|
+
# @rbs return: Object
|
91
|
+
def path_link: (Store store, Array[wasmValue] args) -> Object
|
92
|
+
|
93
|
+
# @rbs store: Store
|
94
|
+
# @rbs args: Array[wasmValue]
|
95
|
+
# @rbs return: Object
|
96
|
+
def path_open: (Store store, Array[wasmValue] args) -> Object
|
97
|
+
|
98
|
+
# @rbs store: Store
|
99
|
+
# @rbs args: Array[wasmValue]
|
100
|
+
# @rbs return: Object
|
101
|
+
def path_readlink: (Store store, Array[wasmValue] args) -> Object
|
102
|
+
|
103
|
+
# @rbs store: Store
|
104
|
+
# @rbs args: Array[wasmValue]
|
105
|
+
# @rbs return: Object
|
106
|
+
def path_remove_directory: (Store store, Array[wasmValue] args) -> Object
|
107
|
+
|
108
|
+
# @rbs store: Store
|
109
|
+
# @rbs args: Array[wasmValue]
|
110
|
+
# @rbs return: Object
|
111
|
+
def path_rename: (Store store, Array[wasmValue] args) -> Object
|
112
|
+
|
113
|
+
# @rbs store: Store
|
114
|
+
# @rbs args: Array[wasmValue]
|
115
|
+
# @rbs return: Object
|
116
|
+
def path_symlink: (Store store, Array[wasmValue] args) -> Object
|
117
|
+
|
118
|
+
# @rbs store: Store
|
119
|
+
# @rbs args: Array[wasmValue]
|
120
|
+
# @rbs return: Object
|
121
|
+
def path_unlink_file: (Store store, Array[wasmValue] args) -> Object
|
122
|
+
|
45
123
|
# @rbs store: Store
|
46
124
|
# @rbs args: Array[wasmValue]
|
47
125
|
# @rbs return: Object
|
48
126
|
def fd_prestat_get: (Store store, Array[wasmValue] args) -> Object
|
49
127
|
|
128
|
+
# @rbs store: Store
|
129
|
+
# @rbs args: Array[wasmValue]
|
130
|
+
# @rbs return: Object
|
131
|
+
def fd_prestat_dir_name: (Store store, Array[wasmValue] args) -> Object
|
132
|
+
|
50
133
|
# @rbs store: Store
|
51
134
|
# @rbs args: Array[wasmValue]
|
52
135
|
# @rbs return: Object
|
@@ -67,6 +150,20 @@ module Wardite
|
|
67
150
|
# @rbs return: Object
|
68
151
|
def fd_filestat_get: (Store store, Array[wasmValue] args) -> Object
|
69
152
|
|
153
|
+
# @rbs store: Store
|
154
|
+
# @rbs args: Array[wasmValue]
|
155
|
+
# @rbs return: Object
|
156
|
+
def fd_readdir: (Store store, Array[wasmValue] args) -> Object
|
157
|
+
|
158
|
+
# @rbs store: Store
|
159
|
+
# @rbs args: Array[wasmValue]
|
160
|
+
def fd_tell: (Store store, Array[wasmValue] args) -> untyped
|
161
|
+
|
162
|
+
# @rbs store: Store
|
163
|
+
# @rbs args: Array[wasmValue]
|
164
|
+
# @rbs return: Object
|
165
|
+
def fd_close: (Store store, Array[wasmValue] args) -> Object
|
166
|
+
|
70
167
|
# @rbs store: Store
|
71
168
|
# @rbs args: Array[wasmValue]
|
72
169
|
# @rbs return: Object
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wardite
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Uchio Kondo
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-04 00:00:00.000000000 Z
|
11
11
|
dependencies: []
|
12
12
|
description: A pure-ruby webassembly runtime
|
13
13
|
email:
|
@@ -58,6 +58,8 @@ files:
|
|
58
58
|
- lib/wardite/version.rb
|
59
59
|
- lib/wardite/wasi.rb
|
60
60
|
- lib/wardite/wasi/consts.rb
|
61
|
+
- lib/wardite/wasi/dirent_cache.rb
|
62
|
+
- lib/wardite/wasi/preopens.rb
|
61
63
|
- lib/wardite/wasm_module.rb
|
62
64
|
- misc/bench-value.rb
|
63
65
|
- misc/slides/fib.c
|
@@ -92,6 +94,8 @@ files:
|
|
92
94
|
- sig/generated/wardite/version.rbs
|
93
95
|
- sig/generated/wardite/wasi.rbs
|
94
96
|
- sig/generated/wardite/wasi/consts.rbs
|
97
|
+
- sig/generated/wardite/wasi/dirent_cache.rbs
|
98
|
+
- sig/generated/wardite/wasi/preopens.rbs
|
95
99
|
- sig/generated/wardite/wasm_module.rbs
|
96
100
|
- sig/wardite.rbs
|
97
101
|
homepage: https://github.com/udzura/wardite
|