@cimplify/cli 0.15.3 → 0.16.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 (120) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2 -2
  3. package/dist/add-SXC6RUPQ.mjs +140 -0
  4. package/dist/{add-KRIIKAS4.mjs → add-XQVQLD3F.mjs} +4 -4
  5. package/dist/ai-NQH5L4I6.mjs +17 -0
  6. package/dist/{assets-CWB72PZG.mjs → assets-FZGVOQXH.mjs} +12 -7
  7. package/dist/{auth-step-up-Z6KOTTV7.mjs → auth-step-up-67LCPDNL.mjs} +5 -5
  8. package/dist/build-J4ZUIOPX.mjs +625 -0
  9. package/dist/{cancel-ZHVVILOU.mjs → cancel-VGJHZJ4J.mjs} +4 -4
  10. package/dist/capture-RAJ2B3BH.mjs +69 -0
  11. package/dist/chunk-25ZPFHLF.mjs +51 -0
  12. package/dist/chunk-47ZXSY47.mjs +52 -0
  13. package/dist/{chunk-O2TO2J4I.mjs → chunk-54J3XR4T.mjs} +2 -2
  14. package/dist/chunk-5HP2INMY.mjs +10631 -0
  15. package/dist/chunk-7JR6JCFF.mjs +32 -0
  16. package/dist/chunk-7PQL7E7K.mjs +68 -0
  17. package/dist/chunk-AKACUJ3W.mjs +81 -0
  18. package/dist/chunk-BYNE553A.mjs +2945 -0
  19. package/dist/{chunk-NYXA6X56.mjs → chunk-CLQYPTJ2.mjs} +31 -11
  20. package/dist/chunk-CNZAOVSK.mjs +104 -0
  21. package/dist/chunk-CPBESPWK.mjs +5576 -0
  22. package/dist/{chunk-3RPR33MO.mjs → chunk-DYWUPHV3.mjs} +11 -7
  23. package/dist/chunk-EAV2P4N3.mjs +1941 -0
  24. package/dist/{chunk-UTD34C2H.mjs → chunk-EDZSOL5O.mjs} +2 -4
  25. package/dist/chunk-EGQIPYUN.mjs +696 -0
  26. package/dist/{chunk-DMLQBAGC.mjs → chunk-EOO4UOQD.mjs} +1 -1
  27. package/dist/chunk-EYEMPIMP.mjs +74 -0
  28. package/dist/chunk-G2ZEFSQJ.mjs +46 -0
  29. package/dist/{chunk-TH4XENKH.mjs → chunk-I4HNHPEM.mjs} +1 -1
  30. package/dist/chunk-JEVSFNPT.mjs +363 -0
  31. package/dist/chunk-JKECUAAV.mjs +2169 -0
  32. package/dist/chunk-KMHORI4Y.mjs +638 -0
  33. package/dist/chunk-KNPYBZ6B.mjs +502 -0
  34. package/dist/{chunk-3QUK5BPY.mjs → chunk-KOD4GBQ5.mjs} +8 -1
  35. package/dist/chunk-KQNZKV6E.mjs +535 -0
  36. package/dist/{chunk-2MKZKUVH.mjs → chunk-LLRUOIMU.mjs} +1 -2
  37. package/dist/{chunk-OLZKNUMK.mjs → chunk-LNMITJ4Z.mjs} +6 -6
  38. package/dist/chunk-MEM3MDV4.mjs +6463 -0
  39. package/dist/chunk-NY4YT7O6.mjs +84 -0
  40. package/dist/{chunk-LZEG3FEY.mjs → chunk-Q6CF4C3E.mjs} +7 -7
  41. package/dist/chunk-RP66A52P.mjs +86 -0
  42. package/dist/{chunk-I2UP7YTG.mjs → chunk-SAXGWS2K.mjs} +1 -1
  43. package/dist/chunk-SCKQ4XSD.mjs +41 -0
  44. package/dist/chunk-SF44L2OD.mjs +1152 -0
  45. package/dist/chunk-SGT5IJVW.mjs +28 -0
  46. package/dist/{chunk-LJEKKFC7.mjs → chunk-SS4JTMIV.mjs} +8 -8
  47. package/dist/chunk-T4MW3PD4.mjs +1456 -0
  48. package/dist/chunk-THATLMEX.mjs +1227 -0
  49. package/dist/{chunk-MLE4MVYC.mjs → chunk-TT4YI33G.mjs} +2 -2
  50. package/dist/chunk-TYV2SVFN.mjs +101 -0
  51. package/dist/chunk-VHK7WBO3.mjs +189 -0
  52. package/dist/chunk-VSA44UKR.mjs +391 -0
  53. package/dist/chunk-XL54SQJ3.mjs +42 -0
  54. package/dist/{chunk-5KYR6WJB.mjs → chunk-XQAHREKO.mjs} +17 -1
  55. package/dist/chunk-ZUCDXRFI.mjs +2011 -0
  56. package/dist/create-4S2EAUR3.mjs +10 -0
  57. package/dist/credits-NJOAOPPW.mjs +33 -0
  58. package/dist/{deploy-STWZ3OSM.mjs → deploy-26Y4UGZZ.mjs} +11 -11
  59. package/dist/dev-MOYURRWQ.mjs +401 -0
  60. package/dist/dev-WL43Q7VD.mjs +8 -0
  61. package/dist/dispatcher.mjs +131 -30
  62. package/dist/{doctor-3RW3OGZJ.mjs → doctor-E6ETD2GJ.mjs} +12 -20
  63. package/dist/{domains-FTNK4IKY.mjs → domains-LOTQMVOR.mjs} +6 -6
  64. package/dist/engine-runtime-fetch-CIE7S7PB.mjs +10 -0
  65. package/dist/{env-TNCYUAMT.mjs → env-3PDFC5XF.mjs} +7 -7
  66. package/dist/env-MOTYOPM5.mjs +19 -0
  67. package/dist/explain-K5QEVWCD.mjs +251 -0
  68. package/dist/{inspect-X3M7WSTL.mjs → inspect-Q3E2DHYY.mjs} +3 -3
  69. package/dist/inspect-SJ4WBAXO.mjs +86 -0
  70. package/dist/introspect-7F34YN5V.mjs +9 -0
  71. package/dist/kernel-DEGWMHFL.mjs +662 -0
  72. package/dist/kernel-plugin.js +6862 -0
  73. package/dist/keys-W5SN3DPK.mjs +71 -0
  74. package/dist/lines-XGJYTQ7P.mjs +56 -0
  75. package/dist/{link-76Z6V6CJ.mjs → link-NKUAVNM2.mjs} +6 -6
  76. package/dist/{lint-DDZ7HUQN.mjs → lint-G4YPQSSO.mjs} +2 -2
  77. package/dist/{list-2MFOQKKQ.mjs → list-TDR7K2JB.mjs} +3 -3
  78. package/dist/lock-EJPW2LM3.mjs +57 -0
  79. package/dist/{login-RLMDEWAL.mjs → login-AYLU7JU7.mjs} +10 -8
  80. package/dist/{logout-Z57X6HPE.mjs → logout-3M6VMHLH.mjs} +2 -2
  81. package/dist/{logs-TNDM4RFE.mjs → logs-4EL5SOXN.mjs} +5 -5
  82. package/dist/logs-4QQGG2XY.mjs +44 -0
  83. package/dist/mcp-4R2R6E5M.mjs +1077 -0
  84. package/dist/{mock-EVER34IX.mjs → mock-AK24GSP2.mjs} +2 -2
  85. package/dist/outdated-JEKCVLTG.mjs +58 -0
  86. package/dist/port-SBZ7X3EH.mjs +2408 -0
  87. package/dist/{projects-YL4T24VV.mjs → projects-7JKTC5WJ.mjs} +6 -6
  88. package/dist/publish-QQCX47HK.mjs +20 -0
  89. package/dist/remix-NLLYD3BI.mjs +125 -0
  90. package/dist/repo-Z4G4EW3N.mjs +9 -0
  91. package/dist/report-M7F4ZYP7.mjs +2 -0
  92. package/dist/rollback-2WQ2CW7T.mjs +43 -0
  93. package/dist/{rollback-47VQ4HJK.mjs → rollback-ZGU32HGT.mjs} +6 -6
  94. package/dist/scene-HXARHUM7.mjs +324 -0
  95. package/dist/{status-TWPOMWNA.mjs → status-C3ZSLZ7Q.mjs} +5 -5
  96. package/dist/status-WEQOC25K.mjs +18 -0
  97. package/dist/test-ZPBWV4VX.mjs +233 -0
  98. package/dist/testers-A3LMXOJJ.mjs +49 -0
  99. package/dist/{unlink-H3BO3DOQ.mjs → unlink-4G4FE4RJ.mjs} +2 -2
  100. package/dist/{update-FLY46XI3.mjs → update-GHKKM5FS.mjs} +4 -4
  101. package/dist/{whoami-CQPPARRS.mjs → whoami-3QQN6G2A.mjs} +3 -3
  102. package/dist/workshop-CD74D2LK.mjs +1703 -0
  103. package/package.json +11 -7
  104. package/templates/storefront-auto/app/products/[slug]/page.tsx +1 -1
  105. package/templates/storefront-auto/package.json +1 -1
  106. package/templates/storefront-bakery/package.json +1 -1
  107. package/templates/storefront-fashion/app/products/[slug]/page.tsx +1 -1
  108. package/templates/storefront-fashion/package.json +1 -1
  109. package/templates/storefront-grocery/package.json +1 -1
  110. package/templates/storefront-pharmacy/app/products/[slug]/page.tsx +1 -1
  111. package/templates/storefront-pharmacy/package.json +1 -1
  112. package/templates/storefront-restaurant/package.json +1 -1
  113. package/templates/storefront-retail/app/products/[slug]/page.tsx +1 -1
  114. package/templates/storefront-retail/package.json +1 -1
  115. package/templates/storefront-services/package.json +1 -1
  116. package/dist/chunk-ARIDYKLO.mjs +0 -6463
  117. package/dist/dev-7O65HY6C.mjs +0 -8
  118. package/dist/explain-DLRUUCNS.mjs +0 -251
  119. package/dist/introspect-RC265ACF.mjs +0 -9
  120. package/dist/repo-UUT3AZ3L.mjs +0 -9
@@ -0,0 +1,2169 @@
1
+ #!/usr/bin/env node
2
+ import { diagnostic } from './chunk-SGT5IJVW.mjs';
3
+ import { gunzipSync, constants } from 'zlib';
4
+ import ts from 'typescript';
5
+
6
+ var NATIVE_MAGIC = [
7
+ { bytes: [127, 69, 76, 70], what: "an ELF native binary" },
8
+ { bytes: [254, 237, 250, 206], what: "a Mach-O native binary" },
9
+ { bytes: [254, 237, 250, 207], what: "a Mach-O native binary" },
10
+ { bytes: [206, 250, 237, 254], what: "a Mach-O native binary" },
11
+ { bytes: [207, 250, 237, 254], what: "a Mach-O native binary" },
12
+ { bytes: [202, 254, 186, 190], what: "a universal binary or Java class file" },
13
+ { bytes: [77, 90], what: "a Windows executable" },
14
+ { bytes: [100, 101, 120, 10], what: "Android bytecode" },
15
+ { bytes: [198, 31, 188, 3, 193, 3, 25, 31], what: "Hermes bytecode" },
16
+ { bytes: [71, 68, 80, 67], what: "an exported Godot pack" }
17
+ ];
18
+ var ARCHIVE_MAGIC = [
19
+ { bytes: [80, 75, 3, 4], what: "a zip archive" },
20
+ { bytes: [31, 139], what: "a gzip archive" },
21
+ { bytes: [66, 90, 104], what: "a bzip2 archive" },
22
+ { bytes: [253, 55, 122, 88, 90, 0], what: "an xz archive" },
23
+ { bytes: [55, 122, 188, 175, 39, 28], what: "a 7z archive" },
24
+ { bytes: [40, 181, 47, 253], what: "a zstd archive" }
25
+ ];
26
+ var WASM_MAGIC = [0, 97, 115, 109];
27
+ var GZIP_MAGIC = [31, 139];
28
+ var SPZ_MAGIC = [78, 71, 83, 80];
29
+ var SPZ_EXTENSION = ".spz";
30
+ var SPZ_PROBE_BYTES = 4096;
31
+ var REFUSED_EXTENSIONS = {
32
+ ".node": "a native addon",
33
+ ".so": "a native library",
34
+ ".dylib": "a native library",
35
+ ".dll": "a native library",
36
+ ".exe": "a native executable",
37
+ ".a": "a native archive",
38
+ ".o": "a native object file",
39
+ ".lib": "a native library",
40
+ ".jsc": "compiled JavaScript bytecode",
41
+ ".hbc": "Hermes bytecode",
42
+ ".pck": "an exported Godot pack",
43
+ ".class": "Java bytecode",
44
+ ".jar": "a Java archive",
45
+ ".dex": "Android bytecode",
46
+ ".pyc": "Python bytecode",
47
+ ".bin": "an opaque binary",
48
+ ".zip": "an archive",
49
+ ".tar": "an archive",
50
+ ".tgz": "an archive",
51
+ ".gz": "an archive"
52
+ };
53
+ var CODE_EXTENSIONS = /* @__PURE__ */ new Set([".ts", ".mts", ".cts", ".tsx", ".js", ".mjs", ".cjs", ".jsx"]);
54
+ var MAX_LINE_CHARS = 1e3;
55
+ var DENSE_FILE_BYTES = 4096;
56
+ var MIN_WHITESPACE_RATIO = 0.06;
57
+ var MAX_HEX_IDENTIFIERS = 4;
58
+ var MAX_ESCAPES = 64;
59
+ var MAX_STRING_LITERAL_CHARS = 8192;
60
+ var MAX_CHAR_CODE_ARGS = 24;
61
+ var HEX_IDENTIFIER = /\b_0x[0-9a-fA-F]{4,}\b/g;
62
+ var ESCAPE_SEQUENCE = /\\x[0-9a-fA-F]{2}|\\u[0-9a-fA-F]{4}/g;
63
+ var CHAR_CODE_CALL = /String\.fromCharCode\(([^)]*)\)/g;
64
+ var BUNDLE_SIGNATURES = ["__webpack_require__", "parcelRequire", "__vite_ssr_import__", "System.register("];
65
+ var LONG_STRING = new RegExp(`(["'\`])[A-Za-z0-9+/=_-]{${MAX_STRING_LITERAL_CHARS},}\\1`);
66
+ var CH_LF = 10;
67
+ var CH_SPACE = 32;
68
+ var CH_TAB = 9;
69
+ var CH_CR = 13;
70
+ function extensionOf(filePath) {
71
+ const slash = filePath.lastIndexOf("/");
72
+ const dot = filePath.lastIndexOf(".");
73
+ return dot > slash + 1 ? filePath.slice(dot).toLowerCase() : "";
74
+ }
75
+ function isCodePath(filePath) {
76
+ return CODE_EXTENSIONS.has(extensionOf(filePath));
77
+ }
78
+ function startsWith(bytes, magic) {
79
+ if (bytes.length < magic.length) return false;
80
+ for (let i = 0; i < magic.length; i++) if (bytes[i] !== magic[i]) return false;
81
+ return true;
82
+ }
83
+ function isWasm(file) {
84
+ return extensionOf(file.path) === ".wasm" || startsWith(file.bytes, WASM_MAGIC);
85
+ }
86
+ function isGzipSpz(file) {
87
+ if (extensionOf(file.path) !== SPZ_EXTENSION || !startsWith(file.bytes, GZIP_MAGIC)) return false;
88
+ try {
89
+ const head = gunzipSync(file.bytes.subarray(0, SPZ_PROBE_BYTES), { finishFlush: constants.Z_SYNC_FLUSH });
90
+ return startsWith(head, SPZ_MAGIC);
91
+ } catch {
92
+ return false;
93
+ }
94
+ }
95
+ function binaryRefusal(file) {
96
+ const byExtension = REFUSED_EXTENSIONS[extensionOf(file.path)];
97
+ if (byExtension !== void 0) return byExtension;
98
+ for (const m of NATIVE_MAGIC) if (startsWith(file.bytes, m.bytes)) return m.what;
99
+ if (isGzipSpz(file)) return null;
100
+ for (const m of ARCHIVE_MAGIC) if (startsWith(file.bytes, m.bytes)) return m.what;
101
+ return null;
102
+ }
103
+ function denseShape(bytes) {
104
+ let longest = 0;
105
+ let longestLineNumber = 1;
106
+ let current = 0;
107
+ let line = 1;
108
+ let whitespace = 0;
109
+ for (let i = 0; i < bytes.length; i++) {
110
+ const c = bytes[i];
111
+ if (c === CH_LF) {
112
+ if (current > longest) {
113
+ longest = current;
114
+ longestLineNumber = line;
115
+ }
116
+ current = 0;
117
+ line++;
118
+ whitespace++;
119
+ continue;
120
+ }
121
+ if (c === CH_SPACE || c === CH_TAB || c === CH_CR) whitespace++;
122
+ current++;
123
+ }
124
+ if (current > longest) {
125
+ longest = current;
126
+ longestLineNumber = line;
127
+ }
128
+ return { longestLine: longest, longestLineNumber, whitespace };
129
+ }
130
+ function countMatches(text, pattern) {
131
+ pattern.lastIndex = 0;
132
+ let n = 0;
133
+ while (pattern.exec(text) !== null) n++;
134
+ return n;
135
+ }
136
+ function obfuscationReason(text) {
137
+ for (const signature of BUNDLE_SIGNATURES) {
138
+ if (text.includes(signature)) return `it is bundler output (${signature}); upload the original source`;
139
+ }
140
+ if (countMatches(text, HEX_IDENTIFIER) > MAX_HEX_IDENTIFIERS) return "it uses machine-generated _0x identifiers";
141
+ if (countMatches(text, ESCAPE_SEQUENCE) > MAX_ESCAPES) return "it hides text behind escape sequences";
142
+ CHAR_CODE_CALL.lastIndex = 0;
143
+ for (let m = CHAR_CODE_CALL.exec(text); m !== null; m = CHAR_CODE_CALL.exec(text)) {
144
+ if (m[1].split(",").length > MAX_CHAR_CODE_ARGS) return "it builds strings from character codes";
145
+ }
146
+ if (LONG_STRING.test(text)) return "it embeds an encoded payload in a string literal";
147
+ return null;
148
+ }
149
+ function checkRefusals(files, wasm) {
150
+ const out = [];
151
+ for (const file of files) {
152
+ if (isWasm(file)) {
153
+ if (!wasm.approved(file.digest)) {
154
+ out.push(
155
+ diagnostic(
156
+ "refusal.wasm",
157
+ `WebAssembly module ${file.digest} is not in the approved module registry; WASM is admitted only when Cimplify built it from reviewed source`,
158
+ file.path,
159
+ null
160
+ )
161
+ );
162
+ }
163
+ continue;
164
+ }
165
+ const binary = binaryRefusal(file);
166
+ if (binary !== null) {
167
+ out.push(diagnostic("refusal.binary", `this file is ${binary}; upload source, never binaries or bytecode`, file.path, null));
168
+ continue;
169
+ }
170
+ if (!isCodePath(file.path)) continue;
171
+ const shape = denseShape(file.bytes);
172
+ if (shape.longestLine > MAX_LINE_CHARS) {
173
+ out.push(
174
+ diagnostic(
175
+ "refusal.minified",
176
+ `line ${shape.longestLineNumber} is ${shape.longestLine} characters; minified code is refused, upload the original source`,
177
+ file.path,
178
+ { line: shape.longestLineNumber, column: 1 }
179
+ )
180
+ );
181
+ continue;
182
+ }
183
+ if (file.bytes.length > DENSE_FILE_BYTES && shape.whitespace / file.bytes.length < MIN_WHITESPACE_RATIO) {
184
+ out.push(diagnostic("refusal.minified", "this file has almost no whitespace; minified code is refused", file.path, null));
185
+ continue;
186
+ }
187
+ const reason = obfuscationReason(file.bytes.toString("utf8"));
188
+ if (reason !== null) out.push(diagnostic("refusal.obfuscated", `obfuscated code is refused: ${reason}`, file.path, null));
189
+ }
190
+ return out;
191
+ }
192
+
193
+ // src/interactives/build/assets.ts
194
+ var KIND_BY_EXTENSION = {
195
+ ".png": "texture",
196
+ ".jpg": "texture",
197
+ ".jpeg": "texture",
198
+ ".webp": "texture",
199
+ ".avif": "texture",
200
+ ".ktx2": "texture",
201
+ ".basis": "texture",
202
+ ".gltf": "mesh",
203
+ ".glb": "mesh",
204
+ ".ogg": "audio",
205
+ ".opus": "audio",
206
+ ".mp3": "audio",
207
+ ".m4a": "audio",
208
+ ".aac": "audio",
209
+ ".wav": "audio",
210
+ ".ttf": "font",
211
+ ".otf": "font",
212
+ ".woff": "font",
213
+ ".woff2": "font",
214
+ ".wasm": "wasm"
215
+ };
216
+ function assetKind(path) {
217
+ return KIND_BY_EXTENSION[extensionOf(path)] ?? "data";
218
+ }
219
+ var PASSTHROUGH_CONVERTER = {
220
+ id: "passthrough@1",
221
+ convert(path, bytes) {
222
+ return { path, kind: assetKind(path), bytes };
223
+ }
224
+ };
225
+ var GLOB_SPECIAL = /[.+^${}()|[\]\\]/g;
226
+ function compileGlob(pattern) {
227
+ let out = "^";
228
+ for (let i = 0; i < pattern.length; i++) {
229
+ const c = pattern[i];
230
+ if (c === "*") {
231
+ if (pattern[i + 1] === "*") {
232
+ i++;
233
+ if (pattern[i + 1] === "/") {
234
+ i++;
235
+ out += "(?:[^/]+/)*";
236
+ } else {
237
+ out += ".*";
238
+ }
239
+ } else {
240
+ out += "[^/]*";
241
+ }
242
+ } else if (c === "?") {
243
+ out += "[^/]";
244
+ } else {
245
+ out += c.replace(GLOB_SPECIAL, "\\$&");
246
+ }
247
+ }
248
+ return new RegExp(`${out}$`);
249
+ }
250
+ function compileGroups(groups) {
251
+ return { groups, matchers: groups.map((g) => g.assets.map(compileGlob)) };
252
+ }
253
+ function groupOf(compiled, path) {
254
+ for (let g = 0; g < compiled.matchers.length; g++) {
255
+ const patterns = compiled.matchers[g];
256
+ for (let p = 0; p < patterns.length; p++) if (patterns[p].test(path)) return g;
257
+ }
258
+ return -1;
259
+ }
260
+
261
+ // src/interactives/scripting/ts/bytecode.ts
262
+ var BYTECODE_VERSION = 6;
263
+ var TYPES_VERSION = 1;
264
+ var VARINT_PAYLOAD = 127;
265
+ var VARINT_CONTINUE = 128;
266
+ var VARINT_SHIFT = 7;
267
+ var LINE_GAP_LOG2 = 0;
268
+ var LINEINFO_PRESENT = 1;
269
+ var DEBUGINFO_ABSENT = 0;
270
+ var BYTE_MASK = 255;
271
+ var NUMBER_BYTES = 8;
272
+ var WORD_BYTES = 4;
273
+ var ConstantTag = {
274
+ NIL: 0,
275
+ BOOLEAN: 1,
276
+ NUMBER: 2,
277
+ STRING: 3
278
+ };
279
+ var Out = class {
280
+ bytes = [];
281
+ u8(value) {
282
+ this.bytes.push(value & BYTE_MASK);
283
+ }
284
+ u32(value) {
285
+ for (let i = 0; i < WORD_BYTES; i++) this.u8(value >>> i * 8);
286
+ }
287
+ i32(value) {
288
+ this.u32(value | 0);
289
+ }
290
+ f64(value) {
291
+ const view = new DataView(new ArrayBuffer(NUMBER_BYTES));
292
+ view.setFloat64(0, value, true);
293
+ for (let i = 0; i < NUMBER_BYTES; i++) this.u8(view.getUint8(i));
294
+ }
295
+ varint(value) {
296
+ let v = value >>> 0;
297
+ do {
298
+ let byte = v & VARINT_PAYLOAD;
299
+ v >>>= VARINT_SHIFT;
300
+ if (v !== 0) byte |= VARINT_CONTINUE;
301
+ this.u8(byte);
302
+ } while (v !== 0);
303
+ }
304
+ raw(data) {
305
+ for (const b of data) this.bytes.push(b);
306
+ }
307
+ finish() {
308
+ return Uint8Array.from(this.bytes);
309
+ }
310
+ };
311
+ var StringTable = class {
312
+ index = /* @__PURE__ */ new Map();
313
+ list = [];
314
+ ref(value) {
315
+ const found = this.index.get(value);
316
+ if (found !== void 0) return found;
317
+ this.list.push(value);
318
+ const id = this.list.length;
319
+ this.index.set(value, id);
320
+ return id;
321
+ }
322
+ };
323
+ function utf8(value) {
324
+ return new TextEncoder().encode(value);
325
+ }
326
+ function writeLines(out, lines) {
327
+ out.u8(LINEINFO_PRESENT);
328
+ out.u8(LINE_GAP_LOG2);
329
+ for (let j = 0; j < lines.length; j++) out.u8(0);
330
+ let previous = 0;
331
+ for (const line of lines) {
332
+ out.i32(line - previous);
333
+ previous = line;
334
+ }
335
+ }
336
+ function writeBytecode(protos, main) {
337
+ const strings = new StringTable();
338
+ for (const proto of protos) {
339
+ for (const k of proto.constants) if (k.kind === "string") strings.ref(k.value);
340
+ if (proto.debugName !== null) strings.ref(proto.debugName);
341
+ }
342
+ const out = new Out();
343
+ out.u8(BYTECODE_VERSION);
344
+ out.u8(TYPES_VERSION);
345
+ out.varint(strings.list.length);
346
+ for (const s of strings.list) {
347
+ const bytes = utf8(s);
348
+ out.varint(bytes.length);
349
+ out.raw(bytes);
350
+ }
351
+ out.varint(protos.length);
352
+ for (const proto of protos) {
353
+ out.u8(proto.maxStackSize);
354
+ out.u8(proto.numParams);
355
+ out.u8(proto.numUpvalues);
356
+ out.u8(proto.isVararg ? 1 : 0);
357
+ out.u8(0);
358
+ out.varint(0);
359
+ out.varint(proto.code.length);
360
+ for (const word of proto.code) out.u32(word);
361
+ out.varint(proto.constants.length);
362
+ for (const k of proto.constants) {
363
+ switch (k.kind) {
364
+ case "nil":
365
+ out.u8(ConstantTag.NIL);
366
+ break;
367
+ case "boolean":
368
+ out.u8(ConstantTag.BOOLEAN);
369
+ out.u8(k.value ? 1 : 0);
370
+ break;
371
+ case "number":
372
+ out.u8(ConstantTag.NUMBER);
373
+ out.f64(k.value);
374
+ break;
375
+ case "string":
376
+ out.u8(ConstantTag.STRING);
377
+ out.varint(strings.ref(k.value));
378
+ break;
379
+ }
380
+ }
381
+ out.varint(proto.children.length);
382
+ for (const child of proto.children) out.varint(child);
383
+ out.varint(proto.lineDefined);
384
+ out.varint(proto.debugName === null ? 0 : strings.ref(proto.debugName));
385
+ writeLines(out, proto.lines);
386
+ out.u8(DEBUGINFO_ABSENT);
387
+ }
388
+ out.varint(main);
389
+ return out.finish();
390
+ }
391
+
392
+ // src/interactives/scripting/ts/lib.ts
393
+ var LIB_FILE = "rive.d.ts";
394
+ var GLOBAL_RENAMES = /* @__PURE__ */ new Map([["Math", "math"]]);
395
+ var MATH_RENAMES = /* @__PURE__ */ new Map([["PI", "pi"]]);
396
+ var TOOL_LIB_SOURCE = `
397
+ interface ProductionRead {
398
+ id?: string | number;
399
+ depth?: number;
400
+ }
401
+ interface Production {
402
+ readonly kinds: () => any;
403
+ readonly read: (request?: ProductionRead) => any;
404
+ readonly edit: (changes: object[]) => any;
405
+ readonly undo: () => any;
406
+ readonly redo: () => any;
407
+ }
408
+ declare const production: Production;
409
+ `;
410
+ var LIB_SOURCE = `
411
+ interface Array<T> {
412
+ length: number;
413
+ [n: number]: T;
414
+ push(item: T): number;
415
+ pop(): T | undefined;
416
+ }
417
+ interface ReadonlyArray<T> {
418
+ readonly length: number;
419
+ readonly [n: number]: T;
420
+ }
421
+ interface Boolean {}
422
+ interface Function {}
423
+ interface CallableFunction {}
424
+ interface NewableFunction {}
425
+ interface IArguments {}
426
+ interface Number {}
427
+ interface Object {}
428
+ interface RegExp {}
429
+ interface String {
430
+ readonly length: number;
431
+ toUpperCase(): string;
432
+ toLowerCase(): string;
433
+ substring(start: number, end?: number): string;
434
+ }
435
+ interface TemplateStringsArray extends ReadonlyArray<string> {}
436
+ type Record<K extends string, T> = { [P in K]: T };
437
+ type Partial<T> = { [P in keyof T]?: T[P] };
438
+
439
+ interface Math {
440
+ readonly PI: number;
441
+ abs(x: number): number;
442
+ acos(x: number): number;
443
+ asin(x: number): number;
444
+ atan(x: number): number;
445
+ atan2(y: number, x: number): number;
446
+ ceil(x: number): number;
447
+ cos(x: number): number;
448
+ exp(x: number): number;
449
+ floor(x: number): number;
450
+ log(x: number): number;
451
+ max(...values: number[]): number;
452
+ min(...values: number[]): number;
453
+ pow(x: number, y: number): number;
454
+ sin(x: number): number;
455
+ sqrt(x: number): number;
456
+ tan(x: number): number;
457
+ }
458
+ declare const Math: Math;
459
+ declare function print(...values: unknown[]): void;
460
+ declare function tostring(value: unknown): string;
461
+
462
+ declare class Vector {
463
+ private constructor();
464
+ static xy(x: number, y: number): Vector;
465
+ readonly x: number;
466
+ readonly y: number;
467
+ }
468
+
469
+ declare class Mat2D {
470
+ private constructor();
471
+ static identity(): Mat2D;
472
+ static withTranslation(x: number, y: number): Mat2D;
473
+ static withRotation(radians: number): Mat2D;
474
+ static withScale(x: number, y: number): Mat2D;
475
+ xx: number;
476
+ xy: number;
477
+ yx: number;
478
+ yy: number;
479
+ tx: number;
480
+ ty: number;
481
+ }
482
+
483
+ declare class Color {
484
+ private constructor();
485
+ static rgb(r: number, g: number, b: number): number;
486
+ static rgba(r: number, g: number, b: number, a: number): number;
487
+ static lerp(from: number, to: number, t: number): number;
488
+ }
489
+
490
+ declare class Path {
491
+ private constructor();
492
+ static new(): Path;
493
+ moveTo(point: Vector): void;
494
+ lineTo(point: Vector): void;
495
+ quadTo(control: Vector, to: Vector): void;
496
+ cubicTo(first: Vector, second: Vector, to: Vector): void;
497
+ close(): void;
498
+ reset(): void;
499
+ }
500
+
501
+ interface PaintDescription {
502
+ color?: number;
503
+ thickness?: number;
504
+ style?: "fill" | "stroke";
505
+ }
506
+
507
+ declare class Paint {
508
+ private constructor();
509
+ static new(): Paint;
510
+ static with(description: PaintDescription): Paint;
511
+ color: number;
512
+ thickness: number;
513
+ style: "fill" | "stroke";
514
+ }
515
+
516
+ declare class Renderer {
517
+ private constructor();
518
+ drawPath(path: Path, paint: Paint): void;
519
+ clipPath(path: Path): void;
520
+ save(): void;
521
+ restore(): void;
522
+ transform(matrix: Mat2D): void;
523
+ }
524
+
525
+ declare class NumberProperty {
526
+ private constructor();
527
+ value: number;
528
+ }
529
+
530
+ declare class StringProperty {
531
+ private constructor();
532
+ value: string;
533
+ }
534
+
535
+ declare class BooleanProperty {
536
+ private constructor();
537
+ value: boolean;
538
+ }
539
+
540
+ declare class ViewModel {
541
+ private constructor();
542
+ getNumber(name: string): NumberProperty | undefined;
543
+ getString(name: string): StringProperty | undefined;
544
+ getBoolean(name: string): BooleanProperty | undefined;
545
+ }
546
+
547
+ declare class Context {
548
+ private constructor();
549
+ viewModel(): ViewModel | undefined;
550
+ markNeedsUpdate(): void;
551
+ }
552
+ `;
553
+
554
+ // src/interactives/scripting/ts/emit.ts
555
+ var Op = {
556
+ LOADNIL: 2,
557
+ LOADB: 3,
558
+ LOADN: 4,
559
+ LOADK: 5,
560
+ MOVE: 6,
561
+ GETGLOBAL: 7,
562
+ SETGLOBAL: 8,
563
+ GETUPVAL: 9,
564
+ SETUPVAL: 10,
565
+ CLOSEUPVALS: 11,
566
+ GETTABLE: 13,
567
+ SETTABLE: 14,
568
+ GETTABLEKS: 15,
569
+ SETTABLEKS: 16,
570
+ NEWCLOSURE: 19,
571
+ NAMECALL: 20,
572
+ CALL: 21,
573
+ RETURN: 22,
574
+ JUMP: 23,
575
+ JUMPBACK: 24,
576
+ JUMPIFNOT: 26,
577
+ JUMPIFEQ: 27,
578
+ JUMPIFLE: 28,
579
+ JUMPIFLT: 29,
580
+ JUMPIFNOTEQ: 30,
581
+ JUMPIFNOTLE: 31,
582
+ JUMPIFNOTLT: 32,
583
+ ADD: 33,
584
+ SUB: 34,
585
+ MUL: 35,
586
+ DIV: 36,
587
+ POW: 38,
588
+ ADDK: 39,
589
+ SUBK: 40,
590
+ CONCAT: 49,
591
+ MINUS: 51,
592
+ LENGTH: 52,
593
+ NEWTABLE: 53,
594
+ SETLIST: 55,
595
+ PREPVARARGS: 65,
596
+ CAPTURE: 70
597
+ };
598
+ var CAPTURE_REF = 1;
599
+ var CAPTURE_UPVAL = 2;
600
+ var MAX_REGISTERS = 255;
601
+ var MAX_UPVALUES = 200;
602
+ var MAX_ARGUMENT = 255;
603
+ var LOADN_MIN = -32768;
604
+ var LOADN_MAX = 32767;
605
+ var D_MIN = -32768;
606
+ var D_MAX = 32767;
607
+ var A_SHIFT = 8;
608
+ var B_SHIFT = 16;
609
+ var C_SHIFT = 24;
610
+ var BYTE = 255;
611
+ var D_MASK = 65535;
612
+ var TWO_WORD_OPS = /* @__PURE__ */ new Set([
613
+ Op.GETGLOBAL,
614
+ Op.SETGLOBAL,
615
+ Op.GETTABLEKS,
616
+ Op.SETTABLEKS,
617
+ Op.NAMECALL,
618
+ Op.JUMPIFEQ,
619
+ Op.JUMPIFLE,
620
+ Op.JUMPIFLT,
621
+ Op.JUMPIFNOTEQ,
622
+ Op.JUMPIFNOTLE,
623
+ Op.JUMPIFNOTLT,
624
+ Op.NEWTABLE,
625
+ Op.SETLIST
626
+ ]);
627
+ var CompileLimit = class extends Error {
628
+ };
629
+ function field(value, what) {
630
+ if (value < 0 || value > MAX_ARGUMENT) throw new CompileLimit(`${what} ${value} does not fit in a byte`);
631
+ return value;
632
+ }
633
+ function abc(op, a, b, c) {
634
+ return (op | field(a, "A") << A_SHIFT | field(b, "B") << B_SHIFT | field(c, "C") << C_SHIFT) >>> 0;
635
+ }
636
+ function ad(op, a, d) {
637
+ if (d < D_MIN || d > D_MAX) throw new CompileLimit(`jump or constant ${d} does not fit in 16 bits`);
638
+ return (op | field(a, "A") << A_SHIFT | (d & D_MASK) << B_SHIFT) >>> 0;
639
+ }
640
+ var FunctionBuilder = class {
641
+ constructor(numParams, isVararg, debugName, lineDefined) {
642
+ this.numParams = numParams;
643
+ this.isVararg = isVararg;
644
+ this.debugName = debugName;
645
+ this.lineDefined = lineDefined;
646
+ this.top = numParams;
647
+ this.maxStack = numParams;
648
+ }
649
+ numParams;
650
+ isVararg;
651
+ debugName;
652
+ lineDefined;
653
+ code = [];
654
+ lines = [];
655
+ constants = [];
656
+ children = [];
657
+ upvalues = [];
658
+ constantIndex = /* @__PURE__ */ new Map();
659
+ top = 0;
660
+ maxStack = 0;
661
+ line = 1;
662
+ lastLabel = -1;
663
+ push(word) {
664
+ this.code.push(word);
665
+ this.lines.push(this.line);
666
+ return this.code.length - 1;
667
+ }
668
+ emit(word, aux) {
669
+ const at = this.push(word);
670
+ const op = word & BYTE;
671
+ if (TWO_WORD_OPS.has(op)) this.push(aux ?? 0);
672
+ return at;
673
+ }
674
+ reserve(count) {
675
+ const base = this.top;
676
+ this.top += count;
677
+ if (this.top > MAX_REGISTERS) throw new CompileLimit("the function needs more than 255 registers");
678
+ if (this.top > this.maxStack) this.maxStack = this.top;
679
+ return base;
680
+ }
681
+ release(mark) {
682
+ this.top = mark;
683
+ }
684
+ constant(k) {
685
+ const key = k.kind === "number" ? `n:${Object.is(k.value, -0) ? "-0" : String(k.value)}` : k.kind === "string" ? `s:${k.value}` : k.kind === "boolean" ? `b:${k.value}` : "nil";
686
+ const found = this.constantIndex.get(key);
687
+ if (found !== void 0) return found;
688
+ this.constants.push(k);
689
+ const index = this.constants.length - 1;
690
+ this.constantIndex.set(key, index);
691
+ return index;
692
+ }
693
+ string(value) {
694
+ return this.constant({ kind: "string", value });
695
+ }
696
+ number(value) {
697
+ return this.constant({ kind: "number", value });
698
+ }
699
+ loadNumber(target, value) {
700
+ if (Number.isInteger(value) && value >= LOADN_MIN && value <= LOADN_MAX && !Object.is(value, -0)) {
701
+ this.emit(ad(Op.LOADN, target, value));
702
+ } else {
703
+ this.emit(ad(Op.LOADK, target, this.number(value)));
704
+ }
705
+ }
706
+ loadString(target, value) {
707
+ this.emit(ad(Op.LOADK, target, this.string(value)));
708
+ }
709
+ label() {
710
+ return { target: -1, patches: [] };
711
+ }
712
+ here(label) {
713
+ label.target = this.code.length;
714
+ this.lastLabel = label.target;
715
+ for (const at of label.patches) this.patch(at, label.target);
716
+ }
717
+ patch(at, target) {
718
+ const word = this.code[at];
719
+ const op = word & BYTE;
720
+ const delta = target - (at + 1);
721
+ if (delta < D_MIN || delta > D_MAX) throw new CompileLimit("a jump spans more than 32767 instructions");
722
+ this.code[at] = (word & D_MASK | (delta & D_MASK) << B_SHIFT) >>> 0;
723
+ if (op === Op.JUMP && delta <= 0) this.code[at] = (this.code[at] & ~BYTE | Op.JUMPBACK) >>> 0;
724
+ }
725
+ jumpTo(op, a, label, aux) {
726
+ const at = this.emit(ad(op, a, 0), aux);
727
+ if (label.target >= 0) {
728
+ const delta = label.target - (at + 1);
729
+ if (op !== Op.JUMP && delta <= 0) throw new CompileLimit("a conditional jump goes backwards");
730
+ this.patch(at, label.target);
731
+ } else {
732
+ label.patches.push(at);
733
+ }
734
+ }
735
+ jump(label) {
736
+ this.jumpTo(Op.JUMP, 0, label);
737
+ }
738
+ upvalue(ref) {
739
+ const found = this.upvalues.findIndex((u) => u.kind === ref.kind && u.index === ref.index);
740
+ if (found >= 0) return found;
741
+ if (this.upvalues.length >= MAX_UPVALUES) throw new CompileLimit("a function captures more than 200 upvalues");
742
+ this.upvalues.push(ref);
743
+ return this.upvalues.length - 1;
744
+ }
745
+ endsWithTerminator() {
746
+ if (this.code.length === 0) return false;
747
+ let pc = 0;
748
+ let last = -1;
749
+ while (pc < this.code.length) {
750
+ last = pc;
751
+ pc += TWO_WORD_OPS.has(this.code[pc] & BYTE) ? 2 : 1;
752
+ }
753
+ const op = this.code[last] & BYTE;
754
+ return op === Op.RETURN || op === Op.JUMP || op === Op.JUMPBACK;
755
+ }
756
+ finish() {
757
+ if (!this.endsWithTerminator() || this.lastLabel === this.code.length) this.emit(abc(Op.RETURN, 0, 1, 0));
758
+ return {
759
+ maxStackSize: Math.max(this.maxStack, 1),
760
+ numParams: this.numParams,
761
+ numUpvalues: this.upvalues.length,
762
+ isVararg: this.isVararg,
763
+ code: this.code,
764
+ lines: this.lines,
765
+ constants: this.constants,
766
+ children: this.children,
767
+ lineDefined: this.lineDefined,
768
+ debugName: this.debugName
769
+ };
770
+ }
771
+ };
772
+
773
+ // src/interactives/scripting/ts/lower.ts
774
+ var RESULTS_NONE = 1;
775
+ var RESULTS_ONE = 2;
776
+ var ARGS_OFFSET = 1;
777
+ var NAMECALL_ARGS_OFFSET = 2;
778
+ var LIST_BATCH = 32;
779
+ var ARRAY_BASE = 1;
780
+ var TRUE = 1;
781
+ var FALSE = 0;
782
+ var SKIP_ONE = 1;
783
+ var QUOTE_CHARS = 40;
784
+ var TOO_LARGE = "this script is too large to run; split its longest functions into smaller ones";
785
+ var Refusal = class extends Error {
786
+ constructor(node, message) {
787
+ super(message);
788
+ this.node = node;
789
+ }
790
+ node;
791
+ };
792
+ var FnState = class {
793
+ constructor(b, parent) {
794
+ this.b = b;
795
+ this.parent = parent;
796
+ }
797
+ b;
798
+ parent;
799
+ scopes = [];
800
+ loops = [];
801
+ selfKey = null;
802
+ };
803
+ function numberOf(node) {
804
+ return Number(node.text.replace(/_/g, ""));
805
+ }
806
+ function functionScopeOf(node) {
807
+ let current = node.parent;
808
+ while (current !== void 0) {
809
+ if (ts.isFunctionDeclaration(current) || ts.isFunctionExpression(current) || ts.isArrowFunction(current) || ts.isMethodDeclaration(current) || ts.isConstructorDeclaration(current) || ts.isSourceFile(current)) {
810
+ return current;
811
+ }
812
+ if (ts.isPropertyDeclaration(current) && ts.isClassDeclaration(current.parent)) {
813
+ return current.parent;
814
+ }
815
+ current = current.parent;
816
+ }
817
+ return node;
818
+ }
819
+ function declarationScope(declaration) {
820
+ if (ts.isParameter(declaration)) return declaration.parent;
821
+ if (ts.isFunctionDeclaration(declaration) || ts.isClassDeclaration(declaration)) return functionScopeOf(declaration);
822
+ return functionScopeOf(declaration);
823
+ }
824
+ var Lowering = class {
825
+ constructor(checker, source) {
826
+ this.checker = checker;
827
+ this.source = source;
828
+ }
829
+ checker;
830
+ source;
831
+ protos = [];
832
+ captured = /* @__PURE__ */ new Set();
833
+ selfKeys = /* @__PURE__ */ new Map();
834
+ fn;
835
+ refuse(node, message) {
836
+ throw new Refusal(node, message);
837
+ }
838
+ quoted(node) {
839
+ const text = node.getText(this.source).split("\n")[0]?.trim() ?? "";
840
+ return text.length > QUOTE_CHARS ? `'${text.slice(0, QUOTE_CHARS)}...'` : `'${text}'`;
841
+ }
842
+ isAmbient(symbol) {
843
+ const declarations = symbol.declarations ?? [];
844
+ return declarations.length > 0 && declarations.every((d) => d.getSourceFile().fileName === LIB_FILE);
845
+ }
846
+ symbolOf(node) {
847
+ const symbol = this.checker.getSymbolAtLocation(node);
848
+ if (symbol !== void 0 && ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node) {
849
+ return this.checker.getShorthandAssignmentValueSymbol(node.parent) ?? symbol;
850
+ }
851
+ return symbol;
852
+ }
853
+ selfKeyOf(scope) {
854
+ let key = this.selfKeys.get(scope);
855
+ if (key === void 0) {
856
+ key = {};
857
+ this.selfKeys.set(scope, key);
858
+ }
859
+ return key;
860
+ }
861
+ thisScope(node) {
862
+ let scope = functionScopeOf(node);
863
+ while (ts.isArrowFunction(scope)) scope = functionScopeOf(scope);
864
+ if (ts.isConstructorDeclaration(scope)) return scope.parent;
865
+ return scope;
866
+ }
867
+ findCaptures() {
868
+ const visit = (node) => {
869
+ if (ts.isClassDeclaration(node) && node.name !== void 0) {
870
+ const symbol = this.symbolOf(node.name);
871
+ if (symbol !== void 0) this.captured.add(symbol);
872
+ }
873
+ if (ts.isIdentifier(node)) {
874
+ const symbol = this.symbolOf(node);
875
+ const declaration = symbol?.valueDeclaration ?? symbol?.declarations?.[0];
876
+ if (symbol !== void 0 && declaration !== void 0 && !this.isAmbient(symbol)) {
877
+ let use = functionScopeOf(node);
878
+ let owner = declarationScope(declaration);
879
+ if (ts.isConstructorDeclaration(use)) use = use.parent;
880
+ if (ts.isConstructorDeclaration(owner)) owner = owner.parent;
881
+ if (use !== owner) this.captured.add(symbol);
882
+ }
883
+ } else if (node.kind === ts.SyntaxKind.ThisKeyword) {
884
+ let use = functionScopeOf(node);
885
+ if (ts.isConstructorDeclaration(use)) use = use.parent;
886
+ const owner = this.thisScope(node);
887
+ if (use !== owner) this.captured.add(this.selfKeyOf(owner));
888
+ }
889
+ ts.forEachChild(node, visit);
890
+ };
891
+ visit(this.source);
892
+ }
893
+ compileModule() {
894
+ this.findCaptures();
895
+ const b = new FunctionBuilder(0, true, null, 1);
896
+ this.fn = new FnState(b, null);
897
+ b.emit(abc(Op.PREPVARARGS, 0, 0, 0));
898
+ const scope = this.openScope();
899
+ const result = b.reserve(1);
900
+ b.emit(abc(Op.LOADNIL, result, 0, 0));
901
+ this.declareBlock(this.source.statements);
902
+ for (const statement of this.source.statements) {
903
+ if (ts.isExportAssignment(statement)) {
904
+ this.at(statement);
905
+ this.exprTo(statement.expression, result);
906
+ continue;
907
+ }
908
+ if (ts.isFunctionDeclaration(statement) && this.isDefaultExport(statement)) {
909
+ this.at(statement);
910
+ this.closureTo(statement, result, "default");
911
+ continue;
912
+ }
913
+ this.statement(statement);
914
+ }
915
+ this.closeScope(scope, true);
916
+ b.emit(abc(Op.RETURN, result, 2, 0));
917
+ this.protos.push(b.finish());
918
+ return this.protos.length - 1;
919
+ }
920
+ isDefaultExport(node) {
921
+ const flags = ts.getCombinedModifierFlags(node);
922
+ return (flags & ts.ModifierFlags.Default) !== 0;
923
+ }
924
+ at(node) {
925
+ const { line } = this.source.getLineAndCharacterOfPosition(node.getStart(this.source));
926
+ this.fn.b.line = line + 1;
927
+ }
928
+ openScope() {
929
+ const scope = { vars: /* @__PURE__ */ new Map(), firstReg: this.fn.b.top, captured: false };
930
+ this.fn.scopes.push(scope);
931
+ return scope;
932
+ }
933
+ closeScope(scope, closeUpvalues) {
934
+ const popped = this.fn.scopes.pop();
935
+ if (popped !== scope) throw new CompileLimit("scope stack out of order");
936
+ const lowest = this.lowestCaptured([scope]);
937
+ if (closeUpvalues && lowest >= 0) this.fn.b.emit(abc(Op.CLOSEUPVALS, lowest, 0, 0));
938
+ this.fn.b.release(scope.firstReg);
939
+ }
940
+ lowestCaptured(scopes) {
941
+ let lowest = -1;
942
+ for (const scope of scopes) {
943
+ for (const [key, reg] of scope.vars) {
944
+ if (this.captured.has(key) && (lowest < 0 || reg < lowest)) lowest = reg;
945
+ }
946
+ }
947
+ return lowest;
948
+ }
949
+ emitReturn(reg, countPlusOne) {
950
+ const lowest = this.lowestCaptured(this.fn.scopes);
951
+ if (lowest >= 0) this.fn.b.emit(abc(Op.CLOSEUPVALS, lowest, 0, 0));
952
+ this.fn.b.emit(abc(Op.RETURN, reg, countPlusOne, 0));
953
+ }
954
+ declare(key) {
955
+ const scope = this.fn.scopes[this.fn.scopes.length - 1];
956
+ const reg = this.fn.b.reserve(1);
957
+ scope.vars.set(key, reg);
958
+ if (this.captured.has(key)) scope.captured = true;
959
+ return reg;
960
+ }
961
+ declareBlock(statements) {
962
+ for (const statement of statements) {
963
+ if (ts.isVariableStatement(statement)) {
964
+ for (const declaration of statement.declarationList.declarations) {
965
+ if (!ts.isIdentifier(declaration.name)) this.refuse(declaration, "destructuring declarations are not supported");
966
+ const symbol = this.symbolOf(declaration.name);
967
+ if (symbol === void 0) this.refuse(declaration, "a declaration without a symbol");
968
+ const reg = this.declare(symbol);
969
+ this.fn.b.emit(abc(Op.LOADNIL, reg, 0, 0));
970
+ }
971
+ } else if (ts.isFunctionDeclaration(statement) && !this.isDefaultExport(statement)) {
972
+ if (statement.name === void 0) this.refuse(statement, "a function declaration needs a name");
973
+ const symbol = this.symbolOf(statement.name);
974
+ if (symbol === void 0) this.refuse(statement, "a function without a symbol");
975
+ this.declare(symbol);
976
+ } else if (ts.isClassDeclaration(statement)) {
977
+ if (statement.name === void 0) this.refuse(statement, "a class declaration needs a name");
978
+ const symbol = this.symbolOf(statement.name);
979
+ if (symbol === void 0) this.refuse(statement, "a class without a symbol");
980
+ const reg = this.declare(symbol);
981
+ this.fn.b.emit(abc(Op.LOADNIL, reg, 0, 0));
982
+ }
983
+ }
984
+ for (const statement of statements) {
985
+ if (ts.isFunctionDeclaration(statement) && !this.isDefaultExport(statement) && statement.body !== void 0) {
986
+ const reg = this.lookupLocal(this.symbolOf(statement.name));
987
+ this.at(statement);
988
+ this.closureTo(statement, reg, statement.name.text);
989
+ }
990
+ }
991
+ }
992
+ lookupLocal(key) {
993
+ for (let i = this.fn.scopes.length - 1; i >= 0; i--) {
994
+ const reg = this.fn.scopes[i].vars.get(key);
995
+ if (reg !== void 0) return reg;
996
+ }
997
+ return void 0;
998
+ }
999
+ resolveIn(fn, key) {
1000
+ for (let i = fn.scopes.length - 1; i >= 0; i--) {
1001
+ const reg = fn.scopes[i].vars.get(key);
1002
+ if (reg !== void 0) return { kind: "local", reg };
1003
+ }
1004
+ if (fn.parent === null) return null;
1005
+ const outer = this.resolveIn(fn.parent, key);
1006
+ if (outer === null || outer.kind === "global") return outer;
1007
+ const index = fn.b.upvalue(
1008
+ outer.kind === "local" ? { kind: CAPTURE_REF, index: outer.reg } : { kind: CAPTURE_UPVAL, index: outer.index }
1009
+ );
1010
+ return { kind: "upval", index };
1011
+ }
1012
+ place(node) {
1013
+ if (node.text === "undefined") return { kind: "global", name: "nil" };
1014
+ const symbol = this.symbolOf(node);
1015
+ if (symbol === void 0) this.refuse(node, `unknown name '${node.text}'`);
1016
+ if (this.isAmbient(symbol)) return { kind: "global", name: GLOBAL_RENAMES.get(node.text) ?? node.text };
1017
+ const found = this.resolveIn(this.fn, symbol);
1018
+ if (found === null) this.refuse(node, `'${node.text}' is used before it is declared in an enclosing block`);
1019
+ return found;
1020
+ }
1021
+ selfPlace(node) {
1022
+ const key = this.selfKeyOf(this.thisScope(node));
1023
+ const found = this.resolveIn(this.fn, key);
1024
+ if (found === null) this.refuse(node, "'this' is only supported inside class methods and constructors");
1025
+ return found;
1026
+ }
1027
+ typeOf(node) {
1028
+ return this.checker.getTypeAtLocation(node);
1029
+ }
1030
+ parts(type) {
1031
+ return type.isUnion() ? type.types : [type];
1032
+ }
1033
+ isString(type) {
1034
+ return this.parts(type).every((t) => (t.flags & ts.TypeFlags.StringLike) !== 0);
1035
+ }
1036
+ isNumber(type) {
1037
+ return this.parts(type).every((t) => (t.flags & ts.TypeFlags.NumberLike) !== 0);
1038
+ }
1039
+ isBoolean(type) {
1040
+ return this.parts(type).every((t) => (t.flags & ts.TypeFlags.BooleanLike) !== 0);
1041
+ }
1042
+ mayBe(type, flags) {
1043
+ return this.parts(type).some((t) => (t.flags & (flags | ts.TypeFlags.Any | ts.TypeFlags.Unknown)) !== 0);
1044
+ }
1045
+ isArray(type) {
1046
+ const nonNull = this.checker.getNonNullableType(type);
1047
+ return this.checker.isArrayType(nonNull) || this.checker.isTupleType(nonNull);
1048
+ }
1049
+ statement(node) {
1050
+ this.at(node);
1051
+ const b = this.fn.b;
1052
+ const mark = b.top;
1053
+ if (ts.isVariableStatement(node)) {
1054
+ for (const declaration of node.declarationList.declarations) {
1055
+ if (declaration.initializer === void 0) continue;
1056
+ const reg = this.lookupLocal(this.symbolOf(declaration.name));
1057
+ this.exprTo(declaration.initializer, reg);
1058
+ }
1059
+ } else if (ts.isExpressionStatement(node)) {
1060
+ this.effect(node.expression);
1061
+ } else if (ts.isReturnStatement(node)) {
1062
+ if (node.expression === void 0) {
1063
+ this.emitReturn(0, 1);
1064
+ } else {
1065
+ const reg = this.exprAny(node.expression);
1066
+ this.emitReturn(reg, 2);
1067
+ }
1068
+ } else if (ts.isIfStatement(node)) {
1069
+ const otherwise = b.label();
1070
+ this.jumpIfFalse(node.expression, otherwise);
1071
+ b.release(mark);
1072
+ this.block(node.thenStatement);
1073
+ if (node.elseStatement !== void 0) {
1074
+ const end = b.label();
1075
+ b.jump(end);
1076
+ b.here(otherwise);
1077
+ this.block(node.elseStatement);
1078
+ b.here(end);
1079
+ } else {
1080
+ b.here(otherwise);
1081
+ }
1082
+ } else if (ts.isWhileStatement(node)) {
1083
+ const top = b.label();
1084
+ const exit = b.label();
1085
+ b.here(top);
1086
+ this.jumpIfFalse(node.expression, exit);
1087
+ b.release(mark);
1088
+ this.loopBody(node.statement, exit, top);
1089
+ b.jump(top);
1090
+ b.here(exit);
1091
+ } else if (ts.isDoStatement(node)) {
1092
+ const top = b.label();
1093
+ const exit = b.label();
1094
+ const next = b.label();
1095
+ b.here(top);
1096
+ this.loopBody(node.statement, exit, next);
1097
+ b.here(next);
1098
+ this.jumpIfFalse(node.expression, exit);
1099
+ b.release(mark);
1100
+ b.jump(top);
1101
+ b.here(exit);
1102
+ } else if (ts.isForStatement(node)) {
1103
+ this.forStatement(node);
1104
+ } else if (ts.isForOfStatement(node)) {
1105
+ this.forOfStatement(node);
1106
+ } else if (ts.isBreakStatement(node) || ts.isContinueStatement(node)) {
1107
+ if (node.label !== void 0) this.refuse(node, "labelled break and continue are not supported");
1108
+ const contexts = this.fn.loops.filter((l) => ts.isBreakStatement(node) || l.loop);
1109
+ const loop = contexts[contexts.length - 1];
1110
+ if (loop === void 0) this.refuse(node, "break or continue outside a loop");
1111
+ const lowest = this.lowestCaptured(this.fn.scopes.slice(loop.scopeDepth));
1112
+ if (lowest >= 0) b.emit(abc(Op.CLOSEUPVALS, lowest, 0, 0));
1113
+ b.jump(ts.isBreakStatement(node) ? loop.breakLabel : loop.continueLabel);
1114
+ } else if (ts.isBlock(node)) {
1115
+ this.block(node);
1116
+ } else if (ts.isSwitchStatement(node)) {
1117
+ this.switchStatement(node);
1118
+ } else if (ts.isThrowStatement(node)) {
1119
+ const base = b.reserve(2);
1120
+ b.emit(abc(Op.GETGLOBAL, base, 0, 0), b.string("error"));
1121
+ this.exprTo(node.expression, base + ARGS_OFFSET);
1122
+ b.emit(abc(Op.CALL, base, 2, RESULTS_NONE));
1123
+ } else if (ts.isFunctionDeclaration(node)) {
1124
+ if (node.body === void 0) this.refuse(node, "a function declaration needs a body");
1125
+ } else if (ts.isClassDeclaration(node)) {
1126
+ this.classDeclaration(node);
1127
+ } else if (ts.isEmptyStatement(node) || ts.isInterfaceDeclaration(node) || ts.isTypeAliasDeclaration(node)) {
1128
+ return;
1129
+ } else if (ts.isTryStatement(node)) {
1130
+ this.refuse(node, "try and catch are not supported in Rive scripts yet");
1131
+ } else {
1132
+ this.refuse(node, `${this.quoted(node)} is not supported in Rive scripts`);
1133
+ }
1134
+ b.release(mark);
1135
+ }
1136
+ block(node) {
1137
+ const scope = this.openScope();
1138
+ const statements = ts.isBlock(node) ? node.statements : ts.factory.createNodeArray([node]);
1139
+ this.declareBlock(statements);
1140
+ for (const statement of statements) this.statement(statement);
1141
+ this.closeScope(scope, true);
1142
+ }
1143
+ loopBody(body, exit, next) {
1144
+ this.fn.loops.push({ breakLabel: exit, continueLabel: next, scopeDepth: this.fn.scopes.length, loop: true });
1145
+ this.block(body);
1146
+ this.fn.loops.pop();
1147
+ }
1148
+ forStatement(node) {
1149
+ const b = this.fn.b;
1150
+ const scope = this.openScope();
1151
+ if (node.initializer !== void 0) {
1152
+ if (ts.isVariableDeclarationList(node.initializer)) {
1153
+ for (const declaration of node.initializer.declarations) {
1154
+ if (!ts.isIdentifier(declaration.name)) this.refuse(declaration, "destructuring declarations are not supported");
1155
+ const symbol = this.symbolOf(declaration.name);
1156
+ if (this.captured.has(symbol)) {
1157
+ this.refuse(declaration, "a closure cannot capture a for loop's counter; copy it into a const inside the body");
1158
+ }
1159
+ const reg = this.declare(symbol);
1160
+ if (declaration.initializer === void 0) b.emit(abc(Op.LOADNIL, reg, 0, 0));
1161
+ else this.exprTo(declaration.initializer, reg);
1162
+ }
1163
+ } else {
1164
+ this.effect(node.initializer);
1165
+ }
1166
+ }
1167
+ const top = b.label();
1168
+ const exit = b.label();
1169
+ const next = b.label();
1170
+ b.here(top);
1171
+ if (node.condition !== void 0) {
1172
+ const mark = b.top;
1173
+ this.jumpIfFalse(node.condition, exit);
1174
+ b.release(mark);
1175
+ }
1176
+ this.loopBody(node.statement, exit, next);
1177
+ b.here(next);
1178
+ if (node.incrementor !== void 0) {
1179
+ const mark = b.top;
1180
+ this.effect(node.incrementor);
1181
+ b.release(mark);
1182
+ }
1183
+ b.jump(top);
1184
+ b.here(exit);
1185
+ this.closeScope(scope, true);
1186
+ }
1187
+ forOfStatement(node) {
1188
+ const b = this.fn.b;
1189
+ if (node.awaitModifier !== void 0) this.refuse(node, "for await is not supported");
1190
+ if (!this.isArray(this.typeOf(node.expression))) this.refuse(node.expression, "for...of iterates arrays only");
1191
+ if (!ts.isVariableDeclarationList(node.initializer) || node.initializer.declarations.length !== 1) {
1192
+ this.refuse(node.initializer, "for...of needs one const or let declaration");
1193
+ }
1194
+ const declaration = node.initializer.declarations[0];
1195
+ if (!ts.isIdentifier(declaration.name)) this.refuse(declaration, "destructuring declarations are not supported");
1196
+ const outer = this.openScope();
1197
+ const table = b.reserve(1);
1198
+ this.exprTo(node.expression, table);
1199
+ const index = b.reserve(1);
1200
+ b.loadNumber(index, ARRAY_BASE);
1201
+ const length = b.reserve(1);
1202
+ const top = b.label();
1203
+ const exit = b.label();
1204
+ const next = b.label();
1205
+ b.here(top);
1206
+ b.emit(abc(Op.LENGTH, length, table, 0));
1207
+ b.jumpTo(Op.JUMPIFNOTLE, index, exit, length);
1208
+ const iteration = this.openScope();
1209
+ const item = this.declare(this.symbolOf(declaration.name));
1210
+ b.emit(abc(Op.GETTABLE, item, table, index));
1211
+ this.fn.loops.push({ breakLabel: exit, continueLabel: next, scopeDepth: this.fn.scopes.length - 1, loop: true });
1212
+ this.block(node.statement);
1213
+ this.fn.loops.pop();
1214
+ this.closeScope(iteration, true);
1215
+ b.here(next);
1216
+ b.emit(abc(Op.ADDK, index, index, b.number(ARRAY_BASE)));
1217
+ b.jump(top);
1218
+ b.here(exit);
1219
+ this.closeScope(outer, true);
1220
+ }
1221
+ switchStatement(node) {
1222
+ const b = this.fn.b;
1223
+ const scope = this.openScope();
1224
+ const value = b.reserve(1);
1225
+ this.exprTo(node.expression, value);
1226
+ const exit = b.label();
1227
+ const labels = node.caseBlock.clauses.map(() => b.label());
1228
+ let fallback = exit;
1229
+ node.caseBlock.clauses.forEach((clause, i) => {
1230
+ if (ts.isDefaultClause(clause)) {
1231
+ fallback = labels[i];
1232
+ return;
1233
+ }
1234
+ const mark = b.top;
1235
+ const candidate = this.exprAny(clause.expression);
1236
+ b.jumpTo(Op.JUMPIFEQ, value, labels[i], candidate);
1237
+ b.release(mark);
1238
+ });
1239
+ b.jump(fallback);
1240
+ this.fn.loops.push({ breakLabel: exit, continueLabel: exit, scopeDepth: this.fn.scopes.length, loop: false });
1241
+ const body = this.openScope();
1242
+ const statements = node.caseBlock.clauses.flatMap((clause) => [...clause.statements]);
1243
+ this.declareBlock(ts.factory.createNodeArray(statements));
1244
+ node.caseBlock.clauses.forEach((clause, i) => {
1245
+ b.here(labels[i]);
1246
+ for (const statement of clause.statements) this.statement(statement);
1247
+ });
1248
+ this.closeScope(body, true);
1249
+ this.fn.loops.pop();
1250
+ b.here(exit);
1251
+ this.closeScope(scope, true);
1252
+ }
1253
+ classDeclaration(node) {
1254
+ const b = this.fn.b;
1255
+ if (node.heritageClauses !== void 0 && node.heritageClauses.length > 0) {
1256
+ this.refuse(node, "classes cannot extend or implement in Rive scripts yet");
1257
+ }
1258
+ const reg = this.lookupLocal(this.symbolOf(node.name));
1259
+ b.emit(abc(Op.NEWTABLE, reg, 0, 0), 0);
1260
+ b.emit(abc(Op.SETTABLEKS, reg, reg, 0), b.string("__index"));
1261
+ const mark = b.top;
1262
+ let constructor;
1263
+ for (const member of node.members) {
1264
+ if (ts.isConstructorDeclaration(member)) {
1265
+ constructor = member;
1266
+ } else if (ts.isMethodDeclaration(member)) {
1267
+ if (!ts.isIdentifier(member.name)) this.refuse(member, "computed method names are not supported");
1268
+ const isStatic = (ts.getCombinedModifierFlags(member) & ts.ModifierFlags.Static) !== 0;
1269
+ const temp2 = b.reserve(1);
1270
+ this.at(member);
1271
+ this.closureTo(member, temp2, member.name.text, !isStatic);
1272
+ b.emit(abc(Op.SETTABLEKS, temp2, reg, 0), b.string(member.name.text));
1273
+ b.release(mark);
1274
+ } else if (ts.isPropertyDeclaration(member)) {
1275
+ if ((ts.getCombinedModifierFlags(member) & ts.ModifierFlags.Static) !== 0) {
1276
+ this.refuse(member, "static fields are not supported in Rive scripts yet");
1277
+ }
1278
+ } else {
1279
+ this.refuse(member, `${this.quoted(member)} in a class is not supported in Rive scripts yet`);
1280
+ }
1281
+ }
1282
+ const temp = b.reserve(1);
1283
+ this.constructorTo(node, constructor, temp);
1284
+ b.emit(abc(Op.SETTABLEKS, temp, reg, 0), b.string("new"));
1285
+ b.release(mark);
1286
+ }
1287
+ constructorTo(node, constructor, target) {
1288
+ const params = constructor?.parameters ?? ts.factory.createNodeArray([]);
1289
+ const parent = this.fn;
1290
+ const child = new FunctionBuilder(params.length, false, "new", parent.b.line);
1291
+ this.fn = new FnState(child, parent);
1292
+ const scope = this.openScope();
1293
+ params.forEach((param, i) => this.bindParameter(param, i));
1294
+ const selfKey = this.selfKeyOf(node);
1295
+ const self = this.declare(selfKey);
1296
+ const mark = child.top;
1297
+ const base = child.reserve(3);
1298
+ child.emit(abc(Op.GETGLOBAL, base, 0, 0), child.string("setmetatable"));
1299
+ child.emit(abc(Op.NEWTABLE, base + 1, 0, 0), 0);
1300
+ const classPlace = this.resolveIn(this.fn, this.symbolOf(node.name));
1301
+ if (classPlace === null || classPlace.kind !== "upval") throw new CompileLimit("a class must be visible to its constructor");
1302
+ child.emit(abc(Op.GETUPVAL, base + 2, classPlace.index, 0));
1303
+ child.emit(abc(Op.CALL, base, 3, RESULTS_ONE));
1304
+ child.emit(abc(Op.MOVE, self, base, 0));
1305
+ child.release(mark);
1306
+ for (const member of node.members) {
1307
+ if (ts.isPropertyDeclaration(member) && member.initializer !== void 0) {
1308
+ if (!ts.isIdentifier(member.name)) this.refuse(member, "computed field names are not supported");
1309
+ this.at(member);
1310
+ const value = this.exprAny(member.initializer);
1311
+ child.emit(abc(Op.SETTABLEKS, value, self, 0), child.string(member.name.text));
1312
+ child.release(mark);
1313
+ }
1314
+ }
1315
+ if (constructor?.body !== void 0) {
1316
+ this.declareBlock(constructor.body.statements);
1317
+ for (const statement of constructor.body.statements) {
1318
+ if (ts.isReturnStatement(statement)) this.refuse(statement, "a constructor cannot return");
1319
+ this.statement(statement);
1320
+ }
1321
+ }
1322
+ this.emitReturn(self, 2);
1323
+ this.closeScope(scope, false);
1324
+ this.finishClosure(parent, child, target);
1325
+ }
1326
+ bindParameter(param, index) {
1327
+ if (!ts.isIdentifier(param.name)) this.refuse(param, "destructuring parameters are not supported");
1328
+ if (param.dotDotDotToken !== void 0) this.refuse(param, "rest parameters are not supported");
1329
+ const symbol = this.symbolOf(param.name);
1330
+ const scope = this.fn.scopes[this.fn.scopes.length - 1];
1331
+ scope.vars.set(symbol, index);
1332
+ if (this.captured.has(symbol)) scope.captured = true;
1333
+ }
1334
+ closureTo(node, target, name, method = false) {
1335
+ if (node.asteriskToken !== void 0) this.refuse(node, "generators are not supported");
1336
+ if (node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AsyncKeyword)) this.refuse(node, "async functions are not supported in Rive scripts yet");
1337
+ const parent = this.fn;
1338
+ const offset = method ? 1 : 0;
1339
+ const child = new FunctionBuilder(node.parameters.length + offset, false, name, parent.b.line);
1340
+ this.fn = new FnState(child, parent);
1341
+ const scope = this.openScope();
1342
+ if (method) {
1343
+ const key = this.selfKeyOf(node);
1344
+ scope.vars.set(key, 0);
1345
+ if (this.captured.has(key)) scope.captured = true;
1346
+ }
1347
+ node.parameters.forEach((param, i) => this.bindParameter(param, i + offset));
1348
+ node.parameters.forEach((param, i) => {
1349
+ if (param.initializer === void 0) return;
1350
+ this.at(param);
1351
+ const reg = i + offset;
1352
+ const skip = child.label();
1353
+ const mark = child.top;
1354
+ const nil = child.reserve(1);
1355
+ child.emit(abc(Op.LOADNIL, nil, 0, 0));
1356
+ child.jumpTo(Op.JUMPIFNOTEQ, reg, skip, nil);
1357
+ child.release(mark);
1358
+ this.exprTo(param.initializer, reg);
1359
+ child.here(skip);
1360
+ });
1361
+ const body = node.body;
1362
+ if (body === void 0) this.refuse(node, "a function needs a body");
1363
+ if (ts.isBlock(body)) {
1364
+ this.declareBlock(body.statements);
1365
+ for (const statement of body.statements) this.statement(statement);
1366
+ } else {
1367
+ this.at(body);
1368
+ const reg = this.exprAny(body);
1369
+ this.emitReturn(reg, 2);
1370
+ }
1371
+ this.closeScope(scope, true);
1372
+ this.finishClosure(parent, child, target);
1373
+ }
1374
+ finishClosure(parent, child, target) {
1375
+ this.fn = parent;
1376
+ this.protos.push(child.finish());
1377
+ parent.b.children.push(this.protos.length - 1);
1378
+ parent.b.emit(ad(Op.NEWCLOSURE, target, parent.b.children.length - 1));
1379
+ for (const upvalue of child.upvalues) {
1380
+ parent.b.emit(abc(Op.CAPTURE, upvalue.kind, upvalue.index, 0));
1381
+ }
1382
+ }
1383
+ effect(node) {
1384
+ const b = this.fn.b;
1385
+ const mark = b.top;
1386
+ if (ts.isParenthesizedExpression(node)) {
1387
+ this.effect(node.expression);
1388
+ } else if (ts.isCallExpression(node)) {
1389
+ this.call(node, null);
1390
+ } else if (ts.isBinaryExpression(node) && this.isAssignment(node.operatorToken.kind)) {
1391
+ this.assignment(node, null);
1392
+ } else if ((ts.isPrefixUnaryExpression(node) || ts.isPostfixUnaryExpression(node)) && (node.operator === ts.SyntaxKind.PlusPlusToken || node.operator === ts.SyntaxKind.MinusMinusToken)) {
1393
+ this.increment(node, null);
1394
+ } else {
1395
+ this.exprAny(node);
1396
+ }
1397
+ b.release(mark);
1398
+ }
1399
+ isAssignment(kind) {
1400
+ return kind === ts.SyntaxKind.EqualsToken || kind === ts.SyntaxKind.PlusEqualsToken || kind === ts.SyntaxKind.MinusEqualsToken || kind === ts.SyntaxKind.AsteriskEqualsToken || kind === ts.SyntaxKind.SlashEqualsToken || kind === ts.SyntaxKind.QuestionQuestionEqualsToken;
1401
+ }
1402
+ exprAny(node) {
1403
+ const inner = this.unwrap(node);
1404
+ if (ts.isIdentifier(inner)) {
1405
+ const place = this.place(inner);
1406
+ if (place.kind === "local") return place.reg;
1407
+ }
1408
+ if (inner.kind === ts.SyntaxKind.ThisKeyword) {
1409
+ const place = this.selfPlace(inner);
1410
+ if (place.kind === "local") return place.reg;
1411
+ }
1412
+ const reg = this.fn.b.reserve(1);
1413
+ this.exprTo(inner, reg);
1414
+ return reg;
1415
+ }
1416
+ unwrap(node) {
1417
+ let current = node;
1418
+ while (ts.isParenthesizedExpression(current) || ts.isAsExpression(current) || ts.isNonNullExpression(current) || ts.isTypeAssertionExpression(current) || ts.isSatisfiesExpression(current)) {
1419
+ current = current.expression;
1420
+ }
1421
+ return current;
1422
+ }
1423
+ loadPlace(place, target) {
1424
+ const b = this.fn.b;
1425
+ switch (place.kind) {
1426
+ case "local":
1427
+ if (place.reg !== target) b.emit(abc(Op.MOVE, target, place.reg, 0));
1428
+ break;
1429
+ case "upval":
1430
+ b.emit(abc(Op.GETUPVAL, target, place.index, 0));
1431
+ break;
1432
+ case "global":
1433
+ if (place.name === "nil") b.emit(abc(Op.LOADNIL, target, 0, 0));
1434
+ else b.emit(abc(Op.GETGLOBAL, target, 0, 0), b.string(place.name));
1435
+ break;
1436
+ }
1437
+ }
1438
+ exprTo(node, target) {
1439
+ const b = this.fn.b;
1440
+ const inner = this.unwrap(node);
1441
+ const mark = b.top;
1442
+ if (ts.isNumericLiteral(inner)) {
1443
+ b.loadNumber(target, numberOf(inner));
1444
+ } else if (ts.isStringLiteral(inner) || ts.isNoSubstitutionTemplateLiteral(inner)) {
1445
+ b.loadString(target, inner.text);
1446
+ } else if (inner.kind === ts.SyntaxKind.TrueKeyword || inner.kind === ts.SyntaxKind.FalseKeyword) {
1447
+ b.emit(abc(Op.LOADB, target, inner.kind === ts.SyntaxKind.TrueKeyword ? TRUE : FALSE, 0));
1448
+ } else if (inner.kind === ts.SyntaxKind.NullKeyword) {
1449
+ b.emit(abc(Op.LOADNIL, target, 0, 0));
1450
+ } else if (ts.isIdentifier(inner)) {
1451
+ this.loadPlace(this.place(inner), target);
1452
+ } else if (inner.kind === ts.SyntaxKind.ThisKeyword) {
1453
+ this.loadPlace(this.selfPlace(inner), target);
1454
+ } else if (ts.isTemplateExpression(inner)) {
1455
+ this.template(inner, target);
1456
+ } else if (ts.isArrayLiteralExpression(inner)) {
1457
+ this.arrayLiteral(inner, target);
1458
+ } else if (ts.isObjectLiteralExpression(inner)) {
1459
+ this.objectLiteral(inner, target);
1460
+ } else if (ts.isPropertyAccessExpression(inner)) {
1461
+ this.propertyGet(inner, target);
1462
+ } else if (ts.isElementAccessExpression(inner)) {
1463
+ this.elementGet(inner, target);
1464
+ } else if (ts.isCallExpression(inner)) {
1465
+ this.call(inner, target);
1466
+ } else if (ts.isNewExpression(inner)) {
1467
+ this.newExpression(inner, target);
1468
+ } else if (ts.isArrowFunction(inner) || ts.isFunctionExpression(inner)) {
1469
+ this.closureTo(inner, target, ts.isFunctionExpression(inner) ? inner.name?.text ?? null : null);
1470
+ } else if (ts.isPrefixUnaryExpression(inner)) {
1471
+ this.prefix(inner, target);
1472
+ } else if (ts.isPostfixUnaryExpression(inner)) {
1473
+ this.increment(inner, target);
1474
+ } else if (ts.isBinaryExpression(inner)) {
1475
+ this.binary(inner, target);
1476
+ } else if (ts.isConditionalExpression(inner)) {
1477
+ const otherwise = b.label();
1478
+ const end = b.label();
1479
+ this.jumpIfFalse(inner.condition, otherwise);
1480
+ b.release(mark);
1481
+ this.exprTo(inner.whenTrue, target);
1482
+ b.jump(end);
1483
+ b.here(otherwise);
1484
+ this.exprTo(inner.whenFalse, target);
1485
+ b.here(end);
1486
+ } else {
1487
+ this.refuse(inner, `${this.quoted(inner)} is not supported in Rive scripts`);
1488
+ }
1489
+ b.release(mark);
1490
+ }
1491
+ template(node, target) {
1492
+ const parts = [];
1493
+ if (node.head.text.length > 0) parts.push(node.head.text);
1494
+ for (const span of node.templateSpans) {
1495
+ parts.push(span.expression);
1496
+ if (span.literal.text.length > 0) parts.push(span.literal.text);
1497
+ }
1498
+ this.concat(parts, target);
1499
+ }
1500
+ concat(parts, target) {
1501
+ const b = this.fn.b;
1502
+ if (parts.length === 1 && typeof parts[0] !== "string") {
1503
+ this.stringify(parts[0], target);
1504
+ return;
1505
+ }
1506
+ const base = b.reserve(parts.length);
1507
+ parts.forEach((part, i) => {
1508
+ if (typeof part === "string") b.loadString(base + i, part);
1509
+ else this.concatOperand(part, base + i);
1510
+ });
1511
+ b.emit(abc(Op.CONCAT, target, base, base + parts.length - 1));
1512
+ }
1513
+ concatOperand(node, target) {
1514
+ const type = this.typeOf(node);
1515
+ if (this.isString(type) || this.isNumber(type)) this.exprTo(node, target);
1516
+ else this.stringify(node, target);
1517
+ }
1518
+ stringify(node, target) {
1519
+ const b = this.fn.b;
1520
+ if (this.isString(this.typeOf(node))) {
1521
+ this.exprTo(node, target);
1522
+ return;
1523
+ }
1524
+ const mark = b.top;
1525
+ const base = b.reserve(2);
1526
+ b.emit(abc(Op.GETGLOBAL, base, 0, 0), b.string("tostring"));
1527
+ this.exprTo(node, base + ARGS_OFFSET);
1528
+ b.emit(abc(Op.CALL, base, 2, RESULTS_ONE));
1529
+ if (base !== target) b.emit(abc(Op.MOVE, target, base, 0));
1530
+ b.release(mark);
1531
+ }
1532
+ flattenConcat(node, out) {
1533
+ const inner = this.unwrap(node);
1534
+ if (ts.isBinaryExpression(inner) && inner.operatorToken.kind === ts.SyntaxKind.PlusToken && this.isString(this.typeOf(inner))) {
1535
+ this.flattenConcat(inner.left, out);
1536
+ this.flattenConcat(inner.right, out);
1537
+ return;
1538
+ }
1539
+ if (ts.isStringLiteral(inner) || ts.isNoSubstitutionTemplateLiteral(inner)) {
1540
+ out.push(inner.text);
1541
+ return;
1542
+ }
1543
+ out.push(inner);
1544
+ }
1545
+ arrayLiteral(node, target) {
1546
+ const b = this.fn.b;
1547
+ const count = node.elements.length;
1548
+ const table = b.reserve(1);
1549
+ b.emit(abc(Op.NEWTABLE, table, 0, 0), count);
1550
+ for (let start = 0; start < count; start += LIST_BATCH) {
1551
+ const batch = node.elements.slice(start, start + LIST_BATCH);
1552
+ const mark = b.top;
1553
+ const base = b.reserve(batch.length);
1554
+ batch.forEach((element, i) => {
1555
+ if (ts.isSpreadElement(element)) this.refuse(element, "spread is not supported");
1556
+ if (ts.isOmittedExpression(element)) this.refuse(element, "array holes are not supported");
1557
+ this.exprTo(element, base + i);
1558
+ });
1559
+ b.emit(abc(Op.SETLIST, table, base, batch.length + 1), start + ARRAY_BASE);
1560
+ b.release(mark);
1561
+ }
1562
+ if (table !== target) b.emit(abc(Op.MOVE, target, table, 0));
1563
+ }
1564
+ propertyName(name) {
1565
+ if (ts.isIdentifier(name) || ts.isStringLiteral(name)) return name.text;
1566
+ if (ts.isNumericLiteral(name)) return name.text;
1567
+ return this.refuse(name, "computed property names are not supported");
1568
+ }
1569
+ objectLiteral(node, target) {
1570
+ const b = this.fn.b;
1571
+ const table = b.reserve(1);
1572
+ b.emit(abc(Op.NEWTABLE, table, 0, 0), 0);
1573
+ for (const property of node.properties) {
1574
+ const mark = b.top;
1575
+ this.at(property);
1576
+ if (ts.isPropertyAssignment(property)) {
1577
+ const value = this.exprAny(property.initializer);
1578
+ b.emit(abc(Op.SETTABLEKS, value, table, 0), b.string(this.propertyName(property.name)));
1579
+ } else if (ts.isShorthandPropertyAssignment(property)) {
1580
+ const value = this.exprAny(property.name);
1581
+ b.emit(abc(Op.SETTABLEKS, value, table, 0), b.string(property.name.text));
1582
+ } else if (ts.isMethodDeclaration(property)) {
1583
+ const value = b.reserve(1);
1584
+ const name = this.propertyName(property.name);
1585
+ this.closureTo(property, value, name);
1586
+ b.emit(abc(Op.SETTABLEKS, value, table, 0), b.string(name));
1587
+ } else {
1588
+ this.refuse(property, `${this.quoted(property)} in an object literal is not supported in Rive scripts`);
1589
+ }
1590
+ b.release(mark);
1591
+ }
1592
+ if (table !== target) b.emit(abc(Op.MOVE, target, table, 0));
1593
+ }
1594
+ isMathObject(node) {
1595
+ const inner = this.unwrap(node);
1596
+ if (!ts.isIdentifier(inner) || inner.text !== "Math") return false;
1597
+ const symbol = this.symbolOf(inner);
1598
+ return symbol !== void 0 && this.isAmbient(symbol);
1599
+ }
1600
+ propertyGet(node, target) {
1601
+ const b = this.fn.b;
1602
+ if (node.questionDotToken !== void 0) this.refuse(node, "optional chaining is not supported in Rive scripts yet");
1603
+ const name = node.name.text;
1604
+ const objectType = this.typeOf(node.expression);
1605
+ if (name === "length" && (this.isArray(objectType) || this.isString(objectType))) {
1606
+ const object2 = this.exprAny(node.expression);
1607
+ b.emit(abc(Op.LENGTH, target, object2, 0));
1608
+ return;
1609
+ }
1610
+ const key = this.isMathObject(node.expression) ? MATH_RENAMES.get(name) ?? name : name;
1611
+ const object = this.exprAny(node.expression);
1612
+ b.emit(abc(Op.GETTABLEKS, target, object, 0), b.string(key));
1613
+ }
1614
+ arrayIndex(node) {
1615
+ const b = this.fn.b;
1616
+ const inner = this.unwrap(node);
1617
+ if (!this.isNumber(this.typeOf(inner))) this.refuse(inner, "arrays are indexed by numbers");
1618
+ const index = b.reserve(1);
1619
+ if (ts.isNumericLiteral(inner)) {
1620
+ b.loadNumber(index, numberOf(inner) + ARRAY_BASE);
1621
+ } else {
1622
+ const value = this.exprAny(inner);
1623
+ b.emit(abc(Op.ADDK, index, value, b.number(ARRAY_BASE)));
1624
+ }
1625
+ return index;
1626
+ }
1627
+ elementKey(node) {
1628
+ if (this.isArray(this.typeOf(node.expression))) return this.arrayIndex(node.argumentExpression);
1629
+ if (!this.isString(this.typeOf(node.argumentExpression))) {
1630
+ this.refuse(node.argumentExpression, "only arrays and string-keyed records can be indexed");
1631
+ }
1632
+ return this.exprAny(node.argumentExpression);
1633
+ }
1634
+ elementGet(node, target) {
1635
+ const b = this.fn.b;
1636
+ if (node.questionDotToken !== void 0) this.refuse(node, "optional chaining is not supported in Rive scripts yet");
1637
+ const object = this.exprAny(node.expression);
1638
+ const key = this.elementKey(node);
1639
+ b.emit(abc(Op.GETTABLE, target, object, key));
1640
+ }
1641
+ isSelfMethod(node) {
1642
+ const symbol = this.checker.getSymbolAtLocation(node.name);
1643
+ const declaration = symbol?.declarations?.[0];
1644
+ if (declaration === void 0) return false;
1645
+ if (!ts.isMethodDeclaration(declaration) && !ts.isMethodSignature(declaration)) return false;
1646
+ if ((ts.getCombinedModifierFlags(declaration) & ts.ModifierFlags.Static) !== 0) return false;
1647
+ if (declaration.getSourceFile().fileName === LIB_FILE) return true;
1648
+ return ts.isClassDeclaration(declaration.parent);
1649
+ }
1650
+ call(node, target) {
1651
+ const b = this.fn.b;
1652
+ if (node.questionDotToken !== void 0) this.refuse(node, "optional calls are not supported in Rive scripts yet");
1653
+ for (const arg of node.arguments) if (ts.isSpreadElement(arg)) this.refuse(arg, "spread arguments are not supported");
1654
+ const callee = this.unwrap(node.expression);
1655
+ if (callee.kind === ts.SyntaxKind.SuperKeyword) this.refuse(callee, "super is not supported");
1656
+ const mark = b.top;
1657
+ if (ts.isPropertyAccessExpression(callee)) {
1658
+ const objectType = this.typeOf(callee.expression);
1659
+ const name = callee.name.text;
1660
+ if (this.isArray(objectType) && (name === "push" || name === "pop")) {
1661
+ this.arrayMethod(callee, name, node.arguments, target);
1662
+ b.release(mark);
1663
+ return;
1664
+ }
1665
+ if (this.isString(objectType)) {
1666
+ this.stringMethod(callee, name, node.arguments, target);
1667
+ b.release(mark);
1668
+ return;
1669
+ }
1670
+ if (!this.isMathObject(callee.expression) && this.isSelfMethod(callee)) {
1671
+ const object = this.exprAny(callee.expression);
1672
+ const base2 = b.reserve(NAMECALL_ARGS_OFFSET + node.arguments.length);
1673
+ node.arguments.forEach((arg, i) => this.exprTo(arg, base2 + NAMECALL_ARGS_OFFSET + i));
1674
+ b.emit(abc(Op.NAMECALL, base2, object, 0), b.string(name));
1675
+ this.finishCall(base2, node.arguments.length + NAMECALL_ARGS_OFFSET, target);
1676
+ b.release(mark);
1677
+ return;
1678
+ }
1679
+ }
1680
+ const base = b.reserve(ARGS_OFFSET + node.arguments.length);
1681
+ this.exprTo(callee, base);
1682
+ node.arguments.forEach((arg, i) => this.exprTo(arg, base + ARGS_OFFSET + i));
1683
+ this.finishCall(base, node.arguments.length + ARGS_OFFSET, target);
1684
+ b.release(mark);
1685
+ }
1686
+ finishCall(base, argsPlusOne, target) {
1687
+ const b = this.fn.b;
1688
+ b.emit(abc(Op.CALL, base, argsPlusOne, target === null ? RESULTS_NONE : RESULTS_ONE));
1689
+ if (target !== null && target !== base) b.emit(abc(Op.MOVE, target, base, 0));
1690
+ }
1691
+ arrayMethod(callee, name, args, target) {
1692
+ const b = this.fn.b;
1693
+ const table = this.exprAny(callee.expression);
1694
+ const index = b.reserve(1);
1695
+ b.emit(abc(Op.LENGTH, index, table, 0));
1696
+ if (name === "push") {
1697
+ if (args.length !== 1) this.refuse(callee, "push takes one item in Rive scripts");
1698
+ b.emit(abc(Op.ADDK, index, index, b.number(ARRAY_BASE)));
1699
+ const value2 = this.exprAny(args[0]);
1700
+ b.emit(abc(Op.SETTABLE, value2, table, index));
1701
+ if (target !== null) b.emit(abc(Op.MOVE, target, index, 0));
1702
+ return;
1703
+ }
1704
+ const value = b.reserve(1);
1705
+ b.emit(abc(Op.GETTABLE, value, table, index));
1706
+ const nil = b.reserve(1);
1707
+ b.emit(abc(Op.LOADNIL, nil, 0, 0));
1708
+ b.emit(abc(Op.SETTABLE, nil, table, index));
1709
+ if (target !== null) b.emit(abc(Op.MOVE, target, value, 0));
1710
+ }
1711
+ stringMethod(callee, name, args, target) {
1712
+ const b = this.fn.b;
1713
+ const renames = { toUpperCase: "upper", toLowerCase: "lower", substring: "sub" };
1714
+ const method = renames[name];
1715
+ if (method === void 0) this.refuse(callee, `string method ${name} is not supported`);
1716
+ const object = this.exprAny(callee.expression);
1717
+ const base = b.reserve(NAMECALL_ARGS_OFFSET + args.length);
1718
+ if (name === "substring") {
1719
+ const start = args[0];
1720
+ if (start === void 0) this.refuse(callee, "substring needs a start");
1721
+ const first = this.exprAny(start);
1722
+ b.emit(abc(Op.ADDK, base + NAMECALL_ARGS_OFFSET, first, b.number(ARRAY_BASE)));
1723
+ if (args[1] !== void 0) this.exprTo(args[1], base + NAMECALL_ARGS_OFFSET + 1);
1724
+ }
1725
+ b.emit(abc(Op.NAMECALL, base, object, 0), b.string(method));
1726
+ this.finishCall(base, NAMECALL_ARGS_OFFSET + args.length, target);
1727
+ }
1728
+ newExpression(node, target) {
1729
+ const b = this.fn.b;
1730
+ const args = node.arguments ?? ts.factory.createNodeArray([]);
1731
+ for (const arg of args) if (ts.isSpreadElement(arg)) this.refuse(arg, "spread arguments are not supported");
1732
+ const constructor = this.exprAny(node.expression);
1733
+ const base = b.reserve(ARGS_OFFSET + args.length);
1734
+ b.emit(abc(Op.GETTABLEKS, base, constructor, 0), b.string("new"));
1735
+ args.forEach((arg, i) => this.exprTo(arg, base + ARGS_OFFSET + i));
1736
+ this.finishCall(base, args.length + ARGS_OFFSET, target);
1737
+ }
1738
+ prefix(node, target) {
1739
+ const b = this.fn.b;
1740
+ switch (node.operator) {
1741
+ case ts.SyntaxKind.MinusToken: {
1742
+ const operand = this.unwrap(node.operand);
1743
+ if (ts.isNumericLiteral(operand)) {
1744
+ b.loadNumber(target, -numberOf(operand));
1745
+ return;
1746
+ }
1747
+ const value = this.exprAny(operand);
1748
+ b.emit(abc(Op.MINUS, target, value, 0));
1749
+ return;
1750
+ }
1751
+ case ts.SyntaxKind.PlusToken:
1752
+ if (!this.isNumber(this.typeOf(node.operand))) this.refuse(node, "unary plus applies to numbers only");
1753
+ this.exprTo(node.operand, target);
1754
+ return;
1755
+ case ts.SyntaxKind.ExclamationToken:
1756
+ this.booleanTo(node, target);
1757
+ return;
1758
+ case ts.SyntaxKind.PlusPlusToken:
1759
+ case ts.SyntaxKind.MinusMinusToken:
1760
+ this.increment(node, target);
1761
+ return;
1762
+ default:
1763
+ this.refuse(node, "bitwise operators are not supported in Rive scripts yet");
1764
+ }
1765
+ }
1766
+ booleanTo(node, target) {
1767
+ const b = this.fn.b;
1768
+ const otherwise = b.label();
1769
+ const mark = b.top;
1770
+ this.jumpIfFalse(node, otherwise);
1771
+ b.release(mark);
1772
+ b.emit(abc(Op.LOADB, target, TRUE, SKIP_ONE));
1773
+ b.here(otherwise);
1774
+ b.emit(abc(Op.LOADB, target, FALSE, 0));
1775
+ }
1776
+ binary(node, target) {
1777
+ const b = this.fn.b;
1778
+ const kind = node.operatorToken.kind;
1779
+ if (this.isAssignment(kind)) {
1780
+ this.assignment(node, target);
1781
+ return;
1782
+ }
1783
+ switch (kind) {
1784
+ case ts.SyntaxKind.PlusToken:
1785
+ if (this.isString(this.typeOf(node))) {
1786
+ const parts = [];
1787
+ this.flattenConcat(node, parts);
1788
+ this.concat(parts, target);
1789
+ return;
1790
+ }
1791
+ this.arithmetic(Op.ADD, node.left, node.right, target);
1792
+ return;
1793
+ case ts.SyntaxKind.MinusToken:
1794
+ this.arithmetic(Op.SUB, node.left, node.right, target);
1795
+ return;
1796
+ case ts.SyntaxKind.AsteriskToken:
1797
+ this.arithmetic(Op.MUL, node.left, node.right, target);
1798
+ return;
1799
+ case ts.SyntaxKind.SlashToken:
1800
+ this.arithmetic(Op.DIV, node.left, node.right, target);
1801
+ return;
1802
+ case ts.SyntaxKind.AsteriskAsteriskToken:
1803
+ this.arithmetic(Op.POW, node.left, node.right, target);
1804
+ return;
1805
+ case ts.SyntaxKind.PercentToken: {
1806
+ const base = b.reserve(3);
1807
+ b.emit(abc(Op.GETGLOBAL, base, 0, 0), b.string("math"));
1808
+ b.emit(abc(Op.GETTABLEKS, base, base, 0), b.string("fmod"));
1809
+ this.exprTo(node.left, base + 1);
1810
+ this.exprTo(node.right, base + 2);
1811
+ b.emit(abc(Op.CALL, base, 3, RESULTS_ONE));
1812
+ if (base !== target) b.emit(abc(Op.MOVE, target, base, 0));
1813
+ return;
1814
+ }
1815
+ case ts.SyntaxKind.AmpersandAmpersandToken:
1816
+ case ts.SyntaxKind.BarBarToken: {
1817
+ const end = b.label();
1818
+ const leftType = this.typeOf(node.left);
1819
+ const scratch = b.reserve(1);
1820
+ this.exprTo(node.left, scratch);
1821
+ if (kind === ts.SyntaxKind.AmpersandAmpersandToken) {
1822
+ b.emit(abc(Op.MOVE, target, scratch, 0));
1823
+ this.falsyJumps(scratch, leftType, end);
1824
+ } else {
1825
+ const falsy = b.label();
1826
+ b.emit(abc(Op.MOVE, target, scratch, 0));
1827
+ this.falsyJumps(scratch, leftType, falsy);
1828
+ b.jump(end);
1829
+ b.here(falsy);
1830
+ }
1831
+ this.exprTo(node.right, target);
1832
+ b.here(end);
1833
+ return;
1834
+ }
1835
+ case ts.SyntaxKind.QuestionQuestionToken: {
1836
+ const end = b.label();
1837
+ const scratch = b.reserve(1);
1838
+ this.exprTo(node.left, scratch);
1839
+ b.emit(abc(Op.MOVE, target, scratch, 0));
1840
+ const nil = b.reserve(1);
1841
+ b.emit(abc(Op.LOADNIL, nil, 0, 0));
1842
+ b.jumpTo(Op.JUMPIFNOTEQ, scratch, end, nil);
1843
+ this.exprTo(node.right, target);
1844
+ b.here(end);
1845
+ return;
1846
+ }
1847
+ case ts.SyntaxKind.EqualsEqualsEqualsToken:
1848
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
1849
+ case ts.SyntaxKind.EqualsEqualsToken:
1850
+ case ts.SyntaxKind.ExclamationEqualsToken:
1851
+ case ts.SyntaxKind.LessThanToken:
1852
+ case ts.SyntaxKind.LessThanEqualsToken:
1853
+ case ts.SyntaxKind.GreaterThanToken:
1854
+ case ts.SyntaxKind.GreaterThanEqualsToken:
1855
+ this.booleanTo(node, target);
1856
+ return;
1857
+ case ts.SyntaxKind.CommaToken:
1858
+ this.effect(node.left);
1859
+ this.exprTo(node.right, target);
1860
+ return;
1861
+ default:
1862
+ this.refuse(node, `the ${ts.tokenToString(kind) ?? "operator"} operator is not supported in Rive scripts yet`);
1863
+ }
1864
+ }
1865
+ arithmetic(op, left, right, target) {
1866
+ const b = this.fn.b;
1867
+ for (const side of [left, right]) {
1868
+ if (!this.isNumber(this.typeOf(side))) this.refuse(side, "arithmetic applies to numbers only");
1869
+ }
1870
+ const rightInner = this.unwrap(right);
1871
+ if ((op === Op.ADD || op === Op.SUB) && ts.isNumericLiteral(rightInner)) {
1872
+ const a2 = this.exprAny(left);
1873
+ b.emit(abc(op === Op.ADD ? Op.ADDK : Op.SUBK, target, a2, b.number(numberOf(rightInner))));
1874
+ return;
1875
+ }
1876
+ const a = this.exprAny(left);
1877
+ const c = this.exprAny(right);
1878
+ b.emit(abc(op, target, a, c));
1879
+ }
1880
+ falsyJumps(reg, type, falsy) {
1881
+ const b = this.fn.b;
1882
+ b.jumpTo(Op.JUMPIFNOT, reg, falsy);
1883
+ const mark = b.top;
1884
+ if (this.mayBe(type, ts.TypeFlags.NumberLike)) {
1885
+ const zero = b.reserve(1);
1886
+ b.loadNumber(zero, 0);
1887
+ b.jumpTo(Op.JUMPIFEQ, reg, falsy, zero);
1888
+ b.jumpTo(Op.JUMPIFNOTEQ, reg, falsy, reg);
1889
+ }
1890
+ if (this.mayBe(type, ts.TypeFlags.StringLike)) {
1891
+ const empty = b.reserve(1);
1892
+ b.loadString(empty, "");
1893
+ b.jumpTo(Op.JUMPIFEQ, reg, falsy, empty);
1894
+ }
1895
+ b.release(mark);
1896
+ }
1897
+ jumpIfFalse(node, falsy) {
1898
+ const b = this.fn.b;
1899
+ const inner = this.unwrap(node);
1900
+ if (ts.isPrefixUnaryExpression(inner) && inner.operator === ts.SyntaxKind.ExclamationToken) {
1901
+ this.jumpIfTrue(inner.operand, falsy);
1902
+ return;
1903
+ }
1904
+ if (ts.isBinaryExpression(inner)) {
1905
+ const kind = inner.operatorToken.kind;
1906
+ if (kind === ts.SyntaxKind.AmpersandAmpersandToken) {
1907
+ this.jumpIfFalse(inner.left, falsy);
1908
+ this.jumpIfFalse(inner.right, falsy);
1909
+ return;
1910
+ }
1911
+ if (kind === ts.SyntaxKind.BarBarToken) {
1912
+ const truthy = b.label();
1913
+ this.jumpIfTrue(inner.left, truthy);
1914
+ this.jumpIfFalse(inner.right, falsy);
1915
+ b.here(truthy);
1916
+ return;
1917
+ }
1918
+ if (this.compare(inner, falsy, false)) return;
1919
+ }
1920
+ if (inner.kind === ts.SyntaxKind.TrueKeyword) return;
1921
+ const mark = b.top;
1922
+ const reg = this.exprAny(inner);
1923
+ this.falsyJumps(reg, this.typeOf(inner), falsy);
1924
+ b.release(mark);
1925
+ }
1926
+ jumpIfTrue(node, truthy) {
1927
+ const b = this.fn.b;
1928
+ const falsy = b.label();
1929
+ this.jumpIfFalse(node, falsy);
1930
+ b.jump(truthy);
1931
+ b.here(falsy);
1932
+ }
1933
+ compare(node, label, whenTrue) {
1934
+ const b = this.fn.b;
1935
+ const kind = node.operatorToken.kind;
1936
+ let op;
1937
+ let swap = false;
1938
+ switch (kind) {
1939
+ case ts.SyntaxKind.EqualsEqualsEqualsToken:
1940
+ case ts.SyntaxKind.EqualsEqualsToken:
1941
+ op = whenTrue ? Op.JUMPIFEQ : Op.JUMPIFNOTEQ;
1942
+ break;
1943
+ case ts.SyntaxKind.ExclamationEqualsEqualsToken:
1944
+ case ts.SyntaxKind.ExclamationEqualsToken:
1945
+ op = whenTrue ? Op.JUMPIFNOTEQ : Op.JUMPIFEQ;
1946
+ break;
1947
+ case ts.SyntaxKind.LessThanToken:
1948
+ op = whenTrue ? Op.JUMPIFLT : Op.JUMPIFNOTLT;
1949
+ break;
1950
+ case ts.SyntaxKind.LessThanEqualsToken:
1951
+ op = whenTrue ? Op.JUMPIFLE : Op.JUMPIFNOTLE;
1952
+ break;
1953
+ case ts.SyntaxKind.GreaterThanToken:
1954
+ op = whenTrue ? Op.JUMPIFLT : Op.JUMPIFNOTLT;
1955
+ swap = true;
1956
+ break;
1957
+ case ts.SyntaxKind.GreaterThanEqualsToken:
1958
+ op = whenTrue ? Op.JUMPIFLE : Op.JUMPIFNOTLE;
1959
+ swap = true;
1960
+ break;
1961
+ default:
1962
+ return false;
1963
+ }
1964
+ const ordered = op !== Op.JUMPIFEQ && op !== Op.JUMPIFNOTEQ;
1965
+ if (ordered) {
1966
+ for (const side of [node.left, node.right]) {
1967
+ const type = this.typeOf(side);
1968
+ if (!this.isNumber(type) && !this.isString(type)) this.refuse(side, "ordered comparisons apply to numbers or strings");
1969
+ }
1970
+ }
1971
+ const mark = b.top;
1972
+ const left = this.exprAny(node.left);
1973
+ const right = this.exprAny(node.right);
1974
+ const [a, c] = swap ? [right, left] : [left, right];
1975
+ b.jumpTo(op, a, label, c);
1976
+ b.release(mark);
1977
+ return true;
1978
+ }
1979
+ assignment(node, target) {
1980
+ const b = this.fn.b;
1981
+ const kind = node.operatorToken.kind;
1982
+ const left = this.unwrap(node.left);
1983
+ const compute = (into) => {
1984
+ if (kind === ts.SyntaxKind.EqualsToken) {
1985
+ this.exprTo(node.right, into);
1986
+ return;
1987
+ }
1988
+ const synthetic = this.compoundValue(node, left);
1989
+ synthetic(into);
1990
+ };
1991
+ if (ts.isIdentifier(left)) {
1992
+ const place = this.place(left);
1993
+ if (place.kind === "global") this.refuse(left, "globals cannot be assigned");
1994
+ const value = b.reserve(1);
1995
+ compute(value);
1996
+ if (place.kind === "local") b.emit(abc(Op.MOVE, place.reg, value, 0));
1997
+ else b.emit(abc(Op.SETUPVAL, value, place.index, 0));
1998
+ if (target !== null) b.emit(abc(Op.MOVE, target, value, 0));
1999
+ return;
2000
+ }
2001
+ if (ts.isPropertyAccessExpression(left)) {
2002
+ const object = this.exprAny(left.expression);
2003
+ const value = b.reserve(1);
2004
+ compute(value);
2005
+ b.emit(abc(Op.SETTABLEKS, value, object, 0), b.string(left.name.text));
2006
+ if (target !== null) b.emit(abc(Op.MOVE, target, value, 0));
2007
+ return;
2008
+ }
2009
+ if (ts.isElementAccessExpression(left)) {
2010
+ const object = this.exprAny(left.expression);
2011
+ const key = this.elementKey(left);
2012
+ const value = b.reserve(1);
2013
+ compute(value);
2014
+ b.emit(abc(Op.SETTABLE, value, object, key));
2015
+ if (target !== null) b.emit(abc(Op.MOVE, target, value, 0));
2016
+ return;
2017
+ }
2018
+ if (left.kind === ts.SyntaxKind.ThisKeyword) this.refuse(left, "this cannot be assigned");
2019
+ this.refuse(left, "this assignment target is not supported");
2020
+ }
2021
+ compoundValue(node, left) {
2022
+ const b = this.fn.b;
2023
+ const kind = node.operatorToken.kind;
2024
+ return (into) => {
2025
+ if (kind === ts.SyntaxKind.QuestionQuestionEqualsToken) {
2026
+ const end = b.label();
2027
+ this.exprTo(left, into);
2028
+ const mark = b.top;
2029
+ const nil = b.reserve(1);
2030
+ b.emit(abc(Op.LOADNIL, nil, 0, 0));
2031
+ b.jumpTo(Op.JUMPIFNOTEQ, into, end, nil);
2032
+ b.release(mark);
2033
+ this.exprTo(node.right, into);
2034
+ b.here(end);
2035
+ return;
2036
+ }
2037
+ if (kind === ts.SyntaxKind.PlusEqualsToken && this.isString(this.typeOf(left))) {
2038
+ const mark = b.top;
2039
+ const base = b.reserve(2);
2040
+ this.exprTo(left, base);
2041
+ this.concatOperand(node.right, base + 1);
2042
+ b.emit(abc(Op.CONCAT, into, base, base + 1));
2043
+ b.release(mark);
2044
+ return;
2045
+ }
2046
+ const ops = {
2047
+ [ts.SyntaxKind.PlusEqualsToken]: Op.ADD,
2048
+ [ts.SyntaxKind.MinusEqualsToken]: Op.SUB,
2049
+ [ts.SyntaxKind.AsteriskEqualsToken]: Op.MUL,
2050
+ [ts.SyntaxKind.SlashEqualsToken]: Op.DIV
2051
+ };
2052
+ const op = ops[kind];
2053
+ if (op === void 0) this.refuse(node, "this compound assignment is not supported");
2054
+ this.arithmetic(op, left, node.right, into);
2055
+ };
2056
+ }
2057
+ increment(node, target) {
2058
+ const b = this.fn.b;
2059
+ const step = node.operator === ts.SyntaxKind.PlusPlusToken ? Op.ADDK : Op.SUBK;
2060
+ const operand = this.unwrap(node.operand);
2061
+ if (!this.isNumber(this.typeOf(operand))) this.refuse(operand, "++ and -- apply to numbers only");
2062
+ const old = b.reserve(1);
2063
+ const value = b.reserve(1);
2064
+ const store = () => {
2065
+ if (ts.isIdentifier(operand)) {
2066
+ const place = this.place(operand);
2067
+ if (place.kind === "local") b.emit(abc(Op.MOVE, place.reg, value, 0));
2068
+ else if (place.kind === "upval") b.emit(abc(Op.SETUPVAL, value, place.index, 0));
2069
+ else this.refuse(operand, "globals cannot be assigned");
2070
+ }
2071
+ };
2072
+ if (ts.isIdentifier(operand)) {
2073
+ this.exprTo(operand, old);
2074
+ b.emit(abc(step, value, old, b.number(1)));
2075
+ store();
2076
+ } else if (ts.isPropertyAccessExpression(operand)) {
2077
+ const object = this.exprAny(operand.expression);
2078
+ b.emit(abc(Op.GETTABLEKS, old, object, 0), b.string(operand.name.text));
2079
+ b.emit(abc(step, value, old, b.number(1)));
2080
+ b.emit(abc(Op.SETTABLEKS, value, object, 0), b.string(operand.name.text));
2081
+ } else if (ts.isElementAccessExpression(operand)) {
2082
+ const object = this.exprAny(operand.expression);
2083
+ const key = this.elementKey(operand);
2084
+ b.emit(abc(Op.GETTABLE, old, object, key));
2085
+ b.emit(abc(step, value, old, b.number(1)));
2086
+ b.emit(abc(Op.SETTABLE, value, object, key));
2087
+ } else {
2088
+ this.refuse(operand, "this increment target is not supported");
2089
+ }
2090
+ if (target !== null) {
2091
+ const prefix = ts.isPrefixUnaryExpression(node);
2092
+ b.emit(abc(Op.MOVE, target, prefix ? value : old, 0));
2093
+ }
2094
+ }
2095
+ };
2096
+ function lowerError(error, source) {
2097
+ if (error instanceof Refusal) {
2098
+ const { line, character } = source.getLineAndCharacterOfPosition(error.node.getStart(source));
2099
+ return { message: error.message, line: line + 1, column: character + 1 };
2100
+ }
2101
+ if (error instanceof CompileLimit) return { message: TOO_LARGE, line: 0, column: 0 };
2102
+ return null;
2103
+ }
2104
+
2105
+ // src/interactives/scripting/ts/compile.ts
2106
+ var OPTIONS = {
2107
+ noLib: true,
2108
+ strict: true,
2109
+ target: ts.ScriptTarget.ES2020,
2110
+ module: ts.ModuleKind.ESNext,
2111
+ types: [],
2112
+ noEmit: true,
2113
+ allowUnreachableCode: false
2114
+ };
2115
+ var LIB_TEXT = {
2116
+ rive: LIB_SOURCE,
2117
+ tool: `${LIB_SOURCE}${TOOL_LIB_SOURCE}`
2118
+ };
2119
+ var libraries = /* @__PURE__ */ new Map();
2120
+ function library(kind) {
2121
+ let file = libraries.get(kind);
2122
+ if (file === void 0) {
2123
+ file = ts.createSourceFile(LIB_FILE, LIB_TEXT[kind], ts.ScriptTarget.ES2020, true);
2124
+ libraries.set(kind, file);
2125
+ }
2126
+ return file;
2127
+ }
2128
+ function host(fileName, source, kind) {
2129
+ const files = /* @__PURE__ */ new Map([
2130
+ [fileName, ts.createSourceFile(fileName, source, ts.ScriptTarget.ES2020, true)],
2131
+ [LIB_FILE, library(kind)]
2132
+ ]);
2133
+ return {
2134
+ getSourceFile: (name) => files.get(name),
2135
+ getDefaultLibFileName: () => LIB_FILE,
2136
+ writeFile: () => void 0,
2137
+ getCurrentDirectory: () => "",
2138
+ getCanonicalFileName: (name) => name,
2139
+ useCaseSensitiveFileNames: () => true,
2140
+ getNewLine: () => "\n",
2141
+ fileExists: (name) => files.has(name),
2142
+ readFile: (name) => files.get(name)?.text,
2143
+ getDirectories: () => []
2144
+ };
2145
+ }
2146
+ function diagnostic2(d) {
2147
+ const message = ts.flattenDiagnosticMessageText(d.messageText, "\n");
2148
+ if (d.file === void 0 || d.start === void 0) return { message, line: 0, column: 0 };
2149
+ const { line, character } = d.file.getLineAndCharacterOfPosition(d.start);
2150
+ return { message, line: line + 1, column: character + 1 };
2151
+ }
2152
+ function compileScript(fileName, source, kind = "rive") {
2153
+ const program = ts.createProgram({ rootNames: [fileName, LIB_FILE], options: OPTIONS, host: host(fileName, source, kind) });
2154
+ const diagnostics = ts.getPreEmitDiagnostics(program).map(diagnostic2);
2155
+ if (diagnostics.length > 0) return { ok: false, diagnostics };
2156
+ const file = program.getSourceFile(fileName);
2157
+ if (file === void 0) return { ok: false, diagnostics: [{ message: "the script did not parse", line: 0, column: 0 }] };
2158
+ const lowering = new Lowering(program.getTypeChecker(), file);
2159
+ try {
2160
+ const main = lowering.compileModule();
2161
+ return { ok: true, bytecode: writeBytecode(lowering.protos, main) };
2162
+ } catch (error) {
2163
+ const found = lowerError(error, file);
2164
+ if (found === null) throw error;
2165
+ return { ok: false, diagnostics: [found] };
2166
+ }
2167
+ }
2168
+
2169
+ export { PASSTHROUGH_CONVERTER, assetKind, checkRefusals, compileGroups, compileScript, extensionOf, groupOf, isCodePath };