JDK-8130853 : Non-extensible global is not handled property
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-07-09
  • Updated: 2016-01-14
  • Resolved: 2015-07-13
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.
JDK 8 JDK 9
8u72Fixed 9 b74Fixed
Description
Object.freeze(this); var x = 10; print(x); 

-> undefined

Object.freeze(this); eval("var x = 10"); print(x)

-> 10

eval "works around" frozen nature of Global object.

With v8 and Rhino, 'undefined' is printed in the first case. In the second case ReferenceError is thrown for "x"!!

Per my reading of the ECMAScript 5.1 spec., it appears "var x = 10" should result in TypeError in the "eval" case.

Reason:

* per 10.2.3 The Global Environment section

/ The global environment is a unique Lexical Environment which is created before any ECMAScript code is executed. The global environment���s Environment Record is an object environment record whose binding object is the global object (15.1). /

=> global is an object environment record.

* CreateMutableBinding on Object environment records is defined here:
 https://es5.github.io/#x10.2.1.2.2

Step 5 is as follows:

/Call the [[DefineOwnProperty]] internal method of bindings, passing N, Property Descriptor {[[Value]]:undefined, [[Writable]]: true, [[Enumerable]]: true , [[Configurable]]: configValue}, and true as arguments./

* [[DefineOwnProperty]] as defined in https://es5.github.io/#x8.12.9

says:

/ In the following algorithm, the term ���Reject��� means ���If Throw is true, then throw a TypeError exception, otherwise return false���./

And Step 3 is 

/  If current is undefined and extensible is false, then Reject./


So, it appears TypeError should be thrown for frozen global when a new mutable binding is attempted on it.

In any case, Nashorn's current behaviour is inconsistent. at the mininum, "var x =10" via "eval" should also be ignored like v8 and rhino do. i.e., can not create new binding when global is frozen.
Comments
I think above analysis of the ES5 spec is correct. One caveat is that ES6 adds a declarative global environment for let/const declarations. This is not an object environment and therefore not subject to above behaviour.
13-07-2015