Comparing v8 strings (Node.js addon)

1k Views Asked by At

I have this:

  if (!args[2]->IsString() || (*args[2]->ToString() != "true" && *args[2]->ToString() != "false")) {
        Nan::ThrowTypeError("Third argument to 'replace-line' must be a string representing whether to find or replace.");
        return;
    }

but I get a compilation errors andwarnings:

../hello.cpp:49:58: error: comparison between distinct pointer types ‘v8::String*’ and ‘const char*’ lacks a cast [-fpermissive]
../hello.cpp:49:92: warning: comparison with string literal results in unspecified behaviour [-Waddress]
     if (!args[2]->IsString() || (*args[2]->ToString() != "true" && *args[2]->ToString() != "false")) {

how can I properly compare v8 strings with plain C strings?

3

There are 3 best solutions below

0
On

You can convert using v8::String::NewFromOneByte detailed in the documentation there are also other sources if you want.

If you want to go the other way it looks like you would have to create your own buffer and use WriteOneByte.

0
On

You can construct a v8::String::Utf8Value like v8::String::Utf8Value arg(args[2]->ToString()) and compare that to C string literals (event though use strcmp/strncmp instead of == or construct an std::string from it).

0
On

V8 is for Javascript

How do you properly compare two strings in Javascript?

"String 1" === "String 2"

How do you properly compare two values in Javascript?

value1 === value2

The magic of === is also available in C++

Do not extract the internal character values for comparing. Compare (===) the v8::Values.

Assuming args[2] is a v8::Local<v8::Value> and not an empty handle, you may do:

Isolate *isolate = Isolate::GetCurrent();
v8::Local<v8::String> h_true = v8::String::NewFromUtf8(isolate, "true");
v8::Local<v8::String> h_false = v8::String::NewFromUtf8(isolate, "false");
if(args[2]->StrictEquals(h_true) || args[2]->StrictEquals(h_false) == false)
{
    v8::Local<v8::String> h_error_message = v8::String::NewFromUtf8(
        isolate,
        "The argument must be a \"true\" or a \"false\"."
    );
    v8::Local<v8::Error> h_error = v8::Exception::RangeError(h_error_message);
    isolate->ThrowException(h_error);
    return;
}

However, since you're using Nan, things can be much simpler:

if(info[2]->StrictEquals(Nan::New("true")) // arguments[2] === "true"
|| info[2]->StrictEquals(Nan::New("false")) // arguments[2] === "false"
== false)
{
    Nan::ThrowRangeError("The argument must be a \"true\" or a \"false\".");
    return;
}

You don't even have to check if the argument is a string, nor if it is provided by the caller.