treestyletab/modules/lib/extended-immutable.js

81 lines
2.5 KiB
JavaScript
Raw Permalink Normal View History

2016-09-04 02:15:23 -04:00
// Original author: ClearCode Inc.
// License: MIT
// Repository: https://github.com/clear-code/js-extended-immutable
var EXPORTED_SYMBOLS = ['ExtendedImmutable'];
function ExtendedImmutable(aImmutable, aExtraProperties) {
var descriptors = {};
Object.keys(aExtraProperties).forEach(function(aName) {
descriptors[aName] = Object.getOwnPropertyDescriptor(aExtraProperties, aName);
});
var base = Object.create({}, descriptors);
return new Proxy(base, {
getPrototypeOf: function(aTarget) {
return Object.getPrototypeOf(aImmutable);
},
setPrototypeOf: function(aTarget, aPrototype) {
return Object.setPrototypeOf(aImmutable, aPrototype);
},
isExtensible: function(aTarget) {
return Object.isExtensible(aImmutable);
},
preventExtensions: function(aTarget) {
return Object.preventExtensions(aImmutable);
},
getOwnPropertyDescriptor: function(aTarget, aProperty) {
return Object.getOwnPropertyDescriptor(aImmutable, aProperty);
},
defineProperty: function(aTarget, aProperty, aDescriptor) {
return Object.defineProperty(aImmutable, aProperty, aDescriptor);
},
has: function(aTarget, aProperty) {
return aProperty in aImmutable;
},
get: function(aTarget, aName, aReceiver) {
if (descriptors.hasOwnProperty(aName)) {
let value;
if (typeof descriptors[aName].get == 'function')
value = descriptors[aName].get.call(base);
else
value = descriptors[aName].value;
if (typeof value == 'function')
return value.bind(base);
else
return value;
}
var value = aImmutable[aName];
if (typeof value == 'function')
return value.bind(aImmutable);
else
return value;
},
set: function(aTarget, aName, aValue, aReceiver) {
if (descriptors.hasOwnProperty(aName)) {
if (typeof descriptors[aName].set == 'function')
return descriptors[aName].set.call(base, aValue);
else
return descriptors[aName].value = aValue;
}
return aImmutable[aName] = aValue;
},
deleteProperty: function(aTarget, aProperty) {
delete aImmutable[aProperty];
},
enumerate: function(aTarget) {
return Reflect.enumerate(aImmutable);
},
ownKeys: function(aTarget) {
return Object.getOwnPropertyNames(aImmutable);
},
apply: function(aTarget, aThis, aArgs) {
return aImmutable.apply(aThis, aArgs);
},
construct: function(aTarget, aArgs) {
return new aImmutable(...aArgs);
}
});
}