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

Promise.prototype.finally() broken in Firefox #2012

Closed
imtbl opened this issue Jul 31, 2018 · 26 comments
Closed

Promise.prototype.finally() broken in Firefox #2012

imtbl opened this issue Jul 31, 2018 · 26 comments

Comments

@imtbl
Copy link

imtbl commented Jul 31, 2018

Version

3.0.0-rc.10

Node and OS info

Node 10.6.0 / Yarn 1.9.2 / macOS 10.13.5

Steps to reproduce

  1. Clone https://github.com/mserajnik/vue-cli-promise-finally
  2. Install with Yarn
  3. Run with yarn serve
  4. Open the development URL in Firefox (tested under Firefox 61.0.1)
  5. Check the console: [Vue warn]: Error in created hook: "TypeError: this.fetchData(...).then(...).catch(...).finally is not a function"

What is expected?

According to the MDN web docs, Promise.prototype.finally() is supported natively in Firefox since 58, so it should work, even without any polyfill.

What is actually happening?

Promise.prototype.finally() does not work in Firefox (61.0.1).


Not sure if I'm missing something obvious here – I'm not even sure if this is actually a bug or just a configuration issue (maybe I have to adjust my babel.config.js in some way?). What is weird is that Promise.prototype.finally() works in Safari when I run the same test app, which doesn't have native support for it apparently – so the polyfill seems to be working there. I can only reproduce the issue in Firefox. A friend has also confirmed the same issue in Firefox under Windows 10.

Oh, and sorry if this issue belongs somewhere else. Since I couldn't pin down if it's a Firefox bug, an issue with Babel or one with the @vue/app preset (or just a configuration error on my end), it made the most sense to me to open it here first.

@imtbl imtbl changed the title Promise.prototype.finally() broken on Firefox Promise.prototype.finally() broken in Firefox Jul 31, 2018
@LinusBorg LinusBorg added scope: babel needs team repro We acknowledged your report and will soon try to reproduce it labels Aug 1, 2018
@LinusBorg
Copy link
Member

Hm, I remember coming across something like this a while ago when building a prototype with beta.3 or something.

We include a Promise polyfill with vue-cli by default. Maybe we have a weird situation where

  1. The polyfill doesn't include finally
  2. in Firefox, the polyfill is installed even though it should be skipped as FF has native Promises already

If so, 1.) would be an issue to solve in vue-cli, if 2.), which would be a problem with babel-polyfill / core.js, can't be resolved quickly.

@imtbl
Copy link
Author

imtbl commented Aug 1, 2018

According to this there's also es.promise.finally, which I tried to add the following way:

module.exports = {
  presets: [
    ['@vue/app', {
      polyfills: ['es6.promise', 'es6.promise.finally', 'es6.array.iterator']
    }]
  ]
}

Hoewever, this throws an error on build:

Cannot read property 'android' of undefined (While processing
: "/fake/path/vue-cli-promise-finally/node_modules/@vue/babel-preset-app/index.js")
    at targetEnvironments.filter.environment (/fake/path/vue-cli-promise-finally/node_modules/@babel/preset-env/lib/index.js:75:
16)

Might also be related to this, will try that workaround out later.

@imtbl
Copy link
Author

imtbl commented Aug 1, 2018

Doing the following seems to work:

// babel.config.js

module.exports = {
  presets: [
    ['@vue/app', { useBuiltIns: 'entry' }]
  ]
}
// src/main.js

import '@babel/polyfill'

[]

It does increase the bundle size a bit (as expected), but that's not really an issue.

According to this comment from Brian Ng:

Yep, there's currently no usage mapping for .then, .catch or .finally.

So, issue solved for me. Do you think you could mention this limitation of having useBuiltIns in usage mode somewhere in the readme of @vue/babel-preset-app? I know that's an issue/limitation with @babel/preset-env itself, but given that @vue/cli is pretty much zero config by default and very beginner-friendly for people who haven't worked with webpack/Babel/etc. before, this is likely one of the first places they'd look if they encountered such an issue.

@LinusBorg LinusBorg added bug upstream and removed needs team repro We acknowledged your report and will soon try to reproduce it labels Aug 1, 2018
@yyx990803
Copy link
Member

This is an issue in core-js - its promise polyfill replaces the native Promise in Firefox, however according to author of core-js, it is doing it because Firefox's Promise implementation somehow fails a subclassing check so is technically not spec-compliant.

For now I've included es7.promise.finally by default to fix this in Vue CLI.

@imtbl
Copy link
Author

imtbl commented Aug 3, 2018

@yyx990803

Thanks, I think that's a decent solution for now.

I had forgotten Promise.prototype.finally() is not part of the ES6 spec, so the way I've tried to include the polyfill before (via es6.promise.finally) obviously didn't work in hindsight. Time to switch useBuiltins back to the default usage mode. :)

@zlab
Copy link

zlab commented Aug 5, 2018

@yyx990803
什么时候发布版本,这个finally配了好久都没有配置好

@luizhenriquerdias
Copy link

Sorry to comment on a closed topic but I'm getting an error relative to the subject.

`This dependency was not found:

  • core-js/modules/es7.promise.finally in ./src/main.js

To install it, you can run: npm install --save core-js/modules/es7.promise.finally`

I'm getting the error AFTER the rc10, so I had to fix the version in rc10.

@eyar
Copy link

eyar commented Oct 3, 2018

Happens to me also after installing vue-styled-components

`This dependency was not found:

core-js/modules/es7.promise.finally in ./src/main.js
To install it, you can run: npm install --save core-js/modules/es7.promise.finally`

@mrodal
Copy link

mrodal commented Jan 7, 2019

Im still missing the finally on firefox..

using ['@vue/app', { useBuiltIns: 'entry' }] fails to build with Unknown option: .useBuiltIns.

@LinusBorg
Copy link
Member

It's a nested array:

[['@vue/app', { useBuiltIns: 'entry' }]]

@mrodal
Copy link

mrodal commented Jan 9, 2019

@LinusBorg yes, thanks, that fixed the build error! but I still dont have the finally on promises :\

@mrodal
Copy link

mrodal commented Jan 21, 2019

can this issue be reopened? its still happening 😕

@imtbl
Copy link
Author

imtbl commented Jan 21, 2019

@mrodal and others:

It's been fixed for me since @yyx990803 has included es7.promise.finally by default. I also don't have to use useBuiltIns: 'entry' (except when building for Electron).

Feel free to check out the configuration in my project.

@LinusBorg
Copy link
Member

@mrodal if it's still happening for your, open a new issue with reproduction and a reference to this issue here.

I won't reopen this old one, it's outdated and I can't tell if the problem you describe actually exists in the way you say it does.

@mrodal
Copy link

mrodal commented Jan 21, 2019

Its fixed, I upgraded vue to the latest version. Its weird, because the version I had (2.5.17) had the changes made by @yyx990803.. but anyways, its working now, thanks @mserajnik and @LinusBorg

@LinusBorg
Copy link
Member

I think you are confusing Vue ( currently 2.5.18) with vue-cli (3.3.0).

The latter is responsible for injecting the polyfill. The Vue version isn't important for that.

@mrodal
Copy link

mrodal commented Jan 21, 2019

true, sorry, I also upgraded vue cli service and plugins from 3.0.3 to 3.0.4

@imtbl
Copy link
Author

imtbl commented Jan 21, 2019

@LinusBorg

Actually, latest Vue is 2.5.22.

@mrodal

Latest version of @vue/cli-plugin-babel and @vue/cli-service is 3.3.0; if you encounter any issues when building, I'd always recommend upgrading every dev dependency to the latest version (if you can) – chances are, the issue has been fixed. And as long as it's not a new major version, the chance of your build environment breaking should be pretty slim (and you can always roll back anyway if something goes wrong).

You can use a tool like updates to check for newer versions.

@pmochine
Copy link

pmochine commented Feb 4, 2019

I'm a noobie, but have the same issue but without having vue-cli installed. I come from Laravel. Anyhow, here is one open question in StackOverflow. Perhaps someone can help me :)

Edit 1:
The issue lies in my installed package. Somehow it overwrites my promise

@ahussein3
Copy link

@mserajnik in Which Vue cli version were this bug had Fixed ?

@imtbl
Copy link
Author

imtbl commented Mar 20, 2019

@ahussein3 This has been fixed in v3.0.0-rc.11 in August 2018.

@schmurfy
Copy link

schmurfy commented Jun 7, 2019

I still have this issue with:

  • @vue/cli-service@3.8.0
  • vue@2.6.10

in firefox:

Promise.resolve(42).finally(() => console.log('works'));
TypeError: Promise.resolve(...).finally is not a function[Learn More]

If I type this in the console on another website it works :(

@LinusBorg
Copy link
Member

LinusBorg commented Jun 7, 2019

Sorry to hear that.

If you can provide an actual reproduction of your issue we could investigate.

Saying "I have this problem" doesn't allow us to do that.

@schmurfy
Copy link

I realize that but the building environment is so complex I cannot allocate time for this currently, I solved my issue by just removing finally and use catch/then.

If it helps I don't have ny es(6/7).promise.finally in my current dependencies, if I understand correctly this was the fix applied, if so how is is supposed to be included ? do I need to have it explicitely in my package.json ?

@imtbl
Copy link
Author

imtbl commented Jun 10, 2019

@schmurfy:

If your project was created using vue-cli and you didn‘t make any manual changes to the build setup (e.g., change the Babel config in some way it would disable the usage of the es7.promise.finally polyfill), it should work out of the box.

As for the reproducible example, see the one in my opening post. That‘s just an empty project created with vue-cli (a version before the fix).

You could go this approach as well and start isolating the issue – if a new/empty project works, try to figure out what change(s) in your project cause(s) it not to work.

@jalovatt
Copy link

jalovatt commented Jun 10, 2019

If core-js is used by any of your modules (i.e. Babel), that's the cause.

This code isn't present in the current version, but core-js 3.0.1 overrides the Promise prototype:

var FORCED = isForced(PROMISE, function () {
 // correct subclassing with @@species support
 var promise = PromiseConstructor.resolve(1);
 var empty = function () { /* empty */ };
 var FakePromise = (promise.constructor = {})[SPECIES] = function (exec) {
   exec(empty, empty);
 };
 // unhandled rejections tracking support, NodeJS Promise without it fails @@species test
 return !((IS_NODE || typeof PromiseRejectionEvent == 'function')
   && (!IS_PURE || promise['finally'])
   && promise.then(empty) instanceof FakePromise
   // v8 6.6 (Node 10 and Chrome 66) have a bug with resolving custom thenables
   // https://bugs.chromium.org/p/chromium/issues/detail?id=830565
   // we can't detect it synchronously, so just check versions
   && v8.indexOf('6.6') !== 0
   && userAgent.indexOf('Chrome/66') === -1);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests