From 27e251413ad7ccdc0e940892fb97577c4adb0e59 Mon Sep 17 00:00:00 2001 From: wuwenlu Date: Wed, 20 Sep 2023 01:46:26 -0700 Subject: [PATCH] static block for class Signed-off-by: wuwenlu --- es2panda/BUILD.gn | 1 + es2panda/compiler/core/pandagen.cpp | 2 +- es2panda/ir/astNode.h | 3 +- es2panda/ir/astNodeMapping.h | 1 + es2panda/ir/base/classDefinition.cpp | 31 +++++++++ es2panda/ir/base/classDefinition.h | 1 + es2panda/ir/base/classStaticBlock.cpp | 73 ++++++++++++++++++++ es2panda/ir/base/classStaticBlock.h | 88 +++++++++++++++++++++++++ es2panda/ir/base/methodDefinition.cpp | 4 ++ es2panda/ir/base/methodDefinition.h | 2 +- es2panda/ir/base/scriptFunction.h | 5 ++ es2panda/lexer/lexer.cpp | 14 ++++ es2panda/lexer/lexer.h | 7 ++ es2panda/parser/context/parserContext.h | 6 ++ es2panda/parser/expressionParser.cpp | 7 +- es2panda/parser/parserImpl.cpp | 65 +++++++++++++++++- es2panda/parser/parserImpl.h | 9 +++ es2panda/parser/statementParser.cpp | 2 +- test262/es2022_tests.txt | 65 +++++++++++++++++- 19 files changed, 377 insertions(+), 9 deletions(-) create mode 100644 es2panda/ir/base/classStaticBlock.cpp create mode 100644 es2panda/ir/base/classStaticBlock.h diff --git a/es2panda/BUILD.gn b/es2panda/BUILD.gn index 788719bab9..47eca20c74 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 0eb85b5cbc..681e3d7a6b 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 82f1d30853..53207b9a91 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 fb75caa922..918712bfae 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 1dcd5c4edd..9bedbb2c99 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 b008cabe92..aab010389a 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 0000000000..29ef50b142 --- /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 0000000000..c1286f18d7 --- /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 b2ca65e9e2..10aa868e32 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 1d3a1e2efa..7fccba34bb 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 27944768b7..841b083a87 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 30fe69c2b6..fab6f150e0 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 8e56da6ed2..33486491a4 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 984209c774..fd14f249c2 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 d63a59dd7b..ee114b5000 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 3efaad027a..8b10373baa 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 7350735c29..812610efdc 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 b47cf9e724..89b66fc0bb 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 b22438685b..e2439cf2cb 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 -- Gitee