diff --git a/es2panda/binder/binder.cpp b/es2panda/binder/binder.cpp index 03bce9e7eccbb9713a4b27c936aab667f7ee5d57..300b6dce25ee494ed34dd515af6a251daed51d14 100644 --- a/es2panda/binder/binder.cpp +++ b/es2panda/binder/binder.cpp @@ -396,7 +396,7 @@ void Binder::BuildScriptFunction(Scope *outerScope, const ir::ScriptFunction *sc } ASSERT(scope_->IsFunctionScope() || scope_->IsTSModuleScope() || scope_->IsTSEnumScope()); - BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(scriptFunc), scriptFunc); + BuildFunction(scope_->AsFunctionVariableScope(), util::Helpers::FunctionName(Allocator(), scriptFunc), scriptFunc); } void Binder::BuildVarDeclaratorId(const ir::AstNode *parent, ir::AstNode *childNode) diff --git a/es2panda/ir/base/classDefinition.cpp b/es2panda/ir/base/classDefinition.cpp index 14896cf5f382195cd79d4f8d9393d3600463d9a5..1dcd5c4eddc1e0c95657510f5b3cab3852116725 100644 --- a/es2panda/ir/base/classDefinition.cpp +++ b/es2panda/ir/base/classDefinition.cpp @@ -166,7 +166,7 @@ int32_t ClassDefinition::CreateClassStaticProperties(compiler::PandaGen *pg, uti continue; } - util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); + util::StringView name = util::Helpers::LiteralToPropName(pg->Allocator(), prop->Key()); compiler::LiteralBuffer *literalBuf = prop->IsStatic() ? &staticBuf : buf; auto &nameMap = prop->IsStatic() ? staticPropNameMap : propNameMap; diff --git a/es2panda/ir/expressions/objectExpression.cpp b/es2panda/ir/expressions/objectExpression.cpp index 2e5e0e924dc28594635ce8a394a7e5a50090116a..3c401ebb0bc6c7bbdb91bb2dd287392742c0706a 100644 --- a/es2panda/ir/expressions/objectExpression.cpp +++ b/es2panda/ir/expressions/objectExpression.cpp @@ -295,7 +295,7 @@ void ObjectExpression::CompileStaticProperties(compiler::PandaGen *pg, util::Bit } std::vector propBuf; - util::StringView name = util::Helpers::LiteralToPropName(prop->Key()); + util::StringView name = util::Helpers::LiteralToPropName(pg->Allocator(), prop->Key()); size_t propIndex = i; auto res = propNameMap.insert({name, propIndex}); if (res.second) { // name not found in map diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-bound-value-expected.txt b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-bound-value-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..e44681b5c21be5203cbbd8079f1b8c3bb38d0b4f --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-bound-value-expected.txt @@ -0,0 +1,8 @@ +1,000,000 +0.000001 +10,000,000 +1e-7 +1,000,000,000,000,000,000 +10,000,000,000,000,000,000 +100,000,000,000,000,000,000 +1,000,000,000,000,000,000,000 diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-bound-value.js b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-bound-value.js new file mode 100644 index 0000000000000000000000000000000000000000..0893fa1884c4662debc888c89e7f8c1bc6811601 --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-bound-value.js @@ -0,0 +1,19 @@ +let number = { + 1e6 : '1,000,000', + 1e-6 : '0.000001', + 1e7 : '10,000,000', + 1e-7 : '1e-7', + 1e18 : '1,000,000,000,000,000,000', + 1e19 : '10,000,000,000,000,000,000', + 1e20 : '100,000,000,000,000,000,000', + 1e21 : '1,000,000,000,000,000,000,000', +} + +print(number[1e6]); +print(number[1e-6]); +print(number[1e7]); +print(number[1e-7]); +print(number[1e18]); +print(number[1e19]); +print(number[1e20]); +print(number[1e21]); diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-diff-type-expected.txt b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-diff-type-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..8fda00d6d889695dcb90ed6cf04bbeb07dceaf87 --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-diff-type-expected.txt @@ -0,0 +1,5 @@ +A +B +C +D +E diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-diff-type.js b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-diff-type.js new file mode 100644 index 0000000000000000000000000000000000000000..4f87734766d24404ec251bfbaa1542abe3c9eeb4 --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-diff-type.js @@ -0,0 +1,13 @@ +let number = { + 1e3 : 'A', + 1E4 : 'B', + 100 : 'C', + 0.11 : 'D', + '1.11' : 'E' +} + +print(number[1e3]); +print(number[1E4]); +print(number[100]); +print(number[0.11]); +print(number[1.11]); diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-float-expected.txt b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-float-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..4fc803e1274e3eb6976c134acad5f06abf865da3 --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-float-expected.txt @@ -0,0 +1 @@ +1000,2000 diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-float.js b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-float.js new file mode 100644 index 0000000000000000000000000000000000000000..b9e662b20e59aad0b9c010e14c2c11e1286666ca --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-key-float.js @@ -0,0 +1,6 @@ +let number = { + 1e3 : '1000', + '2000' : 2e3 +} + +print(Object.keys(number)); diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-value-float-expected.txt b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-value-float-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..4fc803e1274e3eb6976c134acad5f06abf865da3 --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-value-float-expected.txt @@ -0,0 +1 @@ +1000,2000 diff --git a/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-value-float.js b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-value-float.js new file mode 100644 index 0000000000000000000000000000000000000000..438cc79a07ca61d5bc2432688b9c95c445ecec9e --- /dev/null +++ b/es2panda/test/compiler/js/language/arguments-object/test-obj-expr-value-float.js @@ -0,0 +1,6 @@ +let number = { + 1e3 : '1000', + '2000' : 2e3 +} + +print(Object.values(number)); diff --git a/es2panda/util/helpers.cpp b/es2panda/util/helpers.cpp index cd09d5cf089ce3f535f8913a7c6757f7b72de048..721fb0ad5faa2690da0d9fbcff1889529a4c0e73 100644 --- a/es2panda/util/helpers.cpp +++ b/es2panda/util/helpers.cpp @@ -70,7 +70,7 @@ bool Helpers::ContainSpreadElement(const ArenaVector &args) return std::any_of(args.begin(), args.end(), [](const auto *it) { return it->IsSpreadElement(); }); } -util::StringView Helpers::LiteralToPropName(const ir::Expression *lit) +util::StringView Helpers::LiteralToPropName(ArenaAllocator *allocator, const ir::Expression *lit) { switch (lit->Type()) { case ir::AstNodeType::IDENTIFIER: { @@ -80,7 +80,15 @@ util::StringView Helpers::LiteralToPropName(const ir::Expression *lit) return lit->AsStringLiteral()->Str(); } case ir::AstNodeType::NUMBER_LITERAL: { - return lit->AsNumberLiteral()->Str(); + auto strName = lit->AsNumberLiteral()->Str(); + auto numName = lit->AsNumberLiteral()->Number(); + + if ((strName.Find("e") != std::string::npos || strName.Find("E") != std::string::npos) && + std::fabs(numName) < MAX_LITERAL_FORMAT && std::fabs(numName) >= MIN_LITERAL_FORMAT) { + return util::Helpers::ToStringView(allocator, numName); + } + + return strName; } case ir::AstNodeType::NULL_LITERAL: { return "null"; @@ -149,12 +157,44 @@ bool Helpers::EndsWith(std::string_view str, std::string_view suffix) return str.find(suffix, expectPos) == expectPos; } +std::string Helpers::RemoveLastZero(std::string &str) +{ + uint32_t index = 0; + + if (str.empty() || str.find('.') == std::string::npos) { + return str; + } + + for (int i = str.size() - 1; i > 0; --i) { + if (str[i] == '.') { + index = i; + break; + } + if (str[i] != '0') { + index = i + 1; + break; + } + } + + return str.substr(0, index); +} + std::string Helpers::ToString(double number) { std::string str; - if (Helpers::IsInteger(number)) { - str = std::to_string(static_cast(number)); + if (std::fabs(number) <= static_cast(std::numeric_limits::max()) && + std::fabs(number) >= MIN_LITERAL_FORMAT) { + if (Helpers::IsInteger(number)) { + str = std::to_string(static_cast(number)); + } else { + str = std::to_string(number); + str = RemoveLastZero(str); + } + } else if (std::fabs(number) > static_cast(std::numeric_limits::max()) && + std::fabs(number) < MAX_LITERAL_FORMAT) { + str = std::to_string(number); + str = RemoveLastZero(str); } else { str = std::to_string(number); } @@ -332,7 +372,7 @@ std::vector Helpers::CollectBindingNames(const ir::AstNo return bindings; } -util::StringView Helpers::FunctionName(const ir::ScriptFunction *func) +util::StringView Helpers::FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func) { if (func->Id()) { return func->Id()->Name(); @@ -395,7 +435,7 @@ util::StringView Helpers::FunctionName(const ir::ScriptFunction *func) if (prop->Kind() != ir::PropertyKind::PROTO && Helpers::IsConstantPropertyKey(prop->Key(), prop->IsComputed())) { - return Helpers::LiteralToPropName(prop->Key()); + return Helpers::LiteralToPropName(allocator, prop->Key()); } break; diff --git a/es2panda/util/helpers.h b/es2panda/util/helpers.h index cc0e41cd397c058799996288d759643702b9092d..609e584744d597e9a25167b87b2bbe040031286e 100644 --- a/es2panda/util/helpers.h +++ b/es2panda/util/helpers.h @@ -59,7 +59,7 @@ public: static bool IsGlobalIdentifier(const util::StringView &str); static bool ContainSpreadElement(const ArenaVector &args); - static util::StringView LiteralToPropName(const ir::Expression *lit); + static util::StringView LiteralToPropName(ArenaAllocator *allocator, const ir::Expression *lit); template static bool IsInteger(double number); @@ -68,6 +68,7 @@ public: static bool FileExtensionIs(std::string_view filePath, std::string_view extension); static bool EndsWith(std::string_view str, std::string_view suffix); + static std::string RemoveLastZero(std::string &str); static std::string ToString(double number); static util::StringView ToStringView(ArenaAllocator *allocator, double number); static util::StringView ToStringView(ArenaAllocator *allocator, int32_t number); @@ -83,7 +84,7 @@ public: static bool IsBindingPattern(const ir::AstNode *node); static bool IsPattern(const ir::AstNode *node); static std::vector CollectBindingNames(const ir::AstNode *node); - static util::StringView FunctionName(const ir::ScriptFunction *func); + static util::StringView FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func); static std::tuple ParamName(ArenaAllocator *allocator, const ir::AstNode *param, uint32_t index); static bool IsChild(const ir::AstNode *parent, const ir::AstNode *child); @@ -96,6 +97,8 @@ public: static bool ReadFileToBuffer(const std::string &file, std::stringstream &ss); static void SetFuncFlagsForDirectives(ir::ScriptFunction *func, const lexer::LineIndex &lineIndex); + static constexpr double MAX_LITERAL_FORMAT = 1e21; + static constexpr double MIN_LITERAL_FORMAT = 1e-6; static const uint32_t INVALID_INDEX = 4294967295L; static const uint32_t MAX_INT32 = 2147483647; static const uint32_t MAX_INT16 = std::numeric_limits::max(); diff --git a/es2panda/util/ustring.h b/es2panda/util/ustring.h index dc73aaf4e1f07af186483a84adea0bfb3665096a..52976ee8acabd2c235cb2bafb73229d6c880a2ed 100644 --- a/es2panda/util/ustring.h +++ b/es2panda/util/ustring.h @@ -109,7 +109,7 @@ public: return StringView(std::string_view(sv_.data() + begin, end - begin)); } - constexpr size_t Find(const char *str) + constexpr size_t Find(const char *str) const { return sv_.find(str); }