* Utility to see if a property has a getter associated to it or if * the property itself is a proxy object. * @returns {void}
(obj, astProp, cb)
| 725 | * @returns {void} |
| 726 | */ |
| 727 | function hasGetterOrIsProxy(obj, astProp, cb) { |
| 728 | if (!obj || !astProp) { |
| 729 | return cb(false); |
| 730 | } |
| 731 | |
| 732 | if (astProp.type === 'Literal') { |
| 733 | // We have something like `obj['foo'].x` where `x` is the literal |
| 734 | return propHasGetterOrIsProxy(obj, astProp.value, cb); |
| 735 | } |
| 736 | |
| 737 | if ( |
| 738 | astProp.type === 'Identifier' && |
| 739 | exprStr.at(astProp.start - 1) === '.' |
| 740 | ) { |
| 741 | // We have something like `obj.foo.x` where `foo` is the identifier |
| 742 | return propHasGetterOrIsProxy(obj, astProp.name, cb); |
| 743 | } |
| 744 | |
| 745 | return evalFn( |
| 746 | // Note: this eval runs the property expression, which might be side-effectful, for example |
| 747 | // the user could be running `obj[getKey()].` where `getKey()` has some side effects. |
| 748 | // Arguably this behavior should not be too surprising, but if it turns out that it is, |
| 749 | // then we can revisit this behavior and add logic to analyze the property expression |
| 750 | // and eval it only if we can confidently say that it can't have any side effects |
| 751 | `try { ${exprStr.slice(astProp.start, astProp.end)} } catch {} `, |
| 752 | ctx, |
| 753 | getREPLResourceName(), |
| 754 | (err, evaledProp) => { |
| 755 | if (err) { |
| 756 | return cb(false); |
| 757 | } |
| 758 | |
| 759 | if (typeof evaledProp === 'string') { |
| 760 | return propHasGetterOrIsProxy(obj, evaledProp, cb); |
| 761 | } |
| 762 | |
| 763 | return cb(false); |
| 764 | }, |
| 765 | ); |
| 766 | } |
| 767 | |
| 768 | return callback(false); |
| 769 | } |
no test coverage detected
searching dependent graphs…