From d767104e1c56574da21fcdc62dc80e289cdf0d05 Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 9 Jul 2026 10:57:27 +0800 Subject: [PATCH] refactor(php): separate internal constants loading logic - Extract internal constants loading into dedicated loadInternalConstants method - Filter out user-defined constants from internal constants array - Maintain backward compatibility with non-grouped constants format - Add proper handling of constant groups to prevent runtime state inclusion - Improve static expansion behavior for compile-time vs runtime constants --- phpunit/code/compiler_api/const_decl.php | 3 ++ phpunit/src/CompilerBaseApiTest.php | 40 ++++++++++++++++++++++++ src/Php/Translator.php | 22 ++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 phpunit/code/compiler_api/const_decl.php diff --git a/phpunit/code/compiler_api/const_decl.php b/phpunit/code/compiler_api/const_decl.php new file mode 100644 index 00000000..a80363be --- /dev/null +++ b/phpunit/code/compiler_api/const_decl.php @@ -0,0 +1,3 @@ +assertSame('ZEND_LONG_MIN', $this->compiler->getConstValue('PHP_INT_MIN')); } + public function testConstDeclarationsAreStaticallyExpanded(): void + { + $this->compiler->prepareFile($this->fixturePath('const_decl.php')); + + $code = $this->invokeMethod( + 'parseConstFetch', + new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('AOT_COMPILE_TIME_CONST')) + ); + + $this->assertSame(CompilerBase::CONST_VAR . 'AOT_COMPILE_TIME_CONST', $code); + } + + public function testDefineConstantsAreNotStaticallyExpanded(): void + { + $internalConstants = $this->getPropertyValue('internalConstants'); + $this->assertArrayHasKey('PHP_VERSION', $internalConstants); + $this->assertArrayNotHasKey('ROOT_PATH', $internalConstants); + + $code = $this->invokeMethod( + 'parseConstFetch', + new \PhpParser\Node\Expr\ConstFetch(new \PhpParser\Node\Name('ROOT_PATH')) + ); + + $this->assertStringStartsWith('php::constant(nullptr, ', $code); + $this->assertStringNotContainsString(ROOT_PATH, $code); + } + + public function testDynamicallyDefinedConstantsAreNotInternalConstants(): void + { + $name = 'AOT_USER_DEFINE_' . str_replace('.', '_', uniqid('', true)); + define($name, 'runtime-value'); + + $compiler = CompilerTest::create($this->testDir); + $ref = new \ReflectionClass($compiler); + $prop = $ref->getProperty('internalConstants'); + $prop->setAccessible(true); + + $this->assertArrayNotHasKey($name, $prop->getValue($compiler)); + } + // ======================================================================== // genAnonClassName // ======================================================================== diff --git a/src/Php/Translator.php b/src/Php/Translator.php index f617ea7f..973a2d59 100644 --- a/src/Php/Translator.php +++ b/src/Php/Translator.php @@ -128,7 +128,7 @@ class Translator extends Preprocessor // 这样可以确保优先级:命令行 > YAML > 默认值 $this->internalFunctions = array_flip(get_defined_functions()['internal']); unset($this->internalFunctions[self::ENTRY_FUNCTION]); - $this->internalConstants = get_defined_constants(); + $this->internalConstants = $this->loadInternalConstants(); if ($this->climate->arguments->defined('help')) { $this->showUsage(); exit(0); @@ -148,6 +148,26 @@ class Translator extends Preprocessor $this->detectPlatform(); } + protected function loadInternalConstants(): array + { + $groups = get_defined_constants(true); + if (!is_array($groups)) { + return get_defined_constants(); + } + + $constants = []; + foreach ($groups as $groupName => $group) { + // 编译器进程中的用户常量属于被编译程序的运行时状态,不能在静态阶段展开。 + if (strcasecmp((string) $groupName, 'user') === 0 || !is_array($group)) { + continue; + } + foreach ($group as $name => $value) { + $constants[$name] = $value; + } + } + return $constants; + } + /** * 检测操作系统、编译器以及 Windows 平台的 PHP lib 文件 */