wa-lang.org/wazero@v1.0.2/internal/gojs/argsenv.go (about)

     1  package gojs
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  
     7  	"wa-lang.org/wazero/api"
     8  	"wa-lang.org/wazero/internal/wasm"
     9  )
    10  
    11  // Constants about memory layout. See REFERENCE.md
    12  const (
    13  	endOfPageZero     = uint32(4096)                      // runtime.minLegalPointer
    14  	maxArgsAndEnviron = uint32(8192)                      // ld.wasmMinDataAddr - runtime.minLegalPointer
    15  	wasmMinDataAddr   = endOfPageZero + maxArgsAndEnviron // ld.wasmMinDataAddr
    16  )
    17  
    18  // WriteArgsAndEnviron writes arguments and environment variables to memory, so
    19  // they can be read by main, Go compiles as the function export "run".
    20  func WriteArgsAndEnviron(ctx context.Context, mod api.Module) (argc, argv uint32, err error) {
    21  	mem := mod.Memory()
    22  	sysCtx := mod.(*wasm.CallContext).Sys
    23  	args := sysCtx.Args()
    24  	environ := sysCtx.Environ()
    25  
    26  	argc = uint32(len(args))
    27  	offset := endOfPageZero
    28  
    29  	strPtr := func(val, field string, i int) (ptr uint32) {
    30  		// TODO: return err and format "%s[%d], field, i"
    31  		ptr = offset
    32  		mustWrite(ctx, mem, field, offset, append([]byte(val), 0))
    33  		offset += uint32(len(val) + 1)
    34  		if pad := offset % 8; pad != 0 {
    35  			offset += 8 - pad
    36  		}
    37  		return
    38  	}
    39  	argvPtrs := make([]uint32, 0, len(args)+1+len(environ)+1)
    40  	for i, arg := range args {
    41  		argvPtrs = append(argvPtrs, strPtr(arg, "args", i))
    42  	}
    43  	argvPtrs = append(argvPtrs, 0)
    44  
    45  	for i, env := range environ {
    46  		argvPtrs = append(argvPtrs, strPtr(env, "env", i))
    47  	}
    48  	argvPtrs = append(argvPtrs, 0)
    49  
    50  	argv = offset
    51  	for _, ptr := range argvPtrs {
    52  		// TODO: return err and format "argvPtrs[%d], i"
    53  		mustWriteUint64Le(ctx, mem, "argvPtrs[i]", offset, uint64(ptr))
    54  		offset += 8
    55  	}
    56  
    57  	if offset >= wasmMinDataAddr {
    58  		err = errors.New("total length of command line and environment variables exceeds limit")
    59  	}
    60  	return
    61  }