From 2c52437039aafe52049506eb8cb067980ff87795 Mon Sep 17 00:00:00 2001 From: Nimaoth Date: Sun, 6 Oct 2024 00:31:53 +0200 Subject: [PATCH] cleanup --- src/popup.nim | 2 +- src/scripting/scripting_base.nim | 25 +- src/scripting/scripting_wasm.nim | 16 +- src/scripting/wasm.nim | 588 +++++++------------------------ src/selector_popup.nim | 2 + 5 files changed, 160 insertions(+), 473 deletions(-) diff --git a/src/popup.nim b/src/popup.nim index 31283cb9..f12848ca 100644 --- a/src/popup.nim +++ b/src/popup.nim @@ -52,4 +52,4 @@ method handleMouseMove*(self: Popup, mousePosWindow: Vec2, mousePosDelta: Vec2, import document_editor method getActiveEditor*(self: Popup): Option[DocumentEditor] {.base.} = - discard \ No newline at end of file + discard diff --git a/src/scripting/scripting_base.nim b/src/scripting/scripting_base.nim index 953ea582..11d19658 100644 --- a/src/scripting/scripting_base.nim +++ b/src/scripting/scripting_base.nim @@ -3,19 +3,24 @@ import misc/[custom_logger, custom_async] import expose, document_editor, compilation_config import platform/filesystem +{.push gcsafe.} +{.push raises: [].} + type ScriptContext* = ref object of RootObj fs*: Filesystem -method init*(self: ScriptContext, path: string, fs: Filesystem): Future[void] {.base, gcsafe, raises: [].} = discard -method deinit*(self: ScriptContext) {.base, gcsafe, raises: [].} = discard -method reload*(self: ScriptContext): Future[void] {.base, gcsafe, raises: [].} = discard +method init*(self: ScriptContext, path: string, fs: Filesystem): Future[void] {.base.} = discard +method deinit*(self: ScriptContext) {.base.} = discard +method reload*(self: ScriptContext): Future[void] {.base.} = discard + +method handleEditorModeChanged*(self: ScriptContext, editor: DocumentEditor, oldMode: string, newMode: string) {.base.} = discard +method postInitialize*(self: ScriptContext): bool {.base.} = discard +method handleCallback*(self: ScriptContext, id: int, arg: JsonNode): bool {.base.} = discard +method handleAnyCallback*(self: ScriptContext, id: int, arg: JsonNode): JsonNode {.base.} = discard +method handleScriptAction*(self: ScriptContext, name: string, args: JsonNode): JsonNode {.base.} = discard +method getCurrentContext*(self: ScriptContext): string {.base.} = "" -method handleEditorModeChanged*(self: ScriptContext, editor: DocumentEditor, oldMode: string, newMode: string) {.base, gcsafe, raises: [].} = discard -method postInitialize*(self: ScriptContext): bool {.base, gcsafe, raises: [].} = discard -method handleCallback*(self: ScriptContext, id: int, arg: JsonNode): bool {.base, gcsafe, raises: [].} = discard -method handleAnyCallback*(self: ScriptContext, id: int, arg: JsonNode): JsonNode {.base, gcsafe, raises: [].} = discard -method handleScriptAction*(self: ScriptContext, name: string, args: JsonNode): JsonNode {.base, gcsafe, raises: [].} = discard -method getCurrentContext*(self: ScriptContext): string {.base, gcsafe, raises: [].} = "" +{.pop.} # raises proc generateScriptingApiPerModule*() {.compileTime.} = var imports_content = "import \"../src/scripting_api\"\nexport scripting_api\n\n## This file is auto generated, don't modify.\n\n" @@ -84,4 +89,4 @@ import scripting_api, misc/myjsonutils imports_content.add "\nconst enableAst* = false\n" echo fmt"Writing scripting/plugin_api.nim" - writeFile(fmt"scripting/plugin_api.nim", imports_content) \ No newline at end of file + writeFile(fmt"scripting/plugin_api.nim", imports_content) diff --git a/src/scripting/scripting_wasm.nim b/src/scripting/scripting_wasm.nim index 83244f1b..49f451bf 100644 --- a/src/scripting/scripting_wasm.nim +++ b/src/scripting/scripting_wasm.nim @@ -10,6 +10,8 @@ when not defined(js): export scripting_base, wasm +{.push gcsafe.} + logCategory "scripting-wasm" type @@ -32,7 +34,7 @@ method readImpl*(self: VFSWasmContext, path: string): Future[Option[string]] {.a log lvlError, &"[VFSWasmContext] read({path}): not found" return string.none -var createEditorWasmImports: proc(): WasmImports {.gcsafe, raises: [].} +var createEditorWasmImports: proc(): WasmImports {.raises: [].} method getCurrentContext*(self: ScriptContextWasm): string = result = "plugs://" @@ -94,6 +96,8 @@ proc loadModules(self: ScriptContextWasm, path: string): Future[void] {.async.} except: log lvlError, &"Failde to load wasm module '{file}': {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" +{.push raises: [].} + method init*(self: ScriptContextWasm, path: string, fs: Filesystem): Future[void] {.async.} = self.fs = fs await self.loadModules("./config/wasm") @@ -111,14 +115,14 @@ method reload*(self: ScriptContextWasm): Future[void] {.async.} = await self.loadModules("./config/wasm") -method handleEditorModeChanged*(self: ScriptContextWasm, editor: DocumentEditor, oldMode: string, newMode: string) {.gcsafe, raises: [].} = +method handleEditorModeChanged*(self: ScriptContextWasm, editor: DocumentEditor, oldMode: string, newMode: string) = try: for (m, f) in self.editorModeChangedCallbacks: f(editor.id.int32, oldMode.cstring, newMode.cstring) except: log lvlError, &"Failed to run handleEditorModeChanged: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" -method postInitialize*(self: ScriptContextWasm): bool {.gcsafe, raises: [].} = +method postInitialize*(self: ScriptContextWasm): bool = result = false try: for (m, f) in self.postInitializeCallbacks: @@ -128,7 +132,7 @@ method postInitialize*(self: ScriptContextWasm): bool {.gcsafe, raises: [].} = except: log lvlError, &"Failed to run post initialize: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" -method handleCallback*(self: ScriptContextWasm, id: int, arg: JsonNode): bool {.gcsafe, raises: [].} = +method handleCallback*(self: ScriptContextWasm, id: int, arg: JsonNode): bool = result = false try: let argStr = $arg @@ -140,7 +144,7 @@ method handleCallback*(self: ScriptContextWasm, id: int, arg: JsonNode): bool {. except: log lvlError, &"Failed to run callback: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" -method handleAnyCallback*(self: ScriptContextWasm, id: int, arg: JsonNode): JsonNode {.gcsafe, raises: [].} = +method handleAnyCallback*(self: ScriptContextWasm, id: int, arg: JsonNode): JsonNode = try: result = nil let argStr = $arg @@ -160,7 +164,7 @@ method handleAnyCallback*(self: ScriptContextWasm, id: int, arg: JsonNode): Json log lvlError, &"Failed to run handleAnyCallback: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" -method handleScriptAction*(self: ScriptContextWasm, name: string, args: JsonNode): JsonNode {.gcsafe, raises: [].} = +method handleScriptAction*(self: ScriptContextWasm, name: string, args: JsonNode): JsonNode = try: result = nil let argStr = $args diff --git a/src/scripting/wasm.nim b/src/scripting/wasm.nim index 775f561c..a882097c 100644 --- a/src/scripting/wasm.nim +++ b/src/scripting/wasm.nim @@ -4,162 +4,49 @@ import platform/filesystem logCategory "wasi" -when defined(js): - import std/jsffi - export jsffi - - type WasmPtr* = distinct uint32 - - type WasmModule* = ref object - env: JsObject - memory: JsObject - myAlloc: proc(size: uint32): WasmPtr - myDealloc: proc(p: WasmPtr) - myStackAlloc: proc(size: uint32): WasmPtr - myStackSave: proc(): WasmPtr - myStackRestore: proc(p: WasmPtr) - - type WasmImports* = ref object - namespace*: string - functions: Table[cstring, proc()] - module: WasmModule - - type WasmError* = object of CatchableError - - proc newUint8Array(memory: JsObject) {.importjs: "new Uint8Array(#.buffer)".} - proc newUint16Array(memory: JsObject) {.importjs: "new Uint16Array(#.buffer)".} - proc newUint32Array(memory: JsObject) {.importjs: "new Uint32Array(#.buffer)".} - proc newInt8Array(memory: JsObject) {.importjs: "new Int8Array(#.buffer)".} - proc newInt16Array(memory: JsObject) {.importjs: "new Int16Array(#.buffer)".} - proc newInt32Array(memory: JsObject) {.importjs: "new Int32Array(#.buffer)".} - proc newFloat32Array(memory: JsObject) {.importjs: "new Float32Array(#.buffer)".} - proc newFloat64Array(memory: JsObject) {.importjs: "new Float64Array(#.buffer)".} - -else: - import wasm3, wasm3/[wasm3c, wasmconversions] - - export WasmPtr - - type WasmModule* = ref object - env: WasmEnv - path*: string - - type WasmImports* = object - namespace*: string - functions: seq[WasmHostProc] - module: WasmModule +import wasm3, wasm3/[wasm3c, wasmconversions] + +export WasmPtr + +type WasmModule* = ref object + env: WasmEnv + path*: string + +type WasmImports* = object + namespace*: string + functions: seq[WasmHostProc] + module: WasmModule proc `$`*(p: WasmPtr): string {.borrow.} proc `+`*(p: WasmPtr, offset: SomeNumber): WasmPtr = return WasmPtr(p.int + offset.int) proc alloc*(module: WasmModule, size: uint32): WasmPtr = - when defined(js): - return module.myAlloc(size) - else: - return module.env.alloc(size) + return module.env.alloc(size) proc stackAlloc*(module: WasmModule, size: uint32): WasmPtr = - when defined(js): - return module.myStackAlloc(size) - else: - return module.env.stackAlloc(size) + return module.env.stackAlloc(size) proc stackSave*(module: WasmModule): WasmPtr = - when defined(js): - return module.myStackSave() - else: - return module.env.stackSave() + return module.env.stackSave() proc stackRestore*(module: WasmModule, p: WasmPtr) = - when defined(js): - module.myStackRestore(p) - else: - module.env.stackRestore(p) + module.env.stackRestore(p) proc dealloc*(module: WasmModule, p: WasmPtr) = - when defined(js): - module.myDealloc(p) - else: - module.env.dealloc(p) - -when defined(js): - proc validateMemory(module: WasmModule) = - proc isDetached(arr: JsObject): bool {.importjs: "#.length == 0".} - if module.memory["HEAPU8"].isDetached: - let memory = module.memory["memory"] - module.memory["HEAPU32"] = newUint32Array(memory) - module.memory["HEAPU16"] = newUint16Array(memory) - module.memory["HEAPU8"] = newUint8Array(memory) - module.memory["HEAP32"] = newInt32Array(memory) - module.memory["HEAP16"] = newInt16Array(memory) - module.memory["HEAP8"] = newInt8Array(memory) - module.memory["HEAPF32"] = newFloat32Array(memory) - module.memory["HEAPF64"] = newFloat64Array(memory) - - proc copyMem*(module: WasmModule, dest: WasmPtr, source: JsObject, len: int, offset = 0u32) = - proc setJs(arr: JsObject, source: JsObject, pos: WasmPtr) {.importjs: "#.set(#, #)".} - proc slice(arr: JsObject, first: int, last: int): JsObject {.importjs: "#.slice(#, #)".} - - module.validateMemory() - - let heap = module.memory["HEAPU8"] - let s = source.slice(0, len) - heap.setJs(s, dest) - - proc setInt32*(module: WasmModule, dest: WasmPtr, value: int32) = - proc setJs(arr: JsObject, dest: int32, value: int32) {.importjs: "#[#] = #".} - module.validateMemory() - if dest.int32 mod 4 == 0: - let heap = module.memory["HEAP32"] - heap.setJs(dest.int32 div 4, value) - else: - let heap = module.memory["HEAPU8"] - heap.setJs(dest.int32 + 0, 0xFF and (value shr 0)) - heap.setJs(dest.int32 + 1, 0xFF and (value shr 8)) - heap.setJs(dest.int32 + 2, 0xFF and (value shr 16)) - heap.setJs(dest.int32 + 3, 0xFF and (value shr 24)) - - proc getInt32*(module: WasmModule, dest: WasmPtr): int32 = - proc getJs(arr: JsObject, dest: int32): int32 {.importjs: "#[#]".} - module.validateMemory() - if dest.int32 mod 4 == 0: - let heap = module.memory["HEAP32"] - return heap.getJs(dest.int32 div 4) - else: - let heap = module.memory["HEAPU8"] - result = 0 - result = result or (heap.getJs(dest.int32 + 0) shl 0) - result = result or (heap.getJs(dest.int32 + 1) shl 8) - result = result or (heap.getJs(dest.int32 + 2) shl 16) - result = result or (heap.getJs(dest.int32 + 3) shl 24) + module.env.dealloc(p) -else: - proc copyMem*(module: WasmModule, dest: WasmPtr, source: pointer, len: int, offset = 0u32) = - module.env.copyMem(dest, source, len, offset) +proc copyMem*(module: WasmModule, dest: WasmPtr, source: pointer, len: int, offset = 0u32) = + module.env.copyMem(dest, source, len, offset) - proc setInt32*(module: WasmModule, dest: WasmPtr, value: int32) = - module.env.setMem(value, dest.uint32) +proc setInt32*(module: WasmModule, dest: WasmPtr, value: int32) = + module.env.setMem(value, dest.uint32) - proc getInt32*(module: WasmModule, dest: WasmPtr): int32 = - return module.env.getFromMem(int32, dest.uint32) +proc getInt32*(module: WasmModule, dest: WasmPtr): int32 = + return module.env.getFromMem(int32, dest.uint32) proc getString*(module: WasmModule, pos: WasmPtr): cstring = - when defined(js): - proc indexOf(arr: JsObject, elem: uint8, start: WasmPtr): WasmPtr {.importjs: "#.indexOf(#, #)".} - proc slice(arr: JsObject, first: WasmPtr, last: WasmPtr): JsObject {.importjs: "#.slice(#, #)".} - proc jsDecodeString(str: JsObject): cstring {.importc.} - - module.validateMemory() - - let heap = module.memory["HEAPU8"] - let terminator = heap.indexOf(0, pos) - let s = heap.slice(pos, terminator) - - return jsDecodeString(s) - - else: - return module.env.getString(pos) + return module.env.getString(pos) proc replace(node: NimNode, target: string, newNodes: openArray[NimNode]): bool = for i, c in node: @@ -173,8 +60,6 @@ proc replace(node: NimNode, target: string, newNodes: openArray[NimNode]): bool return false # Stuff for wrapping functions -when defined(js): - proc jsEncodeString(str: cstring): JsObject {.importc.} macro createHostWrapper(module: WasmModule, function: typed, outFunction: untyped): untyped = # echo "createHostWrapper ", function.repr @@ -232,44 +117,22 @@ macro createHostWrapper(module: WasmModule, function: typed, outFunction: untype x(`parameters`) elif returnCString: - when defined(js): - genAst(function, module): - let x = function - let str = x(`parameters`) - let a = jsEncodeString(str) - proc len(arr: JsObject): int {.importjs: "#.length".} - let p: WasmPtr = module.alloc(a.len.uint32 + 1) - module.copyMem(p, a, a.len + 1) - return p - - else: - genAst(function, module): - let x = function - let str = x(`parameters`) - let len = str.len - let p: WasmPtr = module.alloc(len.uint32 + 1) - module.copyMem(p, cast[pointer](str), len + 1) - return p + genAst(function, module): + let x = function + let str = x(`parameters`) + let len = str.len + let p: WasmPtr = module.alloc(len.uint32 + 1) + module.copyMem(p, cast[pointer](str), len + 1) + return p elif returnString: - when defined(js): - genAst(function, module): - let x = function - let str = x(`parameters`) - let a = jsEncodeString(str.cstring) - proc len(arr: JsObject): int {.importjs: "#.length".} - let p: WasmPtr = module.alloc(a.len.uint32 + 1) - module.copyMem(p, a, a.len + 1) - return p.uint64 or (str.len.uint64 shl 32) - - else: - genAst(function, module): - let x = function - let str = x(`parameters`) - let len = str.len - let p: WasmPtr = module.alloc(len.uint32 + 1) - module.copyMem(p, cast[pointer](str[0].addr), len + 1) - return p.uint64 or (len.uint64 shl 32) + genAst(function, module): + let x = function + let str = x(`parameters`) + let len = str.len + let p: WasmPtr = module.alloc(len.uint32 + 1) + module.copyMem(p, cast[pointer](str[0].addr), len + 1) + return p.uint64 or (len.uint64 shl 32) else: genAst(function): @@ -283,178 +146,79 @@ macro createHostWrapper(module: WasmModule, function: typed, outFunction: untype # echo result.repr result = newProc(outFunction, params=params, body=body) -when defined(js): - proc castFunction[T: proc](f: T): (proc()) {.importjs: "#".} - proc toFunction(f: JsObject, R: typedesc): R {.importjs: "#".} - - template addFunction*(self: var WasmImports, name: static string, function: static proc) = - block: - createHostWrapper(self.module, function, generatedFunctionName) - self.functions[name.cstring] = castFunction(generatedFunctionName) - -else: - proc getWasmType(typ: NimNode): string = - # echo typ.treeRepr - case typ.repr - of "void": return "v" - of "int32", "uint32", "bool": return "i" - of "int64", "uint64": return "I" - of "float32": return "f" - of "float64", "float": return "F" - of "cstring", "pointer", "WasmPtr": return "*" - of "string": return "I" - else: - error(fmt"getWasmType: Invalid type {typ.repr}", typ) +proc getWasmType(typ: NimNode): string = + # echo typ.treeRepr + case typ.repr + of "void": return "v" + of "int32", "uint32", "bool": return "i" + of "int64", "uint64": return "I" + of "float32": return "f" + of "float64", "float": return "F" + of "cstring", "pointer", "WasmPtr": return "*" + of "string": return "I" + else: + error(fmt"getWasmType: Invalid type {typ.repr}", typ) - macro getWasmSignature(function: typed): string = - # echo "getWasmSignature" - # echo function.treeRepr +macro getWasmSignature(function: typed): string = + # echo "getWasmSignature" + # echo function.treeRepr - let types = function.getType - # echo types.treeRepr - let returnType = if types[1].kind == nnkBracketExpr: - types[1][1] - else: - types[1] + let types = function.getType + # echo types.treeRepr + let returnType = if types[1].kind == nnkBracketExpr: + types[1][1] + else: + types[1] - let returnTypeWasm = returnType.getWasmType - if returnTypeWasm == "": - error("Invalid return type " & returnType.repr, function) + let returnTypeWasm = returnType.getWasmType + if returnTypeWasm == "": + error("Invalid return type " & returnType.repr, function) - var signature = returnTypeWasm & "(" + var signature = returnTypeWasm & "(" - for i in 2.. ", signature - return newLit(signature) + # echo function.getType.repr, " -> ", signature + return newLit(signature) - template addFunction*(self: var WasmImports, name: string, function: static proc) = - block: - template buildFunction(runtime, outFunction: untyped) = - let module = cast[WasmModule](m3_GetUserData(runtime)) - createHostWrapper(module, function, outFunction) - self.functions.add toWasmHostProcTemplate(buildFunction, self.namespace, name, getWasmSignature(function)) +template addFunction*(self: var WasmImports, name: string, function: static proc) = + block: + template buildFunction(runtime, outFunction: untyped) = + let module = cast[WasmModule](m3_GetUserData(runtime)) + createHostWrapper(module, function, outFunction) + self.functions.add toWasmHostProcTemplate(buildFunction, self.namespace, name, getWasmSignature(function)) type WasiFD* = distinct uint32 -when defined(js): - proc createWasiJsImports(context: JsObject): WasmImports = - new result - result.namespace = "wasi_snapshot_preview1" - result.addFunction "proc_exit", proc(code: int32) = - echo "[WASI] proc_exit" - - result.addFunction "fd_close", proc(fd: int32) = - echo "[WASI] fd_close" - - result.addFunction "fd_seek", proc(fd: int32, offset: int32, whence: int64, ret: WasmPtr): int32 = - debugf"fd_seek {fd}, {offset}, {whence}" - return 70 - - result.addFunction "clock_time_get", proc(clk_id: int32, ignored_precision: int64, ptime: WasmPtr): int32 = - proc js_clock_time_get(context: JsObject, clk_id: int32, ignored_precision: int64, ptime: WasmPtr): int32 {.importc.} - return js_clock_time_get(context, clk_id, ignored_precision, ptime) - - result.addFunction "fd_fdstat_get", proc(clk_id: int32, ignored_precision: int32): int32 = - return 0 - - result.addFunction "fd_write", proc(fd: int32, iovs: WasmPtr, len: int64, ret: WasmPtr): int32 = - let memory = context["memory"] - # debugf"fd_write {fd}, {len}" - - proc js_fd_write(memory: JsObject, fd: int32, iovs: WasmPtr, len: int64, ret: WasmPtr): int32 {.importc.} - - if not memory.isUndefined: - return js_fd_write(context, fd, iovs, len, ret) - proc newWasmModule*(wasmData: ArrayBuffer, importsOld: seq[WasmImports]): Future[Option[WasmModule]] {.async.} = try: - when defined(js): - proc jsLoadWasmModuleSync(wasmData: ArrayBuffer, importObject: JsObject): Future[JsObject] {.importc.} - - let importObject = newJsObject() - - var context = newJsObject() - - var imports = @importsOld - imports.add createWasiJsImports(context) - - for imp in imports: - var obj = newJsObject() - - for key, value in imp.functions.pairs: - obj[key] = value - - importObject[imp.namespace.cstring] = obj - - var instance: JsObject - try: - instance = await jsLoadWasmModuleSync(wasmData, importObject) - except JsError: - raise newException(WasmError, getCurrentExceptionMsg()) - - let memory = instance["exports"]["memory"] - if not memory.isUndefined: - context["memory"] = memory + var allFunctions: seq[WasmHostProc] = @[] + for imp in importsOld: + allFunctions.add imp.functions - proc newUint8Array(memory: JsObject) {.importjs: "new Uint8Array(#.buffer)".} - proc newUint16Array(memory: JsObject) {.importjs: "new Uint16Array(#.buffer)".} - proc newUint32Array(memory: JsObject) {.importjs: "new Uint32Array(#.buffer)".} - proc newInt8Array(memory: JsObject) {.importjs: "new Int8Array(#.buffer)".} - proc newInt16Array(memory: JsObject) {.importjs: "new Int16Array(#.buffer)".} - proc newInt32Array(memory: JsObject) {.importjs: "new Int32Array(#.buffer)".} - proc newFloat32Array(memory: JsObject) {.importjs: "new Float32Array(#.buffer)".} - proc newFloat64Array(memory: JsObject) {.importjs: "new Float64Array(#.buffer)".} + let res = WasmModule() - context["HEAPU32"] = newUint32Array(memory) - context["HEAPU16"] = newUint16Array(memory) - context["HEAPU8"] = newUint8Array(memory) - context["HEAP32"] = newInt32Array(memory) - context["HEAP16"] = newInt16Array(memory) - context["HEAP8"] = newInt8Array(memory) - context["HEAPF32"] = newFloat32Array(memory) - context["HEAPF64"] = newFloat64Array(memory) - - let myAlloc = instance["exports"]["my_alloc"].toFunction proc(size: uint32): WasmPtr - let myDealloc = instance["exports"]["my_dealloc"].toFunction proc(p: WasmPtr) - - let myStackAlloc = instance["exports"]["stackAlloc"].toFunction proc(size: uint32): WasmPtr - let myStackSave = instance["exports"]["stackSave"].toFunction proc(): WasmPtr - let myStackRestore = instance["exports"]["stackRestore"].toFunction proc(p: WasmPtr) - - var res = WasmModule(env: instance, memory: context, myAlloc: myAlloc, myDealloc: myDealloc, myStackAlloc: myStackAlloc, myStackSave: myStackSave, myStackRestore: myStackRestore) - for imp in imports.mitems: - imp.module = res - return res.some - - else: - var allFunctions: seq[WasmHostProc] = @[] - for imp in importsOld: - allFunctions.add imp.functions - - let res = WasmModule() - - try: - res.env = loadWasmEnv(wasmData.buffer, hostProcs=allFunctions, loadAlloc=true, allocName="my_alloc", deallocName="my_dealloc", userdata=cast[pointer](res)) - except: - log lvlError, &"Failed to create wasm env: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" - return WasmModule.none + try: + res.env = loadWasmEnv(wasmData.buffer, hostProcs=allFunctions, loadAlloc=true, allocName="my_alloc", deallocName="my_dealloc", userdata=cast[pointer](res)) + except: + log lvlError, &"Failed to create wasm env: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" + return WasmModule.none - var imports = @importsOld - for imp in imports.mitems: - imp.module = res - return res.some + var imports = @importsOld + for imp in imports.mitems: + imp.module = res + return res.some except CatchableError: log lvlError, &"Failed to load wasm binary from array buffer: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" @@ -462,92 +226,33 @@ proc newWasmModule*(wasmData: ArrayBuffer, importsOld: seq[WasmImports]): Future proc newWasmModule*(path: string, importsOld: seq[WasmImports], fs: Filesystem): Future[Option[WasmModule]] {.async.} = try: - when defined(js): - proc jsLoadWasmModuleAsync(path: cstring, importObject: JsObject): Future[JsObject] {.importc.} - - let importObject = newJsObject() - - var context = newJsObject() - - var imports = @importsOld - imports.add createWasiJsImports(context) - - for imp in imports: - var obj = newJsObject() - - for key, value in imp.functions.pairs: - obj[key] = value - - importObject[imp.namespace.cstring] = obj - - var instance: JsObject - try: - instance = await jsLoadWasmModuleAsync(path.cstring, importObject) - except JsError: - raise newException(WasmError, getCurrentExceptionMsg()) - - let memory = instance["exports"]["memory"] - if not memory.isUndefined: - context["memory"] = memory - - proc newUint8Array(memory: JsObject) {.importjs: "new Uint8Array(#.buffer)".} - proc newUint16Array(memory: JsObject) {.importjs: "new Uint16Array(#.buffer)".} - proc newUint32Array(memory: JsObject) {.importjs: "new Uint32Array(#.buffer)".} - proc newInt8Array(memory: JsObject) {.importjs: "new Int8Array(#.buffer)".} - proc newInt16Array(memory: JsObject) {.importjs: "new Int16Array(#.buffer)".} - proc newInt32Array(memory: JsObject) {.importjs: "new Int32Array(#.buffer)".} - proc newFloat32Array(memory: JsObject) {.importjs: "new Float32Array(#.buffer)".} - proc newFloat64Array(memory: JsObject) {.importjs: "new Float64Array(#.buffer)".} - - context["HEAPU32"] = newUint32Array(memory) - context["HEAPU16"] = newUint16Array(memory) - context["HEAPU8"] = newUint8Array(memory) - context["HEAP32"] = newInt32Array(memory) - context["HEAP16"] = newInt16Array(memory) - context["HEAP8"] = newInt8Array(memory) - context["HEAPF32"] = newFloat32Array(memory) - context["HEAPF64"] = newFloat64Array(memory) - - let myAlloc = instance["exports"]["my_alloc"].toFunction proc(size: uint32): WasmPtr - let myDealloc = instance["exports"]["my_dealloc"].toFunction proc(p: WasmPtr) + var allFunctions: seq[WasmHostProc] = @[] + for imp in importsOld: + allFunctions.add imp.functions - let myStackAlloc = instance["exports"]["stackAlloc"].toFunction proc(size: uint32): WasmPtr - let myStackSave = instance["exports"]["stackSave"].toFunction proc(): WasmPtr - let myStackRestore = instance["exports"]["stackRestore"].toFunction proc(p: WasmPtr) + let res = WasmModule(path: path) - var res = WasmModule(env: instance, memory: context, myAlloc: myAlloc, myDealloc: myDealloc, myStackAlloc: myStackAlloc, myStackSave: myStackSave, myStackRestore: myStackRestore) - for imp in imports.mitems: - imp.module = res - return res.some - - else: - var allFunctions: seq[WasmHostProc] = @[] - for imp in importsOld: - allFunctions.add imp.functions - - let res = WasmModule(path: path) - - var content: string - try: - content = await fs.loadFileAsync(path) + var content: string + try: + content = await fs.loadFileAsync(path) - if content.len == 0: - log lvlError, &"Failed to load wasm module file {path}" - return WasmModule.none - except CatchableError: - log lvlError, &"Failed to load wasm module file {path}: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" + if content.len == 0: + log lvlError, &"Failed to load wasm module file {path}" return WasmModule.none + except CatchableError: + log lvlError, &"Failed to load wasm module file {path}: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" + return WasmModule.none - try: - res.env = loadWasmEnv(content, hostProcs=allFunctions, loadAlloc=true, allocName="my_alloc", deallocName="my_dealloc", userdata=cast[pointer](res)) - except: - log lvlError, &"Failed to create wasm env for {path}: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" - return WasmModule.none + try: + res.env = loadWasmEnv(content, hostProcs=allFunctions, loadAlloc=true, allocName="my_alloc", deallocName="my_dealloc", userdata=cast[pointer](res)) + except: + log lvlError, &"Failed to create wasm env for {path}: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" + return WasmModule.none - var imports = @importsOld - for imp in imports.mitems: - imp.module = res - return res.some + var imports = @importsOld + for imp in imports.mitems: + imp.module = res + return res.some except CatchableError: log lvlError, &"Failed to load wasm binary from file {path}: {getCurrentExceptionMsg()}\n{getCurrentException().getStackTrace()}" @@ -582,37 +287,18 @@ macro createWasmWrapper(module: WasmModule, returnType: typedesc, typ: typedesc, var arg = argSym - when defined(js): - if isCString: - arg = genAst(argSym): - block: - let a = jsEncodeString(argSym) - proc len(arr: JsObject): int {.importjs: "#.length".} - let p: WasmPtr = module.alloc(a.len.uint32 + 1) - module.copyMem(p, a, argSym.len + 1) - p - - elif isString: - arg = genAst(argSym): - block: - let a = jsEncodeString(argSym.cstring) - let p: WasmPtr = module.alloc(argSym.len.uint32 + 1) - module.copyMem(p, a, argSym.len + 1) - p.uint64 or (argSym.len.uint64 shl 32) - - else: - if isCString: - arg = genAst(argSym): - block: - let p: WasmPtr = module.alloc(argSym.len.uint32 + 1) - module.copyMem(p, cast[pointer](argSym), argSym.len + 1) - p - elif isString: - arg = genAst(argSym): - block: - let p: WasmPtr = module.alloc(argSym.len.uint32 + 1) - module.copyMem(p, cast[ptr char](argSym.cstring), argSym.len + 1) - p.uint64 or (argSym.len.uint64 shl 32) + if isCString: + arg = genAst(argSym): + block: + let p: WasmPtr = module.alloc(argSym.len.uint32 + 1) + module.copyMem(p, cast[pointer](argSym), argSym.len + 1) + p + elif isString: + arg = genAst(argSym): + block: + let p: WasmPtr = module.alloc(argSym.len.uint32 + 1) + module.copyMem(p, cast[ptr char](argSym.cstring), argSym.len + 1) + p.uint64 or (argSym.len.uint64 shl 32) args.add(arg) @@ -634,24 +320,14 @@ macro createWasmWrapper(module: WasmModule, returnType: typedesc, typ: typedesc, return newProc(params=params, body=body) proc findFunction*(module: WasmModule, name: string, R: typedesc, T: typedesc): Option[T] = - when defined(js): - let function = module.env["exports"][name.cstring] - if function.isUndefined: + try: + let f = module.env.findFunction(name) + if f.isNil: return T.none let wrapper = createWasmWrapper(module, R, T): - function.call(nil, `parameters`).to(`returnType`) + f.call(`returnType`, `parameters`) return wrapper.some - else: - try: - let f = module.env.findFunction(name) - if f.isNil: - return T.none - - let wrapper = createWasmWrapper(module, R, T): - f.call(`returnType`, `parameters`) - - return wrapper.some - except CatchableError: - return T.none \ No newline at end of file + except CatchableError: + return T.none diff --git a/src/selector_popup.nim b/src/selector_popup.nim index c726ae8d..2893a75f 100644 --- a/src/selector_popup.nim +++ b/src/selector_popup.nim @@ -9,6 +9,8 @@ import platform/filesystem export popup, selector_popup_builder +{.push gcsafe.} + logCategory "selector" createJavascriptPrototype("popup.selector")