javascript - 如何从 C++ 中返回一个新的 V8 javascript "class"实例?

标签 javascript c++ v8 embedded-v8

当使用 V8 作为脚本引擎时,我向 Javascript 公开了一个名为 construct_with_ec6_syntax 的 C++ 函数。这个函数在被调用时应该简单地返回一个 some_ec6_class 的实例。

这个 C++ 函数基本上应该执行以下等效的 Javascript:

return new some_ec6_class(111, 222);

这个类将在 Javascript 中定义如下 EC6 语法:

class some_ec6_class
{
    constructor(x, y) {
        this.result = x + y;
    }
}

我的目标是在 Javascript 中运行以下...

var the_instance = construct_with_ec6_syntax(111, 222);
the_instance.result ; // .. and get 333 here.

我当前的 C++ 函数实现是这样的:

void construct_with_ec6_syntax(const FunctionCallbackInfo<Value>& args) {
    Handle<Object> global = args.GetIsolate()->GetCurrentContext()->Global();
    std::string newvecfunc = "some_ec6_class";
    Handle<Value> value = global->Get(String::NewFromUtf8(args.GetIsolate(), newvecfunc.c_str(), String::kNormalString, newvecfunc.length()));
    Local<Value> result;
    if (value->IsFunction()) {
        Handle<Function> func = Handle<Function>::Cast(value);
        Handle<Value> args2[2];
        args2[0] = Number::New(args.GetIsolate(), 111);
        args2[1] = Number::New(args.GetIsolate(), 222);
        result = func->CallAsConstructor(args.GetIsolate()->GetCurrentContext(), 2, args2).ToLocalChecked();
    }   
    args.GetReturnValue().Set(result);
}   

从 Javascript 运行这个函数会返回 undefined!而不是我期望的对象。正如 xaxxon 向我指出的那样,这是因为 value->IsFunction() 返回 false,但 value->IsUndefined() 返回 true。如果我使用 with non EC6 语法定义了类,则上述函数确实返回一个实例..

function some_non_ec6_class(x, y) // this guy would work with the above function
{
    this.result = x + y;
}

所以我有点困惑!我是否需要更具体一些,比如首先从对象中获取 constructor 函数,然后调用 CallAsConstructor

感谢任何提示!

(这个问题看起来类似于 Calling a v8 javascript function from c++ with an argument但不同。)

我从 2016 年 10 月 22 日开始使用 V8 结账。 完整的测试用例:

https://gist.github.com/rayburgemeestre/c0abd528f6f67edbfe686d484c45ddbb

次要更新:

正如您在评论中看到的,我还做了一个更具体的关于从上下文中“获取”类的测试用例:https://gist.github.com/rayburgemeestre/df6193d532c7b7908fe27c89799bfa3a

我还发布到 v8-users 邮件列表:https://groups.google.com/forum/#!topic/v8-users/Hj2j4rJMwBw

最佳答案

class 是javascript中创建变量的一种方式,类似于let。使用 class 创建的变量是 block 范围的,不会创建全局属性(同样,类似于 let)。因此它在 context.global 中不可用,就像一个函数是:

http://exploringjs.com/es6/ch_variables.html

function    Complete    Block   Yes

class       No          Block   No

您需要为您的代码明确创建一个全局变量:

some_es6_class = class{}; 

或者在使用“传统 es6”语法创建类对象后显式地将类对象传递给您的 C++ 函数:

class some_es6_class{};
some_native_function(some_es6_class);

编辑:我做了更多的挖掘,我相信上下文对象有一个 LexicalEnvironment,它在它的 script 中共享,但与全局对象不同.查找名称时,它会遍历 LexicalEnvironments 的父层次结构以查找该名称。这些词法环境不会通过 API 公开(并且可能实际上不存在 - 它们是 JS 规范用来定义行为的构造,而不是实现的必需部分)

关于javascript - 如何从 C++ 中返回一个新的 V8 javascript "class"实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41211533/

相关文章:

javascript - Knockout JS - 单击数组中的图像

javascript - !condition 和 variable 之间的区别 != Javascript/Jquery 中的其他变量?

c++ - 实现两个依赖类(类的前向声明)

typescript - V8 上的 Google Apps 脚本继承

c++ - 如何在 C++ v8 中解析参数对象

javascript - 使用javascript的磁性光标移动

javascript - 修改背景: webkit-gradient with javascript

c++ - 如何检查一组值中的一个是否相等?

c++ - MS c++ 中未调用复制构造函数

node.js - Node.js 缓冲区的最大大小是多少