Socket
Socket
Sign inDemoInstall

typescript-to-lua

Package Overview
Dependencies
Maintainers
2
Versions
157
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

typescript-to-lua - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

dist/transformation/visitors/language-extensions/pairsIterable.d.ts

12

CHANGELOG.md
# Changelog
## 1.3.0
- Added `LuaPairsIterable` language extension to mark objects as iterable with Lua's `pairs`.
- Added support for properties on functions.
- Unicode is no longer escaped and used as-is for `"luaTarget": "JIT"`.
- Fixed some bugs related to destructuring in loops and function parameters.
- Fixed incorrect global being generated for some `try` statements.
- Fixed some incorrect behavior for `??` and `? :` when generic types were involved.
- Added missing `...` optimization in cases where casts or parentheses are used.
- Fixed a bug for `Promise` when resolving with another Promise. This also fixes some unexpected behavior with `async` which is built with Promises.
- Fixed `async` functions not aborting after returning from a `catch` block.
## 1.2.0

@@ -4,0 +16,0 @@

2

dist/LuaLib.js

@@ -107,3 +107,3 @@ "use strict";

ArrayFlatMap: [LuaLibFeature.ArrayConcat, LuaLibFeature.ArrayIsArray],
Await: [LuaLibFeature.InstanceOf, LuaLibFeature.New],
Await: [LuaLibFeature.InstanceOf, LuaLibFeature.New, LuaLibFeature.Promise],
Decorate: [LuaLibFeature.ObjectGetOwnPropertyDescriptor, LuaLibFeature.SetDescriptor, LuaLibFeature.ObjectAssign],

@@ -110,0 +110,0 @@ DelegatedYield: [LuaLibFeature.StringAccess],

@@ -35,3 +35,3 @@ "use strict";

*/
const isValidLuaFunctionDeclarationName = (str) => /^[a-zA-Z0-9_.]+$/.test(str);
const isValidLuaFunctionDeclarationName = (str, options) => ((0, safe_names_1.shouldAllowUnicode)(options) ? /^[a-zA-Z0-9_\u00FF-\uFFFD.]+$/ : /^[a-zA-Z0-9_.]+$/).test(str);
/**

@@ -298,3 +298,3 @@ * Returns true if expression contains no function calls.

const name = this.printExpression(statement.left[0]);
if (isValidLuaFunctionDeclarationName(name.toString())) {
if (isValidLuaFunctionDeclarationName(name.toString(), this.options)) {
chunks.push(this.printFunctionDefinition(statement));

@@ -499,3 +499,3 @@ return this.createSourceNode(statement, chunks);

if (expression.key) {
if (lua.isStringLiteral(expression.key) && (0, safe_names_1.isValidLuaIdentifier)(expression.key.value)) {
if (lua.isStringLiteral(expression.key) && (0, safe_names_1.isValidLuaIdentifier)(expression.key.value, this.options)) {
chunks.push(expression.key.value, " = ", value);

@@ -572,3 +572,3 @@ }

chunks.push(this.printExpressionInParenthesesIfNeeded(expression.table));
if (lua.isStringLiteral(expression.index) && (0, safe_names_1.isValidLuaIdentifier)(expression.index.value)) {
if (lua.isStringLiteral(expression.index) && (0, safe_names_1.isValidLuaIdentifier)(expression.index.value, this.options)) {
chunks.push(".", this.createSourceNode(expression.index, expression.index.value));

@@ -575,0 +575,0 @@ }

@@ -27,3 +27,3 @@ "use strict";

return lua.createCallExpression(caller, params, node);
default:
case "toString":
context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(expression.name, "function", expressionName));

@@ -46,3 +46,6 @@ }

: nparams;
default:
case "arguments":
case "caller":
case "displayName":
case "name":
context.diagnostics.push((0, diagnostics_1.unsupportedProperty)(node.name, "function", node.name.text));

@@ -49,0 +52,0 @@ }

@@ -31,3 +31,3 @@ "use strict";

}
if ((0, typescript_1.isFunctionType)(context, ownerType)) {
if ((0, typescript_1.isFunctionType)(ownerType)) {
return (0, function_1.transformFunctionProperty)(context, node);

@@ -119,3 +119,3 @@ }

}
if ((0, typescript_1.isFunctionType)(context, ownerType) && (0, typescript_1.hasStandardLibrarySignature)(context, node)) {
if ((0, typescript_1.isFunctionType)(ownerType) && (0, typescript_1.hasStandardLibrarySignature)(context, node)) {
if (isOptionalCall)

@@ -122,0 +122,0 @@ return unsupportedOptionalCall();

@@ -37,2 +37,5 @@ import * as ts from "typescript";

};
export declare const invalidPairsIterableWithoutDestructuring: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {
code: number;
};
export declare const unsupportedAccessorInObjectLiteral: ((node: ts.Node, ...args: any[]) => ts.Diagnostic) & {

@@ -39,0 +42,0 @@ code: number;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unsupportedOptionalCompileMembersOnly = exports.unsupportedBuiltinOptionalCall = exports.awaitMustBeInAsyncFunction = exports.notAllowedOptionalAssignment = exports.annotationDeprecated = exports.annotationRemoved = exports.invalidTableSetExpression = exports.invalidTableDeleteExpression = exports.invalidTableExtensionUse = exports.invalidOperatorMappingUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0;
exports.unsupportedOptionalCompileMembersOnly = exports.unsupportedBuiltinOptionalCall = exports.awaitMustBeInAsyncFunction = exports.notAllowedOptionalAssignment = exports.annotationDeprecated = exports.annotationRemoved = exports.invalidTableSetExpression = exports.invalidTableDeleteExpression = exports.invalidTableExtensionUse = exports.invalidOperatorMappingUse = exports.invalidMultiReturnAccess = exports.invalidMultiTypeToEmptyPatternOrArrayLiteral = exports.invalidMultiTypeToNonArrayLiteral = exports.invalidMultiFunctionReturnType = exports.invalidMultiFunctionUse = exports.unsupportedVarDeclaration = exports.invalidAmbientIdentifierName = exports.unsupportedProperty = exports.unsupportedForTarget = exports.unsupportedRightShiftOperator = exports.unsupportedAccessorInObjectLiteral = exports.invalidPairsIterableWithoutDestructuring = exports.invalidMultiIterableWithoutDestructuring = exports.invalidRangeControlVariable = exports.invalidVarargUse = exports.invalidRangeUse = exports.annotationInvalidArgumentCount = exports.decoratorInvalidContext = exports.unsupportedOverloadAssignment = exports.unsupportedSelfFunctionConversion = exports.unsupportedNoSelfFunctionConversion = exports.forbiddenForIn = exports.unsupportedNodeKind = void 0;
const ts = require("typescript");

@@ -39,2 +39,3 @@ const CompilerOptions_1 = require("../../CompilerOptions");

exports.invalidMultiIterableWithoutDestructuring = createErrorDiagnosticFactory("LuaIterable with a LuaMultiReturn return value type must be destructured.");
exports.invalidPairsIterableWithoutDestructuring = createErrorDiagnosticFactory("LuaPairsIterable type must be destructured in a for...of statement.");
exports.unsupportedAccessorInObjectLiteral = createErrorDiagnosticFactory("Accessors in object literal are not supported.");

@@ -41,0 +42,0 @@ exports.unsupportedRightShiftOperator = createErrorDiagnosticFactory("Right shift operator is not supported for target Lua 5.3. Use `>>>` instead.");

@@ -9,2 +9,3 @@ import * as ts from "typescript";

IterableType = "IterableType",
PairsIterableType = "PairsIterableType",
AdditionOperatorType = "AdditionOperatorType",

@@ -57,2 +58,3 @@ AdditionOperatorMethodType = "AdditionOperatorMethodType",

export declare function isExtensionType(type: ts.Type, extensionKind: ExtensionKind): boolean;
export declare function getExtensionKinds(type: ts.Type): ExtensionKind[];
export declare function isExtensionValue(context: TransformationContext, symbol: ts.Symbol, extensionKind: ExtensionKind): boolean;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isExtensionValue = exports.isExtensionType = exports.ExtensionKind = void 0;
exports.isExtensionValue = exports.getExtensionKinds = exports.isExtensionType = exports.ExtensionKind = void 0;
var ExtensionKind;

@@ -11,2 +11,3 @@ (function (ExtensionKind) {

ExtensionKind["IterableType"] = "IterableType";
ExtensionKind["PairsIterableType"] = "PairsIterableType";
ExtensionKind["AdditionOperatorType"] = "AdditionOperatorType";

@@ -69,2 +70,3 @@ ExtensionKind["AdditionOperatorMethodType"] = "AdditionOperatorMethodType";

[ExtensionKind.IterableType]: "__luaIterableBrand",
[ExtensionKind.PairsIterableType]: "__luaPairsIterableBrand",
[ExtensionKind.AdditionOperatorType]: "__luaAdditionBrand",

@@ -121,2 +123,6 @@ [ExtensionKind.AdditionOperatorMethodType]: "__luaAdditionMethodBrand",

exports.isExtensionType = isExtensionType;
function getExtensionKinds(type) {
return Object.keys(extensionKindToTypeBrand).filter(e => type.getProperty(extensionKindToTypeBrand[e]) !== undefined);
}
exports.getExtensionKinds = getExtensionKinds;
function isExtensionValue(context, symbol, extensionKind) {

@@ -123,0 +129,0 @@ var _a;

@@ -122,3 +122,5 @@ "use strict";

if (context.isModule || !isTopLevelVariable) {
if (!isFunctionDeclaration && hasMultipleReferences(scope, lhs)) {
const isLuaFunctionExpression = rhs && !Array.isArray(rhs) && lua.isFunctionExpression(rhs);
const isSafeRecursiveFunctionDeclaration = isFunctionDeclaration && isLuaFunctionExpression;
if (!isSafeRecursiveFunctionDeclaration && hasMultipleReferences(scope, lhs)) {
// Split declaration and assignment of identifiers that reference themselves in their declaration.

@@ -131,6 +133,4 @@ // Put declaration above preceding statements in case the identifier is referenced in those.

}
if (!isFunctionDeclaration) {
// Remember local variable declarations for hoisting later
(0, scope_1.addScopeVariableDeclaration)(scope, precedingDeclaration);
}
// Remember local variable declarations for hoisting later
(0, scope_1.addScopeVariableDeclaration)(scope, precedingDeclaration);
}

@@ -137,0 +137,0 @@ else {

import * as ts from "typescript";
import { CompilerOptions } from "../..";
import { TransformationContext } from "../context";
export declare const isValidLuaIdentifier: (name: string) => boolean;
export declare const shouldAllowUnicode: (options: CompilerOptions) => boolean;
export declare const isValidLuaIdentifier: (name: string, options: CompilerOptions) => boolean;
export declare const luaKeywords: ReadonlySet<string>;
export declare const isUnsafeName: (name: string) => boolean;
export declare const isUnsafeName: (name: string, options: CompilerOptions) => boolean;
export declare function hasUnsafeSymbolName(context: TransformationContext, symbol: ts.Symbol, tsOriginal: ts.Identifier): boolean;
export declare function hasUnsafeIdentifierName(context: TransformationContext, identifier: ts.Identifier, checkSymbol?: boolean): boolean;
export declare const createSafeName: (name: string) => string;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createSafeName = exports.hasUnsafeIdentifierName = exports.hasUnsafeSymbolName = exports.isUnsafeName = exports.luaKeywords = exports.isValidLuaIdentifier = void 0;
exports.createSafeName = exports.hasUnsafeIdentifierName = exports.hasUnsafeSymbolName = exports.isUnsafeName = exports.luaKeywords = exports.isValidLuaIdentifier = exports.shouldAllowUnicode = void 0;
const __1 = require("../..");
const diagnostics_1 = require("./diagnostics");
const export_1 = require("./export");
const typescript_1 = require("./typescript");
const isValidLuaIdentifier = (name) => !exports.luaKeywords.has(name) && /^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name);
const shouldAllowUnicode = (options) => options.luaTarget === __1.LuaTarget.LuaJIT;
exports.shouldAllowUnicode = shouldAllowUnicode;
const isValidLuaIdentifier = (name, options) => !exports.luaKeywords.has(name) &&
((0, exports.shouldAllowUnicode)(options)
? /^[a-zA-Z_\u007F-\uFFFD][a-zA-Z0-9_\u007F-\uFFFD]*$/
: /^[a-zA-Z_][a-zA-Z0-9_]*$/).test(name);
exports.isValidLuaIdentifier = isValidLuaIdentifier;

@@ -54,6 +60,6 @@ exports.luaKeywords = new Set([

]);
const isUnsafeName = (name) => !(0, exports.isValidLuaIdentifier)(name) || luaBuiltins.has(name);
const isUnsafeName = (name, options) => !(0, exports.isValidLuaIdentifier)(name, options) || luaBuiltins.has(name);
exports.isUnsafeName = isUnsafeName;
function checkName(context, name, node) {
const isInvalid = !(0, exports.isValidLuaIdentifier)(name);
const isInvalid = !(0, exports.isValidLuaIdentifier)(name, context.options);
if (isInvalid) {

@@ -75,3 +81,3 @@ // Empty identifier is a TypeScript error

// only unsafe when non-ambient and not exported
return (0, exports.isUnsafeName)(symbol.name) && !isAmbient && !(0, export_1.isSymbolExported)(context, symbol);
return (0, exports.isUnsafeName)(symbol.name, context.options) && !isAmbient && !(0, export_1.isSymbolExported)(context, symbol);
}

@@ -78,0 +84,0 @@ exports.hasUnsafeSymbolName = hasUnsafeSymbolName;

@@ -12,3 +12,4 @@ import * as ts from "typescript";

Try = 64,
Catch = 128
Catch = 128,
LoopInitializer = 256
}

@@ -15,0 +16,0 @@ interface FunctionDefinitionInfo {

@@ -19,2 +19,3 @@ "use strict";

ScopeType[ScopeType["Catch"] = 128] = "Catch";
ScopeType[ScopeType["LoopInitializer"] = 256] = "LoopInitializer";
})(ScopeType = exports.ScopeType || (exports.ScopeType = {}));

@@ -21,0 +22,0 @@ const scopeStacks = new WeakMap();

@@ -13,2 +13,4 @@ import * as ts from "typescript";

export declare function isArrayType(context: TransformationContext, type: ts.Type): boolean;
export declare function isFunctionType(context: TransformationContext, type: ts.Type): boolean;
export declare function isFunctionType(type: ts.Type): boolean;
export declare function canBeFalsy(context: TransformationContext, type: ts.Type): boolean;
export declare function canBeFalsyWhenNotNull(context: TransformationContext, type: ts.Type): boolean;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isFunctionType = exports.isArrayType = exports.forTypeOrAnySupertype = exports.isNumberType = exports.isStringType = exports.typeCanSatisfy = exports.typeAlwaysSatisfies = exports.isTypeWithFlags = void 0;
exports.canBeFalsyWhenNotNull = exports.canBeFalsy = exports.isFunctionType = exports.isArrayType = exports.forTypeOrAnySupertype = exports.isNumberType = exports.isStringType = exports.typeCanSatisfy = exports.typeAlwaysSatisfies = exports.isTypeWithFlags = void 0;
const ts = require("typescript");
function isTypeWithFlags(context, type, flags) {
const predicate = (type) => {
if (type.symbol) {
const baseConstraint = context.checker.getBaseConstraintOfType(type);
if (baseConstraint && baseConstraint !== type) {
return isTypeWithFlags(context, baseConstraint, flags);
}
}
return (type.flags & flags) !== 0;
};
const predicate = (type) => (type.flags & flags) !== 0;
return typeAlwaysSatisfies(context, type, predicate);

@@ -19,2 +11,6 @@ }

function typeAlwaysSatisfies(context, type, predicate) {
const baseConstraint = context.checker.getBaseConstraintOfType(type);
if (baseConstraint) {
type = baseConstraint;
}
if (predicate(type)) {

@@ -33,2 +29,11 @@ return true;

function typeCanSatisfy(context, type, predicate) {
const baseConstraint = context.checker.getBaseConstraintOfType(type);
if (!baseConstraint) {
// type parameter with no constraint can be anything, assume it might satisfy predicate
if (type.isTypeParameter())
return true;
}
else {
type = baseConstraint;
}
if (predicate(type)) {

@@ -89,7 +94,29 @@ return true;

exports.isArrayType = isArrayType;
function isFunctionType(context, type) {
const typeNode = context.checker.typeToTypeNode(type, undefined, ts.NodeBuilderFlags.InTypeAlias);
return typeNode !== undefined && ts.isFunctionTypeNode(typeNode);
function isFunctionType(type) {
return type.getCallSignatures().length > 0;
}
exports.isFunctionType = isFunctionType;
function canBeFalsy(context, type) {
const strictNullChecks = context.options.strict === true || context.options.strictNullChecks === true;
const falsyFlags = ts.TypeFlags.Boolean |
ts.TypeFlags.BooleanLiteral |
ts.TypeFlags.Never |
ts.TypeFlags.Void |
ts.TypeFlags.Unknown |
ts.TypeFlags.Any |
ts.TypeFlags.Undefined |
ts.TypeFlags.Null;
return typeCanSatisfy(context, type, type => (type.flags & falsyFlags) !== 0 || (!strictNullChecks && !type.isLiteral()));
}
exports.canBeFalsy = canBeFalsy;
function canBeFalsyWhenNotNull(context, type) {
const falsyFlags = ts.TypeFlags.Boolean |
ts.TypeFlags.BooleanLiteral |
ts.TypeFlags.Never |
ts.TypeFlags.Void |
ts.TypeFlags.Unknown |
ts.TypeFlags.Any;
return typeCanSatisfy(context, type, type => (type.flags & falsyFlags) !== 0);
}
exports.canBeFalsyWhenNotNull = canBeFalsyWhenNotNull;
//# sourceMappingURL=types.js.map

@@ -170,5 +170,3 @@ "use strict";

// Check if we can take a shortcut to 'lhs or rhs' if the left-hand side cannot be 'false'.
const typeCanBeFalse = (type) => (type.flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.Boolean)) !== 0 ||
(type.flags & ts.TypeFlags.BooleanLiteral & ts.TypeFlags.PossiblyFalsy) !== 0;
if ((0, typescript_1.typeCanSatisfy)(context, lhsType, typeCanBeFalse)) {
if ((0, typescript_1.canBeFalsyWhenNotNull)(context, lhsType)) {
// reuse logic from case with preceding statements

@@ -175,0 +173,0 @@ const [precedingStatements, result] = createShortCircuitBinaryExpressionPrecedingStatements(context, transformedLeft, transformedRight, [], ts.SyntaxKind.QuestionQuestionToken, node);

@@ -89,3 +89,3 @@ "use strict";

ts.isIdentifier(left.name) &&
(0, safe_names_1.isValidLuaIdentifier)(left.name.text) &&
(0, safe_names_1.isValidLuaIdentifier)(left.name.text, context.options) &&
argPrecedingStatements.length === 0) {

@@ -92,0 +92,0 @@ // table:name()

@@ -73,3 +73,3 @@ "use strict";

let localClassName;
if ((0, safe_names_1.isUnsafeName)(className.text)) {
if ((0, safe_names_1.isUnsafeName)(className.text, context.options)) {
localClassName = lua.createIdentifier((0, safe_names_1.createSafeName)(className.text), undefined, className.symbolId, className.text);

@@ -76,0 +76,0 @@ lua.setNodePosition(localClassName, className);

@@ -9,24 +9,3 @@ "use strict";

const block_1 = require("./block");
function canBeFalsy(context, type) {
const strictNullChecks = context.options.strict === true || context.options.strictNullChecks === true;
const falsyFlags = ts.TypeFlags.Boolean |
ts.TypeFlags.BooleanLiteral |
ts.TypeFlags.Undefined |
ts.TypeFlags.Null |
ts.TypeFlags.Never |
ts.TypeFlags.Void |
ts.TypeFlags.Any;
if (type.flags & falsyFlags) {
return true;
}
else if (!strictNullChecks && !type.isLiteral()) {
return true;
}
else if (type.isUnion()) {
return type.types.some(subType => canBeFalsy(context, subType));
}
else {
return false;
}
}
const typescript_1 = require("../utils/typescript");
function transformProtectedConditionalExpression(context, expression) {

@@ -46,3 +25,3 @@ const tempVar = context.createTempNameForNode(expression.condition);

const transformConditionalExpression = (expression, context) => {
if (canBeFalsy(context, context.checker.getTypeAtLocation(expression.whenTrue))) {
if ((0, typescript_1.canBeFalsy)(context, context.checker.getTypeAtLocation(expression.whenTrue))) {
return transformProtectedConditionalExpression(context, expression);

@@ -49,0 +28,0 @@ }

@@ -15,2 +15,3 @@ "use strict";

const transformTryStatement = (statement, context) => {
var _a;
const [tryBlock, tryScope] = (0, block_1.transformScopeBlock)(context, statement.tryBlock, scope_1.ScopeType.Try);

@@ -38,10 +39,10 @@ if (context.options.luaTarget === __1.LuaTarget.Lua51 && (0, typescript_1.isInAsyncFunction)(statement)) {

: undefined;
const catchParameters = () => (catchParameter ? [lua.cloneIdentifier(catchParameter)] : []);
const catchFunction = lua.createFunctionExpression(catchBlock, catchParameter ? [lua.cloneIdentifier(catchParameter)] : []);
const catchIdentifier = lua.createIdentifier("____catch");
const catchFunction = lua.createFunctionExpression(catchBlock, catchParameters());
result.push(lua.createVariableDeclarationStatement(catchIdentifier, catchFunction));
const hasReturn = (_a = tryScope.functionReturned) !== null && _a !== void 0 ? _a : catchScope.functionReturned;
const tryReturnIdentifiers = [tryResultIdentifier]; // ____try
if (returnedIdentifier) {
tryReturnIdentifiers.push(returnedIdentifier); // ____returned or catch variable
if (tryScope.functionReturned || catchScope.functionReturned) {
if (hasReturn || statement.catchClause.variableDeclaration) {
tryReturnIdentifiers.push(returnedIdentifier); // ____returned
if (hasReturn) {
tryReturnIdentifiers.push(returnValueIdentifier); // ____returnValue

@@ -52,7 +53,8 @@ returnCondition = lua.cloneIdentifier(returnedIdentifier);

result.push(lua.createVariableDeclarationStatement(tryReturnIdentifiers, tryCall));
// Wrap catch in function if try or catch has return
const catchCall = lua.createCallExpression(catchIdentifier, [lua.cloneIdentifier(returnedIdentifier)]);
const catchAssign = lua.createAssignmentStatement([lua.cloneIdentifier(returnedIdentifier), lua.cloneIdentifier(returnValueIdentifier)], catchCall);
const catchCall = lua.createCallExpression(catchIdentifier, statement.catchClause.variableDeclaration ? [lua.cloneIdentifier(returnedIdentifier)] : []);
const catchCallStatement = hasReturn
? lua.createAssignmentStatement([lua.cloneIdentifier(returnedIdentifier), lua.cloneIdentifier(returnValueIdentifier)], catchCall)
: lua.createExpressionStatement(catchCall);
const notTryCondition = lua.createUnaryExpression(tryResultIdentifier, lua.SyntaxKind.NotOperator);
result.push(lua.createIfStatement(notTryCondition, lua.createBlock([catchAssign])));
result.push(lua.createIfStatement(notTryCondition, lua.createBlock([catchCallStatement])));
}

@@ -59,0 +61,0 @@ else if (tryScope.functionReturned) {

@@ -5,2 +5,4 @@ import * as ts from "typescript";

import { Scope } from "../utils/scope";
export declare function createCallableTable(functionExpression: lua.Expression): lua.Expression;
export declare function isFunctionTypeWithProperties(functionType: ts.Type): boolean;
export declare function transformFunctionBodyContent(context: TransformationContext, body: ts.ConciseBody): lua.Statement[];

@@ -7,0 +9,0 @@ export declare function transformFunctionBodyHeader(context: TransformationContext, bodyScope: Scope, parameters: ts.NodeArray<ts.ParameterDeclaration>, spreadIdentifier?: lua.Identifier): lua.Statement[];

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.transformYieldExpression = exports.transformFunctionDeclaration = exports.transformFunctionLikeDeclaration = exports.transformFunctionToExpression = exports.transformParameters = exports.transformFunctionBody = exports.transformFunctionBodyHeader = exports.transformFunctionBodyContent = void 0;
exports.transformYieldExpression = exports.transformFunctionDeclaration = exports.transformFunctionLikeDeclaration = exports.transformFunctionToExpression = exports.transformParameters = exports.transformFunctionBody = exports.transformFunctionBodyHeader = exports.transformFunctionBodyContent = exports.isFunctionTypeWithProperties = exports.createCallableTable = void 0;
const ts = require("typescript");

@@ -11,2 +11,3 @@ const lua = require("../../LuaAST");

const function_context_1 = require("../utils/function-context");
const language_extensions_1 = require("../utils/language-extensions");
const lua_ast_1 = require("../utils/lua-ast");

@@ -16,2 +17,3 @@ const lualib_1 = require("../utils/lualib");

const scope_1 = require("../utils/scope");
const typescript_1 = require("../utils/typescript");
const async_await_1 = require("./async-await");

@@ -38,2 +40,35 @@ const identifier_1 = require("./identifier");

}
function createCallableTable(functionExpression) {
var _a;
// __call metamethod receives the table as the first argument, so we need to add a dummy parameter
if (lua.isFunctionExpression(functionExpression)) {
(_a = functionExpression.params) === null || _a === void 0 ? void 0 : _a.unshift(lua.createAnonymousIdentifier());
}
else {
// functionExpression may have been replaced (lib functions, etc...),
// so we create a forwarding function to eat the extra argument
functionExpression = lua.createFunctionExpression(lua.createBlock([
lua.createReturnStatement([lua.createCallExpression(functionExpression, [lua.createDotsLiteral()])]),
]), [lua.createAnonymousIdentifier()], lua.createDotsLiteral(), lua.FunctionExpressionFlags.Inline);
}
return lua.createCallExpression(lua.createIdentifier("setmetatable"), [
lua.createTableExpression(),
lua.createTableExpression([
lua.createTableFieldExpression(functionExpression, lua.createStringLiteral("__call")),
]),
]);
}
exports.createCallableTable = createCallableTable;
function isFunctionTypeWithProperties(functionType) {
if (functionType.isUnion()) {
return functionType.types.some(isFunctionTypeWithProperties);
}
else {
return ((0, typescript_1.isFunctionType)(functionType) &&
functionType.getProperties().length > 0 &&
(0, language_extensions_1.getExtensionKinds)(functionType).length === 0 // ignore TSTL extension functions like $range
);
}
}
exports.isFunctionTypeWithProperties = isFunctionTypeWithProperties;
function transformFunctionBodyContent(context, body) {

@@ -61,3 +96,5 @@ if (!ts.isBlock(body)) {

// Binding pattern
bindingPatternDeclarations.push(...(0, variable_declaration_1.transformBindingPattern)(context, declaration.name, identifier));
const name = declaration.name;
const [precedingStatements, bindings] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => (0, variable_declaration_1.transformBindingPattern)(context, name, identifier));
bindingPatternDeclarations.push(...precedingStatements, ...bindings);
}

@@ -174,3 +211,11 @@ else if (declaration.initializer !== undefined) {

const nameIdentifier = (0, identifier_1.transformIdentifier)(context, node.name);
context.addPrecedingStatements(lua.createVariableDeclarationStatement(nameIdentifier, functionExpression));
if (isFunctionTypeWithProperties(context.checker.getTypeAtLocation(node))) {
context.addPrecedingStatements([
lua.createVariableDeclarationStatement(nameIdentifier),
lua.createAssignmentStatement(nameIdentifier, createCallableTable(functionExpression)),
]);
}
else {
context.addPrecedingStatements(lua.createVariableDeclarationStatement(nameIdentifier, functionExpression));
}
return lua.cloneIdentifier(nameIdentifier);

@@ -207,3 +252,7 @@ }

}
return (0, lua_ast_1.createLocalOrExportedOrGlobalDeclaration)(context, name, functionExpression, node);
// Wrap functions with properties into a callable table
const wrappedFunction = node.name && isFunctionTypeWithProperties(context.checker.getTypeAtLocation(node.name))
? createCallableTable(functionExpression)
: functionExpression;
return (0, lua_ast_1.createLocalOrExportedOrGlobalDeclaration)(context, name, wrappedFunction, node);
};

@@ -210,0 +259,0 @@ exports.transformFunctionDeclaration = transformFunctionDeclaration;

@@ -11,2 +11,3 @@ "use strict";

const iterable_1 = require("../language-extensions/iterable");
const pairsIterable_1 = require("../language-extensions/pairsIterable");
const range_1 = require("../language-extensions/range");

@@ -37,2 +38,5 @@ const utils_1 = require("./utils");

}
else if ((0, pairsIterable_1.isPairsIterableExpression)(context, node.expression)) {
return (0, pairsIterable_1.transformForOfPairsIterableStatement)(context, node, body);
}
else if ((0, annotations_1.isLuaIteratorType)(context, node.expression)) {

@@ -39,0 +43,0 @@ context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node.expression, annotations_1.AnnotationKind.LuaIterator));

@@ -6,2 +6,3 @@ "use strict";

const lua = require("../../../LuaAST");
const preceding_statements_1 = require("../../utils/preceding-statements");
const scope_1 = require("../../utils/scope");

@@ -38,2 +39,3 @@ const typescript_1 = require("../../utils/typescript");

const valueVariable = lua.createIdentifier("____value");
(0, scope_1.pushScope)(context, scope_1.ScopeType.LoopInitializer);
if (ts.isVariableDeclarationList(initializer)) {

@@ -43,6 +45,8 @@ // Declaration of new variable

if (ts.isArrayBindingPattern(binding) || ts.isObjectBindingPattern(binding)) {
block.statements.unshift(...(0, variable_declaration_1.transformBindingPattern)(context, binding, valueVariable));
const [precedingStatements, bindings] = (0, preceding_statements_1.transformInPrecedingStatementScope)(context, () => (0, variable_declaration_1.transformBindingPattern)(context, binding, valueVariable));
block.statements.unshift(...precedingStatements, ...bindings);
}
else {
// Single variable declared in for loop
(0, scope_1.popScope)(context);
return (0, identifier_1.transformIdentifier)(context, binding);

@@ -57,2 +61,3 @@ }

}
(0, scope_1.popScope)(context);
return valueVariable;

@@ -59,0 +64,0 @@ }

@@ -16,3 +16,3 @@ "use strict";

const moduleSymbol = context.checker.getSymbolAtLocation(declaration.name);
if (moduleSymbol !== undefined && (0, safe_names_1.isUnsafeName)(moduleSymbol.name)) {
if (moduleSymbol !== undefined && (0, safe_names_1.isUnsafeName)(moduleSymbol.name, context.options)) {
return lua.createIdentifier((0, safe_names_1.createSafeName)(declaration.name.text), declaration.name, moduleSymbol && (0, symbols_1.getSymbolIdOfSymbol)(context, moduleSymbol), declaration.name.text);

@@ -19,0 +19,0 @@ }

@@ -14,5 +14,11 @@ "use strict";

const vararg_1 = require("./language-extensions/vararg");
function skipOuterExpressionParents(node) {
while (ts.isOuterExpression(node)) {
node = node.parent;
}
return node;
}
function isOptimizedVarArgSpread(context, symbol, identifier) {
var _a;
if (!ts.isSpreadElement(identifier.parent)) {
if (!ts.isSpreadElement(skipOuterExpressionParents(identifier.parent))) {
return false;

@@ -55,8 +61,9 @@ }

const transformSpreadElement = (node, context) => {
if (ts.isIdentifier(node.expression)) {
if ((0, annotations_1.isVarargType)(context, node.expression)) {
const tsInnerExpression = ts.skipOuterExpressions(node.expression);
if (ts.isIdentifier(tsInnerExpression)) {
if ((0, annotations_1.isVarargType)(context, tsInnerExpression)) {
context.diagnostics.push((0, diagnostics_1.annotationRemoved)(node, annotations_1.AnnotationKind.Vararg));
}
const symbol = context.checker.getSymbolAtLocation(node.expression);
if (symbol && isOptimizedVarArgSpread(context, symbol, node.expression)) {
const symbol = context.checker.getSymbolAtLocation(tsInnerExpression);
if (symbol && isOptimizedVarArgSpread(context, symbol, tsInnerExpression)) {
return lua.createDotsLiteral(node);

@@ -66,5 +73,5 @@ }

const innerExpression = context.transformExpression(node.expression);
if ((0, multi_1.isMultiReturnCall)(context, node.expression))
if ((0, multi_1.isMultiReturnCall)(context, tsInnerExpression))
return innerExpression;
const type = context.checker.getTypeAtLocation(node.expression);
const type = context.checker.getTypeAtLocation(node.expression); // not ts-inner expression, in case of casts
if ((0, typescript_1.isArrayType)(context, type)) {

@@ -71,0 +78,0 @@ return (0, lua_ast_1.createUnpackCall)(context, innerExpression, node);

@@ -13,2 +13,3 @@ "use strict";

const preceding_statements_1 = require("../utils/preceding-statements");
const function_1 = require("./function");
const identifier_1 = require("./identifier");

@@ -187,3 +188,11 @@ const multi_1 = require("./language-extensions/multi");

const value = statement.initializer && context.transformExpression(statement.initializer);
return (0, lua_ast_1.createLocalOrExportedOrGlobalDeclaration)(context, identifierName, value, statement);
// Wrap functions being assigned to a type that contains additional properties in a callable table
// This catches 'const foo = function() {}; foo.bar = "FOOBAR";'
const wrappedValue = value &&
// Skip named function expressions because they will have been wrapped already
!(statement.initializer && ts.isFunctionExpression(statement.initializer) && statement.initializer.name) &&
(0, function_1.isFunctionTypeWithProperties)(context.checker.getTypeAtLocation(statement.name))
? (0, function_1.createCallableTable)(value)
: value;
return (0, lua_ast_1.createLocalOrExportedOrGlobalDeclaration)(context, identifierName, wrappedValue, statement);
}

@@ -190,0 +199,0 @@ else if (ts.isArrayBindingPattern(statement.name) || ts.isObjectBindingPattern(statement.name)) {

@@ -82,2 +82,12 @@ type AnyTable = Record<any, any>;

/**
* Represents an object that can be iterated with pairs()
* For more information see: https://typescripttolua.github.io/docs/advanced/language-extensions
*
* @param TKey The type of the key returned each iteration.
* @param TValue The type of the value returned each iteration.
*/
declare type LuaPairsIterable<TKey extends AnyNotNil, TValue> = Iterable<[TKey, TValue]> &
LuaExtension<"__luaPairsIterableBrand">;
/**
* Calls to functions with this type are translated to `left + right`.

@@ -539,3 +549,3 @@ * For more information see: https://typescripttolua.github.io/docs/advanced/language-extensions

*/
declare interface LuaTable<TKey extends AnyNotNil = AnyNotNil, TValue = any> {
declare interface LuaTable<TKey extends AnyNotNil = AnyNotNil, TValue = any> extends LuaPairsIterable<TKey, TValue> {
length: LuaLengthMethod<number>;

@@ -542,0 +552,0 @@ get: LuaTableGetMethod<TKey, TValue>;

{
"name": "typescript-to-lua",
"version": "1.2.0",
"version": "1.3.0",
"description": "A generic TypeScript to Lua transpiler. Write your code in TypeScript and publish Lua!",

@@ -5,0 +5,0 @@ "repository": "https://github.com/TypeScriptToLua/TypeScriptToLua",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc