Odette’s company uses a popular video conferencing solution for browser use. In the base library, there’s a handy-dandy class called ObjectStorage, which implements an in-memory key/value store entirely in TypeScript/JavaScript.

“Wait,” you ask, “isn’t a JavaScript in-memory, key/value store just… an object? A map, if you’re being pedantic?”

Yes, of course, but have you thought about ways to make JavaScript’s maps/objects worse?

export class ObjectStorage {
    private _storage: {
        [k: string]: any;
    } = {};

    private _counter = 0;

    public set(key: string, value: any): void {
        this._storage[key] = value;
    }

    public push(value: any): string {
        const key = this._getNextUniqueKey();
        this._storage[key] = value;
        return key;
    }

    public get(key: string): any {
        return this._storage[key];
    }

    public get keys(): string[] {
        return Object.keys(this._storage);
    }

    public get values(): any[] {
        return Object.values(this._storage);
    }

    private _getNextUniqueKey() {
        if (Object.keys(this._storage).includes(this._counter.toString())) {
            this._counter++;
            return this._getNextUniqueKey();
        }
        return (this._counter++).toString();
    }
}

So, yes, this does just wrap access to object fields in a set of methods: set, push, and get, with a handy-dandy little autonumber ID generator, _getNextUniqueKey. It’s not making anything significantly worse, but it’s hard to imagine how this makes anything better.

The clear flow, though it’s clearly not documented in the code, is that you store an object using push. push will return the key of the object, so get ready to remember that key someplace else in your application- maybe you should use an ObjectStorage to store the keys for your other ObjectStorage.

And how does that key get generated? We just increment a counter and convert it to a string. We’re at least smart enough to check that that key isn’t already in use, which at least avoids some disasters.

Of course, there’s no checks on set so it’s trivially easy to accidentally stomp on an existing key. This means that the calling code has to be very intentional about whether or not this is an insert or an update.

Which is to say: the whole push and set abstraction really doesn’t gain us anything. Yes, an autogenerated key is possible. But that’s strictly client side- if this is shipping objects to anyone else, there’s no way to avoid key collisions, so this ID can’t drive any API calls.

And that’s the core WTF: what is even the point of this object? It’s inconvenient and opaque methods wrapped around the same basic JavaScript object mangling that’s your standard process for web development.