diff --git a/ets2panda/ir/module/exportSpecifier.cpp b/ets2panda/ir/module/exportSpecifier.cpp index 1133414d19f41eb489e3847f49e98fb98041246f..1c28d57fe53a0f57a6606771288018944388a220 100644 --- a/ets2panda/ir/module/exportSpecifier.cpp +++ b/ets2panda/ir/module/exportSpecifier.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-2025 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 @@ -48,6 +48,12 @@ void ExportSpecifier::Dump(ir::AstDumper *dumper) const void ExportSpecifier::Dump(ir::SrcDumper *dumper) const { + if (GetConstantExpression() != nullptr) { + GetConstantExpression()->Dump(dumper); + dumper->Add("as default"); + return; + } + exported_->Dump(dumper); if (local_ != nullptr) { diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 5541ac57d5cccf3e8bd73bceeebf9e07e9ab73a1..c6fc097575f7dc25ee55b62f53a6715f81fdf2db 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -1123,17 +1123,36 @@ ir::Statement *ETSParser::CreateReExportDeclarationNode(ir::ETSImportDeclaration return reExport; } +ir::Statement *ETSParser::ParseDefaultIfSingleExport(ir::ModifierFlags modifiers) +{ + auto tokenType = Lexer()->GetToken().Type(); + if (tokenType != lexer::TokenType::PUNCTUATOR_LEFT_BRACE) { + return ParseSingleExport(modifiers); + } + auto savePos = Lexer()->Save(); + Lexer()->NextToken(); + auto isSelectiveExport = Lexer()->TryEatTokenType(lexer::TokenType::LITERAL_IDENT) && + (Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_COMMA || + Lexer()->GetToken().Type() == lexer::TokenType::KEYW_AS || + Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE); + Lexer()->Rewind(savePos); + return !isSelectiveExport ? ParseSingleExport(modifiers) : nullptr; +} + ir::Statement *ETSParser::ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers) { const size_t exportDefaultMaxSize = 1; if (!InAmbientContext() && (GetContext().Status() & ParserStatus::IN_NAMESPACE) != 0) { LogError(diagnostic::EXPORT_IN_NAMESPACE); } - [[maybe_unused]] auto tokenType = Lexer()->GetToken().Type(); // export a constant variable anonymously, as export default new A() - if ((modifiers & ir::ModifierFlags::DEFAULT_EXPORT) != 0U && tokenType != lexer::TokenType::PUNCTUATOR_MULTIPLY && - tokenType != lexer::TokenType::PUNCTUATOR_LEFT_BRACE && tokenType != lexer::TokenType::LITERAL_IDENT) { - return ParseSingleExport(modifiers); + if ((modifiers & ir::ModifierFlags::DEFAULT_EXPORT) != 0U && + Lexer()->GetToken().Type() != lexer::TokenType::PUNCTUATOR_MULTIPLY && + Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + auto exportedExpression = ParseDefaultIfSingleExport(modifiers); + if (exportedExpression != nullptr) { + return exportedExpression; + } } ArenaVector specifiers(Allocator()->Adapter()); @@ -1366,6 +1385,10 @@ ir::ExportNamedDeclaration *ETSParser::ParseSingleExport(ir::ModifierFlags modif return ParseSingleExportForAnonymousConst(modifiers); } + if (token.KeywordType() == lexer::TokenType::KEYW_AS) { + LogError(diagnostic::ERROR_ARKTS_NO_UMD, {}, token.Start()); + return nullptr; + } if (token.Type() != lexer::TokenType::LITERAL_IDENT) { LogError(diagnostic::EXPORT_NON_DECLARATION, {}, token.Start()); return nullptr; @@ -1498,6 +1521,12 @@ SpecifiersInfo ETSParser::ParseNamedSpecifiers() ArenaVector resultDefault(Allocator()->Adapter()); ArenaVector resultExportDefault(Allocator()->Adapter()); + auto token = Lexer()->GetToken(); + if (token.Ident() == (lexer::TokenToString(lexer::TokenType::KEYW_IMPORT)) && + token.Type() == lexer::TokenType::PUNCTUATOR_RIGHT_BRACE) { + LogError(diagnostic::ERROR_ARKTS_NO_SIDE_EFFECT_IMPORT); + } + ParseList( lexer::TokenType::PUNCTUATOR_RIGHT_BRACE, lexer::NextTokenFlags::KEYWORD_TO_IDENT, [this, &result, &resultDefault, &resultExportDefault, &fileName]() { @@ -1552,6 +1581,10 @@ void ETSParser::ParseNameSpaceSpecifier(ArenaVector *specifiers, ir::AstNode *ETSParser::ParseImportDefaultSpecifier(ArenaVector *specifiers) { + if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_STRING) { + LogError(diagnostic::ERROR_ARKTS_NO_SIDE_EFFECT_IMPORT); + return nullptr; + } if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { LogExpectedToken(lexer::TokenType::LITERAL_IDENT); } diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index 8dddff53b552b11d0a614b68096e469630cd1ceb..c92657f13900e3aae4ff74cca6efcb43f2b286a4 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -302,6 +302,7 @@ private: ExpressionParseFlags flags = ExpressionParseFlags::NO_OPTS) override; ir::Statement *ParseTryStatement() override; ir::Statement *ParseDebuggerStatement() override; + ir::Statement *ParseDefaultIfSingleExport(ir::ModifierFlags modifiers); ir::Statement *ParseExport(lexer::SourcePosition startLoc, ir::ModifierFlags modifiers); ir::Statement *ParseImportDeclaration(StatementParsingFlags flags) override; ir::Statement *ParseExportDeclaration(StatementParsingFlags flags) override; diff --git a/ets2panda/parser/expressionParser.cpp b/ets2panda/parser/expressionParser.cpp index 596a70e086461c7b6ffc6648ae3bc186c78da65e..6c329cba1af6cd2a661a684d6e48a8a9e2ed5f06 100644 --- a/ets2panda/parser/expressionParser.cpp +++ b/ets2panda/parser/expressionParser.cpp @@ -1599,6 +1599,9 @@ ir::MemberExpression *ParserImpl::ParsePrivatePropertyAccess(ir::Expression *pri auto *privateIdent = AllocNode(lexer_->GetToken().Ident(), Allocator()); ES2PANDA_ASSERT(privateIdent != nullptr); + if (program_->Extension() == util::gen::extension::ETS && privateIdent->Name().Is("prototype")) { + LogError(diagnostic::PROTOTYPE_ACCESS); + } privateIdent->SetRange({memberStart, lexer_->GetToken().End()}); privateIdent->SetPrivate(true); lexer_->NextToken(); @@ -1613,6 +1616,9 @@ ir::MemberExpression *ParserImpl::ParsePrivatePropertyAccess(ir::Expression *pri ir::MemberExpression *ParserImpl::ParsePropertyAccess(ir::Expression *primaryExpr, bool isOptional) { ir::Identifier *ident = ExpectIdentifier(true); + if (program_->Extension() == util::gen::extension::ETS && ident->Name().Is("prototype")) { + LogError(diagnostic::PROTOTYPE_ACCESS); + } auto *memberExpr = AllocNode(primaryExpr, ident, ir::MemberExpressionKind::PROPERTY_ACCESS, false, isOptional); ES2PANDA_ASSERT(memberExpr != nullptr); diff --git a/ets2panda/test/ast/parser/ets/export_as.ets b/ets2panda/test/ast/parser/ets/export_as.ets new file mode 100644 index 0000000000000000000000000000000000000000..f2c130fbe82e2eb4dc9f52b8c778f816c0390894 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/export_as.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +export /* @@ label1 */as /* @@ label2 */namespace mathLib {} + +/* @@@ label1 Error SyntaxError: Universal module definitions are not supported, please use ordinary import/export syntax instead. */ +/* @@@ label1 Error SyntaxError: Unexpected token 'as'. */ +/* @@@ label2 Error SyntaxError: Unexpected token 'namespace'. */ diff --git a/ets2panda/test/ast/parser/ets/import_no_empty_binding_list.ets b/ets2panda/test/ast/parser/ets/import_no_empty_binding_list.ets new file mode 100644 index 0000000000000000000000000000000000000000..dd2ff3124f685c3e2ecc51514d1e4a27b8f41f38 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/import_no_empty_binding_list.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 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. + */ + +import {/* @@ label1 */} /* @@ label2 */from /* @@ label3 */'module' + +/* @@@ label1 Error SyntaxError: Importing for side-effect only is prohibited! Please provide objects to be imported explicitly or use * to import all objects declared in the module! */ +/* @@@ label2 Error TypeError: Unresolved reference from */ +/* @@@ label3 Error SyntaxError: Unexpected token 'module'. */ diff --git a/ets2panda/test/ast/parser/ets/import_no_side_effect.ets b/ets2panda/test/ast/parser/ets/import_no_side_effect.ets new file mode 100644 index 0000000000000000000000000000000000000000..cd4d80cab0b0de58957e3a3cec521d46be29cc37 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/import_no_side_effect.ets @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2025 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. + */ + +import /* @@ label1 */'module' + +/* @@@ label1 Error SyntaxError: Importing for side-effect only is prohibited! Please provide objects to be imported explicitly or use * to import all objects declared in the module! */ diff --git a/ets2panda/test/ast/parser/ets/no_prototype.ets b/ets2panda/test/ast/parser/ets/no_prototype.ets new file mode 100644 index 0000000000000000000000000000000000000000..2f70cb7112e9d176b0c326e6865da24e13facf2e --- /dev/null +++ b/ets2panda/test/ast/parser/ets/no_prototype.ets @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2025 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 {} + +C.prototype = Object.prototype + +C.prototype = { + m() { + console.log("C.m()") + } +} + +/* @@? 18:3 Error TypeError: Property 'prototype' does not exist on type 'C' */ +/* @@? 18:13 Error SyntaxError: Runtime prototype assignment is not supported because of static typing */ +/* @@? 18:22 Error TypeError: Property 'prototype' does not exist on type 'Object' */ +/* @@? 20:1 Error SyntaxError: Runtime prototype assignment is not supported because of static typing */ +/* @@? 20:3 Error TypeError: Property 'prototype' does not exist on type 'C' */ +/* @@? 20:13 Error SyntaxError: Runtime prototype assignment is not supported because of static typing */ +/* @@? 21:4 Error SyntaxError: Unexpected token, expected ':'. */ +/* @@? 21:5 Error SyntaxError: Unexpected token ')'. */ +/* @@? 21:7 Error SyntaxError: Unexpected token. */ +/* @@? 22:12 Error SyntaxError: Unexpected token, expected ':'. */ +/* @@? 24:1 Error SyntaxError: Unexpected token '}'. */ diff --git a/ets2panda/test/runtime/ets/defaultExportObjectLiteral_exp.ets b/ets2panda/test/runtime/ets/defaultExportObjectLiteral_exp.ets new file mode 100644 index 0000000000000000000000000000000000000000..885d31856d248e4b5846195e93be02b324b5ad0f --- /dev/null +++ b/ets2panda/test/runtime/ets/defaultExportObjectLiteral_exp.ets @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 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. + */ + +interface User { + name: string; + age: number; + email: string; +}; + +export default { + name: 'John Doe', + age: 30, + email: 'johndoe@example.com' +} as User; diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index a998b7eacc637388b76862e1f7d1c186d3e43878..9a9440342d68c36cb550610b74158cd609639d22 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -225,6 +225,15 @@ syntax: id: 312 message: "Importing by 'require' and 'import' assignment is not supported, use 'import * as ... from ...' form instead!" +- name: ERROR_ARKTS_NO_SIDE_EFFECT_IMPORT + id: 73297 + message: "Importing for side-effect only is prohibited! Please provide objects to be imported explicitly or use * to import + all objects declared in the module!" + +- name: ERROR_ARKTS_NO_UMD + id: 114179 + message: "Universal module definitions are not supported, please use ordinary import/export syntax instead." + - name: ERROR_ARKTS_NO_VAR id: 297 message: "'var' keyword is not supported. Use 'let' instead." @@ -941,6 +950,10 @@ syntax: id: 238 message: "Methods or fields should not be decorated with {} in ambient class." +- name: PROTOTYPE_ACCESS + id: 30818 + message: "Runtime prototype assignment is not supported because of static typing" + - name: QUANTIFIER_OUT_OF_ORDER id: 78 message: "Quantifier range out of order."