我目前想获取我在JS中调用的一个函数的返回值。下面的代码可以重现(减去v8的包含)。
#include "v8.h"
#include "libplatform/libplatform.h"
#include <string>
#include <cassert>
int64_t repro()
{
auto isolate = v8::Isolate::New(initializer.create_params_);
assert(isolate != nullptr);
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
auto context = v8::Context::New(isolate);
v8::Context::Scope context_scope(context);
assert(context.IsEmpty() == false);
auto global = context->Global();
std::string script = "function foo() {\n"
" return BigInt(1);\n"
"}";
v8::Local<v8::String> sourceScript =
v8::String::NewFromUtf8(isolate, script.c_str(),
v8::NewStringType::kNormal)
.ToLocalChecked();
v8::Local<v8::Script> s =
v8::Script::Compile(context, sourceScript).ToLocalChecked();
s->Run(context);
v8::Local<v8::String> name =
v8::String::NewFromUtf8(isolate, "foo",
v8::NewStringType::kInternalized)
.ToLocalChecked();
auto value = global->Get(context, name).ToLocalChecked();
assert(value->IsFunction());
auto func = v8::Handle<v8::Function>::Cast(value);
auto result = func->Call(context, context->Global(), 0, nullptr)
.ToLocalChecked();
assert(result->IsBigInt());
auto bigint = result->IntegerValue(context);
assert(bigint.IsNothing() == false);
return bigint.ToChecked();
}
当我现在查看bigint时 - 类型报告为BigInt,但IsNothing()返回true。我到底做错了什么?
谢谢你
托比亚斯
正如文件中所说。v8::Value::IntegerValue()
"返回相当于 ToInteger()->Value()
",这意味着它将抛出一个异常(即返回 Nothing
),当调用 BigInt
,反映了在JavaScript中,调用 "抽象操作" ToInteger()
关于 BigInt
抛出 TypeError
,或者换句话说:a BigInt
并不只是隐含地转换为一个。Number
.
要提取一个 BigInt
的值,你可以这样做。
int64_t bigint = v8::Local<v8::BigInt>::cast(result)->Int64Value();
当然,当BigInt的值大于int64时,这样做会得到一个错误的结果。它需要一个可选的 bool*
来表示转换到int64的过程是无损的还是截断的。如果你需要得到更大的值,你可以使用 ToWordsArray(...)
方法。
如何从V8获取JS函数的返回值?
和你的做法一模一样。
v8::MaybeLocal<v8::Value> result = func->Call(...);
注意,使用 .ToLocalChecked();
是有风险的:如果函数抛出一个异常而不是返回一个值,那么 .ToLocalChecked()
会崩溃。如果你不控制函数的代码,因此不能保证它不会抛出,那么最好测试结果是否为空,并优雅地处理异常。参见V8的 samples/
目录中,或在 v8.devdocs,以获得大量的例子和额外的解释。
(附注:我建议使用 auto
少得多。看清类型是有帮助的。之间的差异,比如。v8::Value
, v8::Local<v8::Value>
, v8::MaybeLocal<v8::Value>
和 v8::Local<v8::BigInt>
是有意义的,当你不只是把它们隐藏在后面时,它有助于你写出正确的代码。auto
.)