An open standard formalizing patterns for polyfill identification and interoperability.
Polyfills are great. But they do not always conform perfectly to the behavior of the features they emulate. This can mislead downstream code, whose feature detection might result in an assumption of full conformance. We need a standard so that polyfills can be identified as such.
This allows downstream code to check for a possibly polyfilled feature, whose implementation and level of conformance is unknown to it, and then in those cases, choose whether to opt instead to use a preferred implementation, or use fallback behavior.
In a recent project, we used Respond.js to support media queries for older browsers. It relies on the matchMedia.js polyfill to determine whether media queries are supported in the browser. The fact that matchMedia.js always returns false for tests of media queries in older browsers is what Respond uses to know that it should polyfill.
But other code in the project wanted to use the more conformant media-match polyfill to keep responsive JavaScript behavior in sync with responsive CSS styles. But media-match would have fooled Respond into thinking media queries were supported in older browsers, so that Respond would not polyfill.
So we modified matchMedia.js to set the polyfill property, and modified media-match to detect this so that would could then override with its implementation.
Polyfill implementations should expose a polyfill property with a value of true.
For polyfill library authors, here is a code wrapper that can help your library conform to this spec.
(function (root, factory) {
var spec = factory(root);
var feature = spec.get ? spec.get() : root[spec.global];
if ( ! feature || ( feature.polyfill && spec.replace ) ) {
var polyfill = spec.polyfill;
polyfill.polyfill = true;
spec.set ? spec.set(polyfill) : root[spec.global] = polyfill;
}
})(this, function (root) {
// return spec definition...
});a. Global name
{
global: 'matchMedia',
polyfill: function () {
// implementation...
}
};b. Getter/setter
{
get: function () {
return root.navigator.geolocation;
},
set: function (poylfill) {
root.navigator.geolocation = polyfill;
},
polyfill: function () {
// implementation...
}
};c. Replace an existing polyfill
{
global: 'matchMedia',
replace: true,
polyfill: function () {
// implementation...
}
};