diff --git a/ts2panda/scripts/generate_js_bytecode.py b/ts2panda/scripts/generate_js_bytecode.py index f0935d561559137caad712d42d7527a8180853b8..2e7949cda3a523410e4b0d7d8d15d182df4a41f0 100755 --- a/ts2panda/scripts/generate_js_bytecode.py +++ b/ts2panda/scripts/generate_js_bytecode.py @@ -44,6 +44,8 @@ def parse_args(): help='whether is commonjs') parser.add_argument("--q", action='store_true', help='whether is d.ts') + parser.add_argument("--b", action='store_true', + help='enable builtin types recognition for .d.ts files') parser.add_argument("--functionSourceCode", action='store_true', help='compile abc with function sourcecode info') arguments = parser.parse_args() @@ -94,8 +96,10 @@ def gen_abc_info(input_arguments): cmd.insert(5, '-c') if input_arguments.q: cmd.insert(6, '-q') + if input_arguments.b: + cmd.insert(7, '-b') if input_arguments.functionSourceCode: - cmd.insert(7, '--function-sourcecode') + cmd.insert(8, '--function-sourcecode') run_command(cmd, path) diff --git a/ts2panda/src/base/typeSystem.ts b/ts2panda/src/base/typeSystem.ts index 380dbba1b147f6d997660f36a585e9792d36f957..3920efbff3ce2a552a88140c78ca4544399facb7 100644 --- a/ts2panda/src/base/typeSystem.ts +++ b/ts2panda/src/base/typeSystem.ts @@ -18,11 +18,13 @@ import * as jshelpers from "../jshelpers"; import { PandaGen } from "../pandagen"; import { TypeChecker } from "../typeChecker"; import { TypeRecorder } from "../typeRecorder"; +import { isGlobalDeclare } from "../strictMode"; import { Literal, LiteralBuffer, LiteralTag } from "./literal"; +import { CmdOptions } from "../cmdOptions"; export enum PrimitiveType { ANY, @@ -34,9 +36,76 @@ export enum PrimitiveType { NULL, UNDEFINED, INT, - _LENGTH = 50 } +export enum BuiltinType { + _HEAD = 20, + Function, + RangeError, + Error, + Object, + SyntaxError, + TypeError, + ReferenceError, + URIError, + Symbol, + EvalError, + Number, + parseFloat, + Date, + Boolean, + BigInt, + parseInt, + WeakMap, + RegExp, + Set, + Map, + WeakRef, + WeakSet, + FinalizationRegistry, + Array, + Uint8ClampedArray, + Uint8Array, + TypedArray, + Int8Array, + Uint16Array, + Uint32Array, + Int16Array, + Int32Array, + Float32Array, + Float64Array, + BigInt64Array, + BigUint64Array, + SharedArrayBuffer, + DataView, + String, + ArrayBuffer, + eval, + isFinite, + ArkPrivate, + print, + decodeURI, + decodeURIComponent, + isNaN, + encodeURI, + NaN, + globalThis, + encodeURIComponent, + Infinity, + Math, + JSON, + Atomics, + undefined, + Reflect, + Promise, + Proxy, + GeneratorFunction, + Intl, +} + +export const userDefinedTypeStartIndex = 100; +let literalBufferIndexShift = userDefinedTypeStartIndex; + export enum L2Type { _COUNTER, CLASS, @@ -46,17 +115,20 @@ export enum L2Type { ARRAY, OBJECT, EXTERNAL, - INTERFACE + INTERFACE, + BUILTINCONTAINER } + export enum ModifierAbstract { NONABSTRACT, ABSTRACT } -export enum ModifierStatic { - NONSTATIC, - STATIC +export enum Modifier { + STATIC = 4, + ASYNC = 8, + ASTERISK = 16 } export enum ModifierReadonly { @@ -106,6 +178,23 @@ export abstract class BaseType { PandaGen.setTypeArrayBuffer(type, index); } + protected calculateIndex(builtinTypeIdx) { + let typeIndex: number; + let shiftedTypeIndex: number; + let recordBuiltin = builtinTypeIdx && CmdOptions.needRecordBuiltinDtsType(); + if (recordBuiltin) { + typeIndex = undefined; + shiftedTypeIndex = builtinTypeIdx; + if (isGlobalDeclare()) { + typeIndex = builtinTypeIdx - BuiltinType._HEAD; + } + } else { + typeIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); + shiftedTypeIndex = typeIndex + literalBufferIndexShift; + } + return {typeIndex: typeIndex, shiftedTypeIndex: shiftedTypeIndex}; + } + } export class PlaceHolderType extends BaseType { @@ -121,6 +210,13 @@ export class TypeSummary extends BaseType { constructor() { super(); this.preservedIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); + if (isGlobalDeclare()) { + let builtinTypeSlotNum = userDefinedTypeStartIndex - BuiltinType._HEAD; + for (let i = 0; i < builtinTypeSlotNum; i++) { + this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); + } + literalBufferIndexShift = BuiltinType._HEAD; + } } public setInfo(userDefinedClassNum: number, anonymousRedirect: Array) { @@ -137,7 +233,11 @@ export class TypeSummary extends BaseType { let countBuf = new LiteralBuffer(); let summaryLiterals: Array = new Array(); summaryLiterals.push(new Literal(LiteralTag.INTEGER, L2Type._COUNTER)); - summaryLiterals.push(new Literal(LiteralTag.INTEGER, this.userDefinedClassNum)); + let definedTypeNum = this.userDefinedClassNum; + if (isGlobalDeclare()) { + definedTypeNum += userDefinedTypeStartIndex - BuiltinType._HEAD; + } + summaryLiterals.push(new Literal(LiteralTag.INTEGER, definedTypeNum)); summaryLiterals.push(new Literal(LiteralTag.INTEGER, this.anonymousRedirect.length)); for (let element of this.anonymousRedirect) { summaryLiterals.push(new Literal(LiteralTag.STRING, element)); @@ -159,17 +259,22 @@ export class ClassType extends BaseType { typeIndex: number; shiftedTypeIndex: number; - constructor(classNode: ts.ClassDeclaration | ts.ClassExpression) { + constructor(classNode: ts.ClassDeclaration | ts.ClassExpression, builtinTypeIdx: number = undefined) { super(); - this.typeIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + let res = this.calculateIndex(builtinTypeIdx); + this.typeIndex = res.typeIndex; + this.shiftedTypeIndex = res.shiftedTypeIndex; + // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type this.addCurrentType(classNode, this.shiftedTypeIndex); this.fillInModifiers(classNode); this.fillInHeritages(classNode); this.fillInFieldsAndMethods(classNode); - this.setTypeArrayBuffer(this, this.typeIndex); + + if (!builtinTypeIdx || isGlobalDeclare()) { + this.setTypeArrayBuffer(this, this.typeIndex); + } } private fillInModifiers(node: ts.ClassDeclaration | ts.ClassExpression) { @@ -290,6 +395,9 @@ export class ClassType extends BaseType { } transfer2LiteralBuffer() { + if (!this.typeIndex) { + return; + } let classTypeBuf = new LiteralBuffer(); let classTypeLiterals: Array = new Array(); // the first element is to determine the L2 type @@ -345,7 +453,7 @@ export class ClassInstType extends BaseType { super(); this.shiftedReferredClassIndex = referredClassIndex; this.typeIndex = this.getIndexFromTypeArrayBuffer(this); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + this.shiftedTypeIndex = this.typeIndex + literalBufferIndexShift; this.typeRecorder.setClass2InstanceMap(this.shiftedReferredClassIndex, this.shiftedTypeIndex); } @@ -363,17 +471,20 @@ export class ClassInstType extends BaseType { export class FunctionType extends BaseType { name: string = ''; - accessFlag: number = AccessFlag.PUBLIC; // 0 -> public -> 0, private -> 1, protected -> 2 - modifierStatic: number = ModifierStatic.NONSTATIC; // 0 -> unstatic, 1 -> static + accessFlag: number = AccessFlag.PUBLIC; // 0 -> public, 1 -> private, 2 -> protected + modifiers: number = 0; // 0 -> non-static, 4 -> static, 8 -> async, 16-> asterisk + containThisParam: boolean = false; parameters: Array = new Array(); returnType: number = PrimitiveType.ANY; typeIndex: number; shiftedTypeIndex: number; - constructor(funcNode: ts.FunctionLikeDeclaration | ts.MethodSignature) { + constructor(funcNode: ts.FunctionLikeDeclaration | ts.MethodSignature, builtinTypeIdx: number = undefined) { super(); - this.typeIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + let res = this.calculateIndex(builtinTypeIdx); + this.typeIndex = res.typeIndex; + this.shiftedTypeIndex = res.shiftedTypeIndex; + // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type this.addCurrentType(funcNode, this.shiftedTypeIndex); @@ -406,7 +517,11 @@ export class FunctionType extends BaseType { break; } case ts.SyntaxKind.StaticKeyword: { - this.modifierStatic = ModifierStatic.STATIC; + this.modifiers = Modifier.STATIC; + break; + } + case ts.SyntaxKind.AsyncKeyword: { + this.modifiers += Modifier.ASYNC; break; } default: @@ -414,6 +529,10 @@ export class FunctionType extends BaseType { } } } + + if (!ts.isMethodSignature(node) && node.asteriskToken) { + this.modifiers += Modifier.ASTERISK; + } } private fillInParameters(node: ts.FunctionLikeDeclaration | ts.MethodSignature) { @@ -423,6 +542,9 @@ export class FunctionType extends BaseType { let variableNode = parameter.name; let typeIndex = this.getOrCreateRecordForTypeNode(typeNode, variableNode); this.parameters.push(typeIndex); + if (variableNode.getFullText() == 'this') { + this.containThisParam = true; + } } } } @@ -434,20 +556,29 @@ export class FunctionType extends BaseType { } getModifier() { - return this.modifierStatic; + return this.modifiers; } transfer2LiteralBuffer(): LiteralBuffer { let funcTypeBuf = new LiteralBuffer(); let funcTypeLiterals: Array = new Array(); funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.FUNCTION)); - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.accessFlag)); - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.modifierStatic)); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.accessFlag + this.modifiers)); funcTypeLiterals.push(new Literal(LiteralTag.STRING, this.name)); - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length)); - this.parameters.forEach((type) => { - funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); - }); + if (this.containThisParam) { + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, 1)); // marker for having 'this' param + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters[0])); + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length - 1)); + for (let i = 1; i < this.parameters.length; i++) { + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters[i])); + } + } else { + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, 0)); // marker for not having 'this' param + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters.length)); + for (let i = 0; i < this.parameters.length; i++) { + funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.parameters[i])); + } + } funcTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.returnType)); funcTypeBuf.addLiterals(...funcTypeLiterals); @@ -464,7 +595,7 @@ export class ExternalType extends BaseType { super(); this.fullRedirectNath = `#${importName}#${redirectPath}`; this.typeIndex = this.getIndexFromTypeArrayBuffer(this); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + this.shiftedTypeIndex = this.typeIndex + literalBufferIndexShift; } transfer2LiteralBuffer(): LiteralBuffer { @@ -494,7 +625,7 @@ export class UnionType extends BaseType { return; } this.typeIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + this.shiftedTypeIndex = this.typeIndex + literalBufferIndexShift; this.fillInUnionArray(typeNode, this.unionedTypeArray); this.setUnionTypeMap(unionStr, this.shiftedTypeIndex); this.setTypeArrayBuffer(this, this.typeIndex); @@ -549,7 +680,7 @@ export class ArrayType extends BaseType { this.shiftedTypeIndex = this.getFromArrayTypeMap(this.referedTypeIndex)!; } else { this.typeIndex = this.getIndexFromTypeArrayBuffer(this); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + this.shiftedTypeIndex = this.typeIndex + literalBufferIndexShift; this.setTypeArrayBuffer(this, this.typeIndex); this.setArrayTypeMap(this.referedTypeIndex, this.shiftedTypeIndex); } @@ -585,7 +716,7 @@ export class ObjectType extends BaseType { constructor(objNode: ts.TypeLiteralNode) { super(); this.typeIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + this.shiftedTypeIndex = this.typeIndex + literalBufferIndexShift; this.fillInMembers(objNode); this.setTypeArrayBuffer(this, this.typeIndex); } @@ -624,7 +755,7 @@ export class InterfaceType extends BaseType { constructor(interfaceNode: ts.InterfaceDeclaration) { super(); this.typeIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); - this.shiftedTypeIndex = this.typeIndex + PrimitiveType._LENGTH; + this.shiftedTypeIndex = this.typeIndex + literalBufferIndexShift; // record type before its initialization, so its index can be recorded // in case there's recursive reference of this type this.addCurrentType(interfaceNode, this.shiftedTypeIndex); @@ -748,3 +879,37 @@ export class InterfaceType extends BaseType { }); } } + +export class BuiltinContainerType extends BaseType { + containerArray: Array = []; + builtinTypeIndex: number; + typeIndex: number = PrimitiveType.ANY; + shiftedTypeIndex: number = PrimitiveType.ANY; + + constructor(builtinContainerSignature: object) { + super(); + this.typeIndex = this.getIndexFromTypeArrayBuffer(new PlaceHolderType()); + this.shiftedTypeIndex = this.typeIndex + literalBufferIndexShift; + this.builtinTypeIndex = builtinContainerSignature['typeIndex']; + this.containerArray = builtinContainerSignature['typeArgIdxs']; + this.setBuiltinContainer2InstanceMap(builtinContainerSignature, this.shiftedTypeIndex); + this.setTypeArrayBuffer(this, this.typeIndex); + } + + setBuiltinContainer2InstanceMap(builtinContainerSignature: object, index: number) { + return this.typeRecorder.setBuiltinContainer2InstanceMap(builtinContainerSignature, index); + } + + transfer2LiteralBuffer(): LiteralBuffer { + let UnionTypeBuf = new LiteralBuffer(); + let UnionTypeLiterals: Array = new Array(); + UnionTypeLiterals.push(new Literal(LiteralTag.INTEGER, L2Type.BUILTINCONTAINER)); + UnionTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.builtinTypeIndex)); + UnionTypeLiterals.push(new Literal(LiteralTag.INTEGER, this.containerArray.length)); + for (let type of this.containerArray) { + UnionTypeLiterals.push(new Literal(LiteralTag.INTEGER, type)); + } + UnionTypeBuf.addLiterals(...UnionTypeLiterals); + return UnionTypeBuf; + } +} \ No newline at end of file diff --git a/ts2panda/src/cmdOptions.ts b/ts2panda/src/cmdOptions.ts index 521bed07aa9125230544ef059713d4a361401dfb..cfe721a32cf5840b1b866acc8d19436a70de8586 100644 --- a/ts2panda/src/cmdOptions.ts +++ b/ts2panda/src/cmdOptions.ts @@ -43,6 +43,7 @@ const ts2pandaOptions = [ { name: 'included-files', alias: 'i', type: String, lazyMultiple: true, defaultValue: [], description: "The list of dependent files." }, { name: 'record-type', alias: 'p', type: Boolean, defaultValue: false, description: "Record type info. Default: true" }, { name: 'dts-type-record', alias: 'q', type: Boolean, defaultValue: false, description: "Record type info for .d.ts files. Default: false" }, + { name: 'dts-builtin-type-record', alias: 'b', type: Boolean, defaultValue: false, description: "Recognize builtin types for .d.ts files. Default: false" }, { name: 'debug-type', alias: 'g', type: Boolean, defaultValue: false, description: "Print type-related log. Default: false" }, { name: 'output-type', type: Boolean, defaultValue: false, description: "set output type."}, { name: 'display-typeinfo', type: Boolean, defaultValue: false, description: "Display typeinfo of pairs of instruction orders and types when enable-typeinfo is true" }, @@ -280,6 +281,13 @@ export class CmdOptions { return this.options["dts-type-record"]; } + static needRecordBuiltinDtsType(): boolean { + if (!this.options) { + return false; + } + return this.options["dts-builtin-type-record"]; + } + static enableTypeLog(): boolean { if (!this.options) { return false; diff --git a/ts2panda/src/ts2panda.ts b/ts2panda/src/ts2panda.ts index 2bd1bc846d8617f1ca8508acb914b01d9fa421e8..384f5fb0dc27feff742140de28ab6f0698baa389 100644 --- a/ts2panda/src/ts2panda.ts +++ b/ts2panda/src/ts2panda.ts @@ -50,6 +50,7 @@ import { ModuleScope } from "./scope"; import { getRecordTypeFlag } from "./base/util"; import { TypeSummary } from "./base/typeSystem"; import { TypeRecorder } from "./typeRecorder"; +import { isGlobalDeclare } from "./strictMode"; const dollarSign: RegExp = /\$/g; @@ -195,7 +196,8 @@ export class Ts2Panda { "log_enabled": CmdOptions.isEnableDebugLog(), "opt_level": CmdOptions.getOptLevel(), "opt_log_level": CmdOptions.getOptLogLevel(), - "display_typeinfo": CmdOptions.getDisplayTypeinfo() + "display_typeinfo": CmdOptions.getDisplayTypeinfo(), + "is_dts_file": isGlobalDeclare() }; let jsonOpt = JSON.stringify(options, null, 2); jsonOpt = "$" + jsonOpt.replace(dollarSign, '#$') + "$"; diff --git a/ts2panda/src/typeChecker.ts b/ts2panda/src/typeChecker.ts index cfec7328d8eb176d595f888d2407d2f890858bda..420c8b482bf4be74024024b158ab3faec6a1ccd3 100644 --- a/ts2panda/src/typeChecker.ts +++ b/ts2panda/src/typeChecker.ts @@ -16,6 +16,8 @@ import * as ts from "typescript"; import { ArrayType, + BuiltinContainerType, + BuiltinType, ClassInstType, ClassType, ExternalType, @@ -224,13 +226,66 @@ export class TypeChecker { } } + isBuiltinType(expr: ts.NewExpression) { + let name = expr.expression.getFullText().replace(/\s/g, ""); + return name in BuiltinType; + } + + getOrCreateInstanceTypeForBuiltin(builtinIdx: number) { + let typeRec = TypeRecorder.getInstance(); + if (typeRec.hasClass2InstanceMap(builtinIdx)) { + return typeRec.getClass2InstanceMap(builtinIdx); + } + let instanceType = new ClassInstType(builtinIdx); + return instanceType.shiftedTypeIndex; + } + + getOrCreateInstanceTypeForBuiltinContainer(builtinContainerSignature: object) { + let typeRec = TypeRecorder.getInstance(); + if (typeRec.hasBuiltinContainer2InstanceMap(builtinContainerSignature)) { + return typeRec.getBuiltinContainer2InstanceMap(builtinContainerSignature); + } + let builtinContainerType = new BuiltinContainerType(builtinContainerSignature); + let builtinContainerTypeIdx = builtinContainerType.shiftedTypeIndex; + if (typeRec.hasClass2InstanceMap(builtinContainerTypeIdx)) { + return typeRec.getClass2InstanceMap(builtinContainerTypeIdx); + } + let instanceType = new ClassInstType(builtinContainerTypeIdx); + return instanceType.shiftedTypeIndex; + } + + getBuiltinTypeIndex(expr: ts.NewExpression) { + let origExprNode = ts.getOriginalNode(expr); + let name = origExprNode.expression.getFullText().replace(/\s/g, ""); + let typeArguments = origExprNode.typeArguments; + if (typeArguments) { + let typeArgIdxs = new Array(); + for(let typeArg of typeArguments) { + let typeArgIdx = this.getOrCreateRecordForTypeNode(typeArg); + typeArgIdxs.push(typeArgIdx); + } + let builtinContainerSignature = { + "typeIndex": BuiltinType[name], + "typeArgIdxs": typeArgIdxs + } + return this.getOrCreateInstanceTypeForBuiltinContainer(builtinContainerSignature); + } + return this.getOrCreateInstanceTypeForBuiltin(BuiltinType[name]); + } + public getOrCreateRecordForDeclNode(initializer: ts.Node | undefined, variableNode?: ts.Node) { if (!initializer) { return PrimitiveType.ANY; } + let typeIndex = PrimitiveType.ANY; - let declNode = this.getDeclNodeForInitializer(initializer); - typeIndex = this.getTypeFromDecl(declNode, initializer.kind == ts.SyntaxKind.NewExpression); + if (initializer.kind == ts.SyntaxKind.NewExpression && this.isBuiltinType(initializer)) { + typeIndex = this.getBuiltinTypeIndex(initializer); + } else { + let declNode = this.getDeclNodeForInitializer(initializer); + typeIndex = this.getTypeFromDecl(declNode, initializer.kind == ts.SyntaxKind.NewExpression); + } + if (variableNode) { TypeRecorder.getInstance().setVariable2Type(variableNode, typeIndex); } @@ -272,17 +327,19 @@ export class TypeChecker { } public formatClassDeclaration(classDeclNode: ts.ClassDeclaration) { - let classType = new ClassType(classDeclNode); - let typeIndex = classType.shiftedTypeIndex; - let className = classDeclNode.name; - let exportedName = "default"; - if (className) { - exportedName = jshelpers.getTextOfIdentifierOrLiteral(className); + let classNameNode = classDeclNode.name; + let className = "default"; + if (classNameNode) { + className = jshelpers.getTextOfIdentifierOrLiteral(classNameNode).replace(/\s/g, ""); } + + let classType = new ClassType(classDeclNode, BuiltinType[className]); + let typeIndex = classType.shiftedTypeIndex; + if (this.hasExportKeyword(classDeclNode)) { - TypeRecorder.getInstance().setExportedType(exportedName, typeIndex); + TypeRecorder.getInstance().setExportedType(className, typeIndex); } else if (this.hasDeclareKeyword(classDeclNode) && isGlobalDeclare()) { - TypeRecorder.getInstance().setDeclaredType(exportedName, typeIndex); + TypeRecorder.getInstance().setDeclaredType(className, typeIndex); } } @@ -299,17 +356,17 @@ export class TypeChecker { case ts.SyntaxKind.FunctionDeclaration: let functionDeclNode = ts.getOriginalNode(node); let functionName = functionDeclNode.name ? functionDeclNode.name : undefined; - let funcType = new FunctionType(functionDeclNode); + let nameText = jshelpers.getTextOfIdentifierOrLiteral(functionName); + let funcType = new FunctionType(functionDeclNode, BuiltinType[nameText]); if (functionName) { TypeRecorder.getInstance().setVariable2Type(functionName, funcType.shiftedTypeIndex); } break; case ts.SyntaxKind.ClassDeclaration: - // Create the type if it is exported or declared. Otherwise, waite until it gets instantiated + // Create the type if it is exported or declared. If not, also create type in case there's + // static property access of this class. let classDeclNode = ts.getOriginalNode(node); - if (this.hasExportKeyword(node) || this.hasDeclareKeyword(node)) { - this.formatClassDeclaration(classDeclNode); - } + this.formatClassDeclaration(classDeclNode); break; case ts.SyntaxKind.InterfaceDeclaration: if (isGlobalDeclare()) { diff --git a/ts2panda/src/typeRecorder.ts b/ts2panda/src/typeRecorder.ts index 4c836e391a3afb00b7d1ac36100f59e4948edb2a..3baff2ea18cd76bffe36bd63a1596f7a81c6f964 100644 --- a/ts2panda/src/typeRecorder.ts +++ b/ts2panda/src/typeRecorder.ts @@ -15,7 +15,7 @@ import * as ts from "typescript"; import { - ExternalType, PrimitiveType, TypeSummary + ExternalType, PrimitiveType, TypeSummary, userDefinedTypeStartIndex } from "./base/typeSystem"; import * as jshelpers from "./jshelpers"; import { ModuleStmt } from "./modules"; @@ -28,6 +28,7 @@ export class TypeRecorder { private userDefinedTypeSet: Set = new Set();; private typeSummary: TypeSummary = new TypeSummary(); private class2InstanceMap: Map = new Map(); + private builtinContainer2InstanceMap: Map = new Map(); private arrayTypeMap: Map = new Map(); private unionTypeMap: Map = new Map(); private exportedType: Map = new Map(); @@ -67,12 +68,14 @@ export class TypeRecorder { public addType2Index(typeNode: ts.Node, index: number) { this.type2Index.set(typeNode, index); - this.addUserDefinedTypeSet(index); + if (index > userDefinedTypeStartIndex) { + this.addUserDefinedTypeSet(index); + } } public setVariable2Type(variableNode: ts.Node, index: number) { this.variable2Type.set(variableNode, index); - if (index > PrimitiveType._LENGTH) { + if (index > userDefinedTypeStartIndex) { this.addUserDefinedTypeSet(index); } } @@ -133,6 +136,18 @@ export class TypeRecorder { return this.class2InstanceMap.get(classIndex); } + public setBuiltinContainer2InstanceMap(builtinContainer: object, instanceIndex: number) { + this.builtinContainer2InstanceMap.set(builtinContainer, instanceIndex) + } + + public hasBuiltinContainer2InstanceMap(builtinContainer: object) { + return this.builtinContainer2InstanceMap.has(builtinContainer); + } + + public getBuiltinContainer2InstanceMap(builtinContainer: object) { + return this.builtinContainer2InstanceMap.get(builtinContainer); + } + // exported/imported public addImportedType(moduleStmt: ModuleStmt) { moduleStmt.getBindingNodeMap().forEach((externalNode, localNode) => { diff --git a/ts2panda/tests/types/array.test.ts b/ts2panda/tests/types/array.test.ts index 5d7fde32276d983c54a57d062534ece53ea45e99..edaf90fdfa928ace5bac50f93c05acbf4c9932ed 100644 --- a/ts2panda/tests/types/array.test.ts +++ b/ts2panda/tests/types/array.test.ts @@ -22,9 +22,9 @@ import { createVRegTypePair, compareVReg2Type } from "./typeUtils"; -import { PrimitiveType } from '../../src/base/typeSystem'; +import { userDefinedTypeStartIndex } from '../../src/base/typeSystem'; -let shift = PrimitiveType._LENGTH; +let shift = userDefinedTypeStartIndex; describe("array tests in array.test.ts", function() { it("test array with primitives", function() { diff --git a/ts2panda/tests/types/class.test.ts b/ts2panda/tests/types/class.test.ts index 9c536133ce2f70d759502ea49611a0b8eed65bed..adabe5ebf72eadafb17f921c6fff13403235974d 100644 --- a/ts2panda/tests/types/class.test.ts +++ b/ts2panda/tests/types/class.test.ts @@ -22,9 +22,9 @@ import { createVRegTypePair, compareVReg2Type } from "./typeUtils"; -import { PrimitiveType } from '../../src/base/typeSystem'; +import { userDefinedTypeStartIndex } from '../../src/base/typeSystem'; -let shift = PrimitiveType._LENGTH; +let shift = userDefinedTypeStartIndex; describe("class tests in class.test.ts", function () { it("test class with no parameter in block", function () { diff --git a/ts2panda/tests/types/function.test.ts b/ts2panda/tests/types/function.test.ts index 70a41faf6c21e3215ccf1acafa9c8e20c109f830..2e4d0bfbe3ba24614dc1bef7060f73347ad8b0e3 100644 --- a/ts2panda/tests/types/function.test.ts +++ b/ts2panda/tests/types/function.test.ts @@ -22,9 +22,9 @@ import { createVRegTypePair, compareVReg2Type } from "./typeUtils"; -import { PrimitiveType } from '../../src/base/typeSystem'; +import { userDefinedTypeStartIndex } from '../../src/base/typeSystem'; -let shift = PrimitiveType._LENGTH; +let shift = userDefinedTypeStartIndex; describe("function tests in function.test.ts", function () { it("test function with no parameter", function () { diff --git a/ts2panda/tests/types/object.test.ts b/ts2panda/tests/types/object.test.ts index 7657bacb7e100a9a2143b49b513a5b172b542282..e790b85a56ff4614d98cf6d5e72d52aa7a1b15b8 100644 --- a/ts2panda/tests/types/object.test.ts +++ b/ts2panda/tests/types/object.test.ts @@ -22,9 +22,9 @@ import { createVRegTypePair, compareVReg2Type } from "./typeUtils"; -import { PrimitiveType } from '../../src/base/typeSystem'; +import { userDefinedTypeStartIndex } from '../../src/base/typeSystem'; -let shift = PrimitiveType._LENGTH; +let shift = userDefinedTypeStartIndex; describe("object tests in object.test.ts", function() { it("test object with primitives", function() { diff --git a/ts2panda/tests/types/primitives.test.ts b/ts2panda/tests/types/primitives.test.ts index 4a02b2e12d12009c9c79360a35c31c3851fd0736..d05b7c1ba2b25665ec77173c11029d61673b0af0 100644 --- a/ts2panda/tests/types/primitives.test.ts +++ b/ts2panda/tests/types/primitives.test.ts @@ -22,9 +22,9 @@ import { createVRegTypePair, compareVReg2Type } from "./typeUtils"; -import { PrimitiveType } from '../../src/base/typeSystem'; +import { userDefinedTypeStartIndex } from '../../src/base/typeSystem'; -let shift = PrimitiveType._LENGTH; +let shift = userDefinedTypeStartIndex; describe("primitives tests in primitives.test.ts", function() { it("test primitives in block", function() { diff --git a/ts2panda/tests/types/union.test.ts b/ts2panda/tests/types/union.test.ts index 47fb5fc960f5854215d2d33f2b3030a6bcf5a1f8..ca075db6aee903a9c16f393c789eecbf98d05737 100644 --- a/ts2panda/tests/types/union.test.ts +++ b/ts2panda/tests/types/union.test.ts @@ -22,9 +22,9 @@ import { createVRegTypePair, compareVReg2Type } from "./typeUtils"; -import { PrimitiveType } from '../../src/base/typeSystem'; +import { userDefinedTypeStartIndex } from '../../src/base/typeSystem'; -let shift = PrimitiveType._LENGTH; +let shift = userDefinedTypeStartIndex; describe("union tests in union.test.ts", function () { it("test union with primitives", function () { diff --git a/ts2panda/ts2abc/ts2abc.cpp b/ts2panda/ts2abc/ts2abc.cpp index f58511157852b205f1ffa40e2ea4be07c6438989..3fcd81f41c322774e8cb30315ba17d7bfd9a0dff 100644 --- a/ts2panda/ts2abc/ts2abc.cpp +++ b/ts2panda/ts2abc/ts2abc.cpp @@ -42,6 +42,7 @@ bool g_debugLogEnabled = false; int g_optLevel = 0; bool g_enableTypeinfo = false; bool g_displayTypeinfo = false; +bool g_isDtsFile = false; std::string g_optLogLevel = "error"; uint32_t g_literalArrayCount = 0; using ts2abc_type_adapter::TypeAdapter; @@ -777,6 +778,11 @@ static panda::pandasm::Function ParseFunction(const Json::Value &function) ParseFunctionExportedType(function, pandaFunc); ParseFunctionDeclaredType(function, pandaFunc); + if (g_isDtsFile && pandaFunc.name != "func_main_0") { + pandaFunc.metadata->SetAttribute("external"); + } + + return pandaFunc; } @@ -914,6 +920,14 @@ static void ParseOptLogLevel(const Json::Value &rootValue) } } +static void ParseIsDtsFile(const Json::Value &rootValue) +{ + Logd("-----------------parse is dts file-----------------"); + if (rootValue.isMember("is_dts_file") && rootValue["is_dts_file"].isBool()) { + g_isDtsFile = rootValue["is_dts_file"].asBool(); + } +} + static void ReplaceAllDistinct(std::string &str, const std::string &oldValue, const std::string &newValue) { for (std::string::size_type pos(0); pos != std::string::npos; pos += newValue.length()) { @@ -936,6 +950,7 @@ static void ParseOptions(const Json::Value &rootValue, panda::pandasm::Program & ParseOptLevel(rootValue); ParseDisplayTypeinfo(rootValue); ParseOptLogLevel(rootValue); + ParseIsDtsFile(rootValue); } static void ParseSingleFunc(const Json::Value &rootValue, panda::pandasm::Program &prog) diff --git a/ts2panda/ts2abc/type_adapter.cpp b/ts2panda/ts2abc/type_adapter.cpp index a0ae080162e2fe91ded247d95191fea82c36b2bc..661cb1df839e5e69b578d6ce440ffa938723b2da 100644 --- a/ts2panda/ts2abc/type_adapter.cpp +++ b/ts2panda/ts2abc/type_adapter.cpp @@ -79,6 +79,9 @@ void TypeAdapter::HandleTypeForFunction(panda::pandasm::Function *func, size_t a continue; } order++; + + FillInBuiltinType(insn, order_type_map, order); + bool maybe_arg = MaybeArg(func, i); if (!maybe_arg && insn.opcode != panda::pandasm::Opcode::STA_DYN) { continue; @@ -114,6 +117,22 @@ void TypeAdapter::HandleTypeForFunction(panda::pandasm::Function *func, size_t a UpdateTypeAnnotation(func, anno_idx, ele_idx, order_type_map); } +void TypeAdapter::FillInBuiltinType(const panda::pandasm::Ins &insn, + std::unordered_map &order_type_map, + const int32_t order) const +{ + if (insn.opcode != panda::pandasm::Opcode::ECMA_TRYLDGLOBALBYNAME) { + return; + } + + auto objName = insn.ids[0]; + auto typeIter = std::find(builtinTypes.begin(), builtinTypes.end(), objName); + if (typeIter != builtinTypes.end()) { + int builtinTypeIdx = typeIter - builtinTypes.begin() + builtinTypeOffset; + order_type_map.emplace(order - 1, builtinTypeIdx); + } +} + void TypeAdapter::UpdateTypeAnnotation(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx, const std::unordered_map &order_type_map) const { diff --git a/ts2panda/ts2abc/type_adapter.h b/ts2panda/ts2abc/type_adapter.h index 141cfcc89b16fca77b5eadca1317caccbbac8c3f..440f9771299872d30964447a50d4c68824dcade7 100644 --- a/ts2panda/ts2abc/type_adapter.h +++ b/ts2panda/ts2abc/type_adapter.h @@ -20,6 +20,73 @@ #include "assembler/assembly-function.h" namespace ts2abc_type_adapter { + +const int builtinTypeOffset = 21; + +const std::vector builtinTypes { + "Function", + "RangeError", + "Error", + "Object", + "SyntaxError", + "TypeError", + "ReferenceError", + "URIError", + "Symbol", + "EvalError", + "Number", + "parseFloat", + "Date", + "Boolean", + "BigInt", + "parseInt", + "WeakMap", + "RegExp", + "Set", + "Map", + "WeakRef", + "WeakSet", + "FinalizationRegistry", + "Array", + "Uint8ClampedArray", + "Uint8Array", + "TypedArray", + "Int8Array", + "Uint16Array", + "Uint32Array", + "Int16Array", + "Int32Array", + "Float32Array", + "Float64Array", + "BigInt64Array", + "BigUint64Array", + "SharedArrayBuffer", + "DataView", + "String", + "ArrayBuffer", + "eval", + "isFinite", + "ArkPrivate", + "print", + "decodeURI", + "decodeURIComponent", + "isNaN", + "encodeURI", + "NaN", + "globalThis", + "encodeURIComponent", + "Infinity", + "Math", + "JSON", + "Atomics", + "undefined", + "Reflect", + "Promise", + "Proxy", + "GeneratorFunction", + "Intl", +}; + class TypeAdapter { public: TypeAdapter() {}; @@ -40,6 +107,8 @@ private: void AdaptTypeForFunction(panda::pandasm::Function *func) const; void HandleTypeForFunction(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx, const std::unordered_map &vreg_type_map) const; + void FillInBuiltinType(const panda::pandasm::Ins &insn, std::unordered_map &order_type_map, + const int32_t order) const; void UpdateTypeAnnotation(panda::pandasm::Function *func, size_t anno_idx, size_t ele_idx, const std::unordered_map &order_type_map) const; bool display_typeinfo_ = false;