Skip to content

Instantly share code, notes, and snippets.

@j100002ben
Forked from elct9620/app-tinygo.js
Created October 5, 2020 15:10
Show Gist options
  • Save j100002ben/2c40e5e6b57302ca337d08f7dccbfc0a to your computer and use it in GitHub Desktop.
Save j100002ben/2c40e5e6b57302ca337d08f7dccbfc0a to your computer and use it in GitHub Desktop.
Define JavaScript class inside Golang (WebAssembly)
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);
});
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)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment