in ClearScriptV8/V8ContextImpl.cpp [3113:3310]
void V8ContextImpl::Verify(const V8IsolateImpl::ExecutionScope& isolateExecutionScope, const v8::TryCatch& tryCatch)
{
if (tryCatch.HasCaught())
{
if (!tryCatch.CanContinue())
{
VerifyNotOutOfMemory();
throw V8Exception(V8Exception::Type::Interrupt, m_Name, StdString(SL("Script execution interrupted by host")), CreateStdString(FROM_MAYBE_DEFAULT(tryCatch.StackTrace(m_hContext))), isolateExecutionScope.ExecutionStarted(), V8Value(V8Value::Null), V8Value(V8Value::Undefined));
}
auto hException = tryCatch.Exception();
if (hException->SameValue(m_hTerminationException))
{
VerifyNotOutOfMemory();
throw V8Exception(V8Exception::Type::Interrupt, m_Name, StdString(SL("Script execution interrupted by host")), CreateStdString(FROM_MAYBE_DEFAULT(tryCatch.StackTrace(m_hContext))), isolateExecutionScope.ExecutionStarted(), V8Value(V8Value::Null), V8Value(V8Value::Undefined));
}
StdString message;
bool stackOverflow;
StdString constructorName;
if (hException->IsObject())
{
constructorName = CreateStdString(hException.As<v8::Object>()->GetConstructorName());
}
auto value = CreateStdString(hException);
if (value.GetLength() > 0)
{
message = std::move(value);
stackOverflow = (strcmp(message.ToUTF8().c_str(), "RangeError: Maximum call stack size exceeded") == 0);
}
else if (!hException->IsObject())
{
message = SL("Unknown error; an unrecognized value was thrown and not caught");
stackOverflow = false;
}
else
{
if ((constructorName == SL("Error")) || (constructorName == SL("RangeError")))
{
// It is unclear why V8 sometimes throws Error or RangeError objects that convert
// to empty strings, but it probably has to do with memory pressure. It seems to
// happen only during stack overflow recovery.
message = SL("Unknown error (");
message += constructorName;
message += SL("); potential stack overflow detected");
stackOverflow = true;
}
else if (constructorName.GetLength() > 0)
{
message = SL("Unknown error (");
message += constructorName;
message += SL(")");
stackOverflow = false;
}
else
{
message = SL("Unknown error; an unrecognized object was thrown and not caught");
stackOverflow = false;
}
}
StdString stackTrace;
V8Value hostException(V8Value::Undefined);
if (stackOverflow)
{
stackTrace = message;
}
else
{
auto hStackTrace = FROM_MAYBE_DEFAULT(tryCatch.StackTrace(m_hContext));
if (!hStackTrace.IsEmpty())
{
stackTrace = CreateStdString(hStackTrace);
}
auto hMessage = tryCatch.Message();
if (!hMessage.IsEmpty())
{
if (message.GetLength() < 1)
{
message = CreateStdString(hMessage->Get());
}
stackTrace = message;
auto hMessageStackTrace = hMessage->GetStackTrace();
auto frameCount = !hMessageStackTrace.IsEmpty() ? hMessageStackTrace->GetFrameCount() : 0;
auto usedSourceLine = false;
if ((frameCount < 1) || (constructorName == SL("SyntaxError")))
{
auto hScriptResourceName = hMessage->GetScriptResourceName();
if (!hScriptResourceName.IsEmpty() && !hScriptResourceName->IsNull() && !hScriptResourceName->IsUndefined())
{
auto hScriptName = FROM_MAYBE_DEFAULT(hScriptResourceName->ToString(m_hContext));
if (!hScriptName.IsEmpty() && (hScriptName->Length() > 0))
{
stackTrace += SL("\n at ");
stackTrace += CreateStdString(hScriptName);
}
else
{
stackTrace += SL("\n at <anonymous>");
}
}
else
{
stackTrace += SL("\n at <anonymous>");
}
stackTrace += SL(':');
stackTrace += StdString(std::to_string(FROM_MAYBE_DEFAULT(hMessage->GetLineNumber(m_hContext))));
stackTrace += SL(':');
stackTrace += StdString(std::to_string(FROM_MAYBE_DEFAULT(hMessage->GetStartColumn(m_hContext)) + 1));
auto hSourceLine = FROM_MAYBE_DEFAULT(hMessage->GetSourceLine(m_hContext));
if (!hSourceLine.IsEmpty() && (hSourceLine->Length() > 0))
{
stackTrace += SL(" -> ");
stackTrace += CreateStdString(hSourceLine);
}
usedSourceLine = true;
}
for (int index = 0; index < frameCount; index++)
{
auto hFrame = GetStackFrame(hMessageStackTrace, index);
stackTrace += SL("\n at ");
auto hFunctionName = hFrame->GetFunctionName();
if (!hFunctionName.IsEmpty() && (hFunctionName->Length() > 0))
{
if (hFrame->IsConstructor())
{
stackTrace += SL("new ");
}
stackTrace += CreateStdString(hFunctionName);
stackTrace += SL(" (");
}
auto hScriptName = hFrame->GetScriptName();
if (!hScriptName.IsEmpty() && (hScriptName->Length() > 0))
{
stackTrace += CreateStdString(hScriptName);
}
else
{
stackTrace += SL("<anonymous>");
}
stackTrace += SL(':');
auto lineNumber = hFrame->GetLineNumber();
if (lineNumber != v8::Message::kNoLineNumberInfo)
{
stackTrace += StdString(std::to_string(lineNumber));
}
stackTrace += SL(':');
auto column = hFrame->GetColumn();
if (column != v8::Message::kNoColumnInfo)
{
stackTrace += StdString(std::to_string(column));
}
if (!hFunctionName.IsEmpty() && (hFunctionName->Length() > 0))
{
stackTrace += L')';
}
if (!usedSourceLine)
{
auto hSourceLine = FROM_MAYBE_DEFAULT(hMessage->GetSourceLine(m_hContext));
if (!hSourceLine.IsEmpty() && (hSourceLine->Length() > 0))
{
stackTrace += SL(" -> ");
stackTrace += CreateStdString(hSourceLine);
}
usedSourceLine = true;
}
}
}
if (hException->IsObject())
{
hostException = ExportValue(FROM_MAYBE_DEFAULT(hException.As<v8::Object>()->Get(m_hContext, m_hHostExceptionKey)));
}
}
throw V8Exception(V8Exception::Type::General, m_Name, std::move(message), std::move(stackTrace), isolateExecutionScope.ExecutionStarted(), ExportValue(hException), std::move(hostException));
}
}