Search code examples
v8

How to convert a v8::Local<v8::Value> into a uint32_t


Given the following code how can I convert the v8::Local<v8::Value> into a uint32_t. Or other types based on the Is* method?

v8::Local<v8::Value> value;
v8::Local<v8::Context> context = v8::Context::New(v8::Isolate::GetCurrent());
if(value->IsUint32()) {
   v8::MaybeLocal<Int32> maybeLocal = value->Uint32Value(context);
   uint32_t i = maybeLocal;
}

Solution

  • Your posted code doesn't work because value->Uint32Value(context) doesn't return a v8::MaybeLocal<Int32>. C++ types are your friend (just like TypeScript)!

    You have two possibilities:

    (1) You can use Value::Uint32Value(...) which returns a Maybe<uint32_t>. Since you already checked that value->IsUint32(), this conversion cannot fail, so you can extract the uint32_t wrapped in the Maybe using Maybe::ToChecked().

    (2) You can use Value::ToUint32(...) which returns a MaybeLocal<Uint32>. Again, since you already checked that value->IsUint32(), that cannot fail, so you can get a Local<Uint32> via MaybeLocal::ToLocalChecked(), and then simply use -> syntax to call the wrapped Uint32's Value() method, which gives a uint32_t.
    If you're only interested in the final uint32_t (and not in the intermediate Local<Uint32>, which you could pass back to JavaScript), then option (1) will be slightly more efficient.

    Note that IsUint32() will say false for objects like {valueOf: () => 42; }. If you want to handle such objects, then attempt the conversion, and handle failures, e.g.:

    Maybe<uint32_t> maybe_uint = value->Uint32Value(context);
    if (maybe_uint.IsJust()) {
      uint32_t i = maybe_uint.FromJust();
    } else {
      // Conversion failed. Maybe it threw an exception (use a `v8::TryCatch` to catch it), or maybe the object wasn't convertible to a uint32.
      // Handle that somehow.
    }
    

    Also, note that most of these concepts are illustrated in V8's samples and API tests. Reading comments and implementations in the API headers themselves also provides a lot of insight.

    Final note: you'll probably want to track the current context you're using, rather than creating a fresh context every time you need one.