firefly-compiler 0.4.51 → 0.4.53
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/.hintrc +4 -4
- package/.vscode/settings.json +4 -4
- package/bin/Release.ff +153 -153
- package/bin/firefly.mjs +1 -1
- package/compiler/Builder.ff +257 -257
- package/compiler/Compiler.ff +227 -227
- package/compiler/Dependencies.ff +186 -186
- package/compiler/DependencyLock.ff +17 -17
- package/compiler/JsEmitter.ff +946 -946
- package/compiler/LspHook.ff +202 -202
- package/compiler/ModuleCache.ff +178 -178
- package/compiler/Workspace.ff +88 -88
- package/core/.firefly/include/package-lock.json +394 -394
- package/core/.firefly/include/package.json +5 -5
- package/core/.firefly/include/prepare.sh +1 -1
- package/core/.firefly/package.ff +2 -2
- package/core/Array.ff +265 -265
- package/core/Atomic.ff +64 -64
- package/core/Box.ff +7 -7
- package/core/BrowserSystem.ff +40 -40
- package/core/BuildSystem.ff +148 -148
- package/core/Crypto.ff +96 -96
- package/core/Equal.ff +36 -36
- package/core/HttpClient.ff +87 -87
- package/core/JsSystem.ff +69 -69
- package/core/Json.ff +434 -434
- package/core/List.ff +486 -486
- package/core/Lock.ff +144 -144
- package/core/NodeSystem.ff +190 -189
- package/core/Ordering.ff +161 -161
- package/core/Path.ff +401 -401
- package/core/Random.ff +134 -134
- package/core/RbMap.ff +216 -216
- package/core/Show.ff +43 -43
- package/core/SourceLocation.ff +68 -68
- package/core/Task.ff +141 -141
- package/experimental/benchmarks/ListGrab.ff +23 -23
- package/experimental/benchmarks/ListGrab.java +55 -55
- package/experimental/benchmarks/Pyrotek45.ff +30 -30
- package/experimental/benchmarks/Pyrotek45.java +64 -64
- package/experimental/bidirectional/Bidi.ff +88 -88
- package/experimental/random/Index.ff +53 -53
- package/experimental/random/Process.ff +120 -120
- package/experimental/random/Scrape.ff +51 -51
- package/experimental/random/Symbols.ff +73 -73
- package/experimental/random/Tensor.ff +52 -52
- package/experimental/random/Units.ff +36 -36
- package/experimental/s3/S3TestAuthorizationHeader.ff +38 -38
- package/experimental/s3/S3TestPut.ff +15 -15
- package/experimental/tests/TestJson.ff +26 -26
- package/firefly.sh +0 -0
- package/fireflysite/Main.ff +13 -13
- package/lsp/.firefly/package.ff +1 -1
- package/lsp/CompletionHandler.ff +808 -808
- package/lsp/Handler.ff +714 -714
- package/lsp/HoverHandler.ff +79 -79
- package/lsp/LanguageServer.ff +272 -272
- package/lsp/SignatureHelpHandler.ff +55 -55
- package/lsp/SymbolHandler.ff +181 -181
- package/lsp/TestReferences.ff +16 -16
- package/lsp/TestReferencesCase.ff +7 -7
- package/lsp/stderr.txt +1 -1
- package/lsp/stdin.txt +10 -10
- package/lsp/stdout.txt +40 -40
- package/lux/.firefly/package.ff +1 -1
- package/lux/Css.ff +648 -648
- package/lux/CssTest.ff +48 -48
- package/lux/Lux.ff +487 -487
- package/lux/LuxEvent.ff +116 -116
- package/lux/Main.ff +128 -128
- package/lux/Main2.ff +144 -144
- package/output/js/ff/compiler/Builder.mjs +43 -43
- package/output/js/ff/compiler/Dependencies.mjs +3 -3
- package/output/js/ff/core/Array.mjs +59 -59
- package/output/js/ff/core/Atomic.mjs +36 -36
- package/output/js/ff/core/BrowserSystem.mjs +11 -11
- package/output/js/ff/core/BuildSystem.mjs +30 -30
- package/output/js/ff/core/Crypto.mjs +40 -40
- package/output/js/ff/core/HttpClient.mjs +24 -24
- package/output/js/ff/core/Json.mjs +147 -147
- package/output/js/ff/core/List.mjs +50 -50
- package/output/js/ff/core/Lock.mjs +97 -97
- package/output/js/ff/core/NodeSystem.mjs +78 -77
- package/output/js/ff/core/Ordering.mjs +8 -8
- package/output/js/ff/core/Path.mjs +231 -231
- package/output/js/ff/core/Random.mjs +56 -56
- package/output/js/ff/core/Task.mjs +31 -31
- package/package.json +1 -1
- package/rpc/.firefly/package.ff +1 -1
- package/rpc/Rpc.ff +69 -69
- package/s3/.firefly/package.ff +1 -1
- package/s3/S3.ff +90 -90
- package/unsafejs/UnsafeJs.ff +19 -19
- package/vscode/LICENSE.txt +21 -21
- package/vscode/Prepublish.ff +15 -15
- package/vscode/README.md +16 -16
- package/vscode/client/package.json +22 -22
- package/vscode/client/src/extension.ts +104 -104
- package/vscode/icons/firefly-icon.svg +10 -10
- package/vscode/language-configuration.json +61 -61
- package/vscode/package-lock.json +3623 -3623
- package/vscode/package.json +1 -1
- package/vscode/snippets.json +241 -241
- package/webserver/.firefly/include/package-lock.json +16 -16
- package/webserver/.firefly/include/package.json +5 -5
- package/webserver/.firefly/package.ff +2 -2
- package/webserver/WebServer.ff +685 -685
- package/websocket/.firefly/package.ff +1 -1
- package/websocket/WebSocket.ff +131 -131
package/core/Lock.ff
CHANGED
|
@@ -1,144 +1,144 @@
|
|
|
1
|
-
capability Lock {}
|
|
2
|
-
capability LockCondition {}
|
|
3
|
-
|
|
4
|
-
extend self: Lock {
|
|
5
|
-
|
|
6
|
-
condition(): LockCondition
|
|
7
|
-
target js async """
|
|
8
|
-
return {lock: self_, stack: [], queue: []}
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
acquire(reentrant: Bool): Unit
|
|
12
|
-
target js async """
|
|
13
|
-
if(self_.level === 0) {
|
|
14
|
-
self_.owner = $task
|
|
15
|
-
self_.level += 1
|
|
16
|
-
} else {
|
|
17
|
-
if(self_.owner !== $task || !reentrant_) {
|
|
18
|
-
try {
|
|
19
|
-
await new Promise((resolve, reject) => {
|
|
20
|
-
$task.controller.signal.addEventListener('abort', reject)
|
|
21
|
-
try {
|
|
22
|
-
self_.queue.push({owner: $task, resolve: resolve})
|
|
23
|
-
} finally {
|
|
24
|
-
$task.controller.signal.removeEventListener('abort', reject)
|
|
25
|
-
}
|
|
26
|
-
})
|
|
27
|
-
} finally {
|
|
28
|
-
if($task.controller.signal.aborted) $task.controller = new AbortController()
|
|
29
|
-
}
|
|
30
|
-
} else {
|
|
31
|
-
self_.level += 1
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
release(): Unit
|
|
37
|
-
target js async """
|
|
38
|
-
if(self_.owner !== $task) {
|
|
39
|
-
throw new Error("Tried to release a lock without acquiring it first.")
|
|
40
|
-
} else if(self_.level > 1) {
|
|
41
|
-
self_.level -= 1
|
|
42
|
-
} else {
|
|
43
|
-
self_.owner = null
|
|
44
|
-
self_.level = 0
|
|
45
|
-
if(self_.stack.length === 0) {
|
|
46
|
-
const empty = self_.stack
|
|
47
|
-
self_.stack = self_.queue.reverse()
|
|
48
|
-
self_.queue = empty
|
|
49
|
-
}
|
|
50
|
-
if(self_.stack.length !== 0) {
|
|
51
|
-
const pending = self_.stack.pop()
|
|
52
|
-
self_.owner = pending.owner
|
|
53
|
-
self_.level = 1
|
|
54
|
-
pending.resolve()
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
"""
|
|
58
|
-
|
|
59
|
-
do[T](reentrant: Bool, body: () => T): T {
|
|
60
|
-
self.acquire(reentrant)
|
|
61
|
-
try {
|
|
62
|
-
body()
|
|
63
|
-
} finally {
|
|
64
|
-
self.release()
|
|
65
|
-
} grab()
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
extend self: LockCondition {
|
|
71
|
-
|
|
72
|
-
sleep(): Unit
|
|
73
|
-
target js async """
|
|
74
|
-
if(self_.lock.owner !== $task) {
|
|
75
|
-
throw new Error("Tried to sleep on a condition without acquiring it first.")
|
|
76
|
-
}
|
|
77
|
-
const level = self_.lock.level
|
|
78
|
-
self_.lock.level = 1
|
|
79
|
-
await ff_core_Lock.Lock_release$(self_.lock)
|
|
80
|
-
try {
|
|
81
|
-
await new Promise((resolve, reject) => {
|
|
82
|
-
$task.controller.signal.addEventListener('abort', reject)
|
|
83
|
-
try {
|
|
84
|
-
self_.queue.push(resolve)
|
|
85
|
-
} finally {
|
|
86
|
-
$task.controller.signal.removeEventListener('abort', reject)
|
|
87
|
-
if($task.controller.signal.aborted) $task.controller = new AbortController()
|
|
88
|
-
}
|
|
89
|
-
})
|
|
90
|
-
} finally {
|
|
91
|
-
let exception = null
|
|
92
|
-
let acquired = false
|
|
93
|
-
while(!acquired) {
|
|
94
|
-
try {
|
|
95
|
-
await ff_core_Lock.Lock_acquire$(self_.lock)
|
|
96
|
-
self_.lock.level = level
|
|
97
|
-
acquired = true
|
|
98
|
-
} catch(e) {
|
|
99
|
-
exception = e
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
if(e !== null) throw e;
|
|
103
|
-
}
|
|
104
|
-
"""
|
|
105
|
-
|
|
106
|
-
sleepUntil[T](body: () => Option[T]): T {
|
|
107
|
-
body().{
|
|
108
|
-
| Some(value) =>
|
|
109
|
-
value
|
|
110
|
-
| None =>
|
|
111
|
-
self.sleep()
|
|
112
|
-
tailcall self.sleepUntil(body)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
wakeOne(): Unit
|
|
117
|
-
target js async """
|
|
118
|
-
if(self_.stack.length === 0) {
|
|
119
|
-
const empty = self_.stack
|
|
120
|
-
self_.stack = self_.queue.reverse()
|
|
121
|
-
self_.queue = empty
|
|
122
|
-
}
|
|
123
|
-
if(self_.stack.length !== 0) {
|
|
124
|
-
const resolve = self_.stack.pop()
|
|
125
|
-
resolve()
|
|
126
|
-
}
|
|
127
|
-
"""
|
|
128
|
-
|
|
129
|
-
wakeAll(): Unit
|
|
130
|
-
target js async """
|
|
131
|
-
while(self_.stack.length !== 0) {
|
|
132
|
-
const resolve = self_.stack.pop()
|
|
133
|
-
resolve()
|
|
134
|
-
}
|
|
135
|
-
const empty = self_.stack
|
|
136
|
-
self_.stack = self_.queue.reverse()
|
|
137
|
-
self_.queue = empty
|
|
138
|
-
while(self_.stack.length !== 0) {
|
|
139
|
-
const resolve = self_.stack.pop()
|
|
140
|
-
resolve()
|
|
141
|
-
}
|
|
142
|
-
"""
|
|
143
|
-
|
|
144
|
-
}
|
|
1
|
+
capability Lock {}
|
|
2
|
+
capability LockCondition {}
|
|
3
|
+
|
|
4
|
+
extend self: Lock {
|
|
5
|
+
|
|
6
|
+
condition(): LockCondition
|
|
7
|
+
target js async """
|
|
8
|
+
return {lock: self_, stack: [], queue: []}
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
acquire(reentrant: Bool): Unit
|
|
12
|
+
target js async """
|
|
13
|
+
if(self_.level === 0) {
|
|
14
|
+
self_.owner = $task
|
|
15
|
+
self_.level += 1
|
|
16
|
+
} else {
|
|
17
|
+
if(self_.owner !== $task || !reentrant_) {
|
|
18
|
+
try {
|
|
19
|
+
await new Promise((resolve, reject) => {
|
|
20
|
+
$task.controller.signal.addEventListener('abort', reject)
|
|
21
|
+
try {
|
|
22
|
+
self_.queue.push({owner: $task, resolve: resolve})
|
|
23
|
+
} finally {
|
|
24
|
+
$task.controller.signal.removeEventListener('abort', reject)
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
} finally {
|
|
28
|
+
if($task.controller.signal.aborted) $task.controller = new AbortController()
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
self_.level += 1
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
release(): Unit
|
|
37
|
+
target js async """
|
|
38
|
+
if(self_.owner !== $task) {
|
|
39
|
+
throw new Error("Tried to release a lock without acquiring it first.")
|
|
40
|
+
} else if(self_.level > 1) {
|
|
41
|
+
self_.level -= 1
|
|
42
|
+
} else {
|
|
43
|
+
self_.owner = null
|
|
44
|
+
self_.level = 0
|
|
45
|
+
if(self_.stack.length === 0) {
|
|
46
|
+
const empty = self_.stack
|
|
47
|
+
self_.stack = self_.queue.reverse()
|
|
48
|
+
self_.queue = empty
|
|
49
|
+
}
|
|
50
|
+
if(self_.stack.length !== 0) {
|
|
51
|
+
const pending = self_.stack.pop()
|
|
52
|
+
self_.owner = pending.owner
|
|
53
|
+
self_.level = 1
|
|
54
|
+
pending.resolve()
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
do[T](reentrant: Bool, body: () => T): T {
|
|
60
|
+
self.acquire(reentrant)
|
|
61
|
+
try {
|
|
62
|
+
body()
|
|
63
|
+
} finally {
|
|
64
|
+
self.release()
|
|
65
|
+
} grab()
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
extend self: LockCondition {
|
|
71
|
+
|
|
72
|
+
sleep(): Unit
|
|
73
|
+
target js async """
|
|
74
|
+
if(self_.lock.owner !== $task) {
|
|
75
|
+
throw new Error("Tried to sleep on a condition without acquiring it first.")
|
|
76
|
+
}
|
|
77
|
+
const level = self_.lock.level
|
|
78
|
+
self_.lock.level = 1
|
|
79
|
+
await ff_core_Lock.Lock_release$(self_.lock)
|
|
80
|
+
try {
|
|
81
|
+
await new Promise((resolve, reject) => {
|
|
82
|
+
$task.controller.signal.addEventListener('abort', reject)
|
|
83
|
+
try {
|
|
84
|
+
self_.queue.push(resolve)
|
|
85
|
+
} finally {
|
|
86
|
+
$task.controller.signal.removeEventListener('abort', reject)
|
|
87
|
+
if($task.controller.signal.aborted) $task.controller = new AbortController()
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
} finally {
|
|
91
|
+
let exception = null
|
|
92
|
+
let acquired = false
|
|
93
|
+
while(!acquired) {
|
|
94
|
+
try {
|
|
95
|
+
await ff_core_Lock.Lock_acquire$(self_.lock)
|
|
96
|
+
self_.lock.level = level
|
|
97
|
+
acquired = true
|
|
98
|
+
} catch(e) {
|
|
99
|
+
exception = e
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if(e !== null) throw e;
|
|
103
|
+
}
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
sleepUntil[T](body: () => Option[T]): T {
|
|
107
|
+
body().{
|
|
108
|
+
| Some(value) =>
|
|
109
|
+
value
|
|
110
|
+
| None =>
|
|
111
|
+
self.sleep()
|
|
112
|
+
tailcall self.sleepUntil(body)
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
wakeOne(): Unit
|
|
117
|
+
target js async """
|
|
118
|
+
if(self_.stack.length === 0) {
|
|
119
|
+
const empty = self_.stack
|
|
120
|
+
self_.stack = self_.queue.reverse()
|
|
121
|
+
self_.queue = empty
|
|
122
|
+
}
|
|
123
|
+
if(self_.stack.length !== 0) {
|
|
124
|
+
const resolve = self_.stack.pop()
|
|
125
|
+
resolve()
|
|
126
|
+
}
|
|
127
|
+
"""
|
|
128
|
+
|
|
129
|
+
wakeAll(): Unit
|
|
130
|
+
target js async """
|
|
131
|
+
while(self_.stack.length !== 0) {
|
|
132
|
+
const resolve = self_.stack.pop()
|
|
133
|
+
resolve()
|
|
134
|
+
}
|
|
135
|
+
const empty = self_.stack
|
|
136
|
+
self_.stack = self_.queue.reverse()
|
|
137
|
+
self_.queue = empty
|
|
138
|
+
while(self_.stack.length !== 0) {
|
|
139
|
+
const resolve = self_.stack.pop()
|
|
140
|
+
resolve()
|
|
141
|
+
}
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
}
|
package/core/NodeSystem.ff
CHANGED
|
@@ -1,189 +1,190 @@
|
|
|
1
|
-
capability NodeSystem {}
|
|
2
|
-
|
|
3
|
-
class ProcessResult(exitCode: Int, standardOut: Buffer, standardError: Buffer)
|
|
4
|
-
data ProcessException(problem: String)
|
|
5
|
-
|
|
6
|
-
extend self: NodeSystem {
|
|
7
|
-
|
|
8
|
-
arguments(): List[String]
|
|
9
|
-
target node async "return self_.array_"
|
|
10
|
-
|
|
11
|
-
assets(): AssetSystem {
|
|
12
|
-
let assetPkgSnapshotPath = self.path("/snapshot/output/assets")
|
|
13
|
-
if(assetPkgSnapshotPath.isDirectory()) {
|
|
14
|
-
// Opendir gives ENOENT: no such file or directory, opendir '/snapshot/output/assets'
|
|
15
|
-
function streams(path: Path): Stream[Pair[String, () => Stream[Buffer]]] {
|
|
16
|
-
internalListDirectoryWithoutOpendir(self, path).toStream().flatMap {file =>
|
|
17
|
-
if(file.isDirectory()) {
|
|
18
|
-
streams(file)
|
|
19
|
-
} else {
|
|
20
|
-
[Pair("/" + file.relativeTo(assetPkgSnapshotPath), {file.readStream()})].toStream()
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
AssetSystem(streams(assetPkgSnapshotPath).toMap())
|
|
25
|
-
} else {
|
|
26
|
-
internalAssets(self)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
path(relativePath: String): Path
|
|
31
|
-
target node async """
|
|
32
|
-
import * as path from 'path'
|
|
33
|
-
return path.resolve(relativePath_)
|
|
34
|
-
"""
|
|
35
|
-
|
|
36
|
-
pathFromUrl(url: String): Path
|
|
37
|
-
target node async """
|
|
38
|
-
import * as url from 'url';
|
|
39
|
-
return url.fileURLToPath(new URL(url_));
|
|
40
|
-
"""
|
|
41
|
-
|
|
42
|
-
httpClient(): HttpClient
|
|
43
|
-
target js async "return null"
|
|
44
|
-
|
|
45
|
-
mainTask(): Task
|
|
46
|
-
target js async "return self_.task_"
|
|
47
|
-
|
|
48
|
-
crypto(): Crypto
|
|
49
|
-
target js async "return (typeof globalThis !== 'undefined' ? globalThis : window).crypto"
|
|
50
|
-
|
|
51
|
-
js(): JsSystem
|
|
52
|
-
target js async "return typeof globalThis !== 'undefined' ? globalThis : window"
|
|
53
|
-
|
|
54
|
-
exit[T](exitCode: Int = 0): T
|
|
55
|
-
target js async "process.exit(exitCode_)"
|
|
56
|
-
|
|
57
|
-
readStream(): Stream[Buffer]
|
|
58
|
-
target js async """
|
|
59
|
-
return ff_core_Path.internalReadStream_$(() => process.stdin)
|
|
60
|
-
"""
|
|
61
|
-
|
|
62
|
-
writeBuffer(buffer: Buffer): Unit
|
|
63
|
-
target js async "process.stdout.write(new Uint8Array(buffer_.buffer, buffer_.byteOffset, buffer_.byteLength))"
|
|
64
|
-
|
|
65
|
-
writeStream(stream: Stream[Buffer]): Unit {
|
|
66
|
-
stream.each {self.writeBuffer(_)}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
writeText(text: String): Unit {
|
|
70
|
-
self.writeBuffer(text.toBuffer())
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
writeLine(text: String): Unit {
|
|
74
|
-
self.writeText(text + "\n")
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
writeErrorBuffer(buffer: Buffer): Unit
|
|
78
|
-
target js async "process.stderr.write(new Uint8Array(buffer_.buffer, buffer_.byteOffset, buffer_.byteLength))"
|
|
79
|
-
|
|
80
|
-
writeErrorStream(stream: Stream[Buffer]): Unit {
|
|
81
|
-
stream.each {self.writeErrorBuffer(_)}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
writeErrorText(text: String): Unit {
|
|
85
|
-
self.writeErrorBuffer(text.toBuffer())
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
writeErrorLine(text: String): Unit {
|
|
89
|
-
self.writeErrorText(text + "\n")
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
environment(): Map[String, String]
|
|
93
|
-
target node async """
|
|
94
|
-
const result = [];
|
|
95
|
-
for(const key in process.env) {
|
|
96
|
-
result.push(ff_core_Pair.Pair(key, process.env[key]));
|
|
97
|
-
}
|
|
98
|
-
return ff_core_List.List_toMap(result, ff_core_Ordering.ff_core_Ordering_Order$ff_core_String_String);
|
|
99
|
-
"""
|
|
100
|
-
|
|
101
|
-
execute(
|
|
102
|
-
command: String
|
|
103
|
-
arguments: List[String]
|
|
104
|
-
standardIn: Buffer = Buffer.new(0)
|
|
105
|
-
workingDirectory: Option[Path] = None
|
|
106
|
-
environment: Option[Map[String, String]] = None
|
|
107
|
-
maxBuffer: Int = 16777216
|
|
108
|
-
killSignal: Int = 9
|
|
109
|
-
): ProcessResult
|
|
110
|
-
target node async """
|
|
111
|
-
import * as childProcess from 'node:child_process';
|
|
112
|
-
const environment = environment_.value_ !== void 0 ? {} : process.env;
|
|
113
|
-
if(environment_.value_ !== void 0) {
|
|
114
|
-
ff_core_Map.Map_each(
|
|
115
|
-
environment_.value_,
|
|
116
|
-
(k, v) => environment[k] = v,
|
|
117
|
-
ff_core_Ordering.ff_core_Ordering_Order$ff_core_String_String
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
const newProcess = childProcess.spawn(command_, arguments_, {
|
|
121
|
-
cwd: workingDirectory_.value_,
|
|
122
|
-
windowsHide: true,
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
size
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
size
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
newProcess.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
new DataView(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
import * as
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
1
|
+
capability NodeSystem {}
|
|
2
|
+
|
|
3
|
+
class ProcessResult(exitCode: Int, standardOut: Buffer, standardError: Buffer)
|
|
4
|
+
data ProcessException(problem: String)
|
|
5
|
+
|
|
6
|
+
extend self: NodeSystem {
|
|
7
|
+
|
|
8
|
+
arguments(): List[String]
|
|
9
|
+
target node async "return self_.array_"
|
|
10
|
+
|
|
11
|
+
assets(): AssetSystem {
|
|
12
|
+
let assetPkgSnapshotPath = self.path("/snapshot/output/assets")
|
|
13
|
+
if(assetPkgSnapshotPath.isDirectory()) {
|
|
14
|
+
// Opendir gives ENOENT: no such file or directory, opendir '/snapshot/output/assets'
|
|
15
|
+
function streams(path: Path): Stream[Pair[String, () => Stream[Buffer]]] {
|
|
16
|
+
internalListDirectoryWithoutOpendir(self, path).toStream().flatMap {file =>
|
|
17
|
+
if(file.isDirectory()) {
|
|
18
|
+
streams(file)
|
|
19
|
+
} else {
|
|
20
|
+
[Pair("/" + file.relativeTo(assetPkgSnapshotPath), {file.readStream()})].toStream()
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
AssetSystem(streams(assetPkgSnapshotPath).toMap())
|
|
25
|
+
} else {
|
|
26
|
+
internalAssets(self)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
path(relativePath: String): Path
|
|
31
|
+
target node async """
|
|
32
|
+
import * as path from 'path'
|
|
33
|
+
return path.resolve(relativePath_)
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
pathFromUrl(url: String): Path
|
|
37
|
+
target node async """
|
|
38
|
+
import * as url from 'url';
|
|
39
|
+
return url.fileURLToPath(new URL(url_));
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
httpClient(): HttpClient
|
|
43
|
+
target js async "return null"
|
|
44
|
+
|
|
45
|
+
mainTask(): Task
|
|
46
|
+
target js async "return self_.task_"
|
|
47
|
+
|
|
48
|
+
crypto(): Crypto
|
|
49
|
+
target js async "return (typeof globalThis !== 'undefined' ? globalThis : window).crypto"
|
|
50
|
+
|
|
51
|
+
js(): JsSystem
|
|
52
|
+
target js async "return typeof globalThis !== 'undefined' ? globalThis : window"
|
|
53
|
+
|
|
54
|
+
exit[T](exitCode: Int = 0): T
|
|
55
|
+
target js async "process.exit(exitCode_)"
|
|
56
|
+
|
|
57
|
+
readStream(): Stream[Buffer]
|
|
58
|
+
target js async """
|
|
59
|
+
return ff_core_Path.internalReadStream_$(() => process.stdin)
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
writeBuffer(buffer: Buffer): Unit
|
|
63
|
+
target js async "process.stdout.write(new Uint8Array(buffer_.buffer, buffer_.byteOffset, buffer_.byteLength))"
|
|
64
|
+
|
|
65
|
+
writeStream(stream: Stream[Buffer]): Unit {
|
|
66
|
+
stream.each {self.writeBuffer(_)}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
writeText(text: String): Unit {
|
|
70
|
+
self.writeBuffer(text.toBuffer())
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
writeLine(text: String): Unit {
|
|
74
|
+
self.writeText(text + "\n")
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
writeErrorBuffer(buffer: Buffer): Unit
|
|
78
|
+
target js async "process.stderr.write(new Uint8Array(buffer_.buffer, buffer_.byteOffset, buffer_.byteLength))"
|
|
79
|
+
|
|
80
|
+
writeErrorStream(stream: Stream[Buffer]): Unit {
|
|
81
|
+
stream.each {self.writeErrorBuffer(_)}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
writeErrorText(text: String): Unit {
|
|
85
|
+
self.writeErrorBuffer(text.toBuffer())
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
writeErrorLine(text: String): Unit {
|
|
89
|
+
self.writeErrorText(text + "\n")
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
environment(): Map[String, String]
|
|
93
|
+
target node async """
|
|
94
|
+
const result = [];
|
|
95
|
+
for(const key in process.env) {
|
|
96
|
+
result.push(ff_core_Pair.Pair(key, process.env[key]));
|
|
97
|
+
}
|
|
98
|
+
return ff_core_List.List_toMap(result, ff_core_Ordering.ff_core_Ordering_Order$ff_core_String_String);
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
execute(
|
|
102
|
+
command: String
|
|
103
|
+
arguments: List[String]
|
|
104
|
+
standardIn: Buffer = Buffer.new(0)
|
|
105
|
+
workingDirectory: Option[Path] = None
|
|
106
|
+
environment: Option[Map[String, String]] = None
|
|
107
|
+
maxBuffer: Int = 16777216
|
|
108
|
+
killSignal: Int = 9
|
|
109
|
+
): ProcessResult
|
|
110
|
+
target node async """
|
|
111
|
+
import * as childProcess from 'node:child_process';
|
|
112
|
+
const environment = environment_.value_ !== void 0 ? {} : process.env;
|
|
113
|
+
if(environment_.value_ !== void 0) {
|
|
114
|
+
ff_core_Map.Map_each(
|
|
115
|
+
environment_.value_,
|
|
116
|
+
(k, v) => environment[k] = v,
|
|
117
|
+
ff_core_Ordering.ff_core_Ordering_Order$ff_core_String_String
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
const newProcess = childProcess.spawn(command_, arguments_, {
|
|
121
|
+
cwd: workingDirectory_.value_,
|
|
122
|
+
windowsHide: true,
|
|
123
|
+
shell: process.platform === 'win32',
|
|
124
|
+
signal: $task.controller.signal,
|
|
125
|
+
killSignal: killSignal_,
|
|
126
|
+
env: environment,
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
let size = 0;
|
|
130
|
+
const out = [];
|
|
131
|
+
const err = [];
|
|
132
|
+
|
|
133
|
+
newProcess.stdout.on('data', (data) => {
|
|
134
|
+
if(size > maxBuffer_) return;
|
|
135
|
+
size += data.byteLength;
|
|
136
|
+
if(size > maxBuffer_) newProcess.kill(killSignal_);
|
|
137
|
+
else out.push(data);
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
newProcess.stderr.on('data', (data) => {
|
|
141
|
+
if(size > maxBuffer_) return;
|
|
142
|
+
size += data.byteLength;
|
|
143
|
+
if(size > maxBuffer_) newProcess.kill(killSignal_);
|
|
144
|
+
else err.push(data);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return await new Promise((resolve, reject) => {
|
|
148
|
+
if(standardIn_.byteLength !== 0) {
|
|
149
|
+
newProcess.stdin.write(standardIn_);
|
|
150
|
+
}
|
|
151
|
+
newProcess.stdin.end();
|
|
152
|
+
newProcess.on('error', error => {
|
|
153
|
+
if(size > maxBuffer_) {
|
|
154
|
+
reject(internalProcessError_("maxBuffer exceeded"));
|
|
155
|
+
} else {
|
|
156
|
+
reject(internalProcessError_(error.message));
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
newProcess.on('close', code => {
|
|
160
|
+
const o = Buffer.concat(out);
|
|
161
|
+
const e = Buffer.concat(err);
|
|
162
|
+
resolve(ProcessResult(
|
|
163
|
+
code,
|
|
164
|
+
new DataView(o.buffer, o.byteOffset, o.byteLength),
|
|
165
|
+
new DataView(e.buffer, e.byteOffset, e.byteLength),
|
|
166
|
+
));
|
|
167
|
+
});
|
|
168
|
+
});
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
internalAssets(system: NodeSystem): AssetSystem
|
|
174
|
+
target node async "return system_.assets_"
|
|
175
|
+
|
|
176
|
+
internalListDirectoryWithoutOpendir(system: NodeSystem, path: Path): List[Path]
|
|
177
|
+
target node async """
|
|
178
|
+
import * as fsPromises from 'fs/promises'
|
|
179
|
+
import * as path from 'path'
|
|
180
|
+
let files = await fsPromises.readdir(path_)
|
|
181
|
+
return files.map(file => path.join(path_, file))
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
internalProcessError(problem: String): Error {
|
|
185
|
+
try {
|
|
186
|
+
throw(ProcessException(problem))
|
|
187
|
+
} catchAny {error =>
|
|
188
|
+
error
|
|
189
|
+
} grab()
|
|
190
|
+
}
|