@live-codes/ocaml 0.0.0-stage → 0.1.1

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 (130) hide show
  1. package/LICENSE +220 -0
  2. package/README.md +165 -2
  3. package/THIRD-PARTY-NOTICES.md +52 -0
  4. package/assets/compiler/compile_stdout.browser.js +27856 -0
  5. package/assets/compiler/jsoo.js +12631 -0
  6. package/assets/compiler/package.json +3 -0
  7. package/assets/compiler/runtime/bigarray.js +1072 -0
  8. package/assets/compiler/runtime/bigstring.js +137 -0
  9. package/assets/compiler/runtime/domain.js +393 -0
  10. package/assets/compiler/runtime/dynlink.js +91 -0
  11. package/assets/compiler/runtime/float32.js +486 -0
  12. package/assets/compiler/runtime/fs.js +416 -0
  13. package/assets/compiler/runtime/fs_fake.js +600 -0
  14. package/assets/compiler/runtime/fs_node.js +609 -0
  15. package/assets/compiler/runtime/fs_quickjs.js +532 -0
  16. package/assets/compiler/runtime/gc.js +201 -0
  17. package/assets/compiler/runtime/graphics.js +1053 -0
  18. package/assets/compiler/runtime/ieee_754.js +621 -0
  19. package/assets/compiler/runtime/int64.js +516 -0
  20. package/assets/compiler/runtime/io.js +739 -0
  21. package/assets/compiler/runtime/jslib.js +553 -0
  22. package/assets/compiler/runtime/jslib_js_of_ocaml.js +81 -0
  23. package/assets/compiler/runtime/lexing.js +240 -0
  24. package/assets/compiler/runtime/manifest.txt +31 -0
  25. package/assets/compiler/runtime/marshal.js +863 -0
  26. package/assets/compiler/runtime/md5.js +236 -0
  27. package/assets/compiler/runtime/mlBytes.js +1007 -0
  28. package/assets/compiler/runtime/nat.js +469 -0
  29. package/assets/compiler/runtime/parsing.js +317 -0
  30. package/assets/compiler/runtime/prng.js +84 -0
  31. package/assets/compiler/runtime/promise.js +45 -0
  32. package/assets/compiler/runtime/runtime.js +16688 -0
  33. package/assets/compiler/runtime/runtime_events.js +90 -0
  34. package/assets/compiler/runtime/stdlib.js +363 -0
  35. package/assets/compiler/runtime/sync.js +35 -0
  36. package/assets/compiler/runtime/toplevel.js +150 -0
  37. package/assets/compiler/runtime/unix.js +914 -0
  38. package/assets/compiler/runtime/weak.js +247 -0
  39. package/assets/compiler/stdlib.js +254 -0
  40. package/assets/compiler/worker.js +46 -0
  41. package/assets/interpreter/libs/greet.cma +0 -0
  42. package/assets/interpreter/libs/greet.cmi +0 -0
  43. package/assets/interpreter/libs/manifest.txt +1 -0
  44. package/assets/interpreter/package.json +3 -0
  45. package/assets/interpreter/stdlib/camlinternalFormat.cmi +0 -0
  46. package/assets/interpreter/stdlib/camlinternalFormatBasics.cmi +0 -0
  47. package/assets/interpreter/stdlib/camlinternalLazy.cmi +0 -0
  48. package/assets/interpreter/stdlib/camlinternalMod.cmi +0 -0
  49. package/assets/interpreter/stdlib/camlinternalOO.cmi +0 -0
  50. package/assets/interpreter/stdlib/std_exit.cmi +0 -0
  51. package/assets/interpreter/stdlib/stdlib.cmi +0 -0
  52. package/assets/interpreter/stdlib/stdlib__Arg.cmi +0 -0
  53. package/assets/interpreter/stdlib/stdlib__Array.cmi +0 -0
  54. package/assets/interpreter/stdlib/stdlib__ArrayLabels.cmi +0 -0
  55. package/assets/interpreter/stdlib/stdlib__Atomic.cmi +0 -0
  56. package/assets/interpreter/stdlib/stdlib__Bigarray.cmi +0 -0
  57. package/assets/interpreter/stdlib/stdlib__Bool.cmi +0 -0
  58. package/assets/interpreter/stdlib/stdlib__Buffer.cmi +0 -0
  59. package/assets/interpreter/stdlib/stdlib__Bytes.cmi +0 -0
  60. package/assets/interpreter/stdlib/stdlib__BytesLabels.cmi +0 -0
  61. package/assets/interpreter/stdlib/stdlib__Callback.cmi +0 -0
  62. package/assets/interpreter/stdlib/stdlib__Char.cmi +0 -0
  63. package/assets/interpreter/stdlib/stdlib__Complex.cmi +0 -0
  64. package/assets/interpreter/stdlib/stdlib__Condition.cmi +0 -0
  65. package/assets/interpreter/stdlib/stdlib__Digest.cmi +0 -0
  66. package/assets/interpreter/stdlib/stdlib__Domain.cmi +0 -0
  67. package/assets/interpreter/stdlib/stdlib__Dynarray.cmi +0 -0
  68. package/assets/interpreter/stdlib/stdlib__Effect.cmi +0 -0
  69. package/assets/interpreter/stdlib/stdlib__Either.cmi +0 -0
  70. package/assets/interpreter/stdlib/stdlib__Ephemeron.cmi +0 -0
  71. package/assets/interpreter/stdlib/stdlib__Filename.cmi +0 -0
  72. package/assets/interpreter/stdlib/stdlib__Float.cmi +0 -0
  73. package/assets/interpreter/stdlib/stdlib__Format.cmi +0 -0
  74. package/assets/interpreter/stdlib/stdlib__Fun.cmi +0 -0
  75. package/assets/interpreter/stdlib/stdlib__Gc.cmi +0 -0
  76. package/assets/interpreter/stdlib/stdlib__Hashtbl.cmi +0 -0
  77. package/assets/interpreter/stdlib/stdlib__Iarray.cmi +0 -0
  78. package/assets/interpreter/stdlib/stdlib__In_channel.cmi +0 -0
  79. package/assets/interpreter/stdlib/stdlib__Int.cmi +0 -0
  80. package/assets/interpreter/stdlib/stdlib__Int32.cmi +0 -0
  81. package/assets/interpreter/stdlib/stdlib__Int64.cmi +0 -0
  82. package/assets/interpreter/stdlib/stdlib__Lazy.cmi +0 -0
  83. package/assets/interpreter/stdlib/stdlib__Lexing.cmi +0 -0
  84. package/assets/interpreter/stdlib/stdlib__List.cmi +0 -0
  85. package/assets/interpreter/stdlib/stdlib__ListLabels.cmi +0 -0
  86. package/assets/interpreter/stdlib/stdlib__Map.cmi +0 -0
  87. package/assets/interpreter/stdlib/stdlib__Marshal.cmi +0 -0
  88. package/assets/interpreter/stdlib/stdlib__MoreLabels.cmi +0 -0
  89. package/assets/interpreter/stdlib/stdlib__Mutex.cmi +0 -0
  90. package/assets/interpreter/stdlib/stdlib__Nativeint.cmi +0 -0
  91. package/assets/interpreter/stdlib/stdlib__Obj.cmi +0 -0
  92. package/assets/interpreter/stdlib/stdlib__Oo.cmi +0 -0
  93. package/assets/interpreter/stdlib/stdlib__Option.cmi +0 -0
  94. package/assets/interpreter/stdlib/stdlib__Out_channel.cmi +0 -0
  95. package/assets/interpreter/stdlib/stdlib__Pair.cmi +0 -0
  96. package/assets/interpreter/stdlib/stdlib__Parsing.cmi +0 -0
  97. package/assets/interpreter/stdlib/stdlib__Pqueue.cmi +0 -0
  98. package/assets/interpreter/stdlib/stdlib__Printexc.cmi +0 -0
  99. package/assets/interpreter/stdlib/stdlib__Printf.cmi +0 -0
  100. package/assets/interpreter/stdlib/stdlib__Queue.cmi +0 -0
  101. package/assets/interpreter/stdlib/stdlib__Random.cmi +0 -0
  102. package/assets/interpreter/stdlib/stdlib__Repr.cmi +0 -0
  103. package/assets/interpreter/stdlib/stdlib__Result.cmi +0 -0
  104. package/assets/interpreter/stdlib/stdlib__Scanf.cmi +0 -0
  105. package/assets/interpreter/stdlib/stdlib__Semaphore.cmi +0 -0
  106. package/assets/interpreter/stdlib/stdlib__Seq.cmi +0 -0
  107. package/assets/interpreter/stdlib/stdlib__Set.cmi +0 -0
  108. package/assets/interpreter/stdlib/stdlib__Stack.cmi +0 -0
  109. package/assets/interpreter/stdlib/stdlib__StdLabels.cmi +0 -0
  110. package/assets/interpreter/stdlib/stdlib__String.cmi +0 -0
  111. package/assets/interpreter/stdlib/stdlib__StringLabels.cmi +0 -0
  112. package/assets/interpreter/stdlib/stdlib__Sys.cmi +0 -0
  113. package/assets/interpreter/stdlib/stdlib__Type.cmi +0 -0
  114. package/assets/interpreter/stdlib/stdlib__Uchar.cmi +0 -0
  115. package/assets/interpreter/stdlib/stdlib__Unit.cmi +0 -0
  116. package/assets/interpreter/stdlib/stdlib__Weak.cmi +0 -0
  117. package/assets/interpreter/stdlib/topdirs.cmi +0 -0
  118. package/assets/interpreter/stdlib/units.txt +75 -0
  119. package/assets/interpreter/stdlib/unix.cmi +0 -0
  120. package/assets/interpreter/stdlib/unixLabels.cmi +0 -0
  121. package/assets/interpreter/worker-entry.js +39 -0
  122. package/assets/interpreter/worker.js +42356 -0
  123. package/bin/copy-assets.mjs +75 -0
  124. package/package.json +41 -4
  125. package/src/compiler/compile.js +195 -0
  126. package/src/compiler/index.js +46 -0
  127. package/src/compiler/worker.js +46 -0
  128. package/src/index.js +12 -0
  129. package/src/interpreter/api.js +182 -0
  130. package/src/interpreter/index.js +5 -0
@@ -0,0 +1,600 @@
1
+ // Js_of_ocaml runtime support
2
+ // http://www.ocsigen.org/js_of_ocaml/
3
+ // Copyright (C) 2014 Jérôme Vouillon, Hugo Heuzard
4
+ // Laboratoire PPS - CNRS Université Paris Diderot
5
+ //
6
+ // This program is free software; you can redistribute it and/or modify
7
+ // it under the terms of the GNU Lesser General Public License as published by
8
+ // the Free Software Foundation, with linking exception;
9
+ // either version 2.1 of the License, or (at your option) any later version.
10
+ //
11
+ // This program is distributed in the hope that it will be useful,
12
+ // but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ // GNU Lesser General Public License for more details.
15
+ //
16
+ // You should have received a copy of the GNU Lesser General Public License
17
+ // along with this program; if not, write to the Free Software
18
+ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
+
20
+ //Provides: MlFakeDevice
21
+ //Requires: MlFakeFile, MlFakeFd, caml_create_bytes
22
+ //Requires: caml_raise_sys_error, caml_raise_no_such_file
23
+ //Requires: caml_string_of_jsbytes, caml_string_of_jsstring
24
+ //Requires: caml_bytes_of_array, caml_bytes_of_string, caml_bytes_of_jsbytes
25
+ //Requires: caml_is_ml_bytes, caml_is_ml_string
26
+ //Requires: caml_raise_system_error
27
+ class MlFakeDevice {
28
+ constructor(root, f) {
29
+ this.content = {};
30
+ this.root = root;
31
+ this.lookupFun = f;
32
+ }
33
+
34
+ nm(name) {
35
+ return this.root + name;
36
+ }
37
+
38
+ create_dir_if_needed(name) {
39
+ var comp = name.split("/");
40
+ var res = "";
41
+ for (var i = 0; i < comp.length - 1; i++) {
42
+ res += comp[i] + "/";
43
+ if (this.content[res]) continue;
44
+ this.content[res] = Symbol("directory");
45
+ }
46
+ }
47
+
48
+ slash(name) {
49
+ return /\/$/.test(name) ? name : name + "/";
50
+ }
51
+
52
+ lookup(name) {
53
+ if (!this.content[name] && this.lookupFun) {
54
+ var res = this.lookupFun(
55
+ caml_string_of_jsstring(this.root),
56
+ caml_string_of_jsstring(name),
57
+ );
58
+ if (res !== 0) {
59
+ this.create_dir_if_needed(name);
60
+ this.content[name] = new MlFakeFile(caml_bytes_of_string(res[1]));
61
+ }
62
+ }
63
+ }
64
+
65
+ exists(name, do_not_lookup) {
66
+ // The root of the device exists
67
+ if (name === "") return 1;
68
+ // Check if a directory exists
69
+ var name_slash = this.slash(name);
70
+ if (this.content[name_slash]) return 1;
71
+ // Check if a file exists
72
+ if (!do_not_lookup) this.lookup(name);
73
+ return this.content[name] ? 1 : 0;
74
+ }
75
+
76
+ isFile(name) {
77
+ if (this.exists(name) && !this.is_dir(name)) {
78
+ return 1;
79
+ } else {
80
+ return 0;
81
+ }
82
+ }
83
+
84
+ rename_dir(oldname, newname, raise_unix) {
85
+ var old_slash = this.slash(oldname);
86
+ var new_slash = this.slash(newname);
87
+ if (newname !== oldname && new_slash.startsWith(old_slash))
88
+ // renaming a directory into its own subtree would recurse forever
89
+ caml_raise_system_error(
90
+ raise_unix,
91
+ "EINVAL",
92
+ "rename",
93
+ "invalid argument",
94
+ this.nm(newname),
95
+ );
96
+ if (this.exists(newname)) {
97
+ if (!this.is_dir(newname)) {
98
+ caml_raise_system_error(
99
+ raise_unix,
100
+ "ENOTDIR",
101
+ "rename",
102
+ "not a directory",
103
+ this.nm(newname),
104
+ );
105
+ }
106
+ if (this.readdir(newname).length > 0) {
107
+ caml_raise_system_error(
108
+ raise_unix,
109
+ "ENOTEMPTY",
110
+ "rename",
111
+ "directory not empty",
112
+ this.nm(newname),
113
+ );
114
+ }
115
+ }
116
+ this.create_dir_if_needed(new_slash);
117
+ for (const f of this.readdir(oldname)) {
118
+ this.rename(old_slash + f, new_slash + f, raise_unix);
119
+ }
120
+ delete this.content[old_slash];
121
+ }
122
+
123
+ rename(oldname, newname, raise_unix) {
124
+ if (!this.exists(oldname))
125
+ caml_raise_no_such_file(this.nm(oldname), raise_unix, "rename");
126
+ if (this.is_dir(oldname)) {
127
+ this.rename_dir(oldname, newname, raise_unix);
128
+ } else {
129
+ if (this.exists(newname) && this.is_dir(newname)) {
130
+ caml_raise_system_error(
131
+ raise_unix,
132
+ "EISDIR",
133
+ "rename",
134
+ "is a directory",
135
+ this.nm(newname),
136
+ );
137
+ }
138
+ if (newname !== oldname) {
139
+ this.content[newname] = this.content[oldname];
140
+ delete this.content[oldname];
141
+ }
142
+ }
143
+ }
144
+
145
+ mkdir(name, _mode, raise_unix) {
146
+ if (this.exists(name))
147
+ caml_raise_system_error(
148
+ raise_unix,
149
+ "EEXIST",
150
+ "mkdir",
151
+ "file already exists",
152
+ this.nm(name),
153
+ );
154
+ var parent = /^(.*)\/[^/]+/.exec(name);
155
+ parent = parent?.[1] || "";
156
+ if (!this.exists(parent))
157
+ caml_raise_system_error(
158
+ raise_unix,
159
+ "ENOENT",
160
+ "mkdir",
161
+ "no such file or directory",
162
+ this.nm(name),
163
+ );
164
+ if (!this.is_dir(parent))
165
+ caml_raise_system_error(
166
+ raise_unix,
167
+ "ENOTDIR",
168
+ "mkdir",
169
+ "not a directory",
170
+ this.nm(name),
171
+ );
172
+ this.create_dir_if_needed(this.slash(name));
173
+ }
174
+
175
+ rmdir(name, raise_unix) {
176
+ var name_slash = name === "" ? "" : this.slash(name);
177
+ if (!this.exists(name))
178
+ caml_raise_system_error(
179
+ raise_unix,
180
+ "ENOENT",
181
+ "rmdir",
182
+ "no such file or directory",
183
+ this.nm(name),
184
+ );
185
+ if (!this.is_dir(name))
186
+ caml_raise_system_error(
187
+ raise_unix,
188
+ "ENOTDIR",
189
+ "rmdir",
190
+ "not a directory",
191
+ this.nm(name),
192
+ );
193
+ for (var n in this.content) {
194
+ if (n.startsWith(name_slash) && n !== name_slash)
195
+ caml_raise_system_error(
196
+ raise_unix,
197
+ "ENOTEMPTY",
198
+ "rmdir",
199
+ "directory not empty",
200
+ this.nm(name),
201
+ );
202
+ }
203
+ delete this.content[name_slash];
204
+ }
205
+
206
+ readdir(name, raise_unix) {
207
+ var name_slash = name === "" ? "" : this.slash(name);
208
+ if (!this.exists(name)) {
209
+ caml_raise_no_such_file(this.nm(name), raise_unix, "readdir");
210
+ }
211
+ if (!this.is_dir(name)) {
212
+ caml_raise_system_error(
213
+ raise_unix,
214
+ "ENOTDIR",
215
+ "readdir",
216
+ "not a directory",
217
+ this.nm(name),
218
+ );
219
+ }
220
+ var seen = {};
221
+ var a = [];
222
+ for (var n in this.content) {
223
+ if (n.startsWith(name_slash) && n !== name_slash) {
224
+ var last = n.indexOf("/", name_slash.length);
225
+ if (last < 0) last = undefined;
226
+ var m = n.slice(name_slash.length, last);
227
+ if (m && !seen[m]) {
228
+ seen[m] = true;
229
+ a.push(m);
230
+ }
231
+ }
232
+ }
233
+ return a;
234
+ }
235
+
236
+ opendir(name, raise_unix) {
237
+ var a = this.readdir(name, raise_unix);
238
+ var c = false;
239
+ var i = 0;
240
+ return {
241
+ readSync: function () {
242
+ if (c)
243
+ caml_raise_system_error(
244
+ raise_unix,
245
+ "EBADF",
246
+ "readdir",
247
+ "bad file descriptor",
248
+ );
249
+ if (i === a.length) return null;
250
+ var entry = a[i];
251
+ i++;
252
+ return { name: entry };
253
+ },
254
+ closeSync: function () {
255
+ if (c)
256
+ caml_raise_system_error(
257
+ raise_unix,
258
+ "EBADF",
259
+ "readdir",
260
+ "bad file descriptor",
261
+ );
262
+ c = true;
263
+ a = [];
264
+ },
265
+ };
266
+ }
267
+
268
+ is_dir(name) {
269
+ if (name === "") return true;
270
+ var name_slash = this.slash(name);
271
+ return this.content[name_slash] ? 1 : 0;
272
+ }
273
+
274
+ unlink(name, raise_unix) {
275
+ if (!this.exists(name, true)) {
276
+ // [true] means no "lookup" if not found.
277
+ caml_raise_system_error(
278
+ raise_unix,
279
+ "ENOENT",
280
+ "unlink",
281
+ "no such file or directory",
282
+ name,
283
+ );
284
+ }
285
+ if (this.is_dir(name))
286
+ caml_raise_system_error(
287
+ raise_unix,
288
+ "EISDIR",
289
+ "unlink",
290
+ "is a directory",
291
+ this.nm(name),
292
+ );
293
+ delete this.content[name];
294
+ return 0;
295
+ }
296
+
297
+ access(name, _flags, raise_unix) {
298
+ this.lookup(name);
299
+ if (!this.exists(name))
300
+ caml_raise_no_such_file(this.nm(name), raise_unix, "access");
301
+ return 0;
302
+ }
303
+
304
+ open(name, f, _perms, raise_unix) {
305
+ var file;
306
+ this.lookup(name);
307
+ if (this.content[name]) {
308
+ if (this.is_dir(name))
309
+ caml_raise_system_error(
310
+ raise_unix,
311
+ "EISDIR",
312
+ "open",
313
+ "illegal operation on a directory",
314
+ this.nm(name),
315
+ );
316
+ if (f.create && f.excl)
317
+ caml_raise_system_error(
318
+ raise_unix,
319
+ "EEXIST",
320
+ "open",
321
+ "file already exists",
322
+ this.nm(name),
323
+ );
324
+ file = this.content[name];
325
+ if (f.truncate) file.truncate(0);
326
+ } else if (f.create) {
327
+ this.create_dir_if_needed(name);
328
+ this.content[name] = new MlFakeFile(caml_create_bytes(0));
329
+ file = this.content[name];
330
+ } else {
331
+ caml_raise_no_such_file(this.nm(name), raise_unix, "open");
332
+ }
333
+ return new MlFakeFd(this.nm(name), file, f);
334
+ }
335
+
336
+ truncate(name, len, raise_unix) {
337
+ var file;
338
+ this.lookup(name);
339
+ if (this.content[name]) {
340
+ if (this.is_dir(name))
341
+ caml_raise_system_error(
342
+ raise_unix,
343
+ "EISDIR",
344
+ "open",
345
+ "illegal operation on a directory",
346
+ this.nm(name),
347
+ );
348
+ file = this.content[name];
349
+ file.truncate(len);
350
+ } else {
351
+ caml_raise_no_such_file(this.nm(name), raise_unix, "truncate");
352
+ }
353
+ }
354
+
355
+ register(name, content) {
356
+ var file;
357
+ if (this.content[name])
358
+ caml_raise_sys_error(this.nm(name) + " : file already exists");
359
+ if (caml_is_ml_bytes(content)) file = new MlFakeFile(content);
360
+ else if (caml_is_ml_string(content))
361
+ file = new MlFakeFile(caml_bytes_of_string(content));
362
+ else if (Array.isArray(content))
363
+ file = new MlFakeFile(caml_bytes_of_array(content));
364
+ else if (typeof content === "string")
365
+ file = new MlFakeFile(caml_bytes_of_jsbytes(content));
366
+ else if (content.toString) {
367
+ var bytes = caml_bytes_of_string(
368
+ caml_string_of_jsstring(content.toString()),
369
+ );
370
+ file = new MlFakeFile(bytes);
371
+ }
372
+ if (file) {
373
+ this.create_dir_if_needed(name);
374
+ this.content[name] = file;
375
+ } else
376
+ caml_raise_sys_error(
377
+ this.nm(name) + " : registering file with invalid content type",
378
+ );
379
+ }
380
+ }
381
+
382
+ //Provides: MlFakeFile
383
+ //Requires: MlFile
384
+ //Requires: caml_create_bytes, caml_ml_bytes_length, caml_blit_bytes
385
+ //Requires: caml_uint8_array_of_bytes, caml_bytes_of_uint8_array
386
+ class MlFakeFile extends MlFile {
387
+ constructor(content) {
388
+ super();
389
+ this.data = content;
390
+ }
391
+
392
+ truncate(len) {
393
+ var old = this.data;
394
+ var old_len = caml_ml_bytes_length(old);
395
+ this.data = caml_create_bytes(len | 0);
396
+ caml_blit_bytes(old, 0, this.data, 0, Math.min(len, old_len));
397
+ }
398
+
399
+ length() {
400
+ return caml_ml_bytes_length(this.data);
401
+ }
402
+
403
+ write(offset, buf, pos, len) {
404
+ var clen = this.length();
405
+ if (offset + len >= clen) {
406
+ var new_str = caml_create_bytes(offset + len);
407
+ var old_data = this.data;
408
+ this.data = new_str;
409
+ caml_blit_bytes(old_data, 0, this.data, 0, clen);
410
+ }
411
+ caml_blit_bytes(
412
+ caml_bytes_of_uint8_array(buf),
413
+ pos,
414
+ this.data,
415
+ offset,
416
+ len,
417
+ );
418
+ return len;
419
+ }
420
+
421
+ read(offset, buf, pos, len) {
422
+ var clen = this.length();
423
+ if (offset + len >= clen) {
424
+ len = clen - offset;
425
+ }
426
+ if (len > 0) {
427
+ var data = caml_create_bytes(len | 0);
428
+ caml_blit_bytes(this.data, offset, data, 0, len);
429
+ buf.set(caml_uint8_array_of_bytes(data), pos);
430
+ return len;
431
+ }
432
+ return 0;
433
+ }
434
+ }
435
+
436
+ //Provides: MlFakeFd_out
437
+ //Requires: MlFakeFile, caml_create_bytes, caml_blit_bytes, caml_bytes_of_uint8_array
438
+ //Requires: caml_raise_system_error
439
+ class MlFakeFd_out extends MlFakeFile {
440
+ constructor(fd, flags) {
441
+ super(caml_create_bytes(0));
442
+ // Pick a stdout / stderr sink. console.log / console.error always
443
+ // append a newline, so wrap them to drop at most one trailing \n
444
+ // (otherwise OCaml's own newline doubles up).
445
+ var via_console = (sink) => (s) =>
446
+ sink(
447
+ s.length > 0 && s.charCodeAt(s.length - 1) === 10 ? s.slice(0, -1) : s,
448
+ );
449
+ if (fd === 1 && typeof console.log === "function")
450
+ this.log = via_console(console.log);
451
+ else if (fd === 2 && typeof console.error === "function")
452
+ this.log = via_console(console.error);
453
+ else if (typeof console.log === "function")
454
+ this.log = via_console(console.log);
455
+ else this.log = (_s) => 0;
456
+ this.flags = flags;
457
+ }
458
+
459
+ length() {
460
+ return 0;
461
+ }
462
+
463
+ truncate(_len, raise_unix) {
464
+ caml_raise_system_error(
465
+ raise_unix,
466
+ "EINVAL",
467
+ "ftruncate",
468
+ "invalid argument",
469
+ );
470
+ }
471
+
472
+ write(buf, pos, len, raise_unix) {
473
+ if (this.log) {
474
+ var src = caml_create_bytes(len);
475
+ caml_blit_bytes(caml_bytes_of_uint8_array(buf), pos, src, 0, len);
476
+ this.log(src.toUtf16());
477
+ return len;
478
+ }
479
+ caml_raise_system_error(
480
+ raise_unix,
481
+ "EBADF",
482
+ "write",
483
+ "bad file descriptor",
484
+ );
485
+ }
486
+
487
+ read(_buf, _pos, _len, raise_unix) {
488
+ caml_raise_system_error(raise_unix, "EBADF", "read", "bad file descriptor");
489
+ }
490
+
491
+ seek(_len, _whence, raise_unix) {
492
+ caml_raise_system_error(raise_unix, "ESPIPE", "lseek", "illegal seek");
493
+ }
494
+ pos() {
495
+ return -1;
496
+ }
497
+
498
+ close() {
499
+ this.log = undefined;
500
+ }
501
+
502
+ check_stream_semantics(_cmd) {}
503
+ }
504
+
505
+ //Provides: MlFakeFd
506
+ //Requires: MlFakeFile
507
+ //Requires: caml_raise_system_error
508
+ class MlFakeFd {
509
+ constructor(name, file, flags) {
510
+ this.file = file;
511
+ this.name = name;
512
+ this.flags = flags;
513
+ // Like native [O_APPEND], the offset starts at the beginning of the file;
514
+ // it is each [write] that repositions to the end (see [write] below).
515
+ this.offset = 0;
516
+ this.seeked = false;
517
+ }
518
+
519
+ err_closed(cmd, raise_unix) {
520
+ caml_raise_system_error(raise_unix, "EBADF", cmd, "bad file descriptor");
521
+ }
522
+
523
+ length(raise_unix) {
524
+ if (this.file) return this.file.length();
525
+ this.err_closed("length", raise_unix);
526
+ }
527
+
528
+ truncate(len, raise_unix) {
529
+ if (this.file) {
530
+ if (!(this.flags.wronly || this.flags.rdwr))
531
+ caml_raise_system_error(
532
+ raise_unix,
533
+ "EINVAL",
534
+ "truncate",
535
+ "invalid argument",
536
+ );
537
+ return this.file.truncate(len);
538
+ }
539
+ this.err_closed("truncate", raise_unix);
540
+ }
541
+
542
+ write(buf, pos, len, raise_unix) {
543
+ if (this.file && (this.flags.wronly || this.flags.rdwr)) {
544
+ // [O_APPEND]: every write goes to the end of the file, regardless of the
545
+ // current offset (which may have been moved by [seek]).
546
+ if (this.flags.append) this.offset = this.file.length();
547
+ var offset = this.offset;
548
+ len = this.file.write(offset, buf, pos, len);
549
+ this.offset += len;
550
+ return len;
551
+ }
552
+ this.err_closed("write", raise_unix);
553
+ }
554
+
555
+ read(buf, pos, len, raise_unix) {
556
+ if (this.file && !this.flags.wronly) {
557
+ var offset = this.offset;
558
+ len = this.file.read(offset, buf, pos, len);
559
+ this.offset += len;
560
+ return len;
561
+ }
562
+ this.err_closed("read", raise_unix);
563
+ }
564
+
565
+ seek(offset, whence, raise_unix) {
566
+ switch (whence) {
567
+ case 0:
568
+ break;
569
+ case 1:
570
+ offset += this.offset;
571
+ break;
572
+ case 2:
573
+ offset += this.length();
574
+ break;
575
+ }
576
+ if (offset < 0)
577
+ caml_raise_system_error(
578
+ raise_unix,
579
+ "EINVAL",
580
+ "lseek",
581
+ "invalid argument",
582
+ );
583
+ this.offset = offset;
584
+ this.seeked = true;
585
+ return offset;
586
+ }
587
+
588
+ pos() {
589
+ return this.offset;
590
+ }
591
+
592
+ close(raise_unix) {
593
+ if (!this.file) this.err_closed("close", raise_unix);
594
+ this.file = undefined;
595
+ }
596
+
597
+ check_stream_semantics(cmd) {
598
+ if (!this.file) return this.err_closed(cmd, /* raise Unix_error */ 1);
599
+ }
600
+ }