(function(Object){
// (C) WebReflection - Mit Style License
function createGetter(callback) {
return function get() {
if (arguments.length) {
throw "setting a property that has only a getter";
}
return callback.call(this);
};
}
function createSetter(callback) {
return function set(value) {
callback.call(this, value);
// a setter does not return anything
// since 123 === (obj.setter = 123)
// value is returned by design
return value;
};
}
function createGetterAndSetter(get, set) {
return function getOrSet(value) {
// obj.setter(undefined)
// is still a setter
// same as obj.setter = undefined in ES5
if (arguments.length) {
set.call(this, value);
// a setter does not return anything
// since 123 === (obj.setter = 123)
// value is returned by design
return value;
} else {
return get.call(this);
}
};
}
function defineHybridProperty(object, property, descriptor) {
var
get = hasOwnProperty.call(descriptor, "get") && descriptor.get,
set = hasOwnProperty.call(descriptor, "set") && descriptor.set
;
if (hasOwnProperty.call(descriptor, "value")) {
if (get || set) {
throw "Invalid property. 'value' present on property with getter or setter";
}
object[property] = descriptor.value;
} else if (get && set) {
object[property] = createGetterAndSetter(get, set);
} else if(get) {
object[property] = createGetter(get);
} else if(set) {
object[property] = createSetter(set);
}
return object;
}
function defineHybridProperties(object, descriptor) {
for (var key in descriptor) {
if (hasOwnProperty.call(descriptor, key)) {
defineHybridProperty(object, key, descriptor[key]);
}
}
hiddenNatives(object, descriptor);
return object;
}
var
hasOwnProperty = Object.prototype.hasOwnProperty,
hiddenNatives,
name
;
for (name in {toString:1}) {
hiddenNatives = function (object, descriptor) {};
}
if (!hiddenNatives) {
name = "constructor.hasOwnProperty.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.valueOf".split(".");
hiddenNatives = function (object, descriptor) {
var i = name.length, key;
while (i--) {
if (hasOwnProperty.call(descriptor, key = name[i])) {
defineHybridProperty(object, key, descriptor[key]);
}
}
};
}
Object.defineHybridProperty = defineHybridProperty;
Object.defineHybridProperties = defineHybridProperties;
}(Object));