substrate-lang 0.9.3 → 0.10.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 (208) hide show
  1. package/README.md +1 -1
  2. package/build/compiler/binary.2d43b43d1600@0+0.wasm +0 -0
  3. package/build/compiler/checker.4dd4556dd421@0+0.wasm +0 -0
  4. package/build/compiler/compile.5d8f6407af2a@0+0.wasm +0 -0
  5. package/build/compiler/{core.fc3dab9d1846@0+0.wasm → core.f2defb75e00b@0+0.wasm} +0 -0
  6. package/build/compiler/expander.967ce443d379@0+0.wasm +0 -0
  7. package/build/compiler/fs.01b8aab4a9a8@0+0.wasm +0 -0
  8. package/build/compiler/{leb128.748b1c37277a@0+0.wasm → leb128.15d814b7b4f2@0+0.wasm} +0 -0
  9. package/build/compiler/{link.11b643d35670@0+0.wasm → link.b826ea7c8f17@0+0.wasm} +0 -0
  10. package/build/compiler/{macros.4083601c00db@0+0.wasm → macros.b269e0c42784@0+0.wasm} +0 -0
  11. package/build/compiler/{main.ed62cce43000@0+0.wasm → main.4fc52f204d54@0+0.wasm} +0 -0
  12. package/build/compiler/{ops.b361e858d8e1@0+0.wasm → ops.515b5e05f646@0+0.wasm} +0 -0
  13. package/build/compiler/{path.dcc4712bcc7b@0+0.wasm → path.5a6286472cd4@0+0.wasm} +0 -0
  14. package/build/compiler/program +21 -21
  15. package/build/compiler/prune.406215c3e4f8@0+0.wasm +0 -0
  16. package/build/compiler/reader.694b03770bf0@0+0.wasm +0 -0
  17. package/build/compiler/roots.cefd10e93684@0+0.wasm +0 -0
  18. package/build/compiler/{running.d73f7826cb74@0+0.wasm → running.0d25dbaec018@0+0.wasm} +0 -0
  19. package/build/compiler/serialize.b0d82f3d63d2@0+0.wasm +0 -0
  20. package/build/compiler/{sha256.5fc9d60f8bb2@0+0.wasm → sha256.a6c32b04d799@0+0.wasm} +0 -0
  21. package/build/compiler/substrate.5ee5d0b4d3e7@0+0.wasm +0 -0
  22. package/build/compiler/syntax.32f3e40b61c7@0+0.wasm +0 -0
  23. package/build/compiler/{writer.806bc85aa684@0+0.wasm → writer.00b7802cbe39@0+0.wasm} +0 -0
  24. package/build/sub/{base64.8fba03e1be0a@0+0.wasm → base64.a26bdcf60a2d@0+0.wasm} +0 -0
  25. package/build/sub/build.459c5b9412bd@0+0.wasm +0 -0
  26. package/build/sub/chromium.3d5818f2707d@0+0.wasm +0 -0
  27. package/build/sub/common.1edc613607a0@0+0.wasm +0 -0
  28. package/build/sub/deflate.23f7c4679260@0+0.wasm +0 -0
  29. package/build/sub/doc.0775df5de6fe@0+0.wasm +0 -0
  30. package/build/sub/{doc.566f9861828e@0+0.wasm → doc.ef9965d5d402@0+0.wasm} +0 -0
  31. package/build/sub/env.e5451da6e747@0+0.wasm +0 -0
  32. package/build/sub/events.bf5473ebf220@0+0.wasm +0 -0
  33. package/build/sub/fetch.7790d4943758@0+0.wasm +0 -0
  34. package/build/sub/fetch.96b2d10f025e@0+0.wasm +0 -0
  35. package/build/sub/files.ad0469fdf6fa@0+0.wasm +0 -0
  36. package/build/sub/fs.01b8aab4a9a8@0+0.wasm +0 -0
  37. package/build/sub/git.dc4c0e757ebe@0+0.wasm +0 -0
  38. package/build/sub/grants.c54776c0d7e3@0+0.wasm +0 -0
  39. package/build/sub/gzip.16e372eda1cf@0+0.wasm +0 -0
  40. package/build/sub/hash.660682e4f491@0+0.wasm +0 -0
  41. package/build/sub/{html.20baa1dc7ca6@0+0.wasm → html.a23126eb949a@0+0.wasm} +0 -0
  42. package/build/sub/{html.c1671a102b4d@0+0.wasm → html.e9ed37f34977@0+0.wasm} +0 -0
  43. package/build/sub/{inflate.8899e0933792@0+0.wasm → inflate.59bb61f14001@0+0.wasm} +0 -0
  44. package/build/sub/json.55590d2f518a@0+0.wasm +0 -0
  45. package/build/sub/manifest.ef317480deb0@0+0.wasm +0 -0
  46. package/build/sub/map.f455cca6a42a@0+0.wasm +0 -0
  47. package/build/sub/pack.e02836264f6a@0+0.wasm +0 -0
  48. package/build/sub/{path.dcc4712bcc7b@0+0.wasm → path.5a6286472cd4@0+0.wasm} +0 -0
  49. package/build/sub/path.6891ffea73ca@0+0.wasm +0 -0
  50. package/build/sub/process.7106571fa723@0+0.wasm +0 -0
  51. package/build/sub/program +48 -48
  52. package/build/sub/read.0b93933d62a2@0+0.wasm +0 -0
  53. package/build/sub/{reader.b535e61f99f4@0+0.wasm → reader.694b03770bf0@0+0.wasm} +0 -0
  54. package/build/sub/{root.9b713ec588c1@0+0.wasm → root.f10a4906f460@0+0.wasm} +0 -0
  55. package/build/sub/{roots.6d2942578055@0+0.wasm → roots.cefd10e93684@0+0.wasm} +0 -0
  56. package/build/sub/{sha256.5fc9d60f8bb2@0+0.wasm → sha256.a6c32b04d799@0+0.wasm} +0 -0
  57. package/build/sub/{sha512.b988b9dc6114@0+0.wasm → sha512.c24a792d7891@0+0.wasm} +0 -0
  58. package/build/sub/site.1732b58ec0e8@0+0.wasm +0 -0
  59. package/build/sub/site.ae3913b0b0f4@0+0.wasm +0 -0
  60. package/build/sub/store.a24d7a25daa6@0+0.wasm +0 -0
  61. package/build/sub/stream.126e3bd5d626@0+0.wasm +0 -0
  62. package/build/sub/sub.2e3092140706@0+0.wasm +0 -0
  63. package/build/sub/substrate.5ee5d0b4d3e7@0+0.wasm +0 -0
  64. package/build/sub/{syntax.9857f6784d63@0+0.wasm → syntax.32f3e40b61c7@0+0.wasm} +0 -0
  65. package/build/sub/tar.2a633861e654@0+0.wasm +0 -0
  66. package/build/sub/test.9bd59c73f65e@0+0.wasm +0 -0
  67. package/build/sub/{text.4ab70ac35b5a@0+0.wasm → text.1bc90482bd43@0+0.wasm} +0 -0
  68. package/build/sub/{timer.3809bb17a7a1@0+0.wasm → timer.f35eb62ae446@0+0.wasm} +0 -0
  69. package/build/sub/upgrade.39ee449b00d5@0+0.wasm +0 -0
  70. package/build/sub/{utf8.524c475ecd40@0+0.wasm → utf8.e7216bd054e1@0+0.wasm} +0 -0
  71. package/build/sub/worker.762a9d642af0@0+0.wasm +0 -0
  72. package/build/sub/writer.00b7802cbe39@0+0.wasm +0 -0
  73. package/package.json +1 -1
  74. package/std/archive/tar.sub +44 -44
  75. package/std/browser/chromium.sub +5 -4
  76. package/std/browser/devtools.sub +24 -19
  77. package/std/compress/deflate.sub +10 -12
  78. package/std/compress/gzip.sub +18 -16
  79. package/std/compress/inflate.sub +7 -4
  80. package/std/crypto/password.sub +3 -3
  81. package/std/doc/doc.sub +2 -2
  82. package/std/encoding/json.sub +64 -73
  83. package/std/encoding/wire.sub +15 -15
  84. package/std/http/checks.sub +3 -3
  85. package/std/http/conditional.sub +2 -4
  86. package/std/http/cookie.sub +5 -7
  87. package/std/http/form.sub +9 -12
  88. package/std/http/http.sub +17 -24
  89. package/std/http/multipart.sub +13 -15
  90. package/std/http/route.sub +18 -13
  91. package/std/http/server.sub +21 -23
  92. package/std/http/session.sub +3 -6
  93. package/std/http/sse-client.sub +9 -14
  94. package/std/http/static.sub +5 -5
  95. package/std/http/url.sub +10 -10
  96. package/std/http/websocket.sub +2 -5
  97. package/std/meta/derive.sub +0 -2
  98. package/std/meta/method.sub +41 -0
  99. package/std/meta/type-info.sub +30 -37
  100. package/std/package/files.sub +24 -25
  101. package/std/package/git.sub +26 -33
  102. package/std/package/hash.sub +9 -9
  103. package/std/package/manifest.sub +81 -57
  104. package/std/package/map.sub +5 -9
  105. package/std/package/pack.sub +13 -13
  106. package/std/package/path.sub +1 -4
  107. package/std/package/read.sub +10 -14
  108. package/std/package/site.sub +11 -11
  109. package/std/package/store.sub +16 -12
  110. package/std/package.sub +6 -6
  111. package/std/test/browser.sub +9 -8
  112. package/std/test/build.sub +2 -2
  113. package/std/test/compare.sub +9 -10
  114. package/std/test/page.sub +32 -27
  115. package/std/test/run.sub +9 -8
  116. package/std/test/test.sub +36 -30
  117. package/std/vector/vector.sub +75 -0
  118. package/substrate/VERSION +1 -1
  119. package/substrate/compiler/binary.sub +5 -14
  120. package/substrate/compiler/checker.sub +235 -222
  121. package/substrate/compiler/compile.sub +11 -11
  122. package/substrate/compiler/expander.sub +52 -78
  123. package/substrate/compiler/link.sub +2 -2
  124. package/substrate/compiler/main.sub +9 -9
  125. package/substrate/compiler/ops.sub +1 -1
  126. package/substrate/compiler/prune.sub +12 -17
  127. package/substrate/compiler/reader.sub +4 -4
  128. package/substrate/compiler/roots.sub +11 -10
  129. package/substrate/compiler/running.sub +1 -1
  130. package/substrate/compiler/serialize.sub +57 -50
  131. package/substrate/compiler/substrate.sub +60 -23
  132. package/substrate/compiler/syntax.sub +8 -21
  133. package/substrate/host/errors.mjs +3 -2
  134. package/substrate/host/events.sub +3 -16
  135. package/substrate/host/fs.mjs +5 -4
  136. package/substrate/host/fs.sub +142 -112
  137. package/substrate/host/grants.mjs +1 -1
  138. package/substrate/host/grants.sub +33 -33
  139. package/substrate/host/modules/fake.mjs +1 -1
  140. package/substrate/host/modules/websocket.mjs +4 -4
  141. package/substrate/host/modules/websocket.sub +8 -6
  142. package/substrate/host/node/env.mjs +12 -6
  143. package/substrate/host/node/env.sub +21 -16
  144. package/substrate/host/node/fs.mjs +1 -1
  145. package/substrate/host/node/net.mjs +2 -2
  146. package/substrate/host/node/net.sub +13 -6
  147. package/substrate/host/node/process.mjs +4 -4
  148. package/substrate/host/node/process.sub +28 -28
  149. package/substrate/host/node/signal.mjs +3 -2
  150. package/substrate/host/node/signal.sub +9 -6
  151. package/substrate/host/node/watch.mjs +1 -1
  152. package/substrate/host/node/watch.sub +11 -9
  153. package/substrate/host/stream.sub +2 -0
  154. package/substrate/host/subhost-core.mjs +9 -1
  155. package/substrate/host/web/clipboard.mjs +2 -2
  156. package/substrate/host/web/clipboard.sub +10 -3
  157. package/substrate/host/web/files.mjs +2 -2
  158. package/substrate/host/web/files.sub +6 -2
  159. package/substrate/host/web/fs.mjs +3 -3
  160. package/substrate/host/web/location.mjs +3 -1
  161. package/substrate/host/web/location.sub +8 -4
  162. package/substrate/host/worker-side.mjs +3 -1
  163. package/substrate/host/worker.mjs +6 -5
  164. package/substrate/host/worker.sub +10 -10
  165. package/build/compiler/binary.3823f89ce414@0+0.wasm +0 -0
  166. package/build/compiler/checker.592d37dcbec9@0+0.wasm +0 -0
  167. package/build/compiler/compile.86a2b03b0c9b@0+0.wasm +0 -0
  168. package/build/compiler/expander.689d326e5a1b@0+0.wasm +0 -0
  169. package/build/compiler/fs.563034be70c3@0+0.wasm +0 -0
  170. package/build/compiler/prune.d4a3f9834095@0+0.wasm +0 -0
  171. package/build/compiler/reader.b535e61f99f4@0+0.wasm +0 -0
  172. package/build/compiler/roots.6d2942578055@0+0.wasm +0 -0
  173. package/build/compiler/serialize.b2196de75bc8@0+0.wasm +0 -0
  174. package/build/compiler/substrate.4c780d6dd6d4@0+0.wasm +0 -0
  175. package/build/compiler/syntax.9857f6784d63@0+0.wasm +0 -0
  176. package/build/sub/build.84ac996eda63@0+0.wasm +0 -0
  177. package/build/sub/chromium.e4db7d29897c@0+0.wasm +0 -0
  178. package/build/sub/common.91ddee6b7a67@0+0.wasm +0 -0
  179. package/build/sub/deflate.fc8075e3aed1@0+0.wasm +0 -0
  180. package/build/sub/doc.0b48bbac404b@0+0.wasm +0 -0
  181. package/build/sub/env.f051f8166526@0+0.wasm +0 -0
  182. package/build/sub/events.f952172735e0@0+0.wasm +0 -0
  183. package/build/sub/fetch.097f1cc9502d@0+0.wasm +0 -0
  184. package/build/sub/fetch.5d2f427c995e@0+0.wasm +0 -0
  185. package/build/sub/files.30e55182c5df@0+0.wasm +0 -0
  186. package/build/sub/fs.563034be70c3@0+0.wasm +0 -0
  187. package/build/sub/git.48aefa1644be@0+0.wasm +0 -0
  188. package/build/sub/grants.5bf25700d47c@0+0.wasm +0 -0
  189. package/build/sub/gzip.69588e97c35a@0+0.wasm +0 -0
  190. package/build/sub/hash.3f0d118da63f@0+0.wasm +0 -0
  191. package/build/sub/json.f15a29d99d8d@0+0.wasm +0 -0
  192. package/build/sub/manifest.cf7471880377@0+0.wasm +0 -0
  193. package/build/sub/map.dc516eec27ff@0+0.wasm +0 -0
  194. package/build/sub/pack.55992e8cc09c@0+0.wasm +0 -0
  195. package/build/sub/path.b7a8e1cf3aaa@0+0.wasm +0 -0
  196. package/build/sub/process.aea2c88cb7a0@0+0.wasm +0 -0
  197. package/build/sub/read.cd1e693f4fb4@0+0.wasm +0 -0
  198. package/build/sub/site.7c6d8c7747af@0+0.wasm +0 -0
  199. package/build/sub/site.81548474c323@0+0.wasm +0 -0
  200. package/build/sub/store.d4e845ff24ac@0+0.wasm +0 -0
  201. package/build/sub/stream.4c07247477f7@0+0.wasm +0 -0
  202. package/build/sub/sub.b57e17b6876b@0+0.wasm +0 -0
  203. package/build/sub/substrate.4c780d6dd6d4@0+0.wasm +0 -0
  204. package/build/sub/tar.e482cf873cfc@0+0.wasm +0 -0
  205. package/build/sub/test.0d9c079bb309@0+0.wasm +0 -0
  206. package/build/sub/upgrade.18a5aa0dae89@0+0.wasm +0 -0
  207. package/build/sub/worker.f1190de21b21@0+0.wasm +0 -0
  208. package/build/sub/writer.806bc85aa684@0+0.wasm +0 -0
@@ -1,8 +1,7 @@
1
- ;; Environment variables: the host module "env". env-get stores a variable's value at value and returns #t, or returns
2
- ;; #f when it is not set or not granted, with the reason at err. env-set and env-delete change the caller's environment
3
- ;; and return 0, or -1 with the reason at err. Programs the caller runs and workers it starts afterwards see the change;
4
- ;; each gets a copy of the caller's environment when it starts. env-list stores the variables -E grants at into,
5
- ;; NAME=VALUE, in name order, as Deno's toObject does, and returns 0, or -1 without -E.
1
+ ;; Environment variables: the host module "env". env-get stores a variable's value at value, and fails when the
2
+ ;; variable is not set. env-set and env-delete change the caller's environment. Programs the caller runs and workers it
3
+ ;; starts afterwards see the change; each gets a copy of the caller's environment when it starts. env-list stores the
4
+ ;; variables -E grants at into, NAME=VALUE, in name order, as Deno's toObject does.
6
5
  (provide env-get env-set env-delete env-list)
7
6
 
8
7
  (import get "env" "get" (i32 i32 i32 i32 -> i32))
@@ -10,19 +9,25 @@
10
9
  (import drop "env" "delete" (i32 i32 i32 -> i32))
11
10
  (import listed "env" "list" (i32 i32 -> i32))
12
11
 
13
- (define (env-get [name string] [value (ptr string)] [err (ptr string)]) -> bool
14
- (let* ([n u32 0] [p (get (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (& n)) (cast i32 err))])
12
+ (define (env-get [name string] [value (ptr string)] [err (ptr error)]) -> bool
13
+ (let* ([why string] [n u32 0]
14
+ [p (get (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (& n)) (cast i32 (& why)))])
15
15
  (set! (@ value) (cast string (slice (cast (ptr u8) p) n)))
16
- (!= p 0)))
16
+ (or (!= p 0) (host-failed! (& why) err))))
17
17
 
18
- (define (env-set [name string] [value string] [err (ptr string)]) -> i32
19
- (put (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (-> value bytes)) (cast i32 (-> value length))
20
- (cast i32 err)))
18
+ (define (env-set [name string] [value string] [err (ptr error)]) -> bool
19
+ (let ([why string])
20
+ (or (== (put (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (-> value bytes))
21
+ (cast i32 (-> value length)) (cast i32 (& why)))
22
+ 0)
23
+ (host-failed! (& why) err))))
21
24
 
22
- (define (env-delete [name string] [err (ptr string)]) -> i32
23
- (drop (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 err)))
25
+ (define (env-delete [name string] [err (ptr error)]) -> bool
26
+ (let ([why string])
27
+ (or (== (drop (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (& why))) 0)
28
+ (host-failed! (& why) err))))
24
29
 
25
- (define (env-list [into (ptr (slice string))] [err (ptr string)]) -> i32
26
- (let* ([n u32 0] [p (listed (cast i32 (& n)) (cast i32 err))])
30
+ (define (env-list [into (ptr (slice string))] [err (ptr error)]) -> bool
31
+ (let* ([why string] [n u32 0] [p (listed (cast i32 (& n)) (cast i32 (& why)))])
27
32
  (set! (@ into) (entry-strings (cast (ptr u8) p) n))
28
- (if (== p 0) -1 0)))
33
+ (or (!= p 0) (host-failed! (& why) err))))
@@ -20,7 +20,7 @@ const plain = (f) => (...args) => {
20
20
  return f(...args);
21
21
  } catch (e) {
22
22
  if (typeof e.errno !== 'number') throw e;
23
- throw new Error(plainMessage(e));
23
+ throw Object.assign(new Error(plainMessage(e)), { code: e.code });
24
24
  }
25
25
  };
26
26
 
@@ -50,7 +50,7 @@ export function netModule(grants, certificate) {
50
50
  });
51
51
  } else server.listen(port, host);
52
52
  } catch (e) {
53
- caller.fail(err, e.message);
53
+ caller.fail(err, e.message, errorOf(e));
54
54
  return 0;
55
55
  }
56
56
  id = next++;
@@ -81,7 +81,7 @@ export function netModule(grants, certificate) {
81
81
  ? tls.connect({ host, port, servername, ca, allowHalfOpen: true, lookup })
82
82
  : net.connect({ host, port, allowHalfOpen: true, lookup });
83
83
  } catch (e) {
84
- caller.fail(err, e.message);
84
+ caller.fail(err, e.message, errorOf(e));
85
85
  return 0;
86
86
  }
87
87
  let connected = false;
@@ -14,12 +14,19 @@
14
14
  (const net-connected u32 3)
15
15
  (const net-failed u32 4)
16
16
 
17
- (define (net-listen [port u32] [host string] [secure bool] [most u32] [tag (ptr void)] [err (ptr string)]) -> u32
18
- (cast u32 (listen (cast i32 port) (cast i32 (-> host bytes)) (cast i32 (-> host length)) secure (cast i32 most)
19
- (cast i32 tag) (cast i32 err))))
17
+ (define (net-listen [port u32] [host string] [secure bool] [most u32] [tag (ptr void)] [id (ptr u32)]
18
+ [err (ptr error)]) -> bool
19
+ (let ([why string] [n u32 0])
20
+ (set! n (cast u32 (listen (cast i32 port) (cast i32 (-> host bytes)) (cast i32 (-> host length)) secure
21
+ (cast i32 most) (cast i32 tag) (cast i32 (& why)))))
22
+ (unless (== id 0) (set! (@ id) n))
23
+ (or (!= n 0) (host-failed! (& why) err))))
20
24
 
21
- (define (net-connect [port u32] [host string] [secure bool] [tag (ptr void)] [err (ptr string)]) -> u32
22
- (cast u32 (connect (cast i32 port) (cast i32 (-> host bytes)) (cast i32 (-> host length)) secure (cast i32 tag)
23
- (cast i32 err))))
25
+ (define (net-connect [port u32] [host string] [secure bool] [tag (ptr void)] [id (ptr u32)] [err (ptr error)]) -> bool
26
+ (let ([why string] [n u32 0])
27
+ (set! n (cast u32 (connect (cast i32 port) (cast i32 (-> host bytes)) (cast i32 (-> host length)) secure
28
+ (cast i32 tag) (cast i32 (& why)))))
29
+ (unless (== id 0) (set! (@ id) n))
30
+ (or (!= n 0) (host-failed! (& why) err))))
24
31
 
25
32
  (define (net-close [id u32]) (close (cast i32 id)))
@@ -84,7 +84,7 @@ export function processes(grants, loader, setup = {}) {
84
84
  const l = launched(file ?? program, entries(caller.string(ap, al)));
85
85
  process = child.spawn(l.command, l.args, { cwd, env, stdio: modes });
86
86
  } catch (e) {
87
- caller.fail(err, e.message);
87
+ caller.fail(err, e.message, errorOf(e));
88
88
  return 0;
89
89
  }
90
90
  const id = next++;
@@ -130,7 +130,7 @@ export function processes(grants, loader, setup = {}) {
130
130
  new DataView(caller.memory().buffer).setUint32(caller.u(op), p, true);
131
131
  return r.status !== null ? r.status : 128 + (os.constants.signals[r.signal] || 0);
132
132
  } catch (e) {
133
- caller.fail(err, e.message);
133
+ caller.fail(err, e.message, errorOf(e));
134
134
  return -1;
135
135
  } finally {
136
136
  if (dir) fs.rmSync(dir, { recursive: true, force: true });
@@ -146,7 +146,7 @@ export function processes(grants, loader, setup = {}) {
146
146
  const l = launched(file ?? program, entries(caller.string(ap, al)), program);
147
147
  become(l.command, [l.argv0, ...l.args], env);
148
148
  } catch (e) {
149
- caller.fail(err, e.message);
149
+ caller.fail(err, e.message, errorOf(e));
150
150
  }
151
151
  return -1;
152
152
  },
@@ -161,7 +161,7 @@ export function processes(grants, loader, setup = {}) {
161
161
  const l = launched(file ?? program, entries(caller.string(ap, al)), program);
162
162
  setup.atEnd = { file: l.command, argv: [l.argv0, ...l.args], env };
163
163
  } catch (e) {
164
- caller.fail(err, e.message);
164
+ caller.fail(err, e.message, errorOf(e));
165
165
  return -1;
166
166
  }
167
167
  return 0;
@@ -20,11 +20,10 @@
20
20
  (const process-source u32 10)
21
21
  (const process-exit u32 1)
22
22
  (const process-failed u32 2)
23
- (const process-pipe i32 0)
24
- (const process-ignore i32 1)
25
- (const process-inherit i32 2)
23
+ (enum process-stdio process-pipe process-ignore process-inherit)
26
24
 
27
- (struct process-options [dir string] [env (slice string)] [clear bool] [stdin i32] [stdout i32] [stderr i32])
25
+ (struct process-options [dir string] [env (slice string)] [clear bool] [stdin process-stdio] [stdout process-stdio]
26
+ [stderr process-stdio])
28
27
 
29
28
  (define (process-options-init! [o (ptr process-options)])
30
29
  (set! (-> o dir) "")
@@ -34,54 +33,55 @@
34
33
  (set! (-> o stdout) process-pipe)
35
34
  (set! (-> o stderr) process-pipe))
36
35
 
37
- (define (process-spawn [program string] [args (slice string)] [o (ptr process-options)] [tag (ptr void)]
38
- [err (ptr string)]) -> u32
39
- (let ([defaults process-options] [p o] [a (make-buffer)] [e (make-buffer)] [id u32 0])
36
+ (define (process-spawn [program string] [args (slice string)] [o (ptr process-options)] [tag (ptr void)] [id (ptr u32)]
37
+ [err (ptr error)]) -> bool
38
+ (let ([defaults process-options] [p o] [a (make-buffer)] [e (make-buffer)] [why string] [n u32 0])
40
39
  (when (== p 0)
41
40
  (process-options-init! (& defaults))
42
41
  (set! p (& defaults)))
43
42
  (buffer-add-entries! (& a) args)
44
43
  (buffer-add-entries! (& e) (-> p env))
45
- (set! id (cast u32 (spawn (cast i32 (-> program bytes)) (cast i32 (-> program length)) (cast i32 (-> a bytes))
46
- (cast i32 (-> a length)) (cast i32 (-> p dir bytes)) (cast i32 (-> p dir length))
47
- (cast i32 (-> e bytes)) (cast i32 (-> e length)) (-> p clear) (-> p stdin) (-> p stdout)
48
- (-> p stderr) (cast i32 tag) (cast i32 err))))
44
+ (set! n (cast u32 (spawn (cast i32 (-> program bytes)) (cast i32 (-> program length)) (cast i32 (-> a bytes))
45
+ (cast i32 (-> a length)) (cast i32 (-> p dir bytes)) (cast i32 (-> p dir length))
46
+ (cast i32 (-> e bytes)) (cast i32 (-> e length)) (-> p clear) (cast i32 (-> p stdin))
47
+ (cast i32 (-> p stdout)) (cast i32 (-> p stderr)) (cast i32 tag) (cast i32 (& why)))))
49
48
  (buffer-free! (& a))
50
49
  (buffer-free! (& e))
51
- id))
50
+ (unless (== id 0) (set! (@ id) n))
51
+ (or (!= n 0) (host-failed! (& why) err))))
52
52
 
53
53
  (define (process-run [program string] [args (slice string)] [o (ptr process-options)] [input (slice u8)] [timeout u32]
54
- [output (ptr (slice u8))] [err (ptr string)]) -> i32
55
- (let ([defaults process-options] [p o] [a (make-buffer)] [e (make-buffer)] [code i32 0])
54
+ [output (ptr (slice u8))] [status (ptr i32)] [err (ptr error)]) -> bool
55
+ (let ([defaults process-options] [p o] [a (make-buffer)] [e (make-buffer)] [why string])
56
56
  (when (== p 0)
57
57
  (process-options-init! (& defaults))
58
58
  (set! p (& defaults)))
59
59
  (set! (@ output) (slice (cast (ptr u8) 0) 0))
60
60
  (buffer-add-entries! (& a) args)
61
61
  (buffer-add-entries! (& e) (-> p env))
62
- (set! code (run (cast i32 (-> program bytes)) (cast i32 (-> program length)) (cast i32 (-> a bytes)) (cast i32 (-> a length))
63
- (cast i32 (-> p dir bytes)) (cast i32 (-> p dir length)) (cast i32 (-> e bytes)) (cast i32 (-> e length))
64
- (-> p clear) (cast i32 (-> input items)) (cast i32 (-> input length)) (cast i32 timeout)
65
- (cast i32 output) (cast i32 err)))
62
+ (set! (@ status) (run (cast i32 (-> program bytes)) (cast i32 (-> program length)) (cast i32 (-> a bytes))
63
+ (cast i32 (-> a length)) (cast i32 (-> p dir bytes)) (cast i32 (-> p dir length))
64
+ (cast i32 (-> e bytes)) (cast i32 (-> e length)) (-> p clear) (cast i32 (-> input items))
65
+ (cast i32 (-> input length)) (cast i32 timeout) (cast i32 output) (cast i32 (& why))))
66
66
  (buffer-free! (& a))
67
67
  (buffer-free! (& e))
68
- code))
68
+ (or (>= (@ status) 0) (host-failed! (& why) err))))
69
69
 
70
- (define (process-exec [program string] [args (slice string)] [err (ptr string)]) -> i32
71
- (let ([a (make-buffer)] [r i32 0])
70
+ (define (process-exec [program string] [args (slice string)] [err (ptr error)]) -> bool
71
+ (let ([a (make-buffer)] [why string])
72
72
  (buffer-add-entries! (& a) args)
73
- (set! r (exec (cast i32 (-> program bytes)) (cast i32 (-> program length)) (cast i32 (-> a bytes)) (cast i32 (-> a length))
74
- (cast i32 err)))
73
+ (exec (cast i32 (-> program bytes)) (cast i32 (-> program length)) (cast i32 (-> a bytes)) (cast i32 (-> a length))
74
+ (cast i32 (& why)))
75
75
  (buffer-free! (& a))
76
- r))
76
+ (host-failed! (& why) err)))
77
77
 
78
- (define (process-exec-at-end [program string] [args (slice string)] [err (ptr string)]) -> i32
79
- (let ([a (make-buffer)] [r i32 0])
78
+ (define (process-exec-at-end [program string] [args (slice string)] [err (ptr error)]) -> bool
79
+ (let ([a (make-buffer)] [r i32 0] [why string])
80
80
  (buffer-add-entries! (& a) args)
81
81
  (set! r (exec-at-end (cast i32 (-> program bytes)) (cast i32 (-> program length)) (cast i32 (-> a bytes))
82
- (cast i32 (-> a length)) (cast i32 err)))
82
+ (cast i32 (-> a length)) (cast i32 (& why))))
83
83
  (buffer-free! (& a))
84
- r))
84
+ (or (== r 0) (host-failed! (& why) err))))
85
85
 
86
86
  (define (process-stdin [id u32]) -> u32 (cast u32 (stdin (cast i32 id))))
87
87
 
@@ -1,5 +1,6 @@
1
1
  // The host module "signal" (signal.sub) on Node.
2
2
  import os from 'node:os';
3
+ import { errors } from '../errors.mjs';
3
4
 
4
5
  const SOURCE = 16;
5
6
  const RECEIVED = 1;
@@ -18,11 +19,11 @@ export function signals() {
18
19
  listen(np, nl, tag, err) {
19
20
  const name = caller.string(np, nl);
20
21
  if (!Object.hasOwn(os.constants.signals, name)) {
21
- caller.fail(err, `signal.listen: ${name} is not a signal`);
22
+ caller.fail(err, `signal.listen: ${name} is not a signal`, errors.invalid);
22
23
  return 0;
23
24
  }
24
25
  if (forbidden.has(name)) {
25
- caller.fail(err, `signal.listen: ${name} cannot be listened for`);
26
+ caller.fail(err, `signal.listen: ${name} cannot be listened for`, errors.invalid);
26
27
  return 0;
27
28
  }
28
29
  const id = next++;
@@ -1,8 +1,7 @@
1
1
  ;; Signals to the program: the host module "signal", after Deno's addSignalListener. signal-listen listens for the
2
- ;; signal named, such as "SIGINT" or "SIGTERM", and returns the listener's number, or 0 with the reason at err; while
3
- ;; any listener is there, the signal no longer ends the program, and a listener alone does not keep it running. A
4
- ;; received event comes each time the signal arrives. SIGKILL, SIGSTOP, SIGILL, SIGFPE and SIGSEGV cannot be listened
5
- ;; for, and a worker has no signals.
2
+ ;; signal named, such as "SIGINT" or "SIGTERM". While any listener is there, the signal no longer ends the program, and
3
+ ;; a listener alone does not keep it running. A received event comes each time the signal arrives. SIGKILL, SIGSTOP,
4
+ ;; SIGILL, SIGFPE and SIGSEGV cannot be listened for, and a worker has no signals.
6
5
  (provide signal-source signal-received signal-listen signal-stop)
7
6
 
8
7
  (import listen "signal" "listen" (i32 i32 i32 i32 -> i32))
@@ -11,7 +10,11 @@
11
10
  (const signal-source u32 16)
12
11
  (const signal-received u32 1)
13
12
 
14
- (define (signal-listen [name string] [tag (ptr void)] [err (ptr string)]) -> u32
15
- (cast u32 (listen (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 tag) (cast i32 err))))
13
+ (define (signal-listen [name string] [tag (ptr void)] [id (ptr u32)] [err (ptr error)]) -> bool
14
+ (let ([why string] [n u32 0])
15
+ (set! n (cast u32 (listen (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 tag)
16
+ (cast i32 (& why)))))
17
+ (unless (== id 0) (set! (@ id) n))
18
+ (or (!= n 0) (host-failed! (& why) err))))
16
19
 
17
20
  (define (signal-stop [id u32]) (stop (cast i32 id)))
@@ -60,7 +60,7 @@ export function watchModule(grants) {
60
60
  return id;
61
61
  } catch (e) {
62
62
  close(w);
63
- caller.fail(err, `watch.start: ${at}: ${plainMessage(e)}`);
63
+ caller.fail(err, `watch.start: ${at}: ${plainMessage(e)}`, errorOf(e));
64
64
  return 0;
65
65
  }
66
66
  },
@@ -1,8 +1,7 @@
1
1
  ;; Watching files: the host module "watch", after Deno's watchFs. watch-start watches the paths, and everything under
2
- ;; them unless the options' recursive is #f, and returns the watch's number, or 0 with the reason at err. A changed
3
- ;; event's value is watch-create, watch-modify or watch-remove, and its bytes are the absolute paths it is about, as
4
- ;; entries; a rename comes as a remove and a create. Changes under the options' ignore paths are left out. A failed
5
- ;; event ends the watch.
2
+ ;; them unless the options' recursive is #f. A changed event's value is watch-create, watch-modify or watch-remove, and
3
+ ;; its bytes are the absolute paths it is about, as entries; a rename comes as a remove and a create. Changes under the
4
+ ;; options' ignore paths are left out. A failed event ends the watch.
6
5
  (provide watch-source watch-changed watch-failed watch-create watch-modify watch-remove watch-options
7
6
  watch-options-init! watch-start watch-stop)
8
7
 
@@ -23,17 +22,20 @@
23
22
  (set! (-> o recursive) #t)
24
23
  (set! (-> o ignore) 0))
25
24
 
26
- (define (watch-start [paths (slice string)] [o (ptr watch-options)] [tag (ptr void)] [err (ptr string)]) -> u32
27
- (let ([defaults watch-options] [p o] [watched (make-buffer)] [ignored (make-buffer)] [id u32 0])
25
+ (define (watch-start [paths (slice string)] [o (ptr watch-options)] [tag (ptr void)] [id (ptr u32)] [err (ptr error)])
26
+ -> bool
27
+ (let ([defaults watch-options] [p o] [watched (make-buffer)] [ignored (make-buffer)] [why string] [n u32 0])
28
28
  (when (== p 0)
29
29
  (watch-options-init! (& defaults))
30
30
  (set! p (& defaults)))
31
31
  (buffer-add-entries! (& watched) paths)
32
32
  (buffer-add-entries! (& ignored) (-> p ignore))
33
- (set! id (cast u32 (start (cast i32 (-> watched bytes)) (cast i32 (-> watched length)) (-> p recursive)
34
- (cast i32 (-> ignored bytes)) (cast i32 (-> ignored length)) (cast i32 tag) (cast i32 err))))
33
+ (set! n (cast u32 (start (cast i32 (-> watched bytes)) (cast i32 (-> watched length)) (-> p recursive)
34
+ (cast i32 (-> ignored bytes)) (cast i32 (-> ignored length)) (cast i32 tag)
35
+ (cast i32 (& why)))))
35
36
  (buffer-free! (& watched))
36
37
  (buffer-free! (& ignored))
37
- id))
38
+ (unless (== id 0) (set! (@ id) n))
39
+ (or (!= n 0) (host-failed! (& why) err))))
38
40
 
39
41
  (define (watch-stop [w u32]) (stop (cast i32 w)))
@@ -1,6 +1,8 @@
1
1
  ;; Byte streams: the host module "stream", whose ids other modules give out. A read event's value is how many bytes
2
2
  ;; were read, or 0 at the end. A read that stream-take! posts holds no room: its event carries the bytes, at most
3
3
  ;; most of them, for events-take. A finished event comes once everything written before stream-finish has been sent.
4
+ ;; stream-write returns 0 when the stream can take more, and 1 when it is full. It takes the bytes in both cases. After
5
+ ;; a 1, wait for a drained event before writing again. It returns -1 when the stream is not open.
4
6
  (require-unqualified "events.sub")
5
7
 
6
8
  (provide stream-source stream-read stream-drained stream-failed stream-finished
@@ -1,6 +1,7 @@
1
1
  // The JavaScript host, shared by Node (subhost.mjs) and the browser (web/subhost-web.mjs).
2
2
  import { createStreams, STREAM } from './streams.mjs';
3
3
  import { joined } from './entries.mjs';
4
+ import { errors } from './errors.mjs';
4
5
 
5
6
  const utf8 = new TextEncoder();
6
7
  const text = new TextDecoder();
@@ -174,6 +175,7 @@ export function createHost(platform) {
174
175
  // A memory's malloc, from the module that exports both.
175
176
  const allocators = new WeakMap();
176
177
  let lastError = '';
178
+ let failureCode = errors.other;
177
179
  // The running program: its module names in load order, a function that returns a module's bytes, and the files of
178
180
  // the compiled modules its build wrote, keyed by file name (null if it wrote none).
179
181
  let programNames = [];
@@ -330,7 +332,8 @@ export function createHost(platform) {
330
332
  trap: hostTrap,
331
333
  write: (fd, bytes) => platform.write(fd === 2 ? 2 : 1, bytes),
332
334
  give,
333
- fail(err, message) {
335
+ fail(err, message, code = errors.other) {
336
+ failureCode = code;
334
337
  if (!err) return;
335
338
  const p = give(utf8.encode(message), u(err) + 4);
336
339
  new DataView(memory().buffer).setUint32(u(err), p, true);
@@ -377,6 +380,11 @@ export function createHost(platform) {
377
380
  platform.write(fd === 2 ? 2 : 1, memory().subarray(u(ptr), u(ptr) + len));
378
381
  return len;
379
382
  },
383
+ failure_code() {
384
+ const code = failureCode;
385
+ failureCode = errors.other;
386
+ return code;
387
+ },
380
388
  trap(ptr, len) {
381
389
  hostTrap(string(ptr, len));
382
390
  },
@@ -1,5 +1,5 @@
1
1
  // The host module "clipboard" (clipboard.sub).
2
- import { errorOf, reasonOf } from '../errors.mjs';
2
+ import { errors, errorOf, reasonOf } from '../errors.mjs';
3
3
 
4
4
  const utf8 = new TextEncoder();
5
5
 
@@ -14,7 +14,7 @@ export function clipboard() {
14
14
  let ended = false;
15
15
  const attempt = (tag, err, ask, answer) => {
16
16
  if (!navigator.clipboard) {
17
- caller.fail(err, 'clipboard: none');
17
+ caller.fail(err, 'clipboard: none', errors.other);
18
18
  return 0;
19
19
  }
20
20
  const id = next++;
@@ -9,7 +9,14 @@
9
9
  (const clipboard-written u32 2)
10
10
  (const clipboard-failed u32 3)
11
11
 
12
- (define (clipboard-read [tag (ptr void)] [err (ptr string)]) -> u32 (cast u32 (read (cast i32 tag) (cast i32 err))))
12
+ (define (clipboard-read [tag (ptr void)] [id (ptr u32)] [err (ptr error)]) -> bool
13
+ (let ([why string] [n u32 0])
14
+ (set! n (cast u32 (read (cast i32 tag) (cast i32 (& why)))))
15
+ (unless (== id 0) (set! (@ id) n))
16
+ (or (!= n 0) (host-failed! (& why) err))))
13
17
 
14
- (define (clipboard-write [text string] [tag (ptr void)] [err (ptr string)]) -> u32
15
- (cast u32 (write (cast i32 (-> text bytes)) (cast i32 (-> text length)) (cast i32 tag) (cast i32 err))))
18
+ (define (clipboard-write [text string] [tag (ptr void)] [id (ptr u32)] [err (ptr error)]) -> bool
19
+ (let ([why string] [n u32 0])
20
+ (set! n (cast u32 (write (cast i32 (-> text bytes)) (cast i32 (-> text length)) (cast i32 tag) (cast i32 (& why)))))
21
+ (unless (== id 0) (set! (@ id) n))
22
+ (or (!= n 0) (host-failed! (& why) err))))
@@ -1,5 +1,5 @@
1
1
  // The host module "files" (files.sub).
2
- import { errors } from '../errors.mjs';
2
+ import { errors, errorOf } from '../errors.mjs';
3
3
  import { readerSource } from '../streams.mjs';
4
4
 
5
5
  const utf8 = new TextEncoder();
@@ -43,7 +43,7 @@ export function files() {
43
43
  input.showPicker();
44
44
  } catch (e) {
45
45
  input.remove();
46
- caller.fail(err, e.message);
46
+ caller.fail(err, e.message, errorOf(e));
47
47
  return 0;
48
48
  }
49
49
  return id;
@@ -10,8 +10,12 @@
10
10
  (const files-picked u32 2)
11
11
  (const files-failed u32 3)
12
12
 
13
- (define (files-pick [multiple bool] [accept string] [tag (ptr void)] [err (ptr string)]) -> u32
14
- (cast u32 (pick multiple (cast i32 (-> accept bytes)) (cast i32 (-> accept length)) (cast i32 tag) (cast i32 err))))
13
+ (define (files-pick [multiple bool] [accept string] [tag (ptr void)] [id (ptr u32)] [err (ptr error)]) -> bool
14
+ (let ([why string] [n u32 0])
15
+ (set! n (cast u32 (pick multiple (cast i32 (-> accept bytes)) (cast i32 (-> accept length)) (cast i32 tag)
16
+ (cast i32 (& why)))))
17
+ (unless (== id 0) (set! (@ id) n))
18
+ (or (!= n 0) (host-failed! (& why) err))))
15
19
 
16
20
  (define (files-save [name string] [b (slice u8)])
17
21
  (save (cast i32 (-> name bytes)) (cast i32 (-> name length)) (cast i32 (-> b items)) (cast i32 (-> b length))))
@@ -13,7 +13,7 @@ export function resolvePath(cwd, path) {
13
13
  return `/${out.join('/')}`;
14
14
  }
15
15
 
16
- const missing = () => new Error('No such file or directory');
16
+ const missing = () => Object.assign(new Error('No such file or directory'), { code: 'ENOENT' });
17
17
  const unsupported = () => new Error('Operation not supported');
18
18
  const under = (dir) => (dir === '/' ? '/' : `${dir}/`);
19
19
 
@@ -142,7 +142,7 @@ export function pageFiles(files, cwd, grants) {
142
142
  },
143
143
  readLink(p) {
144
144
  info(at('read', p));
145
- throw new Error('Invalid argument');
145
+ throw Object.assign(new Error('Invalid argument'), { code: 'EINVAL' });
146
146
  },
147
147
  realPath(p) {
148
148
  const key = at('read', p);
@@ -180,7 +180,7 @@ export function pageFiles(files, cwd, grants) {
180
180
  const key = at(changes ? 'write' : 'read', p);
181
181
  if (how.read && changes) at('read', p);
182
182
  if (files.has(key)) {
183
- if (how.createNew) throw new Error('File already exists');
183
+ if (how.createNew) throw Object.assign(new Error('File already exists'), { code: 'EEXIST' });
184
184
  } else if (inside(key).length > 0) {
185
185
  throw new Error('Illegal operation on a directory');
186
186
  } else if (how.create || how.createNew) {
@@ -1,4 +1,6 @@
1
1
  // The host module "location" (location.sub).
2
+ import { errorOf } from '../errors.mjs';
3
+
2
4
  const utf8 = new TextEncoder();
3
5
 
4
6
  const SOURCE = 12;
@@ -13,7 +15,7 @@ export function locationModule() {
13
15
  go(caller.string(ptr, len));
14
16
  return 0;
15
17
  } catch (e) {
16
- caller.fail(err, e.message);
18
+ caller.fail(err, e.message, errorOf(e));
17
19
  return -1;
18
20
  }
19
21
  };
@@ -12,10 +12,14 @@
12
12
 
13
13
  (define (location-get) -> string (let* ([n u32 0] [p (get (cast i32 (& n)))]) (cast string (slice (cast (ptr u8) p) n))))
14
14
 
15
- (define (location-push [url string] [err (ptr string)]) -> i32
16
- (push (cast i32 (-> url bytes)) (cast i32 (-> url length)) (cast i32 err)))
15
+ (define (location-push [url string] [err (ptr error)]) -> bool
16
+ (let ([why string])
17
+ (or (== (push (cast i32 (-> url bytes)) (cast i32 (-> url length)) (cast i32 (& why))) 0)
18
+ (host-failed! (& why) err))))
17
19
 
18
- (define (location-replace [url string] [err (ptr string)]) -> i32
19
- (replace (cast i32 (-> url bytes)) (cast i32 (-> url length)) (cast i32 err)))
20
+ (define (location-replace [url string] [err (ptr error)]) -> bool
21
+ (let ([why string])
22
+ (or (== (replace (cast i32 (-> url bytes)) (cast i32 (-> url length)) (cast i32 (& why))) 0)
23
+ (host-failed! (& why) err))))
20
24
 
21
25
  (define (location-back) (back))
@@ -1,5 +1,7 @@
1
1
  // The worker module's side inside a worker, in a browser or on Node. It batches output, delivers the parent's
2
2
  // messages as events, and reports back.
3
+ import { errors } from './errors.mjs';
4
+
3
5
  const utf8 = new TextEncoder();
4
6
 
5
7
  const SOURCE = 3;
@@ -72,7 +74,7 @@ export function workerSide(post) {
72
74
  const worker = (caller) => ({
73
75
  source: SOURCE,
74
76
  start(f, bp, bl, time, size, heard, tag, gp, gl, err) {
75
- caller.fail(err, 'worker.start: a worker cannot start workers');
77
+ caller.fail(err, 'worker.start: a worker cannot start workers', errors.invalid);
76
78
  return 0;
77
79
  },
78
80
  send(w, ptr, length) {
@@ -1,6 +1,7 @@
1
1
  // The host module "worker" (worker.sub). The browser and Node each give spawn, their way of starting a thread.
2
2
  import { entries } from './entries.mjs';
3
- import { askedOf, mayTree, within } from './grants.mjs';
3
+ import { errors, errorOf } from './errors.mjs';
4
+ import { askedOf, mayTree, notGranted, within } from './grants.mjs';
4
5
 
5
6
  const utf8 = new TextEncoder();
6
7
 
@@ -69,7 +70,7 @@ export function workerModule({ spawn }) {
69
70
  thread = spawn({ modules, compiled, entry, argument, grants, names: caller.moduleNames(), pages, heard, ...setup },
70
71
  app);
71
72
  } catch (e) {
72
- caller.fail(err, e.message);
73
+ caller.fail(err, e.message, errorOf(e));
73
74
  return 0;
74
75
  }
75
76
  const w = nextNumber++;
@@ -100,7 +101,7 @@ export function workerModule({ spawn }) {
100
101
  start(f, bp, bl, time, size, heard, tag, gp, gl, err, ends, ap, al) {
101
102
  const entry = caller.named(f >>> 0);
102
103
  if (!entry) {
103
- caller.fail(err, 'worker.start: a function of code the program loaded');
104
+ caller.fail(err, 'worker.start: a function of code the program loaded', errors.invalid);
104
105
  return 0;
105
106
  }
106
107
  const pages = Math.ceil((size >>> 0) / 65536);
@@ -113,11 +114,11 @@ export function workerModule({ spawn }) {
113
114
  const parent = caller.grants();
114
115
  const files = caller.parseGrants(read.flatMap((file) => ['read', file])).grants.read.items;
115
116
  for (const file of files) {
116
- if (!mayTree(parent.read, file)) throw new Error(`read ${file} reaches beyond the parent's grants`);
117
+ if (!mayTree(parent.read, file)) throw notGranted(`read ${file} reaches beyond the parent's grants`);
117
118
  }
118
119
  grants = within(askedOf(request, parent), parent);
119
120
  } catch (e) {
120
- caller.fail(err, `worker.start: ${e.message}`);
121
+ caller.fail(err, `worker.start: ${e.message}`, errorOf(e));
121
122
  return 0;
122
123
  }
123
124
  const args = al > 0 ? entries(string(ap, al)) : null;
@@ -1,6 +1,5 @@
1
1
  ;; Workers: functions of this program, each running on its own thread and sharing only messages. worker-start runs one
2
- ;; of the program's own functions with the bytes as its argument 0, and returns the worker's number, or 0 with the
3
- ;; reason at err. Its options:
2
+ ;; of the program's own functions with the bytes as its argument 0. Its options:
4
3
  ;; time, memory limits in ms for each stretch of work and in bytes, or 0 for none
5
4
  ;; output the worker's stdout and stderr come as events
6
5
  ;; grants the worker's grants (grants.sub), within the parent's and by default the parent's own
@@ -41,22 +40,23 @@
41
40
  (set! (-> o grants) (make-grants))
42
41
  (grants-inherit! (& (-> o grants))))
43
42
 
44
- (define (worker-start [function (fn ())] [argument (slice u8)] [o (ptr worker-options)] [tag (ptr void)]
45
- [err (ptr string)]) -> u32
46
- (let ([defaults worker-options] [p o] [entries (make-buffer)] [args (make-buffer)] [id u32 0])
43
+ (define (worker-start [function (fn ())] [argument (slice u8)] [o (ptr worker-options)] [tag (ptr void)] [id (ptr u32)]
44
+ [err (ptr error)]) -> bool
45
+ (let ([defaults worker-options] [p o] [entries (make-buffer)] [args (make-buffer)] [why string] [n u32 0])
47
46
  (when (== p 0)
48
47
  (worker-options-init! (& defaults))
49
48
  (set! p (& defaults)))
50
49
  (grants-entries! (& entries) (& (-> p grants)))
51
50
  (buffer-add-entries! (& args) (-> p args))
52
- (set! id (cast u32 (start (cast i32 function) (cast i32 (-> argument items)) (cast i32 (-> argument length))
53
- (cast i32 (-> p time)) (cast i32 (-> p memory)) (-> p output) (cast i32 tag)
54
- (cast i32 (-> entries bytes)) (cast i32 (-> entries length)) (cast i32 err) (-> p ends)
55
- (cast i32 (-> args bytes)) (cast i32 (-> args length)))))
51
+ (set! n (cast u32 (start (cast i32 function) (cast i32 (-> argument items)) (cast i32 (-> argument length))
52
+ (cast i32 (-> p time)) (cast i32 (-> p memory)) (-> p output) (cast i32 tag)
53
+ (cast i32 (-> entries bytes)) (cast i32 (-> entries length)) (cast i32 (& why))
54
+ (-> p ends) (cast i32 (-> args bytes)) (cast i32 (-> args length)))))
56
55
  (buffer-free! (& entries))
57
56
  (buffer-free! (& args))
58
57
  (when (== o 0) (buffer-free! (& (-> defaults grants list))))
59
- id))
58
+ (unless (== id 0) (set! (@ id) n))
59
+ (or (!= n 0) (host-failed! (& why) err))))
60
60
 
61
61
  (define (worker-send [w u32] [b (slice u8)]) -> i32 (send (cast i32 w) (cast i32 (-> b items)) (cast i32 (-> b length))))
62
62