substrate-lang 0.10.0 → 0.10.2
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/build/compiler/{checker.4dd4556dd421@0+0.wasm → checker.1d67e1d4e91a@0+0.wasm} +0 -0
- package/build/compiler/{expander.967ce443d379@0+0.wasm → expander.34110a31a949@0+0.wasm} +0 -0
- package/build/compiler/{main.4fc52f204d54@0+0.wasm → main.ca9b5089c24d@0+0.wasm} +0 -0
- package/build/compiler/program +4 -4
- package/build/compiler/{roots.cefd10e93684@0+0.wasm → roots.2f1ad1a79459@0+0.wasm} +0 -0
- package/build/sub/{build.459c5b9412bd@0+0.wasm → build.eef7dfa467ec@0+0.wasm} +0 -0
- package/build/sub/{common.1edc613607a0@0+0.wasm → common.7617940db2dc@0+0.wasm} +0 -0
- package/build/sub/deflate.23f7c4679260@0+0.wasm +0 -0
- package/build/sub/{doc.0775df5de6fe@0+0.wasm → doc.92d6d82d99c1@0+0.wasm} +0 -0
- package/build/sub/{doc.ef9965d5d402@0+0.wasm → doc.dab689b811ca@0+0.wasm} +0 -0
- package/build/sub/{fetch.96b2d10f025e@0+0.wasm → fetch.3367ff4f88c0@0+0.wasm} +0 -0
- package/build/sub/{files.ad0469fdf6fa@0+0.wasm → files.5ae9d3cebeca@0+0.wasm} +0 -0
- package/build/sub/gzip.16e372eda1cf@0+0.wasm +0 -0
- package/build/sub/{hash.660682e4f491@0+0.wasm → hash.c57c141b4862@0+0.wasm} +0 -0
- package/build/sub/{html.a23126eb949a@0+0.wasm → html.803f73c35c4a@0+0.wasm} +0 -0
- package/build/sub/{manifest.ef317480deb0@0+0.wasm → manifest.da52a88c7af7@0+0.wasm} +0 -0
- package/build/sub/{map.f455cca6a42a@0+0.wasm → map.5c8084999550@0+0.wasm} +0 -0
- package/build/sub/program +22 -22
- package/build/sub/{root.f10a4906f460@0+0.wasm → root.78253db36643@0+0.wasm} +0 -0
- package/build/sub/{roots.cefd10e93684@0+0.wasm → roots.2f1ad1a79459@0+0.wasm} +0 -0
- package/build/sub/sha256.a6c32b04d799@0+0.wasm +0 -0
- package/build/sub/site.47fd989be8fb@0+0.wasm +0 -0
- package/build/sub/site.c908b1f6db12@0+0.wasm +0 -0
- package/build/sub/{store.a24d7a25daa6@0+0.wasm → store.048c77bb124d@0+0.wasm} +0 -0
- package/build/sub/sub.a618f89f2ec8@0+0.wasm +0 -0
- package/build/sub/{test.9bd59c73f65e@0+0.wasm → test.b529bf52ba3e@0+0.wasm} +0 -0
- package/build/sub/{text.1bc90482bd43@0+0.wasm → text.b214933a4984@0+0.wasm} +0 -0
- package/build/sub/{upgrade.39ee449b00d5@0+0.wasm → upgrade.7ec5651ed2e9@0+0.wasm} +0 -0
- package/package.json +1 -1
- package/std/http/server.sub +7 -7
- package/std/http/static.sub +66 -30
- package/std/package/manifest.sub +9 -4
- package/std/package/site.sub +209 -15
- package/std/package.sub +4 -3
- package/std/test/browser.sub +20 -14
- package/std/test/build.sub +8 -6
- package/std/test/page/agent.mjs +8 -2
- package/std/web/canvas.sub +4 -4
- package/std/web/dom.sub +45 -11
- package/std/web/gpu-commands.sub +439 -0
- package/std/web/gpu.sub +17 -424
- package/std/web/patches.sub +53 -18
- package/substrate/VERSION +1 -1
- package/substrate/compiler/expander.sub +2 -3
- package/substrate/compiler/roots.sub +12 -5
- package/substrate/host/grants.mjs +3 -3
- package/substrate/host/node/net.mjs +17 -2
- package/substrate/host/node/worker.mjs +3 -1
- package/substrate/host/subhost.mjs +4 -1
- package/substrate/host/web/audio.mjs +18 -10
- package/substrate/host/web/audio.sub +9 -3
- package/substrate/host/web/dom.mjs +167 -66
- package/substrate/host/web/dom.sub +9 -27
- package/substrate/host/web/fs.mjs +3 -3
- package/substrate/host/web/gpu.mjs +65 -27
- package/substrate/host/web/gpu.sub +18 -4
- package/substrate/host/web/location.mjs +15 -1
- package/substrate/host/web/location.sub +11 -3
- package/substrate/host/web/start.mjs +11 -7
- package/substrate/host/web/subhost-web.mjs +54 -33
- package/substrate/host/web/worker-script.mjs +4 -4
- package/substrate/host/web/worker.mjs +4 -4
- package/substrate/host/worker.mjs +1 -1
- package/build/sub/site.1732b58ec0e8@0+0.wasm +0 -0
- package/build/sub/site.ae3913b0b0f4@0+0.wasm +0 -0
- package/build/sub/sub.2e3092140706@0+0.wasm +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/build/compiler/program
CHANGED
|
@@ -4,11 +4,11 @@ syntax.32f3e40b61c7@0+0
|
|
|
4
4
|
path.5a6286472cd4@0+0
|
|
5
5
|
fs.01b8aab4a9a8@0+0
|
|
6
6
|
reader.694b03770bf0@0+0
|
|
7
|
-
roots.
|
|
7
|
+
roots.2f1ad1a79459@0+0
|
|
8
8
|
running.0d25dbaec018@0+0
|
|
9
9
|
core.f2defb75e00b@0+0
|
|
10
10
|
ops.515b5e05f646@0+0
|
|
11
|
-
checker.
|
|
11
|
+
checker.1d67e1d4e91a@0+0
|
|
12
12
|
leb128.15d814b7b4f2@0+0
|
|
13
13
|
binary.2d43b43d1600@0+0
|
|
14
14
|
serialize.b0d82f3d63d2@0+0
|
|
@@ -16,6 +16,6 @@ compile.5d8f6407af2a@0+0
|
|
|
16
16
|
sha256.a6c32b04d799@0+0
|
|
17
17
|
link.b826ea7c8f17@0+0
|
|
18
18
|
macros.b269e0c42784@0+0
|
|
19
|
-
expander.
|
|
19
|
+
expander.34110a31a949@0+0
|
|
20
20
|
prune.406215c3e4f8@0+0
|
|
21
|
-
main.
|
|
21
|
+
main.ca9b5089c24d@0+0
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/build/sub/program
CHANGED
|
@@ -3,46 +3,46 @@ process.7106571fa723@0+0
|
|
|
3
3
|
path.5a6286472cd4@0+0
|
|
4
4
|
path.6891ffea73ca@0+0
|
|
5
5
|
fs.01b8aab4a9a8@0+0
|
|
6
|
-
common.
|
|
6
|
+
common.7617940db2dc@0+0
|
|
7
7
|
grants.c54776c0d7e3@0+0
|
|
8
8
|
writer.00b7802cbe39@0+0
|
|
9
9
|
syntax.32f3e40b61c7@0+0
|
|
10
10
|
reader.694b03770bf0@0+0
|
|
11
|
-
roots.
|
|
11
|
+
roots.2f1ad1a79459@0+0
|
|
12
12
|
read.0b93933d62a2@0+0
|
|
13
|
-
manifest.
|
|
13
|
+
manifest.da52a88c7af7@0+0
|
|
14
14
|
git.dc4c0e757ebe@0+0
|
|
15
|
-
files.
|
|
15
|
+
files.5ae9d3cebeca@0+0
|
|
16
16
|
sha256.a6c32b04d799@0+0
|
|
17
|
-
hash.
|
|
18
|
-
store.
|
|
19
|
-
map.
|
|
17
|
+
hash.c57c141b4862@0+0
|
|
18
|
+
store.048c77bb124d@0+0
|
|
19
|
+
map.5c8084999550@0+0
|
|
20
20
|
env.e5451da6e747@0+0
|
|
21
21
|
events.bf5473ebf220@0+0
|
|
22
|
-
build.
|
|
22
|
+
build.eef7dfa467ec@0+0
|
|
23
23
|
pack.e02836264f6a@0+0
|
|
24
|
-
site.ae3913b0b0f4@0+0
|
|
25
|
-
site.1732b58ec0e8@0+0
|
|
26
|
-
fetch.7790d4943758@0+0
|
|
27
|
-
stream.126e3bd5d626@0+0
|
|
28
|
-
worker.762a9d642af0@0+0
|
|
29
24
|
deflate.23f7c4679260@0+0
|
|
30
25
|
inflate.59bb61f14001@0+0
|
|
31
26
|
gzip.16e372eda1cf@0+0
|
|
27
|
+
site.47fd989be8fb@0+0
|
|
28
|
+
site.c908b1f6db12@0+0
|
|
29
|
+
fetch.7790d4943758@0+0
|
|
30
|
+
stream.126e3bd5d626@0+0
|
|
31
|
+
worker.762a9d642af0@0+0
|
|
32
32
|
tar.2a633861e654@0+0
|
|
33
|
-
fetch.
|
|
34
|
-
doc.
|
|
33
|
+
fetch.3367ff4f88c0@0+0
|
|
34
|
+
doc.dab689b811ca@0+0
|
|
35
35
|
html.e9ed37f34977@0+0
|
|
36
|
-
html.
|
|
37
|
-
text.
|
|
38
|
-
root.
|
|
39
|
-
doc.
|
|
36
|
+
html.803f73c35c4a@0+0
|
|
37
|
+
text.b214933a4984@0+0
|
|
38
|
+
root.78253db36643@0+0
|
|
39
|
+
doc.92d6d82d99c1@0+0
|
|
40
40
|
timer.f35eb62ae446@0+0
|
|
41
41
|
chromium.3d5818f2707d@0+0
|
|
42
|
-
test.
|
|
42
|
+
test.b529bf52ba3e@0+0
|
|
43
43
|
utf8.e7216bd054e1@0+0
|
|
44
44
|
json.55590d2f518a@0+0
|
|
45
45
|
sha512.c24a792d7891@0+0
|
|
46
46
|
base64.a26bdcf60a2d@0+0
|
|
47
|
-
upgrade.
|
|
48
|
-
sub.
|
|
47
|
+
upgrade.7ec5651ed2e9@0+0
|
|
48
|
+
sub.a618f89f2ec8@0+0
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
package/std/http/server.sub
CHANGED
|
@@ -22,10 +22,10 @@
|
|
|
22
22
|
|
|
23
23
|
(provide http-server http-request http-check http-hook http-serve! http-server-close! http-server-shutdown!
|
|
24
24
|
http-stop-on-signals! http-hook! http-unhook! http-log-access http-request-header http-request-server
|
|
25
|
-
http-request-gone? http-request-address http-request-https? http-
|
|
26
|
-
http-respond! http-header! http-length! http-write! http-send! http-send-text!
|
|
27
|
-
http-take! http-read-body! http-answer-text! http-redirect! http-trapped
|
|
28
|
-
http-connection-close!)
|
|
25
|
+
http-request-gone? http-request-address http-request-https? http-accepts-gzip? http-request-deadline!
|
|
26
|
+
http-add-header! http-respond! http-header! http-length! http-write! http-send! http-send-text!
|
|
27
|
+
http-send-stream! http-finish! http-take! http-read-body! http-answer-text! http-redirect! http-trapped
|
|
28
|
+
http-connect! http-connection-feed! http-connection-close!)
|
|
29
29
|
|
|
30
30
|
(const default-body-limit u32 1048576)
|
|
31
31
|
(const most-dropped u64 262144)
|
|
@@ -630,8 +630,8 @@
|
|
|
630
630
|
(unless (or (== (@ q i) #\.) (== (@ q i) #\0)) (return #f)))
|
|
631
631
|
#t)
|
|
632
632
|
|
|
633
|
-
;; accepts-gzip? reads Accept-Encoding: gzip, or else *, with a weight above 0.
|
|
634
|
-
(define (accepts-gzip? [r (ptr http-request)]) -> bool
|
|
633
|
+
;; http-accepts-gzip? reads Accept-Encoding: gzip, or else *, with a weight above 0.
|
|
634
|
+
(define (http-accepts-gzip? [r (ptr http-request)]) -> bool
|
|
635
635
|
(let ([v (http-request-header r "accept-encoding")] [i u32 0] [gzip i32 -1] [any i32 -1])
|
|
636
636
|
(while (< i (-> v length))
|
|
637
637
|
(let ([end i] [k i])
|
|
@@ -653,7 +653,7 @@
|
|
|
653
653
|
|
|
654
654
|
(define (zip? [r (ptr http-request)]) -> bool
|
|
655
655
|
(and (> (-> (http-request-server r) compress) 0) (-> r compressible) (not (-> r encoded)) (has-body? r)
|
|
656
|
-
(!= (-> r status) 206) (accepts-gzip? r)))
|
|
656
|
+
(!= (-> r status) 206) (http-accepts-gzip? r)))
|
|
657
657
|
|
|
658
658
|
;; One deflater for every whole answer and event, each done before the next begins; zipped holds its output.
|
|
659
659
|
(define shared deflater)
|
package/std/http/static.sub
CHANGED
|
@@ -1,15 +1,17 @@
|
|
|
1
1
|
;; Files: http-send-file! answers with a file under the root, as Flask's send_from_directory does, and http-static! with
|
|
2
2
|
;; the file at the request's path, a directory's index.html, or a redirect adding a final slash. Answers carry
|
|
3
3
|
;; Last-Modified and an ETag, are 304 or 412 as preconditions require, hold one range when asked, and have Cache-Control
|
|
4
|
-
;; no-cache unless cache gives another value for the path.
|
|
5
|
-
;;
|
|
4
|
+
;; no-cache unless cache gives another value for the path. When a file has a gzipped copy beside it, named name.gz, a
|
|
5
|
+
;; request that takes gzip gets the copy. A part that is . or .., or that starts with a dot other than .well-known, is
|
|
6
|
+
;; not found. An empty root is the current directory. http-hashed-cache caches a path for a year when one of its
|
|
7
|
+
;; directories is named by 16 hex digits, as in the sites that substrate site --release writes.
|
|
6
8
|
(require-unqualified host/fs)
|
|
7
9
|
(require-unqualified "http.sub")
|
|
8
10
|
(require-unqualified "server.sub")
|
|
9
11
|
(require-unqualified "conditional.sub")
|
|
10
12
|
(require-unqualified "url.sub")
|
|
11
13
|
|
|
12
|
-
(provide http-files http-static! http-send-file!)
|
|
14
|
+
(provide http-files http-static! http-send-file! http-hashed-cache)
|
|
13
15
|
|
|
14
16
|
(struct http-files [root string] [cache (fn (string) -> string)])
|
|
15
17
|
|
|
@@ -185,53 +187,87 @@
|
|
|
185
187
|
(let ([value (if (== (-> files cache) 0) "" ((-> files cache) path))])
|
|
186
188
|
(if (== (-> value length) 0) "no-cache" value)))
|
|
187
189
|
|
|
188
|
-
(define (
|
|
190
|
+
(define (hex-digit? [c u8]) -> bool (or (and (>= c #\0) (<= c #\9)) (and (>= c #\a) (<= c #\f))))
|
|
191
|
+
|
|
192
|
+
(define (hash-part? [part string]) -> bool
|
|
193
|
+
(when (!= (-> part length) 16) (return #f))
|
|
194
|
+
(for ([i u32 0]) (< i 16) (+= i 1) (unless (hex-digit? (@ part i)) (return #f)))
|
|
195
|
+
#t)
|
|
196
|
+
|
|
197
|
+
(define (http-hashed-cache [path string]) -> string
|
|
198
|
+
(let ([start u32 0])
|
|
199
|
+
(for ([i u32 0]) (< i (-> path length)) (+= i 1)
|
|
200
|
+
(when (== (@ path i) #\/)
|
|
201
|
+
(when (hash-part? (slice path start i)) (return "public, max-age=31536000, immutable"))
|
|
202
|
+
(set! start (+ i 1))))
|
|
203
|
+
""))
|
|
204
|
+
|
|
205
|
+
(struct zipped [name string] [info fs-info] [found bool])
|
|
206
|
+
|
|
207
|
+
(define (zipped! [z (ptr zipped)] [name string])
|
|
208
|
+
(let ([b (make-buffer)])
|
|
209
|
+
(buffer-add-string! (& b) name)
|
|
210
|
+
(buffer-add-string! (& b) ".gz")
|
|
211
|
+
(set! (-> z name) (buffer-string (& b)))
|
|
212
|
+
(set! (-> z found) (and (fs-stat (-> z name) (& (-> z info)) 0) (== (-> z info kind) fs-file)))))
|
|
213
|
+
|
|
214
|
+
(define (head-of! [r (ptr http-request)] [name string] [encoded bool] [partial bool] [s (ptr span)] [size i64])
|
|
189
215
|
(http-respond! r (if partial 206 200))
|
|
190
216
|
(when partial (content-range! r s size))
|
|
191
|
-
(http-header! r "content-type" (content-type name))
|
|
217
|
+
(http-header! r "content-type" (content-type name))
|
|
218
|
+
(when encoded (http-header! r "content-encoding" "gzip")))
|
|
192
219
|
|
|
193
220
|
(define (failed! [r (ptr http-request)]) (http-answer-text! r 500 "cannot read the file"))
|
|
194
221
|
|
|
195
|
-
(define (body! [r (ptr http-request)] [name string] [partial bool] [s (ptr span)]
|
|
222
|
+
(define (body! [r (ptr http-request)] [name string] [file string] [encoded bool] [partial bool] [s (ptr span)]
|
|
223
|
+
[size i64])
|
|
196
224
|
(let ([n (- (-> s end) (-> s start))])
|
|
197
225
|
(cond [(== (-> r method) "HEAD")
|
|
198
|
-
(head-of! r name partial s size)
|
|
226
|
+
(head-of! r name encoded partial s size)
|
|
199
227
|
(http-length! r n)
|
|
200
228
|
(http-finish! r)]
|
|
201
229
|
[(<= size whole)
|
|
202
230
|
(let ([f (slice u8)])
|
|
203
|
-
(if (not (fs-read-file
|
|
231
|
+
(if (not (fs-read-file file (& f) 0))
|
|
204
232
|
(failed! r)
|
|
205
233
|
(begin
|
|
206
|
-
(head-of! r name partial s size)
|
|
234
|
+
(head-of! r name encoded partial s size)
|
|
207
235
|
(http-send! r (slice f (cast u32 (-> s start)) (cast u32 (-> s end))))
|
|
208
236
|
(free (-> f items)))))]
|
|
209
237
|
[else
|
|
210
|
-
(let ([h u32 0] [
|
|
211
|
-
(if (not (and (fs-open-file
|
|
238
|
+
(let ([h u32 0] [stream u32 0])
|
|
239
|
+
(if (not (and (fs-open-file file fs-read-flag (& h) 0) (fs-read-stream h (-> s start) 0 (& stream) 0)))
|
|
212
240
|
(failed! r)
|
|
213
241
|
(begin
|
|
214
|
-
(head-of! r name partial s size)
|
|
215
|
-
(http-send-stream! r
|
|
242
|
+
(head-of! r name encoded partial s size)
|
|
243
|
+
(http-send-stream! r stream n))))])))
|
|
216
244
|
|
|
217
|
-
;; send! answers with the file at name, whose path under the root is path.
|
|
245
|
+
;; send! answers with the file at name, whose path under the root is path, or with its gzipped copy. When there is a
|
|
246
|
+
;; copy, send! adds Vary itself and marks the answer encoded. The server then neither compresses it nor adds Vary again.
|
|
218
247
|
(define (send! [r (ptr http-request)] [files (ptr http-files)] [name string] [path string] [info (ptr fs-info)])
|
|
219
|
-
(let ([
|
|
220
|
-
(
|
|
221
|
-
(
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
(
|
|
225
|
-
(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
248
|
+
(let* ([z zipped] [tag (make-buffer)] [s span] [partial i32 0])
|
|
249
|
+
(zipped! (& z) name)
|
|
250
|
+
(let* ([encoded (and (-> z found) (http-accepts-gzip? r))] [sent (if encoded (& (-> z info)) info)]
|
|
251
|
+
[size (-> sent size)])
|
|
252
|
+
(span! (& s) 0 size)
|
|
253
|
+
(etag! (& tag) sent)
|
|
254
|
+
(http-add-header! r "cache-control" (cache-of files path))
|
|
255
|
+
(when (-> z found)
|
|
256
|
+
(http-add-header! r "vary" "accept-encoding")
|
|
257
|
+
(set! (-> r encoded) #t))
|
|
258
|
+
(unless (http-conditional! r (buffer-string (& tag)) (-> sent modified))
|
|
259
|
+
(set! partial (if encoded 0 (ranges! r size (buffer-string (& tag)) (-> sent modified) (& s))))
|
|
260
|
+
(if (< partial 0)
|
|
261
|
+
(let ([all span])
|
|
262
|
+
(span! (& all) -1 0)
|
|
263
|
+
(http-respond! r 416)
|
|
264
|
+
(content-range! r (& all) size)
|
|
265
|
+
(http-header! r "content-type" "text/plain; charset=utf-8")
|
|
266
|
+
(http-send-text! r "range not satisfiable"))
|
|
267
|
+
(begin
|
|
268
|
+
(set! (-> r ranges) (not encoded))
|
|
269
|
+
(body! r name (if encoded (-> z name) name) encoded (> partial 0) (& s) size)))))
|
|
270
|
+
(free (-> (-> z name) bytes))
|
|
235
271
|
(buffer-free! (& tag))))
|
|
236
272
|
|
|
237
273
|
(define (not-found! [r (ptr http-request)]) (http-answer-text! r 404 "not found"))
|
package/std/package/manifest.sub
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
;; The substrate clause gives the oldest substrate the package builds with. (substrate "0.10.0") also takes later 0.10
|
|
7
7
|
;; releases, and (substrate "1.2.0") takes later 1.x releases. Every clause but version is optional, and so are a path
|
|
8
8
|
;; dependency's hash and a site's html and files. A files part gives the program the files matching its paths, from its
|
|
9
|
-
;; from directory, under the directory it names; * matches any text in a name and ** any directories. (
|
|
9
|
+
;; from directory, under the directory it names; * matches any text in a name and ** any directories. (from name)
|
|
10
|
+
;; takes them from the directory that name stands for in a require: a dependency, std, compiler or host. (browser) says
|
|
10
11
|
;; that the package's tests open browsers with std/test/browser.sub.
|
|
11
12
|
(require-unqualified "read.sub")
|
|
12
13
|
(require-unqualified host/fs)
|
|
@@ -16,7 +17,7 @@
|
|
|
16
17
|
package-name? full-hash? version-before? version-compatible?)
|
|
17
18
|
|
|
18
19
|
(struct dependency [name string] [path string] [url string] [hash string] [line u32] [column u32])
|
|
19
|
-
(struct site-files [dir string] [from string] [patterns (slice string)])
|
|
20
|
+
(struct site-files [dir string] [from string] [root string] [patterns (slice string)])
|
|
20
21
|
(struct declared-site [name string] [program string] [html string] [files (slice site-files)] [line u32] [column u32])
|
|
21
22
|
(struct manifest [name string] [version string] [major u32] [substrate string] [exports (slice string)]
|
|
22
23
|
[dependencies (slice dependency)] [tests (slice string)]
|
|
@@ -267,10 +268,14 @@
|
|
|
267
268
|
(define (files-of [file string] [c (ptr data)] [a (ptr arena)] [f (ptr site-files)] [err (ptr buffer)]) -> bool
|
|
268
269
|
(let* ([items (items-of c)] [k u32 2] [n u32 0] [ps (new a string (-> items length))])
|
|
269
270
|
(set! (-> f from) "")
|
|
271
|
+
(set! (-> f root) "")
|
|
270
272
|
(unless (and (>= (-> items length) 3) (string-of (& (@ items 1)) (& (-> f dir))) (starts? (-> f dir) "/"))
|
|
271
273
|
(return (failed-at! err file c files-form)))
|
|
272
274
|
(when (list-of? (& (@ items 2)) "from" 2)
|
|
273
|
-
(
|
|
275
|
+
(let ([given (& (@ (items-of (& (@ items 2))) 1))])
|
|
276
|
+
(set! (-> f root) (symbol-of given))
|
|
277
|
+
(unless (or (> (-> f root length) 0) (string-of given (& (-> f from))))
|
|
278
|
+
(return (failed-at! err file c files-form))))
|
|
274
279
|
(set! k 3))
|
|
275
280
|
(for ([i u32 k]) (< i (-> items length)) (+= i 1)
|
|
276
281
|
(unless (and (string-of (& (@ items i)) (& (@ ps n))) (> (-> (@ ps n) length) 0))
|
|
@@ -284,7 +289,7 @@
|
|
|
284
289
|
"a site is (name \"program.sub\" (html \"file.html\") (files \"/dir\" \"path\" ...) ...), and the parts after the program are optional")
|
|
285
290
|
|
|
286
291
|
(define files-form string
|
|
287
|
-
"a site's files are (files \"/dir\" (from \"directory\") \"path\" ...), where from is optional, and in a path * matches any text in a name and ** matches any directories")
|
|
292
|
+
"a site's files are (files \"/dir\" (from \"directory\") \"path\" ...) or (files \"/dir\" (from name) \"path\" ...), where from is optional, and in a path * matches any text in a name and ** matches any directories")
|
|
288
293
|
|
|
289
294
|
(define (module-name? [s string]) -> bool
|
|
290
295
|
(let ([start u32 0])
|
package/std/package/site.sub
CHANGED
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
;; Sites: directories that a static server can serve. A site holds index.html, the web host, the program,
|
|
2
|
-
;;
|
|
3
|
-
;; program
|
|
4
|
-
;;
|
|
1
|
+
;; Sites: directories that a static server can serve. A site holds index.html, the web host, the program, and
|
|
2
|
+
;; files.pack with the files the site declares. It also holds the assets from beside the program, and assets.list lists
|
|
3
|
+
;; them. The program reads the declared files as files and loads the assets by URL. site-write! writes all of it except
|
|
4
|
+
;; a program given as a file. The caller builds that program into the site's program directory, as cmd/sub/site.sub and
|
|
5
|
+
;; std/test/browser.sub do. Files from a name need the program's module map in compiler/roots, so both callers load it
|
|
6
|
+
;; first. site-release! makes a written site a release (below).
|
|
7
|
+
(require-unqualified compiler/macros)
|
|
8
|
+
(require-unqualified compiler/roots)
|
|
5
9
|
(require-unqualified host/fs)
|
|
10
|
+
(require-unqualified std/crypto/sha256)
|
|
11
|
+
(require-unqualified std/compress/deflate)
|
|
12
|
+
(require-unqualified std/compress/gzip)
|
|
6
13
|
(require-unqualified "manifest.sub")
|
|
7
14
|
(require-unqualified "pack.sub")
|
|
8
15
|
(require-unqualified "path.sub")
|
|
9
16
|
|
|
10
|
-
(provide site-plan site-named? site-declared site-write!)
|
|
17
|
+
(provide site-plan site-named? site-declared site-write! site-release!)
|
|
11
18
|
|
|
12
19
|
(struct site-plan [name string] [program string] [html string] [files (slice site-files)] [base string])
|
|
13
20
|
|
|
@@ -36,6 +43,19 @@
|
|
|
36
43
|
(define (written! [path string] [b (slice u8)])
|
|
37
44
|
(let ([why error]) (unless (fs-write-file path b (& why)) (throw site-failed (error-text (& why))))))
|
|
38
45
|
|
|
46
|
+
(define (strings-of [b (ptr buffer)]) -> (slice string)
|
|
47
|
+
(slice (cast (ptr string) (-> b bytes)) (/ (-> b length) (sizeof string))))
|
|
48
|
+
|
|
49
|
+
(define (added! [b (ptr buffer)] [s string]) (buffer-add! b (slice (cast (ptr u8) (& s)) (sizeof string))))
|
|
50
|
+
|
|
51
|
+
(define (sorted! [ps (slice string)])
|
|
52
|
+
(for ([i u32 1]) (< i (-> ps length)) (+= i 1)
|
|
53
|
+
(let ([s (@ ps i)] [j i])
|
|
54
|
+
(while (and (> j 0) (< s (@ ps (- j 1))))
|
|
55
|
+
(set! (@ ps j) (@ ps (- j 1)))
|
|
56
|
+
(-= j 1))
|
|
57
|
+
(set! (@ ps j) s))))
|
|
58
|
+
|
|
39
59
|
(define (copy-tree! [from string] [to string] [base string] [files (ptr buffer)])
|
|
40
60
|
(let ([names (names-in from)])
|
|
41
61
|
(made! to)
|
|
@@ -110,9 +130,19 @@
|
|
|
110
130
|
(set! start (+ i 1))))
|
|
111
131
|
(slice (cast (ptr string) (-> out bytes)) (/ (-> out length) (sizeof string)))))
|
|
112
132
|
|
|
133
|
+
(define (root-directory [p (ptr site-plan)] [name string]) -> string
|
|
134
|
+
(let ([dir datum '#f])
|
|
135
|
+
(try (set! dir (named-directory (string->datum (-> p program)) (string->datum name)))
|
|
136
|
+
[catch compile-error (message blamed loc) (set! dir '#f)])
|
|
137
|
+
(unless (string? dir)
|
|
138
|
+
(throw site-failed (joined (joined "site: (from " name) ") names nothing that the site's program can require")))
|
|
139
|
+
(datum->string dir)))
|
|
140
|
+
|
|
113
141
|
(define (packed! [p (ptr site-plan)] [g (ptr site-files)] [files (ptr buffer)])
|
|
114
|
-
(let ([base (
|
|
115
|
-
|
|
142
|
+
(let ([base (cond [(> (-> g root length) 0) (root-directory p (-> g root))]
|
|
143
|
+
[(== (-> g from length) 0) (-> p base)]
|
|
144
|
+
[else (resolved-path (-> p base) (-> g from))])]
|
|
145
|
+
[found (make-buffer)] [err (make-buffer)])
|
|
116
146
|
(for ([i u32 0]) (< i (-> g patterns length)) (+= i 1)
|
|
117
147
|
(let ([before (-> found length)])
|
|
118
148
|
(matched! base "" (parts-of (@ (-> g patterns) i)) 0 (& found))
|
|
@@ -143,14 +173,9 @@
|
|
|
143
173
|
(let ([assets (joined-path (parent-of (-> p program)) "assets")] [found (make-buffer)])
|
|
144
174
|
(when (== (kind-of assets) fs-directory)
|
|
145
175
|
(copy-tree! assets (joined-path out "assets") "assets" (& found))
|
|
146
|
-
(let ([ps (
|
|
147
|
-
(
|
|
148
|
-
|
|
149
|
-
(while (and (> j 0) (< s (@ ps (- j 1))))
|
|
150
|
-
(set! (@ ps j) (@ ps (- j 1)))
|
|
151
|
-
(-= j 1))
|
|
152
|
-
(set! (@ ps j) s)))
|
|
153
|
-
(for ([i u32 0]) (< i n) (+= i 1)
|
|
176
|
+
(let ([ps (strings-of (& found))])
|
|
177
|
+
(sorted! ps)
|
|
178
|
+
(for ([i u32 0]) (< i (-> ps length)) (+= i 1)
|
|
154
179
|
(buffer-add-string! (& list) (@ ps i))
|
|
155
180
|
(buffer-add-byte! (& list) 10)))))
|
|
156
181
|
(written! (joined-path out "assets.list") (buffer-bytes (& list)))
|
|
@@ -163,3 +188,172 @@
|
|
|
163
188
|
(joined-path out "index.html"))
|
|
164
189
|
(when (== (kind-of (-> p program)) fs-directory)
|
|
165
190
|
(copy-tree! (-> p program) (joined-path out "program") "" (& files)))))
|
|
191
|
+
|
|
192
|
+
;; ---- releases ----
|
|
193
|
+
|
|
194
|
+
;; A release keeps index.html and the assets where they are. It moves the host, the program, files.pack and assets.list
|
|
195
|
+
;; into a directory named by a hash of their paths and bytes, the first 16 hex digits of a SHA-256. Each asset also gets
|
|
196
|
+
;; a copy in a directory named by its own hash, and assets.list gives each copy's path after a tab. A server can cache
|
|
197
|
+
;; all of these for good, as http-hashed-cache in std/http/static.sub does. index.html loads the program from its new
|
|
198
|
+
;; directory and preloads the program's files. A file gets a gzipped copy, name.gz, when gzip shrinks it to nine tenths
|
|
199
|
+
;; of its size or less.
|
|
200
|
+
|
|
201
|
+
;; site-release! makes the site written in out a release, or returns #f with the reason in err.
|
|
202
|
+
(define (site-release! [out string] [err (ptr buffer)]) -> bool
|
|
203
|
+
(try (begin (site-released! out) #t)
|
|
204
|
+
[catch site-failed (why)
|
|
205
|
+
(buffer-add-string! err why)
|
|
206
|
+
#f]))
|
|
207
|
+
|
|
208
|
+
(define (read! [path string]) -> (slice u8)
|
|
209
|
+
(let ([b (slice u8)] [why error])
|
|
210
|
+
(unless (fs-read-file path (& b) (& why)) (throw site-failed (error-text (& why))))
|
|
211
|
+
b))
|
|
212
|
+
|
|
213
|
+
(define (renamed! [from string] [to string])
|
|
214
|
+
(let ([why error]) (unless (fs-rename from to (& why)) (throw site-failed (error-text (& why))))))
|
|
215
|
+
|
|
216
|
+
(define (slashed [a string] [b string]) -> string (if (== (-> a length) 0) b (joined (joined a "/") b)))
|
|
217
|
+
|
|
218
|
+
(define (walked! [dir string] [rel string] [into (ptr buffer)])
|
|
219
|
+
(let ([names (names-in dir)])
|
|
220
|
+
(for ([i u32 0]) (< i (-> names length)) (+= i 1)
|
|
221
|
+
(let ([f (joined-path dir (@ names i))] [r (slashed rel (@ names i))])
|
|
222
|
+
(if (== (kind-of f) fs-directory) (walked! f r into) (added! into r))))))
|
|
223
|
+
|
|
224
|
+
(define (hex! [b (ptr buffer)] [bytes (slice u8)])
|
|
225
|
+
(let ([digits "0123456789abcdef"])
|
|
226
|
+
(for ([i u32 0]) (< i (-> bytes length)) (+= i 1)
|
|
227
|
+
(buffer-add-byte! b (@ digits (>> (cast u32 (@ bytes i)) 4)))
|
|
228
|
+
(buffer-add-byte! b (@ digits (bit-and (cast u32 (@ bytes i)) 15))))))
|
|
229
|
+
|
|
230
|
+
(define (release-name [out string] [paths (slice string)]) -> string
|
|
231
|
+
(let ([s sha256] [digest (array u8 32)] [name (make-buffer)] [size (make-buffer)])
|
|
232
|
+
(sha256-init! (& s))
|
|
233
|
+
(for ([i u32 0]) (< i (-> paths length)) (+= i 1)
|
|
234
|
+
(let ([b (read! (joined-path out (@ paths i)))])
|
|
235
|
+
(set! (-> size length) 0)
|
|
236
|
+
(buffer-add-byte! (& size) 0)
|
|
237
|
+
(buffer-add-u32! (& size) (-> b length))
|
|
238
|
+
(sha256-add! (& s) (cast (slice u8) (@ paths i)))
|
|
239
|
+
(sha256-add! (& s) (buffer-bytes (& size)))
|
|
240
|
+
(sha256-add! (& s) b)
|
|
241
|
+
(free (-> b items))))
|
|
242
|
+
(sha256-end! (& s) (slice digest))
|
|
243
|
+
(hex! (& name) (slice (slice digest) 0 8))
|
|
244
|
+
(buffer-free! (& size))
|
|
245
|
+
(buffer-string (& name))))
|
|
246
|
+
|
|
247
|
+
(define (found [s string] [part string]) -> i64
|
|
248
|
+
(for ([i u32 0]) (<= (+ i (-> part length)) (-> s length)) (+= i 1)
|
|
249
|
+
(when (== (slice s i (+ i (-> part length))) part) (return (cast i64 i))))
|
|
250
|
+
-1)
|
|
251
|
+
|
|
252
|
+
(define (found-before [s string] [part string] [before u32]) -> i64
|
|
253
|
+
(let ([i before])
|
|
254
|
+
(while (> i 0)
|
|
255
|
+
(-= i 1)
|
|
256
|
+
(when (and (<= (+ i (-> part length)) before) (== (slice s i (+ i (-> part length))) part))
|
|
257
|
+
(return (cast i64 i))))
|
|
258
|
+
-1))
|
|
259
|
+
|
|
260
|
+
(define (url-safe? [c u8]) -> bool
|
|
261
|
+
(or (and (>= c #\a) (<= c #\z)) (and (>= c #\A) (<= c #\Z)) (and (>= c #\0) (<= c #\9))
|
|
262
|
+
(== c 45) (== c 95) (== c 46) (== c 33) (== c 126) (== c 42) (== c 39) (== c 40) (== c 41)))
|
|
263
|
+
|
|
264
|
+
;; url! escapes each part of a path as encodeURIComponent does in the web host (subhost-web.mjs).
|
|
265
|
+
(define (url! [b (ptr buffer)] [path string])
|
|
266
|
+
(let ([digits "0123456789ABCDEF"])
|
|
267
|
+
(for ([i u32 0]) (< i (-> path length)) (+= i 1)
|
|
268
|
+
(let ([c (@ path i)])
|
|
269
|
+
(if (or (url-safe? c) (== c #\/))
|
|
270
|
+
(buffer-add-byte! b c)
|
|
271
|
+
(begin
|
|
272
|
+
(buffer-add-byte! b 37)
|
|
273
|
+
(buffer-add-byte! b (@ digits (>> (cast u32 c) 4)))
|
|
274
|
+
(buffer-add-byte! b (@ digits (bit-and (cast u32 c) 15)))))))))
|
|
275
|
+
|
|
276
|
+
(define (link! [b (ptr buffer)] [name string] [path string])
|
|
277
|
+
(buffer-add-string! b "<link rel=\"preload\" href=\"")
|
|
278
|
+
(buffer-add-string! b name)
|
|
279
|
+
(buffer-add-byte! b #\/)
|
|
280
|
+
(url! b path)
|
|
281
|
+
(buffer-add-string! b "\" as=\"fetch\" crossorigin>\n"))
|
|
282
|
+
|
|
283
|
+
(define (released-html! [out string] [name string] [fetched (slice string)])
|
|
284
|
+
(let* ([path (joined-path out "index.html")] [html (cast string (read! path))] [at (found html "host/web/start.mjs")]
|
|
285
|
+
[tag (if (< at 0) -1 (found-before html "<script" (cast u32 at)))] [b (make-buffer)])
|
|
286
|
+
(when (< tag 0)
|
|
287
|
+
(throw site-failed "site: index.html has no script that loads host/web/start.mjs, so it cannot be released"))
|
|
288
|
+
(buffer-add-string! (& b) (slice html 0 (cast u32 tag)))
|
|
289
|
+
(for ([i u32 0]) (< i (-> fetched length)) (+= i 1) (link! (& b) name (@ fetched i)))
|
|
290
|
+
(buffer-add-string! (& b) (slice html (cast u32 tag) (cast u32 at)))
|
|
291
|
+
(buffer-add-string! (& b) name)
|
|
292
|
+
(buffer-add-byte! (& b) #\/)
|
|
293
|
+
(buffer-add-string! (& b) (slice html (cast u32 at) (-> html length)))
|
|
294
|
+
(written! path (buffer-bytes (& b)))
|
|
295
|
+
(buffer-free! (& b))
|
|
296
|
+
(free (-> html bytes))))
|
|
297
|
+
|
|
298
|
+
(define (zipped! [dir string] [d (ptr deflater)])
|
|
299
|
+
(let ([names (names-in dir)])
|
|
300
|
+
(for ([i u32 0]) (< i (-> names length)) (+= i 1)
|
|
301
|
+
(let ([name (@ names i)] [f (joined-path dir (@ names i))])
|
|
302
|
+
(cond [(== (kind-of f) fs-directory) (zipped! f d)]
|
|
303
|
+
[(or (== name ".site") (ends? name ".gz")) (begin)]
|
|
304
|
+
[else
|
|
305
|
+
(let ([b (read! f)] [z (make-buffer)])
|
|
306
|
+
(gzip! d (& z) b "")
|
|
307
|
+
(when (<= (* (cast u64 (-> z length)) 10) (* (cast u64 (-> b length)) 9))
|
|
308
|
+
(written! (joined f ".gz") (buffer-bytes (& z))))
|
|
309
|
+
(free (-> b items))
|
|
310
|
+
(buffer-free! (& z)))])))))
|
|
311
|
+
|
|
312
|
+
(define (hash-of [b (slice u8)]) -> string
|
|
313
|
+
(let ([digest (array u8 32)] [name (make-buffer)])
|
|
314
|
+
(sha256-of b (slice digest))
|
|
315
|
+
(hex! (& name) (slice (slice digest) 0 8))
|
|
316
|
+
(buffer-string (& name))))
|
|
317
|
+
|
|
318
|
+
(define (hashed-assets! [out string])
|
|
319
|
+
(let ([listed (cast string (read! (joined-path out "assets.list")))] [b (make-buffer)] [start u32 0])
|
|
320
|
+
(for ([i u32 0]) (<= i (-> listed length)) (+= i 1)
|
|
321
|
+
(when (or (== i (-> listed length)) (== (@ listed i) 10))
|
|
322
|
+
(when (> i start)
|
|
323
|
+
(let* ([path (slice listed start i)] [bytes (read! (joined-path out path))] [hash (hash-of bytes)] [k i])
|
|
324
|
+
(while (and (> k start) (!= (@ listed (- k 1)) #\/)) (-= k 1))
|
|
325
|
+
(let ([dir (joined-path (joined-path out "assets") hash)] [name (slice listed k i)])
|
|
326
|
+
(made! dir)
|
|
327
|
+
(written! (joined-path dir name) bytes)
|
|
328
|
+
(buffer-add-string! (& b) path)
|
|
329
|
+
(buffer-add-byte! (& b) 9)
|
|
330
|
+
(buffer-add-string! (& b) (slashed "assets" (slashed hash name)))
|
|
331
|
+
(buffer-add-byte! (& b) 10))
|
|
332
|
+
(free (-> bytes items))))
|
|
333
|
+
(set! start (+ i 1))))
|
|
334
|
+
(written! (joined-path out "assets.list") (buffer-bytes (& b)))
|
|
335
|
+
(buffer-free! (& b))
|
|
336
|
+
(free (-> listed bytes))))
|
|
337
|
+
|
|
338
|
+
(define (site-released! [out string])
|
|
339
|
+
(let ([paths (make-buffer)] [fetched (make-buffer)] [d deflater])
|
|
340
|
+
(hashed-assets! out)
|
|
341
|
+
(walked! (joined-path out "host") "host" (& paths))
|
|
342
|
+
(walked! (joined-path out "program") "program" (& paths))
|
|
343
|
+
(added! (& paths) "files.pack")
|
|
344
|
+
(added! (& paths) "assets.list")
|
|
345
|
+
(sorted! (strings-of (& paths)))
|
|
346
|
+
(let* ([name (release-name out (strings-of (& paths)))] [code (joined-path out name)])
|
|
347
|
+
(made! code)
|
|
348
|
+
(renamed! (joined-path out "host") (joined-path code "host"))
|
|
349
|
+
(renamed! (joined-path out "program") (joined-path code "program"))
|
|
350
|
+
(renamed! (joined-path out "files.pack") (joined-path code "files.pack"))
|
|
351
|
+
(renamed! (joined-path out "assets.list") (joined-path code "assets.list"))
|
|
352
|
+
(walked! (joined-path code "program") "program" (& fetched))
|
|
353
|
+
(added! (& fetched) "files.pack")
|
|
354
|
+
(added! (& fetched) "assets.list")
|
|
355
|
+
(sorted! (strings-of (& fetched)))
|
|
356
|
+
(released-html! out name (strings-of (& fetched)))
|
|
357
|
+
(deflater-init! (& d) 9)
|
|
358
|
+
(zipped! out (& d))
|
|
359
|
+
(deflater-free! (& d)))))
|