Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8062132

Nashorn incorrectly binds "this" for constructor created by another function

    XMLWordPrintable

    Details

    • Subcomponent:
    • Introduced In Version:
    • Resolved In Build:
      b39
    • CPU:
      x86
    • OS:
      os_x
    • Verification:
      Verified

      Backports

        Description

        FULL PRODUCT VERSION :
        java version "1.8.0_25"
        Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
        Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)

        ADDITIONAL OS VERSION INFORMATION :
        Mac OS X 10.9.5

        EXTRA RELEVANT SYSTEM CONFIGURATION :
        Standard Macbook Pro setup

        A DESCRIPTION OF THE PROBLEM :
        When a higher order function is used to create JavaScript constructor functions, Nashorn incorrectly binds the "this" var within the created constructor function in some cases. This seems to be limited to cases where:

        * Higher order function used to generate constructors
        * Two child constructors share the same parent prototype.
        * The two child prototypes disagree in the *number* of properties.

        When the second of the two children is instantiated, its constructor's "this" var is incorrectly bound to the Parent's object rather than the Child's. To demonstrate this, I've included a reduction in the "Source code for an executable test case" section below.

        One really strange aspect of this is that the two "Child" constructors must disagree in the *number* of properties to trigger the failure. Notice that Child1 has a single property "prop1", but Child2 has none. If you add any property to Child2, the error goes away. If you then add a property to Child1, the error returns.

        This test case functions properly in all major browsers and in previous JDK version 1.8.0_05

        REGRESSION. Last worked in version 8u5

        ADDITIONAL REGRESSION INFORMATION:
        java version "1.8.0_05"
        Java(TM) SE Runtime Environment (build 1.8.0_05-b13)
        Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode)

        STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
        Use jrunscript to run the reduction provided in the "Source code for an executable test case" section below.


        EXPECTED VERSUS ACTUAL BEHAVIOR :
        EXPECTED -
        The script should run without error, producing the following output:

        !!! child 1
        !!! child 2
        ACTUAL -
        It reaches line 18, where it tries calling "this.init()". This should work, since we're dealing with an instance of "Child2", which has overridden the "init" function. It fails, however, because "this" is incorrectly bound to the "Parent" object, for which "init" is null:

        !!! child 1
        script error in file scripts/test2.js : TypeError: null is not a function in scripts/nashorn_this_binding_bug_reduction.js at line number 18

        ERROR MESSAGES/STACK TRACES THAT OCCUR :
        script error in file scripts/test2.js : TypeError: null is not a function in scripts/nashorn_this_binding_bug_reduction.js at line number 18

        REPRODUCIBILITY :
        This bug can be reproduced always.

        ---------- BEGIN SOURCE ----------
        function subclass(parentConstructor, proto) {
          function C() {
            parentConstructor.call(this);
          }
          
          C.prototype = Object.create(parentConstructor.prototype);

          for (var prop in proto) {
            if (proto.hasOwnProperty(prop)) {
              C.prototype[prop] = proto[prop];
            }
          }
          
          return C;
        }

        var Parent = function() {
          this.init();
        };

        Parent.prototype = {
          init: null
        }

        var Child1 = subclass(Parent, {
          prop1: 1,
          init: function() {
            print('!!! child 1');
          }
        });

        var Child2 = subclass(Parent, {
          init: function() {
            print('!!! child 2');
          }
        });

        new Child1();
        new Child2();

        ---------- END SOURCE ----------

        CUSTOMER SUBMITTED WORKAROUND :
        No workaround available. Many 3rd party products use this type of inheritance pattern in JavaScript.

          Attachments

            Issue Links

              Activity

                People

                Assignee:
                hannesw Hannes Wallnoefer
                Reporter:
                webbuggrp Webbug Group
                Votes:
                0 Vote for this issue
                Watchers:
                6 Start watching this issue

                  Dates

                  Created:
                  Updated:
                  Resolved: