...
1 package gojs
2
3 import (
4 "encoding/binary"
5 "errors"
6
7 "github.com/tetratelabs/wazero/api"
8 "github.com/tetratelabs/wazero/internal/gojs/util"
9 "github.com/tetratelabs/wazero/internal/wasm"
10 )
11
12
13 const (
14 endOfPageZero = uint32(4096)
15 maxArgsAndEnviron = uint32(8192)
16 wasmMinDataAddr = endOfPageZero + maxArgsAndEnviron
17 )
18
19 var le = binary.LittleEndian
20
21
22
23 func WriteArgsAndEnviron(mod api.Module) (argc, argv uint32, err error) {
24 mem := mod.Memory()
25 sysCtx := mod.(*wasm.ModuleInstance).Sys
26 args := sysCtx.Args()
27 environ := sysCtx.Environ()
28
29 argc = uint32(len(args))
30 offset := endOfPageZero
31
32 strPtr := func(val []byte, field string, i int) (ptr uint32) {
33
34 ptr = offset
35 util.MustWrite(mem, field, offset, append(val, 0))
36 offset += uint32(len(val) + 1)
37 if pad := offset % 8; pad != 0 {
38 offset += 8 - pad
39 }
40 return
41 }
42
43 argvPtrLen := len(args) + 1 + len(environ) + 1
44 argvPtrs := make([]uint32, 0, argvPtrLen)
45 for i, arg := range args {
46 argvPtrs = append(argvPtrs, strPtr(arg, "args", i))
47 }
48 argvPtrs = append(argvPtrs, 0)
49
50 for i, env := range environ {
51 argvPtrs = append(argvPtrs, strPtr(env, "env", i))
52 }
53 argvPtrs = append(argvPtrs, 0)
54
55 argv = offset
56
57 stop := uint32(argvPtrLen << 3)
58 if offset+stop >= wasmMinDataAddr {
59 err = errors.New("total length of command line and environment variables exceeds limit")
60 }
61
62 buf, ok := mem.Read(argv, stop)
63 if !ok {
64 panic("out of memory reading argvPtrs")
65 }
66 pos := uint32(0)
67 for _, ptr := range argvPtrs {
68 le.PutUint64(buf[pos:], uint64(ptr))
69 pos += 8
70 }
71
72 return
73 }
74
View as plain text