@defold-typescript/types 0.51.0 → 0.53.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 (228) hide show
  1. package/api-availability.json +4 -58
  2. package/api-signatures.json +2804 -3172
  3. package/api-targets.json +15 -5
  4. package/examples/translations.json +19 -71
  5. package/generated/b2d.d.ts +39 -39
  6. package/generated/b2d_body.d.ts +11 -11
  7. package/generated/b2d_chain.d.ts +3 -3
  8. package/generated/b2d_fixture.d.ts +5 -5
  9. package/generated/b2d_joint.d.ts +29 -29
  10. package/generated/b2d_shape.d.ts +13 -13
  11. package/generated/b2d_world.d.ts +15 -15
  12. package/generated/buffer.d.ts +10 -11
  13. package/generated/bullet3d.d.ts +6 -6
  14. package/generated/bullet3d_collision_object.d.ts +10 -10
  15. package/generated/bullet3d_constraint.d.ts +173 -71
  16. package/generated/bullet3d_rigid_body.d.ts +3 -3
  17. package/generated/bullet3d_shape.d.ts +11 -11
  18. package/generated/bullet3d_world.d.ts +20 -20
  19. package/generated/camera.d.ts +4 -4
  20. package/generated/collectionfactory.d.ts +2 -3
  21. package/generated/collectionproxy.d.ts +5 -5
  22. package/generated/compute.d.ts +5 -5
  23. package/generated/crash.d.ts +7 -7
  24. package/generated/editor-vm/http.d.ts +13 -13
  25. package/generated/editor-vm/image.d.ts +4 -4
  26. package/generated/editor-vm/json.d.ts +1 -1
  27. package/generated/editor-vm/tilemap_tiles.d.ts +9 -9
  28. package/generated/editor-vm/zip.d.ts +4 -4
  29. package/generated/editor.d.ts +183 -183
  30. package/generated/factory.d.ts +2 -3
  31. package/generated/font.d.ts +4 -4
  32. package/generated/go.d.ts +122 -230
  33. package/generated/graphics.d.ts +23 -25
  34. package/generated/gui.d.ts +186 -423
  35. package/generated/http.d.ts +3 -3
  36. package/generated/image.d.ts +63 -11
  37. package/generated/json.d.ts +4 -4
  38. package/generated/kinds/gui-script.d.ts +2 -0
  39. package/generated/kinds/render-script.d.ts +14 -15
  40. package/generated/label.d.ts +5 -5
  41. package/generated/liveupdate.d.ts +7 -3
  42. package/generated/material.d.ts +49 -49
  43. package/generated/model.d.ts +46 -14
  44. package/generated/particlefx.d.ts +24 -5
  45. package/generated/physics.d.ts +64 -20
  46. package/generated/profiler.d.ts +3 -5
  47. package/generated/render-script-modules/b2d.d.ts +711 -0
  48. package/generated/render-script-modules/bullet3d.d.ts +73 -0
  49. package/generated/render-script-modules/collectionfactory.d.ts +24 -0
  50. package/generated/render-script-modules/collectionproxy.d.ts +39 -0
  51. package/generated/render-script-modules/factory.d.ts +24 -0
  52. package/generated/render-script-modules/go.d.ts +434 -0
  53. package/generated/render-script-modules/label.d.ts +105 -0
  54. package/generated/render-script-modules/model.d.ts +121 -0
  55. package/generated/render-script-modules/particlefx.d.ts +59 -0
  56. package/generated/render-script-modules/physics.d.ts +333 -0
  57. package/generated/render-script-modules/resource.d.ts +1232 -0
  58. package/generated/render-script-modules/sound.d.ts +227 -0
  59. package/generated/render-script-modules/sprite.d.ts +68 -0
  60. package/generated/render-script-modules/tilemap.d.ts +43 -0
  61. package/generated/render.d.ts +172 -47
  62. package/generated/resource.d.ts +81 -61
  63. package/generated/socket.d.ts +18 -23
  64. package/generated/sound.d.ts +6 -6
  65. package/generated/sprite.d.ts +51 -3
  66. package/generated/sys.d.ts +87 -24
  67. package/generated/tilemap.d.ts +3 -3
  68. package/generated/timer.d.ts +3 -3
  69. package/generated/versions/defold-1.12.4/b2d.d.ts +2 -2
  70. package/generated/versions/defold-1.12.4/b2d_body.d.ts +2 -2
  71. package/generated/versions/defold-1.12.4/buffer.d.ts +8 -8
  72. package/generated/versions/defold-1.12.4/go.d.ts +117 -345
  73. package/generated/versions/defold-1.12.4/graphics.d.ts +2 -1
  74. package/generated/versions/defold-1.12.4/gui.d.ts +169 -532
  75. package/generated/versions/defold-1.12.4/http.d.ts +2 -2
  76. package/generated/versions/defold-1.12.4/image.d.ts +82 -2
  77. package/generated/versions/defold-1.12.4/index.d.ts +1 -0
  78. package/generated/versions/defold-1.12.4/label.d.ts +1 -1
  79. package/generated/versions/defold-1.12.4/liveupdate.d.ts +4 -0
  80. package/generated/versions/defold-1.12.4/model.d.ts +42 -10
  81. package/generated/versions/defold-1.12.4/particlefx.d.ts +23 -2
  82. package/generated/versions/defold-1.12.4/physics.d.ts +46 -2
  83. package/generated/versions/defold-1.12.4/render.d.ts +83 -7
  84. package/generated/versions/defold-1.12.4/resource.d.ts +50 -17
  85. package/generated/versions/defold-1.12.4/socket.d.ts +12 -12
  86. package/generated/versions/defold-1.12.4/sound.d.ts +1 -1
  87. package/generated/versions/defold-1.12.4/sprite.d.ts +59 -2
  88. package/generated/versions/defold-1.12.4/sys.d.ts +103 -8
  89. package/generated/versions/defold-1.12.4/tilemap.d.ts +1 -1
  90. package/generated/versions/defold-1.12.4/vmath.d.ts +0 -24
  91. package/generated/versions/defold-1.12.4/window.d.ts +3 -4
  92. package/generated/versions/defold-1.13.0/b2d.d.ts +2 -2
  93. package/generated/versions/defold-1.13.0/b2d_body.d.ts +2 -2
  94. package/generated/versions/defold-1.13.0/b2d_chain.d.ts +1 -1
  95. package/generated/versions/defold-1.13.0/b2d_joint.d.ts +1 -1
  96. package/generated/versions/defold-1.13.0/b2d_shape.d.ts +1 -1
  97. package/generated/versions/defold-1.13.0/buffer.d.ts +8 -8
  98. package/generated/versions/defold-1.13.0/camera.d.ts +1 -1
  99. package/generated/versions/defold-1.13.0/go.d.ts +117 -372
  100. package/generated/versions/defold-1.13.0/graphics.d.ts +2 -1
  101. package/generated/versions/defold-1.13.0/gui.d.ts +169 -532
  102. package/generated/versions/defold-1.13.0/http.d.ts +2 -2
  103. package/generated/versions/defold-1.13.0/image.d.ts +82 -2
  104. package/generated/versions/defold-1.13.0/index.d.ts +1 -0
  105. package/generated/versions/defold-1.13.0/label.d.ts +1 -1
  106. package/generated/versions/defold-1.13.0/liveupdate.d.ts +4 -0
  107. package/generated/versions/defold-1.13.0/material.d.ts +3 -1
  108. package/generated/versions/defold-1.13.0/model.d.ts +42 -10
  109. package/generated/versions/defold-1.13.0/particlefx.d.ts +23 -2
  110. package/generated/versions/defold-1.13.0/physics.d.ts +46 -2
  111. package/generated/versions/defold-1.13.0/render.d.ts +147 -9
  112. package/generated/versions/defold-1.13.0/resource.d.ts +50 -17
  113. package/generated/versions/defold-1.13.0/socket.d.ts +12 -12
  114. package/generated/versions/defold-1.13.0/sound.d.ts +1 -1
  115. package/generated/versions/defold-1.13.0/sprite.d.ts +59 -2
  116. package/generated/versions/defold-1.13.0/sys.d.ts +103 -8
  117. package/generated/versions/defold-1.13.0/tilemap.d.ts +1 -1
  118. package/generated/versions/defold-1.13.0/vmath.d.ts +0 -24
  119. package/generated/versions/defold-1.13.0/window.d.ts +3 -4
  120. package/generated/versions/defold-1.13.1/b2d.d.ts +2 -2
  121. package/generated/versions/defold-1.13.1/b2d_body.d.ts +2 -2
  122. package/generated/versions/defold-1.13.1/b2d_chain.d.ts +1 -1
  123. package/generated/versions/defold-1.13.1/b2d_joint.d.ts +1 -1
  124. package/generated/versions/defold-1.13.1/b2d_shape.d.ts +1 -1
  125. package/generated/versions/defold-1.13.1/buffer.d.ts +8 -8
  126. package/generated/versions/defold-1.13.1/camera.d.ts +1 -1
  127. package/generated/versions/defold-1.13.1/go.d.ts +117 -372
  128. package/generated/versions/defold-1.13.1/graphics.d.ts +2 -1
  129. package/generated/versions/defold-1.13.1/gui.d.ts +169 -548
  130. package/generated/versions/defold-1.13.1/http.d.ts +2 -2
  131. package/generated/versions/defold-1.13.1/image.d.ts +82 -2
  132. package/generated/versions/defold-1.13.1/index.d.ts +2 -0
  133. package/generated/versions/defold-1.13.1/label.d.ts +1 -1
  134. package/generated/versions/defold-1.13.1/liveupdate.d.ts +4 -0
  135. package/generated/versions/defold-1.13.1/material.d.ts +3 -1
  136. package/generated/versions/defold-1.13.1/model.d.ts +42 -10
  137. package/generated/versions/defold-1.13.1/particlefx.d.ts +23 -2
  138. package/generated/versions/defold-1.13.1/physics.d.ts +46 -2
  139. package/generated/versions/defold-1.13.1/render.d.ts +147 -9
  140. package/generated/versions/defold-1.13.1/resource.d.ts +50 -17
  141. package/generated/versions/defold-1.13.1/socket.d.ts +12 -12
  142. package/generated/versions/defold-1.13.1/sound.d.ts +1 -1
  143. package/generated/versions/defold-1.13.1/sprite.d.ts +59 -2
  144. package/generated/versions/defold-1.13.1/sys.d.ts +103 -8
  145. package/generated/versions/defold-1.13.1/tilemap.d.ts +1 -1
  146. package/generated/versions/defold-1.13.1/vmath.d.ts +0 -24
  147. package/generated/versions/defold-1.13.1/window.d.ts +3 -4
  148. package/generated/versions/defold-1.13.2/b2d.d.ts +39 -39
  149. package/generated/versions/defold-1.13.2/b2d_body.d.ts +11 -11
  150. package/generated/versions/defold-1.13.2/b2d_chain.d.ts +3 -3
  151. package/generated/versions/defold-1.13.2/b2d_fixture.d.ts +5 -5
  152. package/generated/versions/defold-1.13.2/b2d_joint.d.ts +29 -29
  153. package/generated/versions/defold-1.13.2/b2d_shape.d.ts +13 -13
  154. package/generated/versions/defold-1.13.2/b2d_world.d.ts +15 -15
  155. package/generated/versions/defold-1.13.2/buffer.d.ts +10 -11
  156. package/generated/versions/defold-1.13.2/bullet3d.d.ts +6 -6
  157. package/generated/versions/defold-1.13.2/bullet3d_collision_object.d.ts +10 -10
  158. package/generated/versions/defold-1.13.2/bullet3d_constraint.d.ts +173 -71
  159. package/generated/versions/defold-1.13.2/bullet3d_rigid_body.d.ts +3 -3
  160. package/generated/versions/defold-1.13.2/bullet3d_shape.d.ts +11 -11
  161. package/generated/versions/defold-1.13.2/bullet3d_world.d.ts +20 -20
  162. package/generated/versions/defold-1.13.2/camera.d.ts +4 -4
  163. package/generated/versions/defold-1.13.2/collectionfactory.d.ts +2 -3
  164. package/generated/versions/defold-1.13.2/collectionproxy.d.ts +5 -5
  165. package/generated/versions/defold-1.13.2/compute.d.ts +5 -5
  166. package/generated/versions/defold-1.13.2/crash.d.ts +7 -7
  167. package/generated/versions/defold-1.13.2/editor-vm/http.d.ts +13 -13
  168. package/generated/versions/defold-1.13.2/editor-vm/image.d.ts +4 -4
  169. package/generated/versions/defold-1.13.2/editor-vm/json.d.ts +1 -1
  170. package/generated/versions/defold-1.13.2/editor-vm/tilemap_tiles.d.ts +9 -9
  171. package/generated/versions/defold-1.13.2/editor-vm/zip.d.ts +4 -4
  172. package/generated/versions/defold-1.13.2/editor.d.ts +183 -183
  173. package/generated/versions/defold-1.13.2/factory.d.ts +2 -3
  174. package/generated/versions/defold-1.13.2/font.d.ts +4 -4
  175. package/generated/versions/defold-1.13.2/go.d.ts +122 -230
  176. package/generated/versions/defold-1.13.2/graphics.d.ts +22 -24
  177. package/generated/versions/defold-1.13.2/gui.d.ts +186 -423
  178. package/generated/versions/defold-1.13.2/http.d.ts +3 -3
  179. package/generated/versions/defold-1.13.2/image.d.ts +63 -11
  180. package/generated/versions/defold-1.13.2/index.d.ts +2 -0
  181. package/generated/versions/defold-1.13.2/json.d.ts +4 -4
  182. package/generated/versions/defold-1.13.2/label.d.ts +5 -5
  183. package/generated/versions/defold-1.13.2/liveupdate.d.ts +7 -3
  184. package/generated/versions/defold-1.13.2/material.d.ts +49 -49
  185. package/generated/versions/defold-1.13.2/model.d.ts +46 -14
  186. package/generated/versions/defold-1.13.2/particlefx.d.ts +24 -5
  187. package/generated/versions/defold-1.13.2/physics.d.ts +64 -20
  188. package/generated/versions/defold-1.13.2/profiler.d.ts +3 -5
  189. package/generated/versions/defold-1.13.2/render.d.ts +161 -46
  190. package/generated/versions/defold-1.13.2/resource.d.ts +81 -61
  191. package/generated/versions/defold-1.13.2/socket.d.ts +18 -23
  192. package/generated/versions/defold-1.13.2/sound.d.ts +6 -6
  193. package/generated/versions/defold-1.13.2/sprite.d.ts +51 -3
  194. package/generated/versions/defold-1.13.2/sys.d.ts +87 -24
  195. package/generated/versions/defold-1.13.2/tilemap.d.ts +3 -3
  196. package/generated/versions/defold-1.13.2/timer.d.ts +3 -3
  197. package/generated/versions/defold-1.13.2/vmath.d.ts +0 -25
  198. package/generated/versions/defold-1.13.2/window.d.ts +8 -10
  199. package/generated/vmath.d.ts +0 -25
  200. package/generated/window.d.ts +8 -10
  201. package/identity-vocabulary.json +86 -34
  202. package/index.d.ts +2 -0
  203. package/package.json +3 -1
  204. package/scripts/generate-api-availability.ts +10 -24
  205. package/scripts/generate-api-signatures.ts +75 -14
  206. package/scripts/materialize-version.ts +48 -7
  207. package/scripts/regen.ts +214 -19
  208. package/scripts/shared-handle-methods.ts +3 -2
  209. package/scripts/signature-store-fs.ts +1 -0
  210. package/scripts/target-version.ts +26 -0
  211. package/src/api-doc.ts +34 -0
  212. package/src/api-identity.ts +32 -1
  213. package/src/component-properties.d.ts +96 -7
  214. package/src/core-types.ts +71 -28
  215. package/src/doc-corrections.ts +62 -5
  216. package/src/emit-dts.ts +1423 -401
  217. package/src/engine-globals.d.ts +5 -1
  218. package/src/engine-type-name.ts +33 -0
  219. package/src/go-overloads.d.ts +74 -19
  220. package/src/gui-overloads.d.ts +489 -0
  221. package/src/gui-texture-removal.d.ts +41 -0
  222. package/src/index.ts +3 -0
  223. package/src/lifecycle.ts +32 -23
  224. package/src/msg-overloads.d.ts +25 -13
  225. package/src/signature-store.ts +50 -0
  226. package/src/socket-types.d.ts +3 -3
  227. package/src/timers.d.ts +2 -1
  228. package/src/vmath-overloads.d.ts +26 -0
package/scripts/regen.ts CHANGED
@@ -44,6 +44,7 @@ import { loadTranslations } from "./example-store-io";
44
44
  import { synthesizeProseConstants } from "./prose-constants";
45
45
  import { restoreSharedHandleMethods } from "./shared-handle-methods";
46
46
  import { groupDocsByNamespace, mergeApiDocs, type readZip } from "./sync-api-docs";
47
+ import { compareVersions, versionOf } from "./target-version";
47
48
 
48
49
  export interface ApiTargetModule {
49
50
  readonly namespace: string;
@@ -461,12 +462,19 @@ export interface GenerateOptions {
461
462
  urlParameters?: UrlParameterTable;
462
463
  registeredConstants?: ReadonlySet<string>;
463
464
  bindingEvidence?: ReadonlySet<string>;
465
+ nilRaisingSlots?: ReadonlyMap<string, readonly number[]>;
464
466
  // The modules the entry is emitted beside, the entry among them. Routing
465
467
  // reads this set instead of looking the entry up in a committed manifest, so
466
468
  // a surface built with its own import root still routes as a whole.
467
469
  surface?: readonly ModuleManifestEntry[];
468
470
  }
469
471
 
472
+ // What a target's own engine source decides for its emit (`targetBindingOptions`).
473
+ export type TargetBindingOptions = Pick<
474
+ GenerateOptions,
475
+ "registeredConstants" | "bindingEvidence" | "nilRaisingSlots"
476
+ >;
477
+
470
478
  interface PreparedGeneratedModule {
471
479
  module: ApiModule;
472
480
  knownConstantFqns: ReadonlySet<string>;
@@ -474,6 +482,7 @@ interface PreparedGeneratedModule {
474
482
  urlParameters: UrlParameterTable;
475
483
  registeredConstants: ReadonlySet<string> | undefined;
476
484
  bindingEvidence: ReadonlySet<string> | undefined;
485
+ nilRaisingSlots: ReadonlyMap<string, readonly number[]> | undefined;
477
486
  typeLeaves: Readonly<Record<string, string>> | undefined;
478
487
  declaredTypes: ReadonlyMap<string, string> | undefined;
479
488
  dropped: string[];
@@ -500,6 +509,7 @@ function prepareGeneratedModule(
500
509
  urlParameters,
501
510
  registeredConstants: options?.registeredConstants,
502
511
  bindingEvidence: options?.bindingEvidence,
512
+ nilRaisingSlots: options?.nilRaisingSlots,
503
513
  typeLeaves: entry.typeLeaves,
504
514
  declaredTypes: routed?.declaredTypes,
505
515
  dropped,
@@ -753,6 +763,7 @@ export function generateModuleDeclaration(
753
763
  urlParameters,
754
764
  registeredConstants,
755
765
  bindingEvidence,
766
+ nilRaisingSlots,
756
767
  typeLeaves,
757
768
  declaredTypes,
758
769
  dropped,
@@ -765,6 +776,7 @@ export function generateModuleDeclaration(
765
776
  withheldFunctions,
766
777
  ...(registeredConstants ? { registeredConstants } : {}),
767
778
  ...(bindingEvidence ? { bindingEvidence } : {}),
779
+ ...(nilRaisingSlots ? { nilRaisingSlots } : {}),
768
780
  ...(typeLeaves ? { typeLeaves } : {}),
769
781
  ...(declaredTypes ? { declaredTypes } : {}),
770
782
  ...(entry.indexBaseSource ? { indexBaseSource: entry.indexBaseSource } : {}),
@@ -790,14 +802,18 @@ export function generateModuleSignatures(
790
802
  urlParameters,
791
803
  registeredConstants,
792
804
  bindingEvidence,
805
+ nilRaisingSlots,
793
806
  typeLeaves,
794
807
  declaredTypes,
808
+ withheldFunctions,
795
809
  } = prepareGeneratedModule(entry, options);
796
810
  return emitSymbolSignatures(module, {
797
811
  knownConstantFqns,
798
812
  urlParameters,
813
+ withheldFunctions,
799
814
  ...(registeredConstants ? { registeredConstants } : {}),
800
815
  ...(bindingEvidence ? { bindingEvidence } : {}),
816
+ ...(nilRaisingSlots ? { nilRaisingSlots } : {}),
801
817
  ...(typeLeaves ? { typeLeaves } : {}),
802
818
  ...(declaredTypes ? { declaredTypes } : {}),
803
819
  });
@@ -864,9 +880,17 @@ export function kindStdlibReferences(entry: KindManifestEntry): string {
864
880
  // `generateKindIndex` stays pure; `srcAugmentationScopingViolations` in
865
881
  // `./augmentation-namespaces` is what catches a future restricted augmentation
866
882
  // added without one, by reading the namespaces each file really re-opens.
883
+ // `since` is the first Defold release, a bare semver, whose engine has what the
884
+ // augmentation declares; a surface generated for an older target omits it.
885
+ // `requiresGoInstance` lists the exact functions an augmentation declares that
886
+ // need a game object, so it rides no index of a kind without one; the same
887
+ // guard checks this list against the functions the file declares, in both
888
+ // directions.
867
889
  interface UniversalExtraImport {
868
890
  readonly specifier: string;
869
891
  readonly restrictedTo?: string;
892
+ readonly since?: string;
893
+ readonly requiresGoInstance?: readonly string[];
870
894
  }
871
895
 
872
896
  const UNIVERSAL_EXTRA_IMPORTS: readonly UniversalExtraImport[] = [
@@ -878,9 +902,17 @@ const UNIVERSAL_EXTRA_IMPORTS: readonly UniversalExtraImport[] = [
878
902
  { specifier: "../../src/window-event-guard" },
879
903
  { specifier: "../../src/physics-event-guard" },
880
904
  { specifier: "../../src/scene-addresses" },
881
- { specifier: "../../src/go-overloads" },
905
+ // `go.property` is listed by hand: `GetScript` finds no `.script` instance in
906
+ // a render script and returns null rather than raising, and `Script_Property`
907
+ // raises on that null itself, a check the bindings manifest does not record.
908
+ {
909
+ specifier: "../../src/go-overloads",
910
+ requiresGoInstance: ["go.get", "go.set", "go.property"],
911
+ },
882
912
  { specifier: "../../src/component-properties" },
883
913
  { specifier: "../../src/render-overloads", restrictedTo: "render" },
914
+ { specifier: "../../src/gui-overloads", restrictedTo: "gui" },
915
+ { specifier: "../../src/gui-texture-removal", restrictedTo: "gui", since: "1.13.1" },
884
916
  { specifier: "../../src/vmath-overloads" },
885
917
  { specifier: "../../src/sys-overloads" },
886
918
  ];
@@ -903,14 +935,57 @@ export const RESTRICTED_SRC_AUGMENTATIONS: Readonly<Record<string, string>> = Ob
903
935
  ).map((entry) => [entry.specifier.slice(SRC_IMPORT_PREFIX.length), entry.restrictedTo as string]),
904
936
  );
905
937
 
906
- // Read those augmentations as surface-root files. Mirrors
907
- // `loadTargetEditorModules`: a missing file throws with its path rather than
908
- // filtering silently, so a renamed augmentation fails loud instead of vanishing
909
- // from every materialized surface.
938
+ // The `src/*` augmentations that declare a function needing a game object, as
939
+ // `<module name> -> <the functions it declares that need one>`. Exported so the
940
+ // scoping guard and the wall probe read the same list.
941
+ export const GO_INSTANCE_SRC_FUNCTIONS: Readonly<Record<string, readonly string[]>> =
942
+ Object.fromEntries(
943
+ UNIVERSAL_EXTRA_IMPORTS.filter(
944
+ (entry) =>
945
+ entry.requiresGoInstance !== undefined && entry.specifier.startsWith(SRC_IMPORT_PREFIX),
946
+ ).map((entry) => [
947
+ entry.specifier.slice(SRC_IMPORT_PREFIX.length),
948
+ entry.requiresGoInstance as readonly string[],
949
+ ]),
950
+ );
951
+
952
+ // The same augmentations as module names. Exported so the materialized kind
953
+ // indexes drop them the same way the in-repo ones do.
954
+ export const GO_INSTANCE_SRC_AUGMENTATIONS: readonly string[] =
955
+ Object.keys(GO_INSTANCE_SRC_FUNCTIONS);
956
+
957
+ // The `src/*` augmentations gated to a release, as `<module name> -> <since>`.
958
+ export const SRC_AUGMENTATION_GATES: Readonly<Record<string, string>> = Object.fromEntries(
959
+ UNIVERSAL_EXTRA_IMPORTS.filter(
960
+ (entry) => entry.since !== undefined && entry.specifier.startsWith(SRC_IMPORT_PREFIX),
961
+ ).map((entry) => [entry.specifier.slice(SRC_IMPORT_PREFIX.length), entry.since as string]),
962
+ );
963
+
964
+ function admitsTarget(entry: UniversalExtraImport, target: ApiTarget): boolean {
965
+ return entry.since === undefined || compareVersions(versionOf(target), entry.since) >= 0;
966
+ }
967
+
968
+ // The `src/*` augmentations a surface generated for `target` carries: those
969
+ // whose gate the target's version meets. Every surface writer reads this one
970
+ // filter, so the committed indexes, the kind indexes and both materializers
971
+ // agree on which arms a target declares.
972
+ export function srcAugmentationModulesFor(target: ApiTarget): readonly string[] {
973
+ return UNIVERSAL_EXTRA_IMPORTS.filter(
974
+ (entry) => entry.specifier.startsWith(SRC_IMPORT_PREFIX) && admitsTarget(entry, target),
975
+ ).map((entry) => entry.specifier.slice(SRC_IMPORT_PREFIX.length));
976
+ }
977
+
978
+ // Read those augmentations as surface-root files, narrowed to `target`'s set
979
+ // when one is given. Mirrors `loadTargetEditorModules`: a missing file throws
980
+ // with its path rather than filtering silently, so a renamed augmentation fails
981
+ // loud instead of vanishing from every materialized surface.
910
982
  export function loadSrcAugmentations(
911
983
  packageRoot: string = PACKAGE_ROOT,
984
+ target?: ApiTarget,
912
985
  ): { path: string; contents: string }[] {
913
- return SRC_AUGMENTATION_MODULES.map((name) => {
986
+ const modules =
987
+ target === undefined ? SRC_AUGMENTATION_MODULES : srcAugmentationModulesFor(target);
988
+ return modules.map((name) => {
914
989
  const from = resolve(packageRoot, "src", `${name}.d.ts`);
915
990
  let contents: string;
916
991
  try {
@@ -922,6 +997,76 @@ export function loadSrcAugmentations(
922
997
  });
923
998
  }
924
999
 
1000
+ export const GO_INSTANCE_FUNCTIONS_FILE = "go-instance-functions.json";
1001
+
1002
+ export type GoInstanceFunctions = Readonly<Record<string, readonly string[]>>;
1003
+
1004
+ // The functions that need a game-object instance on `target`, keyed by fqn,
1005
+ // read from the manifest `go-instance-functions.ts` commits beside the target's
1006
+ // fixtures. `null` for a target with no vendored engine source to derive it
1007
+ // from, whose surfaces keep every function.
1008
+ export function loadGoInstanceFunctions(
1009
+ target: ApiTarget,
1010
+ packageRoot: string = PACKAGE_ROOT,
1011
+ ): GoInstanceFunctions | null {
1012
+ const path = resolve(packageRoot, target.fixturesDir, GO_INSTANCE_FUNCTIONS_FILE);
1013
+ if (!existsSync(path)) return null;
1014
+ return JSON.parse(readFileSync(path, "utf8")) as GoInstanceFunctions;
1015
+ }
1016
+
1017
+ // The functions a kind with no game object omits, by the bare name of the
1018
+ // module declaring them: `<module> -> <local names>`. A module declaring none,
1019
+ // or declaring only names its skip rules already withhold, has no entry.
1020
+ export function goInstanceWalls(
1021
+ modules: readonly ModuleManifestEntry[],
1022
+ needsGoInstance: GoInstanceFunctions | null,
1023
+ ): Map<string, string[]> {
1024
+ const walls = new Map<string, string[]>();
1025
+ if (needsGoInstance === null) return walls;
1026
+ const fqns = Object.keys(needsGoInstance);
1027
+ for (const entry of modules) {
1028
+ const prefix = `${entry.namespace}.`;
1029
+ const localOf = (name: string): string =>
1030
+ name.startsWith(prefix) ? name.slice(prefix.length) : name;
1031
+ const declared = new Set(parseDefoldApiDoc(entry.doc).functions.map((fn) => localOf(fn.name)));
1032
+ const rules = entry.skipFunctions ?? [];
1033
+ const skipped = (local: string): boolean =>
1034
+ rules.some((rule) => (rule.endsWith(".") ? local.startsWith(rule) : local === rule));
1035
+ const walled = fqns
1036
+ .filter((fqn) => fqn.startsWith(prefix))
1037
+ .map(localOf)
1038
+ .filter((local) => !local.includes(".") && declared.has(local) && !skipped(local))
1039
+ .sort();
1040
+ if (walled.length > 0) walls.set(entry.outFile.replace(/\.d\.ts$/, ""), walled);
1041
+ }
1042
+ return walls;
1043
+ }
1044
+
1045
+ // The modules a kind with no game object is emitted from: each walled module is
1046
+ // replaced by a copy that withholds the functions needing one and lands in
1047
+ // `dir`, one level below the surface root. The surface is returned whole
1048
+ // because a copy routes its types across its siblings, never alone.
1049
+ export function goInstanceFreeSurface(
1050
+ modules: readonly ModuleManifestEntry[],
1051
+ walls: ReadonlyMap<string, readonly string[]>,
1052
+ dir: string,
1053
+ ): { surface: ModuleManifestEntry[]; copies: ModuleManifestEntry[] } {
1054
+ const copies: ModuleManifestEntry[] = [];
1055
+ const surface = modules.map((entry) => {
1056
+ const walled = walls.get(entry.outFile.replace(/\.d\.ts$/, ""));
1057
+ if (walled === undefined) return entry;
1058
+ const copy: ModuleManifestEntry = {
1059
+ ...entry,
1060
+ outFile: `${dir}/${entry.outFile}`,
1061
+ importsFrom: oneLevelDeeper(entry.importsFrom ?? "../src/core-types"),
1062
+ skipFunctions: [...(entry.skipFunctions ?? []), ...walled],
1063
+ };
1064
+ copies.push(copy);
1065
+ return copy;
1066
+ });
1067
+ return { surface, copies };
1068
+ }
1069
+
925
1070
  const DEFAULT_FACTORY_MODULE = "../../src/lifecycle";
926
1071
 
927
1072
  export interface KindManifestEntry {
@@ -947,12 +1092,23 @@ export interface KindManifestEntry {
947
1092
  readonly propertyTypes?: boolean;
948
1093
  // Whether the kind's VM is LuaJIT. The editor runs plain Lua 5.1.
949
1094
  readonly jit?: boolean;
1095
+ // Set for a kind whose script has no game object: the directory, beside the
1096
+ // surface root, holding copies of the modules that declare a function needing
1097
+ // one, with those functions withheld. Its index imports the copies instead.
1098
+ readonly goInstanceFreeDir?: string;
950
1099
  }
951
1100
 
952
1101
  export const KIND_MODULE_MANIFEST: readonly KindManifestEntry[] = [
953
1102
  { kind: "script", factory: "defineScript" },
954
1103
  { kind: "gui-script", restricted: "gui", factory: "defineGuiScript" },
955
- { kind: "render-script", restricted: "render", factory: "defineRenderScript" },
1104
+ {
1105
+ kind: "render-script",
1106
+ restricted: "render",
1107
+ factory: "defineRenderScript",
1108
+ // Only the GUI component registers a game-object resolver
1109
+ // (`comp_gui.cpp`), so every `CheckGOInstance` raises in a render script.
1110
+ goInstanceFreeDir: "render-script-modules",
1111
+ },
956
1112
  {
957
1113
  kind: "editor-script",
958
1114
  // Empty on purpose: the emitted namespaces come from the declaring target's
@@ -999,17 +1155,30 @@ export function generateKindIndex(kind: string, target: ApiTarget = DEFAULT_TARG
999
1155
  const entry = KIND_MODULE_MANIFEST.find((e) => e.kind === kind);
1000
1156
  if (!entry) throw new Error(`unknown script kind: ${kind}`);
1001
1157
  const srcPrefix = targetSrcPrefix(target);
1158
+ // A kind with no game object loses what needs one, on a target whose engine
1159
+ // source records what that is; a module declaring such a function is
1160
+ // imported from its filtered copy.
1161
+ const freeDir = entry.goInstanceFreeDir;
1162
+ const needsGoInstance = freeDir === undefined ? null : loadGoInstanceFunctions(target);
1163
+ const walls = goInstanceWalls(MODULE_MANIFEST, needsGoInstance);
1002
1164
  const universalNamespaces = MODULE_MANIFEST.filter(
1003
1165
  (m) => !Object.hasOwn(RESTRICTED_NAMESPACES, m.namespace),
1004
- ).map((m) => `../${m.outFile.replace(/\.d\.ts$/, "")}`);
1166
+ )
1167
+ .map((m) => m.outFile.replace(/\.d\.ts$/, ""))
1168
+ .sort()
1169
+ .map((base) => (walls.has(base) ? `../${freeDir}/${base}` : `../${base}`));
1005
1170
  // An augmentation bound to a restricted namespace rides only that namespace's
1006
- // kind index; every unmarked entry stays universal.
1171
+ // kind index; every unmarked entry stays universal. A gated entry rides only a
1172
+ // target its gate admits, and a marked one only a kind with a game object.
1007
1173
  const extraImports = UNIVERSAL_EXTRA_IMPORTS.filter(
1008
- (extra) => extra.restrictedTo === undefined || extra.restrictedTo === entry.restricted,
1174
+ (extra) =>
1175
+ (extra.restrictedTo === undefined || extra.restrictedTo === entry.restricted) &&
1176
+ (needsGoInstance === null || extra.requiresGoInstance === undefined) &&
1177
+ admitsTarget(extra, target),
1009
1178
  ).map((extra) => extra.specifier);
1010
1179
  const modules = (
1011
1180
  entry.only === undefined
1012
- ? [...new Set([...universalNamespaces.sort(), ...extraImports.sort()])]
1181
+ ? [...new Set([...universalNamespaces, ...extraImports.sort()])]
1013
1182
  : [...editorKindModules(target), ...(entry.extraModules ?? [])]
1014
1183
  ).map((path) => retargetSrcPath(path, srcPrefix));
1015
1184
  const lines = modules.map((path) => `import "${path}";`);
@@ -1054,11 +1223,11 @@ export function generateVersionIndex(
1054
1223
  // The authored augmentations a committed per-version index imports, addressed
1055
1224
  // back into the package's `src/`. The in-repo surface has no copies beside its
1056
1225
  // modules, so a skipped symbol would otherwise be declared on no versioned
1057
- // surface at all. Derived from `SRC_AUGMENTATION_MODULES`, so a new augmentation
1226
+ // surface at all. Derived from `srcAugmentationModulesFor`, so a new augmentation
1058
1227
  // reaches the pinned surfaces on the same edit that reaches the materialized ones.
1059
1228
  export function versionSrcAugmentationImports(target: ApiTarget): string[] {
1060
1229
  const srcPrefix = target.coreTypesImport.slice(0, -"core-types".length);
1061
- return SRC_AUGMENTATION_MODULES.map((name) => `${srcPrefix}${name}`);
1230
+ return srcAugmentationModulesFor(target).map((name) => `${srcPrefix}${name}`);
1062
1231
  }
1063
1232
 
1064
1233
  // The `src/`-relative prefix a kind index living in `<generatedDir>/kinds/` needs
@@ -1089,6 +1258,9 @@ export function targetKindManifest(target: ApiTarget): readonly KindManifestEntr
1089
1258
 
1090
1259
  // Every `src/*` augmentation bound to a kind-restricted namespace carries its
1091
1260
  // `restrictedTo` marker, and every marker names a namespace its file re-opens.
1261
+ // Likewise `requiresGoInstance` sits on exactly the files declaring a function
1262
+ // the default target's manifest lists, read from this package whatever root the
1263
+ // files come from, and lists exactly the functions its file declares.
1092
1264
  // Exported so a test can reach the guard the entry point runs; never called on
1093
1265
  // import, so the dynamic import below stays unreached from an installed package.
1094
1266
  export async function assertSrcAugmentationScoping(
@@ -1096,13 +1268,18 @@ export async function assertSrcAugmentationScoping(
1096
1268
  ): Promise<number> {
1097
1269
  // Imported here rather than at module scope: it imports the devDependency
1098
1270
  // `typescript`, and `resolve` loads this module from an installed package.
1099
- const { srcAugmentationScopingViolations } = await import("./augmentation-namespaces");
1100
- const files = loadSrcAugmentations(packageRoot);
1101
- const violations = srcAugmentationScopingViolations(
1102
- files,
1103
- RESTRICTED_SRC_AUGMENTATIONS,
1104
- RESTRICTED_NAMESPACES,
1271
+ const { goInstanceMarkerViolations, srcAugmentationScopingViolations } = await import(
1272
+ "./augmentation-namespaces"
1105
1273
  );
1274
+ const files = loadSrcAugmentations(packageRoot);
1275
+ const violations = [
1276
+ ...srcAugmentationScopingViolations(files, RESTRICTED_SRC_AUGMENTATIONS, RESTRICTED_NAMESPACES),
1277
+ ...goInstanceMarkerViolations(
1278
+ files,
1279
+ GO_INSTANCE_SRC_FUNCTIONS,
1280
+ new Set(Object.keys(loadGoInstanceFunctions(DEFAULT_TARGET) ?? {})),
1281
+ ),
1282
+ ];
1106
1283
  if (violations.length > 0) {
1107
1284
  throw new Error(`src augmentation scoping violations:\n${violations.join("\n")}`);
1108
1285
  }
@@ -1239,6 +1416,24 @@ export async function regenerate(
1239
1416
  }
1240
1417
  }
1241
1418
 
1419
+ // The copies a kind with no game object imports instead of the modules that
1420
+ // declare a function needing one; `generateKindIndex` routes to this same set.
1421
+ const defaultWalls = goInstanceWalls(MODULE_MANIFEST, loadGoInstanceFunctions(DEFAULT_TARGET));
1422
+ for (const entry of KIND_MODULE_MANIFEST) {
1423
+ if (entry.goInstanceFreeDir === undefined) continue;
1424
+ const { surface, copies } = goInstanceFreeSurface(
1425
+ MODULE_MANIFEST,
1426
+ defaultWalls,
1427
+ entry.goInstanceFreeDir,
1428
+ );
1429
+ io.mkdir(resolve(generated, entry.goInstanceFreeDir));
1430
+ for (const copy of copies) {
1431
+ const out = resolve(generated, copy.outFile);
1432
+ io.write(out, generateModuleDeclaration(copy, { ...defaultBinding, surface }).contents);
1433
+ io.log(`wrote ${out}`);
1434
+ }
1435
+ }
1436
+
1242
1437
  const kindsDir = resolve(generated, "kinds");
1243
1438
  io.mkdir(kindsDir);
1244
1439
  for (const entry of KIND_MODULE_MANIFEST) {
@@ -1,3 +1,4 @@
1
+ import type { SocketHandleReceiver } from "../src/core-types";
1
2
  import type { ModuleManifestEntry } from "./regen";
2
3
 
3
4
  // A method the engine shares across several handle classes where a release's
@@ -20,8 +21,8 @@ export const SHARED_HANDLE_METHODS: readonly SharedHandleMethod[] = (
20
21
  ).map((method) => ({
21
22
  namespace: "socket",
22
23
  method,
23
- source: "client",
24
- handles: ["master", "server"],
24
+ source: "client" satisfies SocketHandleReceiver,
25
+ handles: ["master", "server"] satisfies SocketHandleReceiver[],
25
26
  evidence: TCP_ANY,
26
27
  }));
27
28
 
@@ -23,6 +23,7 @@ export const BASE_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures",
23
23
  export const SOCKET_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "socket.json");
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
+ export const GUI_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "gui.json");
26
27
  export const MSG_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "msg.json");
27
28
  export const RENDER_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "render.json");
28
29
  export const SYS_SIGNATURES_PATH = resolve(import.meta.dir, "..", "signatures", "sys.json");
@@ -0,0 +1,26 @@
1
+ const VERSION_FROM_ID = /^defold-(\d+\.\d+\.\d+)$/;
2
+
3
+ // A ref-doc target names its release outright; a committed one carries it in
4
+ // its id.
5
+ export function versionOf(target: {
6
+ readonly id: string;
7
+ readonly source?: { readonly version: string } | null;
8
+ }): string {
9
+ if (target.source) return target.source.version;
10
+ const match = VERSION_FROM_ID.exec(target.id);
11
+ if (!match?.[1]) throw new Error(`cannot derive a release version from target id "${target.id}"`);
12
+ return match[1];
13
+ }
14
+
15
+ function versionTuple(version: string): number[] {
16
+ return version.split(".").map((part) => Number.parseInt(part, 10));
17
+ }
18
+
19
+ export function compareVersions(a: string, b: string): number {
20
+ const [ta, tb] = [versionTuple(a), versionTuple(b)];
21
+ for (let index = 0; index < Math.max(ta.length, tb.length); index += 1) {
22
+ const diff = (ta[index] ?? 0) - (tb[index] ?? 0);
23
+ if (diff !== 0) return diff;
24
+ }
25
+ return 0;
26
+ }
package/src/api-doc.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { correctedDoc, docCorrectionKey } from "./doc-corrections";
2
+ import { SCRIPT_HOOK_NAMES } from "./lifecycle";
2
3
 
3
4
  export interface ApiModule {
4
5
  namespace: string;
@@ -16,6 +17,12 @@ export interface ApiModule {
16
17
  enums?: ApiEnum[];
17
18
  /** Each ref-doc `STRUCT`. Absent on a hand-built module, read as an empty list. */
18
19
  structs?: ApiStruct[];
20
+ /**
21
+ * Each lifecycle hook the reference documents as a bare-named `FUNCTION` under
22
+ * `go` or `gui`. The engine calls it as a script global and binds nothing under
23
+ * the name. Absent on a hand-built module.
24
+ */
25
+ scriptHooks?: ApiFunction[];
19
26
  }
20
27
 
21
28
  /** A ref-doc `STRUCT`: a named table shape. */
@@ -24,6 +31,8 @@ export interface ApiStruct {
24
31
  brief: string;
25
32
  description: string;
26
33
  members: ApiStructMember[];
34
+ /** See {@link ApiTypedef.declaredIn}. */
35
+ declaredIn?: string;
27
36
  }
28
37
 
29
38
  /** One `STRUCT` member; upstream marks an optional one with a `name?` suffix. */
@@ -66,6 +75,12 @@ export interface ApiTypedef {
66
75
  aliasOf?: string[];
67
76
  /** See {@link ApiFunction.global}. */
68
77
  global?: true;
78
+ /**
79
+ * The namespace of the ref-doc module that declared this type, set when
80
+ * `routeTypeDeclarations` moves it to another module; the reference lists it
81
+ * on the declaring module's page. Absent on a type its own module declares.
82
+ */
83
+ declaredIn?: string;
69
84
  }
70
85
 
71
86
  export interface ApiConstant {
@@ -193,6 +208,17 @@ export const FUNCTION_NAME_CORRECTIONS: ReadonlyMap<string, FunctionNameCorrecti
193
208
  ],
194
209
  ]);
195
210
 
211
+ // The engine reads each hook a script defines with `lua_getglobal` over
212
+ // `SCRIPT_FUNCTION_NAMES` (`gameobject_script.cpp`, and `gui.cpp` for GUI
213
+ // scripts) and registers no module function under the name, yet the reference
214
+ // documents the hooks as bare-named `go` and `gui` functions.
215
+ export const SCRIPT_HOOK_NAMESPACES: ReadonlySet<string> = new Set(["go", "gui"]);
216
+ const SCRIPT_HOOK_NAME_SET: ReadonlySet<string> = new Set(SCRIPT_HOOK_NAMES);
217
+
218
+ function isScriptHook(namespace: string, name: string): boolean {
219
+ return SCRIPT_HOOK_NAMESPACES.has(namespace) && SCRIPT_HOOK_NAME_SET.has(name);
220
+ }
221
+
196
222
  export function parseDefoldApiDoc(input: unknown): ApiModule {
197
223
  if (!isRecord(input)) {
198
224
  throw new Error(`parseDefoldApiDoc: expected object, got ${describeKind(input)}`);
@@ -218,12 +244,17 @@ export function parseDefoldApiDoc(input: unknown): ApiModule {
218
244
  const typedefs: ApiTypedef[] = [];
219
245
  const enums: ApiEnum[] = [];
220
246
  const structs: ApiStruct[] = [];
247
+ const scriptHooks: ApiFunction[] = [];
221
248
 
222
249
  for (const element of elements) {
223
250
  if (!isRecord(element)) continue;
224
251
  const type = element.type;
225
252
  if (type === "FUNCTION") {
226
253
  const fn = withDocCorrections(parseFunction(element));
254
+ if (isScriptHook(namespace, fn.name)) {
255
+ scriptHooks.push(fn);
256
+ continue;
257
+ }
227
258
  const corrected = FUNCTION_NAME_CORRECTIONS.get(fn.name);
228
259
  functions.push(corrected === undefined ? fn : { ...fn, name: corrected.name });
229
260
  } else if (type === "VARIABLE") {
@@ -264,6 +295,7 @@ export function parseDefoldApiDoc(input: unknown): ApiModule {
264
295
  typedefs,
265
296
  enums,
266
297
  structs,
298
+ scriptHooks,
267
299
  };
268
300
  }
269
301
 
@@ -310,6 +342,8 @@ function withDocCorrections(fn: ApiFunction): ApiFunction {
310
342
  };
311
343
  return {
312
344
  ...fn,
345
+ brief: correctedDoc(docCorrectionKey(fn.name, "brief"), fn.brief),
346
+ description: correctedDoc(docCorrectionKey(fn.name, "description"), fn.description),
313
347
  parameters: fn.parameters.map(correct("param")),
314
348
  returnValues: fn.returnValues.map(correct("return")),
315
349
  };
@@ -1,6 +1,7 @@
1
1
  import type { ApiFunction, ApiModule, ApiParameter } from "./api-doc";
2
2
  import { DEFOLD_TYPE_MAP } from "./core-types";
3
3
  import { pinMatches } from "./correction-pins";
4
+ import { engineTypeName } from "./engine-type-name";
4
5
  import { splitTopLevel } from "./luals-type-expr";
5
6
 
6
7
  /**
@@ -32,7 +33,7 @@ export interface IdentityCorrections {
32
33
  readonly parameterCorrections: Readonly<Record<string, IdentityCorrection>>;
33
34
  /** Keyed by element. */
34
35
  readonly returnCorrections: Readonly<Record<string, IdentityCorrection>>;
35
- /** Constant-family aliases a correction may name (`window.DimModeStateSettable`), with members. */
36
+ /** Constant-family aliases a correction may name (`graphics.BLEND_FACTOR`), with members. */
36
37
  readonly constantFamilies: Readonly<Record<string, readonly string[]>>;
37
38
  }
38
39
 
@@ -117,6 +118,32 @@ const NUMERIC_LITERAL = /^-?\d+(\.\d+)?$/;
117
118
  const STRING_LITERAL = /^(".*"|'.*')$/;
118
119
  // The TypeScript table types a correction writes.
119
120
  const TS_TABLE = /^(Record|LuaMap|ReadonlyLuaMap|LuaTable)\b/;
121
+ // A subset of a constant union a correction writes, which is still that union's value.
122
+ const EXCLUDE = /^Exclude<([\w.]+),.*>$/;
123
+
124
+ const REFERENCE_TYPE_PATHS = new WeakMap<IdentityVocabulary, ReadonlyMap<string, string>>();
125
+
126
+ // The reference name a correction's TypeScript type path was derived from
127
+ // (`gui.Anchor` -> `gui.ANCHOR`), so renaming a type re-keys no identity.
128
+ function referenceTypePath(path: string, vocabulary: IdentityVocabulary): string {
129
+ let paths = REFERENCE_TYPE_PATHS.get(vocabulary);
130
+ if (paths === undefined) {
131
+ const built = new Map<string, string>();
132
+ for (const name of [
133
+ ...Object.keys(vocabulary.enums),
134
+ ...vocabulary.tables,
135
+ ...Object.keys(vocabulary.aliases),
136
+ ]) {
137
+ const dot = name.lastIndexOf(".");
138
+ if (dot < 0) continue;
139
+ const renamed = `${name.slice(0, dot + 1)}${engineTypeName(name.slice(dot + 1))}`;
140
+ if (renamed !== name) built.set(renamed, name);
141
+ }
142
+ paths = built;
143
+ REFERENCE_TYPE_PATHS.set(vocabulary, paths);
144
+ }
145
+ return paths.get(path) ?? path;
146
+ }
120
147
 
121
148
  function canonicalLeaves(
122
149
  token: string,
@@ -136,6 +163,10 @@ function canonicalLeaves(
136
163
  if (trimmed.startsWith("typeof ")) {
137
164
  return canonicalLeaves(trimmed.slice("typeof ".length), vocabulary, expanding);
138
165
  }
166
+ const excluded = EXCLUDE.exec(trimmed);
167
+ if (excluded !== null) return canonicalLeaves(excluded[1] as string, vocabulary, expanding);
168
+ const reference = referenceTypePath(trimmed, vocabulary);
169
+ if (reference !== trimmed) return canonicalLeaves(reference, vocabulary, expanding);
139
170
  if (trimmed === "nil" || trimmed === "undefined") return ["nil"];
140
171
  // Every table shape — a bare or typed `table`, a list, an inline record, a
141
172
  // struct, a built-in message payload — is one Lua table at runtime; its