Skip to content

Commit

Permalink
Merge pull request #84 from syumai/pass-runtime-context-on-create-go-…
Browse files Browse the repository at this point in the history
…instance

pass RuntimeContext on creating Go instance
  • Loading branch information
syumai authored Jan 4, 2024
2 parents 7585460 + dd4684b commit 7529cef
Show file tree
Hide file tree
Showing 11 changed files with 670 additions and 45 deletions.
3 changes: 1 addition & 2 deletions .github/workflows/pull_request.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,4 @@ jobs:
- name: Test
shell: bash
run: |
export PATH=$(go env GOROOT)/misc/wasm:$PATH
GOOS=js GOARCH=wasm go test ./...
PATH=$PWD/misc/wasm:$PATH GOOS=js GOARCH=wasm go test ./...
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: test
test:
@GOOS=js GOARCH=wasm go test ./...
@PATH=$(CURDIR)/misc/wasm:$(PATH) GOOS=js GOARCH=wasm go test ./...

2 changes: 1 addition & 1 deletion cloudflare/cron/cron.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,5 @@ func init() {

return jsutil.NewPromise(cb)
})
js.Global().Set("runScheduler", runSchedulerCallback)
jsutil.Binding.Set("runScheduler", runSchedulerCallback)
}
22 changes: 13 additions & 9 deletions cmd/workers-assets-gen/assets/common/shim.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export function init(m) {
mod = m;
}

async function run() {
async function run(ctx) {
let ready;
const readyPromise = new Promise((resolve) => {
ready = resolve;
Expand All @@ -32,31 +32,35 @@ async function run() {
ready: () => { ready() }
},
});
go.run(instance);
go.run(instance, ctx);
await readyPromise;
}

function createRuntimeContext(env, ctx) {
function createRuntimeContext(env, ctx, binding) {
return {
env,
ctx,
connect,
binding,
};
}

export async function fetch(req, env, ctx) {
await run();
return handleRequest(req, createRuntimeContext(env, ctx));
const binding = {};
await run(createRuntimeContext(env, ctx, binding));
return binding.handleRequest(req);
}

export async function scheduled(event, env, ctx) {
await run();
return runScheduler(event, createRuntimeContext(env, ctx));
const binding = {};
await run(createRuntimeContext(env, ctx, binding));
return binding.runScheduler(event);
}

// onRequest handles request to Cloudflare Pages
export async function onRequest(ctx) {
await run();
const binding = {};
const { request, env } = ctx;
return handleRequest(request, createRuntimeContext(env, ctx));
await run(createRuntimeContext(env, ctx, binding));
return binding.handleRequest(request);
}
14 changes: 11 additions & 3 deletions cmd/workers-assets-gen/assets/wasm_exec_go.js
Original file line number Diff line number Diff line change
Expand Up @@ -462,19 +462,27 @@
};
}

async run(instance) {
async run(instance, context) {
if (!(instance instanceof WebAssembly.Instance)) {
throw new Error("Go.run: WebAssembly.Instance expected");
}
this._inst = instance;
this.mem = new DataView(this._inst.exports.mem.buffer);
const globalProxy = new Proxy(globalThis, {
get(target, prop) {
if (prop === 'context') {
return context;
}
return Reflect.get(...arguments);
}
})
this._values = [ // JS values that Go currently has references to, indexed by reference id
NaN,
0,
null,
true,
false,
globalThis,
globalProxy,
this,
];
this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
Expand All @@ -483,7 +491,7 @@
[null, 2],
[true, 3],
[false, 4],
[globalThis, 5],
[globalProxy, 5],
[this, 6],
]);
this._idPool = []; // unused ids that have been garbage collected
Expand Down
33 changes: 10 additions & 23 deletions cmd/workers-assets-gen/assets/wasm_exec_tinygo.js
Original file line number Diff line number Diff line change
Expand Up @@ -458,15 +458,23 @@
this.importObject.env = this.importObject.gojs;
}

async run(instance) {
async run(instance, context) {
this._inst = instance;
const globalProxy = new Proxy(global, {
get(target, prop) {
if (prop === 'context') {
return context;
}
return Reflect.get(...arguments);
}
})
this._values = [ // JS values that Go currently has references to, indexed by reference id
NaN,
0,
null,
true,
false,
global,
globalProxy,
this,
];
this._goRefCounts = []; // number of references that Go has to a JS value, indexed by reference id
Expand Down Expand Up @@ -513,25 +521,4 @@
};
}
}

if (
global.require &&
global.require.main === module &&
global.process &&
global.process.versions &&
!global.process.versions.electron
) {
if (process.argv.length != 3) {
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
process.exit(1);
}

const go = new Go();
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
return go.run(result.instance);
}).catch((err) => {
console.error(err);
process.exit(1);
});
}
})();
9 changes: 3 additions & 6 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,11 @@ var httpHandler http.Handler
func init() {
var handleRequestCallback js.Func
handleRequestCallback = js.FuncOf(func(this js.Value, args []js.Value) any {
if len(args) > 2 {
if len(args) > 1 {
panic(fmt.Errorf("too many args given to handleRequest: %d", len(args)))
}
reqObj := args[0]
runtimeCtxObj := js.Null()
if len(args) > 1 {
runtimeCtxObj = args[1]
}
runtimeCtxObj := jsutil.RuntimeContext
var cb js.Func
cb = js.FuncOf(func(_ js.Value, pArgs []js.Value) any {
defer cb.Release()
Expand All @@ -40,7 +37,7 @@ func init() {
})
return jsutil.NewPromise(cb)
})
js.Global().Set("handleRequest", handleRequestCallback)
jsutil.Binding.Set("handleRequest", handleRequestCallback)
}

// handleRequest accepts a Request object and returns Response object.
Expand Down
2 changes: 2 additions & 0 deletions internal/jsutil/jsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
)

var (
RuntimeContext = js.Global().Get("context")
Binding = js.Global().Get("context").Get("binding")
ObjectClass = js.Global().Get("Object")
PromiseClass = js.Global().Get("Promise")
RequestClass = js.Global().Get("Request")
Expand Down
17 changes: 17 additions & 0 deletions misc/wasm/go_js_wasm_exec
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/usr/bin/env bash
# Copyright 2018 The Go Authors. All rights reserved.
# Use of this source code is governed by a BSD-style
# license that can be found in the LICENSE file.

SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"

# Increase the V8 stack size from the default of 984K
# to 8192K to ensure all tests can pass without hitting
# stack size limits.
exec node --stack-size=8192 "$DIR/wasm_exec_node.js" "$@"
Loading

0 comments on commit 7529cef

Please sign in to comment.