From a54b04118d517aa3550eee81c8ceb4102d2b9f7e Mon Sep 17 00:00:00 2001 From: tianfenghan Date: Thu, 8 Jan 2026 16:16:36 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E9=94=99=E8=AF=AF=E6=8A=91?= =?UTF-8?q?=E5=88=B6=E6=93=8D=E4=BD=9C=E7=AC=A6=EF=BC=8C=E4=BD=86=E4=BB=85?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=8E=A7=E5=88=B6=E4=B8=80=E4=B8=AA=E5=87=BD?= =?UTF-8?q?=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/silentCall.php | 5 + src/Php/Translator.php | 27 +++-- src/functions.php | 1 + tests/std/file/001.phpt | 146 +++++++++++++++++++++++++++ tests/std/file/002.phpt | 52 ++++++++++ tests/std/file/003.phpt | 41 ++++++++ tests/std/file/004.phpt | 61 +++++++++++ tests/std/file/005_basic.phpt | 37 +++++++ tests/std/file/005_error.phpt | 33 ++++++ tests/std/filters/001.phpt | 32 ++++++ tests/std/filters/basic.phpt | 45 +++++++++ tests/std/filters/convert.phpt | 129 +++++++++++++++++++++++ tests/std/general_functions/001.phpt | 67 ++++++++++++ tests/std/general_functions/002.phpt | 11 ++ tests/std/general_functions/003.phpt | 59 +++++++++++ tests/std/general_functions/007.phpt | 26 +++++ tests/std/general_functions/008.phpt | 43 ++++++++ tests/std/general_functions/009.phpt | 26 +++++ 18 files changed, 831 insertions(+), 10 deletions(-) create mode 100644 examples/silentCall.php create mode 100644 tests/std/file/001.phpt create mode 100644 tests/std/file/002.phpt create mode 100644 tests/std/file/003.phpt create mode 100644 tests/std/file/004.phpt create mode 100644 tests/std/file/005_basic.phpt create mode 100644 tests/std/file/005_error.phpt create mode 100644 tests/std/filters/001.phpt create mode 100644 tests/std/filters/basic.phpt create mode 100644 tests/std/filters/convert.phpt create mode 100644 tests/std/general_functions/001.phpt create mode 100644 tests/std/general_functions/002.phpt create mode 100644 tests/std/general_functions/003.phpt create mode 100644 tests/std/general_functions/007.phpt create mode 100644 tests/std/general_functions/008.phpt create mode 100644 tests/std/general_functions/009.phpt diff --git a/examples/silentCall.php b/examples/silentCall.php new file mode 100644 index 00000000..7b9638b2 --- /dev/null +++ b/examples/silentCall.php @@ -0,0 +1,5 @@ +type = $type; if (isset($param->default)) { $this->functionDef->argCountRequired = count($list) - 1; - $argInfo->default = $this->parseScalar($param->default); + $argInfo->default = $this->parseIdentifier($param->default); } $this->functionDef->argInfoList[] = $argInfo; } @@ -819,6 +816,8 @@ class Translator extends \PhpAot\Core\Translator return $this->parseUnaryPlus($expr); case 'InterpolatedStringPart': return $this->parseInterpolatedStringPart($expr); + case 'Expr_ErrorSuppress': + return $this->parseErrorSuppress($expr); case 'Expr_Exit': return $this->parseExit($expr); default: @@ -1080,7 +1079,7 @@ class Translator extends \PhpAot\Core\Translator if ($this->isNativeFunction($name)) { return $this->nativeFunctions[$name]->returnType; } - return $this->detectFuncCallReturnType($expr); + return $this->detectFuncCallReturnType($name); case 'Expr_New': return self::TYPE_OBJECT; case 'Expr_Assign': @@ -1466,7 +1465,7 @@ class Translator extends \PhpAot\Core\Translator return false; } - private function parseFuncCall(mixed $expr): string + private function parseFuncCall(Node\Expr\FuncCall $expr, bool $silent = false): string { if ($expr->name->getType() === self::EXPR_VARIABLE) { $fn = $this->parseIdentifier($expr->name); @@ -1504,10 +1503,11 @@ class Translator extends \PhpAot\Core\Translator $fn = $tmpVar; $name = ''; } + $call = $silent ? 'php::silentCall' : 'php::call'; if (empty($expr->args)) { - return 'php::call(' . $fn . ')'; + return $call . '(' . $fn . ')'; } else { - return 'php::call(' . $fn . ', {' . $this->parseCallArgs($expr->args, $name) . '})'; + return $call . '(' . $fn . ', {' . $this->parseCallArgs($expr->args, $name) . '})'; } } @@ -2447,9 +2447,8 @@ class Translator extends \PhpAot\Core\Translator return $this->convertFloatExpr($this->parseIdentifier($expr->expr)); } - private function detectFuncCallReturnType($expr): string + private function detectFuncCallReturnType(string $name): string { - $name = $expr->name; $returnType = Reflection::getFunctionReturnType($name); if ($returnType) { return $this->getTypeFromZendType($returnType); @@ -2943,4 +2942,12 @@ class Translator extends \PhpAot\Core\Translator } return $code; } + + private function parseErrorSuppress(Node\Expr\ErrorSuppress $expr): string + { + if ($expr->expr instanceof Node\Expr\FuncCall) { + return $this->parseFuncCall($expr->expr, true); + } + abort($expr); + } } diff --git a/src/functions.php b/src/functions.php index 9767ee1b..e43c6a00 100644 --- a/src/functions.php +++ b/src/functions.php @@ -15,6 +15,7 @@ function abort($v) if ($translator->mode == 'cli') { if (DEBUG) { var_dump($v); + debug_print_backtrace(); } } else { header('Content-Type: application/json'); diff --git a/tests/std/file/001.phpt b/tests/std/file/001.phpt new file mode 100644 index 00000000..8fe6946d --- /dev/null +++ b/tests/std/file/001.phpt @@ -0,0 +1,146 @@ +--TEST-- +File type functions +--SKIPIF-- + +--FILE-- + +--EXPECT-- +test.file does not exist +test.file exists +test.link exists +test.file is not a symlink +test.link is a symlink +test.file exists +test.link lstat and stat differ at element 1 +test.link lstat and stat differ at element 2 +test.link lstat and stat differ at element 7 +test.link lstat and stat differ at element 8 +test.link lstat and stat differ at element 9 +test.file is file +test.link is link +test.file permissions are 0744 +test.file size is 0 +test.file is writeable +test.file is readable +test.file is executable +test.file is a regular file +test.link is a regular file +test.link is not a directory +../file is a directory +test.file is not a directory +test.file does not exist +test.file does not exist diff --git a/tests/std/file/002.phpt b/tests/std/file/002.phpt new file mode 100644 index 00000000..0eb882dc --- /dev/null +++ b/tests/std/file/002.phpt @@ -0,0 +1,52 @@ +--TEST-- +File/Stream functions +--FILE-- + +--EXPECT-- +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah +blah blah blah blah blah blah blah diff --git a/tests/std/file/003.phpt b/tests/std/file/003.phpt new file mode 100644 index 00000000..59e03f0c --- /dev/null +++ b/tests/std/file/003.phpt @@ -0,0 +1,41 @@ +--TEST-- +is_*() and file_exists() return values are boolean. +--FILE-- + +--EXPECT-- +boolean +boolean +boolean +boolean +boolean +boolean +boolean +boolean +boolean +boolean diff --git a/tests/std/file/004.phpt b/tests/std/file/004.phpt new file mode 100644 index 00000000..cb67225c --- /dev/null +++ b/tests/std/file/004.phpt @@ -0,0 +1,61 @@ +--TEST-- +file_put_contents() test +--FILE-- + +--EXPECT-- +String Test: OK +Integer Test: OK +Float Test: OK +Bool Test: OK +Array Test: OK diff --git a/tests/std/file/005_basic.phpt b/tests/std/file/005_basic.phpt new file mode 100644 index 00000000..3f68e010 --- /dev/null +++ b/tests/std/file/005_basic.phpt @@ -0,0 +1,37 @@ +--TEST-- +Test fileatime(), filemtime(), filectime() & touch() functions : basic functionality +--FILE-- + +--CLEAN-- + +--EXPECTF-- +*** Testing the basic functionality with file *** +%d:%s:%s:%d:%d:%d +%d:%s:%s:%d:%d:%d +%d:%s:%s:%d:%d:%d +%d:%s:%s:%d:%d:%d +*** Testing the basic functionality with dir *** +%d:%s:%s:%d:%d:%d +%d:%s:%s:%d:%d:%d +%d:%s:%s:%d:%d:%d +%d:%s:%s:%d:%d:%d + +*** Done *** diff --git a/tests/std/file/005_error.phpt b/tests/std/file/005_error.phpt new file mode 100644 index 00000000..1eda3fd1 --- /dev/null +++ b/tests/std/file/005_error.phpt @@ -0,0 +1,33 @@ +--TEST-- +Test fileatime(), filemtime(), filectime() & touch() functions : error conditions +--FILE-- + +--EXPECTF-- +*** Testing error conditions *** + +-- Testing with Non-existing files -- +Warning: %s: stat failed for /no/such/file/or/dir in %s on line %d +bool(false) + +Warning: %s: stat failed for /no/such/file/or/dir in %s on line %d +bool(false) + +Warning: %s: stat failed for /no/such/file/or/dir in %s on line %d +bool(false) + +Warning: %s: Unable to create file /no/such/file/or/dir because No such file or directory in %s on line %d +bool(false) + +Done diff --git a/tests/std/filters/001.phpt b/tests/std/filters/001.phpt new file mode 100644 index 00000000..3f0d5f5e --- /dev/null +++ b/tests/std/filters/001.phpt @@ -0,0 +1,32 @@ +--TEST-- +stream_filter_register() and invalid arguments +--FILE-- +getMessage() . "\n"; +} + +try { + stream_filter_register("test", ""); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} + +try { + stream_filter_register("", "test"); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} + +var_dump(stream_filter_register("------", "nonexistentclass")); + +echo "Done\n"; +?> +--EXPECT-- +stream_filter_register(): Argument #1 ($filter_name) must be a non-empty string +stream_filter_register(): Argument #2 ($class) must be a non-empty string +stream_filter_register(): Argument #1 ($filter_name) must be a non-empty string +bool(true) +Done diff --git a/tests/std/filters/basic.phpt b/tests/std/filters/basic.phpt new file mode 100644 index 00000000..94ebbf0f --- /dev/null +++ b/tests/std/filters/basic.phpt @@ -0,0 +1,45 @@ +--TEST-- +basic stream filter tests +--FILE-- + +--EXPECTF-- +filter: string.rot13 +resource(%d) of type (stream filter) +string(12) "Uryyb Gurer!" +filter: string.toupper +resource(%d) of type (stream filter) +string(12) "HELLO THERE!" +filter: string.tolower +resource(%d) of type (stream filter) +string(12) "hello there!" +filter: string.rot13 +resource(%d) of type (stream filter) +filter: string.toupper +resource(%d) of type (stream filter) +string(12) "URYYB GURER!" diff --git a/tests/std/filters/convert.phpt b/tests/std/filters/convert.phpt new file mode 100644 index 00000000..a3319c4e --- /dev/null +++ b/tests/std/filters/convert.phpt @@ -0,0 +1,129 @@ +--TEST-- +convert stream filter tests +--FILE-- + 20, 'line-break-chars' => "\n"); + test_roundtrip("Long text that will be wrapped", "convert.base64-encode", "convert.base64-decode", $opts); + + $opts2 = array('binary' => true); + test_roundtrip("Text\t\r\n", "convert.quoted-printable-encode", "convert.quoted-printable-decode", $opts2); + + $fp = tmpfile(); + fwrite($fp, "Test"); + rewind($fp); + stream_filter_prepend($fp, 'convert.base64-encode', STREAM_FILTER_READ); + $result = stream_get_contents($fp); + fclose($fp); + var_dump($result === base64_encode("Test")); +} +?> +--EXPECTF-- +Filter: convert.base64-encode +Original: Hello World! +Encoded: SGVsbG8gV29ybGQh +Decoded: Hello World! +bool(true) + +Filter: convert.base64-encode +Original (hex): 414243ff +Encoded: QUJD/w== +Decoded (hex): 414243ff +bool(true) + +Filter: convert.base64-encode +Original: +Encoded: +Decoded: +bool(true) + +Filter: convert.base64-encode +Original: A +Encoded: QQ== +Decoded: A +bool(true) + +Filter: convert.quoted-printable-encode +Original: Hello World! +Encoded: Hello World! +Decoded: Hello World! +bool(true) + +Filter: convert.quoted-printable-encode +Original: Line1 +Line2 +Encoded: Line1=0D=0ALine2 +Decoded: Line1 +Line2 +bool(true) + +Filter: convert.base64-encode +Original: Long text that will be wrapped +Encoded: TG9uZyB0ZXh0IHRoYXQg +d2lsbCBiZSB3cmFwcGVk +Decoded: Long text that will be wrapped +bool(true) + +Filter: convert.quoted-printable-encode +Original: Text + +Encoded: Text=09=0D=0A +Decoded: Text + +bool(true) + +bool(true) diff --git a/tests/std/general_functions/001.phpt b/tests/std/general_functions/001.phpt new file mode 100644 index 00000000..a43215c2 --- /dev/null +++ b/tests/std/general_functions/001.phpt @@ -0,0 +1,67 @@ +--TEST-- +sprintf() function +--FILE-- + +--EXPECT-- +sprintf string truncate test: passed +sprintf padding and align test: passed +sprintf octal and hex test: passed +sprintf octal binary test: passed +sprintf float test: passed +99.00 +99.00 +1.234000e-18 +1.234000e+18 +9.843243e+6 +-9.843243e+6 diff --git a/tests/std/general_functions/002.phpt b/tests/std/general_functions/002.phpt new file mode 100644 index 00000000..43c67ec0 --- /dev/null +++ b/tests/std/general_functions/002.phpt @@ -0,0 +1,11 @@ +--TEST-- +quoted_printable_decode() function test +--FILE-- + +--EXPECT-- +úwow-factorÁÐÕÝÅÎÎÙÅ + ÔÏÒÇÏ×ÙÅ ÐÒÏÅËÔÙ diff --git a/tests/std/general_functions/003.phpt b/tests/std/general_functions/003.phpt new file mode 100644 index 00000000..0851f887 --- /dev/null +++ b/tests/std/general_functions/003.phpt @@ -0,0 +1,59 @@ +--TEST-- +levenshtein() function test +--FILE-- + +--EXPECT-- +all passed diff --git a/tests/std/general_functions/007.phpt b/tests/std/general_functions/007.phpt new file mode 100644 index 00000000..53e4a534 --- /dev/null +++ b/tests/std/general_functions/007.phpt @@ -0,0 +1,26 @@ +--TEST-- +MD5 / Base64 +--FILE-- + +--EXPECT-- +d41d8cd98f00b204e9800998ecf8427e +0cc175b9c0f1b6a831c399e269772661 +900150983cd24fb0d6963f7d28e17f72 +f96b697d7cb7938d525a2f31aaf161d0 +c3fcd3d76192e4007dfb496cca67e13b +d174ab98d277d9f5a5611c2c9f419d9f +57edf4a22be3c955ac49da2e2107b67a diff --git a/tests/std/general_functions/008.phpt b/tests/std/general_functions/008.phpt new file mode 100644 index 00000000..6786fdce --- /dev/null +++ b/tests/std/general_functions/008.phpt @@ -0,0 +1,43 @@ +--TEST-- +var_dump float test +--FILE-- + +--EXPECT-- +array(14) { + [0]=> + string(2) "17" + [1]=> + float(0.012) + [2]=> + float(-0.012) + [3]=> + float(0.12) + [4]=> + float(-0.12) + [5]=> + float(1.2) + [6]=> + float(-1.2) + [7]=> + float(12) + [8]=> + float(-12) + [9]=> + float(0.000123) + [10]=> + float(1.23E-5) + [11]=> + float(123456789012) + [12]=> + float(1234567890123) + [13]=> + float(1.2345678901234567E+19) +} diff --git a/tests/std/general_functions/009.phpt b/tests/std/general_functions/009.phpt new file mode 100644 index 00000000..437190fb --- /dev/null +++ b/tests/std/general_functions/009.phpt @@ -0,0 +1,26 @@ +--TEST-- +SHA1 +--FILE-- + +--EXPECT-- +da39a3ee5e6b4b0d3255bfef95601890afd80709 +86f7e437faa5a7fce15d1ddcb9eaeaea377667b8 +a9993e364706816aba3e25717850c26c9cd0d89d +c12252ceda8be8994d5fa0290a47231c1d16aae3 +32d10c7b8cf96570ca04ce37f2a19d84240d3a89 +761c457bf73b14d27e9e9265c46f4b4dda11f940 +50abf5706a150990a08b2c5ea40fa0e585554732