Split.io: Conflict replacing Promise.then

I am trying to include a SDK in our Meteor 2.2 app: Split.io’s Node SDK . We are using this SDK in other Node apps. However, when it runs in Meteor, it crashes while attempting to replace the then property of a Promise… which is apparently ok in other environments, but not in Meteor (I think that’s on purpose based on the latest version of meteor/promise). Here is the error:

W20210714-18:02:14.087(-3)? (STDERR) (node:3220222) UnhandledPromiseRejectionWarning: TypeError: Cannot assign to read only property 'then' of object '#<Promise>'
W20210714-18:02:14.088(-3)? (STDERR)     at chain (/home/x/tmp/meteor-split/simple-todos/node_modules/@splitsoftware/splitio/lib/utils/promise/wrapper.js:42:21)

Does Meteor implement its own Promise object? Or otherwise, is there a way to prevent Meteor from replacing then by that read-only property? We are just looking into including this SDK, so any ideas for doing it are greatly welcome (including building meteor differently, installing splitio differently, etc).

For the record and if it helps: there is a very easy way to reproduce the same problem the splitio package generates, which is simply

'use strict';
(new Promise(function() {})).then = function() {};

From there we verified the same thing works in node in general, but not in Meteor. And it also works if we remove 'use strict' in the example; but that’s not something we can do from within the built SDK.

Just for the reference, here’s where Meteor’s own global Promise implementation is being created and made closed for modifications:

Apparently that core initialization code runs before any application code.

Based on the comments on the top of the module it becomes clear that Meteor heavily relies on their own Fiber compatible Promise implementation:

It’s vitally important that we wrap Fiber.yield and other yielding
methods before we call makeCompatible, because the meteor-promise
implementation captures Fiber.yield and keeps calling the captured
version, which ignores any wrapping that happens later.

I’m no Meteor core expert, but if I had to guess, tempering with Meteor’s own Promise would probably render the app dysfunctional.

1 Like

After a while stuck with this package (we went with a workaround, but still needed to go back and make Split.io work in our Meteor deployments), we received some news from Split.io team: They just released SDK v10.15.9, which fixes the problem with Meteor.

Looking at the fix I still wonder if there can be any risks. Here is how this package now replaces Promise.then, see this commit https://github.com/splitio/javascript-client/commit/07d4e49fd71acc94c6e372515b621e9efb1c65f7 (sorry for the formatting - new user I cannot add more links to this post!). At the same time Meteor does pretty much thing (see code in the initial post).

While this appears to work: How do these two interact as they both replace then via defineProperty? Are they really both being applied, or one’s changes are lost? I fear that some of the edge cases covered by any of them (the Split SDK or Meteor), as they seem to focus on error handling, will not going to be handled and be a source of hard-to-find issues; perhaps just as hard to reproduce as to make this seem to work ok.

Do Meteor developers have an opinion here? Your advice is highly appreciated! Maybe Ben @benjamn
if you are still around? (As you appear to be the author in Meteor’s changes)

Thanks!