I run the following JS code in the Chrome console:

// Version 67.0.3396.87 (Official Build) (64-bit)

var x = [1, 2, {"foo": 11}];
x[2].bar = x;

Now from C++ code, I get ahold of x as a Local<Object>, and wish to 
traverse the whole structure; for the sake of the example, let's say I am 
converting it into serialized data (I know I can use JSON.stringify() to do 
this, serializing is just an example to clarify ideas).  My question is, 
how can I keep track of the nodes in the structure  that I have already 
seen, and their associated serialized value, so that I can avoid an 
infinite traversal?

It seems to me doing this would require a way to get a unique identity for 
each node, so that the C++ code can do something similar to this:

typedef map<NodeId, NodeData> NodeMap;
NodeMap seen;
...
Local<Object> node = current.GetNextChild();
NodeId id = node.GetUniqueId();
NodeMap::iterator k = seen.find(id);
NodeData data;
if (k != seen.end()) {
    // node already seen, reuse its serialization
    data = k->first;
} else {
    // first time we see node, serialize and remember
    data = node.Serialize(); // recurses
    seen[id] = data;
}

The specific question is: what type could be NodeId, and how do I get the 
equivalent of GetUniqueId()?

I am very tempted to ask for a way to get a raw void* to each node, but I 
guess any way of doing this is fine, as long as I can get a unique id that 
is stable while I'm traversing the data.  For these reasons, 
GetIdentityHash() does not seem to fit the bill: "*The return value will 
never be 0. Also, it is not guaranteed to be unique.*"

Incidentally, If I try to use JSON.stringify for my data, I get this:

JSON.stringify(x)
VM170:1 Uncaught TypeError: Converting circular structure to JSON
    at JSON.stringify (<anonymous>)
    at <anonymous>:1:6

This is taken care of here in the V8 code:

JsonStringifier::Result JsonStringifier::StackPush(Handle<Object> object) {
...
    // member stack_ is: Handle<JSArray> stack_;
    int length = Smi::ToInt(stack_->length());
    FixedArray* elements = FixedArray::cast(stack_->elements());
    for (int i = 0; i < length; i++) {
        FixedArray* elements = FixedArray::cast(stack_->elements());
        if (elements->get(i) == *object) {
            // boom
        }
    }
}

So, operator*() in a Handle<Object> gives me a unique id? Which is the type 
for this? Can I store that in a C++ map? Is it stable (enough)?

Thanks!

-- 
-- 
v8-users mailing list
v8-users@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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to