msgProc: Hooks
Message hooks let you intercept PAC messages before they reach their target container's msgProc, making them the right tool for cross-cutting concerns like debugging, telemetry, and middleware-style message transformation.
Hooks vs msgProc
A message hook sits above the normal message routing layer: it intercepts messages before dispatch, regardless of which container they are heading to. Where msgProc has scope over a single container, a hook sees everything.
| msgProc | Message Hook | |
|---|---|---|
| Scope | Single container | All containers on the page |
| Purpose | Application logic | Tooling, middleware, cross-cutting concerns |
| Fires | After hook chain completes | Before msgProc receives the message |
| Defined on | The PAC component object | The wakaPAC runtime via installMessageHook |
| Can suppress | Yes — return false |
Yes — do not call callNextHook |
installMessageHook
Registers a callback that fires for every dispatched PAC message, before the target container's msgProc is called:
const hhook = wakaPAC.installMessageHook((event, callNextHook) => {
// inspect or transform the event here
callNextHook(); // pass to the next hook and eventually to msgProc
});
The method returns a hook handle (hhook) that identifies the installed hook. Pass it to uninstallMessageHook to remove the hook later.
Callback Arguments
| Argument | Type | Description |
|---|---|---|
event |
CustomEvent | The PAC message event — same structure as the event received by msgProc, including message, wParam, lParam, pacId, and target |
callNextHook |
Function | Passes the message to the next hook in the chain. When the last hook calls through, the message is delivered to msgProc. Must be called for the message to continue — omitting it swallows the message |
uninstallMessageHook
Removes a previously installed hook. After this call the callback will no longer fire:
wakaPAC.uninstallMessageHook(hhook);
Passing an invalid or already-removed handle is a no-op.
The Hook Chain
Multiple hooks can be active simultaneously. They form a chain and are called in installation order. Each hook must explicitly call callNextHook to pass the message forward:
1. DOM event occurs
↓
2. Hook 1 fires
├─ Calls callNextHook? → continue
└─ Does not call? → message swallowed, chain stops here
↓
3. Hook 2 fires
└─ Calls callNextHook → continue
↓
4. msgProc of the target container fires
callNextHook suppresses the message for the target container and all subsequent hooks. Only omit the call if you intentionally want to block the message.
Examples
Logging all messages
const hhook = wakaPAC.installMessageHook((event, callNextHook) => {
const hex = '0x' + event.message.toString(16).toUpperCase().padStart(4, '0');
console.log('[' + event.pacId + '] ' + hex);
callNextHook();
});
Filtering a message type globally
Suppress MSG_MOUSEMOVE for all containers while a modal is open:
let hhook = null;
function openModal() {
hhook = wakaPAC.installMessageHook((event, callNextHook) => {
if (event.message === wakaPAC.MSG_MOUSEMOVE) {
return; // swallow — do not call callNextHook
}
callNextHook();
});
}
function closeModal() {
if (hhook !== null) {
wakaPAC.uninstallMessageHook(hhook);
hhook = null;
}
}
Measuring message throughput
const counts = {};
const hhook = wakaPAC.installMessageHook((event, callNextHook) => {
counts[event.message] = (counts[event.message] ?? 0) + 1;
callNextHook();
});
// Later — remove the hook and print results
wakaPAC.uninstallMessageHook(hhook);
console.table(counts);
Best Practices
- Always call through in spy hooks: Failing to call
callNextHooksilently breaks message delivery for the target container - Keep hook callbacks fast: Hooks run on every message across all containers — expensive operations will degrade responsiveness
- Uninstall when done: Store the
hhookhandle and calluninstallMessageHookwhen the hook is no longer needed, especially inside components with a lifecycle