shim.js 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Big thanks to @WebReflection for sorting this out
  2. // https://gist.github.com/WebReflection/5593554
  3. 'use strict';
  4. var isObject = require('../is-object')
  5. , value = require('../valid-value')
  6. , isPrototypeOf = Object.prototype.isPrototypeOf
  7. , defineProperty = Object.defineProperty
  8. , nullDesc = { configurable: true, enumerable: false, writable: true,
  9. value: undefined }
  10. , validate;
  11. validate = function (obj, prototype) {
  12. value(obj);
  13. if ((prototype === null) || isObject(prototype)) return obj;
  14. throw new TypeError('Prototype must be null or an object');
  15. };
  16. module.exports = (function (status) {
  17. var fn, set;
  18. if (!status) return null;
  19. if (status.level === 2) {
  20. if (status.set) {
  21. set = status.set;
  22. fn = function (obj, prototype) {
  23. set.call(validate(obj, prototype), prototype);
  24. return obj;
  25. };
  26. } else {
  27. fn = function (obj, prototype) {
  28. validate(obj, prototype).__proto__ = prototype;
  29. return obj;
  30. };
  31. }
  32. } else {
  33. fn = function self(obj, prototype) {
  34. var isNullBase;
  35. validate(obj, prototype);
  36. isNullBase = isPrototypeOf.call(self.nullPolyfill, obj);
  37. if (isNullBase) delete self.nullPolyfill.__proto__;
  38. if (prototype === null) prototype = self.nullPolyfill;
  39. obj.__proto__ = prototype;
  40. if (isNullBase) defineProperty(self.nullPolyfill, '__proto__', nullDesc);
  41. return obj;
  42. };
  43. }
  44. return Object.defineProperty(fn, 'level', { configurable: false,
  45. enumerable: false, writable: false, value: status.level });
  46. }((function () {
  47. var x = Object.create(null), y = {}, set
  48. , desc = Object.getOwnPropertyDescriptor(Object.prototype, '__proto__');
  49. if (desc) {
  50. try {
  51. set = desc.set; // Opera crashes at this point
  52. set.call(x, y);
  53. } catch (ignore) { }
  54. if (Object.getPrototypeOf(x) === y) return { set: set, level: 2 };
  55. }
  56. x.__proto__ = y;
  57. if (Object.getPrototypeOf(x) === y) return { level: 2 };
  58. x = {};
  59. x.__proto__ = y;
  60. if (Object.getPrototypeOf(x) === y) return { level: 1 };
  61. return false;
  62. }())));
  63. require('../create');