13af6ab5fSopenharmony_ci/*
23af6ab5fSopenharmony_ci * Copyright (c) 2021-2022 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 "options.h"
173af6ab5fSopenharmony_ci
183af6ab5fSopenharmony_ci#include <fstream>
193af6ab5fSopenharmony_ci#include <set>
203af6ab5fSopenharmony_ci#include <sstream>
213af6ab5fSopenharmony_ci#include <utility>
223af6ab5fSopenharmony_ci
233af6ab5fSopenharmony_ci#if defined(PANDA_TARGET_WINDOWS)
243af6ab5fSopenharmony_ci#include <io.h>
253af6ab5fSopenharmony_ci#else
263af6ab5fSopenharmony_ci#include <dirent.h>
273af6ab5fSopenharmony_ci#endif
283af6ab5fSopenharmony_ci
293af6ab5fSopenharmony_ci#include "bytecode_optimizer/bytecodeopt_options.h"
303af6ab5fSopenharmony_ci#include "compiler_options.h"
313af6ab5fSopenharmony_ci#include "os/file.h"
323af6ab5fSopenharmony_ci#include "utils/pandargs.h"
333af6ab5fSopenharmony_ci#include "utils/timers.h"
343af6ab5fSopenharmony_ci
353af6ab5fSopenharmony_ci#include "mergeProgram.h"
363af6ab5fSopenharmony_ci#include "util/helpers.h"
373af6ab5fSopenharmony_ci
383af6ab5fSopenharmony_cinamespace panda::es2panda::aot {
393af6ab5fSopenharmony_ciconstexpr char PROCESS_AS_LIST_MARK = '@';
403af6ab5fSopenharmony_ci// item list: [filePath; recordName; moduleKind; sourceFile; pkgName; isSharedModule]
413af6ab5fSopenharmony_ciconstexpr size_t ITEM_COUNT_MERGE = 6;
423af6ab5fSopenharmony_ci// item list: [filePath; recordName; moduleKind; sourceFile; outputfile; isSharedModule]
433af6ab5fSopenharmony_ciconstexpr size_t ITEM_COUNT_NOT_MERGE = 6;
443af6ab5fSopenharmony_ciconst std::string LIST_ITEM_SEPERATOR = ";";
453af6ab5fSopenharmony_ciconst std::set<std::string> VALID_EXTENSIONS = { "js", "ts", "as", "abc" };
463af6ab5fSopenharmony_ci
473af6ab5fSopenharmony_citemplate <class T>
483af6ab5fSopenharmony_ciT RemoveExtension(T const &filename)
493af6ab5fSopenharmony_ci{
503af6ab5fSopenharmony_ci    typename T::size_type const P(filename.find_last_of('.'));
513af6ab5fSopenharmony_ci    return P > 0 && P != T::npos ? filename.substr(0, P) : filename;
523af6ab5fSopenharmony_ci}
533af6ab5fSopenharmony_ci
543af6ab5fSopenharmony_cistatic es2panda::ScriptExtension GetScriptExtensionFromStr(const std::string &extension)
553af6ab5fSopenharmony_ci{
563af6ab5fSopenharmony_ci    if (extension == "js") {
573af6ab5fSopenharmony_ci        return es2panda::ScriptExtension::JS;
583af6ab5fSopenharmony_ci    } else if (extension == "ts") {
593af6ab5fSopenharmony_ci        return es2panda::ScriptExtension::TS;
603af6ab5fSopenharmony_ci    } else if (extension == "as") {
613af6ab5fSopenharmony_ci        return es2panda::ScriptExtension::AS;
623af6ab5fSopenharmony_ci    } else if (extension == "abc") {
633af6ab5fSopenharmony_ci        return es2panda::ScriptExtension::ABC;
643af6ab5fSopenharmony_ci    } else {
653af6ab5fSopenharmony_ci        return es2panda::ScriptExtension::JS;
663af6ab5fSopenharmony_ci    }
673af6ab5fSopenharmony_ci}
683af6ab5fSopenharmony_ci
693af6ab5fSopenharmony_cistatic es2panda::ScriptExtension GetScriptExtension(const std::string &filename, const std::string &inputExtension)
703af6ab5fSopenharmony_ci{
713af6ab5fSopenharmony_ci    std::string fileExtension = "";
723af6ab5fSopenharmony_ci    std::string::size_type pos(filename.find_last_of('.'));
733af6ab5fSopenharmony_ci    if (pos > 0 && pos != std::string::npos) {
743af6ab5fSopenharmony_ci        fileExtension = filename.substr(pos + 1);
753af6ab5fSopenharmony_ci    }
763af6ab5fSopenharmony_ci
773af6ab5fSopenharmony_ci    if (VALID_EXTENSIONS.find(fileExtension) != VALID_EXTENSIONS.end()) {
783af6ab5fSopenharmony_ci        return GetScriptExtensionFromStr(fileExtension);
793af6ab5fSopenharmony_ci    }
803af6ab5fSopenharmony_ci
813af6ab5fSopenharmony_ci    return GetScriptExtensionFromStr(inputExtension);
823af6ab5fSopenharmony_ci}
833af6ab5fSopenharmony_ci
843af6ab5fSopenharmony_cistatic std::vector<std::string> GetStringItems(std::string &input, const std::string &delimiter)
853af6ab5fSopenharmony_ci{
863af6ab5fSopenharmony_ci    std::vector<std::string> items;
873af6ab5fSopenharmony_ci    size_t pos = 0;
883af6ab5fSopenharmony_ci    std::string token;
893af6ab5fSopenharmony_ci    while ((pos = input.find(delimiter)) != std::string::npos) {
903af6ab5fSopenharmony_ci        token = input.substr(0, pos);
913af6ab5fSopenharmony_ci        if (!token.empty()) {
923af6ab5fSopenharmony_ci            items.push_back(token);
933af6ab5fSopenharmony_ci        }
943af6ab5fSopenharmony_ci        input.erase(0, pos + delimiter.length());
953af6ab5fSopenharmony_ci    }
963af6ab5fSopenharmony_ci    if (!input.empty()) {
973af6ab5fSopenharmony_ci        items.push_back(input);
983af6ab5fSopenharmony_ci    }
993af6ab5fSopenharmony_ci    return items;
1003af6ab5fSopenharmony_ci}
1013af6ab5fSopenharmony_ci
1023af6ab5fSopenharmony_civoid Options::CollectInputAbcFile(const std::vector<std::string> &itemList, const std::string &inputExtension)
1033af6ab5fSopenharmony_ci{
1043af6ab5fSopenharmony_ci    std::string fileName = itemList[0];
1053af6ab5fSopenharmony_ci    // Split the fileInfo string to itemList by the delimiter ';'. If the element is empty, it will not be added to
1063af6ab5fSopenharmony_ci    // the itemList. The fileInfo string of the abc file only contains the file path and pkgName, so the index
1073af6ab5fSopenharmony_ci    // of pkgName is 1.
1083af6ab5fSopenharmony_ci    constexpr uint32_t PKG_NAME_IDX = 1;
1093af6ab5fSopenharmony_ci    es2panda::SourceFile src(fileName, "", parser::ScriptKind::SCRIPT, GetScriptExtension(fileName,
1103af6ab5fSopenharmony_ci                             inputExtension));
1113af6ab5fSopenharmony_ci    src.isSourceMode = false;
1123af6ab5fSopenharmony_ci    if (itemList.size() > PKG_NAME_IDX && compilerOptions_.mergeAbc) {
1133af6ab5fSopenharmony_ci        src.pkgName = itemList[PKG_NAME_IDX];
1143af6ab5fSopenharmony_ci    }
1153af6ab5fSopenharmony_ci    sourceFiles_.push_back(src);
1163af6ab5fSopenharmony_ci}
1173af6ab5fSopenharmony_ci
1183af6ab5fSopenharmony_civoid Options::CollectInputSourceFile(const std::vector<std::string> &itemList, const std::string &inputExtension)
1193af6ab5fSopenharmony_ci{
1203af6ab5fSopenharmony_ci    std::string fileName = itemList[0];
1213af6ab5fSopenharmony_ci    std::string recordName = compilerOptions_.mergeAbc ? itemList[1] : "";
1223af6ab5fSopenharmony_ci    constexpr uint32_t SCRIPT_KIND_IDX = 2;
1233af6ab5fSopenharmony_ci    constexpr uint32_t SOURCE_FIEL_IDX = 3;
1243af6ab5fSopenharmony_ci    constexpr uint32_t PKG_NAME_IDX = 4;
1253af6ab5fSopenharmony_ci    constexpr uint32_t Is_SHARED_MODULE_IDX = 5;
1263af6ab5fSopenharmony_ci    parser::ScriptKind scriptKind;
1273af6ab5fSopenharmony_ci    if (itemList[SCRIPT_KIND_IDX] == "script") {
1283af6ab5fSopenharmony_ci        scriptKind = parser::ScriptKind::SCRIPT;
1293af6ab5fSopenharmony_ci    } else if (itemList[SCRIPT_KIND_IDX] == "commonjs") {
1303af6ab5fSopenharmony_ci        scriptKind = parser::ScriptKind::COMMONJS;
1313af6ab5fSopenharmony_ci    } else {
1323af6ab5fSopenharmony_ci        scriptKind = parser::ScriptKind::MODULE;
1333af6ab5fSopenharmony_ci    }
1343af6ab5fSopenharmony_ci
1353af6ab5fSopenharmony_ci    es2panda::SourceFile src(fileName, recordName, scriptKind, GetScriptExtension(fileName, inputExtension));
1363af6ab5fSopenharmony_ci    src.sourcefile = itemList[SOURCE_FIEL_IDX];
1373af6ab5fSopenharmony_ci    if (compilerOptions_.mergeAbc) {
1383af6ab5fSopenharmony_ci        src.pkgName = itemList[PKG_NAME_IDX];
1393af6ab5fSopenharmony_ci    }
1403af6ab5fSopenharmony_ci
1413af6ab5fSopenharmony_ci    if (itemList.size() == ITEM_COUNT_MERGE) {
1423af6ab5fSopenharmony_ci        src.isSharedModule = itemList[Is_SHARED_MODULE_IDX] == "true";
1433af6ab5fSopenharmony_ci    }
1443af6ab5fSopenharmony_ci
1453af6ab5fSopenharmony_ci    sourceFiles_.push_back(src);
1463af6ab5fSopenharmony_ci    if (!compilerOptions_.mergeAbc) {
1473af6ab5fSopenharmony_ci        outputFiles_.insert({fileName, itemList[PKG_NAME_IDX]});
1483af6ab5fSopenharmony_ci    }
1493af6ab5fSopenharmony_ci}
1503af6ab5fSopenharmony_ci
1513af6ab5fSopenharmony_cibool Options::CheckFilesValidity(const std::string &input, const std::vector<std::string> &itemList,
1523af6ab5fSopenharmony_ci                                 const std::string &line)
1533af6ab5fSopenharmony_ci{
1543af6ab5fSopenharmony_ci    // For compatibility, only throw error when item list's size is bigger than given size.
1553af6ab5fSopenharmony_ci    if ((compilerOptions_.mergeAbc && itemList.size() > ITEM_COUNT_MERGE) ||
1563af6ab5fSopenharmony_ci        (!compilerOptions_.mergeAbc && itemList.size() > ITEM_COUNT_NOT_MERGE) || itemList.empty()) {
1573af6ab5fSopenharmony_ci        std::cerr << "Failed to parse line " << line << " of the input file: '"
1583af6ab5fSopenharmony_ci            << input << "'." << std::endl
1593af6ab5fSopenharmony_ci            << "Expected " << (compilerOptions_.mergeAbc ? ITEM_COUNT_MERGE : ITEM_COUNT_NOT_MERGE)
1603af6ab5fSopenharmony_ci            << " items per line, but found " << itemList.size() << " items." << std::endl
1613af6ab5fSopenharmony_ci            << "Please check the file format and content for correctness." << std::endl;
1623af6ab5fSopenharmony_ci        return false;
1633af6ab5fSopenharmony_ci    }
1643af6ab5fSopenharmony_ci    return true;
1653af6ab5fSopenharmony_ci}
1663af6ab5fSopenharmony_ci
1673af6ab5fSopenharmony_cibool Options::IsAbcFile(const std::string &fileName, const std::string &inputExtension)
1683af6ab5fSopenharmony_ci{
1693af6ab5fSopenharmony_ci    return (GetScriptExtension(fileName, inputExtension) == es2panda::ScriptExtension::ABC);
1703af6ab5fSopenharmony_ci}
1713af6ab5fSopenharmony_ci
1723af6ab5fSopenharmony_ci// Options
1733af6ab5fSopenharmony_cibool Options::CollectInputFilesFromFileList(const std::string &input, const std::string &inputExtension)
1743af6ab5fSopenharmony_ci{
1753af6ab5fSopenharmony_ci    std::ifstream ifs;
1763af6ab5fSopenharmony_ci    std::string line;
1773af6ab5fSopenharmony_ci    ifs.open(panda::os::file::File::GetExtendedFilePath(input));
1783af6ab5fSopenharmony_ci    if (!ifs.is_open()) {
1793af6ab5fSopenharmony_ci        std::cerr << "Failed to open source list file '" << input << "' during input file collection." << std::endl
1803af6ab5fSopenharmony_ci                  << "Please check if the file exists or the path is correct, "
1813af6ab5fSopenharmony_ci                  << "and you have the necessary permissions to access it." << std::endl;
1823af6ab5fSopenharmony_ci        return false;
1833af6ab5fSopenharmony_ci    }
1843af6ab5fSopenharmony_ci
1853af6ab5fSopenharmony_ci    while (std::getline(ifs, line)) {
1863af6ab5fSopenharmony_ci        std::vector<std::string> itemList = GetStringItems(line, LIST_ITEM_SEPERATOR);
1873af6ab5fSopenharmony_ci        if (!CheckFilesValidity(input, itemList, line)) {
1883af6ab5fSopenharmony_ci            return false;
1893af6ab5fSopenharmony_ci        }
1903af6ab5fSopenharmony_ci        if (IsAbcFile(itemList[0], inputExtension)) {
1913af6ab5fSopenharmony_ci            CollectInputAbcFile(itemList, inputExtension);
1923af6ab5fSopenharmony_ci        } else {
1933af6ab5fSopenharmony_ci            CollectInputSourceFile(itemList, inputExtension);
1943af6ab5fSopenharmony_ci        }
1953af6ab5fSopenharmony_ci    }
1963af6ab5fSopenharmony_ci    return true;
1973af6ab5fSopenharmony_ci}
1983af6ab5fSopenharmony_ci
1993af6ab5fSopenharmony_cibool Options::CollectInputFilesFromFileDirectory(const std::string &input, const std::string &extension)
2003af6ab5fSopenharmony_ci{
2013af6ab5fSopenharmony_ci    std::vector<std::string> files;
2023af6ab5fSopenharmony_ci    if (!proto::MergeProgram::GetProtoFiles(input, extension, files)) {
2033af6ab5fSopenharmony_ci        return false;
2043af6ab5fSopenharmony_ci    }
2053af6ab5fSopenharmony_ci
2063af6ab5fSopenharmony_ci    for (const auto &f : files) {
2073af6ab5fSopenharmony_ci        es2panda::SourceFile src(f, RemoveExtension(f.substr(input.length() + 1)),
2083af6ab5fSopenharmony_ci                                 scriptKind_, GetScriptExtensionFromStr(extension));
2093af6ab5fSopenharmony_ci        sourceFiles_.push_back(src);
2103af6ab5fSopenharmony_ci    }
2113af6ab5fSopenharmony_ci
2123af6ab5fSopenharmony_ci    return true;
2133af6ab5fSopenharmony_ci}
2143af6ab5fSopenharmony_ci
2153af6ab5fSopenharmony_civoid Options::ParseCacheFileOption(const std::string &cacheInput)
2163af6ab5fSopenharmony_ci{
2173af6ab5fSopenharmony_ci    if (cacheInput[0] != PROCESS_AS_LIST_MARK) {
2183af6ab5fSopenharmony_ci        compilerOptions_.cacheFiles.insert({sourceFile_, cacheInput});
2193af6ab5fSopenharmony_ci        return;
2203af6ab5fSopenharmony_ci    }
2213af6ab5fSopenharmony_ci
2223af6ab5fSopenharmony_ci    std::ifstream ifs;
2233af6ab5fSopenharmony_ci    std::string line;
2243af6ab5fSopenharmony_ci    ifs.open(panda::os::file::File::GetExtendedFilePath(cacheInput.substr(1)));
2253af6ab5fSopenharmony_ci    if (!ifs.is_open()) {
2263af6ab5fSopenharmony_ci        std::cerr << "Failed to open cache file list from the provided path: '" << cacheInput << "'." << std::endl
2273af6ab5fSopenharmony_ci                  << "Please check if the file exists or the path is correct, "
2283af6ab5fSopenharmony_ci                  << "and you have the necessary permissions to read the file." << std::endl;
2293af6ab5fSopenharmony_ci        return;
2303af6ab5fSopenharmony_ci    }
2313af6ab5fSopenharmony_ci
2323af6ab5fSopenharmony_ci    constexpr int cacheListItemCount = 2;
2333af6ab5fSopenharmony_ci    while (std::getline(ifs, line)) {
2343af6ab5fSopenharmony_ci        std::vector<std::string> itemList = GetStringItems(line, LIST_ITEM_SEPERATOR);
2353af6ab5fSopenharmony_ci        if (itemList.size() != cacheListItemCount) {
2363af6ab5fSopenharmony_ci            continue;
2373af6ab5fSopenharmony_ci        }
2383af6ab5fSopenharmony_ci        compilerOptions_.cacheFiles.insert({itemList[0], itemList[1]});
2393af6ab5fSopenharmony_ci    }
2403af6ab5fSopenharmony_ci}
2413af6ab5fSopenharmony_ci
2423af6ab5fSopenharmony_civoid Options::ParseUpdateVersionInfo(nlohmann::json &compileContextInfoJson)
2433af6ab5fSopenharmony_ci{
2443af6ab5fSopenharmony_ci    if (compileContextInfoJson.contains("updateVersionInfo") &&
2453af6ab5fSopenharmony_ci        compileContextInfoJson["updateVersionInfo"].is_object()) {
2463af6ab5fSopenharmony_ci        std::unordered_map<std::string, std::unordered_map<std::string, PkgInfo>> updateVersionInfo {};
2473af6ab5fSopenharmony_ci        for (const auto& [abcName, versionInfo] : compileContextInfoJson["updateVersionInfo"].items()) {
2483af6ab5fSopenharmony_ci            if (!versionInfo.is_object()) {
2493af6ab5fSopenharmony_ci                std::cerr << "The input file '" << compilerOptions_.compileContextInfoPath
2503af6ab5fSopenharmony_ci                          << "' is incomplete format of json" << std::endl;
2513af6ab5fSopenharmony_ci            }
2523af6ab5fSopenharmony_ci            std::unordered_map<std::string, PkgInfo> pkgContextMap {};
2533af6ab5fSopenharmony_ci            for (const auto& [pkgName, version] : versionInfo.items()) {
2543af6ab5fSopenharmony_ci                PkgInfo pkgInfo;
2553af6ab5fSopenharmony_ci                pkgInfo.version = version;
2563af6ab5fSopenharmony_ci                pkgInfo.packageName = pkgName;
2573af6ab5fSopenharmony_ci                pkgContextMap[pkgName] = pkgInfo;
2583af6ab5fSopenharmony_ci            }
2593af6ab5fSopenharmony_ci            updateVersionInfo[abcName] = pkgContextMap;
2603af6ab5fSopenharmony_ci        }
2613af6ab5fSopenharmony_ci        compilerOptions_.compileContextInfo.updateVersionInfo = updateVersionInfo;
2623af6ab5fSopenharmony_ci    } else if (compileContextInfoJson.contains("pkgContextInfo") &&
2633af6ab5fSopenharmony_ci               compileContextInfoJson["pkgContextInfo"].is_object()) {
2643af6ab5fSopenharmony_ci        std::unordered_map<std::string, PkgInfo> pkgContextMap {};
2653af6ab5fSopenharmony_ci        for (const auto& [pkgName, pkgContextInfo] : compileContextInfoJson["pkgContextInfo"].items()) {
2663af6ab5fSopenharmony_ci            PkgInfo pkgInfo;
2673af6ab5fSopenharmony_ci            if (pkgContextInfo.contains("version") && pkgContextInfo["version"].is_string()) {
2683af6ab5fSopenharmony_ci                pkgInfo.version = pkgContextInfo["version"];
2693af6ab5fSopenharmony_ci            } else {
2703af6ab5fSopenharmony_ci                std::cerr << "Failed to get version from pkgContextInfo."  << std::endl;
2713af6ab5fSopenharmony_ci            }
2723af6ab5fSopenharmony_ci            if (pkgContextInfo.contains("packageName") && pkgContextInfo["packageName"].is_string()) {
2733af6ab5fSopenharmony_ci                pkgInfo.packageName = pkgContextInfo["packageName"];
2743af6ab5fSopenharmony_ci            } else {
2753af6ab5fSopenharmony_ci                std::cerr << "Failed to get package name from pkgContextInfo."  << std::endl;
2763af6ab5fSopenharmony_ci            }
2773af6ab5fSopenharmony_ci            pkgContextMap[pkgName] = pkgInfo;
2783af6ab5fSopenharmony_ci        }
2793af6ab5fSopenharmony_ci        compilerOptions_.compileContextInfo.pkgContextInfo = pkgContextMap;
2803af6ab5fSopenharmony_ci    } else {
2813af6ab5fSopenharmony_ci        UNREACHABLE();
2823af6ab5fSopenharmony_ci    }
2833af6ab5fSopenharmony_ci}
2843af6ab5fSopenharmony_ci
2853af6ab5fSopenharmony_civoid Options::ParseCompileContextInfo(const std::string compileContextInfoPath)
2863af6ab5fSopenharmony_ci{
2873af6ab5fSopenharmony_ci    std::stringstream ss;
2883af6ab5fSopenharmony_ci    std::string buffer;
2893af6ab5fSopenharmony_ci    if (!util::Helpers::ReadFileToBuffer(compileContextInfoPath, ss)) {
2903af6ab5fSopenharmony_ci        return;
2913af6ab5fSopenharmony_ci    }
2923af6ab5fSopenharmony_ci
2933af6ab5fSopenharmony_ci    buffer = ss.str();
2943af6ab5fSopenharmony_ci    if (buffer.empty() || !nlohmann::json::accept(buffer)) {
2953af6ab5fSopenharmony_ci        std::cerr << "The input file '" << compileContextInfoPath <<"' is incomplete format of json" << std::endl;
2963af6ab5fSopenharmony_ci        return;
2973af6ab5fSopenharmony_ci    }
2983af6ab5fSopenharmony_ci    // Parser compile context info base on the input json file.
2993af6ab5fSopenharmony_ci    nlohmann::json compileContextInfoJson = nlohmann::json::parse(buffer);
3003af6ab5fSopenharmony_ci    if (!compileContextInfoJson.contains("compileEntries") || !compileContextInfoJson.contains("hspPkgNames")) {
3013af6ab5fSopenharmony_ci        std::cerr << "The input json file '" << compileContextInfoPath << "' content format is incorrect" << std::endl;
3023af6ab5fSopenharmony_ci        return;
3033af6ab5fSopenharmony_ci    }
3043af6ab5fSopenharmony_ci    if (!compileContextInfoJson["compileEntries"].is_array() || !compileContextInfoJson["hspPkgNames"].is_array()) {
3053af6ab5fSopenharmony_ci        std::cerr << "The input json file '" << compileContextInfoPath << "' content type is incorrect" << std::endl;
3063af6ab5fSopenharmony_ci        return;
3073af6ab5fSopenharmony_ci    }
3083af6ab5fSopenharmony_ci    std::set<std::string> externalPkgNames;
3093af6ab5fSopenharmony_ci    for (const auto& elem : compileContextInfoJson["hspPkgNames"]) {
3103af6ab5fSopenharmony_ci        if (elem.is_string()) {
3113af6ab5fSopenharmony_ci            externalPkgNames.insert(elem.get<std::string>());
3123af6ab5fSopenharmony_ci        }
3133af6ab5fSopenharmony_ci    }
3143af6ab5fSopenharmony_ci    compilerOptions_.compileContextInfo.externalPkgNames = externalPkgNames;
3153af6ab5fSopenharmony_ci    compilerOptions_.compileContextInfo.compileEntries = compileContextInfoJson["compileEntries"];
3163af6ab5fSopenharmony_ci    ParseUpdateVersionInfo(compileContextInfoJson);
3173af6ab5fSopenharmony_ci}
3183af6ab5fSopenharmony_ci
3193af6ab5fSopenharmony_ci// Collect dependencies based on the compile entries.
3203af6ab5fSopenharmony_cibool Options::NeedCollectDepsRelation()
3213af6ab5fSopenharmony_ci{
3223af6ab5fSopenharmony_ci    return compilerOptions_.enableAbcInput && !compilerOptions_.compileContextInfo.compileEntries.empty();
3233af6ab5fSopenharmony_ci}
3243af6ab5fSopenharmony_ci
3253af6ab5fSopenharmony_ci// Remove redundant content from the abc file and remove programs generated from redundant source files.
3263af6ab5fSopenharmony_cibool Options::NeedRemoveRedundantRecord()
3273af6ab5fSopenharmony_ci{
3283af6ab5fSopenharmony_ci    return compilerOptions_.removeRedundantFile && NeedCollectDepsRelation();
3293af6ab5fSopenharmony_ci}
3303af6ab5fSopenharmony_ci
3313af6ab5fSopenharmony_ciOptions::Options() : argparser_(new panda::PandArgParser()) {}
3323af6ab5fSopenharmony_ci
3333af6ab5fSopenharmony_ciOptions::~Options()
3343af6ab5fSopenharmony_ci{
3353af6ab5fSopenharmony_ci    delete argparser_;
3363af6ab5fSopenharmony_ci}
3373af6ab5fSopenharmony_ci
3383af6ab5fSopenharmony_cibool Options::Parse(int argc, const char **argv)
3393af6ab5fSopenharmony_ci{
3403af6ab5fSopenharmony_ci    panda::PandArg<bool> opHelp("help", false, "Print this message and exit");
3413af6ab5fSopenharmony_ci
3423af6ab5fSopenharmony_ci    // parser
3433af6ab5fSopenharmony_ci    panda::PandArg<std::string> inputExtension("extension", "js",
3443af6ab5fSopenharmony_ci                                               "Parse the input as the given extension (options: js | ts | as | abc)");
3453af6ab5fSopenharmony_ci    panda::PandArg<bool> opModule("module", false, "Parse the input as module");
3463af6ab5fSopenharmony_ci    panda::PandArg<bool> opCommonjs("commonjs", false, "Parse the input as commonjs");
3473af6ab5fSopenharmony_ci    panda::PandArg<bool> opParseOnly("parse-only", false, "Parse the input only");
3483af6ab5fSopenharmony_ci    panda::PandArg<bool> opEnableTypeCheck("enable-type-check", false, "Check the type in ts after parse");
3493af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpAst("dump-ast", false, "Dump the parsed AST");
3503af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpTransformedAst("dump-transformed-ast", false, "Dump the parsed AST after transform");
3513af6ab5fSopenharmony_ci    panda::PandArg<bool> opCheckTransformedAstStructure("check-transformed-ast-structure", false,
3523af6ab5fSopenharmony_ci                                                        "Check the AST structure after transform");
3533af6ab5fSopenharmony_ci    panda::PandArg<bool> opRecordDebugSource("record-debug-source", false, "Record source code to support "\
3543af6ab5fSopenharmony_ci        "multi-platform debugger & detailed backtrace in debug mode");
3553af6ab5fSopenharmony_ci
3563af6ab5fSopenharmony_ci    // compiler
3573af6ab5fSopenharmony_ci    panda::PandArg<bool> opEnableAbcInput("enable-abc-input", false, "Allow abc file as input");
3583af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpAsmProgram("dump-asm-program", false, "Dump program");
3593af6ab5fSopenharmony_ci    std::string descOfDumpNormalizedProg =
3603af6ab5fSopenharmony_ci        "Dump program in normalized form to ensure the output of source code compilation is consistent with that of "
3613af6ab5fSopenharmony_ci        "abc file compilation.\n"
3623af6ab5fSopenharmony_ci        "  The normalized form differs mainly as follows:\n"
3633af6ab5fSopenharmony_ci        "  1. all instructions will be labled consecutively and all the labels will be dumped\n"
3643af6ab5fSopenharmony_ci        "  2. the content of a literal array, rather than its id, will be dumped when the literal array appears in "
3653af6ab5fSopenharmony_ci        "an opcode or is nested in another literal array\n"
3663af6ab5fSopenharmony_ci        "  3. labels stored in catch blocks will be unified\n"
3673af6ab5fSopenharmony_ci        "  4. strings won't be dumped\n"
3683af6ab5fSopenharmony_ci        "  5. invalid opcodes won't be dumped, local variables' start and end offset will skip invalid opcodes";
3693af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpNormalizedAsmProgram("dump-normalized-asm-program", false, descOfDumpNormalizedProg);
3703af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpAssembly("dump-assembly", false, "Dump pandasm");
3713af6ab5fSopenharmony_ci    panda::PandArg<bool> opDebugInfo("debug-info", false, "Compile with debug info");
3723af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpDebugInfo("dump-debug-info", false, "Dump debug info");
3733af6ab5fSopenharmony_ci    panda::PandArg<int> opOptLevel("opt-level", 2,
3743af6ab5fSopenharmony_ci        "Compiler optimization level (options: 0 | 1 | 2). In debug and base64Input mode, optimizer is disabled");
3753af6ab5fSopenharmony_ci    panda::PandArg<int> opFunctionThreadCount("function-threads", 0, "Number of worker threads to compile function");
3763af6ab5fSopenharmony_ci    panda::PandArg<int> opFileThreadCount("file-threads", 0, "Number of worker threads to compile file");
3773af6ab5fSopenharmony_ci    panda::PandArg<int> opAbcClassThreadCount("abc-class-threads", 4,
3783af6ab5fSopenharmony_ci        "Number of worker threads to compile classes of abc file");
3793af6ab5fSopenharmony_ci    panda::PandArg<bool> opSizeStat("dump-size-stat", false, "Dump size statistics");
3803af6ab5fSopenharmony_ci    panda::PandArg<bool> opSizePctStat("dump-file-item-size", false, "Dump the size of each kind of file item "\
3813af6ab5fSopenharmony_ci        "of the abc file");
3823af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpLiteralBuffer("dump-literal-buffer", false, "Dump literal buffer");
3833af6ab5fSopenharmony_ci    panda::PandArg<std::string> outputFile("output", "", "Compiler binary output (.abc)");
3843af6ab5fSopenharmony_ci    panda::PandArg<std::string> recordName("record-name", "", "Specify the record name");
3853af6ab5fSopenharmony_ci    panda::PandArg<bool> debuggerEvaluateExpression("debugger-evaluate-expression", false,
3863af6ab5fSopenharmony_ci                                                    "evaluate expression in debugger mode");
3873af6ab5fSopenharmony_ci    panda::PandArg<std::string> base64Input("base64Input", "", "base64 input of js content");
3883af6ab5fSopenharmony_ci    panda::PandArg<bool> base64Output("base64Output", false, "output panda file content as base64 to std out");
3893af6ab5fSopenharmony_ci    panda::PandArg<std::string> sourceFile("source-file", "",
3903af6ab5fSopenharmony_ci                                           "specify the file path info recorded in generated abc");
3913af6ab5fSopenharmony_ci    panda::PandArg<std::string> outputProto("outputProto", "",
3923af6ab5fSopenharmony_ci                                            "specify the output name for serializd protobuf file (.protoBin)");
3933af6ab5fSopenharmony_ci    panda::PandArg<std::string> opCacheFile("cache-file", "", "cache file for incremental compile");
3943af6ab5fSopenharmony_ci    panda::PandArg<std::string> opNpmModuleEntryList("npm-module-entry-list", "", "entry list file for module compile");
3953af6ab5fSopenharmony_ci    panda::PandArg<bool> opMergeAbc("merge-abc", false, "Compile as merge abc");
3963af6ab5fSopenharmony_ci    panda::PandArg<std::string> opPerfFile("perf-file", "perf.txt", "Specify the file path to dump time consuming data"\
3973af6ab5fSopenharmony_ci        " during compilation process, default to 'perf.txt' in the current directory");
3983af6ab5fSopenharmony_ci    panda::PandArg<int> opPerfLevel("perf-level", 0, "Specify the performance data output level:"\
3993af6ab5fSopenharmony_ci        "  0: Output compilation time data(default)");
4003af6ab5fSopenharmony_ci    panda::PandArg<bool> opuseDefineSemantic("use-define-semantic", false, "Compile ts class fields "\
4013af6ab5fSopenharmony_ci        "in accordance with ECMAScript2022");
4023af6ab5fSopenharmony_ci    panda::PandArg<std::string> moduleRecordFieldName("module-record-field-name", "", "Specify the field name "\
4033af6ab5fSopenharmony_ci        "of module record in unmerged abc");
4043af6ab5fSopenharmony_ci
4053af6ab5fSopenharmony_ci    // optimizer
4063af6ab5fSopenharmony_ci    panda::PandArg<bool> opBranchElimination("branch-elimination", false, "Enable branch elimination optimization");
4073af6ab5fSopenharmony_ci    panda::PandArg<bool> opOptTryCatchFunc("opt-try-catch-func", true, "Enable optimizations for functions with "\
4083af6ab5fSopenharmony_ci        "try-catch blocks");
4093af6ab5fSopenharmony_ci
4103af6ab5fSopenharmony_ci    // patchfix && hotreload
4113af6ab5fSopenharmony_ci    panda::PandArg<std::string> opDumpSymbolTable("dump-symbol-table", "", "dump symbol table to file");
4123af6ab5fSopenharmony_ci    panda::PandArg<std::string> opInputSymbolTable("input-symbol-table", "", "input symbol table file");
4133af6ab5fSopenharmony_ci    panda::PandArg<bool> opGeneratePatch("generate-patch", false, "generate patch abc, default as hotfix mode unless "\
4143af6ab5fSopenharmony_ci        "the cold-fix argument is set");
4153af6ab5fSopenharmony_ci    panda::PandArg<bool> opHotReload("hot-reload", false, "compile as hot-reload mode");
4163af6ab5fSopenharmony_ci    panda::PandArg<bool> opColdReload("cold-reload", false, "compile as cold-reload mode");
4173af6ab5fSopenharmony_ci    panda::PandArg<bool> opColdFix("cold-fix", false, "generate patch abc as cold-fix mode");
4183af6ab5fSopenharmony_ci
4193af6ab5fSopenharmony_ci    // version
4203af6ab5fSopenharmony_ci    panda::PandArg<bool> bcVersion("bc-version", false, "Print ark bytecode version. If both bc-version and"\
4213af6ab5fSopenharmony_ci        "bc-min-version are enabled, only bc-version will take effects");
4223af6ab5fSopenharmony_ci    panda::PandArg<bool> bcMinVersion("bc-min-version", false, "Print ark bytecode minimum supported version");
4233af6ab5fSopenharmony_ci    // todo(huyunhui): change default api verion to 0 after refactoring
4243af6ab5fSopenharmony_ci    // The latest api version in isa.yaml is 15
4253af6ab5fSopenharmony_ci    panda::PandArg<int> targetApiVersion("target-api-version", 15,
4263af6ab5fSopenharmony_ci        "Specify the targeting api version for es2abc to generated the corresponding version of bytecode");
4273af6ab5fSopenharmony_ci    panda::PandArg<bool> targetBcVersion("target-bc-version", false, "Print the corresponding ark bytecode version"\
4283af6ab5fSopenharmony_ci        "for target api version. If both target-bc-version and bc-version are enabled, only target-bc-version"\
4293af6ab5fSopenharmony_ci        "will take effects");
4303af6ab5fSopenharmony_ci    panda::PandArg<std::string> targetApiSubVersion("target-api-sub-version",
4313af6ab5fSopenharmony_ci        std::string {util::Helpers::DEFAULT_SUB_API_VERSION},
4323af6ab5fSopenharmony_ci        "Specify the targeting api sub version for es2abc to generated the corresponding version of bytecode");
4333af6ab5fSopenharmony_ci    panda::PandArg<bool> enableAnnotations("enable-annotations", false, "Permits es2abc to compile annotations");
4343af6ab5fSopenharmony_ci
4353af6ab5fSopenharmony_ci    // compile entries and pkg context info
4363af6ab5fSopenharmony_ci    panda::PandArg<std::string> compileContextInfoPath("compile-context-info", "", "The path to compile context"\
4373af6ab5fSopenharmony_ci        "info file");
4383af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpDepsInfo("dump-deps-info", false, "Dump all dependency files and records "\
4393af6ab5fSopenharmony_ci        "including source files and bytecode files");
4403af6ab5fSopenharmony_ci    panda::PandArg<bool> opRemoveRedundantFile("remove-redundant-file", false, "Remove redundant info"\
4413af6ab5fSopenharmony_ci        " from abc file and remove redundant source file, which is effective when the compile-context-info switch"\
4423af6ab5fSopenharmony_ci        "  is turned on and there is abc input");
4433af6ab5fSopenharmony_ci    panda::PandArg<bool> opDumpString("dump-string", false, "Dump program strings");
4443af6ab5fSopenharmony_ci
4453af6ab5fSopenharmony_ci    // aop transform
4463af6ab5fSopenharmony_ci    panda::PandArg<std::string> transformLib("transform-lib", "", "aop transform lib file path");
4473af6ab5fSopenharmony_ci
4483af6ab5fSopenharmony_ci    // tail arguments
4493af6ab5fSopenharmony_ci    panda::PandArg<std::string> inputFile("input", "", "input file");
4503af6ab5fSopenharmony_ci
4513af6ab5fSopenharmony_ci    argparser_->Add(&opHelp);
4523af6ab5fSopenharmony_ci    argparser_->Add(&opModule);
4533af6ab5fSopenharmony_ci    argparser_->Add(&opCommonjs);
4543af6ab5fSopenharmony_ci    argparser_->Add(&opDumpAst);
4553af6ab5fSopenharmony_ci    argparser_->Add(&opDumpTransformedAst);
4563af6ab5fSopenharmony_ci    argparser_->Add(&opCheckTransformedAstStructure);
4573af6ab5fSopenharmony_ci    argparser_->Add(&opRecordDebugSource);
4583af6ab5fSopenharmony_ci    argparser_->Add(&opParseOnly);
4593af6ab5fSopenharmony_ci    argparser_->Add(&opEnableTypeCheck);
4603af6ab5fSopenharmony_ci    argparser_->Add(&opEnableAbcInput);
4613af6ab5fSopenharmony_ci    argparser_->Add(&opDumpAsmProgram);
4623af6ab5fSopenharmony_ci    argparser_->Add(&opDumpNormalizedAsmProgram);
4633af6ab5fSopenharmony_ci    argparser_->Add(&opDumpAssembly);
4643af6ab5fSopenharmony_ci    argparser_->Add(&opDebugInfo);
4653af6ab5fSopenharmony_ci    argparser_->Add(&opDumpDebugInfo);
4663af6ab5fSopenharmony_ci    argparser_->Add(&debuggerEvaluateExpression);
4673af6ab5fSopenharmony_ci    argparser_->Add(&base64Input);
4683af6ab5fSopenharmony_ci    argparser_->Add(&base64Output);
4693af6ab5fSopenharmony_ci
4703af6ab5fSopenharmony_ci    argparser_->Add(&opOptLevel);
4713af6ab5fSopenharmony_ci    argparser_->Add(&opFunctionThreadCount);
4723af6ab5fSopenharmony_ci    argparser_->Add(&opFileThreadCount);
4733af6ab5fSopenharmony_ci    argparser_->Add(&opAbcClassThreadCount);
4743af6ab5fSopenharmony_ci    argparser_->Add(&opSizeStat);
4753af6ab5fSopenharmony_ci    argparser_->Add(&opSizePctStat);
4763af6ab5fSopenharmony_ci    argparser_->Add(&opDumpLiteralBuffer);
4773af6ab5fSopenharmony_ci
4783af6ab5fSopenharmony_ci    argparser_->Add(&inputExtension);
4793af6ab5fSopenharmony_ci    argparser_->Add(&outputFile);
4803af6ab5fSopenharmony_ci    argparser_->Add(&sourceFile);
4813af6ab5fSopenharmony_ci    argparser_->Add(&recordName);
4823af6ab5fSopenharmony_ci    argparser_->Add(&outputProto);
4833af6ab5fSopenharmony_ci    argparser_->Add(&opCacheFile);
4843af6ab5fSopenharmony_ci    argparser_->Add(&opNpmModuleEntryList);
4853af6ab5fSopenharmony_ci    argparser_->Add(&opMergeAbc);
4863af6ab5fSopenharmony_ci    argparser_->Add(&opPerfLevel);
4873af6ab5fSopenharmony_ci    argparser_->Add(&opPerfFile);
4883af6ab5fSopenharmony_ci    argparser_->Add(&opuseDefineSemantic);
4893af6ab5fSopenharmony_ci    argparser_->Add(&moduleRecordFieldName);
4903af6ab5fSopenharmony_ci    argparser_->Add(&opBranchElimination);
4913af6ab5fSopenharmony_ci    argparser_->Add(&opOptTryCatchFunc);
4923af6ab5fSopenharmony_ci
4933af6ab5fSopenharmony_ci    argparser_->Add(&opDumpSymbolTable);
4943af6ab5fSopenharmony_ci    argparser_->Add(&opInputSymbolTable);
4953af6ab5fSopenharmony_ci    argparser_->Add(&opGeneratePatch);
4963af6ab5fSopenharmony_ci    argparser_->Add(&opHotReload);
4973af6ab5fSopenharmony_ci    argparser_->Add(&opColdReload);
4983af6ab5fSopenharmony_ci    argparser_->Add(&opColdFix);
4993af6ab5fSopenharmony_ci
5003af6ab5fSopenharmony_ci    argparser_->Add(&bcVersion);
5013af6ab5fSopenharmony_ci    argparser_->Add(&bcMinVersion);
5023af6ab5fSopenharmony_ci    argparser_->Add(&targetApiVersion);
5033af6ab5fSopenharmony_ci    argparser_->Add(&targetBcVersion);
5043af6ab5fSopenharmony_ci    argparser_->Add(&targetApiSubVersion);
5053af6ab5fSopenharmony_ci    argparser_->Add(&enableAnnotations);
5063af6ab5fSopenharmony_ci
5073af6ab5fSopenharmony_ci    argparser_->Add(&compileContextInfoPath);
5083af6ab5fSopenharmony_ci    argparser_->Add(&opDumpDepsInfo);
5093af6ab5fSopenharmony_ci    argparser_->Add(&opRemoveRedundantFile);
5103af6ab5fSopenharmony_ci    argparser_->Add(&opDumpString);
5113af6ab5fSopenharmony_ci
5123af6ab5fSopenharmony_ci    argparser_->Add(&transformLib);
5133af6ab5fSopenharmony_ci
5143af6ab5fSopenharmony_ci    argparser_->PushBackTail(&inputFile);
5153af6ab5fSopenharmony_ci    argparser_->EnableTail();
5163af6ab5fSopenharmony_ci    argparser_->EnableRemainder();
5173af6ab5fSopenharmony_ci
5183af6ab5fSopenharmony_ci    bool parseStatus = argparser_->Parse(argc, argv);
5193af6ab5fSopenharmony_ci
5203af6ab5fSopenharmony_ci    compilerOptions_.targetApiVersion = targetApiVersion.GetValue();
5213af6ab5fSopenharmony_ci    compilerOptions_.targetApiSubVersion = targetApiSubVersion.GetValue();
5223af6ab5fSopenharmony_ci    if (parseStatus && targetBcVersion.GetValue()) {
5233af6ab5fSopenharmony_ci        compilerOptions_.targetBcVersion = targetBcVersion.GetValue();
5243af6ab5fSopenharmony_ci        return true;
5253af6ab5fSopenharmony_ci    }
5263af6ab5fSopenharmony_ci
5273af6ab5fSopenharmony_ci    if (parseStatus && (bcVersion.GetValue() || bcMinVersion.GetValue())) {
5283af6ab5fSopenharmony_ci        compilerOptions_.bcVersion = bcVersion.GetValue();
5293af6ab5fSopenharmony_ci        compilerOptions_.bcMinVersion = bcMinVersion.GetValue();
5303af6ab5fSopenharmony_ci        return true;
5313af6ab5fSopenharmony_ci    }
5323af6ab5fSopenharmony_ci
5333af6ab5fSopenharmony_ci    if (!parseStatus || opHelp.GetValue() || (inputFile.GetValue().empty() && base64Input.GetValue().empty())) {
5343af6ab5fSopenharmony_ci        std::stringstream ss;
5353af6ab5fSopenharmony_ci
5363af6ab5fSopenharmony_ci        ss << argparser_->GetErrorString() << std::endl;
5373af6ab5fSopenharmony_ci        ss << "Usage: "
5383af6ab5fSopenharmony_ci           << "es2panda"
5393af6ab5fSopenharmony_ci           << " [OPTIONS] [input file] -- [arguments]" << std::endl;
5403af6ab5fSopenharmony_ci        ss << std::endl;
5413af6ab5fSopenharmony_ci        ss << "optional arguments:" << std::endl;
5423af6ab5fSopenharmony_ci        ss << argparser_->GetHelpString() << std::endl;
5433af6ab5fSopenharmony_ci
5443af6ab5fSopenharmony_ci        errorMsg_ = ss.str();
5453af6ab5fSopenharmony_ci        return false;
5463af6ab5fSopenharmony_ci    }
5473af6ab5fSopenharmony_ci
5483af6ab5fSopenharmony_ci    bool inputIsEmpty = inputFile.GetValue().empty();
5493af6ab5fSopenharmony_ci    bool base64InputIsEmpty = base64Input.GetValue().empty();
5503af6ab5fSopenharmony_ci    bool outputIsEmpty = outputFile.GetValue().empty();
5513af6ab5fSopenharmony_ci
5523af6ab5fSopenharmony_ci    if (!inputIsEmpty && !base64InputIsEmpty) {
5533af6ab5fSopenharmony_ci        errorMsg_ = "--input and --base64Input can not be used simultaneously";
5543af6ab5fSopenharmony_ci        return false;
5553af6ab5fSopenharmony_ci    }
5563af6ab5fSopenharmony_ci
5573af6ab5fSopenharmony_ci    if (!outputIsEmpty && base64Output.GetValue()) {
5583af6ab5fSopenharmony_ci        errorMsg_ = "--output and --base64Output can not be used simultaneously";
5593af6ab5fSopenharmony_ci        return false;
5603af6ab5fSopenharmony_ci    }
5613af6ab5fSopenharmony_ci
5623af6ab5fSopenharmony_ci    if (opModule.GetValue() && opCommonjs.GetValue()) {
5633af6ab5fSopenharmony_ci        errorMsg_ = "[--module] and [--commonjs] can not be used simultaneously";
5643af6ab5fSopenharmony_ci        return false;
5653af6ab5fSopenharmony_ci    }
5663af6ab5fSopenharmony_ci
5673af6ab5fSopenharmony_ci    if (opModule.GetValue()) {
5683af6ab5fSopenharmony_ci        scriptKind_ = es2panda::parser::ScriptKind::MODULE;
5693af6ab5fSopenharmony_ci    } else if (opCommonjs.GetValue()) {
5703af6ab5fSopenharmony_ci        scriptKind_ = es2panda::parser::ScriptKind::COMMONJS;
5713af6ab5fSopenharmony_ci    } else {
5723af6ab5fSopenharmony_ci        scriptKind_ = es2panda::parser::ScriptKind::SCRIPT;
5733af6ab5fSopenharmony_ci    }
5743af6ab5fSopenharmony_ci
5753af6ab5fSopenharmony_ci    std::string extension = inputExtension.GetValue();
5763af6ab5fSopenharmony_ci    if (!extension.empty()) {
5773af6ab5fSopenharmony_ci        if (VALID_EXTENSIONS.find(extension) == VALID_EXTENSIONS.end()) {
5783af6ab5fSopenharmony_ci            errorMsg_ = "Invalid extension (available options: js, ts, as, abc)";
5793af6ab5fSopenharmony_ci            return false;
5803af6ab5fSopenharmony_ci        }
5813af6ab5fSopenharmony_ci    }
5823af6ab5fSopenharmony_ci
5833af6ab5fSopenharmony_ci    bool isInputFileList = false;
5843af6ab5fSopenharmony_ci    if (!inputIsEmpty) {
5853af6ab5fSopenharmony_ci        std::string rawInput = inputFile.GetValue();
5863af6ab5fSopenharmony_ci        isInputFileList = rawInput[0] == PROCESS_AS_LIST_MARK;
5873af6ab5fSopenharmony_ci        std::string input = isInputFileList ? rawInput.substr(1) : rawInput;
5883af6ab5fSopenharmony_ci        sourceFile_ = input;
5893af6ab5fSopenharmony_ci    }
5903af6ab5fSopenharmony_ci
5913af6ab5fSopenharmony_ci    if (base64Output.GetValue()) {
5923af6ab5fSopenharmony_ci        compilerOutput_ = "";
5933af6ab5fSopenharmony_ci    } else if (!outputIsEmpty) {
5943af6ab5fSopenharmony_ci        compilerOutput_ = outputFile.GetValue();
5953af6ab5fSopenharmony_ci    } else if (outputIsEmpty && !inputIsEmpty) {
5963af6ab5fSopenharmony_ci        compilerOutput_ = RemoveExtension(util::Helpers::BaseName(sourceFile_)).append(".abc");
5973af6ab5fSopenharmony_ci    }
5983af6ab5fSopenharmony_ci
5993af6ab5fSopenharmony_ci    if (opMergeAbc.GetValue()) {
6003af6ab5fSopenharmony_ci        recordName_ = recordName.GetValue();
6013af6ab5fSopenharmony_ci        if (recordName_.empty()) {
6023af6ab5fSopenharmony_ci            recordName_ = compilerOutput_.empty() ? "Base64Output" :
6033af6ab5fSopenharmony_ci                RemoveExtension(util::Helpers::BaseName(compilerOutput_));
6043af6ab5fSopenharmony_ci        }
6053af6ab5fSopenharmony_ci        compilerOptions_.mergeAbc = opMergeAbc.GetValue();
6063af6ab5fSopenharmony_ci    }
6073af6ab5fSopenharmony_ci
6083af6ab5fSopenharmony_ci    if (opuseDefineSemantic.GetValue()) {
6093af6ab5fSopenharmony_ci        compilerOptions_.useDefineSemantic = opuseDefineSemantic.GetValue();
6103af6ab5fSopenharmony_ci    }
6113af6ab5fSopenharmony_ci
6123af6ab5fSopenharmony_ci    if (!inputIsEmpty) {
6133af6ab5fSopenharmony_ci        // common mode
6143af6ab5fSopenharmony_ci        auto inputAbs = panda::os::file::File::GetAbsolutePath(sourceFile_);
6153af6ab5fSopenharmony_ci        if (!inputAbs) {
6163af6ab5fSopenharmony_ci            std::cerr << "Failed to find file '" << sourceFile_ << "' during input file resolution" << std::endl
6173af6ab5fSopenharmony_ci                      << "Please check if the file name is correct, the file exists at the specified path, "
6183af6ab5fSopenharmony_ci                      << "and your project has the necessary permissions to access it." << std::endl;
6193af6ab5fSopenharmony_ci            return false;
6203af6ab5fSopenharmony_ci        }
6213af6ab5fSopenharmony_ci
6223af6ab5fSopenharmony_ci        auto fpath = inputAbs.Value();
6233af6ab5fSopenharmony_ci        if (isInputFileList) {
6243af6ab5fSopenharmony_ci            CollectInputFilesFromFileList(fpath, extension);
6253af6ab5fSopenharmony_ci        } else if (panda::os::file::File::IsDirectory(fpath)) {
6263af6ab5fSopenharmony_ci            CollectInputFilesFromFileDirectory(fpath, extension);
6273af6ab5fSopenharmony_ci        } else {
6283af6ab5fSopenharmony_ci            es2panda::SourceFile src(sourceFile_, recordName_, scriptKind_, GetScriptExtension(sourceFile_, extension));
6293af6ab5fSopenharmony_ci            src.isSourceMode = !IsAbcFile(sourceFile_, extension);
6303af6ab5fSopenharmony_ci            sourceFiles_.push_back(src);
6313af6ab5fSopenharmony_ci        }
6323af6ab5fSopenharmony_ci    } else if (!base64InputIsEmpty) {
6333af6ab5fSopenharmony_ci        // input content is base64 string
6343af6ab5fSopenharmony_ci        base64Input_ = ExtractContentFromBase64Input(base64Input.GetValue());
6353af6ab5fSopenharmony_ci        if (base64Input_.empty()) {
6363af6ab5fSopenharmony_ci            errorMsg_ = "The input string is not a valid base64 data";
6373af6ab5fSopenharmony_ci            return false;
6383af6ab5fSopenharmony_ci        }
6393af6ab5fSopenharmony_ci
6403af6ab5fSopenharmony_ci        es2panda::SourceFile src("", recordName_, es2panda::parser::ScriptKind::SCRIPT,
6413af6ab5fSopenharmony_ci                                 GetScriptExtensionFromStr(extension));
6423af6ab5fSopenharmony_ci        src.source = base64Input_;
6433af6ab5fSopenharmony_ci        sourceFiles_.push_back(src);
6443af6ab5fSopenharmony_ci    }
6453af6ab5fSopenharmony_ci
6463af6ab5fSopenharmony_ci    if (!outputProto.GetValue().empty()) {
6473af6ab5fSopenharmony_ci        compilerProtoOutput_ = outputProto.GetValue();
6483af6ab5fSopenharmony_ci    }
6493af6ab5fSopenharmony_ci
6503af6ab5fSopenharmony_ci    optLevel_ = opOptLevel.GetValue();
6513af6ab5fSopenharmony_ci    functionThreadCount_ = opFunctionThreadCount.GetValue();
6523af6ab5fSopenharmony_ci    fileThreadCount_ = opFileThreadCount.GetValue();
6533af6ab5fSopenharmony_ci    abcClassThreadCount_ = opAbcClassThreadCount.GetValue();
6543af6ab5fSopenharmony_ci    npmModuleEntryList_ = opNpmModuleEntryList.GetValue();
6553af6ab5fSopenharmony_ci
6563af6ab5fSopenharmony_ci    if (!opCacheFile.GetValue().empty()) {
6573af6ab5fSopenharmony_ci        ParseCacheFileOption(opCacheFile.GetValue());
6583af6ab5fSopenharmony_ci    }
6593af6ab5fSopenharmony_ci
6603af6ab5fSopenharmony_ci    if (opParseOnly.GetValue()) {
6613af6ab5fSopenharmony_ci        options_ |= OptionFlags::PARSE_ONLY;
6623af6ab5fSopenharmony_ci    }
6633af6ab5fSopenharmony_ci
6643af6ab5fSopenharmony_ci    if (opSizeStat.GetValue()) {
6653af6ab5fSopenharmony_ci        options_ |= OptionFlags::SIZE_STAT;
6663af6ab5fSopenharmony_ci    }
6673af6ab5fSopenharmony_ci
6683af6ab5fSopenharmony_ci    if (opSizePctStat.GetValue()) {
6693af6ab5fSopenharmony_ci        options_ |= OptionFlags::SIZE_PCT_STAT;
6703af6ab5fSopenharmony_ci    }
6713af6ab5fSopenharmony_ci
6723af6ab5fSopenharmony_ci    perfFile_ = "";
6733af6ab5fSopenharmony_ci    perfLevel_ = opPerfLevel.GetValue();
6743af6ab5fSopenharmony_ci    if (opPerfFile.WasSet() && (perfLevel_ == 0)) {
6753af6ab5fSopenharmony_ci        perfFile_ = opPerfFile.GetValue().empty() ? opPerfFile.GetDefaultValue() : opPerfFile.GetValue();
6763af6ab5fSopenharmony_ci    }
6773af6ab5fSopenharmony_ci    panda::Timer::InitializeTimer(perfFile_);
6783af6ab5fSopenharmony_ci
6793af6ab5fSopenharmony_ci    compilerOptions_.recordDebugSource = opRecordDebugSource.GetValue();
6803af6ab5fSopenharmony_ci    compilerOptions_.enableAbcInput = opEnableAbcInput.GetValue();
6813af6ab5fSopenharmony_ci    compilerOptions_.dumpAsmProgram = opDumpAsmProgram.GetValue();
6823af6ab5fSopenharmony_ci    compilerOptions_.dumpNormalizedAsmProgram = opDumpNormalizedAsmProgram.GetValue();
6833af6ab5fSopenharmony_ci    compilerOptions_.dumpAsm = opDumpAssembly.GetValue();
6843af6ab5fSopenharmony_ci    compilerOptions_.dumpAst = opDumpAst.GetValue();
6853af6ab5fSopenharmony_ci    compilerOptions_.dumpTransformedAst = opDumpTransformedAst.GetValue();
6863af6ab5fSopenharmony_ci    compilerOptions_.checkTransformedAstStructure = opCheckTransformedAstStructure.GetValue();
6873af6ab5fSopenharmony_ci    compilerOptions_.dumpDebugInfo = opDumpDebugInfo.GetValue();
6883af6ab5fSopenharmony_ci    compilerOptions_.isDebug = opDebugInfo.GetValue();
6893af6ab5fSopenharmony_ci    compilerOptions_.parseOnly = opParseOnly.GetValue();
6903af6ab5fSopenharmony_ci    compilerOptions_.enableTypeCheck = opEnableTypeCheck.GetValue();
6913af6ab5fSopenharmony_ci    compilerOptions_.dumpLiteralBuffer = opDumpLiteralBuffer.GetValue();
6923af6ab5fSopenharmony_ci    compilerOptions_.isDebuggerEvaluateExpressionMode = debuggerEvaluateExpression.GetValue();
6933af6ab5fSopenharmony_ci
6943af6ab5fSopenharmony_ci    compilerOptions_.functionThreadCount = functionThreadCount_;
6953af6ab5fSopenharmony_ci    compilerOptions_.fileThreadCount = fileThreadCount_;
6963af6ab5fSopenharmony_ci    compilerOptions_.abcClassThreadCount = abcClassThreadCount_;
6973af6ab5fSopenharmony_ci    compilerOptions_.output = compilerOutput_;
6983af6ab5fSopenharmony_ci    compilerOptions_.debugInfoSourceFile = sourceFile.GetValue();
6993af6ab5fSopenharmony_ci    compilerOptions_.optLevel = (compilerOptions_.isDebug || !base64Input.GetValue().empty() ||
7003af6ab5fSopenharmony_ci        base64Output.GetValue()) ? 0 : opOptLevel.GetValue();
7013af6ab5fSopenharmony_ci    compilerOptions_.sourceFiles = sourceFiles_;
7023af6ab5fSopenharmony_ci    compilerOptions_.mergeAbc = opMergeAbc.GetValue();
7033af6ab5fSopenharmony_ci    compilerOptions_.compileContextInfoPath = compileContextInfoPath.GetValue();
7043af6ab5fSopenharmony_ci    if (!compileContextInfoPath.GetValue().empty()) {
7053af6ab5fSopenharmony_ci        ParseCompileContextInfo(compileContextInfoPath.GetValue());
7063af6ab5fSopenharmony_ci    }
7073af6ab5fSopenharmony_ci    compilerOptions_.dumpDepsInfo = opDumpDepsInfo.GetValue();
7083af6ab5fSopenharmony_ci    compilerOptions_.updatePkgVersionForAbcInput = compilerOptions_.enableAbcInput &&
7093af6ab5fSopenharmony_ci        (!compilerOptions_.compileContextInfo.pkgContextInfo.empty() ||
7103af6ab5fSopenharmony_ci        !compilerOptions_.compileContextInfo.updateVersionInfo.empty());
7113af6ab5fSopenharmony_ci    compilerOptions_.removeRedundantFile = opRemoveRedundantFile.GetValue();
7123af6ab5fSopenharmony_ci    compilerOptions_.dumpString = opDumpString.GetValue();
7133af6ab5fSopenharmony_ci    compilerOptions_.moduleRecordFieldName = moduleRecordFieldName.GetValue();
7143af6ab5fSopenharmony_ci
7153af6ab5fSopenharmony_ci    compilerOptions_.patchFixOptions.dumpSymbolTable = opDumpSymbolTable.GetValue();
7163af6ab5fSopenharmony_ci    compilerOptions_.patchFixOptions.symbolTable = opInputSymbolTable.GetValue();
7173af6ab5fSopenharmony_ci
7183af6ab5fSopenharmony_ci    bool generatePatch = opGeneratePatch.GetValue();
7193af6ab5fSopenharmony_ci    bool hotReload = opHotReload.GetValue();
7203af6ab5fSopenharmony_ci    bool coldReload = opColdReload.GetValue();
7213af6ab5fSopenharmony_ci    bool coldFix = opColdFix.GetValue();
7223af6ab5fSopenharmony_ci    if (generatePatch && hotReload) {
7233af6ab5fSopenharmony_ci        errorMsg_ = "--generate-patch and --hot-reload can not be used simultaneously";
7243af6ab5fSopenharmony_ci        return false;
7253af6ab5fSopenharmony_ci    }
7263af6ab5fSopenharmony_ci    if (coldFix && !generatePatch) {
7273af6ab5fSopenharmony_ci        errorMsg_ = "--cold-fix can not be used without --generate-patch";
7283af6ab5fSopenharmony_ci        return false;
7293af6ab5fSopenharmony_ci    }
7303af6ab5fSopenharmony_ci    compilerOptions_.patchFixOptions.generatePatch = generatePatch;
7313af6ab5fSopenharmony_ci    compilerOptions_.patchFixOptions.hotReload = hotReload;
7323af6ab5fSopenharmony_ci    compilerOptions_.patchFixOptions.coldReload = coldReload;
7333af6ab5fSopenharmony_ci    compilerOptions_.patchFixOptions.coldFix = coldFix;
7343af6ab5fSopenharmony_ci
7353af6ab5fSopenharmony_ci    compilerOptions_.enableAnnotations = enableAnnotations.GetValue();
7363af6ab5fSopenharmony_ci
7373af6ab5fSopenharmony_ci    bool transformLibIsEmpty = transformLib.GetValue().empty();
7383af6ab5fSopenharmony_ci    if (!transformLibIsEmpty) {
7393af6ab5fSopenharmony_ci        auto libName = transformLib.GetValue();
7403af6ab5fSopenharmony_ci        // check file exist or not
7413af6ab5fSopenharmony_ci        auto transformLibAbs = panda::os::file::File::GetAbsolutePath(libName);
7423af6ab5fSopenharmony_ci        if (!transformLibAbs) {
7433af6ab5fSopenharmony_ci            std::cerr << "Failed to find file '" << libName << "' during transformLib file resolution" << std::endl
7443af6ab5fSopenharmony_ci                      << "Please check if the file name is correct, the file exists at the specified path, "
7453af6ab5fSopenharmony_ci                      << "and your project has the necessary permissions to access it." << std::endl;
7463af6ab5fSopenharmony_ci            return false;
7473af6ab5fSopenharmony_ci        }
7483af6ab5fSopenharmony_ci        compilerOptions_.transformLib = transformLibAbs.Value();
7493af6ab5fSopenharmony_ci    }
7503af6ab5fSopenharmony_ci
7513af6ab5fSopenharmony_ci    compilerOptions_.branchElimination = opBranchElimination.GetValue();
7523af6ab5fSopenharmony_ci    compilerOptions_.requireGlobalOptimization = compilerOptions_.optLevel > 0 &&
7533af6ab5fSopenharmony_ci                                                 compilerOptions_.branchElimination &&
7543af6ab5fSopenharmony_ci                                                 compilerOptions_.mergeAbc;
7553af6ab5fSopenharmony_ci    panda::compiler::options.SetCompilerBranchElimination(compilerOptions_.branchElimination);
7563af6ab5fSopenharmony_ci    panda::bytecodeopt::options.SetSkipMethodsWithEh(!opOptTryCatchFunc.GetValue());
7573af6ab5fSopenharmony_ci
7583af6ab5fSopenharmony_ci    return true;
7593af6ab5fSopenharmony_ci}
7603af6ab5fSopenharmony_ci
7613af6ab5fSopenharmony_cistd::string Options::ExtractContentFromBase64Input(const std::string &inputBase64String)
7623af6ab5fSopenharmony_ci{
7633af6ab5fSopenharmony_ci    std::string inputContent = util::Base64Decode(inputBase64String);
7643af6ab5fSopenharmony_ci    if (inputContent == "") {
7653af6ab5fSopenharmony_ci        return "";
7663af6ab5fSopenharmony_ci    }
7673af6ab5fSopenharmony_ci    bool validBase64Input = util::Base64Encode(inputContent) == inputBase64String;
7683af6ab5fSopenharmony_ci    if (!validBase64Input) {
7693af6ab5fSopenharmony_ci        return "";
7703af6ab5fSopenharmony_ci    }
7713af6ab5fSopenharmony_ci    return inputContent;
7723af6ab5fSopenharmony_ci}
7733af6ab5fSopenharmony_ci}  // namespace panda::es2panda::aot
774