-
-
Save j100002ben/2c40e5e6b57302ca337d08f7dccbfc0a to your computer and use it in GitHub Desktop.
Define JavaScript class inside Golang (WebAssembly)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'vendor/tinygo' | |
| const go = new Go(); | |
| go.importObject.env['main.defineClass'] = function(namePtr, nameLen, cPtr, cGcPtr, pPtr/*, pGcPtr*/) { | |
| const mem = new DataView(go._inst.exports.memory.buffer) | |
| const decoder = new TextDecoder("utf-8"); | |
| const name = decoder.decode(new DataView(go._inst.exports.memory.buffer, namePtr, nameLen)); | |
| const constructorID = mem.getUint32(cPtr, true) | |
| const constructor = go._values[constructorID] | |
| const prototypeID = mem.getUint32(pPtr, true) | |
| const prototypes = go._values[prototypeID] | |
| window[name] = (new Function( | |
| 'constructor', 'prototypes', | |
| ` | |
| function ${name}() { | |
| if(!(this instanceof ${name})) { | |
| throw new TypeError("Cannot call a class as a function") | |
| } | |
| return constructor.apply(this, arguments) | |
| } | |
| prototypes.call(${name}.prototype) | |
| return ${name} | |
| ` | |
| ))(constructor, prototypes); | |
| } | |
| WebAssembly | |
| .instantiateStreaming( | |
| fetch(require('./main.wasm')), | |
| go.importObject, | |
| ) | |
| .then(result => { | |
| go.run(result.instance); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'vendor/golang' | |
| const go = new Go(); | |
| const decoder = new TextDecoder("utf-8"); | |
| const getInt64 = (mem, addr) => { | |
| const low = mem.getUint32(addr + 0, true); | |
| const high = mem.getInt32(addr + 4, true); | |
| return low + high * 4294967296; | |
| } | |
| const loadString = (mem, addr) => { | |
| const saddr = getInt64(mem, addr + 0); | |
| const len = getInt64(mem, addr + 8); | |
| return decoder.decode(new DataView(mem.buffer, saddr, len)); | |
| } | |
| const loadValue = (mem, addr) => { | |
| const f = mem.getFloat64(addr, true); | |
| if (f === 0) { | |
| return undefined; | |
| } | |
| if (!isNaN(f)) { | |
| return f; | |
| } | |
| const id = mem.getUint32(addr, true); | |
| return go._values[id]; | |
| } | |
| go.importObject.go['main.defineClass'] = function(sp) { | |
| const mem = new DataView(go._inst.exports.mem.buffer) | |
| const name = loadString(mem, sp + 8); | |
| const constructor = loadValue(mem, sp + 24) | |
| const prototypes = loadValue(mem, sp + 40) | |
| window[name] = (new Function( | |
| 'constructor', 'prototypes', | |
| ` | |
| function ${name}() { | |
| if(!(this instanceof ${name})) { | |
| throw new TypeError("Cannot call a class as a function") | |
| } | |
| return constructor.apply(this, arguments) | |
| } | |
| prototypes.call(${name}.prototype) | |
| return ${name} | |
| ` | |
| ))(constructor, prototypes); | |
| } | |
| WebAssembly | |
| .instantiateStreaming( | |
| fetch(require('./main.wasm')), | |
| go.importObject, | |
| ) | |
| .then(result => { | |
| go.run(result.instance); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| func defineClass(name string, constructor js.Value) | |
| func pointGetX(this js.Value, []inputs js.Value) interface{} { | |
| return this.Get("x") | |
| } | |
| func pointConstructor(this js.Value, []inputs js.Value) interface{} { | |
| this.Set("x", inputs[0]) | |
| this.Set("y", inputs[1]) | |
| return this; | |
| } | |
| func pointPrototype(this js.Value, []inputs js.Value) interface{} { | |
| this.Set("getX", js.FuncOf(pointGetX)) | |
| return nil | |
| } | |
| func main() { | |
| defineClass("Point", js.FuncOf(pointConstructor).Value) | |
| // Keep Golang running | |
| <-make(chan bool) | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include "textflag.h" | |
| TEXT ·defineClass(SB), NOSPLIT, $0 | |
| CallImport | |
| RET |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment