firefly-compiler 0.5.39 → 0.5.40

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 (129) hide show
  1. package/.hintrc +4 -4
  2. package/.vscode/settings.json +4 -4
  3. package/bin/Release.ff +157 -157
  4. package/bin/firefly.mjs +1 -1
  5. package/compiler/Builder.ff +275 -275
  6. package/compiler/Compiler.ff +234 -234
  7. package/compiler/Dependencies.ff +186 -186
  8. package/compiler/DependencyLock.ff +17 -17
  9. package/compiler/JsEmitter.ff +1437 -1437
  10. package/compiler/LspHook.ff +202 -202
  11. package/compiler/ModuleCache.ff +178 -178
  12. package/compiler/Workspace.ff +88 -88
  13. package/core/.firefly/include/package.json +5 -5
  14. package/core/.firefly/package.ff +2 -2
  15. package/core/Any.ff +25 -25
  16. package/core/Array.ff +298 -298
  17. package/core/Atomic.ff +63 -63
  18. package/core/Box.ff +7 -7
  19. package/core/BrowserSystem.ff +40 -40
  20. package/core/BuildSystem.ff +156 -156
  21. package/core/Crypto.ff +94 -94
  22. package/core/Equal.ff +41 -41
  23. package/core/Error.ff +25 -25
  24. package/core/HttpClient.ff +142 -142
  25. package/core/Instant.ff +24 -24
  26. package/core/Js.ff +305 -305
  27. package/core/JsSystem.ff +135 -135
  28. package/core/Json.ff +423 -423
  29. package/core/List.ff +482 -482
  30. package/core/Lock.ff +108 -108
  31. package/core/NodeSystem.ff +198 -198
  32. package/core/Ordering.ff +160 -160
  33. package/core/Path.ff +377 -378
  34. package/core/Queue.ff +90 -90
  35. package/core/Random.ff +140 -140
  36. package/core/RbMap.ff +216 -216
  37. package/core/Show.ff +44 -44
  38. package/core/SourceLocation.ff +68 -68
  39. package/core/Task.ff +165 -165
  40. package/experimental/benchmarks/ListGrab.ff +23 -23
  41. package/experimental/benchmarks/ListGrab.java +55 -55
  42. package/experimental/benchmarks/Pyrotek45.ff +30 -30
  43. package/experimental/benchmarks/Pyrotek45.java +64 -64
  44. package/experimental/bidirectional/Bidi.ff +88 -88
  45. package/experimental/lines/Main.ff +40 -40
  46. package/experimental/random/Index.ff +53 -53
  47. package/experimental/random/Process.ff +120 -120
  48. package/experimental/random/RunLength.ff +65 -65
  49. package/experimental/random/Scrape.ff +51 -51
  50. package/experimental/random/Symbols.ff +73 -73
  51. package/experimental/random/Tensor.ff +52 -52
  52. package/experimental/random/Units.ff +36 -36
  53. package/experimental/s3/S3TestAuthorizationHeader.ff +39 -39
  54. package/experimental/s3/S3TestPut.ff +16 -16
  55. package/experimental/tests/TestJson.ff +26 -26
  56. package/firefly.sh +0 -0
  57. package/fireflysite/.firefly/package.ff +4 -4
  58. package/fireflysite/CommunityOverview.ff +20 -20
  59. package/fireflysite/CountingButtonDemo.ff +58 -58
  60. package/fireflysite/DocumentParser.ff +325 -325
  61. package/fireflysite/ExamplesOverview.ff +40 -40
  62. package/fireflysite/FrontPage.ff +344 -344
  63. package/fireflysite/GettingStarted.ff +45 -45
  64. package/fireflysite/Guide.ff +456 -456
  65. package/fireflysite/Main.ff +163 -163
  66. package/fireflysite/MatchingPasswordsDemo.ff +82 -82
  67. package/fireflysite/PackagesOverview.ff +49 -49
  68. package/fireflysite/PostgresqlDemo.ff +34 -34
  69. package/fireflysite/ReferenceAll.ff +18 -18
  70. package/fireflysite/ReferenceIntroduction.ff +11 -11
  71. package/fireflysite/Styles.ff +567 -567
  72. package/fireflysite/Test.ff +121 -121
  73. package/fireflysite/assets/markdown/reference/BaseTypes.md +209 -209
  74. package/fireflysite/assets/markdown/reference/EmittedJavascript.md +65 -65
  75. package/fireflysite/assets/markdown/reference/Exceptions.md +101 -101
  76. package/fireflysite/assets/markdown/reference/FunctionsAndMethods.md +364 -364
  77. package/fireflysite/assets/markdown/reference/JavascriptInterop.md +235 -235
  78. package/fireflysite/assets/markdown/reference/ModulesAndPackages.md +162 -162
  79. package/fireflysite/assets/markdown/reference/OldStructuredConcurrency.md +48 -48
  80. package/fireflysite/assets/markdown/reference/PatternMatching.md +224 -224
  81. package/fireflysite/assets/markdown/reference/StatementsAndExpressions.md +86 -86
  82. package/fireflysite/assets/markdown/reference/StructuredConcurrency.md +99 -99
  83. package/fireflysite/assets/markdown/reference/TraitsAndInstances.md +100 -100
  84. package/fireflysite/assets/markdown/reference/UserDefinedTypes.md +184 -184
  85. package/fireflysite/assets/markdown/scratch/ControlFlow.md +136 -136
  86. package/fireflysite/assets/markdown/scratch/Toc.md +40 -40
  87. package/lsp/.firefly/package.ff +1 -1
  88. package/lsp/CompletionHandler.ff +827 -827
  89. package/lsp/Handler.ff +714 -714
  90. package/lsp/HoverHandler.ff +79 -79
  91. package/lsp/LanguageServer.ff +272 -272
  92. package/lsp/SignatureHelpHandler.ff +55 -55
  93. package/lsp/SymbolHandler.ff +181 -181
  94. package/lsp/TestReferences.ff +17 -17
  95. package/lsp/TestReferencesCase.ff +7 -7
  96. package/lsp/stderr.txt +1 -1
  97. package/lsp/stdout.txt +34 -34
  98. package/lux/.firefly/package.ff +1 -1
  99. package/lux/Css.ff +648 -648
  100. package/lux/CssTest.ff +48 -48
  101. package/lux/Lux.ff +608 -608
  102. package/lux/LuxEvent.ff +79 -79
  103. package/lux/Main.ff +123 -123
  104. package/lux/Main2.ff +143 -143
  105. package/lux/TestDry.ff +28 -28
  106. package/output/js/ff/compiler/Builder.mjs +36 -36
  107. package/output/js/ff/core/Path.mjs +0 -2
  108. package/package.json +1 -1
  109. package/rpc/.firefly/package.ff +1 -1
  110. package/rpc/Rpc.ff +70 -70
  111. package/s3/.firefly/package.ff +1 -1
  112. package/s3/S3.ff +92 -92
  113. package/vscode/LICENSE.txt +21 -21
  114. package/vscode/Prepublish.ff +15 -15
  115. package/vscode/README.md +16 -16
  116. package/vscode/client/package-lock.json +544 -544
  117. package/vscode/client/package.json +22 -22
  118. package/vscode/client/src/extension.ts +104 -104
  119. package/vscode/icons/firefly-icon.svg +10 -10
  120. package/vscode/language-configuration.json +61 -61
  121. package/vscode/package-lock.json +3623 -3623
  122. package/vscode/package.json +1 -1
  123. package/vscode/snippets.json +241 -241
  124. package/vscode/syntaxes/firefly-markdown-injection.json +45 -45
  125. package/webserver/.firefly/include/package.json +5 -5
  126. package/webserver/.firefly/package.ff +2 -2
  127. package/webserver/WebServer.ff +647 -647
  128. package/websocket/.firefly/package.ff +1 -1
  129. package/websocket/WebSocket.ff +100 -100
package/core/Lock.ff CHANGED
@@ -1,108 +1,108 @@
1
- capability Lock(
2
- mutable owner: JsValue
3
- mutable level: Int
4
- queue: Queue[Pair[JsValue, Unit => Unit]]
5
- )
6
-
7
- capability LockCondition(
8
- lock: Lock
9
- queue: Queue[Unit => Unit]
10
- )
11
-
12
- extend self: Lock {
13
-
14
- condition(): LockCondition {
15
- LockCondition(self, Queue.new())
16
- }
17
-
18
- acquire(): Unit {
19
- if(self.level == 0 || self.owner === Js.currentTask()!) {
20
- self.owner = Js.currentTask()!
21
- self.level += 1
22
- } else {
23
- Js.awaitCancellablePromise {resolve, reject, onSettle =>
24
- let key = self.queue.push(Pair(Js.currentTask()!, resolve))
25
- onSettle {_ => self.queue.remove(key)}
26
- }
27
- }
28
- }
29
-
30
- release(): Unit {
31
- if(self.owner !== Js.currentTask()!) {
32
- throw(GrabException)
33
- } elseIf {self.level > 1} {
34
- self.level -= 1
35
- } else {
36
- self.owner = Js.undefined()
37
- self.level = 0
38
- if(!self.queue.isEmpty()) {
39
- let pending = self.queue.pop().grab()
40
- self.owner = pending.first
41
- self.level = 1
42
- pending.second(Unit)
43
- }
44
- }
45
- }
46
-
47
- do[T](body: () => T): T {
48
- self.acquire()
49
- try {
50
- body()
51
- } finally {
52
- self.release()
53
- }
54
- }
55
-
56
- }
57
-
58
- extend self: LockCondition {
59
-
60
- sleep(): Unit {
61
- if(self.lock.owner !== Js.currentTask()!) {
62
- throw(GrabException)
63
- }
64
- Js.throwIfCancelled()
65
- let level = self.lock.level
66
- self.lock.level = 1
67
- self.lock.release()
68
- try {
69
- Js.awaitCancellablePromise {resolve, reject, onSettle =>
70
- let key = self.queue.push(resolve)
71
- onSettle {_ => self.queue.remove(key)}
72
- }
73
- } finally {
74
- mutable error = Js.undefined()
75
- mutable acquired = False
76
- while {!acquired} {
77
- try {
78
- self.lock.acquire()
79
- self.lock.level = level
80
- acquired = True
81
- } catchAny {e =>
82
- error = e!
83
- }
84
- }
85
- if(error.isUndefined()) {Js.throw(error)}
86
- }
87
- }
88
-
89
- sleepUntil[T](body: () => Option[T]): T {
90
- body().{
91
- | Some(value) =>
92
- value
93
- | None =>
94
- self.sleep()
95
- tailcall self.sleepUntil(body)
96
- }
97
- }
98
-
99
- wakeOne(): Unit {
100
- self.queue.pop().each {resolve => resolve(Unit)}
101
- }
102
-
103
- wakeAll(): Unit {
104
- self.queue.each {_, resolve => resolve(Unit)}
105
- self.queue.clear()
106
- }
107
-
108
- }
1
+ capability Lock(
2
+ mutable owner: JsValue
3
+ mutable level: Int
4
+ queue: Queue[Pair[JsValue, Unit => Unit]]
5
+ )
6
+
7
+ capability LockCondition(
8
+ lock: Lock
9
+ queue: Queue[Unit => Unit]
10
+ )
11
+
12
+ extend self: Lock {
13
+
14
+ condition(): LockCondition {
15
+ LockCondition(self, Queue.new())
16
+ }
17
+
18
+ acquire(): Unit {
19
+ if(self.level == 0 || self.owner === Js.currentTask()!) {
20
+ self.owner = Js.currentTask()!
21
+ self.level += 1
22
+ } else {
23
+ Js.awaitCancellablePromise {resolve, reject, onSettle =>
24
+ let key = self.queue.push(Pair(Js.currentTask()!, resolve))
25
+ onSettle {_ => self.queue.remove(key)}
26
+ }
27
+ }
28
+ }
29
+
30
+ release(): Unit {
31
+ if(self.owner !== Js.currentTask()!) {
32
+ throw(GrabException)
33
+ } elseIf {self.level > 1} {
34
+ self.level -= 1
35
+ } else {
36
+ self.owner = Js.undefined()
37
+ self.level = 0
38
+ if(!self.queue.isEmpty()) {
39
+ let pending = self.queue.pop().grab()
40
+ self.owner = pending.first
41
+ self.level = 1
42
+ pending.second(Unit)
43
+ }
44
+ }
45
+ }
46
+
47
+ do[T](body: () => T): T {
48
+ self.acquire()
49
+ try {
50
+ body()
51
+ } finally {
52
+ self.release()
53
+ }
54
+ }
55
+
56
+ }
57
+
58
+ extend self: LockCondition {
59
+
60
+ sleep(): Unit {
61
+ if(self.lock.owner !== Js.currentTask()!) {
62
+ throw(GrabException)
63
+ }
64
+ Js.throwIfCancelled()
65
+ let level = self.lock.level
66
+ self.lock.level = 1
67
+ self.lock.release()
68
+ try {
69
+ Js.awaitCancellablePromise {resolve, reject, onSettle =>
70
+ let key = self.queue.push(resolve)
71
+ onSettle {_ => self.queue.remove(key)}
72
+ }
73
+ } finally {
74
+ mutable error = Js.undefined()
75
+ mutable acquired = False
76
+ while {!acquired} {
77
+ try {
78
+ self.lock.acquire()
79
+ self.lock.level = level
80
+ acquired = True
81
+ } catchAny {e =>
82
+ error = e!
83
+ }
84
+ }
85
+ if(error.isUndefined()) {Js.throw(error)}
86
+ }
87
+ }
88
+
89
+ sleepUntil[T](body: () => Option[T]): T {
90
+ body().{
91
+ | Some(value) =>
92
+ value
93
+ | None =>
94
+ self.sleep()
95
+ tailcall self.sleepUntil(body)
96
+ }
97
+ }
98
+
99
+ wakeOne(): Unit {
100
+ self.queue.pop().each {resolve => resolve(Unit)}
101
+ }
102
+
103
+ wakeAll(): Unit {
104
+ self.queue.each {_, resolve => resolve(Unit)}
105
+ self.queue.clear()
106
+ }
107
+
108
+ }
@@ -1,198 +1,198 @@
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
- self!->"array_"?
10
- }
11
-
12
- assets(): AssetSystem {
13
- let assetPkgSnapshotPath = self.path("/snapshot/output/assets")
14
- if(assetPkgSnapshotPath.isDirectory()) {
15
- // Opendir gives ENOENT: no such file or directory, opendir '/snapshot/output/assets'
16
- function streams(path: Path): Stream[Pair[String, () => Stream[Buffer]]] {
17
- internalListDirectoryWithoutOpendir(self, path).toStream().flatMap {file =>
18
- if(file.isDirectory()) {
19
- streams(file)
20
- } else {
21
- [Pair("/" + file.relativeTo(assetPkgSnapshotPath), {file.readStream()})].toStream()
22
- }
23
- }
24
- }
25
- AssetSystem(streams(assetPkgSnapshotPath).toMap())
26
- } else {
27
- self!->"assets_"?
28
- }
29
- }
30
-
31
- path(relativePath: String): Path {
32
- let nodePath = Js.import("path")
33
- Path(nodePath->resolve(relativePath)?)
34
- }
35
-
36
- pathFromUrl(url: String): Path {
37
- let nodeUrl = Js.import("url")
38
- Path(nodeUrl->fileURLToPath(Js->URL->(url))?)
39
- }
40
-
41
- httpClient(): HttpClient {
42
- Js.globalThis()?
43
- }
44
-
45
- mainTask(): Task {
46
- self!->"task_"?
47
- }
48
-
49
- crypto(): Crypto {
50
- Js.globalThis()->crypto?
51
- }
52
-
53
- js(): JsSystem {
54
- Js.jsSystem()
55
- }
56
-
57
- exit[T](exitCode: Int = 0): T {
58
- Js->process->exit(exitCode)?
59
- }
60
-
61
- readStream(): Stream[Buffer] {
62
- Path.internalReadStream {Js->process->stdin}
63
- }
64
-
65
- writeBuffer(buffer: Buffer): Unit {
66
- Js->process->stdout->write(Js->Uint8Array->(buffer!->buffer, buffer!->byteOffset, buffer!->byteLength))
67
- }
68
-
69
- writeStream(stream: Stream[Buffer]): Unit {
70
- stream.each {self.writeBuffer(_)}
71
- }
72
-
73
- writeText(text: String): Unit {
74
- self.writeBuffer(text.toBuffer())
75
- }
76
-
77
- writeLine(text: String): Unit {
78
- self.writeText(text + "\n")
79
- }
80
-
81
- writeErrorBuffer(buffer: Buffer): Unit {
82
- Js->process->stderr->write(Js->Uint8Array->(buffer!->buffer, buffer!->byteOffset, buffer!->byteLength))
83
- }
84
-
85
- writeErrorStream(stream: Stream[Buffer]): Unit {
86
- stream.each {self.writeErrorBuffer(_)}
87
- }
88
-
89
- writeErrorText(text: String): Unit {
90
- self.writeErrorBuffer(text.toBuffer())
91
- }
92
-
93
- writeErrorLine(text: String): Unit {
94
- self.writeErrorText(text + "\n")
95
- }
96
-
97
- environment(): Map[String, String] {
98
- mutable result = Map.new()
99
- Js->process->env.each {key =>
100
- result = result.add(key?, Js->process->env.get(key)?)
101
- }
102
- result
103
- }
104
-
105
- execute(
106
- command: String
107
- arguments: List[String]
108
- standardIn: Buffer = Buffer.new(0)
109
- directory: Option[Path] = None
110
- environment: Option[Map[String, String]] = None
111
- maxBuffer: Int = 16777216
112
- killSignal: Int = 9
113
- shell: Bool = False
114
- ): ProcessResult {
115
- let childProcess = Js.import("node:child_process")
116
- let env = environment.map {e =>
117
- let o = Js.object()
118
- e.each {k, v => o.set(k, v)}
119
- o
120
- }.else {Js->process->env}
121
- Js.withSignal {signal => Js.awaitCancellablePromise {resolve, reject, onSettle =>
122
- let newProcess = childProcess->spawn(command, arguments, Js->(
123
- cwd = directory.map {_.absolutePath!}.else {Js.undefined()}
124
- windowsHide = True
125
- signal = signal
126
- killSignal = killSignal
127
- env = env
128
- shell = shell
129
- ))
130
- mutable size = 0
131
- let out = Array.new()
132
- let err = Array.new()
133
- newProcess->stdout->on("data", Js->{data =>
134
- if(size <= maxBuffer) {
135
- size += data->byteLength?
136
- if(size > maxBuffer) {
137
- newProcess->kill(killSignal)
138
- } else {
139
- out.push(data)
140
- }
141
- }
142
- Unit
143
- })
144
- newProcess->stderr->on("data", Js->{data =>
145
- if(size <= maxBuffer) {
146
- size += data->byteLength?
147
- if(size > maxBuffer) {
148
- newProcess->kill(killSignal)
149
- } else {
150
- err.push(data)
151
- }
152
- }
153
- Unit
154
- })
155
- if(standardIn!->byteLength !== 0) {
156
- newProcess->stdin->write(standardIn!)
157
- }
158
- newProcess->stdin->end()
159
- newProcess->on("error", Js->{error =>
160
- if(size > maxBuffer) {
161
- reject(internalProcessError("maxBuffer exceeded"))
162
- } else {
163
- reject(internalProcessError(error->message?))
164
- }
165
- })
166
- newProcess->on("close", Js->{code =>
167
- let o = Js->Buffer->concat(out.drain()!)
168
- let e = Js->Buffer->concat(err.drain()!)
169
- resolve(ProcessResult(
170
- code?
171
- Js->DataView->(o->buffer, o->byteOffset, o->byteLength)?
172
- Js->DataView->(e->buffer, e->byteOffset, e->byteLength)?
173
- ))
174
- })
175
- onSettle {fulfilled =>
176
- if(!fulfilled) {
177
- newProcess->kill(killSignal)
178
- }
179
- }
180
- }}
181
- }
182
-
183
- }
184
-
185
- internalListDirectoryWithoutOpendir(system: NodeSystem, path: Path): List[Path] {
186
- let fsPromises = Js.import("fs/promises")
187
- let nodePath = Js.import("path")
188
- let files = Js.await(fsPromises->readdir(path.absolutePath))
189
- files.grabArray().map {file => Path(nodePath->join(path.absolutePath, file)?)}
190
- }
191
-
192
- internalProcessError(problem: String): Error {
193
- try {
194
- throw(ProcessException(problem))
195
- } catchAny {error =>
196
- error
197
- }
198
- }
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
+ self!->"array_"?
10
+ }
11
+
12
+ assets(): AssetSystem {
13
+ let assetPkgSnapshotPath = self.path("/snapshot/output/assets")
14
+ if(assetPkgSnapshotPath.isDirectory()) {
15
+ // Opendir gives ENOENT: no such file or directory, opendir '/snapshot/output/assets'
16
+ function streams(path: Path): Stream[Pair[String, () => Stream[Buffer]]] {
17
+ internalListDirectoryWithoutOpendir(self, path).toStream().flatMap {file =>
18
+ if(file.isDirectory()) {
19
+ streams(file)
20
+ } else {
21
+ [Pair("/" + file.relativeTo(assetPkgSnapshotPath), {file.readStream()})].toStream()
22
+ }
23
+ }
24
+ }
25
+ AssetSystem(streams(assetPkgSnapshotPath).toMap())
26
+ } else {
27
+ self!->"assets_"?
28
+ }
29
+ }
30
+
31
+ path(relativePath: String): Path {
32
+ let nodePath = Js.import("path")
33
+ Path(nodePath->resolve(relativePath)?)
34
+ }
35
+
36
+ pathFromUrl(url: String): Path {
37
+ let nodeUrl = Js.import("url")
38
+ Path(nodeUrl->fileURLToPath(Js->URL->(url))?)
39
+ }
40
+
41
+ httpClient(): HttpClient {
42
+ Js.globalThis()?
43
+ }
44
+
45
+ mainTask(): Task {
46
+ self!->"task_"?
47
+ }
48
+
49
+ crypto(): Crypto {
50
+ Js.globalThis()->crypto?
51
+ }
52
+
53
+ js(): JsSystem {
54
+ Js.jsSystem()
55
+ }
56
+
57
+ exit[T](exitCode: Int = 0): T {
58
+ Js->process->exit(exitCode)?
59
+ }
60
+
61
+ readStream(): Stream[Buffer] {
62
+ Path.internalReadStream {Js->process->stdin}
63
+ }
64
+
65
+ writeBuffer(buffer: Buffer): Unit {
66
+ Js->process->stdout->write(Js->Uint8Array->(buffer!->buffer, buffer!->byteOffset, buffer!->byteLength))
67
+ }
68
+
69
+ writeStream(stream: Stream[Buffer]): Unit {
70
+ stream.each {self.writeBuffer(_)}
71
+ }
72
+
73
+ writeText(text: String): Unit {
74
+ self.writeBuffer(text.toBuffer())
75
+ }
76
+
77
+ writeLine(text: String): Unit {
78
+ self.writeText(text + "\n")
79
+ }
80
+
81
+ writeErrorBuffer(buffer: Buffer): Unit {
82
+ Js->process->stderr->write(Js->Uint8Array->(buffer!->buffer, buffer!->byteOffset, buffer!->byteLength))
83
+ }
84
+
85
+ writeErrorStream(stream: Stream[Buffer]): Unit {
86
+ stream.each {self.writeErrorBuffer(_)}
87
+ }
88
+
89
+ writeErrorText(text: String): Unit {
90
+ self.writeErrorBuffer(text.toBuffer())
91
+ }
92
+
93
+ writeErrorLine(text: String): Unit {
94
+ self.writeErrorText(text + "\n")
95
+ }
96
+
97
+ environment(): Map[String, String] {
98
+ mutable result = Map.new()
99
+ Js->process->env.each {key =>
100
+ result = result.add(key?, Js->process->env.get(key)?)
101
+ }
102
+ result
103
+ }
104
+
105
+ execute(
106
+ command: String
107
+ arguments: List[String]
108
+ standardIn: Buffer = Buffer.new(0)
109
+ directory: Option[Path] = None
110
+ environment: Option[Map[String, String]] = None
111
+ maxBuffer: Int = 16777216
112
+ killSignal: Int = 9
113
+ shell: Bool = False
114
+ ): ProcessResult {
115
+ let childProcess = Js.import("node:child_process")
116
+ let env = environment.map {e =>
117
+ let o = Js.object()
118
+ e.each {k, v => o.set(k, v)}
119
+ o
120
+ }.else {Js->process->env}
121
+ Js.withSignal {signal => Js.awaitCancellablePromise {resolve, reject, onSettle =>
122
+ let newProcess = childProcess->spawn(command, arguments, Js->(
123
+ cwd = directory.map {_.absolutePath!}.else {Js.undefined()}
124
+ windowsHide = True
125
+ signal = signal
126
+ killSignal = killSignal
127
+ env = env
128
+ shell = shell
129
+ ))
130
+ mutable size = 0
131
+ let out = Array.new()
132
+ let err = Array.new()
133
+ newProcess->stdout->on("data", Js->{data =>
134
+ if(size <= maxBuffer) {
135
+ size += data->byteLength?
136
+ if(size > maxBuffer) {
137
+ newProcess->kill(killSignal)
138
+ } else {
139
+ out.push(data)
140
+ }
141
+ }
142
+ Unit
143
+ })
144
+ newProcess->stderr->on("data", Js->{data =>
145
+ if(size <= maxBuffer) {
146
+ size += data->byteLength?
147
+ if(size > maxBuffer) {
148
+ newProcess->kill(killSignal)
149
+ } else {
150
+ err.push(data)
151
+ }
152
+ }
153
+ Unit
154
+ })
155
+ if(standardIn!->byteLength !== 0) {
156
+ newProcess->stdin->write(standardIn!)
157
+ }
158
+ newProcess->stdin->end()
159
+ newProcess->on("error", Js->{error =>
160
+ if(size > maxBuffer) {
161
+ reject(internalProcessError("maxBuffer exceeded"))
162
+ } else {
163
+ reject(internalProcessError(error->message?))
164
+ }
165
+ })
166
+ newProcess->on("close", Js->{code =>
167
+ let o = Js->Buffer->concat(out.drain()!)
168
+ let e = Js->Buffer->concat(err.drain()!)
169
+ resolve(ProcessResult(
170
+ code?
171
+ Js->DataView->(o->buffer, o->byteOffset, o->byteLength)?
172
+ Js->DataView->(e->buffer, e->byteOffset, e->byteLength)?
173
+ ))
174
+ })
175
+ onSettle {fulfilled =>
176
+ if(!fulfilled) {
177
+ newProcess->kill(killSignal)
178
+ }
179
+ }
180
+ }}
181
+ }
182
+
183
+ }
184
+
185
+ internalListDirectoryWithoutOpendir(system: NodeSystem, path: Path): List[Path] {
186
+ let fsPromises = Js.import("fs/promises")
187
+ let nodePath = Js.import("path")
188
+ let files = Js.await(fsPromises->readdir(path.absolutePath))
189
+ files.grabArray().map {file => Path(nodePath->join(path.absolutePath, file)?)}
190
+ }
191
+
192
+ internalProcessError(problem: String): Error {
193
+ try {
194
+ throw(ProcessException(problem))
195
+ } catchAny {error =>
196
+ error
197
+ }
198
+ }