Skip to content

No hydration for maps stored in arrays #16

@kevgug

Description

@kevgug

Failing tests

  • array_of_maps
  • map_size_in_array (getting any property, not just size, would also fail)

How to reproduce

runtime/tests/array_of_maps.js

const baseArray = [
    new Map([["a", 1], ["b", 2]]),
    new Map([["a", "3"], ["b", "4"]]),
    new Map([["a", 5]]),
];

function checkMapValueEquivalence({ map1, map2, test_ctx }) {
    console.log("map1", map1);
    console.log("map2", map2);
    if (map1.size !== map2.size) {
        throw new Error(
            `${test_ctx} different number of keys (${map1.size} !== ${map2.size})`,
        );
    }
    for (const [key, value] of map1) {
        console.log("key of map1", key);
        console.log("value of map1", value);
        if (!map2.has(key)) {
            throw new Error(`${test_ctx} key ${key} not found in map2 keys`);
        }
        if (map2.get(key) !== value) {
            console.log("map2.get(key)", map2.get(key));
            throw new Error(
                `${test_ctx} different values for key ${key} (${value} !== ${
                    map2.get(key)
                })`,
            );
        }
    }
}

{
    const object = {
        value: [...baseArray],
    };

    setRoot("test-root", object);
    commit();
}

{
    const root = getRoot("test-root");
    if (!root) {
        throw new Error("root should exist");
    }
    if (!root.value) {
        throw new Error("root.value should exist");
    }
    if (root.value.length !== baseArray.length) {
        throw new Error(`root.value should have length ${baseArray.length}`);
    }
    for (let i = 0; i < root.value.length; i++) {
        checkMapValueEquivalence({
            map1: root.value[i],
            map2: baseArray[i],
            test_ctx: "first getRoot after commit",
        });
    }
}

Run the test

In runtime/src/tests.rs run the single test js_test!(array_of_maps);

Terminal output

map1 CloudstateMapReference {
  objectId: "9cbe9dc6-64c9-4b17-a7c1-7df6f5f24b27"
}
map2 Map(2) { "a" => 1, "b" => 2 }

Expected output

map1 Map(2) { "a" => 1, "b" => 2 }
map2 Map(2) { "a" => 1, "b" => 2 }

What I think the issue is

In runtime/src/extensions/cloudstate.js, the hydrate method is called to correctly hydrate the CloudstateArrayReference (which contains a single CloudstateMapReference). But in

Object.defineProperty(object, key, {
    value: this.getArray(value.objectId),
});

the method getArray() doesn't recursively hydrate its elements.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions