1 package gojs
2
3 import (
4 "context"
5 "fmt"
6
7 "github.com/tetratelabs/wazero/api"
8 "github.com/tetratelabs/wazero/internal/gojs/custom"
9 "github.com/tetratelabs/wazero/internal/gojs/goarch"
10 "github.com/tetratelabs/wazero/internal/gojs/goos"
11 "github.com/tetratelabs/wazero/sys"
12 )
13
14
15
16
17
18 var FinalizeRef = goos.NewFunc(custom.NameSyscallFinalizeRef, finalizeRef)
19
20 func finalizeRef(ctx context.Context, _ api.Module, stack goos.Stack) {
21 r := stack.ParamRef(0)
22
23 id := uint32(r)
24
25 getState(ctx).values.Decrement(id)
26 }
27
28
29
30
31
32
33 var StringVal = goos.NewFunc(custom.NameSyscallStringVal, stringVal)
34
35 func stringVal(ctx context.Context, mod api.Module, stack goos.Stack) {
36 x := stack.ParamString(mod.Memory(), 0)
37
38 r := storeValue(ctx, x)
39
40 stack.SetResultRef(0, r)
41 }
42
43
44
45
46
47
48
49 var ValueGet = goos.NewFunc(custom.NameSyscallValueGet, valueGet)
50
51 func valueGet(ctx context.Context, mod api.Module, stack goos.Stack) {
52 v := stack.ParamVal(ctx, 0, LoadValue)
53 p := stack.ParamString(mod.Memory(), 1 )
54
55 var result interface{}
56 if g, ok := v.(goos.GetFunction); ok {
57 result = g.Get(p)
58 } else if e, ok := v.(error); ok {
59 switch p {
60 case "message":
61 result = e.Error()
62 case "code":
63 result = ToErrno(e).Error()
64 default:
65 panic(fmt.Errorf("TODO: valueGet(v=%v, p=%s)", v, p))
66 }
67 } else {
68 panic(fmt.Errorf("TODO: valueGet(v=%v, p=%s)", v, p))
69 }
70
71 r := storeValue(ctx, result)
72 stack.SetResultRef(0, r)
73 }
74
75
76
77
78
79
80
81 var ValueSet = goos.NewFunc(custom.NameSyscallValueSet, valueSet)
82
83 func valueSet(ctx context.Context, mod api.Module, stack goos.Stack) {
84 v := stack.ParamVal(ctx, 0, LoadValue)
85 p := stack.ParamString(mod.Memory(), 1 )
86 x := stack.ParamVal(ctx, 3, LoadValue)
87
88 if p := p; v == getState(ctx) {
89 switch p {
90 case "_pendingEvent":
91 if x == nil {
92 s := v.(*State)
93 s._lastEvent = s._pendingEvent
94 s._pendingEvent = nil
95 return
96 }
97 }
98 } else if e, ok := v.(*event); ok {
99 switch p {
100 case "result":
101 e.result = x
102 return
103 }
104 } else if m, ok := v.(*object); ok {
105 m.properties[p] = x
106 return
107 }
108 panic(fmt.Errorf("TODO: valueSet(v=%v, p=%s, x=%v)", v, p, x))
109 }
110
111
112
113
114 var ValueDelete = goarch.StubFunction(custom.NameSyscallValueDelete)
115
116
117
118
119
120
121
122 var ValueIndex = goos.NewFunc(custom.NameSyscallValueIndex, valueIndex)
123
124 func valueIndex(ctx context.Context, _ api.Module, stack goos.Stack) {
125 v := stack.ParamVal(ctx, 0, LoadValue)
126 i := stack.ParamUint32(1)
127
128 result := v.(*objectArray).slice[i]
129
130 r := storeValue(ctx, result)
131 stack.SetResultRef(0, r)
132 }
133
134
135
136
137
138 var ValueSetIndex = goarch.StubFunction(custom.NameSyscallValueSetIndex)
139
140
141
142
143
144
145 var ValueCall = goos.NewFunc(custom.NameSyscallValueCall, valueCall)
146
147 func valueCall(ctx context.Context, mod api.Module, stack goos.Stack) {
148 mem := mod.Memory()
149 vRef := stack.ParamRef(0)
150 m := stack.ParamString(mem, 1 )
151 args := stack.ParamVals(ctx, mem, 3 , LoadValue)
152
153
154 v := LoadValue(ctx, vRef)
155 c, isCall := v.(jsCall)
156 if !isCall {
157 panic(fmt.Errorf("TODO: valueCall(v=%v, m=%s, args=%v)", v, m, args))
158 }
159
160 var res goos.Ref
161 var ok bool
162 if result, err := c.call(ctx, mod, vRef, m, args...); err != nil {
163 res = storeValue(ctx, err)
164 } else {
165 res = storeValue(ctx, result)
166 ok = true
167 }
168
169 stack.Refresh(mod)
170 stack.SetResultRef(0, res)
171 stack.SetResultBool(1, ok)
172 }
173
174
175
176
177 var ValueInvoke = goarch.StubFunction(custom.NameSyscallValueInvoke)
178
179
180
181
182
183
184 var ValueNew = goos.NewFunc(custom.NameSyscallValueNew, valueNew)
185
186 func valueNew(ctx context.Context, mod api.Module, stack goos.Stack) {
187 mem := mod.Memory()
188 vRef := stack.ParamRef(0)
189 args := stack.ParamVals(ctx, mem, 1 , LoadValue)
190
191
192 var res goos.Ref
193 var ok bool
194 switch vRef {
195 case goos.RefArrayConstructor:
196 result := &objectArray{}
197 res = storeValue(ctx, result)
198 ok = true
199 case goos.RefUint8ArrayConstructor:
200 var result interface{}
201 a := args[0]
202 if n, ok := a.(float64); ok {
203 result = goos.WrapByteArray(make([]byte, uint32(n)))
204 } else if _, ok := a.(*goos.ByteArray); ok {
205
206
207 result = stack.ParamRefs(mem, 1)[0]
208 } else {
209 panic(fmt.Errorf("TODO: valueNew(v=%v, args=%v)", vRef, args))
210 }
211 res = storeValue(ctx, result)
212 ok = true
213 case goos.RefObjectConstructor:
214 result := &object{properties: map[string]interface{}{}}
215 res = storeValue(ctx, result)
216 ok = true
217 case goos.RefJsDateConstructor:
218 res = goos.RefJsDate
219 ok = true
220 default:
221 panic(fmt.Errorf("TODO: valueNew(v=%v, args=%v)", vRef, args))
222 }
223
224 stack.Refresh(mod)
225 stack.SetResultRef(0, res)
226 stack.SetResultBool(1, ok)
227 }
228
229
230
231
232
233
234 var ValueLength = goos.NewFunc(custom.NameSyscallValueLength, valueLength)
235
236 func valueLength(ctx context.Context, _ api.Module, stack goos.Stack) {
237 v := stack.ParamVal(ctx, 0, LoadValue)
238
239 len := len(v.(*objectArray).slice)
240
241 stack.SetResultUint32(0, uint32(len))
242 }
243
244
245
246
247
248
249
250
251 var ValuePrepareString = goos.NewFunc(custom.NameSyscallValuePrepareString, valuePrepareString)
252
253 func valuePrepareString(ctx context.Context, _ api.Module, stack goos.Stack) {
254 v := stack.ParamVal(ctx, 0, LoadValue)
255
256 s := valueString(v)
257
258 sRef := storeValue(ctx, s)
259 sLen := uint32(len(s))
260
261 stack.SetResultRef(0, sRef)
262 stack.SetResultUint32(1, sLen)
263 }
264
265
266
267
268
269
270 var ValueLoadString = goos.NewFunc(custom.NameSyscallValueLoadString, valueLoadString)
271
272 func valueLoadString(ctx context.Context, mod api.Module, stack goos.Stack) {
273 v := stack.ParamVal(ctx, 0, LoadValue)
274 b := stack.ParamBytes(mod.Memory(), 1 )
275
276 s := valueString(v)
277 copy(b, s)
278 }
279
280
281
282
283 var ValueInstanceOf = goarch.StubFunction(custom.NameSyscallValueInstanceOf)
284
285
286
287
288
289
290
291
292
293
294
295 var CopyBytesToGo = goos.NewFunc(custom.NameSyscallCopyBytesToGo, copyBytesToGo)
296
297 func copyBytesToGo(ctx context.Context, mod api.Module, stack goos.Stack) {
298 dst := stack.ParamBytes(mod.Memory(), 0 )
299
300 src := stack.ParamVal(ctx, 3, LoadValue)
301
302 var n uint32
303 var ok bool
304 if src, isBuf := src.(*goos.ByteArray); isBuf {
305 n = uint32(copy(dst, src.Unwrap()))
306 ok = true
307 }
308
309 stack.SetResultUint32(0, n)
310 stack.SetResultBool(1, ok)
311 }
312
313
314
315
316
317
318
319
320
321
322
323 var CopyBytesToJS = goos.NewFunc(custom.NameSyscallCopyBytesToJS, copyBytesToJS)
324
325 func copyBytesToJS(ctx context.Context, mod api.Module, stack goos.Stack) {
326 dst := stack.ParamVal(ctx, 0, LoadValue)
327 src := stack.ParamBytes(mod.Memory(), 1 )
328
329
330 var n uint32
331 var ok bool
332 if dst, isBuf := dst.(*goos.ByteArray); isBuf {
333 if dst != nil {
334 n = uint32(copy(dst.Unwrap(), src))
335 }
336 ok = true
337 }
338
339 stack.SetResultUint32(0, n)
340 stack.SetResultBool(1, ok)
341 }
342
343
344
345
346 type funcWrapper uint32
347
348
349 func (f funcWrapper) invoke(ctx context.Context, mod api.Module, args ...interface{}) (interface{}, error) {
350 e := &event{id: uint32(f), this: args[0].(goos.Ref)}
351
352 if len(args) > 1 {
353 e.args = &objectArray{args[1:]}
354 for i, v := range e.args.slice {
355 if s, ok := v.([]byte); ok {
356 args[i] = goos.WrapByteArray(s)
357 } else if s, ok := v.([]interface{}); ok {
358 args[i] = &objectArray{s}
359 } else if e, ok := v.(error); ok {
360 args[i] = e
361 }
362 }
363 }
364
365 getState(ctx)._pendingEvent = e
366
367 if _, err := mod.ExportedFunction("resume").Call(ctx); err != nil {
368 if _, ok := err.(*sys.ExitError); ok {
369 return nil, nil
370 } else {
371 return nil, err
372 }
373 }
374
375 return e.result, nil
376 }
377
View as plain text