diff options
author | sebres <sebres@users.sourceforge.net> | 2024-03-08 13:40:57 (GMT) |
---|---|---|
committer | sebres <sebres@users.sourceforge.net> | 2024-03-08 13:40:57 (GMT) |
commit | de7fa6e02c27b87267b10ca5e635841104031593 (patch) | |
tree | dc1c6a8fd4d0e6f8a7a65fb112d11a5db4ce985d | |
parent | c45c0e9d7fdee6d7a15c176e55bb93d67dea48ef (diff) | |
download | tcl-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.c | 27 | ||||
-rw-r--r-- | tests/namespace.test | 17 |
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} { |