Open shirakaba opened 6 years ago
If anyone needs this patch before it is reviewed (or wants to review it without a git checkout
), they can add a function called patchedPolyfill()
to the es6-promise
module and invoke that instead:
const ep = require('es6-promise');
ep.patchedPolyfill = function(){
let local;
if (typeof global !== 'undefined') {
local = global;
} else if (typeof self !== 'undefined') {
local = self;
} else {
try {
local = Function('return this')();
} catch (e) {
throw new Error('polyfill failed because global object is unavailable in this environment');
}
}
let P = local.Promise;
if (P) {
var promiseToString = null;
try {
promiseToString = Object.prototype.toString.call(P.resolve());
} catch(e) {
// silently ignored
}
if (promiseToString === '[object Promise]' && !P.cast){
if (typeof P.prototype.finally !== "undefined"){
return;
}
}
}
local.Promise = ep;
};
// returns 'undefined', in desktop Safari (but likely not all browsers)
console.log(`typeof Promise.prototype.finally, before polyfill:`, typeof Promise.prototype.finally);
ep.patchedPolyfill();
// returns 'function'.
console.log(`typeof Promise.prototype.finally, after polyfill:`, typeof Promise.prototype.finally);
@jakearchibald would love you input on this.
It can polyfill only finally
instead of Promise
object.
I suppose what would be ideal would be to add some configuration to the polyfill function. Here are two options (presented using TypeScript-style interfaces) for comment:
// Option #1: Simply opt-in to ALL features beyond ES6/ES2015
interface Polyfill {
// DEFAULT: polyfill(true, true);
polyfill(beyondES2015?: boolean, asAugmentation?: boolean): void;
}
// Option #2: Opt-in to a specific ECMAScript version.
interface Polyfill {
// DEFAULT: polyfill("ES2018", true);
polyfill(ESVersion?: "ES2015"|"ES2018"|"next", asAugmentation?: boolean): void;
}
Nice because it's simple.
Helpful because it allows users to polyfill only an ECMAScript version of this library that would be in line with the rest of their libraries.
Any beyond-ES6/ES2015 feature will have to be written as optional into our distributed TypeScript typings, and all TypeScript users will have to mark usages of finally
as explicitly non-optional (unless, like me, they ditch the typings altogether and just set up their tsconfig.json
to include the appropriate lib
option, e.g. "ES2015.Promise" or "ES2018.Promise"
).
asAugmentation
flagThis is the relevant part to this issue filing. If a Promise
implementation is already present, we need to decide whether to replace it altogether or just augment it with this library's extra features like Promise.prototype.finally
.
@sherdeadlock is suggesting to just augment it. If we're confident that inter-op with native implementations of Promise
can be assured, then this flag should default to true
.
If we're not so confident, it should default to false
, meaning that the native Promise implementation should be altogether replaced with that of this library.
As @stefanpenner says, this module really shouldn't be called es6-promise
!
I can implement whatever is desired, but I shall first require a conclusion on which solution is preferred.
Alternatively, instead of adding parameters to polyfill()
: we rename this repo to es-promise
and just force polyfilling of all the latest features like Promise.prototype.finally
.
Also: I just realised that if we parameterised polyfill()
, then the var Promise = require('es6-promise').Promise;
API would become confusing (as it implicitly provides all the latest Promise
features. require('es6-promise/auto')
would also need to be supplemented by a require('es6-promise/justES6')
. Looking a bit messy...
its been two months.. any ideas here?
@stefanpenner is there anything we can do without @jakearchibald's input in the mean time?
this feature is currently in TC39 stage4,why this request hasn't been merged yet?
Hi Guys Any chance this will get merged? What's preventing it from being merged?
we rename this repo to es-promise
Although this is semantically accurate, Im not sure its super valuable. I suspect if we nail the details here, we can simply have es6-promise's uses benefit... Kinda sucks if you gotta choose different modules entirely to get what you want.
Also: I just realised that if we parameterised polyfill()
This may be a path forward, some random thoughts:
require('es6-promise/es-2018'); // forces finally
require('es6-promise/ensure-finally'); // forces finally
@stefanpenner The conundrum I was wondering about mainly was: If the browser doesn't have Promise.prototype.finally
already, should we:
1) Augment it just with Promise.prototype.finally
(using the – presumably – highly-optimised native version of Promise
, but having the unforeseen problems of running a chimaeric library); or
2) Replace the browser's whole Promise
implementation with that of es6-promise
(which ensures consistency of the whole implementation)?
Currently my PR does 2). Do users have any preference towards 1)?
What are chances of getting a browser with native Promises, but without finally?
Chances are good. Chrome v66 and a recent version of FireFox didn’t have it. We had to poly fill with Bluebird, because es6-promise didn’t work. Chrome 67 does support finally.
I'd go with granular approach then (see what i did? :D)
Fixes #330 .