fix(closure): 修复箭头函数和闭包生成中的代码顺序问题

- 在闭包生成器中保存和恢复 beforeStmtLines 和 afterStmtLines 状态
- 移除闭包结束大括号前的重复代码插入
- 在编译基类中正确处理表达式前的代码行
- 添加对静态属性写入的测试用例
- 添加对箭头函数功能的测试用例
pull/1/head
韩天峰 6 months ago
parent f56bd745e7
commit eed45fdb61
  1. 9
      src/Php/CompilerBase.php
  2. 9
      src/Php/Generator/ClosureGenerator.php
  3. 17
      tests/aot/arrow-func-2.phpt
  4. 32
      tests/aot/static_prop_write.phpt

@ -4039,12 +4039,17 @@ class CompilerBase extends \PhpAot\Core\Translator
{ {
$cb = function () use ($expr) { $cb = function () use ($expr) {
$code = $this->parseExpr($expr->expr); $code = $this->parseExpr($expr->expr);
if ($this->beforeStmtLines) {
$beforeCode = implode(PHP_EOL, $this->beforeStmtLines);
} else {
$beforeCode = '';
}
if ($this->isCallExpr($expr->expr)) { if ($this->isCallExpr($expr->expr)) {
if ($this->lastNativeCall and $this->lastNativeCall->returnType === self::TYPE_VOID) { if ($this->lastNativeCall and $this->lastNativeCall->returnType === self::TYPE_VOID) {
return $code . ";\nreturn " . self::VALUE_NULL . ';'; return $beforeCode . PHP_EOL . $code . ";" . PHP_EOL . "return " . self::VALUE_NULL . ';';
} }
} }
return 'return ' . $code . ';'; return $beforeCode . PHP_EOL . 'return ' . $code . ';';
}; };
return $this->genClosure($expr, $expr->params, $cb, [], true); return $this->genClosure($expr, $expr->params, $cb, [], true);
} }

@ -37,12 +37,16 @@ trait ClosureGenerator
$oriCeWrappers = $this->ceWrappers; $oriCeWrappers = $this->ceWrappers;
$oriArgs = $this->arguments; $oriArgs = $this->arguments;
$oriInClosure = $this->inClosure; $oriInClosure = $this->inClosure;
$oriBeforeStmtLines = $this->beforeStmtLines;
$oriAfterStmtLines = $this->afterStmtLines;
$this->objects = []; $this->objects = [];
$this->objectWrappers = []; $this->objectWrappers = [];
$this->ceWrappers = []; $this->ceWrappers = [];
$this->arguments = []; $this->arguments = [];
$this->inClosure = true; $this->inClosure = true;
$this->beforeStmtLines = [];
$this->afterStmtLines = [];
$this->indentLevel++; $this->indentLevel++;
@ -70,8 +74,6 @@ trait ClosureGenerator
$this->indentLevel--; $this->indentLevel--;
$code .= '};' . PHP_EOL; $code .= '};' . PHP_EOL;
$this->beforeStmtLines[] = $code;
$useVars = []; $useVars = [];
if ($uses) { if ($uses) {
foreach ($uses as $useItem) { foreach ($uses as $useItem) {
@ -95,6 +97,9 @@ trait ClosureGenerator
$this->ceWrappers = $oriCeWrappers; $this->ceWrappers = $oriCeWrappers;
$this->arguments = $oriArgs; $this->arguments = $oriArgs;
$this->inClosure = $oriInClosure; $this->inClosure = $oriInClosure;
$this->beforeStmtLines = $oriBeforeStmtLines;
$this->afterStmtLines = $oriAfterStmtLines;
$this->beforeStmtLines[] = $code;
if ($this->methodDef) { if ($this->methodDef) {
return 'php::newClosure(' . $tmpVar . ', { ' . implode(', ', $useVars) . ' }, this_)'; return 'php::newClosure(' . $tmpVar . ', { ' . implode(', ', $useVars) . ' }, this_)';

@ -0,0 +1,17 @@
--TEST--
arrow function 2
--FILE--
<?php
function main()
{
$array = [1, 5, 9];
$fn1 = fn($x) => var_dump(0, ...$array);
$fn1();
}
?>
--EXPECT--
int(0)
int(1)
int(5)
int(9)

@ -0,0 +1,32 @@
--TEST--
Static Class Property Read/Write Test
--FILE--
<?php
class Select {
public $errorHandler = null;
public function setErrorHandler($errorHandler): void
{
$this->errorHandler = $errorHandler;
($this->errorHandler)();
}
}
class Worker
{
public static ?stdClass $globalEvent = null;
public static string $eventLoopClass = 'Select';
public static function init() {
self::$globalEvent = new static::$eventLoopClass();
self::$globalEvent->setErrorHandler(function ($exception) {
var_dump(__FUNCTION__);
});
}
}
function main() {
Worker::init();
}
?>
--EXPECT--
string(4) "init"
Loading…
Cancel
Save