Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

JS: Event System

Event System

GObjects communicate only with events that carry a JSON key-value payload (kw). There is no direct method call. Every interaction goes through the event dispatcher of the finite state machine.

Source code: src/gobj.js, src/command_parser.js, src/stats_parser.js


gobj_send_event()

Sends an event to dst and runs the action of the current state immediately.

gobj_send_event(dst, event, kw, src)

Parameters

KeyTypeDescription
dstGObjThe destination gobj.
eventstringThe event name. The GClass must declare it in the state that is active.
kwobjectThe JSON payload of the event.
srcGObjThe gobj that sends the event.

Returns

The value that the action function returns. It returns -1 when the event is not defined in the current state.

Notes

Delivery is synchronous. When the call returns, the action ran to the end, together with every cascade that the action started. To send an event that must run after the current action returns, use gobj_post_event().

An event that the current state does not declare is an error, and the framework logs it. Do not add an empty action to make the message quiet. The message shows a bad state machine, or a sender that emits in the wrong situation.


gobj_post_event()

Puts an event in a queue for delivery on the next turn of the browser task queue. It is gobj_send_event() with the delivery delayed.

gobj_post_event(dst, event, kw, src)

Parameters

KeyTypeDescription
dstGObjThe destination gobj.
eventstringThe event name. The GClass of dst must declare it.
kwobjectThe JSON payload of the event.
srcGObjThe gobj that posts the message.

Returns

Returns 0 when the message goes into the queue. Returns -1 when the framework refuses it, and logs the cause: dst is not a gobj, dst is under destruction, the event name is empty, the GClass does not declare the event, or the queue holds MAX_POSTED_EVENTS (10000) messages already. The queue is not a work queue, and the limit protects that rule.

Notes

Use it to leave the stack that you stand on. gobj_publish_event() dispatches synchronously, so the action of a subscriber runs inside the stack of the publisher. To destroy or to stop that publisher there dismantles what is still in an iteration. Post the event instead, and do the work on the next turn.

The queue drains with setTimeout(…, 0), which is a macrotask. It does not drain with queueMicrotask(). A microtask runs before the browser paints or handles an input, so a chain of posted events holds the page. A macrotask gives the browser its turn between one event and the next.

Delivery is a snapshot per turn. The messages that are in the queue when a drain begins are the messages that the drain delivers. An event that an action posts while the drain runs waits for the next turn. A chain of messages that each post the next one advances one step per turn, and the browser keeps its turns.

gobj_destroy() takes the gobj out of the queue, and the two halves are different. As destination the framework drops the message. As source the framework only clears the pointer, because the destination still wants its event. That event arrives with src set to null, which every action must accept.

Do not use a C_TIMER of one millisecond for this. A deferral is not a time. Written as a time it costs a timer, a child gobj with its own start and stop, and the name of the event: every continuation arrives as EV_TIMEOUT, so the machine trace says “timeout” instead of what occurs. Use a timer when there is a real time to measure: a schedule, an inactivity window, or a backoff.

The C function takes three parameters, because there the gobj that posts is also the destination and the source. The JS function takes four, and the destination and the source are independent.


gobj_posted_events_size()

Gives the quantity of posted events that wait for delivery.

gobj_posted_events_size()

Returns

The quantity of messages in the queue, as a number.

Notes

Use it in a test to show that a queue is empty, or in a diagnostic. Application code must not make a decision from this value, because the value changes on every turn of the browser task queue.


gobj_deliver_posted_events()

Delivers the messages that are in the queue. One turn, one snapshot.

gobj_deliver_posted_events()

Returns

The quantity of messages that the function delivered. It does not count the messages of a gobj that went into destruction after the message went into the queue.

Notes

gobj_post_event() schedules this function automatically, so application code does not call it. Call it in a test, to deliver a queue immediately and to keep the test synchronous.

The function takes a snapshot of the queue, and it replaces the queue with an empty one before the first delivery. If the actions post new messages, the function schedules one more turn.


gobj_publish_event()

Sends an event to every gobj that has a subscription to it.

gobj_publish_event(publisher, event, kw)

Parameters

KeyTypeDescription
publisherGObjThe gobj that publishes the event.
eventstringThe event name. The GClass must declare it as an output event.
kwobjectThe JSON payload of the event.

Returns

The sum of the values that the actions of the subscribers returned. It is not the quantity of subscribers. To count the subscribers, use gobj_find_subscriptions().

Notes

Dispatch is synchronous, and it goes to one subscriber after the other. Never stop or destroy the tree of the publisher inside the action of a subscriber. Use gobj_post_event(), or set a flag and do the work from a timeout action.

When a subscriber is optional, mark the event with EVF_NO_WARN_SUBS in the event table. If you do not, the framework logs “Publish event WITHOUT subscribers” on every call.


gobj_subscribe_event()

Makes a subscription of subscriber to an event of publisher.

gobj_subscribe_event(publisher, event, kw, subscriber)

Parameters

KeyTypeDescription
publisherGObjThe gobj that publishes.
eventstringThe event name. Use null to subscribe to every output event.
kwobjectThe filter and the configuration of the subscription. Use {} to accept every payload.
subscriberGObjThe gobj that receives the event.

Returns

The subscription, as a JSON object.

Notes

A partial object in kw subscribes only to the events with a payload that matches those keys.

The kw accepts four configuration keys: __config__, __global__, __local__ and __filter__. See Subscription options.

Each GClass takes one of two subscription models, and writes the block in mt_create. A child gobj uses its parent when the subscriber attribute is empty. A service gobj subscribes only when the attribute holds a gobj.


gobj_unsubscribe_event()

Deletes a subscription.

gobj_unsubscribe_event(publisher, event, kw, subscriber)

Parameters

KeyTypeDescription
publisherGObjThe gobj that publishes.
eventstringThe event name of the subscription.
kwobjectThe filter that the subscription used.
subscriberGObjThe gobj that receives the event.

Returns

Returns 0 on success, or -1 when there is no subscription that matches.


gobj_unsubscribe_list()

Deletes every subscription of a list.

gobj_unsubscribe_list(gobj, dl_subs, force)

Parameters

KeyTypeDescription
gobjGObjThe gobj that owns the operation.
dl_subsarrayThe list of subscriptions, from gobj_find_subscriptions().
forcebooleanWhen it is true, the function also deletes the hard subscriptions.

Returns

Returns 0.


gobj_find_subscriptions()

Finds the subscriptions that a publisher holds.

gobj_find_subscriptions(publisher, event, kw, subscriber)

Parameters

KeyTypeDescription
publisherGObjThe gobj that publishes.
eventstringThe event name to match. Use null to match every event.
kwobjectThe filter to match. Use {} to match every subscription.
subscriberGObjThe subscriber to match. Use null to match every subscriber.

Returns

A list of the subscriptions that match.


gobj_find_subscribings()

Finds the subscriptions that a subscriber holds. It is the opposite direction of gobj_find_subscriptions().

gobj_find_subscribings(subscriber, event, kw, publisher)

Parameters

KeyTypeDescription
subscriberGObjThe gobj that receives the events.
eventstringThe event name to match. Use null to match every event.
kwobjectThe filter to match.
publisherGObjThe publisher to match. Use null to match every publisher.

Returns

A list of the subscriptions that match.


gobj_list_subscriptions()

Gives the subscriptions of a gobj in a form that a human reads.

gobj_list_subscriptions(gobj2view)

Parameters

KeyTypeDescription
gobj2viewGObjThe gobj to examine.

Returns

A list of JSON objects. Each object names the publisher, the subscriber and the event.


Subscription options

The kw of gobj_subscribe_event() accepts four keys that change the delivery. Every other key is a filter on the payload.

KeyDescription
__config__The options of the subscription. Put the two booleans below inside this object.
__config__.__hard_subscription__Keeps the subscription when a stop deletes the others.
__config__.__own_event__Stops the publication when the action of this subscriber returns a negative value, and gives that value to the publisher. The subscriber owns the event.
__global__A JSON object that the framework adds to the payload delivered to this subscriber.
__local__A JSON object. The framework removes its keys from the payload delivered to this subscriber. The values are not used.
__filter__A JSON object that the payload must match. The framework does not deliver the event when the payload does not match.

Which payload a subscriber gets. Since gobj-js 7.25.8 the rule is the same as in the C runtime (gobj_publish_event()):

Up to gobj-js 7.25.7 every subscriber got the same object, and __global__ and __local__ changed it. So one subscription changed the payload of every subscriber after it, and of the publisher.

gobj_subscribe_event(publisher, "EV_X", {__global__: {tag: "a"}}, subscriber_a);
gobj_subscribe_event(publisher, "EV_X", {__local__: {secret: 0}}, subscriber_b);
gobj_subscribe_event(publisher, "EV_X", {__filter__: {v: 1}}, subscriber_c);

gobj_publish_event(publisher, "EV_X", {v: 1, secret: "s"});
// subscriber_a gets {v: 1, secret: "s", tag: "a"}
// subscriber_b gets {v: 1}
// subscriber_c gets {v: 1, secret: "s"}, the object of the publisher
// the object of the publisher stays {v: 1, secret: "s"}

Commands and stats

gobj_command()

Runs a command of a gobj.

gobj_command(gobj, command, kw, src)

Parameters

KeyTypeDescription
gobjGObjThe gobj that holds the command.
commandstringThe command name, as the command table declares it.
kwobjectThe parameters of the command.
srcGObjThe gobj that asks for the command.

Returns

The response, as a JSON object with the keys result, comment, schema and data. Build it with build_command_response().

Notes

The command goes to the gclass’s own mt_command_parser method when it has one, and else, when the gclass has a command table (SDATACM), to the global parser of gobj_start_up(). A gclass with neither answers -1 “<gobj>: command table not available”. See Commands and statistics.

For a yuno of C_YUNO (as gui_agent and gui_treedb create it), whose mt_command_parser answers get-global-trace:

let r = gobj_command(gobj_yuno(), "get-global-trace", {}, gobj);
// r: {result: 0, comment: "", schema: {}, data: ["machine"]}     (the global levels that are set)

gobj_stats()

Reads the statistics of a gobj.

gobj_stats(gobj, stats, kw, src)

Parameters

KeyTypeDescription
gobjGObjThe gobj to examine.
statsstringThe name of the statistic. An empty string asks for every statistic.
kwobjectThe options of the operation.
srcGObjThe gobj that asks.

Returns

The response, as a JSON object. Build it with build_stats_response().


command_parser()

An empty stub, exported to fill the global_command_parser_fn slot of gobj_start_up(). It reads no command table, types no parameter and returns undefined: it is NOT a parser of commands as the C kernel’s command_parser() is. A gclass that answers its commands gives its own mt_command_parser method (see Commands and statistics).

command_parser(gobj, command, kw, src)

Returns

undefined.

gobj_command(gobj, "help", {}, src);
// a gclass with a command table and no mt_command_parser, started with
// command_parser as global_command_parser_fn: undefined, the command did nothing

stats_parser()

An empty stub, exported to fill the global_stats_parser_fn slot of gobj_start_up(). It reads no statistic and returns undefined. gobj_stats() asks the gclass’s own mt_stats method first, and this global parser only for a gclass without one; with no global parser it answers -1 “<gobj>, stats parser not available”.

stats_parser(gobj, stats, kw, src)

Returns

undefined.

gobj_stats(gobj, "", {}, src);
// a gclass with no mt_stats, started with stats_parser as global_stats_parser_fn: undefined

build_command_response()

Builds the JSON response of a command.

build_command_response(gobj, result, comment, schema, data)

Parameters

KeyTypeDescription
gobjGObjThe gobj that answers.
resultnumber0 on success, a negative number on failure.
commentstringA message for the operator.
schemaobjectThe description of the columns of data. Use null when there is none.
dataobjectThe payload of the response.

Returns

A JSON object with the four keys.


build_stats_response()

Builds the JSON response of a statistics request. It takes the same parameters as build_command_response().

build_stats_response(gobj, result, comment, schema, data)

Returns

A JSON object with the four keys.