【js 引擎】如何使用 quickjs 中异常处理功能

开发 js 运行时,要在 c/c++ 代码中,通过调用 quickjs 的 api 来实现 native 层的异常抛出。本文讲解一下如何在quickjs中实现这个操作。

要讲清楚这个操作,需要知道 quickjs 中表示异常有两种值。

  1. 一种表示发生了异常,叫他 exception,表示为 JS_EXCEPTION
  2. 另一种表示异常具体是什么,叫他 Error,表示为 各种类型的错误。相关 API 如下
c++ 复制代码
JSValue JS_Throw(JSContext *ctx, JSValue obj);
JSValue JS_GetException(JSContext *ctx);
JS_BOOL JS_IsError(JSContext *ctx, JSValueConst val);
JS_BOOL JS_IsException(JSValueConst v)
void JS_ResetUncatchableError(JSContext *ctx);
JSValue JS_NewError(JSContext *ctx);

JSValue __js_printf_like(2, 3) JS_ThrowSyntaxError(JSContext *ctx, const char *fmt, ...);
JSValue __js_printf_like(2, 3) JS_ThrowTypeError(JSContext *ctx, const char *fmt, ...);
JSValue __js_printf_like(2, 3) JS_ThrowReferenceError(JSContext *ctx, const char *fmt, ...);
JSValue __js_printf_like(2, 3) JS_ThrowRangeError(JSContext *ctx, const char *fmt, ...);
JSValue __js_printf_like(2, 3) JS_ThrowInternalError(JSContext *ctx, const char *fmt, ...);
JSValue JS_ThrowOutOfMemory(JSContext *ctx);

抛出异常

  1. 错误发生时,我们通常返回 Execption,并将 Error 放置在 context 上。具体做法如下
c 复制代码
// 抛出异常
void js_cfunc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
	JSValue ret = JS_UNDEFINED;
	if (/*error occur*/) {
		JSValue err = JS_NewError(ctx);
		/*set err info, 
		ref: JS_AddIntrinsicBasicObjects 
			 JS_ThrowSyntaxError
		*/
		JS_Throw(ctx, err);
		return JS_EXCEPTION;
	}
	return ret;
}
  1. 便利函数,语法糖
    一些常见的错误,创建异常并抛出的动作可以合并成 JS_ThrowSyntaxError 等便利函数,见上。
c 复制代码
void js_cfunc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
	JSValue ret = JS_UNDEFINED;
	if (/*error occur*/) {
		return JS_ThrowSyntaxError(ctx, "error info", ...);
	}
	return ret;
}

处理异常

异常发生时,我们通常获取 Error,并处理错误

c 复制代码
// 处理异常
void js_cfunc(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
	JSValue ret = JS_Call(ctx, ....);
	if (JS_IsException(ret)) {
		JSValue err = JS_GetException(ctx);
		/**
			处理异常,常见手段是
			1. 打印异常栈和异常信息:ref:函数 js_std_dump_error / eval_buf
			2. 也可以直接不处理,异常会自动传播到上层函数。其中原理,看这块代码是可以完全搞清楚的。
		*/
	}
	return ret;
}
相关推荐
Wang's Blog1 分钟前
Java 项目实战: 外卖平台优化-前后端分离开发模式与工程拆分
java·开发语言
凤城老人37 分钟前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)40 分钟前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
HRTOS1 小时前
HRTOS:一个名字背后的目标——不断逼近硬实时
经验分享·单片机·系统架构·51单片机
sunshine22 girl1 小时前
Java学习六 Java常见API-2--String-3-字符串的截取替换和其他方法
java·开发语言·学习
零基础1231 小时前
DeepSeek V4.1 Flash (Batch) 的性能测试与应用
经验分享·python·语言模型·vllm
LOVE️YOU1 小时前
Python 函数名、函数对象与“把函数作为参数传递”
开发语言·python
码艺-Alimjan1 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
sunshine22 girl2 小时前
Java学习六 Java常见API-1-Radom随机数
java·开发语言·学习
可乐鸡翅yeah_2 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线