I'm embedding V8 as an auxiliary language in a C++ program.
I retrieve a Handle<Value>
from V8 when I call something like
Handle<Value> value_handle = context->Global()->Get(key_handle);
I can then find out that it is (say) a string with value_handle->IsString()
. And if so I can convert it to a Handle<String>
to access its string-specific methods.
But there seems to be two ways of doing that, either:
Handle<String> string = value_handle->ToString();
or
Handle<String> string = Handle<String>::Cast(value_handle);
However, for Arrays and Functions, there is no toArray()
or toFunction
methods, just the casting.
So my question is:
a) are the ToXXX
just syntactic sugar for casting?
and, if not b) what is the ToXXX
method doing?
I'm embedding V8 as an auxiliary language in a C++ program.
I retrieve a Handle<Value>
from V8 when I call something like
Handle<Value> value_handle = context->Global()->Get(key_handle);
I can then find out that it is (say) a string with value_handle->IsString()
. And if so I can convert it to a Handle<String>
to access its string-specific methods.
But there seems to be two ways of doing that, either:
Handle<String> string = value_handle->ToString();
or
Handle<String> string = Handle<String>::Cast(value_handle);
However, for Arrays and Functions, there is no toArray()
or toFunction
methods, just the casting.
So my question is:
a) are the ToXXX
just syntactic sugar for casting?
and, if not b) what is the ToXXX
method doing?
2 Answers
Reset to default 9ToXXX
functions perform type coercions as described in subsections of section 9 of ECMA-262 5th. For example ToString
is described in section 9.8: when given a non-string value it'll return an appropriate string representation of it, if you are passing object it'll call toString
method on it (or valueOf
if toString
is not present). Relevant code for ToString
: in api
Value::ToString
that calls into runtime.js
ToString
On the other hand Handle<XXX>::Cast(...)
does no coercions. It's just a type cast for handles. Essentially it is just a static_cast<XXX*>
. In debug mode Handle<T>::Cast(...)
is checked and aborts execution when types do not match. It would be a fatal error if you are given a Handle<Value>
containing an Object
and you are trying to cast it to a Handle<String>
. In release mode casting to an inpatible type will just later lead to weird results and possibly crashes, when you try to use the result of the cast. Relevant code in v8.h
Handle<T>::Cast
which delegates to (for example) String::Cast
which checks the cast (if checks are enabled) via String::CheckCast
.
We can locate
V8EXPORT Local ToString() const;
in line 971 of v8.h
where V8EXPORT is a OS dependent approach for functions.
ToString of Handle of String is located at line 2362 of api
Local<String> Value::ToString() const {
i::Handle<i::Object> obj = Utils::OpenHandle(this);
i::Handle<i::Object> str;
if (obj->IsString()) {
str = obj;
} else {
i::Isolate* isolate = i::Isolate::Current();
if (IsDeadCheck(isolate, "v8::Value::ToString()")) {
return Local<String>();
}
LOG_API(isolate, "ToString");
ENTER_V8(isolate);
EXCEPTION_PREAMBLE(isolate);
str = i::Execution::ToString(obj, &has_pending_exception);
EXCEPTION_BAILOUT_CHECK(isolate, Local<String>());
}
return Local<String>(ToApi<String>(str));
}
For consistency and take advantages from further upgrade of V8 versions, I strongly remend to use toString() instead of the primitive cast.