@defold-typescript/transpiler 0.40.0 → 0.42.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/dist/index.js CHANGED
@@ -270,11 +270,11 @@ function emitInitMerge(fn, context, property) {
270
270
  const initFn = createFunctionExpression2(createBlock2([stateDecl, guard]), [createIdentifier2("self")], undefined, NodeFlags2.Declaration, fn);
271
271
  return [builderDecl, createAssignmentStatement(createIdentifier2("init"), initFn, property)];
272
272
  }
273
- function emitPropertyRegistrations(property, context) {
273
+ function propertyMembers(property) {
274
274
  if (!ts2.isPropertyAssignment(property) || !ts2.isObjectLiteralExpression(property.initializer)) {
275
275
  return [];
276
276
  }
277
- const registrations = [];
277
+ const members = [];
278
278
  for (const member of property.initializer.properties) {
279
279
  if (!ts2.isPropertyAssignment(member)) {
280
280
  continue;
@@ -283,21 +283,34 @@ function emitPropertyRegistrations(property, context) {
283
283
  if (!ts2.isIdentifier(key) && !ts2.isStringLiteral(key)) {
284
284
  continue;
285
285
  }
286
- registrations.push(createExpressionStatement(createCallExpression2(createTableIndexExpression(createIdentifier2("go"), createStringLiteral2("property")), [createStringLiteral2(key.text), context.transformExpression(member.initializer)])));
286
+ members.push({ name: key.text, initializer: member.initializer });
287
287
  }
288
- return registrations;
288
+ return members;
289
289
  }
290
- function eraseFactoryCall(expression, context) {
290
+ function factoryHooks(expression, checker) {
291
291
  if (!ts2.isCallExpression(expression)) {
292
292
  return;
293
293
  }
294
- if (!resolvesToFactoryExport(expression.expression, context.checker)) {
294
+ if (!resolvesToFactoryExport(expression.expression, checker)) {
295
295
  return;
296
296
  }
297
297
  const hooks = expression.arguments[0];
298
298
  if (hooks === undefined || !ts2.isObjectLiteralExpression(hooks)) {
299
299
  return;
300
300
  }
301
+ return hooks;
302
+ }
303
+ function isPropertiesHook(property) {
304
+ return hookName(property) === "properties";
305
+ }
306
+ function emitPropertyRegistrations(property, context) {
307
+ return propertyMembers(property).map(({ name, initializer }) => createExpressionStatement(createCallExpression2(createTableIndexExpression(createIdentifier2("go"), createStringLiteral2("property")), [createStringLiteral2(name), context.transformExpression(initializer)])));
308
+ }
309
+ function eraseFactoryCall(expression, context) {
310
+ const hooks = factoryHooks(expression, context.checker);
311
+ if (hooks === undefined) {
312
+ return;
313
+ }
301
314
  const registrations = [];
302
315
  const statements = [];
303
316
  for (const property of hooks.properties) {
@@ -1675,9 +1688,13 @@ function buildInputActionIndex(documents) {
1675
1688
  }
1676
1689
  // src/project-resources.ts
1677
1690
  var SCAFFOLDED_DEFIGNORE_LINES = ["/node_modules", "/.defold-types", "/.vscode"];
1678
- function isDefignoredPath(displayPath) {
1691
+ function parseDefignore(text) {
1692
+ return text.split(`
1693
+ `).map((line) => line.trim()).filter((line) => line !== "").map((line) => line.startsWith("/") ? line : `/${line}`);
1694
+ }
1695
+ function isDefignoredPath(displayPath, lines = SCAFFOLDED_DEFIGNORE_LINES) {
1679
1696
  const rooted = `/${displayPath.replace(/^\/+/, "")}`;
1680
- return SCAFFOLDED_DEFIGNORE_LINES.some((line) => rooted === line || rooted.startsWith(`${line}/`));
1697
+ return lines.some((line) => rooted === line || rooted.startsWith(`${line}/`));
1681
1698
  }
1682
1699
 
1683
1700
  // src/scene-documents.ts
@@ -2061,176 +2078,13 @@ function computeOutputRel(rel, config, kind) {
2061
2078
  import * as ts9 from "typescript";
2062
2079
  import * as tstl from "typescript-to-lua";
2063
2080
 
2064
- // src/array-index-option-lowering.ts
2081
+ // src/message-guard-lowering.ts
2065
2082
  import * as ts5 from "typescript";
2066
2083
  import {
2067
2084
  createBinaryExpression as createBinaryExpression3,
2068
- createNumericLiteral,
2069
- getOriginalPos,
2070
- isCallExpression as isCallExpression3,
2071
- isNumericLiteral as isNumericLiteral3,
2072
- isStringLiteral as isStringLiteral5,
2073
- isTableExpression,
2074
- SyntaxKind as SyntaxKind7,
2075
- setNodePosition
2076
- } from "typescript-to-lua";
2077
- var ONE_BASED_INDEX_OPTION_APIS = new Set([
2078
- "go.get",
2079
- "go.set",
2080
- "gui.get",
2081
- "gui.set"
2082
- ]);
2083
- var INDEX_OPTION_VARIABLE_MESSAGE = "`options.index` is zero-based and is converted to Defold's 1-based index only in an object literal written at the call; pass the options inline.";
2084
- var INDEX_OPTION_SPREAD_MESSAGE = "A spread carrying `index` cannot be converted to Defold's 1-based index; write `index` explicitly after the spread.";
2085
- var INDEX_OPTION_UNDEFINED_MESSAGE = "`options.index` may be undefined here, so it cannot be converted to Defold's 1-based index; pass a number, or leave `index` out.";
2086
- var OPTIONS_PARAMETER = "options";
2087
- var INDEX_KEY = "index";
2088
- var loweredLiterals = new WeakSet;
2089
- function oneBasedApi(declaration, checker) {
2090
- let node = declaration;
2091
- while (node !== undefined && !ts5.isFunctionDeclaration(node))
2092
- node = node.parent;
2093
- if (node?.name === undefined)
2094
- return false;
2095
- const symbol = checker.getSymbolAtLocation(node.name);
2096
- if (symbol === undefined)
2097
- return false;
2098
- const fqn = checker.getFullyQualifiedName(symbol);
2099
- return fqn.startsWith("global.") && ONE_BASED_INDEX_OPTION_APIS.has(fqn.slice("global.".length));
2100
- }
2101
- function optionsArgument(call, checker) {
2102
- const declaration = checker.getResolvedSignature(call)?.declaration;
2103
- if (declaration === undefined || !ts5.isFunctionLike(declaration))
2104
- return;
2105
- if (!oneBasedApi(declaration, checker))
2106
- return;
2107
- const index = declaration.parameters.findIndex((parameter) => parameter.dotDotDotToken === undefined && ts5.isIdentifier(parameter.name) && parameter.name.text === OPTIONS_PARAMETER);
2108
- return index === -1 ? undefined : call.arguments[index];
2109
- }
2110
- function unwrap(expression) {
2111
- let current = expression;
2112
- while (ts5.isParenthesizedExpression(current) || ts5.isAsExpression(current) || ts5.isSatisfiesExpression(current) || ts5.isNonNullExpression(current) || ts5.isTypeAssertionExpression(current)) {
2113
- current = current.expression;
2114
- }
2115
- return current;
2116
- }
2117
- function someConstituent(type, predicate) {
2118
- return type.isUnion() ? type.types.some(predicate) : predicate(type);
2119
- }
2120
- function carriesIndex(type) {
2121
- return someConstituent(type, (t) => t.getProperty(INDEX_KEY) !== undefined);
2122
- }
2123
- function admitsUndefined(type) {
2124
- return someConstituent(type, (t) => (t.flags & (ts5.TypeFlags.Undefined | ts5.TypeFlags.Void)) !== 0);
2125
- }
2126
- function propertyName(property, checker) {
2127
- const name = property.name;
2128
- if (name === undefined)
2129
- return;
2130
- if (ts5.isIdentifier(name) || ts5.isStringLiteral(name) || ts5.isNumericLiteral(name)) {
2131
- return name.text;
2132
- }
2133
- if (ts5.isComputedPropertyName(name)) {
2134
- const type = checker.getTypeAtLocation(name.expression);
2135
- if (type.isStringLiteral())
2136
- return type.value;
2137
- }
2138
- return;
2139
- }
2140
- function indexValueType(property, checker) {
2141
- if (ts5.isPropertyAssignment(property))
2142
- return checker.getTypeAtLocation(property.initializer);
2143
- if (ts5.isShorthandPropertyAssignment(property))
2144
- return checker.getTypeAtLocation(property.name);
2145
- return;
2146
- }
2147
- function rejection(node, messageText) {
2148
- const file = node.getSourceFile();
2149
- const start = node.getStart(file);
2150
- return {
2151
- file,
2152
- start,
2153
- length: node.getEnd() - start,
2154
- category: ts5.DiagnosticCategory.Error,
2155
- code: 0,
2156
- messageText
2157
- };
2158
- }
2159
- function rejectOptions(options, checker) {
2160
- const literal = unwrap(options);
2161
- if (!ts5.isObjectLiteralExpression(literal)) {
2162
- return carriesIndex(checker.getTypeAtLocation(literal)) ? rejection(options, INDEX_OPTION_VARIABLE_MESSAGE) : undefined;
2163
- }
2164
- let uncoveredSpread;
2165
- let explicitIndex;
2166
- for (const property of literal.properties) {
2167
- if (ts5.isSpreadAssignment(property)) {
2168
- if (carriesIndex(checker.getTypeAtLocation(property.expression)))
2169
- uncoveredSpread = property;
2170
- } else if (propertyName(property, checker) === INDEX_KEY) {
2171
- uncoveredSpread = undefined;
2172
- explicitIndex = property;
2173
- }
2174
- }
2175
- if (uncoveredSpread !== undefined)
2176
- return rejection(uncoveredSpread, INDEX_OPTION_SPREAD_MESSAGE);
2177
- const valueType = explicitIndex && indexValueType(explicitIndex, checker);
2178
- if (explicitIndex !== undefined && valueType !== undefined && admitsUndefined(valueType)) {
2179
- return rejection(explicitIndex, INDEX_OPTION_UNDEFINED_MESSAGE);
2180
- }
2181
- return;
2182
- }
2183
- function plusOne(value) {
2184
- if (isNumericLiteral3(value)) {
2185
- return setNodePosition(createNumericLiteral(value.value + 1), getOriginalPos(value));
2186
- }
2187
- return setNodePosition(createBinaryExpression3(value, createNumericLiteral(1), SyntaxKind7.AdditionOperator), getOriginalPos(value));
2188
- }
2189
- function offsetEffectiveIndexField(tables) {
2190
- for (const field of tables.flatMap((table) => table.fields).reverse()) {
2191
- if (field.key !== undefined && isStringLiteral5(field.key) && field.key.value === INDEX_KEY) {
2192
- field.value = plusOne(field.value);
2193
- return;
2194
- }
2195
- }
2196
- }
2197
- var arrayIndexOptionLoweringPlugin = {
2198
- visitors: {
2199
- [ts5.SyntaxKind.CallExpression]: (node, context) => {
2200
- const options = optionsArgument(node, context.checker);
2201
- if (options !== undefined) {
2202
- const diagnostic = rejectOptions(options, context.checker);
2203
- if (diagnostic !== undefined) {
2204
- context.diagnostics.push(diagnostic);
2205
- } else {
2206
- const literal = unwrap(options);
2207
- if (ts5.isObjectLiteralExpression(literal))
2208
- loweredLiterals.add(literal);
2209
- }
2210
- }
2211
- return context.superTransformExpression(node);
2212
- },
2213
- [ts5.SyntaxKind.ObjectLiteralExpression]: (node, context) => {
2214
- const result = context.superTransformExpression(node);
2215
- if (!loweredLiterals.has(node))
2216
- return result;
2217
- if (isTableExpression(result)) {
2218
- offsetEffectiveIndexField([result]);
2219
- } else if (isCallExpression3(result)) {
2220
- offsetEffectiveIndexField(result.params.filter(isTableExpression));
2221
- }
2222
- return result;
2223
- }
2224
- }
2225
- };
2226
-
2227
- // src/message-guard-lowering.ts
2228
- import * as ts6 from "typescript";
2229
- import {
2230
- createBinaryExpression as createBinaryExpression4,
2231
2085
  createCallExpression as createCallExpression3,
2232
2086
  createIdentifier as createIdentifier3,
2233
- SyntaxKind as SyntaxKind9
2087
+ SyntaxKind as SyntaxKind7
2234
2088
  } from "typescript-to-lua";
2235
2089
  var GUARD_MODULE = "@defold-typescript/types";
2236
2090
  var GUARD_NAME = "isMessage";
@@ -2239,7 +2093,7 @@ function resolvesToGuardExport(callee, checker) {
2239
2093
  if (symbol === undefined) {
2240
2094
  return false;
2241
2095
  }
2242
- if (symbol.flags & ts6.SymbolFlags.Alias) {
2096
+ if (symbol.flags & ts5.SymbolFlags.Alias) {
2243
2097
  symbol = checker.getAliasedSymbol(symbol);
2244
2098
  }
2245
2099
  if (symbol.getName() !== GUARD_NAME) {
@@ -2253,12 +2107,12 @@ function resolvesToGuardExport(callee, checker) {
2253
2107
  }
2254
2108
  var messageGuardLoweringPlugin = {
2255
2109
  visitors: {
2256
- [ts6.SyntaxKind.CallExpression]: (node, context) => {
2110
+ [ts5.SyntaxKind.CallExpression]: (node, context) => {
2257
2111
  const [messageIdArg, , expectedArg] = node.arguments;
2258
2112
  if (node.arguments.length === 3 && messageIdArg !== undefined && expectedArg !== undefined && resolvesToGuardExport(node.expression, context.checker)) {
2259
2113
  const messageId = context.transformExpression(messageIdArg);
2260
2114
  const expected = context.transformExpression(expectedArg);
2261
- return createBinaryExpression4(messageId, createCallExpression3(createIdentifier3("hash"), [expected]), SyntaxKind9.EqualityOperator, node);
2115
+ return createBinaryExpression3(messageId, createCallExpression3(createIdentifier3("hash"), [expected]), SyntaxKind7.EqualityOperator, node);
2262
2116
  }
2263
2117
  return context.superTransformExpression(node);
2264
2118
  }
@@ -2266,34 +2120,64 @@ var messageGuardLoweringPlugin = {
2266
2120
  };
2267
2121
 
2268
2122
  // src/timers-lowering.ts
2269
- import * as ts7 from "typescript";
2123
+ import * as ts6 from "typescript";
2270
2124
  import { LuaLibFeature } from "typescript-to-lua";
2271
2125
  function isTimersSpecifier(node) {
2272
- return ts7.isStringLiteral(node) && node.text === TIMERS_MODULE_SPECIFIER;
2126
+ return ts6.isStringLiteral(node) && node.text === TIMERS_MODULE_SPECIFIER;
2273
2127
  }
2274
2128
  function importsTimersModule(sourceFile) {
2275
- return sourceFile.statements.some((statement) => ts7.isImportDeclaration(statement) && isTimersSpecifier(statement.moduleSpecifier));
2129
+ return sourceFile.statements.some((statement) => ts6.isImportDeclaration(statement) && isTimersSpecifier(statement.moduleSpecifier));
2276
2130
  }
2277
2131
  var TIMERS_REQUIRE_PATH = `@NoResolution:${TIMERS_REQUIRE_NAME}`;
2278
2132
  var timersLoweringPlugin = {
2279
2133
  visitors: {
2280
- [ts7.SyntaxKind.ImportDeclaration]: (node, context) => {
2134
+ [ts6.SyntaxKind.ImportDeclaration]: (node, context) => {
2281
2135
  if (!isTimersSpecifier(node.moduleSpecifier)) {
2282
2136
  return context.superTransformStatements(node);
2283
2137
  }
2284
2138
  context.usedLuaLibFeatures.add(LuaLibFeature.Promise);
2285
2139
  context.usedLuaLibFeatures.add(LuaLibFeature.New);
2286
- const rewritten = ts7.factory.updateImportDeclaration(node, node.modifiers, node.importClause, ts7.factory.createStringLiteral(TIMERS_REQUIRE_PATH), node.attributes);
2140
+ const rewritten = ts6.factory.updateImportDeclaration(node, node.modifiers, node.importClause, ts6.factory.createStringLiteral(TIMERS_REQUIRE_PATH), node.attributes);
2287
2141
  return context.superTransformStatements(rewritten);
2288
2142
  }
2289
2143
  }
2290
2144
  };
2291
2145
 
2146
+ // src/type-application-erasure.ts
2147
+ import * as ts7 from "typescript";
2148
+ var TYPE_APPLICATION_APIS = new Set(["go.get", "go.set"]);
2149
+ function isTypeApplication(call, checker) {
2150
+ if (call.arguments.length !== 0)
2151
+ return false;
2152
+ const declaration = checker.getResolvedSignature(call)?.declaration;
2153
+ if (declaration === undefined || !ts7.isFunctionDeclaration(declaration))
2154
+ return false;
2155
+ if (declaration.parameters.length !== 0 || declaration.typeParameters === undefined)
2156
+ return false;
2157
+ if (declaration.name === undefined)
2158
+ return false;
2159
+ const symbol = checker.getSymbolAtLocation(declaration.name);
2160
+ if (symbol === undefined)
2161
+ return false;
2162
+ const fqn = checker.getFullyQualifiedName(symbol);
2163
+ return fqn.startsWith("global.") && TYPE_APPLICATION_APIS.has(fqn.slice("global.".length));
2164
+ }
2165
+ var typeApplicationErasurePlugin = {
2166
+ visitors: {
2167
+ [ts7.SyntaxKind.CallExpression]: (node, context) => {
2168
+ if (isTypeApplication(node, context.checker)) {
2169
+ return context.transformExpression(node.expression);
2170
+ }
2171
+ return context.superTransformExpression(node);
2172
+ }
2173
+ }
2174
+ };
2175
+
2292
2176
  // src/window-event-guard-lowering.ts
2293
2177
  import * as ts8 from "typescript";
2294
2178
  import {
2295
- createBinaryExpression as createBinaryExpression5,
2296
- SyntaxKind as SyntaxKind12
2179
+ createBinaryExpression as createBinaryExpression4,
2180
+ SyntaxKind as SyntaxKind11
2297
2181
  } from "typescript-to-lua";
2298
2182
  var GUARD_MODULE2 = "@defold-typescript/types";
2299
2183
  var GUARD_NAME2 = "isWindowEvent";
@@ -2321,7 +2205,7 @@ var windowEventGuardLoweringPlugin = {
2321
2205
  if (node.arguments.length === 3 && eventArg !== undefined && expectedArg !== undefined && resolvesToGuardExport2(node.expression, context.checker)) {
2322
2206
  const event = context.transformExpression(eventArg);
2323
2207
  const expected = context.transformExpression(expectedArg);
2324
- return createBinaryExpression5(event, expected, SyntaxKind12.EqualityOperator, node);
2208
+ return createBinaryExpression4(event, expected, SyntaxKind11.EqualityOperator, node);
2325
2209
  }
2326
2210
  return context.superTransformExpression(node);
2327
2211
  }
@@ -2335,7 +2219,7 @@ var LUA_PLUGINS = [
2335
2219
  windowEventGuardLoweringPlugin,
2336
2220
  messageDispatchLoweringPlugin,
2337
2221
  timersLoweringPlugin,
2338
- arrayIndexOptionLoweringPlugin
2222
+ typeApplicationErasurePlugin
2339
2223
  ];
2340
2224
  var noopWriteFile = () => {};
2341
2225
  function isAmbient(fileName) {
@@ -2930,18 +2814,18 @@ import {
2930
2814
  createTableIndexExpression as createTableIndexExpression2,
2931
2815
  createVariableDeclarationStatement as createVariableDeclarationStatement3,
2932
2816
  isBlock as isBlock3,
2933
- isCallExpression as isCallExpression5,
2817
+ isCallExpression as isCallExpression4,
2934
2818
  isDoStatement,
2935
2819
  isForInStatement as isForInStatement2,
2936
2820
  isForStatement,
2937
2821
  isFunctionDefinition,
2938
2822
  isFunctionExpression as isFunctionExpression4,
2939
- isIdentifier as isIdentifier5,
2823
+ isIdentifier as isIdentifier4,
2940
2824
  isMethodCallExpression,
2941
2825
  isRepeatStatement,
2942
2826
  isReturnStatement as isReturnStatement2,
2943
- isStringLiteral as isStringLiteral8,
2944
- isTableExpression as isTableExpression2,
2827
+ isStringLiteral as isStringLiteral6,
2828
+ isTableExpression,
2945
2829
  isVariableDeclarationStatement,
2946
2830
  LuaPrinter
2947
2831
  } from "typescript-to-lua";
@@ -3013,7 +2897,7 @@ function freeNames(statements) {
3013
2897
  if (node === undefined) {
3014
2898
  return;
3015
2899
  }
3016
- if (isIdentifier5(node)) {
2900
+ if (isIdentifier4(node)) {
3017
2901
  if (!isBound(node.text)) {
3018
2902
  free.add(node.text);
3019
2903
  }
@@ -3119,14 +3003,14 @@ function resolvedRequirePaths(sourceFile, checker) {
3119
3003
  function resolveMovedRequires(statements, paths) {
3120
3004
  for (const statement of statements) {
3121
3005
  forEachLuaNode(statement, (node) => {
3122
- if (!isCallExpression5(node) || !isIdentifier5(node.expression)) {
3006
+ if (!isCallExpression4(node) || !isIdentifier4(node.expression)) {
3123
3007
  return;
3124
3008
  }
3125
3009
  if (node.expression.text !== "require" || node.params.length !== 1) {
3126
3010
  return;
3127
3011
  }
3128
3012
  const [argument] = node.params;
3129
- if (argument === undefined || !isStringLiteral8(argument)) {
3013
+ if (argument === undefined || !isStringLiteral6(argument)) {
3130
3014
  return;
3131
3015
  }
3132
3016
  const resolved = paths.get(argument.value);
@@ -3142,14 +3026,14 @@ function withResolvedRequire(statement, paths) {
3142
3026
  }
3143
3027
  const name = statement.left[0];
3144
3028
  const [value] = statement.right ?? [];
3145
- if (name === undefined || value === undefined || !isCallExpression5(value)) {
3029
+ if (name === undefined || value === undefined || !isCallExpression4(value)) {
3146
3030
  return statement;
3147
3031
  }
3148
- if (!isIdentifier5(value.expression) || value.expression.text !== "require") {
3032
+ if (!isIdentifier4(value.expression) || value.expression.text !== "require") {
3149
3033
  return statement;
3150
3034
  }
3151
3035
  const [argument] = value.params;
3152
- if (argument === undefined || !isStringLiteral8(argument)) {
3036
+ if (argument === undefined || !isStringLiteral6(argument)) {
3153
3037
  return statement;
3154
3038
  }
3155
3039
  const resolved = paths.get(argument.value);
@@ -3185,7 +3069,7 @@ function copiedPrelude(halves, importBindings) {
3185
3069
  function namesIdentifier(statement, names) {
3186
3070
  let found = false;
3187
3071
  forEachLuaNode(statement, (node) => {
3188
- if (isIdentifier5(node) && names.has(node.text)) {
3072
+ if (isIdentifier4(node) && names.has(node.text)) {
3189
3073
  found = true;
3190
3074
  }
3191
3075
  });
@@ -3196,14 +3080,14 @@ function isExportsTableInit(statement) {
3196
3080
  return false;
3197
3081
  }
3198
3082
  const [single] = statement.right ?? [];
3199
- return statement.left[0]?.text === EXPORTS_NAME && single !== undefined && isTableExpression2(single);
3083
+ return statement.left[0]?.text === EXPORTS_NAME && single !== undefined && isTableExpression(single);
3200
3084
  }
3201
3085
  function isExportsReturn(statement) {
3202
3086
  if (!isReturnStatement2(statement) || statement.expressions.length !== 1) {
3203
3087
  return false;
3204
3088
  }
3205
3089
  const [single] = statement.expressions;
3206
- return single !== undefined && isIdentifier5(single) && single.text === EXPORTS_NAME;
3090
+ return single !== undefined && isIdentifier4(single) && single.text === EXPORTS_NAME;
3207
3091
  }
3208
3092
  function isHoistedNameDeclaration(statement) {
3209
3093
  return isVariableDeclarationStatement(statement) && statement.right === undefined;
@@ -3631,7 +3515,7 @@ function transpileProject(input) {
3631
3515
  { plugin: windowEventGuardLoweringPlugin },
3632
3516
  { plugin: messageDispatchLoweringPlugin },
3633
3517
  { plugin: timersLoweringPlugin },
3634
- { plugin: arrayIndexOptionLoweringPlugin },
3518
+ { plugin: typeApplicationErasurePlugin },
3635
3519
  { plugin: companionEmit.plugin }
3636
3520
  ]
3637
3521
  });
@@ -3662,7 +3546,7 @@ function compilerOptions(companionEmit) {
3662
3546
  { plugin: windowEventGuardLoweringPlugin },
3663
3547
  { plugin: messageDispatchLoweringPlugin },
3664
3548
  { plugin: timersLoweringPlugin },
3665
- { plugin: arrayIndexOptionLoweringPlugin },
3549
+ { plugin: typeApplicationErasurePlugin },
3666
3550
  { plugin: companionEmit.plugin }
3667
3551
  ]
3668
3552
  };
@@ -3779,8 +3663,71 @@ function createTranspileSession() {
3779
3663
  getProgram: () => program
3780
3664
  };
3781
3665
  }
3782
- // src/url-address-slots.ts
3666
+ // src/text-script-property.ts
3783
3667
  import * as ts14 from "typescript";
3668
+ function findTextScriptProperties(program, fileNames) {
3669
+ const checker = program.getTypeChecker();
3670
+ const findings = [];
3671
+ for (const file of fileNames) {
3672
+ const sourceFile = program.getSourceFile(file);
3673
+ if (sourceFile === undefined) {
3674
+ continue;
3675
+ }
3676
+ const located = [];
3677
+ const visit = (node) => {
3678
+ if (ts14.isCallExpression(node)) {
3679
+ const hooks = factoryHooks(node, checker);
3680
+ for (const property of hooks?.properties ?? []) {
3681
+ if (!isPropertiesHook(property)) {
3682
+ continue;
3683
+ }
3684
+ for (const { name, initializer } of propertyMembers(property)) {
3685
+ if (mayHoldString(checker.getTypeAtLocation(initializer), checker)) {
3686
+ located.push({ name, value: initializer });
3687
+ }
3688
+ }
3689
+ }
3690
+ }
3691
+ ts14.forEachChild(node, visit);
3692
+ };
3693
+ visit(sourceFile);
3694
+ for (const call of findDirectGoPropertyCalls(sourceFile)) {
3695
+ const [nameArgument, value] = call.arguments;
3696
+ if (nameArgument === undefined || value === undefined) {
3697
+ continue;
3698
+ }
3699
+ if (mayHoldString(checker.getTypeAtLocation(value), checker)) {
3700
+ const name = ts14.isStringLiteralLike(nameArgument) ? nameArgument.text : nameArgument.getText(sourceFile);
3701
+ located.push({ name, value });
3702
+ }
3703
+ }
3704
+ located.sort((left, right) => left.value.getStart(sourceFile) - right.value.getStart(sourceFile));
3705
+ for (const { name, value } of located) {
3706
+ const position = sourceFile.getLineAndCharacterOfPosition(value.getStart(sourceFile));
3707
+ findings.push({ name, file, line: position.line + 1, column: position.character + 1 });
3708
+ }
3709
+ }
3710
+ return findings;
3711
+ }
3712
+ function mayHoldString(type, checker, visited = new Set) {
3713
+ if (visited.has(type)) {
3714
+ return false;
3715
+ }
3716
+ visited.add(type);
3717
+ if (type.flags & ts14.TypeFlags.StringLike) {
3718
+ return true;
3719
+ }
3720
+ if (type.isUnionOrIntersection()) {
3721
+ return type.types.some((member) => mayHoldString(member, checker, visited));
3722
+ }
3723
+ if (type.flags & ts14.TypeFlags.Instantiable) {
3724
+ const constraint = checker.getBaseConstraintOfType(type);
3725
+ return constraint !== undefined && constraint !== type ? mayHoldString(constraint, checker, visited) : false;
3726
+ }
3727
+ return false;
3728
+ }
3729
+ // src/url-address-slots.ts
3730
+ import * as ts15 from "typescript";
3784
3731
  var ADDRESS_CLASSES = {
3785
3732
  "game-object": true,
3786
3733
  component: true,
@@ -3799,7 +3746,7 @@ function isFragmentCaret(slot, position) {
3799
3746
  return slot.fragmentStart !== -1 && position >= slot.fragmentStart;
3800
3747
  }
3801
3748
  function tableKey(checker, callee) {
3802
- const symbol = checker.getSymbolAtLocation(ts14.isIdentifier(callee) ? callee : callee.name);
3749
+ const symbol = checker.getSymbolAtLocation(ts15.isIdentifier(callee) ? callee : callee.name);
3803
3750
  if (!symbol)
3804
3751
  return;
3805
3752
  const fqn = checker.getFullyQualifiedName(symbol);
@@ -3807,43 +3754,43 @@ function tableKey(checker, callee) {
3807
3754
  }
3808
3755
  function parameterName(checker, call, index) {
3809
3756
  const declaration = checker.getResolvedSignature(call)?.declaration;
3810
- if (!declaration || !ts14.isFunctionLike(declaration))
3757
+ if (!declaration || !ts15.isFunctionLike(declaration))
3811
3758
  return;
3812
3759
  const parameter = declaration.parameters[index];
3813
- if (!parameter || parameter.dotDotDotToken || !ts14.isIdentifier(parameter.name))
3760
+ if (!parameter || parameter.dotDotDotToken || !ts15.isIdentifier(parameter.name))
3814
3761
  return;
3815
3762
  return parameter.name.text;
3816
3763
  }
3817
3764
  var EQUALITY_OPERATORS = new Set([
3818
- ts14.SyntaxKind.EqualsEqualsEqualsToken,
3819
- ts14.SyntaxKind.ExclamationEqualsEqualsToken,
3820
- ts14.SyntaxKind.EqualsEqualsToken,
3821
- ts14.SyntaxKind.ExclamationEqualsToken
3765
+ ts15.SyntaxKind.EqualsEqualsEqualsToken,
3766
+ ts15.SyntaxKind.ExclamationEqualsEqualsToken,
3767
+ ts15.SyntaxKind.EqualsEqualsToken,
3768
+ ts15.SyntaxKind.ExclamationEqualsToken
3822
3769
  ]);
3823
3770
  function comparisonSatisfied(checker, entry, call) {
3824
3771
  if (entry.comparedParameter === undefined)
3825
3772
  return true;
3826
3773
  let node = call;
3827
- while (ts14.isParenthesizedExpression(node.parent))
3774
+ while (ts15.isParenthesizedExpression(node.parent))
3828
3775
  node = node.parent;
3829
3776
  const comparison = node.parent;
3830
- if (!ts14.isBinaryExpression(comparison))
3777
+ if (!ts15.isBinaryExpression(comparison))
3831
3778
  return false;
3832
3779
  if (!EQUALITY_OPERATORS.has(comparison.operatorToken.kind))
3833
3780
  return false;
3834
3781
  const other = comparison.left === node ? comparison.right : comparison.left;
3835
3782
  const symbol = checker.getSymbolAtLocation(other);
3836
- return (symbol?.declarations ?? []).some((declaration) => ts14.isParameter(declaration) && ts14.isIdentifier(declaration.name) && declaration.name.text === entry.comparedParameter);
3783
+ return (symbol?.declarations ?? []).some((declaration) => ts15.isParameter(declaration) && ts15.isIdentifier(declaration.name) && declaration.name.text === entry.comparedParameter);
3837
3784
  }
3838
3785
  function classifiedEntryOfArgument(checker, table, argument) {
3839
3786
  const call = argument.parent;
3840
- if (!ts14.isCallExpression(call))
3787
+ if (!ts15.isCallExpression(call))
3841
3788
  return;
3842
3789
  const argumentIndex = call.arguments.indexOf(argument);
3843
3790
  if (argumentIndex === -1)
3844
3791
  return;
3845
3792
  const callee = call.expression;
3846
- if (!ts14.isPropertyAccessExpression(callee) && !ts14.isIdentifier(callee))
3793
+ if (!ts15.isPropertyAccessExpression(callee) && !ts15.isIdentifier(callee))
3847
3794
  return;
3848
3795
  const fqn = tableKey(checker, callee);
3849
3796
  if (fqn === undefined)
@@ -3860,10 +3807,10 @@ function classifiedEntryOfArgument(checker, table, argument) {
3860
3807
  }
3861
3808
  function slotThroughHashedCall(checker, table, literal) {
3862
3809
  const call = literal.parent;
3863
- if (!ts14.isCallExpression(call))
3810
+ if (!ts15.isCallExpression(call))
3864
3811
  return;
3865
3812
  const callee = call.expression;
3866
- if (!ts14.isPropertyAccessExpression(callee) && !ts14.isIdentifier(callee))
3813
+ if (!ts15.isPropertyAccessExpression(callee) && !ts15.isIdentifier(callee))
3867
3814
  return;
3868
3815
  if (tableKey(checker, callee) !== "hash")
3869
3816
  return;
@@ -3881,24 +3828,24 @@ function addressTextOf(checker, entry, call) {
3881
3828
  if (entry.addressParameter === undefined)
3882
3829
  return;
3883
3830
  const declaration = checker.getResolvedSignature(call)?.declaration;
3884
- if (!declaration || !ts14.isFunctionLike(declaration))
3831
+ if (!declaration || !ts15.isFunctionLike(declaration))
3885
3832
  return;
3886
- const index = declaration.parameters.findIndex((parameter) => !parameter.dotDotDotToken && ts14.isIdentifier(parameter.name) && parameter.name.text === entry.addressParameter);
3833
+ const index = declaration.parameters.findIndex((parameter) => !parameter.dotDotDotToken && ts15.isIdentifier(parameter.name) && parameter.name.text === entry.addressParameter);
3887
3834
  if (index === -1)
3888
3835
  return;
3889
3836
  const argument = call.arguments[index];
3890
- return argument && ts14.isStringLiteralLike(argument) ? argument.text : undefined;
3837
+ return argument && ts15.isStringLiteralLike(argument) ? argument.text : undefined;
3891
3838
  }
3892
3839
  function innermostLiteralAt(sourceFile, position) {
3893
3840
  let found;
3894
3841
  const visit = (node) => {
3895
3842
  if (position < node.getStart(sourceFile) || position > node.getEnd())
3896
3843
  return;
3897
- if (ts14.isStringLiteralLike(node))
3844
+ if (ts15.isStringLiteralLike(node))
3898
3845
  found = node;
3899
- ts14.forEachChild(node, visit);
3846
+ ts15.forEachChild(node, visit);
3900
3847
  };
3901
- ts14.forEachChild(sourceFile, visit);
3848
+ ts15.forEachChild(sourceFile, visit);
3902
3849
  return found;
3903
3850
  }
3904
3851
  function resolveClassifiedSlotAtPosition(input) {
@@ -3932,23 +3879,23 @@ function resolveClassifiedSlotAtPosition(input) {
3932
3879
  };
3933
3880
  }
3934
3881
  // src/url-cross-world-address.ts
3935
- import * as ts16 from "typescript";
3882
+ import * as ts17 from "typescript";
3936
3883
 
3937
3884
  // src/url-address-literals.ts
3938
- import * as ts15 from "typescript";
3885
+ import * as ts16 from "typescript";
3939
3886
  function isAmbient2(fileName) {
3940
3887
  return /[\\/]node_modules[\\/]/.test(fileName) || /(^|[\\/])lib\.[^\\/]*\.d\.ts$/.test(fileName);
3941
3888
  }
3942
3889
  function referenceTargetSymbol(type) {
3943
- if ((type.flags & ts15.TypeFlags.Object) === 0)
3890
+ if ((type.flags & ts16.TypeFlags.Object) === 0)
3944
3891
  return;
3945
- if ((type.objectFlags & ts15.ObjectFlags.Reference) === 0)
3892
+ if ((type.objectFlags & ts16.ObjectFlags.Reference) === 0)
3946
3893
  return;
3947
3894
  return type.target.symbol;
3948
3895
  }
3949
3896
  function ambientHashAliasTargets(checker, anchor) {
3950
3897
  const targets = new Set;
3951
- for (const symbol of checker.getSymbolsInScope(anchor, ts15.SymbolFlags.Type)) {
3898
+ for (const symbol of checker.getSymbolsInScope(anchor, ts16.SymbolFlags.Type)) {
3952
3899
  if (symbol.name !== "Hash")
3953
3900
  continue;
3954
3901
  const target = referenceTargetSymbol(checker.getDeclaredTypeOfSymbol(symbol));
@@ -3964,7 +3911,7 @@ function canonicalHashSymbols(checker, program) {
3964
3911
  if (!anchor)
3965
3912
  return canonical;
3966
3913
  const aliased = ambientHashAliasTargets(checker, anchor);
3967
- for (const symbol of checker.getSymbolsInScope(anchor, ts15.SymbolFlags.Function)) {
3914
+ for (const symbol of checker.getSymbolsInScope(anchor, ts16.SymbolFlags.Function)) {
3968
3915
  if (symbol.name !== "hash")
3969
3916
  continue;
3970
3917
  const declaration = symbol.declarations?.[0];
@@ -3986,7 +3933,7 @@ function hashedSourceOfType(checker, type, canonical) {
3986
3933
  return source?.isStringLiteral() ? source.value : undefined;
3987
3934
  }
3988
3935
  function staticAddressTextOf(checker, node, canonical) {
3989
- return ts15.isStringLiteralLike(node) ? node.text : hashedSourceOfType(checker, checker.getTypeAtLocation(node), canonical);
3936
+ return ts16.isStringLiteralLike(node) ? node.text : hashedSourceOfType(checker, checker.getTypeAtLocation(node), canonical);
3990
3937
  }
3991
3938
 
3992
3939
  // src/url-cross-world-address.ts
@@ -4010,7 +3957,7 @@ function checkCrossWorldAddresses(input) {
4010
3957
  if (worlds.length === 0)
4011
3958
  continue;
4012
3959
  const visit = (node) => {
4013
- if (ts16.isExpression(node)) {
3960
+ if (ts17.isExpression(node)) {
4014
3961
  const entry = addressEntryOfArgument(checker, table, node);
4015
3962
  if (entry !== undefined && slotRejectsForeignSocket(entry)) {
4016
3963
  const address = staticAddressTextOf(checker, node, canonical);
@@ -4027,14 +3974,14 @@ function checkCrossWorldAddresses(input) {
4027
3974
  }
4028
3975
  }
4029
3976
  }
4030
- ts16.forEachChild(node, visit);
3977
+ ts17.forEachChild(node, visit);
4031
3978
  };
4032
- ts16.forEachChild(sourceFile, visit);
3979
+ ts17.forEachChild(sourceFile, visit);
4033
3980
  }
4034
3981
  return findings;
4035
3982
  }
4036
3983
  // src/url-fragment-reachability.ts
4037
- import * as ts17 from "typescript";
3984
+ import * as ts18 from "typescript";
4038
3985
  function pathOfKey(key) {
4039
3986
  const socket = socketOfAddress(key);
4040
3987
  return socket === undefined ? key : key.slice(socket.length + 1);
@@ -4079,7 +4026,7 @@ function checkUrlFragmentReachability(input) {
4079
4026
  if (isAmbient2(sourceFile.fileName))
4080
4027
  continue;
4081
4028
  const visit = (node) => {
4082
- if (ts17.isExpression(node) && isAddressClass(addressClassOfArgument(checker, table, node))) {
4029
+ if (ts18.isExpression(node) && isAddressClass(addressClassOfArgument(checker, table, node))) {
4083
4030
  const text = staticAddressTextOf(checker, node, canonical);
4084
4031
  if (text !== undefined) {
4085
4032
  const hash = text.indexOf("#");
@@ -4098,9 +4045,9 @@ function checkUrlFragmentReachability(input) {
4098
4045
  }
4099
4046
  }
4100
4047
  }
4101
- ts17.forEachChild(node, visit);
4048
+ ts18.forEachChild(node, visit);
4102
4049
  };
4103
- ts17.forEachChild(sourceFile, visit);
4050
+ ts18.forEachChild(sourceFile, visit);
4104
4051
  }
4105
4052
  return { kind: "checked", findings };
4106
4053
  }
@@ -4145,6 +4092,7 @@ export {
4145
4092
  displayPathOf,
4146
4093
  findEmittedRequires,
4147
4094
  findMainEntryFactoryImports,
4095
+ findTextScriptProperties,
4148
4096
  getProgramDiagnostics,
4149
4097
  guiScriptResourceOf,
4150
4098
  guiScriptResourcesOf,
@@ -4156,6 +4104,7 @@ export {
4156
4104
  libraryIncludedEntries,
4157
4105
  listProjectResourcePaths,
4158
4106
  parseBuildConfig,
4107
+ parseDefignore,
4159
4108
  parseSceneTextFormat,
4160
4109
  projectRelativeBase,
4161
4110
  readGameProjectDependencies,