JDK-8051778 : Function.prototype.bind doesn't work on all callables
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u40
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2014-07-23
  • Updated: 2015-06-04
  • Resolved: 2014-11-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
8u40Fixed 9 b42Fixed
Related Reports
Relates :  
I will reduce the scope of this issue to making sure that everything that Nashorn recognizes as [[Callable]] can be used with Function.prototype.bind. This is because Function.prototype.call already works with all [[Callable]] objects. Function.prototype.apply also sort-of works, with the caveat that it's by its nature a variable-arity invocation, so at least when linked with POJO methods, it'll only work as long as the method itself is variable-arity. That's a limitation I can live with. On the other side, the question is whether we want to provide synthetic properties on these callables. E.g. if something is a [[Callable]], should it expose properties named "bind", "call", and "apply"? In the end, I decided against this. One callable is StaticClass; these properties would clash with static methods of the same name on classes. Additionally, lots of java.util.function.* interfaces have an "apply" method; java.util.Callable has a "call" method. For these reasons, I think exposing synthetic properties is harmful. Instead, explicit call of Function.prototype functions can be used: callable.call(...) => Function.prototype.call.call(callable, ...) callable.bind(...) => Function.prototype.bind.call(callable, ...) callbale.apply(...) => Function.prototype.apply.call(callable, ...)

Preliminary testing shows that even though DynamicMethod objects don't expose .call method, Function.call.call(pojoMethod, newThis, args���) actually works as we're very good about specially-linking Function.call, so it ends up being linked as a dyn:call on the actual argument as long as the expression evaluates to Function.call (or apply), e.g. even Function.call.call.call.call.call ��� would be recognized, although if you nest 'em deep enough, you can get a StackOverflowError in the linker :-) Apply and bind can actually be invoked with the same trick, e.g. Function.bind.call(pojoMethod, boundThis, boundArgs) but they don't work yet. Apply seems to have some kinks, and bind just plain does not work (because its code is written specifically only for ScriptFunction). So there's some work to do. After we'd got them to work, the next step would be to ensure they are also exposed as properties on DynamicMethod objects. There are two approaches to this that I can see. Approach 1 is to add a new NashornDynamicMethodLinker to Nashorn's Bootstrap class to answer "dyn:getProp:call", "dyn:getProp:apply", "dyn:getProp:bind". The problem with this approach is that we also need to add linkage for "dyn:getElem" with no fixed argument, and then if that ends up not being one of these three, then treat it as bottom linker would. Approach 2 would be to add customization ability to the built-in Dynalink DynamicMethodLinker. Right now, DynamicMethodLinker doesn't go through BeansLinker, but maybe some sort of ability to customize Dynalink's FacetIntrospector would be desirable, to add language-specific synthetic properties to POJOs. I'm admittedly a bit undecided about this, just throwing it out as an idea here. This actually might be relevant to JDK-8057173 too, which currently lacks the ability to fall back from a "dyn:getElem" for a non-existent element to a language-specific behavior (e.g. treating the POJO as a sealed object). Currently it seems like only language-specific customization could solve this, although another idea ("LinkerServices.getFallbackLinkage()" -- basically ask linker services for a linkage of the form "if I couldn't link this, what would the rest of the linker chain do").