// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.
#include "ClearScriptV8Native.h"
//-----------------------------------------------------------------------------
// local helper functions
//-----------------------------------------------------------------------------
static size_t AdjustConstraint(int value) noexcept
{
value = std::max(value, 0);
size_t result = value;
const int maxValueInMiB = 1024 * 1024;
if (value 0)
{
words.resize((length + sizeof(uint64_t) - 1) / sizeof(uint64_t), 0);
memcpy(words.data(), pBytes, length);
}
*pV8Value = V8Value(new V8BigInt(signBit, std::move(words)));
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Value_SetV8Object(V8Value* pV8Value, const V8ObjectHandle& handle, V8Value::Subtype subtype) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
*pV8Value = V8Value(spV8ObjectHolder->Clone(), subtype);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Value_SetHostObject(V8Value* pV8Value, void* pvObject) noexcept
{
*pV8Value = V8Value(new HostObjectHolderImpl(pvObject));
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8Value::Type) V8Value_Decode(const V8Value& value, int32_t& intValue, uint32_t& uintValue, double& doubleValue, const void*& pvData) noexcept
{
{
bool result;
if (value.AsBoolean(result))
{
intValue = result;
return V8Value::Type::Boolean;
}
}
{
double result;
if (value.AsNumber(result))
{
doubleValue = result;
return V8Value::Type::Number;
}
}
{
int32_t result;
if (value.AsInt32(result))
{
intValue = result;
return V8Value::Type::Int32;
}
}
{
uint32_t result;
if (value.AsUInt32(result))
{
uintValue = result;
return V8Value::Type::UInt32;
}
}
{
const StdString* pString;
if (value.AsString(pString))
{
pvData = pString->ToCString();
intValue = pString->GetLength();
return V8Value::Type::String;
}
}
{
double result;
if (value.AsDateTime(result))
{
doubleValue = result;
return V8Value::Type::DateTime;
}
}
{
const V8BigInt* pBigInt;
if (value.AsBigInt(pBigInt))
{
intValue = pBigInt->GetSignBit();
pvData = pBigInt->GetWords().data();
uintValue = static_cast(pBigInt->GetWords().size());
return V8Value::Type::BigInt;
}
}
{
V8ObjectHolder* pHolder;
V8Value::Subtype subtype;
if (value.AsV8Object(pHolder, subtype))
{
pvData = new V8ObjectHandle(pHolder->Clone());
uintValue = static_cast(subtype);
return V8Value::Type::V8Object;
}
}
{
HostObjectHolder* pHolder;
if (value.AsHostObject(pHolder))
{
pvData = pHolder->GetObject();
return V8Value::Type::HostObject;
}
}
return value.GetType();
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Value_Delete(V8Value* pV8Value) noexcept
{
delete pV8Value;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8CpuProfile_GetInfo(const v8::CpuProfile& profile, const V8EntityHandleBase& entityHandle, StdString& name, uint64_t& startTimestamp, uint64_t& endTimestamp, int32_t& sampleCount, const v8::CpuProfileNode*& pRootNode) noexcept
{
name = entityHandle.CreateStdString(profile.GetTitle());
startTimestamp = profile.GetStartTime();
endTimestamp = profile.GetEndTime();
sampleCount = profile.GetSamplesCount();
pRootNode = profile.GetTopDownRoot();
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(StdBool) V8CpuProfile_GetSample(const v8::CpuProfile& profile, int32_t index, uint64_t& nodeId, uint64_t& timestamp) noexcept
{
auto pNode = profile.GetSample(index);
if (pNode != nullptr)
{
nodeId = pNode->GetNodeId();
timestamp = profile.GetSampleTimestamp(index);
return true;
}
return false;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8CpuProfileNode_GetInfo(const v8::CpuProfileNode& node, const V8EntityHandleBase& entityHandle, uint64_t& nodeId, int64_t& scriptId, StdString& scriptName, StdString& functionName, StdString& bailoutReason, int64_t& lineNumber, int64_t& columnNumber, uint64_t& hitCount, uint32_t& hitLineCount, int32_t& childCount)
{
nodeId = node.GetNodeId();
scriptId = node.GetScriptId();
scriptName = entityHandle.CreateStdString(node.GetScriptResourceName());
functionName = entityHandle.CreateStdString(node.GetFunctionName());
bailoutReason = StdString(node.GetBailoutReason());
lineNumber = node.GetLineNumber();
columnNumber = node.GetColumnNumber();
hitCount = node.GetHitCount();
hitLineCount = node.GetHitLineCount();
childCount = node.GetChildrenCount();
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(StdBool) V8CpuProfileNode_GetHitLines(const v8::CpuProfileNode& node, std::vector& lineNumbers, std::vector& hitCounts) noexcept
{
auto hitLineCount = node.GetHitLineCount();
if (hitLineCount > 0)
{
std::vector hitLines(hitLineCount);
if (node.GetLineTicks(hitLines.data(), static_cast(hitLines.size())))
{
lineNumbers.resize(hitLineCount);
hitCounts.resize(hitLineCount);
for (auto index = 0U; index < hitLineCount; index++)
{
lineNumbers[index] = hitLines[index].line;
hitCounts[index] = hitLines[index].hit_count;
}
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(const v8::CpuProfileNode*) V8CpuProfileNode_GetChildNode(const v8::CpuProfileNode& node, int32_t index) noexcept
{
return node.GetChild(index);
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8IsolateHandle*) V8Isolate_Create(const StdString& name, int32_t maxNewSpaceSize, int32_t maxOldSpaceSize, StdBool enableDebugging, StdBool enableRemoteDebugging, StdBool enableDynamicModuleImports, int32_t debugPort) noexcept
{
v8::ResourceConstraints* pConstraints = nullptr;
v8::ResourceConstraints constraints;
if ((maxNewSpaceSize >= 0) && (maxOldSpaceSize >= 0))
{
constraints.set_max_young_generation_size_in_bytes(AdjustConstraint(maxNewSpaceSize));
constraints.set_max_old_generation_size_in_bytes(AdjustConstraint(maxOldSpaceSize));
pConstraints = &constraints;
}
V8Isolate::Options options;
options.EnableDebugging = enableDebugging;
options.EnableRemoteDebugging = enableRemoteDebugging;
options.EnableDynamicModuleImports = enableDynamicModuleImports;
options.DebugPort = debugPort;
try
{
return new V8IsolateHandle(V8Isolate::Create(name, pConstraints, options));
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
return nullptr;
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8ContextHandle*) V8Isolate_CreateContext(const V8IsolateHandle& handle, const StdString& name, StdBool enableDebugging, StdBool enableRemoteDebugging, StdBool disableGlobalMembers, StdBool enableDateTimeConversion, StdBool enableDynamicModuleImports, int32_t debugPort) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
V8Context::Options options;
options.EnableDebugging = enableDebugging;
options.EnableRemoteDebugging = enableRemoteDebugging;
options.DisableGlobalMembers = disableGlobalMembers;
options.EnableDateTimeConversion = enableDateTimeConversion;
options.EnableDynamicModuleImports = enableDynamicModuleImports;
options.DebugPort = debugPort;
try
{
return new V8ContextHandle(V8Context::Create(spIsolate, name, options));
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(size_t) V8Isolate_GetMaxHeapSize(const V8IsolateHandle& handle) noexcept
{
auto spIsolate = handle.GetEntity();
return !spIsolate.IsEmpty() ? spIsolate->GetMaxHeapSize() : 0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_SetMaxHeapSize(const V8IsolateHandle& handle, size_t size) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->SetMaxHeapSize(size);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(double) V8Isolate_GetHeapSizeSampleInterval(const V8IsolateHandle& handle) noexcept
{
auto spIsolate = handle.GetEntity();
return !spIsolate.IsEmpty() ? spIsolate->GetHeapSizeSampleInterval() : 0.0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_SetHeapSizeSampleInterval(const V8IsolateHandle& handle, double milliseconds) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->SetHeapSizeSampleInterval(milliseconds);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(size_t) V8Isolate_GetMaxStackUsage(const V8IsolateHandle& handle) noexcept
{
auto spIsolate = handle.GetEntity();
return !spIsolate.IsEmpty() ? spIsolate->GetMaxStackUsage() : 0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_SetMaxStackUsage(const V8IsolateHandle& handle, size_t size) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->SetMaxStackUsage(size);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_AwaitDebuggerAndPause(const V8IsolateHandle& handle) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->AwaitDebuggerAndPause();
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Isolate_Compile(const V8IsolateHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, StdBool isModule, void* pvDocumentInfo, StdString&& code) noexcept
{
V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo);
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
try
{
return new V8ScriptHandle(spIsolate->Compile(documentInfo, std::move(code)));
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Isolate_CompileProducingCache(const V8IsolateHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, StdBool isModule, void* pvDocumentInfo, StdString&& code, V8CacheType cacheType, std::vector& cacheBytes) noexcept
{
cacheBytes.clear();
if (cacheType == V8CacheType::None)
{
return V8Isolate_Compile(handle, std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo, std::move(code));
}
V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo);
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
try
{
return new V8ScriptHandle(spIsolate->Compile(documentInfo, std::move(code), cacheType, cacheBytes));
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Isolate_CompileConsumingCache(const V8IsolateHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, StdBool isModule, void* pvDocumentInfo, StdString&& code, V8CacheType cacheType, const std::vector& cacheBytes, StdBool& cacheAccepted) noexcept
{
cacheAccepted = false;
if ((cacheType == V8CacheType::None) || cacheBytes.empty())
{
return V8Isolate_Compile(handle, std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo, std::move(code));
}
V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo);
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
try
{
auto tempCacheAccepted = false;
auto pScriptHandle = new V8ScriptHandle(spIsolate->Compile(documentInfo, std::move(code), cacheType, cacheBytes, tempCacheAccepted));
cacheAccepted = tempCacheAccepted;
return pScriptHandle;
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_GetHeapStatistics(const V8IsolateHandle& handle, uint64_t& totalHeapSize, uint64_t& totalHeapSizeExecutable, uint64_t& totalPhysicalSize, uint64_t& usedHeapSize, uint64_t& heapSizeLimit) noexcept
{
totalHeapSize = 0UL;
totalHeapSizeExecutable = 0UL;
totalPhysicalSize = 0UL;
usedHeapSize = 0UL;
heapSizeLimit = 0UL;
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
v8::HeapStatistics statistics;
spIsolate->GetHeapStatistics(statistics);
totalHeapSize = statistics.total_heap_size();
totalHeapSizeExecutable = statistics.total_heap_size_executable();
totalPhysicalSize = statistics.total_physical_size();
usedHeapSize = statistics.used_heap_size();
heapSizeLimit = statistics.heap_size_limit();
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_GetStatistics(const V8IsolateHandle& handle, uint64_t& scriptCount, uint64_t& scriptCacheSize, uint64_t& moduleCount, std::vector& postedTaskCounts, std::vector& invokedTaskCounts) noexcept
{
scriptCount = 0UL;
scriptCacheSize = 0UL;
moduleCount = 0UL;
postedTaskCounts.clear();
invokedTaskCounts.clear();
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
auto statistics = spIsolate->GetStatistics();
scriptCount = statistics.ScriptCount;
scriptCacheSize = statistics.ScriptCacheSize;
moduleCount = statistics.ModuleCount;
auto count = statistics.PostedTaskCounts.size();
postedTaskCounts.reserve(count);
std::copy(statistics.PostedTaskCounts.cbegin(), statistics.PostedTaskCounts.cend(), std::back_inserter(postedTaskCounts));
count = statistics.InvokedTaskCounts.size();
invokedTaskCounts.reserve(count);
std::copy(statistics.InvokedTaskCounts.cbegin(), statistics.InvokedTaskCounts.cend(), std::back_inserter(invokedTaskCounts));
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_CollectGarbage(const V8IsolateHandle& handle, StdBool exhaustive) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->CollectGarbage(exhaustive);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(StdBool) V8Isolate_BeginCpuProfile(const V8IsolateHandle& handle, const StdString& name, StdBool recordSamples) noexcept
{
auto spIsolate = handle.GetEntity();
return !spIsolate.IsEmpty() && spIsolate->BeginCpuProfile(name, v8::kLeafNodeLineNumbers, recordSamples);
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_EndCpuProfile(const V8IsolateHandle& handle, const StdString& name, void* pvAction) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->EndCpuProfile(name, ProcessCpuProfile, pvAction);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_CollectCpuProfileSample(const V8IsolateHandle& handle) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->CollectCpuProfileSample();
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(uint32_t) V8Isolate_GetCpuProfileSampleInterval(const V8IsolateHandle& handle) noexcept
{
auto spIsolate = handle.GetEntity();
return !spIsolate.IsEmpty() ? spIsolate->GetCpuProfileSampleInterval() : 0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_SetCpuProfileSampleInterval(const V8IsolateHandle& handle, uint32_t value) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->SetCpuProfileSampleInterval(value);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Isolate_WriteHeapSnapshot(const V8IsolateHandle& handle, void* pvStream) noexcept
{
auto spIsolate = handle.GetEntity();
if (!spIsolate.IsEmpty())
{
spIsolate->WriteHeapSnapshot(pvStream);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(size_t) V8Context_GetMaxIsolateHeapSize(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
return !spContext.IsEmpty() ? spContext->GetMaxIsolateHeapSize() : 0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_SetMaxIsolateHeapSize(const V8ContextHandle& handle, size_t size) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->SetMaxIsolateHeapSize(size);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(double) V8Context_GetIsolateHeapSizeSampleInterval(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
return !spContext.IsEmpty() ? spContext->GetIsolateHeapSizeSampleInterval() : 0.0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_SetIsolateHeapSizeSampleInterval(const V8ContextHandle& handle, double milliseconds) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->SetIsolateHeapSizeSampleInterval(milliseconds);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(size_t) V8Context_GetMaxIsolateStackUsage(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
return !spContext.IsEmpty() ? spContext->GetMaxIsolateStackUsage() : 0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_SetMaxIsolateStackUsage(const V8ContextHandle& handle, size_t size) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->SetMaxIsolateStackUsage(size);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_InvokeWithLock(const V8ContextHandle& handle, void* pvAction) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
spContext->CallWithLock(InvokeHostAction, pvAction);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_GetRootItem(const V8ContextHandle& handle, V8Value& item) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
item = spContext->GetRootObject();
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_AddGlobalItem(const V8ContextHandle& handle, const StdString& name, const V8Value& value, StdBool globalMembers) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
spContext->SetGlobalProperty(name, value, globalMembers);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_AwaitDebuggerAndPause(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
spContext->AwaitDebuggerAndPause();
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_ExecuteCode(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, StdBool isModule, void* pvDocumentInfo, const StdString& code, StdBool evaluate, V8Value& result) noexcept
{
V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo);
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
result = spContext->Execute(documentInfo, code, evaluate);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_Compile(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, StdBool isModule, void* pvDocumentInfo, StdString&& code) noexcept
{
V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo);
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
return new V8ScriptHandle(spContext->Compile(documentInfo, std::move(code)));
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileProducingCache(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, StdBool isModule, void* pvDocumentInfo, StdString&& code, V8CacheType cacheType, std::vector& cacheBytes) noexcept
{
cacheBytes.clear();
if (cacheType == V8CacheType::None)
{
return V8Context_Compile(handle, std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo, std::move(code));
}
V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo);
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
return new V8ScriptHandle(spContext->Compile(documentInfo, std::move(code), cacheType, cacheBytes));
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(V8ScriptHandle*) V8Context_CompileConsumingCache(const V8ContextHandle& handle, StdString&& resourceName, StdString&& sourceMapUrl, uint64_t uniqueId, StdBool isModule, void* pvDocumentInfo, StdString&& code, V8CacheType cacheType, const std::vector& cacheBytes, StdBool& cacheAccepted) noexcept
{
cacheAccepted = false;
if ((cacheType == V8CacheType::None) || cacheBytes.empty())
{
return V8Context_Compile(handle, std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo, std::move(code));
}
V8DocumentInfo documentInfo(std::move(resourceName), std::move(sourceMapUrl), uniqueId, isModule, pvDocumentInfo);
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
try
{
auto tempCacheAccepted = false;
auto pScriptHandle = new V8ScriptHandle(spContext->Compile(documentInfo, std::move(code), cacheType, cacheBytes, tempCacheAccepted));
cacheAccepted = tempCacheAccepted;
return pScriptHandle;
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return nullptr;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_ExecuteScript(const V8ContextHandle& handle, const V8ScriptHandle& scriptHandle, StdBool evaluate, V8Value& result) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
auto spScriptHolder = scriptHandle.GetEntity();
if (!spScriptHolder.IsEmpty())
{
try
{
result = spContext->Execute(spScriptHolder, evaluate);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_Interrupt(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->Interrupt();
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_GetIsolateHeapStatistics(const V8ContextHandle& handle, uint64_t& totalHeapSize, uint64_t& totalHeapSizeExecutable, uint64_t& totalPhysicalSize, uint64_t& usedHeapSize, uint64_t& heapSizeLimit) noexcept
{
totalHeapSize = 0UL;
totalHeapSizeExecutable = 0UL;
totalPhysicalSize = 0UL;
usedHeapSize = 0UL;
heapSizeLimit = 0UL;
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
v8::HeapStatistics statistics;
spContext->GetIsolateHeapStatistics(statistics);
totalHeapSize = statistics.total_heap_size();
totalHeapSizeExecutable = statistics.total_heap_size_executable();
totalPhysicalSize = statistics.total_physical_size();
usedHeapSize = statistics.used_heap_size();
heapSizeLimit = statistics.heap_size_limit();
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_GetIsolateStatistics(const V8ContextHandle& handle, uint64_t& scriptCount, uint64_t& scriptCacheSize, uint64_t& moduleCount, std::vector& postedTaskCounts, std::vector& invokedTaskCounts) noexcept
{
scriptCount = 0UL;
scriptCacheSize = 0UL;
moduleCount = 0UL;
postedTaskCounts.clear();
invokedTaskCounts.clear();
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
auto statistics = spContext->GetIsolateStatistics();
scriptCount = statistics.ScriptCount;
scriptCacheSize = statistics.ScriptCacheSize;
moduleCount = statistics.ModuleCount;
auto count = statistics.PostedTaskCounts.size();
postedTaskCounts.reserve(count);
std::copy(statistics.PostedTaskCounts.cbegin(), statistics.PostedTaskCounts.cend(), std::back_inserter(postedTaskCounts));
count = statistics.InvokedTaskCounts.size();
invokedTaskCounts.reserve(count);
std::copy(statistics.InvokedTaskCounts.cbegin(), statistics.InvokedTaskCounts.cend(), std::back_inserter(invokedTaskCounts));
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_GetStatistics(const V8ContextHandle& handle, uint64_t& scriptCount, uint64_t& moduleCount, uint64_t& moduleCacheSize) noexcept
{
scriptCount = 0UL;
moduleCount = 0UL;
moduleCacheSize = 0UL;
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
auto statistics = spContext->GetStatistics();
scriptCount = statistics.ScriptCount;
moduleCount = statistics.ModuleCount;
moduleCacheSize = statistics.ModuleCacheSize;
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_CollectGarbage(const V8ContextHandle& handle, StdBool exhaustive) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->CollectGarbage(exhaustive);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_OnAccessSettingsChanged(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->OnAccessSettingsChanged();
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(StdBool) V8Context_BeginCpuProfile(const V8ContextHandle& handle, const StdString& name, StdBool recordSamples) noexcept
{
auto spContext = handle.GetEntity();
return !spContext.IsEmpty() && spContext->BeginCpuProfile(name, v8::kLeafNodeLineNumbers, recordSamples);
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_EndCpuProfile(const V8ContextHandle& handle, const StdString& name, void* pvAction) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->EndCpuProfile(name, ProcessCpuProfile, pvAction);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_CollectCpuProfileSample(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->CollectCpuProfileSample();
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(uint32_t) V8Context_GetCpuProfileSampleInterval(const V8ContextHandle& handle) noexcept
{
auto spContext = handle.GetEntity();
return !spContext.IsEmpty() ? spContext->GetCpuProfileSampleInterval() : 0;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_SetCpuProfileSampleInterval(const V8ContextHandle& handle, uint32_t value) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->SetCpuProfileSampleInterval(value);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Context_WriteIsolateHeapSnapshot(const V8ContextHandle& handle, void* pvStream) noexcept
{
auto spContext = handle.GetEntity();
if (!spContext.IsEmpty())
{
spContext->WriteIsolateHeapSnapshot(pvStream);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_GetNamedProperty(const V8ObjectHandle& handle, const StdString& name, V8Value& value) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
value = V8ObjectHelpers::GetProperty(spV8ObjectHolder, name);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_SetNamedProperty(const V8ObjectHandle& handle, const StdString& name, const V8Value& value) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
V8ObjectHelpers::SetProperty(spV8ObjectHolder, name, value);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(StdBool) V8Object_DeleteNamedProperty(const V8ObjectHandle& handle, const StdString& name) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
return V8ObjectHelpers::DeleteProperty(spV8ObjectHolder, name);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return false;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_GetPropertyNames(const V8ObjectHandle& handle, std::vector& names) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
V8ObjectHelpers::GetPropertyNames(spV8ObjectHolder, names);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_GetIndexedProperty(const V8ObjectHandle& handle, int32_t index, V8Value& value) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
value = V8ObjectHelpers::GetProperty(spV8ObjectHolder, index);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_SetIndexedProperty(const V8ObjectHandle& handle, int32_t index, const V8Value& value) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
V8ObjectHelpers::SetProperty(spV8ObjectHolder, index, value);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(StdBool) V8Object_DeleteIndexedProperty(const V8ObjectHandle& handle, int32_t index) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
return V8ObjectHelpers::DeleteProperty(spV8ObjectHolder, index);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
return false;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_GetPropertyIndices(const V8ObjectHandle& handle, std::vector& indices) noexcept
{
indices.clear();
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
V8ObjectHelpers::GetPropertyIndices(spV8ObjectHolder, indices);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_Invoke(const V8ObjectHandle& handle, StdBool asConstructor, const std::vector& args, V8Value& result) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
result = V8ObjectHelpers::Invoke(spV8ObjectHolder, asConstructor, args);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_InvokeMethod(const V8ObjectHandle& handle, const StdString& name, const std::vector& args, V8Value& result) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
result = V8ObjectHelpers::InvokeMethod(spV8ObjectHolder, name, args);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_GetArrayBufferOrViewInfo(const V8ObjectHandle& handle, V8Value& arrayBuffer, uint64_t& offset, uint64_t& size, uint64_t& length) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
size_t tempOffset;
size_t tempSize;
size_t tempLength;
V8ObjectHelpers::GetArrayBufferOrViewInfo(spV8ObjectHolder, arrayBuffer, tempOffset, tempSize, tempLength);
offset = tempOffset;
size = tempSize;
length = tempLength;
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Object_InvokeWithArrayBufferOrViewData(const V8ObjectHandle& handle, void* pvAction) noexcept
{
auto spV8ObjectHolder = handle.GetEntity();
if (!spV8ObjectHolder.IsEmpty())
{
try
{
V8ObjectHelpers::InvokeWithArrayBufferOrViewData(spV8ObjectHolder, ProcessArrayBufferOrViewData, pvAction);
}
catch (const V8Exception& exception)
{
exception.ScheduleScriptEngineException();
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8DebugCallback_ConnectClient(const V8DebugCallbackHandle& handle) noexcept
{
SharedPtr spCallback;
if (handle.TryGetEntity(spCallback))
{
(*spCallback)(IHostObjectUtil::DebugDirective::ConnectClient, nullptr /*pCommand*/);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8DebugCallback_SendCommand(const V8DebugCallbackHandle& handle, const StdString& command) noexcept
{
SharedPtr spCallback;
if (handle.TryGetEntity(spCallback))
{
(*spCallback)(IHostObjectUtil::DebugDirective::SendCommand, &command);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8DebugCallback_DisconnectClient(const V8DebugCallbackHandle& handle) noexcept
{
SharedPtr spCallback;
if (handle.TryGetEntity(spCallback))
{
(*spCallback)(IHostObjectUtil::DebugDirective::DisconnectClient, nullptr /*pCommand*/);
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) NativeCallback_Invoke(const NativeCallbackHandle& handle) noexcept
{
SharedPtr spCallback;
if (handle.TryGetEntity(spCallback))
{
try
{
(*spCallback)();
}
catch (const std::exception&)
{
}
catch (...)
{
}
}
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Entity_Release(V8EntityHandleBase& handle) noexcept
{
handle.ReleaseEntity();
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8Entity_DestroyHandle(V8EntityHandleBase* pHandle) noexcept
{
delete pHandle;
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) HostException_Schedule(StdString&& message, V8Value&& exception) noexcept
{
V8SplitProxyManaged::SetHostException(HostException(std::move(message), std::move(exception)));
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(size_t) V8UnitTestSupport_GetTextDigest(const StdString& value) noexcept
{
return value.GetDigest();
}
//-----------------------------------------------------------------------------
NATIVE_ENTRY_POINT(void) V8UnitTestSupport_GetStatistics(uint64_t& isolateCount, uint64_t& contextCount) noexcept
{
isolateCount = V8IsolateImpl::GetInstanceCount();
contextCount = V8ContextImpl::GetInstanceCount();
}