如何从V8中获取JS函数的返回值?

问题描述 投票:0回答:1

我目前想获取我在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 embedded-v8
1个回答
1
投票

正如文件中所说。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.)

© www.soinside.com 2019 - 2024. All rights reserved.