Skip to content

Commit b153be6

Browse files
committed
AG-27573 Fix set-constant - set proxy trap only once #380
Squashed commit of the following: commit d325bd7 Merge: 95fded6 f5c5921 Author: Adam Wróblewski <adam@adguard.com> Date: Mon Nov 13 13:16:59 2023 +0100 Merge branch 'master' into fix/AG-27573 commit 95fded6 Author: Slava Leleka <v.leleka@adguard.com> Date: Fri Nov 10 20:27:54 2023 +0300 Update test commit b30f892 Author: Slava Leleka <v.leleka@adguard.com> Date: Fri Nov 10 20:27:42 2023 +0300 Update test commit f76eaf3 Author: Adam Wróblewski <adam@adguard.com> Date: Fri Nov 10 17:57:42 2023 +0100 Update test commit f5543e8 Author: Adam Wróblewski <adam@adguard.com> Date: Fri Nov 10 15:58:22 2023 +0100 Fix set-constant - set proxy trap only once
1 parent f5c5921 commit b153be6

File tree

3 files changed

+56
-14
lines changed

3 files changed

+56
-14
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1919

2020
### Fixed
2121

22+
- issue with setting proxy trap every time when property is accessed in `set-constant` scriptlet
23+
[#380](https://github.com/AdguardTeam/Scriptlets/issues/380)
2224
- issue with `stack` in `evaldata-prune` scriptlet [#378](https://github.com/AdguardTeam/Scriptlets/issues/378)
2325
- issue with setting values to wrong properties in `set-constant` scriptlet
2426
[#373](https://github.com/AdguardTeam/Scriptlets/issues/373)

src/scriptlets/set-constant.js

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ export function setConstant(source, property, value, stack = '', valueWrapper =
155155
return;
156156
}
157157

158+
let isProxyTrapSet = false;
159+
158160
const emptyArr = noopArray();
159161
const emptyObj = noopObject();
160162

@@ -297,20 +299,23 @@ export function setConstant(source, property, value, stack = '', valueWrapper =
297299
// Get properties which should be checked and remove first one
298300
// because it's current object
299301
const propertiesToCheck = property.split('.').slice(1);
300-
a = new Proxy(a, {
301-
get: (target, propertyKey, val) => {
302-
// Check if object contains required property, if so
303-
// check if current value is equal to constantValue, if not, set it to constantValue
304-
propertiesToCheck.reduce((object, currentProp, index, array) => {
305-
const currentObj = object?.[currentProp];
306-
if (currentObj && index === array.length - 1 && currentObj !== constantValue) {
307-
object[currentProp] = constantValue;
308-
}
309-
return currentObj || object;
310-
}, target);
311-
return Reflect.get(target, propertyKey, val);
312-
},
313-
});
302+
if (!isProxyTrapSet) {
303+
isProxyTrapSet = true;
304+
a = new Proxy(a, {
305+
get: (target, propertyKey, val) => {
306+
// Check if object contains required property, if so
307+
// check if current value is equal to constantValue, if not, set it to constantValue
308+
propertiesToCheck.reduce((object, currentProp, index, array) => {
309+
const currentObj = object?.[currentProp];
310+
if (currentObj && index === array.length - 1 && currentObj !== constantValue) {
311+
object[currentProp] = constantValue;
312+
}
313+
return currentObj || object;
314+
}, target);
315+
return Reflect.get(target, propertyKey, val);
316+
},
317+
});
318+
}
314319
}
315320
handler.set(a);
316321
},

tests/scriptlets/set-constant.test.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -795,4 +795,39 @@ if (!isSupported) {
795795
assert.strictEqual(window.something.start, undefined, 'something.start was not set');
796796
clearGlobalProps('something');
797797
});
798+
799+
test('Check if proxy was not set many times', (assert) => {
800+
runScriptletFromTag('proxy.test.abc', 'trueFunc');
801+
802+
// Expected number of calls to getOwnPropertyDescriptor
803+
const EXPECTED_NUMBER = 4;
804+
805+
let number = 0;
806+
window.proxy = window.proxy || {};
807+
808+
const handler = {
809+
getOwnPropertyDescriptor(target, prop) {
810+
number += 1;
811+
return Reflect.getOwnPropertyDescriptor(target, prop);
812+
},
813+
};
814+
815+
window.proxy = new Proxy(window.proxy, handler);
816+
817+
// Access object 100 times, if getOwnPropertyDescriptor was called more than 4 times
818+
// it means that proxy was set more than once
819+
for (let index = 0; index < 100; index += 1) {
820+
if (number > EXPECTED_NUMBER) {
821+
break;
822+
}
823+
window.proxy = window.proxy || {};
824+
}
825+
window.proxy.test = {
826+
abc: () => false,
827+
};
828+
const result = window.proxy.test.abc();
829+
assert.strictEqual(result, true, 'proxy.test.abc set to true by scriptlet');
830+
assert.strictEqual(number, EXPECTED_NUMBER, `getOwnPropertyDescriptor was called ${EXPECTED_NUMBER} times`);
831+
clearGlobalProps('proxy');
832+
});
798833
}

0 commit comments

Comments
 (0)