fix(php): 修复箭头函数变量作用域和二元运算符解析问题

- 添加箭头函数基本功能测试用例验证闭包行为
- 修复二元运算符解析时变量存在性检查逻辑
- 解决全局变量在箭头函数中的访问问题
- 修复数组解包空数组导致断言失败的bug
- 改进变量名转义和局部变量检测机制
pull/1/head
韩天峰 5 months ago
parent b8516b6ac0
commit e7db0c7348
  1. 14
      src/Php/CompilerBase.php
  2. 11
      tests/zend/array_unpack/gh19303.phpt
  3. 45
      tests/zend/arrow_functions/001.phpt
  4. 13
      tests/zend/arrow_functions/004.phpt

@ -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);

@ -0,0 +1,11 @@
--TEST--
GH-19303 (Unpacking empty packed array into uninitialized array causes assertion failure)
--FILE--
<?php
$a = [0];
unset($a[0]);
var_dump([...$a]);
?>
--EXPECT--
array(0) {
}

@ -0,0 +1,45 @@
--TEST--
Basic arrow function functionality check
--FILE--
<?php
$foo = fn() => 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)

@ -0,0 +1,13 @@
--TEST--
Auto-globals in arrow functions
--FILE--
<?php
function main() {
global $a;
$a = 123;
$fn = fn() => $GLOBALS['a'];
var_dump($fn());
}
?>
--EXPECT--
int(123)
Loading…
Cancel
Save