IsFunction() on v8::Name returns false

30 views
Skip to first unread message

Gautham B A

unread,
Sep 26, 2019, 2:07:07 AM9/26/19
to v8-users
Hi all,

Calling IsFunction() on v8::Local<v8::Name> is returning false, even though v8::Local<v8::Name> was pointing to a function in JavaScript. Is this expected? Consider the following code -

#include <iostream>
#include <libplatform/libplatform.h>
#include <ostream>
#include <v8.h>


void Getter(v8::Local<v8::Name> key,
           
const v8::PropertyCallbackInfo<v8::Value> &info) {
  std
::cout << "Getter:" << std::endl;
  std
::cout << "IsFunction: " << key->IsFunction() << std::endl;
}


void Setter(v8::Local<v8::Name> key, v8::Local<v8::Value> value,
           
const v8::PropertyCallbackInfo<v8::Value> &info) {
  std
::cout << "Setter:" << std::endl;
 
// key->IsFunction() returns false, expected to be true
  std
::cout << "Key IsFunction: " << key->IsFunction() << std::endl;


 
// value->IsFunction() returns true, as expected
  std
::cout << "\nValue IsFunction:" << value->IsFunction() << std::endl;
}


void Deleter(v8::Local<v8::Name> key,
             
const v8::PropertyCallbackInfo<v8::Boolean> &info) {}


bool InstallMap(v8::Isolate *isolate, const v8::Local<v8::Context> &context) {
  v8
::HandleScope handle_scope(isolate);
 
auto obj_template = v8::ObjectTemplate::New(isolate);
  obj_template
->SetHandler(
      v8
::NamedPropertyHandlerConfiguration(Getter, Setter, nullptr, Deleter));


  v8
::Local<v8::Object> obj;
 
if (!obj_template->NewInstance(context).ToLocal(&obj)) {
    std
::cerr << "Unable to instantiate object template" << std::endl;
   
return false;
 
}


  v8
::Local<v8::String> obj_name;
 
if (!v8::String::NewFromUtf8(isolate, "dict", v8::String::kNormalString)
           
->ToString(context)
           
.ToLocal(&obj_name)) {
    std
::cerr << "Unable to create map key name" << std::endl;
   
return false;
 
}


 
auto global = context->Global();
 
if (!global->Set(context, obj_name, obj).FromJust()) {
    std
::cerr << "Unable to install object into global scope" << std::endl;
   
return false;
 
}
 
return true;
}


int main(int argc, char *argv[]) {
 
const auto script_str = R"(
  function x() {
  }


  dict[x] = x;
  )"
;


  v8
::V8::InitializeICUDefaultLocation(argv[0]);
  v8
::V8::InitializeExternalStartupData(argv[0]);
 
auto platform = v8::platform::NewDefaultPlatform();
  v8
::V8::InitializePlatform(platform.get());
  v8
::V8::Initialize();


  v8
::Isolate::CreateParams create_params;
  create_params
.array_buffer_allocator =
      v8
::ArrayBuffer::Allocator::NewDefaultAllocator();
  v8
::Isolate *isolate = v8::Isolate::New(create_params);
 
{
    v8
::Isolate::Scope isolate_scope(isolate);
    v8
::HandleScope handle_scope(isolate);
   
auto context = v8::Context::New(isolate);
    v8
::Context::Scope context_scope(context);


   
InstallMap(isolate, context);


   
auto source =
        v8
::String::NewFromUtf8(isolate, script_str, v8::NewStringType::kNormal)
           
.ToLocalChecked();
   
auto script = v8::Script::Compile(context, source).ToLocalChecked();
   
auto result = script->Run(context).ToLocalChecked();
    v8
::String::Utf8Value result_utf8(isolate, result);
    std
::cout << *result_utf8 << std::endl;
 
}
  isolate
->Dispose();
  v8
::V8::Dispose();
  v8
::V8::ShutdownPlatform();
 
delete create_params.array_buffer_allocator;
 
return 0;
}


As seen in the code above, I'm exposing a global variable dict which has the Setter, Getter and Deleter callbacks set appropriately on dict.

function x() {
}
dict
[x] = x;
When I run the above JavaScript code, The Setter callback gets called and I see that name and value have different results upon calling IsFunction() on them.
Could someone please tell me if this is the expected behavior, if so, the reason behind why it is so?

Thanks,
--Gautham

Simon Zünd

unread,
Sep 26, 2019, 2:44:26 AM9/26/19
to v8-users
In terms of the JavaScript spec, you are performing a [[Set]] operation with `dict[x] = x`. The key for [[Set]] must be a valid property key, which is either a String or a Symbol. In this case, the code actually looks more like `dict[x.toString()] = x`. This is just how JavaScript works, and is intended.

--
--
v8-users mailing list
v8-u...@googlegroups.com
http://groups.google.com/group/v8-users
---
You received this message because you are subscribed to the Google Groups "v8-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to v8-users+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/v8-users/06da69ba-ec72-47d3-972d-7a241699b8fa%40googlegroups.com.

Jakob Kummerow

unread,
Sep 26, 2019, 5:12:59 AM9/26/19
to v8-users
In addition to what Simon said: from a V8 API point of view, we have a strict type system and class hierarchy (this is C++ after all, not JavaScript). A v8::Name is a name, not a function. For a v8::Local<v8::Name> key, it will and must always be the case that key->IsName() returns true, and key->IsFunction() returns false. Anything else would be a very serious bug.
Reply all
Reply to author
Forward
0 new messages