@defold-typescript/types 0.33.1 → 0.35.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.
- package/api-signatures.json +156 -183
- package/api-targets.json +9 -66
- package/generated/buffer.d.ts +2 -2
- package/generated/collectionfactory.d.ts +2 -2
- package/generated/factory.d.ts +2 -2
- package/generated/gui.d.ts +23 -23
- package/generated/kinds/gui-script.d.ts +0 -4
- package/generated/kinds/render-script.d.ts +1 -4
- package/generated/kinds/script.d.ts +0 -4
- package/generated/model.d.ts +2 -2
- package/generated/profiler.d.ts +2 -4
- package/generated/render.d.ts +2 -150
- package/generated/sys.d.ts +1 -1
- package/generated/versions/defold-1.12.4/buffer.d.ts +2 -2
- package/generated/versions/defold-1.12.4/collectionfactory.d.ts +2 -2
- package/generated/versions/defold-1.12.4/factory.d.ts +2 -2
- package/generated/versions/defold-1.12.4/gui.d.ts +23 -23
- package/generated/versions/defold-1.12.4/index.d.ts +9 -4
- package/generated/versions/defold-1.12.4/model.d.ts +2 -2
- package/generated/versions/defold-1.12.4/profiler.d.ts +2 -4
- package/generated/versions/defold-1.12.4/render.d.ts +2 -150
- package/generated/versions/defold-1.12.4/sys.d.ts +1 -1
- package/generated/versions/defold-1.12.4/vmath.d.ts +0 -19
- package/generated/versions/defold-1.12.4/window.d.ts +2 -4
- package/generated/versions/defold-1.13.0/buffer.d.ts +2 -2
- package/generated/versions/defold-1.13.0/collectionfactory.d.ts +2 -2
- package/generated/versions/defold-1.13.0/factory.d.ts +2 -2
- package/generated/versions/defold-1.13.0/gui.d.ts +23 -23
- package/generated/versions/defold-1.13.0/index.d.ts +9 -4
- package/generated/versions/defold-1.13.0/model.d.ts +2 -2
- package/generated/versions/defold-1.13.0/profiler.d.ts +2 -4
- package/generated/versions/defold-1.13.0/render.d.ts +2 -150
- package/generated/versions/defold-1.13.0/sys.d.ts +1 -1
- package/generated/versions/defold-1.13.0/vmath.d.ts +0 -19
- package/generated/versions/defold-1.13.0/window.d.ts +2 -4
- package/generated/vmath.d.ts +0 -19
- package/generated/window.d.ts +2 -4
- package/index.d.ts +1 -4
- package/package.json +4 -2
- package/scripts/extension-goldens.ts +23 -0
- package/scripts/generate-api-signatures.ts +40 -1
- package/scripts/materialize-version.ts +15 -1
- package/scripts/regen.ts +109 -27
- package/scripts/signature-store-fs.ts +1 -0
- package/scripts/sync-api-docs.ts +11 -61
- package/src/doc-comment.ts +10 -6
- package/src/emit-dts.ts +212 -21
- package/src/optional-correction-provenance.ts +13 -2
- package/src/render-overloads.d.ts +29 -0
- package/src/script-api.ts +154 -23
- package/src/vmath-overloads.d.ts +19 -0
- package/generated/iac.d.ts +0 -18
- package/generated/iap.d.ts +0 -60
- package/generated/push.d.ts +0 -66
- package/generated/versions/defold-1.12.4/iac.d.ts +0 -18
- package/generated/versions/defold-1.12.4/iap.d.ts +0 -60
- package/generated/versions/defold-1.12.4/push.d.ts +0 -66
- package/generated/versions/defold-1.12.4/webview.d.ts +0 -68
- package/generated/versions/defold-1.13.0/iac.d.ts +0 -18
- package/generated/versions/defold-1.13.0/iap.d.ts +0 -60
- package/generated/versions/defold-1.13.0/push.d.ts +0 -66
- package/generated/versions/defold-1.13.0/webview.d.ts +0 -68
- package/generated/webview.d.ts +0 -68
- package/scripts/fidelity-audit.ts +0 -684
|
@@ -24,6 +24,7 @@ export const SOCKET_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures
|
|
|
24
24
|
export const VMATH_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "vmath.json");
|
|
25
25
|
export const GO_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "go.json");
|
|
26
26
|
export const MSG_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "msg.json");
|
|
27
|
+
export const RENDER_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "render.json");
|
|
27
28
|
|
|
28
29
|
export function loadSignatureFile(path: string): SignatureStore {
|
|
29
30
|
let raw: string;
|
package/scripts/sync-api-docs.ts
CHANGED
|
@@ -109,9 +109,9 @@ export const SYNC_MANIFEST: readonly SyncManifestEntry[] = [
|
|
|
109
109
|
entry("zlib", "doc/src-script_zlib.cpp_doc.json"),
|
|
110
110
|
];
|
|
111
111
|
|
|
112
|
-
// Checklist namespaces with no machine-readable doc anywhere
|
|
113
|
-
// ref-doc.zip
|
|
114
|
-
//
|
|
112
|
+
// Checklist namespaces with no machine-readable doc anywhere in core
|
|
113
|
+
// ref-doc.zip. Currently empty: extension namespaces are not engine surfaces;
|
|
114
|
+
// they are typed through `resolve` from each extension's own `.script_api`.
|
|
115
115
|
export const UNMAPPED: ReadonlyMap<string, string> = new Map();
|
|
116
116
|
|
|
117
117
|
// A Lua script namespace is a lowercase, dot-separated identifier (`sys`,
|
|
@@ -211,53 +211,18 @@ function entry(
|
|
|
211
211
|
return { namespace, zipEntry, fixture, ...(mergeEntries ? { mergeEntries } : {}) };
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
export interface ExtensionManifestEntry {
|
|
215
|
-
readonly namespace: string;
|
|
216
|
-
readonly repo: string;
|
|
217
|
-
readonly tag: string;
|
|
218
|
-
readonly path: string;
|
|
219
|
-
readonly fixture: string;
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
// Extension-only namespaces: each ships a single `.script_api` (YAML) doc in
|
|
223
|
-
// its own repo rather than appearing in core ref-doc.zip. Pinned to a release
|
|
224
|
-
// tag and converted to the core ref-doc JSON shape via parseScriptApi so they
|
|
225
|
-
// flow through MODULE_MANIFEST and the drift guard like every core namespace.
|
|
226
|
-
export const EXTENSION_MANIFEST: readonly ExtensionManifestEntry[] = [
|
|
227
|
-
ext("iac", "defold/extension-iac", "1.4.0", "extension-iac/api/iac.script_api"),
|
|
228
|
-
ext("iap", "defold/extension-iap", "8.4.0", "extension-iap/api/iap.script_api"),
|
|
229
|
-
ext("push", "defold/extension-push", "4.1.0", "extension-push/api/push.script_api"),
|
|
230
|
-
ext("webview", "defold/extension-webview", "1.5.0", "webview/api/webview.script_api"),
|
|
231
|
-
];
|
|
232
|
-
|
|
233
|
-
function ext(namespace: string, repo: string, tag: string, path: string): ExtensionManifestEntry {
|
|
234
|
-
return {
|
|
235
|
-
namespace,
|
|
236
|
-
repo,
|
|
237
|
-
tag,
|
|
238
|
-
path,
|
|
239
|
-
fixture: `fixtures/defold-1.13.1/${namespace}_doc.json`,
|
|
240
|
-
};
|
|
241
|
-
}
|
|
242
|
-
|
|
243
214
|
// Every vendored fixture set the coverage report audits, and the namespaces it
|
|
244
215
|
// counts as reached from upstream. Composed once here so the `--check` run and
|
|
245
216
|
// the guard over it cannot disagree about which sets are in scope.
|
|
246
217
|
export const COVERAGE_MANIFEST: readonly { readonly namespace: string }[] = [
|
|
247
218
|
...SYNC_MANIFEST,
|
|
248
|
-
...EXTENSION_MANIFEST,
|
|
249
219
|
...EDITOR_MANIFEST,
|
|
250
220
|
];
|
|
251
221
|
|
|
252
222
|
export const UPSTREAM_MAPPED_NAMESPACES: ReadonlySet<string> = new Set(
|
|
253
|
-
[...SYNC_MANIFEST, ...
|
|
254
|
-
(e) => e.namespace,
|
|
255
|
-
),
|
|
223
|
+
[...SYNC_MANIFEST, ...LUA_STDLIB_MANIFEST, ...EDITOR_MANIFEST].map((e) => e.namespace),
|
|
256
224
|
);
|
|
257
225
|
|
|
258
|
-
export const extensionRawUrl = (e: ExtensionManifestEntry): string =>
|
|
259
|
-
`https://raw.githubusercontent.com/${e.repo}/${e.tag}/${e.path}`;
|
|
260
|
-
|
|
261
226
|
// Convert a raw `.script_api` YAML doc to the core ref-doc JSON string written
|
|
262
227
|
// to fixtures/<ns>_doc.json. The result is byte-compared by the same drift
|
|
263
228
|
// semantics core fixtures use.
|
|
@@ -265,6 +230,12 @@ export function scriptApiToFixtureJson(text: string): string {
|
|
|
265
230
|
return JSON.stringify(parseScriptApi(text));
|
|
266
231
|
}
|
|
267
232
|
|
|
233
|
+
// The docs-only variant: the same ref-doc JSON with constants kept, for pages
|
|
234
|
+
// that render a module's full surface rather than feed the emitter.
|
|
235
|
+
export function scriptApiToDocsJson(text: string): string {
|
|
236
|
+
return JSON.stringify(parseScriptApi(text, { complete: true }));
|
|
237
|
+
}
|
|
238
|
+
|
|
268
239
|
// The types-api-coverage `What` checklist in vision.md lists every namespace as
|
|
269
240
|
// a backtick-quoted token on the "Concrete breadth checklist" line. Reading it
|
|
270
241
|
// here keeps SYNC_MANIFEST + UNMAPPED honest against the source of truth: the
|
|
@@ -486,25 +457,6 @@ export function syncExtractedFixtures(
|
|
|
486
457
|
return results;
|
|
487
458
|
}
|
|
488
459
|
|
|
489
|
-
export async function downloadExtensionFixtures(
|
|
490
|
-
manifest: readonly ExtensionManifestEntry[] = EXTENSION_MANIFEST,
|
|
491
|
-
): Promise<ExtractedFixture[]> {
|
|
492
|
-
const out: ExtractedFixture[] = [];
|
|
493
|
-
for (const e of manifest) {
|
|
494
|
-
const url = extensionRawUrl(e);
|
|
495
|
-
const res = await fetch(url);
|
|
496
|
-
if (!res.ok) {
|
|
497
|
-
throw new Error(`extension doc download failed: ${url} -> ${res.status} ${res.statusText}`);
|
|
498
|
-
}
|
|
499
|
-
out.push({
|
|
500
|
-
namespace: e.namespace,
|
|
501
|
-
fixture: e.fixture,
|
|
502
|
-
contents: scriptApiToFixtureJson(await res.text()),
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
return out;
|
|
506
|
-
}
|
|
507
|
-
|
|
508
460
|
function readFixtureOrNull(path: string): string | null {
|
|
509
461
|
try {
|
|
510
462
|
return readFileSync(path, "utf8");
|
|
@@ -675,18 +627,16 @@ if (import.meta.main) {
|
|
|
675
627
|
const zip = zipPath ? readZip(zipPath) : await downloadZip();
|
|
676
628
|
|
|
677
629
|
const coreFixtures = extractFixtures(zip);
|
|
678
|
-
const extensionFixtures = await downloadExtensionFixtures();
|
|
679
630
|
const luaStdlibFixtures = extractFixtures(zip, LUA_STDLIB_MANIFEST);
|
|
680
631
|
const editorFixtures = extractFixtures(zip, EDITOR_MANIFEST);
|
|
681
632
|
const editorVmFixtures = extractFixtures(zip, EDITOR_VM_MANIFEST);
|
|
682
633
|
const results = [
|
|
683
634
|
...syncExtractedFixtures(coreFixtures, { check }),
|
|
684
|
-
...syncExtractedFixtures(extensionFixtures, { check }),
|
|
685
635
|
...syncExtractedFixtures(luaStdlibFixtures, { check }),
|
|
686
636
|
...syncExtractedFixtures(editorFixtures, { check }),
|
|
687
637
|
...syncExtractedFixtures(editorVmFixtures, { check }),
|
|
688
638
|
];
|
|
689
|
-
const syncedDocs =
|
|
639
|
+
const syncedDocs = coreFixtures.map((f) => ({
|
|
690
640
|
namespace: f.namespace,
|
|
691
641
|
doc: JSON.parse(f.contents),
|
|
692
642
|
}));
|
package/src/doc-comment.ts
CHANGED
|
@@ -73,10 +73,12 @@ export function htmlToCodeText(html: string): string {
|
|
|
73
73
|
/**
|
|
74
74
|
* Convert a ref-doc `examples` HTML fragment — prose interleaved with one or
|
|
75
75
|
* more `<div class="codehilite">…</div>` syntax-highlight blocks — into Markdown:
|
|
76
|
-
* prose runs become `htmlToDocText`, each highlight block becomes a
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
76
|
+
* prose runs become `htmlToDocText`, each highlight block becomes a fence via
|
|
77
|
+
* `htmlToCodeText`. The fence language comes from a `class="language-X"` on the
|
|
78
|
+
* block's `<code>` (as converted extension `.script_api` examples carry), else
|
|
79
|
+
* `lua`, since engine ref-doc blocks carry no language class. A fragment with no
|
|
80
|
+
* `codehilite` block is wrapped whole as a single ` ```lua ` fence (back-compat
|
|
81
|
+
* for plain-code examples). Returns `""` for empty / whitespace-only input.
|
|
80
82
|
*/
|
|
81
83
|
export function examplesHtmlToMarkdown(html: string): string {
|
|
82
84
|
if (html.trim() === "") return "";
|
|
@@ -89,8 +91,10 @@ export function examplesHtmlToMarkdown(html: string): string {
|
|
|
89
91
|
matched = true;
|
|
90
92
|
const prose = htmlToDocText(html.slice(lastIndex, match.index));
|
|
91
93
|
if (prose !== "") parts.push(prose);
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
+
const inner = match[1] ?? "";
|
|
95
|
+
const lang = /<code\b[^>]*\bclass="language-([^"\s]+)"/i.exec(inner)?.[1] ?? "lua";
|
|
96
|
+
const code = htmlToCodeText(inner);
|
|
97
|
+
if (code !== "") parts.push(`\`\`\`${lang}\n${code}\n\`\`\``);
|
|
94
98
|
lastIndex = match.index + match[0].length;
|
|
95
99
|
}
|
|
96
100
|
|
package/src/emit-dts.ts
CHANGED
|
@@ -151,11 +151,10 @@ export const ARBITRARY_TABLE_SLOTS = new Set([
|
|
|
151
151
|
"socket.dns.toip",
|
|
152
152
|
"socket.dns.getaddrinfo",
|
|
153
153
|
"socket.dns.getnameinfo",
|
|
154
|
-
// engine-built render-target tables: the "see the description" cross-
|
|
155
|
-
//
|
|
154
|
+
// engine-built render-target tables: the "see the description" cross-ref is
|
|
155
|
+
// dead (the function's own description is empty) or carries a typed
|
|
156
156
|
// `transient: table` field whose sub-doc is prose-only, so the nested table
|
|
157
157
|
// is opaque to the field-list parser and the whole-slot `Record` is faithful.
|
|
158
|
-
"render.render_target",
|
|
159
158
|
"render.set_render_target",
|
|
160
159
|
// reserved-but-undocumented options bag: `collectionproxy.load`'s `options`
|
|
161
160
|
// slot is documented verbatim as "options table, currently unused" and accepts
|
|
@@ -204,6 +203,10 @@ export const OVERLOAD_COVERED_SKIPS = new Set([
|
|
|
204
203
|
// msg-overloads.d.ts supplies the typed msg.url shape (0 / 1-string / 3-arg
|
|
205
204
|
// arities; the runtime-invalid two-arg form is intentionally omitted).
|
|
206
205
|
"msg.url",
|
|
206
|
+
// render-overloads.d.ts supplies the name-less and named render_target arities.
|
|
207
|
+
"render.render_target",
|
|
208
|
+
// vmath-overloads.d.ts supplies the vector3 and three-number euler_to_quat arities.
|
|
209
|
+
"vmath.euler_to_quat",
|
|
207
210
|
// vmath-overloads.d.ts supplies the generic covariant signatures.
|
|
208
211
|
"vmath.clamp",
|
|
209
212
|
"vmath.lerp",
|
|
@@ -351,6 +354,119 @@ export const OPTIONAL_SLOT_CORRECTIONS: ReadonlyMap<string, string> = new Map([
|
|
|
351
354
|
),
|
|
352
355
|
]);
|
|
353
356
|
|
|
357
|
+
export type ConstantSlotResolution =
|
|
358
|
+
| { readonly borrow: string }
|
|
359
|
+
| { readonly family: string; readonly evidence: string }
|
|
360
|
+
| { readonly residual: string };
|
|
361
|
+
|
|
362
|
+
// A top-level `constant` slot takes the constants its own doc names. This table
|
|
363
|
+
// fills only a slot whose own doc names none: a `borrow` reads another slot's doc
|
|
364
|
+
// (same key shape), a `family` expands a `<prefix>*` wildcard evidenced by the
|
|
365
|
+
// named element's example, and a `residual` records why nothing can brand it.
|
|
366
|
+
// Constants always come from the brand universe, never from a hand-typed list.
|
|
367
|
+
export const CONSTANT_SLOT_RESOLUTIONS: ReadonlyMap<string, ConstantSlotResolution> = new Map<
|
|
368
|
+
string,
|
|
369
|
+
ConstantSlotResolution
|
|
370
|
+
>([
|
|
371
|
+
["gui.get:param:property", { borrow: "gui.animate:param:property" }],
|
|
372
|
+
["gui.set:param:property", { borrow: "gui.animate:param:property" }],
|
|
373
|
+
["gui.cancel_animations:param:property", { borrow: "gui.animate:param:property" }],
|
|
374
|
+
[
|
|
375
|
+
"buffer.set_metadata:param:value_type",
|
|
376
|
+
{ family: "buffer.VALUE_TYPE_*", evidence: "buffer.set_metadata" },
|
|
377
|
+
],
|
|
378
|
+
[
|
|
379
|
+
"buffer.get_metadata:return:value_type",
|
|
380
|
+
{ family: "buffer.VALUE_TYPE_*", evidence: "buffer.set_metadata" },
|
|
381
|
+
],
|
|
382
|
+
["gui.new_texture:param:type", { residual: "the doc lists texture type strings only" }],
|
|
383
|
+
["gui.set_texture_data:param:type", { residual: "the doc lists texture type strings only" }],
|
|
384
|
+
[
|
|
385
|
+
"iap.get_provider_id:return:provider_id",
|
|
386
|
+
{ residual: "the doc names iap.PROVIDER_ID_*, which no ref-doc defines as a constant" },
|
|
387
|
+
],
|
|
388
|
+
]);
|
|
389
|
+
|
|
390
|
+
const DOC_CONSTANT_TOKEN =
|
|
391
|
+
/(?<![A-Za-z0-9_.])([a-z][a-z0-9_]*(?:\.[a-z][a-z0-9_]*)*\.[A-Z][A-Z0-9_]*)(\*)?/g;
|
|
392
|
+
|
|
393
|
+
// The constant FQNs a piece of ref-doc text names, in doc order: exact tokens kept
|
|
394
|
+
// only when they are in `universe`, and each `<prefix>*` wildcard expanded to every
|
|
395
|
+
// universe FQN with that prefix, sorted.
|
|
396
|
+
export function documentedConstantTokens(text: string, universe: ReadonlySet<string>): string[] {
|
|
397
|
+
const out = new Set<string>();
|
|
398
|
+
for (const match of text.replace(/<[^>]*>/g, "").matchAll(DOC_CONSTANT_TOKEN)) {
|
|
399
|
+
const token = match[1] as string;
|
|
400
|
+
if (match[2] === undefined) {
|
|
401
|
+
if (universe.has(token)) out.add(token);
|
|
402
|
+
continue;
|
|
403
|
+
}
|
|
404
|
+
for (const fqn of [...universe].filter((candidate) => candidate.startsWith(token)).sort()) {
|
|
405
|
+
out.add(fqn);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
return [...out];
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
type SlotDocLookup = (slotKey: string) => string | undefined;
|
|
412
|
+
|
|
413
|
+
function constantSlotTokens(
|
|
414
|
+
ownDoc: string,
|
|
415
|
+
slotKey: string,
|
|
416
|
+
lookupDoc: SlotDocLookup,
|
|
417
|
+
universe: ReadonlySet<string>,
|
|
418
|
+
): string[] {
|
|
419
|
+
const own = documentedConstantTokens(ownDoc, universe);
|
|
420
|
+
if (own.length > 0) return own;
|
|
421
|
+
const entry = CONSTANT_SLOT_RESOLUTIONS.get(slotKey);
|
|
422
|
+
if (entry === undefined || "residual" in entry) return [];
|
|
423
|
+
if ("borrow" in entry) return documentedConstantTokens(lookupDoc(entry.borrow) ?? "", universe);
|
|
424
|
+
return documentedConstantTokens(entry.family, universe);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function slotDocLookup(module: ApiModule): SlotDocLookup {
|
|
428
|
+
const docs = new Map<string, string>();
|
|
429
|
+
for (const fn of module.functions) {
|
|
430
|
+
for (const p of fn.parameters) {
|
|
431
|
+
const key = tableSlotKey(fn.name, "param", p.name);
|
|
432
|
+
if (!docs.has(key)) docs.set(key, p.doc);
|
|
433
|
+
}
|
|
434
|
+
for (const rv of fn.returnValues) {
|
|
435
|
+
const key = tableSlotKey(fn.name, "return", rv.name);
|
|
436
|
+
if (!docs.has(key)) docs.set(key, rv.doc);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
return (slotKey) => docs.get(slotKey);
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
// The constants a module's top-level `constant` slot expands into: its own doc
|
|
443
|
+
// first, then its CONSTANT_SLOT_RESOLUTIONS entry. Empty means the slot keeps
|
|
444
|
+
// `Opaque<"constant">`.
|
|
445
|
+
export function resolveConstantSlotTokens(
|
|
446
|
+
module: ApiModule,
|
|
447
|
+
slotKey: string,
|
|
448
|
+
universe: ReadonlySet<string>,
|
|
449
|
+
): string[] {
|
|
450
|
+
const lookupDoc = slotDocLookup(module);
|
|
451
|
+
return constantSlotTokens(lookupDoc(slotKey) ?? "", slotKey, lookupDoc, universe);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
type ConstantSlotTokens = (
|
|
455
|
+
elementName: string,
|
|
456
|
+
slotKind: "param" | "return",
|
|
457
|
+
slotName: string,
|
|
458
|
+
doc: string,
|
|
459
|
+
) => readonly string[];
|
|
460
|
+
|
|
461
|
+
function constantSlotTokenResolver(
|
|
462
|
+
module: ApiModule,
|
|
463
|
+
universe: ReadonlySet<string>,
|
|
464
|
+
): ConstantSlotTokens {
|
|
465
|
+
const lookupDoc = slotDocLookup(module);
|
|
466
|
+
return (elementName, slotKind, slotName, doc) =>
|
|
467
|
+
constantSlotTokens(doc, tableSlotKey(elementName, slotKind, slotName), lookupDoc, universe);
|
|
468
|
+
}
|
|
469
|
+
|
|
354
470
|
// FQN-keyed allowlist of the `types.is_*` checks that genuinely narrow their
|
|
355
471
|
// argument, mapped to the `DEFOLD_TYPE_MAP` token whose interface they prove.
|
|
356
472
|
// Emitting these as user-defined type guards (`var_ is Vector3`) is the only way
|
|
@@ -1580,6 +1696,10 @@ export function emitDeclarations(module: ApiModule, options?: EmitOptions): stri
|
|
|
1580
1696
|
constantFqns.has(token) || knownConstantFqns?.has(token)
|
|
1581
1697
|
? brandType(token)
|
|
1582
1698
|
: baseMapType(token);
|
|
1699
|
+
const constantTokens = constantSlotTokenResolver(
|
|
1700
|
+
module,
|
|
1701
|
+
new Set([...constantFqns, ...(knownConstantFqns ?? [])]),
|
|
1702
|
+
);
|
|
1583
1703
|
|
|
1584
1704
|
const constants = module.constants
|
|
1585
1705
|
.map((c) => prepareConstant(c, prefix))
|
|
@@ -1656,7 +1776,9 @@ export function emitDeclarations(module: ApiModule, options?: EmitOptions): stri
|
|
|
1656
1776
|
for (const docLine of functionDocLines(fn.original, translations, handleIndent)) {
|
|
1657
1777
|
lines.push(docLine);
|
|
1658
1778
|
}
|
|
1659
|
-
lines.push(
|
|
1779
|
+
lines.push(
|
|
1780
|
+
`${handleIndent}${emitMethod(fn, mapType, resolver, constantTokens, urlParameters)}`,
|
|
1781
|
+
);
|
|
1660
1782
|
}
|
|
1661
1783
|
lines.push(`${INDENT}}`);
|
|
1662
1784
|
}
|
|
@@ -1685,7 +1807,7 @@ export function emitDeclarations(module: ApiModule, options?: EmitOptions): stri
|
|
|
1685
1807
|
const reserved = TS_RESERVED_NAMES.has(fn.name);
|
|
1686
1808
|
const emitName = aliasName(fn.name, aliases);
|
|
1687
1809
|
for (const docLine of functionDocLines(fn.original, translations)) lines.push(docLine);
|
|
1688
|
-
const line = emitFunction(fn, emitName, mapType, resolver, urlParameters);
|
|
1810
|
+
const line = emitFunction(fn, emitName, mapType, resolver, constantTokens, urlParameters);
|
|
1689
1811
|
lines.push(`${INDENT}${reserved ? "" : decl}${line}`);
|
|
1690
1812
|
}
|
|
1691
1813
|
|
|
@@ -1733,7 +1855,7 @@ export function emitDeclarations(module: ApiModule, options?: EmitOptions): stri
|
|
|
1733
1855
|
lines.push(docLine);
|
|
1734
1856
|
}
|
|
1735
1857
|
lines.push(
|
|
1736
|
-
`${bodyIndent}${reserved ? "" : segmentDecl}${emitFunction(fn, emitName, mapType, resolver, urlParameters)}`,
|
|
1858
|
+
`${bodyIndent}${reserved ? "" : segmentDecl}${emitFunction(fn, emitName, mapType, resolver, constantTokens, urlParameters)}`,
|
|
1737
1859
|
);
|
|
1738
1860
|
}
|
|
1739
1861
|
for (const alias of [...segmentAliases].sort((a, b) => a.public.localeCompare(b.public))) {
|
|
@@ -1789,6 +1911,10 @@ export function emitSymbolSignatures(module: ApiModule, options?: EmitOptions):
|
|
|
1789
1911
|
constantFqns.has(token) || knownConstantFqns?.has(token)
|
|
1790
1912
|
? brandType(token)
|
|
1791
1913
|
: baseMapType(token);
|
|
1914
|
+
const constantTokens = constantSlotTokenResolver(
|
|
1915
|
+
module,
|
|
1916
|
+
new Set([...constantFqns, ...(knownConstantFqns ?? [])]),
|
|
1917
|
+
);
|
|
1792
1918
|
const resolver = buildTableDocResolver(
|
|
1793
1919
|
module.functions.map((fn) => ({
|
|
1794
1920
|
name: fn.name,
|
|
@@ -1815,6 +1941,7 @@ export function emitSymbolSignatures(module: ApiModule, options?: EmitOptions):
|
|
|
1815
1941
|
emitName(prepared.name),
|
|
1816
1942
|
mapType,
|
|
1817
1943
|
resolver,
|
|
1944
|
+
constantTokens,
|
|
1818
1945
|
urlParameters,
|
|
1819
1946
|
),
|
|
1820
1947
|
});
|
|
@@ -1835,7 +1962,14 @@ export function emitSymbolSignatures(module: ApiModule, options?: EmitOptions):
|
|
|
1835
1962
|
for (const fn of nested.functions) {
|
|
1836
1963
|
out.push({
|
|
1837
1964
|
identity: fnIdentity(fn.original),
|
|
1838
|
-
tsSignature: emitFunction(
|
|
1965
|
+
tsSignature: emitFunction(
|
|
1966
|
+
fn,
|
|
1967
|
+
emitName(fn.name),
|
|
1968
|
+
mapType,
|
|
1969
|
+
resolver,
|
|
1970
|
+
constantTokens,
|
|
1971
|
+
urlParameters,
|
|
1972
|
+
),
|
|
1839
1973
|
});
|
|
1840
1974
|
}
|
|
1841
1975
|
|
|
@@ -1844,7 +1978,7 @@ export function emitSymbolSignatures(module: ApiModule, options?: EmitOptions):
|
|
|
1844
1978
|
for (const prepared of group) {
|
|
1845
1979
|
out.push({
|
|
1846
1980
|
identity: fnIdentity(prepared.original),
|
|
1847
|
-
tsSignature: emitMethod(prepared, mapType, resolver, urlParameters),
|
|
1981
|
+
tsSignature: emitMethod(prepared, mapType, resolver, constantTokens, urlParameters),
|
|
1848
1982
|
});
|
|
1849
1983
|
}
|
|
1850
1984
|
}
|
|
@@ -2072,6 +2206,7 @@ function memberSignature(
|
|
|
2072
2206
|
name: string,
|
|
2073
2207
|
mapType: (t: string) => string,
|
|
2074
2208
|
resolver: TableDocResolver,
|
|
2209
|
+
constantTokens: ConstantSlotTokens,
|
|
2075
2210
|
urlParameters: UrlParameterTable,
|
|
2076
2211
|
): string {
|
|
2077
2212
|
const original = prepared.original.parameters;
|
|
@@ -2079,17 +2214,31 @@ function memberSignature(
|
|
|
2079
2214
|
const cutoff = trailingOptionalCutoff(original, elementName);
|
|
2080
2215
|
const varargIndex = original.findIndex(isVarargParameter);
|
|
2081
2216
|
const positional = (varargIndex === -1 ? original : original.slice(0, varargIndex)).map((p, i) =>
|
|
2082
|
-
emitParameter(p, i, i >= cutoff, mapType, resolver, elementName, urlParameters),
|
|
2217
|
+
emitParameter(p, i, i >= cutoff, mapType, resolver, constantTokens, elementName, urlParameters),
|
|
2083
2218
|
);
|
|
2084
2219
|
const params = (
|
|
2085
2220
|
varargIndex === -1
|
|
2086
2221
|
? positional
|
|
2087
2222
|
: [
|
|
2088
2223
|
...positional,
|
|
2089
|
-
emitRestParameter(
|
|
2224
|
+
emitRestParameter(
|
|
2225
|
+
original,
|
|
2226
|
+
varargIndex,
|
|
2227
|
+
mapType,
|
|
2228
|
+
resolver,
|
|
2229
|
+
constantTokens,
|
|
2230
|
+
elementName,
|
|
2231
|
+
urlParameters,
|
|
2232
|
+
),
|
|
2090
2233
|
]
|
|
2091
2234
|
).join(", ");
|
|
2092
|
-
const ret = emitReturn(
|
|
2235
|
+
const ret = emitReturn(
|
|
2236
|
+
prepared.original.returnValues,
|
|
2237
|
+
mapType,
|
|
2238
|
+
resolver,
|
|
2239
|
+
constantTokens,
|
|
2240
|
+
elementName,
|
|
2241
|
+
);
|
|
2093
2242
|
const predicateToken = TYPE_PREDICATES.get(elementName);
|
|
2094
2243
|
const soleParam = original[0];
|
|
2095
2244
|
if (
|
|
@@ -2108,9 +2257,10 @@ function emitFunction(
|
|
|
2108
2257
|
name: string,
|
|
2109
2258
|
mapType: (t: string) => string,
|
|
2110
2259
|
resolver: TableDocResolver,
|
|
2260
|
+
constantTokens: ConstantSlotTokens,
|
|
2111
2261
|
urlParameters: UrlParameterTable,
|
|
2112
2262
|
): string {
|
|
2113
|
-
return `function ${memberSignature(prepared, name, mapType, resolver, urlParameters)}`;
|
|
2263
|
+
return `function ${memberSignature(prepared, name, mapType, resolver, constantTokens, urlParameters)}`;
|
|
2114
2264
|
}
|
|
2115
2265
|
|
|
2116
2266
|
// A colon-method member of a handle interface: identical signature machinery to a
|
|
@@ -2120,9 +2270,10 @@ function emitMethod(
|
|
|
2120
2270
|
prepared: PreparedFunction,
|
|
2121
2271
|
mapType: (t: string) => string,
|
|
2122
2272
|
resolver: TableDocResolver,
|
|
2273
|
+
constantTokens: ConstantSlotTokens,
|
|
2123
2274
|
urlParameters: UrlParameterTable,
|
|
2124
2275
|
): string {
|
|
2125
|
-
return memberSignature(prepared, prepared.name, mapType, resolver, urlParameters);
|
|
2276
|
+
return memberSignature(prepared, prepared.name, mapType, resolver, constantTokens, urlParameters);
|
|
2126
2277
|
}
|
|
2127
2278
|
|
|
2128
2279
|
// Build the indented JSDoc lines for a function from its ref-doc prose. The
|
|
@@ -2238,6 +2389,7 @@ function parameterType(
|
|
|
2238
2389
|
p: ApiParameter,
|
|
2239
2390
|
mapType: (t: string) => string,
|
|
2240
2391
|
resolver: TableDocResolver,
|
|
2392
|
+
constantTokens: ConstantSlotTokens,
|
|
2241
2393
|
elementName: string,
|
|
2242
2394
|
urlParameters: UrlParameterTable,
|
|
2243
2395
|
): string {
|
|
@@ -2247,13 +2399,25 @@ function parameterType(
|
|
|
2247
2399
|
const alias = SCENE_ADDRESS_ALIASES[classifyUrlParameter(urlParameters, elementName, p.name)];
|
|
2248
2400
|
const slotMapType = alias === undefined ? mapType : addressMapType(mapType, alias);
|
|
2249
2401
|
return concrete.length > 0
|
|
2250
|
-
? mapSlotUnion(
|
|
2402
|
+
? mapSlotUnion(
|
|
2403
|
+
concrete,
|
|
2404
|
+
p.doc,
|
|
2405
|
+
slotMapType,
|
|
2406
|
+
true,
|
|
2407
|
+
resolver,
|
|
2408
|
+
constantTokens,
|
|
2409
|
+
elementName,
|
|
2410
|
+
"param",
|
|
2411
|
+
p.name,
|
|
2412
|
+
)
|
|
2251
2413
|
: "unknown";
|
|
2252
2414
|
}
|
|
2253
2415
|
|
|
2254
2416
|
const VARARG_PREFIX = "...";
|
|
2255
2417
|
|
|
2256
|
-
|
|
2418
|
+
// Exported because the fidelity audit must ask the same question about the
|
|
2419
|
+
// same input: what the emitted declaration accepts is the emitter's to decide.
|
|
2420
|
+
export function isVarargParameter(p: ApiParameter): boolean {
|
|
2257
2421
|
return p.name.startsWith(VARARG_PREFIX);
|
|
2258
2422
|
}
|
|
2259
2423
|
|
|
@@ -2277,6 +2441,7 @@ function emitRestParameter(
|
|
|
2277
2441
|
varargIndex: number,
|
|
2278
2442
|
mapType: (t: string) => string,
|
|
2279
2443
|
resolver: TableDocResolver,
|
|
2444
|
+
constantTokens: ConstantSlotTokens,
|
|
2280
2445
|
elementName: string,
|
|
2281
2446
|
urlParameters: UrlParameterTable,
|
|
2282
2447
|
): string {
|
|
@@ -2286,7 +2451,9 @@ function emitRestParameter(
|
|
|
2286
2451
|
...new Set(
|
|
2287
2452
|
params
|
|
2288
2453
|
.slice(varargIndex)
|
|
2289
|
-
.map((p) =>
|
|
2454
|
+
.map((p) =>
|
|
2455
|
+
parameterType(p, mapType, resolver, constantTokens, elementName, urlParameters),
|
|
2456
|
+
),
|
|
2290
2457
|
),
|
|
2291
2458
|
];
|
|
2292
2459
|
const first = members[0] ?? "unknown";
|
|
@@ -2300,11 +2467,12 @@ function emitParameter(
|
|
|
2300
2467
|
optional: boolean,
|
|
2301
2468
|
mapType: (t: string) => string,
|
|
2302
2469
|
resolver: TableDocResolver,
|
|
2470
|
+
constantTokens: ConstantSlotTokens,
|
|
2303
2471
|
elementName: string,
|
|
2304
2472
|
urlParameters: UrlParameterTable,
|
|
2305
2473
|
): string {
|
|
2306
2474
|
const name = safeParamName(p.name, index);
|
|
2307
|
-
const ts = parameterType(p, mapType, resolver, elementName, urlParameters);
|
|
2475
|
+
const ts = parameterType(p, mapType, resolver, constantTokens, elementName, urlParameters);
|
|
2308
2476
|
// An interior doc-optional param (a required param follows, so the trailing-`?`
|
|
2309
2477
|
// projection cannot mark it) keeps its optionality as `| undefined` — TSTL
|
|
2310
2478
|
// lowers `undefined` to `nil`, the faithful call. Trailing optionals keep the
|
|
@@ -2317,6 +2485,7 @@ function emitReturn(
|
|
|
2317
2485
|
returnValues: ApiParameter[],
|
|
2318
2486
|
mapType: (t: string) => string,
|
|
2319
2487
|
resolver: TableDocResolver,
|
|
2488
|
+
constantTokens: ConstantSlotTokens,
|
|
2320
2489
|
elementName: string,
|
|
2321
2490
|
): { type: string; trailing: string } {
|
|
2322
2491
|
const override = RETURN_TYPE_OVERRIDES.get(elementName);
|
|
@@ -2328,7 +2497,17 @@ function emitReturn(
|
|
|
2328
2497
|
// typescript-to-lua erases to `local a, b = fn()`.
|
|
2329
2498
|
const slots = returnValues.map((rv) =>
|
|
2330
2499
|
rv.types.length > 0
|
|
2331
|
-
? mapSlotUnion(
|
|
2500
|
+
? mapSlotUnion(
|
|
2501
|
+
rv.types,
|
|
2502
|
+
rv.doc,
|
|
2503
|
+
mapType,
|
|
2504
|
+
false,
|
|
2505
|
+
resolver,
|
|
2506
|
+
constantTokens,
|
|
2507
|
+
elementName,
|
|
2508
|
+
"return",
|
|
2509
|
+
rv.name,
|
|
2510
|
+
)
|
|
2332
2511
|
: "unknown",
|
|
2333
2512
|
);
|
|
2334
2513
|
return { type: `LuaMultiReturn<[${slots.join(", ")}]>`, trailing: "" };
|
|
@@ -2343,6 +2522,7 @@ function emitReturn(
|
|
|
2343
2522
|
mapType,
|
|
2344
2523
|
false,
|
|
2345
2524
|
resolver,
|
|
2525
|
+
constantTokens,
|
|
2346
2526
|
elementName,
|
|
2347
2527
|
"return",
|
|
2348
2528
|
first.name,
|
|
@@ -2380,13 +2560,26 @@ function mapSlotUnion(
|
|
|
2380
2560
|
mapType: (t: string) => string,
|
|
2381
2561
|
optionalFields: boolean,
|
|
2382
2562
|
resolver: TableDocResolver,
|
|
2563
|
+
constantTokens: ConstantSlotTokens,
|
|
2383
2564
|
elementName: string,
|
|
2384
2565
|
slotKind?: "param" | "return",
|
|
2385
2566
|
slotName?: string,
|
|
2386
2567
|
): string {
|
|
2387
2568
|
const mapped: string[] = [];
|
|
2388
2569
|
const seen = new Set<string>();
|
|
2570
|
+
const push = (ts: string): void => {
|
|
2571
|
+
if (seen.has(ts)) return;
|
|
2572
|
+
seen.add(ts);
|
|
2573
|
+
mapped.push(ts);
|
|
2574
|
+
};
|
|
2389
2575
|
for (const token of types) {
|
|
2576
|
+
if (token === "constant" && slotKind !== undefined && slotName !== undefined) {
|
|
2577
|
+
const expanded = constantTokens(elementName, slotKind, slotName, doc);
|
|
2578
|
+
if (expanded.length > 0) {
|
|
2579
|
+
for (const fqn of expanded) push(mapType(fqn));
|
|
2580
|
+
continue;
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2390
2583
|
let ts: string;
|
|
2391
2584
|
if (token === "table") {
|
|
2392
2585
|
const curation =
|
|
@@ -2457,9 +2650,7 @@ function mapSlotUnion(
|
|
|
2457
2650
|
: undefined;
|
|
2458
2651
|
ts = curated ?? mapType(token);
|
|
2459
2652
|
}
|
|
2460
|
-
|
|
2461
|
-
seen.add(ts);
|
|
2462
|
-
mapped.push(ts);
|
|
2653
|
+
push(ts);
|
|
2463
2654
|
}
|
|
2464
2655
|
// A genuine `unknown` member (an `any` slot, including `any | nil`) absorbs
|
|
2465
2656
|
// every other union member, so collapse to exactly `unknown` rather than emit
|
|
@@ -24,13 +24,19 @@ interface VersionedManifestEntry extends ManifestEntry {
|
|
|
24
24
|
readonly editor?: boolean;
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
// The provenance target the committed extension goldens are recorded under. They
|
|
28
|
+
// belong to no engine version: `resolve` applies the same correction table to them.
|
|
29
|
+
export const EXTENSION_GOLDENS_TARGET = "extension-goldens";
|
|
30
|
+
|
|
27
31
|
// Every runtime module regen emits through the global correction table: the
|
|
28
|
-
// default target's manifest plus every older generated target's
|
|
29
|
-
// entries are outside the scope the
|
|
32
|
+
// default target's manifest plus every older generated target's, plus the
|
|
33
|
+
// extension goldens when given. Editor-VM entries are outside the scope the
|
|
34
|
+
// corrections cover.
|
|
30
35
|
export function retainedSurfaces(
|
|
31
36
|
defaultTarget: string,
|
|
32
37
|
defaultManifest: readonly ManifestEntry[],
|
|
33
38
|
versionedManifest: readonly VersionedManifestEntry[],
|
|
39
|
+
extensionGoldenManifest: readonly ManifestEntry[] = [],
|
|
34
40
|
): ProvenanceSurface[] {
|
|
35
41
|
return [
|
|
36
42
|
...defaultManifest.map((entry) => ({
|
|
@@ -41,6 +47,11 @@ export function retainedSurfaces(
|
|
|
41
47
|
...versionedManifest
|
|
42
48
|
.filter((entry) => entry.editor !== true)
|
|
43
49
|
.map((entry) => ({ target: entry.versionId, namespace: entry.namespace, doc: entry.doc })),
|
|
50
|
+
...extensionGoldenManifest.map((entry) => ({
|
|
51
|
+
target: EXTENSION_GOLDENS_TARGET,
|
|
52
|
+
namespace: entry.namespace,
|
|
53
|
+
doc: entry.doc,
|
|
54
|
+
})),
|
|
44
55
|
];
|
|
45
56
|
}
|
|
46
57
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** @noSelfInFile */
|
|
2
|
+
|
|
3
|
+
import type { Opaque } from "./core-types";
|
|
4
|
+
|
|
5
|
+
declare global {
|
|
6
|
+
namespace render {
|
|
7
|
+
/**
|
|
8
|
+
* Creates a new render target according to the supplied specification table.
|
|
9
|
+
* The parameter table is keyed by buffer type, with one parameter table per
|
|
10
|
+
* attachment; see the reference for the available keys and values.
|
|
11
|
+
*
|
|
12
|
+
* @param parameters - table of buffer parameters, see the description for available keys and values
|
|
13
|
+
* @returns new render target
|
|
14
|
+
*/
|
|
15
|
+
function render_target(parameters: Record<string | number, unknown>): Opaque<"render_target">;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new named render target according to the supplied specification
|
|
18
|
+
* table. The name is used by the profiler and by render target lookups.
|
|
19
|
+
*
|
|
20
|
+
* @param name - render target name
|
|
21
|
+
* @param parameters - table of buffer parameters, see the description for available keys and values
|
|
22
|
+
* @returns new render target
|
|
23
|
+
*/
|
|
24
|
+
function render_target(
|
|
25
|
+
name: string,
|
|
26
|
+
parameters: Record<string | number, unknown>,
|
|
27
|
+
): Opaque<"render_target">;
|
|
28
|
+
}
|
|
29
|
+
}
|