Search code examples
javascriptc++llvmcheerp

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


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;
};

Solution

  • 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"]);