refactor(js): apply pr suggestions

master
ALI Hamza 2021-03-21 14:41:36 +07:00
parent caaad47c74
commit 92296f6a56
Signed by: hamza
GPG Key ID: 22473A32291F8CB6
16 changed files with 144 additions and 1680 deletions

2
.gitignore vendored

@ -1,4 +1,4 @@
node_modules
example/node_modules
.gocache
wasm_exec.js
*.wasm

@ -1,4 +0,0 @@
dist/main.wasm
dist/main.js
node_modules
src/api/main.wasm

@ -0,0 +1 @@
dist/main.js

@ -0,0 +1,3 @@
module example
go 1.16

File diff suppressed because it is too large Load Diff

@ -4,17 +4,12 @@
"description": "",
"private": true,
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "GOROOT=`go env GOROOT` webpack serve"
},
"author": "",
"license": "ISC",
"devDependencies": {
"webpack": "^5.27.0",
"webpack-cli": "^4.5.0",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"crypto-browserify": "^3.12.0"
}
}

@ -0,0 +1,31 @@
package main
import (
"fmt"
"syscall/js"
)
func main() {
fmt.Println("Hello from go-mod-wasm!")
setup()
c := make(chan bool, 0) // To use anything from Go WASM, the program may not exit.
<-c
}
const hello = "Sample value"
func helloName(_ js.Value, args []js.Value) interface{} {
return fmt.Sprintf("Hello, %s!", args[0].String())
}
func setup() {
bridge := js.Global().Get("__go_wasm__")
bridge.Set("__ready__", true)
bridge.Set("hello", hello)
bridge.Set("helloName", js.FuncOf(helloName))
js.Global()
}

@ -0,0 +1,8 @@
import wasm from './api/main.go';
const { hello, helloName } = wasm;
(async () => {
console.log(await hello());
console.log(await helloName("world"));
})()

@ -7,13 +7,13 @@ module.exports = {
compress: true,
port: 3000,
},
mode: "production",
mode: "development",
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
resolve: {
extensions: [".go", ".tsx", ".ts", ".js"],
extensions: [".js", ".go"],
fallback: {
"fs": false,
"os": false,
@ -26,7 +26,6 @@ module.exports = {
"https": false,
"stream": false,
"crypto": false,
"crypto-browserify": require.resolve('crypto-browserify'), //if you want to use this module also don't forget npm i crypto-browserify
}
},
module: {
@ -35,7 +34,7 @@ module.exports = {
test: /\.go$/,
use: [
{
loader: path.resolve(__dirname, '../src/index.js')
loader: path.resolve(__dirname, '../../src/index.js')
}
]
}
@ -43,7 +42,7 @@ module.exports = {
},
performance: {
assetFilter: (file) => {
return !/\.wasm/.test(file)
return !/(\.wasm|.map)$/.test(file)
}
},
ignoreWarnings: [

@ -1,5 +0,0 @@
module example
go 1.16
replace gitea.teamortix.com/Team-Ortix/go-mod-wasm/wasm => /home/hamza/code/misc/go-mod-wasm/wasm

@ -1,14 +0,0 @@
package main
import (
"fmt"
"syscall/js"
)
func main() {
fmt.Println("Hello from go-mod-wasm!")
js.Global().Get("__go_wasm__").Set("__ready__", true)
c := make(chan bool, 0) // in Go Wasm, the program may not exit
<-c
}

@ -1,5 +0,0 @@
import wasm from './api/main.go';
(async () => {
console.log(await wasm.__ready__())
})()

@ -1,6 +1,6 @@
{
"name": "go-mod-wasm",
"version": "0.1.2",
"version": "0.1.0",
"description": "A webpack-based configuration to work with wasm using Go.",
"main": "src/index.js",
"repository": {

@ -1,41 +1,42 @@
const g = global || window || self
const g = global || window || self;
if (!g.__go_wasm__) {
g.__go_wasm__ = {};
}
const maxTime = new Date()
maxTime.setSeconds(maxTime.getSeconds() + 3) // if js does not initialize after 3 seconds, we allow it to start anyhow and print a warning
const maxTime = 3 * 1000;
const bridge = g.__go_wasm__;
function sleep() {
return new Promise(requestAnimationFrame)
return new Promise(requestAnimationFrame);
}
export default function (getBytes) {
let proxy;
async function init() {
const go = new g.Go();
let bytes = await getBytes
let bytes = await getBytes;
let result = await WebAssembly.instantiate(bytes, go.importObject);
go.run(result.instance);
bridge.__proxy__ = proxy
setTimeout(() => {
if (bridge.__ready__ !== true) {
console.warn("Golang Wasm Bridge (__go_wasm__.__ready__) still not true after max time")
console.warn("Golang Wasm Bridge (__go_wasm__.__ready__) still not true after max time");
}
}, 3 * 1000)
}, maxTime);
}
init();
let proxy = new Proxy(
proxy = new Proxy(
{},
{
get: (_, key) => {
return (...args) => {
return new Promise(async (res, rej) => {
while (bridge.__ready__ !== true) {
await sleep()
await sleep();
}
if (typeof bridge[key] !== 'function') {
@ -43,12 +44,14 @@ export default function (getBytes) {
return;
}
const returnObj = bridge[key].apply(undefined, args)
if (returnObj.error) {
rej(returnObj.error)
} else {
res(returnObj.result)
const returnObj = bridge[key].apply(undefined, args);
if (returnObj.error instanceof Error) {
return rej(returnObj.error)
}
if (returnObj.result) return res(returnObj.result);
return res(returnObj)
})
};
}

@ -1,21 +1,11 @@
const fs = require("fs")
const { execFileSync } = require("child_process")
const path = require("path")
const { lookpath } = require("lookpath")
const exists = async (dir, file) => {
return new Promise((res, rej) => {
fs.access(path.join(dir, file), fs.constants.F_OK, (err) => {
if (err) {
return res(false)
}
return res(true)
})
})
}
const fs = require("fs/promises");
const util = require("util");
const execFile = util.promisify(require("child_process").execFile);
const path = require("path");
const { lookpath } = require("lookpath");
module.exports = function (source) {
const cb = this.async()
const cb = this.async();
const goBin = lookpath("go");
if (!goBin) {
@ -24,62 +14,72 @@ module.exports = function (source) {
if (!process.env.GOROOT) {
return cb(new Error("Could not find GOROOT in environment.\n" +
"Please try adding this to your script:\nGOROOT=`go env GOROOT` npm run ..."))
"Please try adding this to your script:\n" +
"GOROOT=`go env GOROOT` npm run ..."));
}
const parent = path.dirname(this.resourcePath)
const outFile = this.resourcePath.slice(0, -2) + "wasm"
let modDir = parent
let found = false;
const parent = path.dirname(this.resourcePath);
const outFile = this.resourcePath.slice(0, -2) + "wasm";
let modDir = parent;
const opts = {
cwd: parent,
env: {
GOPATH: process.env.GOPATH,
GOPATH: process.env.GOPATH || path.join(process.env.HOME, "go"),
GOROOT: process.env.GOROOT,
GOCACHE: path.join(__dirname, ".gocache"),
GOOS: "js",
GOARCH: "wasm",
}
},
};
(async () => {
const root = path.resolve(path.sep)
let found = false;
const root = path.resolve(path.sep);
while (path.resolve(modDir) != root) {
if (!(await exists(modDir, 'go.mod'))) {
modDir = path.join(modDir, '..');
} else {
found = true;
found = await fs.access(path.join(modDir, 'go.mod')).then(() => true).catch(() => false);
if (found) {
break;
}
modDir = path.join(modDir, "..");
}
if (!found) {
return cb(new Error("Could not find go.mod in any parent directory of " + this.resourcePath))
return cb(new Error("Could not find go.mod in any parent directory of " + this.resourcePath));
}
try {
execFileSync("go", ["build", "-o", outFile, parent], opts)
} catch (e) {
return cb(e)
const wasmOrigPath = path.join(process.env.GOROOT, "misc", "wasm", "wasm_exec.js");
const wasmSavePath = path.join(__dirname, 'wasm_exec.js');
const errorPaths = ["\t" + wasmOrigPath, "\t" + wasmSavePath];
if (!(await fs.access(wasmOrigPath).then(() => true).catch(() => false)) &&
!(await fs.access(wasmSavePath).then(() => true).catch(() => false))) {
return cb(new Error("Could not find wasm_exec.js file. Invalid GOROOT? Searched paths:\n" +
errorPaths.join(",\n") + "\n"));
}
const wasmOrigPath = path.join(process.env.GOROOT, "misc", "wasm", "wasm_exec.js")
const wasmEmitPath = path.join(__dirname, 'wasm_exec.js')
if (!(await exists(__dirname, 'wasm_exec.js'))) {
fs.copyFileSync(wasmOrigPath, wasmEmitPath)
const res = await execFile("go", ["build", "-o", outFile, parent], opts)
.then(() => true)
.catch(e => e);
if (res instanceof Error) {
return cb(e);
}
const contents = fs.readFileSync(outFile)
fs.unlinkSync(outFile)
const emitPath = path.basename(outFile)
this.emitFile(emitPath, contents)
this.addContextDependency(modDir)
found = await fs.access(wasmSavePath).then(() => true).catch(() => false);
if (!found) fs.copyFile(wasmOrigPath, wasmSavePath);
const contents = await fs.readFile(outFile);
fs.unlink(outFile);
const emitPath = path.basename(outFile);
this.emitFile(emitPath, contents);
this.addContextDependency(modDir);
cb(null,
`require('!${wasmEmitPath}')
`require('!${wasmSavePath}');
import goWasm from '${path.join(__dirname, 'bridge.js')}';
const wasm = fetch('${emitPath}').then(response => response.arrayBuffer())
export default goWasm(wasm)`)
})()
const wasm = fetch('${emitPath}').then(response => response.arrayBuffer());
export default goWasm(wasm);`);
})();
}