/*! Object.defineStrictProperty Experiment
* @author Andrea Giammarchi
* @blog http://webreflection.blogspot.com/
* @version 1.0b
* @license Mit Style
*/
Object.defineStrictProperty || (Object.defineStrictProperty = function () {
function args(args, get) {
return function () {
var callback = get.call(this);
return function get() {
for (var
length = args.length,
i = 0,
match = 0;
i < length && !match;
++i
) {
for (var
current = args[i],
j = current.length,
single = 1;
j-- && single;
) {
single = typeCheck(arguments[j], current[j]);
}
match = single;
}
if (!match && length) {
error("wrong arguments", {expected:args, received:args.slice.call(arguments)});
}
return callback.apply(this, arguments);
};
};
}
function argumentsGroups(args) {
for (var i = args.length, match = 1; i-- && match;) {
match = args[i] instanceof Array;
}
return match ? args : [args];
}
function concat(value) {
return [].concat(value);
}
function defineStrictProperty(self, key, descriptor) {
if (defineStrictProperty.production || !hasOwnProperty.call(descriptor, "type")) {
defineProperty(self, key, descriptor);
} else {
var
type = descriptor.type,
$get = hasOwnProperty.call(descriptor, "get"),
$set = hasOwnProperty.call(descriptor, "set"),
$value = hasOwnProperty.call(descriptor, "value"),
$key, value
;
if ($value || (!$get && !$set)) {
value = $value ? descriptor.value : null;
delete descriptor.value;
descriptor.get = get("this[p]", $key = "@" + key);
descriptor.set = set(
"Object.defineStrictProperty(this,p,{configurable:0,writable:1,enumerable:0,value:v})",
$key,
type
);
} else {
if ($get) {
descriptor.get = get("p.call(this)", descriptor.get);
}
if ($set) {
descriptor.set = set("p.call(this,v)", descriptor.set, type);
}
}
if (type == fn || type == create) {
if (hasOwnProperty.call(descriptor, "returns")) {
descriptor.get = returns(concat(descriptor.returns), descriptor.get);
}
if (hasOwnProperty.call(descriptor, "arguments")) {
descriptor.get = args(argumentsGroups(descriptor.arguments), descriptor.get);
}
}
defineProperty(self, key, descriptor);
if ($value) {
self[key] = value;
}
}
return self;
}
function error(message, log) {
if (log && typeof console == ob) {
console.log(log);
}
throw new TypeError(message);
}
function get(body, param) {
return create("p", "return " + fn + " get(){return " + body + "}")(param);
}
function returns(returns, get) {
return function () {
var callback = get.call(this);
return function get() {
for (var
result = callback.apply(this, arguments),
i = returns.length,
match = 0;
i-- && !match;
) {
match = typeCheck(result, returns[i]);
}
if (!match) {
error("wrong return", {expected:returns, received:result});
}
return result;
};
};
}
function set(body, param, expected) {
return create(
"t,y,p,e",
"return " +
fn +
" set(v){if(!t(v,e))y('wrong type',{expected:e,received:v});" +
body +
"}"
)(typeCheck, error, param, expected);
}
function typeCheck(current, expected) {
var
type = typeof expected,
undefined
;
return (
(type == st && typeof current == expected) ||
(type == fn && (current instanceof expected)) ||
(type == ob && (
(expected != null && expected.isPrototypeOf(current)) ||
(expected === null && current === expected)
)) ||
expected === undefined && current === expected
);
}
var
fn = "function", st = "string", ob = "object",
hasOwnProperty = {}.hasOwnProperty,
create = Function,
defineProperty = Object.defineProperty || function (object, key, descriptor) {
if (hasOwnProperty.call(descriptor, "value")) {
object[key] = descriptor.value;
} else {
if (hasOwnProperty.call(descriptor, "get")) {
object.__defineGetter__(key, descriptor.get);
}
if (hasOwnProperty.call(descriptor, "set")) {
object.__defineSetter__(key, descriptor.set);
}
}
}
;
defineStrictProperty.production = false;
return defineStrictProperty;
}());
Object.defineStrictProperties || (Object.defineStrictProperties = function () {
function defineStrictProperties(self, descriptor) {
for (var key in descriptor) {
descriptor.hasOwnProperty(key) &&
Object.defineStrictProperty(
self,
key,
descriptor[key]
)
;
}
return self;
}
return defineStrictProperties;
}());