* Copyright (c) 2024 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef ECMASCRIPT_MODULE_TOOLS_H
#define ECMASCRIPT_MODULE_TOOLS_H
#include "ecmascript/module/js_module_source_text.h"
#include "ecmascript/module/module_logger.h"
namespace panda::ecmascript {
class ModuleManager;
class ModuleTraceScope {
public:
template<typename... Args>
static ModuleTraceScope Open(JSThread *thread, const Args&... args)
{
if (!thread->GetEcmaVM()->GetJSOptions().EnableESMTrace()) {
return ModuleTraceScope();
}
return ModuleTraceScope(base::ConcatToCString(args...));
}
~ModuleTraceScope()
{
if (enableESMTrace_) {
ECMA_BYTRACE_FINISH_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK);
}
}
private:
ModuleTraceScope(const CString &info) : enableESMTrace_(true)
{
ECMA_BYTRACE_START_TRACE(HITRACE_LEVEL_COMMERCIAL, HITRACE_TAG_ARK, info.c_str());
}
ModuleTraceScope() : enableESMTrace_(false) {}
bool enableESMTrace_ {false};
};
class ModuleLoggerTimeScope {
public:
void* operator new[](size_t size) = delete;
void operator delete[](void* ptr) = delete;
void* operator new(size_t size) = delete;
void operator delete(void* ptr) = delete;
ModuleLoggerTimeScope(JSThread *thread, CString &&moduleRequestName) = delete;
ModuleLoggerTimeScope(JSThread *thread, const CString &moduleRequestName)
: moduleRequestName_(moduleRequestName), moduleLogger_(thread->GetModuleLogger())
{
if (moduleLogger_ != nullptr) {
startTime_ = moduleLogger_->now();
}
}
~ModuleLoggerTimeScope()
{
if (moduleLogger_ != nullptr) {
moduleLogger_->SetDuration(moduleRequestName_, startTime_);
}
}
private:
double startTime_ {};
const CString& moduleRequestName_;
ModuleLogger *moduleLogger_ {nullptr};
};
class ModuleImportStackScope {
public:
static constexpr size_t MODULE_IMPORT_STACK_HEAD_LENGTH = 19;
static constexpr size_t ELLIPSIS_PLACEHOLDER_LENGTH = 5;
static constexpr std::string_view NEWLINE_CHARACTER = "\n";
static constexpr std::string_view ELLIPSIS_PLACEHOLDER = "\n....";
static constexpr std::string_view MODULE_IMPORT_STACK_HEAD = "\nModuleImportStack:";
static constexpr char ALIGNMENT_SYMBOL = '0';
static constexpr std::string_view MODULE_IMPORT_STACK_NUMBER_LABEL = "\n#";
explicit ModuleImportStackScope(JSThread *thread, JSHandle<SourceTextModule> module);
~ModuleImportStackScope();
NO_COPY_SEMANTIC(ModuleImportStackScope);
NO_MOVE_SEMANTIC(ModuleImportStackScope);
private:
void PushModuleImportStack(const CString &moduleName);
void PopModuleImportStack(const CString &moduleName);
void RenumberModuleImportStack();
int GetNumberOfDigits(int number) const;
std::string FormatStackNumber(int stackIndex, int totalDepth) const;
int GetModuleImportStackDepth() const;
bool enableModuleStack_ {false};
ModuleManager* moduleManager_;
CString moduleName_;
uintptr_t handle_ {0};
std::string truncatedStack_;
};
class ModuleTools {
public:
static std::string TruncateImportStackForCPPCrash(const CString &moduleName,
std::string_view stackData, size_t maxSize);
static std::string TruncateImportStackForJSCrash(std::string_view stackData, size_t maxSize);
private:
static std::string TruncateModuleImportStack(std::string_view stackData, size_t maxSize);
};
}
#endif