{"id":16179,"library":"post-robot","title":"Cross-Domain Post-Messaging","description":"post-robot is a JavaScript library that simplifies secure cross-domain communication between browser windows (e.g., parent/iframe, opener/popup) using the native HTML5 `postMessage` API. It provides a robust, promise-based listener/sender pattern, abstracting away the complexities of serialization and asynchronous communication. A key differentiator is its ability to automatically serialize and deserialize complex data types, including functions, Promises (wrapped in `ZalgoPromise`), and Error objects, enabling advanced inter-window interactions. The library ensures reliable messaging with built-in error handling, timeouts, and options for securing channels by specifying target windows or domains. The current stable version is 8.0.32, and while a strict release cadence isn't explicitly stated, it is actively maintained by KrakenJS. This library is crucial for applications requiring seamless interaction between different origins.","status":"active","version":"8.0.32","language":"javascript","source_language":"en","source_url":"git://github.com/krakenjs/post-robot","tags":["javascript","cross-domain","cross domain","xdm","iframe","postmessage","krakenjs","kraken"],"install":[{"cmd":"npm install post-robot","lang":"bash","label":"npm"},{"cmd":"yarn add post-robot","lang":"bash","label":"yarn"},{"cmd":"pnpm add post-robot","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"Primarily consumed as a default ESM import. CommonJS `require` is also supported but often less preferred in modern build systems. The package exposes `postRobot` as the main entry point for all its functionalities like `on`, `send`, `once`.","wrong":"const postRobot = require('post-robot');","symbol":"postRobot","correct":"import postRobot from 'post-robot';"},{"note":"`send` is a method of the default `postRobot` export, not a named export itself. All core functionalities are accessed via the `postRobot` object.","wrong":"import { send } from 'post-robot'; // Incorrect destructuring","symbol":"send","correct":"import postRobot from 'post-robot';\npostRobot.send(someWindow, 'messageType', data);"},{"note":"`on` is also a method of the default `postRobot` export. Do not attempt to destructure it directly from the package import.","wrong":"import { on } from 'post-robot'; // Incorrect destructuring","symbol":"on","correct":"import postRobot from 'post-robot';\npostRobot.on('messageType', handler);"}],"quickstart":{"code":"import postRobot from 'post-robot';\n\n// --- Listener Window (e.g., in an iframe) ---\npostRobot.on('getUserDetails', function(event) {\n    const userId = event.data.id;\n    console.log(`Listener received request for user ID: ${userId} from ${event.origin}`);\n\n    // Simulate fetching user data asynchronously\n    return new Promise(resolve => {\n        setTimeout(() => {\n            if (userId === 123) {\n                resolve({\n                    id: userId,\n                    name: 'Alice Smith',\n                    email: 'alice@example.com',\n                    // Functions can also be returned and invoked remotely\n                    logStatus: (status) => console.log(`[Remote Log] Alice's status: ${status}`)\n                });\n            } else {\n                resolve(null); // User not found\n            }\n        }, 500);\n    });\n});\n\nconsole.log('post-robot listener initialized for getUserDetails.');\n\n// --- Sender Window (e.g., parent window) ---\n// This would typically be in a *different* window context, e.g., the parent window calling the iframe.\n// For demonstration, we'll simulate the call.\n\n// In a real scenario, 'someWindow' would be window.frames[0] or a popup window reference.\nconst someWindow = window.opener || window.parent; // Placeholder, adjust for actual target window\n\nif (someWindow && someWindow !== window) {\n    postRobot.send(someWindow, 'getUserDetails', { id: 123 }, { timeout: 3000 })\n        .then(function(event) {\n            const user = event.data;\n            if (user) {\n                console.log(`Sender received user: ${user.name} from ${event.origin}`);\n                user.logStatus('active'); // Call a function passed from the other window\n            } else {\n                console.log('Sender: User not found.');\n            }\n        })\n        .catch(function(err) {\n            console.error('Sender error:', err.message);\n        });\n} else {\n    console.warn('Sender simulation: Target window not found. This code needs to run in a separate context to function.');\n}\n","lang":"javascript","description":"This quickstart demonstrates setting up a `post-robot` listener in one window and sending a message to it from another window. It showcases passing data, handling asynchronous responses with Promises, and even invoking functions that were returned across the domain boundary. It includes basic error handling for timeouts."},"warnings":[{"fix":"Be aware that received Promises are `ZalgoPromise` instances. If compatibility with native Promises is critical, manually convert them (e.g., `Promise.resolve(zalgoPromise)`) or adjust checks to account for `ZalgoPromise`.","message":"When functions or Promises are passed across domains, post-robot wraps them with its internal `ZalgoPromise` implementation. If you are expecting native `Promise` instances for `instanceof` checks or specific promise library interoperability, this could lead to unexpected behavior.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always consult the official documentation for your specific `post-robot` version. When upgrading, review the release notes for breaking changes. For example, some configuration options might have changed names or structures.","message":"Older versions (prior to v7) might have different API signatures or behaviors, especially regarding error handling and serialization. While the core `on`/`send` pattern remains, internal mechanics and advanced options have evolved.","severity":"breaking","affected_versions":"<7.0.0"},{"fix":"Always explicitly define the `domain` option on both `on` and `send` calls to match the expected origin for secure and reliable communication. Use `*` sparingly and only when you fully understand the security implications. For same-domain communication, `window.location.origin` can be used.","message":"Improper configuration of the `domain` option (e.g., `postRobot.on('event', { domain: 'http://specific-domain.com' }, handler)`) can lead to messages being ignored or `SecurityError` exceptions if the message's origin does not match the specified domain. Conversely, omitting a specific domain can open up security vulnerabilities if not intended.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Handle promise rejections from `postRobot.send` calls to gracefully manage timeouts. Adjust the `timeout` option (e.g., `postRobot.send(window, 'msg', data, { timeout: 5000 })`) if you expect longer processing times on the receiving end.","message":"Messages sent via `post-robot` have a default timeout. If the listening window does not respond within this period, the sending promise will reject with a timeout error. This is by design to prevent hanging calls, but can be unexpected if not accounted for.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-21T00:00:00.000Z","next_check":"2026-07-20T00:00:00.000Z","problems":[{"fix":"Ensure `import postRobot from 'post-robot';` (ESM) or `const postRobot = require('post-robot');` (CommonJS) is at the top of your file where `postRobot` is used. Verify your bundler configuration if using a module system.","cause":"The `postRobot` object was not correctly imported or is not available in the global scope.","error":"TypeError: postRobot.send is not a function"},{"fix":"Check the listening window for errors or long-running operations. Increase the `timeout` option in the `postRobot.send` call if a longer processing time is expected on the receiver side (e.g., `{ timeout: 10000 }`). Ensure the listener function actually returns a value or a Promise that resolves.","cause":"The target window or listener did not send a response within the configured timeout period.","error":"Error: Message timeout: No response from window"},{"fix":"`post-robot` is designed to *circumvent* this exact problem for message passing. Ensure you are using `postRobot.send()` and `postRobot.on()` correctly for communication, and not attempting direct DOM manipulation or property access across origins. Also, verify that the `domain` option in `postRobot.on` and `postRobot.send` is correctly configured.","cause":"The browser's same-origin policy is preventing direct JavaScript access to another window's content. This error typically occurs when attempting to directly manipulate an iframe's `contentWindow` or `contentDocument` from a different origin, and not directly related to `post-robot`'s message passing.","error":"SecurityError: Blocked a frame from accessing a cross-origin frame."},{"fix":"Review the `domain` (and `window`) option provided to `postRobot.on`. Ensure it correctly specifies the expected origin(s) from which messages should be accepted. If messages are expected from multiple specific origins, the `domain` option can often accept an array of strings.","cause":"The `postRobot.on` listener was configured with a specific `domain` option (or `window` option), and the incoming message's origin did not match the allowed source.","error":"Error: Can not accept message from https://evil-domain.com"}],"ecosystem":"npm"}