JDK-8149334 : JSON.parse(JSON.stringify([])).push(10) creates an array containing two elements
  • Type: Bug
  • Component: core-libs
  • Sub-Component: jdk.nashorn
  • Affected Version: 8u60,9
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2016-02-05
  • Updated: 2016-07-21
  • Resolved: 2016-02-08
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
8u102Fixed 9 b105Fixed
Description
FULL PRODUCT VERSION :
java version "1.8.0_72"
Java(TM) SE Runtime Environment (build 1.8.0_72-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.72-b15, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux dev01 3.13.0-49-generic #83-Ubuntu SMP Fri Apr 10 20:11:33 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
An empty array created by JSON.parse() behaves differently from an empty array created from an empty array literal.

The empty array from JSON.parse() has length 0, but after calling push() once on the array it has length 2.

The empty array literal behaves as expected - after calling push() once the array has length 1, and the single element in the array is the one pushed into the array.

REGRESSION.  Last worked in version 8u60

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

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Use the jjs command line tool to run the following:

var a = JSON.parse(JSON.stringify([]));
a.push(10);
a
a.length



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
jjs> var a = JSON.parse(JSON.stringify([]));
jjs> a.push(10);                            
1
jjs> a
10
jjs> a.length
1

ACTUAL -
jjs> var a = JSON.parse(JSON.stringify([]));
jjs> a.push(10);
1
jjs> a
0,10
jjs> a.length
2

REPRODUCIBILITY :
This bug can be reproduced always.

CUSTOMER SUBMITTED WORKAROUND :
Check for empty array before the push() call, and replace with empty array from array literal.


Comments
The problem here is that the transition from an immutable empty array (of the internal type ArrayData.UntouchedArrayData) to an array containing actual data would create an array with one entry before then appending the pushed element. The fix is to return an actually empty (if mutable) ArrayData instance in these cases.
08-02-2016

Tried the steps provided by submitter on following versions: JDK 1.8.0 -Pass JDK 8u45 -Pass JDK 8u51 - Pass JDK 8u60 -Fail JDK 8u72 -Fail JDK 9ea -Fail The behavior in JDK 9ea is slightly different as the push call returns 2 at the time first element is pushed, whereas in other version where it is failing, the push call returns 1. ------------------------------- D:\Java7Workspace\TestCases\src>jjs -version nashorn 9-ea jjs> var a = JSON.parse(JSON.stringify([])); jjs> a.length 0 jjs> a.push(10); 2 jjs> a 0,10 jjs> a.length 2 ------------------------------------------------------------------ D:\Java7Workspace\TestCases\src>jjs -version nashorn 1.8.0_60 jjs> var a = JSON.parse(JSON.stringify([])); jjs> a.length 0 jjs> a.push(10); 1 jjs> a 0,10 jjs> a.length 2 jjs> ------------------------------------------------
08-02-2016