diff --git a/src/mapping.c b/src/mapping.c index 07c35c8273c367b090f2883f8402be38d92aabca..5126ba9c39bfb1e1d877074161dcff24874761e9 100644 --- a/src/mapping.c +++ b/src/mapping.c @@ -1891,12 +1891,21 @@ void o_append_mapping( INT32 args ) struct mapping *m = val->u.mapping; if( m->refs == 2 ) { - int i; - /* fprintf( stderr, "map_refs==2\n" ); */ - for( i=0; i<args; i+=2 ) - low_mapping_insert( m, Pike_sp-(i+2), Pike_sp-(i+1), 2 ); - stack_pop_n_elems_keep_top(2+args); - return; + if ((TYPEOF(*lval) == T_OBJECT) && + lval->u.object->prog && + ((FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_INDEX) >= 0) || + (FIND_LFUN(lval->u.object->prog, LFUN_ASSIGN_ARROW) >= 0))) { + /* There's a function controlling assignments in this object, + * so we can't alter the mapping in place. + */ + } else { + int i; + /* fprintf( stderr, "map_refs==2\n" ); */ + for( i=0; i<args; i+=2 ) + low_mapping_insert( m, Pike_sp-(i+2), Pike_sp-(i+1), 2 ); + stack_pop_n_elems_keep_top(2+args); + return; + } } } diff --git a/src/testsuite.in b/src/testsuite.in index e8ac2a877435fa402da2ee55184b14ce985b6454..4e69fc128fa1c13d9545d772c4038ddc9c375371 100644 --- a/src/testsuite.in +++ b/src/testsuite.in @@ -4112,6 +4112,29 @@ test_any([[ return has_index(a->_modified, "foo"); ]], 1) +test_any([[ + // Since the addition of F_APPEND_MAPPING in set_bar below + // the setter is not being called anymore. Instead, the mapping + // _data->foo is modified in place. + class A(mapping foo) { + mapping _modified = ([]); + + mixed `->=(string sym, mixed v) { + return _modified[sym] = v; + } + + void set_bar(int v) { + this->foo += ([ "bar" : v ]); + } + }; + + object a = A(([ "foo" : ([]) ])); + + a->set_bar(2); + + return has_index(a->_modified, "foo"); +]], 1) + test_any([[ // Since the addition of F_APPEND_ARRAY the setter is not being // called anymore. Instead, the array _data is modified in place.