Index: generic/nsf.c =================================================================== diff -u -r7c9c450f99d98116703a8532065df1d9c5a3be15 -rf34ac86da9500e115e9bbd5e638b055d64896925 --- generic/nsf.c (.../nsf.c) (revision 7c9c450f99d98116703a8532065df1d9c5a3be15) +++ generic/nsf.c (.../nsf.c) (revision f34ac86da9500e115e9bbd5e638b055d64896925) @@ -7102,7 +7102,7 @@ } /* - * check, if startCl is a per-class mixin of some other classes + * Check, if startCl is a per-class mixin of some other classes */ if (startCl->opt) { NsfCmdList *m; @@ -21406,6 +21406,13 @@ */ static int NsfParameterInvalidateClassCacheCmd(Tcl_Interp *interp, NsfClass *cl) { + + /* + * First, invalidate the cached parameters on this class (if available) and + * bump the epoch counter. Even when the current class does not have parsed + * parameters (yet), e.g. a subclass might have cached this information + * already. + */ if (cl->parsedParamPtr) { NsfClassParamPtrEpochIncr("NsfParameterInvalidateClassCacheCmd"); /* fprintf(stderr, " %s invalidate %p\n", ClassName(cl), cl->parsedParamPtr); */ @@ -21420,20 +21427,25 @@ */ if (likely(RUNTIME_STATE(interp)->exitHandlerDestroyRound == NSF_EXITHANDLER_OFF)) { - /* Is the current class mixed into at least another one class? */ - if (cl->opt && cl->opt->isClassMixinOf) { + if (unlikely(cl->opt != NULL) && unlikely(cl->opt->isClassMixinOf != NULL)) { Tcl_HashTable objTable, *commandTable = &objTable; Tcl_HashSearch hSrch; Tcl_HashEntry *hPtr; + /* + * The current class is mixed into some other class. + */ + Tcl_InitHashTable(commandTable, TCL_ONE_WORD_KEYS); MEM_COUNT_ALLOC("Tcl_InitHashTable", commandTable); + GetAllClassMixinsOf(interp, commandTable, Tcl_GetObjResult(interp), - cl, 1, 0, NULL, NULL); + cl, 1, 0, NULL, NULL); for (hPtr = Tcl_FirstHashEntry(commandTable, &hSrch); hPtr; hPtr = Tcl_NextHashEntry(&hSrch)) { NsfClass *mixinOfClass = (NsfClass *)Tcl_GetHashKey(commandTable, hPtr); + if (mixinOfClass) { /* fprintf(stderr, "mixinOfClass %s\n", ClassName(mixinOfClass)); */ if (mixinOfClass->parsedParamPtr) { @@ -21444,13 +21456,18 @@ } Tcl_DeleteHashTable(commandTable); MEM_COUNT_FREE("Tcl_InitHashTable", commandTable); + } else { - /* The current class is only a potential superclass */ NsfClasses *subClasses = TransitiveSubClasses(cl), *clPtr; - - /* invalidate cached parameters in subclasses */ + + /* + * The current class is NOT mixed into some other class and is just a + * potential superclass of some other classes. In this case, we have to + * invalidate cached parameters in subclasses. + */ for (clPtr = subClasses; clPtr; clPtr = clPtr->nextPtr) { NsfClass *subClass = clPtr->cl; + if (subClass->parsedParamPtr) { ParsedParamFree(subClass->parsedParamPtr); subClass->parsedParamPtr = NULL; Index: library/mongodb/nsfmongo.c =================================================================== diff -u -r25023d3c048b369645973fdfa125a3705c7f1898 -rf34ac86da9500e115e9bbd5e638b055d64896925 --- library/mongodb/nsfmongo.c (.../nsfmongo.c) (revision 25023d3c048b369645973fdfa125a3705c7f1898) +++ library/mongodb/nsfmongo.c (.../nsfmongo.c) (revision f34ac86da9500e115e9bbd5e638b055d64896925) @@ -811,7 +811,7 @@ if (withName) {options.name = withName;} /* TODO: not handled: is_initialized, v, weights, default_language, laguage_override, padding */ - success = mongoc_collection_ensure_index(collectionPtr, keysPtr, &options, &bsonError); + success = mongoc_collection_create_index(collectionPtr, keysPtr, &options, &bsonError); bson_destroy(keysPtr); Index: tests/properties.test =================================================================== diff -u -r3f34f07ea7f3fcee21a4b48d402dd4c20da2a6de -rf34ac86da9500e115e9bbd5e638b055d64896925 --- tests/properties.test (.../properties.test) (revision 3f34f07ea7f3fcee21a4b48d402dd4c20da2a6de) +++ tests/properties.test (.../properties.test) (revision f34ac86da9500e115e9bbd5e638b055d64896925) @@ -945,6 +945,47 @@ } +nx::test case indirect-transitive-mixin-info { + + nx::Class create M0 + nx::Class create M1 -superclass M0 + nx::Class create M2 -superclass M1 + + nx::Class create C + nx::Class create D -superclass C + + C create c1 + D create d1 + M0 create m0 + M1 create m1 + M2 create m2 + + ? {llength [C info configure parameters]} 4 + ? {llength [D info configure parameters]} 4 + ? {llength [M0 info configure parameters]} 4 + ? {llength [M1 info configure parameters]} 4 + ? {llength [M2 info configure parameters]} 4 + + M0 property x + + ? {llength [M0 info configure parameters]} 5 + ? {llength [M1 info configure parameters]} 5 + ? {llength [M2 info configure parameters]} 5 + + C mixin add M2 + + ? {llength [C info configure parameters]} 5 + ? {llength [D info configure parameters]} 5 + + M1 property y + ? {llength [C info configure parameters]} 6 + ? {llength [D info configure parameters]} 6 + ? {llength [M0 info configure parameters]} 5 + ? {llength [M1 info configure parameters]} 6 + ? {llength [M2 info configure parameters]} 6 +} + + # # Local variables: # mode: tcl