简体   繁体   中英

Javascript generator function — written in C++

Using the V8 C++ API, how can I implement the generator interface for use in Javascript? I'd like to create an object that can be used as the iterator for a for-of loop.

Looks like the first thing that's necessary is to check for a property lookup for 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()) {
      ...

Respond with a function that takes no arguments. The function returns an object with a next property set to another function:

      ...
      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());
      ...

The next function also takes no arguments. It returns iteration values sequentially on each call. I'm using a C++ iterator for this:

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);
}

I'm keeping state in the wrapped object itself. That makes this generator non-reentrant. That's probably fine for a read/write object, for something read-only another state-keeping approach is probably warranted.

The full code for an example object is available.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM