How to iterate over dynamically named objects in Cheerp/js?

116 Views Asked by At

Cheerp is a C++ to js/wasm transpiler.

Using C++, I am able to interface with extern Javascript objects by statically defining a type and name of an object (and it's members).

Take the following object as an example:

var example1 = {
    "itemA" : {
        value : 3
    },
    "itemB" : {
        value : 1
    },
    "item3165942" : {
        value : 4
    }
}

It would be trivial to statically define example1 as a struct with itemA/itemB as sub-structs. But I would never be able to access example1["item3165942"].

How do I dynamically retrieve, index and iterate over a javascript object's keys/values from within C++? Assume that all items in example1 are the following type:

struct item_type {
    int32_t value;
};
1

There are 1 best solutions below

3
Carlo Piovesan On BEST ANSWER

IF you need to handle properties with unknown structure (= you do not known at compile time the structure of a JavaScript struct) you better iterate through its entries:

#include <cheerp/types.h>
#include <cheerp/client.h>

namespace client
{
        struct CustomItem : public Object
        {
                int get_value();
        };
}

void enumerateProperties(client::Object* obj)
{
        auto entries = client::Object::keys(obj);
        for (int i = 0; i<entries->get_length(); i++)
        {
                client::String* K = (client::String*)(*entries)[i];
                client::CustomItem* CI = (client::CustomItem*)((*obj)[*K]);
                client::console.log(*K, CI->get_value());
        }
}

Note that there are two casts that have to be explicitly made: specificying that entries are client::String*, and that the mapped items are of type (client::CustomItem*). You should also inside namespace client declare that CustomItem has a method get_value() (that will be compiled down to a javascript getter on the property named "value").

You can use the same pattern also to access properties through via ["itemA"], in this way:

client::CustomItem * CI = (client::CustomItem*)((*obj)["itemA"]);