mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 14:48:40 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8e7a288bb4 |
@@ -770,12 +770,11 @@ func Run(pkgName string, options *compileopts.Options, cmdArgs []string) error {
|
||||
// for the given emulator.
|
||||
func buildAndRun(pkgName string, config *compileopts.Config, stdout io.Writer, cmdArgs, environmentVars []string, timeout time.Duration, run func(cmd *exec.Cmd, result builder.BuildResult) error) (builder.BuildResult, error) {
|
||||
// Determine whether we're on a system that supports environment variables
|
||||
// and command line parameters (operating systems, WASI) or not (baremetal,
|
||||
// WebAssembly in the browser). If we're on a system without an environment,
|
||||
// we need to pass command line arguments and environment variables through
|
||||
// global variables (built into the binary directly) instead of the
|
||||
// conventional way.
|
||||
needsEnvInVars := config.GOOS() == "js"
|
||||
// and command line parameters (operating systems, WASI) or not (baremetal).
|
||||
// If we're on a system without an environment, we need to pass command line
|
||||
// arguments and environment variables through global variables (built into
|
||||
// the binary directly) instead of the conventional way.
|
||||
needsEnvInVars := false
|
||||
for _, tag := range config.BuildTags() {
|
||||
if tag == "baremetal" {
|
||||
needsEnvInVars = true
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build baremetal || js || wasm_unknown
|
||||
//go:build baremetal || wasm_unknown
|
||||
|
||||
package runtime
|
||||
|
||||
|
||||
@@ -29,6 +29,44 @@ func proc_exit(exitcode uint32)
|
||||
//export __stdio_exit
|
||||
func __stdio_exit()
|
||||
|
||||
var args []string
|
||||
|
||||
//go:linkname os_runtime_args os.runtime_args
|
||||
func os_runtime_args() []string {
|
||||
if args == nil {
|
||||
// Read the number of args (argc) and the buffer size required to store
|
||||
// all these args (argv).
|
||||
var argc, argv_buf_size uint32
|
||||
args_sizes_get(&argc, &argv_buf_size)
|
||||
if argc == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Obtain the command line arguments
|
||||
argsSlice := make([]unsafe.Pointer, argc)
|
||||
buf := make([]byte, argv_buf_size)
|
||||
args_get(&argsSlice[0], unsafe.Pointer(&buf[0]))
|
||||
|
||||
// Convert the array of C strings to an array of Go strings.
|
||||
args = make([]string, argc)
|
||||
for i, cstr := range argsSlice {
|
||||
length := strlen(cstr)
|
||||
argString := _string{
|
||||
length: length,
|
||||
ptr: (*byte)(cstr),
|
||||
}
|
||||
args[i] = *(*string)(unsafe.Pointer(&argString))
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
//go:wasmimport wasi_snapshot_preview1 args_get
|
||||
func args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16)
|
||||
|
||||
//go:wasmimport wasi_snapshot_preview1 args_sizes_get
|
||||
func args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16)
|
||||
|
||||
const (
|
||||
putcharBufferSize = 120
|
||||
stdout = 1
|
||||
|
||||
@@ -2,10 +2,6 @@
|
||||
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type timeUnit int64
|
||||
|
||||
// libc constructors
|
||||
@@ -21,38 +17,6 @@ func init() {
|
||||
__wasm_call_ctors()
|
||||
}
|
||||
|
||||
var args []string
|
||||
|
||||
//go:linkname os_runtime_args os.runtime_args
|
||||
func os_runtime_args() []string {
|
||||
if args == nil {
|
||||
// Read the number of args (argc) and the buffer size required to store
|
||||
// all these args (argv).
|
||||
var argc, argv_buf_size uint32
|
||||
args_sizes_get(&argc, &argv_buf_size)
|
||||
if argc == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Obtain the command line arguments
|
||||
argsSlice := make([]unsafe.Pointer, argc)
|
||||
buf := make([]byte, argv_buf_size)
|
||||
args_get(&argsSlice[0], unsafe.Pointer(&buf[0]))
|
||||
|
||||
// Convert the array of C strings to an array of Go strings.
|
||||
args = make([]string, argc)
|
||||
for i, cstr := range argsSlice {
|
||||
length := strlen(cstr)
|
||||
argString := _string{
|
||||
length: length,
|
||||
ptr: (*byte)(cstr),
|
||||
}
|
||||
args[i] = *(*string)(unsafe.Pointer(&argString))
|
||||
}
|
||||
}
|
||||
return args
|
||||
}
|
||||
|
||||
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||
return int64(ticks)
|
||||
}
|
||||
@@ -97,12 +61,6 @@ func beforeExit() {
|
||||
|
||||
// Implementations of WASI APIs
|
||||
|
||||
//go:wasmimport wasi_snapshot_preview1 args_get
|
||||
func args_get(argv *unsafe.Pointer, argv_buf unsafe.Pointer) (errno uint16)
|
||||
|
||||
//go:wasmimport wasi_snapshot_preview1 args_sizes_get
|
||||
func args_sizes_get(argc *uint32, argv_buf_size *uint32) (errno uint16)
|
||||
|
||||
//go:wasmimport wasi_snapshot_preview1 clock_time_get
|
||||
func clock_time_get(clockid uint32, precision uint64, time *uint64) (errno uint16)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build nintendoswitch || wasip1
|
||||
//go:build js || nintendoswitch || wasip1
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build !wasip1 && !wasip2
|
||||
//go:build !js && !wasip1 && !wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build wasip1
|
||||
//go:build js || wasip1
|
||||
|
||||
package syscall
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build nintendoswitch || wasip1 || wasip2
|
||||
//go:build js || nintendoswitch || wasip1 || wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build wasip1 || wasip2
|
||||
//go:build js || wasip1 || wasip2
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//go:build baremetal || js || wasm_unknown
|
||||
//go:build baremetal || wasm_unknown
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build baremetal || nintendoswitch || js || wasm_unknown
|
||||
//go:build baremetal || nintendoswitch || wasm_unknown
|
||||
|
||||
package syscall
|
||||
|
||||
|
||||
+54
-1
@@ -135,6 +135,8 @@
|
||||
|
||||
global.Go = class {
|
||||
constructor() {
|
||||
this.argv = ["js"];
|
||||
this.env = {};
|
||||
this._callbackTimeouts = new Map();
|
||||
this._nextCallbackTimeoutID = 1;
|
||||
|
||||
@@ -235,9 +237,58 @@
|
||||
return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
|
||||
}
|
||||
|
||||
const storeStringArraySizes = (array, num_ptr, buf_size_ptr) => {
|
||||
let buf_size = 0;
|
||||
for (let s of array) {
|
||||
buf_size += s.length + 1;
|
||||
}
|
||||
mem().setUint32(num_ptr, array.length, true);
|
||||
mem().setUint32(buf_size_ptr, buf_size, true);
|
||||
}
|
||||
|
||||
const storeStringArray = (array, ptrs_ptr, buf_ptr) => {
|
||||
for (let s of array) {
|
||||
// Put string data in buffer.
|
||||
let data = encoder.encode(s);
|
||||
let dest = new Uint8Array(this._inst.exports.memory.buffer, buf_ptr, data.length);
|
||||
dest.set(data);
|
||||
mem().setUint8(buf_ptr+data.length, 0);
|
||||
|
||||
// Put pointer to buffer in pointers array.
|
||||
mem().setUint32(ptrs_ptr, buf_ptr, true);
|
||||
|
||||
// Advance to the next element in the array.
|
||||
ptrs_ptr += 4;
|
||||
buf_ptr += data.length + 1;
|
||||
}
|
||||
}
|
||||
|
||||
const envArray = () => {
|
||||
let array = [];
|
||||
for (let [key, value] of Object.entries(this.env)) {
|
||||
array.push(`${key}=${value}`);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
const timeOrigin = Date.now() - performance.now();
|
||||
this.importObject = {
|
||||
wasi_snapshot_preview1: {
|
||||
args_sizes_get: (argc_ptr, argv_buf_size_ptr) => {
|
||||
storeStringArraySizes(this.argv, argc_ptr, argv_buf_size_ptr);
|
||||
return 0;
|
||||
},
|
||||
args_get: (argv_ptr, argv_buf_ptr) => {
|
||||
storeStringArray(this.argv, argv_ptr, argv_buf_ptr);
|
||||
return 0;
|
||||
},
|
||||
environ_get: (env_ptr, env_buf_ptr) => {
|
||||
storeStringArray(envArray(), env_ptr, env_buf_ptr);
|
||||
},
|
||||
environ_sizes_get: (env_ptr, env_buf_size_ptr) => {
|
||||
storeStringArraySizes(envArray(), env_ptr, env_buf_size_ptr);
|
||||
return 0;
|
||||
},
|
||||
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
|
||||
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
||||
let nwritten = 0;
|
||||
@@ -504,12 +555,14 @@
|
||||
global.process.versions &&
|
||||
!global.process.versions.electron
|
||||
) {
|
||||
if (process.argv.length != 3) {
|
||||
if (process.argv.length < 3) {
|
||||
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const go = new Go();
|
||||
go.argv = process.argv.slice(2);
|
||||
go.env = process.env;
|
||||
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
|
||||
return go.run(result.instance);
|
||||
}).catch((err) => {
|
||||
|
||||
Reference in New Issue
Block a user