@@ -731,35 +731,15 @@ function includesProxiesOrGetters(expr, exprStr, evalFn, ctx, callback) {
731731
732732 if (astProp.type === 'Literal') {
733733 // We have something like `obj['foo'].x` where `x` is the literal
734-
735- if (safeIsProxyAccess(obj, astProp.value)) {
736- return cb(true);
737- }
738-
739- const propDescriptor = ObjectGetOwnPropertyDescriptor(
740- obj,
741- `${astProp.value}`,
742- );
743- const propHasGetter = typeof propDescriptor?.get === 'function';
744- return cb(propHasGetter);
734+ return propHasGetterOrIsProxy(obj, astProp.value, cb);
745735 }
746736
747737 if (
748738 astProp.type === 'Identifier' &&
749739 exprStr.at(astProp.start - 1) === '.'
750740 ) {
751741 // We have something like `obj.foo.x` where `foo` is the identifier
752-
753- if (safeIsProxyAccess(obj, astProp.name)) {
754- return cb(true);
755- }
756-
757- const propDescriptor = ObjectGetOwnPropertyDescriptor(
758- obj,
759- `${astProp.name}`,
760- );
761- const propHasGetter = typeof propDescriptor?.get === 'function';
762- return cb(propHasGetter);
742+ return propHasGetterOrIsProxy(obj, astProp.name, cb);
763743 }
764744
765745 return evalFn(
@@ -773,37 +753,48 @@ function includesProxiesOrGetters(expr, exprStr, evalFn, ctx, callback) {
773753 getREPLResourceName(),
774754 (err, evaledProp) => {
775755 if (err) {
776- return callback (false);
756+ return cb (false);
777757 }
778758
779759 if (typeof evaledProp === 'string') {
780- if (safeIsProxyAccess(obj, evaledProp)) {
781- return cb(true);
782- }
783-
784- const propDescriptor = ObjectGetOwnPropertyDescriptor(
785- obj,
786- evaledProp,
787- );
788- const propHasGetter = typeof propDescriptor?.get === 'function';
789- return cb(propHasGetter);
760+ return propHasGetterOrIsProxy(obj, evaledProp, cb);
790761 }
791762
792- return callback (false);
763+ return cb (false);
793764 },
794765 );
795766 }
796767
797- function safeIsProxyAccess(obj, prop) {
798- // Accessing `prop` may trigger a getter that throws, so we use try-catch to guard against it
799- try {
800- return isProxy(obj[prop]);
801- } catch {
802- return false;
803- }
768+ return callback(false);
769+ }
770+
771+ /**
772+ * Given an object and a property name, checks whether the property has a getter, if not checks whether its
773+ * value is a proxy.
774+ *
775+ * Note: the order is relevant here, we want to check whether the property has a getter _before_ we check
776+ * whether its value is a proxy, to ensure that is the property does have a getter we don't end up
777+ * triggering it when checking its value
778+ * @param {any} obj The target object
779+ * @param {string | number | bigint | boolean | RegExp} prop The target property
780+ * @param {(includes: boolean) => void} cb Callback that will be called with the result of the operation
781+ * @returns {void}
782+ */
783+ function propHasGetterOrIsProxy(obj, prop, cb) {
784+ const propDescriptor = ObjectGetOwnPropertyDescriptor(
785+ obj,
786+ prop,
787+ );
788+ const propHasGetter = typeof propDescriptor?.get === 'function';
789+ if (propHasGetter) {
790+ return cb(true);
804791 }
805792
806- return callback(false);
793+ if (isProxy(obj[prop])) {
794+ return cb(true);
795+ }
796+
797+ return cb(false);
807798}
808799
809800module.exports = {
0 commit comments