diff --git a/src/004-base/000-proxies.js b/src/004-base/000-proxies.js index 69b72acd7d6e9cf89d4301989b3a20a0c8de9df6..9738e68bf063ed42b792f6cf905465fcf22ba7f9 100644 --- a/src/004-base/000-proxies.js +++ b/src/004-base/000-proxies.js @@ -1,43 +1,50 @@ (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; diff --git a/src/endWeek/saSocialEffects.js b/src/endWeek/saSocialEffects.js index 3682c374157267ddc237db94b05269169aed8c89..6e83d548e3e7d8c7f2110060d415b5fd483db84d 100644 --- a/src/endWeek/saSocialEffects.js +++ b/src/endWeek/saSocialEffects.js @@ -723,7 +723,6 @@ App.SlaveAssignment.saSocialEffects = function(slave) { if (slave.geneMods.NCS > 0 && (slave.boobs <= 2000 || slave.butt <= 7)) { t.push(new SocialEffect("Asset Expansionist", -2, `NCS Youthening`, `Society <span class="red">strongly disapproves</span> of ${slave.slaveName} who can't get bigger; ${his} shrinking body hurts the fashion for Asset expansion.`)); - assets++; } if (slave.boobs > 2000) { t.push(new SocialEffect("Asset Expansionist", 1, `Titanic tits`, diff --git a/src/events/RESS/review/heavyPiercing.js b/src/events/RESS/review/heavyPiercing.js index f51e22078c50d42f0063705084a84723a0b43826..700b8e259c01f9ca2e311ff02c0c6ad3506aae8b 100644 --- a/src/events/RESS/review/heavyPiercing.js +++ b/src/events/RESS/review/heavyPiercing.js @@ -57,7 +57,7 @@ App.Events.RESSHeavyPiercing = class RESSHeavyPiercing extends App.Events.BaseEv r.push(`with ${his} legs spread,`); } if (eventSlave.belly >= 50000) { - r.push(`, belly brushing the floor,`); + r.push(r.pop() + `, belly brushing the floor,`); } if (canSee(eventSlave)) { r.push(`blindfold ${him},`); diff --git a/src/npc/interaction/fDance.js b/src/npc/interaction/fDance.js index f058b5a22116dc92cdbb00dceb46dfe33f92f393..466ffa260eb2836a00585cb8188055c61b5c4673 100644 --- a/src/npc/interaction/fDance.js +++ b/src/npc/interaction/fDance.js @@ -910,7 +910,7 @@ App.Interact.fDance = function(slave) { r.push(`s`); } } - r.push(`, but is open in front, leaving ${his}`); + r.push(r.pop() + `, but is open in front, leaving ${his}`); if (slave.boobs > 4000) { r.push(`boobs completely bare. It tucks into a golden belt, though this is buried under ${his} breasts.`); } else if (slave.boobs > 300) { diff --git a/src/pregmod/FCTV/FCTVshows.js b/src/pregmod/FCTV/FCTVshows.js index c9a7901f3aafeb520f33d54616f3cf3c10013aa9..4c36f4463a6ddd65432bb0a15c4c27b483dac9ca 100644 --- a/src/pregmod/FCTV/FCTVshows.js +++ b/src/pregmod/FCTV/FCTVshows.js @@ -1508,9 +1508,11 @@ App.Data.FCTV.channels = { if (V.purchasedSagBGone === 1) { r.push(`You've already made the mistake of ordering the sham of a product. While it gave you a great excuse to fondle breasts, it's not like you needed one in the first place.</p>`); if (S.Concubine && canTalk(S.Concubine)) { - r.push(`<p>`); - r.push(Spoken(S.Concubine, `"I told you it wouldn't work, ${Master}. Plus you know you can touch these anytime!"`)); - r.push(`${S.Concubine.slaveName} shakes ${his} chest at you.</p>`); + r.push( + `<p>`, + Spoken(S.Concubine, `"I told you it wouldn't work, ${Master}. Plus you know you can touch these anytime!"`), + `${S.Concubine.slaveName} shakes ${his} chest at you.</p>` + ); } } else { if (FCTV.channelCount(11, 1, 'gt')) {