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
@@ -1,235 +1,235 @@
1
- # JavaScript interop
2
-
3
- Firefly compiles to JavaScript, which enables it to run in the browser.
4
- It uses Node.js as its server side and desktop runtime.
5
-
6
- The JavaScript interop features enable the wrapping of libraries that are written in JavaScript so that they can be used in Firefly.
7
-
8
-
9
- # The JsSystem
10
-
11
- Most JavaScript functionality can be accessed via the `JsSystem` object.
12
-
13
- ```firefly
14
- browserMain(system: BrowserSystem): Unit {
15
- let js = system.js()
16
- js->document->onclick = js->{
17
- js->Notification->requestPermission()->then(js->{
18
- js->Notification->(
19
- "Hi!"
20
- js->(body = "From the Firefly JS FFI")
21
- )
22
- })
23
- }
24
- }
25
- ```
26
-
27
- This is equivalent to the following JavaScript:
28
-
29
- ```js
30
- document.onclick = () =>
31
- Notification.requestPermission().then(() =>
32
- new Notification(
33
- "Hi!",
34
- {body: "From the Firefly JS FFI"}
35
- )
36
- )
37
- ```
38
-
39
- The `->` is shorthand for calling the methods `get`, `set`, `increment`, `decrement`, `object`, `call1`, `new1` and `function1` (substitute 0 to 9 for 1).
40
-
41
- The `js` variable is of the type `JsSystem` and the rest of the expressions return `JsValue`, which represents an arbitrary JavaScript value.
42
-
43
- In addition, the `!` and `?` postfix operators can be used as shorthand for `Js.value(...)` and `Js.fromValue(...)`.
44
-
45
-
46
- # The Js module
47
-
48
- This module provides access to unsafe JavaScript features:
49
-
50
- ```firefly
51
- // Returns a JsSystem.
52
- jsSystem(): JsSystem
53
-
54
- // A static JS import that works anywhere but the browser target.
55
- import(module: String): JsValue
56
-
57
- // A static JS import that works in the browser target.
58
- browserImport(module: String): JsValue
59
-
60
- // A dynamic JS import.
61
- dynamicImport(module: String): JsValue
62
-
63
- // Creates an async JS function. Goes up to 9.
64
- async0[R](body: () => JsValue): JsValue
65
-
66
- // Returns True if the current target is async
67
- inAsync(): Bool
68
-
69
- // Returns True if the current target is browser
70
- inBrowser(): Bool
71
-
72
- // Returns True if the current target is node
73
- inNode(): Bool
74
-
75
- // Returns True if the current target is build
76
- inBuild(): Bool
77
-
78
- // Returns the current task.
79
- currentTask(): Task
80
-
81
- // Throws if the current task is cancelled.
82
- throwIfCancelled(): Unit
83
-
84
- // Returns True if the current task is cancelled.
85
- cancelled(): Bool
86
-
87
- // Returns the AbortController of the current task.
88
- controller(): JsValue {
89
- currentTask().controller
90
- }
91
-
92
- // Sets the AbortController of the current task.
93
- setController(controller: JsValue)
94
-
95
- // Gives access to the AbortSignal of the current task and resets it if needed after use.
96
- withSignal[T](body: JsValue => T): T
97
-
98
- // Awaits a JS promise.
99
- await(promise: JsValue): JsValue
100
-
101
- // Creates a promise and awaits it, while handling cancellation and cleanup. Used like:
102
- // awaitCancellablePromise {resolve, reject, onSettle => ... onSettle {fulfilled => cleanup()} ...}
103
- awaitCancellablePromise[T](body: (T => Unit, Error => Unit, (Bool => Unit) => Unit) => Unit): T
104
-
105
- // Casts a Firefly value to a JS value.
106
- value[T](value: T): JsValue
107
-
108
- // Casts a JS value to a Firefly value.
109
- fromValue[T](value: JsValue): T
110
-
111
- // Throw a JS value (preferably a JS Error).
112
- throw[T](value: JsValue): T
113
-
114
- // JS operators like !
115
- unaryOperator[T1: IsJsValue](operator: String, a1: T1): JsValue
116
-
117
- // JS operators like + - *
118
- binaryOperator[T1: IsJsValue, T2: IsJsValue](operator: String, a1: T1, a2: T2): JsValue
119
-
120
- // JS operators like || && ??
121
- shortCircuitingOperator[T1: IsJsValue, T2: IsJsValue](operator: String, a1: T1, a2: () => T2): JsValue
122
-
123
- // Access a raw JS identifier.
124
- rawIdentifier(operator: String): JsValue
125
-
126
- // Returns the JS globalThis object.
127
- globalThis(): JsValue
128
-
129
- // Gets the value of a JS variable.
130
- get(key: String): JsValue
131
-
132
- // Sets the value of a JS variable.
133
- set[V: IsJsValue](key: String, value: V): Unit
134
-
135
- // Increments the value of a JS variable.
136
- increment[V: IsJsValue](key: String, value: V): Unit
137
-
138
- // Decrements the value of a JS variable.
139
- decrement[V: IsJsValue](key: String, value: V): Unit
140
-
141
- // Calls a JS variable with zero arguments. Goes up to 9.
142
- call0(name: String): JsValue
143
-
144
- // Returns JS null
145
- null(): JsValue
146
-
147
- // Returns JS undefined
148
- undefined(): JsValue
149
-
150
- // Returns JS undefined if None, and casts the value otherwise
151
- orUndefined[T: IsJsValue](value: Option[T]): JsValue
152
-
153
- // Creates an empty JS object
154
- object(): JsValue
155
-
156
- // Same as Js.object()
157
- new0(): JsValue
158
-
159
- // Cast a List to a JsValue
160
- array(values: List[JsValue]): JsValue
161
-
162
- // Cast a Json value to a JsValue
163
- json(value: Json): JsValue
164
-
165
- // A JS function of 0 parameters. Goes up to 9.
166
- function0[R](body: () => R): JsValue
167
- ```
168
-
169
- In the future, it may be possible to provide a whitelist of dependencies that are allowed to use this module.
170
-
171
-
172
- # Emitted JavaScript
173
-
174
- While most Firefly code maps directly to the JavaScript equivalent, there are two notable exceptions:
175
-
176
- * I/O appears to be blocking, but compiles down to JavaScript `async`/`await`.
177
- * Methods are resolved statically in Firefly and become top level functions in JavaScript.
178
-
179
- In addition, pattern matching doesn't have a direct equivalent in JavaScript, and neither does traits.
180
-
181
- Consider the following main function:
182
-
183
- ```firefly
184
- nodeMain(system: NodeSystem) {
185
-
186
- let files = ["a.txt", "b.txt"]
187
-
188
- let contents = files.map {file =>
189
- system.path(file).readText()
190
- }
191
-
192
- let upper = contents.map {content =>
193
- content.upper()
194
- }
195
-
196
- system.writeLine("Result: " + upper.join(""))
197
-
198
- }
199
- ```
200
-
201
- The JavaScript that's emitted looks roughly like this:
202
-
203
- ```js
204
- export async function nodeMain$(system) {
205
-
206
- const files = ["a.txt", "b.txt"]
207
-
208
- const contents = await List_map$(files, async file => {
209
- return await Path_readText$(await NodeSystem_path$(system, file))
210
- })
211
-
212
- const upper = List_map(contents, content => {
213
- return String_upper(content)
214
- })
215
-
216
- NodeSystem_writeLine$("Result: " + String_join(upper, ""))
217
-
218
- }
219
- ```
220
-
221
- In JavaScript, `nodeMain` becomes an `async` function and gets the `$` suffix to distinguish it from a synchronous function.
222
-
223
- The `let` keyword in Firefly corresponds to the `const` keyword in JavaScript, and Firefly list literals become JavaScript array literals.
224
-
225
- The `map` method becomes a top level function, or rather, one `async` top level function named `List_map$` and another synchronous function named `List_map`.
226
- A static analysis is performed to decide which version to call.
227
-
228
- Because the first call to `map` is passed an anonymous function that calls a method on `system`, which is a capability, and the current top level function is asynchronous,
229
- the analysis picks the asynchronous version `List_map$` and uses the `await` keyword.
230
-
231
- The second call to `map` is passed an anonymous function that doesn't involve any other capabilities, the analysis picks the synchronous version `List_map`.
232
-
233
- This static analysis is necessarily conservative, and may occasionally call the asynchronous version of a function where the synchrhonous version would suffice.
234
- When using the VSCode extension, the hover information for a call will note if the call is asynchronous.
235
-
1
+ # JavaScript interop
2
+
3
+ Firefly compiles to JavaScript, which enables it to run in the browser.
4
+ It uses Node.js as its server side and desktop runtime.
5
+
6
+ The JavaScript interop features enable the wrapping of libraries that are written in JavaScript so that they can be used in Firefly.
7
+
8
+
9
+ # The JsSystem
10
+
11
+ Most JavaScript functionality can be accessed via the `JsSystem` object.
12
+
13
+ ```firefly
14
+ browserMain(system: BrowserSystem): Unit {
15
+ let js = system.js()
16
+ js->document->onclick = js->{
17
+ js->Notification->requestPermission()->then(js->{
18
+ js->Notification->(
19
+ "Hi!"
20
+ js->(body = "From the Firefly JS FFI")
21
+ )
22
+ })
23
+ }
24
+ }
25
+ ```
26
+
27
+ This is equivalent to the following JavaScript:
28
+
29
+ ```js
30
+ document.onclick = () =>
31
+ Notification.requestPermission().then(() =>
32
+ new Notification(
33
+ "Hi!",
34
+ {body: "From the Firefly JS FFI"}
35
+ )
36
+ )
37
+ ```
38
+
39
+ The `->` is shorthand for calling the methods `get`, `set`, `increment`, `decrement`, `object`, `call1`, `new1` and `function1` (substitute 0 to 9 for 1).
40
+
41
+ The `js` variable is of the type `JsSystem` and the rest of the expressions return `JsValue`, which represents an arbitrary JavaScript value.
42
+
43
+ In addition, the `!` and `?` postfix operators can be used as shorthand for `Js.value(...)` and `Js.fromValue(...)`.
44
+
45
+
46
+ # The Js module
47
+
48
+ This module provides access to unsafe JavaScript features:
49
+
50
+ ```firefly
51
+ // Returns a JsSystem.
52
+ jsSystem(): JsSystem
53
+
54
+ // A static JS import that works anywhere but the browser target.
55
+ import(module: String): JsValue
56
+
57
+ // A static JS import that works in the browser target.
58
+ browserImport(module: String): JsValue
59
+
60
+ // A dynamic JS import.
61
+ dynamicImport(module: String): JsValue
62
+
63
+ // Creates an async JS function. Goes up to 9.
64
+ async0[R](body: () => JsValue): JsValue
65
+
66
+ // Returns True if the current target is async
67
+ inAsync(): Bool
68
+
69
+ // Returns True if the current target is browser
70
+ inBrowser(): Bool
71
+
72
+ // Returns True if the current target is node
73
+ inNode(): Bool
74
+
75
+ // Returns True if the current target is build
76
+ inBuild(): Bool
77
+
78
+ // Returns the current task.
79
+ currentTask(): Task
80
+
81
+ // Throws if the current task is cancelled.
82
+ throwIfCancelled(): Unit
83
+
84
+ // Returns True if the current task is cancelled.
85
+ cancelled(): Bool
86
+
87
+ // Returns the AbortController of the current task.
88
+ controller(): JsValue {
89
+ currentTask().controller
90
+ }
91
+
92
+ // Sets the AbortController of the current task.
93
+ setController(controller: JsValue)
94
+
95
+ // Gives access to the AbortSignal of the current task and resets it if needed after use.
96
+ withSignal[T](body: JsValue => T): T
97
+
98
+ // Awaits a JS promise.
99
+ await(promise: JsValue): JsValue
100
+
101
+ // Creates a promise and awaits it, while handling cancellation and cleanup. Used like:
102
+ // awaitCancellablePromise {resolve, reject, onSettle => ... onSettle {fulfilled => cleanup()} ...}
103
+ awaitCancellablePromise[T](body: (T => Unit, Error => Unit, (Bool => Unit) => Unit) => Unit): T
104
+
105
+ // Casts a Firefly value to a JS value.
106
+ value[T](value: T): JsValue
107
+
108
+ // Casts a JS value to a Firefly value.
109
+ fromValue[T](value: JsValue): T
110
+
111
+ // Throw a JS value (preferably a JS Error).
112
+ throw[T](value: JsValue): T
113
+
114
+ // JS operators like !
115
+ unaryOperator[T1: IsJsValue](operator: String, a1: T1): JsValue
116
+
117
+ // JS operators like + - *
118
+ binaryOperator[T1: IsJsValue, T2: IsJsValue](operator: String, a1: T1, a2: T2): JsValue
119
+
120
+ // JS operators like || && ??
121
+ shortCircuitingOperator[T1: IsJsValue, T2: IsJsValue](operator: String, a1: T1, a2: () => T2): JsValue
122
+
123
+ // Access a raw JS identifier.
124
+ rawIdentifier(operator: String): JsValue
125
+
126
+ // Returns the JS globalThis object.
127
+ globalThis(): JsValue
128
+
129
+ // Gets the value of a JS variable.
130
+ get(key: String): JsValue
131
+
132
+ // Sets the value of a JS variable.
133
+ set[V: IsJsValue](key: String, value: V): Unit
134
+
135
+ // Increments the value of a JS variable.
136
+ increment[V: IsJsValue](key: String, value: V): Unit
137
+
138
+ // Decrements the value of a JS variable.
139
+ decrement[V: IsJsValue](key: String, value: V): Unit
140
+
141
+ // Calls a JS variable with zero arguments. Goes up to 9.
142
+ call0(name: String): JsValue
143
+
144
+ // Returns JS null
145
+ null(): JsValue
146
+
147
+ // Returns JS undefined
148
+ undefined(): JsValue
149
+
150
+ // Returns JS undefined if None, and casts the value otherwise
151
+ orUndefined[T: IsJsValue](value: Option[T]): JsValue
152
+
153
+ // Creates an empty JS object
154
+ object(): JsValue
155
+
156
+ // Same as Js.object()
157
+ new0(): JsValue
158
+
159
+ // Cast a List to a JsValue
160
+ array(values: List[JsValue]): JsValue
161
+
162
+ // Cast a Json value to a JsValue
163
+ json(value: Json): JsValue
164
+
165
+ // A JS function of 0 parameters. Goes up to 9.
166
+ function0[R](body: () => R): JsValue
167
+ ```
168
+
169
+ In the future, it may be possible to provide a whitelist of dependencies that are allowed to use this module.
170
+
171
+
172
+ # Emitted JavaScript
173
+
174
+ While most Firefly code maps directly to the JavaScript equivalent, there are two notable exceptions:
175
+
176
+ * I/O appears to be blocking, but compiles down to JavaScript `async`/`await`.
177
+ * Methods are resolved statically in Firefly and become top level functions in JavaScript.
178
+
179
+ In addition, pattern matching doesn't have a direct equivalent in JavaScript, and neither does traits.
180
+
181
+ Consider the following main function:
182
+
183
+ ```firefly
184
+ nodeMain(system: NodeSystem) {
185
+
186
+ let files = ["a.txt", "b.txt"]
187
+
188
+ let contents = files.map {file =>
189
+ system.path(file).readText()
190
+ }
191
+
192
+ let upper = contents.map {content =>
193
+ content.upper()
194
+ }
195
+
196
+ system.writeLine("Result: " + upper.join(""))
197
+
198
+ }
199
+ ```
200
+
201
+ The JavaScript that's emitted looks roughly like this:
202
+
203
+ ```js
204
+ export async function nodeMain$(system) {
205
+
206
+ const files = ["a.txt", "b.txt"]
207
+
208
+ const contents = await List_map$(files, async file => {
209
+ return await Path_readText$(await NodeSystem_path$(system, file))
210
+ })
211
+
212
+ const upper = List_map(contents, content => {
213
+ return String_upper(content)
214
+ })
215
+
216
+ NodeSystem_writeLine$("Result: " + String_join(upper, ""))
217
+
218
+ }
219
+ ```
220
+
221
+ In JavaScript, `nodeMain` becomes an `async` function and gets the `$` suffix to distinguish it from a synchronous function.
222
+
223
+ The `let` keyword in Firefly corresponds to the `const` keyword in JavaScript, and Firefly list literals become JavaScript array literals.
224
+
225
+ The `map` method becomes a top level function, or rather, one `async` top level function named `List_map$` and another synchronous function named `List_map`.
226
+ A static analysis is performed to decide which version to call.
227
+
228
+ Because the first call to `map` is passed an anonymous function that calls a method on `system`, which is a capability, and the current top level function is asynchronous,
229
+ the analysis picks the asynchronous version `List_map$` and uses the `await` keyword.
230
+
231
+ The second call to `map` is passed an anonymous function that doesn't involve any other capabilities, the analysis picks the synchronous version `List_map`.
232
+
233
+ This static analysis is necessarily conservative, and may occasionally call the asynchronous version of a function where the synchrhonous version would suffice.
234
+ When using the VSCode extension, the hover information for a call will note if the call is asynchronous.
235
+