mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-03 02:27:48 +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.
|
// 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) {
|
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
|
// Determine whether we're on a system that supports environment variables
|
||||||
// and command line parameters (operating systems, WASI) or not (baremetal,
|
// and command line parameters (operating systems, WASI) or not (baremetal).
|
||||||
// WebAssembly in the browser). If we're on a system without an environment,
|
// If we're on a system without an environment, we need to pass command line
|
||||||
// we need to pass command line arguments and environment variables through
|
// arguments and environment variables through global variables (built into
|
||||||
// global variables (built into the binary directly) instead of the
|
// the binary directly) instead of the conventional way.
|
||||||
// conventional way.
|
needsEnvInVars := false
|
||||||
needsEnvInVars := config.GOOS() == "js"
|
|
||||||
for _, tag := range config.BuildTags() {
|
for _, tag := range config.BuildTags() {
|
||||||
if tag == "baremetal" {
|
if tag == "baremetal" {
|
||||||
needsEnvInVars = true
|
needsEnvInVars = true
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build baremetal || js || wasm_unknown
|
//go:build baremetal || wasm_unknown
|
||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,44 @@ func proc_exit(exitcode uint32)
|
|||||||
//export __stdio_exit
|
//export __stdio_exit
|
||||||
func __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 (
|
const (
|
||||||
putcharBufferSize = 120
|
putcharBufferSize = 120
|
||||||
stdout = 1
|
stdout = 1
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
|
|
||||||
package runtime
|
package runtime
|
||||||
|
|
||||||
import (
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
type timeUnit int64
|
type timeUnit int64
|
||||||
|
|
||||||
// libc constructors
|
// libc constructors
|
||||||
@@ -21,38 +17,6 @@ func init() {
|
|||||||
__wasm_call_ctors()
|
__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 {
|
func ticksToNanoseconds(ticks timeUnit) int64 {
|
||||||
return int64(ticks)
|
return int64(ticks)
|
||||||
}
|
}
|
||||||
@@ -97,12 +61,6 @@ func beforeExit() {
|
|||||||
|
|
||||||
// Implementations of WASI APIs
|
// 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
|
//go:wasmimport wasi_snapshot_preview1 clock_time_get
|
||||||
func clock_time_get(clockid uint32, precision uint64, time *uint64) (errno uint16)
|
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
|
package syscall
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build !wasip1 && !wasip2
|
//go:build !js && !wasip1 && !wasip2
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build wasip1
|
//go:build js || wasip1
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build nintendoswitch || wasip1 || wasip2
|
//go:build js || nintendoswitch || wasip1 || wasip2
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build wasip1 || wasip2
|
//go:build js || wasip1 || wasip2
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build baremetal || js || wasm_unknown
|
//go:build baremetal || wasm_unknown
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
//go:build baremetal || nintendoswitch || js || wasm_unknown
|
//go:build baremetal || nintendoswitch || wasm_unknown
|
||||||
|
|
||||||
package syscall
|
package syscall
|
||||||
|
|
||||||
|
|||||||
+54
-1
@@ -135,6 +135,8 @@
|
|||||||
|
|
||||||
global.Go = class {
|
global.Go = class {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
this.argv = ["js"];
|
||||||
|
this.env = {};
|
||||||
this._callbackTimeouts = new Map();
|
this._callbackTimeouts = new Map();
|
||||||
this._nextCallbackTimeoutID = 1;
|
this._nextCallbackTimeoutID = 1;
|
||||||
|
|
||||||
@@ -235,9 +237,58 @@
|
|||||||
return decoder.decode(new DataView(this._inst.exports.memory.buffer, ptr, len));
|
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();
|
const timeOrigin = Date.now() - performance.now();
|
||||||
this.importObject = {
|
this.importObject = {
|
||||||
wasi_snapshot_preview1: {
|
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
|
// https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#fd_write
|
||||||
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
fd_write: function(fd, iovs_ptr, iovs_len, nwritten_ptr) {
|
||||||
let nwritten = 0;
|
let nwritten = 0;
|
||||||
@@ -504,12 +555,14 @@
|
|||||||
global.process.versions &&
|
global.process.versions &&
|
||||||
!global.process.versions.electron
|
!global.process.versions.electron
|
||||||
) {
|
) {
|
||||||
if (process.argv.length != 3) {
|
if (process.argv.length < 3) {
|
||||||
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
|
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const go = new Go();
|
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) => {
|
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
|
||||||
return go.run(result.instance);
|
return go.run(result.instance);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user