@thigasdevelopment/luam 1.0.0 → 1.0.2
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/lua/async.lua +6 -6
- package/lua/class.lua +239 -211
- package/lua/development-logs-client.lua +15 -9
- package/lua/development-logs-server.lua +41 -44
- package/lua/math.lua +21 -18
- package/lua/promise.lua +446 -0
- package/lua/string.lua +78 -62
- package/lua/table.lua +57 -49
- package/lua/threads.lua +326 -269
- package/lua/validate.lua +230 -185
- package/luam.mjs +301 -47
- package/package.json +1 -1
package/luam.mjs
CHANGED
|
@@ -3609,6 +3609,8 @@ var LUA_KEYWORDS = /* @__PURE__ */ new Set([
|
|
|
3609
3609
|
"while"
|
|
3610
3610
|
]);
|
|
3611
3611
|
var LUAM_KEYWORDS = /* @__PURE__ */ new Set([
|
|
3612
|
+
"async",
|
|
3613
|
+
"await",
|
|
3612
3614
|
"class",
|
|
3613
3615
|
"constructor",
|
|
3614
3616
|
"continue",
|
|
@@ -4279,7 +4281,20 @@ function parseParameters(stream) {
|
|
|
4279
4281
|
stream.expect("punctuation", ")");
|
|
4280
4282
|
return parameters;
|
|
4281
4283
|
}
|
|
4282
|
-
|
|
4284
|
+
var ASYNC_MODIFIER = "async";
|
|
4285
|
+
function isAsyncFunctionStart(stream, offset = 0) {
|
|
4286
|
+
return stream.checkAhead(offset, "keyword", ASYNC_MODIFIER) && stream.checkAhead(offset + 1, "keyword", "function");
|
|
4287
|
+
}
|
|
4288
|
+
function consumeAsyncModifier(stream) {
|
|
4289
|
+
if (!isAsyncFunctionStart(stream)) {
|
|
4290
|
+
return false;
|
|
4291
|
+
}
|
|
4292
|
+
const checkpoint = stream.checkpoint();
|
|
4293
|
+
stream.next();
|
|
4294
|
+
stream.eraseToCurrent(checkpoint);
|
|
4295
|
+
return true;
|
|
4296
|
+
}
|
|
4297
|
+
function parseFunctionExpression(stream, isAsync = false) {
|
|
4283
4298
|
const position2 = stream.expect("keyword", "function").position;
|
|
4284
4299
|
const typeParameters = parseTypeParameters(stream);
|
|
4285
4300
|
const parameters = parseParameters(stream);
|
|
@@ -4288,6 +4303,7 @@ function parseFunctionExpression(stream) {
|
|
|
4288
4303
|
stream.expect("keyword", "end");
|
|
4289
4304
|
return {
|
|
4290
4305
|
kind: "function-expression",
|
|
4306
|
+
isAsync,
|
|
4291
4307
|
typeParameters: typeParameters.names,
|
|
4292
4308
|
typeConstraints: typeParameters.constraints,
|
|
4293
4309
|
parameters,
|
|
@@ -4309,7 +4325,7 @@ function parseFunctionName(stream) {
|
|
|
4309
4325
|
const property = stream.expect("identifier").value;
|
|
4310
4326
|
return { name: { kind: "member-expression", object: name, property, position: token.position }, isMethod: true };
|
|
4311
4327
|
}
|
|
4312
|
-
function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExport = false) {
|
|
4328
|
+
function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExport = false, isAsync = false) {
|
|
4313
4329
|
const position2 = stream.expect("keyword", "function").position;
|
|
4314
4330
|
const { name, isMethod } = parseFunctionName(stream);
|
|
4315
4331
|
const typeParameters = parseTypeParameters(stream);
|
|
@@ -4320,6 +4336,7 @@ function parseFunctionDeclaration(stream, isLocal, isExported = false, isHttpExp
|
|
|
4320
4336
|
return {
|
|
4321
4337
|
kind: "function-declaration",
|
|
4322
4338
|
name,
|
|
4339
|
+
isAsync,
|
|
4323
4340
|
isLocal,
|
|
4324
4341
|
isExported,
|
|
4325
4342
|
isHttpExport,
|
|
@@ -4374,6 +4391,14 @@ function isRightAssociative(operator) {
|
|
|
4374
4391
|
|
|
4375
4392
|
// ../compiler/src/parser/expression.ts
|
|
4376
4393
|
var LITERAL_KEYWORDS = /* @__PURE__ */ new Set(["nil", "true", "false"]);
|
|
4394
|
+
var AWAIT_OPERATOR = "await";
|
|
4395
|
+
function isAwaitStart(stream) {
|
|
4396
|
+
return stream.check("keyword", AWAIT_OPERATOR);
|
|
4397
|
+
}
|
|
4398
|
+
function parseAwaitExpression(stream) {
|
|
4399
|
+
const position2 = stream.next().position;
|
|
4400
|
+
return { kind: "await-expression", operand: parseSuffixed(stream), position: position2 };
|
|
4401
|
+
}
|
|
4377
4402
|
function parseKeywordLiteral(token) {
|
|
4378
4403
|
if (token.value === "nil") {
|
|
4379
4404
|
return { kind: "nil-literal", position: token.position };
|
|
@@ -4432,6 +4457,10 @@ function parsePrimary(stream) {
|
|
|
4432
4457
|
stream.next();
|
|
4433
4458
|
return { kind: "identifier", name: token.value, position: token.position };
|
|
4434
4459
|
}
|
|
4460
|
+
if (isAsyncFunctionStart(stream)) {
|
|
4461
|
+
consumeAsyncModifier(stream);
|
|
4462
|
+
return parseFunctionExpression(stream, true);
|
|
4463
|
+
}
|
|
4435
4464
|
if (token.kind === "identifier") {
|
|
4436
4465
|
stream.next();
|
|
4437
4466
|
return { kind: "identifier", name: token.value, position: token.position };
|
|
@@ -4524,6 +4553,9 @@ function parseSuffixed(stream) {
|
|
|
4524
4553
|
}
|
|
4525
4554
|
}
|
|
4526
4555
|
function parseUnary(stream) {
|
|
4556
|
+
if (isAwaitStart(stream)) {
|
|
4557
|
+
return parseAwaitExpression(stream);
|
|
4558
|
+
}
|
|
4527
4559
|
const token = stream.current();
|
|
4528
4560
|
const isUnary2 = (token.kind === "operator" || token.kind === "keyword") && UNARY_OPERATORS.has(token.value);
|
|
4529
4561
|
if (!isUnary2) {
|
|
@@ -4715,12 +4747,14 @@ function parseDecorators(stream) {
|
|
|
4715
4747
|
}
|
|
4716
4748
|
return decorators;
|
|
4717
4749
|
}
|
|
4718
|
-
function parseClassMethod(stream, token, decorators, isStatic) {
|
|
4750
|
+
function parseClassMethod(stream, token, decorators, isStatic, isAsync) {
|
|
4719
4751
|
stream.expect("operator", "=");
|
|
4720
|
-
const
|
|
4752
|
+
const modified = consumeAsyncModifier(stream) || isAsync;
|
|
4753
|
+
const expression = parseFunctionExpression(stream, modified);
|
|
4721
4754
|
return {
|
|
4722
4755
|
kind: "class-method",
|
|
4723
4756
|
name: token.value,
|
|
4757
|
+
isAsync: modified,
|
|
4724
4758
|
isConstructor: token.value === "constructor",
|
|
4725
4759
|
isSynthetic: false,
|
|
4726
4760
|
isStatic,
|
|
@@ -4733,13 +4767,14 @@ function parseClassMethod(stream, token, decorators, isStatic) {
|
|
|
4733
4767
|
position: token.position
|
|
4734
4768
|
};
|
|
4735
4769
|
}
|
|
4736
|
-
function parseBraceClassMethod(stream, token, decorators, isStatic) {
|
|
4770
|
+
function parseBraceClassMethod(stream, token, decorators, isStatic, isAsync) {
|
|
4737
4771
|
const parameters = parseParameters(stream);
|
|
4738
4772
|
const returnAnnotation = parseOptionalAnnotation(stream);
|
|
4739
4773
|
const body = parseBraceBlock(stream);
|
|
4740
4774
|
return {
|
|
4741
4775
|
kind: "class-method",
|
|
4742
4776
|
name: token.value,
|
|
4777
|
+
isAsync,
|
|
4743
4778
|
isConstructor: token.value === "constructor",
|
|
4744
4779
|
isSynthetic: false,
|
|
4745
4780
|
isStatic,
|
|
@@ -4772,12 +4807,12 @@ function expectClassFieldBoundary(stream, token) {
|
|
|
4772
4807
|
throw stream.error(`Expected a line break or separator after class member "${token.value}".`, "parse-unexpected-token");
|
|
4773
4808
|
}
|
|
4774
4809
|
var STATIC_MODIFIER = "static";
|
|
4775
|
-
function
|
|
4776
|
-
if (!stream.check(
|
|
4810
|
+
function parseMemberModifier(stream, modifier, kind = "identifier") {
|
|
4811
|
+
if (!stream.check(kind, modifier)) {
|
|
4777
4812
|
return false;
|
|
4778
4813
|
}
|
|
4779
|
-
const
|
|
4780
|
-
if (!stream.checkName(1) || stream.peek(1).position.line !==
|
|
4814
|
+
const token = stream.current();
|
|
4815
|
+
if (!stream.checkName(1) || stream.peek(1).position.line !== token.position.line) {
|
|
4781
4816
|
return false;
|
|
4782
4817
|
}
|
|
4783
4818
|
const checkpoint = stream.checkpoint();
|
|
@@ -4787,14 +4822,15 @@ function parseStaticModifier(stream) {
|
|
|
4787
4822
|
}
|
|
4788
4823
|
function parseClassMember(stream) {
|
|
4789
4824
|
const decorators = parseDecorators(stream);
|
|
4790
|
-
const isStatic =
|
|
4825
|
+
const isStatic = parseMemberModifier(stream, STATIC_MODIFIER);
|
|
4826
|
+
const isAsync = parseMemberModifier(stream, ASYNC_MODIFIER, "keyword");
|
|
4791
4827
|
const token = stream.expectMemberKey();
|
|
4792
4828
|
if (stream.check("punctuation", "(")) {
|
|
4793
4829
|
stream.report("parse-class-method-form", `Write class member "${token.value}" as "${token.value} = function (...) ... end".`, token.position);
|
|
4794
|
-
return parseBraceClassMethod(stream, token, decorators, isStatic);
|
|
4830
|
+
return parseBraceClassMethod(stream, token, decorators, isStatic, isAsync);
|
|
4795
4831
|
}
|
|
4796
|
-
if (stream.check("operator", "=") && stream.checkAhead(1, "keyword", "function")) {
|
|
4797
|
-
return parseClassMethod(stream, token, decorators, isStatic);
|
|
4832
|
+
if (stream.check("operator", "=") && (stream.checkAhead(1, "keyword", "function") || isAsyncFunctionStart(stream, 1))) {
|
|
4833
|
+
return parseClassMethod(stream, token, decorators, isStatic, isAsync);
|
|
4798
4834
|
}
|
|
4799
4835
|
const annotation = parseFieldAnnotation(stream);
|
|
4800
4836
|
const value = stream.match("operator", "=") ? parseFieldValue(stream) : null;
|
|
@@ -5075,6 +5111,10 @@ function parseGlobalDeclaration(stream) {
|
|
|
5075
5111
|
return null;
|
|
5076
5112
|
}
|
|
5077
5113
|
function parseExpressionStatement(stream) {
|
|
5114
|
+
if (isAwaitStart(stream)) {
|
|
5115
|
+
const expression = parseAwaitExpression(stream);
|
|
5116
|
+
return { kind: "call-statement", expression, position: expression.position };
|
|
5117
|
+
}
|
|
5078
5118
|
const declaration = parseGlobalDeclaration(stream);
|
|
5079
5119
|
if (declaration !== null) {
|
|
5080
5120
|
return declaration;
|
|
@@ -5106,6 +5146,10 @@ function parseKeywordStatement(stream, value) {
|
|
|
5106
5146
|
if (stream.check("keyword", "function")) {
|
|
5107
5147
|
return parseFunctionDeclaration(stream, true);
|
|
5108
5148
|
}
|
|
5149
|
+
if (isAsyncFunctionStart(stream)) {
|
|
5150
|
+
consumeAsyncModifier(stream);
|
|
5151
|
+
return parseFunctionDeclaration(stream, true, false, false, true);
|
|
5152
|
+
}
|
|
5109
5153
|
const isEnum = stream.check("keyword", "enum") && stream.checkAhead(1, "identifier");
|
|
5110
5154
|
return isEnum ? parseEnumDeclaration(stream, true) : parseLocalStatement(stream, token.position);
|
|
5111
5155
|
}
|
|
@@ -5148,6 +5192,10 @@ function parseStatement(stream) {
|
|
|
5148
5192
|
return statement;
|
|
5149
5193
|
}
|
|
5150
5194
|
}
|
|
5195
|
+
if (isAsyncFunctionStart(stream)) {
|
|
5196
|
+
consumeAsyncModifier(stream);
|
|
5197
|
+
return parseFunctionDeclaration(stream, false, false, false, true);
|
|
5198
|
+
}
|
|
5151
5199
|
if (isTypeAlias(stream)) {
|
|
5152
5200
|
return parseTypeAlias(stream);
|
|
5153
5201
|
}
|
|
@@ -5794,9 +5842,16 @@ var RUNTIME_HELPERS = {
|
|
|
5794
5842
|
},
|
|
5795
5843
|
env: { name: "env", file: "env.lua", injection: "manual", features: [], environment: "server" },
|
|
5796
5844
|
math: { name: "math", file: "math.lua", injection: "automatic", features: ["number-extension"] },
|
|
5845
|
+
promise: {
|
|
5846
|
+
name: "promise",
|
|
5847
|
+
file: "promise.lua",
|
|
5848
|
+
injection: "reference",
|
|
5849
|
+
features: ["async-function"],
|
|
5850
|
+
globals: ["Promise", "delay", "sleep"]
|
|
5851
|
+
},
|
|
5797
5852
|
string: { name: "string", file: "string.lua", injection: "automatic", features: ["string-extension", "template-string"] },
|
|
5798
5853
|
table: { name: "table", file: "table.lua", injection: "automatic", features: ["table-extension"] },
|
|
5799
|
-
threads: { name: "threads", file: "threads.lua", injection: "reference", features: ["thread"], globals: ["
|
|
5854
|
+
threads: { name: "threads", file: "threads.lua", injection: "reference", features: ["thread"], globals: ["Threads"], requires: ["promise"] },
|
|
5800
5855
|
validate: { name: "validate", file: "validate.lua", injection: "automatic", features: ["boundary-validation"] }
|
|
5801
5856
|
};
|
|
5802
5857
|
var DEVELOPMENT_RUNTIME_HELPERS = {
|
|
@@ -7099,7 +7154,7 @@ import { tmpdir } from "node:os";
|
|
|
7099
7154
|
import { join as join2 } from "node:path";
|
|
7100
7155
|
|
|
7101
7156
|
// src/cli/version.ts
|
|
7102
|
-
var VERSION = true ? "1.0.
|
|
7157
|
+
var VERSION = true ? "1.0.2" : "0.0.0-dev";
|
|
7103
7158
|
var PROGRAM_NAME = "luam";
|
|
7104
7159
|
var PROGRAM_DESCRIPTION = "luam \u2014 the Luam compiler for Multi Theft Auto resources.";
|
|
7105
7160
|
|
|
@@ -8987,7 +9042,7 @@ var EMPTY_AMBIENT = { classes: [], interfaces: [], enums: [], aliases: [], globa
|
|
|
8987
9042
|
function ambientFromRegistry(registry) {
|
|
8988
9043
|
return {
|
|
8989
9044
|
classes: registry.allClasses(),
|
|
8990
|
-
interfaces: registry.allInterfaces(),
|
|
9045
|
+
interfaces: registry.allInterfaces().filter((info) => info.isBuiltin !== true),
|
|
8991
9046
|
enums: registry.allEnums().filter((info) => info.isLocal !== true),
|
|
8992
9047
|
aliases: registry.allAliases(),
|
|
8993
9048
|
globals: registry.allGlobals(),
|
|
@@ -9155,6 +9210,74 @@ function descriptorToType(descriptor) {
|
|
|
9155
9210
|
return PRIMITIVES[descriptor.kind] ?? ANY_TYPE;
|
|
9156
9211
|
}
|
|
9157
9212
|
|
|
9213
|
+
// ../compiler/src/checker/async.ts
|
|
9214
|
+
var PROMISE_TYPE = "Promise";
|
|
9215
|
+
var SLEEP_FUNCTION = "sleep";
|
|
9216
|
+
var PROMISE_PARAMETER = "T";
|
|
9217
|
+
var ORIGIN = { line: 0, column: 0, offset: 0 };
|
|
9218
|
+
var AWAIT_OUTSIDE_MESSAGE = '"await" is only valid inside an async function. Declare the function "async function name()", or wait on the promise with ":next(...)".';
|
|
9219
|
+
var ASYNC_ANNOTATION_MESSAGE = 'An async function is annotated with the type it resolves to, not with "Promise". Write the inner type and the signature becomes a promise of it.';
|
|
9220
|
+
var SLEEP_OUTSIDE_MESSAGE = '"sleep" suspends a coroutine and there is none here. Declare the function "async function name()", or run the body as a thread pool job.';
|
|
9221
|
+
function promiseOf(inner) {
|
|
9222
|
+
return createNamed(PROMISE_TYPE, [inner]);
|
|
9223
|
+
}
|
|
9224
|
+
function isPromiseType(type) {
|
|
9225
|
+
return (type.kind === "named" || type.kind === "record") && type.name === PROMISE_TYPE;
|
|
9226
|
+
}
|
|
9227
|
+
function declarePromiseType(declarations) {
|
|
9228
|
+
const value = createNamed(PROMISE_PARAMETER);
|
|
9229
|
+
const onFulfilled = createFunction([value], ANY_TYPE, 1, false, ["value"]);
|
|
9230
|
+
const onRejected = createFunction([ANY_TYPE], ANY_TYPE, 1, false, ["reason"]);
|
|
9231
|
+
const chained = promiseOf(ANY_TYPE);
|
|
9232
|
+
const next = createFunction([onFulfilled, createOptional(onRejected)], chained, 1, false, ["onFulfilled", "onRejected"]);
|
|
9233
|
+
const failure3 = createFunction([onRejected], chained, 1, false, ["onRejected"]);
|
|
9234
|
+
declarations.declareInterface({
|
|
9235
|
+
name: PROMISE_TYPE,
|
|
9236
|
+
isBuiltin: true,
|
|
9237
|
+
typeParameters: [PROMISE_PARAMETER],
|
|
9238
|
+
typeConstraints: [null],
|
|
9239
|
+
superInterfaces: [],
|
|
9240
|
+
members: /* @__PURE__ */ new Map([
|
|
9241
|
+
["next", { name: "next", type: next, isMethod: true, position: ORIGIN }],
|
|
9242
|
+
["catch", { name: "catch", type: failure3, isMethod: true, position: ORIGIN }]
|
|
9243
|
+
]),
|
|
9244
|
+
position: ORIGIN
|
|
9245
|
+
});
|
|
9246
|
+
}
|
|
9247
|
+
function awaitedType(context, operand, expression) {
|
|
9248
|
+
if (!context.inAsyncBody()) {
|
|
9249
|
+
context.report("check-await-outside-async", AWAIT_OUTSIDE_MESSAGE, expression.position);
|
|
9250
|
+
return ANY_TYPE;
|
|
9251
|
+
}
|
|
9252
|
+
if (operand.kind === "any" || operand.kind === "unknown") {
|
|
9253
|
+
return ANY_TYPE;
|
|
9254
|
+
}
|
|
9255
|
+
if (isPromiseType(operand)) {
|
|
9256
|
+
return (operand.kind === "named" ? operand.typeArguments?.[0] : ANY_TYPE) ?? ANY_TYPE;
|
|
9257
|
+
}
|
|
9258
|
+
const message = `"await" expects a promise but received "${typeToString(operand)}". Only an async function or "new Promise(...)" produces one.`;
|
|
9259
|
+
context.report("check-await-non-promise", message, expression.position);
|
|
9260
|
+
return ANY_TYPE;
|
|
9261
|
+
}
|
|
9262
|
+
function isPromiseAnnotation(isAsync, annotation) {
|
|
9263
|
+
return isAsync && annotation !== null && annotation.kind === "type-name" && annotation.name === PROMISE_TYPE;
|
|
9264
|
+
}
|
|
9265
|
+
function asyncInnerAnnotation(isAsync, annotation) {
|
|
9266
|
+
return isPromiseAnnotation(isAsync, annotation) ? null : annotation;
|
|
9267
|
+
}
|
|
9268
|
+
function reportAsyncAnnotation(context, isAsync, annotation) {
|
|
9269
|
+
if (!isPromiseAnnotation(isAsync, annotation) || annotation === null) {
|
|
9270
|
+
return;
|
|
9271
|
+
}
|
|
9272
|
+
context.report("check-async-return-annotation", ASYNC_ANNOTATION_MESSAGE, annotation.position);
|
|
9273
|
+
}
|
|
9274
|
+
function reportSleepOutsideAsync(context, name, position2) {
|
|
9275
|
+
if (name !== SLEEP_FUNCTION || context.declaredGlobals.has(name) || context.binder.lookup(name)?.isLocal === true || context.suspendable()) {
|
|
9276
|
+
return;
|
|
9277
|
+
}
|
|
9278
|
+
context.warn("check-sleep-outside-async", SLEEP_OUTSIDE_MESSAGE, position2);
|
|
9279
|
+
}
|
|
9280
|
+
|
|
9158
9281
|
// ../compiler/src/checker/binder.ts
|
|
9159
9282
|
var Binder = class {
|
|
9160
9283
|
scopes = [/* @__PURE__ */ new Map()];
|
|
@@ -9486,6 +9609,17 @@ var LUA_GLOBALS = {
|
|
|
9486
9609
|
};
|
|
9487
9610
|
|
|
9488
9611
|
// ../mta-types/src/luam-runtime.ts
|
|
9612
|
+
var PROMISE_VALUE = named("Promise");
|
|
9613
|
+
var RESOLVE = fn([ANY], VOID, 0, true, ["values"]);
|
|
9614
|
+
var REJECT = fn([ANY], VOID, 0, true, ["reason"]);
|
|
9615
|
+
var EXECUTOR = fn([RESOLVE, REJECT], ANY, 2, false, ["resolve", "reject"]);
|
|
9616
|
+
var ON_FULFILLED = fn([ANY], ANY, 0, true, ["value"]);
|
|
9617
|
+
var ON_REJECTED = fn([ANY], ANY, 1, false, ["reason"]);
|
|
9618
|
+
var PROMISE = record("Promise", [
|
|
9619
|
+
{ name: "next", type: fn([ON_FULFILLED, optionalOf(ON_REJECTED)], PROMISE_VALUE, 1, false, ["onFulfilled", "onRejected"]) },
|
|
9620
|
+
{ name: "catch", type: fn([ON_REJECTED], PROMISE_VALUE, 1, false, ["onRejected"]) }
|
|
9621
|
+
]);
|
|
9622
|
+
var JOB = tupleOf([NUMBER, PROMISE]);
|
|
9489
9623
|
var THREAD = record("Thread", [
|
|
9490
9624
|
{ name: "get", type: fn([], NUMBER, 0) },
|
|
9491
9625
|
{ name: "set", type: fn([NUMBER], BOOLEAN, 1) },
|
|
@@ -9494,8 +9628,10 @@ var THREAD = record("Thread", [
|
|
|
9494
9628
|
{ name: "isPaused", type: fn([], BOOLEAN, 0) },
|
|
9495
9629
|
{ name: "isStarted", type: fn([], BOOLEAN, 0) }
|
|
9496
9630
|
]);
|
|
9631
|
+
var JOB_BODY = fn([THREAD], ANY, 0, true, ["thread"]);
|
|
9632
|
+
var TASK_BODY = fn([ANY], ANY, 0, true, ["values"]);
|
|
9497
9633
|
var THREADS = record("Threads", [
|
|
9498
|
-
{ name: "add", type: fn([
|
|
9634
|
+
{ name: "add", type: fn([JOB_BODY, TABLE], JOB, 1, true, ["target", "options"]) },
|
|
9499
9635
|
{ name: "remove", type: fn([NUMBER], BOOLEAN, 1) },
|
|
9500
9636
|
{ name: "clear", type: fn([], BOOLEAN, 0) },
|
|
9501
9637
|
{ name: "start", type: fn([], BOOLEAN, 0) },
|
|
@@ -9503,18 +9639,31 @@ var THREADS = record("Threads", [
|
|
|
9503
9639
|
{ name: "getType", type: fn([], STRING, 0) }
|
|
9504
9640
|
]);
|
|
9505
9641
|
var ASYNC = record("Async", [
|
|
9506
|
-
{ name: "map", type: fn([TABLE, ANY, ANY],
|
|
9507
|
-
{ name: "iterate", type: fn([NUMBER, NUMBER, NUMBER, ANY, ANY],
|
|
9508
|
-
{ name: "foreach", type: fn([TABLE, ANY, ANY],
|
|
9642
|
+
{ name: "map", type: fn([TABLE, ANY, ANY], JOB, 2) },
|
|
9643
|
+
{ name: "iterate", type: fn([NUMBER, NUMBER, NUMBER, ANY, ANY], JOB, 4) },
|
|
9644
|
+
{ name: "foreach", type: fn([TABLE, ANY, ANY], JOB, 2) },
|
|
9509
9645
|
{ name: "getInterval", type: fn([], NUMBER, 0) },
|
|
9510
9646
|
{ name: "setInterval", type: fn([NUMBER], BOOLEAN, 1) }
|
|
9511
9647
|
]);
|
|
9648
|
+
var PROMISE_LIBRARY = record("PromiseLibrary", [
|
|
9649
|
+
{ name: "new", type: fn([EXECUTOR], PROMISE, 1, false, ["executor"]) },
|
|
9650
|
+
{ name: "spawn", type: fn([TASK_BODY], PROMISE, 1, true, ["target"]) },
|
|
9651
|
+
{ name: "resolve", type: fn([ANY], PROMISE, 0, true) },
|
|
9652
|
+
{ name: "reject", type: fn([ANY], PROMISE, 0, true) },
|
|
9653
|
+
{ name: "all", type: fn([arrayOf(ANY)], PROMISE, 1) },
|
|
9654
|
+
{ name: "race", type: fn([arrayOf(ANY)], PROMISE, 1) },
|
|
9655
|
+
{ name: "settle", type: fn([PROMISE], tupleOf([BOOLEAN, ANY]), 1) },
|
|
9656
|
+
{ name: "await", type: fn([PROMISE], ANY, 1) },
|
|
9657
|
+
{ name: "delay", type: fn([NUMBER], PROMISE, 1) }
|
|
9658
|
+
]);
|
|
9512
9659
|
var LUAM_RUNTIME_SERVER_GLOBALS = {};
|
|
9513
9660
|
var LUAM_RUNTIME_GLOBALS = {
|
|
9514
9661
|
bind: fn([ANY, ANY], ANY, 2),
|
|
9515
9662
|
getClass: fn([STRING], optionalOf(TABLE), 1),
|
|
9516
9663
|
getClasses: fn([], TABLE, 0),
|
|
9517
9664
|
sleep: fn([NUMBER], ANY, 1),
|
|
9665
|
+
delay: fn([NUMBER], PROMISE, 1),
|
|
9666
|
+
Promise: PROMISE_LIBRARY,
|
|
9518
9667
|
Thread: THREAD,
|
|
9519
9668
|
Threads: record("ThreadsLibrary", [{ name: "new", type: fn([STRING, STRING], THREADS, 0) }]),
|
|
9520
9669
|
Async: record("AsyncLibrary", [{ name: "new", type: fn([NUMBER], ASYNC, 0) }])
|
|
@@ -14591,6 +14740,7 @@ var CheckContext = class {
|
|
|
14591
14740
|
isDeclarationFile = false;
|
|
14592
14741
|
returnStack = [];
|
|
14593
14742
|
methodStack = [];
|
|
14743
|
+
functionStack = [];
|
|
14594
14744
|
projectEnvironments = /* @__PURE__ */ new Map();
|
|
14595
14745
|
predeclared = /* @__PURE__ */ new Map();
|
|
14596
14746
|
ambientClasses = /* @__PURE__ */ new Set();
|
|
@@ -14606,6 +14756,7 @@ var CheckContext = class {
|
|
|
14606
14756
|
this.environment = environment;
|
|
14607
14757
|
this.mtaClasses = oop ? mtaClassRegistry() : null;
|
|
14608
14758
|
this.binder.useBuiltins(builtinSymbols(environment));
|
|
14759
|
+
declarePromiseType(this.declarations);
|
|
14609
14760
|
this.declareProject(project);
|
|
14610
14761
|
this.declareAmbient(ambient);
|
|
14611
14762
|
}
|
|
@@ -14779,6 +14930,18 @@ var CheckContext = class {
|
|
|
14779
14930
|
currentClassMethod() {
|
|
14780
14931
|
return this.methodStack[this.methodStack.length - 1] ?? null;
|
|
14781
14932
|
}
|
|
14933
|
+
pushFunctionFrame(frame) {
|
|
14934
|
+
this.functionStack.push(frame);
|
|
14935
|
+
}
|
|
14936
|
+
popFunctionFrame() {
|
|
14937
|
+
this.functionStack.pop();
|
|
14938
|
+
}
|
|
14939
|
+
inAsyncBody() {
|
|
14940
|
+
return this.functionStack[this.functionStack.length - 1]?.isAsync === true;
|
|
14941
|
+
}
|
|
14942
|
+
suspendable() {
|
|
14943
|
+
return this.functionStack.some((frame) => frame.isAsync || frame.isExpression);
|
|
14944
|
+
}
|
|
14782
14945
|
resolveAnnotation(annotation) {
|
|
14783
14946
|
if (annotation === null) {
|
|
14784
14947
|
return ANY_TYPE;
|
|
@@ -15040,6 +15203,7 @@ function childExpressions(expression) {
|
|
|
15040
15203
|
case "binary-expression":
|
|
15041
15204
|
return [expression.left, expression.right];
|
|
15042
15205
|
case "unary-expression":
|
|
15206
|
+
case "await-expression":
|
|
15043
15207
|
return [expression.operand];
|
|
15044
15208
|
case "group-expression":
|
|
15045
15209
|
return [expression.expression];
|
|
@@ -15615,6 +15779,7 @@ function accessorMethod(field2, decorator, name) {
|
|
|
15615
15779
|
return {
|
|
15616
15780
|
kind: "class-method",
|
|
15617
15781
|
name,
|
|
15782
|
+
isAsync: false,
|
|
15618
15783
|
isConstructor: false,
|
|
15619
15784
|
isSynthetic: true,
|
|
15620
15785
|
isStatic: false,
|
|
@@ -15628,7 +15793,7 @@ function accessorMethod(field2, decorator, name) {
|
|
|
15628
15793
|
};
|
|
15629
15794
|
}
|
|
15630
15795
|
function generatedMethod(field2, name, parameters, returnAnnotation, kind, fields) {
|
|
15631
|
-
return { kind: "class-method", name, isConstructor: false, isSynthetic: true, isStatic: false, typeParameters: [], typeConstraints: [], parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
15796
|
+
return { kind: "class-method", name, isAsync: false, isConstructor: false, isSynthetic: true, isStatic: false, typeParameters: [], typeConstraints: [], parameters, returnAnnotation, body: [], decorators: [], generated: { kind, fields }, position: field2.position };
|
|
15632
15797
|
}
|
|
15633
15798
|
function typeName(name, node) {
|
|
15634
15799
|
return { kind: "type-name", name, typeArguments: [], position: node.position };
|
|
@@ -15663,6 +15828,7 @@ function staticMethod(statement, name, returnAnnotation, kind, descriptor) {
|
|
|
15663
15828
|
return {
|
|
15664
15829
|
kind: "class-method",
|
|
15665
15830
|
name,
|
|
15831
|
+
isAsync: false,
|
|
15666
15832
|
isConstructor: false,
|
|
15667
15833
|
isSynthetic: true,
|
|
15668
15834
|
isStatic: true,
|
|
@@ -15818,6 +15984,7 @@ function childExpressions2(expression) {
|
|
|
15818
15984
|
case "binary-expression":
|
|
15819
15985
|
return [expression.left, expression.right];
|
|
15820
15986
|
case "unary-expression":
|
|
15987
|
+
case "await-expression":
|
|
15821
15988
|
return [expression.operand];
|
|
15822
15989
|
case "group-expression":
|
|
15823
15990
|
return [expression.expression];
|
|
@@ -20721,7 +20888,7 @@ function checkEventDeclaration(context, declaration) {
|
|
|
20721
20888
|
}
|
|
20722
20889
|
|
|
20723
20890
|
// ../compiler/src/checker/statements.ts
|
|
20724
|
-
var
|
|
20891
|
+
var ORIGIN2 = { line: 0, column: 0, offset: 0 };
|
|
20725
20892
|
function minimumArguments(context, parameters) {
|
|
20726
20893
|
const index = parameters.findIndex((parameter) => {
|
|
20727
20894
|
const type = context.resolveAnnotation(parameter.annotation);
|
|
@@ -20729,14 +20896,17 @@ function minimumArguments(context, parameters) {
|
|
|
20729
20896
|
});
|
|
20730
20897
|
return index === -1 ? parameters.length : index;
|
|
20731
20898
|
}
|
|
20732
|
-
function buildFunctionType(context, parameters, returnAnnotation, contextual = null) {
|
|
20899
|
+
function buildFunctionType(context, parameters, returnAnnotation, contextual = null, isAsync = false) {
|
|
20733
20900
|
const isVariadic = parameters.some((parameter) => parameter.isVararg);
|
|
20734
20901
|
const named2 = parameters.filter((parameter) => !parameter.isVararg);
|
|
20735
20902
|
const types = named2.map(
|
|
20736
20903
|
(parameter, index) => parameter.annotation === null ? contextual?.parameters[index] ?? ANY_TYPE : context.resolveValueAnnotation(parameter.annotation, "a parameter")
|
|
20737
20904
|
);
|
|
20738
20905
|
const names = named2.map((parameter) => parameter.name);
|
|
20739
|
-
|
|
20906
|
+
reportAsyncAnnotation(context, isAsync, returnAnnotation);
|
|
20907
|
+
const declared = context.resolveAnnotation(asyncInnerAnnotation(isAsync, returnAnnotation));
|
|
20908
|
+
const returnType = isAsync ? promiseOf(declared) : declared;
|
|
20909
|
+
return createFunction(types, returnType, minimumArguments(context, parameters), isVariadic, names);
|
|
20740
20910
|
}
|
|
20741
20911
|
function applyTypeParameters(context, type, names, constraints) {
|
|
20742
20912
|
if (names.length === 0) {
|
|
@@ -20762,14 +20932,16 @@ function reportMissingReturn(context, declared, position2) {
|
|
|
20762
20932
|
const repair = declared.kind === "tuple" ? "Add a return on every path." : `Add a return on every path, or declare "${name}?".`;
|
|
20763
20933
|
context.report("check-missing-return", `This function declares "${name}" but can end without returning a value. ${repair}`, position2);
|
|
20764
20934
|
}
|
|
20765
|
-
function checkFunctionBody(context, parameters, returnAnnotation, body, signature2, selfType2, position2 =
|
|
20935
|
+
function checkFunctionBody(context, parameters, returnAnnotation, body, signature2, selfType2, position2 = ORIGIN2, frame = { isAsync: false, isExpression: false }) {
|
|
20766
20936
|
forgetAssignedPaths(context, body);
|
|
20767
20937
|
const entry = context.flowState;
|
|
20938
|
+
const annotation = asyncInnerAnnotation(frame.isAsync, returnAnnotation);
|
|
20768
20939
|
context.setFlow(cloneFlow(entry));
|
|
20769
20940
|
context.binder.pushScope();
|
|
20770
|
-
context.
|
|
20941
|
+
context.pushFunctionFrame(frame);
|
|
20942
|
+
context.pushReturnType(annotation === null ? null : context.resolveAnnotation(annotation));
|
|
20771
20943
|
if (selfType2 !== null) {
|
|
20772
|
-
context.binder.declare({ name: "self", type: selfType2, isLocal: true, position:
|
|
20944
|
+
context.binder.declare({ name: "self", type: selfType2, isLocal: true, position: ORIGIN2 });
|
|
20773
20945
|
}
|
|
20774
20946
|
let parameterIndex = 0;
|
|
20775
20947
|
for (const parameter of parameters) {
|
|
@@ -20789,9 +20961,10 @@ function checkFunctionBody(context, parameters, returnAnnotation, body, signatur
|
|
|
20789
20961
|
reportMissingReturn(context, declared, position2);
|
|
20790
20962
|
}
|
|
20791
20963
|
const inferred = context.popReturnType();
|
|
20792
|
-
if (
|
|
20793
|
-
signature2.returnType = inferred;
|
|
20964
|
+
if (annotation === null) {
|
|
20965
|
+
signature2.returnType = frame.isAsync ? promiseOf(inferred) : inferred;
|
|
20794
20966
|
}
|
|
20967
|
+
context.popFunctionFrame();
|
|
20795
20968
|
context.binder.popScope();
|
|
20796
20969
|
context.setFlow(entry);
|
|
20797
20970
|
}
|
|
@@ -20931,7 +21104,7 @@ function reportShadowedAssignment(context, target) {
|
|
|
20931
21104
|
}
|
|
20932
21105
|
}
|
|
20933
21106
|
function checkFunctionDeclaration(context, statement) {
|
|
20934
|
-
const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation);
|
|
21107
|
+
const built = buildFunctionType(context, statement.parameters, statement.returnAnnotation, null, statement.isAsync);
|
|
20935
21108
|
const type = applyTypeParameters(context, built, statement.typeParameters, statement.typeConstraints);
|
|
20936
21109
|
if (statement.name.kind === "identifier") {
|
|
20937
21110
|
const symbol = { name: statement.name.name, type, isLocal: statement.isLocal, position: statement.position };
|
|
@@ -20946,7 +21119,10 @@ function checkFunctionDeclaration(context, statement) {
|
|
|
20946
21119
|
reportShadowedAssignment(context, statement.name);
|
|
20947
21120
|
}
|
|
20948
21121
|
context.record(statement.name, type);
|
|
20949
|
-
checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position
|
|
21122
|
+
checkFunctionBody(context, statement.parameters, statement.returnAnnotation, statement.body, type, statement.isMethod ? ANY_TYPE : null, statement.position, {
|
|
21123
|
+
isAsync: statement.isAsync,
|
|
21124
|
+
isExpression: false
|
|
21125
|
+
});
|
|
20950
21126
|
}
|
|
20951
21127
|
function checkReturn(context, statement) {
|
|
20952
21128
|
const valueTypes = checkValueList(context, statement.values);
|
|
@@ -21299,6 +21475,9 @@ function checkMethodCall(context, expression, method, receiver) {
|
|
|
21299
21475
|
return checkSignature(context, expression.args, member.type, expression.position);
|
|
21300
21476
|
}
|
|
21301
21477
|
function checkCall(context, expression) {
|
|
21478
|
+
if (expression.method === null && expression.callee.kind === "identifier") {
|
|
21479
|
+
reportSleepOutsideAsync(context, expression.callee.name, expression.position);
|
|
21480
|
+
}
|
|
21302
21481
|
const contracted = checkResourceCall(context, expression);
|
|
21303
21482
|
if (contracted !== null) {
|
|
21304
21483
|
return context.record(expression, contracted);
|
|
@@ -21430,9 +21609,12 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
21430
21609
|
case "table-expression":
|
|
21431
21610
|
return checkTable(context, expression);
|
|
21432
21611
|
case "function-expression": {
|
|
21433
|
-
const built = buildFunctionType(context, expression.parameters, expression.returnAnnotation, contextualFunction(expected));
|
|
21612
|
+
const built = buildFunctionType(context, expression.parameters, expression.returnAnnotation, contextualFunction(expected), expression.isAsync);
|
|
21434
21613
|
const type = applyTypeParameters(context, built, expression.typeParameters, expression.typeConstraints);
|
|
21435
|
-
checkFunctionBody(context, expression.parameters, expression.returnAnnotation, expression.body, type, null, expression.position
|
|
21614
|
+
checkFunctionBody(context, expression.parameters, expression.returnAnnotation, expression.body, type, null, expression.position, {
|
|
21615
|
+
isAsync: expression.isAsync,
|
|
21616
|
+
isExpression: true
|
|
21617
|
+
});
|
|
21436
21618
|
return context.record(expression, type);
|
|
21437
21619
|
}
|
|
21438
21620
|
case "binary-expression": {
|
|
@@ -21442,6 +21624,8 @@ function checkMultiValueExpression(context, expression, expected = null) {
|
|
|
21442
21624
|
}
|
|
21443
21625
|
case "unary-expression":
|
|
21444
21626
|
return checkUnary(context, expression.operator, checkExpression(context, expression.operand), expression);
|
|
21627
|
+
case "await-expression":
|
|
21628
|
+
return context.record(expression, awaitedType(context, checkExpression(context, expression.operand), expression));
|
|
21445
21629
|
default:
|
|
21446
21630
|
return context.record(expression, checkExpression(context, expression.expression, expected));
|
|
21447
21631
|
}
|
|
@@ -21517,7 +21701,12 @@ function registerMembers(context, info, statement) {
|
|
|
21517
21701
|
}
|
|
21518
21702
|
const generated = expandClassDecorators(context, statement, fieldTypes);
|
|
21519
21703
|
for (const member of [...statement.members, ...generated]) {
|
|
21520
|
-
const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : applyTypeParameters(
|
|
21704
|
+
const type = member.kind === "class-field" ? fieldTypes.get(member) ?? ANY_TYPE : member.isSynthetic ? syntheticMethodType(context, member, fieldTypes) : applyTypeParameters(
|
|
21705
|
+
context,
|
|
21706
|
+
buildFunctionType(context, member.parameters, member.returnAnnotation, null, member.isAsync),
|
|
21707
|
+
member.typeParameters,
|
|
21708
|
+
member.typeConstraints
|
|
21709
|
+
);
|
|
21521
21710
|
const decorators = member.decorators.map((decorator) => decorator.name);
|
|
21522
21711
|
if (member.kind === "class-method" && isMetamethodMember(member)) {
|
|
21523
21712
|
checkMetamethod(context, info.name, member, type);
|
|
@@ -21577,12 +21766,13 @@ function checkMethodBody(context, info, member) {
|
|
|
21577
21766
|
if (signature2?.kind !== "function") {
|
|
21578
21767
|
return;
|
|
21579
21768
|
}
|
|
21769
|
+
const frame = { isAsync: member.isAsync, isExpression: false };
|
|
21580
21770
|
if (member.isStatic) {
|
|
21581
|
-
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, null, member.position);
|
|
21771
|
+
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, null, member.position, frame);
|
|
21582
21772
|
return;
|
|
21583
21773
|
}
|
|
21584
21774
|
context.pushClassMethod({ className: info.name, methodName: member.name });
|
|
21585
|
-
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, selfType(info), member.position);
|
|
21775
|
+
checkFunctionBody(context, member.parameters, member.returnAnnotation, member.body, signature2, selfType(info), member.position, frame);
|
|
21586
21776
|
context.popClassMethod();
|
|
21587
21777
|
}
|
|
21588
21778
|
function assignSuperClass(context, info, statement) {
|
|
@@ -21665,7 +21855,8 @@ function checkClassDeclaration(context, statement) {
|
|
|
21665
21855
|
}
|
|
21666
21856
|
}
|
|
21667
21857
|
function checkInterfaceDeclaration(context, statement) {
|
|
21668
|
-
|
|
21858
|
+
const existing = context.declarations.lookupInterface(statement.name);
|
|
21859
|
+
if (existing !== null && existing.isBuiltin !== true) {
|
|
21669
21860
|
context.report("check-duplicate-interface", `Interface "${statement.name}" is already defined.`, statement.position);
|
|
21670
21861
|
return;
|
|
21671
21862
|
}
|
|
@@ -21697,10 +21888,10 @@ function checkInterfaceDeclaration(context, statement) {
|
|
|
21697
21888
|
const inherited = /* @__PURE__ */ new Map();
|
|
21698
21889
|
for (const parent of statement.superInterfaces) {
|
|
21699
21890
|
for (const member of context.declarations.collectInterfaceContract(parent)) {
|
|
21700
|
-
const
|
|
21701
|
-
if (
|
|
21891
|
+
const existing2 = members.get(member.name) ?? inherited.get(member.name);
|
|
21892
|
+
if (existing2 !== void 0 && (existing2.isMethod !== member.isMethod || typeToString(existing2.type) !== typeToString(member.type))) {
|
|
21702
21893
|
context.report("check-conflicting-interface-member", `Interface "${statement.name}" inherits conflicting declarations of "${member.name}".`, statement.position);
|
|
21703
|
-
} else if (
|
|
21894
|
+
} else if (existing2 === void 0) {
|
|
21704
21895
|
inherited.set(member.name, member);
|
|
21705
21896
|
}
|
|
21706
21897
|
}
|
|
@@ -22087,7 +22278,24 @@ function emitString(value) {
|
|
|
22087
22278
|
function emitParameters(parameters) {
|
|
22088
22279
|
return parameters.map((parameter) => parameter.isVararg ? "..." : parameter.name).join(", ");
|
|
22089
22280
|
}
|
|
22090
|
-
function
|
|
22281
|
+
function emitAsyncFunctionBody(state, parameters, body, header, receiver) {
|
|
22282
|
+
requireHelper(state, "promise");
|
|
22283
|
+
const declared = emitParameters(parameters);
|
|
22284
|
+
const forwarded = (receiver === null ? [declared] : [receiver, declared]).filter((part) => part.length > 0).join(", ");
|
|
22285
|
+
const previous = state.loopWrap;
|
|
22286
|
+
state.indent += 1;
|
|
22287
|
+
state.loopWrap = false;
|
|
22288
|
+
const lines = emitBlock(state, body);
|
|
22289
|
+
state.loopWrap = previous;
|
|
22290
|
+
state.indent -= 1;
|
|
22291
|
+
const signature2 = `${header}(${declared}) return Promise.spawn(function(${forwarded})`;
|
|
22292
|
+
const closing = indentLine(state, `end${forwarded.length === 0 ? "" : `, ${forwarded}`}) end`);
|
|
22293
|
+
return [signature2, ...lines, closing].join("\n");
|
|
22294
|
+
}
|
|
22295
|
+
function emitFunctionBody(state, parameters, body, header, isAsync = false, receiver = null) {
|
|
22296
|
+
if (isAsync) {
|
|
22297
|
+
return emitAsyncFunctionBody(state, parameters, body, header, receiver);
|
|
22298
|
+
}
|
|
22091
22299
|
const previous = state.loopWrap;
|
|
22092
22300
|
state.indent += 1;
|
|
22093
22301
|
state.loopWrap = false;
|
|
@@ -22197,7 +22405,7 @@ function emitExpression(state, expression, limit = 0) {
|
|
|
22197
22405
|
case "table-expression":
|
|
22198
22406
|
return emitTable(state, expression);
|
|
22199
22407
|
case "function-expression":
|
|
22200
|
-
return emitFunctionBody(state, expression.parameters, expression.body, "function");
|
|
22408
|
+
return emitFunctionBody(state, expression.parameters, expression.body, "function", expression.isAsync);
|
|
22201
22409
|
case "binary-expression":
|
|
22202
22410
|
return emitBinary(state, expression, limit);
|
|
22203
22411
|
case "unary-expression": {
|
|
@@ -22205,6 +22413,9 @@ function emitExpression(state, expression, limit = 0) {
|
|
|
22205
22413
|
const text = expression.operator === "not" ? `not ${operand}` : `${expression.operator}${operand}`;
|
|
22206
22414
|
return UNARY_PRECEDENCE < limit ? `(${text})` : text;
|
|
22207
22415
|
}
|
|
22416
|
+
case "await-expression":
|
|
22417
|
+
requireHelper(state, "promise");
|
|
22418
|
+
return `Promise.await(${emitExpression(state, expression.operand)})`;
|
|
22208
22419
|
default:
|
|
22209
22420
|
return `(${emitExpression(state, expression.expression)})`;
|
|
22210
22421
|
}
|
|
@@ -22221,7 +22432,7 @@ function emitMethod(state, className, member) {
|
|
|
22221
22432
|
return emitGeneratedMethod(state, className, member);
|
|
22222
22433
|
}
|
|
22223
22434
|
const parameters = member.isStatic ? member.parameters : [self, ...member.parameters];
|
|
22224
|
-
return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${emitMemberKey(member.name)} = function
|
|
22435
|
+
return withSymbol(state, `${className}${member.isStatic ? "." : ":"}${member.name}`, () => emitFunctionBody(state, parameters, member.body, `${emitMemberKey(member.name)} = function`, member.isAsync));
|
|
22225
22436
|
}
|
|
22226
22437
|
function emitGeneratedMethod(state, className, member) {
|
|
22227
22438
|
const fields = member.generated?.fields ?? [];
|
|
@@ -22461,7 +22672,7 @@ function emitFunctionDeclaration(state, statement) {
|
|
|
22461
22672
|
const prefix = statement.isLocal ? "local function " : "function ";
|
|
22462
22673
|
const name = emitFunctionName(state, statement);
|
|
22463
22674
|
const header = `${prefix}${name}`;
|
|
22464
|
-
return withSymbol(state, name, () => emitFunctionBody(state, statement.parameters, statement.body, header));
|
|
22675
|
+
return withSymbol(state, name, () => emitFunctionBody(state, statement.parameters, statement.body, header, statement.isAsync, statement.isMethod ? "self" : null));
|
|
22465
22676
|
}
|
|
22466
22677
|
function emitNested2(state, body) {
|
|
22467
22678
|
state.indent += 1;
|
|
@@ -22675,6 +22886,7 @@ function fromExpression(expression, blocks) {
|
|
|
22675
22886
|
fromExpression(expression.right, blocks);
|
|
22676
22887
|
return;
|
|
22677
22888
|
case "unary-expression":
|
|
22889
|
+
case "await-expression":
|
|
22678
22890
|
fromExpression(expression.operand, blocks);
|
|
22679
22891
|
return;
|
|
22680
22892
|
case "group-expression":
|
|
@@ -22790,6 +23002,16 @@ function reindent(code, indent) {
|
|
|
22790
23002
|
}
|
|
22791
23003
|
return code.split("\n").map((line2, index) => index === 0 || line2.length === 0 ? line2 : `${indent}${line2}`).join("\n");
|
|
22792
23004
|
}
|
|
23005
|
+
var CLOSING_LINE = /^\s*(?:end|\})/;
|
|
23006
|
+
function padAboveClosing(replacement, missing2) {
|
|
23007
|
+
const lines = replacement.split("\n");
|
|
23008
|
+
const closing = lines[lines.length - 1] ?? "";
|
|
23009
|
+
const blanks = Array.from({ length: missing2 }, () => "");
|
|
23010
|
+
if (lines.length < 2 || !CLOSING_LINE.test(closing)) {
|
|
23011
|
+
return [replacement, ...blanks].join("\n");
|
|
23012
|
+
}
|
|
23013
|
+
return [...lines.slice(0, -1), ...blanks, closing].join("\n");
|
|
23014
|
+
}
|
|
22793
23015
|
function erasedEnd(source, span) {
|
|
22794
23016
|
const trailing = TRAILING_SEMICOLON.exec(source.slice(span.end));
|
|
22795
23017
|
return trailing === null ? span.end : span.end + trailing[0].length;
|
|
@@ -22812,7 +23034,7 @@ function canonicalEdit(input, statement, span) {
|
|
|
22812
23034
|
if (missing2 < 0 && input.development) {
|
|
22813
23035
|
return null;
|
|
22814
23036
|
}
|
|
22815
|
-
const padded = missing2 > 0 && source.slice(end).trim().length > 0 ?
|
|
23037
|
+
const padded = missing2 > 0 && source.slice(end).trim().length > 0 ? padAboveClosing(replacement, missing2) : replacement;
|
|
22816
23038
|
return { start: span.start, end, replacement: padded, lines: emitted2.lines };
|
|
22817
23039
|
}
|
|
22818
23040
|
|
|
@@ -22841,7 +23063,10 @@ function isPreservableExpression(expression, types, statics = NO_STATIC_ACCESS)
|
|
|
22841
23063
|
switch (expression.kind) {
|
|
22842
23064
|
case "template-literal":
|
|
22843
23065
|
case "new-expression":
|
|
23066
|
+
case "await-expression":
|
|
22844
23067
|
return false;
|
|
23068
|
+
case "function-expression":
|
|
23069
|
+
return !expression.isAsync;
|
|
22845
23070
|
case "member-expression":
|
|
22846
23071
|
return !statics.has(expression) && resolvePropertyExtension(types.get(expression.object) ?? null, expression.property) === null && isPreservableExpression(expression.object, types, statics);
|
|
22847
23072
|
case "index-expression":
|
|
@@ -22890,11 +23115,12 @@ function isPreservableStatement(statement, types, statics = NO_STATIC_ACCESS) {
|
|
|
22890
23115
|
return isPreservableExpression(statement.start, types, statics) && isPreservableExpression(statement.limit, types, statics) && (statement.step === null || isPreservableExpression(statement.step, types, statics));
|
|
22891
23116
|
case "generic-for-statement":
|
|
22892
23117
|
return every(statement.iterators, types, statics);
|
|
23118
|
+
case "function-declaration":
|
|
23119
|
+
return !statement.isAsync;
|
|
22893
23120
|
case "break-statement":
|
|
22894
23121
|
case "declare-statement":
|
|
22895
23122
|
case "do-statement":
|
|
22896
23123
|
case "event-declaration":
|
|
22897
|
-
case "function-declaration":
|
|
22898
23124
|
case "interface-declaration":
|
|
22899
23125
|
case "type-alias-statement":
|
|
22900
23126
|
return true;
|
|
@@ -23070,6 +23296,7 @@ function children(expression) {
|
|
|
23070
23296
|
case "binary-expression":
|
|
23071
23297
|
return [expression.left, expression.right];
|
|
23072
23298
|
case "unary-expression":
|
|
23299
|
+
case "await-expression":
|
|
23073
23300
|
return [expression.operand];
|
|
23074
23301
|
case "group-expression":
|
|
23075
23302
|
return [expression.expression];
|
|
@@ -23122,6 +23349,22 @@ function statementExpressions3(statement) {
|
|
|
23122
23349
|
return null;
|
|
23123
23350
|
}
|
|
23124
23351
|
}
|
|
23352
|
+
function constructionEdit(input, expression, span) {
|
|
23353
|
+
const start = input.source.indexOf(expression.className, span.start);
|
|
23354
|
+
if (start === -1 || start >= span.end) {
|
|
23355
|
+
return null;
|
|
23356
|
+
}
|
|
23357
|
+
const isLibrary2 = input.types.get(expression)?.kind === "record";
|
|
23358
|
+
if (isLibrary2) {
|
|
23359
|
+
return { start: span.start, end: start + expression.className.length, replacement: `${expression.className}.new` };
|
|
23360
|
+
}
|
|
23361
|
+
const spacing = /^[ \t]*/.exec(input.source.slice(start + expression.className.length))?.[0] ?? "";
|
|
23362
|
+
return {
|
|
23363
|
+
start: span.start,
|
|
23364
|
+
end: start + expression.className.length + spacing.length,
|
|
23365
|
+
replacement: `new ${emitString(expression.className)} `
|
|
23366
|
+
};
|
|
23367
|
+
}
|
|
23125
23368
|
function expressionEdits(input, statement) {
|
|
23126
23369
|
const slots = input.development ? statementExpressions3(statement) : null;
|
|
23127
23370
|
if (slots === null) {
|
|
@@ -23134,7 +23377,18 @@ function expressionEdits(input, statement) {
|
|
|
23134
23377
|
const edits = [];
|
|
23135
23378
|
for (const expression of found) {
|
|
23136
23379
|
const span = input.spans.get(expression);
|
|
23137
|
-
if (span === void 0
|
|
23380
|
+
if (span === void 0) {
|
|
23381
|
+
return null;
|
|
23382
|
+
}
|
|
23383
|
+
if (expression.kind === "new-expression") {
|
|
23384
|
+
const edit = constructionEdit(input, expression, span);
|
|
23385
|
+
if (edit === null) {
|
|
23386
|
+
return null;
|
|
23387
|
+
}
|
|
23388
|
+
edits.push(edit);
|
|
23389
|
+
continue;
|
|
23390
|
+
}
|
|
23391
|
+
if (holdsFunction(expression)) {
|
|
23138
23392
|
return null;
|
|
23139
23393
|
}
|
|
23140
23394
|
const state = createEmitState(input.types, input.references, input.generatedMembers, input.staticAccess);
|