Last active
November 3, 2024 14:41
-
-
Save elct9620/44db8ce0beb7e08cd588e9cdecafbd56 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
I didn't suggest you do this.
React.Component
? React usually does not expose it towindow
therefore you are unable to extend it.The most reasonable way is to define a JavaScript object under
window
and access it in your React component.