Skip to content
Snippets Groups Projects
Commit fe8216a6 authored by Pregmodder's avatar Pregmodder
Browse files

Merge branch 'feature/readonly-proxy-for-set' into 'pregmod-master'

Extend readonly proxy support to cover Set and Map

See merge request !10453
parents 12fca6bb 111c29d1
No related branches found
No related tags found
1 merge request!10453Extend readonly proxy support to cover Set and Map
Pipeline #44545 passed
(function() {
const readOnlySymbol = Symbol("readonly proxy");
const dummy = () => true;
/**
* Creates a readonly proxy for all the target properties except banned methods
* @param {any} target
* @param {string[]} bannedMethodNames The list of method names that are banned and can't be accesses via the proxy
* @param {string} errorMessage message for throwing exceptions
*/
const createProxyWithBannedMethods = (target, bannedMethodNames, errorMessage) => {
return new Proxy(target, {
get: function(o, prop) {
if (prop === readOnlySymbol) { return true; }
const val = o[prop];
if (typeof val === 'function') {
if (bannedMethodNames.includes(prop)) {
return function() {
throw Error(errorMessage);
};
}
return val.bind(target);
}
return createReadonlyProxy(val);
},
set: dummy,
deleteProperty: dummy
});
};
globalThis.createReadonlyProxy = function(target) {
if (target == null) { return target; } // intentionally ==
if (target[readOnlySymbol]) { return target; }
if (_.isArray(target)) {
return new Proxy(target, {
get: function(o, prop) {
if (prop === readOnlySymbol) { return true; }
const val = o[prop];
if (typeof val === 'function') {
if (['push', 'unshift', 'pop'].includes(prop)) {
return function() {
throw Error("Cannot modify a readonly array");
};
}
return val.bind(target);
}
return createReadonlyProxy(val);
},
set: function(o, prop, value) {
return true;
},
deleteProperty: function(o, prop) {
return true;
}
});
}
if (_.isObject(target)) {
return createProxyWithBannedMethods(target, ['push', 'unshift', 'pop'], "Cannot modify a readonly array");
} else if (_.isMap(target)) {
return createProxyWithBannedMethods(target, ['clear', 'delete', 'set'], "Cannot modify a readonly Map");
} else if (_.isSet(target)) {
return createProxyWithBannedMethods(target, ['add', 'clear', 'delete'], "Cannot modify a readonly Set");
} else if (_.isObject(target)) {
return new Proxy(target, {
get: function(o, prop) {
if (prop === readOnlySymbol) { return true; }
return createReadonlyProxy(o[prop]);
},
set: function(o, prop, value) {
return true;
},
deleteProperty: function(o, prop) {
return true;
}
set: dummy,
deleteProperty: dummy
});
}
return target;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment