13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License.
53af6ab5fSopenharmony_ci * You may obtain a copy of the License at
63af6ab5fSopenharmony_ci *
73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0
83af6ab5fSopenharmony_ci *
93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and
133af6ab5fSopenharmony_ci * limitations under the License.
143af6ab5fSopenharmony_ci */
153af6ab5fSopenharmony_ci
163af6ab5fSopenharmony_ci#include "objectExpression.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include <util/helpers.h>
193af6ab5fSopenharmony_ci#include <compiler/base/literals.h>
203af6ab5fSopenharmony_ci#include <compiler/core/pandagen.h>
213af6ab5fSopenharmony_ci#include <typescript/checker.h>
223af6ab5fSopenharmony_ci#include <typescript/core/destructuringContext.h>
233af6ab5fSopenharmony_ci#include <ir/astDump.h>
243af6ab5fSopenharmony_ci#include <ir/base/classDefinition.h>
253af6ab5fSopenharmony_ci#include <ir/base/property.h>
263af6ab5fSopenharmony_ci#include <ir/base/scriptFunction.h>
273af6ab5fSopenharmony_ci#include <ir/base/spreadElement.h>
283af6ab5fSopenharmony_ci#include <ir/expressions/arrayExpression.h>
293af6ab5fSopenharmony_ci#include <ir/expressions/arrowFunctionExpression.h>
303af6ab5fSopenharmony_ci#include <ir/expressions/assignmentExpression.h>
313af6ab5fSopenharmony_ci#include <ir/expressions/classExpression.h>
323af6ab5fSopenharmony_ci#include <ir/expressions/functionExpression.h>
333af6ab5fSopenharmony_ci#include <ir/expressions/identifier.h>
343af6ab5fSopenharmony_ci#include <ir/expressions/literals/nullLiteral.h>
353af6ab5fSopenharmony_ci#include <ir/expressions/literals/numberLiteral.h>
363af6ab5fSopenharmony_ci#include <ir/expressions/literals/stringLiteral.h>
373af6ab5fSopenharmony_ci#include <ir/expressions/literals/taggedLiteral.h>
383af6ab5fSopenharmony_ci#include <ir/expressions/unaryExpression.h>
393af6ab5fSopenharmony_ci#include <ir/statements/classDeclaration.h>
403af6ab5fSopenharmony_ci#include <ir/validationInfo.h>
413af6ab5fSopenharmony_ci#include <util/bitset.h>
423af6ab5fSopenharmony_ci
433af6ab5fSopenharmony_cinamespace panda::es2panda::ir {
443af6ab5fSopenharmony_ci
453af6ab5fSopenharmony_cistatic bool IsAnonClassOrFuncExpr(const ir::Expression *expr)
463af6ab5fSopenharmony_ci{
473af6ab5fSopenharmony_ci    const ir::Identifier *identifier;
483af6ab5fSopenharmony_ci    switch (expr->Type()) {
493af6ab5fSopenharmony_ci        case ir::AstNodeType::FUNCTION_EXPRESSION: {
503af6ab5fSopenharmony_ci            identifier = expr->AsFunctionExpression()->Function()->Id();
513af6ab5fSopenharmony_ci            break;
523af6ab5fSopenharmony_ci        }
533af6ab5fSopenharmony_ci        case ir::AstNodeType::ARROW_FUNCTION_EXPRESSION: {
543af6ab5fSopenharmony_ci            identifier = expr->AsArrowFunctionExpression()->Function()->Id();
553af6ab5fSopenharmony_ci            break;
563af6ab5fSopenharmony_ci        }
573af6ab5fSopenharmony_ci        case ir::AstNodeType::CLASS_EXPRESSION: {
583af6ab5fSopenharmony_ci            identifier = expr->AsClassExpression()->Definition()->Ident();
593af6ab5fSopenharmony_ci            break;
603af6ab5fSopenharmony_ci        }
613af6ab5fSopenharmony_ci        default: {
623af6ab5fSopenharmony_ci            return false;
633af6ab5fSopenharmony_ci        }
643af6ab5fSopenharmony_ci    }
653af6ab5fSopenharmony_ci    return identifier == nullptr || identifier->Name().Empty();
663af6ab5fSopenharmony_ci}
673af6ab5fSopenharmony_ci
683af6ab5fSopenharmony_cistatic bool IsLegalNameFormat(const ir::Expression *expr)
693af6ab5fSopenharmony_ci{
703af6ab5fSopenharmony_ci    util::StringView name;
713af6ab5fSopenharmony_ci    if (expr->IsIdentifier()) {
723af6ab5fSopenharmony_ci        name = expr->AsIdentifier()->Name();
733af6ab5fSopenharmony_ci    } else if (expr->IsStringLiteral()) {
743af6ab5fSopenharmony_ci        name = expr->AsStringLiteral()->Str();
753af6ab5fSopenharmony_ci    } else if (expr->IsNumberLiteral()) {
763af6ab5fSopenharmony_ci        name = expr->AsNumberLiteral()->Str();
773af6ab5fSopenharmony_ci    } else {
783af6ab5fSopenharmony_ci        UNREACHABLE();
793af6ab5fSopenharmony_ci    }
803af6ab5fSopenharmony_ci    return name.Find(".") != std::string::npos && name.Find("\\") != std::string::npos;
813af6ab5fSopenharmony_ci}
823af6ab5fSopenharmony_ci
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_ciValidationInfo ObjectExpression::ValidateExpression()
853af6ab5fSopenharmony_ci{
863af6ab5fSopenharmony_ci    ValidationInfo info;
873af6ab5fSopenharmony_ci    bool foundProto = false;
883af6ab5fSopenharmony_ci
893af6ab5fSopenharmony_ci    for (auto *it : properties_) {
903af6ab5fSopenharmony_ci        switch (it->Type()) {
913af6ab5fSopenharmony_ci            case AstNodeType::OBJECT_EXPRESSION:
923af6ab5fSopenharmony_ci            case AstNodeType::ARRAY_EXPRESSION: {
933af6ab5fSopenharmony_ci                return {"Unexpected token.", it->Start()};
943af6ab5fSopenharmony_ci            }
953af6ab5fSopenharmony_ci            case AstNodeType::SPREAD_ELEMENT: {
963af6ab5fSopenharmony_ci                info = it->AsSpreadElement()->ValidateExpression();
973af6ab5fSopenharmony_ci                break;
983af6ab5fSopenharmony_ci            }
993af6ab5fSopenharmony_ci            case AstNodeType::PROPERTY: {
1003af6ab5fSopenharmony_ci                auto *prop = it->AsProperty();
1013af6ab5fSopenharmony_ci                info = prop->ValidateExpression();
1023af6ab5fSopenharmony_ci
1033af6ab5fSopenharmony_ci                if (prop->Kind() == PropertyKind::PROTO) {
1043af6ab5fSopenharmony_ci                    if (foundProto) {
1053af6ab5fSopenharmony_ci                        return {"Duplicate __proto__ fields are not allowed in object literals", prop->Key()->Start()};
1063af6ab5fSopenharmony_ci                    }
1073af6ab5fSopenharmony_ci
1083af6ab5fSopenharmony_ci                    foundProto = true;
1093af6ab5fSopenharmony_ci                }
1103af6ab5fSopenharmony_ci
1113af6ab5fSopenharmony_ci                break;
1123af6ab5fSopenharmony_ci            }
1133af6ab5fSopenharmony_ci            default: {
1143af6ab5fSopenharmony_ci                break;
1153af6ab5fSopenharmony_ci            }
1163af6ab5fSopenharmony_ci        }
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_ci        if (info.Fail()) {
1193af6ab5fSopenharmony_ci            break;
1203af6ab5fSopenharmony_ci        }
1213af6ab5fSopenharmony_ci    }
1223af6ab5fSopenharmony_ci
1233af6ab5fSopenharmony_ci    return info;
1243af6ab5fSopenharmony_ci}
1253af6ab5fSopenharmony_ci
1263af6ab5fSopenharmony_cibool ObjectExpression::ConvertibleToObjectPattern()
1273af6ab5fSopenharmony_ci{
1283af6ab5fSopenharmony_ci    bool restFound = false;
1293af6ab5fSopenharmony_ci    bool convResult = true;
1303af6ab5fSopenharmony_ci
1313af6ab5fSopenharmony_ci    for (auto *it : properties_) {
1323af6ab5fSopenharmony_ci        switch (it->Type()) {
1333af6ab5fSopenharmony_ci            case AstNodeType::ARRAY_EXPRESSION: {
1343af6ab5fSopenharmony_ci                convResult = it->AsArrayExpression()->ConvertibleToArrayPattern();
1353af6ab5fSopenharmony_ci                break;
1363af6ab5fSopenharmony_ci            }
1373af6ab5fSopenharmony_ci            case AstNodeType::SPREAD_ELEMENT: {
1383af6ab5fSopenharmony_ci                if (!restFound && it == properties_.back() && !trailingComma_) {
1393af6ab5fSopenharmony_ci                    convResult = it->AsSpreadElement()->ConvertibleToRest(isDeclaration_, false);
1403af6ab5fSopenharmony_ci                } else {
1413af6ab5fSopenharmony_ci                    convResult = false;
1423af6ab5fSopenharmony_ci                }
1433af6ab5fSopenharmony_ci
1443af6ab5fSopenharmony_ci                restFound = true;
1453af6ab5fSopenharmony_ci                break;
1463af6ab5fSopenharmony_ci            }
1473af6ab5fSopenharmony_ci            case AstNodeType::OBJECT_EXPRESSION: {
1483af6ab5fSopenharmony_ci                convResult = it->AsObjectExpression()->ConvertibleToObjectPattern();
1493af6ab5fSopenharmony_ci                break;
1503af6ab5fSopenharmony_ci            }
1513af6ab5fSopenharmony_ci            case AstNodeType::ASSIGNMENT_EXPRESSION: {
1523af6ab5fSopenharmony_ci                convResult = it->AsAssignmentExpression()->ConvertibleToAssignmentPattern();
1533af6ab5fSopenharmony_ci                break;
1543af6ab5fSopenharmony_ci            }
1553af6ab5fSopenharmony_ci            case AstNodeType::META_PROPERTY_EXPRESSION:
1563af6ab5fSopenharmony_ci            case AstNodeType::CHAIN_EXPRESSION:
1573af6ab5fSopenharmony_ci            case AstNodeType::SEQUENCE_EXPRESSION: {
1583af6ab5fSopenharmony_ci                convResult = false;
1593af6ab5fSopenharmony_ci                break;
1603af6ab5fSopenharmony_ci            }
1613af6ab5fSopenharmony_ci            case AstNodeType::PROPERTY: {
1623af6ab5fSopenharmony_ci                convResult = it->AsProperty()->ConventibleToPatternProperty();
1633af6ab5fSopenharmony_ci                break;
1643af6ab5fSopenharmony_ci            }
1653af6ab5fSopenharmony_ci            default: {
1663af6ab5fSopenharmony_ci                break;
1673af6ab5fSopenharmony_ci            }
1683af6ab5fSopenharmony_ci        }
1693af6ab5fSopenharmony_ci
1703af6ab5fSopenharmony_ci        if (!convResult) {
1713af6ab5fSopenharmony_ci            break;
1723af6ab5fSopenharmony_ci        }
1733af6ab5fSopenharmony_ci    }
1743af6ab5fSopenharmony_ci
1753af6ab5fSopenharmony_ci    SetType(AstNodeType::OBJECT_PATTERN);
1763af6ab5fSopenharmony_ci    return convResult;
1773af6ab5fSopenharmony_ci}
1783af6ab5fSopenharmony_ci
1793af6ab5fSopenharmony_civoid ObjectExpression::SetDeclaration()
1803af6ab5fSopenharmony_ci{
1813af6ab5fSopenharmony_ci    isDeclaration_ = true;
1823af6ab5fSopenharmony_ci}
1833af6ab5fSopenharmony_ci
1843af6ab5fSopenharmony_civoid ObjectExpression::SetOptional(bool optional)
1853af6ab5fSopenharmony_ci{
1863af6ab5fSopenharmony_ci    optional_ = optional;
1873af6ab5fSopenharmony_ci}
1883af6ab5fSopenharmony_ci
1893af6ab5fSopenharmony_civoid ObjectExpression::SetTsTypeAnnotation(Expression *typeAnnotation)
1903af6ab5fSopenharmony_ci{
1913af6ab5fSopenharmony_ci    typeAnnotation_ = typeAnnotation;
1923af6ab5fSopenharmony_ci}
1933af6ab5fSopenharmony_ci
1943af6ab5fSopenharmony_civoid ObjectExpression::Iterate(const NodeTraverser &cb) const
1953af6ab5fSopenharmony_ci{
1963af6ab5fSopenharmony_ci    for (auto *it : properties_) {
1973af6ab5fSopenharmony_ci        cb(it);
1983af6ab5fSopenharmony_ci    }
1993af6ab5fSopenharmony_ci
2003af6ab5fSopenharmony_ci    if (typeAnnotation_) {
2013af6ab5fSopenharmony_ci        cb(typeAnnotation_);
2023af6ab5fSopenharmony_ci    }
2033af6ab5fSopenharmony_ci}
2043af6ab5fSopenharmony_ci
2053af6ab5fSopenharmony_civoid ObjectExpression::Dump(ir::AstDumper *dumper) const
2063af6ab5fSopenharmony_ci{
2073af6ab5fSopenharmony_ci    dumper->Add({{"type", (type_ == AstNodeType::OBJECT_EXPRESSION) ? "ObjectExpression" : "ObjectPattern"},
2083af6ab5fSopenharmony_ci                 {"properties", properties_},
2093af6ab5fSopenharmony_ci                 {"typeAnnotation", AstDumper::Optional(typeAnnotation_)},
2103af6ab5fSopenharmony_ci                 {"optional", AstDumper::Optional(optional_)}});
2113af6ab5fSopenharmony_ci}
2123af6ab5fSopenharmony_ci
2133af6ab5fSopenharmony_civoid ObjectExpression::FillInLiteralBuffer(compiler::LiteralBuffer *buf,
2143af6ab5fSopenharmony_ci                                           std::vector<std::vector<const Literal *>> &tempLiteralBuffer) const
2153af6ab5fSopenharmony_ci{
2163af6ab5fSopenharmony_ci    for (size_t i = 0 ; i < tempLiteralBuffer.size(); i++) {
2173af6ab5fSopenharmony_ci        if (tempLiteralBuffer[i].size() == 0) {
2183af6ab5fSopenharmony_ci            continue;
2193af6ab5fSopenharmony_ci        }
2203af6ab5fSopenharmony_ci
2213af6ab5fSopenharmony_ci        auto propBuf = tempLiteralBuffer[i];
2223af6ab5fSopenharmony_ci        for (size_t j = 0; j < propBuf.size(); j++) {
2233af6ab5fSopenharmony_ci            buf->Add(propBuf[j]);
2243af6ab5fSopenharmony_ci        }
2253af6ab5fSopenharmony_ci    }
2263af6ab5fSopenharmony_ci}
2273af6ab5fSopenharmony_ci
2283af6ab5fSopenharmony_civoid ObjectExpression::EmitCreateObjectWithBuffer(compiler::PandaGen *pg, compiler::LiteralBuffer *buf,
2293af6ab5fSopenharmony_ci                                                  bool hasMethod) const
2303af6ab5fSopenharmony_ci{
2313af6ab5fSopenharmony_ci    if (buf->IsEmpty()) {
2323af6ab5fSopenharmony_ci        pg->CreateEmptyObject(this);
2333af6ab5fSopenharmony_ci        return;
2343af6ab5fSopenharmony_ci    }
2353af6ab5fSopenharmony_ci
2363af6ab5fSopenharmony_ci    int32_t bufIdx = pg->AddLiteralBuffer(buf);
2373af6ab5fSopenharmony_ci    pg->CreateObjectWithBuffer(this, static_cast<uint32_t>(bufIdx));
2383af6ab5fSopenharmony_ci}
2393af6ab5fSopenharmony_ci
2403af6ab5fSopenharmony_cistatic const Literal *CreateLiteral(compiler::PandaGen *pg, const ir::Property *prop, util::BitSet *compiled,
2413af6ab5fSopenharmony_ci                                    size_t propIndex)
2423af6ab5fSopenharmony_ci{
2433af6ab5fSopenharmony_ci    if (util::Helpers::IsConstantExpr(prop->Value())) {
2443af6ab5fSopenharmony_ci        compiled->Set(propIndex);
2453af6ab5fSopenharmony_ci        return prop->Value()->AsLiteral();
2463af6ab5fSopenharmony_ci    }
2473af6ab5fSopenharmony_ci
2483af6ab5fSopenharmony_ci    if (prop->Kind() != ir::PropertyKind::INIT) {
2493af6ab5fSopenharmony_ci        ASSERT(prop->IsAccessor());
2503af6ab5fSopenharmony_ci        return pg->Allocator()->New<TaggedLiteral>(LiteralTag::ACCESSOR);
2513af6ab5fSopenharmony_ci    }
2523af6ab5fSopenharmony_ci
2533af6ab5fSopenharmony_ci    if (prop->IsMethod()) {
2543af6ab5fSopenharmony_ci        const ir::ScriptFunction *method = prop->Value()->AsFunctionExpression()->Function();
2553af6ab5fSopenharmony_ci
2563af6ab5fSopenharmony_ci        LiteralTag tag = LiteralTag::METHOD;
2573af6ab5fSopenharmony_ci
2583af6ab5fSopenharmony_ci        if (method->IsGenerator()) {
2593af6ab5fSopenharmony_ci            tag = LiteralTag::GENERATOR_METHOD;
2603af6ab5fSopenharmony_ci
2613af6ab5fSopenharmony_ci            if (method->IsAsync()) {
2623af6ab5fSopenharmony_ci                tag = LiteralTag::ASYNC_GENERATOR_METHOD;
2633af6ab5fSopenharmony_ci            }
2643af6ab5fSopenharmony_ci        }
2653af6ab5fSopenharmony_ci
2663af6ab5fSopenharmony_ci        compiled->Set(propIndex);
2673af6ab5fSopenharmony_ci        return pg->Allocator()->New<TaggedLiteral>(tag, method->Scope()->InternalName());
2683af6ab5fSopenharmony_ci    }
2693af6ab5fSopenharmony_ci
2703af6ab5fSopenharmony_ci    return pg->Allocator()->New<NullLiteral>();
2713af6ab5fSopenharmony_ci}
2723af6ab5fSopenharmony_ci
2733af6ab5fSopenharmony_civoid ObjectExpression::CompileStaticProperties(compiler::PandaGen *pg, util::BitSet *compiled) const
2743af6ab5fSopenharmony_ci{
2753af6ab5fSopenharmony_ci    bool hasMethod = false;
2763af6ab5fSopenharmony_ci    auto *buf = pg->NewLiteralBuffer();
2773af6ab5fSopenharmony_ci    std::vector<std::vector<const Literal *>> tempLiteralBuffer(properties_.size());
2783af6ab5fSopenharmony_ci    std::unordered_map<util::StringView, size_t> propNameMap;
2793af6ab5fSopenharmony_ci    std::unordered_map<util::StringView, size_t> getterIndxNameMap;
2803af6ab5fSopenharmony_ci    std::unordered_map<util::StringView, size_t> setterIndxNameMap;
2813af6ab5fSopenharmony_ci
2823af6ab5fSopenharmony_ci    for (size_t i = 0; i < properties_.size(); i++) {
2833af6ab5fSopenharmony_ci        if (properties_[i]->IsSpreadElement()) {
2843af6ab5fSopenharmony_ci            break;
2853af6ab5fSopenharmony_ci        }
2863af6ab5fSopenharmony_ci
2873af6ab5fSopenharmony_ci        const ir::Property *prop = properties_[i]->AsProperty();
2883af6ab5fSopenharmony_ci
2893af6ab5fSopenharmony_ci        if (!util::Helpers::IsConstantPropertyKey(prop->Key(), prop->IsComputed()) ||
2903af6ab5fSopenharmony_ci            prop->Kind() == ir::PropertyKind::PROTO) {
2913af6ab5fSopenharmony_ci            break;
2923af6ab5fSopenharmony_ci        }
2933af6ab5fSopenharmony_ci
2943af6ab5fSopenharmony_ci        std::vector<const Literal *> propBuf;
2953af6ab5fSopenharmony_ci        util::StringView name = util::Helpers::LiteralToPropName(pg->Allocator(), prop->Key());
2963af6ab5fSopenharmony_ci        size_t propIndex = i;
2973af6ab5fSopenharmony_ci        auto res = propNameMap.insert({name, propIndex});
2983af6ab5fSopenharmony_ci        if (!res.second) {    // name is found in map
2993af6ab5fSopenharmony_ci            propIndex = res.first->second;
3003af6ab5fSopenharmony_ci
3013af6ab5fSopenharmony_ci            if (prop->Kind() != ir::PropertyKind::SET && getterIndxNameMap.find(name) != getterIndxNameMap.end()) {
3023af6ab5fSopenharmony_ci                compiled->Set(getterIndxNameMap[name]);
3033af6ab5fSopenharmony_ci            }
3043af6ab5fSopenharmony_ci
3053af6ab5fSopenharmony_ci            if (prop->Kind() != ir::PropertyKind::GET && setterIndxNameMap.find(name) != setterIndxNameMap.end()) {
3063af6ab5fSopenharmony_ci                compiled->Set(setterIndxNameMap[name]);
3073af6ab5fSopenharmony_ci            }
3083af6ab5fSopenharmony_ci        }
3093af6ab5fSopenharmony_ci
3103af6ab5fSopenharmony_ci        if (prop->Kind() == ir::PropertyKind::GET) {
3113af6ab5fSopenharmony_ci            getterIndxNameMap[name] = i;
3123af6ab5fSopenharmony_ci        } else if (prop->Kind() == ir::PropertyKind::SET) {
3133af6ab5fSopenharmony_ci            setterIndxNameMap[name] = i;
3143af6ab5fSopenharmony_ci        }
3153af6ab5fSopenharmony_ci
3163af6ab5fSopenharmony_ci        propBuf.push_back(pg->Allocator()->New<StringLiteral>(name));
3173af6ab5fSopenharmony_ci        propBuf.push_back(CreateLiteral(pg, prop, compiled, i));
3183af6ab5fSopenharmony_ci
3193af6ab5fSopenharmony_ci        if (prop->IsMethod()) {
3203af6ab5fSopenharmony_ci            hasMethod = true;
3213af6ab5fSopenharmony_ci            const ir::FunctionExpression *func = prop->Value()->AsFunctionExpression();
3223af6ab5fSopenharmony_ci            size_t paramNum = func->Function()->FormalParamsLength();
3233af6ab5fSopenharmony_ci            Literal *methodAffiliate = pg->Allocator()->New<TaggedLiteral>(LiteralTag::METHODAFFILIATE, paramNum);
3243af6ab5fSopenharmony_ci            propBuf.push_back(methodAffiliate);
3253af6ab5fSopenharmony_ci        }
3263af6ab5fSopenharmony_ci
3273af6ab5fSopenharmony_ci        tempLiteralBuffer[propIndex] = propBuf;
3283af6ab5fSopenharmony_ci    }
3293af6ab5fSopenharmony_ci
3303af6ab5fSopenharmony_ci    FillInLiteralBuffer(buf, tempLiteralBuffer);
3313af6ab5fSopenharmony_ci    EmitCreateObjectWithBuffer(pg, buf, hasMethod);
3323af6ab5fSopenharmony_ci}
3333af6ab5fSopenharmony_ci
3343af6ab5fSopenharmony_civoid ObjectExpression::CompilePropertyOfGetterOrSetter(compiler::PandaGen *pg, const ir::Property *prop,
3353af6ab5fSopenharmony_ci    compiler::VReg objReg) const
3363af6ab5fSopenharmony_ci{
3373af6ab5fSopenharmony_ci    compiler::VReg key = pg->LoadPropertyKey(prop->Key(), prop->IsComputed());
3383af6ab5fSopenharmony_ci
3393af6ab5fSopenharmony_ci    compiler::VReg undef = pg->AllocReg();
3403af6ab5fSopenharmony_ci    pg->LoadConst(this, compiler::Constant::JS_UNDEFINED);
3413af6ab5fSopenharmony_ci    pg->StoreAccumulator(this, undef);
3423af6ab5fSopenharmony_ci
3433af6ab5fSopenharmony_ci    compiler::VReg getter = undef;
3443af6ab5fSopenharmony_ci    compiler::VReg setter = undef;
3453af6ab5fSopenharmony_ci
3463af6ab5fSopenharmony_ci    compiler::VReg accessor = pg->AllocReg();
3473af6ab5fSopenharmony_ci    pg->LoadAccumulator(prop->Value(), objReg);
3483af6ab5fSopenharmony_ci    prop->Value()->Compile(pg);
3493af6ab5fSopenharmony_ci    pg->StoreAccumulator(prop->Value(), accessor);
3503af6ab5fSopenharmony_ci
3513af6ab5fSopenharmony_ci    if (prop->Kind() == ir::PropertyKind::GET) {
3523af6ab5fSopenharmony_ci        getter = accessor;
3533af6ab5fSopenharmony_ci    } else {
3543af6ab5fSopenharmony_ci        setter = accessor;
3553af6ab5fSopenharmony_ci    }
3563af6ab5fSopenharmony_ci
3573af6ab5fSopenharmony_ci    pg->DefineGetterSetterByValue(this, objReg, key, getter, setter, prop->IsComputed());
3583af6ab5fSopenharmony_ci}
3593af6ab5fSopenharmony_ci
3603af6ab5fSopenharmony_civoid ObjectExpression::CompilePropertyWithInit(compiler::PandaGen *pg, const ir::Property *prop,
3613af6ab5fSopenharmony_ci    compiler::VReg objReg) const
3623af6ab5fSopenharmony_ci{
3633af6ab5fSopenharmony_ci    compiler::Operand key = pg->ToPropertyKey(prop->Key(), prop->IsComputed());
3643af6ab5fSopenharmony_ci    const auto *value = prop->Value();
3653af6ab5fSopenharmony_ci
3663af6ab5fSopenharmony_ci    bool nameSetting = false;
3673af6ab5fSopenharmony_ci    if (prop->IsMethod()) {
3683af6ab5fSopenharmony_ci        pg->LoadAccumulator(value, objReg);
3693af6ab5fSopenharmony_ci        if (prop->IsComputed()) {
3703af6ab5fSopenharmony_ci            nameSetting = true;
3713af6ab5fSopenharmony_ci        }
3723af6ab5fSopenharmony_ci    } else {
3733af6ab5fSopenharmony_ci        if (prop->IsComputed()) {
3743af6ab5fSopenharmony_ci            nameSetting = IsAnonClassOrFuncExpr(value);
3753af6ab5fSopenharmony_ci        } else {
3763af6ab5fSopenharmony_ci            nameSetting = IsAnonClassOrFuncExpr(value) && IsLegalNameFormat(prop->Key());
3773af6ab5fSopenharmony_ci        }
3783af6ab5fSopenharmony_ci    }
3793af6ab5fSopenharmony_ci
3803af6ab5fSopenharmony_ci    // This is for disallowing breakpoint on property with negative number as initializer
3813af6ab5fSopenharmony_ci    // TODO: remove setting invalid flag after puttting negative number into literal buffer
3823af6ab5fSopenharmony_ci    bool shouldSetInvalidFlag = value->IsUnaryExpression() && value->AsUnaryExpression()->IsNegativeNumber()
3833af6ab5fSopenharmony_ci        && !prop->IsComputed();
3843af6ab5fSopenharmony_ci    if (shouldSetInvalidFlag) {
3853af6ab5fSopenharmony_ci        pg->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION);
3863af6ab5fSopenharmony_ci    }
3873af6ab5fSopenharmony_ci
3883af6ab5fSopenharmony_ci    value->Compile(pg);
3893af6ab5fSopenharmony_ci    if (!nameSetting && pg->Binder()->Program()->TargetApiVersion() > 10) {
3903af6ab5fSopenharmony_ci        pg->DefineOwnProperty(this, objReg, key);
3913af6ab5fSopenharmony_ci    } else {
3923af6ab5fSopenharmony_ci        pg->StoreOwnProperty(this, objReg, key, nameSetting);
3933af6ab5fSopenharmony_ci    }
3943af6ab5fSopenharmony_ci    pg->SetSourceLocationFlag(lexer::SourceLocationFlag::VALID_SOURCE_LOCATION);
3953af6ab5fSopenharmony_ci}
3963af6ab5fSopenharmony_ci
3973af6ab5fSopenharmony_civoid ObjectExpression::CompileRemainingProperties(compiler::PandaGen *pg, const util::BitSet *compiled,
3983af6ab5fSopenharmony_ci                                                  compiler::VReg objReg) const
3993af6ab5fSopenharmony_ci{
4003af6ab5fSopenharmony_ci    for (size_t i = 0; i < properties_.size(); i++) {
4013af6ab5fSopenharmony_ci        if (compiled->Test(i)) {
4023af6ab5fSopenharmony_ci            continue;
4033af6ab5fSopenharmony_ci        }
4043af6ab5fSopenharmony_ci
4053af6ab5fSopenharmony_ci        compiler::RegScope rs(pg);
4063af6ab5fSopenharmony_ci
4073af6ab5fSopenharmony_ci        if (properties_[i]->IsSpreadElement()) {
4083af6ab5fSopenharmony_ci            const ir::SpreadElement *spread = properties_[i]->AsSpreadElement();
4093af6ab5fSopenharmony_ci
4103af6ab5fSopenharmony_ci            spread->Argument()->Compile(pg);
4113af6ab5fSopenharmony_ci            // srcObj is now stored in acc
4123af6ab5fSopenharmony_ci            pg->CopyDataProperties(spread, objReg);
4133af6ab5fSopenharmony_ci            continue;
4143af6ab5fSopenharmony_ci        }
4153af6ab5fSopenharmony_ci
4163af6ab5fSopenharmony_ci        const ir::Property *prop = properties_[i]->AsProperty();
4173af6ab5fSopenharmony_ci
4183af6ab5fSopenharmony_ci        switch (prop->Kind()) {
4193af6ab5fSopenharmony_ci            case ir::PropertyKind::GET:
4203af6ab5fSopenharmony_ci            case ir::PropertyKind::SET: {
4213af6ab5fSopenharmony_ci                CompilePropertyOfGetterOrSetter(pg, prop, objReg);
4223af6ab5fSopenharmony_ci                break;
4233af6ab5fSopenharmony_ci            }
4243af6ab5fSopenharmony_ci            case ir::PropertyKind::INIT: {
4253af6ab5fSopenharmony_ci                CompilePropertyWithInit(pg, prop, objReg);
4263af6ab5fSopenharmony_ci                break;
4273af6ab5fSopenharmony_ci            }
4283af6ab5fSopenharmony_ci            case ir::PropertyKind::PROTO: {
4293af6ab5fSopenharmony_ci                prop->Value()->Compile(pg);
4303af6ab5fSopenharmony_ci                compiler::VReg proto = pg->AllocReg();
4313af6ab5fSopenharmony_ci                pg->StoreAccumulator(this, proto);
4323af6ab5fSopenharmony_ci
4333af6ab5fSopenharmony_ci                pg->SetObjectWithProto(this, proto, objReg);
4343af6ab5fSopenharmony_ci                break;
4353af6ab5fSopenharmony_ci            }
4363af6ab5fSopenharmony_ci            default: {
4373af6ab5fSopenharmony_ci                UNREACHABLE();
4383af6ab5fSopenharmony_ci            }
4393af6ab5fSopenharmony_ci        }
4403af6ab5fSopenharmony_ci    }
4413af6ab5fSopenharmony_ci
4423af6ab5fSopenharmony_ci    pg->LoadAccumulator(this, objReg);
4433af6ab5fSopenharmony_ci}
4443af6ab5fSopenharmony_ci
4453af6ab5fSopenharmony_civoid ObjectExpression::Compile(compiler::PandaGen *pg) const
4463af6ab5fSopenharmony_ci{
4473af6ab5fSopenharmony_ci    if (properties_.empty()) {
4483af6ab5fSopenharmony_ci        pg->CreateEmptyObject(this);
4493af6ab5fSopenharmony_ci        return;
4503af6ab5fSopenharmony_ci    }
4513af6ab5fSopenharmony_ci
4523af6ab5fSopenharmony_ci    util::BitSet compiled(properties_.size());
4533af6ab5fSopenharmony_ci    CompileStaticProperties(pg, &compiled);
4543af6ab5fSopenharmony_ci
4553af6ab5fSopenharmony_ci    compiler::RegScope rs(pg);
4563af6ab5fSopenharmony_ci    compiler::VReg objReg = pg->AllocReg();
4573af6ab5fSopenharmony_ci
4583af6ab5fSopenharmony_ci    pg->StoreAccumulator(this, objReg);
4593af6ab5fSopenharmony_ci
4603af6ab5fSopenharmony_ci    CompileRemainingProperties(pg, &compiled, objReg);
4613af6ab5fSopenharmony_ci}
4623af6ab5fSopenharmony_ci
4633af6ab5fSopenharmony_cichecker::Type *ObjectExpression::CheckPattern(checker::Checker *checker) const
4643af6ab5fSopenharmony_ci{
4653af6ab5fSopenharmony_ci    checker::ObjectDescriptor *desc = checker->Allocator()->New<checker::ObjectDescriptor>(checker->Allocator());
4663af6ab5fSopenharmony_ci    CHECK_NOT_NULL(desc);
4673af6ab5fSopenharmony_ci    bool isOptional = false;
4683af6ab5fSopenharmony_ci
4693af6ab5fSopenharmony_ci    for (auto it = properties_.rbegin(); it != properties_.rend(); it++) {
4703af6ab5fSopenharmony_ci        if ((*it)->IsRestElement()) {
4713af6ab5fSopenharmony_ci            ASSERT((*it)->AsRestElement()->Argument()->IsIdentifier());
4723af6ab5fSopenharmony_ci            util::StringView indexInfoName("x");
4733af6ab5fSopenharmony_ci            auto *newIndexInfo =
4743af6ab5fSopenharmony_ci                checker->Allocator()->New<checker::IndexInfo>(checker->GlobalAnyType(), indexInfoName, false);
4753af6ab5fSopenharmony_ci            desc->stringIndexInfo = newIndexInfo;
4763af6ab5fSopenharmony_ci            continue;
4773af6ab5fSopenharmony_ci        }
4783af6ab5fSopenharmony_ci
4793af6ab5fSopenharmony_ci        ASSERT((*it)->IsProperty());
4803af6ab5fSopenharmony_ci        const ir::Property *prop = (*it)->AsProperty();
4813af6ab5fSopenharmony_ci
4823af6ab5fSopenharmony_ci        if (prop->IsComputed()) {
4833af6ab5fSopenharmony_ci            // TODO(aszilagyi)
4843af6ab5fSopenharmony_ci            continue;
4853af6ab5fSopenharmony_ci        }
4863af6ab5fSopenharmony_ci
4873af6ab5fSopenharmony_ci        binder::LocalVariable *foundVar = desc->FindProperty(prop->Key()->AsIdentifier()->Name());
4883af6ab5fSopenharmony_ci        checker::Type *patternParamType = checker->GlobalAnyType();
4893af6ab5fSopenharmony_ci        binder::Variable *bindingVar = nullptr;
4903af6ab5fSopenharmony_ci
4913af6ab5fSopenharmony_ci        if (prop->IsShorthand()) {
4923af6ab5fSopenharmony_ci            switch (prop->Value()->Type()) {
4933af6ab5fSopenharmony_ci                case ir::AstNodeType::IDENTIFIER: {
4943af6ab5fSopenharmony_ci                    const ir::Identifier *ident = prop->Value()->AsIdentifier();
4953af6ab5fSopenharmony_ci                    ASSERT(ident->Variable());
4963af6ab5fSopenharmony_ci                    bindingVar = ident->Variable();
4973af6ab5fSopenharmony_ci                    break;
4983af6ab5fSopenharmony_ci                }
4993af6ab5fSopenharmony_ci                case ir::AstNodeType::ASSIGNMENT_PATTERN: {
5003af6ab5fSopenharmony_ci                    const ir::AssignmentExpression *assignmentPattern = prop->Value()->AsAssignmentPattern();
5013af6ab5fSopenharmony_ci                    patternParamType = assignmentPattern->Right()->Check(checker);
5023af6ab5fSopenharmony_ci                    ASSERT(assignmentPattern->Left()->AsIdentifier()->Variable());
5033af6ab5fSopenharmony_ci                    bindingVar = assignmentPattern->Left()->AsIdentifier()->Variable();
5043af6ab5fSopenharmony_ci                    isOptional = true;
5053af6ab5fSopenharmony_ci                    break;
5063af6ab5fSopenharmony_ci                }
5073af6ab5fSopenharmony_ci                default: {
5083af6ab5fSopenharmony_ci                    UNREACHABLE();
5093af6ab5fSopenharmony_ci                }
5103af6ab5fSopenharmony_ci            }
5113af6ab5fSopenharmony_ci        } else {
5123af6ab5fSopenharmony_ci            switch (prop->Value()->Type()) {
5133af6ab5fSopenharmony_ci                case ir::AstNodeType::IDENTIFIER: {
5143af6ab5fSopenharmony_ci                    bindingVar = prop->Value()->AsIdentifier()->Variable();
5153af6ab5fSopenharmony_ci                    break;
5163af6ab5fSopenharmony_ci                }
5173af6ab5fSopenharmony_ci                case ir::AstNodeType::ARRAY_PATTERN: {
5183af6ab5fSopenharmony_ci                    patternParamType = prop->Value()->AsArrayPattern()->CheckPattern(checker);
5193af6ab5fSopenharmony_ci                    break;
5203af6ab5fSopenharmony_ci                }
5213af6ab5fSopenharmony_ci                case ir::AstNodeType::OBJECT_PATTERN: {
5223af6ab5fSopenharmony_ci                    patternParamType = prop->Value()->AsObjectPattern()->CheckPattern(checker);
5233af6ab5fSopenharmony_ci                    break;
5243af6ab5fSopenharmony_ci                }
5253af6ab5fSopenharmony_ci                case ir::AstNodeType::ASSIGNMENT_PATTERN: {
5263af6ab5fSopenharmony_ci                    const ir::AssignmentExpression *assignmentPattern = prop->Value()->AsAssignmentPattern();
5273af6ab5fSopenharmony_ci
5283af6ab5fSopenharmony_ci                    if (assignmentPattern->Left()->IsIdentifier()) {
5293af6ab5fSopenharmony_ci                        bindingVar = assignmentPattern->Left()->AsIdentifier()->Variable();
5303af6ab5fSopenharmony_ci                        patternParamType =
5313af6ab5fSopenharmony_ci                            checker->GetBaseTypeOfLiteralType(assignmentPattern->Right()->Check(checker));
5323af6ab5fSopenharmony_ci                        isOptional = true;
5333af6ab5fSopenharmony_ci                        break;
5343af6ab5fSopenharmony_ci                    }
5353af6ab5fSopenharmony_ci
5363af6ab5fSopenharmony_ci                    if (assignmentPattern->Left()->IsArrayPattern()) {
5373af6ab5fSopenharmony_ci                        auto savedContext = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE);
5383af6ab5fSopenharmony_ci                        auto destructuringContext =
5393af6ab5fSopenharmony_ci                            checker::ArrayDestructuringContext(checker, assignmentPattern->Left()->AsArrayPattern(),
5403af6ab5fSopenharmony_ci                                                               false, true, nullptr, assignmentPattern->Right());
5413af6ab5fSopenharmony_ci
5423af6ab5fSopenharmony_ci                        if (foundVar) {
5433af6ab5fSopenharmony_ci                            destructuringContext.SetInferedType(
5443af6ab5fSopenharmony_ci                                checker->CreateUnionType({foundVar->TsType(), destructuringContext.InferedType()}));
5453af6ab5fSopenharmony_ci                        }
5463af6ab5fSopenharmony_ci
5473af6ab5fSopenharmony_ci                        destructuringContext.Start();
5483af6ab5fSopenharmony_ci                        patternParamType = destructuringContext.InferedType();
5493af6ab5fSopenharmony_ci                        isOptional = true;
5503af6ab5fSopenharmony_ci                        break;
5513af6ab5fSopenharmony_ci                    }
5523af6ab5fSopenharmony_ci
5533af6ab5fSopenharmony_ci                    ASSERT(assignmentPattern->Left()->IsObjectPattern());
5543af6ab5fSopenharmony_ci                    auto savedContext = checker::SavedCheckerContext(checker, checker::CheckerStatus::FORCE_TUPLE);
5553af6ab5fSopenharmony_ci                    auto destructuringContext =
5563af6ab5fSopenharmony_ci                        checker::ObjectDestructuringContext(checker, assignmentPattern->Left()->AsObjectPattern(),
5573af6ab5fSopenharmony_ci                                                            false, true, nullptr, assignmentPattern->Right());
5583af6ab5fSopenharmony_ci
5593af6ab5fSopenharmony_ci                    if (foundVar) {
5603af6ab5fSopenharmony_ci                        destructuringContext.SetInferedType(
5613af6ab5fSopenharmony_ci                            checker->CreateUnionType({foundVar->TsType(), destructuringContext.InferedType()}));
5623af6ab5fSopenharmony_ci                    }
5633af6ab5fSopenharmony_ci
5643af6ab5fSopenharmony_ci                    destructuringContext.Start();
5653af6ab5fSopenharmony_ci                    patternParamType = destructuringContext.InferedType();
5663af6ab5fSopenharmony_ci                    isOptional = true;
5673af6ab5fSopenharmony_ci                    break;
5683af6ab5fSopenharmony_ci                }
5693af6ab5fSopenharmony_ci                default: {
5703af6ab5fSopenharmony_ci                    UNREACHABLE();
5713af6ab5fSopenharmony_ci                }
5723af6ab5fSopenharmony_ci            }
5733af6ab5fSopenharmony_ci        }
5743af6ab5fSopenharmony_ci
5753af6ab5fSopenharmony_ci        if (bindingVar) {
5763af6ab5fSopenharmony_ci            bindingVar->SetTsType(patternParamType);
5773af6ab5fSopenharmony_ci        }
5783af6ab5fSopenharmony_ci
5793af6ab5fSopenharmony_ci        if (foundVar) {
5803af6ab5fSopenharmony_ci            continue;
5813af6ab5fSopenharmony_ci        }
5823af6ab5fSopenharmony_ci
5833af6ab5fSopenharmony_ci        binder::LocalVariable *patternVar = binder::Scope::CreateVar(
5843af6ab5fSopenharmony_ci            checker->Allocator(), prop->Key()->AsIdentifier()->Name(), binder::VariableFlags::PROPERTY, *it);
5853af6ab5fSopenharmony_ci        patternVar->SetTsType(patternParamType);
5863af6ab5fSopenharmony_ci
5873af6ab5fSopenharmony_ci        if (isOptional) {
5883af6ab5fSopenharmony_ci            patternVar->AddFlag(binder::VariableFlags::OPTIONAL);
5893af6ab5fSopenharmony_ci        }
5903af6ab5fSopenharmony_ci
5913af6ab5fSopenharmony_ci        desc->properties.insert(desc->properties.begin(), patternVar);
5923af6ab5fSopenharmony_ci    }
5933af6ab5fSopenharmony_ci
5943af6ab5fSopenharmony_ci    checker::Type *returnType = checker->Allocator()->New<checker::ObjectLiteralType>(desc);
5953af6ab5fSopenharmony_ci    CHECK_NOT_NULL(returnType);
5963af6ab5fSopenharmony_ci    returnType->AsObjectType()->AddObjectFlag(checker::ObjectFlags::RESOLVED_MEMBERS);
5973af6ab5fSopenharmony_ci    return returnType;
5983af6ab5fSopenharmony_ci}
5993af6ab5fSopenharmony_ci
6003af6ab5fSopenharmony_ciconst util::StringView &GetPropertyName(const ir::Expression *key)
6013af6ab5fSopenharmony_ci{
6023af6ab5fSopenharmony_ci    if (key->IsIdentifier()) {
6033af6ab5fSopenharmony_ci        return key->AsIdentifier()->Name();
6043af6ab5fSopenharmony_ci    }
6053af6ab5fSopenharmony_ci
6063af6ab5fSopenharmony_ci    if (key->IsStringLiteral()) {
6073af6ab5fSopenharmony_ci        return key->AsStringLiteral()->Str();
6083af6ab5fSopenharmony_ci    }
6093af6ab5fSopenharmony_ci
6103af6ab5fSopenharmony_ci    ASSERT(key->IsNumberLiteral());
6113af6ab5fSopenharmony_ci    return key->AsNumberLiteral()->Str();
6123af6ab5fSopenharmony_ci}
6133af6ab5fSopenharmony_ci
6143af6ab5fSopenharmony_cibinder::VariableFlags GetFlagsForProperty(const ir::Property *prop)
6153af6ab5fSopenharmony_ci{
6163af6ab5fSopenharmony_ci    if (!prop->IsMethod()) {
6173af6ab5fSopenharmony_ci        return binder::VariableFlags::PROPERTY;
6183af6ab5fSopenharmony_ci    }
6193af6ab5fSopenharmony_ci
6203af6ab5fSopenharmony_ci    binder::VariableFlags propFlags = binder::VariableFlags::METHOD;
6213af6ab5fSopenharmony_ci
6223af6ab5fSopenharmony_ci    if (prop->IsAccessor() && prop->Kind() == PropertyKind::GET) {
6233af6ab5fSopenharmony_ci        propFlags |= binder::VariableFlags::READONLY;
6243af6ab5fSopenharmony_ci    }
6253af6ab5fSopenharmony_ci
6263af6ab5fSopenharmony_ci    return propFlags;
6273af6ab5fSopenharmony_ci}
6283af6ab5fSopenharmony_ci
6293af6ab5fSopenharmony_cichecker::Type *GetTypeForProperty(const ir::Property *prop, checker::Checker *checker)
6303af6ab5fSopenharmony_ci{
6313af6ab5fSopenharmony_ci    if (prop->IsAccessor()) {
6323af6ab5fSopenharmony_ci        checker::Type *funcType = prop->Value()->Check(checker);
6333af6ab5fSopenharmony_ci
6343af6ab5fSopenharmony_ci        if (prop->Kind() == PropertyKind::SET) {
6353af6ab5fSopenharmony_ci            return checker->GlobalAnyType();
6363af6ab5fSopenharmony_ci        }
6373af6ab5fSopenharmony_ci
6383af6ab5fSopenharmony_ci        ASSERT(funcType->IsObjectType() && funcType->AsObjectType()->IsFunctionType());
6393af6ab5fSopenharmony_ci        return funcType->AsObjectType()->CallSignatures()[0]->ReturnType();
6403af6ab5fSopenharmony_ci    }
6413af6ab5fSopenharmony_ci
6423af6ab5fSopenharmony_ci    if (prop->IsShorthand()) {
6433af6ab5fSopenharmony_ci        return prop->Key()->Check(checker);
6443af6ab5fSopenharmony_ci    }
6453af6ab5fSopenharmony_ci
6463af6ab5fSopenharmony_ci    return prop->Value()->Check(checker);
6473af6ab5fSopenharmony_ci}
6483af6ab5fSopenharmony_ci
6493af6ab5fSopenharmony_cichecker::Type *ObjectExpression::Check(checker::Checker *checker) const
6503af6ab5fSopenharmony_ci{
6513af6ab5fSopenharmony_ci    checker::ObjectDescriptor *desc = checker->Allocator()->New<checker::ObjectDescriptor>(checker->Allocator());
6523af6ab5fSopenharmony_ci    CHECK_NOT_NULL(desc);
6533af6ab5fSopenharmony_ci    std::unordered_map<util::StringView, lexer::SourcePosition> allPropertiesMap;
6543af6ab5fSopenharmony_ci    bool inConstContext = checker->HasStatus(checker::CheckerStatus::IN_CONST_CONTEXT);
6553af6ab5fSopenharmony_ci    ArenaVector<checker::Type *> computedNumberPropTypes(checker->Allocator()->Adapter());
6563af6ab5fSopenharmony_ci    ArenaVector<checker::Type *> computedStringPropTypes(checker->Allocator()->Adapter());
6573af6ab5fSopenharmony_ci    bool hasComputedNumberProperty = false;
6583af6ab5fSopenharmony_ci    bool hasComputedStringProperty = false;
6593af6ab5fSopenharmony_ci    bool seenSpread = false;
6603af6ab5fSopenharmony_ci
6613af6ab5fSopenharmony_ci    for (const auto *it : properties_) {
6623af6ab5fSopenharmony_ci        if (it->IsProperty()) {
6633af6ab5fSopenharmony_ci            const ir::Property *prop = it->AsProperty();
6643af6ab5fSopenharmony_ci
6653af6ab5fSopenharmony_ci            if (prop->IsComputed()) {
6663af6ab5fSopenharmony_ci                checker::Type *computedNameType = checker->CheckComputedPropertyName(prop->Key());
6673af6ab5fSopenharmony_ci
6683af6ab5fSopenharmony_ci                if (computedNameType->IsNumberType()) {
6693af6ab5fSopenharmony_ci                    hasComputedNumberProperty = true;
6703af6ab5fSopenharmony_ci                    computedNumberPropTypes.push_back(prop->Value()->Check(checker));
6713af6ab5fSopenharmony_ci                    continue;
6723af6ab5fSopenharmony_ci                }
6733af6ab5fSopenharmony_ci
6743af6ab5fSopenharmony_ci                if (computedNameType->IsStringType()) {
6753af6ab5fSopenharmony_ci                    hasComputedStringProperty = true;
6763af6ab5fSopenharmony_ci                    computedStringPropTypes.push_back(prop->Value()->Check(checker));
6773af6ab5fSopenharmony_ci                    continue;
6783af6ab5fSopenharmony_ci                }
6793af6ab5fSopenharmony_ci            }
6803af6ab5fSopenharmony_ci
6813af6ab5fSopenharmony_ci            checker::Type *propType = GetTypeForProperty(prop, checker);
6823af6ab5fSopenharmony_ci            binder::VariableFlags flags = GetFlagsForProperty(prop);
6833af6ab5fSopenharmony_ci            const util::StringView &propName = GetPropertyName(prop->Key());
6843af6ab5fSopenharmony_ci
6853af6ab5fSopenharmony_ci            auto *memberVar = binder::Scope::CreateVar(checker->Allocator(), propName, flags, it);
6863af6ab5fSopenharmony_ci            CHECK_NOT_NULL(memberVar);
6873af6ab5fSopenharmony_ci            if (inConstContext) {
6883af6ab5fSopenharmony_ci                memberVar->AddFlag(binder::VariableFlags::READONLY);
6893af6ab5fSopenharmony_ci            } else {
6903af6ab5fSopenharmony_ci                propType = checker->GetBaseTypeOfLiteralType(propType);
6913af6ab5fSopenharmony_ci            }
6923af6ab5fSopenharmony_ci
6933af6ab5fSopenharmony_ci            memberVar->SetTsType(propType);
6943af6ab5fSopenharmony_ci
6953af6ab5fSopenharmony_ci            if (prop->Key()->IsNumberLiteral()) {
6963af6ab5fSopenharmony_ci                memberVar->AddFlag(binder::VariableFlags::NUMERIC_NAME);
6973af6ab5fSopenharmony_ci            }
6983af6ab5fSopenharmony_ci
6993af6ab5fSopenharmony_ci            binder::LocalVariable *foundMember = desc->FindProperty(propName);
7003af6ab5fSopenharmony_ci            allPropertiesMap.insert({propName, it->Start()});
7013af6ab5fSopenharmony_ci
7023af6ab5fSopenharmony_ci            if (foundMember) {
7033af6ab5fSopenharmony_ci                foundMember->SetTsType(propType);
7043af6ab5fSopenharmony_ci                continue;
7053af6ab5fSopenharmony_ci            }
7063af6ab5fSopenharmony_ci
7073af6ab5fSopenharmony_ci            desc->properties.push_back(memberVar);
7083af6ab5fSopenharmony_ci            continue;
7093af6ab5fSopenharmony_ci        }
7103af6ab5fSopenharmony_ci
7113af6ab5fSopenharmony_ci        ASSERT(it->IsSpreadElement());
7123af6ab5fSopenharmony_ci
7133af6ab5fSopenharmony_ci        checker::Type *spreadType = it->AsSpreadElement()->Argument()->Check(checker);
7143af6ab5fSopenharmony_ci        seenSpread = true;
7153af6ab5fSopenharmony_ci
7163af6ab5fSopenharmony_ci        // TODO(aszilagyi): handle union of object types
7173af6ab5fSopenharmony_ci        if (!spreadType->IsObjectType()) {
7183af6ab5fSopenharmony_ci            checker->ThrowTypeError("Spread types may only be created from object types.", it->Start());
7193af6ab5fSopenharmony_ci        }
7203af6ab5fSopenharmony_ci
7213af6ab5fSopenharmony_ci        for (auto *spreadProp : spreadType->AsObjectType()->Properties()) {
7223af6ab5fSopenharmony_ci            auto found = allPropertiesMap.find(spreadProp->Name());
7233af6ab5fSopenharmony_ci            if (found != allPropertiesMap.end()) {
7243af6ab5fSopenharmony_ci                checker->ThrowTypeError(
7253af6ab5fSopenharmony_ci                    {found->first, " is specified more than once, so this usage will be overwritten."}, found->second);
7263af6ab5fSopenharmony_ci            }
7273af6ab5fSopenharmony_ci
7283af6ab5fSopenharmony_ci            binder::LocalVariable *foundMember = desc->FindProperty(spreadProp->Name());
7293af6ab5fSopenharmony_ci
7303af6ab5fSopenharmony_ci            if (foundMember) {
7313af6ab5fSopenharmony_ci                foundMember->SetTsType(spreadProp->TsType());
7323af6ab5fSopenharmony_ci                continue;
7333af6ab5fSopenharmony_ci            }
7343af6ab5fSopenharmony_ci
7353af6ab5fSopenharmony_ci            desc->properties.push_back(spreadProp);
7363af6ab5fSopenharmony_ci        }
7373af6ab5fSopenharmony_ci    }
7383af6ab5fSopenharmony_ci
7393af6ab5fSopenharmony_ci    if (!seenSpread && (hasComputedNumberProperty || hasComputedStringProperty)) {
7403af6ab5fSopenharmony_ci        for (auto *it : desc->properties) {
7413af6ab5fSopenharmony_ci            computedStringPropTypes.push_back(it->TsType());
7423af6ab5fSopenharmony_ci
7433af6ab5fSopenharmony_ci            if (hasComputedNumberProperty && it->HasFlag(binder::VariableFlags::NUMERIC_NAME)) {
7443af6ab5fSopenharmony_ci                computedNumberPropTypes.push_back(it->TsType());
7453af6ab5fSopenharmony_ci            }
7463af6ab5fSopenharmony_ci        }
7473af6ab5fSopenharmony_ci
7483af6ab5fSopenharmony_ci        if (hasComputedNumberProperty) {
7493af6ab5fSopenharmony_ci            desc->numberIndexInfo = checker->Allocator()->New<checker::IndexInfo>(
7503af6ab5fSopenharmony_ci                checker->CreateUnionType(std::move(computedNumberPropTypes)), "x", inConstContext);
7513af6ab5fSopenharmony_ci        }
7523af6ab5fSopenharmony_ci
7533af6ab5fSopenharmony_ci        if (hasComputedStringProperty) {
7543af6ab5fSopenharmony_ci            desc->stringIndexInfo = checker->Allocator()->New<checker::IndexInfo>(
7553af6ab5fSopenharmony_ci                checker->CreateUnionType(std::move(computedStringPropTypes)), "x", inConstContext);
7563af6ab5fSopenharmony_ci        }
7573af6ab5fSopenharmony_ci    }
7583af6ab5fSopenharmony_ci
7593af6ab5fSopenharmony_ci    checker::Type *returnType = checker->Allocator()->New<checker::ObjectLiteralType>(desc);
7603af6ab5fSopenharmony_ci    CHECK_NOT_NULL(returnType);
7613af6ab5fSopenharmony_ci    returnType->AsObjectType()->AddObjectFlag(checker::ObjectFlags::RESOLVED_MEMBERS |
7623af6ab5fSopenharmony_ci                                              checker::ObjectFlags::CHECK_EXCESS_PROPS);
7633af6ab5fSopenharmony_ci    return returnType;
7643af6ab5fSopenharmony_ci}
7653af6ab5fSopenharmony_ci
7663af6ab5fSopenharmony_civoid ObjectExpression::UpdateSelf(const NodeUpdater &cb, [[maybe_unused]] binder::Binder *binder)
7673af6ab5fSopenharmony_ci{
7683af6ab5fSopenharmony_ci    for (auto iter = properties_.begin(); iter != properties_.end(); iter++) {
7693af6ab5fSopenharmony_ci        *iter = std::get<ir::AstNode *>(cb(*iter))->AsExpression();
7703af6ab5fSopenharmony_ci    }
7713af6ab5fSopenharmony_ci
7723af6ab5fSopenharmony_ci    if (typeAnnotation_) {
7733af6ab5fSopenharmony_ci        typeAnnotation_ = std::get<ir::AstNode *>(cb(typeAnnotation_))->AsExpression();
7743af6ab5fSopenharmony_ci    }
7753af6ab5fSopenharmony_ci}
7763af6ab5fSopenharmony_ci
7773af6ab5fSopenharmony_ci}  // namespace panda::es2panda::ir
778