Обновление кода V8 с использованием устаревшего v8::Local v8::Object::Get(v8::Local)?

#c #node.js #v8

#c #node.js #v8

Вопрос:

Я нахожусь в процессе обновления пакета NodeJS из-за поломки в NodeJS 14. Эта библиотека использует код C . В NodeJS 12 тот же код отображается как предупреждение об устаревании:

warning: ‘v8::Local<v8::Value> v8::Object::Get(v8::Local<v8::Value>)’ is deprecated: Use maybe version

При этом рассматриваемый код является:

 v8::Local<v8::Object> options = v8::Local<v8::Object>::Cast(info[0]);
v8::Local<v8::Value> debug = options->Get(Nan::New<v8::String>("debug").ToLocalChecked());

if (true) {
    v8::Local<v8::Value> leds = options->Get(Nan::New<v8::String>("leds").ToLocalChecked());

    if (!leds->IsUndefined())
        ws2811.channel[0].count = Nan::To<int>(leds).FromMaybe(ws2811.channel[0].count);
    else
        return Nan::ThrowTypeError("configure(): leds must be defined");
}

 

Я попробовал следующее, и хотя он компилируется, среда выполнения предполагает, что это может быть неправильно, поскольку я получаю сбой, которого не было до этого изменения кода:

 v8::Local<v8::Object> options = v8::Local<v8::Object>::Cast(info[0]);
Nan::MaybeLocal<v8::Value> debug = Nan::Get(options, Nan::New<v8::String>("debug").ToLocalChecked());

if (true) {
    Nan::MaybeLocal<v8::Value> maybe_leds = Nan::Get(options, Nan::New<v8::String>("leds").ToLocalChecked());
    v8::Local<v8::Value> leds;

    if (!maybe_leds.IsEmpty() amp;amp; maybe_leds.ToLocal(amp;leds))
        ws2811.channel[0].count = Nan::To<int>(leds).FromMaybe(ws2811.channel[0].count);
    else
        return Nan::ThrowTypeError("configure(): leds must be defined");
}
 

Будучи довольно знакомым с C и новичком в версии 8, я немного сбит с толку относительно того, какая правильная замена для этого Get метода в данном контексте. Я думаю, я понимаю, что нам нужно использовать MaybeLocal вместо Local . При выполнении поиска появляется много других людей с похожими проблемами, но ничего, что я мог бы использовать в качестве решения.

Кстати, этот проект зависит от nan.

Ответ №1:

Ключевым моментом является то, что большинство операций, связанных с JavaScript, могут генерировать исключение вместо возврата значения. MaybeLocal Соглашение делает это явным: a MaybeLocal является либо локальным (если функция / операция вернула значение), либо пустым (если было исключение). Если у вас есть v8::TryCatch или Nan::TryCatch , он поймает исключение в последнем случае.

Существует несколько способов встраивания кода для работы с MaybeLocals; наиболее элегантным является метод bool -returning .ToLocal(...) . Это эквивалентно проверке .IsEmpty() , поэтому вам не нужно делать и то, и другое.

Так что это даст вам:

 Nan::TryCatch try_catch;
v8::Local<v8::String> leds_string = Nan::New<v8::String>("leds").ToLocalChecked();
Nan::MaybeLocal<v8::Value> maybe_leds = Nan::Get(options, leds_string);

v8::Local<v8::Value> leds;
if (!maybe_leds.ToLocal(amp;leds)) {
  // An exception was thrown while reading `options["leds"]`.
  // This is the same as `maybe_leds.IsEmpty() == true`.
  // It is also the same as `try_catch.HasCaught() == true`.
  return try_catch.ReThrow();
}
// Now follows your original code.
if (leds->IsUndefined()) {
  // The `options` object didn't have a `leds` property, or it was undefined.
  return Nan::ThrowTypeError("configure(): leds must be defined");
}

// Success case: all good.
ws2811.channel[0].count = Nan::To<int>(leds).FromMaybe(ws2811.channel[0].count);
 

См. Документацию по адресу https://github.com/nodejs/nan/blob/master/doc/maybe_types.md .

Ответ №2:

Если еще немного покопаться, это кажется правильным подходом. По сути, это составлено на основе документов Nan и фрагментов, которые я нашел в сети:

 v8::Local<v8::Object> options = v8::Local<v8::Object>::Cast(info[0]);
v8::MaybeLocal<v8::Value> debug = Nan::Get(options, Nan::New<v8::String>("debug").ToLocalChecked());

if (Nan::Has(options, Nan::New<v8::String>("leds").ToLocalChecked()).ToChecked()) {
    Nan::MaybeLocal<v8::Value> maybe_leds = Nan::Get(options, Nan::New<v8::String>("leds").ToLocalChecked());
    v8::Local<v8::Value> leds;

    if (maybe_leds.ToLocal(amp;leds))
        ws2811.channel[0].count = Nan::To<int>(leds).FromMaybe(ws2811.channel[0].count);
    else
        return Nan::ThrowTypeError("configure(): leds must be defined");
}
 

Похоже Nan::Has , проверка важна, иначе код, похоже, ведет себя некорректно.

Комментарии:

1. Нет, Nan::Has это не важно, он просто описывает один конкретный случай сбоя, который вы можете более элегантно проверить другими способами. Подробности см. в моем ответе.