question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Legacy browser support: Issue with subclassing "Promise"

See original GitHub issue

Related to #51. react-async is hard to use in legacy ES5 browsers due to the implementation of NeverSettle class. The problem is subclassing native Promise is not supported in well-known transpilers, and to achieve this we have to polyfill Reflect and use custom transpilers.

References:

Built-in classes such as Date, Array, DOM etc cannot be properly subclassed due to limitations in ES5 (for the transform-classes plugin). You can try to use babel-plugin-transform-builtin-extend based on Object.setPrototypeOf and Reflect.construct, but it also has some limitations. https://babeljs.io/docs/en/caveats/#classes

Let me show an example:

var NeverSettle = (function (_super) {
    __extends(NeverSettle, _super);
    function NeverSettle() {
        var _this = _super.call(this, function () { }, function () { }) || this;
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                    ^ TypeError: undefined is not a promise

        if (Object.setPrototypeOf) {
            Object.setPrototypeOf(_this, NeverSettle.prototype);
        }
        return _this;
    }
    NeverSettle.prototype.finally = function () {
        return this;
    };
    NeverSettle.prototype.catch = function () {
        return this;
    };
    NeverSettle.prototype.then = function () {
        return this;
    };
    return NeverSettle;
}(Promise));
  • simple reproducible code about the error:
Promise.call(this, function () {}, function () {})
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
^ TypeError: undefined is not a promise
    at Promise (<anonymous>)

So I wish we can change the NeverSettle implementation rather than force us to set it up that complex setup. For example:

class NeverSettle {
  constructor() {
    const promise = new Promise(() => {}, () => {});
    this.then = promise.then.bind(promise);
    this.catch = promise.catch.bind(promise);
    this.finally = promise.finally.bind(promise);
  }
}

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:1
  • Comments:9 (9 by maintainers)

github_iconTop GitHub Comments

1reaction
ghengeveldcommented, Oct 10, 2019

Hey, thanks for reporting this! It’s a pretty big problem so we need to find a proper solution. However, the new Promise workaround is not the right one. This was in fact the original implementation, but it was changed because it causes a memory leak, where callbacks chained on it will never be called and never garbage collected, because the promise itself never resolves. So instead, I’m looking to do something like this:

function NeverSettle() {}

Object.setPrototypeOf(NeverSettle, Promise)

NeverSettle.prototype = Object.assign(Object.create(Promise.prototype), {
  finally() {
    return this
  },
  catch() {
    return this
  },
  then() {
    return this
  },
})
0reactions
ghengeveldcommented, Oct 11, 2019

Awesome. I’ll ship it early next week, as I’m out for the weekend.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Extend Javascript promise and resolve or reject it inside ...
When creating a subclass of Promise, the subclass constructor must take an executor function as its first argument, and call the executor ...
Read more >
Legacy Browser Support (LBS) now Integrated into Chrome ...
Legacy Browser Support functionality has been integrated directly into Chrome. As a result the Legacy Browser Support extension is no longer ...
Read more >
Promise.cast and Promise.resolve - ES Discuss
There's still some concern about supporting Promise subclassing, too, but I think it can be handled without controversy (I could be wrong).
Read more >
Inheritance and the prototype chain - JavaScript | MDN
In order to use this method, the function in question must be initialized. During this initialization, the constructor may store unique ...
Read more >
Changes - Selenium
NOTE: The legacy API is considered strongly deprecated and will be removed in a minor release once Google's Chrome and Microsoft's Edge browsers...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found