From 7694bbe1071ccbbbca92ebda5d905cadae00200f Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Tue, 28 Mar 2023 19:54:19 +0300 Subject: [PATCH] Implement dynamic object List of changes: * Add builtin package: std.interop.js.* * Add ability to access property by dot for dynamic objects * Add automatic conversion of primitive types to a dynamic object Signed-off-by: Vyacheslav Cherkashin --- BUILD.gn | 1 + CMakeLists.txt | 1 + binder/ETSBinder.h | 1 + checker/ETSchecker.cpp | 10 + checker/ETSchecker.h | 2 + checker/ets/object.cpp | 7 + checker/ets/typeCreation.cpp | 4 + checker/types/ets/etsDynamicType.cpp | 57 +++ checker/types/ets/etsDynamicType.h | 43 ++ checker/types/ets/etsObjectType.h | 6 + checker/types/ets/types.h | 1 + checker/types/globalTypesHolder.cpp | 14 + checker/types/globalTypesHolder.h | 7 + checker/types/type.h | 12 + checker/types/typeFlag.h | 5 +- compiler/base/lreference.cpp | 6 +- compiler/core/ETSGen.cpp | 241 ++++++++++ compiler/core/ETSGen.h | 6 + compiler/scripts/signatures.yaml | 216 +++++++++ ir/expressions/assignmentExpression.cpp | 5 + ir/expressions/memberExpression.cpp | 6 +- parser/ETSparser.cpp | 2 +- test/parser/ets/test_jsvalue-expected.txt | 136 ++++++ test/parser/ets/test_jsvalue.ets | 16 + .../ets/test_jsvalue_get_double-expected.txt | 200 ++++++++ test/parser/ets/test_jsvalue_get_double.ets | 17 + .../test_jsvalue_get_property_1-expected.txt | 258 +++++++++++ .../ets/test_jsvalue_get_property_1.ets | 17 + .../test_jsvalue_get_property_2-expected.txt | 288 ++++++++++++ .../ets/test_jsvalue_get_property_2.ets | 17 + .../ets/test_jsvalue_set_double-expected.txt | 309 +++++++++++++ test/parser/ets/test_jsvalue_set_double.ets | 19 + .../test_jsvalue_set_property_1-expected.txt | 426 ++++++++++++++++++ .../ets/test_jsvalue_set_property_1.ets | 20 + .../test_jsvalue_set_property_2-expected.txt | 339 ++++++++++++++ .../ets/test_jsvalue_set_property_2.ets | 19 + 36 files changed, 2730 insertions(+), 4 deletions(-) create mode 100644 checker/types/ets/etsDynamicType.cpp create mode 100644 checker/types/ets/etsDynamicType.h create mode 100644 test/parser/ets/test_jsvalue-expected.txt create mode 100644 test/parser/ets/test_jsvalue.ets create mode 100644 test/parser/ets/test_jsvalue_get_double-expected.txt create mode 100644 test/parser/ets/test_jsvalue_get_double.ets create mode 100644 test/parser/ets/test_jsvalue_get_property_1-expected.txt create mode 100644 test/parser/ets/test_jsvalue_get_property_1.ets create mode 100644 test/parser/ets/test_jsvalue_get_property_2-expected.txt create mode 100644 test/parser/ets/test_jsvalue_get_property_2.ets create mode 100644 test/parser/ets/test_jsvalue_set_double-expected.txt create mode 100644 test/parser/ets/test_jsvalue_set_double.ets create mode 100644 test/parser/ets/test_jsvalue_set_property_1-expected.txt create mode 100644 test/parser/ets/test_jsvalue_set_property_1.ets create mode 100644 test/parser/ets/test_jsvalue_set_property_2-expected.txt create mode 100644 test/parser/ets/test_jsvalue_set_property_2.ets diff --git a/BUILD.gn b/BUILD.gn index c2048e00c..bf2af5b4b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -291,6 +291,7 @@ libes2panda_sources = [ "checker/types/ets/shortType.cpp", "checker/types/ets/etsArrayType.cpp", "checker/types/ets/etsBooleanType.cpp", + "checker/types/ets/etsDynamicType.cpp", "checker/types/ets/etsEnumType.cpp", "checker/types/ets/etsFunctionType.cpp", "checker/types/ets/etsObjectType.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index 15edd4845..69ddbfe53 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -341,6 +341,7 @@ set(ES2PANDA_LIB_SRC checker/types/ets/shortType.cpp checker/types/ets/etsArrayType.cpp checker/types/ets/etsBooleanType.cpp + checker/types/ets/etsDynamicType.cpp checker/types/ets/etsEnumType.cpp checker/types/ets/etsFunctionType.cpp checker/types/ets/etsObjectType.cpp diff --git a/binder/ETSBinder.h b/binder/ETSBinder.h index 7f89722bf..2646d99b3 100644 --- a/binder/ETSBinder.h +++ b/binder/ETSBinder.h @@ -140,6 +140,7 @@ import * from "std/core"; import * from "std/math"; import * from "std/containers"; import * from "std/time"; +import * from "std/interop/js"; )"; private: diff --git a/checker/ETSchecker.cpp b/checker/ETSchecker.cpp index 658e1be5f..9eb169998 100644 --- a/checker/ETSchecker.cpp +++ b/checker/ETSchecker.cpp @@ -226,6 +226,16 @@ ETSObjectType *ETSChecker::GlobalBuiltinPromiseType() const return AsETSObjectType(&GlobalTypesHolder::GlobalPromiseBuiltinType); } +ETSObjectType *ETSChecker::GlobalBuiltinJSRuntimeType() const +{ + return AsETSObjectType(&GlobalTypesHolder::GlobalJSRuntimeBuiltinType); +} + +ETSObjectType *ETSChecker::GlobalBuiltinJSValueType() const +{ + return AsETSObjectType(&GlobalTypesHolder::GlobalJSValueBuiltinType); +} + const checker::WrapperDesc &ETSChecker::PrimitiveWrapper() const { return primitive_wrappers_.Wrappers(); diff --git a/checker/ETSchecker.h b/checker/ETSchecker.h index e7ea123fc..eb4a4baaf 100644 --- a/checker/ETSchecker.h +++ b/checker/ETSchecker.h @@ -123,6 +123,8 @@ public: ETSObjectType *GlobalBuiltinPanicType() const; ETSObjectType *GlobalStringBuilderBuiltinType() const; ETSObjectType *GlobalBuiltinPromiseType() const; + ETSObjectType *GlobalBuiltinJSRuntimeType() const; + ETSObjectType *GlobalBuiltinJSValueType() const; const checker::WrapperDesc &PrimitiveWrapper() const; diff --git a/checker/ets/object.cpp b/checker/ets/object.cpp index e2c6235b4..e3600e726 100644 --- a/checker/ets/object.cpp +++ b/checker/ets/object.cpp @@ -48,6 +48,7 @@ #include "plugins/ecmascript/es2panda/binder/declaration.h" #include "plugins/ecmascript/es2panda/binder/ETSBinder.h" #include "plugins/ecmascript/es2panda/checker/ETSchecker.h" +#include "plugins/ecmascript/es2panda/checker/types/ets/etsDynamicType.h" #include "plugins/ecmascript/es2panda/checker/types/ets/types.h" #include "plugins/ecmascript/es2panda/checker/ets/typeRelationContext.h" @@ -961,6 +962,12 @@ void ETSChecker::ValidateResolvedProperty(const binder::LocalVariable *const pro binder::LocalVariable *ETSChecker::ResolveMemberReference(const ir::MemberExpression *const member_expr, const ETSObjectType *const target) { + if (target->IsETSDynamicType()) { + auto prop_name = member_expr->Property()->AsIdentifier()->Name(); + binder::LocalVariable *prop_var = target->AsETSDynamicType()->GetPropertyDynamic(prop_name, this); + return prop_var; + } + auto search_flag = [member_expr]() { const auto base_flags = PropertySearchFlags::SEARCH_IN_BASE | PropertySearchFlags::SEARCH_IN_INTERFACES; diff --git a/checker/ets/typeCreation.cpp b/checker/ets/typeCreation.cpp index 701a89972..dfd28c9fe 100644 --- a/checker/ets/typeCreation.cpp +++ b/checker/ets/typeCreation.cpp @@ -293,6 +293,10 @@ ETSObjectType *ETSChecker::CreateNewETSObjectType(util::StringView name, ir::Ast assembler_name = full_path.View(); } + if (ETSDynamicType::IsDynamicType(assembler_name)) { + return Allocator()->New(Allocator(), name, assembler_name, decl_node, flags); + } + return Allocator()->New(Allocator(), name, assembler_name, decl_node, flags); } diff --git a/checker/types/ets/etsDynamicType.cpp b/checker/types/ets/etsDynamicType.cpp new file mode 100644 index 000000000..990f744bb --- /dev/null +++ b/checker/types/ets/etsDynamicType.cpp @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2023 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. + */ + +#include "etsDynamicType.h" +#include "plugins/ecmascript/es2panda/checker/ETSchecker.h" + +namespace panda::es2panda::checker { + +/*static*/ +bool ETSDynamicType::IsDynamicType(util::StringView assembler_name) +{ + return assembler_name == compiler::Signatures::BUILTIN_JSVALUE; +} + +binder::LocalVariable *ETSDynamicType::GetPropertyDynamic(const util::StringView &name, const ETSChecker *checker) const +{ + auto it = properties_cache_.find(name); + if (it != properties_cache_.end()) { + return it->second; + } + + binder::LocalVariable *var = + binder::Scope::CreateVar(Allocator(), name, binder::VariableFlags::BUILTIN_TYPE, nullptr); + var->SetTsType(checker->GlobalBuiltinJSValueType()); + properties_cache_.emplace(name, var); + + return var; +} + +void ETSDynamicType::AssignmentTarget(TypeRelation *relation, Type *source) +{ + if (source->HasTypeFlag(checker::TypeFlag::ETS_TYPE_TO_DYNAMIC)) { + relation->Result(true); + } +} + +bool ETSDynamicType::AssignmentSource(TypeRelation *relation, Type *target) +{ + if (target->HasTypeFlag(checker::TypeFlag::ETS_TYPE_TO_DYNAMIC)) { + relation->Result(true); + } + return relation->IsTrue(); +} + +} // namespace panda::es2panda::checker diff --git a/checker/types/ets/etsDynamicType.h b/checker/types/ets/etsDynamicType.h new file mode 100644 index 000000000..38d8c990b --- /dev/null +++ b/checker/types/ets/etsDynamicType.h @@ -0,0 +1,43 @@ +/** + * Copyright (c) 2023 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. + */ + +#ifndef ES2PANDA_COMPILER_CHECKER_TYPES_ETS_DYNAMIC_TYPE_H +#define ES2PANDA_COMPILER_CHECKER_TYPES_ETS_DYNAMIC_TYPE_H + +#include "plugins/ecmascript/es2panda/checker/types/ets/etsObjectType.h" + +namespace panda::es2panda::checker { +class ETSDynamicType : public ETSObjectType { +public: + explicit ETSDynamicType(ArenaAllocator *allocator, util::StringView name, util::StringView assembler_name, + ir::AstNode *decl_node, ETSObjectFlags flags) + : ETSObjectType(allocator, name, assembler_name, decl_node, flags | ETSObjectFlags::DYNAMIC), + properties_cache_ {allocator->Adapter()} + { + AddTypeFlag(TypeFlag::ETS_DYNAMIC_TYPE); + } + + static bool IsDynamicType(util::StringView assembler_name); + + binder::LocalVariable *GetPropertyDynamic(const util::StringView &name, const ETSChecker *checker) const; + void AssignmentTarget(TypeRelation *relation, Type *source) override; + bool AssignmentSource(TypeRelation *relation, Type *target) override; + +private: + mutable PropertyMap properties_cache_; +}; +} // namespace panda::es2panda::checker + +#endif diff --git a/checker/types/ets/etsObjectType.h b/checker/types/ets/etsObjectType.h index 118ab3460..186c73fb1 100644 --- a/checker/types/ets/etsObjectType.h +++ b/checker/types/ets/etsObjectType.h @@ -43,6 +43,7 @@ enum class ETSObjectFlags : uint32_t { STRING = 1U << 13U, INCOMPLETE_INSTANTIATION = 1U << 14U, INNER = 1U << 15U, + DYNAMIC = 1U << 16U, BUILTIN_STRING = 1U << 23U, BUILTIN_BOOLEAN = 1U << 24U, @@ -451,6 +452,11 @@ public: ss << compiler::Signatures::GENERIC_END; } + ArenaAllocator *Allocator() const + { + return allocator_; + } + private: template explicit ETSObjectType(ArenaAllocator *allocator, util::StringView name, util::StringView assembler_name, diff --git a/checker/types/ets/types.h b/checker/types/ets/types.h index 9c1d3d7e1..576278b9d 100644 --- a/checker/types/ets/types.h +++ b/checker/types/ets/types.h @@ -29,6 +29,7 @@ #include "etsVoidType.h" #include "etsStringType.h" #include "etsObjectType.h" +#include "etsDynamicType.h" #include "etsArrayType.h" #include "wildcardType.h" #include "etsTypeReference.h" diff --git a/checker/types/globalTypesHolder.cpp b/checker/types/globalTypesHolder.cpp index 35e0dae23..e4aeb68e1 100644 --- a/checker/types/globalTypesHolder.cpp +++ b/checker/types/globalTypesHolder.cpp @@ -133,6 +133,10 @@ GlobalTypesHolder::GlobalTypesHolder(ArenaAllocator *allocator) : builtin_name_m builtin_name_mappings_.emplace("Type", GlobalTypeId::ETS_TYPE_BUILTIN); builtin_name_mappings_.emplace("Types", GlobalTypeId::ETS_TYPES_BUILTIN); builtin_name_mappings_.emplace("Promise", GlobalTypeId::ETS_PROMISE_BUILTIN); + + // ETS interop js specific types + builtin_name_mappings_.emplace("JSRuntime", GlobalTypeId::ETS_INTEROP_JSRUNTIME_BUILTIN); + builtin_name_mappings_.emplace("JSValue", GlobalTypeId::ETS_INTEROP_JSVALUE_BUILTIN); } Type *GlobalTypesHolder::GlobalNumberType() @@ -490,6 +494,16 @@ Type *GlobalTypesHolder::GlobalPromiseBuiltinType() return global_types_.at(static_cast(GlobalTypeId::ETS_PROMISE_BUILTIN)); } +Type *GlobalTypesHolder::GlobalJSRuntimeBuiltinType() +{ + return global_types_.at(static_cast(GlobalTypeId::ETS_INTEROP_JSRUNTIME_BUILTIN)); +} + +Type *GlobalTypesHolder::GlobalJSValueBuiltinType() +{ + return global_types_.at(static_cast(GlobalTypeId::ETS_INTEROP_JSVALUE_BUILTIN)); +} + void GlobalTypesHolder::InitializeBuiltin(const util::StringView name, Type *type) { const auto type_id = builtin_name_mappings_.find(name); diff --git a/checker/types/globalTypesHolder.h b/checker/types/globalTypesHolder.h index ecd27f3cc..7fa4f8834 100644 --- a/checker/types/globalTypesHolder.h +++ b/checker/types/globalTypesHolder.h @@ -92,6 +92,9 @@ enum class GlobalTypeId { ETS_TYPE_BUILTIN, ETS_TYPES_BUILTIN, ETS_PROMISE_BUILTIN, + ETS_INTEROP_JSRUNTIME_BUILTIN, + ETS_INTEROP_JSVALUE_BUILTIN, + COUNT, }; @@ -177,6 +180,10 @@ public: Type *GlobalTypesBuiltinType(); Type *GlobalPromiseBuiltinType(); + // JS specific types + Type *GlobalJSRuntimeBuiltinType(); + Type *GlobalJSValueBuiltinType(); + void InitializeBuiltin(util::StringView name, Type *type); using Holder = std::array(GlobalTypeId::COUNT)>; diff --git a/checker/types/type.h b/checker/types/type.h index a33a6c316..10e51980a 100644 --- a/checker/types/type.h +++ b/checker/types/type.h @@ -32,6 +32,7 @@ class Variable; namespace panda::es2panda::checker { class ObjectDescriptor; class GlobalTypesHolder; +class ETSDynamicType; // NOLINTNEXTLINE(cppcoreguidelines-macro-usage) #define DECLARE_TYPENAMES(typeFlag, typeName) class typeName; @@ -91,6 +92,17 @@ public: return reinterpret_cast(this); } + bool IsETSDynamicType() const + { + return TypeFlags() == TypeFlag::ETS_DYNAMIC_TYPE; + } + + const ETSDynamicType *AsETSDynamicType() const + { + ASSERT(IsETSDynamicType()); + return reinterpret_cast(this); + } + TypeFlag TypeFlags() const { return type_flags_; diff --git a/checker/types/typeFlag.h b/checker/types/typeFlag.h index 51d8dcd48..ae069c958 100644 --- a/checker/types/typeFlag.h +++ b/checker/types/typeFlag.h @@ -74,8 +74,10 @@ enum class TypeFlag : uint64_t { ETS_TYPE_REFERENCE = 1ULL << 49ULL, // ETS type reference GENERIC = 1ULL << 50ULL, // ETS Generic ETS_ENUM = 1ULL << 51ULL, // ETS Enum + ETS_DYNAMIC_FLAG = 1ULL << 52ULL, // ETS Dynamic flag + ETS_DYNAMIC_TYPE = ETS_OBJECT | ETS_DYNAMIC_FLAG, ETS_TYPE = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN | ETS_VOID | ETS_OBJECT | ETS_ARRAY | - WILDCARD | ETS_TYPE_PARAMETER | ETS_ENUM, + WILDCARD | ETS_TYPE_PARAMETER | ETS_ENUM | ETS_DYNAMIC_TYPE, ETS_PRIMITIVE = BYTE | SHORT | INT | LONG | FLOAT | DOUBLE | CHAR | ETS_BOOLEAN | ETS_VOID, ETS_ARRAY_INDEX = BYTE | SHORT | INT, ETS_INTEGRAL = BYTE | CHAR | SHORT | INT | LONG, @@ -83,6 +85,7 @@ enum class TypeFlag : uint64_t { ETS_NUMERIC = ETS_INTEGRAL | FLOAT | DOUBLE, ETS_ARRAY_OR_OBJECT = ETS_ARRAY | ETS_OBJECT, ETS_WIDE_NUMERIC = LONG | DOUBLE, + ETS_TYPE_TO_DYNAMIC = ETS_NUMERIC, VALID_SWITCH_TYPE = BYTE | SHORT | INT | CHAR | LONG | ETS_ENUM, NARROWABLE_TO_FLOAT = DOUBLE, NARROWABLE_TO_LONG = FLOAT | NARROWABLE_TO_FLOAT, diff --git a/compiler/base/lreference.cpp b/compiler/base/lreference.cpp index 4747b50ea..5017ab26b 100644 --- a/compiler/base/lreference.cpp +++ b/compiler/base/lreference.cpp @@ -281,7 +281,11 @@ void ETSLReference::SetValue() const break; } - etsg_->StoreProperty(Node(), member_expr->TsType(), base_reg_, prop_name); + if (static_obj_ref_->IsETSDynamicType()) { + etsg_->StorePropertyDynamic(Node(), member_expr->TsType(), base_reg_, prop_name); + } else { + etsg_->StoreProperty(Node(), member_expr->TsType(), base_reg_, prop_name); + } break; } default: { diff --git a/compiler/core/ETSGen.cpp b/compiler/core/ETSGen.cpp index 13c5c5ed1..ed54593ea 100644 --- a/compiler/core/ETSGen.cpp +++ b/compiler/core/ETSGen.cpp @@ -285,6 +285,88 @@ void ETSGen::LoadProperty(const ir::AstNode *node, const checker::Type *prop_typ SetAccumulatorType(prop_type); } +void ETSGen::StorePropertyDynamic(const ir::AstNode *node, const checker::Type *prop_type, VReg obj_reg, + const util::StringView &prop_name) +{ + std::string_view method_name {}; + if (prop_type->IsETSBooleanType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_BOOLEAN; + } else if (prop_type->IsByteType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_BYTE; + } else if (prop_type->IsCharType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_CHAR; + } else if (prop_type->IsShortType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_SHORT; + } else if (prop_type->IsIntType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_INT; + } else if (prop_type->IsLongType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_LONG; + } else if (prop_type->IsFloatType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_FLOAT; + } else if (prop_type->IsDoubleType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_DOUBLE; + } else if (prop_type->IsETSObjectType()) { + ASSERT(prop_type->IsETSDynamicType()); + method_name = Signatures::BUILTIN_JSRUNTIME_SET_PROPERTY_JSVALUE; + } else { + ASSERT_PRINT(false, "Unsupported property type"); + } + + RegScope rs(this); + + // Load property value + VReg prop_value_reg = AllocReg(); + StoreAccumulator(node, prop_value_reg); + + // Load property name + LoadAccumulatorString(node, prop_name); + VReg prop_name_reg = AllocReg(); + StoreAccumulator(node, prop_name_reg); + + // Set property by name + Ra().Emit(node, method_name, obj_reg, prop_name_reg, prop_value_reg, dummy_reg_); + SetAccumulatorType(Checker()->GlobalVoidType()); +} + +void ETSGen::LoadPropertyDynamic(const ir::AstNode *node, const checker::Type *prop_type, VReg obj_reg, + const util::StringView &prop_name) +{ + std::string_view method_name {}; + if (prop_type->IsETSBooleanType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_BOOLEAN; + } else if (prop_type->IsByteType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_BYTE; + } else if (prop_type->IsCharType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_CHAR; + } else if (prop_type->IsShortType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_SHORT; + } else if (prop_type->IsIntType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_INT; + } else if (prop_type->IsLongType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_LONG; + } else if (prop_type->IsFloatType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_FLOAT; + } else if (prop_type->IsDoubleType()) { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_DOUBLE; + } else if (prop_type->IsETSObjectType()) { + ASSERT(prop_type->IsETSDynamicType()); + method_name = Signatures::BUILTIN_JSRUNTIME_GET_PROPERTY_JSVALUE; + } else { + ASSERT_PRINT(false, "Unsupported property type"); + } + + RegScope rs(this); + + // Load property name + LoadAccumulatorString(node, prop_name); + VReg prop_name_object = AllocReg(); + StoreAccumulator(node, prop_name_object); + + // Get property by name + Ra().Emit(node, method_name, obj_reg, prop_name_object); + SetAccumulatorType(prop_type); +} + void ETSGen::LoadThis(const ir::AstNode *node) { LoadAccumulator(node, GetThisReg()); @@ -515,6 +597,10 @@ void ETSGen::ApplyConversion(const ir::AstNode *node, const checker::Type *targe CastToLong(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastToDynamic(node); + break; + } default: { break; } @@ -663,6 +749,11 @@ void ETSGen::CastToBoolean([[maybe_unused]] const ir::AstNode *node) Sa().Emit(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::BOOLEAN); + ASSERT(GetAccumulatorType() == Checker()->GlobalETSBooleanType()); + break; + } default: { UNREACHABLE(); } @@ -700,6 +791,11 @@ void ETSGen::CastToByte([[maybe_unused]] const ir::AstNode *node) Sa().Emit(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::BYTE); + ASSERT(GetAccumulatorType() == Checker()->GlobalByteType()); + break; + } default: { UNREACHABLE(); } @@ -738,6 +834,11 @@ void ETSGen::CastToChar([[maybe_unused]] const ir::AstNode *node) Sa().Emit(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::CHAR); + ASSERT(GetAccumulatorType() == Checker()->GlobalCharType()); + break; + } default: { UNREACHABLE(); } @@ -775,6 +876,11 @@ void ETSGen::CastToShort([[maybe_unused]] const ir::AstNode *node) Sa().Emit(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::SHORT); + ASSERT(GetAccumulatorType() == Checker()->GlobalShortType()); + break; + } default: { UNREACHABLE(); } @@ -806,6 +912,11 @@ void ETSGen::CastToDouble(const ir::AstNode *node) case checker::TypeFlag::DOUBLE: { return; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::DOUBLE); + ASSERT(GetAccumulatorType() == Checker()->GlobalDoubleType()); + break; + } default: { UNREACHABLE(); } @@ -837,6 +948,11 @@ void ETSGen::CastToFloat(const ir::AstNode *node) Sa().Emit(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::FLOAT); + ASSERT(GetAccumulatorType() == Checker()->GlobalFloatType()); + break; + } default: { UNREACHABLE(); } @@ -868,6 +984,11 @@ void ETSGen::CastToLong(const ir::AstNode *node) Sa().Emit(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::LONG); + ASSERT(GetAccumulatorType() == Checker()->GlobalLongType()); + break; + } default: { UNREACHABLE(); } @@ -900,6 +1021,11 @@ void ETSGen::CastToInt(const ir::AstNode *node) Sa().Emit(node); break; } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + CastDynamicTo(node, checker::TypeFlag::INT); + ASSERT(GetAccumulatorType() == Checker()->GlobalIntType()); + break; + } default: { UNREACHABLE(); } @@ -933,6 +1059,121 @@ void ETSGen::CastToString(const ir::AstNode *const node) SetAccumulatorType(Checker()->GetGlobalTypesHolder()->GlobalETSStringBuiltinType()); } +void ETSGen::CastToDynamic(const ir::AstNode *node) +{ + std::string_view method_name {}; + auto type_kind = checker::ETSChecker::TypeKind(GetAccumulatorType()); + switch (type_kind) { + case checker::TypeFlag::ETS_BOOLEAN: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_BOOLEAN; + break; + } + case checker::TypeFlag::BYTE: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_BYTE; + break; + } + case checker::TypeFlag::CHAR: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_CHAR; + break; + } + case checker::TypeFlag::SHORT: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_SHORT; + break; + } + case checker::TypeFlag::INT: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_INT; + break; + } + case checker::TypeFlag::LONG: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_LONG; + break; + } + case checker::TypeFlag::FLOAT: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_FLOAT; + break; + } + case checker::TypeFlag::DOUBLE: { + method_name = Signatures::BUILTIN_JSRUNTIME_NEW_JSVALUE_DOUBLE; + break; + } + case checker::TypeFlag::ETS_DYNAMIC_TYPE: { + return; + } + default: { + UNREACHABLE(); + } + } + + RegScope rs(this); + // Load value + VReg val_reg = AllocReg(); + StoreAccumulator(node, val_reg); + + // Create new JSValue and initialize it + Ra().Emit(node, method_name, val_reg, dummy_reg_); + SetAccumulatorType(Checker()->GlobalBuiltinJSValueType()); +} + +void ETSGen::CastDynamicTo(const ir::AstNode *node, enum checker::TypeFlag type_flag) +{ + std::string_view method_name {}; + checker::Type *object_type {}; + switch (type_flag) { + case checker::TypeFlag::ETS_BOOLEAN: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_BOOLEAN; + object_type = Checker()->GlobalETSBooleanType(); + break; + } + case checker::TypeFlag::BYTE: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_BYTE; + object_type = Checker()->GlobalByteType(); + break; + } + case checker::TypeFlag::CHAR: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_CHAR; + object_type = Checker()->GlobalCharType(); + break; + } + case checker::TypeFlag::SHORT: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_SHORT; + object_type = Checker()->GlobalShortType(); + break; + } + case checker::TypeFlag::INT: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_INT; + object_type = Checker()->GlobalIntType(); + break; + } + case checker::TypeFlag::LONG: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_LONG; + object_type = Checker()->GlobalLongType(); + break; + } + case checker::TypeFlag::FLOAT: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_FLOAT; + object_type = Checker()->GlobalFloatType(); + break; + } + case checker::TypeFlag::DOUBLE: { + method_name = Signatures::BUILTIN_JSRUNTIME_GET_VALUE_DOUBLE; + object_type = Checker()->GlobalDoubleType(); + break; + } + default: { + UNREACHABLE(); + } + } + + RegScope rs(this); + // Load dynamic object + VReg dyn_obj_reg = AllocReg(); + StoreAccumulator(node, dyn_obj_reg); + + // Get value from dynamic object + Ra().Emit(node, method_name, dyn_obj_reg, dummy_reg_); + SetAccumulatorType(object_type); +} + void ETSGen::EmitCheckedNarrowingReferenceConversion(const ir::AstNode *const node, const checker::Type *const target_type) { diff --git a/compiler/core/ETSGen.h b/compiler/core/ETSGen.h index 735efe7cd..c53f21daa 100644 --- a/compiler/core/ETSGen.h +++ b/compiler/core/ETSGen.h @@ -78,6 +78,10 @@ public: const util::StringView &name); void LoadProperty(const ir::AstNode *node, const checker::Type *prop_type, VReg obj_reg, const util::StringView &name); + void StorePropertyDynamic(const ir::AstNode *node, const checker::Type *prop_type, VReg obj_reg, + const util::StringView &name); + void LoadPropertyDynamic(const ir::AstNode *node, const checker::Type *prop_type, VReg obj_reg, + const util::StringView &prop_name); void LoadThis(const ir::AstNode *node); VReg &GetThisReg(); @@ -220,6 +224,8 @@ public: void CastToLong(const ir::AstNode *node); void CastToInt(const ir::AstNode *node); void CastToString(const ir::AstNode *node); + void CastToDynamic(const ir::AstNode *node); + void CastDynamicTo(const ir::AstNode *node, enum checker::TypeFlag type_flag); void CastToArrayOrObject(const ir::AstNode *node, const checker::Type *target_type, bool unchecked); void EmitCheckedNarrowingReferenceConversion(const ir::AstNode *node, const checker::Type *target_type); diff --git a/compiler/scripts/signatures.yaml b/compiler/scripts/signatures.yaml index a7e12f1d7..5bd4a6f33 100644 --- a/compiler/scripts/signatures.yaml +++ b/compiler/scripts/signatures.yaml @@ -94,6 +94,8 @@ packages: ref: PKG_STD_CORE - name: 'std.math' ref: PKG_STD_MATH + - name: 'std.interop.js' + ref: PKG_STD_INTEROP_JS primitives: - name: u1 @@ -221,6 +223,12 @@ builtins: - name: Promise package: PKG_STD_CORE ref: BUILTIN_PROMISE + - name: JSRuntime + package: PKG_STD_INTEROP_JS + ref: BUILTIN_JSRUNTIME + - name: JSValue + package: PKG_STD_INTEROP_JS + ref: BUILTIN_JSVALUE signatures: - callee: BUILTIN_OBJECT @@ -420,3 +428,211 @@ signatures: params: [] return_type: PRIMITIVE_DOUBLE ref: BUILTIN_DOUBLE_UNBOXED + + # BUILTIN_JSRUNTIME_NEW_JSVALUE_ + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueBoolean + params: [PRIMITIVE_BOOLEAN] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_BOOLEAN + + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueByte + params: [PRIMITIVE_BYTE] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_BYTE + + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueChar + params: [PRIMITIVE_CHAR] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_CHAR + + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueShort + params: [PRIMITIVE_SHORT] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_SHORT + + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueInt + params: [PRIMITIVE_INT] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_INT + + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueLong + params: [PRIMITIVE_LONG] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_LONG + + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueFloat + params: [PRIMITIVE_FLOAT] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_FLOAT + + - callee: BUILTIN_JSRUNTIME + method_name: newJSValueDouble + params: [PRIMITIVE_DOUBLE] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_NEW_JSVALUE_DOUBLE + + # BUILTIN_JSRUNTIME_GET_VALUE_ + - callee: BUILTIN_JSRUNTIME + method_name: getValueBoolean + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_BOOLEAN + ref: BUILTIN_JSRUNTIME_GET_VALUE_BOOLEAN + + - callee: BUILTIN_JSRUNTIME + method_name: getValueByte + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_BYTE + ref: BUILTIN_JSRUNTIME_GET_VALUE_BYTE + + - callee: BUILTIN_JSRUNTIME + method_name: getValueChar + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_CHAR + ref: BUILTIN_JSRUNTIME_GET_VALUE_CHAR + + - callee: BUILTIN_JSRUNTIME + method_name: getValueShort + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_SHORT + ref: BUILTIN_JSRUNTIME_GET_VALUE_SHORT + + - callee: BUILTIN_JSRUNTIME + method_name: getValueInt + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_INT + ref: BUILTIN_JSRUNTIME_GET_VALUE_INT + + - callee: BUILTIN_JSRUNTIME + method_name: getValueLong + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_LONG + ref: BUILTIN_JSRUNTIME_GET_VALUE_LONG + + - callee: BUILTIN_JSRUNTIME + method_name: getValueFloat + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_FLOAT + ref: BUILTIN_JSRUNTIME_GET_VALUE_FLOAT + + - callee: BUILTIN_JSRUNTIME + method_name: getValueDouble + params: [BUILTIN_JSVALUE] + return_type: PRIMITIVE_DOUBLE + ref: BUILTIN_JSRUNTIME_GET_VALUE_DOUBLE + + # BUILTIN_JSRUNTIME_GET_PROPERTY_ + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyBoolean + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_BOOLEAN + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_BOOLEAN + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyByte + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_BYTE + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_BYTE + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyChar + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_CHAR + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_CHAR + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyShort + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_SHORT + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_SHORT + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyInt + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_INT + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_INT + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyLong + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_LONG + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_LONG + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyFloat + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_FLOAT + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_FLOAT + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyDouble + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: PRIMITIVE_DOUBLE + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_DOUBLE + + - callee: BUILTIN_JSRUNTIME + method_name: getPropertyJSValue + params: [BUILTIN_JSVALUE, BUILTIN_STRING] + return_type: BUILTIN_JSVALUE + ref: BUILTIN_JSRUNTIME_GET_PROPERTY_JSVALUE + + # BUILTIN_JSRUNTIME_SET_PROPERTY_ + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyBoolean + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_BOOLEAN] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_BOOLEAN + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyByte + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_BYTE] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_BYTE + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyChar + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_CHAR] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_CHAR + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyShort + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_SHORT] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_SHORT + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyInt + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_INT] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_INT + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyLong + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_LONG] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_LONG + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyFloat + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_FLOAT] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_FLOAT + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyDouble + params: [BUILTIN_JSVALUE, BUILTIN_STRING, PRIMITIVE_DOUBLE] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_DOUBLE + + - callee: BUILTIN_JSRUNTIME + method_name: setPropertyJSValue + params: [BUILTIN_JSVALUE, BUILTIN_STRING, BUILTIN_JSVALUE] + return_type: PRIMITIVE_VOID + ref: BUILTIN_JSRUNTIME_SET_PROPERTY_JSVALUE diff --git a/ir/expressions/assignmentExpression.cpp b/ir/expressions/assignmentExpression.cpp index 650e18b21..0631d7e43 100644 --- a/ir/expressions/assignmentExpression.cpp +++ b/ir/expressions/assignmentExpression.cpp @@ -283,6 +283,11 @@ checker::Type *AssignmentExpression::Check([[maybe_unused]] checker::ETSChecker break; } case lexer::TokenType::PUNCTUATOR_SUBSTITUTION: { + if (left_type->IsETSDynamicType() && right_type->HasTypeFlag(checker::TypeFlag::ETS_TYPE_TO_DYNAMIC)) { + // Update the left dynamic type if it can be converted to the right type + left_->SetTsType(right_type); + } + bin_type = right_type; break; } diff --git a/ir/expressions/memberExpression.cpp b/ir/expressions/memberExpression.cpp index 03d45b4b4..df105b6ce 100644 --- a/ir/expressions/memberExpression.cpp +++ b/ir/expressions/memberExpression.cpp @@ -171,7 +171,11 @@ void MemberExpression::Compile(compiler::ETSGen *etsg) const etsg->StoreAccumulator(this, obj_reg); auto ttctx = compiler::TargetTypeContext(etsg, TsType()); - etsg->LoadProperty(this, TsType(), obj_reg, prop_name); + if (object_->TsType()->IsETSDynamicType()) { + etsg->LoadPropertyDynamic(this, TsType(), obj_reg, prop_name); + } else { + etsg->LoadProperty(this, TsType(), obj_reg, prop_name); + } etsg->ApplyConversion(this); } diff --git a/parser/ETSparser.cpp b/parser/ETSparser.cpp index 8c5489925..ed30e7635 100644 --- a/parser/ETSparser.cpp +++ b/parser/ETSparser.cpp @@ -231,7 +231,7 @@ static bool IsCompitableExtension(const std::string &extension) std::vector ETSParser::CollectExternalSources() { std::vector paths; - std::vector stdlib = {"std/core", "std/math", "std/containers", "std/time"}; + std::vector stdlib = {"std/core", "std/math", "std/containers", "std/time", "std/interop/js"}; #ifdef USE_UNIX_SYSCALL for (auto const &path : stdlib) { diff --git a/test/parser/ets/test_jsvalue-expected.txt b/test/parser/ets/test_jsvalue-expected.txt new file mode 100644 index 000000000..5b5d8b3c9 --- /dev/null +++ b/test/parser/ets/test_jsvalue-expected.txt @@ -0,0 +1,136 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 17, + "column": 1 + } + } +} diff --git a/test/parser/ets/test_jsvalue.ets b/test/parser/ets/test_jsvalue.ets new file mode 100644 index 000000000..acf09c211 --- /dev/null +++ b/test/parser/ets/test_jsvalue.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023 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 v: JSValue; diff --git a/test/parser/ets/test_jsvalue_get_double-expected.txt b/test/parser/ets/test_jsvalue_get_double-expected.txt new file mode 100644 index 000000000..1fdcb8d77 --- /dev/null +++ b/test/parser/ets/test_jsvalue_get_double-expected.txt @@ -0,0 +1,200 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "num_v", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + "value": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 1 + } + } +} diff --git a/test/parser/ets/test_jsvalue_get_double.ets b/test/parser/ets/test_jsvalue_get_double.ets new file mode 100644 index 000000000..427ee04bd --- /dev/null +++ b/test/parser/ets/test_jsvalue_get_double.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 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 v: JSValue; +let num_v: double = v; diff --git a/test/parser/ets/test_jsvalue_get_property_1-expected.txt b/test/parser/ets/test_jsvalue_get_property_1-expected.txt new file mode 100644 index 000000000..07e4be2fa --- /dev/null +++ b/test/parser/ets/test_jsvalue_get_property_1-expected.txt @@ -0,0 +1,258 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "prop", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "value": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "property": { + "type": "Identifier", + "name": "prop_name", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 32 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 32 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 1 + } + } +} diff --git a/test/parser/ets/test_jsvalue_get_property_1.ets b/test/parser/ets/test_jsvalue_get_property_1.ets new file mode 100644 index 000000000..58b85b91a --- /dev/null +++ b/test/parser/ets/test_jsvalue_get_property_1.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 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 v: JSValue; +let prop: JSValue = v.prop_name; diff --git a/test/parser/ets/test_jsvalue_get_property_2-expected.txt b/test/parser/ets/test_jsvalue_get_property_2-expected.txt new file mode 100644 index 000000000..51db34a87 --- /dev/null +++ b/test/parser/ets/test_jsvalue_get_property_2-expected.txt @@ -0,0 +1,288 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 5 + }, + "end": { + "line": 16, + "column": 6 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 15 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 8 + }, + "end": { + "line": 16, + "column": 16 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + { + "type": "ClassProperty", + "key": { + "type": "Identifier", + "name": "prop", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 9 + } + } + }, + "value": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 22 + } + } + }, + "property": { + "type": "Identifier", + "name": "prop_name_1", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 23 + }, + "end": { + "line": 17, + "column": 34 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 34 + } + } + }, + "property": { + "type": "Identifier", + "name": "prop_name_2", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 35 + }, + "end": { + "line": 17, + "column": 46 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 17, + "column": 21 + }, + "end": { + "line": 17, + "column": 46 + } + } + }, + "accessibility": "public", + "static": true, + "readonly": false, + "declare": false, + "optional": false, + "computed": false, + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 18 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 11 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "definite": false, + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 18, + "column": 1 + } + } +} diff --git a/test/parser/ets/test_jsvalue_get_property_2.ets b/test/parser/ets/test_jsvalue_get_property_2.ets new file mode 100644 index 000000000..a11328f99 --- /dev/null +++ b/test/parser/ets/test_jsvalue_get_property_2.ets @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2023 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 v: JSValue; +let prop: JSValue = v.prop_name_1.prop_name_2; diff --git a/test/parser/ets/test_jsvalue_set_double-expected.txt b/test/parser/ets/test_jsvalue_set_double-expected.txt new file mode 100644 index 000000000..00e6d822e --- /dev/null +++ b/test/parser/ets/test_jsvalue_set_double-expected.txt @@ -0,0 +1,309 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "fn", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "fn", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 16 + }, + "end": { + "line": 16, + "column": 20 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "v", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 10 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 6 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 63.74, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 14 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 15 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 1 + } + } +} diff --git a/test/parser/ets/test_jsvalue_set_double.ets b/test/parser/ets/test_jsvalue_set_double.ets new file mode 100644 index 000000000..ada3ec5b2 --- /dev/null +++ b/test/parser/ets/test_jsvalue_set_double.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 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 fn(): void { + let v: JSValue; + v = 63.74; +} diff --git a/test/parser/ets/test_jsvalue_set_property_1-expected.txt b/test/parser/ets/test_jsvalue_set_property_1-expected.txt new file mode 100644 index 000000000..3ddcd615b --- /dev/null +++ b/test/parser/ets/test_jsvalue_set_property_1-expected.txt @@ -0,0 +1,426 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "fn", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "fn", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 16 + }, + "end": { + "line": 16, + "column": 20 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "v", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 10 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "new_prop_value", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 32 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 25 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 23 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 18, + "column": 9 + }, + "end": { + "line": 18, + "column": 23 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 33 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 6 + } + } + }, + "property": { + "type": "Identifier", + "name": "prop_name", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 7 + }, + "end": { + "line": 19, + "column": 16 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 16 + } + } + }, + "right": { + "type": "Identifier", + "name": "new_prop_value", + "decorators": [], + "loc": { + "start": { + "line": 19, + "column": 19 + }, + "end": { + "line": 19, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 33 + } + } + }, + "loc": { + "start": { + "line": 19, + "column": 5 + }, + "end": { + "line": 19, + "column": 34 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 20, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 20, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 21, + "column": 1 + } + } +} diff --git a/test/parser/ets/test_jsvalue_set_property_1.ets b/test/parser/ets/test_jsvalue_set_property_1.ets new file mode 100644 index 000000000..386beaea0 --- /dev/null +++ b/test/parser/ets/test_jsvalue_set_property_1.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2023 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 fn(): void { + let v: JSValue; + let new_prop_value: JSValue; + v.prop_name = new_prop_value; +} diff --git a/test/parser/ets/test_jsvalue_set_property_2-expected.txt b/test/parser/ets/test_jsvalue_set_property_2-expected.txt new file mode 100644 index 000000000..714334b8b --- /dev/null +++ b/test/parser/ets/test_jsvalue_set_property_2-expected.txt @@ -0,0 +1,339 @@ +{ + "type": "Program", + "statements": [ + { + "type": "ClassDeclaration", + "definition": { + "id": { + "type": "Identifier", + "name": "ETSGLOBAL", + "decorators": [], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "superClass": null, + "implements": [], + "body": [ + { + "type": "MethodDefinition", + "key": { + "type": "Identifier", + "name": "fn", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "kind": "method", + "accessibility": "public", + "static": true, + "optional": false, + "computed": false, + "value": { + "type": "FunctionExpression", + "function": { + "type": "ScriptFunction", + "id": { + "type": "Identifier", + "name": "fn", + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 10 + }, + "end": { + "line": 16, + "column": 12 + } + } + }, + "generator": false, + "async": false, + "expression": false, + "params": [], + "returnType": { + "type": "ETSPrimitiveType", + "loc": { + "start": { + "line": 16, + "column": 16 + }, + "end": { + "line": 16, + "column": 20 + } + } + }, + "body": { + "type": "BlockStatement", + "statements": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "v", + "typeAnnotation": { + "type": "ETSTypeReference", + "part": { + "type": "ETSTypeReferencePart", + "name": { + "type": "Identifier", + "name": "JSValue", + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 19 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "loc": { + "start": { + "line": 17, + "column": 12 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + "decorators": [], + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 10 + } + } + }, + "init": null, + "loc": { + "start": { + "line": 17, + "column": 9 + }, + "end": { + "line": 17, + "column": 10 + } + } + } + ], + "kind": "let", + "loc": { + "start": { + "line": 17, + "column": 5 + }, + "end": { + "line": 17, + "column": 20 + } + } + }, + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "v", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 6 + } + } + }, + "property": { + "type": "Identifier", + "name": "prop_name", + "decorators": [], + "loc": { + "start": { + "line": 18, + "column": 7 + }, + "end": { + "line": 18, + "column": 16 + } + } + }, + "computed": false, + "optional": false, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 16 + } + } + }, + "right": { + "type": "NumberLiteral", + "value": 5.6, + "loc": { + "start": { + "line": 18, + "column": 19 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 22 + } + } + }, + "loc": { + "start": { + "line": 18, + "column": 5 + }, + "end": { + "line": 18, + "column": 23 + } + } + } + ], + "loc": { + "start": { + "line": 16, + "column": 21 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "loc": { + "start": { + "line": 16, + "column": 12 + }, + "end": { + "line": 19, + "column": 2 + } + } + }, + "overloads": [], + "decorators": [], + "loc": { + "start": { + "line": 16, + "column": 1 + }, + "end": { + "line": 19, + "column": 2 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + }, + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 1, + "column": 1 + } + } + } + ], + "loc": { + "start": { + "line": 1, + "column": 1 + }, + "end": { + "line": 20, + "column": 1 + } + } +} diff --git a/test/parser/ets/test_jsvalue_set_property_2.ets b/test/parser/ets/test_jsvalue_set_property_2.ets new file mode 100644 index 000000000..de8dc1144 --- /dev/null +++ b/test/parser/ets/test_jsvalue_set_property_2.ets @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2023 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 fn(): void { + let v: JSValue; + v.prop_name = 5.6; +} -- Gitee