Понимание Node Addon API (N-API) HandleScope - PullRequest
0 голосов
/ 14 января 2019

Мне сложно понять, как правильно использовать HandleScope и EscapableHandleScope . Например, с пример этого узла :

MyObject::MyObject(const Napi::CallbackInfo& info) : Napi::ObjectWrap<MyObject>(info) {
  Napi::Env env = info.Env();
  Napi::HandleScope scope(env);

  this->val_ = info[0].As<Napi::Number>().DoubleValue();
};

Зачем нам в этом случае создавать новый HandleScope? А из это другой пример :

Napi::Object CreateObject(const Napi::CallbackInfo& info) {
  Napi::Env env = info.Env();
  Napi::Object obj = Napi::Object::New(env);
  obj.Set(Napi::String::New(env, "msg"), info[0].ToString());

  return obj;
}

Почему это здесь не нужно?

Кроме того, я не нашел ни одного примера использования EscapableHandleScope, когда это необходимо?

1 Ответ

0 голосов
/ 15 января 2019

Объяснение того, что такое HandleScopes и для чего их использовать, см. В документации V8 , например. для класса Local:

Существует два типа дескрипторов: локальные и постоянные.

Местные ручки легкие и переходные и обычно используются в местные операции. Они управляются HandleScopes. Это означает, что HandleScope должен существовать в стеке при его создании, и он действителен только внутри HandleScope, активного во время их создание. Для передачи локального дескриптора к внешнему HandleScope, Необходимо использовать EscapableHandleScope и его метод Escape ().

А для класса HandleScope:

Класс, выделенный стеком, который управляет несколькими локальными дескрипторами. После была создана область маркера, все локальные маркеры будут выделены в пределах этой области дескриптора, пока либо область дескриптора не будет удалена или создана другая область видимости. Если уже есть область действия ручки и новый создается, все распределения будут происходить в новом обрабатывать область, пока она не будет удалена. После этого новые ручки снова будут выделяться в оригинальной области видимости дескриптора.

После удаления области видимости локального дескриптора мусор сборщик больше не будет отслеживать объект, хранящийся в дескрипторе, и может освободить его. Поведение доступа к дескриптору, для которого область действия дескриптора была удалена не определено.

Прагматический:

  • При вызове из JavaScript в C ++ вам потребуется как минимум один HandleScope, если код C ++ создает какие-либо Local<> s. Обычно ровно один HandleScope является правильным числом.
  • Создание и уничтожение HandleScopes обходится дорого, поэтому, если у вас много детальных HandleScopes, вы теряете время. С другой стороны, HandleScope (по замыслу, это его цель!) Поддерживает все объекты живыми (в смысле GC), на которые ссылаются содержащиеся в нем дескрипторы, поэтому для очень долго выполняющегося кода или циклов с большим количеством итераций, Вы можете захотеть ввести недолговечные HandleScopes, чтобы временные объекты, с которыми вы сделали, могли быть освобождены.
  • Как сказано в документации, вам нужно EscapableHandleScope, если вы хотите вернуть объект после окончания срока действия области действия.
...