Improve JS Exception handling.

- Check for pending exceptions after function calls and script
executions.
- Call LOGERROR instead of JS_ReportError when there is a conversion
error in FromJSVal, since that can only be called from C++ (where JS
errors don't really make sense). Instead, C++ callers of FromJSVal
should handle the failure and, themselves, either report an error or
simply do something else.
- Wrap JS_ReportError since that makes updating it later easier.

This isn't a systematical fix since ToJSVal also ought return a boolean
for failures, and we probably should trigger errors instead of warnings
on 'implicit' conversions, rather a preparation diff.

Part of the SM52 migration, stage: SM45 compatible (actually SM52
incompatible, too).

Based on a patch by: Itms
Comments by: Vladislavbelov, Stan`
Refs #742, #4893

Differential Revision: https://code.wildfiregames.com/D3093
This was SVN commit r24187.
This commit is contained in:
wraitii
2020-11-15 18:29:17 +00:00
parent 88bc973530
commit 25490bfec3
79 changed files with 810 additions and 667 deletions
+19 -13
View File
@@ -152,13 +152,13 @@ bool CComponentManager::LoadScript(const VfsPath& filename, bool hotload)
void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::CmptPrivate* pCmptPrivate, int iid, const std::string& cname, JS::HandleValue ctor, bool reRegister, bool systemComponent)
{
CComponentManager* componentManager = static_cast<CComponentManager*> (pCmptPrivate->pCBData);
ScriptInterface::Request rq(componentManager->m_ScriptInterface);
ScriptRequest rq(componentManager->m_ScriptInterface);
// Find the C++ component that wraps the interface
int cidWrapper = componentManager->GetScriptWrapper(iid);
if (cidWrapper == CID__Invalid)
{
componentManager->m_ScriptInterface.ReportError("Invalid interface id");
ScriptException::Raise(rq, "Invalid interface id");
return;
}
const ComponentType& ctWrapper = componentManager->m_ComponentTypesById[cidWrapper];
@@ -170,7 +170,7 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::Cmp
{
if (reRegister)
{
componentManager->m_ScriptInterface.ReportError(("ReRegistering component type that was not registered before '" + cname + "'").c_str());
ScriptException::Raise(rq, "ReRegistering component type that was not registered before '%s'", cname.c_str());
return;
}
// Allocate a new cid number
@@ -185,7 +185,7 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::Cmp
if (!componentManager->m_CurrentlyHotloading && !reRegister)
{
componentManager->m_ScriptInterface.ReportError(("Registering component type with already-registered name '" + cname + "'").c_str());
ScriptException::Raise(rq, "Registering component type with already-registered name '%s'", cname.c_str());
return;
}
@@ -194,7 +194,7 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::Cmp
// We can only replace scripted component types, not native ones
if (ctPrevious.type != CT_Script)
{
componentManager->m_ScriptInterface.ReportError(("Loading script component type with same name '" + cname + "' as native component").c_str());
ScriptException::Raise(rq, "Loading script component type with same name '%s' as native component", cname.c_str());
return;
}
@@ -205,7 +205,7 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::Cmp
// ...though it only matters if any components exist with this type
if (!componentManager->m_ComponentsByTypeId[cid].empty())
{
componentManager->m_ScriptInterface.ReportError("Hotloading script component type mustn't change interface ID");
ScriptException::Raise(rq, "Hotloading script component type mustn't change interface ID");
return;
}
}
@@ -233,12 +233,12 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::Cmp
JS::RootedValue protoVal(rq.cx);
if (!componentManager->m_ScriptInterface.GetProperty(ctor, "prototype", &protoVal))
{
componentManager->m_ScriptInterface.ReportError("Failed to get property 'prototype'");
ScriptException::Raise(rq, "Failed to get property 'prototype'");
return;
}
if (!protoVal.isObject())
{
componentManager->m_ScriptInterface.ReportError("Component has no constructor");
ScriptException::Raise(rq, "Component has no constructor");
return;
}
std::string schema = "<empty/>";
@@ -265,7 +265,7 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::Cmp
if (!componentManager->m_ScriptInterface.EnumeratePropertyNames(protoVal, false, methods))
{
componentManager->m_ScriptInterface.ReportError("Failed to enumerate component properties.");
ScriptException::Raise(rq, "Failed to enumerate component properties.");
return;
}
@@ -288,7 +288,7 @@ void CComponentManager::Script_RegisterComponentType_Common(ScriptInterface::Cmp
std::map<std::string, MessageTypeId>::const_iterator mit = componentManager->m_MessageTypeIdsByName.find(name);
if (mit == componentManager->m_MessageTypeIdsByName.end())
{
componentManager->m_ScriptInterface.ReportError(("Registered component has unrecognized '" + *it + "' message handler method").c_str());
ScriptException::Raise(rq, "Registered component has unrecognized '%s' message handler method", it->c_str());
return;
}
@@ -344,7 +344,10 @@ void CComponentManager::Script_RegisterInterface(ScriptInterface::CmptPrivate* p
// Redefinitions are fine (and just get ignored) when hotloading; otherwise
// they're probably unintentional and should be reported
if (!componentManager->m_CurrentlyHotloading)
componentManager->m_ScriptInterface.ReportError(("Registering interface with already-registered name '" + name + "'").c_str());
{
ScriptRequest rq(componentManager->m_ScriptInterface);
ScriptException::Raise(rq, "Registering interface with already-registered name '%s'", name.c_str());
}
return;
}
@@ -365,7 +368,10 @@ void CComponentManager::Script_RegisterMessageType(ScriptInterface::CmptPrivate*
// Redefinitions are fine (and just get ignored) when hotloading; otherwise
// they're probably unintentional and should be reported
if (!componentManager->m_CurrentlyHotloading)
componentManager->m_ScriptInterface.ReportError(("Registering message type with already-registered name '" + name + "'").c_str());
{
ScriptRequest rq(componentManager->m_ScriptInterface);
ScriptException::Raise(rq, "Registering message type with already-registered name '%s'", name.c_str());
}
return;
}
@@ -729,7 +735,7 @@ void CComponentManager::AddSystemComponents(bool skipScriptedComponents, bool sk
IComponent* CComponentManager::ConstructComponent(CEntityHandle ent, ComponentTypeId cid)
{
ScriptInterface::Request rq(m_ScriptInterface);
ScriptRequest rq(m_ScriptInterface);
std::map<ComponentTypeId, ComponentType>::const_iterator it = m_ComponentTypesById.find(cid);
if (it == m_ComponentTypesById.end())