Exposing nested maps from C++ into JS world

56 views
Skip to first unread message

Abhishek Singh

unread,
Jul 22, 2016, 2:12:48 AM7/22/16
to v8-u...@googlegroups.com
Hi,

I’m wondering if there is a way to expose map<string, map<string, string> > into JS world from C++? Exposing map<string, string> looks straightforward and I’m doing for some C++ objects using NamedPropertyConfigurationHandler. I’ll just show sample JS code that I would like to have and where C++ map<string, map<string, string> > will come into picture:

function OnHTTPGet(request, response) {

var city = “BLR”;
var limit = “10”;

var queryResult = dbCal(“select * from users where city=${city} limit ${limit}”);

// This works for me presently
/* response.data = queryResult;
response.status_code = 200; */

// What I would like to have
response.body.data = queryResult;
response.header.status_code = 200;
}

“request” - native HTTP request JSON passed from C++ V8 binding as args to JS function
“response” - C++ based HTTP object exposed with Setter callback set using NamedPropertyConfigHandler and this what I write back to user who made the “request"

I basically want to set HTTP response body and header transparently, which would require me to expose C++ HTTP object probably as a map<string, map<string, string> >. Hope my question is clear, please let me know if there a way to do this?

Thanks,
Abhishek

Jochen Eisinger

unread,
Jul 25, 2016, 12:31:05 PM7/25/16
to v8-u...@googlegroups.com
To create dynamic nested maps from C++, the outter object (response) would have to return another intercepted object (e.g. body) that then returns the actual values on access.

--
--
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.
For more options, visit https://groups.google.com/d/optout.

Abhishek Singh

unread,
Jul 25, 2016, 4:01:21 PM7/25/16
to v8-u...@googlegroups.com
Thanks Jochen, will give it a shot.

Abhishek Singh

unread,
Jul 26, 2016, 7:04:01 AM7/26/16
to v8-u...@googlegroups.com
Would you mind guiding me a bit here? For now just trying to expose nested “body” map i.e. to allow something like “response.body.result = dbQueryResult"

First is the Set interceptor for “response” (C++ object) and here I’m setting up “body” (C++ object for “body”) & setting return value to “body” object. Second one is Set interceptor for “body”

void HTTPResponse::HTTPResponseSet(Local<Name> name, Local<Value> value_obj,
                                   const PropertyCallbackInfo<Value>& info) {
  if (name->IsSymbol()) return;

  V8Handle* w = UnwrapV8HandleInstance(info.Holder());
  HTTPBody* body = new HTTPBody(w);

  Local<Object> body_map = body->WrapHTTPBodyMap();
  info.GetReturnValue().Set(body_map);
}


void HTTPBody::HTTPBodySet(Local<Name> name, Local<Value> value_obj,
                           const PropertyCallbackInfo<Value>& info) {
  if (name->IsSymbol()) return;

  string key = ObjectToString(Local<String>::Cast(name));
  string value = ToString(info.GetIsolate(), value_obj);

  map<string, string>* body = UnwrapMap(info.Holder());
  (*body)[key] = value;

  cout << "body field " << value << endl;
}


Currently I’m not hitting Set interceptor of “body” object, I suppose I’m doing something wrong here.

On 25-Jul-2016, at 10:00 PM, Jochen Eisinger <joc...@chromium.org> wrote:

Jochen Eisinger

unread,
Jul 27, 2016, 10:18:08 AM7/27/16
to v8-u...@googlegroups.com
Can you provide a complete example? I suspect that WrapHTTPBodyMap doesn't do what you expect it does

Abhishek Singh

unread,
Jul 27, 2016, 10:27:03 AM7/27/16
to v8-u...@googlegroups.com
Hi Jochen,

Full code of relevant file available - http://pastebin.com/fZJENvSi

Snippet of relevant portions for WrapHTTPBodyMap:

Local<ObjectTemplate> HTTPBody::MakeHTTPBodyMapTemplate(
    Isolate* isolate) {
  EscapableHandleScope handle_scope(isolate);

  Local<ObjectTemplate> result = ObjectTemplate::New(isolate);
  result->SetInternalFieldCount(1);
  result->SetHandler(NamedPropertyHandlerConfiguration(NULL,
                                                       HTTPBodySet));

  return handle_scope.Escape(result);
}

Local<Object> HTTPBody::WrapHTTPBodyMap() {
  EscapableHandleScope handle_scope(GetIsolate());

  if (http_body_map_template_.IsEmpty()) {
    Local<ObjectTemplate> raw_template = MakeHTTPBodyMapTemplate(GetIsolate());
    http_body_map_template_.Reset(GetIsolate(), raw_template);
  }
  Local<ObjectTemplate> templ =
      Local<ObjectTemplate>::New(GetIsolate(), http_body_map_template_);

  Local<Object> result =
      templ->NewInstance(GetIsolate()->GetCurrentContext()).ToLocalChecked();

  Local<External> map_ptr = External::New(GetIsolate(), &http_body);

  result->SetInternalField(0, map_ptr);

  return handle_scope.Escape(result);

Jochen Eisinger

unread,
Jul 28, 2016, 3:25:01 AM7/28/16
to v8-u...@googlegroups.com
I guess you should use function templates here.

Local<FunctionTemplate> body_map_template = FunctionTemplate::New(isolate);
body_map_template->InstanceTemplate()->SetHandler(...)
body_map_template->InstanceTemplate()->SetInternalFieldCount(1);
result = body_map_template->GetFunction()->NewInstance();

Abhishek Singh

unread,
Jul 28, 2016, 6:35:59 AM7/28/16
to v8-u...@googlegroups.com
I believe this is the change you wanted me to do:

Local<Object> HTTPBody::WrapHTTPBodyMap() {
  EscapableHandleScope handle_scope(GetIsolate());

  Local<FunctionTemplate> body_map_template = FunctionTemplate::New(GetIsolate());
  body_map_template->InstanceTemplate()->SetHandler(
          NamedPropertyHandlerConfiguration(NULL, HTTPBodySet));
  body_map_template->InstanceTemplate()->SetInternalFieldCount(1);
  Local<Object> result = body_map_template->GetFunction()->NewInstance();

  Local<External> map_ptr = External::New(GetIsolate(), &http_body);

  result->SetInternalField(0, map_ptr);

  return handle_scope.Escape(result);
}

This didn’t help. I’ll share a standalone program that simulates problem I see, maybe that would help you to see what the problem could be? Would be some bit of effort for me, but will do given it will be very useful to have nested c++ maps exposed to JS.

Abhishek Singh

unread,
Jul 28, 2016, 8:14:17 AM7/28/16
to v8-u...@googlegroups.com
Please find standalone code simulating your suggestion - https://gist.github.com/abhi-bit/d3a2910ec54a47ce8294c2cc0c4bef93 (In the comment pasted output in my case). Will appreciate if you could guide using this test script.

Jochen Eisinger

unread,
Jul 29, 2016, 2:34:36 AM7/29/16
to v8-u...@googlegroups.com
I commented on the example

Abhishek Singh

unread,
Jul 29, 2016, 3:01:13 AM7/29/16
to v8-u...@googlegroups.com
Thanks much, now things work as expected. Looking back, I think if I were thinking bit more openly it would have been an easy pattern to figure out. 
Reply all
Reply to author
Forward
0 new messages