es5-shim icon indicating copy to clipboard operation
es5-shim copied to clipboard

Provide shims as individual files

Open joshuacc opened this issue 10 years ago • 32 comments

It would be awesome if the shims were provided as individual files so that I could easily use only the shims that are necessary for my particular project.

joshuacc avatar Aug 22 '13 14:08 joshuacc

I’ll take that under advisement. In the interim, if you’re using Google Closure Compiler, you might look into dead code elimination (tree shaking).

kriskowal avatar Aug 22 '13 15:08 kriskowal

Can GCC remove dead code from prototypes?

SLaks avatar Aug 22 '13 15:08 SLaks

It would be nicer to have a build script that takes a list of methods to shim and outputs a JS file with only those shims (and their dependencies).

You could then write something with https://github.com/substack/lexical-scope (or esprima directly) to scan a set of JS files and figure out which shims are needed.
This would be very cool as Browserify middleware (it could take a minimum supported target browserset too).

However, it might be difficult to tell usage of prototype methods (you'd need to find the runtime value of variables).

//cc @substack

SLaks avatar Aug 22 '13 15:08 SLaks

@kriskowal Cool. Would you be interested in a pull request that breaks them out and then concatenates them with Grunt?

joshuacc avatar Aug 22 '13 16:08 joshuacc

@joshuacc Not as such. If we go down this route, we’ll follow the path that @domenic and I are plotting at http://github.com/kriskowal/q, which is to say, we’ll not merely break and concat, but will entrain CommonJS dependency management and use Browserify or MontageJS’s Mr/Mrs/Mop to perform the concatenation. However, this might be a destabilizing change for some of ES5-Shim’s bigger stake-holders like Twitter, and I would expect them to weigh in.

But if it’s worth doing, you do not need my permission. You just might be signing up to maintain a fork.

kriskowal avatar Aug 22 '13 16:08 kriskowal

I think this will be quite valuable, for example for Q. I envision a future where they are all provided as individual modules, perhaps with meta-modules for each object that needs work. So e.g. the main es5-shim does

require("./shims/array");
require("./shims/object");
require("./shims/function");
require("./shims/date");
// ...

and shims/array/index.js does

require("./map");
require("./reduce");
require("./filter");
// ...

and thus if you only needed Array.prototype.filter and Object.keys to work, e.g. in a library like Q, you'd do

require("es5-shim/shims/array/filter");
require("es5-shim/shims/object/keys");

We'd of course use Browserify's standalone ("UMD") support to maintain the status quo and thus nothing would actually change for consumers, besides this new ability to require individual files.

domenic avatar Aug 22 '13 17:08 domenic

Alternately we could attempt to provide "uncurry-this'ed" versions, so e.g. you'd do

var filter = require("es5-shim/shims/array/filter");
filter(myArrayLike, ...);

But I think this is not really in the spirit of es5-shim, and if you want to do that, I believe lo-dash has you covered.

domenic avatar Aug 22 '13 17:08 domenic

@domenic I would want to break these up in cohorts that are likely to need to be shimmed together, so maybe not quite so granular, but yes to everything else.

kriskowal avatar Aug 22 '13 17:08 kriskowal

There is already some work undergoing about this

I'm sure there are other people that were frustrated and broke out subsets of ES5 shim into individual standalone modules.

Raynos avatar Aug 28 '13 23:08 Raynos

@Raynos What is problem with copy-pasting or forking?

Yaffle avatar Aug 29 '13 04:08 Yaffle

@Yaffle

  • copy-pasting : ಠ_ಠ
  • forking : I'm not maintaining a different version of es5-shim, I'm writing a new thing that is smaller in scope. Mainly to reduce dependency size as much as possible as I want to use es5-shim functions in 30 line modules.

Raynos avatar Aug 29 '13 05:08 Raynos

What about using Square's es5 module transpiler?

knownasilya avatar Feb 01 '14 22:02 knownasilya

I'm far more likely to use browserify, and require in each method as a separate shim.

ljharb avatar Feb 01 '14 22:02 ljharb

+1

kof avatar Mar 01 '14 22:03 kof

I've decided how I want to approach this - I'll be collating a list of 100% spec-compliant npm modules, one for each shim. Each module must be browserifiable, and VERY strong weight will be given to modules that are willing to grant ownership to the @es-shims Github organization, to ensure future maintenance and upkeep.

In parallel with this effort, I'll be working on a way to integrate browserify so that people can still include es5-shim.js wholesale, but it will be composed of smaller pieces wherever possible.

In addition, in a future (major) release, I'd like to make require('es5-shim') not do any active shimming or modification of the global env, but instead have a shim method that will do so (and ideally each submodule will also have a shim method). Part of the normal release a new version workflow will still produce complete es5-shim.js and es5-shim.min.js files that auto-shim as they do now.

This will be a large, slow effort, but please feel free to make PRs to the shims.json file I added in https://github.com/es-shims/es5-shim/commit/d24a08dfe81e0eda3d5e9f3b859d63c1da05aba7 so we can begin collaborating the list. I'll evaluate each one before accepting it.

ljharb avatar Mar 16 '14 23:03 ljharb

  1. Exporting shim functionality as commonjs module + .shim() function which will extend a native prototype is absolutely nice. I have done exactly the same for my raf shim https://github.com/kof/animation-frame
  2. Every shim in separate repository is probably not needed if every shim is a separate file, written in pure commonjs without amd stuff. So one can require any shim like var forEach = require('es5-shim/lib/for-each'); Extend native prototype like forEach.shim() or require all shims like var allShims = require('es5-shim/lib') and allShims.shim(). And optionally provide a browserified version with umd inside in the dist or root dir.

kof avatar Mar 17 '14 08:03 kof

The advantage of making a separate module for each shim would be a shorter module name if people who own namespaces right now will free them, like var forEach = require('for-each'). If you still need to write samething like require('es5-shim-for-each') then its the same like var forEach = require('es5-shim/lib/for-each');

kof avatar Mar 17 '14 08:03 kof

Also what about dependencies between shims? If you want to build them into one file you will need to include something like this https://github.com/kof/micro-modules I would love to see if it works for you!

kof avatar Mar 17 '14 09:03 kof

That's a good point that they don't have to be separate shims, they can just be separate files. I'll work on that as well so that I can speed up the introduction of the build process.

However, separate small modules and repos imo is always better than one large one.

As for dependencies between shims - ideally, shims would have no dependencies (other than perhaps a shared ES5 helper module), and if they need interdependencies, we'll need to be careful not to create circular dependencies.

ljharb avatar Mar 17 '14 09:03 ljharb

I suppose there will be dependencies between shims, not just helper functions. F.e. my animation frame shim implements Date.now and performance.now. Of course its a tiny dependency, but still it would be nicer to include them separately.

kof avatar Mar 17 '14 09:03 kof

The more I think about separate repository for each shim, the more I like this idea. You could define dependencies in package.json and bower.json for each separately.

kof avatar Mar 17 '14 09:03 kof

@ljharb I own github.com/Raynos/function-bind I added you as as a collaborater to it.

Raynos avatar Mar 17 '14 18:03 Raynos

@Raynos thanks! i'll take a look and make sure all the spec edge cases are tested, and then i'll add it to the list.

ljharb avatar Mar 17 '14 23:03 ljharb

+1. It will be very useful for the autopolyfiller

ps: https://github.com/azproduction/autopolyfiller-stable/issues/1

monolithed avatar Oct 20 '14 13:10 monolithed

+1

mightyiam avatar Oct 29 '14 14:10 mightyiam

+1, clear separation of concerns and modularized approach is definitely from which Browserifiable packages would benefit from.

niksy avatar Dec 01 '14 09:12 niksy

I have tried to do a modular port using CommonJS and webpack as bundler. Here's the file for Array.prototype.every: https://github.com/tomchentw-deprecated/holyfills/blob/master/lib/array/array_every.js

I'm interested to help on this. Any thoughts?

tomchentw avatar Jun 12 '15 14:06 tomchentw

Most every shim already exists as a standalone, and standalones will need to follow a certain convention I've yet to lay out. The difficulty is in constructing a build process.

While I appreciate the offer of help, I'm already working on this. I'll update here as I make progress.

ljharb avatar Jun 12 '15 15:06 ljharb

Personally I think that it should be solved in a Common.js way: we should use only the things that are required. A good example would be a module called es5-shim/array that could be used like

 var Array = require(`es5-shim/array`);

and it should contain all the internal stuff for browserify to translate it into either a piece of JS with all the browser support or plain module.exports = Array if there's no additional support needed.

Changing prototypes or defining global variables has never been a good idea. That's not the way a shim should work at all.

reverofevil avatar Sep 06 '15 20:09 reverofevil

Changing prototypes or defining global variables has never been a good idea. That's not the way a shim should work at all.

It works exactly as it should. Shim provides polyfill for standard APIs which are not supported in some browsers. Otherwise you'll end up using lodash/underscore-like APIs instead of native APIs

hazzik avatar Sep 06 '15 23:09 hazzik