diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 788719bab92903858e9bd5f066d73e8555b7b304..47eca20c743ea26e626d974c280b120713a8276a 100644 --- a/es2panda/BUILD.gn +++ b/es2panda/BUILD.gn @@ -55,6 +55,7 @@ es2panda_src = [ "ir/base/catchClause.cpp", "ir/base/classDefinition.cpp", "ir/base/classProperty.cpp", + "ir/base/classStaticBlock.cpp", "ir/base/decorator.cpp", "ir/base/metaProperty.cpp", "ir/base/methodDefinition.cpp", diff --git a/es2panda/compiler/core/pandagen.cpp b/es2panda/compiler/core/pandagen.cpp index 0eb85b5cbcd5d02f51c8f515a85640fefc2ea53e..681e3d7a6bb3f6bb3470bbaf32fb93d9e4fcb5a1 100644 --- a/es2panda/compiler/core/pandagen.cpp +++ b/es2panda/compiler/core/pandagen.cpp @@ -1322,7 +1322,7 @@ void PandaGen::DefineFunction(const ir::AstNode *node, const ir::ScriptFunction } auto formalParamCnt = realNode->FormalParamsLength(); - if (realNode->IsMethod()) { + if (realNode->IsMethod() || realNode->IsStaticBlock()) { ra_.Emit(node, 0, name, static_cast(formalParamCnt)); } else { ra_.Emit(node, 0, name, static_cast(formalParamCnt)); diff --git a/es2panda/ir/astNode.h b/es2panda/ir/astNode.h index 82f1d30853ccb37e8879d37d2d2a0765bd429f28..53207b9a9135a7798b11249d085bb2510b671d8c 100644 --- a/es2panda/ir/astNode.h +++ b/es2panda/ir/astNode.h @@ -89,7 +89,8 @@ enum class ScriptFunctionFlags { CONSTRUCTOR = 1 << 5, METHOD = 1 << 6, CONCURRENT = 1 << 7, - SHOW_SOURCE = 1 << 8 + SHOW_SOURCE = 1 << 8, + STATIC_BLOCK = 1 << 9 }; DEFINE_BITOPS(ScriptFunctionFlags) diff --git a/es2panda/ir/astNodeMapping.h b/es2panda/ir/astNodeMapping.h index fb75caa922cf8fac1a9479f8b16815570fbb9260..918712bfae234cd42f06af66d138e4eff0d2e6c5 100644 --- a/es2panda/ir/astNodeMapping.h +++ b/es2panda/ir/astNodeMapping.h @@ -67,6 +67,7 @@ _(RETURN_STATEMENT, ReturnStatement) \ _(SCRIPT_FUNCTION, ScriptFunction) \ _(SEQUENCE_EXPRESSION, SequenceExpression) \ + _(CLASS_STATIC_BLOCK, ClassStaticBlock) \ _(STRING_LITERAL, StringLiteral) \ _(SUPER_EXPRESSION, SuperExpression) \ _(SWITCH_CASE_STATEMENT, SwitchCaseStatement) \ diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index 1dcd5c4eddc1e0c95657510f5b3cab3852116725..9bedbb2c99439d4b8009fa587692b5ced0cc9465 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -23,6 +23,7 @@ #include "typescript/checker.h" #include "ir/astDump.h" #include "ir/base/classProperty.h" +#include "ir/base/classStaticBlock.h" #include "ir/base/methodDefinition.h" #include "ir/base/scriptFunction.h" #include "ir/expression.h" @@ -141,6 +142,7 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti const auto &properties = body_; + for (size_t i = 0; i < properties.size(); i++) { if (!properties[i]->IsMethodDefinition()) { continue; @@ -295,6 +297,34 @@ void ClassDefinition::CompileMissingProperties(compiler::PandaGen *pg, const uti pg->LoadAccumulator(this, classReg); } +void ClassDefinition::CompileStaticBlocks(compiler::PandaGen *pg, const util::BitSet &compiled, + compiler::VReg classReg) const +{ + const auto& properties = body_; + + for (size_t i = 0; i < properties.size(); i++) { + if (!properties[i]->IsClassStaticBlock()) { + continue; + } + + const ir::ClassStaticBlock* prop = properties[i]->AsClassStaticBlock(); + + compiler::RegScope rs(pg); + compiler::VReg callee = pg->AllocReg(); + compiler::VReg thisReg = pg->AllocReg(); + prop->BodyFunction()->Compile(pg); + pg->StoreAccumulator(this, thisReg); + compiler::Operand propCall = util::StringView("call"); + pg->LoadObjProperty(this, thisReg, propCall); + pg->StoreAccumulator(this, callee); + compiler::VReg arg = pg->AllocReg(); + pg->LoadAccumulator(this, classReg); + pg->StoreAccumulator(this, arg); + pg->CallThis(this, callee, 2); + pg->LoadAccumulator(this, classReg); + } +} + void ClassDefinition::Compile(compiler::PandaGen *pg) const { if (declare_) { @@ -317,6 +347,7 @@ void ClassDefinition::Compile(compiler::PandaGen *pg) const InitializeClassName(pg); CompileMissingProperties(pg, compiled, classReg); + CompileStaticBlocks(pg, compiled, classReg); } checker::Type *ClassDefinition::Check(checker::Checker *checker) const diff --git a/es2panda/ir/base/classDefinition.h b/es2panda/ir/base/classDefinition.h index b008cabe924c08492da2ef173e367dbc62e8b580..aab010389a555cad4949f92a39522a6abdea14a1 100644 --- a/es2panda/ir/base/classDefinition.h +++ b/es2panda/ir/base/classDefinition.h @@ -177,6 +177,7 @@ private: void InitializeClassName(compiler::PandaGen *pg) const; int32_t CreateClassStaticProperties(compiler::PandaGen *pg, util::BitSet &compiled) const; void CompileMissingProperties(compiler::PandaGen *pg, const util::BitSet &compiled, compiler::VReg classReg) const; + void CompileStaticBlocks(compiler::PandaGen *pg, const util::BitSet &compiled, compiler::VReg classReg) const; binder::LocalScope *scope_; Identifier *ident_; diff --git a/es2panda/ir/base/classStaticBlock.cpp b/es2panda/ir/base/classStaticBlock.cpp new file mode 100644 index 0000000000000000000000000000000000000000..29ef50b14219f82caf61f902e15b62e51a83f72b --- /dev/null +++ b/es2panda/ir/base/classStaticBlock.cpp @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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. + */ + +#include "classStaticBlock.h" + +#include +#include +#include +#include +#include + +#include + +namespace panda::es2panda::ir { + +const ScriptFunction *ClassStaticBlock::Function() const +{ + return bodyFunction_->Function(); +} + +ScriptFunction *ClassStaticBlock::Function() +{ + return bodyFunction_->Function(); +} + +void ClassStaticBlock::Iterate(const NodeTraverser &cb) const +{ + cb(bodyFunction_); + + for (auto *it : decorators_) { + cb(it); + } +} + +void ClassStaticBlock::Dump(ir::AstDumper *dumper) const +{ + dumper->Add({{"type", "ClassStaticBlock"}, + {"accessibility", AstDumper::Optional(AstDumper::ModifierToString(modifiers_))}, + {"static", true}, + {"bodyFunction", bodyFunction_}, + {"decorators", decorators_}}); +} + +void ClassStaticBlock::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} + +checker::Type *ClassStaticBlock::Check([[maybe_unused]] checker::Checker *checker) const +{ + return nullptr; +} + +void ClassStaticBlock::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) +{ + bodyFunction_ = std::get(cb(bodyFunction_))->AsFunctionExpression(); + + for (auto iter = decorators_.begin(); iter != decorators_.end(); iter++) { + *iter = std::get(cb(*iter))->AsDecorator(); + } +} + +} // namespace panda::es2panda::ir + diff --git a/es2panda/ir/base/classStaticBlock.h b/es2panda/ir/base/classStaticBlock.h new file mode 100644 index 0000000000000000000000000000000000000000..c1286f18d767ce27b3d43b2a76579569174b2fbe --- /dev/null +++ b/es2panda/ir/base/classStaticBlock.h @@ -0,0 +1,88 @@ +/** + * Copyright (c) 2023 Shenzhen Kaihong Digital Industry Development 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. + */ + +#ifndef ES2PANDA_PARSER_INCLUDE_AST_STATIC_BLOCK_H +#define ES2PANDA_PARSER_INCLUDE_AST_STATIC_BLOCK_H + +#include + +namespace panda::es2panda::compiler { +class PandaGen; +} // namespace panda::es2panda::compiler + +namespace panda::es2panda::checker { +class Checker; +class Type; +} // namespace panda::es2panda::checker + +namespace panda::es2panda::ir { + +class Expression; + +class ClassStaticBlock : public Statement { +public: + explicit ClassStaticBlock(FunctionExpression *bodyFunction, + ModifierFlags modifiers, ArenaVector &&decorators) + : Statement(AstNodeType::CLASS_STATIC_BLOCK), + bodyFunction_(bodyFunction), + modifiers_(modifiers), + decorators_(std::move(decorators)) + { + } + + ModifierFlags Modifiers() const + { + return modifiers_; + } + + const FunctionExpression *BodyFunction() const + { + return bodyFunction_; + } + + bool IsStatic() const + { + return (modifiers_ & ModifierFlags::STATIC) != 0; + } + + bool IsOptional() const + { + return (modifiers_ & ModifierFlags::OPTIONAL) != 0; + } + + const ArenaVector &Decorators() const + { + return decorators_; + } + + 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; + checker::Type *Check([[maybe_unused]] checker::Checker *checker) const override; + void UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder) override; + +private: + FunctionExpression *bodyFunction_; + ModifierFlags modifiers_; + ArenaVector decorators_; +}; + +} // namespace panda::es2panda::ir + +#endif diff --git a/es2panda/ir/base/methodDefinition.cpp b/es2panda/ir/base/methodDefinition.cpp index b2ca65e9e2b94d3e90416dcd5a600b0473f5229c..10aa868e32e62fa55e2c8da86bfdbd485e64824b 100644 --- a/es2panda/ir/base/methodDefinition.cpp +++ b/es2panda/ir/base/methodDefinition.cpp @@ -76,6 +76,10 @@ void MethodDefinition::Dump(ir::AstDumper *dumper) const kind = "set"; break; } + case MethodDefinitionKind::STATIC_BLOCK: { + kind = "staticblock"; + break; + } default: { UNREACHABLE(); } diff --git a/es2panda/ir/base/methodDefinition.h b/es2panda/ir/base/methodDefinition.h index 1d3a1e2efa540dffd64cfe902934ac310626cf8f..7fccba34bb11a17528a1df73bbcd208fec5cc811 100644 --- a/es2panda/ir/base/methodDefinition.h +++ b/es2panda/ir/base/methodDefinition.h @@ -32,7 +32,7 @@ namespace panda::es2panda::ir { class Expression; class FunctionExpression; -enum class MethodDefinitionKind { CONSTRUCTOR, METHOD, GET, SET }; +enum class MethodDefinitionKind { CONSTRUCTOR, METHOD, GET, SET, STATIC_BLOCK }; struct ParamDecorators { size_t paramIndex; diff --git a/es2panda/ir/base/scriptFunction.h b/es2panda/ir/base/scriptFunction.h index 27944768b7d20cd865592750d61ed30648a88654..841b083a875df31777a268485b15ae8bb19ffb1f 100644 --- a/es2panda/ir/base/scriptFunction.h +++ b/es2panda/ir/base/scriptFunction.h @@ -155,6 +155,11 @@ public: return (flags_ & ir::ScriptFunctionFlags::METHOD) != 0; } + bool IsStaticBlock() const + { + return (flags_ & ir::ScriptFunctionFlags::STATIC_BLOCK) != 0; + } + bool FunctionBodyIsExpression() const { return (flags_ & ir::ScriptFunctionFlags::EXPRESSION) != 0; diff --git a/es2panda/lexer/lexer.cpp b/es2panda/lexer/lexer.cpp index 30fe69c2b6cb26dbb31154cfc1ecbaa52b104bca..fab6f150e009b1f8549afd5b1c5193b78639d2fc 100644 --- a/es2panda/lexer/lexer.cpp +++ b/es2panda/lexer/lexer.cpp @@ -1175,6 +1175,11 @@ void Lexer::SetTokenEnd() void Lexer::CheckAwaitKeyword() { + if (parserContext_->IsInStaticBlock() && + (parserContext_->Status() & parser::ParserStatus::FUNCTION_DECLARATION) == 0) { + ThrowError("'await' is not allowed in static initialization block"); + } + if (!parserContext_->IsAsync()) { GetToken().type_ = TokenType::LITERAL_IDENT; return; @@ -1187,6 +1192,15 @@ void Lexer::CheckAwaitKeyword() GetToken().type_ = TokenType::KEYW_AWAIT; } +void Lexer::CheckArgumentsKeyword() +{ + if (parserContext_->IsInStaticBlock()) { + ThrowError("'arguments' is not allowed in static initialization block"); + } + + GetToken().type_ = TokenType::LITERAL_IDENT; +} + void Lexer::CheckKeywordEscape(TokenType type) { if (GetToken().flags_ & TokenFlags::HAS_ESCAPE) { diff --git a/es2panda/lexer/lexer.h b/es2panda/lexer/lexer.h index 8e56da6ed23d1c25d7e6a9a3cce75474f5087611..33486491a4a7c2df7f3ba6f538bf3596c8e3fe7d 100644 --- a/es2panda/lexer/lexer.h +++ b/es2panda/lexer/lexer.h @@ -123,6 +123,7 @@ private: void CheckKeyword([[maybe_unused]] TokenType type, [[maybe_unused]] LexerNextTokenFlags flags); void CheckKeywordEscape(TokenType type); void CheckAwaitKeyword(); + void CheckArgumentsKeyword(); void CheckEnumKeyword(); void CheckLetKeyword(); void CheckYieldKeyword(); @@ -373,6 +374,12 @@ void Lexer::CheckKeyword([[maybe_unused]] TokenType type, [[maybe_unused]] Lexer return; } + // NOLINTNEXTLINE + if constexpr (keyword_type == TokenType::KEYW_ARGUMENTS) { + CheckArgumentsKeyword(); + return; + } + // NOLINTNEXTLINE if constexpr (keyword_type == TokenType::KEYW_ENUM) { CheckEnumKeyword(); diff --git a/es2panda/parser/context/parserContext.h b/es2panda/parser/context/parserContext.h index 984209c7741e34bf0d705137db224865b5cfbdac..fd14f249c214c3b622f33c6c8b629a5c47e083a9 100644 --- a/es2panda/parser/context/parserContext.h +++ b/es2panda/parser/context/parserContext.h @@ -62,6 +62,7 @@ enum class ParserStatus { DISALLOW_CONTINUE = (1 << 27), TS_MODULE = (1 << 28), + STATIC_BLOCK = (1 << 29), }; DEFINE_BITOPS(ParserStatus) @@ -122,6 +123,11 @@ public: return (status_ & ParserStatus::ASYNC_FUNCTION) != 0; } + bool IsInStaticBlock() const + { + return (status_ & ParserStatus::STATIC_BLOCK) != 0; + } + bool IsModule() const { return (status_ & ParserStatus::MODULE) != 0; diff --git a/es2panda/parser/expressionParser.cpp b/es2panda/parser/expressionParser.cpp index d63a59dd7bad0108709e899b5df29bbd5a9a6907..ee114b5000ceb9cecf022d796c0bc873a601bbfd 100644 --- a/es2panda/parser/expressionParser.cpp +++ b/es2panda/parser/expressionParser.cpp @@ -2374,6 +2374,9 @@ ir::FunctionExpression *ParserImpl::ParseFunctionExpression(ParserStatus newStat if (newStatus & ParserStatus::ASYNC_FUNCTION) { context_.Status() |= (ParserStatus::DISALLOW_AWAIT | ParserStatus::ASYNC_FUNCTION); } + if (context_.IsInStaticBlock()) { + context_.Status() |= ParserStatus::FUNCTION_DECLARATION; + } lexer_->NextToken(); @@ -2381,7 +2384,9 @@ ir::FunctionExpression *ParserImpl::ParseFunctionExpression(ParserStatus newStat newStatus |= ParserStatus::GENERATOR_FUNCTION; lexer_->NextToken(); } - + if (context_.IsInStaticBlock()) { + context_.Status() &= ~ParserStatus::FUNCTION_DECLARATION; + } if ((Extension() == ScriptExtension::JS && lexer_->GetToken().Type() != lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) || (Extension() == ScriptExtension::TS && diff --git a/es2panda/parser/parserImpl.cpp b/es2panda/parser/parserImpl.cpp index 3efaad027a83a8dbfbd2be2c7e7bcd263b5cf574..8b10373baa5211c263e6d49bce359e3cbfdc9753 100644 --- a/es2panda/parser/parserImpl.cpp +++ b/es2panda/parser/parserImpl.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -2154,7 +2155,7 @@ void ParserImpl::ParseClassKeyModifiers(ClassElmentDescriptor *desc) desc->methodKind = ir::MethodDefinitionKind::GET; desc->methodStart = lexer_->GetToken().Start(); - + desc->getOrSet = true; lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); CheckClassPrivateIdentifier(desc); } else if (lexer_->GetToken().KeywordType() == lexer::TokenType::KEYW_SET) { @@ -2164,7 +2165,7 @@ void ParserImpl::ParseClassKeyModifiers(ClassElmentDescriptor *desc) desc->methodKind = ir::MethodDefinitionKind::SET; desc->methodStart = lexer_->GetToken().Start(); - + desc->getOrSet = true; lexer_->NextToken(lexer::LexerNextTokenFlags::KEYWORD_TO_IDENT); CheckClassPrivateIdentifier(desc); } @@ -2300,6 +2301,16 @@ ir::Expression *ParserImpl::ParseClassKey(ClassElmentDescriptor *desc, bool isDe } break; } + case lexer::TokenType::PUNCTUATOR_LEFT_BRACE: { + if ((desc->modifiers & ir::ModifierFlags::STATIC) && (Extension() == ScriptExtension::JS) && + !desc->getOrSet) { + desc->staticBlock = true; + return propName; + } else { + ThrowSyntaxError("Unexpected token in class property"); + } + break; + } default: { ThrowSyntaxError("Unexpected token in class property"); } @@ -2445,14 +2456,62 @@ ir::MethodDefinition *ParserImpl::ParseClassMethod(ClassElmentDescriptor *desc, return method; } +ir::ClassStaticBlock* ParserImpl::ParseClassStaticBlock(ClassElmentDescriptor* desc, + lexer::SourcePosition* propEnd, + ArenaVector&& decorators) +{ + FunctionContext functionContext( + this, desc->newStatus | ParserStatus::STATIC_BLOCK | ParserStatus::FUNCTION | ParserStatus::ALLOW_NEW_TARGET); + + FunctionParameterContext funcParamContext(&context_, Binder()); + auto* funcParamScope = funcParamContext.LexicalScope().GetScope(); + + lexer::SourcePosition startLoc = lexer_->GetToken().Start(); + + ir::TSTypeParameterDeclaration* typeParamDecl = nullptr; + ArenaVector params(Allocator()->Adapter()); + ir::Expression* returnTypeAnnotation = nullptr; + + auto functionCtx = binder::LexicalScope(Binder()); + auto* functionScope = functionCtx.GetScope(); + functionScope->BindParamScope(funcParamScope); + funcParamScope->BindFunctionScope(functionScope); + + ir::BlockStatement* body = nullptr; + lexer::SourcePosition endLoc = lexer_->GetToken().End(); + + body = ParseBlockStatement(functionScope); + endLoc = body->End(); + *propEnd = body->End(); + lexer_->NextToken(); + auto* funcNode = AllocNode(functionScope, std::move(params), typeParamDecl, body, + returnTypeAnnotation, functionContext.Flags(), false, false); + functionScope->BindNode(funcNode); + funcParamScope->BindNode(funcNode); + funcNode->SetRange({ startLoc, endLoc }); + funcNode->AddFlag(ir::ScriptFunctionFlags::STATIC_BLOCK); + + auto* funcExpr = AllocNode(funcNode); + funcExpr->SetRange(funcNode->Range()); + ArenaVector paramDecorators(Allocator()->Adapter()); + auto* staticBlock = AllocNode(funcExpr, desc->modifiers, std::move(decorators)); + staticBlock->SetRange(funcExpr->Range()); + return staticBlock; +} + ir::Statement *ParserImpl::ParseClassProperty(ClassElmentDescriptor *desc, const ArenaVector &properties, ir::Expression *propName, ir::Expression *typeAnnotation, ArenaVector &&decorators, bool isDeclare) { - lexer::SourcePosition propEnd = propName->End(); + lexer::SourcePosition propEnd; ir::Statement *property = nullptr; + if (desc->staticBlock) { + property = ParseClassStaticBlock(desc, &propEnd, std::move(decorators)); + return property; + } + propEnd = propName->End(); if (desc->classMethod) { property = ParseClassMethod(desc, properties, propName, &propEnd, std::move(decorators), isDeclare); property->SetRange({desc->propStart, propEnd}); diff --git a/es2panda/parser/parserImpl.h b/es2panda/parser/parserImpl.h index 7350735c29b980fb97de59a8b9a957fd90db2dfb..812610efdcaa25fb94e54b7416c14cf70281e5d0 100644 --- a/es2panda/parser/parserImpl.h +++ b/es2panda/parser/parserImpl.h @@ -51,6 +51,7 @@ class BreakStatement; class CallExpression; class ClassDeclaration; class ClassDefinition; +class ClassStaticBlock; class ContinueStatement; class DoWhileStatement; class ExportAllDeclaration; @@ -139,6 +140,8 @@ public: bool isIndexSignature {}; bool classMethod {}; bool classField {}; + bool getOrSet {}; + bool staticBlock {}; }; class ArrowFunctionDescriptor { @@ -298,6 +301,8 @@ private: ir::MethodDefinition *ParseClassMethod(ClassElmentDescriptor *desc, const ArenaVector &properties, ir::Expression *propName, lexer::SourcePosition *propEnd, ArenaVector &&decorators, bool isDeclare); + ir::ClassStaticBlock *ParseClassStaticBlock(ClassElmentDescriptor *desc, lexer::SourcePosition *propEnd, + ArenaVector &&decorators); ir::Statement *ParseClassProperty(ClassElmentDescriptor *desc, const ArenaVector &properties, ir::Expression *propName, ir::Expression *typeAnnotation, ArenaVector &&decorators, bool isDeclare); @@ -677,6 +682,10 @@ public: if (newStatus & ParserStatus::CONSTRUCTOR_FUNCTION) { flags_ |= ir::ScriptFunctionFlags::CONSTRUCTOR; } + + if (newStatus & ParserStatus::STATIC_BLOCK) { + flags_ |= ir::ScriptFunctionFlags::STATIC_BLOCK; + } } ir::ScriptFunctionFlags Flags() const diff --git a/es2panda/parser/statementParser.cpp b/es2panda/parser/statementParser.cpp index b47cf9e724579517857fc0b0aa3a1aafee481c5d..89b66fc0bb9ec208d9151bb1dc83ca05bd8b8fd3 100644 --- a/es2panda/parser/statementParser.cpp +++ b/es2panda/parser/statementParser.cpp @@ -1631,7 +1631,7 @@ ir::LabelledStatement *ParserImpl::ParseLabelledStatement(const lexer::LexerPosi ir::ReturnStatement *ParserImpl::ParseReturnStatement() { - if (!(context_.Status() & ParserStatus::FUNCTION)) { + if (!(context_.Status() & ParserStatus::FUNCTION) || (context_.Status() & ParserStatus::STATIC_BLOCK)) { ThrowSyntaxError("return keyword should be used in function body"); } diff --git a/test262/es2022_tests.txt b/test262/es2022_tests.txt index b22438685be761c11453a72a61a7e382e34d9ac2..e2439cf2cbf0de45ccf98f60721773e67d8bad2c 100644 --- a/test262/es2022_tests.txt +++ b/test262/es2022_tests.txt @@ -120,4 +120,67 @@ built-ins/RegExp/prototype/hasIndices/name.js built-ins/RegExp/prototype/hasIndices/prop-desc.js built-ins/RegExp/prototype/hasIndices/this-val-invalid-obj.js built-ins/RegExp/prototype/hasIndices/this-val-non-obj.js -built-ins/RegExp/prototype/hasIndices/this-val-regexp.js \ No newline at end of file +built-ins/RegExp/prototype/hasIndices/this-val-regexp.js +language/expressions/arrow-function/static-init-await-binding.js +language/expressions/arrow-function/static-init-await-reference.js +language/expressions/class/static-init-await-binding.js +language/expressions/class/static-init-await-reference.js +language/expressions/function/static-init-await-binding.js +language/expressions/function/static-init-await-reference.js +language/expressions/generators/static-init-await-binding.js +language/expressions/generators/static-init-await-reference.js +language/expressions/object/ident-name-prop-name-literal-await-static-init.js +language/expressions/object/identifier-shorthand-static-init-await-invalid.js +language/expressions/object/identifier-shorthand-static-init-await-valid.js +language/expressions/object/method-definition/static-init-await-binding-accessor.js +language/expressions/object/method-definition/static-init-await-binding-generator.js +language/expressions/object/method-definition/static-init-await-binding-normal.js +language/expressions/object/method-definition/static-init-await-reference-accessor.js +language/expressions/object/method-definition/static-init-await-reference-generator.js +language/expressions/object/method-definition/static-init-await-reference-normal.js +language/identifier-resolution/static-init-invalid-await.js +language/statements/break/static-init-without-label.js +language/statements/class/static-init-abrupt.js +language/statements/class/static-init-arguments-functions.js +language/statements/class/static-init-arguments-methods.js +language/statements/class/static-init-await-binding-invalid.js +language/statements/class/static-init-await-binding-valid.js +language/statements/class/static-init-expr-new-target.js +language/statements/class/static-init-expr-this.js +language/statements/class/static-init-invalid-arguments.js +language/statements/class/static-init-invalid-await.js +language/statements/class/static-init-invalid-label-dup.js +language/statements/class/static-init-invalid-lex-dup.js +language/statements/class/static-init-invalid-lex-var.js +language/statements/class/static-init-invalid-return.js +language/statements/class/static-init-invalid-super-call.js +language/statements/class/static-init-invalid-undefined-break-target.js +language/statements/class/static-init-invalid-undefined-continue-target.js +language/statements/class/static-init-invalid-yield.js +language/statements/class/static-init-scope-lex-close.js +language/statements/class/static-init-scope-lex-derived.js +language/statements/class/static-init-scope-lex-open.js +language/statements/class/static-init-scope-private.js +language/statements/class/static-init-scope-var-close.js +language/statements/class/static-init-scope-var-derived.js +language/statements/class/static-init-scope-var-open.js +language/statements/class/static-init-sequence.js +language/statements/class/static-init-statement-list-optional.js +language/statements/class/static-init-super-property.js +language/statements/const/static-init-await-binding-invalid.js +language/statements/const/static-init-await-binding-valid.js +language/statements/continue/static-init-with-label.js +language/statements/continue/static-init-without-label.js +language/statements/function/static-init-await-binding-invalid.js +language/statements/function/static-init-await-binding-valid.js +language/statements/labeled/static-init-invalid-await.js +language/statements/let/static-init-await-binding-invalid.js +language/statements/let/static-init-await-binding-valid.js +language/statements/try/static-init-await-binding-invalid.js +language/statements/try/static-init-await-binding-valid.js +language/statements/variable/dstr/ary-ptrn-elem-id-static-init-await-invalid.js +language/statements/variable/dstr/ary-ptrn-elem-id-static-init-await-valid.js +language/statements/variable/dstr/obj-ptrn-elem-id-static-init-await-invalid.js +language/statements/variable/dstr/obj-ptrn-elem-id-static-init-await-valid.js +language/statements/variable/static-init-await-binding-invalid.js +language/statements/variable/static-init-await-binding-valid.js