[ https://issues.apache.org/jira/browse/GROOVY-11058?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Jim Klimov updated GROOVY-11058: -------------------------------- Description: {color:#172b4d}Groovy UnmodifiableMap.plus() operations return a different Map class and modified data in the object, compromising common syntax like {{myView += myMap}} (which can happen e.g. during script refactoring from maps to read-only views and *should* throw when misused).{color} Originally found in Jenkins with its built-in old groovy-2.4.21 (in-core for pipeline scripts) and [http://tpcg.io/_R7VESY], but verified with a newer 2.5.14 version at e.g. [https://groovyconsole.appspot.com/script/4819062429319168] (see "Output" tab since it shows stack trace by default) and groovy-3.0.9/jvm-17.0.1 as seen at [https://jdoodle.com/ia/HVH] and double-checked locally with GroovyConsole from a freshly fetched 4.0.12 tarball. {code:java} // Repro case for Groovy println GroovySystem.version def m1 = [t: 'somestring', n: 1] def m2 = Collections.unmodifiableMap(m1) println m1.getClass() // AS EXPECTED: class java.util.LinkedHashMap println m2.getClass() // AS EXPECTED: class java.util.Collections$UnmodifiableMap // NOTE: plus() operations return a different class and modified data: m2 += [m:2] //m2 = m2 + [m:2] println m2.getClass() // NOT AS EXPECTED: class java.util.LinkedHashMap println m2 // NOT AS EXPECTED: [t:somestring, n:1, m:2] // NOTE: Direct operations on the view (put, putAll, replace, remove, // leftShift and << operator) are constrained as expected: def m3 = Collections.unmodifiableMap(m1) //m3.putAll([m:2]) m3 << [m:2] // THROWS AS EXPECTED: java.lang.UnsupportedOperationException ... {code} was: {color:#172b4d}Groovy UnmodifiableMap.plus() operations return a different Map class and modified data in the object, compromising common syntax like {{myView += myMap}} (which can happen e.g. during script refactoring from maps to read-only views and *should* throw when misused).{color} Originally found in Jenkins with its built-in old groovy-2.4.21 (in-core for pipeline scripts) and [http://tpcg.io/_R7VESY], but verified with a newer 2.5.14 version at e.g. [https://groovyconsole.appspot.com/script/4819062429319168] (see "Output" tab since it shows stack trace by default) and groovy-3.0.9/jvm-17.0.1 as seen at [https://jdoodle.com/ia/HVH] {code:java} // Repro case for Groovy println GroovySystem.version def m1 = [t: 'somestring', n: 1] def m2 = Collections.unmodifiableMap(m1) println m1.getClass() // AS EXPECTED: class java.util.LinkedHashMap println m2.getClass() // AS EXPECTED: class java.util.Collections$UnmodifiableMap // NOTE: plus() operations return a different class and modified data: m2 += [m:2] //m2 = m2 + [m:2] println m2.getClass() // NOT AS EXPECTED: class java.util.LinkedHashMap println m2 // NOT AS EXPECTED: [t:somestring, n:1, m:2] // NOTE: Direct operations on the view (put, putAll, replace, remove, // leftShift and << operator) are constrained as expected: def m3 = Collections.unmodifiableMap(m1) //m3.putAll([m:2]) m3 << [m:2] // THROWS AS EXPECTED: java.lang.UnsupportedOperationException ... {code} > plus() on UnmodifiableMap returns a new Map with changed data > ------------------------------------------------------------- > > Key: GROOVY-11058 > URL: https://issues.apache.org/jira/browse/GROOVY-11058 > Project: Groovy > Issue Type: Bug > Components: Groovy Console > Affects Versions: 2.4.21, 2.5.14, 3.0.9 > Reporter: Jim Klimov > Priority: Major > > {color:#172b4d}Groovy UnmodifiableMap.plus() operations return a different > Map class and modified data in the object, compromising common syntax like > {{myView += myMap}} (which can happen e.g. during script refactoring from > maps to read-only views and *should* throw when misused).{color} > Originally found in Jenkins with its built-in old groovy-2.4.21 (in-core for > pipeline scripts) and [http://tpcg.io/_R7VESY], but verified with a newer > 2.5.14 version at e.g. > [https://groovyconsole.appspot.com/script/4819062429319168] (see "Output" tab > since it shows stack trace by default) and groovy-3.0.9/jvm-17.0.1 as seen at > [https://jdoodle.com/ia/HVH] and double-checked locally with GroovyConsole > from a freshly fetched 4.0.12 tarball. > > {code:java} > // Repro case for Groovy > println GroovySystem.version > def m1 = [t: 'somestring', n: 1] > def m2 = Collections.unmodifiableMap(m1) > println m1.getClass() // AS EXPECTED: class java.util.LinkedHashMap > println m2.getClass() // AS EXPECTED: class > java.util.Collections$UnmodifiableMap > // NOTE: plus() operations return a different class and modified data: > m2 += [m:2] > //m2 = m2 + [m:2] > println m2.getClass() // NOT AS EXPECTED: class java.util.LinkedHashMap > println m2 // NOT AS EXPECTED: [t:somestring, n:1, m:2] > // NOTE: Direct operations on the view (put, putAll, replace, remove, > // leftShift and << operator) are constrained as expected: > def m3 = Collections.unmodifiableMap(m1) > //m3.putAll([m:2]) > m3 << [m:2] > // THROWS AS EXPECTED: java.lang.UnsupportedOperationException ... > {code} > -- This message was sent by Atlassian Jira (v8.20.10#820010)