diff --git a/es2panda/binder/scope.h b/es2panda/binder/scope.h index 70be5ce9a70b62060ee50a843eb4bf1fcdc7fb26..3fd392aef7982534dee77146c36fe2e30080ca48 100644 --- a/es2panda/binder/scope.h +++ b/es2panda/binder/scope.h @@ -258,7 +258,12 @@ public: return node_; } - void BindNode(const ir::AstNode *node) + ir::AstNode *Node() + { + return node_; + } + + void BindNode(ir::AstNode *node) { node_ = node; } @@ -358,7 +363,7 @@ protected: ArenaVector decls_; VariableMap bindings_; TSBindings tsBindings_; - const ir::AstNode *node_ {}; + ir::AstNode *node_ {}; const compiler::IRNode *startIns_ {}; const compiler::IRNode *endIns_ {}; }; diff --git a/es2panda/compiler/core/function.cpp b/es2panda/compiler/core/function.cpp index b9a4bce84f25fb5ddf8ee00fc4d97bebd9ee837a..80bd914fa046c8fc50408ad1e4281d576e3df78a 100644 --- a/es2panda/compiler/core/function.cpp +++ b/es2panda/compiler/core/function.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include namespace panda::es2panda::compiler { @@ -58,7 +59,11 @@ static void CompileFunctionParameterDeclaration(PandaGen *pg, const ir::ScriptFu uint32_t index = 0; - for (const auto *param : func->Params()) { + for (const auto *it : func->Params()) { + auto *param = it; + if (param->IsTSParameterProperty()) { + param = param->AsTSParameterProperty()->Parameter(); + } LReference ref = LReference::CreateLRef(pg, param, true); [[maybe_unused]] binder::Variable *paramVar = ref.Variable(); @@ -124,6 +129,9 @@ static void CompileInstanceFields(PandaGen *pg, const ir::ScriptFunction *decl) for (auto const &stmt : statements) { if (stmt->IsClassProperty()) { const auto *prop = stmt->AsClassProperty(); + if (prop->IsStatic()) { + continue; + } if (!prop->Value()) { pg->LoadConst(stmt, Constant::JS_UNDEFINED); } else { diff --git a/es2panda/ir/base/classProperty.h b/es2panda/ir/base/classProperty.h index 2380eea35677c8d100758fb3dccf79c225689055..b2cc33c8d73884245ed9eb938f7caaf0b65d2cf1 100644 --- a/es2panda/ir/base/classProperty.h +++ b/es2panda/ir/base/classProperty.h @@ -51,11 +51,26 @@ public: return key_; } + Expression *Key() + { + return key_; + } + + void SetKey(Expression *key) + { + key_ = key; + } + const Expression *Value() const { return value_; } + Expression *Value() + { + return value_; + } + const Expression *TypeAnnotation() const { return typeAnnotation_; @@ -66,11 +81,21 @@ public: return modifiers_; } + bool IsStatic() const + { + return (modifiers_ & ModifierFlags::STATIC) != 0; + } + const ArenaVector &Decorators() const { return decorators_; } + bool HasDecorators() const + { + return !decorators_.empty(); + } + bool IsComputed() const { return isComputed_; diff --git a/es2panda/ir/base/decorator.h b/es2panda/ir/base/decorator.h index 8ea87b4b04a88416f70a9322e1ecf513f5d76373..6c6f2410f2a45e379015e7de0acc451e4decde07 100644 --- a/es2panda/ir/base/decorator.h +++ b/es2panda/ir/base/decorator.h @@ -39,6 +39,11 @@ public: return expr_; } + Expression *Expr() + { + return expr_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/base/methodDefinition.cpp b/es2panda/ir/base/methodDefinition.cpp index 4c814e6eacc663f5e6482f76251e3890e74c5cb6..3975b528cac8b290175e887860d96fd3e620ff0f 100644 --- a/es2panda/ir/base/methodDefinition.cpp +++ b/es2panda/ir/base/methodDefinition.cpp @@ -30,6 +30,11 @@ const ScriptFunction *MethodDefinition::Function() const return value_->Function(); } +ScriptFunction *MethodDefinition::Function() +{ + return value_->Function(); +} + void MethodDefinition::Iterate(const NodeTraverser &cb) const { cb(key_); diff --git a/es2panda/ir/base/methodDefinition.h b/es2panda/ir/base/methodDefinition.h index 77c5fc8c29741e9a4c69effa261d17417903f49e..ff51e020bf4f1d2bee4781ed076ba4c6d2b61a8f 100644 --- a/es2panda/ir/base/methodDefinition.h +++ b/es2panda/ir/base/methodDefinition.h @@ -34,11 +34,16 @@ class FunctionExpression; enum class MethodDefinitionKind { CONSTRUCTOR, METHOD, GET, SET }; +struct ParamDecorators { + size_t paramIndex; + ArenaVector decorators; +}; + class MethodDefinition : public Statement { public: explicit MethodDefinition(MethodDefinitionKind kind, Expression *key, FunctionExpression *value, ModifierFlags modifiers, ArenaAllocator *allocator, ArenaVector &&decorators, - bool isComputed) + ArenaVector &¶mDecorators, bool isComputed) : Statement(AstNodeType::METHOD_DEFINITION), kind_(kind), key_(key), @@ -46,6 +51,7 @@ public: modifiers_(modifiers), overloads_(allocator->Adapter()), decorators_(std::move(decorators)), + paramDecorators_(std::move(paramDecorators)), isComputed_(isComputed) { } @@ -65,6 +71,16 @@ public: return key_; } + Expression *Key() + { + return key_; + } + + void SetKey(Expression *key) + { + key_ = key; + } + const FunctionExpression *Value() const { return value_; @@ -100,6 +116,21 @@ public: return decorators_; } + const ArenaVector &GetParamDecorators() const + { + return paramDecorators_; + } + + bool HasParamDecorators() const + { + return !paramDecorators_.empty(); + } + + bool HasDecorators() const + { + return !decorators_.empty(); + } + void SetOverloads(ArenaVector &&overloads) { overloads_ = std::move(overloads); @@ -112,6 +143,8 @@ public: const ScriptFunction *Function() const; + ScriptFunction *Function(); + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; @@ -125,6 +158,7 @@ private: ModifierFlags modifiers_; ArenaVector overloads_; ArenaVector decorators_; + ArenaVector paramDecorators_; bool isComputed_; }; diff --git a/es2panda/ir/base/scriptFunction.h b/es2panda/ir/base/scriptFunction.h index aaf29adb9004263fba0b21d380e6a6254b36d301..9d73b8121cec922602352a12fbd01e0b198ab92d 100644 --- a/es2panda/ir/base/scriptFunction.h +++ b/es2panda/ir/base/scriptFunction.h @@ -139,6 +139,11 @@ public: return (flags_ & ir::ScriptFunctionFlags::METHOD) != 0; } + bool FunctionBodyIsExpression() const + { + return (flags_ & ir::ScriptFunctionFlags::EXPRESSION) != 0; + } + bool Declare() const { return declare_; diff --git a/es2panda/ir/expressions/classExpression.h b/es2panda/ir/expressions/classExpression.h index b4f350b3ee70e4f44126d93b81175abc4b9e1341..e20a4641615ae4f927b3d7489345009832005f22 100644 --- a/es2panda/ir/expressions/classExpression.h +++ b/es2panda/ir/expressions/classExpression.h @@ -40,6 +40,11 @@ public: return def_; } + ClassDefinition *Definition() + { + return def_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/expressions/functionExpression.h b/es2panda/ir/expressions/functionExpression.h index 3211855b980adfc96fa76f52ad833501dc2f89c0..227e630b9fd3e8bd032d7de3f4e3532733d86e03 100644 --- a/es2panda/ir/expressions/functionExpression.h +++ b/es2panda/ir/expressions/functionExpression.h @@ -40,6 +40,11 @@ public: return func_; } + ScriptFunction *Function() + { + return func_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/expressions/identifier.h b/es2panda/ir/expressions/identifier.h index 543397f6c6abdb5315f787e0c5120857159f88a4..1055ba458d5685903d8a01eeac693bef33dfd117 100644 --- a/es2panda/ir/expressions/identifier.h +++ b/es2panda/ir/expressions/identifier.h @@ -78,6 +78,11 @@ public: return name_; } + void SetName(util::StringView name) + { + name_ = name; + } + const ArenaVector &Decorators() const { return decorators_; @@ -132,6 +137,7 @@ private: util::StringView name_; Expression *typeAnnotation_ {}; IdentifierFlags flags_ {IdentifierFlags::NONE}; + // TODO(xucheng): remove the decorators in identifier ArenaVector decorators_; }; diff --git a/es2panda/ir/expressions/literals/bigIntLiteral.h b/es2panda/ir/expressions/literals/bigIntLiteral.h index ef1aee885f5adc1992385e46f9a61c9015740e21..70290e3c4b2cbb1e420bec85cd74bb89a0f852f4 100644 --- a/es2panda/ir/expressions/literals/bigIntLiteral.h +++ b/es2panda/ir/expressions/literals/bigIntLiteral.h @@ -39,6 +39,11 @@ public: return src_; } + util::StringView Str() + { + return src_; + } + LiteralTag Tag() const override { return LiteralTag::NULL_VALUE; diff --git a/es2panda/ir/statements/blockStatement.cpp b/es2panda/ir/statements/blockStatement.cpp index 24abd03273c82f412db78c8051011cdb26771444..39bff4eff14646265bacfe1ff4ce150a1da94efa 100644 --- a/es2panda/ir/statements/blockStatement.cpp +++ b/es2panda/ir/statements/blockStatement.cpp @@ -82,4 +82,9 @@ void BlockStatement::UpdateSelf(const NodeUpdater &cb, binder::Binder *binder) } } +void BlockStatement::AddStatementInFront(Statement *statement) +{ + statements_.insert(statements_.begin(), statement); +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/statements/blockStatement.h b/es2panda/ir/statements/blockStatement.h index 3769fd6862cf46d978620070f411987678305248..c9225bfdac9b86dd4a8b437b8cdfc4e6f18662c3 100644 --- a/es2panda/ir/statements/blockStatement.h +++ b/es2panda/ir/statements/blockStatement.h @@ -50,6 +50,8 @@ public: return statements_; } + void AddStatementInFront(Statement *statement); + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/statements/classDeclaration.h b/es2panda/ir/statements/classDeclaration.h index 5f2864fa1c19e3cd9ca386ff8aca6e5b62cbdff2..f13b0708e31d577458c6e3341c42426e4a8cb103 100644 --- a/es2panda/ir/statements/classDeclaration.h +++ b/es2panda/ir/statements/classDeclaration.h @@ -41,10 +41,21 @@ public: return def_; } + ClassDefinition *Definition() + { + return def_; + } + const ArenaVector &Decorators() const { return decorators_; } + + bool HasDecorators() const + { + return !decorators_.empty(); + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/statements/expressionStatement.h b/es2panda/ir/statements/expressionStatement.h index 36b2d2cf9da17d2207ac8db72793c214d64aa1f2..1e2fa27caf9bbfea8bb9551ad0a2688f9468578a 100644 --- a/es2panda/ir/statements/expressionStatement.h +++ b/es2panda/ir/statements/expressionStatement.h @@ -40,6 +40,11 @@ public: return expression_; } + Expression *GetExpression() + { + return expression_; + } + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile(compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/ts/tsModuleBlock.cpp b/es2panda/ir/ts/tsModuleBlock.cpp index 8955fc3b40ed3e9ea881fc1232713bbb475d02d3..1ffe23e4e4a851d266d6d59d69a7d84209b5f690 100644 --- a/es2panda/ir/ts/tsModuleBlock.cpp +++ b/es2panda/ir/ts/tsModuleBlock.cpp @@ -64,4 +64,9 @@ void TSModuleBlock::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::B } } +void TSModuleBlock::AddStatementInFront(Statement *statement) +{ + statements_.insert(statements_.begin(), statement); +} + } // namespace panda::es2panda::ir diff --git a/es2panda/ir/ts/tsModuleBlock.h b/es2panda/ir/ts/tsModuleBlock.h index f62792938f2f1fdb5161facf454e27ef1b73ae28..48babf52c8ad24d7c2f6e5c605d2dd0f117535f9 100644 --- a/es2panda/ir/ts/tsModuleBlock.h +++ b/es2panda/ir/ts/tsModuleBlock.h @@ -46,6 +46,8 @@ public: return statements_; } + void AddStatementInFront(Statement *statement); + void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; diff --git a/es2panda/ir/ts/tsParameterProperty.cpp b/es2panda/ir/ts/tsParameterProperty.cpp index 2768a1e41940dc4e6c59f54a3dfc9ff25abe4106..f1a33df64b6a673a01165541591834d1693ff4c6 100644 --- a/es2panda/ir/ts/tsParameterProperty.cpp +++ b/es2panda/ir/ts/tsParameterProperty.cpp @@ -39,7 +39,10 @@ void TSParameterProperty::Dump(ir::AstDumper *dumper) const {"parameter", parameter_}}); } -void TSParameterProperty::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} +void TSParameterProperty::Compile(compiler::PandaGen *pg) const +{ + parameter_->Compile(pg); +} checker::Type *TSParameterProperty::Check([[maybe_unused]] checker::Checker *checker) const { diff --git a/es2panda/ir/ts/tsParameterProperty.h b/es2panda/ir/ts/tsParameterProperty.h index 4e655d76afd73ae68ba6ea8110f33642f2949105..9d351d9e419a18b3cbbe9434e6294be522d561ee 100644 --- a/es2panda/ir/ts/tsParameterProperty.h +++ b/es2panda/ir/ts/tsParameterProperty.h @@ -76,7 +76,7 @@ public: void Iterate(const NodeTraverser &cb) const override; void Dump(ir::AstDumper *dumper) const override; - void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + void Compile(compiler::PandaGen *pg) const override; checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; void UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) override; diff --git a/es2panda/ir/ts/tsPrivateIdentifier.h b/es2panda/ir/ts/tsPrivateIdentifier.h index 594261e2de23f946e5832665f63f00de530732cb..f5d65bbdc88141154214c54dc5a55f904b7710ac 100644 --- a/es2panda/ir/ts/tsPrivateIdentifier.h +++ b/es2panda/ir/ts/tsPrivateIdentifier.h @@ -41,6 +41,11 @@ public: return key_; } + Expression *Key() + { + return key_; + } + const Expression *Value() const { return value_; diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index b772127022a3471c8b77aa53c0caf72430813be3..c6051aaeac78ada75f68c7c237c2272bc345ebe9 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -1729,11 +1729,6 @@ void ParserImpl::ParsePotentialTsFunctionParameter(ExpressionParseFlags flags, i ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool allowDefault, bool isDeclare) { ir::Expression *returnNode = nullptr; - ArenaVector decorators(Allocator()->Adapter()); - - if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) { - decorators = ParseDecorators(); - } switch (lexer_->GetToken().Type()) { case lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET: { @@ -1754,15 +1749,9 @@ ir::Expression *ParserImpl::ParsePatternElement(ExpressionParseFlags flags, bool break; } case lexer::TokenType::LITERAL_IDENT: { - returnNode = AllocNode(lexer_->GetToken().Ident(), std::move(decorators)); + returnNode = AllocNode(lexer_->GetToken().Ident(), Allocator()); returnNode->AsIdentifier()->SetReference(); - - if (returnNode->AsIdentifier()->Decorators().empty()) { - returnNode->SetRange(lexer_->GetToken().Loc()); - } else { - returnNode->SetRange( - {returnNode->AsIdentifier()->Decorators().front()->Start(), lexer_->GetToken().End()}); - } + returnNode->SetRange(lexer_->GetToken().Loc()); lexer_->NextToken(); break; } diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 09a79b3c26effb24a1eabadad2768182b09abe90..112f804ce9d19952c25546a3deabb3893992e799 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -2271,7 +2271,8 @@ ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc, ThrowSyntaxError("Generators are not allowed in an ambient context."); } - ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare); + ArenaVector paramDecorators(Allocator()->Adapter()); + ir::ScriptFunction *func = ParseFunction(desc->newStatus, isDeclare, ¶mDecorators); if (func->Body() != nullptr) { lexer_->NextToken(); } @@ -2295,7 +2296,8 @@ ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc, *propEnd = func->End(); func->AddFlag(ir::ScriptFunctionFlags::METHOD); auto *method = AllocNode(desc->methodKind, propName, funcExpr, desc->modifiers, Allocator(), - std::move(decorators), desc->isComputed); + std::move(decorators), std::move(paramDecorators), + desc->isComputed); method->SetRange(funcExpr->Range()); return method; } @@ -2571,9 +2573,10 @@ ir::MethodDefinition *ParserImpl::CreateImplicitConstructor(bool hasSuperClass, auto *key = AllocNode("constructor", Allocator()); ArenaVector decorators(Allocator()->Adapter()); - + ArenaVector paramDecorators(Allocator()->Adapter()); auto *ctor = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr, - ir::ModifierFlags::NONE, Allocator(), std::move(decorators), false); + ir::ModifierFlags::NONE, Allocator(), std::move(decorators), + std::move(paramDecorators), false); return ctor; } @@ -2972,7 +2975,8 @@ void ParserImpl::ValidateFunctionParam(const ArenaVector ¶ } } -ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare) +ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare, + ArenaVector *paramDecorators) { ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS); lexer_->NextToken(); @@ -2980,7 +2984,15 @@ ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare) ArenaVector params(Allocator()->Adapter()); bool seenOptional = false; + size_t index = 0; while (lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS) { + if (context_.Status() & ParserStatus::IN_METHOD_DEFINITION) { + auto decorators = ParseDecorators(); + if (!decorators.empty()) { + paramDecorators->push_back({index, std::move(decorators)}); + } + } + ir::Expression *parameter = ParseFunctionParameter(isDeclare); ValidateFunctionParam(params, parameter, &seenOptional); @@ -2994,6 +3006,8 @@ ArenaVector ParserImpl::ParseFunctionParams(bool isDeclare) if (lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA) { lexer_->NextToken(); } + + index++; } ASSERT(lexer_->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_PARENTHESIS); @@ -3183,7 +3197,9 @@ ir::TSTypeParameterInstantiation *ParserImpl::ParseTsTypeParameterInstantiation( return typeParamInst; } -ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus, bool isDeclare) +ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus, + bool isDeclare, + ArenaVector *paramDecorators) { FunctionContext functionContext(this, newStatus | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET); @@ -3205,7 +3221,7 @@ ir::ScriptFunction *ParserImpl::ParseFunction(ParserStatus newStatus, bool isDec context_.Status() |= ParserStatus::DISALLOW_AWAIT; } - ArenaVector params = ParseFunctionParams(isDeclare); + ArenaVector params = ParseFunctionParams(isDeclare, paramDecorators); ir::Expression *returnTypeAnnotation = nullptr; diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 16d2929ce91b2b3749cdb27b10cfcb10e9f4d99d..83dee0969dc88a92b015e8bb2c12d3a85ed50551 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -319,14 +320,17 @@ private: ir::TSTypeParameter *ParseTsTypeParameter(bool throwError, bool addBinding = false); ir::TSTypeParameterDeclaration *ParseTsTypeParameterDeclaration(bool throwError = true); ir::TSTypeParameterInstantiation *ParseTsTypeParameterInstantiation(bool throwError = true); - ir::ScriptFunction *ParseFunction(ParserStatus newStatus = ParserStatus::NO_OPTS, bool isDeclare = false); + ir::ScriptFunction *ParseFunction(ParserStatus newStatus = ParserStatus::NO_OPTS, + bool isDeclare = false, + ArenaVector *paramDecorators = nullptr); void ValidateFunctionParam(const ArenaVector ¶ms, const ir::Expression *parameter, bool *seenOptional); void ValidateTsFunctionOverloadParams(const ArenaVector ¶ms); void CheckAccessorPair(const ArenaVector &properties, const ir::Expression *propName, ir::MethodDefinitionKind methodKind, ir::ModifierFlags access, bool hasDecorator, lexer::SourcePosition errorInfo); - ArenaVector ParseFunctionParams(bool isDeclare = false); + ArenaVector ParseFunctionParams(bool isDeclare = false, + ArenaVector *paramDecorators = nullptr); ir::SpreadElement *ParseSpreadElement(ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS); ir::TSParameterProperty *CreateTsParameterProperty(ir::Expression *parameter, ir::ModifierFlags modifiers); ir::Expression *ParseFunctionParameter(bool isDeclare); diff --git a/es2panda/parser/transformer/transformer.cpp b/es2panda/parser/transformer/transformer.cpp index 463d60e78a94bd5b4e89599a4c7e7a0bd1bfb0e2..bb0825beea0d62d967f4c351f012e6f0675fa1bb 100644 --- a/es2panda/parser/transformer/transformer.cpp +++ b/es2panda/parser/transformer/transformer.cpp @@ -15,15 +15,26 @@ #include "transformer.h" -#include "ir/base/scriptFunction.h" +#include + #include "ir/base/classDefinition.h" +#include "ir/base/classProperty.h" +#include "ir/base/decorator.h" +#include "ir/base/methodDefinition.h" +#include "ir/base/scriptFunction.h" #include "ir/expressions/assignmentExpression.h" #include "ir/expressions/binaryExpression.h" #include "ir/expressions/callExpression.h" +#include "ir/expressions/classExpression.h" #include "ir/expressions/functionExpression.h" #include "ir/expressions/identifier.h" +#include "ir/expressions/literals/stringLiteral.h" +#include "ir/expressions/literals/numberLiteral.h" +#include "ir/expressions/literals/bigIntLiteral.h" #include "ir/expressions/memberExpression.h" #include "ir/expressions/objectExpression.h" +#include "ir/expressions/sequenceExpression.h" +#include "ir/expressions/thisExpression.h" #include "ir/module/exportNamedDeclaration.h" #include "ir/statements/blockStatement.h" #include "ir/statements/classDeclaration.h" @@ -35,10 +46,11 @@ #include "ir/ts/tsImportEqualsDeclaration.h" #include "ir/ts/tsModuleBlock.h" #include "ir/ts/tsModuleDeclaration.h" +#include "ir/ts/tsParameterProperty.h" +#include "ir/ts/tsPrivateIdentifier.h" #include "ir/ts/tsQualifiedName.h" #include "util/helpers.h" - namespace panda::es2panda::parser { void Transformer::Transform(Program *program) @@ -53,6 +65,7 @@ void Transformer::TransformFromTS() { ASSERT(Extension() == ScriptExtension::TS); VisitTSNodes(program_->Ast()); + PushVariablesToNearestStatements(program_->Ast()); } ir::AstNode *Transformer::VisitTSNodes(ir::AstNode *parent) @@ -64,6 +77,74 @@ ir::AstNode *Transformer::VisitTSNodes(ir::AstNode *parent) return parent; } +void Transformer::AddVariableToNearestStatements(util::StringView name) +{ + /* + * Add variable declare like 'var ##var_1;' to nearest statements in namespace function or top level scope + * Record the variable name and scope in tempVarDeclStatements_ and will push the VariableDeclaration nodes + * to statements in PushVariablesToNearestStatements + */ + auto currentScope = Scope(); + while (currentScope != nullptr) { + if (currentScope->IsTSModuleScope()) { + auto node = currentScope->Node(); + ASSERT(node->IsTSModuleDeclaration()); + if (node->AsTSModuleDeclaration()->Body()->IsTSModuleBlock()) { + break; + } + } + if (currentScope->IsFunctionScope()) { + auto node = currentScope->Node(); + ASSERT(node->IsScriptFunction()); + if (!node->AsScriptFunction()->FunctionBodyIsExpression()) { + break; + } + } + currentScope = currentScope->Parent(); + } + tempVarDeclStatements_.insert({name, currentScope}); +} + +void Transformer::PushVariablesToNearestStatements(ir::BlockStatement *ast) +{ + /* + * Push the VariableDeclaration nodes to nearest statements + * For example, transform: + * namespace ns { + * ... + * } + * + * To: + * namespace ns { + * var ##var_1; + * ... + * } + */ + if (tempVarDeclStatements_.empty()) { + return; + } + for (auto it : tempVarDeclStatements_) { + auto *scope = it.second; + if (scope == nullptr) { + auto scopeCtx = binder::LexicalScope::Enter(Binder(), ast->Scope()); + ast->AddStatementInFront(CreateVariableDeclarationWithIdentify(it.first, VariableParsingFlags::VAR, + nullptr, false)); + } else if (scope->IsFunctionScope()) { + auto *body = scope->Node()->AsScriptFunction()->Body(); + ASSERT(body->IsBlockStatement()); + auto scopeCtx = binder::LexicalScope::Enter(Binder(), scope); + body->AsBlockStatement()->AddStatementInFront(CreateVariableDeclarationWithIdentify(it.first, + VariableParsingFlags::VAR, nullptr, false)); + } else if (scope->IsTSModuleScope()) { + auto *body = scope->Node()->AsTSModuleDeclaration()->Body(); + ASSERT(body->IsTSModuleBlock()); + auto scopeCtx = binder::LexicalScope::Enter(Binder(), scope); + body->AsTSModuleBlock()->AddStatementInFront(CreateVariableDeclarationWithIdentify(it.first, + VariableParsingFlags::VAR, nullptr, false)); + } + } +} + binder::Scope *Transformer::FindExportVariableInTsModuleScope(util::StringView name) const { bool isExport = false; @@ -110,8 +191,7 @@ ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) auto scope = FindExportVariableInTsModuleScope(name); if (scope) { auto moduleName = FindTSModuleNameByScope(scope); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); auto *res = AllocNode(id, AllocNode(name, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); SetOriginalNode(res, childNode); @@ -164,12 +244,607 @@ ir::UpdateNodes Transformer::VisitTSNode(ir::AstNode *childNode) SetOriginalNode(res, childNode); return res; } + case ir::AstNodeType::CLASS_DECLARATION: { + auto *node = childNode->AsClassDeclaration(); + DuringClass duringClass(&classList_, node->Definition()->GetName()); + node = VisitTSNodes(node)->AsClassDeclaration(); + auto res = VisitClassDeclaration(node); + SetOriginalNode(res, childNode); + return res; + } + case ir::AstNodeType::CLASS_EXPRESSION: { + auto *node = childNode->AsClassExpression(); + DuringClass duringClass(&classList_, node->Definition()->GetName()); + node = VisitTSNodes(node)->AsClassExpression(); + auto res = VisitClassExpression(node); + SetOriginalNode(res, childNode); + return res; + } + case ir::AstNodeType::CLASS_DEFINITION: { + auto *node = childNode->AsClassDefinition(); + VisitPrivateProperty(node); + VisitComputedProperty(node); + VisitTSParameterProperty(node); + auto res = VisitTSNodes(childNode); + SetOriginalNode(res, childNode); + return res; + } + case ir::AstNodeType::TS_PRIVATE_IDENTIFIER: { + auto id = childNode->AsTSPrivateIdentifier()->Key()->AsIdentifier(); + auto name = FindPrivatePropertyBindName(id->Name()); + auto res = CreateReferenceIdentifier(name); + SetOriginalNode(res, childNode); + return res; + } default: { return VisitTSNodes(childNode); } } } +util::StringView Transformer::CreateNewVariable(bool needAddToStatements) +{ + util::StringView name = CreateNewVariableName(); + if (needAddToStatements) { + AddVariableToNearestStatements(name); + } + return name; +} + +util::StringView Transformer::CreateUniqueName(const std::string &head, size_t *index) const +{ + util::StringView name; + size_t idx = 0; + if (index != nullptr) { + idx = *index; + } + do { + idx++; + std::stringstream ss; + ss << head << std::to_string(idx); + auto s = ss.str(); + if (!Binder()->HasVariableName(util::StringView(s))) { + name = util::UString(s, Allocator()).View(); + break; + } + } while (true); + if (index != nullptr) { + *index = idx; + } + Binder()->AddDeclarationName(name); + return name; +} + +util::StringView Transformer::CreateNewVariableName() const +{ + auto name = CreateUniqueName(std::string(NEW_VAR_PREFIX) + std::string(NEW_VAR_HEAD)); + return name; +} + +ir::UpdateNodes Transformer::VisitClassExpression(ir::ClassExpression *node) +{ + /* + * Transform: + * var c = class C { + * static a = 1 + * } + * + * To: + * var ##var_1; + * var c = (##var_1 = class C {}, + * ##var_1.a = 1, + * ##var_1) + */ + auto varName = CreateNewVariable(false); + auto staticProperty = VisitStaticProperty(node->Definition(), varName); + if (staticProperty.empty()) { + return node; + } + AddVariableToNearestStatements(varName); + + auto assignment = AllocNode(CreateReferenceIdentifier(varName), + node->AsExpression(), lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + ArenaVector sequence(Allocator()->Adapter()); + sequence.push_back(assignment); + for (auto *it : staticProperty) { + sequence.push_back(it->GetExpression()); + } + sequence.push_back(CreateReferenceIdentifier(varName)); + return AllocNode(std::move(sequence)); +} + +void Transformer::VisitComputedProperty(ir::ClassDefinition *node) +{ + /* + * Only create variable for the computed members with decorators or static class property + * The new value will be used in the decorators or static property initialize + * Transform: + * class C { + * @f + * [a](){} + * static [b] = 1 + * } + * + * To: + * var ##var_1; + * var ##var_2; + * class C { + * @f + * [##var_1 = a](){} + * static [##var_2 = b] = 1 + * } + */ + for (auto *it : node->Body()) { + if (it->IsClassProperty()) { + auto *classProperty = it->AsClassProperty(); + if (!classProperty->IsComputed() || (!classProperty->HasDecorators() && !classProperty->IsStatic())) { + continue; + } + auto *key = classProperty->Key(); + auto name = CreateNewVariable(); + auto *newKey = AllocNode(CreateReferenceIdentifier(name), + key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + classProperty->SetKey(newKey); + AddComputedPropertyBinding(it, name); + } else if (it->IsMethodDefinition()) { + auto *methodDefinition = it->AsMethodDefinition(); + if (!methodDefinition->Computed() || + (!methodDefinition->HasDecorators() && !methodDefinition->HasParamDecorators())) { + continue; + } + auto *key = methodDefinition->Key(); + auto name = CreateNewVariable(); + auto *newKey = AllocNode(CreateReferenceIdentifier(name), + key, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + methodDefinition->SetKey(newKey); + AddComputedPropertyBinding(it, name); + } + } +} + +void Transformer::VisitPrivateProperty(ir::ClassDefinition *node) +{ + /* + * Create an unique variable name for private property member in class + * Transform: + * class C { + * #a = 1 + * } + * + * To: + * class C { + * ##${RecordName}#C#a#1 = 1 + * } + */ + for (auto *it : node->Body()) { + if (!it->IsClassProperty()) { + continue; + } + auto *key = it->AsClassProperty()->Key(); + if (!key->IsTSPrivateIdentifier()) { + continue; + } + auto name = key->AsTSPrivateIdentifier()->Key()->AsIdentifier()->Name(); + auto bindName = CreatePrivatePropertyBindName(name); + AddPrivatePropertyBinding(name, bindName); + } +} + +util::StringView Transformer::FindPrivatePropertyBindName(util::StringView name) +{ + for (size_t i = classList_.size() - 1; i >= 0; i--) { + auto res = classList_[i].bindNameMap->find(name); + if (res != classList_[i].bindNameMap->end()) { + return res->second; + } + } + UNREACHABLE(); +} + +util::StringView Transformer::CreatePrivatePropertyBindName(util::StringView name) +{ + std::stringstream head; + head << NEW_VAR_PREFIX << std::string(RecordName()); + for (auto it : classList_) { + head << PRIVATE_PROPERTY_SIGN << std::string(it.name); + } + head << PRIVATE_PROPERTY_SIGN << std::string(name) << PRIVATE_PROPERTY_SIGN; + size_t index = GetCurrentClassInfoPropertyIndex(); + auto uniqueName = CreateUniqueName(head.str(), &index); + SetCurrentClassInfoPropertyIndex(index); + return uniqueName; +} + +void Transformer::VisitTSParameterProperty(ir::ClassDefinition *node) +{ + /* + * Add class property for the parameter property declaration in constructor + * Transform: + * class C { + * constructor(public a = 1) {} + * } + * + * To: + * class C { + * constructor(public a = 1) { + * this.a = a; + * } + * } + */ + auto *func = node->Ctor()->Function(); + auto *body = func->Body(); + if (body == nullptr) { + return; + } + auto blockStatement = body->AsBlockStatement(); + for (auto *it : func->Params()) { + if (!it->IsTSParameterProperty()) { + continue; + } + auto *parameter = it->AsTSParameterProperty()->Parameter(); + util::StringView name; + // TSParameterPropert only can be identifier or assignment expression + if (parameter->IsIdentifier()) { + name = parameter->AsIdentifier()->Name(); + } else { + ASSERT(parameter->IsAssignmentExpression()); + auto *left = parameter->AsAssignmentExpression()->Left(); + ASSERT(left->IsIdentifier()); + name = left->AsIdentifier()->Name(); + } + auto left = AllocNode(AllocNode(), + AllocNode(name, Allocator()), + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); + auto right = CreateReferenceIdentifier(name); + auto assignment = AllocNode(left, right, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + blockStatement->AddStatementInFront(AllocNode(assignment)); + } +} + +std::vector Transformer::VisitStaticProperty(ir::ClassDefinition *node, + util::StringView name) +{ + /* + * Create statement for static class property + * If it's a conputed property, we should initialize it's new variable first. + * Transform: + * var ##var_1; + * class C { + * static a = 1 + * static [##var_1 = s] = 1 + * } + * + * To: + * var ##var_1; + * class C { + * } + * C.a = 1; + * ##var_1 = s; + * C[##var_1] = 1; + * + * TODO(xucheng): should support static private property + */ + std::vector res; + auto classDefinitionBody = node->Body(); + for (auto *it : classDefinitionBody) { + if (!it->IsClassProperty()) { + continue; + } + auto *classProperty = it->AsClassProperty(); + if (!classProperty->IsStatic()) { + continue; + } + if (classProperty->IsComputed()) { + res.push_back(AllocNode(classProperty->Key())); + } + auto right = classProperty->Value(); + if (right == nullptr) { + continue; + } + auto *member = GetClassMemberName(classProperty->Key(), classProperty->IsComputed(), classProperty); + auto left = AllocNode(CreateReferenceIdentifier(name), member, + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, classProperty->IsComputed(), false); + auto assignment = AllocNode(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + res.push_back(AllocNode(assignment)); + } + return res; +} + +ir::UpdateNodes Transformer::VisitClassDeclaration(ir::ClassDeclaration *node) +{ + // TODO(xucheng): maybe will support metadata later + auto name = node->Definition()->GetName(); + std::vector res; + bool hasClassDecorators = node->HasDecorators(); + if (hasClassDecorators) { + auto definiton = node->Definition(); + auto *clsExpression = AllocNode(definiton); + res.push_back(CreateVariableDeclarationWithIdentify(name, VariableParsingFlags::LET, node, false, + clsExpression, false)); + } else { + res.push_back(node); + } + + auto staticProperty = VisitStaticProperty(node->Definition(), name); + if (!staticProperty.empty()) { + res.insert(res.end(), staticProperty.begin(), staticProperty.end()); + } + + auto classDefinitionBody = node->Definition()->Body(); + // decorators of static members, should be called after instance members + std::vector staticMemberDecorators; + for (auto *it : classDefinitionBody) { + if (it->IsMethodDefinition()) { + auto *definition = it->AsMethodDefinition(); + bool isStatic = definition->IsStatic(); + auto paramDecorators = CreateParamDecorators(name, definition, false, isStatic); + if (isStatic) { + staticMemberDecorators.insert(staticMemberDecorators.end(), + paramDecorators.begin(), paramDecorators.end()); + } else { + res.insert(res.end(), paramDecorators.begin(), paramDecorators.end()); + } + if (!definition->HasDecorators()) { + continue; + } + auto methodDecorators = CreateMethodDecorators(name, definition, isStatic); + if (isStatic) { + staticMemberDecorators.insert(staticMemberDecorators.end(), + methodDecorators.begin(), methodDecorators.end()); + } else { + res.insert(res.end(), methodDecorators.begin(), methodDecorators.end()); + } + } else if (it->IsClassProperty()) { + auto *classProperty = it->AsClassProperty(); + bool isStatic = classProperty->IsStatic(); + if (!classProperty->HasDecorators()) { + continue; + } + auto propertyDecorators = CreatePropertyDecorators(name, classProperty, isStatic); + if (isStatic) { + staticMemberDecorators.insert(staticMemberDecorators.end(), + propertyDecorators.begin(), propertyDecorators.end()); + } else { + res.insert(res.end(), propertyDecorators.begin(), propertyDecorators.end()); + } + } + } + + if (!staticMemberDecorators.empty()) { + res.insert(res.end(), staticMemberDecorators.begin(), staticMemberDecorators.end()); + } + + // constructor decorators + auto *ctor = node->Definition()->Ctor(); + auto ctorParamDecorators = CreateParamDecorators(name, ctor, true, false); + res.insert(res.end(), ctorParamDecorators.begin(), ctorParamDecorators.end()); + + // class decorators + if (hasClassDecorators) { + auto classDecorators = CreateClassDecorators(node); + res.insert(res.end(), classDecorators.begin(), classDecorators.end()); + } + if (res.size() == 1) { + return res.front(); + } + return res; +} + +std::vector Transformer::CreateParamDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isConstructor, + bool isStatic) +{ + /* + * Param decorators + * Transform: + * class C { + * f(@g a){} + * } + * + * To: + * class C { + * f(a){} + * } + * g(C.prototype, "f", 0) + * + * Static method or constructor will use constructor function of the class instead of prototype of class + */ + std::vector res; + auto paramsDecorators = node->GetParamDecorators(); + for (int i = paramsDecorators.size() - 1; i >= 0; i--) { + auto paramIndex = paramsDecorators[i].paramIndex; + auto decorators = paramsDecorators[i].decorators; + for (int j = decorators.size() - 1; j >= 0; j--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateDecoratorTarget(className, isConstructor || isStatic)); + arguments.push_back(isConstructor ? + CreateReferenceIdentifier(CONSTRUCTOR_NAME) : + GetClassMemberName(node->Key(), node->Computed(), node)); + arguments.push_back(AllocNode(paramIndex)); + auto *callExpr = AllocNode(decorators[j]->Expr(), + std::move(arguments), nullptr, false); + res.push_back(AllocNode(callExpr)); + } + } + return res; +} + +std::vector Transformer::CreatePropertyDecorators(util::StringView className, + ir::ClassProperty *node, + bool isStatic) +{ + /* + * Property decorators + * Transform: + * class C { + * @f a = 1 + * } + * + * To: + * class C { + * a = 1 + * } + * f(C.prototype, "a") + * + * Static property will use constructor function of the class instead of prototype of class + */ + std::vector res; + auto decorators = node->Decorators(); + for (int i = decorators.size() - 1; i >= 0; i--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateDecoratorTarget(className, isStatic)); + arguments.push_back(GetClassMemberName(node->Key(), node->IsComputed(), node)); + auto *callExpr = AllocNode(decorators[i]->Expr(), std::move(arguments), nullptr, false); + + res.push_back(AllocNode(callExpr)); + } + return res; +} + +std::vector Transformer::CreateMethodDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isStatic) +{ + /* + * Method decorators and accessor decorators + * Transform: + * class C { + * @g + * f(){} + * } + * + * To: + * class C { + * f(){} + * } + * Object.defineProperty(C.prototype, "f", + * g(C.prototype, "f", Object.getOwnPropertyDescriptor(C.prototype, "f")) || + * Object.getOwnPropertyDescriptor(C.prototype, "f")); + * + * static method will use constructor function of the class instead of prototype of class + * If the decorator has a return value, it will be set as the new property of the method + */ + std::vector res; + auto decorators = node->Decorators(); + for (int i = decorators.size() - 1; i >= 0; i--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateDecoratorTarget(className, isStatic)); + arguments.push_back(GetClassMemberName(node->Key(), node->Computed(), node)); + arguments.push_back(CreateGetOwnPropertyDescriptorCall(CreateDecoratorTarget(className, isStatic), + GetClassMemberName(node->Key(), node->Computed(), node))); + auto *callExpr = AllocNode(decorators[i]->Expr(), std::move(arguments), nullptr, false); + + auto *getProperty = CreateGetOwnPropertyDescriptorCall(CreateDecoratorTarget(className, isStatic), + GetClassMemberName(node->Key(), node->Computed(), node)); + auto newValue = AllocNode(callExpr, getProperty, + lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + + auto *defineProperty = CreateDefinePropertyCall(CreateDecoratorTarget(className, isStatic), + GetClassMemberName(node->Key(), node->Computed(), node), newValue); + + res.push_back(AllocNode(defineProperty)); + } + return res; +} + +ir::Expression *Transformer::CreateDecoratorTarget(util::StringView className, bool targetCtor) +{ + if (targetCtor) { + return CreateReferenceIdentifier(className); + } + return CreateClassPrototype(className); +} + +ir::MemberExpression *Transformer::CreateClassPrototype(util::StringView className) +{ + auto *cls = CreateReferenceIdentifier(className); + return AllocNode(cls, AllocNode(CLASS_PROTOTYPE, Allocator()), + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); +} + +ir::CallExpression *Transformer::CreateDefinePropertyCall(ir::Expression *target, + ir::Expression *key, + ir::Expression *value) +{ + auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME); + auto *caller = AllocNode(id, AllocNode(FUNC_NAME_OF_DEFINE_PROPERTY, + Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(target); + arguments.push_back(key); + arguments.push_back(value); + return AllocNode(caller, std::move(arguments), nullptr, false); +} + +ir::CallExpression *Transformer::CreateGetOwnPropertyDescriptorCall(ir::Expression *target, ir::Expression *key) +{ + auto *id = CreateReferenceIdentifier(OBJECT_VAR_NAME); + auto *caller = AllocNode(id, + AllocNode(FUNC_NAME_OF_GET_OWN_PROPERTY_DESCRIPTOR, Allocator()), + ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(target); + arguments.push_back(key); + return AllocNode(caller, std::move(arguments), nullptr, false); +} + +ir::Expression *Transformer::GetClassMemberName(ir::Expression *key, bool isComputed, ir::Statement *node) +{ + if (isComputed) { + auto name = GetComputedPropertyBinding(node); + return AllocNode(name, Allocator()); + } + if (key->IsIdentifier()) { + return AllocNode(key->AsIdentifier()->Name()); + } else if (key->IsStringLiteral()) { + return AllocNode(key->AsStringLiteral()->Str()); + } else if (key->IsNumberLiteral()) { + return AllocNode(key->AsNumberLiteral()->Number(), key->AsNumberLiteral()->Str()); + } else if (key->IsBigIntLiteral()) { + return AllocNode(key->AsBigIntLiteral()->Str()); + } + UNREACHABLE(); + return nullptr; +} + +std::vector Transformer::CreateClassDecorators(ir::ClassDeclaration *node) +{ + /* + * Class decorators + * Transform: + * @f + * class C { + * } + * + * To: + * class C { + * } + * C = f(C) || C; + * + * If the decorator has a return value, it will be used as the new declaration of the class + */ + auto name = node->Definition()->GetName(); + auto decorators = node->Decorators(); + auto size = decorators.size(); + std::vector res; + for (int i = size - 1; i >= 0; i--) { + ArenaVector arguments(Allocator()->Adapter()); + arguments.push_back(CreateReferenceIdentifier(name)); + auto *callExpr = AllocNode(decorators[i]->Expr(), std::move(arguments), nullptr, false); + + auto left = CreateReferenceIdentifier(name); + auto id = CreateReferenceIdentifier(name); + auto right = AllocNode(callExpr, id, lexer::TokenType::PUNCTUATOR_LOGICAL_OR); + auto *assignExpr = AllocNode(left, right, + lexer::TokenType::PUNCTUATOR_SUBSTITUTION); + + res.push_back(AllocNode(assignExpr)); + } + return res; +} + ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node) { auto *express = node->ModuleReference(); @@ -179,8 +854,7 @@ ir::AstNode *Transformer::VisitTsImportEqualsDeclaration(ir::TSImportEqualsDecla auto name = node->Id()->Name(); if (IsTsModule() && node->IsExport()) { auto moduleName = GetCurrentTSModuleName(); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); auto *left = AllocNode(id, AllocNode(name, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); ir::Expression *right = CreateMemberExpressionFromQualified(express); @@ -303,8 +977,7 @@ ir::Expression *Transformer::CreateMemberExpressionFromQualified(ir::Expression ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); } ASSERT(node->IsIdentifier()); - auto *id = AllocNode(node->AsIdentifier()->Name(), Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(node->AsIdentifier()->Name()); return id; } @@ -329,12 +1002,10 @@ void Transformer::SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode ir::ExpressionStatement *Transformer::CreateTsModuleAssignment(util::StringView name) { auto moduleName = GetCurrentTSModuleName(); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); auto *left = AllocNode(id, AllocNode(name, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); - auto *right = AllocNode(name, Allocator()); - right->AsIdentifier()->SetReference(); + auto *right = CreateReferenceIdentifier(name); auto *assignExpr = AllocNode(left, right, lexer::TokenType::PUNCTUATOR_SUBSTITUTION); return AllocNode(assignExpr); } @@ -348,31 +1019,41 @@ ir::VariableDeclaration *Transformer::CreateVariableDeclarationWithIdentify(util VariableParsingFlags flags, ir::AstNode *node, bool isExport, - ir::Expression *init) + ir::Expression *init, + bool needBinding) { - auto *ident = AllocNode(name, Allocator()); - ident->AsIdentifier()->SetReference(); + auto *ident = CreateReferenceIdentifier(name); auto *declarator = AllocNode(ident, init); ArenaVector declarators(Allocator()->Adapter()); declarators.push_back(declarator); - binder::Decl *decl = nullptr; - binder::DeclarationFlags declflag = isExport ? - binder::DeclarationFlags::EXPORT : - binder::DeclarationFlags::NONE; auto varKind = ir::VariableDeclaration::VariableDeclarationKind::VAR; if (flags & VariableParsingFlags::VAR) { - decl = Binder()->AddDecl(node->Start(), declflag, name); } else if (flags & VariableParsingFlags::LET) { varKind = ir::VariableDeclaration::VariableDeclarationKind::LET; - decl = Binder()->AddDecl(node->Start(), declflag, name); } else { varKind = ir::VariableDeclaration::VariableDeclarationKind::CONST; - decl = Binder()->AddDecl(node->Start(), declflag, name); } - auto *declaration = AllocNode(varKind, std::move(declarators), false); - decl->BindNode(declaration); + + lexer::SourcePosition startPos(0, 0); + if (node != nullptr) { + startPos = node->Start(); + } + if (needBinding) { + binder::Decl *decl = nullptr; + binder::DeclarationFlags declflag = isExport ? + binder::DeclarationFlags::EXPORT : + binder::DeclarationFlags::NONE; + if (flags & VariableParsingFlags::VAR) { + decl = Binder()->AddDecl(startPos, declflag, name); + } else if (flags & VariableParsingFlags::LET) { + decl = Binder()->AddDecl(startPos, declflag, name); + } else { + decl = Binder()->AddDecl(startPos, declflag, name); + } + decl->BindNode(declaration); + } return declaration; } @@ -383,19 +1064,8 @@ util::StringView Transformer::GetParamName(ir::TSModuleDeclaration *node, util:: if (!scope->HasVariableName(name)) { return name; } - - auto pramaName = name; - uint32_t idx = 0; - do { - std::stringstream ss; - ss << name; - idx++; - ss << "_" << std::to_string(idx); - util::UString internalName(ss.str(), Allocator()); - pramaName = internalName.View(); - } while (Binder()->HasVariableName(pramaName)); - Binder()->AddDeclarationName(pramaName); - return pramaName; + auto uniqueName = CreateUniqueName(std::string(name) + std::string(INDEX_DIVISION)); + return uniqueName; } ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node, @@ -411,8 +1081,7 @@ ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDec auto paramScopeCtx = binder::LexicalScope::Enter(Binder(), funcParamScope); ArenaVector params(Allocator()->Adapter()); - auto *parameter = AllocNode(paramName, Allocator()); - parameter->AsIdentifier()->SetReference(); + auto *parameter = CreateReferenceIdentifier(paramName); Binder()->AddParamDecl(parameter); params.push_back(parameter); @@ -458,8 +1127,7 @@ ir::CallExpression *Transformer::CreateCallExpressionForTsModule(ir::TSModuleDec assignExpr, lexer::TokenType::PUNCTUATOR_LOGICAL_OR); if (isExport) { - auto *id = AllocNode(name, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(name); arguments.push_back(AllocNode(id, argument, lexer::TokenType::PUNCTUATOR_SUBSTITUTION)); } else { @@ -475,14 +1143,12 @@ ir::Expression *Transformer::CreateTsModuleParam(util::StringView paramName, boo { if (isExport) { auto moduleName = GetCurrentTSModuleName(); - auto *id = AllocNode(moduleName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(moduleName); return AllocNode(id, AllocNode(paramName, Allocator()), ir::MemberExpression::MemberExpressionKind::PROPERTY_ACCESS, false, false); } - auto *id = AllocNode(paramName, Allocator()); - id->AsIdentifier()->SetReference(); + auto *id = CreateReferenceIdentifier(paramName); return id; } @@ -524,4 +1190,11 @@ ir::UpdateNodes Transformer::VisitTsModuleDeclaration(ir::TSModuleDeclaration *n return res; } +ir::Identifier *Transformer::CreateReferenceIdentifier(util::StringView name) +{ + auto *node = AllocNode(name, Allocator()); + node->AsIdentifier()->SetReference(); + return node; +} + } // namespace panda::es2panda::parser diff --git a/es2panda/parser/transformer/transformer.h b/es2panda/parser/transformer/transformer.h index a69ec50c464873b08ee6e56d2819381a10978b04..3ef64914db3552da8748a3dd361e5ff7e7914291 100644 --- a/es2panda/parser/transformer/transformer.h +++ b/es2panda/parser/transformer/transformer.h @@ -32,11 +32,41 @@ struct TsModuleInfo { binder::Scope *scope; }; +using PrivatePropertyMap = std::unordered_map; +using ComputedPropertyMap = std::unordered_map; + +struct ClassInfo { + util::StringView name; + size_t propertyIndex; + PrivatePropertyMap *bindNameMap; + ComputedPropertyMap *computedPropertyMap; +}; + +class DuringClass { +public: + explicit DuringClass(ArenaVector *classList, util::StringView name) + { + classList_ = classList; + classList_->push_back({name, 0, &bindNameMap_, &computedPropertyMap_}); + } + + ~DuringClass() + { + classList_->pop_back(); + } + +private: + PrivatePropertyMap bindNameMap_ {}; + ComputedPropertyMap computedPropertyMap_ {}; + ArenaVector *classList_ {nullptr}; +}; + class Transformer { public: explicit Transformer(panda::ArenaAllocator *allocator) : program_(nullptr), - tsModuleList_(allocator->Adapter()) + tsModuleList_(allocator->Adapter()), + classList_(allocator->Adapter()) { } NO_COPY_SEMANTIC(Transformer); @@ -45,27 +75,72 @@ public: void Transform(Program *program); private: + static constexpr std::string_view PRIVATE_PROPERTY_SIGN = "#"; + static constexpr std::string_view NEW_VAR_PREFIX = "##"; + static constexpr std::string_view NEW_VAR_HEAD = "var_"; + static constexpr std::string_view INDEX_DIVISION = "_"; + static constexpr std::string_view CONSTRUCTOR_NAME = "undefined"; + static constexpr std::string_view CLASS_PROTOTYPE = "prototype"; + static constexpr std::string_view OBJECT_VAR_NAME = "Object"; + static constexpr std::string_view FUNC_NAME_OF_DEFINE_PROPERTY = "defineProperty"; + static constexpr std::string_view FUNC_NAME_OF_GET_OWN_PROPERTY_DESCRIPTOR = "getOwnPropertyDescriptor"; + void TransformFromTS(); + + void AddVariableToNearestStatements(util::StringView name); + void PushVariablesToNearestStatements(ir::BlockStatement *ast); + ir::AstNode *VisitTSNodes(ir::AstNode *parent); ir::UpdateNodes VisitTSNode(ir::AstNode *childNode); ir::UpdateNodes VisitTsModuleDeclaration(ir::TSModuleDeclaration *childNode, bool isExport = false); std::vector VisitExportNamedVariable(ir::Statement *decl); ir::AstNode *VisitTsImportEqualsDeclaration(ir::TSImportEqualsDeclaration *node); + ir::UpdateNodes VisitClassDeclaration(ir::ClassDeclaration *node); + ir::UpdateNodes VisitClassExpression(ir::ClassExpression *node); + void VisitTSParameterProperty(ir::ClassDefinition *node); + std::vector VisitStaticProperty(ir::ClassDefinition *node, util::StringView name); + void VisitPrivateProperty(ir::ClassDefinition *node); + void VisitComputedProperty(ir::ClassDefinition *node); + ir::VariableDeclaration *CreateVariableDeclarationWithIdentify(util::StringView name, VariableParsingFlags flags, ir::AstNode *node, bool isExport, - ir::Expression *init = nullptr); + ir::Expression *init = nullptr, + bool needBinding = true); ir::CallExpression *CreateCallExpressionForTsModule(ir::TSModuleDeclaration *node, util::StringView paramName, bool isExport = false); ir::Expression *CreateTsModuleParam(util::StringView paramName, bool isExport); ir::ExpressionStatement *CreateTsModuleAssignment(util::StringView name); ir::Expression *CreateMemberExpressionFromQualified(ir::Expression *node); + std::vector CreateClassDecorators(ir::ClassDeclaration *node); + std::vector CreateMethodDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isStatic); + std::vector CreatePropertyDecorators(util::StringView className, + ir::ClassProperty *node, + bool isStatic); + ir::CallExpression *CreateGetOwnPropertyDescriptorCall(ir::Expression *target, ir::Expression *key); + ir::CallExpression *CreateDefinePropertyCall(ir::Expression *target, ir::Expression *key, ir::Expression *value); + std::vector CreateParamDecorators(util::StringView className, + ir::MethodDefinition *node, + bool isConstructor, + bool isStatic); + ir::MemberExpression *CreateClassPrototype(util::StringView className); + ir::Expression *CreateDecoratorTarget(util::StringView className, bool isStatic); + ir::Identifier *CreateReferenceIdentifier(util::StringView name); + util::StringView CreatePrivatePropertyBindName(util::StringView name); + util::StringView CreateNewVariable(bool needAddToStatements = true); + util::StringView CreateNewVariableName() const; + util::StringView CreateUniqueName(const std::string &head, size_t *index = nullptr) const; + util::StringView GetNameFromModuleDeclaration(ir::TSModuleDeclaration *node) const; util::StringView GetParamName(ir::TSModuleDeclaration *node, util::StringView name) const; + ir::Expression *GetClassMemberName(ir::Expression *key, bool isComputed, ir::Statement *node); binder::Scope *FindExportVariableInTsModuleScope(util::StringView name) const; binder::Variable *FindTSModuleVariable(const ir::Expression *node, binder::Scope *scope) const; + util::StringView FindPrivatePropertyBindName(util::StringView name); void AddExportLocalEntryItem(util::StringView name, const ir::Identifier *identifier); bool IsInstantiatedTSModule(const ir::Expression *node) const; void SetOriginalNode(ir::UpdateNodes res, ir::AstNode *originalNode) const; @@ -125,8 +200,43 @@ private: return program_->ModuleRecord(); } + util::StringView RecordName() const + { + return program_->RecordName(); + } + + size_t GetCurrentClassInfoPropertyIndex() const + { + return classList_.back().propertyIndex; + } + + void SetCurrentClassInfoPropertyIndex(size_t newIndex) + { + classList_.back().propertyIndex = newIndex; + } + + void AddPrivatePropertyBinding(util::StringView name, util::StringView bindName) + { + classList_.back().bindNameMap->insert({name, bindName}); + } + + void AddComputedPropertyBinding(ir::Statement *property, util::StringView name) + { + classList_.back().computedPropertyMap->insert({property, name}); + } + + util::StringView GetComputedPropertyBinding(ir::Statement *property) + { + auto classInfo = classList_.back(); + auto res = classInfo.computedPropertyMap->find(property); + ASSERT(res != classInfo.computedPropertyMap->end()); + return res->second; + } + Program *program_; ArenaVector tsModuleList_; + ArenaVector classList_; + std::unordered_map tempVarDeclStatements_ {}; }; } // namespace panda::es2panda::parser diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..2b2f2e1b9261c50c3816610eb3eb140fabf1745a --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1-expected.txt @@ -0,0 +1,2 @@ +1 +3 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1.ts new file mode 100644 index 0000000000000000000000000000000000000000..5df2ae0b4fe8458d2fe9b50a4f99c701d62056a3 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-1.ts @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +class C { + constructor(public a : number = 1, public b : number = 2) + { + this.b = 3; + } +} + +var c : C = new C(); +print(c.a); +print(c.b); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..1191247b6d9a206f6ba3d8ac79e26d041dd86941 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2-expected.txt @@ -0,0 +1,2 @@ +1 +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2.ts new file mode 100644 index 0000000000000000000000000000000000000000..ee6cd3ebd85d9578402a98dded6851404886fa04 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-2.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +class C { + a = 2; + static a = 1; +} + +print(C.a); + +var c = new C(); +print(c.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..1191247b6d9a206f6ba3d8ac79e26d041dd86941 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3-expected.txt @@ -0,0 +1,2 @@ +1 +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3.ts new file mode 100644 index 0000000000000000000000000000000000000000..bcc5b639aa833d9c085b9f75c42030d6682be79d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-3.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +class A { + #a = 1; + a = 2; + PrintA() { + print(this.#a); + print(this.a); + } +} + +var a : A = new A(); +a.PrintA(); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4.ts new file mode 100644 index 0000000000000000000000000000000000000000..75e33a4d35080ea079e9d88b8ea8c39bbc30e817 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-4.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +let a = class { + static a = 1; +} + +print(a.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..e329b95a8d37e2d0b4fa28c44c57b7866b3aacfa --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5-expected.txt @@ -0,0 +1 @@ +[1+2] diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5.ts new file mode 100644 index 0000000000000000000000000000000000000000..d8b20bbdf596a0db8979bd6bed38861b42b3c095 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-5.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +class C { + [1 + 2] () {print("[1+2]")}; +} + +var c : C = new C(); +c[1 + 2](); diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6.ts new file mode 100644 index 0000000000000000000000000000000000000000..57c8cdf68afef3c14429a0ae33a068322c0e7140 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-6.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(a = class {static a = 1;}) { + print(a.a); +} +f(); + diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7.ts new file mode 100644 index 0000000000000000000000000000000000000000..a30e9882129f7d4110c3bf2310ffbf3a8349b6b0 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-7.ts @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +class C{ + static [1] = 1; +} +print(C[1]) diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8-expected.txt b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..d00491fd7e5bb6fa28c517a0bb32b8b506539d4d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8-expected.txt @@ -0,0 +1 @@ +1 diff --git a/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8.ts b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8.ts new file mode 100644 index 0000000000000000000000000000000000000000..d5bd06afc55434669067ec9ea2b1f52167dcc702 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/classes/test-ts-classes-8.ts @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +class C { + constructor(public a ?: number) + { + this.a = 1; + } +} + +var c : C = new C(); +print(c.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..bcba9b8c46fbd612969229a3a8efb1a590245b9d --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1-expected.txt @@ -0,0 +1 @@ +test-ts-decorators-1 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1.ts new file mode 100644 index 0000000000000000000000000000000000000000..206ad323f4d7d37ca7159ea5fff120114399df57 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-1.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(constructor) { + print("test-ts-decorators-1"); +} + +@f +class C {} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..1af4bf8965c0c71b3de7864556866dae5f55d035 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10-expected.txt @@ -0,0 +1,4 @@ +1 +1 +1 +2 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10.ts new file mode 100644 index 0000000000000000000000000000000000000000..9f6eea962303f426503fac32d577312076d3d8f0 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-10.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +var a:string = "1" +var b:string = "2" + +function f1(target, key, property){ + print(key) + print(a) +} +function f2(target, key, property){ + print(key) + print(a) + a=b +} +class C{ + @f1 + @f2 + [a](){}; + [b](){}; +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..417130426e7cec7bdc56cbaa7735cb028aae86b8 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11-expected.txt @@ -0,0 +1,2 @@ +3 +[1+2] diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11.ts new file mode 100644 index 0000000000000000000000000000000000000000..a64af05e0bcdbbe006d892318ff84037166a5967 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-11.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(target, key, property) { + print(key); +} + +class C { + @f + [1 + 2] () {print("[1+2]")}; +} + +var c : C = new C(); +c[1 + 2](); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..afacc5d03d23f3c10a38ceaaf5657689fa35172c --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12-expected.txt @@ -0,0 +1,2 @@ +g1 +g2 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12.ts new file mode 100644 index 0000000000000000000000000000000000000000..6cd5992735c93b0fcaace77ba38fed1c8adb5a46 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-12.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(constructor) { + return class extends constructor{ + g1() { + print("g1"); + } + } +} + +@f +class C{ + g2() { + print("g2"); + } +} + +var c = new C() +c.g1() +c.g2() diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..2cdda450af29de45fe75e690e97109e9edab0751 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13-expected.txt @@ -0,0 +1,4 @@ +true +false +true +false diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13.ts new file mode 100644 index 0000000000000000000000000000000000000000..3e5929ee35cdc65c5f73fd93b662d1f60363e970 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-13.ts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(target, key, property) { + property.enumerable=true + return property; +} + +class C{ + @f + a1 (){} + a2 (){return 1} + @f + static b1 (){} + static b2 (){} +} + +print(Object.getOwnPropertyDescriptor(C.prototype,"a1")!.enumerable) +print(Object.getOwnPropertyDescriptor(C.prototype,"a2")!.enumerable) +print(Object.getOwnPropertyDescriptor(C,"b1")!.enumerable) +print(Object.getOwnPropertyDescriptor(C,"b2")!.enumerable) diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..eb1d506a3c0d2db5f27b1679e7bf00d08e7ea57b --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2-expected.txt @@ -0,0 +1,3 @@ +test-ts-decorators-2 flag-1 +test-ts-decorators-2 flag-2 +test-ts-decorators-2 flag-1 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2.ts new file mode 100644 index 0000000000000000000000000000000000000000..d98f0179c78720182a39e8b32b135586c47848a2 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-2.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f1(constructor) { + print("test-ts-decorators-2 flag-1"); +} + +function f2() { + return function(constructor) { + print("test-ts-decorators-2 flag-2");} +} + +@f1 +@f2() +@f1 +class C {} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..6903fe99ab2e991f61b072ed74c4d9813cf9071c --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3-expected.txt @@ -0,0 +1,10 @@ +test-ts-decorators-3 +a +test-ts-decorators-3 +1 +test-ts-decorators-3 +b +test-ts-decorators-3 +c +test-ts-decorators-3 +3 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3.ts new file mode 100644 index 0000000000000000000000000000000000000000..b112358573ed73fc9ae04344ad6739c37697141a --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-3.ts @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(target, propertyKey, descriptor) { + print("test-ts-decorators-3"); + print(propertyKey); +} + +class C { + @f + a() {} + + @f + 1() {} + + @f + "b"() {} + + @f + static [1+2]() {} + + @f + ["c"]() {} +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..e001f89fac4c9ce0cabb1c8660e280e99d64290a --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4-expected.txt @@ -0,0 +1,3 @@ +test-ts-decorators-4 +a +123 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4.ts new file mode 100644 index 0000000000000000000000000000000000000000..54f8eae39cda3222d09f2670134e05d6004fd512 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-4.ts @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(target, propertyKey) { + print("test-ts-decorators-4"); + print(propertyKey); +} + +class C { + @f + a : string = "123"; +} + +var c = new C(); +print(c.a); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..8d8916c04d1fbe43faaefeb84670509dcfbe705a --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5-expected.txt @@ -0,0 +1,21 @@ +test-ts-decorators-5 +g2 +2 +test-ts-decorators-5 +g2 +0 +test-ts-decorators-5 +g2 +0 +test-ts-decorators-5 +g1 +2 +test-ts-decorators-5 +g1 +0 +test-ts-decorators-5 +g1 +0 +test-ts-decorators-5 +undefined +0 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5.ts new file mode 100644 index 0000000000000000000000000000000000000000..20879b82249f2fb361a8cb180f5b3ad1de60da0c --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-5.ts @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(target, propertyKey, b) { + print("test-ts-decorators-5"); + print(propertyKey); + print(b); +} + +class C { + static g1(@f @f a, b, @f {c}){} + + g2(@f @f a, b, @f {c}){} + + constructor(@f a1,b,c){} +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..81e4a7a02e1adbc01618e0457f5847b3f705a4dd --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6-expected.txt @@ -0,0 +1 @@ +test-ts-decorators-6 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6.ts new file mode 100644 index 0000000000000000000000000000000000000000..a71e3f4aa0a3b6f98936877021ee39a7c03cd7a2 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-6.ts @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(ctor) { + return class extends ctor{ + constructor(){ + super(); + this.s = "test-ts-decorators-6"; + } + } +} + +@f +class C{} + +var c = new C(); +print(c.s); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..5a9364b7b48a3aa083127ddeef3d7fbd4a0c5bcb --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7-expected.txt @@ -0,0 +1,18 @@ +methodDecorator2 +methodDecorator1 +propertyDecorator2 +propertyDecorator1 +paramDecorator2 +paramDecorator1 +methodDecorator2 +methodDecorator1 +propertyDecorator2 +propertyDecorator1 +paramDecorator2 +paramDecorator1 +methodDecorator2 +methodDecorator1 +paramDecorator2 +paramDecorator1 +classDecorator2 +classDecorator1 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7.ts new file mode 100644 index 0000000000000000000000000000000000000000..7359721058b1a4f00612b4b50f359a079984a3bc --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-7.ts @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function classDecorator1(ctor) +{ + print("classDecorator1") +} + +function classDecorator2() +{ + return (ctor)=>{print("classDecorator2")} +} + +function methodDecorator1(target, key, property) +{ + print("methodDecorator1") +} + +function methodDecorator2() +{ + return (target, key, property)=>{print("methodDecorator2")} +} + +function propertyDecorator1(target, key) +{ + print("propertyDecorator1") +} + +function propertyDecorator2() +{ + return (target, key)=>{print("propertyDecorator2")} +} + +function paramDecorator1(target, key, index) +{ + print("paramDecorator1"); +} + +function paramDecorator2() +{ + return (target, key, index)=>{print("paramDecorator2")} +} + +@classDecorator1 +@classDecorator2() +class C { + @methodDecorator1 + @methodDecorator2() + get x() {return 1;} + + @propertyDecorator1 + @propertyDecorator2() + static b : number = 1; + + @propertyDecorator1 + @propertyDecorator2() + a : number = 1; + + @methodDecorator1 + @methodDecorator2() + static g1(a, @paramDecorator1 @paramDecorator2() b){} + + @methodDecorator1 + @methodDecorator2() + g2(a, @paramDecorator1 @paramDecorator2() b){} + + constructor(a, b, @paramDecorator1 @paramDecorator2() c){} +} diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..34756f555fcb885e29acc8935d32905eadd7b265 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8-expected.txt @@ -0,0 +1,3 @@ +test-ts-decorators-8 +1 +123 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8.ts new file mode 100644 index 0000000000000000000000000000000000000000..8ca133894dee91f909392e5c18681cde0cf161a7 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-8.ts @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +function f(target, propertyKey) { + print("test-ts-decorators-8"); + print(propertyKey); +} + +class C { + @f + static [1] : string = "123"; + /* + * TODO(xucheng): test computer property when class support it + * @f + * [2] : string = "123"; + */ +} + +print(C[1]); diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9-expected.txt b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..0886de01d5e988fea8aa323ac2e839bc3a8fdc10 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9-expected.txt @@ -0,0 +1 @@ +test-ts-decorators-9 diff --git a/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9.ts b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9.ts new file mode 100644 index 0000000000000000000000000000000000000000..37d54afc1ca2cc652600ef80f8b85c588fff0955 --- /dev/null +++ b/es2panda/test/compiler/ts/cases/conformance/decorators/test-ts-decorators-9.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +const s : unique symbol = Symbol() +function f(target, propertyKey) { + print("test-ts-decorators-9"); +} +class C{ + @f + static [s] : any; +} diff --git a/es2panda/test/parser/ts/test_decorator-expected.txt b/es2panda/test/parser/ts/test_decorator-expected.txt index 0477a6de92ee11adec1f1b27b16f6095ad5305ed..51261278f45944d8604736954cb8430ad600db56 100644 --- a/es2panda/test/parser/ts/test_decorator-expected.txt +++ b/es2panda/test/parser/ts/test_decorator-expected.txt @@ -67,40 +67,11 @@ } } }, - "decorators": [ - { - "type": "Decorator", - "expression": { - "type": "Identifier", - "name": "g", - "decorators": [], - "loc": { - "start": { - "line": 27, - "column": 18 - }, - "end": { - "line": 27, - "column": 19 - } - } - }, - "loc": { - "start": { - "line": 27, - "column": 17 - }, - "end": { - "line": 27, - "column": 19 - } - } - } - ], + "decorators": [], "loc": { "start": { "line": 27, - "column": 17 + "column": 20 }, "end": { "line": 27, diff --git a/es2panda/test/runner.py b/es2panda/test/runner.py index 8b79f1de9f21f5a287934e806ed108183dee8d84..bdfa45dbb5f54005edf41bdd360d57ea34d3d333 100755 --- a/es2panda/test/runner.py +++ b/es2panda/test/runner.py @@ -394,7 +394,7 @@ class Runner: self.failed = 0 self.passed = 0 self.es2panda = path.join(args.build_dir, 'es2abc') - self.test_abc = path.join(args.build_dir, 'runner_test.abc') + self.build_dir = args.build_dir self.cmd_prefix = [] self.ark_js_vm = "" self.ld_library_path = "" @@ -788,9 +788,11 @@ class CompilerTest(Test): Test.__init__(self, test_path, flags) def run(self, runner): + test_abc_name = ("%s.abc" % (path.splitext(self.path)[0])).replace("/", "_") + test_abc_path = path.join(runner.build_dir, test_abc_name) es2abc_cmd = runner.cmd_prefix + [runner.es2panda] es2abc_cmd.extend(self.flags) - es2abc_cmd.extend(["--output=" + runner.test_abc]) + es2abc_cmd.extend(["--output=" + test_abc_path]) es2abc_cmd.append(self.path) self.log_cmd(es2abc_cmd) @@ -804,7 +806,7 @@ class CompilerTest(Test): ld_library_path = runner.ld_library_path os.environ.setdefault("LD_LIBRARY_PATH", ld_library_path) run_abc_cmd = [runner.ark_js_vm] - run_abc_cmd.extend([runner.test_abc]) + run_abc_cmd.extend([test_abc_path]) self.log_cmd(run_abc_cmd) process = subprocess.Popen(run_abc_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) @@ -821,7 +823,7 @@ class CompilerTest(Test): if not self.passed: self.error = err.decode("utf-8", errors="ignore") - os.remove(runner.test_abc) + os.remove(test_abc_path) return self diff --git a/es2panda/test/test_tsc_ignore_list.txt b/es2panda/test/test_tsc_ignore_list.txt index ec89e64c815b7db9ddbfb7968fe7909836f71fc1..b7cfa8daf8746baed498fc2a3732fd24fdab4a01 100644 --- a/es2panda/test/test_tsc_ignore_list.txt +++ b/es2panda/test/test_tsc_ignore_list.txt @@ -45,7 +45,6 @@ es2panda/test/TypeScript/tests/cases/compiler/parseEntityNameWithReservedWord.ts es2panda/test/TypeScript/tests/cases/compiler/shebang.ts es2panda/test/TypeScript/tests/cases/compiler/sigantureIsSubTypeIfTheyAreIdentical.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMap-LineBreaks.ts -es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDecorators.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForArrayBindingPattern2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForArrayBindingPatternDefaultValues2.ts es2panda/test/TypeScript/tests/cases/compiler/sourceMapValidationDestructuringForObjectBindingPattern2.ts