Open source PayPal utility suite for cross domain interaction

The author of the material, the developer of PayPal, describes a set of tools for cross-domain interaction.

We at PayPal write a lot of javascript code, which eventually starts working on other websites and other domains. A vivid example is checkout.js , an integration script that completely covers the process of ordering and paying for an order using our service, which allows merchants to easily embed our button and ordering mechanism into their sites.

Running our code on third-party sites is fraught with a huge amount of risk and pitfalls, but there are some key points:

Last year, we decided to focus on bringing together a truly powerful set of tools that helps to avoid these pitfalls and create a great user experience without having to constantly worry about whether messages get through and all windows are drawn.

We have opened the entire source code set. If you want to create interactions that work with your system from other sites or simply between different domains within your organization, then the search ends here.



First, the main thing. We wanted to create an intelligent procurement, on the basis of which all the tools we planned would work. We have a formal list of technologies that we like, but combining them into some kind of qualitative whole task is not an easy one. We decided to maximally simplify our work in the future and therefore whenever we want to publish a new cross domain library or tool, we fork grumbler and start coding without worrying about pre-setting any environment or tools.

Read more by reference



The first real technical problem we wanted to solve was the message exchange between windows and i-frames. Do you think you can just take window.postMessage and start pouring messages right and left? Think again:

Post-robot is designed to solve all these problems in one fell swoop, providing a stable and reliable way to send messages and receive responses.

Read more by reference



We love using React, and we like the idea of ​​components that work on the “data down, action up” principle, which is great in its simplicity. At the same time, the concept of React is aimed at rendering the user interface directly on your page, without any frames or cross-domain restrictions. But there is one significant "but": we would never even try to download React on a site that does not belong to us.

We asked ourselves: what if we include iiframes and pop-up windows in React-like components, with which we could directly pass properties and callbacks and allow child windows to directly call functions passed by the parent?

Iframes are generally not suitable for this. That is, in normal situations using window.postMessage you can only send simple objects and lines down to the i-frame and back up to its parent. But with xcomponent, you have the ability to render an iframe without any need to set up any message handlers: you will simply transfer data and functions directly to the iframe, and it will directly receive any properties that you pass to it in the window.xprops object.

In addition, it automatically adjusts bindings to popular frameworks, such as React, Angular, Vue, and others, which allows you to draw the iFrames in your application in the native way without any need to worry about how badly the iferames usually behave.

Read more by reference

And this is how we use xcomponent at PayPal



Guided by the same considerations as in the case of grumbler, we wanted to simplify the work on the xcomponent components as much as possible, making it so that setting up the environment and the tools does not slow down the work. Everyone loves when you can just start coding.

Therefore, we have released xcomponent-demo - a template that you can fork and start working on. It has everything you need for building, testing, publishing, and even static typing your code and publishing x-components for general use.



Working with interdomain windows is a tricky thing. There are many questions. For example, how to find out for sure that the window of another domain is closed? What is his domain is yours? What are its children? Browsers provide simple APIs for some of these tasks, but in each browser everything turns out differently.

With cross-domain-utils, we tried to create a library of helper methods designed to help with common cases that simplify working with cross-domain windows and eliminate the need to constantly worry about getting errors or warnings in the console. The tool, among other things, allows you to avoid really strange extreme cases, like this:

Edge, as always, in his repertoire.



Storing window objects is a costly process in terms of RAM, even if the window whose reference you are storing is closed.

WeakMaps is ideal for storing window data because:

The only problem is that many existing WeakMap spacers are trying to call Object.defineProperty by key, which immediately leads to failure in cases where the key is a cross-domain window with restricted access.

Cross-domain-safe-weakmap, by contrast, is designed to make working with cross-domain windows using their keys and the WeakMap native implementation (if available) to be as predictable and reliable as possible.



Many browsers simply de-prioritize everything that is sent to setTimeout if the browser tab in which your code is working is not in focus. Therefore, when you are working on something that should work in a pop-up window, and you need to send a message to the parent and ask him to do something ... In this case, any setTimeout specifically slows down the work of the parent.

Therefore, the output is simple: we refuse setTimeout for any critical paths of code execution, right?

The problem is that many of the existing intermediate promis shells in the absence of helpers like setImmediate resort to using setTimeout to ensure that the passed .then function is called asynchronously. Therefore, if you want to use promises in a variety of browsers and at the same time do so that the code runs in windows without focus, then you are a little unlucky.

zalgo-promise tries to solve this problem by putting all promises in synchronous mode by default. This means that if they are resolved synchronously, then the function transferred .then() will also be called synchronously. It is called zalgo-promise because we literally decided to release zalgo (after careful consideration of all the pros and cons).

Read more by reference



One of the important things about running code on other domains is that you need to know what is happening and how people use your products. And at least you need to know about those cases when the code causes any erroneous scenarios or breaks someone’s website.

On the other hand, there is no need to send one signal after another or write to the log a hundred requests in a row for each event for which you wanted to record.

beaver-logger tries to solve this problem by selecting and compiling logs and periodically dropping them to your server. It even includes the server component of the site to get logs, but you can freely adapt it as you wish for any favorite platform.



CORS - headache. Getting the correct headers requires setting each endpoint on the server. And if we are not talking about a GET request, then CORS makes additional exchange operations to determine whether it is safe to make one or another final request.

fetch-robot is a new experimental module aimed at solving this problem. It allows you to publish in one place a manifest that defines URLs that can be called, as well as by whom they can be called and which headers and other fields can be used.

It shows the contents of URLs with a different domain through the i-frame. With the help of post-robot, this same iframe conducts all messages through itself, thus avoiding the problem of additional interactions (since all checks are performed on the client side, inside a trusted frame).

Read more by reference

Thank you all for reading, and if you have any ideas about what tools are missing in the set of cross-domain interaction or what can be improved in them, please write to the author!

- Daniel, PayPal Checkout Development Team



All Articles