开发 js 运行时时,最重要的模块莫过于 console.log 了。有了它,才可以在 js 代码中打印日志。那么如何用 quickjs 引擎实现该模块呢?
实际上 quickjs 已经实现了一个 console 的模块
js_print 实现
其中使用了接口
str = JS_ToCStringLen(ctx, &len, argv[i]);
但该接口有一定的缺陷。它使用了 ECMAscript 中的标准
如果打印的是一个 Symbol ,那么将返回异常。quickjs 内部的处理是返回空串。也就是说,Symbol 类型的值是打印不出来的。
样例如下:样例如下
s = Symbol("dxx");
console.log(s);
输出如下
❯ ./qjs print_symbol.js
TypeError: cannot convert symbol to string
at log (native)
at <eval> (print_symbol.js:3)
为了将 Symbol 转换成 string,需要调用 Symbol 的 toString 函数。这里有两种办法
方法一:
直接获取 toString 接口
if (JS_IsSymbol(js_value)) {
JSValue toString = JS_GetPropertyStr(ctx, js_value, "toString");
JSValue symbol_str = JS_Call(ctx, toString, js_value, 0, NULL);
str = JS_ToCStringLen(ctx, &len, symbol_str);
JS_FreeValue(ctx, toString);
JS_FreeValue(ctx, symbol_str);
}
方法二: 研究后发现不可行,原因如下
另一种是先把 Symbol 转换成 Symbol Object。标准中规定 Object 会自动调用 toString 函数。这种方案不可行。
- 因为 quickjs 中把 JS_ToObject 接口定义在 c 文件中,并没有开放给使用者,如果强行使用需要改源码
- 标准规定Object在执行到string的类型转换时,需要先调用 toPrimitive 函数,见上面的截图。那么 symbol 仍然还是打印不出来