@px-petals/roku.motion-web 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/bands/bands.js +3 -1
  2. package/bundle/bundle.js +56 -0
  3. package/list/list.js +12 -1
  4. package/lottie/lottie.layers.js +64 -11
  5. package/lottie/lottie.paint.js +30 -0
  6. package/lottie/lottie.paths.js +19 -4
  7. package/lottie/lottie.props.js +18 -8
  8. package/lottie/lottie.shapes.js +2 -1
  9. package/mixer/mixer.js +31 -8
  10. package/mixer/mixer.mix.js +17 -0
  11. package/motion/motion.convert.js +32 -1
  12. package/motion/motion.flow.js +20 -2
  13. package/motion/motion.machine.js +28 -13
  14. package/motion/motion.values.js +13 -9
  15. package/motion.js +196 -20
  16. package/package.json +10 -16
  17. package/player/player.js +25 -5
  18. package/readme.md +78 -3
  19. package/script/luau/lib/base/base.js +202 -0
  20. package/script/luau/lib/base/base.table.js +189 -0
  21. package/script/luau/lib/lib.args.js +152 -0
  22. package/script/luau/lib/lib.js +23 -0
  23. package/script/luau/lib/math/math.bit32.js +144 -0
  24. package/script/luau/lib/math/math.js +288 -0
  25. package/script/luau/lib/math/math.vector.js +125 -0
  26. package/script/luau/lib/string/string.format.js +143 -0
  27. package/script/luau/lib/string/string.js +160 -0
  28. package/script/luau/lib/string/string.pattern.js +505 -0
  29. package/script/luau/load/load.js +362 -0
  30. package/script/luau/load/load.ops.js +79 -0
  31. package/script/luau/luau.convert.js +259 -0
  32. package/script/luau/luau.js +132 -0
  33. package/script/luau/luau.md +111 -0
  34. package/script/luau/vm/vm.js +167 -0
  35. package/script/luau/vm/vm.meta.js +401 -0
  36. package/script/luau/vm/vm.num.js +236 -0
  37. package/script/luau/vm/vm.run.js +842 -0
  38. package/script/luau/vm/vm.value.js +406 -0
  39. package/script/play/play.js +199 -0
  40. package/script/play/play.objects.js +295 -0
  41. package/script/play/play.scope.js +91 -0
  42. package/script/rive/api/api.statics.js +31 -0
  43. package/script/rive/api/api.type.js +188 -0
  44. package/script/rive/api/artboard/artboard.js +89 -0
  45. package/script/rive/api/assets/assets.js +72 -0
  46. package/script/rive/api/data/data.value.js +99 -0
  47. package/script/rive/api/draw/draw.contours.js +163 -0
  48. package/script/rive/api/draw/draw.measure.js +196 -0
  49. package/script/rive/api/draw/draw.paint.js +235 -0
  50. package/script/rive/api/draw/draw.path.js +153 -0
  51. package/script/rive/api/draw/draw.renderer.js +117 -0
  52. package/script/rive/api/math/math.color.js +96 -0
  53. package/script/rive/api/math/math.mat2d.js +180 -0
  54. package/script/rive/api/math/math.vector.js +121 -0
  55. package/script/rive/api/media/media.audio.js +113 -0
  56. package/script/rive/api/media/media.draw.js +73 -0
  57. package/script/rive/api/media/media.image.js +61 -0
  58. package/script/rive/api/media/media.mesh.js +50 -0
  59. package/script/rive/api/pointer/pointer.event.js +64 -0
  60. package/script/rive/api/pointer/pointer.route.js +69 -0
  61. package/script/rive/api/text/text.font.js +129 -0
  62. package/script/rive/api/text/text.js +278 -0
  63. package/script/rive/api/text/text.layout.js +259 -0
  64. package/script/rive/context/context.js +76 -0
  65. package/script/rive/context/context.memory.js +196 -0
  66. package/script/rive/context/context.viewmodel.js +302 -0
  67. package/script/rive/context/lists/lists.js +160 -0
  68. package/script/rive/context/lists/lists.values.js +281 -0
  69. package/script/rive/host/host.globals.js +44 -0
  70. package/script/rive/host/host.js +533 -0
  71. package/script/rive/host/host.node.js +45 -0
  72. package/script/rive/rive.js +23 -0
  73. package/script/rive/rive.md +180 -0
  74. package/script/script.js +11 -0
  75. package/skin/skin.deform.js +514 -0
  76. package/skin/skin.ik.js +260 -0
  77. package/skin/skin.js +297 -0
@@ -0,0 +1,842 @@
1
+ /**
2
+ * The interpreter: call frames and the instruction loop.
3
+ *
4
+ * A frame is a closure, a `base` index into the VM's shared value stack (its
5
+ * registers are `stack[base + n]`), the saved `pc`, and where its results go
6
+ * (`ret`, the slot its function was called from, and `nres`, how many the
7
+ * caller wants, -1 for all). A call from Lua to Lua pushes a frame and keeps
8
+ * looping, so Lua recursion does not grow the JS stack; calls through native
9
+ * functions (metamethods, `pcall`, `table.sort`) nest `execute`.
10
+ *
11
+ * Instructions are 32-bit words: opcode in the low byte, then A, B and C as
12
+ * bytes, or A and a signed 16-bit D, or a signed 24-bit E. Cases are numbered
13
+ * by opcode (see `load.ops.js`; a test keeps the two in step).
14
+ */
15
+
16
+ /** @import { ClosureRef, TableTemplate } from '../load/load.js' */
17
+
18
+ import { arith, concat, equals, index, length, lessEqual, lessThan, metamethod, rawSet, setIndex, toNumber, unm } from './vm.meta.js'
19
+ import { EMPTY, LuaClosure, LuaTable, LuaThrow, NativeFunction, Upvalue, fail, typeName } from './vm.value.js'
20
+
21
+ /** @typedef {import('./vm.js').VM} VM */
22
+
23
+ /** Lua frames allowed before "stack overflow" */
24
+ export const MAX_FRAMES = 20000
25
+
26
+ /** One running Lua function */
27
+ export class Frame {
28
+ /**
29
+ * @param {LuaClosure} cl
30
+ * @param {number} base
31
+ * @param {number} ret stack slot the results go to
32
+ * @param {number} nres results wanted, -1 for all
33
+ * @param {any[] | null} varargs
34
+ */
35
+ constructor(cl, base, ret, nres, varargs) {
36
+ this.cl = cl
37
+ this.base = base
38
+ this.ret = ret
39
+ this.nres = nres
40
+ this.varargs = varargs
41
+ this.pc = 0
42
+ /** True for the frame a host `call` started: its return leaves `execute` */
43
+ this.entry = false
44
+ }
45
+ }
46
+
47
+ /**
48
+ * Pushes the frame for calling `cl`, whose function slot is `ra` with `nargs`
49
+ * arguments after it.
50
+ *
51
+ * @param {VM} vm
52
+ * @param {LuaClosure} cl
53
+ * @param {number} ra
54
+ * @param {number} nargs
55
+ * @param {number} nres
56
+ * @returns {Frame}
57
+ */
58
+ export function enter(vm, cl, ra, nargs, nres) {
59
+ const p = cl.proto
60
+ const stack = vm.stack
61
+ const base = ra + 1
62
+ if (vm.frames.length >= MAX_FRAMES) throw fail('stack overflow')
63
+ const need = base + p.maxStack + 8
64
+ while (stack.length < need) stack.push(undefined)
65
+ const np = p.numParams
66
+ let varargs = null
67
+ if (p.isVararg) varargs = nargs > np ? stack.slice(base + np, base + nargs) : EMPTY
68
+ for (let i = nargs; i < np; i++) stack[base + i] = undefined
69
+ const frame = new Frame(cl, base, ra, nres, varargs)
70
+ vm.frames.push(frame)
71
+ vm.sp = base + p.maxStack
72
+ return frame
73
+ }
74
+
75
+ /**
76
+ * @param {VM} vm
77
+ * @param {Frame} frame
78
+ * @returns {number} the source line the frame is at, 0 when unknown
79
+ */
80
+ export function lineOf(vm, frame) {
81
+ const lines = frame.cl.proto.lines
82
+ if (lines === null) return 0
83
+ const at = frame.pc - 1
84
+ return at >= 0 && at < lines.length ? lines[at] : 0
85
+ }
86
+
87
+ /**
88
+ * Adds the position to a string error that asked for one.
89
+ *
90
+ * @param {VM} vm
91
+ * @param {any} e
92
+ * @param {Frame} frame the running frame
93
+ * @param {number} pc
94
+ */
95
+ function locate(vm, e, frame, pc) {
96
+ frame.pc = pc
97
+ if (!(e instanceof LuaThrow) || e.level <= 0) return
98
+ const frames = vm.frames
99
+ // level 1 is the running Lua frame; a frame entered from native code (pcall, a metamethod, the host) has a native caller one level up, which has no position
100
+ let at = frames.length - 1
101
+ let native = false
102
+ for (let step = 1; step < e.level; step++) {
103
+ if (native) {
104
+ native = false
105
+ at--
106
+ } else if (frames[at] !== undefined && frames[at].entry) native = true
107
+ else at--
108
+ }
109
+ const target = native ? undefined : frames[at]
110
+ e.level = 0
111
+ if (target === undefined) return
112
+ const line = lineOf(vm, target)
113
+ if (line > 0) {
114
+ e.line = line
115
+ e.chunk = target.cl.proto.chunk
116
+ if (typeof e.value === 'string') e.value = e.chunk + ':' + line + ': ' + e.value
117
+ }
118
+ }
119
+
120
+ /**
121
+ * @param {any[]} stack
122
+ * @param {number} from
123
+ * @param {number} to
124
+ * @returns {any[]}
125
+ */
126
+ function slice(stack, from, to) {
127
+ return to > from ? stack.slice(from, to) : []
128
+ }
129
+
130
+ /**
131
+ * @param {any} v
132
+ * @param {string} what
133
+ * @returns {number}
134
+ */
135
+ function forNumber(v, what) {
136
+ const n = toNumber(v)
137
+ if (n === undefined) throw fail("'for' " + what + ' value must be a number')
138
+ return n
139
+ }
140
+
141
+ /**
142
+ * Runs the top frame, and the frames it calls, until the frame marked `entry`
143
+ * returns.
144
+ *
145
+ * @param {VM} vm
146
+ * @returns {any[]} that frame's results
147
+ */
148
+ export function execute(vm) {
149
+ const stack = vm.stack
150
+ const frames = vm.frames
151
+ let frame = frames[frames.length - 1]
152
+ let cl = frame.cl
153
+ let code = cl.proto.code
154
+ let k = cl.proto.k
155
+ let base = frame.base
156
+ let pc = frame.pc
157
+ let upvals = cl.upvals
158
+ /** One past the last value of a multi-value result */
159
+ let top = 0
160
+
161
+ try {
162
+ for (;;) {
163
+ const insn = code[pc++]
164
+ const ra = base + ((insn >> 8) & 255)
165
+ switch (insn & 255) {
166
+ case 0: // NOP
167
+ case 1: // BREAK
168
+ case 69: // COVERAGE
169
+ break
170
+
171
+ case 2: // LOADNIL
172
+ stack[ra] = undefined
173
+ break
174
+
175
+ case 3: // LOADB
176
+ stack[ra] = ((insn >> 16) & 255) !== 0
177
+ pc += (insn >> 24) & 255
178
+ break
179
+
180
+ case 4: // LOADN
181
+ stack[ra] = insn >> 16
182
+ break
183
+
184
+ case 5: // LOADK
185
+ stack[ra] = k[insn >> 16]
186
+ break
187
+
188
+ case 6: // MOVE
189
+ stack[ra] = stack[base + ((insn >> 16) & 255)]
190
+ break
191
+
192
+ case 7: { // GETGLOBAL
193
+ const key = k[code[pc++]]
194
+ const env = cl.env
195
+ let v = env.getStr(key)
196
+ if (v === undefined && env.meta !== undefined) v = index(vm, env, key)
197
+ stack[ra] = v
198
+ break
199
+ }
200
+
201
+ case 8: { // SETGLOBAL
202
+ const key = k[code[pc++]]
203
+ const env = cl.env
204
+ if (env.meta === undefined) rawSet(env, key, stack[ra])
205
+ else setIndex(vm, env, key, stack[ra])
206
+ break
207
+ }
208
+
209
+ case 9: { // GETUPVAL
210
+ const uv = upvals[(insn >> 16) & 255]
211
+ stack[ra] = uv.s !== null ? uv.s[uv.i] : uv.v
212
+ break
213
+ }
214
+
215
+ case 10: { // SETUPVAL
216
+ const uv = upvals[(insn >> 16) & 255]
217
+ if (uv.s !== null) uv.s[uv.i] = stack[ra]
218
+ else uv.v = stack[ra]
219
+ break
220
+ }
221
+
222
+ case 11: // CLOSEUPVALS
223
+ if (vm.openUpvals.length > 0) vm.closeUpvals(ra)
224
+ break
225
+
226
+ case 12: { // GETIMPORT
227
+ const aux = code[pc++]
228
+ const n = aux >>> 30
229
+ let v = index(vm, cl.env, k[(aux >> 20) & 1023])
230
+ if (n > 1) v = index(vm, v, k[(aux >> 10) & 1023])
231
+ if (n > 2) v = index(vm, v, k[aux & 1023])
232
+ stack[ra] = v
233
+ break
234
+ }
235
+
236
+ case 13: { // GETTABLE
237
+ const t = stack[base + ((insn >> 16) & 255)]
238
+ const key = stack[base + ((insn >> 24) & 255)]
239
+ let v
240
+ if (t instanceof LuaTable) {
241
+ v = t.get(key)
242
+ if (v === undefined && t.meta !== undefined) v = index(vm, t, key)
243
+ } else v = index(vm, t, key)
244
+ stack[ra] = v
245
+ break
246
+ }
247
+
248
+ case 14: { // SETTABLE
249
+ const t = stack[base + ((insn >> 16) & 255)]
250
+ const key = stack[base + ((insn >> 24) & 255)]
251
+ if (t instanceof LuaTable && t.meta === undefined && !t.frozen && key !== undefined && key === key) t.set(key, stack[ra])
252
+ else setIndex(vm, t, key, stack[ra])
253
+ break
254
+ }
255
+
256
+ case 15: { // GETTABLEKS
257
+ const t = stack[base + ((insn >> 16) & 255)]
258
+ const key = k[code[pc++]]
259
+ let v
260
+ if (t instanceof LuaTable) {
261
+ v = t.getStr(key)
262
+ if (v === undefined && t.meta !== undefined) v = index(vm, t, key)
263
+ } else v = index(vm, t, key)
264
+ stack[ra] = v
265
+ break
266
+ }
267
+
268
+ case 16: { // SETTABLEKS
269
+ const t = stack[base + ((insn >> 16) & 255)]
270
+ const key = k[code[pc++]]
271
+ if (t instanceof LuaTable && t.meta === undefined && !t.frozen) t.set(key, stack[ra])
272
+ else setIndex(vm, t, key, stack[ra])
273
+ break
274
+ }
275
+
276
+ case 17: { // GETTABLEN
277
+ const t = stack[base + ((insn >> 16) & 255)]
278
+ const key = ((insn >> 24) & 255) + 1
279
+ let v
280
+ if (t instanceof LuaTable) {
281
+ v = key <= t.arr.length ? t.arr[key - 1] : t.get(key)
282
+ if (v === undefined && t.meta !== undefined) v = index(vm, t, key)
283
+ } else v = index(vm, t, key)
284
+ stack[ra] = v
285
+ break
286
+ }
287
+
288
+ case 18: { // SETTABLEN
289
+ const t = stack[base + ((insn >> 16) & 255)]
290
+ const key = ((insn >> 24) & 255) + 1
291
+ if (t instanceof LuaTable && t.meta === undefined && !t.frozen) t.set(key, stack[ra])
292
+ else setIndex(vm, t, key, stack[ra])
293
+ break
294
+ }
295
+
296
+ case 19: { // NEWCLOSURE
297
+ const p = cl.proto.protos[insn >> 16]
298
+ /** @type {any[]} */
299
+ const ups = []
300
+ // the closure is in its register before its captures are read: a local function captures itself
301
+ stack[ra] = new LuaClosure(p, ups, cl.env)
302
+ for (let i = 0; i < p.numUpvals; i++) {
303
+ const cap = code[pc++]
304
+ const b = (cap >> 16) & 255
305
+ const kind = (cap >> 8) & 255
306
+ if (kind === 0) {
307
+ const uv = new Upvalue(stack, -1)
308
+ uv.s = null
309
+ uv.v = stack[base + b]
310
+ ups.push(uv)
311
+ } else if (kind === 1) ups.push(vm.findUpvalue(base + b))
312
+ else ups.push(upvals[b])
313
+ }
314
+ break
315
+ }
316
+
317
+ case 20: { // NAMECALL
318
+ const obj = stack[base + ((insn >> 16) & 255)]
319
+ const key = k[code[pc++]]
320
+ let fn
321
+ if (obj instanceof LuaTable) {
322
+ fn = obj.getStr(key)
323
+ if (fn === undefined && obj.meta !== undefined) fn = index(vm, obj, key)
324
+ } else fn = index(vm, obj, key)
325
+ if (fn === undefined) throw fail("attempt to call missing method '" + key + "' of " + typeName(obj))
326
+ stack[ra + 1] = obj
327
+ stack[ra] = fn
328
+ break
329
+ }
330
+
331
+ case 87: // CALLFB: a CALL that carries a feedback slot word
332
+ pc++
333
+ // falls through
334
+ case 21: { // CALL
335
+ const b = (insn >> 16) & 255
336
+ const nargs = b !== 0 ? b - 1 : top - ra - 1
337
+ const nres = ((insn >> 24) & 255) - 1
338
+ const fn = stack[ra]
339
+ if (fn instanceof LuaClosure) {
340
+ frame.pc = pc
341
+ frame = enter(vm, fn, ra, nargs, nres)
342
+ cl = fn
343
+ code = cl.proto.code
344
+ k = cl.proto.k
345
+ base = frame.base
346
+ pc = 0
347
+ upvals = cl.upvals
348
+ break
349
+ }
350
+ const args = slice(stack, ra + 1, ra + 1 + nargs)
351
+ let res
352
+ if (fn instanceof NativeFunction) {
353
+ frame.pc = pc
354
+ res = fn.fn(vm, args)
355
+ if (!Array.isArray(res)) res = [ res ]
356
+ } else {
357
+ frame.pc = pc
358
+ res = vm.call(fn, args)
359
+ }
360
+ const n = res.length
361
+ if (nres < 0) {
362
+ while (stack.length < ra + n + 8) stack.push(undefined)
363
+ for (let i = 0; i < n; i++) stack[ra + i] = res[i]
364
+ top = ra + n
365
+ } else {
366
+ for (let i = 0; i < nres; i++) stack[ra + i] = i < n ? res[i] : undefined
367
+ }
368
+ break
369
+ }
370
+
371
+ case 22: { // RETURN
372
+ const b = (insn >> 16) & 255
373
+ const n = b !== 0 ? b - 1 : top - ra
374
+ if (vm.openUpvals.length > 0) vm.closeUpvals(base)
375
+ if (frame.entry) {
376
+ const res = slice(stack, ra, ra + n)
377
+ frames.pop()
378
+ return res
379
+ }
380
+ const dest = frame.ret
381
+ const nres = frame.nres
382
+ if (nres < 0) {
383
+ for (let i = 0; i < n; i++) stack[dest + i] = stack[ra + i]
384
+ top = dest + n
385
+ } else {
386
+ for (let i = 0; i < nres; i++) stack[dest + i] = i < n ? stack[ra + i] : undefined
387
+ }
388
+ frames.pop()
389
+ frame = frames[frames.length - 1]
390
+ cl = frame.cl
391
+ code = cl.proto.code
392
+ k = cl.proto.k
393
+ base = frame.base
394
+ pc = frame.pc
395
+ upvals = cl.upvals
396
+ vm.sp = base + cl.proto.maxStack
397
+ break
398
+ }
399
+
400
+ case 23: // JUMP
401
+ case 24: // JUMPBACK
402
+ pc += insn >> 16
403
+ break
404
+
405
+ case 25: { // JUMPIF
406
+ const v = stack[ra]
407
+ if (v !== undefined && v !== false) pc += insn >> 16
408
+ break
409
+ }
410
+
411
+ case 26: { // JUMPIFNOT
412
+ const v = stack[ra]
413
+ if (v === undefined || v === false) pc += insn >> 16
414
+ break
415
+ }
416
+
417
+ case 27: { // JUMPIFEQ
418
+ const a = stack[ra]
419
+ const b = stack[base + code[pc]]
420
+ if (a === b || (typeof a === 'object' && equals(vm, a, b))) pc += insn >> 16
421
+ else pc++
422
+ break
423
+ }
424
+
425
+ case 30: { // JUMPIFNOTEQ
426
+ const a = stack[ra]
427
+ const b = stack[base + code[pc]]
428
+ if (a === b || (typeof a === 'object' && equals(vm, a, b))) pc++
429
+ else pc += insn >> 16
430
+ break
431
+ }
432
+
433
+ case 28: { // JUMPIFLE
434
+ const a = stack[ra]
435
+ const b = stack[base + code[pc]]
436
+ if (typeof a === 'number' && typeof b === 'number' ? a <= b : lessEqual(vm, a, b)) pc += insn >> 16
437
+ else pc++
438
+ break
439
+ }
440
+
441
+ case 31: { // JUMPIFNOTLE
442
+ const a = stack[ra]
443
+ const b = stack[base + code[pc]]
444
+ if (typeof a === 'number' && typeof b === 'number' ? a <= b : lessEqual(vm, a, b)) pc++
445
+ else pc += insn >> 16
446
+ break
447
+ }
448
+
449
+ case 29: { // JUMPIFLT
450
+ const a = stack[ra]
451
+ const b = stack[base + code[pc]]
452
+ if (typeof a === 'number' && typeof b === 'number' ? a < b : lessThan(vm, a, b)) pc += insn >> 16
453
+ else pc++
454
+ break
455
+ }
456
+
457
+ case 32: { // JUMPIFNOTLT
458
+ const a = stack[ra]
459
+ const b = stack[base + code[pc]]
460
+ if (typeof a === 'number' && typeof b === 'number' ? a < b : lessThan(vm, a, b)) pc++
461
+ else pc += insn >> 16
462
+ break
463
+ }
464
+
465
+ case 33: { // ADD
466
+ const b = stack[base + ((insn >> 16) & 255)]
467
+ const c = stack[base + ((insn >> 24) & 255)]
468
+ stack[ra] = typeof b === 'number' && typeof c === 'number' ? b + c : arith(vm, 'add', b, c)
469
+ break
470
+ }
471
+
472
+ case 34: { // SUB
473
+ const b = stack[base + ((insn >> 16) & 255)]
474
+ const c = stack[base + ((insn >> 24) & 255)]
475
+ stack[ra] = typeof b === 'number' && typeof c === 'number' ? b - c : arith(vm, 'sub', b, c)
476
+ break
477
+ }
478
+
479
+ case 35: { // MUL
480
+ const b = stack[base + ((insn >> 16) & 255)]
481
+ const c = stack[base + ((insn >> 24) & 255)]
482
+ stack[ra] = typeof b === 'number' && typeof c === 'number' ? b * c : arith(vm, 'mul', b, c)
483
+ break
484
+ }
485
+
486
+ case 36: { // DIV
487
+ const b = stack[base + ((insn >> 16) & 255)]
488
+ const c = stack[base + ((insn >> 24) & 255)]
489
+ stack[ra] = typeof b === 'number' && typeof c === 'number' ? b / c : arith(vm, 'div', b, c)
490
+ break
491
+ }
492
+
493
+ case 37: { // MOD
494
+ const b = stack[base + ((insn >> 16) & 255)]
495
+ const c = stack[base + ((insn >> 24) & 255)]
496
+ stack[ra] = typeof b === 'number' && typeof c === 'number' ? b - Math.floor(b / c) * c : arith(vm, 'mod', b, c)
497
+ break
498
+ }
499
+
500
+ case 38: { // POW
501
+ const b = stack[base + ((insn >> 16) & 255)]
502
+ const c = stack[base + ((insn >> 24) & 255)]
503
+ stack[ra] = typeof b === 'number' && typeof c === 'number' ? Math.pow(b, c) : arith(vm, 'pow', b, c)
504
+ break
505
+ }
506
+
507
+ case 81: { // IDIV
508
+ const b = stack[base + ((insn >> 16) & 255)]
509
+ const c = stack[base + ((insn >> 24) & 255)]
510
+ stack[ra] = typeof b === 'number' && typeof c === 'number' ? Math.floor(b / c) : arith(vm, 'idiv', b, c)
511
+ break
512
+ }
513
+
514
+ case 39: { // ADDK
515
+ const b = stack[base + ((insn >> 16) & 255)]
516
+ const c = k[(insn >> 24) & 255]
517
+ stack[ra] = typeof b === 'number' ? b + c : arith(vm, 'add', b, c)
518
+ break
519
+ }
520
+
521
+ case 40: { // SUBK
522
+ const b = stack[base + ((insn >> 16) & 255)]
523
+ const c = k[(insn >> 24) & 255]
524
+ stack[ra] = typeof b === 'number' ? b - c : arith(vm, 'sub', b, c)
525
+ break
526
+ }
527
+
528
+ case 41: { // MULK
529
+ const b = stack[base + ((insn >> 16) & 255)]
530
+ const c = k[(insn >> 24) & 255]
531
+ stack[ra] = typeof b === 'number' ? b * c : arith(vm, 'mul', b, c)
532
+ break
533
+ }
534
+
535
+ case 42: { // DIVK
536
+ const b = stack[base + ((insn >> 16) & 255)]
537
+ const c = k[(insn >> 24) & 255]
538
+ stack[ra] = typeof b === 'number' ? b / c : arith(vm, 'div', b, c)
539
+ break
540
+ }
541
+
542
+ case 43: { // MODK
543
+ const b = stack[base + ((insn >> 16) & 255)]
544
+ const c = k[(insn >> 24) & 255]
545
+ stack[ra] = typeof b === 'number' ? b - Math.floor(b / c) * c : arith(vm, 'mod', b, c)
546
+ break
547
+ }
548
+
549
+ case 44: { // POWK
550
+ const b = stack[base + ((insn >> 16) & 255)]
551
+ const c = k[(insn >> 24) & 255]
552
+ stack[ra] = typeof b === 'number' ? Math.pow(b, c) : arith(vm, 'pow', b, c)
553
+ break
554
+ }
555
+
556
+ case 82: { // IDIVK
557
+ const b = stack[base + ((insn >> 16) & 255)]
558
+ const c = k[(insn >> 24) & 255]
559
+ stack[ra] = typeof b === 'number' ? Math.floor(b / c) : arith(vm, 'idiv', b, c)
560
+ break
561
+ }
562
+
563
+ case 71: { // SUBRK
564
+ const b = k[(insn >> 16) & 255]
565
+ const c = stack[base + ((insn >> 24) & 255)]
566
+ stack[ra] = typeof c === 'number' ? b - c : arith(vm, 'sub', b, c)
567
+ break
568
+ }
569
+
570
+ case 72: { // DIVRK
571
+ const b = k[(insn >> 16) & 255]
572
+ const c = stack[base + ((insn >> 24) & 255)]
573
+ stack[ra] = typeof c === 'number' ? b / c : arith(vm, 'div', b, c)
574
+ break
575
+ }
576
+
577
+ case 45: { // AND
578
+ const b = stack[base + ((insn >> 16) & 255)]
579
+ stack[ra] = b === undefined || b === false ? b : stack[base + ((insn >> 24) & 255)]
580
+ break
581
+ }
582
+
583
+ case 46: { // OR
584
+ const b = stack[base + ((insn >> 16) & 255)]
585
+ stack[ra] = b === undefined || b === false ? stack[base + ((insn >> 24) & 255)] : b
586
+ break
587
+ }
588
+
589
+ case 47: { // ANDK
590
+ const b = stack[base + ((insn >> 16) & 255)]
591
+ stack[ra] = b === undefined || b === false ? b : k[(insn >> 24) & 255]
592
+ break
593
+ }
594
+
595
+ case 48: { // ORK
596
+ const b = stack[base + ((insn >> 16) & 255)]
597
+ stack[ra] = b === undefined || b === false ? k[(insn >> 24) & 255] : b
598
+ break
599
+ }
600
+
601
+ case 49: { // CONCAT
602
+ const b = base + ((insn >> 16) & 255)
603
+ const c = base + ((insn >> 24) & 255)
604
+ let acc = stack[c]
605
+ for (let i = c - 1; i >= b; i--) acc = concat(vm, stack[i], acc)
606
+ stack[ra] = acc
607
+ break
608
+ }
609
+
610
+ case 50: { // NOT
611
+ const v = stack[base + ((insn >> 16) & 255)]
612
+ stack[ra] = v === undefined || v === false
613
+ break
614
+ }
615
+
616
+ case 51: { // MINUS
617
+ const v = stack[base + ((insn >> 16) & 255)]
618
+ stack[ra] = typeof v === 'number' ? -v : unm(vm, v)
619
+ break
620
+ }
621
+
622
+ case 52: { // LENGTH
623
+ const v = stack[base + ((insn >> 16) & 255)]
624
+ if (v instanceof LuaTable && v.meta === undefined) stack[ra] = v.arr.length
625
+ else stack[ra] = length(vm, v)
626
+ break
627
+ }
628
+
629
+ case 53: // NEWTABLE
630
+ pc++
631
+ stack[ra] = new LuaTable()
632
+ break
633
+
634
+ case 54: { // DUPTABLE
635
+ const tpl = /** @type {TableTemplate} */ (k[insn >> 16])
636
+ const t = new LuaTable()
637
+ for (let i = 0; i < tpl.keys.length; i++) t.set(tpl.keys[i], tpl.values[i])
638
+ stack[ra] = t
639
+ break
640
+ }
641
+
642
+ case 55: { // SETLIST
643
+ const start = base + ((insn >> 16) & 255)
644
+ const c = (insn >> 24) & 255
645
+ const n = c !== 0 ? c - 1 : top - start
646
+ const first = code[pc++]
647
+ const t = stack[ra]
648
+ if (n > 0) t.setRange(first, stack, start, n)
649
+ break
650
+ }
651
+
652
+ case 56: { // FORNPREP
653
+ let limit = stack[ra]
654
+ let step = stack[ra + 1]
655
+ let idx = stack[ra + 2]
656
+ if (typeof limit !== 'number') stack[ra] = limit = forNumber(limit, 'limit')
657
+ if (typeof step !== 'number') stack[ra + 1] = step = forNumber(step, 'step')
658
+ if (typeof idx !== 'number') stack[ra + 2] = idx = forNumber(idx, 'initial')
659
+ if (!(step > 0 ? idx <= limit : limit <= idx)) pc += insn >> 16
660
+ break
661
+ }
662
+
663
+ case 57: { // FORNLOOP
664
+ const step = stack[ra + 1]
665
+ const idx = stack[ra + 2] + step
666
+ stack[ra + 2] = idx
667
+ const limit = stack[ra]
668
+ if (step > 0 ? idx <= limit : limit <= idx) pc += insn >> 16
669
+ break
670
+ }
671
+
672
+ case 76: // FORGPREP
673
+ case 59: // FORGPREP_INEXT
674
+ case 61: { // FORGPREP_NEXT
675
+ const op = insn & 255
676
+ const f = stack[ra]
677
+ if (op === 59 && f === vm.inext && stack[ra + 1] instanceof LuaTable && stack[ra + 2] === 0) {
678
+ stack[ra] = undefined
679
+ stack[ra + 2] = 0
680
+ } else if (op === 61 && f === vm.next && stack[ra + 1] instanceof LuaTable && stack[ra + 2] === undefined) {
681
+ stack[ra] = undefined
682
+ stack[ra + 2] = 0
683
+ } else if (f instanceof LuaClosure || f instanceof NativeFunction) {
684
+ // called by FORGLOOP
685
+ } else {
686
+ const iter = metamethod(vm, f, '__iter')
687
+ if (iter !== undefined) {
688
+ frame.pc = pc
689
+ const res = vm.call(iter, [ f ])
690
+ stack[ra] = res[0]
691
+ stack[ra + 1] = res[1]
692
+ stack[ra + 2] = res[2]
693
+ if (stack[ra] === undefined) throw fail('attempt to call a nil value')
694
+ } else if (metamethod(vm, f, '__call') !== undefined) {
695
+ // called by FORGLOOP
696
+ } else if (f instanceof LuaTable) {
697
+ stack[ra + 1] = f
698
+ stack[ra] = undefined
699
+ stack[ra + 2] = 0
700
+ } else throw fail('attempt to iterate over a ' + typeName(f) + ' value')
701
+ }
702
+ pc += insn >> 16
703
+ break
704
+ }
705
+
706
+ case 58: { // FORGLOOP
707
+ const aux = code[pc]
708
+ const t = stack[ra + 1]
709
+ if (stack[ra] === undefined && t instanceof LuaTable) {
710
+ const pos = stack[ra + 2]
711
+ if (aux < 0) {
712
+ // ipairs: stops at the first nil
713
+ const arr = t.arr
714
+ if (pos >= arr.length || arr[pos] === undefined) {
715
+ pc++
716
+ break
717
+ }
718
+ stack[ra + 2] = pos + 1
719
+ stack[ra + 3] = pos + 1
720
+ stack[ra + 4] = arr[pos]
721
+ for (let i = 2; i < (aux & 255); i++) stack[ra + 3 + i] = undefined
722
+ pc += insn >> 16
723
+ break
724
+ }
725
+ const next = t.advance(pos)
726
+ if (next === null) {
727
+ pc++
728
+ break
729
+ }
730
+ stack[ra + 2] = next
731
+ stack[ra + 3] = t.ck
732
+ stack[ra + 4] = t.cv
733
+ for (let i = 2; i < aux; i++) stack[ra + 3 + i] = undefined
734
+ pc += insn >> 16
735
+ break
736
+ }
737
+ const nvars = aux & 255
738
+ frame.pc = pc
739
+ const res = vm.call(stack[ra], [ stack[ra + 1], stack[ra + 2] ])
740
+ for (let i = 0; i < nvars; i++) stack[ra + 3 + i] = res[i]
741
+ stack[ra + 2] = stack[ra + 3]
742
+ if (stack[ra + 3] === undefined) pc++
743
+ else pc += insn >> 16
744
+ break
745
+ }
746
+
747
+ case 63: { // GETVARARGS
748
+ const b = (insn >> 16) & 255
749
+ const va = /** @type {any[]} */ (frame.varargs)
750
+ if (b === 0) {
751
+ while (stack.length < ra + va.length + 8) stack.push(undefined)
752
+ for (let i = 0; i < va.length; i++) stack[ra + i] = va[i]
753
+ top = ra + va.length
754
+ } else {
755
+ for (let i = 0; i < b - 1; i++) stack[ra + i] = va[i]
756
+ }
757
+ break
758
+ }
759
+
760
+ case 64: { // DUPCLOSURE
761
+ const p = /** @type {ClosureRef} */ (k[insn >> 16]).proto
762
+ /** @type {any[]} */
763
+ const ups = []
764
+ // the closure is in its register before its captures are read: a local function captures itself
765
+ stack[ra] = new LuaClosure(p, ups, cl.env)
766
+ for (let i = 0; i < p.numUpvals; i++) {
767
+ const cap = code[pc++]
768
+ const b = (cap >> 16) & 255
769
+ const kind = (cap >> 8) & 255
770
+ if (kind === 0) {
771
+ const uv = new Upvalue(stack, -1)
772
+ uv.s = null
773
+ uv.v = stack[base + b]
774
+ ups.push(uv)
775
+ } else if (kind === 1) ups.push(vm.findUpvalue(base + b))
776
+ else ups.push(upvals[b])
777
+ }
778
+ break
779
+ }
780
+
781
+ case 65: // PREPVARARGS: the frame was set up on entry
782
+ break
783
+
784
+ case 66: // LOADKX
785
+ stack[ra] = k[code[pc++]]
786
+ break
787
+
788
+ case 67: // JUMPX
789
+ pc += insn >> 8
790
+ break
791
+
792
+ case 68: // FASTCALL
793
+ case 73: // FASTCALL1
794
+ case 89: // FASTPCALL
795
+ // the builtin runs through the ordinary call that follows
796
+ break
797
+
798
+ case 60: // FASTCALL3
799
+ case 74: // FASTCALL2
800
+ case 75: // FASTCALL2K
801
+ pc++
802
+ break
803
+
804
+ case 77: { // JUMPXEQKNIL
805
+ const aux = code[pc]
806
+ if ((stack[ra] === undefined) !== (aux < 0)) pc += insn >> 16
807
+ else pc++
808
+ break
809
+ }
810
+
811
+ case 78: { // JUMPXEQKB
812
+ const aux = code[pc]
813
+ const v = stack[ra]
814
+ if ((typeof v === 'boolean' && v === ((aux & 1) !== 0)) !== (aux < 0)) pc += insn >> 16
815
+ else pc++
816
+ break
817
+ }
818
+
819
+ case 79: { // JUMPXEQKN
820
+ const aux = code[pc]
821
+ const v = stack[ra]
822
+ if ((typeof v === 'number' && v === k[aux & 0xffffff]) !== (aux < 0)) pc += insn >> 16
823
+ else pc++
824
+ break
825
+ }
826
+
827
+ case 80: { // JUMPXEQKS
828
+ const aux = code[pc]
829
+ if ((stack[ra] === k[aux & 0xffffff]) !== (aux < 0)) pc += insn >> 16
830
+ else pc++
831
+ break
832
+ }
833
+
834
+ default:
835
+ throw fail('unsupported opcode ' + (insn & 255), 0)
836
+ }
837
+ }
838
+ } catch (e) {
839
+ locate(vm, e, frame, pc)
840
+ throw e
841
+ }
842
+ }