Skip to content
/ poly Public

Small, fast, awesome. The only ES5-ish set of polyfills (shims) you can mix-and-match because they're individual modules.

License

Notifications You must be signed in to change notification settings

cujojs/poly

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Code to modern standards. Run everywhere.

License: MIT

poly.js is a collection of UMD modules that shim (aka "polyfill") old browsers to support modern (aka "ES5-ish") javascript.

poly.js is unique amongst ES5-ish shims because it:

  • is modular, not monolithic
  • is configurable to suit your code
  • can be minified using a has-aware optimizer

Note: poly/strict has been deprecated. See below.

Support

Issues: https://github.com/cujojs/poly/issues

Discussion: https://groups.google.com/d/forum/cujojs

Documentation:

What's new

  • 0.6.0
    • Converted all modules to UMD (experimental support for node.js!)
    • ES6 Array.prototype.find() and Array.prototype.findIndex()
    • ES6 Array.from() (without recent mapping functionality)
    • ES6 Array.of()
    • Fix for edge case of Object.getPrototypeOf (thanks Norman Xu!)
    • Allow prototype extension for DOM objects in IE8 (thanks Norman Xu and Mikael Karon!)
  • 0.5.2
    • Implement setImmediate/clearImmediate as a temporary, non-standard method for performant task queueing.
    • New poly/es5 and poly/es5-strict modules. poly/strict is deprecated.
    • Use @kitcambridge's JSON3 instead of JSON2
    • Date shim now keeps properties on Date constructor and keeps the name of the constructor "Date" (was previously "_Date")
    • Fix bugs in Object shims in IE 6-8.

Features

poly augments browsers with all of the following features:

poly/array:

  • array.forEach
  • array.map
  • array.some
  • array.every
  • array.indexOf
  • array.lastIndexOf
  • array.reduce
  • array.reduceRight
  • Array.isArray

poly/array-es6:

  • array.find
  • array.findIndex
  • Array.from (including generic behavior, but without mapping feature)
  • Array.of

poly/function:

  • func.bind

poly/json:

  • (global) JSON

poly/setImmediate:

  • (global) setImmediate
  • (global) clearImmediate

Note: setImmediate is not expected to become standardized, but is included here as an interim solution as a performant next-turn implementation.

poly/object:

  • Object.create *
  • Object.freeze *
  • Object.isFrozen *
  • Object.seal *
  • Object.isSealed *
  • Object.getPrototypeOf
  • Object.keys
  • Object.getOwnPropertyNames
  • Object.defineProperty *
  • Object.defineProperties *
  • Object.isExtensible
  • Object.preventExtensions *
  • Object.getOwnPropertyDescriptor *

Methods marked with * cannot be shimmed completely. You can decide whether these methods should fail silently or loudly. The poly/object and poly/all modules return a function, failIfShimmed, that takes a single parameter.

This parameter may be:

  • a boolean (all Object.XXX functions should fail)
  • a function that takes a method name as a parameter and return truthy/falsey

By default, poly/object will not throw any exceptions and allows non-functional or incomplete shims to fail silently. poly/all works the same way. However, poly/strict sets failIfShimmed so that poly/object will throw exceptions for some functions. (see below)

Object.getPrototypeOf works in all situations except when using raw prototypal inheritance in IE6-8. This is due to a well-known IE bug that clobbers the constructor property on objects whose constructor has a prototype.

By "raw", we mean the following:

function MyClass () {}
MyClass.prototype = { foo: 42 };
var obj = new MyClass();
console.log(obj.constructor == MyClass); // false in IE6-8

The workaround is to set the constructor explicitly:

function MyClass () {}
MyClass.prototype = { foo: 42, constructor: MyClass };
var obj = new MyClass();
console.log(obj.constructor == MyClass); // true everywhere!!!!!

Most inheritance helper libs, including John Resig's Simple Inheritance, dojo, and prototype.js already do this for you.

poly/string:

  • string.trim
  • string.trimLeft
  • string.trimRight

poly/xhr:

  • (global) XMLHttpRequest

poly/date:

  • Date.parse now supports simplified ISO8601 date strings
  • new Date() now supports simplified ISO8601 date strings
  • date.toISOString() returns a simplified ISO8601 date string

poly/all (also just "poly"):

This is a convenience module to load and apply all shims. Shims that have varying levels of "strictness" are set to be loose. Use poly/strict or create your own version of poly/all to be stricter.

The "poly" main module will load poly/all.

poly/es5:

This convenience module loads and applies all es5 shims. Shims, such as poly/setImmediate are not included.

poly/strict:

This is module is deprecated. Please use poly/es5-strict.

poly/es5-strict:

This convenience module loads and applies all es5 shims, but ensures that whitespace characters comply with ES5 specs (many browsers don't do this) and fails loudly for the following object shims that can't reasonably be shimmed to comply with ES5:

  • Object.defineProperty
  • Object.defineProperties
  • Object.preventExtensions
  • Object.getOwnPropertyDescriptor
  • Object.create (but only if supplying the second parameter)

If you would like your code to be even stricter, load poly/object or poly/string separately and set the desired level of strictness.

Examples

Sample AMD package declaration:

var cfg = {
	packages: [
		{ name: 'poly', location: 'js/poly-0.5', main: 'poly' }
	]
};

Sample AMD package declaration (strict):

var cfg = {
	packages: [
		{ name: 'poly', location: 'js/poly-0.5', main: 'strict' }
	]
};

Using poly's modules as shims / polyfills:

	// somewhere in your app's initialization code, load the "poly/array"
	// and it will shim the native Array prototype
	curl({ preloads: [ "poly/array" ] });

	// later, just use arrays as if the js engine supports javascript 1.7!
	define(/* my module */ function () {

		// Arrays are so hawt!

		return {

			myFunc: function (arr, process) {

				arr.forEach(function (item) {

					process(item);

				}

			}

		}

	});
	// use all available shims
	curl({ preloads: [ "poly/all" ] });
	// another way to use all available shims
	curl({ preloads: [ "poly" ] });
	// use all shims, but with stronger ES5 compliance
	curl({ preloads: [ "poly/strict" ] });
	// use just the array and function shims
	curl({ preloads: [ "poly/array", "poly/function" ] });

How do I know which shims to use?

If you've written the code, you probably know what ES5-ish features you've used. If you're using func.bind(), you should load the poly/function module. If you're using str.trim(), you will need the poly/string module.

If you're leveraging code that is meant to run in a CommonJS environment, you probably need all of poly's shims except poly/xhr. (Note: curl.js can load CommonJS Modules/1.1 files without pre-wrapping them in an AMD "transport" wrapper. Check out the moduleLoader package config option.)

If you're using poly.js with wire.js, you will need the following shims to use wire.js in all browsers: poly/array, poly/function, poly/object.

How can I limit the size of the shim modules?

poly.js supports has-aware AMD optimizers. dojo's build tool and RequireJS's r.js optimizer will automatically remove unneeded shims when provided a "has profile". Please refer to either of those optimization tools for more information about using and creating a "has profile".

Can I use feature detection to only load the shims the current browser requires?

Unfortunately, browser's didn't adopt ES5 features over night. There are various degrees of ES5-ishness in the wild. Therefore, there is no magic test that you can use to determine whether to load an ES5-ish shim or not.

However, if you limit your supported browser list, you may be able to make certain assumptions. For instance, if you limit your supported browsers to IE6 and the latest version for the remainder of the vendors, you could choose a fairly broad test. Something like the following is fairly safe:

var preloads = [];
if (typeof Object.preventExtensions != 'function') {
	preloads.push('poly/all');
}
curl({ preloads: preloads });

If your list of supported browsers isn't so clean, try taking a survey of your code so you can find a reasonable set of tests. The following is a possible set of tests for a project that uses object, function, and string shims:

var preloads = [];
if (typeof Object.preventExtensions != 'function') {
	preloads.push('poly/object');
}
if (typeof Function.prototype.bind != 'function') {
	preloads.push('poly/function');
}
if (typeof "".trim != 'function') {
	preloads.push('poly/string');
}
curl({ preloads: preloads });

Can I use poly without a module loader?

Yes. You can use browserify to turn poly's modules into a single file that doesn't require a module loader. Here's a simple example of how to browserify all of the ES5 polyfills into a file named "poly-es5.browserify.js":

browserify -s 'poly' es5.js -o poly-es5.browserify.js

See the browserify documentation for more options and use cases.

JSON3

JSON support via Kit Cambridge's JSON3 lib at: https://github.com/bestiejs/json3.git

Looking for the previous module?

Thanks to the generosity of @mikkelfj, we were able to obtain the poly package name on npm. If you are looking for the previous module, you can find it as poly.shell on npm.

About

Small, fast, awesome. The only ES5-ish set of polyfills (shims) you can mix-and-match because they're individual modules.

Resources

License

Stars

Watchers

Forks

Packages

No packages published