JDK-8204560 : Global scope passed as "thiz" arg in JSObject.call(Object,Object[])
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u152,9,10,11
  • Priority: P3
  • Status: Resolved
  • Resolution: Not an Issue
  • OS: windows_8
  • CPU: x86_64
  • Submitted: 2018-06-07
  • Updated: 2018-11-29
  • Resolved: 2018-06-11
Related Reports
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Microsoft Windows [Version 6.3.9600]

java version "1.8.0_172"
Java(TM) SE Runtime Environment (build 1.8.0_172-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)

A DESCRIPTION OF THE PROBLEM :
When having a host object (JSObject implementation) in the global scope, and calling it like a function (without an owner), the global scope object is erroneously passed as an argument to the JSObject's call(Object,Object[]) method as the first argument.

This is regardless of strict mode: it happens either way.

Extra information: my guess would be that this is a result of changes made for JDK-8170565

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Run the supplied code. 

Uncomment the "use strict" line to see that this happens regardless of strict mode.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The following output:
undefined
ACTUAL -
The following output:
[object global]

---------- BEGIN SOURCE ----------
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import jdk.nashorn.api.scripting.AbstractJSObject;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.api.scripting.NashornScriptEngineFactory;

public class A {

    public static void main(String[] args) throws Exception {
        ScriptEngine se = ((NashornScriptEngineFactory) new ScriptEngineManager()
                .getEngineFactories()
                .get(0))
                .getScriptEngine( //
                //                        "-strict"
                );

        JSObject o = (JSObject) se.eval("var a = ({}); a;");
        o.setMember("something", new AbstractJSObject() {
            @Override
            public Object call(Object thiz, Object... args) {
                System.out.println(thiz);
                return null;
            }

        });
        se.eval("var b = a.something; b();");
    }

}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
There is no workaround.

FREQUENCY : always



Comments
The JSObject interface has a boolean isStrictFunction() method for exactly this use case. AbstractJSObject aways returns false in that method. Overriding it to return true causes the function to be called with undefined "this" argument. o.setMember("strictFn", new AbstractJSObject() { @Override public Object call(Object thiz, Object... args) { System.out.println(thiz); return null; } @Override public boolean isStrictFunction() { return true; } });
11-06-2018

This issue is mostly introduced by JDK-8170565 (As recommended by submitter)
07-06-2018

This is a regression starting from 9 ea b148/8u152 onwards. Below are the results 8u151 - Pass 8u152 - Fail 8u161/162 - Fail 8u172 - Fail 9 ea b147 - Pass 9 ea b148 - Fail //Introduced here... 9 GA - Fail 10 GA - Fail 11 ea b17 - Fail
07-06-2018