JSSM, a JavaScript state machine - the FSM for FSL
    Preparing search index...

    Class Machine<mDT>

    Type Parameters

    • mDT
    Index
    _action_interner _actions _active_state_style _after_any_hook _after_hooks _after_mapping _allow_islands _any_action_hook _any_transition_hook _arrange_declaration _arrange_end_declaration _arrange_start_declaration _boundary_depth _boundary_depth_limit _clear_timeout_source _code_allows_override _committing_transition _config_allows_override _create_started _created _data? _default_graph_config _default_properties _default_size? _default_transition_config _dot_preamble _edge_id_by_action_pair _edge_id_by_pair _edge_map _edge_to_ids _edges _editor_config? _end_state_style _end_states _entry_hooks _event_handlers _event_listener_count _everything_hook _exit_hooks _failed_outputs _farrange_declaration _firing_error _flow _forced_transition_hook _fsl_version? _global_action_hooks _graph_layout _group_hooks _group_metadata _group_order _group_registry _has_after_hooks _has_basic_hooks _has_entry_hooks _has_exit_hooks _has_forced_transitions _has_global_action_hooks _has_hooks _has_named_hooks _has_post_basic_hooks _has_post_entry_hooks _has_post_exit_hooks _has_post_global_action_hooks _has_post_hooks _has_post_named_hooks _has_post_transition_hooks _has_transition_hooks _history _history_length _hooked_state_style _hooks _instance_name _machine_author? _machine_comment? _machine_contributor? _machine_definition? _machine_language? _machine_license? _machine_name? _machine_version? _main_transition_hook _named_hooks _named_transitions _npm_name? _oarrange_declaration _outbound_edge_ids _post_any_action_hook _post_any_transition_hook _post_entry_hooks _post_everything_hook _post_exit_hooks _post_forced_transition_hook _post_global_action_hooks _post_hooks _post_main_transition_hook _post_named_hooks _post_standard_transition_hook _pre_everything_hook _pre_post_everything_hook _property_keys _raw_state_declaration? _required_properties _reverse_action_targets _reverse_actions _rng _rng_seed _standard_transition_hook _start_state_style _start_states _state _state_declarations _state_hooks _state_id _state_interner _state_labels _state_properties _state_property_first_state _state_style _state_to_groups _states _static_state_config_cache _terminal_state_style _themes _time_source _timeout_handle _timeout_source _timeout_target _timeout_target_time
    _fire action actions all_action_label_chars all_state_name_chars all_state_name_first_chars all_themes auto_set_state_timeout clear_state_timeout current_action_edge_for current_action_for current_state_timeout data default_graph_config default_size default_transition_config display_text do dot_preamble edges_between editor_config failed_outputs flow force_transition fsl_version get_transition_by_state_names go graph_layout groups groupsOf has_completes has_hook has_state has_terminals has_unenterables hook hook_action hook_after hook_after_any hook_any_action hook_any_transition hook_entry hook_everything hook_exit hook_forced_transition hook_global_action hook_main_transition hook_post_everything hook_pre_everything hook_pre_post_everything hook_registry hook_standard_transition hooks_on instance_name is_complete is_end_state is_failed is_failed_output is_final is_start_state is_terminal is_unenterable isIn known_prop known_props label_for list_actions list_edges list_entrances list_exit_actions list_exits list_named_transitions list_states_having_action list_transitions lookup_transition_for machine_author machine_comment machine_contributor machine_definition machine_language machine_license machine_name machine_state machine_version npm_name off on once override post_hook post_hook_action post_hook_any_action post_hook_any_transition post_hook_entry post_hook_exit post_hook_forced_transition post_hook_global_action post_hook_main_transition post_hook_standard_transition probabilistic_histo_walk probabilistic_transition probabilistic_walk probable_action_exits probable_exits_for prop props raw_state_declarations remove_hook resolve_state_config serialize set_data set_hook set_state_timeout sm state state_declaration state_declarations state_for state_has_hooks state_is_complete state_is_final state_is_terminal state_timeout_for states statesIn stochastic_runs stochastic_summary strict_prop style_for transition valid_action valid_force_transition valid_transition
    _action_interner: Interner
    _actions: Map<string, Map<string, number>>
    _active_state_style: JssmStateConfig
    _after_any_hook: HookHandler<mDT>
    _after_hooks: Map<string, HookHandler<mDT>>
    _after_mapping: Map<string, [string, number]>
    _allow_islands: JssmAllowIslands
    _any_action_hook: HookHandler<mDT>
    _any_transition_hook: HookHandler<mDT>
    _arrange_declaration: string[][]
    _arrange_end_declaration: string[][]
    _arrange_start_declaration: string[][]
    _boundary_depth: number
    _boundary_depth_limit: number
    _clear_timeout_source: (h: number) => void
    _code_allows_override: JssmAllowsOverride
    _committing_transition: boolean
    _config_allows_override: JssmAllowsOverride
    _create_started: number
    _created: number
    _data?: mDT
    _default_graph_config: JssmGraphConfig
    _default_properties: Map<string, any>
    _default_size?: JssmDefaultSize
    _default_transition_config: JssmTransitionConfig
    _dot_preamble: string
    _edge_id_by_action_pair: Map<number, number>
    _edge_id_by_pair: Map<number, number>
    _edge_map: Map<string, Map<string, number>>
    _edge_to_ids: number[]
    _edges: JssmTransition<string, mDT>[]
    _editor_config?: JssmEditorConfig
    _end_state_style: JssmStateConfig
    _end_states: Set<string>

    _entry_hooks

    _entry_hooks: Map<number, HookHandler<mDT>>
    _event_handlers: Map<JssmEventName, Set<JssmEventEntry<any, any>>>
    _event_listener_count: number
    _everything_hook: EverythingHookHandler<mDT>
    _exit_hooks: Map<number, HookHandler<mDT>>
    _failed_outputs: Set<string>
    _farrange_declaration: string[][]
    _firing_error: boolean
    _flow: "left" | "right" | "up" | "down"
    _forced_transition_hook: HookHandler<mDT>
    _fsl_version?: JssmParsedSemver
    _global_action_hooks: Map<number, HookHandler<mDT>>
    _graph_layout: JssmLayout
    _group_hooks: JssmGroupHooks
    _group_metadata: Map<string, Partial<JssmStateDeclaration>>
    _group_order: string[]
    _group_registry: JssmGroupRegistry
    _has_after_hooks: boolean
    _has_basic_hooks: boolean

    _has_entry_hooks

    _has_entry_hooks: boolean
    _has_exit_hooks: boolean
    _has_forced_transitions: boolean
    _has_global_action_hooks: boolean
    _has_hooks: boolean
    _has_named_hooks: boolean

    _has_post_basic_hooks

    _has_post_basic_hooks: boolean

    _has_post_entry_hooks

    _has_post_entry_hooks: boolean

    _has_post_exit_hooks

    _has_post_exit_hooks: boolean

    _has_post_global_action_hooks

    _has_post_global_action_hooks: boolean

    _has_post_hooks

    _has_post_hooks: boolean

    _has_post_named_hooks

    _has_post_named_hooks: boolean

    _has_post_transition_hooks

    _has_post_transition_hooks: boolean
    _has_transition_hooks: boolean
    _history: JssmHistory<mDT>
    _history_length: number
    _hooked_state_style: JssmStateConfig
    _hooks: Map<number, HookHandler<mDT>>
    _instance_name: string
    _machine_author?: string[]
    _machine_comment?: string
    _machine_contributor?: string[]
    _machine_definition?: string
    _machine_language?: string
    _machine_license?: string
    _machine_name?: string
    _machine_version?: JssmParsedSemver
    _main_transition_hook: HookHandler<mDT>
    _named_hooks: Map<number, Map<number, HookHandler<mDT>>>
    _named_transitions: Map<string, number>
    _npm_name?: string
    _oarrange_declaration: string[][]
    _outbound_edge_ids: Map<string, number[]>

    _post_any_action_hook

    _post_any_action_hook: HookHandler<mDT>

    _post_any_transition_hook

    _post_any_transition_hook: HookHandler<mDT>

    _post_entry_hooks

    _post_entry_hooks: Map<number, HookHandler<mDT>>

    _post_everything_hook

    _post_everything_hook: PostEverythingHookHandler<mDT>

    _post_exit_hooks

    _post_exit_hooks: Map<number, HookHandler<mDT>>

    _post_forced_transition_hook

    _post_forced_transition_hook: HookHandler<mDT>

    _post_global_action_hooks

    _post_global_action_hooks: Map<number, HookHandler<mDT>>

    _post_hooks

    _post_hooks: Map<number, HookHandler<mDT>>

    _post_main_transition_hook

    _post_main_transition_hook: HookHandler<mDT>

    _post_named_hooks

    _post_named_hooks: Map<number, Map<number, HookHandler<mDT>>>

    _post_standard_transition_hook

    _post_standard_transition_hook: HookHandler<mDT>
    _pre_everything_hook: EverythingHookHandler<mDT>

    _pre_post_everything_hook

    _pre_post_everything_hook: PostEverythingHookHandler<mDT>
    _property_keys: Set<string>
    _raw_state_declaration?: object[]
    _required_properties: Set<string>
    _reverse_action_targets: Map<string, Map<string, number>>
    _reverse_actions: Map<string, Map<string, number>>
    _rng: JssmRng
    _rng_seed: number
    _standard_transition_hook: HookHandler<mDT>
    _start_state_style: JssmStateConfig
    _start_states: Set<string>
    _state: string
    _state_declarations: Map<string, JssmStateDeclaration>
    _state_hooks: JssmStateHooks
    _state_id: number
    _state_interner: Interner
    _state_labels: Map<string, string>
    _state_properties: Map<string, any>
    _state_property_first_state: Map<string, string>
    _state_style: JssmStateConfig
    _state_to_groups: Map<string, Set<string>>
    _states: Map<string, JssmGenericState>
    _static_state_config_cache: Map<string, Partial<JssmStateDeclaration>>
    _terminal_state_style: JssmStateConfig
    _themes: ("plain" | "default" | "ocean" | "modern" | "bold")[]
    _time_source: () => number
    _timeout_handle: number
    _timeout_source: (f: () => void, a: number) => number
    _timeout_target: string
    _timeout_target_time: number
    • get active_state_style(): JssmStateConfig

      Get the style for the active state. Does not include composition from an applied theme, or things from the underlying base stylesheet; only the modifications applied by this machine.

      const light = sm`a -> b;`;
      console.log(light.active_state_style);
      // {}

      const light = sm`a -> b; active_state: { shape: circle; };`;
      console.log(light.active_state_style);
      // { shape: 'circle' }

      Returns JssmStateConfig

      The JssmStateConfig for the active state.

    • get allow_islands(): JssmAllowIslands

      Return the effective island policy for this machine. true means disconnected components are allowed (the default), false requires a single connected component, and 'with_start' allows islands only when every component contains at least one start state.

      Returns JssmAllowIslands

      The island policy stored in the machine.

    • get allows_override(): JssmAllowsOverride

      Check if a machine allows overriding state and data. Resolves the combined effect of code and config permissions — config may not be less strict than code.

      Returns JssmAllowsOverride

      The effective override permission.

    • get create_start_time(): number

      Get the timestamp when construction began (before parsing).

      Returns number

      The start-of-construction timestamp as a number.

    • get creation_date(): Date

      Get the creation date of this machine as a Date object.

      Returns Date

      A Date representing when the machine was created.

    • get creation_timestamp(): number

      Get the creation timestamp (milliseconds since epoch).

      Returns number

      The timestamp as a number.

    • get end_state_style(): JssmStateConfig

      Get the end state style. Does not include composition from an applied theme, or things from the underlying base stylesheet; only the modifications applied by this machine.

      End states are defined in the directive end_states, and are distinct from terminal states. End states are voluntary successful endpoints for a process. Terminal states are states that cannot be exited. By example, most error states are terminal states, but not end states. Also, since some end states can be exited and are determined by hooks, such as recursive or iterative nodes, there is such a thing as an end state that is not a terminal state.

      const light = sm`a -> b;`;
      console.log(light.standard_state_style);
      // {}

      const light = sm`a -> b; end_state: { shape: circle; };`;
      console.log(light.standard_state_style);
      // { shape: 'circle' }

      Returns JssmStateConfig

      The JssmStateConfig for end states.

    • get history(): [string, mDT][]

      Get a truncated history of the recent states and data of the machine. Turned off by default; configure with .from('...', {data: 5}) by length, or set .history_length at runtime.

      History does not contain the current state. If you want that, call .history_inclusive instead.

      const foo = jssm.from(
      "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
      { history: 3 }
      );

      foo.action('next');
      foo.action('next');
      foo.action('next');
      foo.action('next');

      foo.history; // [ ['b',undefined], ['c',undefined], ['d',undefined] ]

      Notice that the machine's current state, e, is not in the returned list.

      Returns [string, mDT][]

    • get history_inclusive(): [string, mDT][]

      Get a truncated history of the recent states and data of the machine, including the current state. Turned off by default; configure with .from('...', {data: 5}) by length, or set .history_length at runtime.

      History inclusive contains the current state. If you only want past states, call .history instead.

      The list returned will be one longer than the history buffer kept, as the history buffer kept gets the current state added to it to produce this list.

      const foo = jssm.from(
      "a 'next' -> b 'next' -> c 'next' -> d 'next' -> e;",
      { history: 3 }
      );

      foo.action('next');
      foo.action('next');
      foo.action('next');
      foo.action('next');

      foo.history_inclusive; // [ ['b',undefined], ['c',undefined], ['d',undefined], ['e',undefined] ]

      Notice that the machine's current state, e, is in the returned list.

      Returns [string, mDT][]

    • get history_length(): number

      Find out how long a history this machine is keeping. Defaults to zero. Settable directly.

      const foo = jssm.from("a -> b;");
      foo.history_length; // 0

      const bar = jssm.from("a -> b;", { history: 3 });
      foo.history_length; // 3
      foo.history_length = 5;
      foo.history_length; // 5

      Returns number

    • set history_length(to: number): void

      Parameters

      • to: number

      Returns void

    • get hooked_state_style(): JssmStateConfig

      Get the hooked state style. Does not include composition from an applied theme, or things from the underlying base stylesheet; only the modifications applied by this machine.

      The hooked style is only applied to nodes which have a named hook in the graph. Open hooks set through the external API aren't graphed, because that would be literally every node.

      const light = sm`a -> b;`;
      console.log(light.hooked_state_style);
      // {}

      const light = sm`a -> b; hooked_state: { shape: circle; };`;
      console.log(light.hooked_state_style);
      // { shape: 'circle' }

      Returns JssmStateConfig

      The JssmStateConfig for hooked states.

    • get rng_seed(): number

      Get the current RNG seed used for probabilistic transitions.

      Returns number

      The numeric seed value.

    • set rng_seed(to: number): void

      Set the RNG seed. Pass undefined to reseed from the current time. Resets the internal PRNG so subsequent probabilistic operations use the new seed.

      Parameters

      • to: number

        The seed value, or undefined for time-based seeding.

      Returns void

    • get standard_state_style(): JssmStateConfig

      Get the standard style for a single state. Does not include composition from an applied theme, or things from the underlying base stylesheet; only the modifications applied by this machine.

      const light = sm`a -> b;`;
      console.log(light.standard_state_style);
      // {}

      const light = sm`a -> b; state: { shape: circle; };`;
      console.log(light.standard_state_style);
      // { shape: 'circle' }

      Returns JssmStateConfig

      The JssmStateConfig for standard states.

    • get start_state_style(): JssmStateConfig

      Get the start state style. Does not include composition from an applied theme, or things from the underlying base stylesheet; only the modifications applied by this machine.

      Start states are defined by the directive start_states, or in absentia, are the first mentioned state.

      const light = sm`a -> b;`;
      console.log(light.start_state_style);
      // {}

      const light = sm`a -> b; start_state: { shape: circle; };`;
      console.log(light.start_state_style);
      // { shape: 'circle' }

      Returns JssmStateConfig

      The JssmStateConfig for start states.

    • get terminal_state_style(): JssmStateConfig

      Get the terminal state style. Does not include composition from an applied theme, or things from the underlying base stylesheet; only the modifications applied by this machine.

      Terminal state styles are automatically determined by the machine. Any state without a valid exit transition is terminal.

      const light = sm`a -> b;`;
      console.log(light.terminal_state_style);
      // {}

      const light = sm`a -> b; terminal_state: { shape: circle; };`;
      console.log(light.terminal_state_style);
      // { shape: 'circle' }

      Returns JssmStateConfig

      The JssmStateConfig for terminal states.

    • get themes(): | "plain"
      | "default"
      | "ocean"
      | "modern"
      | "bold"
      | ("plain" | "default" | "ocean" | "modern" | "bold")[]

      Get the active theme(s) for this machine. Always stored as an array internally; the union return type exists for setter compatibility.

      Returns
          | "plain"
          | "default"
          | "ocean"
          | "modern"
          | "bold"
          | ("plain" | "default" | "ocean" | "modern" | "bold")[]

      The current theme or array of themes.

    • set themes(
          to:
              | "plain"
              | "default"
              | "ocean"
              | "modern"
              | "bold"
              | ("plain" | "default" | "ocean" | "modern" | "bold")[],
      ): void

      Set the active theme(s). Accepts a single theme name or an array. Also drops every memoized static state config, so styles resolved before the change re-resolve under the new theme stack.

      const m = sm`a -> b;`;
      m.style_for('b'); // resolved under the default theme
      m.themes = 'ocean';
      m.style_for('b').backgroundColor; // 'cadetblue1' — ocean, not a stale default

      Parameters

      • to:
            | "plain"
            | "default"
            | "ocean"
            | "modern"
            | "bold"
            | ("plain" | "default" | "ocean" | "modern" | "bold")[]

        A theme name or array of theme names to apply.

      Returns void

      resolve_state_config

    • get uses_actions(): boolean

      Whether any actions are defined on this machine.

      Returns boolean

      true if the machine has at least one action.

    • get uses_forced_transitions(): boolean

      Whether any forced (~>) transitions exist in this machine.

      Returns boolean

      true if at least one forced transition is defined.


    • Instruct the machine to complete an action. Synonym for do.

      const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;

      light.state(); // 'red'
      light.action('next'); // true
      light.state(); // 'green'

      Parameters

      • actionName: string

        The action to engage

      • OptionalnewData: mDT

        The data change to insert during the action

      Returns boolean

      true if the action was valid and the transition occurred, false otherwise.


    • List all actions available from this state. Please note that the order of the actions is not guaranteed.

      import { sm } from 'jssm';

      const machine = sm`
      red 'next' -> green 'next' -> yellow 'next' -> red;
      [red yellow green] 'shutdown' ~> off 'start' -> red;
      `;

      console.log( machine.state() ); // logs 'red'
      console.log( machine.actions() ); // logs ['next', 'shutdown']

      machine.action('next'); // true
      console.log( machine.state() ); // logs 'green'
      console.log( machine.actions() ); // logs ['next', 'shutdown']

      machine.action('shutdown'); // true
      console.log( machine.state() ); // logs 'off'
      console.log( machine.actions() ); // logs ['start']

      machine.action('start'); // true
      console.log( machine.state() ); // logs 'red'
      console.log( machine.actions() ); // logs ['next', 'shutdown']

      Parameters

      • whichState: string = ...

        The state whose actions to list. Defaults to the current state.

      Returns string[]

      An array of action names available from the given state.

    • List the character ranges accepted inside a single-quoted FSL action label without escaping. Space is allowed; the apostrophe ' is explicitly excluded since it terminates the label.

      Returns readonly { from: string; to: string }[]

      An array of {from, to} inclusive character ranges.

      import { sm } from 'jssm';
      const m = sm`a -> b;`;
      m.all_action_label_chars().some(r => ' ' >= r.from && ' ' <= r.to); // => true
      m.all_action_label_chars().some(r => "'" >= r.from && "'" <= r.to); // => false
    • List the character ranges accepted by the FSL grammar in any but the first position of a state name (atom). Each entry is an inclusive {from, to} range of single Unicode characters.

      Returns readonly { from: string; to: string }[]

      An array of {from, to} inclusive character ranges.

      import { sm } from 'jssm';
      const m = sm`a -> b;`;
      m.all_state_name_chars().some(r => '+' >= r.from && '+' <= r.to); // => true
    • List the character ranges accepted by the FSL grammar in the first position of a state name (atom). Narrower than all_state_name_chars: notably omits +, (, ), &, #, @.

      Returns readonly { from: string; to: string }[]

      An array of {from, to} inclusive character ranges.

      import { sm } from 'jssm';
      const m = sm`a -> b;`;
      m.all_state_name_first_chars().some(r => '+' >= r.from && '+' <= r.to); // => false
    • List all available theme names.

      Returns ("plain" | "default" | "ocean" | "modern" | "bold")[]

      An array of theme name strings.

    • If the current state has an after timeout configured, schedule it. Called internally after each transition.

      Returns void

    • Cancel any pending state timeout. Safe to call when no timeout is active.

      Returns void

    • Get the full transition object for an action from the current state.

      Parameters

      • action: string

        The action name.

      Returns JssmTransition<string, mDT>

      The JssmTransition object.

      If the action is not available from the current state.

    • Get the edge index for an action from the current state. Interned dispatch: resolves via the numeric (action, from) index — unknown action names miss without throwing.

      Parameters

      • action: string

        The action name.

      Returns number

      The edge index, or undefined if the action is not available.

    • Get the configured after timeout for the current state, if any.

      Returns [string, number]

      A [targetState, delayMs] tuple, or undefined.


    • Get the current data of a machine.

      import * as jssm from 'jssm';

      const lswitch = jssm.from('on <=> off;', {data: 1});
      console.log( lswitch.data() ); // 1

      Returns mDT

      A deep clone of the machine's current data value.

    • Get the consolidated graph: {} default-config block: the ordered, de-duplicated { key, value }[] list of graph-scope style items. The compiler folds the deprecated top-level graph keywords (graph_bg_color → background-color, plus graph_layout, theme, flow, dot_preamble) into this list first, then lets an explicit graph: {} block win on key conflict. The viz layer projects the graph-meaningful keys onto graph-scope Graphviz attributes (e.g. background-color → bgcolor).

      import { sm } from 'jssm';
      sm`a -> b; graph: { background-color: #ffffff; };`.default_graph_config();
      // [ { key: 'background-color', value: '#ffffffff' } ]

      Returns JssmGraphConfig

      The graph-config item list, or undefined if the machine has no graph config (no graph: {} block and no deprecated graph keyword).

      default_transition_config

    • Get the render-size hint for the machine's visualization. Set via the FSL default_size directive. Returns undefined when not present.

      The three FSL forms each produce a different subset of fields:

      • default_size: 800; → { width: 800 }
      • default_size: 800 600; → { width: 800, height: 600 }
      • default_size: height 600; → { height: 600 }

      This is a hint, not a hard constraint. Renderers may ignore it.

      Returns JssmDefaultSize

      The size-hint object, or undefined if not set.

      npm_name

    • Get the consolidated transition: {} default-config block: the ordered, de-duplicated { key, value }[] list of edge-default style items compiled from a transition: {} block (e.g. transition: { color: blue; }). The viz layer projects this onto a Graphviz edge [ … ] default statement so every edge inherits it.

      import { sm } from 'jssm';
      sm`a -> b; transition: { color: blue; };`.default_transition_config();
      // [ { key: 'color', value: '#0000ffff' } ]

      Returns JssmTransitionConfig

      The transition-config item list, or undefined if the machine declared no transition: {} block.

      default_graph_config


    • Get whatever the node should show as text.

      Currently, this means to get the label for a given state, if any; otherwise to return the node's name. However, this definition is expected to grow with time, and it is currently considered ill-advised to manually parse this text.

      See also label_for.

      import * as jssm from 'jssm';

      const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
      console.log( lswitch.display_text('a') ); // 'Foo!'
      console.log( lswitch.display_text('b') ); // 'b'

      Parameters

      • state: string

        The state to get display text for.

      Returns string

      The label if one exists, otherwise the state's name.


    • Instruct the machine to complete an action. Synonym for action.

      const light = sm`
      off 'start' -> red;
      red 'next' -> green 'next' -> yellow 'next' -> red;
      [red yellow green] 'shutdown' ~> off;
      `;

      light.state(); // 'off'
      light.do('start'); // true
      light.state(); // 'red'
      light.do('next'); // true
      light.state(); // 'green'
      light.do('next'); // true
      light.state(); // 'yellow'
      light.do('dance'); // !! false - no such action
      light.state(); // 'yellow'
      light.do('start'); // !! false - yellow does not have the action start
      light.state(); // 'yellow'

      Parameters

      • actionName: string

        The action to engage

      • OptionalnewData: mDT

        The data change to insert during the action

      Returns boolean

      true if the action was valid and the transition occurred, false otherwise.

    • Get the Graphviz DOT preamble string, injected before the graph body during visualization. Set via the FSL dot_preamble directive.

      Returns string

      The preamble string.

    • Get all edges between two states (there can be multiple with different actions).

      Parameters

      • from: string

        Source state name.

      • to: string

        Target state name.

      Returns JssmTransition<string, mDT>[]

      An array of matching JssmTransition objects.

    • The editor/panel defaults declared in the FSL editor: {} block, or undefined when none was given. Read by the all-widgets web control (fsl#1334) — panels drives request panel mode.

      Returns JssmEditorConfig

      { stochastic_run_count?, panels? }, or undefined.

      const m = sm`editor: { panels: [history]; }; a -> b;`;
      m.editor_config(); // => { panels: ['history'] }

    • Get the set of states declared as failure outputs for this machine. Returns an array of state labels, or an empty array when none were declared. A state in this list means the machine is in a failure condition when it occupies that state.

      Returns string[]

    • Get the flow direction for graph layout (e.g. 'right', 'down'). Set via the FSL flow directive.

      Returns "left" | "right" | "up" | "down"

      The current flow direction.


    • Instruct the machine to complete a forced transition (which will reject if called with a normal transition call.)

      const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;

      light.state(); // 'red'
      light.transition('off'); // false
      light.state(); // 'red'
      light.force_transition('off'); // true
      light.state(); // 'off'

      Parameters

      • newState: string

        The state to switch to

      • OptionalnewData: mDT

        The data change to insert during the transition

      Returns boolean

      true if a transition (forced or otherwise) existed and occurred, false otherwise.

    • Get the FSL language version this machine declares, parsed. Set via the FSL fsl_version directive, which takes a semver triple; the parser breaks it into numeric major/minor/patch fields and keeps the exact source text in full. Returns undefined when the directive was not given.

      Returns JssmParsedSemver

      The parsed JssmParsedSemver, or undefined if unset.

      const m = sm`fsl_version: 1.0.0; a -> b;`;
      m.fsl_version(); // => { major: 1, minor: 0, patch: 0, full: '1.0.0' }

      machine_version

    • Look up a transition's edge index by source and target state names.

      Parameters

      • from: string

        Source state name.

      • to: string

        Target state name.

      Returns number

      The edge index in the edges array, or undefined if no such transition exists.


    • Instruct the machine to complete a transition. Synonym for transition.

      const light = sm`red -> green -> yellow -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;

      light.state(); // 'red'
      light.go('green'); // true
      light.state(); // 'green'

      Parameters

      • newState: string

        The state to switch to

      • OptionalnewData: mDT

        The data change to insert during the transition

      Returns boolean

      true if the transition was legal and occurred, false otherwise.

    • Get the graph layout direction (e.g. 'LR', 'TB'). Set via the FSL graph_layout directive.

      Returns string

      The layout string, or the default if not set.


    • Lists all declared group names, in source declaration order. The order matches the order the &group : [ … ]; declarations appear in the FSL, and is the same order used to break depth-specificity ties in the config cascade. Machines that declare no groups return an empty array.

      import { sm } from 'jssm';

      const m = sm`&first : [a]; &second : [b]; a -> b;`;
      m.groups(); // [ 'first', 'second' ]

      Returns string[]

      The declared group names, in declaration order.

      • groupsOf
      • statesIn

    • Lists every group that transitively contains a given state. Membership is deep — direct, nested, and spread sub-group containment all count — and the result is the precomputed inverse-index entry for the state, so the lookup is constant-time. A state that belongs to no group (or a state name that appears in no group) yields an empty Set.

      import { sm } from 'jssm';

      const m = sm`&inner : [a]; &outer : [&inner b]; a -> b;`;
      m.groupsOf('a'); // Set { 'inner', 'outer' } — deep through &inner
      m.groupsOf('b'); // Set { 'outer' }
      m.groupsOf('z'); // Set {} — not in any group

      Parameters

      • state: string

        The state whose containing groups are wanted.

      Returns Set<string>

      A Set of every group name transitively containing state; empty when state belongs to no group.

      • isIn
      • groups
    • Check whether any state in the machine is complete.

      Returns boolean

      true if at least one state is complete.


    • Is at least one observational hook bound to the given target (megaspec §12)? The query is read exactly as in Machine.hooks_on. An optional phase narrows the test to pre- or post-transition hooks only; omitted, either phase satisfies it.

      const m = sm`a -> b;`;
      m.has_hook('b'); // false
      m.hook_entry('b', () => true);
      m.has_hook('b'); // true
      m.has_hook('b', 'post'); // false (the entry hook is pre-phase)

      Parameters

      Returns boolean

      true when a matching hook exists.


    • Check whether the machine knows a given state.

      import * as jssm from 'jssm';

      const lswitch = jssm.from('on <=> off;');

      console.log( lswitch.has_state('off') ); // true
      console.log( lswitch.has_state('dance') ); // false

      Parameters

      • whichState: string

        The state to be checked for existence.

      Returns boolean

      true if the state exists, false otherwise.

    • Check whether any state in the machine is terminal.

      Returns boolean

      true if at least one state has no exits.

    • Check whether any state in the machine is unenterable.

      Returns boolean

      true if at least one state has no incoming transitions.

    • Register a pre-transition hook on a specific edge. Fires before transitioning from from to to. If the handler returns false, the transition is blocked.

      const m = sm`a -> b -> c;`;
      m.hook('a', 'b', () => console.log('a->b'));

      Parameters

      • from: string

        Source state name.

      • to: string

        Target state name.

      • handler: HookHandler<mDT>

        Callback invoked before the transition.

      Returns Machine<mDT>

      this for chaining.

    • Register a pre-transition hook on a specific action-labeled edge.

      Parameters

      • from: string

        Source state name.

      • to: string

        Target state name.

      • action: string

        The action label that triggers this hook.

      • handler: HookHandler<mDT>

        Callback invoked before the transition.

      Returns Machine<mDT>

      this for chaining.

    • Register a hook that fires when a state's after timer elapses — the delay-over companion to a after 5s -> b; style time transitions. It does NOT fire when the state is entered or left by ordinary dispatch; use hook_entry / hook_exit for those. (Versions through 5.143.28 also spuriously fired it on entering the state, the jssm side of StoneCypher/fsl#1327.)

      Parameters

      • from: string

        The state whose after timer is being watched.

      • handler: HookHandler<mDT>

        Callback invoked when the timer fires, just before the timed transition is taken; informational — its outcome cannot reject the transition.

      Returns Machine<mDT>

      this for chaining.

      const m = sm`a after 1000 -> b; a -> c; c -> a;`;
      let calls = 0;
      m.hook_after('a', () => { calls += 1; });
      m.go('c');
      m.go('a');
      // ordinary dispatch never fires it; only the timer elapsing does:
      calls; // => 0
      m.clear_state_timeout();
      • hook_entry
      • hook_exit
      • set_state_timeout
    • Register a hook that fires when ANY state's after timer elapses — the whole-machine companion to hook_after, mirroring how hook_any_transition companions hook. When the elapsing state also has a specific hook_after, the specific hook fires first and this one fires second; a specific after hook firing always implies the any-after hook fires too (StoneCypher/fsl#1299). Like hook_after it is informational — its outcome cannot reject the timed transition — and it does NOT fire on ordinary dispatch.

      Parameters

      • handler: HookHandler<mDT>

        Callback invoked whenever any after timer fires, just before the timed transition is taken.

      Returns Machine<mDT>

      this for chaining.

      const m = sm`a after 1000 -> b; a -> c; c -> a;`;
      let calls = 0;
      m.hook_after_any(() => { calls += 1; });
      m.go('c');
      m.go('a');
      // ordinary dispatch never fires it; only a timer elapsing does:
      calls; // => 0
      m.clear_state_timeout();
      • hook_after
      • hook_any_transition
      • set_state_timeout

    hook_entry

    • Register a pre-transition hook that fires after all other pre-hooks on every transition. If the handler returns false, the transition is blocked. The handler receives an EverythingHookContext whose hook_name is 'everything'.

      const m = sm`a -> b -> c;`;
      m.hook_everything(({ hook_name }) => {
      console.log(`${hook_name} fired`);
      return true;
      });

      Parameters

      Returns Machine<mDT>

      this for chaining.

    • Register a pre-transition hook on any edge triggered by a specific action.

      Parameters

      • action: string

        The action name to hook.

      • handler: HookHandler<mDT>

        Callback invoked before any transition with this action.

      Returns Machine<mDT>

      this for chaining.

    hook_post_everything

    • Register a pre-transition hook that fires before all other pre-hooks on every transition. If the handler returns false, the transition is blocked. The handler receives an EverythingHookContext whose hook_name is 'pre everything'.

      const m = sm`a -> b -> c;`;
      m.hook_pre_everything(({ hook_name }) => {
      console.log(`${hook_name} fired`);
      return true;
      });

      Parameters

      Returns Machine<mDT>

      this for chaining.

    hook_pre_post_everything


    • Generate the uniform observational-hook registry — every currently registered hook projected onto a normalized (kind, target, phase) row (megaspec §12, → #1357). The registry is generated on demand by walking the concrete per-kind storage tables rather than maintained as a second copy, so it can never drift from the tables Machine.set_hook actually dispatches into. It is the single source of truth behind the introspection accessors (Machine.has_hook, Machine.hooks_on) and the hooked_state viz styling.

      Targets are normalized: edge hooks become { scope: 'edge', from, to } (named hooks add action), entry/exit/after become { scope: 'state' }, global-action hooks become { scope: 'action' }, and the any-*, transition-class, and everything observers become { scope: 'global' }.

      const m = sm`a 'go' -> b;`;
      m.hook_entry('b', () => true);
      m.hook_registry();
      // => [ { kind: 'entry', phase: 'pre', target: { scope: 'state', state: 'b' } } ]

      Returns HookRegistryEntry[]

      Every registered hook as a HookRegistryEntry, in a stable table-walk order (pre-phase tables first, then post-phase).


    • Return every registry entry observing the given target (megaspec §12). The query selects the target shape:

      • a bare state name matches entry/exit/after hooks on that state, its state-boundary hooks, and every edge hook touching it (from or to),
      • a { from, to, action? } edge matches edge hooks on that transition (optionally narrowed to the named action),
      • a { action } action matches global-action and named-edge hooks carrying that action,
      • a { group } group matches that group's boundary hooks (group hooks are matched by name only and do not propagate to member states).
      const m = sm`a 'go' -> b;`;
      m.hook_entry('b', () => true);
      m.hooks_on('b').length; // 1
      m.hooks_on({ from: 'a', to: 'b' }); // [] (no edge hook registered)

      Parameters

      Returns HookRegistryEntry[]

      The matching HookRegistryEntry rows (possibly empty).

    • Get the instance name of this machine, if one was assigned at creation.

      Returns string

      The instance name string, or undefined.

    • Check whether the current state is complete (every exit has an action).

      Returns boolean

      true if the current state is complete.


    • Check whether a given state is a valid start state (either because it was explicitly named as such, or because it was the first mentioned state.)

      import { sm, is_end_state } from 'jssm';

      const example = sm`a -> b;`;

      console.log( final_test.is_start_state('a') ); // false
      console.log( final_test.is_start_state('b') ); // true

      const example = sm`end_states: [a b]; a -> b;`;

      console.log( final_test.is_start_state('a') ); // true
      console.log( final_test.is_start_state('b') ); // true

      Parameters

      • whichState: string

        The name of the state to check

      Returns boolean


    • Check whether the machine is currently in a failure state — that is, whether its current state is one of the declared failed_outputs.

      Returns boolean


    • Check whether a given state is declared as a failure output.

      Parameters

      • whichState: string

        The name of the state to check

      Returns boolean


    • Check whether the current state is final (either has no exits or is marked complete.)

      import { sm, is_final } from 'jssm';

      const final_test = sm`first -> second;`;

      console.log( final_test.is_final() ); // false
      state.transition('second');
      console.log( final_test.is_final() ); // true

      Returns boolean


    • Check whether a given state is a valid start state (either because it was explicitly named as such, or because it was the first mentioned state.)

      import { sm, is_start_state } from 'jssm';

      const example = sm`a -> b;`;

      console.log( final_test.is_start_state('a') ); // true
      console.log( final_test.is_start_state('b') ); // false

      const example = sm`start_states: [a b]; a -> b;`;

      console.log( final_test.is_start_state('a') ); // true
      console.log( final_test.is_start_state('b') ); // true

      Parameters

      • whichState: string

        The name of the state to check

      Returns boolean

    • Check whether the current state is terminal (has no exits).

      Returns boolean

      true if the current state has zero exits.

    • Check whether a state has no incoming transitions (unreachable after start).

      Parameters

      • whichState: string

        The state to check.

      Returns boolean

      true if the state has zero entrances.

      If the state does not exist.


    • Reports whether the machine's CURRENT state is a transitive member of a named group. Membership is deep: a state counts as in groupName if it belongs to that group directly, or via any nested (&child) or spread (...&child) sub-group, at any depth. An undeclared group simply has no members, so this returns false rather than throwing.

      import { sm } from 'jssm';

      const m = sm`&busy : [working]; idle 'go' -> working;`;
      m.isIn('busy'); // false — current state is 'idle'
      m.action('go');
      m.isIn('busy'); // true — current state is now 'working'
      m.isIn('nonesuch'); // false — undeclared group has no members

      Parameters

      • groupName: string

        The group to test the current state against.

      Returns boolean

      true if the current state is a transitive member of groupName.

      • groupsOf
      • statesIn

    • Check whether a given string is a known property's name.

      const example = sm`property foo default 1; a->b;`;

      example.known_prop('foo'); // true
      example.known_prop('bar'); // false

      Parameters

      • prop_name: string

        The relevant property name to look up

      Returns boolean


    • List all known property names. If you'd also like values, use props instead. The order of the properties is not defined, and the properties generally will not be sorted.

      const m = sm`property color default "grey"; property size default 1; a -> b;`;

      m.known_props(); // ['color', 'size']

      Returns string[]

      An array of all property name strings defined on this machine.


    • Get the label for a given state, if any; return undefined otherwise.

      import * as jssm from 'jssm';

      const lswitch = jssm.from('a -> b; state a: { label: "Foo!"; };');
      console.log( lswitch.label_for('a') ); // 'Foo!'
      console.log( lswitch.label_for('b') ); // undefined

      See also display_text.

      Parameters

      • state: string

        The state to get the label for.

      Returns string

      The label string, or undefined if no label is set.

    • List all distinct action names defined anywhere in the machine.

      Returns string[]

      An array of action name strings.


    • Lists all edges of a machine.

      import { sm } from 'jssm';

      const lswitch = sm`on 'toggle' <=> 'toggle' off;`;

      lswitch.list_edges();
      [
      {
      from: 'on',
      to: 'off',
      kind: 'main',
      forced_only: false,
      main_path: true,
      action: 'toggle'
      },
      {
      from: 'off',
      to: 'on',
      kind: 'main',
      forced_only: false,
      main_path: true,
      action: 'toggle'
      }
      ]

      Returns JssmTransition<string, mDT>[]

      An array of all JssmTransition edge objects.


    • List all entrances attached to the current state. Please note that the order of the list is not defined. This list includes both unforced and forced entrances; if this isn't desired, consider list_unforced_entrances or list_forced_entrances as appropriate.

      import { sm } from 'jssm';

      const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;

      light.state(); // 'red'
      light.list_entrances(); // [ 'yellow', 'off' ]

      Parameters

      • whichState: string = ...

        The state whose entrances to have listed

      Returns string[]

    • List all action names available as exits from a given state.

      Returns the empty array (does not throw) when whichState exists but has no action-named exits — including terminal states, states whose only exits are plain -> transitions, and states in machines that use no actions at all. Only nonexistent states cause a throw.

      Parameters

      • whichState: string = ...

        The state to inspect. Defaults to the current state.

      Returns string[]

      An array of action name strings, possibly empty.

      If the state does not exist.

      const m = sm`a 'go' -> b; b -> c;`;
      m.list_exit_actions('a'); // => ['go']
      m.list_exit_actions('b'); // => []
      m.list_exit_actions('c'); // => []
      expect(() => m.list_exit_actions('z')).toThrow();

    • List all exits attached to the current state. Please note that the order of the list is not defined. This list includes both unforced and forced exits; if this isn't desired, consider list_unforced_exits or list_forced_exits as appropriate.

      import { sm } from 'jssm';

      const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;

      light.state(); // 'red'
      light.list_exits(); // [ 'green', 'off' ]

      Parameters

      • whichState: string = ...

        The state whose exits to have listed

      Returns string[]

    • Get the map of named transitions (transitions with explicit names).

      Returns Map<string, number>

      A Map from transition name to edge index.


    • List all states that have a specific action attached. Please note that the order of the states is not guaranteed.

      import { sm } from 'jssm';

      const machine = sm`
      red 'next' -> green 'next' -> yellow 'next' -> red;
      [red yellow green] 'shutdown' ~> off 'start' -> red;
      `;

      console.log( machine.list_states_having_action('next') ); // ['red', 'green', 'yellow']
      console.log( machine.list_states_having_action('start') ); // ['off']

      Parameters

      • whichState: string

        The action to be checked for associated states

      Returns string[]


    • List all transitions attached to the current state, sorted by entrance and exit. The order of each sublist is not defined. A node could appear in both lists.

      import { sm } from 'jssm';

      const light = sm`red 'next' -> green 'next' -> yellow 'next' -> red; [red yellow green] 'shutdown' ~> off 'start' -> red;`;

      light.state(); // 'red'
      light.list_transitions(); // { entrances: [ 'yellow', 'off' ], exits: [ 'green', 'off' ] }

      Parameters

      • whichState: string = ...

        The state whose transitions to have listed

      Returns JssmTransitionList

    • Look up the full transition object for a given source→target pair.

      Parameters

      • from: string

        Source state name.

      • to: string

        Target state name.

      Returns JssmTransition<string, mDT>

      The JssmTransition object, or undefined if none exists.

    • Get the machine's author list. Set via the FSL machine_author directive.

      Returns string[]

      An array of author name strings.

    • Get the machine's comment string. Set via the FSL machine_comment directive.

      Returns string

      The comment string.

    • Get the machine's contributor list. Set via the FSL machine_contributor directive.

      Returns string[]

      An array of contributor name strings.

    • Get the machine's definition string. Set via the FSL machine_definition directive.

      Returns string

      The definition string.

    • Get the machine's natural language as an ISO 639-1 code. Set via the FSL machine_language directive, which accepts a language name or code, or a BCP-47 tag whose region subtag is dropped (en-us -> en). Unrecognized values resolve to undefined.

      Returns string

      The ISO 639-1 language code (e.g. 'en'), or undefined if the supplied value did not resolve to a known language.

    • Get the machine's license string. Set via the FSL machine_license directive.

      Returns string

      The license string.

    • Get the machine's name. Set via the FSL machine_name directive.

      Returns string

      The machine name string.

    • Get the machine's declared version, parsed. Set via the FSL machine_version directive, which takes a semver triple; the parser breaks it into numeric major/minor/patch fields and keeps the exact source text in full. Returns undefined when the directive was not given.

      Returns JssmParsedSemver

      The parsed JssmParsedSemver, or undefined if unset.

      const m = sm`machine_version: 1.2.3; a -> b;`;
      m.machine_version(); // => { major: 1, minor: 2, patch: 3, full: '1.2.3' }

      fsl_version

    • Get the npm package name associated with the machine. Set via the FSL npm_name directive. Returns undefined when not present.

      Returns string

      The npm package name string, or undefined.

      machine_name

    • Remove a previously-registered event handler. Match is by reference — the same function value passed to Machine.on or Machine.once. Returns true if a subscription was found and removed, false otherwise.

      const fn = (e: any) => console.log(e);
      m.on('transition', fn);
      m.off('transition', fn); // true
      m.off('transition', fn); // false

      Type Parameters

      Parameters

      Returns boolean

      true if removed, false if no match was registered.

    • Subscribe to a typed observation event. Hooks (set_hook and friends) intercept and may cancel a transition; events fire alongside the same state-machine moments but cannot influence the outcome. This is the surface most users actually want for "tell me when state changes".

      Handlers run synchronously, in registration order. A throwing handler does not block subsequent handlers — its exception is caught and re-emitted as an error event whose detail names the original event and the offending handler.

      const m = sm`a -> b -> c;`;

      m.on('transition', e => console.log(`${e.from} -> ${e.to}`));
      m.on('entry', { state: 'b' }, e => console.log(`entered ${e.state}`));

      const off = m.on('transition', () => {});
      off(); // unsubscribe

      Type Parameters

      • Ev extends JssmEventName

        The event name (drives the detail type).

      Parameters

      • name: Ev

        The event name to subscribe to.

      • handler: JssmEventHandler<mDT, Ev>

        The handler invoked on each matching delivery. The three-argument (name, filter, handler) form inserts a filter object before the handler (see the example above).

      Returns JssmUnsubscribe

      A function that unsubscribes when called.

      • Machine.off
      • Machine.once
    • Subscribe to a typed observation event. Hooks (set_hook and friends) intercept and may cancel a transition; events fire alongside the same state-machine moments but cannot influence the outcome. This is the surface most users actually want for "tell me when state changes".

      Handlers run synchronously, in registration order. A throwing handler does not block subsequent handlers — its exception is caught and re-emitted as an error event whose detail names the original event and the offending handler.

      const m = sm`a -> b -> c;`;

      m.on('transition', e => console.log(`${e.from} -> ${e.to}`));
      m.on('entry', { state: 'b' }, e => console.log(`entered ${e.state}`));

      const off = m.on('transition', () => {});
      off(); // unsubscribe

      Type Parameters

      • Ev extends JssmEventName

        The event name (drives the detail type).

      Parameters

      • name: Ev

        The event name to subscribe to.

      • filter: JssmEventFilter<mDT, Ev>
      • handler: JssmEventHandler<mDT, Ev>

        The handler invoked on each matching delivery. The three-argument (name, filter, handler) form inserts a filter object before the handler (see the example above).

      Returns JssmUnsubscribe

      A function that unsubscribes when called.

      • Machine.off
      • Machine.once
    • Subscribe to a typed observation event for one matching delivery, then auto-remove. Accepts the same (name, handler) and (name, filter, handler) shapes as Machine.on.

      m.once('terminal', e => console.log(`done at ${e.state}`));
      

      Type Parameters

      Parameters

      • name: Ev

        The event name.

      • handler: JssmEventHandler<mDT, Ev>

        The handler invoked on the first matching delivery. The three-argument (name, filter, handler) form inserts a filter object before the handler (same shapes as on).

      Returns JssmUnsubscribe

      A function that unsubscribes early if called before the handler has fired.

      • Machine.on
      • Machine.off
    • Subscribe to a typed observation event for one matching delivery, then auto-remove. Accepts the same (name, handler) and (name, filter, handler) shapes as Machine.on.

      m.once('terminal', e => console.log(`done at ${e.state}`));
      

      Type Parameters

      Parameters

      • name: Ev

        The event name.

      • filter: JssmEventFilter<mDT, Ev>
      • handler: JssmEventHandler<mDT, Ev>

        The handler invoked on the first matching delivery. The three-argument (name, filter, handler) form inserts a filter object before the handler (same shapes as on).

      Returns JssmUnsubscribe

      A function that unsubscribes early if called before the handler has fired.

      • Machine.on
      • Machine.off

    • Replace the current state — and, when a data argument is provided, the data — with no regard to the graph.

      The data argument is arity-detected: omitting it preserves the current data, while explicitly passing undefined really sets the data to undefined (StoneCypher/fsl#1264). Before 5.163 an omitted data argument silently cleared the data.

      import { sm } from 'jssm';

      const machine = sm`a -> b -> c;`;
      console.log( machine.state() ); // 'a'

      machine.go('b');
      machine.go('c');
      console.log( machine.state() ); // 'c'

      machine.override('a');
      console.log( machine.state() ); // 'a'

      Parameters

      • newState: string

        The state to teleport to; must exist in the graph.

      • OptionalnewData: mDT

        Replacement data. Omit to keep the current data; pass undefined explicitly to clear it.

      Returns void

      If the machine's config does not set allows_override: true, or if newState does not exist.

      set_data

    post_hook

    • post_hook(from: string, to: string, handler: HookHandler<mDT>): Machine<mDT>

      Post-transition hook on a specific edge. Fires after the transition from from to to has completed. Cannot block the transition.

      Parameters

      • from: string

        Source state name.

      • to: string

        Target state name.

      • handler: HookHandler<mDT>

        Callback invoked after the transition.

      Returns Machine<mDT>

      this for chaining.

    post_hook_action

    • post_hook_action(
          from: string,
          to: string,
          action: string,
          handler: HookHandler<mDT>,
      ): Machine<mDT>

      Post-transition hook on a specific action-labeled edge.

      Parameters

      • from: string

        Source state name.

      • to: string

        Target state name.

      • action: string

        The action label.

      • handler: HookHandler<mDT>

        Callback invoked after the transition.

      Returns Machine<mDT>

      this for chaining.

    post_hook_any_action

    post_hook_any_transition

    post_hook_entry

    post_hook_exit

    post_hook_forced_transition

    post_hook_global_action

    • post_hook_global_action(action: string, handler: HookHandler<mDT>): Machine<mDT>

      Post-transition hook on any edge triggered by a specific action.

      Parameters

      • action: string

        The action name.

      • handler: HookHandler<mDT>

        Callback invoked after any transition with this action.

      Returns Machine<mDT>

      this for chaining.

    post_hook_main_transition

    post_hook_standard_transition

    • Take n probabilistic steps and return a histograph of how many times each state was visited.

      Parameters

      • n: number

        Number of steps to walk.

      Returns Map<string, number>

      A Map from state name to visit count.

      If a visited state's candidate exit pool is non-empty but all-zero-weight (StoneCypher/fsl#1248).

    • Take a single random transition from the current state, weighted by edge probabilities.

      Returns boolean

      true if a transition was taken, false otherwise.

      If the candidate exit pool is non-empty but its total weight is zero — every candidate declares 0% — per StoneCypher/fsl#1248.

    • Take n consecutive probabilistic transitions and return the sequence of states visited (before each transition).

      Parameters

      • n: number

        Number of steps to walk.

      Returns string[]

      An array of state names visited during the walk.

      If a visited state's candidate exit pool is non-empty but all-zero-weight (StoneCypher/fsl#1248).

    • List all action exits from a state with their probabilities.

      Parameters

      • whichState: string = ...

        The state to inspect. Defaults to the current state.

      Returns any[]

      An array of { action, probability } objects.

      If the state does not exist.

    • Get the transitions available from a state for use by the probabilistic walk system.

      If any exit declares a probability, only those probability-bearing exits are returned, so that non-probability peers cannot dilute the declared distribution. If no exit declares a probability, every legal (non-forced) exit is returned, which weighted_rand_select treats as equal weight. Forced-only exits (~>) are always excluded, since they cannot be taken by an ordinary transition() call.

      Fixes StoneCypher/fsl#1325, in which the function previously returned every exit unconditionally — including forced-only exits and exits with no probability, which distorted the weighted distribution.

      Parameters

      • whichState: string

        The state to inspect.

      Returns JssmTransition<string, mDT>[]

      An array of JssmTransition edges exiting the state, filtered as described above. May be empty.

      If the state does not exist.


    • Get the current value of a given property name. Checks the current state's properties first, then falls back to the global default. Returns undefined if neither exists. For a throwing variant, see strict_prop.

      const m = sm`property color default "grey"; a -> b;
      state b: { property color "blue"; };`;

      m.prop('color'); // 'grey' (default, because state is 'a')
      m.go('b');
      m.prop('color'); // 'blue' (state 'b' overrides the default)
      m.prop('size'); // undefined (no such property)

      Parameters

      • name: string

        The relevant property name to look up.

      Returns any

      The value behind the prop name, or undefined if not defined.


    • Get the current value of every prop, as an object. If no current definition exists for a prop — that is, if the prop was defined without a default and the current state also doesn't define the prop — then that prop will be listed in the returned object with a value of undefined.

      const traffic_light = sm`

      property can_go default true;
      property hesitate default true;
      property stop_first default false;

      Off -> Red => Green => Yellow => Red;
      [Red Yellow Green] ~> [Off FlashingRed];
      FlashingRed -> Red;

      state Red: { property: stop_first true; property: can_go false; };
      state Off: { property: stop_first true; };
      state FlashingRed: { property: stop_first true; };
      state Green: { property: hesitate false; };

      `;

      traffic_light.state(); // Off
      traffic_light.props(); // { can_go: true, hesitate: true, stop_first: true }

      traffic_light.go('Red');
      traffic_light.props(); // { can_go: false, hesitate: true, stop_first: true }

      traffic_light.go('Green');
      traffic_light.props(); // { can_go: true, hesitate: false, stop_first: false }

      Returns object

      An object mapping every known property name to its current value (or undefined if the property has no default and the current state doesn't define it).

    • Get the raw state declaration objects as parsed from the FSL source.

      Returns object[]

      An array of raw state declaration objects.

    • Remove a previously-registered hook described by a HookDescription. Match is by kind + identifying keys (from/to/action/etc.), not by handler reference — there is one hook per slot in the registry, so the description uniquely identifies which one to clear. Fires a hook-removal event for inspector tools.

      This is the symmetric counterpart of Machine.set_hook for the event-bridging use case (#638). Reasoning about hooks via observation events requires being able to observe their disappearance too.

      const m = sm`a -> b;`;
      const fn = () => true;
      m.set_hook({ kind: 'hook', from: 'a', to: 'b', handler: fn });
      m.remove_hook({ kind: 'hook', from: 'a', to: 'b', handler: fn });

      Parameters

      Returns boolean

      true if a hook was removed, false otherwise.


    • Resolves the full unified style/config cascade for a state — the runtime successor to the ad-hoc layer merge style_for used to perform.

      For any state OTHER than the current one, this returns the memoized static resolution (tiers 1–5; see _compose_state_config) — theme → default_state_config → per-kind defaults → depth-ordered group metadata → per-state config. The cache is keyed by state; those tiers do not depend on which state is current, so it survives transitions, but the mutable cascade inputs each clear it when they change — hook registration and removal (Machine.set_hook, Machine.remove_hook; the hooked layer) and theme assignment (the themes setter; tier 1 and the per-kind theme layers).

      For the machine's CURRENTLY-occupied state the result is recomputed each call (never cached) and additionally carries the dynamic active_state layers: the active-state THEME layers fold in just below the per-state config (tier 3-active), and the user active_state : { … } overlay folds in LAST (tier 6), on top of everything, so it wins over per-state config. Every fold uses merge_state_config, so a key set at a lower tier is overridden — never rejected — by a higher one.

      import { sm } from 'jssm';

      const m = sm`&busy : [working]; idle 'go' -> working; state &busy : { color: orange; };`;
      m.resolve_state_config('working').color; // '#ffa500ff' — from group &busy

      Parameters

      • state: string

        The state to compute the composite config for.

      Returns JssmStateConfig

      The fully composited JssmStateConfig for the state, including the active overlay when the state is current.

      style_for


    • Serialize the current machine, including all defining state but not the machine string, to a structure. This means you will need the machine string to recreate (to not waste repeated space;) if you want the machine string embedded, call serialize_with_string instead.

      Parameters

      • Optionalcomment: string

        An optional comment string to embed in the serialized output for identification or debugging.

      Returns JssmSerialization<mDT>

      A JssmSerialization object containing the machine's current state, data, and timestamp.


    • Replace the machine's data in place, without a transition. This is the practical way to assign any value — including undefined, null, or false — outside a hook's complex return, closing the gap where an undefined assignment had no direct API (StoneCypher/fsl#1264). Fires a data-change event with cause 'set_data' when the value actually changes; unlike override it requires no allows_override config, because it never moves the state.

      import * as jssm from 'jssm';

      const lswitch = jssm.from('on <=> off;', {data: 1});
      console.log( lswitch.data() ); // 1

      lswitch.set_data(2);
      console.log( lswitch.data() ); // 2

      lswitch.set_data(undefined);
      console.log( lswitch.data() ); // undefined

      Parameters

      • newData: mDT

        The value to install as the machine's data.

      Returns Machine<mDT>

      The machine, for chaining.

      • Machine.data
      • override
    • Schedule an automatic transition to next_state after after_time milliseconds. Only one timeout may be active at a time.

      Parameters

      • next_state: string

        The state to transition to when the timer fires.

      • after_time: number

        Delay in milliseconds.

      Returns void

      If a timeout is already pending.


    • Get the current state of a machine.

      import * as jssm from 'jssm';

      const lswitch = jssm.from('on <=> off;');
      console.log( lswitch.state() ); // 'on'

      lswitch.transition('off');
      console.log( lswitch.state() ); // 'off'

      Returns string

      The current state name.


    • Does the given state carry any observational hook — i.e. should it receive the hooked_state viz styling? True when an entry/exit/after hook is bound to the state, any edge hook touches it, or the state has its own boundary hook. Group-boundary hooks do not count here — they are matched by group only and never propagate to member states. Powers the hooked styling layer in Machine.resolve_state_config; replaces the long-stubbed has_hooks placeholder (megaspec §12).

      const m = sm`a -> b;`;
      m.state_has_hooks('a'); // false
      m.hook_exit('a', () => true);
      m.state_has_hooks('a'); // true

      Parameters

      • state: string

        The state to test.

      Returns boolean

      true when the state is observed by at least one hook.

    • Check whether a specific state is complete (every exit has an action).

      Parameters

      • whichState: string

        The state to check.

      Returns boolean

      true if the state is complete.

      If the state does not exist.


    • Check whether a given state is final (either has no exits or is marked complete.)

      import { sm, state_is_final } from 'jssm';

      const final_test = sm`first -> second;`;

      console.log( final_test.state_is_final('first') ); // false
      console.log( final_test.state_is_final('second') ); // true

      Parameters

      • whichState: string

        The name of the state to check for finality

      Returns boolean

    • Check whether a specific state is terminal (has no exits).

      Parameters

      • whichState: string

        The state to check.

      Returns boolean

      true if the state has zero exits.

      If the state does not exist.

    • Get the configured after timeout for a given state, if any.

      Parameters

      • which_state: string

        The state to look up.

      Returns [string, number]

      A [targetState, delayMs] tuple, or undefined if no timeout is configured for that state.


    • List all the states known by the machine. Please note that the order of these states is not guaranteed.

      import * as jssm from 'jssm';

      const lswitch = jssm.from('on <=> off;');
      console.log( lswitch.states() ); // ['on', 'off']

      Returns string[]

      An array of all state names in the machine.


    • Lists every state that is a transitive member of a named group — the flattened membership of the group, descending through nested and spread sub-groups, in member-declaration order.

      import { sm } from 'jssm';

      const m = sm`&inner : [a b]; &outer : [&inner c]; a -> b -> c;`;
      m.statesIn('outer'); // [ 'a', 'b', 'c' ]
      m.statesIn('inner'); // [ 'a', 'b' ]

      Parameters

      • groupName: string

        The group whose transitive member states are wanted.

      Returns string[]

      The transitive member states of groupName, in declaration order.

      If groupName is not a declared group.

      • groups
      • groupsOf
    • Run many weighted-random walks and return aggregate statistics.

      Honors % transition probabilities (via the existing probabilistic machinery). Non-destructive: the machine's current state and Machine.rng_seed are restored before returning, so calling this never perturbs the live machine. montecarlo mode (default) reports per-run path_lengths, terminal_reached, and capped; steady_state mode runs one long walk and omits those fields.

      Monte-Carlo runs count as terminal_reached when they start at a terminal or reach one on the final permitted transition. Terminal starts contribute zero to path_lengths, even when max_steps is zero.

      Timing (after) decorations and data-guard conditions are not modeled by this sampler; it walks the probabilistic graph topology.

      Parameters

      Returns JssmStochasticSummary

      A JssmStochasticSummary.

      • Machine.stochastic_runs
      • Machine.probabilistic_walk
      • Machine.editor_config
      const m = sm`a 'go' -> b 'go' -> c;`;
      const s = m.stochastic_summary({ runs: 100, seed: 1 });
      s.terminal_reached; // => 100

    • Get the current value of a given property name. If missing on the state and without a global default, throws a JssmError, unlike prop, which would return undefined instead.

      const m = sm`property color default "grey"; a -> b;`;

      m.strict_prop('color'); // 'grey'
      m.strict_prop('size'); // throws JssmError

      Parameters

      • name: string

        The relevant property name to look up.

      Returns any

      The value behind the prop name.

      If the property is not defined on the current state and has no default.


    • Gets the composite style for a specific node — the public viz entry point, now a thin wrapper over the unified config cascade in resolve_state_config.

      The order of composition runs least-specific to most-specific: theme defaults, then the default_state_config root, then per-kind defaults (terminal, start, end), then depth-ordered group metadata (inner groups winning over outer), then the per-state config, and finally — for the current state only — the active overlay. Last wins at every tier.

      Parameters

      • state: string

        The state to compute the composite style for.

      Returns JssmStateConfig

      The fully composited JssmStateConfig for the given state.

      resolve_state_config


    • Instruct the machine to complete a transition. Synonym for go.

      const light = sm`
      off 'start' -> red;
      red 'next' -> green 'next' -> yellow 'next' -> red;
      [red yellow green] 'shutdown' ~> off;
      `;

      light.state(); // 'off'
      light.go('red'); // true
      light.state(); // 'red'
      light.go('green'); // true
      light.state(); // 'green'
      light.go('blue'); // !! false - no such state
      light.state(); // 'green'
      light.go('red'); // !! false - green may not go directly to red, only to yellow
      light.state(); // 'green'

      Parameters

      • newState: string

        The state to switch to

      • OptionalnewData: mDT

        The data change to insert during the transition

      Returns boolean

      true if the transition was legal and occurred, false otherwise.

    • Check whether an action is available from the current state.

      Parameters

      • action: string

        The action name to check.

      • Optional_newData: mDT

        Reserved for future data validation.

      Returns boolean

      true if the action can be taken.

    • Check whether a forced transition to a given state exists from the current state.

      Parameters

      • newState: string

        The target state.

      • Optional_newData: mDT

        Reserved for future data validation.

      Returns boolean

      true if a forced (or any) transition exists.

    • Check whether a transition to a given state is legal (non-forced) from the current state.

      Parameters

      • newState: string

        The target state.

      • Optional_newData: mDT

        Reserved for future data validation.

      Returns boolean

      true if the transition is legal.