JDK-8029667 : Prototype linking is incorrect
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u20
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2013-12-06
  • Updated: 2014-07-29
  • Resolved: 2014-01-07
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.
8u20Fixed 9 b02Fixed
When a property is found in a prototype of the object, the linkage we emit is incorrect, as we emit a method bound to the prototype instance, but guarding on the map and switchpointing on an event listener for the map. Here's a little reproducer that will print "Expecting 2: 1" in the second line instead of "Expecting 2: 2" as ��� well ��� expected. The reason for this is that the second invocation of function "inner" will keep its linkage for "dyn:getProp:x" bound to the prototype - in this case, the scope obect of f(x) invocation from the first invocation with f(1), and neither the map guard nor the prototype guard will be invalidated.

function f(x) { 
  return (function inner() { 
      var y; (function dummy() { return y })() // force own scope for the inner function
      with({}) { // 'with' block turns off fast scopes
          // Getter for 'x' will now use prototype-bound linking. 
          // Unfortunately, it'll get bound to the scope of the first invocation of f(x).
          return x
print("Expecting 1: " + f(1))
print("Expecting 2: " + f(2))
Pushed fix to JDK9 repo as changeset 688:18eccb9656e0.

This can be relatively easily fixed for the cases where the property is found in a prototype without traversing a "with" block. In that case, instead of binding "methodHandle = bindTo(methodHandle, prototype)", we need to insert an argument filter that does the necessary number of getProto() calls on the receiver. Unfortunately, the presence of a "with" block throws this off. I have modified the test for JDK-8006984 to expose this case by looping twice over the with block, using a different object every time, and it indeed fails: var guiPkgs = [{ JFrame: function() { print("created1");} }, { JFrame: function() { print("created2");} }]; for(var i in guiPkgs) { with (guiPkgs[i]) { var main = function() { var frame; // <---- this local variable caused scope to be not set properly prior to fix function createFrame() { frame = new JFrame(); } createFrame(); } } main(); } Expected output is "created1" then "created2", but now it prints "created1" twice instead.