From e7db0c7348b57a6099e157d952919a3a477f8821 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Tue, 7 Apr 2026 17:12:08 +0800 Subject: [PATCH] =?UTF-8?q?fix(php):=20=E4=BF=AE=E5=A4=8D=E7=AE=AD?= =?UTF-8?q?=E5=A4=B4=E5=87=BD=E6=95=B0=E5=8F=98=E9=87=8F=E4=BD=9C=E7=94=A8?= =?UTF-8?q?=E5=9F=9F=E5=92=8C=E4=BA=8C=E5=85=83=E8=BF=90=E7=AE=97=E7=AC=A6?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加箭头函数基本功能测试用例验证闭包行为 - 修复二元运算符解析时变量存在性检查逻辑 - 解决全局变量在箭头函数中的访问问题 - 修复数组解包空数组导致断言失败的bug - 改进变量名转义和局部变量检测机制 --- src/Php/CompilerBase.php | 14 +++++---- tests/zend/array_unpack/gh19303.phpt | 11 +++++++ tests/zend/arrow_functions/001.phpt | 45 ++++++++++++++++++++++++++++ tests/zend/arrow_functions/004.phpt | 13 ++++++++ 4 files changed, 78 insertions(+), 5 deletions(-) create mode 100644 tests/zend/array_unpack/gh19303.phpt create mode 100644 tests/zend/arrow_functions/001.phpt create mode 100644 tests/zend/arrow_functions/004.phpt diff --git a/src/Php/CompilerBase.php b/src/Php/CompilerBase.php index 75c5ed4d..4734b2ce 100644 --- a/src/Php/CompilerBase.php +++ b/src/Php/CompilerBase.php @@ -1532,12 +1532,15 @@ class CompilerBase extends \PhpAot\Core\Translator return $this->parseIdentifier($expr); } - protected function parseBinaryOp($left, $right, $op): string + protected function parseBinaryOp(NodeAbstract $left, NodeAbstract $right, string $op): string { // 运算逻辑,优先转为数字 $leftExpr = $this->parseNumericIdentifier($left); $rightExpr = $this->parseNumericIdentifier($right); + $this->checkVarMustExist($left, $leftExpr); + $this->checkVarMustExist($right, $rightExpr); + $leftType = $this->detectExprType($left); $rightType = $this->detectExprType($right); @@ -4576,13 +4579,14 @@ class CompilerBase extends \PhpAot\Core\Translator } foreach ($vars as $var) { - if ($var->name === 'this' - or !$this->hasLocalVar($var->name) + $varName = $this->escapeVarName($this->parseVariable($var)); + if ($varName === 'this' + or !$this->hasLocalVar($varName) or isset($params[$var->name]) - or isset($uses[$var->name])) { + or isset($uses[$varName])) { continue; } - $uses[$var->name] = new Node\ClosureUse($var); + $uses[$varName] = new Node\ClosureUse($var); } $uses = array_values($uses); diff --git a/tests/zend/array_unpack/gh19303.phpt b/tests/zend/array_unpack/gh19303.phpt new file mode 100644 index 00000000..af594c37 --- /dev/null +++ b/tests/zend/array_unpack/gh19303.phpt @@ -0,0 +1,11 @@ +--TEST-- +GH-19303 (Unpacking empty packed array into uninitialized array causes assertion failure) +--FILE-- + +--EXPECT-- +array(0) { +} diff --git a/tests/zend/arrow_functions/001.phpt b/tests/zend/arrow_functions/001.phpt new file mode 100644 index 00000000..27b2557b --- /dev/null +++ b/tests/zend/arrow_functions/001.phpt @@ -0,0 +1,45 @@ +--TEST-- +Basic arrow function functionality check +--FILE-- + 1; +var_dump($foo()); + +$foo = fn($x) => $x; +var_dump($foo(2)); + +$foo = fn($x, $y) => $x + $y; +var_dump($foo(1, 2)); + +// Closing over $var +$var = 4; +$foo = fn() => $var; +var_dump($foo()); + +// Not closing over $var, it's a parameter +$foo = fn($var) => $var; +var_dump($foo(5)); + +// Close over $var by-value, not by-reference +$var = 5; +$foo = fn() => ++$var; +var_dump($foo()); +var_dump($var); + +// Nested arrow functions closing over variable +$var = 6; +var_dump((fn() => fn() => $var)()()); +var_dump((fn() => function() use($var) { return $var; })()()); + +?> +--EXPECT-- +int(1) +int(2) +int(3) +int(4) +int(5) +int(6) +int(5) +int(6) +int(6) diff --git a/tests/zend/arrow_functions/004.phpt b/tests/zend/arrow_functions/004.phpt new file mode 100644 index 00000000..f581cb21 --- /dev/null +++ b/tests/zend/arrow_functions/004.phpt @@ -0,0 +1,13 @@ +--TEST-- +Auto-globals in arrow functions +--FILE-- + $GLOBALS['a']; + var_dump($fn()); +} +?> +--EXPECT-- +int(123)