@@ -66,7 +66,12 @@ protected OptionalChainNode(JavaScriptNode chainNode, Object result) {
6666 }
6767
6868 public static JavaScriptNode createTarget (JavaScriptNode chainNode ) {
69- return new OptionalChainNode (chainNode , chainNode instanceof DeletePropertyNode ? Boolean .TRUE : Undefined .instance );
69+ Object result = (chainNode instanceof DeletePropertyNode ) ? Boolean .TRUE : Undefined .instance ;
70+ if (chainNode instanceof JSTargetableNode ) {
71+ return new OptionalTargetableNode ((JSTargetableNode ) chainNode , result );
72+ } else {
73+ return new OptionalChainNode (chainNode , result );
74+ }
7075 }
7176
7277 public static JavaScriptNode createShortCircuit (JavaScriptNode expressionNode ) {
@@ -120,6 +125,58 @@ public JavaScriptNode getAccessNode() {
120125 return accessNode ;
121126 }
122127
128+ public static final class OptionalTargetableNode extends JSTargetableNode {
129+ private static final Object SHORT_CIRCUIT_MARKER = new Object ();
130+ @ Child private JSTargetableNode delegateNode ;
131+ private final Object result ;
132+
133+ protected OptionalTargetableNode (JSTargetableNode delegateNode , Object result ) {
134+ this .delegateNode = delegateNode ;
135+ this .result = result ;
136+ }
137+
138+ @ Override
139+ public JavaScriptNode getTarget () {
140+ return delegateNode .getTarget ();
141+ }
142+
143+ @ Override
144+ public Object evaluateTarget (VirtualFrame frame ) {
145+ try {
146+ return delegateNode .evaluateTarget (frame );
147+ } catch (ShortCircuitException ex ) {
148+ return SHORT_CIRCUIT_MARKER ;
149+ }
150+ }
151+
152+ @ Override
153+ public Object executeWithTarget (VirtualFrame frame , Object target ) {
154+ if (target == SHORT_CIRCUIT_MARKER ) {
155+ return result ;
156+ }
157+ return delegateNode .executeWithTarget (frame , target );
158+ }
159+
160+ @ Override
161+ public Object execute (VirtualFrame frame ) {
162+ try {
163+ return delegateNode .execute (frame );
164+ } catch (ShortCircuitException ex ) {
165+ return result ;
166+ }
167+ }
168+
169+ @ Override
170+ protected JavaScriptNode copyUninitialized (Set <Class <? extends Tag >> materializedTags ) {
171+ return new OptionalTargetableNode (cloneUninitialized (delegateNode , materializedTags ), result );
172+ }
173+
174+ public JavaScriptNode getDelegateNode () {
175+ return delegateNode ;
176+ }
177+
178+ }
179+
123180 /**
124181 * Evaluates an optional expression and if its value is null or undefined, jumps out of the
125182 * short-circuiting expression to the parent {@link OptionalChainNode}.
0 commit comments