13af6ab5fSopenharmony_ci/**
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2024 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 "destructuringContext.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include "util/helpers.h"
193af6ab5fSopenharmony_ci#include "varbinder/scope.h"
203af6ab5fSopenharmony_ci#include "ir/typeNode.h"
213af6ab5fSopenharmony_ci#include "ir/expressions/identifier.h"
223af6ab5fSopenharmony_ci#include "ir/expressions/objectExpression.h"
233af6ab5fSopenharmony_ci#include "ir/expressions/assignmentExpression.h"
243af6ab5fSopenharmony_ci#include "ir/expressions/arrayExpression.h"
253af6ab5fSopenharmony_ci#include "ir/base/spreadElement.h"
263af6ab5fSopenharmony_ci#include "ir/base/property.h"
273af6ab5fSopenharmony_ci#include "ir/expression.h"
283af6ab5fSopenharmony_ci
293af6ab5fSopenharmony_cinamespace ark::es2panda::checker {
303af6ab5fSopenharmony_civoid DestructuringContext::Prepare(ir::TypeNode *typeAnnotation, ir::Expression *initializer,
313af6ab5fSopenharmony_ci                                   const lexer::SourcePosition &loc)
323af6ab5fSopenharmony_ci{
333af6ab5fSopenharmony_ci    if (typeAnnotation != nullptr) {
343af6ab5fSopenharmony_ci        typeAnnotation->Check(checker_);
353af6ab5fSopenharmony_ci        Type *annotationType = typeAnnotation->GetType(checker_);
363af6ab5fSopenharmony_ci
373af6ab5fSopenharmony_ci        if (initializer != nullptr) {
383af6ab5fSopenharmony_ci            checker_->ElaborateElementwise(annotationType, initializer, loc);
393af6ab5fSopenharmony_ci        }
403af6ab5fSopenharmony_ci
413af6ab5fSopenharmony_ci        validateTypeAnnotation_ = true;
423af6ab5fSopenharmony_ci        inferredType_ = annotationType;
433af6ab5fSopenharmony_ci        return;
443af6ab5fSopenharmony_ci    }
453af6ab5fSopenharmony_ci
463af6ab5fSopenharmony_ci    if (initializer != nullptr) {
473af6ab5fSopenharmony_ci        if (!initializer->IsObjectExpression()) {
483af6ab5fSopenharmony_ci            validateObjectPatternInitializer_ = false;
493af6ab5fSopenharmony_ci        }
503af6ab5fSopenharmony_ci
513af6ab5fSopenharmony_ci        inferredType_ = initializer->Check(checker_);
523af6ab5fSopenharmony_ci    }
533af6ab5fSopenharmony_ci}
543af6ab5fSopenharmony_ci
553af6ab5fSopenharmony_civoid DestructuringContext::HandleDestructuringAssignment(ir::Identifier *ident, Type *inferredType, Type *defaultType)
563af6ab5fSopenharmony_ci{
573af6ab5fSopenharmony_ci    if (ident->Variable() == nullptr) {
583af6ab5fSopenharmony_ci        checker_->ThrowTypeError({"Cannot find name '", ident->Name(), "'."}, ident->Start());
593af6ab5fSopenharmony_ci    }
603af6ab5fSopenharmony_ci
613af6ab5fSopenharmony_ci    varbinder::Variable *variable = ident->Variable();
623af6ab5fSopenharmony_ci    ASSERT(variable->TsType());
633af6ab5fSopenharmony_ci
643af6ab5fSopenharmony_ci    if (defaultType != nullptr && !checker_->IsTypeAssignableTo(defaultType, variable->TsType())) {
653af6ab5fSopenharmony_ci        checker_->ThrowAssignmentError(defaultType, variable->TsType(), ident->Start());
663af6ab5fSopenharmony_ci    }
673af6ab5fSopenharmony_ci
683af6ab5fSopenharmony_ci    if (inferredType != nullptr && !checker_->IsTypeAssignableTo(inferredType, variable->TsType())) {
693af6ab5fSopenharmony_ci        checker_->ThrowAssignmentError(inferredType, variable->TsType(), ident->Start());
703af6ab5fSopenharmony_ci    }
713af6ab5fSopenharmony_ci}
723af6ab5fSopenharmony_ci
733af6ab5fSopenharmony_civoid DestructuringContext::SetInferredTypeForVariable(varbinder::Variable *var, Type *inferredType,
743af6ab5fSopenharmony_ci                                                      const lexer::SourcePosition &loc)
753af6ab5fSopenharmony_ci{
763af6ab5fSopenharmony_ci    ASSERT(var);
773af6ab5fSopenharmony_ci
783af6ab5fSopenharmony_ci    if (!checker_->HasStatus(CheckerStatus::IN_CONST_CONTEXT)) {
793af6ab5fSopenharmony_ci        inferredType = checker_->GetBaseTypeOfLiteralType(inferredType);
803af6ab5fSopenharmony_ci    }
813af6ab5fSopenharmony_ci
823af6ab5fSopenharmony_ci    if (var->TsType() != nullptr) {
833af6ab5fSopenharmony_ci        checker_->IsTypeIdenticalTo(var->TsType(), inferredType,
843af6ab5fSopenharmony_ci                                    {"Subsequent variable declaration must have the same type. Variable '", var->Name(),
853af6ab5fSopenharmony_ci                                     "' must be of type '", var->TsType(), "', but here has type '", inferredType,
863af6ab5fSopenharmony_ci                                     "'."},
873af6ab5fSopenharmony_ci                                    loc);
883af6ab5fSopenharmony_ci        return;
893af6ab5fSopenharmony_ci    }
903af6ab5fSopenharmony_ci
913af6ab5fSopenharmony_ci    if (signatureInfo_ != nullptr) {
923af6ab5fSopenharmony_ci        signatureInfo_->params.push_back(var->AsLocalVariable());
933af6ab5fSopenharmony_ci        signatureInfo_->minArgCount++;
943af6ab5fSopenharmony_ci    }
953af6ab5fSopenharmony_ci
963af6ab5fSopenharmony_ci    var->SetTsType(inferredType);
973af6ab5fSopenharmony_ci}
983af6ab5fSopenharmony_ci
993af6ab5fSopenharmony_civoid DestructuringContext::ValidateObjectLiteralType(ObjectType *objType, ir::ObjectExpression *objPattern)
1003af6ab5fSopenharmony_ci{
1013af6ab5fSopenharmony_ci    for (const auto *sourceProp : objType->Properties()) {
1023af6ab5fSopenharmony_ci        const util::StringView &sourceName = sourceProp->Name();
1033af6ab5fSopenharmony_ci        bool found = false;
1043af6ab5fSopenharmony_ci
1053af6ab5fSopenharmony_ci        for (const auto *targetProp : objPattern->Properties()) {
1063af6ab5fSopenharmony_ci            if (targetProp->IsRestElement()) {
1073af6ab5fSopenharmony_ci                continue;
1083af6ab5fSopenharmony_ci            }
1093af6ab5fSopenharmony_ci
1103af6ab5fSopenharmony_ci            ASSERT(targetProp->IsProperty());
1113af6ab5fSopenharmony_ci            const util::StringView &targetName = targetProp->AsProperty()->Key()->AsIdentifier()->Name();
1123af6ab5fSopenharmony_ci
1133af6ab5fSopenharmony_ci            if (sourceName == targetName) {
1143af6ab5fSopenharmony_ci                found = true;
1153af6ab5fSopenharmony_ci                break;
1163af6ab5fSopenharmony_ci            }
1173af6ab5fSopenharmony_ci        }
1183af6ab5fSopenharmony_ci
1193af6ab5fSopenharmony_ci        if (!found) {
1203af6ab5fSopenharmony_ci            checker_->ThrowTypeError({"Object literal may only specify known properties, and property '", sourceName,
1213af6ab5fSopenharmony_ci                                      "' does not exist in the pattern."},
1223af6ab5fSopenharmony_ci                                     objPattern->Start());
1233af6ab5fSopenharmony_ci        }
1243af6ab5fSopenharmony_ci    }
1253af6ab5fSopenharmony_ci}
1263af6ab5fSopenharmony_ci
1273af6ab5fSopenharmony_ci// Helper function to reduce HandleAssignmentPattern and pass code checker
1283af6ab5fSopenharmony_civoid DestructuringContext::HandleAssignmentPatternArrayPattern(ir::AssignmentExpression *assignmentPattern,
1293af6ab5fSopenharmony_ci                                                               Type *inferredType)
1303af6ab5fSopenharmony_ci{
1313af6ab5fSopenharmony_ci    ArrayDestructuringContext nextContext = ArrayDestructuringContext(
1323af6ab5fSopenharmony_ci        {checker_, assignmentPattern->Left(), inAssignment_, convertTupleToArray_, nullptr, nullptr});
1333af6ab5fSopenharmony_ci    nextContext.SetInferredType(inferredType);
1343af6ab5fSopenharmony_ci    nextContext.Start();
1353af6ab5fSopenharmony_ci}
1363af6ab5fSopenharmony_ci
1373af6ab5fSopenharmony_ci// Helper function to reduce HandleAssignmentPattern and pass code checker
1383af6ab5fSopenharmony_civoid DestructuringContext::HandleAssignmentPatternIdentifier(ir::AssignmentExpression *assignmentPattern,
1393af6ab5fSopenharmony_ci                                                             Type *defaultType, Type *inferredType)
1403af6ab5fSopenharmony_ci{
1413af6ab5fSopenharmony_ci    if (validateTypeAnnotation_ && !checker_->IsTypeAssignableTo(defaultType, inferredType)) {
1423af6ab5fSopenharmony_ci        checker_->ThrowAssignmentError(defaultType, inferredType, assignmentPattern->Left()->Start());
1433af6ab5fSopenharmony_ci    }
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_ci    SetInferredTypeForVariable(assignmentPattern->Left()->AsIdentifier()->Variable(), inferredType,
1463af6ab5fSopenharmony_ci                               assignmentPattern->Start());
1473af6ab5fSopenharmony_ci}
1483af6ab5fSopenharmony_ci
1493af6ab5fSopenharmony_civoid DestructuringContext::HandleAssignmentPattern(ir::AssignmentExpression *assignmentPattern, Type *inferredType,
1503af6ab5fSopenharmony_ci                                                   bool validateDefault)
1513af6ab5fSopenharmony_ci{
1523af6ab5fSopenharmony_ci    if (!assignmentPattern->Left()->IsArrayPattern()) {
1533af6ab5fSopenharmony_ci        checker_->RemoveStatus(CheckerStatus::FORCE_TUPLE);
1543af6ab5fSopenharmony_ci    }
1553af6ab5fSopenharmony_ci
1563af6ab5fSopenharmony_ci    Type *defaultType = assignmentPattern->Right()->Check(checker_);
1573af6ab5fSopenharmony_ci    if (!checker_->HasStatus(CheckerStatus::IN_CONST_CONTEXT)) {
1583af6ab5fSopenharmony_ci        defaultType = checker_->GetBaseTypeOfLiteralType(defaultType);
1593af6ab5fSopenharmony_ci    }
1603af6ab5fSopenharmony_ci
1613af6ab5fSopenharmony_ci    if (validateDefault && assignmentPattern->Right()->IsObjectExpression() &&
1623af6ab5fSopenharmony_ci        assignmentPattern->Left()->IsObjectPattern()) {
1633af6ab5fSopenharmony_ci        ValidateObjectLiteralType(defaultType->AsObjectType(), assignmentPattern->Left()->AsObjectPattern());
1643af6ab5fSopenharmony_ci    }
1653af6ab5fSopenharmony_ci
1663af6ab5fSopenharmony_ci    Type *initType = inferredType;
1673af6ab5fSopenharmony_ci    checker_->AddStatus(CheckerStatus::FORCE_TUPLE);
1683af6ab5fSopenharmony_ci
1693af6ab5fSopenharmony_ci    if (validateTypeAnnotation_) {
1703af6ab5fSopenharmony_ci        if (inferredType == nullptr) {
1713af6ab5fSopenharmony_ci            inferredType = checker_->GlobalUndefinedType();
1723af6ab5fSopenharmony_ci        }
1733af6ab5fSopenharmony_ci    } else {
1743af6ab5fSopenharmony_ci        if (inferredType == nullptr) {
1753af6ab5fSopenharmony_ci            inferredType = defaultType;
1763af6ab5fSopenharmony_ci        } else if (inferredType->IsUnionType()) {
1773af6ab5fSopenharmony_ci            inferredType->AsUnionType()->AddConstituentType(defaultType, checker_->Relation());
1783af6ab5fSopenharmony_ci        } else {
1793af6ab5fSopenharmony_ci            inferredType = checker_->CreateUnionType({inferredType, defaultType});
1803af6ab5fSopenharmony_ci        }
1813af6ab5fSopenharmony_ci    }
1823af6ab5fSopenharmony_ci
1833af6ab5fSopenharmony_ci    if (assignmentPattern->Left()->IsIdentifier()) {
1843af6ab5fSopenharmony_ci        if (inAssignment_) {
1853af6ab5fSopenharmony_ci            HandleDestructuringAssignment(assignmentPattern->Left()->AsIdentifier(), initType, defaultType);
1863af6ab5fSopenharmony_ci            return;
1873af6ab5fSopenharmony_ci        }
1883af6ab5fSopenharmony_ci
1893af6ab5fSopenharmony_ci        HandleAssignmentPatternIdentifier(assignmentPattern, defaultType, inferredType);
1903af6ab5fSopenharmony_ci        return;
1913af6ab5fSopenharmony_ci    }
1923af6ab5fSopenharmony_ci
1933af6ab5fSopenharmony_ci    if (assignmentPattern->Left()->IsArrayPattern()) {
1943af6ab5fSopenharmony_ci        HandleAssignmentPatternArrayPattern(assignmentPattern, inferredType);
1953af6ab5fSopenharmony_ci        return;
1963af6ab5fSopenharmony_ci    }
1973af6ab5fSopenharmony_ci
1983af6ab5fSopenharmony_ci    ASSERT(assignmentPattern->Left()->IsObjectPattern());
1993af6ab5fSopenharmony_ci    ObjectDestructuringContext nextContext = ObjectDestructuringContext(
2003af6ab5fSopenharmony_ci        {checker_, assignmentPattern->Left(), inAssignment_, convertTupleToArray_, nullptr, nullptr});
2013af6ab5fSopenharmony_ci    nextContext.SetInferredType(inferredType);
2023af6ab5fSopenharmony_ci    nextContext.Start();
2033af6ab5fSopenharmony_ci}
2043af6ab5fSopenharmony_ci
2053af6ab5fSopenharmony_civoid ArrayDestructuringContext::ValidateInferredType()
2063af6ab5fSopenharmony_ci{
2073af6ab5fSopenharmony_ci    if (!inferredType_->IsArrayType() && !inferredType_->IsUnionType() &&
2083af6ab5fSopenharmony_ci        (!inferredType_->IsObjectType() || !inferredType_->AsObjectType()->IsTupleType())) {
2093af6ab5fSopenharmony_ci        checker_->ThrowTypeError(
2103af6ab5fSopenharmony_ci            {"Type ", inferredType_, " must have a '[Symbol.iterator]()' method that returns an iterator."},
2113af6ab5fSopenharmony_ci            id_->Start());
2123af6ab5fSopenharmony_ci    }
2133af6ab5fSopenharmony_ci
2143af6ab5fSopenharmony_ci    if (inferredType_->IsUnionType()) {
2153af6ab5fSopenharmony_ci        for (auto *it : inferredType_->AsUnionType()->ConstituentTypes()) {
2163af6ab5fSopenharmony_ci            if (!it->IsArrayType() && (!it->IsObjectType() || !it->AsObjectType()->IsTupleType())) {
2173af6ab5fSopenharmony_ci                checker_->ThrowTypeError(
2183af6ab5fSopenharmony_ci                    {"Type ", inferredType_, " must have a '[Symbol.iterator]()' method that returns an iterator."},
2193af6ab5fSopenharmony_ci                    id_->Start());
2203af6ab5fSopenharmony_ci            }
2213af6ab5fSopenharmony_ci        }
2223af6ab5fSopenharmony_ci    }
2233af6ab5fSopenharmony_ci}
2243af6ab5fSopenharmony_ci
2253af6ab5fSopenharmony_ciType *ArrayDestructuringContext::GetTypeFromTupleByIndex(TupleType *tuple)
2263af6ab5fSopenharmony_ci{
2273af6ab5fSopenharmony_ci    util::StringView memberIndex = util::Helpers::ToStringView(checker_->Allocator(), index_);
2283af6ab5fSopenharmony_ci    varbinder::Variable *memberVar = tuple->GetProperty(memberIndex, false);
2293af6ab5fSopenharmony_ci
2303af6ab5fSopenharmony_ci    if (memberVar == nullptr) {
2313af6ab5fSopenharmony_ci        return nullptr;
2323af6ab5fSopenharmony_ci    }
2333af6ab5fSopenharmony_ci
2343af6ab5fSopenharmony_ci    return memberVar->TsType();
2353af6ab5fSopenharmony_ci}
2363af6ab5fSopenharmony_ci
2373af6ab5fSopenharmony_ciType *ArrayDestructuringContext::NextInferredType([[maybe_unused]] const util::StringView &searchName, bool throwError)
2383af6ab5fSopenharmony_ci{
2393af6ab5fSopenharmony_ci    if (inferredType_->IsArrayType()) {
2403af6ab5fSopenharmony_ci        return inferredType_->AsArrayType()->ElementType();
2413af6ab5fSopenharmony_ci    }
2423af6ab5fSopenharmony_ci
2433af6ab5fSopenharmony_ci    if (inferredType_->IsObjectType()) {
2443af6ab5fSopenharmony_ci        ASSERT(inferredType_->AsObjectType()->IsTupleType());
2453af6ab5fSopenharmony_ci        Type *returnType = GetTypeFromTupleByIndex(inferredType_->AsObjectType()->AsTupleType());
2463af6ab5fSopenharmony_ci
2473af6ab5fSopenharmony_ci        if (returnType == nullptr && throwError) {
2483af6ab5fSopenharmony_ci            if (!validateTypeAnnotation_ && checker_->HasStatus(CheckerStatus::IN_PARAMETER)) {
2493af6ab5fSopenharmony_ci                return returnType;
2503af6ab5fSopenharmony_ci            }
2513af6ab5fSopenharmony_ci
2523af6ab5fSopenharmony_ci            checker_->ThrowTypeError({"Tuple type ", inferredType_, " of length ",
2533af6ab5fSopenharmony_ci                                      inferredType_->AsObjectType()->AsTupleType()->FixedLength(),
2543af6ab5fSopenharmony_ci                                      " has no element at index ", index_, "."},
2553af6ab5fSopenharmony_ci                                     id_->Start());
2563af6ab5fSopenharmony_ci        }
2573af6ab5fSopenharmony_ci
2583af6ab5fSopenharmony_ci        return returnType;
2593af6ab5fSopenharmony_ci    }
2603af6ab5fSopenharmony_ci
2613af6ab5fSopenharmony_ci    ASSERT(inferredType_->IsUnionType());
2623af6ab5fSopenharmony_ci
2633af6ab5fSopenharmony_ci    ArenaVector<Type *> unionTypes(checker_->Allocator()->Adapter());
2643af6ab5fSopenharmony_ci
2653af6ab5fSopenharmony_ci    for (auto *type : inferredType_->AsUnionType()->ConstituentTypes()) {
2663af6ab5fSopenharmony_ci        if (type->IsArrayType()) {
2673af6ab5fSopenharmony_ci            unionTypes.push_back(type->AsArrayType()->ElementType());
2683af6ab5fSopenharmony_ci            continue;
2693af6ab5fSopenharmony_ci        }
2703af6ab5fSopenharmony_ci
2713af6ab5fSopenharmony_ci        ASSERT(type->IsObjectType() && type->AsObjectType()->IsTupleType());
2723af6ab5fSopenharmony_ci        Type *elementType = GetTypeFromTupleByIndex(type->AsObjectType()->AsTupleType());
2733af6ab5fSopenharmony_ci
2743af6ab5fSopenharmony_ci        if (elementType == nullptr) {
2753af6ab5fSopenharmony_ci            continue;
2763af6ab5fSopenharmony_ci        }
2773af6ab5fSopenharmony_ci
2783af6ab5fSopenharmony_ci        unionTypes.push_back(elementType);
2793af6ab5fSopenharmony_ci    }
2803af6ab5fSopenharmony_ci
2813af6ab5fSopenharmony_ci    if (unionTypes.empty()) {
2823af6ab5fSopenharmony_ci        if (throwError) {
2833af6ab5fSopenharmony_ci            checker_->ThrowTypeError({"Property ", index_, " does not exist on type ", inferredType_, "."},
2843af6ab5fSopenharmony_ci                                     id_->Start());
2853af6ab5fSopenharmony_ci        }
2863af6ab5fSopenharmony_ci
2873af6ab5fSopenharmony_ci        return nullptr;
2883af6ab5fSopenharmony_ci    }
2893af6ab5fSopenharmony_ci
2903af6ab5fSopenharmony_ci    return checker_->CreateUnionType(std::move(unionTypes));
2913af6ab5fSopenharmony_ci}
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ciType *ArrayDestructuringContext::CreateArrayTypeForRest(UnionType *inferredType)
2943af6ab5fSopenharmony_ci{
2953af6ab5fSopenharmony_ci    ArenaVector<Type *> unionTypes(checker_->Allocator()->Adapter());
2963af6ab5fSopenharmony_ci    uint32_t savedIdx = index_;
2973af6ab5fSopenharmony_ci
2983af6ab5fSopenharmony_ci    for (auto *it : inferredType->ConstituentTypes()) {
2993af6ab5fSopenharmony_ci        if (it->IsArrayType()) {
3003af6ab5fSopenharmony_ci            unionTypes.push_back(it->AsArrayType()->ElementType());
3013af6ab5fSopenharmony_ci            continue;
3023af6ab5fSopenharmony_ci        }
3033af6ab5fSopenharmony_ci
3043af6ab5fSopenharmony_ci        ASSERT(it->IsObjectType() && it->AsObjectType()->IsTupleType());
3053af6ab5fSopenharmony_ci        Type *tupleElementType = GetTypeFromTupleByIndex(it->AsObjectType()->AsTupleType());
3063af6ab5fSopenharmony_ci
3073af6ab5fSopenharmony_ci        while (tupleElementType != nullptr) {
3083af6ab5fSopenharmony_ci            unionTypes.push_back(tupleElementType);
3093af6ab5fSopenharmony_ci            index_++;
3103af6ab5fSopenharmony_ci            tupleElementType = GetTypeFromTupleByIndex(it->AsObjectType()->AsTupleType());
3113af6ab5fSopenharmony_ci        }
3123af6ab5fSopenharmony_ci
3133af6ab5fSopenharmony_ci        index_ = savedIdx;
3143af6ab5fSopenharmony_ci    }
3153af6ab5fSopenharmony_ci
3163af6ab5fSopenharmony_ci    Type *restArrayElementType = checker_->CreateUnionType(std::move(unionTypes));
3173af6ab5fSopenharmony_ci    return checker_->Allocator()->New<ArrayType>(restArrayElementType);
3183af6ab5fSopenharmony_ci}
3193af6ab5fSopenharmony_ci
3203af6ab5fSopenharmony_ciType *ArrayDestructuringContext::CreateTupleTypeForRest(TupleType *tuple)
3213af6ab5fSopenharmony_ci{
3223af6ab5fSopenharmony_ci    ObjectDescriptor *desc = checker_->Allocator()->New<ObjectDescriptor>(checker_->Allocator());
3233af6ab5fSopenharmony_ci    ArenaVector<ElementFlags> elementFlags(checker_->Allocator()->Adapter());
3243af6ab5fSopenharmony_ci    uint32_t savedIdx = index_;
3253af6ab5fSopenharmony_ci    uint32_t iterIndex = 0;
3263af6ab5fSopenharmony_ci
3273af6ab5fSopenharmony_ci    Type *tupleElementType = GetTypeFromTupleByIndex(tuple);
3283af6ab5fSopenharmony_ci
3293af6ab5fSopenharmony_ci    while (tupleElementType != nullptr) {
3303af6ab5fSopenharmony_ci        ElementFlags memberFlag = ElementFlags::REQUIRED;
3313af6ab5fSopenharmony_ci        util::StringView memberIndex = util::Helpers::ToStringView(checker_->Allocator(), iterIndex);
3323af6ab5fSopenharmony_ci        auto *memberVar = varbinder::Scope::CreateVar(checker_->Allocator(), memberIndex,
3333af6ab5fSopenharmony_ci                                                      varbinder::VariableFlags::PROPERTY, nullptr);
3343af6ab5fSopenharmony_ci        memberVar->SetTsType(tupleElementType);
3353af6ab5fSopenharmony_ci        elementFlags.push_back(memberFlag);
3363af6ab5fSopenharmony_ci        desc->properties.push_back(memberVar);
3373af6ab5fSopenharmony_ci
3383af6ab5fSopenharmony_ci        index_++;
3393af6ab5fSopenharmony_ci        iterIndex++;
3403af6ab5fSopenharmony_ci
3413af6ab5fSopenharmony_ci        tupleElementType = GetTypeFromTupleByIndex(tuple);
3423af6ab5fSopenharmony_ci    }
3433af6ab5fSopenharmony_ci
3443af6ab5fSopenharmony_ci    index_ = savedIdx;
3453af6ab5fSopenharmony_ci    const checker::TupleTypeInfo tupleTypeInfo = {ElementFlags::REQUIRED, iterIndex, iterIndex, false};
3463af6ab5fSopenharmony_ci    return checker_->CreateTupleType(desc, std::move(elementFlags), tupleTypeInfo);
3473af6ab5fSopenharmony_ci}
3483af6ab5fSopenharmony_ci
3493af6ab5fSopenharmony_ciType *ArrayDestructuringContext::GetRestType([[maybe_unused]] const lexer::SourcePosition &loc)
3503af6ab5fSopenharmony_ci{
3513af6ab5fSopenharmony_ci    if (inferredType_->IsArrayType()) {
3523af6ab5fSopenharmony_ci        return inferredType_;
3533af6ab5fSopenharmony_ci    }
3543af6ab5fSopenharmony_ci
3553af6ab5fSopenharmony_ci    if (inferredType_->IsObjectType() && inferredType_->AsObjectType()->IsTupleType()) {
3563af6ab5fSopenharmony_ci        return CreateTupleTypeForRest(inferredType_->AsObjectType()->AsTupleType());
3573af6ab5fSopenharmony_ci    }
3583af6ab5fSopenharmony_ci
3593af6ab5fSopenharmony_ci    ASSERT(inferredType_->IsUnionType());
3603af6ab5fSopenharmony_ci    bool createArrayType = false;
3613af6ab5fSopenharmony_ci
3623af6ab5fSopenharmony_ci    for (auto *it : inferredType_->AsUnionType()->ConstituentTypes()) {
3633af6ab5fSopenharmony_ci        if (it->IsArrayType()) {
3643af6ab5fSopenharmony_ci            createArrayType = true;
3653af6ab5fSopenharmony_ci            break;
3663af6ab5fSopenharmony_ci        }
3673af6ab5fSopenharmony_ci    }
3683af6ab5fSopenharmony_ci
3693af6ab5fSopenharmony_ci    if (createArrayType) {
3703af6ab5fSopenharmony_ci        return CreateArrayTypeForRest(inferredType_->AsUnionType());
3713af6ab5fSopenharmony_ci    }
3723af6ab5fSopenharmony_ci
3733af6ab5fSopenharmony_ci    ArenaVector<Type *> tupleUnion(checker_->Allocator()->Adapter());
3743af6ab5fSopenharmony_ci
3753af6ab5fSopenharmony_ci    for (auto *it : inferredType_->AsUnionType()->ConstituentTypes()) {
3763af6ab5fSopenharmony_ci        ASSERT(it->IsObjectType() && it->AsObjectType()->IsTupleType());
3773af6ab5fSopenharmony_ci        Type *newTuple = CreateTupleTypeForRest(it->AsObjectType()->AsTupleType());
3783af6ab5fSopenharmony_ci        tupleUnion.push_back(newTuple);
3793af6ab5fSopenharmony_ci    }
3803af6ab5fSopenharmony_ci
3813af6ab5fSopenharmony_ci    return checker_->CreateUnionType(std::move(tupleUnion));
3823af6ab5fSopenharmony_ci}
3833af6ab5fSopenharmony_ci
3843af6ab5fSopenharmony_civoid ArrayDestructuringContext::HandleRest(ir::SpreadElement *rest)
3853af6ab5fSopenharmony_ci{
3863af6ab5fSopenharmony_ci    Type *inferredRestType = GetRestType(rest->Start());
3873af6ab5fSopenharmony_ci
3883af6ab5fSopenharmony_ci    if (rest->Argument()->IsIdentifier()) {
3893af6ab5fSopenharmony_ci        if (inAssignment_) {
3903af6ab5fSopenharmony_ci            HandleDestructuringAssignment(rest->Argument()->AsIdentifier(), inferredRestType, nullptr);
3913af6ab5fSopenharmony_ci            return;
3923af6ab5fSopenharmony_ci        }
3933af6ab5fSopenharmony_ci
3943af6ab5fSopenharmony_ci        SetInferredTypeForVariable(rest->Argument()->AsIdentifier()->Variable(), inferredRestType, rest->Start());
3953af6ab5fSopenharmony_ci        return;
3963af6ab5fSopenharmony_ci    }
3973af6ab5fSopenharmony_ci
3983af6ab5fSopenharmony_ci    if (rest->Argument()->IsArrayPattern()) {
3993af6ab5fSopenharmony_ci        ArrayDestructuringContext nextContext = ArrayDestructuringContext(
4003af6ab5fSopenharmony_ci            {checker_, rest->Argument(), inAssignment_, convertTupleToArray_, nullptr, nullptr});
4013af6ab5fSopenharmony_ci        nextContext.SetInferredType(inferredRestType);
4023af6ab5fSopenharmony_ci        nextContext.Start();
4033af6ab5fSopenharmony_ci        return;
4043af6ab5fSopenharmony_ci    }
4053af6ab5fSopenharmony_ci
4063af6ab5fSopenharmony_ci    ASSERT(rest->Argument()->IsObjectPattern());
4073af6ab5fSopenharmony_ci    ObjectDestructuringContext nextContext =
4083af6ab5fSopenharmony_ci        ObjectDestructuringContext({checker_, rest->Argument(), inAssignment_, convertTupleToArray_, nullptr, nullptr});
4093af6ab5fSopenharmony_ci    nextContext.SetInferredType(inferredRestType);
4103af6ab5fSopenharmony_ci    nextContext.Start();
4113af6ab5fSopenharmony_ci}
4123af6ab5fSopenharmony_ci
4133af6ab5fSopenharmony_ciType *ArrayDestructuringContext::ConvertTupleTypeToArrayTypeIfNecessary(ir::AstNode *node, Type *type)
4143af6ab5fSopenharmony_ci{
4153af6ab5fSopenharmony_ci    if (!convertTupleToArray_) {
4163af6ab5fSopenharmony_ci        return type;
4173af6ab5fSopenharmony_ci    }
4183af6ab5fSopenharmony_ci
4193af6ab5fSopenharmony_ci    if (type == nullptr) {
4203af6ab5fSopenharmony_ci        return type;
4213af6ab5fSopenharmony_ci    }
4223af6ab5fSopenharmony_ci
4233af6ab5fSopenharmony_ci    if (node->IsArrayPattern() ||
4243af6ab5fSopenharmony_ci        (node->IsAssignmentPattern() && node->AsAssignmentPattern()->Left()->IsArrayPattern())) {
4253af6ab5fSopenharmony_ci        return type;
4263af6ab5fSopenharmony_ci    }
4273af6ab5fSopenharmony_ci
4283af6ab5fSopenharmony_ci    if (type->IsObjectType() && type->AsObjectType()->IsTupleType()) {
4293af6ab5fSopenharmony_ci        return type->AsObjectType()->AsTupleType()->ConvertToArrayType(checker_);
4303af6ab5fSopenharmony_ci    }
4313af6ab5fSopenharmony_ci
4323af6ab5fSopenharmony_ci    return type;
4333af6ab5fSopenharmony_ci}
4343af6ab5fSopenharmony_ci
4353af6ab5fSopenharmony_cistatic void SetParameterType(ir::AstNode *parent, Type *type)
4363af6ab5fSopenharmony_ci{
4373af6ab5fSopenharmony_ci    parent->Iterate([type](ir::AstNode *childNode) -> void {
4383af6ab5fSopenharmony_ci        if (childNode->IsIdentifier() && childNode->AsIdentifier()->Variable() != nullptr) {
4393af6ab5fSopenharmony_ci            childNode->AsIdentifier()->Variable()->SetTsType(type);
4403af6ab5fSopenharmony_ci            return;
4413af6ab5fSopenharmony_ci        }
4423af6ab5fSopenharmony_ci
4433af6ab5fSopenharmony_ci        SetParameterType(childNode, type);
4443af6ab5fSopenharmony_ci    });
4453af6ab5fSopenharmony_ci}
4463af6ab5fSopenharmony_ci
4473af6ab5fSopenharmony_civoid ArrayDestructuringContext::SetRemainingParameterTypes()
4483af6ab5fSopenharmony_ci{
4493af6ab5fSopenharmony_ci    do {
4503af6ab5fSopenharmony_ci        auto *it = id_->AsArrayPattern()->Elements()[index_];
4513af6ab5fSopenharmony_ci        ASSERT(it);
4523af6ab5fSopenharmony_ci        SetParameterType(it, checker_->GlobalAnyType());
4533af6ab5fSopenharmony_ci    } while (++index_ != id_->AsArrayPattern()->Elements().size());
4543af6ab5fSopenharmony_ci}
4553af6ab5fSopenharmony_ci
4563af6ab5fSopenharmony_civoid ArrayDestructuringContext::HandleElement(ir::Expression *element, Type *nextInferredType)
4573af6ab5fSopenharmony_ci{
4583af6ab5fSopenharmony_ci    switch (element->Type()) {
4593af6ab5fSopenharmony_ci        case ir::AstNodeType::IDENTIFIER: {
4603af6ab5fSopenharmony_ci            if (inAssignment_) {
4613af6ab5fSopenharmony_ci                HandleDestructuringAssignment(element->AsIdentifier(), nextInferredType, nullptr);
4623af6ab5fSopenharmony_ci                break;
4633af6ab5fSopenharmony_ci            }
4643af6ab5fSopenharmony_ci
4653af6ab5fSopenharmony_ci            SetInferredTypeForVariable(element->AsIdentifier()->Variable(), nextInferredType, element->Start());
4663af6ab5fSopenharmony_ci            break;
4673af6ab5fSopenharmony_ci        }
4683af6ab5fSopenharmony_ci        case ir::AstNodeType::ARRAY_PATTERN: {
4693af6ab5fSopenharmony_ci            ArrayDestructuringContext nextContext =
4703af6ab5fSopenharmony_ci                ArrayDestructuringContext({checker_, element, inAssignment_, convertTupleToArray_, nullptr, nullptr});
4713af6ab5fSopenharmony_ci            nextContext.SetInferredType(nextInferredType);
4723af6ab5fSopenharmony_ci            nextContext.Start();
4733af6ab5fSopenharmony_ci            break;
4743af6ab5fSopenharmony_ci        }
4753af6ab5fSopenharmony_ci        case ir::AstNodeType::OBJECT_PATTERN: {
4763af6ab5fSopenharmony_ci            ObjectDestructuringContext nextContext =
4773af6ab5fSopenharmony_ci                ObjectDestructuringContext({checker_, element, inAssignment_, convertTupleToArray_, nullptr, nullptr});
4783af6ab5fSopenharmony_ci            nextContext.SetInferredType(nextInferredType);
4793af6ab5fSopenharmony_ci            nextContext.Start();
4803af6ab5fSopenharmony_ci            break;
4813af6ab5fSopenharmony_ci        }
4823af6ab5fSopenharmony_ci        case ir::AstNodeType::ASSIGNMENT_PATTERN: {
4833af6ab5fSopenharmony_ci            HandleAssignmentPattern(element->AsAssignmentPattern(), nextInferredType, false);
4843af6ab5fSopenharmony_ci            break;
4853af6ab5fSopenharmony_ci        }
4863af6ab5fSopenharmony_ci        case ir::AstNodeType::OMITTED_EXPRESSION: {
4873af6ab5fSopenharmony_ci            break;
4883af6ab5fSopenharmony_ci        }
4893af6ab5fSopenharmony_ci        default: {
4903af6ab5fSopenharmony_ci            UNREACHABLE();
4913af6ab5fSopenharmony_ci        }
4923af6ab5fSopenharmony_ci    }
4933af6ab5fSopenharmony_ci}
4943af6ab5fSopenharmony_ci
4953af6ab5fSopenharmony_civoid ArrayDestructuringContext::Start()
4963af6ab5fSopenharmony_ci{
4973af6ab5fSopenharmony_ci    ASSERT(id_->IsArrayPattern());
4983af6ab5fSopenharmony_ci
4993af6ab5fSopenharmony_ci    ValidateInferredType();
5003af6ab5fSopenharmony_ci
5013af6ab5fSopenharmony_ci    util::StringView name = util::Helpers::ToStringView(checker_->Allocator(), 0);
5023af6ab5fSopenharmony_ci
5033af6ab5fSopenharmony_ci    for (auto *it : id_->AsArrayPattern()->Elements()) {
5043af6ab5fSopenharmony_ci        if (it->IsRestElement()) {
5053af6ab5fSopenharmony_ci            HandleRest(it->AsRestElement());
5063af6ab5fSopenharmony_ci            break;
5073af6ab5fSopenharmony_ci        }
5083af6ab5fSopenharmony_ci
5093af6ab5fSopenharmony_ci        Type *nextInferredType =
5103af6ab5fSopenharmony_ci            ConvertTupleTypeToArrayTypeIfNecessary(it, NextInferredType(name, !it->IsAssignmentPattern()));
5113af6ab5fSopenharmony_ci
5123af6ab5fSopenharmony_ci        if (nextInferredType == nullptr && checker_->HasStatus(CheckerStatus::IN_PARAMETER)) {
5133af6ab5fSopenharmony_ci            SetRemainingParameterTypes();
5143af6ab5fSopenharmony_ci            return;
5153af6ab5fSopenharmony_ci        }
5163af6ab5fSopenharmony_ci
5173af6ab5fSopenharmony_ci        if (convertTupleToArray_ && nextInferredType != nullptr && inferredType_->IsObjectType()) {
5183af6ab5fSopenharmony_ci            ASSERT(inferredType_->AsObjectType()->IsTupleType());
5193af6ab5fSopenharmony_ci
5203af6ab5fSopenharmony_ci            varbinder::Variable *currentTupleElement = inferredType_->AsObjectType()->Properties()[index_];
5213af6ab5fSopenharmony_ci
5223af6ab5fSopenharmony_ci            if (currentTupleElement != nullptr) {
5233af6ab5fSopenharmony_ci                currentTupleElement->SetTsType(nextInferredType);
5243af6ab5fSopenharmony_ci            }
5253af6ab5fSopenharmony_ci        }
5263af6ab5fSopenharmony_ci
5273af6ab5fSopenharmony_ci        HandleElement(it, nextInferredType);
5283af6ab5fSopenharmony_ci        index_++;
5293af6ab5fSopenharmony_ci    }
5303af6ab5fSopenharmony_ci}
5313af6ab5fSopenharmony_ci
5323af6ab5fSopenharmony_civoid ObjectDestructuringContext::ValidateInferredType()
5333af6ab5fSopenharmony_ci{
5343af6ab5fSopenharmony_ci    if (!inferredType_->IsObjectType()) {
5353af6ab5fSopenharmony_ci        return;
5363af6ab5fSopenharmony_ci    }
5373af6ab5fSopenharmony_ci
5383af6ab5fSopenharmony_ci    ValidateObjectLiteralType(inferredType_->AsObjectType(), id_->AsObjectPattern());
5393af6ab5fSopenharmony_ci}
5403af6ab5fSopenharmony_ci
5413af6ab5fSopenharmony_civoid ObjectDestructuringContext::HandleRest(ir::SpreadElement *rest)
5423af6ab5fSopenharmony_ci{
5433af6ab5fSopenharmony_ci    Type *inferredRestType = GetRestType(rest->Start());
5443af6ab5fSopenharmony_ci    ASSERT(rest->Argument()->IsIdentifier());
5453af6ab5fSopenharmony_ci
5463af6ab5fSopenharmony_ci    if (inAssignment_) {
5473af6ab5fSopenharmony_ci        HandleDestructuringAssignment(rest->Argument()->AsIdentifier(), inferredRestType, nullptr);
5483af6ab5fSopenharmony_ci        return;
5493af6ab5fSopenharmony_ci    }
5503af6ab5fSopenharmony_ci
5513af6ab5fSopenharmony_ci    SetInferredTypeForVariable(rest->Argument()->AsIdentifier()->Variable(), inferredRestType, rest->Start());
5523af6ab5fSopenharmony_ci}
5533af6ab5fSopenharmony_ci
5543af6ab5fSopenharmony_ciType *ObjectDestructuringContext::CreateObjectTypeForRest(ObjectType *objType)
5553af6ab5fSopenharmony_ci{
5563af6ab5fSopenharmony_ci    ObjectDescriptor *desc = checker_->Allocator()->New<ObjectDescriptor>(checker_->Allocator());
5573af6ab5fSopenharmony_ci
5583af6ab5fSopenharmony_ci    for (auto *it : objType->AsObjectType()->Properties()) {
5593af6ab5fSopenharmony_ci        if (!it->HasFlag(varbinder::VariableFlags::INFERRED_IN_PATTERN)) {
5603af6ab5fSopenharmony_ci            auto *memberVar =
5613af6ab5fSopenharmony_ci                varbinder::Scope::CreateVar(checker_->Allocator(), it->Name(), varbinder::VariableFlags::NONE, nullptr);
5623af6ab5fSopenharmony_ci            memberVar->SetTsType(it->TsType());
5633af6ab5fSopenharmony_ci            memberVar->AddFlag(it->Flags());
5643af6ab5fSopenharmony_ci            desc->properties.push_back(memberVar);
5653af6ab5fSopenharmony_ci        }
5663af6ab5fSopenharmony_ci    }
5673af6ab5fSopenharmony_ci
5683af6ab5fSopenharmony_ci    Type *returnType = checker_->Allocator()->New<ObjectLiteralType>(desc);
5693af6ab5fSopenharmony_ci    returnType->AsObjectType()->AddObjectFlag(ObjectFlags::RESOLVED_MEMBERS);
5703af6ab5fSopenharmony_ci    return returnType;
5713af6ab5fSopenharmony_ci}
5723af6ab5fSopenharmony_ci
5733af6ab5fSopenharmony_ciType *ObjectDestructuringContext::GetRestType([[maybe_unused]] const lexer::SourcePosition &loc)
5743af6ab5fSopenharmony_ci{
5753af6ab5fSopenharmony_ci    if (inferredType_->IsUnionType()) {
5763af6ab5fSopenharmony_ci        ArenaVector<Type *> unionTypes(checker_->Allocator()->Adapter());
5773af6ab5fSopenharmony_ci
5783af6ab5fSopenharmony_ci        for (auto *it : inferredType_->AsUnionType()->ConstituentTypes()) {
5793af6ab5fSopenharmony_ci            if (it->IsObjectType()) {
5803af6ab5fSopenharmony_ci                unionTypes.push_back(CreateObjectTypeForRest(it->AsObjectType()));
5813af6ab5fSopenharmony_ci                continue;
5823af6ab5fSopenharmony_ci            }
5833af6ab5fSopenharmony_ci
5843af6ab5fSopenharmony_ci            checker_->ThrowTypeError("Rest types may only be created from object types.", loc);
5853af6ab5fSopenharmony_ci        }
5863af6ab5fSopenharmony_ci
5873af6ab5fSopenharmony_ci        return checker_->CreateUnionType(std::move(unionTypes));
5883af6ab5fSopenharmony_ci    }
5893af6ab5fSopenharmony_ci
5903af6ab5fSopenharmony_ci    if (inferredType_->IsObjectType()) {
5913af6ab5fSopenharmony_ci        return CreateObjectTypeForRest(inferredType_->AsObjectType());
5923af6ab5fSopenharmony_ci    }
5933af6ab5fSopenharmony_ci
5943af6ab5fSopenharmony_ci    checker_->ThrowTypeError("Rest types may only be created from object types.", loc);
5953af6ab5fSopenharmony_ci}
5963af6ab5fSopenharmony_ci
5973af6ab5fSopenharmony_ciType *ObjectDestructuringContext::ConvertTupleTypeToArrayTypeIfNecessary(ir::AstNode *node, Type *type)
5983af6ab5fSopenharmony_ci{
5993af6ab5fSopenharmony_ci    if (!convertTupleToArray_) {
6003af6ab5fSopenharmony_ci        return type;
6013af6ab5fSopenharmony_ci    }
6023af6ab5fSopenharmony_ci
6033af6ab5fSopenharmony_ci    if (type == nullptr) {
6043af6ab5fSopenharmony_ci        return type;
6053af6ab5fSopenharmony_ci    }
6063af6ab5fSopenharmony_ci
6073af6ab5fSopenharmony_ci    ASSERT(node->IsProperty());
6083af6ab5fSopenharmony_ci
6093af6ab5fSopenharmony_ci    ir::Property *property = node->AsProperty();
6103af6ab5fSopenharmony_ci
6113af6ab5fSopenharmony_ci    if (property->Value()->IsArrayPattern()) {
6123af6ab5fSopenharmony_ci        return type;
6133af6ab5fSopenharmony_ci    }
6143af6ab5fSopenharmony_ci
6153af6ab5fSopenharmony_ci    if (property->Value()->IsAssignmentPattern() &&
6163af6ab5fSopenharmony_ci        property->Value()->AsAssignmentPattern()->Left()->IsArrayPattern()) {
6173af6ab5fSopenharmony_ci        return type;
6183af6ab5fSopenharmony_ci    }
6193af6ab5fSopenharmony_ci
6203af6ab5fSopenharmony_ci    if (type->IsObjectType() && type->AsObjectType()->IsTupleType()) {
6213af6ab5fSopenharmony_ci        return type->AsObjectType()->AsTupleType()->ConvertToArrayType(checker_);
6223af6ab5fSopenharmony_ci    }
6233af6ab5fSopenharmony_ci
6243af6ab5fSopenharmony_ci    return type;
6253af6ab5fSopenharmony_ci}
6263af6ab5fSopenharmony_ci
6273af6ab5fSopenharmony_ciType *ObjectDestructuringContext::NextInferredType([[maybe_unused]] const util::StringView &searchName, bool throwError)
6283af6ab5fSopenharmony_ci{
6293af6ab5fSopenharmony_ci    varbinder::Variable *prop = checker_->GetPropertyOfType(inferredType_, searchName, !throwError,
6303af6ab5fSopenharmony_ci                                                            varbinder::VariableFlags::INFERRED_IN_PATTERN);
6313af6ab5fSopenharmony_ci
6323af6ab5fSopenharmony_ci    if (prop != nullptr) {
6333af6ab5fSopenharmony_ci        prop->AddFlag(varbinder::VariableFlags::INFERRED_IN_PATTERN);
6343af6ab5fSopenharmony_ci        return prop->TsType();
6353af6ab5fSopenharmony_ci    }
6363af6ab5fSopenharmony_ci
6373af6ab5fSopenharmony_ci    if (inferredType_->IsObjectType()) {
6383af6ab5fSopenharmony_ci        checker::ObjectType *objType = inferredType_->AsObjectType();
6393af6ab5fSopenharmony_ci
6403af6ab5fSopenharmony_ci        if (objType->StringIndexInfo() != nullptr) {
6413af6ab5fSopenharmony_ci            return objType->StringIndexInfo()->GetType();
6423af6ab5fSopenharmony_ci        }
6433af6ab5fSopenharmony_ci    }
6443af6ab5fSopenharmony_ci
6453af6ab5fSopenharmony_ci    if (throwError) {
6463af6ab5fSopenharmony_ci        checker_->ThrowTypeError({"Property ", searchName, " does not exist on type ", inferredType_, "."},
6473af6ab5fSopenharmony_ci                                 id_->Start());
6483af6ab5fSopenharmony_ci    }
6493af6ab5fSopenharmony_ci
6503af6ab5fSopenharmony_ci    return nullptr;
6513af6ab5fSopenharmony_ci}
6523af6ab5fSopenharmony_ci
6533af6ab5fSopenharmony_civoid ObjectDestructuringContext::Start()
6543af6ab5fSopenharmony_ci{
6553af6ab5fSopenharmony_ci    ASSERT(id_->IsObjectPattern());
6563af6ab5fSopenharmony_ci
6573af6ab5fSopenharmony_ci    if (!id_->AsObjectPattern()->Properties().back()->IsRestElement() && validateObjectPatternInitializer_) {
6583af6ab5fSopenharmony_ci        ValidateInferredType();
6593af6ab5fSopenharmony_ci    }
6603af6ab5fSopenharmony_ci
6613af6ab5fSopenharmony_ci    for (auto *it : id_->AsObjectPattern()->Properties()) {
6623af6ab5fSopenharmony_ci        switch (it->Type()) {
6633af6ab5fSopenharmony_ci            case ir::AstNodeType::PROPERTY: {
6643af6ab5fSopenharmony_ci                ir::Property *property = it->AsProperty();
6653af6ab5fSopenharmony_ci
6663af6ab5fSopenharmony_ci                if (property->IsComputed()) {
6673af6ab5fSopenharmony_ci                    // NOTE: aszilagyi.
6683af6ab5fSopenharmony_ci                    return;
6693af6ab5fSopenharmony_ci                }
6703af6ab5fSopenharmony_ci
6713af6ab5fSopenharmony_ci                Type *nextInferredType = ConvertTupleTypeToArrayTypeIfNecessary(
6723af6ab5fSopenharmony_ci                    it->AsProperty(),
6733af6ab5fSopenharmony_ci                    NextInferredType(property->Key()->AsIdentifier()->Name(),
6743af6ab5fSopenharmony_ci                                     (!property->Value()->IsAssignmentPattern() || validateTypeAnnotation_)));
6753af6ab5fSopenharmony_ci
6763af6ab5fSopenharmony_ci                if (property->Value()->IsIdentifier()) {
6773af6ab5fSopenharmony_ci                    if (inAssignment_) {
6783af6ab5fSopenharmony_ci                        HandleDestructuringAssignment(property->Value()->AsIdentifier(), nextInferredType, nullptr);
6793af6ab5fSopenharmony_ci                        break;
6803af6ab5fSopenharmony_ci                    }
6813af6ab5fSopenharmony_ci
6823af6ab5fSopenharmony_ci                    SetInferredTypeForVariable(property->Value()->AsIdentifier()->Variable(), nextInferredType,
6833af6ab5fSopenharmony_ci                                               it->Start());
6843af6ab5fSopenharmony_ci                    break;
6853af6ab5fSopenharmony_ci                }
6863af6ab5fSopenharmony_ci
6873af6ab5fSopenharmony_ci                if (property->Value()->IsArrayPattern()) {
6883af6ab5fSopenharmony_ci                    ArrayDestructuringContext nextContext =
6893af6ab5fSopenharmony_ci                        ArrayDestructuringContext({checker_, property->Value()->AsArrayPattern(), inAssignment_,
6903af6ab5fSopenharmony_ci                                                   convertTupleToArray_, nullptr, nullptr});
6913af6ab5fSopenharmony_ci                    nextContext.SetInferredType(nextInferredType);
6923af6ab5fSopenharmony_ci                    nextContext.Start();
6933af6ab5fSopenharmony_ci                    break;
6943af6ab5fSopenharmony_ci                }
6953af6ab5fSopenharmony_ci
6963af6ab5fSopenharmony_ci                if (property->Value()->IsObjectPattern()) {
6973af6ab5fSopenharmony_ci                    ObjectDestructuringContext nextContext =
6983af6ab5fSopenharmony_ci                        ObjectDestructuringContext({checker_, property->Value()->AsObjectPattern(), inAssignment_,
6993af6ab5fSopenharmony_ci                                                    convertTupleToArray_, nullptr, nullptr});
7003af6ab5fSopenharmony_ci                    nextContext.SetInferredType(nextInferredType);
7013af6ab5fSopenharmony_ci                    nextContext.Start();
7023af6ab5fSopenharmony_ci                    break;
7033af6ab5fSopenharmony_ci                }
7043af6ab5fSopenharmony_ci
7053af6ab5fSopenharmony_ci                ASSERT(property->Value()->IsAssignmentPattern());
7063af6ab5fSopenharmony_ci                HandleAssignmentPattern(property->Value()->AsAssignmentPattern(), nextInferredType, true);
7073af6ab5fSopenharmony_ci                break;
7083af6ab5fSopenharmony_ci            }
7093af6ab5fSopenharmony_ci            case ir::AstNodeType::REST_ELEMENT: {
7103af6ab5fSopenharmony_ci                HandleRest(it->AsRestElement());
7113af6ab5fSopenharmony_ci                break;
7123af6ab5fSopenharmony_ci            }
7133af6ab5fSopenharmony_ci            default: {
7143af6ab5fSopenharmony_ci                UNREACHABLE();
7153af6ab5fSopenharmony_ci            }
7163af6ab5fSopenharmony_ci        }
7173af6ab5fSopenharmony_ci    }
7183af6ab5fSopenharmony_ci}
7193af6ab5fSopenharmony_ci}  // namespace ark::es2panda::checker
720