summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--generic/tclBasic.c44
-rw-r--r--generic/tclCompile.h2
-rw-r--r--generic/tclLiteral.c45
-rw-r--r--generic/tclObj.c13
-rw-r--r--tests/resolver.test47
5 files changed, 38 insertions, 113 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 53023d8..2ca90fd 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -1943,17 +1943,6 @@ Tcl_ExposeCommand(
}
/*
- * Command resolvers (per-interp, per-namespace) might have resolved to a
- * command for the given namespace scope with this command not being
- * registered with the namespace's command table. During BC compilation,
- * the so-resolved command turns into a CmdName literal. Without
- * invalidating a possible CmdName literal here explicitly, such literals
- * keep being reused while pointing to overhauled commands.
- */
-
- TclInvalidateCmdLiteral(interp, cmdName, nsPtr);
-
- /*
* The list of command exported from the namespace might have changed.
* However, we do not need to recompute this just yet; next time we need
* the info will be soon enough.
@@ -2109,17 +2098,6 @@ Tcl_CreateCommand(
ckfree(Tcl_GetHashValue(hPtr));
}
} else {
- /*
- * Command resolvers (per-interp, per-namespace) might have resolved
- * to a command for the given namespace scope with this command not
- * being registered with the namespace's command table. During BC
- * compilation, the so-resolved command turns into a CmdName literal.
- * Without invalidating a possible CmdName literal here explicitly,
- * such literals keep being reused while pointing to overhauled
- * commands.
- */
-
- TclInvalidateCmdLiteral(interp, tail, nsPtr);
/*
* The list of command exported from the namespace might have changed.
@@ -2305,17 +2283,6 @@ Tcl_CreateObjCommand(
ckfree(Tcl_GetHashValue(hPtr));
}
} else {
- /*
- * Command resolvers (per-interp, per-namespace) might have resolved
- * to a command for the given namespace scope with this command not
- * being registered with the namespace's command table. During BC
- * compilation, the so-resolved command turns into a CmdName literal.
- * Without invalidating a possible CmdName literal here explicitly,
- * such literals keep being reused while pointing to overhauled
- * commands.
- */
-
- TclInvalidateCmdLiteral(interp, tail, nsPtr);
/*
* The list of command exported from the namespace might have changed.
@@ -2628,17 +2595,6 @@ TclRenameCommand(
TclInvalidateNsCmdLookup(cmdPtr->nsPtr);
/*
- * Command resolvers (per-interp, per-namespace) might have resolved to a
- * command for the given namespace scope with this command not being
- * registered with the namespace's command table. During BC compilation,
- * the so-resolved command turns into a CmdName literal. Without
- * invalidating a possible CmdName literal here explicitly, such literals
- * keep being reused while pointing to overhauled commands.
- */
-
- TclInvalidateCmdLiteral(interp, newTail, cmdPtr->nsPtr);
-
- /*
* Script for rename traces can delete the command "oldName". Therefore
* increment the reference count for cmdPtr so that it's Command structure
* is freed only towards the end of this function by calling
diff --git a/generic/tclCompile.h b/generic/tclCompile.h
index 89cdc59..5db1a01 100644
--- a/generic/tclCompile.h
+++ b/generic/tclCompile.h
@@ -1160,8 +1160,6 @@ MODULE_SCOPE void TclPushVarName(Tcl_Interp *interp,
MODULE_SCOPE void TclPreserveByteCode(ByteCode *codePtr);
MODULE_SCOPE void TclReleaseByteCode(ByteCode *codePtr);
MODULE_SCOPE void TclReleaseLiteral(Tcl_Interp *interp, Tcl_Obj *objPtr);
-MODULE_SCOPE void TclInvalidateCmdLiteral(Tcl_Interp *interp,
- const char *name, Namespace *nsPtr);
MODULE_SCOPE int TclSingleOpCmd(ClientData clientData,
Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[]);
diff --git a/generic/tclLiteral.c b/generic/tclLiteral.c
index 9922cec..db210cb 100644
--- a/generic/tclLiteral.c
+++ b/generic/tclLiteral.c
@@ -1004,51 +1004,6 @@ RebuildLiteralTable(
}
}
-/*
- *----------------------------------------------------------------------
- *
- * TclInvalidateCmdLiteral --
- *
- * Invalidate a command literal entry, if present in the literal hash
- * tables, by resetting its internal representation. This invalidation
- * leaves it in the literal tables and in existing literal arrays. As a
- * result, existing references continue to work but we force a fresh
- * command look-up upon the next use (see, in particular,
- * TclSetCmdNameObj()).
- *
- * Results:
- * None.
- *
- * Side effects:
- * Resets the internal representation of the CmdName Tcl_Obj
- * using TclFreeIntRep().
- *
- *----------------------------------------------------------------------
- */
-
-void
-TclInvalidateCmdLiteral(
- Tcl_Interp *interp, /* Interpreter for which to invalidate a
- * command literal. */
- const char *name, /* Points to the start of the cmd literal
- * name. */
- Namespace *nsPtr) /* The namespace for which to lookup and
- * invalidate a cmd literal. */
-{
- Interp *iPtr = (Interp *) interp;
- Tcl_Obj *literalObjPtr = TclCreateLiteral(iPtr, name,
- strlen(name), -1, NULL, nsPtr, 0, NULL);
-
- if (literalObjPtr != NULL) {
- if (literalObjPtr->typePtr == &tclCmdNameType) {
- TclFreeIntRep(literalObjPtr);
- }
- /* Balance the refcount effects of TclCreateLiteral() above */
- Tcl_IncrRefCount(literalObjPtr);
- TclReleaseLiteral(interp, literalObjPtr);
- }
-}
-
#ifdef TCL_COMPILE_STATS
/*
*----------------------------------------------------------------------
diff --git a/generic/tclObj.c b/generic/tclObj.c
index d3f59ec..54c7bc6 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.c
@@ -4130,6 +4130,7 @@ Tcl_GetCommandFromObj(
* global namespace. */
{
register ResolvedCmdName *resPtr;
+ Tcl_Command result = NULL;
/*
* Get the internal representation, converting to a command type if
@@ -4175,11 +4176,14 @@ Tcl_GetCommandFromObj(
*/
/* See [07d13d99b0a9] why we cannot call SetCmdNameFromAny() directly here. */
- if (tclCmdNameType.setFromAnyProc(interp, objPtr) != TCL_OK) {
- return NULL;
+ if (tclCmdNameType.setFromAnyProc(interp, objPtr) == TCL_OK) {
+ resPtr = objPtr->internalRep.twoPtrValue.ptr1;
+ if (resPtr) {
+ result = (Tcl_Command) resPtr->cmdPtr;
+ }
+ TclFreeIntRep(objPtr);
}
- resPtr = objPtr->internalRep.twoPtrValue.ptr1;
- return (Tcl_Command) (resPtr ? resPtr->cmdPtr : NULL);
+ return result;
}
/*
@@ -4272,6 +4276,7 @@ TclSetCmdNameObj(
return;
}
}
+ return;
SetCmdNameObj(interp, objPtr, cmdPtr, NULL);
}
diff --git a/tests/resolver.test b/tests/resolver.test
index 9bb4c08..db12b99 100644
--- a/tests/resolver.test
+++ b/tests/resolver.test
@@ -41,7 +41,8 @@ test resolver-1.1 {cmdNameObj sharing vs. cmd resolver: namespace import} -setup
# 2) After having requested cmd resolution above, we can now use the
# globally shared CmdName Tcl_Obj "z", now bound to cmd ::y. This is
# certainly questionable, but defensible
- set r1 [z]; # --> The result of [z] is "Y"
+ set r1 untouched
+ catch {set r1 [z]}; # --> The result of [z] is "Y"
# 3) We import from the namespace ns1 another z. [namespace import] takes
# care "shadowed" cmd references, however, till now cmd literals have not
# been touched. This is, however, necessary since the BC compiler (used in
@@ -52,13 +53,14 @@ test resolver-1.1 {cmdNameObj sharing vs. cmd resolver: namespace import} -setup
namespace import ::ns1::z
set r2 [z]
}
- list $r0 $r1 $::r2
+ set r3 [x]
+ list $r0 $r1 $::r2 $r3
} -cleanup {
testinterpresolver down
rename ::x ""
rename ::y ""
namespace delete ::ns1
-} -result {Y Y Z}
+} -result {Y untouched Z Y}
test resolver-1.2 {cmdNameObj sharing vs. cmd resolver: proc creation} -setup {
testinterpresolver up
proc ::y {} { return Y }
@@ -67,19 +69,20 @@ test resolver-1.2 {cmdNameObj sharing vs. cmd resolver: proc creation} -setup {
}
} -constraints testinterpresolver -body {
set r0 [x]
- set r1 [z]
+ set r1 untouched
+ catch {set r1 [z]}
proc ::foo {} {
proc ::z {} { return Z }
return [z]
}
- list $r0 $r1 [::foo]
+ list $r0 $r1 [::foo] [x]
} -cleanup {
testinterpresolver down
rename ::x ""
rename ::y ""
rename ::foo ""
rename ::z ""
-} -result {Y Y Z}
+} -result {Y untouched Z Y}
test resolver-1.3 {cmdNameObj sharing vs. cmd resolver: rename} -setup {
testinterpresolver up
proc ::Z {} { return Z }
@@ -89,18 +92,20 @@ test resolver-1.3 {cmdNameObj sharing vs. cmd resolver: rename} -setup {
}
} -constraints testinterpresolver -body {
set r0 [x]
- set r1 [z]
+ set r1 untouched
+ catch {set r1 [z]}
namespace eval :: {
rename ::Z ::z
set r2 [z]
}
- list $r0 $r1 $r2
+ set r3 [x]
+ list $r0 $r1 $r2 $r3
} -cleanup {
testinterpresolver down
rename ::x ""
rename ::y ""
rename ::z ""
-} -result {Y Y Z}
+} -result {Y untouched Z Y}
test resolver-1.4 {cmdNameObj sharing vs. cmd resolver: interp expose} -setup {
testinterpresolver up
proc ::Z {} { return Z }
@@ -111,18 +116,20 @@ test resolver-1.4 {cmdNameObj sharing vs. cmd resolver: interp expose} -setup {
}
} -constraints testinterpresolver -body {
set r0 [x]
- set r1 [z]
+ set r1 untouched
+ catch {set r1 [z]}
interp expose {} Z z
namespace eval :: {
set r2 [z]
}
- list $r0 $r1 $r2
+ set r0 [x]
+ list $r0 $r1 $r2 $r3
} -cleanup {
testinterpresolver down
rename ::x ""
rename ::y ""
rename ::z ""
-} -result {Y Y Z}
+} -result {Y untouched Z Y}
test resolver-1.5 {cmdNameObj sharing vs. cmd resolver: other than global NS} -setup {
testinterpresolver up
namespace eval ::ns1 {
@@ -140,17 +147,19 @@ test resolver-1.5 {cmdNameObj sharing vs. cmd resolver: other than global NS} -s
}
} -constraints testinterpresolver -body {
set r0 [namespace eval ::ns2 {x}]
- set r1 [namespace eval ::ns2 {z}]
+ set r1 untouched
+ catch {set r1 [namespace eval ::ns2 {z}]}
namespace eval ::ns2 {
namespace import ::ns1::z
set r2 [z]
}
- list $r0 $r1 $r2
+ set r3 [namespace eval ::ns2 {x}]
+ list $r0 $r1 $r2 $r3
} -cleanup {
testinterpresolver down
namespace delete ::ns2
namespace delete ::ns1
-} -result {Y Y Z}
+} -result {Y untouched Z Y}
test resolver-1.6 {cmdNameObj sharing vs. cmd resolver: interp alias} -setup {
testinterpresolver up
proc ::Z {} { return Z }
@@ -160,18 +169,20 @@ test resolver-1.6 {cmdNameObj sharing vs. cmd resolver: interp alias} -setup {
}
} -constraints testinterpresolver -body {
set r0 [x]
- set r1 [z]
+ set r1 untouched
+ catch {set r1 [z]}
namespace eval :: {
interp alias {} ::z {} ::Z
set r2 [z]
}
- list $r0 $r1 $r2
+ set r3 [x]
+ list $r0 $r1 $r2 $r3
} -cleanup {
testinterpresolver down
rename ::x ""
rename ::y ""
rename ::Z ""
-} -result {Y Y Z}
+} -result {Y untouched Z Y}
test resolver-2.1 {compiled var resolver: Bug #3383616} -setup {
testinterpresolver up