From 280635d46e835801d47b6d188a1a2c3d085d5af7 Mon Sep 17 00:00:00 2001 From: William Bell Date: Tue, 28 Mar 2023 00:22:54 +0100 Subject: [PATCH] update --- src/input.go | 7 +- src/wasm.go | 27 ++ wasm/argon_wasm.js | 675 --------------------------------------------- wasm/index.html | 109 -------- 4 files changed, 29 insertions(+), 789 deletions(-) delete mode 100644 wasm/argon_wasm.js delete mode 100644 wasm/index.html diff --git a/src/input.go b/src/input.go index 8f5c94e..d990f74 100644 --- a/src/input.go +++ b/src/input.go @@ -1,7 +1,6 @@ package main import ( - "bufio" "fmt" "os" @@ -14,10 +13,8 @@ func input(args ...any) string { output = append(output, anyToArgon(args[i], false, true, 3, 0, true, 0)) } fmt.Print(output...) - scanner := bufio.NewScanner(os.Stdin) - scanner.Scan() - input := scanner.Text() - return input + inputData := []byte{} + return string(inputData) } func getPassword(args ...any) (string, error) { diff --git a/src/wasm.go b/src/wasm.go index 0092945..8483296 100644 --- a/src/wasm.go +++ b/src/wasm.go @@ -74,6 +74,33 @@ func wasmRun(code string, allowDocument bool) (any, ArErr) { return ThrowOnNonLoop(run(translated, stack{global, localvars, local})) } +func await(awaitable js.Value) ([]js.Value, []js.Value) { + then := make(chan []js.Value) + defer close(then) + thenFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + then <- args + return nil + }) + defer thenFunc.Release() + + catch := make(chan []js.Value) + defer close(catch) + catchFunc := js.FuncOf(func(this js.Value, args []js.Value) interface{} { + catch <- args + return nil + }) + defer catchFunc.Release() + + awaitable.Call("then", thenFunc).Call("catch", catchFunc) + + select { + case result := <-then: + return result, nil + case err := <-catch: + return nil, err + } +} + var IntervalList = []int{} var TimeoutList = []int{} diff --git a/wasm/argon_wasm.js b/wasm/argon_wasm.js deleted file mode 100644 index 85d4600..0000000 --- a/wasm/argon_wasm.js +++ /dev/null @@ -1,675 +0,0 @@ -window.ArgonWASMRuntime = async (config = {}) => { - const term = config.console || console; - const path = config.path || "bin/argon.wasm"; - if (typeof global !== "undefined") { - } else if (typeof window !== "undefined") { - window.global = window; - } else if (typeof self !== "undefined") { - self.global = self; - } else { - throw new Error( - "cannot export Go (neither global, window nor self is defined)" - ); - } - if (!global.require && typeof require !== "undefined") { - global.require = require; - } - if (!global.fs && global.require) { - const fs = require("fs"); - if ( - typeof fs === "object" && - fs !== null && - Object.keys(fs).length !== 0 - ) { - global.fs = fs; - } - } - const enosys = () => { - const err = new Error("not implemented"); - err.code = "ENOSYS"; - return err; - }; - if (!global.fs) { - let outputBuf = ""; - global.fs = { - constants: { - O_WRONLY: -1, - O_RDWR: -1, - O_CREAT: -1, - O_TRUNC: -1, - O_APPEND: -1, - O_EXCL: -1, - }, // unused - writeSync(fd, buf) { - outputBuf += decoder.decode(buf); - const nl = outputBuf.lastIndexOf("\n"); - if (nl != -1) { - term.log(outputBuf.slice(0, nl)); - outputBuf = outputBuf.slice(nl + 1); - } - return buf.length; - }, - write(fd, buf, offset, length, position, callback) { - if ( - offset !== 0 || - length !== buf.length || - position !== null - ) { - callback(enosys()); - return; - } - const n = this.writeSync(fd, buf); - callback(null, n); - }, - chmod(path, mode, callback) { - callback(enosys()); - }, - chown(path, uid, gid, callback) { - callback(enosys()); - }, - close(fd, callback) { - callback(enosys()); - }, - fchmod(fd, mode, callback) { - callback(enosys()); - }, - fchown(fd, uid, gid, callback) { - callback(enosys()); - }, - fstat(fd, callback) { - callback(enosys()); - }, - fsync(fd, callback) { - callback(null); - }, - ftruncate(fd, length, callback) { - callback(enosys()); - }, - lchown(path, uid, gid, callback) { - callback(enosys()); - }, - link(path, link, callback) { - callback(enosys()); - }, - lstat(path, callback) { - callback(enosys()); - }, - mkdir(path, perm, callback) { - callback(enosys()); - }, - open(path, flags, mode, callback) { - callback(enosys()); - }, - read(fd, buffer, offset, length, position, callback) { - callback(enosys()); - }, - readdir(path, callback) { - callback(enosys()); - }, - readlink(path, callback) { - callback(enosys()); - }, - rename(from, to, callback) { - callback(enosys()); - }, - rmdir(path, callback) { - callback(enosys()); - }, - stat(path, callback) { - callback(enosys()); - }, - symlink(path, link, callback) { - callback(enosys()); - }, - truncate(path, length, callback) { - callback(enosys()); - }, - unlink(path, callback) { - callback(enosys()); - }, - utimes(path, atime, mtime, callback) { - callback(enosys()); - }, - }; - } - if (!global.process) { - global.process = { - getuid() { - return -1; - }, - getgid() { - return -1; - }, - geteuid() { - return -1; - }, - getegid() { - return -1; - }, - getgroups() { - throw enosys(); - }, - pid: -1, - ppid: -1, - umask() { - throw enosys(); - }, - cwd() { - throw enosys(); - }, - chdir() { - throw enosys(); - }, - }; - } - if (!global.crypto && global.require) { - const nodeCrypto = require("crypto"); - global.crypto = { - getRandomValues(b) { - nodeCrypto.randomFillSync(b); - }, - }; - } - if (!global.crypto) { - throw new Error( - "global.crypto is not available, polyfill required (getRandomValues only)" - ); - } - if (!global.performance) { - global.performance = { - now() { - const [sec, nsec] = process.hrtime(); - return sec * 1000 + nsec / 1000000; - }, - }; - } - if (!global.TextEncoder && global.require) { - global.TextEncoder = require("util").TextEncoder; - } - if (!global.TextEncoder) { - throw new Error( - "global.TextEncoder is not available, polyfill required" - ); - } - if (!global.TextDecoder && global.require) { - global.TextDecoder = require("util").TextDecoder; - } - if (!global.TextDecoder) { - throw new Error( - "global.TextDecoder is not available, polyfill required" - ); - } - // End of polyfills for common API. - const encoder = new TextEncoder("utf-8"); - const decoder = new TextDecoder("utf-8"); - const Go = class { - constructor() { - this.argv = ["js"]; - this.env = {}; - this.exit = (code) => { - if (code !== 0) { - term.warn("exit code:", code); - } - }; - this._exitPromise = new Promise((resolve) => { - this._resolveExitPromise = resolve; - }); - this._pendingEvent = null; - this._scheduledTimeouts = new Map(); - this._nextCallbackTimeoutID = 1; - const setInt64 = (addr, v) => { - this.mem.setUint32(addr + 0, v, true); - this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); - }; - const getInt64 = (addr) => { - const low = this.mem.getUint32(addr + 0, true); - const high = this.mem.getInt32(addr + 4, true); - return low + high * 4294967296; - }; - const loadValue = (addr) => { - const f = this.mem.getFloat64(addr, true); - if (f === 0) { - return undefined; - } - if (!isNaN(f)) { - return f; - } - const id = this.mem.getUint32(addr, true); - return this._values[id]; - }; - const storeValue = (addr, v) => { - const nanHead = 0x7ff80000; - if (typeof v === "number" && v !== 0) { - if (isNaN(v)) { - this.mem.setUint32(addr + 4, nanHead, true); - this.mem.setUint32(addr, 0, true); - return; - } - this.mem.setFloat64(addr, v, true); - return; - } - if (v === undefined) { - this.mem.setFloat64(addr, 0, true); - return; - } - let id = this._ids.get(v); - if (id === undefined) { - id = this._idPool.pop(); - if (id === undefined) { - id = this._values.length; - } - this._values[id] = v; - this._goRefCounts[id] = 0; - this._ids.set(v, id); - } - this._goRefCounts[id]++; - let typeFlag = 0; - switch (typeof v) { - case "object": - if (v !== null) { - typeFlag = 1; - } - break; - case "string": - typeFlag = 2; - break; - case "symbol": - typeFlag = 3; - break; - case "function": - typeFlag = 4; - break; - } - this.mem.setUint32(addr + 4, nanHead | typeFlag, true); - this.mem.setUint32(addr, id, true); - }; - const loadSlice = (addr) => { - const array = getInt64(addr + 0); - const len = getInt64(addr + 8); - return new Uint8Array( - this._inst.exports.mem.buffer, - array, - len - ); - }; - const loadSliceOfValues = (addr) => { - const array = getInt64(addr + 0); - const len = getInt64(addr + 8); - const a = new Array(len); - for (let i = 0; i < len; i++) { - a[i] = loadValue(array + i * 8); - } - return a; - }; - const loadString = (addr) => { - const saddr = getInt64(addr + 0); - const len = getInt64(addr + 8); - return decoder.decode( - new DataView(this._inst.exports.mem.buffer, saddr, len) - ); - }; - const timeOrigin = Date.now() - performance.now(); - this.importObject = { - env: {}, - go: { - // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) - // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported - // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). - // This changes the SP, thus we have to update the SP used by the imported function. - // func wasmExit(code int32) - "runtime.wasmExit": (sp) => { - sp >>>= 0; - const code = this.mem.getInt32(sp + 8, true); - this.exited = true; - delete this._inst; - delete this._values; - delete this._goRefCounts; - delete this._ids; - delete this._idPool; - this.exit(code); - }, - // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) - "runtime.wasmWrite": (sp) => { - sp >>>= 0; - const fd = getInt64(sp + 8); - const p = getInt64(sp + 16); - const n = this.mem.getInt32(sp + 24, true); - fs.writeSync( - fd, - new Uint8Array(this._inst.exports.mem.buffer, p, n) - ); - }, - // func resetMemoryDataView() - "runtime.resetMemoryDataView": (sp) => { - sp >>>= 0; - this.mem = new DataView(this._inst.exports.mem.buffer); - }, - // func nanotime1() int64 - "runtime.nanotime1": (sp) => { - sp >>>= 0; - setInt64( - sp + 8, - (timeOrigin + performance.now()) * 1000000 - ); - }, - // func walltime() (sec int64, nsec int32) - "runtime.walltime": (sp) => { - sp >>>= 0; - const msec = new Date().getTime(); - setInt64(sp + 8, msec / 1000); - this.mem.setInt32( - sp + 16, - (msec % 1000) * 1000000, - true - ); - }, - // func scheduleTimeoutEvent(delay int64) int32 - "runtime.scheduleTimeoutEvent": (sp) => { - sp >>>= 0; - const id = this._nextCallbackTimeoutID; - this._nextCallbackTimeoutID++; - this._scheduledTimeouts.set( - id, - setTimeout( - () => { - this._resume(); - while (this._scheduledTimeouts.has(id)) { - // for some reason Go failed to register the timeout event, log and try again - // (temporary workaround for https://github.com/golang/go/issues/28975) - term.warn( - "scheduleTimeoutEvent: missed timeout event" - ); - this._resume(); - } - }, - getInt64(sp + 8) + 1 // setTimeout has been seen to fire up to 1 millisecond early - ) - ); - this.mem.setInt32(sp + 16, id, true); - }, - // func clearTimeoutEvent(id int32) - "runtime.clearTimeoutEvent": (sp) => { - sp >>>= 0; - const id = this.mem.getInt32(sp + 8, true); - clearTimeout(this._scheduledTimeouts.get(id)); - this._scheduledTimeouts.delete(id); - }, - // func getRandomData(r []byte) - "runtime.getRandomData": (sp) => { - sp >>>= 0; - crypto.getRandomValues(loadSlice(sp + 8)); - }, - // func finalizeRef(v ref) - "syscall/js.finalizeRef": (sp) => { - sp >>>= 0; - const id = this.mem.getUint32(sp + 8, true); - this._goRefCounts[id]--; - if (this._goRefCounts[id] === 0) { - const v = this._values[id]; - this._values[id] = null; - this._ids.delete(v); - this._idPool.push(id); - } - }, - // func stringVal(value string) ref - "syscall/js.stringVal": (sp) => { - sp >>>= 0; - storeValue(sp + 24, loadString(sp + 8)); - }, - // func valueGet(v ref, p string) ref - "syscall/js.valueGet": (sp) => { - sp >>>= 0; - const result = Reflect.get( - loadValue(sp + 8), - loadString(sp + 16) - ); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 32, result); - }, - // func valueSet(v ref, p string, x ref) - "syscall/js.valueSet": (sp) => { - sp >>>= 0; - Reflect.set( - loadValue(sp + 8), - loadString(sp + 16), - loadValue(sp + 32) - ); - }, - // func valueDelete(v ref, p string) - "syscall/js.valueDelete": (sp) => { - sp >>>= 0; - Reflect.deleteProperty( - loadValue(sp + 8), - loadString(sp + 16) - ); - }, - // func valueIndex(v ref, i int) ref - "syscall/js.valueIndex": (sp) => { - sp >>>= 0; - storeValue( - sp + 24, - Reflect.get(loadValue(sp + 8), getInt64(sp + 16)) - ); - }, - // valueSetIndex(v ref, i int, x ref) - "syscall/js.valueSetIndex": (sp) => { - sp >>>= 0; - Reflect.set( - loadValue(sp + 8), - getInt64(sp + 16), - loadValue(sp + 24) - ); - }, - // func valueCall(v ref, m string, args []ref) (ref, bool) - "syscall/js.valueCall": (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const m = Reflect.get(v, loadString(sp + 16)); - const args = loadSliceOfValues(sp + 32); - const result = Reflect.apply(m, v, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 56, result); - this.mem.setUint8(sp + 64, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 56, err); - this.mem.setUint8(sp + 64, 0); - } - }, - // func valueInvoke(v ref, args []ref) (ref, bool) - "syscall/js.valueInvoke": (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const args = loadSliceOfValues(sp + 16); - const result = Reflect.apply(v, undefined, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, result); - this.mem.setUint8(sp + 48, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, err); - this.mem.setUint8(sp + 48, 0); - } - }, - // func valueNew(v ref, args []ref) (ref, bool) - "syscall/js.valueNew": (sp) => { - sp >>>= 0; - try { - const v = loadValue(sp + 8); - const args = loadSliceOfValues(sp + 16); - const result = Reflect.construct(v, args); - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, result); - this.mem.setUint8(sp + 48, 1); - } catch (err) { - sp = this._inst.exports.getsp() >>> 0; // see comment above - storeValue(sp + 40, err); - this.mem.setUint8(sp + 48, 0); - } - }, - // func valueLength(v ref) int - "syscall/js.valueLength": (sp) => { - sp >>>= 0; - setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); - }, - // valuePrepareString(v ref) (ref, int) - "syscall/js.valuePrepareString": (sp) => { - sp >>>= 0; - const str = encoder.encode(String(loadValue(sp + 8))); - storeValue(sp + 16, str); - setInt64(sp + 24, str.length); - }, - // valueLoadString(v ref, b []byte) - "syscall/js.valueLoadString": (sp) => { - sp >>>= 0; - const str = loadValue(sp + 8); - loadSlice(sp + 16).set(str); - }, - // func valueInstanceOf(v ref, t ref) bool - "syscall/js.valueInstanceOf": (sp) => { - sp >>>= 0; - this.mem.setUint8( - sp + 24, - loadValue(sp + 8) instanceof loadValue(sp + 16) - ? 1 - : 0 - ); - }, - // func copyBytesToGo(dst []byte, src ref) (int, bool) - "syscall/js.copyBytesToGo": (sp) => { - sp >>>= 0; - const dst = loadSlice(sp + 8); - const src = loadValue(sp + 32); - if ( - !( - src instanceof Uint8Array || - src instanceof Uint8ClampedArray - ) - ) { - this.mem.setUint8(sp + 48, 0); - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(sp + 40, toCopy.length); - this.mem.setUint8(sp + 48, 1); - }, - // func copyBytesToJS(dst ref, src []byte) (int, bool) - "syscall/js.copyBytesToJS": (sp) => { - sp >>>= 0; - const dst = loadValue(sp + 8); - const src = loadSlice(sp + 16); - if ( - !( - dst instanceof Uint8Array || - dst instanceof Uint8ClampedArray - ) - ) { - this.mem.setUint8(sp + 48, 0); - return; - } - const toCopy = src.subarray(0, dst.length); - dst.set(toCopy); - setInt64(sp + 40, toCopy.length); - this.mem.setUint8(sp + 48, 1); - }, - debug: (value) => { - term.log(value); - }, - }, - }; - } - async run(instance) { - if (!(instance instanceof WebAssembly.Instance)) { - throw new Error("Go.run: WebAssembly.Instance expected"); - } - this._inst = instance; - this.mem = new DataView(this._inst.exports.mem.buffer); - this._values = [ - // JS values that Go currently has references to, indexed by reference id - NaN, - 0, - null, - true, - false, - global, - this, - ]; - this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id - this._ids = new Map([ - // mapping from JS values to reference ids - [0, 1], - [null, 2], - [true, 3], - [false, 4], - [global, 5], - [this, 6], - ]); - this._idPool = []; // unused ids that have been garbage collected - this.exited = false; // whether the Go program has exited - // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. - let offset = 4096; - const strPtr = (str) => { - const ptr = offset; - const bytes = encoder.encode(str + "\0"); - new Uint8Array(this.mem.buffer, offset, bytes.length).set( - bytes - ); - offset += bytes.length; - if (offset % 8 !== 0) { - offset += 8 - (offset % 8); - } - return ptr; - }; - const argc = this.argv.length; - const argvPtrs = []; - this.argv.forEach((arg) => { - argvPtrs.push(strPtr(arg)); - }); - argvPtrs.push(0); - const keys = Object.keys(this.env).sort(); - keys.forEach((key) => { - argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); - }); - argvPtrs.push(0); - const argv = offset; - argvPtrs.forEach((ptr) => { - this.mem.setUint32(offset, ptr, true); - this.mem.setUint32(offset + 4, 0, true); - offset += 8; - }); - this._inst.exports.run(argc, argv); - if (this.exited) { - this._resolveExitPromise(); - } - await this._exitPromise; - } - _resume() { - if (this.exited) { - throw new Error("Go program has already exited"); - } - this._inst.exports.resume(); - if (this.exited) { - this._resolveExitPromise(); - } - } - _makeFuncWrapper(id) { - const go = this; - return function () { - const event = { id: id, this: this, args: arguments }; - go._pendingEvent = event; - go._resume(); - return event.result; - }; - } - }; - const go = new Go(); - const result = await WebAssembly.instantiateStreaming( - fetch(path), - go.importObject - ); - - go.run(result.instance); -}; diff --git a/wasm/index.html b/wasm/index.html deleted file mode 100644 index 45879d8..0000000 --- a/wasm/index.html +++ /dev/null @@ -1,109 +0,0 @@ - - - - Argon WASM Runtime Example - - - - - -

Argon WASM Runtime Example

- - -
____
/\ |___ \
/ \ _ __ __ _ ___ _ __ __ ____) |
/ /\ \ | '__/ _` |/ _ \| '_ \ \ \ / /__ <
/ ____ \| | | (_| | (_) | | | | \ V /___) |
/_/ \_\_| \__, |\___/|_| |_| \_/|____/
__/ |
|___/
----------------------------------------------
Welcome to ARGON for WASM!
write code above and click run to see it work like magic!
- - -