@Override public GuardedInvocation getGuardedInvocation( final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception { final LinkRequest request = linkRequest.withoutRuntimeContext(); // Nashorn has no runtime context final Object self = request.getReceiver(); if (self.getClass() != StaticClass.class) { return null; } final Class<?> receiverClass = ((StaticClass) self).getRepresentedClass(); Bootstrap.checkReflectionAccess(receiverClass, true); final CallSiteDescriptor desc = request.getCallSiteDescriptor(); // We intercept "new" on StaticClass instances to provide additional capabilities if ("new".equals(desc.getNameToken(CallSiteDescriptor.OPERATOR))) { if (!Modifier.isPublic(receiverClass.getModifiers())) { throw ECMAErrors.typeError("new.on.nonpublic.javatype", receiverClass.getName()); } // make sure new is on accessible Class Context.checkPackageAccess(receiverClass); // Is the class abstract? (This includes interfaces.) if (NashornLinker.isAbstractClass(receiverClass)) { // Change this link request into a link request on the adapter class. final Object[] args = request.getArguments(); args[0] = JavaAdapterFactory.getAdapterClassFor( new Class<?>[] {receiverClass}, null, linkRequest.getCallSiteDescriptor().getLookup()); final LinkRequest adapterRequest = request.replaceArguments(request.getCallSiteDescriptor(), args); final GuardedInvocation gi = checkNullConstructor(delegate(linkerServices, adapterRequest), receiverClass); // Finally, modify the guard to test for the original abstract class. return gi.replaceMethods(gi.getInvocation(), Guards.getIdentityGuard(self)); } // If the class was not abstract, just delegate linking to the standard StaticClass linker. // Make an // additional check to ensure we have a constructor. We could just fall through to the next // "return" // statement, except we also insert a call to checkNullConstructor() which throws an // ECMAScript TypeError // with a more intuitive message when no suitable constructor is found. return checkNullConstructor(delegate(linkerServices, request), receiverClass); } // In case this was not a "new" operation, just delegate to the the standard StaticClass linker. return delegate(linkerServices, request); }
/** * Takes a guarded invocation, and ensures its method and guard conform to the type of the call * descriptor, using all type conversions allowed by the linker's services. This method is used by * Nashorn's linkers as a last step before returning guarded invocations. Most of the code used to * produce the guarded invocations does not make an effort to coordinate types of the methods, and * so a final type adjustment before a guarded invocation is returned to the aggregating linker is * the responsibility of the linkers themselves. * * @param inv the guarded invocation that needs to be type-converted. Can be null. * @param linkerServices the linker services object providing the type conversions. * @param desc the call site descriptor to whose method type the invocation needs to conform. * @return the type-converted guarded invocation. If input is null, null is returned. If the input * invocation already conforms to the requested type, it is returned unchanged. */ static GuardedInvocation asTypeSafeReturn( final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) { return inv == null ? null : inv.asTypeSafeReturn(linkerServices, desc.getMethodType()); }