Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ES7 Promise Finally on Microsoft Internet Explorer 11 and Microsoft Edge #8111

Closed
HyP3r- opened this issue Jun 4, 2018 · 8 comments
Closed
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: polyfill pkg: preset-env

Comments

@HyP3r-
Copy link

HyP3r- commented Jun 4, 2018

Bug Report

Current Behavior
We want to support Microsoft Internet Explorer 11 and Microsoft Edge in out Project. In our Project we have used the ECMAScript 7 feature of Promise Finally a lot of times. In a talk with @existentialism he told me to use this little trick to make this thing working:

  1. Create a new File (e.g. polyfill.js):
import "babel-polyfill";
import "core-js/modules/es7.promise.finally";
  1. Update the webpack.config.js entry Points:
entry: {
    app: [
        "./frontend/pages/polyfill",
        "./frontend/pages/index"
    ],
}

Expected behavior/code
This solution is working for Microsoft Internet Explorer 11 pretty good but does not work for Microsoft Edge:

Unhandled promise rejection TypeError: Object doesn't support property or method 'finally'

How can I solve this problem?

Babel Configuration (.babelrc, package.json, cli command)

module: {
    rules: [
        {
            test: /\.js$/,
            include: path.join(__dirname, "frontend"),
            exclude: /(node_modules|bower_components)/,
            use: [
                {
                    "loader": "babel-loader",
                    "options": {
                        "cacheDirectory": true,
                        "metadataSubscribers": [ReactIntlPlugin.metadataContextFunctionName],
                        "plugins": [
                            "lodash",
                            "react-bootstrap",
                            "recharts",
                            "transform-runtime",
                            ["react-intl", {"enforceDescriptions": false}],
                        ],
                        presets: [
                            ["react"],
                            ["env", {
                                "useBuiltIns": "entry",
                                "targets": {
                                    "browsers": [
                                        "chrome >= 61",
                                        "edge >= 15",
                                        "firefox >= 52",
                                        "ie >= 11",
                                    ]
                                }
                            }]
                        ]
                    }
                },
            ]
        }
}

Environment

  • Babel version(s): babel-core ^6.24.1, babel-loader ^7.0.0, babel-plugin-lodash ^3.3.2, babel-plugin-react-bootstrap ^0.0.2, babel-plugin-react-intl ^2.3.1, babel-plugin-recharts ^1.1.1, babel-plugin-transform-runtime ^6.23.0, babel-polyfill ^6.24.1, babel-preset-env ^1.6.1, babel-preset-react ^6.24.1
  • Node/npm version: Node 6.11.2/npm 3.10.10
  • OS: Windows 10
  • Monorepo: yes
  • How you are using Babel: loader
@babel-bot
Copy link
Collaborator

Hey @HyP3r-! We really appreciate you taking the time to report an issue. The collaborators
on this project attempt to help as many people as possible, but we're a limited number of volunteers,
so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack
community that typically always has someone willing to help. You can sign-up here
for an invite.

@HyP3r-
Copy link
Author

HyP3r- commented Jun 25, 2018

Update to this issue:

If I write this in the polyfill.js

import "babel-polyfill";
import "core-js/modules/es7.promise.finally";

it is working on Microsoft Internet Explorer 11 and not on Microsoft Edge and if I write this in the polyfill.js

import "core-js/modules/es7.promise.finally";
import "babel-polyfill";

it is working on the current version Microsoft Edge but not on Microsoft Internet Explorer 11.

The reason for that is following: The Microsoft Internet Explorer 11 has no Fetch API and no Promise Object and the Microsoft Edge (or older Versions of the Mozilla Firefox or Google Chrome) has a Fetch API and a Promise Object but no finally function.

So in the first case import "babel-polyfill" is polyfilling the Promise Object and import "core-js/modules/es7.promise.finally" is polyfilling the finally function on the new created Promise Object. Thats the reason why it is working on Microsoft Internet Explorer 11, but not on Microsoft Edge because the native Fetch API is returning a non polyfilled (native) Promise Object without the finally function.

And in the second case import "core-js/modules/es7.promise.finally" is polyfilling on the existing Promise Object the finally function on Microsoft Edge and is unable to polyfill this functon on Microsoft Internet Explorer 11 because there is no Promise Object.

So the Problem or Question is: why does import "babel-polyfill" Polyfill (overwrite) the Promsie Object even though it shouldn't do that in this case?

@kyoukhana
Copy link

Did this ever get resolved

@aprilandjan
Copy link

Encountered this problem on IE10/Edge, too. Had to use async function to solve it temporarily.

@xtuc
Copy link
Member

xtuc commented Jul 31, 2018

Maybe @zloirock would have any input on this?

@zloirock
Copy link
Member

It's already explained in many other places. zloirock/core-js#371, zloirock/core-js#332, zloirock/core-js#178, etc.

@rjgotten
Copy link

rjgotten commented Aug 29, 2018

@HyP3r-
@kyoukhana
@aprilandjan

This type of issue can be resolved via a variation of how C# implements extension methods.

You can have a transform plugin which turns anything that looks like foo.finally( fn ) into promise_finally( foo, fn ) and then add a module import for this promise_finally function. What this function internally should do is:

  1. Check foo != null && typeof foo.finally === "function" and if so, call the instance implementation directly; otherwise
  2. Check if foo is a native or polyfilled promise without finally and if so; call a pollyfilled finally implementation; otherwise
  3. Throw a TypeError indicating that finally is undefined on foo.

In browsers that support the native method, performance will still be quite good. It just adds a wrapping function call and a simple typeof check.

In browsers that do not support the native method and need the polyfill, the type check in point 2 will almost never be the bottle-neck. The actual polyfill implementation itself will outweigh it.

Ofcourse, even browsers that do support the native implementation could end up in point 2 when the method is called on the 'wrong type'. But still: that's the exception and not the norm.
And even then: If you are not in a try-context that can catch errors, execution would halt with a thrown error anyway, making the performance impact insignificant. And if you were in a try-context; JS runtimes afaik still don't optimize that well, so you'd have performance problems there anyway.


I'm currently using a homebrewen transform plugin that implements this pattern to solve the larger more general problem of polyfilling instance methods across Array, Date, String etc. built-ins without affecting the native prototypes. It works really well.

@zloirock
Copy link
Member

zloirock commented Aug 30, 2018

@rjgotten this way of polyfilling instance methods will be added to babel-runtime with core-js@3, see #7646. But for some reason, it's not related .finally.

@lock lock bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Nov 29, 2018
@lock lock bot locked as resolved and limited conversation to collaborators Nov 29, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: polyfill pkg: preset-env
Projects
None yet
Development

No branches or pull requests

7 participants