summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsebres <sebres@users.sourceforge.net>2024-03-08 13:40:57 (GMT)
committersebres <sebres@users.sourceforge.net>2024-03-08 13:40:57 (GMT)
commitde7fa6e02c27b87267b10ca5e635841104031593 (patch)
treedc1c6a8fd4d0e6f8a7a65fb112d11a5db4ce985d
parentc45c0e9d7fdee6d7a15c176e55bb93d67dea48ef (diff)
downloadtcl-de7fa6e02c27b87267b10ca5e635841104031593.zip
tcl-de7fa6e02c27b87267b10ca5e635841104031593.tar.gz
tcl-de7fa6e02c27b87267b10ca5e635841104031593.tar.bz2
namespace unknown considers also alternate search path (relative global NS), see namespace-52.14
-rw-r--r--generic/tclBasic.c27
-rw-r--r--tests/namespace.test17
2 files changed, 38 insertions, 6 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index d87fea6..9b4161a 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -4816,20 +4816,35 @@ TEOV_NotFound(
* first try to find namespace unknown handler of the namespace
* of executed command if available:
*/
- Namespace *dummyNsPtr;
+ Namespace *altNsPtr, *dummyNsPtr;
const char *simpleName;
(void) TclGetNamespaceForQualName(interp, qualName, currNsPtr,
- TCL_NAMESPACE_ONLY | TCL_FIND_IF_NOT_SIMPLE, &currNsPtr,
- &dummyNsPtr, &dummyNsPtr, &simpleName);
- if ((currNsPtr == NULL) || (simpleName == NULL)) {
- goto globNS;
+ TCL_FIND_IF_NOT_SIMPLE, &currNsPtr, &altNsPtr,
+ &dummyNsPtr, &simpleName);
+ if (!simpleName) {
+ goto globNS;
+ }
+ if (!currNsPtr || (currNsPtr == iPtr->globalNsPtr)) {
+ if (!altNsPtr || (altNsPtr == iPtr->globalNsPtr)) {
+ goto globNS;
+ }
+ currNsPtr = altNsPtr;
}
while (currNsPtr->unknownHandlerPtr == NULL ||
(currNsPtr->flags & (NS_DYING | NS_DEAD))
) {
/* traverse to alive parent namespace containing handler */
- if (!(currNsPtr = currNsPtr->parentPtr)) {
+ if (!(currNsPtr = currNsPtr->parentPtr) ||
+ (currNsPtr == iPtr->globalNsPtr)
+ ) {
+ /* continue from alternate NS if available */
+ if (!altNsPtr || (altNsPtr == iPtr->globalNsPtr)) {
+ goto globNS;
+ }
+ currNsPtr = altNsPtr;
+ altNsPtr = NULL;
+ continue;
globNS:
/* fallback to the global unknown */
currNsPtr = iPtr->globalNsPtr;
diff --git a/tests/namespace.test b/tests/namespace.test
index 9976cf3..abe642e 100644
--- a/tests/namespace.test
+++ b/tests/namespace.test
@@ -3149,6 +3149,23 @@ test namespace-52.14 {unknown: invocation outside of NS doesn't evade namespace
} -result [lrepeat 2 \
{::foo:bar:_unknown ::foo::bar xxx::yyy} {::foo:bar:_unknown ::foo bar::xxx::yyy} {::foo:bar:_unknown :: ::foo::bar::xxx::yyy} {::foo:bar:_unknown :: foo::bar::xxx::yyy}
]
+test namespace-52.14 {unknown: it must consider alternate search path (relative global NS), bug 910d67a229fe7f65} -body {
+ namespace eval ::foo::bar {}
+ namespace eval ::xxx::yyy {
+ proc _unknown args {list ::xxx:yyy:_unknown [uplevel {namespace current}] $args}
+ namespace unknown [namespace current]::_unknown
+ }
+ set res {}
+ lappend res [namespace inscope ::foo::bar {xxx::yyy::cmd}] [namespace inscope ::foo {xxx::yyy::cmd}]
+ namespace eval ::foo::bar::xxx {}
+ lappend res [namespace inscope ::foo::bar {xxx::yyy::cmd}] [namespace inscope ::foo {xxx::yyy::cmd}]
+ namespace eval ::foo::bar::xxx::yyy {}
+ lappend res [namespace inscope ::foo::bar {xxx::yyy::cmd}] [namespace inscope ::foo {xxx::yyy::cmd}]
+} -cleanup {
+ namespace delete ::foo
+ namespace delete ::xxx
+ unset -nocomplain res
+} -result [lrepeat 3 {::xxx:yyy:_unknown ::foo::bar xxx::yyy::cmd} {::xxx:yyy:_unknown ::foo xxx::yyy::cmd}]
# TIP 314 - ensembles with parameters
test namespace-53.1 {ensembles: parameters} {