Unreviewed, rolling out r247493.
https://bugs.webkit.org/show_bug.cgi?id=199841

"The new whlsl-for-loop.html test is failing on the bots"
(Requested by rmorisset on #webkit).

Reverted changeset:

"[WHLSL] Desugar for loops and while loops"
https://bugs.webkit.org/show_bug.cgi?id=199726
https://trac.webkit.org/changeset/247493

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@247499 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index bd651a8..024f569 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,17 @@
+2019-07-16  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r247493.
+        https://bugs.webkit.org/show_bug.cgi?id=199841
+
+        "The new whlsl-for-loop.html test is failing on the bots"
+        (Requested by rmorisset on #webkit).
+
+        Reverted changeset:
+
+        "[WHLSL] Desugar for loops and while loops"
+        https://bugs.webkit.org/show_bug.cgi?id=199726
+        https://trac.webkit.org/changeset/247493
+
 2019-07-16  Robin Morisset  <rmorisset@apple.com>
 
         [WHLSL] Desugar for loops and while loops
diff --git a/LayoutTests/webgpu/whlsl-for-loop-expected.txt b/LayoutTests/webgpu/whlsl-for-loop-expected.txt
deleted file mode 100644
index ae67e5f..0000000
--- a/LayoutTests/webgpu/whlsl-for-loop-expected.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-
-PASS forLoop 
-
diff --git a/LayoutTests/webgpu/whlsl-for-loop.html b/LayoutTests/webgpu/whlsl-for-loop.html
deleted file mode 100644
index 299a9cf..0000000
--- a/LayoutTests/webgpu/whlsl-for-loop.html
+++ /dev/null
@@ -1,153 +0,0 @@
-<!DOCTYPE html>
-<html>
-<meta charset=utf-8>
-<meta name="timeout" content="long">
-<title>Lvalues.</title>
-<script src="js/whlsl-test-harness.js"></script>
-<script src="js/webgpu-functions.js"></script>
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script>
-const whlslTests = {};
-
-whlslTests.forLoop = async () =>
-{
-    let program = `
-        int foo1(int x)
-        {
-            int sum = 0;
-            int i;
-            for (i = 0; i < x; i = i + 1) {
-                sum = sum + i;
-            }
-            return sum;
-        }
-        int foo2(int x)
-        {
-            int sum = 0;
-            for (int i = 0; i < x; i = i + 1) {
-                sum = sum + i;
-            }
-            return sum;
-        }
-        int foo3(int x)
-        {
-            int sum = 0;
-            int i = 100;
-            for (int i = 0; i < x; i = i + 1) {
-                sum = sum + i;
-            }
-            return sum;
-        }
-        int foo4(int x)
-        {
-            int sum = 0;
-            for (int i = 0; i < x; i = i + 1) {
-                if (i == 4)
-                    continue;
-                sum = sum + i;
-            }
-            return sum;
-        }
-        int foo5(int x)
-        {
-            int sum = 0;
-            for (int i = 0; i < x; i = i + 1) {
-                if (i == 5)
-                    break;
-                sum = sum + i;
-            }
-            return sum;
-        }
-        int foo6(int x)
-        {
-            int sum = 0;
-            for (int i = 0; ; i = i + 1) {
-                if (i >= x)
-                    break;
-                sum = sum + i;
-            }
-            return sum;
-        }
-        int foo7(int x)
-        {
-            int sum = 0;
-            int i = 0;
-            for ( ; ; i = i + 1) {
-                if (i >= x)
-                    break;
-                sum = sum + i;
-            }
-            return sum;
-        }
-        int foo8(int x)
-        {
-            int sum = 0;
-            int i = 0;
-            for ( ; ; ) {
-                if (i >= x)
-                    break;
-                sum = sum + i;
-                i = i + 1;
-            }
-            return sum;
-        }
-    `;
-    assert_equals(await callIntFunction(program, "foo1", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo1", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo1", [makeInt(5)]), 10);
-    assert_equals(await callIntFunction(program, "foo2", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo2", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo2", [makeInt(5)]), 10);
-    assert_equals(await callIntFunction(program, "foo3", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo3", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo3", [makeInt(5)]), 10);
-    assert_equals(await callIntFunction(program, "foo4", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo4", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo4", [makeInt(5)]), 6);
-    assert_equals(await callIntFunction(program, "foo4", [makeInt(6)]), 11);
-    assert_equals(await callIntFunction(program, "foo5", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo5", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo5", [makeInt(5)]), 10);
-    assert_equals(await callIntFunction(program, "foo5", [makeInt(6)]), 10);
-    assert_equals(await callIntFunction(program, "foo5", [makeInt(7)]), 10);
-    assert_equals(await callIntFunction(program, "foo6", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo6", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo6", [makeInt(5)]), 10);
-    assert_equals(await callIntFunction(program, "foo6", [makeInt(6)]), 15);
-    assert_equals(await callIntFunction(program, "foo6", [makeInt(7)]), 21);
-    assert_equals(await callIntFunction(program, "foo7", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo7", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo7", [makeInt(5)]), 10);
-    assert_equals(await callIntFunction(program, "foo7", [makeInt(6)]), 15);
-    assert_equals(await callIntFunction(program, "foo7", [makeInt(7)]), 21);
-    assert_equals(await callIntFunction(program, "foo8", [makeInt(3)]), 3);
-    assert_equals(await callIntFunction(program, "foo8", [makeInt(4)]), 6);
-    assert_equals(await callIntFunction(program, "foo8", [makeInt(5)]), 10);
-    assert_equals(await callIntFunction(program, "foo8", [makeInt(6)]), 15);
-    assert_equals(await callIntFunction(program, "foo8", [makeInt(7)]), 21);
-    await checkFail(
-        `
-            void foo(int x)
-            {
-                for (int i = 0; ; i = i + 1) {
-                    break;
-                    x = i;
-                }
-            }
-        `);
-    await checkFail(
-        `
-            int foo(int x)
-            {
-                for ( ; x < 10; ) {
-                    return 7;
-                }
-            }
-        `);
-}
-
-runTests(whlslTests);
-</script>
-</html>
-
diff --git a/LayoutTests/webgpu/whlsl-return-spec-tests.html b/LayoutTests/webgpu/whlsl-return-spec-tests.html
index e12c309..2621a40 100644
--- a/LayoutTests/webgpu/whlsl-return-spec-tests.html
+++ b/LayoutTests/webgpu/whlsl-return-spec-tests.html
@@ -111,16 +111,17 @@
                 return 11;
             }
         `);
-    await checkFail(
-        `
-            int foo(int x)
-            {
-                int y = 6;
-                if (x == 7)
-                    int y = 8;
-                return y;
-            }
-        `);
+
+    program = `
+        int foo(int x)
+        {
+            int y = 6;
+            if (x == 7)
+                int y = 8;
+            return y;
+        }
+    `;
+    assert_equals(await callIntFunction(program, "foo", [makeInt(7)]), 6);
 };
 
 whlslTests.returnReferenceToSameParameter = async () => {
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 03a8fa7..dd316b6 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,17 @@
+2019-07-16  Commit Queue  <commit-queue@webkit.org>
+
+        Unreviewed, rolling out r247493.
+        https://bugs.webkit.org/show_bug.cgi?id=199841
+
+        "The new whlsl-for-loop.html test is failing on the bots"
+        (Requested by rmorisset on #webkit).
+
+        Reverted changeset:
+
+        "[WHLSL] Desugar for loops and while loops"
+        https://bugs.webkit.org/show_bug.cgi?id=199726
+        https://trac.webkit.org/changeset/247493
+
 2019-07-16  Per Arne Vollan  <pvollan@apple.com>
 
         Prewarm font cache with more fonts
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h
index 0e44612..5794d4e 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLAST.h
@@ -101,5 +101,6 @@
 #include "WHLSLVariableDeclaration.h"
 #include "WHLSLVariableDeclarationsStatement.h"
 #include "WHLSLVariableReference.h"
+#include "WHLSLWhileLoop.h"
 
 #endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h
index fe5936c..f45b974 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLForLoop.h
@@ -44,28 +44,33 @@
 
 class ForLoop : public Statement {
 public:
-    ForLoop(CodeLocation location, UniqueRef<Expression>&& condition, UniqueRef<Expression>&& increment, UniqueRef<Statement>&& body)
+    ForLoop(CodeLocation location, Variant<UniqueRef<Statement>, UniqueRef<Expression>>&& initialization, std::unique_ptr<Expression>&& condition, std::unique_ptr<Expression>&& increment, UniqueRef<Statement>&& body)
         : Statement(location)
+        , m_initialization(WTFMove(initialization))
         , m_condition(WTFMove(condition))
         , m_increment(WTFMove(increment))
         , m_body(WTFMove(body))
     {
     }
 
-    virtual ~ForLoop() = default;
+    virtual ~ForLoop()
+    {
+    }
 
     ForLoop(const ForLoop&) = delete;
     ForLoop(ForLoop&&) = default;
 
     bool isForLoop() const override { return true; }
 
-    Expression& condition() { return m_condition; }
-    Expression& increment() { return m_increment; }
+    Variant<UniqueRef<Statement>, UniqueRef<Expression>>& initialization() { return m_initialization; }
+    Expression* condition() { return m_condition.get(); }
+    Expression* increment() { return m_increment.get(); }
     Statement& body() { return m_body; }
 
 private:
-    UniqueRef<Expression> m_condition;
-    UniqueRef<Expression> m_increment;
+    Variant<UniqueRef<Statement>, UniqueRef<Expression>> m_initialization;
+    std::unique_ptr<Expression> m_condition;
+    std::unique_ptr<Expression> m_increment;
     UniqueRef<Statement> m_body;
 };
 
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h
index bad93ed..278ad2b 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLStatement.h
@@ -62,6 +62,7 @@
     virtual bool isSwitchStatement() const { return false; }
     virtual bool isTrap() const { return false; }
     virtual bool isVariableDeclarationsStatement() const { return false; }
+    virtual bool isWhileLoop() const { return false; }
 
     CodeLocation codeLocation() const { return m_codeLocation; }
     void updateCodeLocation(CodeLocation location) { m_codeLocation = location; }
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h
new file mode 100644
index 0000000..55c0377
--- /dev/null
+++ b/Source/WebCore/Modules/webgpu/WHLSL/AST/WHLSLWhileLoop.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2019 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGPU)
+
+#include "WHLSLExpression.h"
+#include "WHLSLLexer.h"
+#include "WHLSLStatement.h"
+#include <wtf/UniqueRef.h>
+
+namespace WebCore {
+
+namespace WHLSL {
+
+namespace AST {
+
+class WhileLoop : public Statement {
+public:
+    WhileLoop(CodeLocation location, UniqueRef<Expression>&& conditional, UniqueRef<Statement>&& body)
+        : Statement(location)
+        , m_conditional(WTFMove(conditional))
+        , m_body(WTFMove(body))
+    {
+    }
+
+    virtual ~WhileLoop() = default;
+
+    WhileLoop(const WhileLoop&) = delete;
+    WhileLoop(WhileLoop&&) = default;
+
+    bool isWhileLoop() const override { return true; }
+
+    Expression& conditional() { return m_conditional; }
+    Statement& body() { return m_body; }
+
+private:
+    UniqueRef<Expression> m_conditional;
+    UniqueRef<Statement> m_body;
+};
+
+} // namespace AST
+
+}
+
+}
+
+SPECIALIZE_TYPE_TRAITS_WHLSL_STATEMENT(WhileLoop, isWhileLoop())
+
+#endif
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
index a206b45..2b57933 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/Metal/WHLSLFunctionWriter.cpp
@@ -128,6 +128,7 @@
     void visit(AST::SwitchCase&) override;
     void visit(AST::Trap&) override;
     void visit(AST::VariableDeclarationsStatement&) override;
+    void visit(AST::WhileLoop&) override;
     void visit(AST::IntegerLiteral&) override;
     void visit(AST::UnsignedIntegerLiteral&) override;
     void visit(AST::FloatLiteral&) override;
@@ -349,9 +350,24 @@
     emitLoop(LoopConditionLocation::AfterBody, &doWhileLoop.conditional(), nullptr, doWhileLoop.body());
 }
 
+void FunctionDefinitionWriter::visit(AST::WhileLoop& whileLoop)
+{
+    emitLoop(LoopConditionLocation::BeforeBody, &whileLoop.conditional(), nullptr, whileLoop.body());
+}
+
 void FunctionDefinitionWriter::visit(AST::ForLoop& forLoop)
 {
-    emitLoop(LoopConditionLocation::BeforeBody, &forLoop.condition(), &forLoop.increment(), forLoop.body());
+    m_stringBuilder.append("{\n");
+
+    WTF::visit(WTF::makeVisitor([&](AST::Statement& statement) {
+        checkErrorAndVisit(statement);
+    }, [&](UniqueRef<AST::Expression>& expression) {
+        checkErrorAndVisit(expression);
+        takeLastValue(); // We don't need to do anything with the result.
+    }), forLoop.initialization());
+
+    emitLoop(LoopConditionLocation::BeforeBody, forLoop.condition(), forLoop.increment(), forLoop.body());
+    m_stringBuilder.append("}\n");
 }
 
 void FunctionDefinitionWriter::visit(AST::IfStatement& ifStatement)
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp
index 362a862..5cfc8e2 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.cpp
@@ -393,6 +393,14 @@
     m_out.print("continue");
 }
 
+void ASTDumper::visit(AST::WhileLoop& whileLoop)
+{
+    m_out.print("while (");
+    visit(whileLoop.conditional());
+    m_out.print(")");
+    visit(whileLoop.body());
+}
+
 void ASTDumper::visit(AST::DoWhileLoop& doWhileLoop)
 {
     m_out.print("do ");
@@ -404,10 +412,18 @@
 
 void ASTDumper::visit(AST::ForLoop& forLoop)
 {
-    m_out.print("for (; ");
-    visit(forLoop.condition());
+    m_out.print("for (");
+    WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
+        visit(statement);
+    }, [&](UniqueRef<AST::Expression>& expression) {
+        visit(expression);
+    }), forLoop.initialization());
     m_out.print("; ");
-    visit(forLoop.increment());
+    if (forLoop.condition())
+        visit(*forLoop.condition());
+    m_out.print("; ");
+    if (forLoop.increment())
+        visit(*forLoop.increment());
     m_out.print(") ");
     visit(forLoop.body());
 }
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h
index cb3e110..0ab09ff 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLASTDumper.h
@@ -100,6 +100,7 @@
     void visit(AST::SwitchStatement&) override;
     void visit(AST::Trap&) override;
     void visit(AST::VariableDeclarationsStatement&) override;
+    void visit(AST::WhileLoop&) override;
     void visit(AST::VariableDeclaration&) override;
     void visit(AST::AssignmentExpression&) override;
     void visit(AST::CallExpression&) override;
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
index 721e0ba..06997bf 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLChecker.cpp
@@ -57,6 +57,7 @@
 #include "WHLSLSwitchStatement.h"
 #include "WHLSLTernaryExpression.h"
 #include "WHLSLVisitor.h"
+#include "WHLSLWhileLoop.h"
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/Ref.h>
@@ -500,6 +501,7 @@
     void visit(AST::LogicalNotExpression&) override;
     void visit(AST::LogicalExpression&) override;
     void visit(AST::IfStatement&) override;
+    void visit(AST::WhileLoop&) override;
     void visit(AST::DoWhileLoop&) override;
     void visit(AST::ForLoop&) override;
     void visit(AST::SwitchStatement&) override;
@@ -1245,6 +1247,13 @@
         checkErrorAndVisit(*ifStatement.elseBody());
 }
 
+void Checker::visit(AST::WhileLoop& whileLoop)
+{
+    if (!recurseAndRequireBoolType(whileLoop.conditional()))
+        return;
+    checkErrorAndVisit(whileLoop.body());
+}
+
 void Checker::visit(AST::DoWhileLoop& doWhileLoop)
 {
     checkErrorAndVisit(doWhileLoop.body());
@@ -1253,9 +1262,19 @@
 
 void Checker::visit(AST::ForLoop& forLoop)
 {
-    if (!recurseAndRequireBoolType(forLoop.condition()))
+    WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
+        checkErrorAndVisit(statement);
+    }, [&](UniqueRef<AST::Expression>& expression) {
+        checkErrorAndVisit(expression);
+    }), forLoop.initialization());
+    if (error())
         return;
-    checkErrorAndVisit(forLoop.increment());
+    if (forLoop.condition()) {
+        if (!recurseAndRequireBoolType(*forLoop.condition()))
+            return;
+    }
+    if (forLoop.increment())
+        checkErrorAndVisit(*forLoop.increment());
     checkErrorAndVisit(forLoop.body());
 }
 
@@ -1415,7 +1434,7 @@
 
 void Checker::visit(AST::CommaExpression& commaExpression)
 {
-    ASSERT(!commaExpression.list().isEmpty());
+    ASSERT(commaExpression.list().size() > 0);
     Visitor::visit(commaExpression);
     if (error())
         return;
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
index 6991fb3..3660439 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.cpp
@@ -43,6 +43,7 @@
 #include "WHLSLTypeReference.h"
 #include "WHLSLVariableDeclaration.h"
 #include "WHLSLVariableReference.h"
+#include "WHLSLWhileLoop.h"
 
 namespace WebCore {
 
@@ -119,33 +120,48 @@
     if (error())
         return;
 
-    checkErrorAndVisit(ifStatement.body());
+    {
+        NameContext nameContext(&m_nameContext);
+        NameResolver newNameResolver(*this, nameContext);
+        newNameResolver.checkErrorAndVisit(ifStatement.body());
+    }
     if (error())
         return;
 
-    if (ifStatement.elseBody())
-        checkErrorAndVisit(*ifStatement.elseBody());
+    if (ifStatement.elseBody()) {
+        NameContext nameContext(&m_nameContext);
+        NameResolver newNameResolver(*this, nameContext);
+        newNameResolver.checkErrorAndVisit(*ifStatement.elseBody());
+    }
+}
+
+void NameResolver::visit(AST::WhileLoop& whileLoop)
+{
+    checkErrorAndVisit(whileLoop.conditional());
+    if (error())
+        return;
+
+    NameContext nameContext(&m_nameContext);
+    NameResolver newNameResolver(*this, nameContext);
+    newNameResolver.checkErrorAndVisit(whileLoop.body());
 }
 
 void NameResolver::visit(AST::DoWhileLoop& whileLoop)
 {
-    checkErrorAndVisit(whileLoop.body());
-    if (error())
-        return;
+    {
+        NameContext nameContext(&m_nameContext);
+        NameResolver newNameResolver(*this, nameContext);
+        newNameResolver.checkErrorAndVisit(whileLoop.body());
+    }
 
     checkErrorAndVisit(whileLoop.conditional());
 }
 
 void NameResolver::visit(AST::ForLoop& forLoop)
 {
-    checkErrorAndVisit(forLoop.condition());
-    if (error())
-        return;
-    checkErrorAndVisit(forLoop.increment());
-    if (error())
-        return;
-
-    checkErrorAndVisit(forLoop.body());
+    NameContext nameContext(&m_nameContext);
+    NameResolver newNameResolver(*this, nameContext);
+    newNameResolver.Visitor::visit(forLoop);
 }
 
 void NameResolver::visit(AST::VariableDeclaration& variableDeclaration)
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
index 14cfb65..3acdadf 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLNameResolver.h
@@ -50,6 +50,7 @@
     void visit(AST::TypeReference&) override;
     void visit(AST::Block&) override;
     void visit(AST::IfStatement&) override;
+    void visit(AST::WhileLoop&) override;
     void visit(AST::DoWhileLoop&) override;
     void visit(AST::ForLoop&) override;
     void visit(AST::VariableDeclaration&) override;
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp
index 2be1217..20cb939 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.cpp
@@ -1063,8 +1063,7 @@
 
     AST::Statements statements;
     while (!peekTypes<Token::Type::RightCurlyBracket, Token::Type::Case, Token::Type::Default>()) {
-        bool allowVariableDeclarations = true;
-        PARSE(statement, Statement, allowVariableDeclarations);
+        PARSE(statement, Statement);
         statements.append(WTFMove(*statement));
     }
 
@@ -1143,52 +1142,51 @@
     }
 }
 
-auto Parser::parseForLoop() -> Expected<AST::Block, Error>
+auto Parser::parseForLoop() -> Expected<AST::ForLoop, Error>
 {
     CONSUME_TYPE(origin, For);
     CONSUME_TYPE(leftParenthesis, LeftParenthesis);
 
+    auto parseRemainder = [&](Variant<UniqueRef<AST::Statement>, UniqueRef<AST::Expression>>&& initialization) -> Expected<AST::ForLoop, Error> {
+        CONSUME_TYPE(semicolon, Semicolon);
+
+        std::unique_ptr<AST::Expression> condition(nullptr);
+        if (!tryType(Token::Type::Semicolon)) {
+            if (auto expression = parseExpression())
+                condition = (*expression).moveToUniquePtr();
+            else
+                return Unexpected<Error>(expression.error());
+            CONSUME_TYPE(secondSemicolon, Semicolon);
+        }
+
+        std::unique_ptr<AST::Expression> increment(nullptr);
+        if (!tryType(Token::Type::RightParenthesis)) {
+            if (auto expression = parseExpression())
+                increment = (*expression).moveToUniquePtr();
+            else
+                return Unexpected<Error>(expression.error());
+            CONSUME_TYPE(rightParenthesis, RightParenthesis);
+        }
+
+        PARSE(body, Statement);
+        AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
+        return AST::ForLoop(location, WTFMove(initialization), WTFMove(condition), WTFMove(increment), WTFMove(*body));
+    };
 
     auto variableDeclarations = backtrackingScope<Expected<AST::VariableDeclarationsStatement, Error>>([&]() {
         return parseVariableDeclarations();
     });
-    Optional<UniqueRef<AST::Statement>> initialization;
-    if (variableDeclarations)
-        initialization = static_cast<UniqueRef<AST::Statement>>(makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)));
-    else {
-        PARSE(effectfulExpression, EffectfulExpression);
-        initialization = WTFMove(*effectfulExpression);
+    if (variableDeclarations) {
+        UniqueRef<AST::Statement> declarationStatement = makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations));
+        return parseRemainder(WTFMove(declarationStatement));
     }
 
-    CONSUME_TYPE(semicolon, Semicolon);
+    PARSE(effectfulExpression, EffectfulExpression);
 
-    Optional<UniqueRef<AST::Expression>> condition;
-    auto secondSemicolon = tryType(Token::Type::Semicolon);
-    if (!secondSemicolon) {
-        PARSE(expression, Expression);
-        condition = WTFMove(*expression);
-        CONSUME_TYPE(secondSemicolon, Semicolon);
-    } else
-        condition = static_cast<UniqueRef<AST::Expression>>(makeUniqueRef<AST::BooleanLiteral>(*secondSemicolon, true));
-
-    Optional<UniqueRef<AST::Expression>> increment;
-    auto rightParenthesis = tryType(Token::Type::RightParenthesis);
-    if (!rightParenthesis) {
-        PARSE(expression, Expression);
-        increment = WTFMove(*expression);
-        CONSUME_TYPE(rightParenthesis, RightParenthesis);
-    } else
-        increment = static_cast<UniqueRef<AST::Expression>>(makeUniqueRef<AST::BooleanLiteral>(*origin, true)); // FIXME: NullLiteral would make more sense, but is buggy right now. Anything side-effect free is fine.
-
-    PARSE(body, Statement);
-    AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
-
-    auto forLoop = makeUniqueRef<AST::ForLoop>(location, WTFMove(*condition), WTFMove(*increment), WTFMove(*body));
-    AST::Statements statements = Vector<UniqueRef<AST::Statement>>::from(WTFMove(*initialization), WTFMove(forLoop));
-    return AST::Block(location, WTFMove(statements));
+    return parseRemainder(WTFMove(*effectfulExpression));
 }
 
-auto Parser::parseWhileLoop() -> Expected<AST::ForLoop, Error>
+auto Parser::parseWhileLoop() -> Expected<AST::WhileLoop, Error>
 {
     CONSUME_TYPE(origin, While);
     CONSUME_TYPE(leftParenthesis, LeftParenthesis);
@@ -1197,8 +1195,7 @@
     PARSE(body, Statement);
 
     AST::CodeLocation location(origin->codeLocation,  (*body)->codeLocation());
-    auto increment = makeUniqueRef<AST::BooleanLiteral>(*origin, true); // FIXME: NullLiteral would make more sense, but is buggy right now. Anything side-effect free is fine.
-    return AST::ForLoop(location, WTFMove(*conditional), WTFMove(increment), WTFMove(*body));
+    return AST::WhileLoop(location, WTFMove(*conditional), WTFMove(*body));
 }
 
 auto Parser::parseDoWhileLoop() -> Expected<AST::DoWhileLoop, Error>
@@ -1257,7 +1254,7 @@
     return AST::VariableDeclarationsStatement({ origin->startOffset(), endOffset }, WTFMove(result));
 }
 
-auto Parser::parseStatement(bool allowVariableDeclarations) -> Expected<UniqueRef<AST::Statement>, Error>
+auto Parser::parseStatement() -> Expected<UniqueRef<AST::Statement>, Error>
 {
     PEEK(token);
     switch (token->type) {
@@ -1275,11 +1272,11 @@
     }
     case Token::Type::For: {
         PARSE(forLoop, ForLoop);
-        return { makeUniqueRef<AST::Block>(WTFMove(*forLoop)) };
+        return { makeUniqueRef<AST::ForLoop>(WTFMove(*forLoop)) };
     }
     case Token::Type::While: {
         PARSE(whileLoop, WhileLoop);
-        return { makeUniqueRef<AST::ForLoop>(WTFMove(*whileLoop)) };
+        return { makeUniqueRef<AST::WhileLoop>(WTFMove(*whileLoop)) };
     }
     case Token::Type::Do: {
         PARSE(doWhileLoop, DoWhileLoop);
@@ -1349,33 +1346,27 @@
     }
 
     {
-        auto effectfulExpressionStatement = backtrackingScope<Expected<UniqueRef<AST::Statement>, Error>>([&]() -> Expected<UniqueRef<AST::Statement>, Error> {
+        auto effectfulExpression = backtrackingScope<Expected<UniqueRef<AST::Expression>, Error>>([&]() -> Expected<UniqueRef<AST::Expression>, Error> {
             PARSE(result, EffectfulExpression);
             CONSUME_TYPE(semicolon, Semicolon);
             return result;
         });
-        if (effectfulExpressionStatement)
-            return effectfulExpressionStatement;
+        if (effectfulExpression)
+            return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(*effectfulExpression)) };
     }
 
-    if (allowVariableDeclarations) {
-        PARSE(variableDeclarations, VariableDeclarations);
-        CONSUME_TYPE(semicolon, Semicolon);
-        return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
-    }
-
-    return Unexpected<Error>("A variable declaration is only valid inside a block");
+    PARSE(variableDeclarations, VariableDeclarations);
+    CONSUME_TYPE(semicolon, Semicolon);
+    return { makeUniqueRef<AST::VariableDeclarationsStatement>(WTFMove(*variableDeclarations)) };
 }
 
-auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Statement>, Error>
+auto Parser::parseEffectfulExpression() -> Expected<UniqueRef<AST::Expression>, Error>
 {
     PEEK(origin);
-    if (origin->type == Token::Type::Semicolon) {
-        AST::Statements statements;
-        return { makeUniqueRef<AST::Block>(*origin, WTFMove(statements)) };
-    }
-
     Vector<UniqueRef<AST::Expression>> expressions;
+    if (origin->type == Token::Type::Semicolon)
+        return { makeUniqueRef<AST::CommaExpression>(*origin, WTFMove(expressions)) };
+
     PARSE(effectfulExpression, EffectfulAssignment);
     expressions.append(WTFMove(*effectfulExpression));
 
@@ -1385,11 +1376,10 @@
     }
 
     if (expressions.size() == 1)
-        return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(expressions[0])) };
+        return WTFMove(expressions[0]);
     unsigned endOffset = m_lexer.peek().startOffset();
     AST::CodeLocation location(origin->startOffset(), endOffset);
-    auto expression = makeUniqueRef<AST::CommaExpression>(location, WTFMove(expressions));
-    return { makeUniqueRef<AST::EffectfulExpressionStatement>(WTFMove(expression)) };
+    return { makeUniqueRef<AST::CommaExpression>(location, WTFMove(expressions)) };
 }
 
 auto Parser::parseEffectfulAssignment() -> Expected<UniqueRef<AST::Expression>, Error>
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h
index 901097d..400ce66 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLParser.h
@@ -91,6 +91,7 @@
 #include "WHLSLVariableDeclaration.h"
 #include "WHLSLVariableDeclarationsStatement.h"
 #include "WHLSLVariableReference.h"
+#include "WHLSLWhileLoop.h"
 #include <wtf/Expected.h>
 #include <wtf/Optional.h>
 #include <wtf/PrintStream.h>
@@ -202,14 +203,14 @@
     Expected<AST::IfStatement, Error> parseIfStatement();
     Expected<AST::SwitchStatement, Error> parseSwitchStatement();
     Expected<AST::SwitchCase, Error> parseSwitchCase();
-    Expected<AST::Block, Error> parseForLoop();
-    Expected<AST::ForLoop, Error> parseWhileLoop();
+    Expected<AST::ForLoop, Error> parseForLoop();
+    Expected<AST::WhileLoop, Error> parseWhileLoop();
     Expected<AST::DoWhileLoop, Error> parseDoWhileLoop();
     Expected<AST::VariableDeclaration, Error> parseVariableDeclaration(UniqueRef<AST::UnnamedType>&&);
     Expected<AST::VariableDeclarationsStatement, Error> parseVariableDeclarations();
-    Expected<UniqueRef<AST::Statement>, Error> parseStatement(bool allowVariableDeclaration = false);
+    Expected<UniqueRef<AST::Statement>, Error> parseStatement();
 
-    Expected<UniqueRef<AST::Statement>, Error> parseEffectfulExpression();
+    Expected<UniqueRef<AST::Expression>, Error> parseEffectfulExpression();
     Expected<UniqueRef<AST::Expression>, Error> parseEffectfulAssignment();
     struct SuffixExpression {
         SuffixExpression(UniqueRef<AST::Expression>&& result, bool success)
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp
index 474fc80..b4bcd61 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLStatementBehaviorChecker.cpp
@@ -44,6 +44,7 @@
 #include "WHLSLTrap.h"
 #include "WHLSLVariableDeclarationsStatement.h"
 #include "WHLSLVisitor.h"
+#include "WHLSLWhileLoop.h"
 #include <cstdint>
 #include <wtf/OptionSet.h>
 #include <wtf/Vector.h>
@@ -108,6 +109,9 @@
 
     void visit(AST::ForLoop& forLoop) override
     {
+        // The initialization always has a behavior of Nothing, which we already add unconditionally below,
+        // so we can just ignore the initialization.
+
         checkErrorAndVisit(forLoop.body());
         if (error())
             return;
@@ -118,6 +122,18 @@
         m_stack.append(b);
     }
 
+    void visit(AST::WhileLoop& whileLoop) override
+    {
+        checkErrorAndVisit(whileLoop.body());
+        if (error())
+            return;
+        auto b = m_stack.takeLast();
+        b.remove(Behavior::Break);
+        b.remove(Behavior::Continue);
+        b.add(Behavior::Nothing);
+        m_stack.append(b);
+    }
+
     void visit(AST::SwitchCase& switchCase) override
     {
         Visitor::visit(switchCase);
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp
index 372e661..bf12e63 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.cpp
@@ -331,10 +331,10 @@
         checkErrorAndVisit(downcast<AST::SwitchStatement>(statement));
     else if (is<AST::Trap>(statement))
         checkErrorAndVisit(downcast<AST::Trap>(statement));
-    else {
-        ASSERT(is<AST::VariableDeclarationsStatement>(statement));
+    else if (is<AST::VariableDeclarationsStatement>(statement))
         checkErrorAndVisit(downcast<AST::VariableDeclarationsStatement>(statement));
-    }
+    else
+        checkErrorAndVisit(downcast<AST::WhileLoop>(statement));
 }
 
 void Visitor::visit(AST::Break&)
@@ -427,8 +427,15 @@
 
 void Visitor::visit(AST::ForLoop& forLoop)
 {
-    checkErrorAndVisit(forLoop.condition());
-    checkErrorAndVisit(forLoop.increment());
+    WTF::visit(WTF::makeVisitor([&](UniqueRef<AST::Statement>& statement) {
+        checkErrorAndVisit(statement);
+    }, [&](UniqueRef<AST::Expression>& expression) {
+        checkErrorAndVisit(expression);
+    }), forLoop.initialization());
+    if (forLoop.condition())
+        checkErrorAndVisit(*forLoop.condition());
+    if (forLoop.increment())
+        checkErrorAndVisit(*forLoop.increment());
     checkErrorAndVisit(forLoop.body());
 }
 
@@ -470,6 +477,12 @@
         checkErrorAndVisit(variableDeclaration.get());
 }
 
+void Visitor::visit(AST::WhileLoop& whileLoop)
+{
+    checkErrorAndVisit(whileLoop.conditional());
+    checkErrorAndVisit(whileLoop.body());
+}
+
 void Visitor::visit(AST::VariableDeclaration& variableDeclaration)
 {
     if (variableDeclaration.type())
diff --git a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h
index a3fa247..ec396fd 100644
--- a/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h
+++ b/Source/WebCore/Modules/webgpu/WHLSL/WHLSLVisitor.h
@@ -85,6 +85,7 @@
 class SwitchStatement;
 class Trap;
 class VariableDeclarationsStatement;
+class WhileLoop;
 class VariableDeclaration;
 class AssignmentExpression;
 class CallExpression;
@@ -165,6 +166,7 @@
     virtual void visit(AST::SwitchStatement&);
     virtual void visit(AST::Trap&);
     virtual void visit(AST::VariableDeclarationsStatement&);
+    virtual void visit(AST::WhileLoop&);
     virtual void visit(AST::VariableDeclaration&);
     virtual void visit(AST::AssignmentExpression&);
     virtual void visit(AST::CallExpression&);
diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
index 2674e46..70ef35a 100644
--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj
+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj
@@ -13256,6 +13256,7 @@
 		C21BF70121CD89C400227979 /* WHLSLDereferenceExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLDereferenceExpression.h; sourceTree = "<group>"; };
 		C21BF70221CD89C400227979 /* WHLSLEnumerationMemberLiteral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLEnumerationMemberLiteral.h; sourceTree = "<group>"; };
 		C21BF70321CD89C500227979 /* WHLSLReturn.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLReturn.h; sourceTree = "<group>"; };
+		C21BF70421CD89C600227979 /* WHLSLWhileLoop.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLWhileLoop.h; sourceTree = "<group>"; };
 		C21BF70521CD89C700227979 /* WHLSLFunctionAttribute.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLFunctionAttribute.h; sourceTree = "<group>"; };
 		C21BF70621CD89C700227979 /* WHLSLCommaExpression.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLCommaExpression.h; sourceTree = "<group>"; };
 		C21BF70721CD89C800227979 /* WHLSLNullLiteral.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = WHLSLNullLiteral.h; sourceTree = "<group>"; };
@@ -17131,6 +17132,7 @@
 				C21BF71021CD89D000227979 /* WHLSLVariableDeclaration.h */,
 				C21BF71421CD89D300227979 /* WHLSLVariableDeclarationsStatement.h */,
 				C21BF71321CD89D200227979 /* WHLSLVariableReference.h */,
+				C21BF70421CD89C600227979 /* WHLSLWhileLoop.h */,
 			);
 			path = AST;
 			sourceTree = "<group>";