87 lines
2.1 KiB
JavaScript
87 lines
2.1 KiB
JavaScript
/* eslint no-proto: "off" */
|
|
|
|
// Big thanks to @WebReflection for sorting this out
|
|
// https://gist.github.com/WebReflection/5593554
|
|
|
|
"use strict";
|
|
|
|
var isObject = require("../is-object")
|
|
, value = require("../valid-value")
|
|
, objIsPrototypOf = Object.prototype.isPrototypeOf
|
|
, defineProperty = Object.defineProperty
|
|
, nullDesc = {
|
|
configurable: true,
|
|
enumerable: false,
|
|
writable: true,
|
|
value: undefined
|
|
}
|
|
, validate;
|
|
|
|
validate = function (obj, prototype) {
|
|
value(obj);
|
|
if (prototype === null || isObject(prototype)) return obj;
|
|
throw new TypeError("Prototype must be null or an object");
|
|
};
|
|
|
|
module.exports = (function (status) {
|
|
var fn, set;
|
|
if (!status) return null;
|
|
if (status.level === 2) {
|
|
if (status.set) {
|
|
set = status.set;
|
|
fn = function (obj, prototype) {
|
|
set.call(validate(obj, prototype), prototype);
|
|
return obj;
|
|
};
|
|
} else {
|
|
fn = function (obj, prototype) {
|
|
validate(obj, prototype).__proto__ = prototype;
|
|
return obj;
|
|
};
|
|
}
|
|
} else {
|
|
fn = function self (obj, prototype) {
|
|
var isNullBase;
|
|
validate(obj, prototype);
|
|
isNullBase = objIsPrototypOf.call(self.nullPolyfill, obj);
|
|
if (isNullBase) delete self.nullPolyfill.__proto__;
|
|
if (prototype === null) prototype = self.nullPolyfill;
|
|
obj.__proto__ = prototype;
|
|
if (isNullBase) defineProperty(self.nullPolyfill, "__proto__", nullDesc);
|
|
return obj;
|
|
};
|
|
}
|
|
return Object.defineProperty(fn, "level", {
|
|
configurable: false,
|
|
enumerable: false,
|
|
writable: false,
|
|
value: status.level
|
|
});
|
|
}(
|
|
(function () {
|
|
var tmpObj1 = Object.create(null)
|
|
, tmpObj2 = {}
|
|
, set
|
|
, desc = Object.getOwnPropertyDescriptor(Object.prototype, "__proto__");
|
|
|
|
if (desc) {
|
|
try {
|
|
set = desc.set; // Opera crashes at this point
|
|
set.call(tmpObj1, tmpObj2);
|
|
} catch (ignore) {}
|
|
if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { set: set, level: 2 };
|
|
}
|
|
|
|
tmpObj1.__proto__ = tmpObj2;
|
|
if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 2 };
|
|
|
|
tmpObj1 = {};
|
|
tmpObj1.__proto__ = tmpObj2;
|
|
if (Object.getPrototypeOf(tmpObj1) === tmpObj2) return { level: 1 };
|
|
|
|
return false;
|
|
})()
|
|
));
|
|
|
|
require("../create");
|