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 |
extends?
extends?
@elct9620 I'm trying to do this in golang webassembly, but I can't find a way to do it
class Welcome extends React.Component {
render() {
return <h1>Hello, {this.props.name}</h1>;
}
}
You mean you want to define a class in Golang and extend a React component?
@elct9620 Yes, I want to define a JavaScript class in golang and extend it for example with React componet
I didn't suggest you do this.
- How to access the
React.Component
? React usually does not expose it towindow
therefore you are unable to extend it. - The Golang cannot work correctly with React's binding, you need to re-implement it in your project, it is not suggested.
The most reasonable way is to define a JavaScript object under window
and access it in your React component.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
extends?