1

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;
};
Xunie
  • 437
  • 4
  • 21
  • What happens when you try to transpile some iteration code? Can you show an example of something in C++ you want to convert to JS? – JohnFilleau Jun 15 '20 at 15:54
  • [this example](https://raw.githubusercontent.com/wiki/leaningtech/cheerp-meta/tutorials/hello_wasm/segmented_sieve.cpp) shows iteration using a for loop – JohnFilleau Jun 15 '20 at 15:58
  • You could use the [`__asm__`](https://github.com/leaningtech/cheerp-meta/wiki/JavaScript-interoperability#the-_asm_-keyword) feature of cheerp to accomplish this. You could probably also write a browser-side function to do this extraction and call that from C++. – cdhowie Jun 15 '20 at 16:10
  • Here's [an example](http://coliru.stacked-crooked.com/a/88cecd0bc5af41ee) of what I am trying to do. Please note that `items` in my example is only defined inside of the C++ memory model and is completely disconnected from the Javascript world. The example you linked does this: it never interfaces with any Javascript-native objects and merely 'emulates' the behavior of a `vector` (not a `map)`. --- I am trying to index an **external _Javascript-native_ Object** from within C++ using dynamic keys, much like how I would access a standard C++ `std::map`. – Xunie Jun 15 '20 at 16:17

1 Answers1

1

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"]);
  • `enumerateProperties()` takes in a `CustomItem*`. Is this correct? Shouldn't it take in a `client::Object*` instead? – Xunie Jun 15 '20 at 21:50
  • Speaking of dynamic situations: What if I index an object and the key is non-existent? Do I get `0` or do I get undefined behavior? – Xunie Jun 16 '20 at 14:50
  • 1
    I am not sure, I would expect the property would be created and mapped to an "undefined" object. But do not count on it. If you do not known that a property exist, you can first check calling obj->hasOwnProperty("itemA") to first verify the property exist, and only then indexing on it. – Carlo Piovesan Jun 16 '20 at 17:20