aran-access-control
Version:
Access Control System for Aran
194 lines (174 loc) • 7.14 kB
JavaScript
const Proxy = global.Proxy;
const WeakMap = global.WeakMap;
const WeakMap_prototype_get = WeakMap.prototype.get;
const WeakMap_prototype_set = WeakMap.prototype.set;
const Array_isArray = Array.isArray;
const Reflect_apply = Reflect.apply;
const Reflect_construct = Reflect.construct;
const Reflect_defineProperty = Reflect.defineProperty;
const Reflect_deleteProperty = Reflect.deleteProperty;
const Reflect_get = Reflect.get;
const Reflect_getOwnPropertyDescriptor = Reflect.getOwnPropertyDescriptor;
const Reflect_getPrototypeOf = Reflect.getPrototypeOf;
const Reflect_has = Reflect.has;
const Reflect_isExtensible = Reflect.isExtensible;
const Reflect_preventExtensions = Reflect.preventExtensions;
const Reflect_ownKeys = Reflect.ownKeys;
const Reflect_set = Reflect.set;
const Reflect_setPrototypeOf = Reflect.setPrototypeOf;
module.exports = (membrane, release, capture) => {
const objects = new WeakMap();
objects.get = WeakMap_prototype_get;
objects.set = WeakMap_prototype_set;
const handlers = {};
handlers.apply = (target, value, values) => {
const object = objects.get(target);
for (let index = 0, length = values.length; index < length; index++)
values[index] = release(membrane.leave(values[index]));
return membrane.enter(capture(Reflect_apply(object, release(value), values)));
};
handlers.construct = (target, values) => {
const object = objects.get(target);
for (let index = 0, length = values.length; index < length; index++)
values[index] = release(membrane.leave(values[index]));
return membrane.enter(capture(Reflect_construct(object, values)));
};
handlers.defineProperty = (target, key, descriptor) => {
if ("value" in descriptor) {
descriptor.value = release(membrane.leave(descriptor.value));
} else {
if ("get" in descriptor)
descriptor.get = release(descriptor.get);
if ("set" in descriptor)
descriptor.set = release(descriptor.set);
}
return Reflect_defineProperty(objects.get(target), key, descriptor);
};
handlers.deleteProperty = (target, key) => Reflect_deleteProperty(objects.get(target), key);
handlers.get = (target, key, receiver) => {
const descriptor1 = Reflect_getOwnPropertyDescriptor(target, key);
if (descriptor1 && "value" in descriptor1 && !descriptor1.configurable && !descriptor1.writable)
return descriptor1.value;
const object = objects.get(target);
const descriptor2 = Reflect_getOwnPropertyDescriptor(object, key);
if (descriptor2) {
if ("value" in descriptor2) {
if (descriptor2.writable || descriptor2.configurable)
return membrane.enter(capture(descriptor2.value));
descriptor2.value = membrane.enter(capture(descriptor2.value));
Reflect_defineProperty(target, key, descriptor2);
return descriptor2.value;
}
if ("get" in descriptor2)
return membrane.enter(capture(Reflect_apply(descriptor2.get, release(receiver), [])));
return void 0;
}
const prototype = Reflect_getPrototypeOf(object);
if (prototype)
return Reflect_get(capture(prototype), key, receiver);
if (key === "__proto__")
return Reflect_getPrototypeOf(receiver);
return void 0;
};
handlers.getOwnPropertyDescriptor = (target, key) => {
const descriptor1 = Reflect_getOwnPropertyDescriptor(target, key);
if (descriptor1 && !descriptor1.configurable && !descriptor1.writable)
return descriptor1;
const object = objects.get(target);
const descriptor2 = Reflect_getOwnPropertyDescriptor(object, key);
if (descriptor2) {
if ("value" in descriptor2) {
descriptor2.value = membrane.enter(capture(descriptor2.value));
} else {
descriptor2.get = capture(descriptor2.get);
descriptor2.set = capture(descriptor2.set);
}
if (!descriptor2.configurable || (!Reflect_isExtensible(target) && descriptor1)) {
Reflect_defineProperty(target, key, descriptor2);
}
} else if (descriptor1 && Reflect_isExtensible(target)) {
deleteProperty(target, key);
}
return descriptor2;
};
handlers.getPrototypeOf = (target) => capture(Reflect_getPrototypeOf(objects.get(target)));
handlers.has = (target, key) => {
if (Reflect_has(objects.get(target), key))
return true;
const descriptor = Reflect_getOwnPropertyDescriptor(target, key);
if (descriptor && (!descriptor.configurable || !Reflect_isExtensible))
Reflect_deleteProperty(target, key);
return false;
};
handlers.isExtensible = (target) => {
const object = objects.get(target);
if (Reflect_isExtensible(object))
return true;
if (Reflect_isExtensible(target)) {
const keys = Reflect_ownKeys(object);
for (let index = 0, length = keys.length; index < length; index++) {
if (!Reflect_getOwnPropertyDescriptor(target, keys[index])) {
Reflect_defineProperty(target, keys[index], {value:null, configurable:true});
}
}
Reflect_setPrototypeOf(target, capture(Reflect.getPrototypeOf(object)));
Reflect_preventExtensions(target);
}
return false;
};
handlers.ownKeys = (target) => {
const object = objects.get(target);
if (!Reflect_isExtensible(target)) {
const keys = Reflect_ownKeys(target);
for (let index = 0, length = keys.length; index < length; index++) {
if (!Reflect_getOwnPropertyDescriptor(object, keys[index])) {
Reflect_deleteProperty(target, keys[index]);
}
}
}
return Reflect_ownKeys(object);
};
handlers.preventExtensions = (target) => Reflect.preventExtensions(objects.get(target));
handlers.set = (target, key, value, receiver) => {
const object = objects.get(target);
const descriptor = Reflect_getOwnPropertyDescriptor(object, key);
if (descriptor) {
if (descriptor.writable) {
if (release(receiver) === object) {
descriptor.value = release(membrane.leave(value));
Reflect_defineProperty(object, key, descriptor);
} else {
Reflect_defineProperty(receiver, key, {
value: value,
writable: true,
enumerable: true,
configurable: true
});
}
return true;
}
if ("set" in descriptor) {
Reflect_apply(descriptor.set, release(receiver), [release(membrane.leave(value))]);
return true;
}
return false;
}
const prototype = Reflect_getPrototypeOf(object);
if (prototype)
return Reflect_set(capture(prototype), key, value, receiver);
if (key === "__proto__")
return false;
return Reflect_defineProperty(receiver, key, {
value: value,
writable: true,
enumerable: true,
configurable: true
});
};
handlers.setPrototypeOf = (target, prototype) => Reflect_setPrototypeOf(object, release(prototype));
return (object) => {
const target = Array_isArray(object) ? [] : (typeof object === "function" ? (function () {}) : {});
objects.set(target, object);
return new Proxy(target, handlers);
};
};