Skip to content

Instantly share code, notes, and snippets.

@WebReflection
Last active February 24, 2018 04:13
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save WebReflection/5593554 to your computer and use it in GitHub Desktop.
Save WebReflection/5593554 to your computer and use it in GitHub Desktop.
Object.setPrototypeOf(O, proto) full/complete polyfill with boolean flag for partial implementation.
/*jslint devel: true, indent: 2 */
// 15.2.3.2
if (!Object.setPrototypeOf) {
Object.setPrototypeOf = (function(Object, magic) {
'use strict';
var set;
function checkArgs(O, proto) {
if (typeof O !== 'object' || O === null) {
throw new TypeError('can not set prototype on a non-object');
}
if (typeof proto !== 'object' && proto !== null) {
throw new TypeError('can only set prototype to an object or null');
}
}
function setPrototypeOf(O, proto) {
checkArgs(O, proto);
set.call(O, proto);
return O;
}
try {
// this works already in Firefox and Safari
set = Object.getOwnPropertyDescriptor(Object.prototype, magic).set;
set.call({}, null);
} catch (o_O) {
if (
// IE < 11 cannot be shimmed
Object.prototype !== {}[magic] ||
// neither can any browser that actually
// implemented __proto__ correctly
// (all but old V8 will return here)
{__proto__:null}.__proto__ === void 0
// this case means null objects cannot be passed
// through setPrototypeOf in a reliable way
// which means here a **Sham** is needed instead
) {
return;
}
// nodejs 0.8 and 0.10 are (buggy and..) fine here
// probably Chrome or some old Mobile stock browser
set = function(proto) {
this[magic] = proto;
};
// please note that this will **not** work
// in those browsers that do not inherit
// __proto__ by mistake from Object.prototype
// in these cases we should probably throw an error
// or at least be informed about the issue
setPrototypeOf.polyfill = setPrototypeOf(
setPrototypeOf({}, null),
Object.prototype
) instanceof Object;
// setPrototypeOf.polyfill === true means it works as meant
// setPrototypeOf.polyfill === false means it's not 100% reliable
// setPrototypeOf.polyfill === undefined
// or
// setPrototypeOf.polyfill == null means it's not a polyfill
// which means it works as expected
// we can even delete Object.prototype.__proto__;
}
return setPrototypeOf;
}(Object, '__proto__'));
}
@cscott
Copy link

cscott commented Feb 27, 2014

This doesn't work on Opera 12 -- setPrototypeOf.polyfill = true, but Object.setPrototypeOf(foo, null) doesn't work.

Hacky workaround in paulmillr/es6-shim#223

@beanmilk
Copy link

Thanks for your code!

Can you let me know which license is used for distribution of this code?
I'd like to use this code for a commercial app so I need to check the license.

Happy coding! :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment