207 return exprProperty; 208 } 209 return super.findProperty(key, deep, start); 210 } 211 212 @Override 213 protected Object invokeNoSuchProperty(final String name, final int programPoint) { 214 FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true); 215 if (find != null) { 216 final Object func = find.getObjectValue(); 217 if (func instanceof ScriptFunction) { 218 return ScriptRuntime.apply((ScriptFunction)func, expression, name); 219 } 220 } 221 222 return getProto().invokeNoSuchProperty(name, programPoint); 223 } 224 225 @Override 226 public void setSplitState(final int state) { 227 getNonWithParent().setSplitState(state); 228 } 229 230 @Override 231 public int getSplitState() { 232 return getNonWithParent().getSplitState(); 233 } 234 235 /** 236 * Get first parent scope that is not an instance of WithObject. 237 */ 238 private Scope getNonWithParent() { 239 ScriptObject proto = getParentScope(); 240 241 while (proto != null && proto instanceof WithObject) { 242 proto = ((WithObject)proto).getParentScope(); 243 } 244 245 assert proto instanceof Scope : "with scope without parent scope"; 246 return (Scope) proto; 247 } 248 249 250 private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) { 251 // The receiver may be an Object or a ScriptObject. 252 final MethodType invType = link.getInvocation().type(); 253 final MethodType newInvType = invType.changeParameterType(0, filter.type().returnType()); 254 return link.asType(newInvType); 255 } 256 257 private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) { 258 // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its 259 // expression. 260 if (!"getMethod".equals(desc.getFirstOperator())) { 261 return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER); 262 } 263 264 final MethodHandle linkInvocation = link.getInvocation(); 265 final MethodType linkType = linkInvocation.type(); 266 final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType()); 267 268 return link.replaceMethods( 269 // Make sure getMethod will bind the script functions it receives to WithObject.expression 361 @SuppressWarnings("unused") 362 private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) { 363 return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated()); 364 } 365 366 /** 367 * Drops the WithObject wrapper from the scope. 368 * @param receiver WithObject wrapper. 369 * @return The with scope. 370 */ 371 public static Object withFilterScope(final Object receiver) { 372 return ((WithObject)receiver).getProto(); 373 } 374 375 /** 376 * Get the with expression for this {@code WithObject} 377 * @return the with expression 378 */ 379 public ScriptObject getExpression() { 380 return expression; 381 } 382 383 /** 384 * Get the parent scope for this {@code WithObject} 385 * @return the parent scope 386 */ 387 public ScriptObject getParentScope() { 388 return getProto(); 389 } 390 391 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 392 return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types)); 393 } 394 } | 207 return exprProperty; 208 } 209 return super.findProperty(key, deep, start); 210 } 211 212 @Override 213 protected Object invokeNoSuchProperty(final String name, final int programPoint) { 214 FindProperty find = expression.findProperty(NO_SUCH_PROPERTY_NAME, true); 215 if (find != null) { 216 final Object func = find.getObjectValue(); 217 if (func instanceof ScriptFunction) { 218 return ScriptRuntime.apply((ScriptFunction)func, expression, name); 219 } 220 } 221 222 return getProto().invokeNoSuchProperty(name, programPoint); 223 } 224 225 @Override 226 public void setSplitState(final int state) { 227 ((Scope) getNonWithParent()).setSplitState(state); 228 } 229 230 @Override 231 public int getSplitState() { 232 return ((Scope) getNonWithParent()).getSplitState(); 233 } 234 235 @Override 236 public void addBoundProperties(final ScriptObject source, final Property[] properties) { 237 // Declared variables in nested eval go to first normal (non-with) parent scope. 238 getNonWithParent().addBoundProperties(source, properties); 239 } 240 241 /** 242 * Get first parent scope that is not an instance of WithObject. 243 */ 244 private ScriptObject getNonWithParent() { 245 ScriptObject proto = getProto(); 246 247 while (proto != null && proto instanceof WithObject) { 248 proto = proto.getProto(); 249 } 250 251 return proto; 252 } 253 254 private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) { 255 // The receiver may be an Object or a ScriptObject. 256 final MethodType invType = link.getInvocation().type(); 257 final MethodType newInvType = invType.changeParameterType(0, filter.type().returnType()); 258 return link.asType(newInvType); 259 } 260 261 private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) { 262 // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its 263 // expression. 264 if (!"getMethod".equals(desc.getFirstOperator())) { 265 return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER); 266 } 267 268 final MethodHandle linkInvocation = link.getInvocation(); 269 final MethodType linkType = linkInvocation.type(); 270 final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType()); 271 272 return link.replaceMethods( 273 // Make sure getMethod will bind the script functions it receives to WithObject.expression 365 @SuppressWarnings("unused") 366 private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) { 367 return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated()); 368 } 369 370 /** 371 * Drops the WithObject wrapper from the scope. 372 * @param receiver WithObject wrapper. 373 * @return The with scope. 374 */ 375 public static Object withFilterScope(final Object receiver) { 376 return ((WithObject)receiver).getProto(); 377 } 378 379 /** 380 * Get the with expression for this {@code WithObject} 381 * @return the with expression 382 */ 383 public ScriptObject getExpression() { 384 return expression; 385 } 386 387 private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) { 388 return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types)); 389 } 390 } |