LiteLoaderBDS-1.16.40/Tools/ScriptX/docs/zh/Exception.md
2023-03-03 10:18:21 -08:00

94 lines
2.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 异常模型
在脚本语言中,我们通常可以任意调用方法,只需要在方法最外层加一个 `try-catch` 块即可,异常就能很方便的被处理,而无需到处检查。
但是在脚本语言的C API中通常会把内部脚本出现的异常以类似错误码的形式暴露。这就导致了每调用一个API都要检查是否有异常发生。否则在有异常发生的情况下继续执行逻辑通常会有问题甚至带来crash。
因此ScriptX在异常模型设计时将脚本出现的异常统一转成C++异常向外抛出使得C++代码也可以很方便的处理异常同时避免多种问题及crash。
对比一下:
```c++
// V8 需要到处检查
{
v8::TryCatch tryCatch;
auto ret = eval("string source");
if (tryCatch.hasCaught()) retrun false;
auto result = ret.get(key):
if (tryCatch.hasCaught()) retrun false;
auto obj = get(obj);
if (tryCatch.hasCaught()) retrun false;
obj.set(key, result);
if (tryCatch.hasCaught()) retrun false;
return true;
}
// ScriptX
{
script::EngineScope scope(engine);
try {
engine->eval("string source");
auto result = ret.get(key):
auto obj = get(obj);
obj.set(key, result);
return true;
} catch(script::Exception& e) {
log << e;
return false;
}
}
```
`script::Exception`是C++的异常类型,包装了脚本异常,提供了便利的方法来获取异常的消息和堆栈。需要注意的是:
1. `script::Exception`:必须在EngineScope内创建。
2. 几乎所有需要EngineScope的接口都有可能抛异常(除非有noexcept修饰)。
**结论几乎所有的EngineScope都要紧跟一个try-catch用于处理script::Exception异常**。如上代码实例所述,除非你需要在发生异常时 crash掉进程。
## 抛异常&捕获异常。
异常可以在JS和C++间传递。举个例子:
```c++
// 1. script throw, c++ catch
try{
engine->eval("throw Error('hello error')");
FAIL();
} catch (const script::Exception& e) {
std::cout << e.message() << e.stacktrace();
}
// 2. c++ throw, sript catch
auto func = Function::newFunction([](const script::Arguments& args) {
// c++ throw exception
throw Exception("invalid argument");
});
engine->set("func", func);
auto ret = engine->eval(R"(
try {
func();
false;
} catch (e) {
true;
}}
)");
EXPECT_TRUE(ret.isBoolean());
EXPECT_TRUE(ret.asBoolean().value());
// 3. c++ throw, c++ catch
try{
func.call({});
FAIL();
} catch (const script::Exception& e) {
log << e.message() << e.stacktrace();
}
```
详见单元测试 [ExceptionTest](../../test/src/ExceptionTest.cc)