Options
All
  • Public
  • Public/Protected
  • All
Menu

Module awcp/msgq

Message Queue (Block-on-recieve (receive? raseev.)) implementation

This implementation is specialized to this specific application, but the idea can work in general.

Originally, this was implemented as the Skylight logic. I wanted to factor out the "message queue" and "block on recieve" functionality from the actual core skylight logic

Quoth The Dear Founder explaining this ridiculous program structure

Working out dumdum js pointer/messaging logic

the skylight is the thing that sidekick uses to talk to superhero

so the skylight needs to black-box away some internal state. a process is the ideal abstraction to deal with this, but we live in hell so we get to use objects instead.

the first thing the skylight needs to do is let superhero announce itself and record that it has talked to superhero

JS doesn't have "block on recieve" or anything like that so i thought that I would basically do this

class Skylight
{
listen()
{
window.addListener('message', this.listener);
}

ignore()
{
window.removeListener('message', this.listener);
}

listener(msg)
{
this.do_something_with(msg);
}
}

Of course that doesn't work because we live in hell. basically here was the problem: listener() gets executed IN THE CONTEXT OF THE WINDOW despite this being an instance method

so I was getting an error message like "this.do_something_with is not callable". Note that I was NOT getting the error message "this does not have property do_something_with" (which is what the error would be in say Python). Noooooo

instead I was confused for a solid few minutes because I kept saying "yes this does, what are you talking about" and thinking I had made a typo somewhere.

alas, no, my error was not a typo. my error was assuming that javascript behaved in a way that makes sense. which is usually the problem.

note that we CAN'T just do this

listener(skylight, msg)
{
skylight.do_something_with(msg);
}

class Skylight
{
listen()
{
window.addListener('message', (msg) => listener(this, msg));
}

ignore()
{
window.removeListener('message', (msg) => listener(this, msg));
}

}

for two reasons:

  1. if you add an inline lambda as a listener, you can't remove it, so ignore() wouldn't work. because the javascript gods record the POINTER to the function, and so the two inline lambdas, despite being identical code, point to different memory locations.

    Quoth https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

    Note: If a particular anonymous function is in the list of event listeners registered for a certain target, and then later in the code, an identical anonymous function is given in an addEventListener call, the second function will also be added to the list of event listeners for that target.

    Indeed, anonymous functions are not identical even if defined using the same unchanging source-code called repeatedly, even if in a loop.

    Repeatedly defining the same unnamed function in such cases can be problematic. (See Memory issues, below.)

  2. there's a second layer of jogritude to this, which is that, again, the function is executed IN THE CONTEXT OF THE WINDOW. This isn't really jogritude. On the contrary, this is a rare example of javascript behaving in a way that makes at least kind of a little bit of sense.

    this in JS is a bit like self/0 in Erlang.

So in order to work around all of this, I came up with the following basic logic:

listener(skylight, msg)
{
skylight.do_something_with(msg);
}

class Skylight
{
constructor()
{
// grab pointer to this using hack
const pointer_to_this = this;
this.ls =
function(evt)
{
listener(pointer_to_this, evt);
}
}

listen()
{
window.addListener('message', this.ls);
}

ignore()
{
window.removeListener('message', this.ls);
}

}

and this seems to work

still dumb but whatever

Everything that isn't Erlang is wrong

Bye

The Founder loves you

Important to remember that TypeScript is structurally typed: which means that the type system provides some degree of guarantee that some field exists, but the type is not necessarily exhaustive.

Index

Classes

Type aliases

Functions

Type aliases

WindowMsg_W2A: { data: { method: string }; type: "to_waellet" | "to_aepp" }

Type declaration

  • data: { method: string }
    • method: string
  • type: "to_waellet" | "to_aepp"

Functions

Generated using TypeDoc