firefly-compiler 0.5.49 → 0.5.51

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 (132) hide show
  1. package/bin/Release.ff +3 -3
  2. package/bin/firefly.mjs +1 -1
  3. package/compiler/Builder.ff +11 -5
  4. package/compiler/Compiler.ff +14 -3
  5. package/compiler/JsEmitter.ff +6 -11
  6. package/compiler/Main.ff +10 -15
  7. package/compiler/ModuleCache.ff +2 -1
  8. package/core/Buffer.ff +26 -4
  9. package/core/BuildSystem.ff +49 -46
  10. package/core/JsValue.ff +5 -0
  11. package/experimental/date/Date.ff +604 -0
  12. package/experimental/date/Main.ff +51 -0
  13. package/experimental/random/AsciiBuffer.ff +15 -0
  14. package/experimental/rhymeapp/Main.ff +2 -3
  15. package/experimental/site/Main.ff +2 -2
  16. package/experimental/site2/Main.ff +2 -2
  17. package/firefly.sh +1 -1
  18. package/fireflysite/CommunityOverview.ff +3 -3
  19. package/fireflysite/CountingButtonDemo.ff +3 -3
  20. package/fireflysite/ExamplesOverview.ff +3 -12
  21. package/fireflysite/FrontPage.ff +3 -3
  22. package/fireflysite/GettingStarted.ff +3 -3
  23. package/fireflysite/Guide.ff +7 -187
  24. package/fireflysite/Html.ff +66 -0
  25. package/fireflysite/Main.ff +13 -77
  26. package/fireflysite/MatchingPasswordsDemo.ff +3 -3
  27. package/fireflysite/Menu.ff +59 -0
  28. package/fireflysite/PackagesOverview.ff +3 -3
  29. package/fireflysite/PostgresqlDemo.ff +3 -3
  30. package/fireflysite/RouteFront.ff +30 -0
  31. package/fireflysite/RouteNonMarkdown.ff +48 -0
  32. package/fireflysite/RouteReference.ff +40 -0
  33. package/fireflysite/Router.ff +33 -0
  34. package/fireflysite/Website.ff +133 -0
  35. package/fireflysite/assets/markdown/reference/{FunctionsAndMethods.md → functions-and-methods.md} +1 -1
  36. package/fireflysite/assets/markdown/reference/{StatementsAndExpressions.md → statements-and-expressions.md} +0 -1
  37. package/fireflysite/assets/markdown/reference/{StructuredConcurrency.md → structured-concurrency.md} +0 -1
  38. package/fireflysite/assets/markdown/reference.md +3 -0
  39. package/graph/.firefly/package.ff +1 -0
  40. package/graph/Graph.ff +79 -0
  41. package/lsp/CompletionHandler.ff +2 -2
  42. package/lux/CssTest.ff +2 -2
  43. package/lux/Main.ff +2 -2
  44. package/lux/Main2.ff +2 -2
  45. package/output/js/ff/compiler/Builder.mjs +44 -12
  46. package/output/js/ff/compiler/Compiler.mjs +28 -10
  47. package/output/js/ff/compiler/Dependencies.mjs +0 -2
  48. package/output/js/ff/compiler/DependencyLock.mjs +0 -2
  49. package/output/js/ff/compiler/Deriver.mjs +0 -2
  50. package/output/js/ff/compiler/Dictionaries.mjs +0 -2
  51. package/output/js/ff/compiler/Environment.mjs +0 -2
  52. package/output/js/ff/compiler/Inference.mjs +0 -2
  53. package/output/js/ff/compiler/JsEmitter.mjs +12 -30
  54. package/output/js/ff/compiler/JsImporter.mjs +0 -2
  55. package/output/js/ff/compiler/LspHook.mjs +0 -2
  56. package/output/js/ff/compiler/Main.mjs +24 -47
  57. package/output/js/ff/compiler/Main.run.mjs +25 -0
  58. package/output/js/ff/compiler/ModuleCache.mjs +4 -6
  59. package/output/js/ff/compiler/Parser.mjs +0 -2
  60. package/output/js/ff/compiler/Patterns.mjs +0 -2
  61. package/output/js/ff/compiler/Resolver.mjs +0 -2
  62. package/output/js/ff/compiler/Substitution.mjs +0 -2
  63. package/output/js/ff/compiler/Syntax.mjs +0 -2
  64. package/output/js/ff/compiler/Token.mjs +0 -2
  65. package/output/js/ff/compiler/Tokenizer.mjs +0 -2
  66. package/output/js/ff/compiler/Unification.mjs +0 -2
  67. package/output/js/ff/compiler/Wildcards.mjs +0 -2
  68. package/output/js/ff/compiler/Workspace.mjs +0 -2
  69. package/output/js/ff/core/Any.mjs +0 -2
  70. package/output/js/ff/core/Array.mjs +0 -2
  71. package/output/js/ff/core/AssetSystem.mjs +0 -2
  72. package/output/js/ff/core/Atomic.mjs +0 -2
  73. package/output/js/ff/core/Bool.mjs +0 -2
  74. package/output/js/ff/core/BrowserSystem.mjs +0 -2
  75. package/output/js/ff/core/Buffer.mjs +50 -10
  76. package/output/js/ff/core/BuildSystem.mjs +92 -72
  77. package/output/js/ff/core/Channel.mjs +0 -2
  78. package/output/js/ff/core/Char.mjs +0 -2
  79. package/output/js/ff/core/Core.mjs +0 -2
  80. package/output/js/ff/core/Crypto.mjs +0 -2
  81. package/output/js/ff/core/Date.mjs +0 -2
  82. package/output/js/ff/core/Duration.mjs +0 -2
  83. package/output/js/ff/core/Equal.mjs +0 -2
  84. package/output/js/ff/core/Error.mjs +0 -2
  85. package/output/js/ff/core/FileHandle.mjs +0 -2
  86. package/output/js/ff/core/Float.mjs +0 -2
  87. package/output/js/ff/core/HttpClient.mjs +0 -2
  88. package/output/js/ff/core/Int.mjs +0 -2
  89. package/output/js/ff/core/IntMap.mjs +0 -2
  90. package/output/js/ff/core/Js.mjs +0 -2
  91. package/output/js/ff/core/JsSystem.mjs +0 -2
  92. package/output/js/ff/core/JsValue.mjs +8 -2
  93. package/output/js/ff/core/Json.mjs +0 -2
  94. package/output/js/ff/core/List.mjs +0 -2
  95. package/output/js/ff/core/Lock.mjs +0 -2
  96. package/output/js/ff/core/Log.mjs +0 -2
  97. package/output/js/ff/core/Map.mjs +0 -2
  98. package/output/js/ff/core/NodeSystem.mjs +0 -2
  99. package/output/js/ff/core/Nothing.mjs +0 -2
  100. package/output/js/ff/core/Option.mjs +0 -2
  101. package/output/js/ff/core/Ordering.mjs +0 -2
  102. package/output/js/ff/core/Pair.mjs +0 -2
  103. package/output/js/ff/core/Path.mjs +0 -2
  104. package/output/js/ff/core/Queue.mjs +0 -2
  105. package/output/js/ff/core/Random.mjs +0 -2
  106. package/output/js/ff/core/RbMap.mjs +0 -2
  107. package/output/js/ff/core/Serializable.mjs +0 -2
  108. package/output/js/ff/core/Set.mjs +0 -2
  109. package/output/js/ff/core/Show.mjs +0 -2
  110. package/output/js/ff/core/SourceLocation.mjs +0 -2
  111. package/output/js/ff/core/Stream.mjs +0 -2
  112. package/output/js/ff/core/String.mjs +0 -2
  113. package/output/js/ff/core/StringMap.mjs +0 -2
  114. package/output/js/ff/core/Task.mjs +0 -2
  115. package/output/js/ff/core/Try.mjs +0 -2
  116. package/output/js/ff/core/Unit.mjs +0 -2
  117. package/package.json +1 -1
  118. package/vscode/client/src/extension.ts +1 -1
  119. package/vscode/package.json +1 -1
  120. package/vscode/snippets.json +2 -2
  121. package/webserver/WebRoute.ff +51 -14
  122. package/fireflysite/ReferenceAll.ff +0 -18
  123. /package/fireflysite/assets/markdown/reference/{BaseTypes.md → base-types.md} +0 -0
  124. /package/fireflysite/assets/markdown/reference/{EmittedJavascript.md → emitted-javascript.md} +0 -0
  125. /package/fireflysite/assets/markdown/reference/{Exceptions.md → exceptions.md} +0 -0
  126. /package/fireflysite/assets/markdown/reference/{JavascriptInterop.md → javascript-interop.md} +0 -0
  127. /package/fireflysite/assets/markdown/reference/{ModulesAndPackages.md → modules-and-packages.md} +0 -0
  128. /package/fireflysite/assets/markdown/reference/{PatternMatching.md → pattern-matching.md} +0 -0
  129. /package/fireflysite/assets/markdown/reference/{TraitsAndInstances.md → traits-and-instances.md} +0 -0
  130. /package/fireflysite/assets/markdown/reference/{UserDefinedTypes.md → user-defined-types.md} +0 -0
  131. /package/fireflysite/assets/markdown/scratch/{ControlFlow.md → control-flow.md} +0 -0
  132. /package/fireflysite/assets/markdown/{reference/OldStructuredConcurrency.md → scratch/old-structured-concurrency.md} +0 -0
package/bin/Release.ff CHANGED
@@ -22,9 +22,9 @@ release(
22
22
  }
23
23
  requireNpmLoggedIn(system, system.path(".."))
24
24
  requireVsceLoggedIn(system, system.path("../vscode"))
25
- runSuccessful(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
26
- runSuccessful(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
27
- runSuccessful(system, "node", ["output/js/ff/compiler/Main.mjs", "bootstrap"], system.path(".."))
25
+ runSuccessful(system, "node", ["output/js/ff/compiler/Main.run.mjs", "bootstrap"], system.path(".."))
26
+ runSuccessful(system, "node", ["output/js/ff/compiler/Main.run.mjs", "bootstrap"], system.path(".."))
27
+ runSuccessful(system, "node", ["output/js/ff/compiler/Main.run.mjs", "bootstrap"], system.path(".."))
28
28
  let version = bumpMinorVersion(system, system.path("../package.json"))
29
29
  bumpMinorVersion(system, system.path("../vscode/package.json"))
30
30
  runSuccessful(system, "npm", ["publish"], system.path(".."))
package/bin/firefly.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node --harmony-temporal
2
- import * as firefly from '../output/js/ff/compiler/Main.mjs';
2
+ import * as firefly from '../output/js/ff/compiler/Main.run.mjs';
@@ -14,7 +14,7 @@ build(
14
14
  system: NodeSystem
15
15
  emitTarget: EmitTarget
16
16
  mainPackage: PackagePair
17
- mainModule: String
17
+ mainModules: List[String]
18
18
  resolvedDependencies: ResolvedDependencies
19
19
  compilerModulePath: Option[Path]
20
20
  tempPath: Path
@@ -40,7 +40,9 @@ build(
40
40
  moduleCache
41
41
  lspHook = LspHook.disabled()
42
42
  )
43
- compiler.emit(mainPackage, mainModule, isMainModule = True)
43
+ mainModules.each {mainModule =>
44
+ compiler.emit(mainPackage, mainModule, isMainModule = True)
45
+ }
44
46
  if(printMeasurements) {compiler.printMeasurements()}
45
47
  resolvedDependencies.packagePaths.each {packagePair, packagePath =>
46
48
  resolvedDependencies.packages.get(packagePair).each {packageInfo =>
@@ -85,11 +87,15 @@ processNodeModules(system: NodeSystem, jsPathFile: Path, packagePath: Path, info
85
87
  }
86
88
  }
87
89
 
88
- buildViaBuildSystem(system: NodeSystem, fireflyPath: Path, mainFile: String, target: String) {
90
+ buildViaBuildSystem(system: NodeSystem, fireflyPath: Path, mainFiles: List[String], target: String) {
91
+ let mainPaths = mainFiles.map {system.path(_).parent().grab().absolute()}
92
+ mainPaths.find {_ != mainPaths.grabFirst()}.each {path =>
93
+ panic("Can't build multiple main files in different directories: " + path + " vs. " + mainPaths.grabFirst())
94
+ }
89
95
  let resolvedDependencies = Dependencies.process(
90
96
  system.httpClient()
91
97
  DependencyLock.new(system.mainTask())
92
- system.path(mainFile)
98
+ system.path(mainFiles.grabFirst())
93
99
  )
94
100
  let fixedPackagePaths = if(resolvedDependencies.packagePaths.contains(PackagePair("ff", "core"))) {
95
101
  resolvedDependencies.packagePaths
@@ -103,7 +109,7 @@ buildViaBuildSystem(system: NodeSystem, fireflyPath: Path, mainFile: String, tar
103
109
  system = system
104
110
  emitTarget = EmitBrowser
105
111
  mainPackage = resolvedDependencies.mainPackagePair
106
- mainModule = mainFile.dropLast(".ff".size())
112
+ mainModules = mainFiles.map {_.dropLast(".ff".size())}
107
113
  resolvedDependencies = resolvedDependencies.ResolvedDependencies(packagePaths = fixedPackagePaths)
108
114
  compilerModulePath = None
109
115
  tempPath = system.path(".firefly/temporary")
@@ -209,7 +209,7 @@ extend self: Compiler {
209
209
  }
210
210
 
211
211
  emit(packagePair: PackagePair, moduleName: String, isMainModule: Bool): Unit {
212
- self.cache.cacheEmittedModule(self.packagePaths, packagePair, moduleName): path =>
212
+ self.cache.cacheEmittedModule(self.packagePaths, packagePair, moduleName, isMainModule): path =>
213
213
  self.measure("Emit", packagePair, moduleName):
214
214
 
215
215
  let module = self.infer(packagePair, moduleName)
@@ -220,18 +220,29 @@ extend self: Compiler {
220
220
  }
221
221
 
222
222
  let allModules = [module, ...otherModules]
223
- let js = JsEmitter.new(
223
+ let emitter = JsEmitter.new(
224
224
  otherModules = allModules
225
225
  emitTarget = self.emitTarget
226
226
  isMainModule = isMainModule
227
227
  compilerModuleFileUrl = self.compilerModulePath.map {_.url()}
228
228
  packagePair = packagePair
229
229
  moduleName = moduleName
230
- ).emitModule(packagePair, module)
230
+ )
231
+ let js = emitter.emitModule(packagePair, module)
231
232
  let jsPath = self.jsOutputPath.slash(packagePair.group).slash(packagePair.name)
232
233
  let jsFile = jsPath.slash(moduleName + ".mjs")
233
234
  jsPath.createDirectory(createParentDirectories = True)
234
235
  jsFile.writeText(js)
236
+ if(isMainModule) {
237
+ let runJs = emitter.emitRun(
238
+ moduleName
239
+ module.functions
240
+ packagePair
241
+ packagePair.group == "ff" && packagePair.name == "compiler"
242
+ )
243
+ let jsRunFile = jsPath.slash(moduleName + ".run.mjs")
244
+ jsRunFile.writeText(runJs.map {_ + "\n"}.join())
245
+ }
235
246
  }
236
247
 
237
248
  }
@@ -67,9 +67,6 @@ extend self: JsEmitter {
67
67
  self.withEmittingAsync {module.functions.map {"export " + self.emitFunctionDefinition(_, True)}}
68
68
  module.extends.map {self.emitExtendsDefinition(_)}
69
69
  module.instances.map {self.emitInstanceDefinition(_)}
70
- if(self.isMainModule) {
71
- self.emitRun(module.functions, packagePair, packagePair.group == "ff" && packagePair.name == "compiler")
72
- } else {[]}
73
70
  ]
74
71
  let ignoreJsImports = if(
75
72
  self.emitTarget == EmitExecutable &&
@@ -89,7 +86,7 @@ extend self: JsEmitter {
89
86
  }
90
87
  }
91
88
 
92
- emitRun(functions: List[DFunction], mainPackagePair: PackagePair, bootstrapping: Bool): List[String] {
89
+ emitRun(moduleName: String, functions: List[DFunction], mainPackagePair: PackagePair, bootstrapping: Bool): List[String] {
93
90
  let buildMainFunction = functions.find {_.signature.name == "buildMain"}.filter {_ =>
94
91
  self.emitTarget != EmitBrowser && self.emitTarget != EmitExecutable
95
92
  }
@@ -98,6 +95,10 @@ extend self: JsEmitter {
98
95
  let mainFunction =
99
96
  functions.find {_.signature.name == targetMain}.orElse {functions.find {_.signature.name == "main"}}
100
97
  mainFunction.map {_.signature.name}.map {mainName => [[
98
+ ...buildMainFunction.map {buildMain =>
99
+ "import {" + escapeKeyword(buildMain.signature.name) + "$} from './" + moduleName + ".mjs'"
100
+ }.toList()
101
+ "import {" + escapeKeyword(mainName) + "$} from './" + moduleName + ".mjs'"
101
102
  "export async function $run$(fireflyPath_, arguments_) {"
102
103
  "Error.stackTraceLimit = 50"
103
104
  "const $task = {controller_: new AbortController(), subtasks_: new Set(), promise_: new Promise(() => {}), started_: performance.now() * 0.001}"
@@ -124,7 +125,7 @@ extend self: JsEmitter {
124
125
  ]} else {[]}
125
126
  "} finally {"
126
127
  ...if(self.emitTarget != EmitBrowser) {[
127
- "ff_core_Task.Task_abort$($task)"
128
+ "$task.controller_.abort()"
128
129
  "clearInterval(interval)"
129
130
  ]} else {[]}
130
131
  "}"
@@ -365,12 +366,6 @@ extend self: JsEmitter {
365
366
  let call = d + "." + n + "(" + [...emittedArguments, ...ds, ...controller].join(", ") + ")"
366
367
  if(await) {"(await " + call + ")"} else {call}
367
368
  | ECall(at, StaticCall(name, _, _), effect, typeArguments, arguments, dictionaries) =>
368
- if(name.contains("bundleForBrowser")) { // TODO: Delete this test (for branch arraysonly)
369
- if(!arguments.grab(0).name.contains("system")) {
370
- Log.debug("Wrong arguments for bundleForBrowser: " + Show.show(arguments.map {_.name}))
371
- throw(GrabException())
372
- }
373
- }
374
369
  detectIfElse(term).{
375
370
  | [] =>
376
371
  let await = async && effectTypeIsAsync(effect)
package/compiler/Main.ff CHANGED
@@ -51,7 +51,7 @@ main(system: NodeSystem): Unit {
51
51
  system = system
52
52
  emitTarget = emitTarget
53
53
  mainPackage = mainPackagePair
54
- mainModule = mainFile
54
+ mainModules = [mainFile]
55
55
  resolvedDependencies = resolvedDependencies.ResolvedDependencies(packagePaths = fixedPackagePaths)
56
56
  compilerModulePath = compilerModulePath
57
57
  tempPath = system.path(".firefly").slash("temporary")
@@ -71,7 +71,7 @@ main(system: NodeSystem): Unit {
71
71
  prepareFireflyDirectory(system.path("."))
72
72
  let localMainFile = system.path(mainFile).base()
73
73
  buildScript(localMainFile, resolvedDependencies.mainPackagePair, EmitNode, resolvedDependencies)
74
- if(!importAndRun(fireflyPath, "node", resolvedDependencies.mainPackagePair, localMainFile, arguments)) {
74
+ if(!importAndRun(system, fireflyPath, "node", resolvedDependencies.mainPackagePair, localMainFile, arguments)) {
75
75
  let at = Location(system.path(mainFile + ".ff").absolute(), 1, 1)
76
76
  throw(CompileError(at, "This module does not contain a 'nodeMain' function"))
77
77
  }
@@ -98,7 +98,7 @@ main(system: NodeSystem): Unit {
98
98
  buildScript(localMainFile, resolvedDependencies.mainPackagePair, EmitBuild, resolvedDependencies)
99
99
  buildScript(localMainFile, resolvedDependencies.mainPackagePair, EmitExecutable, resolvedDependencies)
100
100
  bundleForPkg(system, resolvedDependencies.mainPackagePair, localMainFile)
101
- importAndRun(fireflyPath, "build", resolvedDependencies.mainPackagePair, localMainFile, [])
101
+ importAndRun(system, fireflyPath, "build", resolvedDependencies.mainPackagePair, localMainFile, [])
102
102
 
103
103
  | CheckCommand(filePath) =>
104
104
  let errors = Builder.check(
@@ -124,7 +124,7 @@ main(system: NodeSystem): Unit {
124
124
  system = system
125
125
  emitTarget = EmitNode
126
126
  mainPackage = PackagePair("ff", "compiler")
127
- mainModule = "Main"
127
+ mainModules = ["Main"]
128
128
  resolvedDependencies = ResolvedDependencies(
129
129
  mainPackagePair = PackagePair("ff", "compiler")
130
130
  packages = [Pair(
@@ -259,16 +259,11 @@ bundleForBrowser(system: NodeSystem, packagePair: PackagePair, mainFile: String)
259
259
  let prefix = ".firefly/output/browser/"
260
260
  let mainJsFile = prefix + packagePair.groupName("/") + "/" + mainFile + ".mjs"
261
261
  let file = prefix + "Main.bundle.js"
262
- let browserCode = BrowserCode(
263
- packageGroup = packagePair.group
264
- packageName = packagePair.name
265
- mainFile = system.path(mainFile)
266
- assetSystem = AssetSystem([Pair("/", {system.path(".").readStream()})].toMap())
267
- ) // TODO
268
- BuildSystem.internalCallEsBuild(browserCode, mainJsFile, outputPath = file, minify = True, sourceMap = True)
262
+ BuildSystem.internalCallEsBuild(system, mainJsFile, outputPath = file, minify = True, sourceMap = True)
269
263
  }
270
264
 
271
265
  importAndRun(
266
+ system: NodeSystem
272
267
  fireflyPath: Path
273
268
  target: String
274
269
  packagePair: PackagePair
@@ -279,10 +274,10 @@ importAndRun(
279
274
  let cwd = process->cwd()
280
275
  let workingDirectory = if(cwd->indexOf(":") === 1) {"file:///" + cwd?} else {cwd?}
281
276
  let packagePath = packagePair.group + "/" + packagePair.name
282
- let main = Js.await(Js.dynamicImport(
283
- workingDirectory + "/.firefly/output/" + target + "/" + packagePath + "/" + mainFile + ".mjs"
284
- ))
285
- if(main->"$run$".typeof() != "undefined") {
277
+ let runFile = workingDirectory + "/.firefly/output/" + target + "/" + packagePath + "/" + mainFile + ".run.mjs"
278
+ let runFilePath = if(runFile.contains("://")) {system.pathFromUrl(runFile)} else {system.path(runFile)}
279
+ if(runFilePath.exists()) {
280
+ let main = Js.await(Js.dynamicImport(runFile))
286
281
  main->"$run$"(fireflyPath.absolutePath, arguments)
287
282
  True
288
283
  } else {
@@ -140,10 +140,11 @@ extend self: ModuleCache {
140
140
  packagePaths: Map[PackagePair, Path]
141
141
  packagePair: PackagePair
142
142
  moduleName: String
143
+ isMainModule: Bool
143
144
  body: Path => Unit
144
145
  ): Unit {
145
146
  let path = modulePath(packagePaths, packagePair, moduleName)
146
- if(!self.emittedModules.contains(path.absolute())):
147
+ if(isMainModule || !self.emittedModules.contains(path.absolute())):
147
148
  self.emittedModules = self.emittedModules.add(path.absolute(), self.version)
148
149
  try {
149
150
  body(path)
package/core/Buffer.ff CHANGED
@@ -144,7 +144,7 @@ extend self: Buffer {
144
144
  Js->TextDecoder->()->decode(self!)?
145
145
  }
146
146
 
147
- toByteArray(): List[Int] {
147
+ toByteList(): List[Int] {
148
148
  Js->Uint8Array->(self!->buffer, self!->byteOffset, self!->byteLength).spreadToArray()!?
149
149
  }
150
150
 
@@ -158,14 +158,26 @@ extend self: Buffer {
158
158
 
159
159
  toBase64(): String {
160
160
  let view = Js->Uint8Array->(self!->buffer, self!->byteOffset, self!->byteLength)
161
- let binaryString = Js->TextDecoder->("latin1")->decode(view)
161
+ //let binaryString = Js->TextDecoder->("latin1")->decode(view)
162
+ let binaryString = Js->Array->from(view, Js->{byte => Js->String->fromCodePoint(byte)})->join("");
162
163
  Js->btoa(binaryString)?
163
164
  }
165
+
166
+ toLetter16(): String {
167
+ let result = Buffer.new(self.size().bitLeft(1))
168
+ 0.until(self.size()).each {i =>
169
+ let b = self.grabUint8(i)
170
+ result.setUint16(i.bitLeft(1), (b.bitRightUnsigned(4).bitAnd(0xf) + 0x68).bitOr(
171
+ (b.bitAnd(0xf) + 0x68).bitLeft(8)
172
+ ), littleEndian = True)
173
+ }
174
+ result.toString()
175
+ }
164
176
 
165
177
  }
166
178
 
167
179
  fromByteList(array: List[Int]): Buffer {
168
- Js->DataView->(Js->Uint8Array(array)->buffer)?
180
+ Js->DataView->(Js->Uint8Array->(array)->buffer)?
169
181
  }
170
182
 
171
183
  fromBufferList(array: List[Buffer]): Buffer {
@@ -193,10 +205,20 @@ fromHex(hex: String): Buffer {
193
205
 
194
206
  fromBase64(base64: String): Buffer {
195
207
  let binaryString = Js->atob(base64)
196
- let bytes = Js->Uint8Array->from(binaryString, Js->{char => char->charCodeAt(0)})
208
+ let bytes = Js->Uint8Array->from(binaryString, Js->{char => char->codePointAt(0)})
197
209
  Js->DataView->(bytes->buffer)?
198
210
  }
199
211
 
212
+ fromLetter16(letters: String): Buffer {
213
+ let buffer = Buffer.new(letters.size().bitRightUnsigned(1))
214
+ 0.until(buffer.size()).each {i =>
215
+ buffer.setUint8(i, (letters.grab(i.bitLeft(1)).codeUnit.bitAnd(0x1f) - 0x8).bitLeft(4).bitOr(
216
+ letters.grab(i.bitLeft(1).bitOr(1)).codeUnit.bitAnd(0x1f) - 0x8
217
+ ))
218
+ }
219
+ buffer
220
+ }
221
+
200
222
  instance Buffer: Show {
201
223
  show(value: Buffer): String {
202
224
  """Buffer.fromHex("""" + value.toHex() + """")"""
@@ -1,20 +1,25 @@
1
1
  capability BuildSystem {}
2
- capability BrowserCode(packageGroup: String, packageName: String, mainFile: Path, assetSystem: AssetSystem)
3
- capability BrowserBundle(assetSystem: AssetSystem)
4
2
 
5
3
  extend self: BuildSystem {
6
4
 
7
- compileForBrowser(mainFile: String): BrowserCode {
5
+ compileForBrowser(mainFiles: List[String]): AssetSystem {
8
6
  // TODO: Check that the mainFile is in the current package directory
9
- internalCompile(self, internalPath(self, mainFile), "browser")
7
+ internalCompile(self, mainFiles.map {internalPath(self, _)}, "browser")
10
8
  let streams = internalListDirectory(internalPath(self, ".firefly/output/browser"))
11
9
  let mainPackagePair = internalMainPackagePair(self)
12
- BrowserCode(
13
- packageGroup = mainPackagePair.first
14
- packageName = mainPackagePair.second
15
- mainFile = internalPath(self, mainFile)
16
- assetSystem = AssetSystem(streams.toMap())
17
- )
10
+ AssetSystem(streams.toMap())
11
+ }
12
+
13
+ bundleForBrowser(mainFiles: List[String], minify: Bool = True, sourceMaps: Bool = False): AssetSystem {
14
+ internalCompile(self, mainFiles.map {internalPath(self, _)}, "browser")
15
+ let browserOutputPath = internalPath(self, ".firefly/output/browser")
16
+ let runPaths = internalListPath(browserOutputPath).filter {_.base().endsWith(".run.mjs")}.toList()
17
+ let outputPath = runPaths.grabFirst().parent().grab()
18
+ internalBrowserCallEsBuild(self, runPaths.map {_.absolute()}, outputPath.absolute(), minify, sourceMaps)
19
+ let bundlePaths = internalListPath(browserOutputPath).filter {_.base().endsWith(".bundle.js")}.toList()
20
+ AssetSystem(bundlePaths.map {p =>
21
+ Pair("/" + p.relativeTo(browserOutputPath).replace("\\", "/"), {p.readStream()})
22
+ }.toMap())
18
23
  }
19
24
 
20
25
  buildMode(): Bool {
@@ -48,41 +53,9 @@ extend self: BuildSystem {
48
53
 
49
54
  }
50
55
 
51
- extend self: BrowserCode {
52
-
53
- assets(): AssetSystem {
54
- self.assetSystem
55
- }
56
-
57
- bundle(minify: Bool = True, sourceMap: Bool = False): BrowserBundle {
58
- let prefix = ".firefly/output/browser"
59
- let mainJsBaseFile = self.mainFile.base().removeLast(".ff").grab() + ".mjs"
60
- let mainJsFile = prefix + "/" + self.packageGroup + "/" + self.packageName + "/" + mainJsBaseFile
61
- let mainDirectory = self.mainFile.parent().grab()
62
- let file = prefix + "/Main.bundle.js"
63
- internalCallEsBuild(self, mainJsFile = mainJsFile, outputPath = file, minify = minify, sourceMap = sourceMap)
64
- let assets = AssetSystem([
65
- Pair(file.dropFirst(prefix.size()), {mainDirectory.path(file).readStream()})
66
- ...if(sourceMap) {[
67
- Pair(file.dropFirst(prefix.size()) + ".map", {mainDirectory.path(file + ".map").readStream()})
68
- ]} else {[]}
69
- ].toMap())
70
- BrowserBundle(assets)
71
- }
72
-
73
- }
74
-
75
- extend self: BrowserBundle {
76
-
77
- assets(): AssetSystem {
78
- self.assetSystem
79
- }
80
-
81
- }
82
-
83
-
56
+ // TODO: Remove
84
57
  internalCallEsBuild(
85
- self: BrowserCode
58
+ self: NodeSystem
86
59
  mainJsFile: String
87
60
  outputPath: String
88
61
  minify: Bool
@@ -101,6 +74,26 @@ internalCallEsBuild(
101
74
  ))
102
75
  }
103
76
 
77
+ internalBrowserCallEsBuild(
78
+ self: BuildSystem
79
+ mainJsFiles: List[String]
80
+ outputPath: String
81
+ minify: Bool
82
+ sourceMap: Bool
83
+ ): Unit {
84
+ let esbuild = Js.import("esbuild")
85
+ Js.await(esbuild->build(Js->(
86
+ entryPoints = mainJsFiles
87
+ bundle = True
88
+ minify = minify
89
+ sourcemap = sourceMap
90
+ platform = "browser"
91
+ target = "es2017"
92
+ outdir = outputPath
93
+ outExtension = Js.object().with(".js", ".bundle.js")
94
+ )))
95
+ }
96
+
104
97
  internalNodeCallEsBuild(
105
98
  self: NodeSystem
106
99
  mainJsFile: String
@@ -135,17 +128,27 @@ internalListDirectory(path: Path): List[Pair[String, () => Stream[Buffer]]] {
135
128
  }.toList()
136
129
  }
137
130
 
131
+ internalListPath(path: Path): Stream[Path] {
132
+ path.entries().flatMap {file =>
133
+ if(file.isDirectory()) {
134
+ internalListPath(file.path())
135
+ } else {
136
+ [file.path()].toStream()
137
+ }
138
+ }
139
+ }
140
+
138
141
  internalPath(buildSystem: BuildSystem, absoluteOrRelative: String): Path {
139
142
  let nodePath = Js.import("path")
140
143
  Path(nodePath->resolve(absoluteOrRelative)?)
141
144
  }
142
145
 
143
- internalCompile(buildSystem: BuildSystem, mainFile: Path, target: String): Unit {
146
+ internalCompile(buildSystem: BuildSystem, mainFiles: List[Path], target: String): Unit {
144
147
  // Ported from the old FFI. It's quite fragile w.r.t. changes in code generation.
145
148
  Js.await(Js.rawIdentifier("$firefly_compiler")->"buildViaBuildSystem_$"(
146
149
  buildSystem!
147
150
  internalPath(buildSystem, buildSystem!->"fireflyPath_"?)!
148
- mainFile.base()
151
+ mainFiles.map {_.base()}
149
152
  target
150
153
  Js.currentTask()!
151
154
  ))
package/core/JsValue.ff CHANGED
@@ -333,6 +333,11 @@ extend self: JsValue {
333
333
  self->(a1, a2, a3, a4, a5, a6, a7, a8, a9)
334
334
  }
335
335
 
336
+ new10[A1: IsJsValue, A2: IsJsValue, A3: IsJsValue, A4: IsJsValue, A5: IsJsValue, A6: IsJsValue, A7: IsJsValue, A8: IsJsValue, A9: IsJsValue, A10: IsJsValue](a1: A1, a2: A2, a3: A3, a4: A4, a5: A5, a6: A6, a7: A7, a8: A8, a9: A9, a10: A10): JsValue {
337
+ // Special cased by the compiler
338
+ self->(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10)
339
+ }
340
+
336
341
 
337
342
  grabPairs(): List[Pair[String, JsValue]] {
338
343
  if(!self.isObject()) {throw(GrabException)}