@wasm-oj/server 0.2.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 (94) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +6 -0
  3. package/THIRD_PARTY_NOTICES.md +302 -0
  4. package/crates/runtime-core/Cargo.lock +5099 -0
  5. package/crates/runtime-core/Cargo.toml +66 -0
  6. package/crates/runtime-core/README.md +47 -0
  7. package/crates/runtime-core/src/bin/wasm-oj-compiler.rs +418 -0
  8. package/crates/runtime-core/src/bin/wasm-oj-runner.rs +294 -0
  9. package/crates/runtime-core/src/capabilities.rs +118 -0
  10. package/crates/runtime-core/src/compiler.rs +658 -0
  11. package/crates/runtime-core/src/contract.rs +5 -0
  12. package/crates/runtime-core/src/deterministic.rs +1051 -0
  13. package/crates/runtime-core/src/error.rs +58 -0
  14. package/crates/runtime-core/src/filesystem.rs +547 -0
  15. package/crates/runtime-core/src/filesystem_quota.rs +167 -0
  16. package/crates/runtime-core/src/go_compiler_session.rs +297 -0
  17. package/crates/runtime-core/src/interactive.rs +1019 -0
  18. package/crates/runtime-core/src/judge_package.rs +1539 -0
  19. package/crates/runtime-core/src/lib.rs +98 -0
  20. package/crates/runtime-core/src/memory.rs +84 -0
  21. package/crates/runtime-core/src/meter.rs +549 -0
  22. package/crates/runtime-core/src/module_imports.rs +149 -0
  23. package/crates/runtime-core/src/module_policy.rs +714 -0
  24. package/crates/runtime-core/src/output.rs +204 -0
  25. package/crates/runtime-core/src/run/mod.rs +208 -0
  26. package/crates/runtime-core/src/run/native.rs +260 -0
  27. package/crates/runtime-core/src/run/web.rs +229 -0
  28. package/crates/runtime-core/src/run/web_runtime.rs +109 -0
  29. package/crates/runtime-core/src/types.rs +268 -0
  30. package/crates/runtime-core/src/web.rs +83 -0
  31. package/dist/chunks/go-toolchain-Dbt-lp2L.js +426 -0
  32. package/dist/chunks/java-toolchain-DajoRCHu.js +44 -0
  33. package/dist/chunks/python-toolchain-Dx834o2A.js +4 -0
  34. package/dist/chunks/rust-toolchain-CJ3sMxPE.js +252 -0
  35. package/dist/chunks/toolchains-C6KuA1yM.js +224 -0
  36. package/dist/go-stage.mjs +193 -0
  37. package/dist/index.d.ts +221 -0
  38. package/dist/index.js +4393 -0
  39. package/dist/java-stage.mjs +111 -0
  40. package/dist/python-stage.mjs +90 -0
  41. package/dist/rustc-stage.mjs +301 -0
  42. package/dist/server-build-stage.mjs +2564 -0
  43. package/dist/server-runner-stage.mjs +155 -0
  44. package/licenses/fflate-MIT.txt +21 -0
  45. package/licenses/runtime-core-dependencies.html +6253 -0
  46. package/licenses/runtime-core-dependencies.json +3041 -0
  47. package/licenses/wasmer-sdk-MIT.txt +21 -0
  48. package/licenses/wasmer-sdk-dependencies.html +6901 -0
  49. package/licenses/wasmer-sdk-dependencies.json +3013 -0
  50. package/package.json +70 -0
  51. package/rust-toolchain.toml +5 -0
  52. package/testdata/wojjdg02-v2-text.hex +1 -0
  53. package/vendor/shared-buffer/Cargo.toml +22 -0
  54. package/vendor/shared-buffer/LICENSE_APACHE.md +176 -0
  55. package/vendor/shared-buffer/LICENSE_MIT.md +25 -0
  56. package/vendor/shared-buffer/README.md +34 -0
  57. package/vendor/shared-buffer/src/lib.rs +58 -0
  58. package/vendor/shared-buffer/src/mmap.rs +250 -0
  59. package/vendor/shared-buffer/src/owned.rs +389 -0
  60. package/vendor/virtual-fs/Cargo.toml +181 -0
  61. package/vendor/virtual-fs/LICENSE +25 -0
  62. package/vendor/virtual-fs/src/arc_box_file.rs +142 -0
  63. package/vendor/virtual-fs/src/arc_file.rs +182 -0
  64. package/vendor/virtual-fs/src/arc_fs.rs +68 -0
  65. package/vendor/virtual-fs/src/buffer_file.rs +103 -0
  66. package/vendor/virtual-fs/src/builder.rs +232 -0
  67. package/vendor/virtual-fs/src/combine_file.rs +101 -0
  68. package/vendor/virtual-fs/src/cow_file.rs +345 -0
  69. package/vendor/virtual-fs/src/dual_write_file.rs +113 -0
  70. package/vendor/virtual-fs/src/empty_fs.rs +81 -0
  71. package/vendor/virtual-fs/src/filesystems.rs +108 -0
  72. package/vendor/virtual-fs/src/host_fs.rs +1390 -0
  73. package/vendor/virtual-fs/src/lib.rs +782 -0
  74. package/vendor/virtual-fs/src/limiter.rs +252 -0
  75. package/vendor/virtual-fs/src/mem_fs/file.rs +1799 -0
  76. package/vendor/virtual-fs/src/mem_fs/file_opener.rs +941 -0
  77. package/vendor/virtual-fs/src/mem_fs/filesystem.rs +2134 -0
  78. package/vendor/virtual-fs/src/mem_fs/mod.rs +245 -0
  79. package/vendor/virtual-fs/src/mem_fs/offloaded_file.rs +474 -0
  80. package/vendor/virtual-fs/src/mem_fs/stdio.rs +318 -0
  81. package/vendor/virtual-fs/src/mount_fs.rs +2225 -0
  82. package/vendor/virtual-fs/src/null_file.rs +87 -0
  83. package/vendor/virtual-fs/src/ops.rs +364 -0
  84. package/vendor/virtual-fs/src/overlay_fs.rs +2216 -0
  85. package/vendor/virtual-fs/src/passthru_fs.rs +119 -0
  86. package/vendor/virtual-fs/src/pipe.rs +603 -0
  87. package/vendor/virtual-fs/src/random_file.rs +88 -0
  88. package/vendor/virtual-fs/src/special_file.rs +108 -0
  89. package/vendor/virtual-fs/src/static_file.rs +133 -0
  90. package/vendor/virtual-fs/src/static_fs.rs +460 -0
  91. package/vendor/virtual-fs/src/tmp_fs.rs +95 -0
  92. package/vendor/virtual-fs/src/trace_fs.rs +258 -0
  93. package/vendor/virtual-fs/src/webc_volume_fs.rs +829 -0
  94. package/vendor/virtual-fs/src/zero_file.rs +90 -0
@@ -0,0 +1,87 @@
1
+ //! NullFile is a special file for `/dev/null`, which returns 0 for all
2
+ //! operations except writing.
3
+
4
+ use std::io::{self, *};
5
+ use std::pin::Pin;
6
+ use std::task::{Context, Poll};
7
+
8
+ use tokio::io::{AsyncRead, AsyncSeek, AsyncWrite};
9
+
10
+ use crate::{CloneableVirtualFile, VirtualFile};
11
+
12
+ #[derive(Debug, Clone, Default)]
13
+ pub struct NullFile {}
14
+
15
+ impl AsyncSeek for NullFile {
16
+ fn start_seek(self: Pin<&mut Self>, _position: SeekFrom) -> io::Result<()> {
17
+ Ok(())
18
+ }
19
+ fn poll_complete(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<u64>> {
20
+ Poll::Ready(Ok(0))
21
+ }
22
+ }
23
+
24
+ impl AsyncWrite for NullFile {
25
+ fn poll_write(
26
+ self: Pin<&mut Self>,
27
+ _cx: &mut Context<'_>,
28
+ buf: &[u8],
29
+ ) -> Poll<io::Result<usize>> {
30
+ Poll::Ready(Ok(buf.len()))
31
+ }
32
+ fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
33
+ Poll::Ready(Ok(()))
34
+ }
35
+ fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
36
+ Poll::Ready(Ok(()))
37
+ }
38
+ fn poll_write_vectored(
39
+ self: Pin<&mut Self>,
40
+ _cx: &mut Context<'_>,
41
+ bufs: &[IoSlice<'_>],
42
+ ) -> Poll<io::Result<usize>> {
43
+ Poll::Ready(Ok(bufs.len()))
44
+ }
45
+ fn is_write_vectored(&self) -> bool {
46
+ false
47
+ }
48
+ }
49
+
50
+ impl AsyncRead for NullFile {
51
+ fn poll_read(
52
+ self: Pin<&mut Self>,
53
+ _cx: &mut Context<'_>,
54
+ _buf: &mut tokio::io::ReadBuf<'_>,
55
+ ) -> Poll<io::Result<()>> {
56
+ Poll::Ready(Ok(()))
57
+ }
58
+ }
59
+
60
+ impl VirtualFile for NullFile {
61
+ fn last_accessed(&self) -> u64 {
62
+ 0
63
+ }
64
+ fn last_modified(&self) -> u64 {
65
+ 0
66
+ }
67
+ fn created_time(&self) -> u64 {
68
+ 0
69
+ }
70
+ fn size(&self) -> u64 {
71
+ 0
72
+ }
73
+ fn set_len(&mut self, _new_size: u64) -> crate::Result<()> {
74
+ Ok(())
75
+ }
76
+ fn unlink(&mut self) -> crate::Result<()> {
77
+ Ok(())
78
+ }
79
+ fn poll_read_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<usize>> {
80
+ Poll::Ready(Ok(8192))
81
+ }
82
+ fn poll_write_ready(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<usize>> {
83
+ Poll::Ready(Ok(8192))
84
+ }
85
+ }
86
+
87
+ impl CloneableVirtualFile for NullFile {}
@@ -0,0 +1,364 @@
1
+ //! Common [`FileSystem`] operations.
2
+ #![allow(dead_code)] // Most of these helpers are used during testing
3
+
4
+ use std::{
5
+ collections::VecDeque,
6
+ path::{Path, PathBuf},
7
+ };
8
+
9
+ use futures::future::BoxFuture;
10
+ use tokio::io::{AsyncReadExt, AsyncWriteExt};
11
+
12
+ use crate::{DirEntry, FileSystem, FsError};
13
+
14
+ /// Does this item exists?
15
+ pub fn exists<F>(fs: &F, path: impl AsRef<Path>) -> bool
16
+ where
17
+ F: FileSystem + ?Sized,
18
+ {
19
+ fs.metadata(path.as_ref()).is_ok()
20
+ }
21
+
22
+ /// Does this path refer to a directory?
23
+ pub fn is_dir<F>(fs: &F, path: impl AsRef<Path>) -> bool
24
+ where
25
+ F: FileSystem + ?Sized,
26
+ {
27
+ match fs.metadata(path.as_ref()) {
28
+ Ok(meta) => meta.is_dir(),
29
+ Err(_) => false,
30
+ }
31
+ }
32
+
33
+ /// Does this path refer to a file?
34
+ pub fn is_file<F>(fs: &F, path: impl AsRef<Path>) -> bool
35
+ where
36
+ F: FileSystem + ?Sized,
37
+ {
38
+ match fs.metadata(path.as_ref()) {
39
+ Ok(meta) => meta.is_file(),
40
+ Err(_) => false,
41
+ }
42
+ }
43
+
44
+ /// Make sure a directory (and all its parents) exist.
45
+ ///
46
+ /// This is analogous to [`std::fs::create_dir_all()`].
47
+ pub fn create_dir_all<F>(fs: &F, path: impl AsRef<Path>) -> Result<(), FsError>
48
+ where
49
+ F: FileSystem + ?Sized,
50
+ {
51
+ let path = path.as_ref();
52
+ if let Some(parent) = path.parent() {
53
+ create_dir_all(fs, parent)?;
54
+ }
55
+
56
+ if let Ok(metadata) = fs.metadata(path) {
57
+ if metadata.is_dir() {
58
+ return Ok(());
59
+ }
60
+ if metadata.is_file() {
61
+ return Err(FsError::BaseNotDirectory);
62
+ }
63
+ }
64
+
65
+ fs.create_dir(path)
66
+ }
67
+
68
+ static WHITEOUT_PREFIX: &str = ".wh.";
69
+
70
+ /// Creates a white out file which hides it from secondary file systems
71
+ pub fn create_white_out<F>(fs: &F, path: impl AsRef<Path>) -> Result<(), FsError>
72
+ where
73
+ F: FileSystem + ?Sized,
74
+ {
75
+ if let Some(filename) = path.as_ref().file_name() {
76
+ let mut path = path.as_ref().to_owned();
77
+ path.set_file_name(format!("{}{}", WHITEOUT_PREFIX, filename.to_string_lossy()));
78
+
79
+ if let Some(parent) = path.parent() {
80
+ create_dir_all(fs, parent).ok();
81
+ }
82
+
83
+ fs.new_open_options()
84
+ .create_new(true)
85
+ .truncate(true)
86
+ .write(true)
87
+ .open(path)?;
88
+ Ok(())
89
+ } else {
90
+ Err(FsError::EntryNotFound)
91
+ }
92
+ }
93
+
94
+ /// Removes a white out file from the primary
95
+ pub fn remove_white_out<F>(fs: &F, path: impl AsRef<Path>)
96
+ where
97
+ F: FileSystem + ?Sized,
98
+ {
99
+ if let Some(filename) = path.as_ref().file_name() {
100
+ let mut path = path.as_ref().to_owned();
101
+ path.set_file_name(format!("{}{}", WHITEOUT_PREFIX, filename.to_string_lossy()));
102
+ fs.remove_file(&path).ok();
103
+ }
104
+ }
105
+
106
+ /// Returns true if the path has been hidden by a whiteout file
107
+ pub fn has_white_out<F>(fs: &F, path: impl AsRef<Path>) -> bool
108
+ where
109
+ F: FileSystem + ?Sized,
110
+ {
111
+ if let Some(filename) = path.as_ref().file_name() {
112
+ let mut path = path.as_ref().to_owned();
113
+ path.set_file_name(format!("{}{}", WHITEOUT_PREFIX, filename.to_string_lossy()));
114
+ fs.metadata(&path).is_ok()
115
+ } else {
116
+ false
117
+ }
118
+ }
119
+
120
+ /// Returns true if the path is a whiteout file
121
+ pub fn is_white_out(path: impl AsRef<Path>) -> Option<PathBuf> {
122
+ if let Some(filename) = path.as_ref().file_name()
123
+ && let Some(filename) = filename.to_string_lossy().strip_prefix(WHITEOUT_PREFIX)
124
+ {
125
+ let mut path = path.as_ref().to_owned();
126
+ path.set_file_name(filename);
127
+ return Some(path);
128
+ }
129
+ None
130
+ }
131
+
132
+ /// Copies the reference of a file from one file system to another
133
+ pub fn copy_reference<'a>(
134
+ source: &'a (impl FileSystem + ?Sized),
135
+ destination: &'a (impl FileSystem + ?Sized),
136
+ path: &'a Path,
137
+ ) -> BoxFuture<'a, Result<(), std::io::Error>> {
138
+ Box::pin(async { copy_reference_ext(source, destination, path, path).await })
139
+ }
140
+
141
+ /// Copies the reference of a file from one file system to another
142
+ pub fn copy_reference_ext<'a>(
143
+ source: &'a (impl FileSystem + ?Sized),
144
+ destination: &'a (impl FileSystem + ?Sized),
145
+ from: &Path,
146
+ to: &Path,
147
+ ) -> BoxFuture<'a, Result<(), std::io::Error>> {
148
+ let from = from.to_owned();
149
+ let to = to.to_owned();
150
+ Box::pin(async move {
151
+ let src = source.new_open_options().read(true).open(from)?;
152
+ let mut dst = destination
153
+ .new_open_options()
154
+ .create(true)
155
+ .write(true)
156
+ .truncate(true)
157
+ .open(to)?;
158
+
159
+ dst.copy_reference(src).await?;
160
+ Ok(())
161
+ })
162
+ }
163
+
164
+ /// Move a file across filesystem boundaries by copying it into the destination
165
+ /// and then removing the original.
166
+ pub fn move_across_filesystems<'a>(
167
+ source: &'a (impl FileSystem + ?Sized),
168
+ destination: &'a (impl FileSystem + ?Sized),
169
+ from: &'a Path,
170
+ to: &'a Path,
171
+ ) -> BoxFuture<'a, crate::Result<()>> {
172
+ let from = from.to_owned();
173
+ let to = to.to_owned();
174
+ Box::pin(async move {
175
+ let metadata = source.metadata(&from)?;
176
+ if metadata.is_dir() {
177
+ return Err(FsError::InvalidInput);
178
+ }
179
+
180
+ copy_reference_ext(source, destination, &from, &to)
181
+ .await
182
+ .map_err(FsError::from)?;
183
+
184
+ if let Err(error) = source.remove_file(&from) {
185
+ tracing::warn!(
186
+ ?from,
187
+ ?to,
188
+ ?error,
189
+ "Failed to remove file after cross-filesystem rename"
190
+ );
191
+ }
192
+
193
+ Ok(())
194
+ })
195
+ }
196
+
197
+ /// Asynchronously write some bytes to a file.
198
+ ///
199
+ /// This is analogous to [`std::fs::write()`].
200
+ pub async fn write<F>(
201
+ fs: &F,
202
+ path: impl AsRef<Path> + Send,
203
+ data: impl AsRef<[u8]> + Send,
204
+ ) -> Result<(), FsError>
205
+ where
206
+ F: FileSystem + ?Sized,
207
+ {
208
+ let path = path.as_ref();
209
+ let data = data.as_ref();
210
+
211
+ let mut f = fs
212
+ .new_open_options()
213
+ .create(true)
214
+ .truncate(true)
215
+ .write(true)
216
+ .open(path)?;
217
+
218
+ f.write_all(data).await?;
219
+ f.flush().await?;
220
+
221
+ Ok(())
222
+ }
223
+
224
+ /// Asynchronously read a file's contents into memory.
225
+ ///
226
+ /// This is analogous to [`std::fs::read()`].
227
+ pub async fn read<F>(fs: &F, path: impl AsRef<Path> + Send) -> Result<Vec<u8>, FsError>
228
+ where
229
+ F: FileSystem + ?Sized,
230
+ {
231
+ let mut f = fs.new_open_options().read(true).open(path.as_ref())?;
232
+ let mut buffer = Vec::new();
233
+ f.read_to_end(&mut buffer).await?;
234
+
235
+ Ok(buffer)
236
+ }
237
+
238
+ /// Asynchronously read a file's contents into memory as a string.
239
+ ///
240
+ /// This is analogous to [`std::fs::read_to_string()`].
241
+ pub async fn read_to_string<F>(fs: &F, path: impl AsRef<Path> + Send) -> Result<String, FsError>
242
+ where
243
+ F: FileSystem + ?Sized,
244
+ {
245
+ let mut f = fs.new_open_options().read(true).open(path.as_ref())?;
246
+ let mut buffer = String::new();
247
+ f.read_to_string(&mut buffer).await?;
248
+
249
+ Ok(buffer)
250
+ }
251
+
252
+ /// Update a file's modification and access times, creating the file if it
253
+ /// doesn't already exist.
254
+ pub fn touch<F>(fs: &F, path: impl AsRef<Path> + Send) -> Result<(), FsError>
255
+ where
256
+ F: FileSystem + ?Sized,
257
+ {
258
+ let _ = fs.new_open_options().create(true).write(true).open(path)?;
259
+
260
+ Ok(())
261
+ }
262
+
263
+ /// Recursively iterate over all paths inside a directory, ignoring any
264
+ /// errors that may occur along the way.
265
+ pub fn walk<F>(fs: &F, path: impl AsRef<Path>) -> Box<dyn Iterator<Item = DirEntry> + '_>
266
+ where
267
+ F: FileSystem + ?Sized,
268
+ {
269
+ let path = path.as_ref();
270
+ let mut dirs_to_visit: VecDeque<_> = fs
271
+ .read_dir(path)
272
+ .ok()
273
+ .into_iter()
274
+ .flatten()
275
+ .filter_map(|result| result.ok())
276
+ .collect();
277
+
278
+ Box::new(std::iter::from_fn(move || {
279
+ let next = dirs_to_visit.pop_back()?;
280
+
281
+ if let Ok(children) = fs.read_dir(&next.path) {
282
+ dirs_to_visit.extend(children.flatten());
283
+ }
284
+
285
+ Some(next)
286
+ }))
287
+ }
288
+
289
+ #[cfg(test)]
290
+ mod tests {
291
+ use super::*;
292
+ use crate::mem_fs::FileSystem as MemFS;
293
+ use tokio::io::AsyncReadExt;
294
+
295
+ #[tokio::test]
296
+ async fn write() {
297
+ let fs = MemFS::default();
298
+
299
+ super::write(&fs, "/file.txt", b"Hello, World!")
300
+ .await
301
+ .unwrap();
302
+
303
+ let mut contents = String::new();
304
+ fs.new_open_options()
305
+ .read(true)
306
+ .open("/file.txt")
307
+ .unwrap()
308
+ .read_to_string(&mut contents)
309
+ .await
310
+ .unwrap();
311
+ assert_eq!(contents, "Hello, World!");
312
+ }
313
+
314
+ #[tokio::test]
315
+ async fn read() {
316
+ let fs = MemFS::default();
317
+ fs.new_open_options()
318
+ .create(true)
319
+ .write(true)
320
+ .open("/file.txt")
321
+ .unwrap()
322
+ .write_all(b"Hello, World!")
323
+ .await
324
+ .unwrap();
325
+
326
+ let contents = super::read_to_string(&fs, "/file.txt").await.unwrap();
327
+ assert_eq!(contents, "Hello, World!");
328
+
329
+ let contents = super::read(&fs, "/file.txt").await.unwrap();
330
+ assert_eq!(contents, b"Hello, World!");
331
+ }
332
+
333
+ #[tokio::test]
334
+ async fn create_dir_all() {
335
+ let fs = MemFS::default();
336
+ super::write(&fs, "/file.txt", b"").await.unwrap();
337
+
338
+ assert!(!super::exists(&fs, "/really/nested/directory"));
339
+ super::create_dir_all(&fs, "/really/nested/directory").unwrap();
340
+ assert!(super::exists(&fs, "/really/nested/directory"));
341
+
342
+ // It's okay to create the same directory multiple times
343
+ super::create_dir_all(&fs, "/really/nested/directory").unwrap();
344
+
345
+ // You can't create a directory on top of a file
346
+ assert_eq!(
347
+ super::create_dir_all(&fs, "/file.txt").unwrap_err(),
348
+ FsError::BaseNotDirectory
349
+ );
350
+ assert_eq!(
351
+ super::create_dir_all(&fs, "/file.txt/invalid/path").unwrap_err(),
352
+ FsError::BaseNotDirectory
353
+ );
354
+ }
355
+
356
+ #[tokio::test]
357
+ async fn touch() {
358
+ let fs = MemFS::default();
359
+
360
+ super::touch(&fs, "/file.txt").unwrap();
361
+
362
+ assert_eq!(super::read(&fs, "/file.txt").await.unwrap(), b"");
363
+ }
364
+ }