Javascript 生成器函数 -- 用 C++ 编写
Javascript generator function -- written in C++
使用 V8 C++ API,如何实现用于 Javascript 的生成器接口?我想创建一个可以用作 for-of
循环的迭代器的对象。
看起来第一件事是检查 属性 查找 Symbol.iterator
:
NAN_PROPERTY_GETTER(My_Obj::Getter) {
auto self = Nan::ObjectWrap::Unwrap<My_Obj>(info.This());
if (property->IsSymbol()) {
if (Nan::Equals(property, v8::Symbol::GetIterator(info.GetIsolate())).FromJust()) {
...
使用不带参数的函数响应。函数 returns 具有 next
属性 的对象设置为另一个函数:
...
auto iter_template = Nan::New<v8::FunctionTemplate>();
Nan::SetCallHandler(iter_template, [](const Nan::FunctionCallbackInfo<v8::Value> &info) {
auto next_template = Nan::New<v8::FunctionTemplate>();
Nan::SetCallHandler(next_template, My_Obj::next, info.Data());
auto obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New<v8::String>("next").ToLocalChecked(),
next_template->GetFunction());
info.GetReturnValue().Set(obj);
}, info.This());
info.GetReturnValue().Set(iter_template->GetFunction());
...
next
函数也没有参数。它 returns 在每次调用时按顺序迭代值。我正在为此使用 C++ 迭代器:
NAN_METHOD(My_Obj::next) {
auto self = Nan::ObjectWrap::Unwrap<My_Obj>(info.Data().As<v8::Object>());
bool done = self->iter == self->contents.end();
auto obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New<v8::String>("done").ToLocalChecked(),
Nan::New<v8::Boolean>(done));
if (!done) {
Nan::Set(obj, Nan::New<v8::String>("value").ToLocalChecked(),
Nan::New<v8::String>(self->iter->first.c_str()).ToLocalChecked());
}
self->iter++;
info.GetReturnValue().Set(obj);
}
我在包装对象本身中保持状态。这使得这个生成器不可重入。对于 read/write 对象,这可能没问题,对于只读对象,可能需要另一种状态保持方法。
使用 V8 C++ API,如何实现用于 Javascript 的生成器接口?我想创建一个可以用作 for-of
循环的迭代器的对象。
看起来第一件事是检查 属性 查找 Symbol.iterator
:
NAN_PROPERTY_GETTER(My_Obj::Getter) {
auto self = Nan::ObjectWrap::Unwrap<My_Obj>(info.This());
if (property->IsSymbol()) {
if (Nan::Equals(property, v8::Symbol::GetIterator(info.GetIsolate())).FromJust()) {
...
使用不带参数的函数响应。函数 returns 具有 next
属性 的对象设置为另一个函数:
...
auto iter_template = Nan::New<v8::FunctionTemplate>();
Nan::SetCallHandler(iter_template, [](const Nan::FunctionCallbackInfo<v8::Value> &info) {
auto next_template = Nan::New<v8::FunctionTemplate>();
Nan::SetCallHandler(next_template, My_Obj::next, info.Data());
auto obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New<v8::String>("next").ToLocalChecked(),
next_template->GetFunction());
info.GetReturnValue().Set(obj);
}, info.This());
info.GetReturnValue().Set(iter_template->GetFunction());
...
next
函数也没有参数。它 returns 在每次调用时按顺序迭代值。我正在为此使用 C++ 迭代器:
NAN_METHOD(My_Obj::next) {
auto self = Nan::ObjectWrap::Unwrap<My_Obj>(info.Data().As<v8::Object>());
bool done = self->iter == self->contents.end();
auto obj = Nan::New<v8::Object>();
Nan::Set(obj, Nan::New<v8::String>("done").ToLocalChecked(),
Nan::New<v8::Boolean>(done));
if (!done) {
Nan::Set(obj, Nan::New<v8::String>("value").ToLocalChecked(),
Nan::New<v8::String>(self->iter->first.c_str()).ToLocalChecked());
}
self->iter++;
info.GetReturnValue().Set(obj);
}
我在包装对象本身中保持状态。这使得这个生成器不可重入。对于 read/write 对象,这可能没问题,对于只读对象,可能需要另一种状态保持方法。