Local variables assigned to null should not be deleted
gerzytet opened this issue ยท 6 comments
Currently, when assigning null to a local variable, the variable is deleted and trying to access it again is an error.
This behavior has zero use cases, especially since trg has no scope.
Also, now that #206 is done, placeholders can return null, local variables need to be able to store null in order to take advantage of that.
I'll give you examples from the code to prove it.
Here's the code that handles local variable assignment (Interpreter.assignValue(Token id, Token value), starting at line 950):
else if (id.type == Type.ID) {
if (value.type == Type.NULLVALUE) {
String name = id.value.toString();
if (vars.containsKey(name))
vars.remove(name);
} else {
if (isVariable(value)) {
value = unwrapVariable(value);
}
vars.put(id.value.toString(), value.value);
}
}
as you can see, assigning a NULLVALUE to variables deletes it from the map.
However, this isn't usually a problem, because this is the code that handles var access (Interpreter.unwrapVariable(Token varToken)):
if (varToken.type == Type.ID) {
if (importMap.containsKey(varToken.value)) {
Class<?> clazz = importMap.get(varToken.value);
return new Token(Type.CLAZZ, clazz, varToken.row, varToken.col);
}
Object var = vars.get(varToken.value);
return parseValue(var, varToken);
parseValue will convert the raw result of get() to a token. If the variable doesn't exist, get() returns null, so the value is converted to a NULLVALUE token and returned. This means that variables assigned to null don't appear to be deleted, even if they are, because they will still yield null.
This means that the example I provided will work as intended (oops), but the reason I opened this wasn't that example, it was an edge case I found while testing after solving #206 that fails due to deleted variables. First, here's the source code of $playername
function playername(args){
if(player == null)
return null;
return player.getName();
}
Looking at this, it's reasonable to think that assigning player to null then running the placeholder will produce null. But it actually crashes on the JavaScript side, since player was not assigned to null. It was deleted.
player = null
#MESSAGE $playername
In general, deleting variables isn't documented anywhere and it's fragile behavior.
The solution? Don't delete variables
Can you clarify what it means by "trying to access it again"?
If the variable is storing 'null,' there is no possible access I can think of.
Any example?
Btw, thank you for keep updating the project. I'm bombarded with lots of homework so didn't have much time to work on it. (And @rkdrns4747 too)
Null assignments can happen in code that interacts with java
a = SomePlugin.foo()
#MESSAGE a
if foo() can sometimes return null, this means that a will be deleted and the script will crash.
Are you sure that's the case?
that wasn't intentional if it's really happening
It must be a bug
@gerzytet btw I tested on 2.1.8, but #MESSAGE works well with null value.
i = player.getKiller()
#MESSAGE i // result: null
Resolved in 4cda451