Skip to content

Commit

Permalink
[api] Expose instanceof through v8::Value::InstanceOf.
Browse files Browse the repository at this point in the history
This is requested for Node.js N-API. Tests to be added.

Review-Url: https://codereview.chromium.org/2812613002
Cr-Commit-Position: refs/heads/master@{#44641}
  • Loading branch information
hashseed authored and Commit bot committed Apr 13, 2017
1 parent 4433ac2 commit 768c5e2
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/v8.h
Original file line number Diff line number Diff line change
Expand Up @@ -2317,6 +2317,8 @@ class V8_EXPORT Value : public Data {

Local<String> TypeOf(Isolate*);

Maybe<bool> InstanceOf(Local<Context> context, Local<Object> object);

private:
V8_INLINE bool QuickIsUndefined() const;
V8_INLINE bool QuickIsNull() const;
Expand Down
13 changes: 12 additions & 1 deletion src/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4181,6 +4181,18 @@ Local<String> Value::TypeOf(v8::Isolate* external_isolate) {
return Utils::ToLocal(i::Object::TypeOf(isolate, Utils::OpenHandle(this)));
}

Maybe<bool> Value::InstanceOf(v8::Local<v8::Context> context,
v8::Local<v8::Object> object) {
PREPARE_FOR_EXECUTION_PRIMITIVE(context, Value, InstanceOf, bool);
auto left = Utils::OpenHandle(this);
auto right = Utils::OpenHandle(*object);
i::Handle<i::Object> result;
has_pending_exception =
!i::Object::InstanceOf(isolate, left, right).ToHandle(&result);
RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool);
return Just(result->IsTrue(isolate));
}

Maybe<bool> v8::Object::Set(v8::Local<v8::Context> context,
v8::Local<Value> key, v8::Local<Value> value) {
PREPARE_FOR_EXECUTION_PRIMITIVE(context, Object, Set, bool);
Expand Down Expand Up @@ -5374,7 +5386,6 @@ Local<v8::Value> Function::GetBoundFunction() const {
return v8::Undefined(reinterpret_cast<v8::Isolate*>(self->GetIsolate()));
}


int Name::GetIdentityHash() {
auto self = Utils::OpenHandle(this);
return static_cast<int>(self->Hash());
Expand Down
1 change: 1 addition & 0 deletions src/counters.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,7 @@ class RuntimeCallTimer final {
V(UnboundScript_GetName) \
V(UnboundScript_GetSourceMappingURL) \
V(UnboundScript_GetSourceURL) \
V(Value_InstanceOf) \
V(Value_TypeOf) \
V(ValueDeserializer_ReadHeader) \
V(ValueDeserializer_ReadValue) \
Expand Down
57 changes: 57 additions & 0 deletions test/cctest/test-api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6224,6 +6224,63 @@ THREADED_TEST(TypeOf) {
.FromJust());
}

THREADED_TEST(InstanceOf) {
LocalContext env;
v8::HandleScope scope(env->GetIsolate());
CompileRun(
"var A = {};"
"var B = {};"
"var C = {};"
"B.__proto__ = A;"
"C.__proto__ = B;"
"function F() {}"
"F.prototype = A;"
"var G = { [Symbol.hasInstance] : null};"
"var H = { [Symbol.hasInstance] : () => { throw new Error(); } };"
"var J = { [Symbol.hasInstance] : () => true };"
"class K {}"
"var D = new K;"
"class L extends K {}"
"var E = new L");

v8::Local<v8::Object> f = v8::Local<v8::Object>::Cast(CompileRun("F"));
v8::Local<v8::Object> g = v8::Local<v8::Object>::Cast(CompileRun("G"));
v8::Local<v8::Object> h = v8::Local<v8::Object>::Cast(CompileRun("H"));
v8::Local<v8::Object> j = v8::Local<v8::Object>::Cast(CompileRun("J"));
v8::Local<v8::Object> k = v8::Local<v8::Object>::Cast(CompileRun("K"));
v8::Local<v8::Object> l = v8::Local<v8::Object>::Cast(CompileRun("L"));
v8::Local<v8::Value> a = v8::Local<v8::Value>::Cast(CompileRun("A"));
v8::Local<v8::Value> b = v8::Local<v8::Value>::Cast(CompileRun("B"));
v8::Local<v8::Value> c = v8::Local<v8::Value>::Cast(CompileRun("C"));
v8::Local<v8::Value> d = v8::Local<v8::Value>::Cast(CompileRun("D"));
v8::Local<v8::Value> e = v8::Local<v8::Value>::Cast(CompileRun("E"));

v8::TryCatch try_catch(env->GetIsolate());
CHECK(!a->InstanceOf(env.local(), f).ToChecked());
CHECK(b->InstanceOf(env.local(), f).ToChecked());
CHECK(c->InstanceOf(env.local(), f).ToChecked());
CHECK(!d->InstanceOf(env.local(), f).ToChecked());
CHECK(!e->InstanceOf(env.local(), f).ToChecked());
CHECK(!try_catch.HasCaught());

CHECK(a->InstanceOf(env.local(), g).IsNothing());
CHECK(try_catch.HasCaught());
try_catch.Reset();

CHECK(b->InstanceOf(env.local(), h).IsNothing());
CHECK(try_catch.HasCaught());
try_catch.Reset();

CHECK(v8_num(1)->InstanceOf(env.local(), j).ToChecked());
CHECK(!try_catch.HasCaught());

CHECK(d->InstanceOf(env.local(), k).ToChecked());
CHECK(e->InstanceOf(env.local(), k).ToChecked());
CHECK(!d->InstanceOf(env.local(), l).ToChecked());
CHECK(e->InstanceOf(env.local(), l).ToChecked());
CHECK(!try_catch.HasCaught());
}

THREADED_TEST(MultiRun) {
LocalContext context;
v8::HandleScope scope(context->GetIsolate());
Expand Down

0 comments on commit 768c5e2

Please sign in to comment.