@live-codes/ocaml 0.0.0-stage → 0.1.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.
- package/LICENSE +220 -0
- package/README.md +165 -2
- package/THIRD-PARTY-NOTICES.md +52 -0
- package/assets/compiler/compile_stdout.browser.js +27856 -0
- package/assets/compiler/jsoo.js +12631 -0
- package/assets/compiler/package.json +3 -0
- package/assets/compiler/runtime/bigarray.js +1072 -0
- package/assets/compiler/runtime/bigstring.js +137 -0
- package/assets/compiler/runtime/domain.js +393 -0
- package/assets/compiler/runtime/dynlink.js +91 -0
- package/assets/compiler/runtime/float32.js +486 -0
- package/assets/compiler/runtime/fs.js +416 -0
- package/assets/compiler/runtime/fs_fake.js +600 -0
- package/assets/compiler/runtime/fs_node.js +609 -0
- package/assets/compiler/runtime/fs_quickjs.js +532 -0
- package/assets/compiler/runtime/gc.js +201 -0
- package/assets/compiler/runtime/graphics.js +1053 -0
- package/assets/compiler/runtime/ieee_754.js +621 -0
- package/assets/compiler/runtime/int64.js +516 -0
- package/assets/compiler/runtime/io.js +739 -0
- package/assets/compiler/runtime/jslib.js +553 -0
- package/assets/compiler/runtime/jslib_js_of_ocaml.js +81 -0
- package/assets/compiler/runtime/lexing.js +240 -0
- package/assets/compiler/runtime/manifest.txt +31 -0
- package/assets/compiler/runtime/marshal.js +863 -0
- package/assets/compiler/runtime/md5.js +236 -0
- package/assets/compiler/runtime/mlBytes.js +1007 -0
- package/assets/compiler/runtime/nat.js +469 -0
- package/assets/compiler/runtime/parsing.js +317 -0
- package/assets/compiler/runtime/prng.js +84 -0
- package/assets/compiler/runtime/promise.js +45 -0
- package/assets/compiler/runtime/runtime.js +16688 -0
- package/assets/compiler/runtime/runtime_events.js +90 -0
- package/assets/compiler/runtime/stdlib.js +363 -0
- package/assets/compiler/runtime/sync.js +35 -0
- package/assets/compiler/runtime/toplevel.js +150 -0
- package/assets/compiler/runtime/unix.js +914 -0
- package/assets/compiler/runtime/weak.js +247 -0
- package/assets/compiler/stdlib.js +254 -0
- package/assets/compiler/worker.js +46 -0
- package/assets/interpreter/libs/greet.cma +0 -0
- package/assets/interpreter/libs/greet.cmi +0 -0
- package/assets/interpreter/libs/manifest.txt +1 -0
- package/assets/interpreter/package.json +3 -0
- package/assets/interpreter/stdlib/camlinternalFormat.cmi +0 -0
- package/assets/interpreter/stdlib/camlinternalFormatBasics.cmi +0 -0
- package/assets/interpreter/stdlib/camlinternalLazy.cmi +0 -0
- package/assets/interpreter/stdlib/camlinternalMod.cmi +0 -0
- package/assets/interpreter/stdlib/camlinternalOO.cmi +0 -0
- package/assets/interpreter/stdlib/std_exit.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Arg.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Array.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__ArrayLabels.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Atomic.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Bigarray.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Bool.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Buffer.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Bytes.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__BytesLabels.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Callback.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Char.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Complex.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Condition.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Digest.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Domain.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Dynarray.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Effect.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Either.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Ephemeron.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Filename.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Float.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Format.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Fun.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Gc.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Hashtbl.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Iarray.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__In_channel.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Int.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Int32.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Int64.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Lazy.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Lexing.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__List.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__ListLabels.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Map.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Marshal.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__MoreLabels.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Mutex.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Nativeint.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Obj.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Oo.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Option.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Out_channel.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Pair.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Parsing.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Pqueue.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Printexc.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Printf.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Queue.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Random.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Repr.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Result.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Scanf.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Semaphore.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Seq.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Set.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Stack.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__StdLabels.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__String.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__StringLabels.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Sys.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Type.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Uchar.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Unit.cmi +0 -0
- package/assets/interpreter/stdlib/stdlib__Weak.cmi +0 -0
- package/assets/interpreter/stdlib/topdirs.cmi +0 -0
- package/assets/interpreter/stdlib/units.txt +75 -0
- package/assets/interpreter/stdlib/unix.cmi +0 -0
- package/assets/interpreter/stdlib/unixLabels.cmi +0 -0
- package/assets/interpreter/worker-entry.js +39 -0
- package/assets/interpreter/worker.js +42356 -0
- package/bin/copy-assets.mjs +75 -0
- package/package.json +41 -4
- package/src/compiler/compile.js +170 -0
- package/src/compiler/index.js +46 -0
- package/src/compiler/worker.js +46 -0
- package/src/index.js +12 -0
- package/src/interpreter/api.js +182 -0
- package/src/interpreter/index.js +5 -0
|
@@ -0,0 +1,532 @@
|
|
|
1
|
+
// Js_of_ocaml runtime support
|
|
2
|
+
// http://www.ocsigen.org/js_of_ocaml/
|
|
3
|
+
//
|
|
4
|
+
// This program is free software; you can redistribute it and/or modify
|
|
5
|
+
// it under the terms of the GNU Lesser General Public License as published by
|
|
6
|
+
// the Free Software Foundation, with linking exception;
|
|
7
|
+
// either version 2.1 of the License, or (at your option) any later version.
|
|
8
|
+
//
|
|
9
|
+
// This program is distributed in the hope that it will be useful,
|
|
10
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
11
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
12
|
+
// GNU Lesser General Public License for more details.
|
|
13
|
+
//
|
|
14
|
+
// You should have received a copy of the GNU Lesser General Public License
|
|
15
|
+
// along with this program; if not, write to the Free Software
|
|
16
|
+
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
17
|
+
|
|
18
|
+
// Real-disk device backed by QuickJS-NG's [os] / [std] modules. Active
|
|
19
|
+
// when the runtime detects a qjs host (no `process`, but `os.open` is
|
|
20
|
+
// available). Mirrors the [MlNodeDevice] interface; primitives qjs
|
|
21
|
+
// does not expose ([access], [chmod], [truncate], [link]) raise
|
|
22
|
+
// "not implemented".
|
|
23
|
+
|
|
24
|
+
//Provides: fs_quickjs_supported
|
|
25
|
+
function fs_quickjs_supported() {
|
|
26
|
+
return (
|
|
27
|
+
globalThis.process?.versions?.node === undefined &&
|
|
28
|
+
typeof globalThis.os?.open === "function"
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
//Provides: fs_quickjs_supported
|
|
32
|
+
//If: browser
|
|
33
|
+
function fs_quickjs_supported() {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// POSIX errno -> Unix-error-code string. Linux values; CI runs on
|
|
38
|
+
// Ubuntu so this is the only platform we rely on for now.
|
|
39
|
+
//Provides: caml_qjs_errno_code
|
|
40
|
+
function caml_qjs_errno_code(errno) {
|
|
41
|
+
switch (-errno) {
|
|
42
|
+
case 1:
|
|
43
|
+
return "EPERM";
|
|
44
|
+
case 2:
|
|
45
|
+
return "ENOENT";
|
|
46
|
+
case 5:
|
|
47
|
+
return "EIO";
|
|
48
|
+
case 9:
|
|
49
|
+
return "EBADF";
|
|
50
|
+
case 11:
|
|
51
|
+
return "EAGAIN";
|
|
52
|
+
case 13:
|
|
53
|
+
return "EACCES";
|
|
54
|
+
case 17:
|
|
55
|
+
return "EEXIST";
|
|
56
|
+
case 20:
|
|
57
|
+
return "ENOTDIR";
|
|
58
|
+
case 21:
|
|
59
|
+
return "EISDIR";
|
|
60
|
+
case 22:
|
|
61
|
+
return "EINVAL";
|
|
62
|
+
case 24:
|
|
63
|
+
return "EMFILE";
|
|
64
|
+
case 28:
|
|
65
|
+
return "ENOSPC";
|
|
66
|
+
case 29:
|
|
67
|
+
return "ESPIPE";
|
|
68
|
+
case 30:
|
|
69
|
+
return "EROFS";
|
|
70
|
+
case 32:
|
|
71
|
+
return "EPIPE";
|
|
72
|
+
case 36:
|
|
73
|
+
return "ENAMETOOLONG";
|
|
74
|
+
case 39:
|
|
75
|
+
return "ENOTEMPTY";
|
|
76
|
+
case 40:
|
|
77
|
+
return "ELOOP";
|
|
78
|
+
default:
|
|
79
|
+
return "EUNKNOWN";
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//Provides: caml_raise_qjs_error
|
|
84
|
+
//Requires: caml_raise_system_error, caml_qjs_errno_code
|
|
85
|
+
function caml_raise_qjs_error(errno, syscall, path, raise_unix) {
|
|
86
|
+
var code = caml_qjs_errno_code(errno);
|
|
87
|
+
caml_raise_system_error(raise_unix, code, syscall, "qjs " + syscall, path);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
//Provides: ocaml_stats_from_qjs_stats
|
|
91
|
+
//Requires: caml_int64_of_float
|
|
92
|
+
function ocaml_stats_from_qjs_stats(s, large) {
|
|
93
|
+
var os = globalThis.os;
|
|
94
|
+
var kind_bits = s.mode & (os.S_IFMT || 0o170000);
|
|
95
|
+
var file_kind = 0;
|
|
96
|
+
if (kind_bits === os.S_IFREG) file_kind = 0;
|
|
97
|
+
else if (kind_bits === os.S_IFDIR) file_kind = 1;
|
|
98
|
+
else if (kind_bits === os.S_IFCHR) file_kind = 2;
|
|
99
|
+
else if (kind_bits === os.S_IFBLK) file_kind = 3;
|
|
100
|
+
else if (kind_bits === os.S_IFLNK) file_kind = 4;
|
|
101
|
+
else if (kind_bits === os.S_IFIFO) file_kind = 5;
|
|
102
|
+
else if (kind_bits === os.S_IFSOCK) file_kind = 6;
|
|
103
|
+
return BLOCK(
|
|
104
|
+
0,
|
|
105
|
+
s.dev | 0,
|
|
106
|
+
s.ino | 0,
|
|
107
|
+
file_kind,
|
|
108
|
+
s.mode & 0o7777,
|
|
109
|
+
s.nlink | 0,
|
|
110
|
+
s.uid | 0,
|
|
111
|
+
s.gid | 0,
|
|
112
|
+
s.rdev | 0,
|
|
113
|
+
large ? caml_int64_of_float(s.size) : s.size | 0,
|
|
114
|
+
s.atime / 1000,
|
|
115
|
+
s.mtime / 1000,
|
|
116
|
+
s.ctime / 1000,
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
//Provides: MlQuickJSDevice
|
|
121
|
+
//Requires: MlQuickJSFd, caml_raise_qjs_error, caml_raise_sys_error
|
|
122
|
+
//Requires: caml_raise_system_error
|
|
123
|
+
//Requires: caml_string_of_jsstring, caml_failwith
|
|
124
|
+
//Requires: ocaml_stats_from_qjs_stats
|
|
125
|
+
class MlQuickJSDevice {
|
|
126
|
+
constructor(root) {
|
|
127
|
+
this.os = globalThis.os;
|
|
128
|
+
this.root = root;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
nm(name) {
|
|
132
|
+
return this.root + name;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
exists(name) {
|
|
136
|
+
var r = this.os.stat(this.nm(name));
|
|
137
|
+
return r[1] === 0 ? 1 : 0;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
isFile(name) {
|
|
141
|
+
var r = this.os.stat(this.nm(name));
|
|
142
|
+
if (r[1] !== 0) caml_raise_sys_error("stat " + this.nm(name));
|
|
143
|
+
return (r[0].mode & this.os.S_IFMT) === this.os.S_IFREG ? 1 : 0;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
is_dir(name) {
|
|
147
|
+
var r = this.os.stat(this.nm(name));
|
|
148
|
+
if (r[1] !== 0) caml_raise_sys_error("stat " + this.nm(name));
|
|
149
|
+
return (r[0].mode & this.os.S_IFMT) === this.os.S_IFDIR ? 1 : 0;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
mkdir(name, mode, raise_unix) {
|
|
153
|
+
var err = this.os.mkdir(this.nm(name), mode);
|
|
154
|
+
if (err !== 0)
|
|
155
|
+
caml_raise_qjs_error(err, "mkdir", this.nm(name), raise_unix);
|
|
156
|
+
return 0;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// qjs has no rmdir; os.remove handles directories (fails if non-empty),
|
|
160
|
+
// but it also removes files, so check the type first.
|
|
161
|
+
rmdir(name, raise_unix) {
|
|
162
|
+
var r = this.os.stat(this.nm(name));
|
|
163
|
+
if (
|
|
164
|
+
r[1] === 0 &&
|
|
165
|
+
(r[0].mode & (this.os.S_IFMT || 0o170000)) !== this.os.S_IFDIR
|
|
166
|
+
)
|
|
167
|
+
caml_raise_system_error(
|
|
168
|
+
raise_unix,
|
|
169
|
+
"ENOTDIR",
|
|
170
|
+
"rmdir",
|
|
171
|
+
"not a directory",
|
|
172
|
+
this.nm(name),
|
|
173
|
+
);
|
|
174
|
+
var err = this.os.remove(this.nm(name));
|
|
175
|
+
if (err !== 0)
|
|
176
|
+
caml_raise_qjs_error(err, "rmdir", this.nm(name), raise_unix);
|
|
177
|
+
return 0;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
readdir(name, raise_unix) {
|
|
181
|
+
var r = this.os.readdir(this.nm(name));
|
|
182
|
+
if (r[1] !== 0)
|
|
183
|
+
caml_raise_qjs_error(r[1], "readdir", this.nm(name), raise_unix);
|
|
184
|
+
// qjs includes "." and ".." — strip to match Node.
|
|
185
|
+
return r[0].filter(function (x) {
|
|
186
|
+
return x !== "." && x !== "..";
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// os.remove also removes directories; refuse them like unlink(2)
|
|
191
|
+
unlink(name, raise_unix) {
|
|
192
|
+
var r = this.os.stat(this.nm(name));
|
|
193
|
+
if (
|
|
194
|
+
r[1] === 0 &&
|
|
195
|
+
(r[0].mode & (this.os.S_IFMT || 0o170000)) === this.os.S_IFDIR
|
|
196
|
+
)
|
|
197
|
+
caml_raise_system_error(
|
|
198
|
+
raise_unix,
|
|
199
|
+
"EISDIR",
|
|
200
|
+
"unlink",
|
|
201
|
+
"is a directory",
|
|
202
|
+
this.nm(name),
|
|
203
|
+
);
|
|
204
|
+
var err = this.os.remove(this.nm(name));
|
|
205
|
+
if (err !== 0)
|
|
206
|
+
caml_raise_qjs_error(err, "unlink", this.nm(name), raise_unix);
|
|
207
|
+
return 0;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
utimes(name, atime, mtime, raise_unix) {
|
|
211
|
+
if (atime === 0 && mtime === 0) {
|
|
212
|
+
atime = Date.now() / 1000;
|
|
213
|
+
mtime = atime;
|
|
214
|
+
}
|
|
215
|
+
var err = this.os.utimes(
|
|
216
|
+
this.nm(name),
|
|
217
|
+
Math.round(atime * 1000),
|
|
218
|
+
Math.round(mtime * 1000),
|
|
219
|
+
);
|
|
220
|
+
if (err !== 0)
|
|
221
|
+
caml_raise_qjs_error(err, "utimes", this.nm(name), raise_unix);
|
|
222
|
+
return 0;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
truncate(_name, _len, _raise_unix) {
|
|
226
|
+
caml_failwith("MlQuickJSDevice.truncate: not implemented");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// qjs has no access(); fall back to stat for "f" (existence) only.
|
|
230
|
+
access(name, _f, raise_unix) {
|
|
231
|
+
var r = this.os.stat(this.nm(name));
|
|
232
|
+
if (r[1] !== 0)
|
|
233
|
+
caml_raise_qjs_error(r[1], "access", this.nm(name), raise_unix);
|
|
234
|
+
return 0;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
open(name, f, perms, raise_unix) {
|
|
238
|
+
var os = this.os;
|
|
239
|
+
var flags = 0;
|
|
240
|
+
for (var key in f) {
|
|
241
|
+
switch (key) {
|
|
242
|
+
case "rdonly":
|
|
243
|
+
flags |= os.O_RDONLY;
|
|
244
|
+
break;
|
|
245
|
+
case "wronly":
|
|
246
|
+
flags |= os.O_WRONLY;
|
|
247
|
+
break;
|
|
248
|
+
case "rdwr":
|
|
249
|
+
flags |= os.O_RDWR;
|
|
250
|
+
break;
|
|
251
|
+
case "append":
|
|
252
|
+
flags |= os.O_APPEND;
|
|
253
|
+
break;
|
|
254
|
+
case "create":
|
|
255
|
+
flags |= os.O_CREAT;
|
|
256
|
+
break;
|
|
257
|
+
case "truncate":
|
|
258
|
+
flags |= os.O_TRUNC;
|
|
259
|
+
break;
|
|
260
|
+
case "excl":
|
|
261
|
+
flags |= os.O_EXCL;
|
|
262
|
+
break;
|
|
263
|
+
// binary/text/nonblock/noctty/dsync/sync: not in qjs, ignored.
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
var fd = os.open(this.nm(name), flags, perms === undefined ? 0o666 : perms);
|
|
267
|
+
if (fd < 0) caml_raise_qjs_error(fd, "open", this.nm(name), raise_unix);
|
|
268
|
+
return new MlQuickJSFd(fd, f, this.nm(name));
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
rename(o, n, raise_unix) {
|
|
272
|
+
var err = this.os.rename(this.nm(o), this.nm(n));
|
|
273
|
+
if (err !== 0) caml_raise_qjs_error(err, "rename", this.nm(o), raise_unix);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
stat(name, large, raise_unix) {
|
|
277
|
+
var r = this.os.stat(this.nm(name));
|
|
278
|
+
if (r[1] !== 0)
|
|
279
|
+
caml_raise_qjs_error(r[1], "stat", this.nm(name), raise_unix);
|
|
280
|
+
return ocaml_stats_from_qjs_stats(r[0], large);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
lstat(name, large, raise_unix) {
|
|
284
|
+
var r = this.os.lstat(this.nm(name));
|
|
285
|
+
if (r[1] !== 0)
|
|
286
|
+
caml_raise_qjs_error(r[1], "lstat", this.nm(name), raise_unix);
|
|
287
|
+
return ocaml_stats_from_qjs_stats(r[0], large);
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
chmod(_name, _perms, _raise_unix) {
|
|
291
|
+
caml_failwith("MlQuickJSDevice.chmod: not implemented");
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
link(_target, _path, _raise_unix) {
|
|
295
|
+
caml_failwith("MlQuickJSDevice.link: not implemented");
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
symlink(_to_dir, target, path, raise_unix) {
|
|
299
|
+
var err = this.os.symlink(target, this.nm(path));
|
|
300
|
+
if (err !== 0)
|
|
301
|
+
caml_raise_qjs_error(err, "symlink", this.nm(path), raise_unix);
|
|
302
|
+
return 0;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
readlink(name, raise_unix) {
|
|
306
|
+
var r = this.os.readlink(this.nm(name));
|
|
307
|
+
if (r[1] !== 0)
|
|
308
|
+
caml_raise_qjs_error(r[1], "readlink", this.nm(name), raise_unix);
|
|
309
|
+
return caml_string_of_jsstring(r[0]);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
opendir(_name, _raise_unix) {
|
|
313
|
+
caml_failwith("MlQuickJSDevice.opendir: not implemented");
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
//Provides: MlQuickJSDevice
|
|
318
|
+
//If: browser
|
|
319
|
+
class MlQuickJSDevice {}
|
|
320
|
+
|
|
321
|
+
//Provides: MlQuickJSFd
|
|
322
|
+
//Requires: MlFile, caml_failwith, caml_raise_qjs_error, caml_raise_system_error
|
|
323
|
+
//Requires: ocaml_stats_from_qjs_stats
|
|
324
|
+
class MlQuickJSFd extends MlFile {
|
|
325
|
+
constructor(fd, flags, path) {
|
|
326
|
+
super();
|
|
327
|
+
this.os = globalThis.os;
|
|
328
|
+
this.fd = fd;
|
|
329
|
+
this.flags = flags;
|
|
330
|
+
this.path = path;
|
|
331
|
+
// Like native [O_APPEND], the offset starts at the beginning of the file;
|
|
332
|
+
// each [write] repositions to the end (see [write] below).
|
|
333
|
+
this.offset = 0;
|
|
334
|
+
this.seeked = false;
|
|
335
|
+
flags.noSeek = false;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
isatty() {
|
|
339
|
+
return this.os.isatty(this.fd) ? 1 : 0;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
length() {
|
|
343
|
+
var cur = this.offset;
|
|
344
|
+
var end = this.os.seek(this.fd, 0, 2 /* SEEK_END */);
|
|
345
|
+
this.os.seek(this.fd, cur, 0 /* SEEK_SET */);
|
|
346
|
+
return end;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// qjs's os.read/os.write take an ArrayBuffer + byte offset.
|
|
350
|
+
// The runtime hands us either a Uint8Array view or a raw buffer.
|
|
351
|
+
|
|
352
|
+
read(a, buf_offset, len, raise_unix) {
|
|
353
|
+
if (this.seeked) this.os.seek(this.fd, this.offset, 0);
|
|
354
|
+
var ab = a.buffer || a;
|
|
355
|
+
var base = a.byteOffset || 0;
|
|
356
|
+
var n = this.os.read(this.fd, ab, base + buf_offset, len);
|
|
357
|
+
if (n < 0) caml_raise_qjs_error(n, "read", this.path, raise_unix);
|
|
358
|
+
this.offset += n;
|
|
359
|
+
return n;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
write(buf, buf_offset, len, raise_unix) {
|
|
363
|
+
// [O_APPEND]: every write goes to the end of the file. The OS already
|
|
364
|
+
// enforces this for the bytes (the fd was opened with O_APPEND); we
|
|
365
|
+
// refresh the tracked offset so [pos]/[lseek] report the native value.
|
|
366
|
+
if (this.flags.append) this.offset = this.length();
|
|
367
|
+
if (this.seeked) this.os.seek(this.fd, this.offset, 0);
|
|
368
|
+
var ab = buf.buffer || buf;
|
|
369
|
+
var base = buf.byteOffset || 0;
|
|
370
|
+
var n = this.os.write(this.fd, ab, base + buf_offset, len);
|
|
371
|
+
if (n < 0) caml_raise_qjs_error(n, "write", this.path, raise_unix);
|
|
372
|
+
this.offset += n;
|
|
373
|
+
return n;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
seek(offset, whence, raise_unix) {
|
|
377
|
+
switch (whence) {
|
|
378
|
+
case 0:
|
|
379
|
+
break;
|
|
380
|
+
case 1:
|
|
381
|
+
offset += this.offset;
|
|
382
|
+
break;
|
|
383
|
+
case 2:
|
|
384
|
+
offset += this.length();
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
if (offset < 0)
|
|
388
|
+
caml_raise_system_error(
|
|
389
|
+
raise_unix,
|
|
390
|
+
"EINVAL",
|
|
391
|
+
"lseek",
|
|
392
|
+
"invalid argument",
|
|
393
|
+
);
|
|
394
|
+
this.offset = offset;
|
|
395
|
+
this.seeked = true;
|
|
396
|
+
return this.offset;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
pos() {
|
|
400
|
+
return this.offset;
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
truncate(_len, _raise_unix) {
|
|
404
|
+
caml_failwith("MlQuickJSFd.truncate: not implemented");
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
stat(large) {
|
|
408
|
+
var r = this.os.stat(this.path);
|
|
409
|
+
if (r[1] !== 0) caml_raise_qjs_error(r[1], "fstat", this.path, 1);
|
|
410
|
+
return ocaml_stats_from_qjs_stats(r[0], large);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
chmod(_perms) {
|
|
414
|
+
caml_failwith("MlQuickJSFd.chmod: not implemented");
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
sync() {
|
|
418
|
+
return 0;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
close(raise_unix) {
|
|
422
|
+
var err = this.os.close(this.fd);
|
|
423
|
+
if (err !== 0) caml_raise_qjs_error(err, "close", this.path, raise_unix);
|
|
424
|
+
return 0;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
check_stream_semantics(_cmd) {
|
|
428
|
+
return 0;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
//Provides: MlQuickJSFd
|
|
433
|
+
//If: browser
|
|
434
|
+
class MlQuickJSFd {}
|
|
435
|
+
|
|
436
|
+
// Stream FD wrapping the host's stdin / stdout / stderr (qjs fd 0 / 1 /
|
|
437
|
+
// 2) via os.read / os.write. Used as the qjs counterpart of MlNodeFd
|
|
438
|
+
// for the standard streams; opt-in like the rest of fs_quickjs.
|
|
439
|
+
|
|
440
|
+
//Provides: MlQuickJSStdFd
|
|
441
|
+
//Requires: MlFile, caml_raise_system_error, caml_raise_qjs_error
|
|
442
|
+
class MlQuickJSStdFd extends MlFile {
|
|
443
|
+
constructor(fd, flags) {
|
|
444
|
+
super();
|
|
445
|
+
this.os = globalThis.os;
|
|
446
|
+
this.fd = fd;
|
|
447
|
+
this.flags = flags;
|
|
448
|
+
flags.noSeek = true;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
isatty() {
|
|
452
|
+
return this.os.isatty(this.fd) ? 1 : 0;
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
length() {
|
|
456
|
+
return 0;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
read(a, buf_offset, len, raise_unix) {
|
|
460
|
+
if (this.fd !== 0)
|
|
461
|
+
caml_raise_system_error(
|
|
462
|
+
raise_unix,
|
|
463
|
+
"EBADF",
|
|
464
|
+
"read",
|
|
465
|
+
"bad file descriptor",
|
|
466
|
+
);
|
|
467
|
+
var ab = a.buffer || a;
|
|
468
|
+
var base = a.byteOffset || 0;
|
|
469
|
+
var n = this.os.read(this.fd, ab, base + buf_offset, len);
|
|
470
|
+
// a negative return is an error, not EOF
|
|
471
|
+
if (n < 0) caml_raise_qjs_error(n, "read", "", raise_unix);
|
|
472
|
+
return n;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
write(buf, buf_offset, len, raise_unix) {
|
|
476
|
+
if (this.fd !== 1 && this.fd !== 2)
|
|
477
|
+
caml_raise_system_error(
|
|
478
|
+
raise_unix,
|
|
479
|
+
"EBADF",
|
|
480
|
+
"write",
|
|
481
|
+
"bad file descriptor",
|
|
482
|
+
);
|
|
483
|
+
var ab = buf.buffer || buf;
|
|
484
|
+
var base = buf.byteOffset || 0;
|
|
485
|
+
var n = this.os.write(this.fd, ab, base + buf_offset, len);
|
|
486
|
+
// a negative return is an error; returning 0 would make the
|
|
487
|
+
// flush/write loop spin forever
|
|
488
|
+
if (n < 0) caml_raise_qjs_error(n, "write", "", raise_unix);
|
|
489
|
+
return n;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
seek(_offset, _whence, raise_unix) {
|
|
493
|
+
caml_raise_system_error(raise_unix, "ESPIPE", "lseek", "illegal seek");
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
pos() {
|
|
497
|
+
return -1;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
truncate(_len, raise_unix) {
|
|
501
|
+
caml_raise_system_error(
|
|
502
|
+
raise_unix,
|
|
503
|
+
"EINVAL",
|
|
504
|
+
"ftruncate",
|
|
505
|
+
"invalid argument",
|
|
506
|
+
);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
close(_raise_unix) {
|
|
510
|
+
return 0;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
check_stream_semantics(_cmd) {
|
|
514
|
+
return 0;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
//Provides: MlQuickJSStdFd
|
|
519
|
+
//If: browser
|
|
520
|
+
class MlQuickJSStdFd {}
|
|
521
|
+
|
|
522
|
+
//Provides: caml_sys_open_for_quickjs
|
|
523
|
+
//Requires: MlQuickJSStdFd
|
|
524
|
+
function caml_sys_open_for_quickjs(fd, flags) {
|
|
525
|
+
return new MlQuickJSStdFd(fd, flags);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
//Provides: caml_sys_open_for_quickjs
|
|
529
|
+
//If: browser
|
|
530
|
+
function caml_sys_open_for_quickjs(_fd, _flags) {
|
|
531
|
+
return null;
|
|
532
|
+
}
|