javascriptecmascript-6salesforceshim

Looking for hacks to shim objects when their prototype are sealed


In my context, String and String.prototype, Array and Array.prototype, Object and Object.prototype are sealed. I have no control on this sealing. My context only supports ES5 and I would like to use an ES6 shim (https://github.com/paulmillr/es6-shim) for use ES6 gracefull methods like find(), reduce() or even startsWith() ...

I can't use theses shims because error are throw when I try to add or edit prototypes. Do you know some tricks to bypass this restriction. I mean using Array.prototype.find() without providing my own implementation.

For example, a solution where I could use new ES6Array([]), before being able to use ES6 function, will be a suitable solution for me. I just want to avoid making my own implementation of Shims. I want to use the paulmillr implementation as much as possible.

Is it possible to use shadowing hacks to use paulmillr implementations ? I've been trying on my side to do that but it doesn't lead to any compliant result.

PS : This is a Salesforce Commerce Cloud context


Solution

  • es6-shim is a polyfill and will surely fail if prototypes are sealed, because it's supposed to modify them.

    The approach that is needed here is ponyfill. As the description says,

    In general, you should not modify API's you don't own.

    A ponyfill, in contrast, doesn't monkey patch anything, but instead exports the functionality as a normal module, so you can use it locally without affecting other code.

    tl;dr; Polyfills are naughty as they patch native APIs, while ponyfills are pure and don't affect the environment.

    Some of them are labeled on NPM with ponyfill keyword.

    core-js provides library version of it that doesn't pollute global namespace and thus can be used as a ponyfill, so generally there's no reason to look any further:

    import * as find from 'core-js/library/fn/array/find';
    
    find(array, 'foo')
    

    Notice that some core-js/library exports are polyfilled implementations (Promise, Map, etc.):

    import { Promise as PolyfilledPromise } from 'core-js/library';
    
    PolyfilledPromise.resolve();
    

    While other ones are collections of polyfilled methods, because it's impractical or impossible to provide independent implementation for them (Array, Object):

    import { Array as arrayPonyfills } from 'core-js/library';
    const { find } = arrayPonyfills;
    
    find.call(array, 'foo');