@defold-typescript/types 0.51.0 → 0.52.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 (130) hide show
  1. package/api-availability.json +4 -58
  2. package/api-signatures.json +878 -1356
  3. package/api-targets.json +15 -5
  4. package/examples/translations.json +4 -56
  5. package/generated/b2d_world.d.ts +10 -10
  6. package/generated/buffer.d.ts +9 -9
  7. package/generated/bullet3d_collision_object.d.ts +1 -1
  8. package/generated/bullet3d_constraint.d.ts +109 -7
  9. package/generated/bullet3d_shape.d.ts +2 -2
  10. package/generated/go.d.ts +114 -220
  11. package/generated/graphics.d.ts +1 -0
  12. package/generated/gui.d.ts +148 -371
  13. package/generated/http.d.ts +2 -2
  14. package/generated/image.d.ts +55 -3
  15. package/generated/kinds/gui-script.d.ts +2 -0
  16. package/generated/kinds/render-script.d.ts +14 -15
  17. package/generated/liveupdate.d.ts +5 -1
  18. package/generated/material.d.ts +3 -3
  19. package/generated/particlefx.d.ts +20 -1
  20. package/generated/physics.d.ts +45 -1
  21. package/generated/render-script-modules/b2d.d.ts +711 -0
  22. package/generated/render-script-modules/bullet3d.d.ts +73 -0
  23. package/generated/render-script-modules/collectionfactory.d.ts +25 -0
  24. package/generated/render-script-modules/collectionproxy.d.ts +39 -0
  25. package/generated/render-script-modules/factory.d.ts +25 -0
  26. package/generated/render-script-modules/go.d.ts +436 -0
  27. package/generated/render-script-modules/label.d.ts +105 -0
  28. package/generated/render-script-modules/model.d.ts +89 -0
  29. package/generated/render-script-modules/particlefx.d.ts +59 -0
  30. package/generated/render-script-modules/physics.d.ts +333 -0
  31. package/generated/render-script-modules/resource.d.ts +1233 -0
  32. package/generated/render-script-modules/sound.d.ts +227 -0
  33. package/generated/render-script-modules/sprite.d.ts +68 -0
  34. package/generated/render-script-modules/tilemap.d.ts +43 -0
  35. package/generated/render.d.ts +134 -8
  36. package/generated/resource.d.ts +31 -10
  37. package/generated/sprite.d.ts +49 -1
  38. package/generated/sys.d.ts +70 -6
  39. package/generated/versions/defold-1.12.4/buffer.d.ts +8 -8
  40. package/generated/versions/defold-1.12.4/go.d.ts +115 -343
  41. package/generated/versions/defold-1.12.4/graphics.d.ts +1 -0
  42. package/generated/versions/defold-1.12.4/gui.d.ts +151 -513
  43. package/generated/versions/defold-1.12.4/http.d.ts +2 -2
  44. package/generated/versions/defold-1.12.4/image.d.ts +82 -2
  45. package/generated/versions/defold-1.12.4/index.d.ts +1 -0
  46. package/generated/versions/defold-1.12.4/liveupdate.d.ts +4 -0
  47. package/generated/versions/defold-1.12.4/particlefx.d.ts +22 -1
  48. package/generated/versions/defold-1.12.4/physics.d.ts +45 -1
  49. package/generated/versions/defold-1.12.4/render.d.ts +78 -2
  50. package/generated/versions/defold-1.12.4/resource.d.ts +43 -10
  51. package/generated/versions/defold-1.12.4/sprite.d.ts +58 -1
  52. package/generated/versions/defold-1.12.4/sys.d.ts +101 -6
  53. package/generated/versions/defold-1.12.4/vmath.d.ts +0 -24
  54. package/generated/versions/defold-1.13.0/buffer.d.ts +8 -8
  55. package/generated/versions/defold-1.13.0/go.d.ts +115 -370
  56. package/generated/versions/defold-1.13.0/graphics.d.ts +1 -0
  57. package/generated/versions/defold-1.13.0/gui.d.ts +151 -513
  58. package/generated/versions/defold-1.13.0/http.d.ts +2 -2
  59. package/generated/versions/defold-1.13.0/image.d.ts +82 -2
  60. package/generated/versions/defold-1.13.0/index.d.ts +1 -0
  61. package/generated/versions/defold-1.13.0/liveupdate.d.ts +4 -0
  62. package/generated/versions/defold-1.13.0/material.d.ts +3 -1
  63. package/generated/versions/defold-1.13.0/particlefx.d.ts +22 -1
  64. package/generated/versions/defold-1.13.0/physics.d.ts +45 -1
  65. package/generated/versions/defold-1.13.0/render.d.ts +142 -4
  66. package/generated/versions/defold-1.13.0/resource.d.ts +43 -10
  67. package/generated/versions/defold-1.13.0/sprite.d.ts +58 -1
  68. package/generated/versions/defold-1.13.0/sys.d.ts +101 -6
  69. package/generated/versions/defold-1.13.0/vmath.d.ts +0 -24
  70. package/generated/versions/defold-1.13.1/buffer.d.ts +8 -8
  71. package/generated/versions/defold-1.13.1/go.d.ts +115 -370
  72. package/generated/versions/defold-1.13.1/graphics.d.ts +1 -0
  73. package/generated/versions/defold-1.13.1/gui.d.ts +151 -529
  74. package/generated/versions/defold-1.13.1/http.d.ts +2 -2
  75. package/generated/versions/defold-1.13.1/image.d.ts +82 -2
  76. package/generated/versions/defold-1.13.1/index.d.ts +2 -0
  77. package/generated/versions/defold-1.13.1/liveupdate.d.ts +4 -0
  78. package/generated/versions/defold-1.13.1/material.d.ts +3 -1
  79. package/generated/versions/defold-1.13.1/particlefx.d.ts +22 -1
  80. package/generated/versions/defold-1.13.1/physics.d.ts +45 -1
  81. package/generated/versions/defold-1.13.1/render.d.ts +142 -4
  82. package/generated/versions/defold-1.13.1/resource.d.ts +43 -10
  83. package/generated/versions/defold-1.13.1/sprite.d.ts +58 -1
  84. package/generated/versions/defold-1.13.1/sys.d.ts +101 -6
  85. package/generated/versions/defold-1.13.1/vmath.d.ts +0 -24
  86. package/generated/versions/defold-1.13.2/b2d_world.d.ts +10 -10
  87. package/generated/versions/defold-1.13.2/buffer.d.ts +9 -9
  88. package/generated/versions/defold-1.13.2/bullet3d_collision_object.d.ts +1 -1
  89. package/generated/versions/defold-1.13.2/bullet3d_constraint.d.ts +109 -7
  90. package/generated/versions/defold-1.13.2/bullet3d_shape.d.ts +2 -2
  91. package/generated/versions/defold-1.13.2/go.d.ts +114 -220
  92. package/generated/versions/defold-1.13.2/graphics.d.ts +1 -0
  93. package/generated/versions/defold-1.13.2/gui.d.ts +148 -371
  94. package/generated/versions/defold-1.13.2/http.d.ts +2 -2
  95. package/generated/versions/defold-1.13.2/image.d.ts +55 -3
  96. package/generated/versions/defold-1.13.2/index.d.ts +2 -0
  97. package/generated/versions/defold-1.13.2/liveupdate.d.ts +5 -1
  98. package/generated/versions/defold-1.13.2/material.d.ts +3 -3
  99. package/generated/versions/defold-1.13.2/particlefx.d.ts +20 -1
  100. package/generated/versions/defold-1.13.2/physics.d.ts +45 -1
  101. package/generated/versions/defold-1.13.2/render.d.ts +123 -7
  102. package/generated/versions/defold-1.13.2/resource.d.ts +31 -10
  103. package/generated/versions/defold-1.13.2/sprite.d.ts +49 -1
  104. package/generated/versions/defold-1.13.2/sys.d.ts +70 -6
  105. package/generated/versions/defold-1.13.2/vmath.d.ts +0 -24
  106. package/generated/vmath.d.ts +0 -24
  107. package/identity-vocabulary.json +52 -7
  108. package/index.d.ts +2 -0
  109. package/package.json +2 -1
  110. package/scripts/generate-api-availability.ts +1 -21
  111. package/scripts/generate-api-signatures.ts +75 -14
  112. package/scripts/materialize-version.ts +48 -7
  113. package/scripts/regen.ts +214 -19
  114. package/scripts/signature-store-fs.ts +1 -0
  115. package/scripts/target-version.ts +26 -0
  116. package/src/api-doc.ts +26 -0
  117. package/src/component-properties.d.ts +89 -0
  118. package/src/core-types.ts +42 -15
  119. package/src/doc-corrections.ts +53 -5
  120. package/src/emit-dts.ts +758 -198
  121. package/src/engine-globals.d.ts +5 -1
  122. package/src/go-overloads.d.ts +68 -13
  123. package/src/gui-overloads.d.ts +489 -0
  124. package/src/gui-texture-removal.d.ts +41 -0
  125. package/src/index.ts +2 -0
  126. package/src/lifecycle.ts +30 -21
  127. package/src/msg-overloads.d.ts +25 -13
  128. package/src/signature-store.ts +50 -0
  129. package/src/timers.d.ts +2 -1
  130. 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) {
@@ -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. */
@@ -193,6 +200,17 @@ export const FUNCTION_NAME_CORRECTIONS: ReadonlyMap<string, FunctionNameCorrecti
193
200
  ],
194
201
  ]);
195
202
 
203
+ // The engine reads each hook a script defines with `lua_getglobal` over
204
+ // `SCRIPT_FUNCTION_NAMES` (`gameobject_script.cpp`, and `gui.cpp` for GUI
205
+ // scripts) and registers no module function under the name, yet the reference
206
+ // documents the hooks as bare-named `go` and `gui` functions.
207
+ export const SCRIPT_HOOK_NAMESPACES: ReadonlySet<string> = new Set(["go", "gui"]);
208
+ const SCRIPT_HOOK_NAME_SET: ReadonlySet<string> = new Set(SCRIPT_HOOK_NAMES);
209
+
210
+ function isScriptHook(namespace: string, name: string): boolean {
211
+ return SCRIPT_HOOK_NAMESPACES.has(namespace) && SCRIPT_HOOK_NAME_SET.has(name);
212
+ }
213
+
196
214
  export function parseDefoldApiDoc(input: unknown): ApiModule {
197
215
  if (!isRecord(input)) {
198
216
  throw new Error(`parseDefoldApiDoc: expected object, got ${describeKind(input)}`);
@@ -218,12 +236,17 @@ export function parseDefoldApiDoc(input: unknown): ApiModule {
218
236
  const typedefs: ApiTypedef[] = [];
219
237
  const enums: ApiEnum[] = [];
220
238
  const structs: ApiStruct[] = [];
239
+ const scriptHooks: ApiFunction[] = [];
221
240
 
222
241
  for (const element of elements) {
223
242
  if (!isRecord(element)) continue;
224
243
  const type = element.type;
225
244
  if (type === "FUNCTION") {
226
245
  const fn = withDocCorrections(parseFunction(element));
246
+ if (isScriptHook(namespace, fn.name)) {
247
+ scriptHooks.push(fn);
248
+ continue;
249
+ }
227
250
  const corrected = FUNCTION_NAME_CORRECTIONS.get(fn.name);
228
251
  functions.push(corrected === undefined ? fn : { ...fn, name: corrected.name });
229
252
  } else if (type === "VARIABLE") {
@@ -264,6 +287,7 @@ export function parseDefoldApiDoc(input: unknown): ApiModule {
264
287
  typedefs,
265
288
  enums,
266
289
  structs,
290
+ scriptHooks,
267
291
  };
268
292
  }
269
293
 
@@ -310,6 +334,8 @@ function withDocCorrections(fn: ApiFunction): ApiFunction {
310
334
  };
311
335
  return {
312
336
  ...fn,
337
+ brief: correctedDoc(docCorrectionKey(fn.name, "brief"), fn.brief),
338
+ description: correctedDoc(docCorrectionKey(fn.name, "description"), fn.description),
313
339
  parameters: fn.parameters.map(correct("param")),
314
340
  returnValues: fn.returnValues.map(correct("return")),
315
341
  };
@@ -44,8 +44,97 @@ declare global {
44
44
  }
45
45
  }
46
46
 
47
+ namespace label {
48
+ interface properties {
49
+ /** The scale's x component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
50
+ "scale.x": number;
51
+ /** The scale's y component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
52
+ "scale.y": number;
53
+ /** The scale's z component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
54
+ "scale.z": number;
55
+ /**
56
+ * The scale's x and y components. `comp_label.cpp` reads it through
57
+ * `comp_private.cpp:GetProperty`, which returns the whole vector3. `go.set`
58
+ * also takes a number, which it applies to both x and y, as `go`'s
59
+ * `"scale.xy"` does.
60
+ */
61
+ "scale.xy": Vector3;
62
+ /** The size's x component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
63
+ "size.x": number;
64
+ /** The size's y component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
65
+ "size.y": number;
66
+ /** The size's z component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
67
+ "size.z": number;
68
+ /**
69
+ * The size's x and y components. `comp_label.cpp` reads it through
70
+ * `comp_private.cpp:GetProperty`, which returns the whole vector3. `go.set`
71
+ * also takes a number, which it applies to both x and y, as `go`'s
72
+ * `"scale.xy"` does.
73
+ */
74
+ "size.xy": Vector3;
75
+ /** The color's x component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
76
+ "color.x": number;
77
+ /** The color's y component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
78
+ "color.y": number;
79
+ /** The color's z component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
80
+ "color.z": number;
81
+ /** The color's w component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
82
+ "color.w": number;
83
+ /** The outline color's x component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
84
+ "outline.x": number;
85
+ /** The outline color's y component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
86
+ "outline.y": number;
87
+ /** The outline color's z component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
88
+ "outline.z": number;
89
+ /** The outline color's w component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
90
+ "outline.w": number;
91
+ /** The shadow color's x component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
92
+ "shadow.x": number;
93
+ /** The shadow color's y component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
94
+ "shadow.y": number;
95
+ /** The shadow color's z component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
96
+ "shadow.z": number;
97
+ /** The shadow color's w component. `comp_label.cpp` and `comp_private.cpp` read and write one float. */
98
+ "shadow.w": number;
99
+ }
100
+ }
101
+
47
102
  namespace sprite {
48
103
  interface properties {
104
+ /** The scale's x component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
105
+ "scale.x": number;
106
+ /** The scale's y component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
107
+ "scale.y": number;
108
+ /** The scale's z component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
109
+ "scale.z": number;
110
+ /**
111
+ * The scale's x and y components. `comp_sprite.cpp` reads it through
112
+ * `comp_private.cpp:GetProperty`, which returns the whole vector3. `go.set`
113
+ * also takes a number, which it applies to both x and y, as `go`'s
114
+ * `"scale.xy"` does.
115
+ */
116
+ "scale.xy": Vector3;
117
+ /** The size's x component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
118
+ "size.x": number;
119
+ /** The size's y component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
120
+ "size.y": number;
121
+ /** The size's z component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
122
+ "size.z": number;
123
+ /**
124
+ * The size's x and y components. `comp_sprite.cpp` reads it through
125
+ * `comp_private.cpp:GetProperty`, which returns the whole vector3. `go.set`
126
+ * also takes a number, which it applies to both x and y, as `go`'s
127
+ * `"scale.xy"` does.
128
+ */
129
+ "size.xy": Vector3;
130
+ /** The slice-9 border's x component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
131
+ "slice.x": number;
132
+ /** The slice-9 border's y component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
133
+ "slice.y": number;
134
+ /** The slice-9 border's z component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
135
+ "slice.z": number;
136
+ /** The slice-9 border's w component. `comp_sprite.cpp` and `comp_private.cpp` read and write one float. */
137
+ "slice.w": number;
49
138
  /**
50
139
  * The texture bound to the sprite's first sampler. Not in the sprite
51
140
  * ref-doc; `resource.set`'s example reads it with