es-shims / es5-shim

ECMAScript 5 compatibility shims for legacy (and modern) JavaScript engines
MIT License
7.12k stars 896 forks source link

Provide shims as individual files #175

Open joshuacc opened 11 years ago

joshuacc commented 11 years ago

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.

kriskowal commented 11 years ago

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).

SLaks commented 11 years ago

Can GCC remove dead code from prototypes?

SLaks commented 11 years ago

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

joshuacc commented 11 years ago

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

kriskowal commented 11 years ago

@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.

domenic commented 11 years ago

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 commented 11 years ago

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.

kriskowal commented 11 years ago

@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.

Raynos commented 11 years ago

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.

Yaffle commented 11 years ago

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

Raynos commented 11 years ago

@Yaffle

knownasilya commented 10 years ago

What about using Square's es5 module transpiler?

ljharb commented 10 years ago

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

kof commented 10 years ago

+1

ljharb commented 10 years ago

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.

kof commented 10 years ago
  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 commented 10 years ago

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 commented 10 years ago

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!

ljharb commented 10 years ago

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.

kof commented 10 years ago

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 commented 10 years ago

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.

Raynos commented 10 years ago

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

ljharb commented 10 years ago

@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.

monolithed commented 10 years ago

+1. It will be very useful for the autopolyfiller

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

mightyiam commented 10 years ago

+1

niksy commented 9 years ago

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

tomchentw commented 9 years ago

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?

ljharb commented 9 years ago

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.

reverofevil commented 9 years ago

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.

hazzik commented 9 years ago

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

thom4parisot commented 8 years ago

Hello there :-)

Is it something which is still under consideration? If so, what help is needed to move it forward?

ljharb commented 8 years ago

@oncletom yes, it is. What I'm going to emulate is the process I've built in the es7-shim, but https://github.com/es-shims/es7-shim/issues/8 is a blocker before attempting that here. Please feel free to help on that issue on the es7-shim!