codeconsole commented on code in PR #16732:
URL: https://github.com/apache/grails-core/pull/16732#discussion_r4369081944


##########
grails-bootstrap/src/main/groovy/org/grails/config/NavigableMap.groovy:
##########
@@ -81,37 +129,48 @@ class NavigableMap implements Map<String, Object>, 
Cloneable {
 
     @Override
     boolean containsKey(Object key) {
-        delegateMap.containsKey(key)
+        delegateMap.containsKey(key) || (key instanceof String && 
!ABSENT.is(elementAt((String) key)))
     }
 
     @Override
     boolean containsValue(Object value) {
         delegateMap.containsValue(value)
     }
 
-    @CompileDynamic
     @Override
     Object get(Object key) {
         Object result = delegateMap.get(key)
-        if (result != null) {
-            return result
+        if (result == null && key instanceof String) {
+            Object element = elementAt((String) key)
+            return ABSENT.is(element) ? null : element
         }
-        null
+        result
     }
 
+    /** Writes the entry in both representations, as {@link #setProperty} 
does, and returns the entry it replaces. */
     @Override
     Object put(String key, Object value) {
-        delegateMap.put(key, value)
+        Object previous = delegateMap.get(key)
+        setProperty(key, value)
+        previous
     }
 
+    /** Removes the entry from both representations, with the flat keys below 
it, and returns it. */
     @Override
     Object remove(Object key) {
-        delegateMap.remove(key)
+        Object previous = delegateMap.get(key)
+        if (key instanceof String) {

Review Comment:
   Fixed in ef4ee4c37f. `remove` and a `null` assignment went through the write 
path, so an indexed key that named nothing was written: 
`remove('app.names[0]')` on an empty map built `app.names = [null]`, under 
`names: 'configured'` it replaced the scalar, past the end of a list it padded 
the list with `null`, and on a present element it set the element to `null` 
instead of taking it out. Removal has its own path now. An indexed key is 
resolved to the container its last step reads from, the list or map, and that 
step; a key that names nothing, on an empty map, below a scalar or past the end 
of a list, removes nothing and creates nothing, and a key that names an element 
takes it from its list or map and returns it. A container that refuses the 
removal, a list built with `asImmutable()`, is replaced by a copy without the 
element in both representations. A `null` through `put` or dot notation removes 
the same way.
   
   Pinned in `NavigableMapSpec` over an empty map, a scalar, an index past the 
end, an element of a list, an entry of an element map, an entry of a map 
subscript and an element of an immutable list, each checking what is returned, 
what the container holds through both representations and that the key set is 
unchanged, and for `put` and dot notation with `null`; in 
`PropertySourcesConfigSpec` for your two cases through a config, and for the 
element taken from its list.
   



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to