Bladeren bron

Shell: Immediately resolve value when setting a variable

The lazy resolution mechanism made it so that the variables were linked
together, causing unexpected behaviour:

    true
    x=$? # expected: x=0
    false
    echo $x # expected: 0, actual: 1
Ali Mohammad Pur 3 jaren geleden
bovenliggende
commit
6e24d845e0
2 gewijzigde bestanden met toevoegingen van 19 en 3 verwijderingen
  1. 9 0
      Userland/Shell/AST.cpp
  2. 10 3
      Userland/Shell/AST.h

+ 9 - 0
Userland/Shell/AST.cpp

@@ -3414,6 +3414,7 @@ RefPtr<Value> VariableDeclarations::run(RefPtr<Shell> shell)
         auto value = var.value->run(shell);
         if (shell && shell->has_any_error())
             break;
+        value = value->resolve_without_cast(shell);
 
         shell->set_local_variable(name, value.release_nonnull());
     }
@@ -3703,6 +3704,14 @@ Vector<String> SpecialVariableValue::resolve_as_list(RefPtr<Shell> shell)
     }
 }
 
+NonnullRefPtr<Value> SpecialVariableValue::resolve_without_cast(RefPtr<Shell> shell)
+{
+    if (!shell)
+        return *this;
+
+    return make_ref_counted<ListValue>(resolve_as_list(shell));
+}
+
 TildeValue::~TildeValue()
 {
 }

+ 10 - 3
Userland/Shell/AST.h

@@ -381,6 +381,7 @@ class SpecialVariableValue final : public Value {
 public:
     virtual Vector<String> resolve_as_list(RefPtr<Shell>) override;
     virtual String resolve_as_string(RefPtr<Shell>) override;
+    virtual NonnullRefPtr<Value> resolve_without_cast(RefPtr<Shell>) override;
     virtual NonnullRefPtr<Value> clone() const override { return make_ref_counted<SpecialVariableValue>(m_name)->set_slices(m_slices); }
     virtual ~SpecialVariableValue();
     SpecialVariableValue(char name)
@@ -512,9 +513,15 @@ protected:
     RefPtr<SyntaxError> m_syntax_error_node;
 };
 
-#define NODE(name)                                               \
-    virtual String class_name() const override { return #name; } \
-    virtual Kind kind() const override { return Kind::name; }
+#define NODE(name)                             \
+    virtual String class_name() const override \
+    {                                          \
+        return #name;                          \
+    }                                          \
+    virtual Kind kind() const override         \
+    {                                          \
+        return Kind::name;                     \
+    }
 
 class PathRedirectionNode : public Node {
 public: