From ee6445febbc577c77380e8c6d05bd7acb9316316 Mon Sep 17 00:00:00 2001 From: PurHur Date: Sun, 19 Jul 2026 01:40:49 +0000 Subject: [PATCH 1/3] Stdlib: IntlBreakIterator preceding/following/isBoundary/getLocale (#20771) Wire random-access boundary APIs and locale/error getters on the existing ICU/fallback boundaries state so PROFILE=8.4 matches php-src breakiterator. Co-authored-by: Cursor --- docs/bootstrap-inventory.md | 328 +++++++++--------- ext/intl/VmBreakIterator.php | 270 ++++++++++++++ test/compliance/JITTest.php | 8 +- test/compliance/VMTest.php | 3 +- .../breakiterator_preceding_following.php | 17 + .../breakiterator_preceding_following.phpt | 24 ++ .../issue_20771_breakiterator_preceding.php | 17 + test/unit/IntlModuleTest.php | 26 ++ 8 files changed, 533 insertions(+), 160 deletions(-) create mode 100644 test/compliance/cases/intl/breakiterator_preceding_following.php create mode 100644 test/compliance/cases/intl/breakiterator_preceding_following.phpt create mode 100644 test/repro/issue_20771_breakiterator_preceding.php diff --git a/docs/bootstrap-inventory.md b/docs/bootstrap-inventory.md index b7ec77fa752..6be6953ab21 100644 --- a/docs/bootstrap-inventory.md +++ b/docs/bootstrap-inventory.md @@ -8,11 +8,11 @@ Regenerate: `php script/bootstrap-inventory.php` | Metric | Count | |--------|------:| -| PHP files on vm.php path | 5830 | -| Phase A inventory files (M2 ratio SSOT) | 5830 | +| PHP files on vm.php path | 5831 | +| Phase A inventory files (M2 ratio SSOT) | 5831 | | Phase A ratio-deferred paths | 0 | | Source constructs flagged (blockers) | 0 | -| Source constructs flagged (warnings) | 17362 | +| Source constructs flagged (warnings) | 17374 | ## Compiler CFG gaps (`lib/Compiler.php`) @@ -830,7 +830,7 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag | `ext/intl/NormalizerIsNormalized.php` | 0 | 2 | | `ext/intl/NormalizerNormalize.php` | 0 | 2 | | `ext/intl/UnicodeCanonical.php` | 0 | 1 | -| `ext/intl/VmBreakIterator.php` | 0 | 31 | +| `ext/intl/VmBreakIterator.php` | 0 | 43 | | `ext/intl/VmCollator.php` | 0 | 55 | | `ext/intl/VmGrapheme.php` | 0 | 1 | | `ext/intl/VmIdn.php` | 0 | 5 | @@ -8481,9 +8481,9 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag - new DOMException (line 9459) - new DOMException (line 9462) - new DOMException (line 9491) -- new Error (line 10459) -- new Error (line 10463) -- 427 class method(s) +- new Error (line 10402) +- new Error (line 10406) +- 426 class method(s) - 2 closure(s) ### `ext/dom/VmDomCollectionDimension.php` @@ -11435,37 +11435,49 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag ### `ext/intl/VmBreakIterator.php` **Warnings** (review for bootstrap subset): -- new Variable (line 74) -- new ClassEntry (line 77) -- new ClassProperty (line 81) -- new ClassEntry (line 86) -- new ClassProperty (line 90) -- new ClassEntry (line 95) -- new ClassProperty (line 97) -- new PartsIteratorCurrent (line 99) -- new PartsIteratorKey (line 100) -- new PartsIteratorNext (line 101) -- new PartsIteratorRewind (line 102) -- new PartsIteratorValid (line 103) -- new Variable (line 116) -- new BreakIteratorCreateWordInstance (line 126) -- new BreakIteratorCreateCharacterInstance (line 127) -- new BreakIteratorCreateLineInstance (line 128) -- new BreakIteratorCreateSentenceInstance (line 129) -- new BreakIteratorCreateTitleInstance (line 130) -- new BreakIteratorSetText (line 142) -- new BreakIteratorGetText (line 143) -- new BreakIteratorFirst (line 144) -- new BreakIteratorLast (line 145) -- new BreakIteratorNext (line 146) -- new BreakIteratorPrevious (line 147) -- new BreakIteratorCurrent (line 148) -- new BreakIteratorGetPartsIterator (line 149) -- new ObjectEntry (line 164) -- new ObjectEntry (line 322) -- new ArgumentCountError (line 590) -- new ArgumentCountError (line 642) -- 50 class method(s) +- new Variable (line 78) +- new ClassEntry (line 81) +- new ClassProperty (line 85) +- new ClassEntry (line 90) +- new ClassProperty (line 94) +- new ClassEntry (line 99) +- new ClassProperty (line 101) +- new PartsIteratorCurrent (line 103) +- new PartsIteratorKey (line 104) +- new PartsIteratorNext (line 105) +- new PartsIteratorRewind (line 106) +- new PartsIteratorValid (line 107) +- new Variable (line 120) +- new BreakIteratorCreateWordInstance (line 130) +- new BreakIteratorCreateCharacterInstance (line 131) +- new BreakIteratorCreateLineInstance (line 132) +- new BreakIteratorCreateSentenceInstance (line 133) +- new BreakIteratorCreateTitleInstance (line 134) +- new BreakIteratorSetText (line 146) +- new BreakIteratorGetText (line 147) +- new BreakIteratorFirst (line 148) +- new BreakIteratorLast (line 149) +- new BreakIteratorNext (line 150) +- new BreakIteratorPrevious (line 151) +- new BreakIteratorCurrent (line 152) +- new BreakIteratorPreceding (line 153) +- new BreakIteratorFollowing (line 154) +- new BreakIteratorIsBoundary (line 155) +- new BreakIteratorGetLocale (line 156) +- new BreakIteratorGetErrorCode (line 157) +- new BreakIteratorGetErrorMessage (line 158) +- new BreakIteratorGetPartsIterator (line 159) +- new ObjectEntry (line 174) +- new ObjectEntry (line 446) +- new ArgumentCountError (line 714) +- new ArgumentCountError (line 766) +- new ArgumentCountError (line 865) +- new ArgumentCountError (line 885) +- new ArgumentCountError (line 905) +- new ArgumentCountError (line 925) +- new ArgumentCountError (line 946) +- new ArgumentCountError (line 965) +- 65 class method(s) ### `ext/intl/VmCollator.php` @@ -41620,111 +41632,111 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag - new Variable (line 9115) - new Variable (line 9122) - new Variable (line 9139) -- new VM\NativeFiberStackOverflow (line 9953) -- new VM\BuiltinCallbackCatchRedirect (line 10004) -- new VM\BuiltinCallbackCatchRedirect (line 10022) -- new Variable (line 10125) -- new Variable (line 10233) -- new Variable (line 10366) -- new ScriptExit (line 10522) -- new Exception (line 10539) -- new ScriptExit (line 10547) -- new Error (line 10810) -- new VM\PropertyHookRefWriteSignal (line 10858) -- new Variable (line 10882) -- new VM\PropertyHookRefWriteSignal (line 10887) -- new VM\PropertyHookFiberSuspendSignal (line 10890) -- new VM\PropertyHookRefWriteSignal (line 11012) -- new Variable (line 11029) -- new VM\PropertyHookRefWriteSignal (line 11043) -- new VM\PropertyHookRefWriteSignal (line 11055) -- new Variable (line 11286) -- new Variable (line 11309) -- new Variable (line 11319) -- new Variable (line 11329) -- new VM\PropertyHookRefWriteSignal (line 11335) -- new VM\PropertyHookRefWriteSignal (line 11343) -- new VM\PropertyHookRefWriteSignal (line 11346) -- new Variable (line 11358) -- new Variable (line 11372) -- new VM\PropertyHookRefWriteSignal (line 11378) -- new Variable (line 11409) -- new VM\PropertyHookRefWriteSignal (line 11414) -- new VM\PropertyHookFiberSuspendSignal (line 11417) -- new Error (line 11916) -- new Error (line 11926) -- new Error (line 11936) -- new Error (line 11946) -- new ClassEntry (line 12716) -- new Variable (line 12717) -- new VM\ClassProperty (line 12718) -- new ObjectEntry (line 12721) -- new Variable (line 12724) -- new Variable (line 12805) -- new Error (line 12891) -- new Variable (line 12983) -- new VM\GeneratorUncaughtThrow (line 12985) -- new Error (line 13054) -- new Variable (line 13099) -- new VM\GeneratorUncaughtThrow (line 13113) -- new Variable (line 13202) -- new VM\GeneratorUncaughtThrow (line 13222) -- new Variable (line 13290) -- new Variable (line 13292) -- new Variable (line 13296) -- new Variable (line 13426) -- new Variable (line 13468) -- new Variable (line 13639) -- new Variable (line 13655) -- new Variable (line 13700) -- new Variable (line 13841) -- new Variable (line 13915) -- new Variable (line 14079) -- new VM\PropertyIsInitializedHandler (line 14088) -- new Error (line 14203) -- new VM\EnumFromHandler (line 14228) -- new CompileError (line 14954) -- new VM\ClassProperty (line 15119) -- new Variable (line 15427) -- new Variable (line 15622) -- new Variable (line 15624) -- new ClassEntry (line 15667) -- new Func\PHP (line 15674) -- new VM\ClassProperty (line 15802) -- new Func\PHP (line 15949) -- new Variable (line 16025) -- new Variable (line 16032) -- new Variable (line 16038) -- new Variable (line 16075) -- new Variable (line 16104) -- new Variable (line 16289) -- new Variable (line 16335) -- new VM\ClassProperty (line 16400) -- new Error (line 16446) -- new Error (line 16481) -- new Error (line 16484) -- new Error (line 16487) -- new Error (line 16490) -- new ObjectEntry (line 16492) -- new Error (line 16505) -- new Error (line 16508) -- new Error (line 16511) +- new VM\NativeFiberStackOverflow (line 9972) +- new VM\BuiltinCallbackCatchRedirect (line 10023) +- new VM\BuiltinCallbackCatchRedirect (line 10041) +- new Variable (line 10144) +- new Variable (line 10252) +- new Variable (line 10385) +- new ScriptExit (line 10541) +- new Exception (line 10558) +- new ScriptExit (line 10566) +- new Error (line 10829) +- new VM\PropertyHookRefWriteSignal (line 10877) +- new Variable (line 10901) +- new VM\PropertyHookRefWriteSignal (line 10906) +- new VM\PropertyHookFiberSuspendSignal (line 10909) +- new VM\PropertyHookRefWriteSignal (line 11031) +- new Variable (line 11048) +- new VM\PropertyHookRefWriteSignal (line 11062) +- new VM\PropertyHookRefWriteSignal (line 11074) +- new Variable (line 11305) +- new Variable (line 11328) +- new Variable (line 11338) +- new Variable (line 11348) +- new VM\PropertyHookRefWriteSignal (line 11354) +- new VM\PropertyHookRefWriteSignal (line 11362) +- new VM\PropertyHookRefWriteSignal (line 11365) +- new Variable (line 11377) +- new Variable (line 11391) +- new VM\PropertyHookRefWriteSignal (line 11397) +- new Variable (line 11428) +- new VM\PropertyHookRefWriteSignal (line 11433) +- new VM\PropertyHookFiberSuspendSignal (line 11436) +- new Error (line 11935) +- new Error (line 11945) +- new Error (line 11955) +- new Error (line 11965) +- new ClassEntry (line 12735) +- new Variable (line 12736) +- new VM\ClassProperty (line 12737) +- new ObjectEntry (line 12740) +- new Variable (line 12743) +- new Variable (line 12824) +- new Error (line 12910) +- new Variable (line 13002) +- new VM\GeneratorUncaughtThrow (line 13004) +- new Error (line 13073) +- new Variable (line 13118) +- new VM\GeneratorUncaughtThrow (line 13132) +- new Variable (line 13221) +- new VM\GeneratorUncaughtThrow (line 13241) +- new Variable (line 13309) +- new Variable (line 13311) +- new Variable (line 13315) +- new Variable (line 13445) +- new Variable (line 13487) +- new Variable (line 13658) +- new Variable (line 13674) +- new Variable (line 13719) +- new Variable (line 13860) +- new Variable (line 13934) +- new Variable (line 14098) +- new VM\PropertyIsInitializedHandler (line 14107) +- new Error (line 14222) +- new VM\EnumFromHandler (line 14247) +- new CompileError (line 14973) +- new VM\ClassProperty (line 15138) +- new Variable (line 15446) +- new Variable (line 15641) +- new Variable (line 15643) +- new ClassEntry (line 15686) +- new Func\PHP (line 15693) +- new VM\ClassProperty (line 15821) +- new Func\PHP (line 15968) +- new Variable (line 16044) +- new Variable (line 16051) +- new Variable (line 16057) +- new Variable (line 16094) +- new Variable (line 16123) +- new Variable (line 16308) +- new Variable (line 16354) +- new VM\ClassProperty (line 16419) +- new Error (line 16465) +- new Error (line 16500) +- new Error (line 16503) +- new Error (line 16506) +- new Error (line 16509) +- new ObjectEntry (line 16511) +- new Error (line 16524) +- new Error (line 16527) - new Error (line 16530) -- new ObjectEntry (line 16534) -- new Variable (line 16536) -- new Variable (line 16550) -- new Variable (line 16577) -- new Variable (line 16590) -- new Error (line 16720) -- new Error (line 16725) -- new VM\ObjectEntry (line 16729) -- new Variable (line 16873) -- new Variable (line 16891) -- new NoDiscardMetadata (line 17060) -- new Variable (line 17229) -- new Variable (line 17231) -- new Variable (line 17331) -- 488 class method(s) +- new Error (line 16549) +- new ObjectEntry (line 16553) +- new Variable (line 16555) +- new Variable (line 16569) +- new Variable (line 16596) +- new Variable (line 16609) +- new Error (line 16739) +- new Error (line 16744) +- new VM\ObjectEntry (line 16748) +- new Variable (line 16892) +- new Variable (line 16910) +- new NoDiscardMetadata (line 17079) +- new Variable (line 17248) +- new Variable (line 17250) +- new Variable (line 17350) +- 489 class method(s) - 25 closure(s) ### `lib/VM/AbstractPropertyHookCheck.php` @@ -44316,10 +44328,10 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag ### `lib/VM/BuiltinExceptionSupport.php` **Warnings** (review for bootstrap subset): -- new ObjectEntry (line 544) -- new Variable (line 548) -- new ObjectEntry (line 564) -- new Variable (line 568) +- new ObjectEntry (line 554) +- new Variable (line 558) +- new ObjectEntry (line 574) +- new Variable (line 578) - 37 class method(s) ### `lib/VM/BuiltinExecute.php` @@ -44754,18 +44766,18 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag ### `lib/VM/ExceptionSupport.php` **Warnings** (review for bootstrap subset): -- new ReflectionObject (line 364) -- new ScriptExit (line 386) -- new ScriptExit (line 416) -- new ErrorException (line 572) -- new SoapFault (line 602) -- new Error (line 615) -- new FiberStackOverflow (line 618) -- new Error (line 620) -- new Error (line 623) -- new Exception (line 625) -- new Exception (line 647) -- new Error (line 655) +- new ReflectionObject (line 365) +- new ScriptExit (line 387) +- new ScriptExit (line 417) +- new ErrorException (line 573) +- new SoapFault (line 603) +- new Error (line 616) +- new FiberStackOverflow (line 619) +- new Error (line 621) +- new Error (line 624) +- new Exception (line 626) +- new Exception (line 648) +- new Error (line 656) - 26 class method(s) ### `lib/VM/ExceptionTrace.php` diff --git a/ext/intl/VmBreakIterator.php b/ext/intl/VmBreakIterator.php index 957c70b886b..4b1ff37c92e 100644 --- a/ext/intl/VmBreakIterator.php +++ b/ext/intl/VmBreakIterator.php @@ -11,6 +11,7 @@ use PHPCompiler\VM\Context; use PHPCompiler\VM\ObjectEntry; use PHPCompiler\VM\Variable; +use PHPCompiler\VM\ReflectionSupport; use PHPCfg\Func as CfgFunc; /** @@ -29,6 +30,9 @@ final class VmBreakIterator private const UBRK_WORD = 1; private const UBRK_LINE = 2; private const UBRK_SENTENCE = 3; + /** ULOC_ACTUAL_LOCALE / ULOC_VALID_LOCALE — php-src Locale::ACTUAL_LOCALE / VALID_LOCALE */ + private const ULOC_ACTUAL_LOCALE = 0; + private const ULOC_VALID_LOCALE = 1; private const PROP_HANDLE = '__breakiterator_id'; /** @var array> */ @@ -146,6 +150,12 @@ private static function installInstanceMethods(ClassEntry $entry, int $vis): voi 'next' => [new BreakIteratorNext(), 'next'], 'previous' => [new BreakIteratorPrevious(), 'previous'], 'current' => [new BreakIteratorCurrent(), 'current'], + 'preceding' => [new BreakIteratorPreceding(), 'preceding'], + 'following' => [new BreakIteratorFollowing(), 'following'], + 'isboundary' => [new BreakIteratorIsBoundary(), 'isBoundary'], + 'getlocale' => [new BreakIteratorGetLocale(), 'getLocale'], + 'geterrorcode' => [new BreakIteratorGetErrorCode(), 'getErrorCode'], + 'geterrormessage' => [new BreakIteratorGetErrorMessage(), 'getErrorMessage'], 'getpartsiterator' => [new BreakIteratorGetPartsIterator(), 'getPartsIterator'], ]; foreach ($methods as $lc => [$handler, $name]) { @@ -172,8 +182,11 @@ public static function createInstance(Context $ctx, int $type, ?string $locale): 'boundaries' => [0], 'parts' => null, 'index' => 0, + 'errorCode' => IntlError::U_ZERO_ERROR, + 'errorMessage' => 'U_ZERO_ERROR', ]; $obj->constructed = true; + self::clearObjectError($obj); IntlError::clear(); return $obj; @@ -216,6 +229,7 @@ public static function setText(ObjectEntry $obj, string $text): bool $st['text'] = $text; $st['boundaries'] = self::computeBoundaries((int) $st['type'], (string) $st['locale'], $text); $st['pos'] = $st['boundaries'][0] ?? 0; + self::clearObjectError($obj); IntlError::clear(); return true; @@ -261,11 +275,15 @@ public static function nextPos(ObjectEntry $obj, ?int $offset = null): int foreach ($bounds as $b) { if ($b > $offset) { $st['pos'] = $b; + self::clearObjectError($obj); + IntlError::clear(); return (int) $b; } } $st['pos'] = self::DONE; + self::clearObjectError($obj); + IntlError::clear(); return self::DONE; } @@ -299,6 +317,112 @@ public static function previousPos(ObjectEntry $obj): int return $prev; } + /** + * preceding($offset) — largest boundary strictly before $offset (ICU ubrk_preceding; #20771). + */ + public static function preceding(ObjectEntry $obj, int $offset): int + { + $st = &self::stateRef($obj); + $prev = self::DONE; + foreach ($st['boundaries'] as $b) { + $b = (int) $b; + if ($b >= $offset) { + break; + } + $prev = $b; + } + $st['pos'] = $prev; + self::clearObjectError($obj); + IntlError::clear(); + + return $prev; + } + + /** + * following($offset) — first boundary strictly after $offset (ICU ubrk_following; #20771). + */ + public static function following(ObjectEntry $obj, int $offset): int + { + return self::nextPos($obj, $offset); + } + + /** + * isBoundary($offset) — whether $offset is a break; advances to first boundary at/after offset + * (ICU ubrk_isBoundary; #20771). + */ + public static function isBoundary(ObjectEntry $obj, int $offset): bool + { + $st = &self::stateRef($obj); + $bounds = $st['boundaries']; + $is = \in_array($offset, $bounds, true); + $atOrAfter = self::DONE; + foreach ($bounds as $b) { + $b = (int) $b; + if ($b >= $offset) { + $atOrAfter = $b; + break; + } + } + $st['pos'] = $atOrAfter; + self::clearObjectError($obj); + IntlError::clear(); + + return $is; + } + + /** + * getLocale($type) — ULOC_ACTUAL_LOCALE / ULOC_VALID_LOCALE (php-src breakiterator_get_locale; #20771). + * + * Without a live UBreakIterator handle, VALID returns the factory locale and ACTUAL is '' + * (matches Zend ICU for createWordInstance('en_US')). + * + * @return string|false + */ + public static function getLocale(ObjectEntry $obj, int $type) + { + $st = self::stateRef($obj); + self::clearObjectError($obj); + IntlError::clear(); + if (self::ULOC_ACTUAL_LOCALE === $type) { + return ''; + } + if (self::ULOC_VALID_LOCALE === $type) { + return (string) $st['locale']; + } + self::fail($obj, 'breakiterator_get_locale: bad type: U_ILLEGAL_ARGUMENT_ERROR'); + + return false; + } + + public static function getErrorCode(ObjectEntry $obj): int + { + $st = self::stateRef($obj); + + return (int) ($st['errorCode'] ?? IntlError::U_ZERO_ERROR); + } + + public static function getErrorMessage(ObjectEntry $obj): string + { + $st = self::stateRef($obj); + + return (string) ($st['errorMessage'] ?? 'U_ZERO_ERROR'); + } + + private static function clearObjectError(ObjectEntry $obj): void + { + $st = &self::stateRef($obj); + $st['errorCode'] = IntlError::U_ZERO_ERROR; + $st['errorMessage'] = 'U_ZERO_ERROR'; + } + + private static function fail(ObjectEntry $obj, string $message): void + { + IntlError::set(IntlError::U_ILLEGAL_ARGUMENT_ERROR, $message); + $st = &self::stateRef($obj); + $st['errorCode'] = IntlError::U_ILLEGAL_ARGUMENT_ERROR; + $st['errorMessage'] = $message; + } + /** @return list */ public static function parts(ObjectEntry $obj): array { @@ -731,6 +855,152 @@ public function execute(Frame $frame): void } } +final class BreakIteratorPreceding extends VmClassMethod +{ + public function __construct() { parent::__construct('preceding'); } + public function execute(Frame $frame): void + { + $argc = \count($frame->calledArgs); + if ($argc !== 2) { + throw new \ArgumentCountError(sprintf( + 'IntlBreakIterator::preceding() expects exactly 1 argument, %d given', + max(0, $argc - 1) + )); + } + $obj = VmBreakIterator::requireBreakIterator($frame, $frame->calledArgs[0]); + $offset = BreakIteratorOffsetArg::coerce($frame->calledArgs[1], 'IntlBreakIterator::preceding'); + if (null !== $frame->returnVar) { + $frame->returnVar->int(VmBreakIterator::preceding($obj, $offset)); + } + } +} + +final class BreakIteratorFollowing extends VmClassMethod +{ + public function __construct() { parent::__construct('following'); } + public function execute(Frame $frame): void + { + $argc = \count($frame->calledArgs); + if ($argc !== 2) { + throw new \ArgumentCountError(sprintf( + 'IntlBreakIterator::following() expects exactly 1 argument, %d given', + max(0, $argc - 1) + )); + } + $obj = VmBreakIterator::requireBreakIterator($frame, $frame->calledArgs[0]); + $offset = BreakIteratorOffsetArg::coerce($frame->calledArgs[1], 'IntlBreakIterator::following'); + if (null !== $frame->returnVar) { + $frame->returnVar->int(VmBreakIterator::following($obj, $offset)); + } + } +} + +final class BreakIteratorIsBoundary extends VmClassMethod +{ + public function __construct() { parent::__construct('isBoundary'); } + public function execute(Frame $frame): void + { + $argc = \count($frame->calledArgs); + if ($argc !== 2) { + throw new \ArgumentCountError(sprintf( + 'IntlBreakIterator::isBoundary() expects exactly 1 argument, %d given', + max(0, $argc - 1) + )); + } + $obj = VmBreakIterator::requireBreakIterator($frame, $frame->calledArgs[0]); + $offset = BreakIteratorOffsetArg::coerce($frame->calledArgs[1], 'IntlBreakIterator::isBoundary'); + if (null !== $frame->returnVar) { + $frame->returnVar->bool(VmBreakIterator::isBoundary($obj, $offset)); + } + } +} + +final class BreakIteratorGetLocale extends VmClassMethod +{ + public function __construct() { parent::__construct('getLocale'); } + public function execute(Frame $frame): void + { + $argc = \count($frame->calledArgs); + if ($argc !== 2) { + throw new \ArgumentCountError(sprintf( + 'IntlBreakIterator::getLocale() expects exactly 1 argument, %d given', + max(0, $argc - 1) + )); + } + $obj = VmBreakIterator::requireBreakIterator($frame, $frame->calledArgs[0]); + $type = BreakIteratorOffsetArg::coerce($frame->calledArgs[1], 'IntlBreakIterator::getLocale', 'type'); + $result = VmBreakIterator::getLocale($obj, $type); + if (null !== $frame->returnVar) { + false === $result ? $frame->returnVar->bool(false) : $frame->returnVar->string($result); + } + } +} + +final class BreakIteratorGetErrorCode extends VmClassMethod +{ + public function __construct() { parent::__construct('getErrorCode'); } + public function execute(Frame $frame): void + { + $argc = \count($frame->calledArgs); + if ($argc !== 1) { + throw new \ArgumentCountError(sprintf( + 'IntlBreakIterator::getErrorCode() expects exactly 0 arguments, %d given', + max(0, $argc - 1) + )); + } + $obj = VmBreakIterator::requireBreakIterator($frame, $frame->calledArgs[0]); + if (null !== $frame->returnVar) { + $frame->returnVar->int(VmBreakIterator::getErrorCode($obj)); + } + } +} + +final class BreakIteratorGetErrorMessage extends VmClassMethod +{ + public function __construct() { parent::__construct('getErrorMessage'); } + public function execute(Frame $frame): void + { + $argc = \count($frame->calledArgs); + if ($argc !== 1) { + throw new \ArgumentCountError(sprintf( + 'IntlBreakIterator::getErrorMessage() expects exactly 0 arguments, %d given', + max(0, $argc - 1) + )); + } + $obj = VmBreakIterator::requireBreakIterator($frame, $frame->calledArgs[0]); + if (null !== $frame->returnVar) { + $frame->returnVar->string(VmBreakIterator::getErrorMessage($obj)); + } + } +} + +/** Coerce int offset / locale-type args for BreakIterator (#20771). */ +final class BreakIteratorOffsetArg +{ + public static function coerce(Variable $arg, string $method, string $param = 'offset'): int + { + $arg = $arg->resolveIndirect(); + if (Variable::TYPE_INTEGER === $arg->type) { + return $arg->toInt(); + } + if (Variable::TYPE_FLOAT === $arg->type) { + return (int) $arg->toFloat(); + } + if (Variable::TYPE_BOOLEAN === $arg->type) { + return $arg->toBool() ? 1 : 0; + } + if (Variable::TYPE_STRING === $arg->type && is_numeric($arg->toString())) { + return (int) $arg->toString(); + } + throw new \TypeError(sprintf( + '%s(): Argument #1 ($%s) must be of type int, %s given', + $method, + $param, + ReflectionSupport::valueTypeLabelPublic($arg) + )); + } +} + final class BreakIteratorGetPartsIterator extends VmClassMethod { public function __construct() { parent::__construct('getPartsIterator'); } diff --git a/test/compliance/JITTest.php b/test/compliance/JITTest.php index 57c1ea6488a..8be64a62779 100755 --- a/test/compliance/JITTest.php +++ b/test/compliance/JITTest.php @@ -641,7 +641,8 @@ public static function providePHPTests(): \Generator || str_contains($name, 'intl_skeleton') || str_contains($name, 'intl_char') || str_contains($name, 'intl_uconverter') - || str_contains($name, 'collator_')) + || str_contains($name, 'collator_') + || str_contains($name, 'breakiterator')) && !str_contains($name, 'intl_phantom')) { continue; } @@ -1395,6 +1396,11 @@ public static function providePHPTests(): \Generator if (str_contains($name, 'resourcebundle_locales_errors')) { continue; } + // IntlBreakIterator preceding/following: VM + bin/jit.php repro green (#20771); + // MCJIT PHPT harness hits WeakRefNativeOpsJit::nullSlot getValue() abort (same as above). + if (str_contains($name, 'breakiterator_preceding_following')) { + continue; + } // Phar instance API: VM green (#20628); jit.php hits MathBaseConvertRuntime::constFloat // (hexdec/WeakRef bootstrap) same as curl_share_init_persistent. if (str_contains($name, 'phar_instance_api')) { diff --git a/test/compliance/VMTest.php b/test/compliance/VMTest.php index abacaa02d47..4f524c38d49 100755 --- a/test/compliance/VMTest.php +++ b/test/compliance/VMTest.php @@ -526,7 +526,8 @@ public static function providePHPTests(): \Generator || str_contains($name, 'intl_skeleton') || str_contains($name, 'intl_char') || str_contains($name, 'intl_uconverter') - || str_contains($name, 'collator_')) + || str_contains($name, 'collator_') + || str_contains($name, 'breakiterator')) && !str_contains($name, 'intl_phantom')) { continue; } diff --git a/test/compliance/cases/intl/breakiterator_preceding_following.php b/test/compliance/cases/intl/breakiterator_preceding_following.php new file mode 100644 index 00000000000..2304f5380e4 --- /dev/null +++ b/test/compliance/cases/intl/breakiterator_preceding_following.php @@ -0,0 +1,17 @@ +setText('Hello world'); +echo 'preceding=', method_exists($bi, 'preceding') ? '1' : '0', "\n"; +echo 'following=', method_exists($bi, 'following') ? '1' : '0', "\n"; +echo 'isBoundary=', method_exists($bi, 'isBoundary') ? '1' : '0', "\n"; +echo 'getLocale=', method_exists($bi, 'getLocale') ? '1' : '0', "\n"; +echo 'preceding6=', $bi->preceding(6), "\n"; +echo 'cur=', $bi->current(), "\n"; +echo 'following6=', $bi->following(6), "\n"; +echo 'b5=', (int) $bi->isBoundary(5), "\n"; +echo 'b6=', (int) $bi->isBoundary(6), "\n"; +echo 'b7=', (int) $bi->isBoundary(7), "\n"; +echo 'actual=', var_export($bi->getLocale(0), true), "\n"; +echo 'valid=', var_export($bi->getLocale(1), true), "\n"; +echo 'err=', $bi->getErrorCode(), ':', $bi->getErrorMessage(), "\n"; diff --git a/test/compliance/cases/intl/breakiterator_preceding_following.phpt b/test/compliance/cases/intl/breakiterator_preceding_following.phpt new file mode 100644 index 00000000000..9f25d52ac8c --- /dev/null +++ b/test/compliance/cases/intl/breakiterator_preceding_following.phpt @@ -0,0 +1,24 @@ +--TEST-- +IntlBreakIterator preceding/following/isBoundary/getLocale (#20771) +--SKIPIF-- + +--RUNFILE-- +breakiterator_preceding_following.php +--EXPECT-- +preceding=1 +following=1 +isBoundary=1 +getLocale=1 +preceding6=5 +cur=5 +following6=11 +b5=1 +b6=1 +b7=0 +actual='' +valid='en_US' +err=0:U_ZERO_ERROR diff --git a/test/repro/issue_20771_breakiterator_preceding.php b/test/repro/issue_20771_breakiterator_preceding.php new file mode 100644 index 00000000000..784c0c19a73 --- /dev/null +++ b/test/repro/issue_20771_breakiterator_preceding.php @@ -0,0 +1,17 @@ +setText('Hello world'); +foreach (['preceding', 'following', 'isBoundary', 'getLocale', 'getErrorCode', 'getErrorMessage'] as $m) { + echo $m, '=', method_exists($bi, $m) ? '1' : '0', "\n"; +} +echo 'preceding6=', $bi->preceding(6), "\n"; +echo 'current_after_preceding=', $bi->current(), "\n"; +echo 'following6=', $bi->following(6), "\n"; +echo 'isBoundary5=', (int) $bi->isBoundary(5), "\n"; +echo 'isBoundary6=', (int) $bi->isBoundary(6), "\n"; +echo 'isBoundary7=', (int) $bi->isBoundary(7), "\n"; +// ULOC_ACTUAL_LOCALE=0 / ULOC_VALID_LOCALE=1 (Locale::ACTUAL_LOCALE / VALID_LOCALE) +echo 'locale_actual=', var_export($bi->getLocale(0), true), "\n"; +echo 'locale_valid=', var_export($bi->getLocale(1), true), "\n"; +echo 'err=', $bi->getErrorCode(), ':', $bi->getErrorMessage(), "\n"; diff --git a/test/unit/IntlModuleTest.php b/test/unit/IntlModuleTest.php index 6b47ba93427..cbbd8faf161 100644 --- a/test/unit/IntlModuleTest.php +++ b/test/unit/IntlModuleTest.php @@ -222,4 +222,30 @@ public function test_breakiterator_word_parts_via_forced_registration(): void ob_get_clean() ); } + + public function test_breakiterator_preceding_following_locale_via_forced_registration(): void + { + $runtime = new Runtime(); + \PHPCompiler\ext\intl\BuiltinClasses::registerBreakIterator($runtime->vmContext); + $code = <<<'PHP' +setText('Hello world'); +echo (int) method_exists($bi, 'preceding'), "\n"; +echo $bi->preceding(6), "\n"; +echo $bi->current(), "\n"; +echo $bi->following(6), "\n"; +echo (int) $bi->isBoundary(5), (int) $bi->isBoundary(6), (int) $bi->isBoundary(7), "\n"; +echo var_export($bi->getLocale(0), true), "\n"; +echo var_export($bi->getLocale(1), true), "\n"; +echo $bi->getErrorCode(), ':', $bi->getErrorMessage(), "\n"; +PHP; + $block = $runtime->parseAndCompile($code, 'intl_breakiterator_preceding.php'); + ob_start(); + $runtime->run($block); + self::assertSame( + "1\n5\n5\n11\n110\n''\n'en_US'\n0:U_ZERO_ERROR\n", + ob_get_clean() + ); + } } From d026692f07e6cc1418fb34fd8e18239caf439787 Mon Sep 17 00:00:00 2001 From: PurHur Date: Sun, 19 Jul 2026 01:49:21 +0000 Subject: [PATCH 2/3] Docs: sync spine footnotes + inventory after #20776 rebase ci-fast auto-heal for 5831/5831 footnotes and VmDom construct-flag refresh. Co-authored-by: Cursor --- README.md | 8 ++++---- docs/bootstrap-inventory.md | 6 +++--- docs/bootstrap-profile.json | 8 ++++++-- docs/bootstrap-selfhost.md | 6 +++--- docs/pages/development-status.md | 12 ++++++------ docs/pages/index.html | 10 +++++----- docs/roadmap-wave3.md | 6 +++--- docs/self-host-target.md | 8 ++++---- test/unit/BootstrapSelfhostBundleTest.php | 2 +- 9 files changed, 35 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index 8a8f38e0fec..5b9b3e139b9 100755 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ > **Stable line (2026)** — First maintained **stable** release **[v1.0.0](https://github.com/PurHur/php-compiler/releases/tag/v1.0.0)**; **v1.1.0** prep adds M5 fast-path stability, enum/property-hook parity, `preg_match` JIT, `spl_autoload*`, and php-in-PHP JIT helpers. Demo-ready VM + AOT for a **web-capable PHP subset**, reference examples **000–009**, and an experimental **self-host** path. Not full Zend PHP compatibility — see [what’s missing](https://purhur.github.io/php-compiler/docs/pages/missing-implementation.html). -**Snapshot (Jul 2026, `master` — v1.1.0 prep):** VM + AOT for shipped examples ✅ · examples web smoke ✅ · self-host spine **5809** / **5809** · **852** builtins · M5 fast + strict ✅ · VM probe ~**20ms** +**Snapshot (Jul 2026, `master` — v1.1.0 prep):** VM + AOT for shipped examples ✅ · examples web smoke ✅ · self-host spine **5831** / **5831** · **852** builtins · M5 fast + strict ✅ · VM probe ~**20ms** --- @@ -23,7 +23,7 @@ | **AOT (`phpc build`)** | ✅ For curated subset | Standalone binaries for examples **000–009** and small CGI apps; not arbitrary Composer stacks | | **JIT (`bin/jit.php`)** | 🚧 Partial | LLVM IR for many constructs; **MCJIT execute** still flaky ([#98](https://github.com/PurHur/php-compiler/issues/98)); EH scripts VM-fallback ([#2114](https://github.com/PurHur/php-compiler/issues/2114)) | | **Language wave 3** | ✅ Closed batch | **12/12** language + **13/13** stdlib tracker items ([#1380](https://github.com/PurHur/php-compiler/issues/1380)); closures, try/catch, generators (VM), `parent::class`, backed enums (VM), intersection AOT checks | -| **Self-host north star** | ✅ ~90% | M5 fast gate green; spine **5809** / **5809**; vendor prelink **3/3** ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) | +| **Self-host north star** | ✅ ~90% | M5 fast gate green; spine **5831** / **5831**; vendor prelink **3/3** ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) | ### What you can rely on today @@ -40,7 +40,7 @@ Counts from `php script/bootstrap-spine-count.php` (literal `require_once` in `c | Milestone | Status | What it means | |-----------|--------|----------------| | **M0–M1** | ✅ | `compiler_minimal` + compile-smoke bundles link and run natively | -| **M2** | ✅ **5809** / **5809** | Full Phase A inventory in spine smoke; native link + lint ✅ | +| **M2** | ✅ **5831** / **5831** | Full Phase A inventory in spine smoke; native link + lint ✅ | | **M3** | ✅ | HelloWorld strict native ✅; inventory argv `bin/compile.php` ✅ | | **M4** | ✅ | `make bootstrap-loop-probe` full ladder ✅ (gen-1→gen-2→gen-3 + full-revision) | | **M5** | ✅ | `make north-star5-verify-fast` (daily); `--strict` pre-merge ✅; vendor **3/3** ✅; gen-0 sidecars refreshed | @@ -259,7 +259,7 @@ Full matrices (auto-generated): [`docs/capabilities.md`](docs/capabilities.md) ( **Self-host (experimental, not “stable app” scope)** -See [Current implementation status](#current-implementation-status-june-2026) for the full M0–M5 ladder. Summary: M0–M5 bootstrap gates ✅; spine **5809** / **5809**; M3 strict native + inventory argv ✅; M4 full `bootstrap-loop-probe` ✅; M5 **`north-star5-verify-fast`** (daily) + **`--strict`** pre-merge ✅ ([#1492](https://github.com/PurHur/php-compiler/issues/1492), [#8559](https://github.com/PurHur/php-compiler/issues/8559)). Recent: native spine bundle probe, fast VM execute smoke ([#2201](https://github.com/PurHur/php-compiler/issues/2201)), `GeneratorYieldSourceMarker` spine unit ([#10356](https://github.com/PurHur/php-compiler/pull/10356)). +See [Current implementation status](#current-implementation-status-june-2026) for the full M0–M5 ladder. Summary: M0–M5 bootstrap gates ✅; spine **5831** / **5831**; M3 strict native + inventory argv ✅; M4 full `bootstrap-loop-probe` ✅; M5 **`north-star5-verify-fast`** (daily) + **`--strict`** pre-merge ✅ ([#1492](https://github.com/PurHur/php-compiler/issues/1492), [#8559](https://github.com/PurHur/php-compiler/issues/8559)). Recent: native spine bundle probe, fast VM execute smoke ([#2201](https://github.com/PurHur/php-compiler/issues/2201)), `GeneratorYieldSourceMarker` spine unit ([#10356](https://github.com/PurHur/php-compiler/pull/10356)). **What we do not target in v1.x** diff --git a/docs/bootstrap-inventory.md b/docs/bootstrap-inventory.md index 6be6953ab21..0e148b03a3d 100644 --- a/docs/bootstrap-inventory.md +++ b/docs/bootstrap-inventory.md @@ -8481,9 +8481,9 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag - new DOMException (line 9459) - new DOMException (line 9462) - new DOMException (line 9491) -- new Error (line 10402) -- new Error (line 10406) -- 426 class method(s) +- new Error (line 10459) +- new Error (line 10463) +- 427 class method(s) - 2 closure(s) ### `ext/dom/VmDomCollectionDimension.php` diff --git a/docs/bootstrap-profile.json b/docs/bootstrap-profile.json index ddc002fda3f..faa534cb30f 100644 --- a/docs/bootstrap-profile.json +++ b/docs/bootstrap-profile.json @@ -893,6 +893,10 @@ "ext/intl/normalizer_get_raw_decomposition.php", "ext/intl/normalizer_is_normalized.php", "ext/intl/normalizer_normalize.php", + "ext/intl/numfmt_create.php", + "ext/intl/numfmt_format.php", + "ext/intl/numfmt_format_currency.php", + "ext/intl/numfmt_parse.php", "ext/intl/transliterator_create.php", "ext/intl/transliterator_create_from_rules.php", "ext/intl/transliterator_create_inverse.php", @@ -6060,9 +6064,9 @@ "test/bootstrap-aot/lib_opcode/main.php" ], "totals": { - "inventory_files": 5827, + "inventory_files": 5831, "excluded": 0, - "eligible": 5827, + "eligible": 5831, "aot_lint_targets": 113, "aot_link_targets": 100, "aot_link_lib_targets": 1 diff --git a/docs/bootstrap-selfhost.md b/docs/bootstrap-selfhost.md index 247bcd9a809..9bb3e7f98bd 100644 --- a/docs/bootstrap-selfhost.md +++ b/docs/bootstrap-selfhost.md @@ -2,7 +2,7 @@ **Gen-0 without Zend:** `BOOTSTRAP_M5_NO_ZEND=1 make bootstrap-selfhost-link` installs `prelinked/bootstrap-gen0/bin-compile-aot` and links `compiler_minimal` without `php bin/compile.php` ([#3053](https://github.com/PurHur/php-compiler/issues/3053)). **M5 lib spine compile:** `BOOTSTRAP_NO_ZEND_FALLBACK=1 make bootstrap-selfhost-lib-spine-smoke` (default in link script) refuses host `php bin/compile.php` on the spine emit path ([#8716](https://github.com/PurHur/php-compiler/issues/8716)). **Contributor workflow:** [bootstrap-dev-workflow.md](bootstrap-dev-workflow.md) (tiered gen-1+ path, spine checklist, CI). -**Project north star:** The **compiler fully compiles itself** — native AOT from `lib/` (no `vendor/` at cold boot), then compiles PHP and rebuilds the next compiler revision without Zend. **M2 spine:** **5809** / **5809** Phase A inventory (`php script/bootstrap-spine-count.php`; `check-selfhost-spine-coverage-sync.php`). **M5 daily gate:** `make north-star5-verify-fast` (~1–2 min) ✅; **`--strict`** (~1h) pre-merge only. Committed `prelinked/bootstrap-gen0/` sidecars + vendor **3/3** cold boot. **Hot loop:** VM driver execute probe ~**20ms**; full spine relink only with `BOOTSTRAP_VM_DRIVER_EXECUTE_PROBE_FULL_LINK=1` ([#2201](https://github.com/PurHur/php-compiler/issues/2201)). **Living tracker:** [#1492](https://github.com/PurHur/php-compiler/issues/1492) (was [#1056](https://github.com/PurHur/php-compiler/issues/1056)) · **re-root doc:** [self-host-target.md](self-host-target.md) · **generation ladder:** [bootstrap-generations.md](bootstrap-generations.md) · **M5 fast path:** [bootstrap-m5-fast-path.md](bootstrap-m5-fast-path.md) · public status: [development-status § North star](https://purhur.github.io/php-compiler/development-status.html#north-star-self-host). Parent tracking: [#78](https://github.com/PurHur/php-compiler/issues/78) (roadmap), [#212](https://github.com/PurHur/php-compiler/issues/212) (closed umbrella). +**Project north star:** The **compiler fully compiles itself** — native AOT from `lib/` (no `vendor/` at cold boot), then compiles PHP and rebuilds the next compiler revision without Zend. **M2 spine:** **5831** / **5831** Phase A inventory (`php script/bootstrap-spine-count.php`; `check-selfhost-spine-coverage-sync.php`). **M5 daily gate:** `make north-star5-verify-fast` (~1–2 min) ✅; **`--strict`** (~1h) pre-merge only. Committed `prelinked/bootstrap-gen0/` sidecars + vendor **3/3** cold boot. **Hot loop:** VM driver execute probe ~**20ms**; full spine relink only with `BOOTSTRAP_VM_DRIVER_EXECUTE_PROBE_FULL_LINK=1` ([#2201](https://github.com/PurHur/php-compiler/issues/2201)). **Living tracker:** [#1492](https://github.com/PurHur/php-compiler/issues/1492) (was [#1056](https://github.com/PurHur/php-compiler/issues/1056)) · **re-root doc:** [self-host-target.md](self-host-target.md) · **generation ladder:** [bootstrap-generations.md](bootstrap-generations.md) · **M5 fast path:** [bootstrap-m5-fast-path.md](bootstrap-m5-fast-path.md) · public status: [development-status § North star](https://purhur.github.io/php-compiler/development-status.html#north-star-self-host). Parent tracking: [#78](https://github.com/PurHur/php-compiler/issues/78) (roadmap), [#212](https://github.com/PurHur/php-compiler/issues/212) (closed umbrella). ## Current gates @@ -10,9 +10,9 @@ |------|---------|--------| | Phase A inventory | `make bootstrap-inventory-check` | ✅ vm.php-path inventory; **0** source blockers; M2 ratio SSOT: `Phase A inventory files` row in `docs/bootstrap-inventory.md` (no ratio-deferred paths — [#2543](https://github.com/PurHur/php-compiler/issues/2543)); `lib/JIT/Builtin/StringPregMatch.php` and `lib/AOT/Linker.php` **included** in spine | | Spine PHPCfg parse | `php script/bootstrap-spine-php-cfg-parse-check.php` (`--minimal` for M0 bundle) | ✅ no unsupported php-cfg expr/stmt on spine ([#2575](https://github.com/PurHur/php-compiler/issues/2575)); `BOOTSTRAP_SPINE_PHPCFG_PARSE_GATE=1` in `ci-fast.sh` | -| Phase B lib AOT lint | `php bin/compile.php -l lib/*.php` (with `script/php-env.sh`) | ✅ **5809/5809** top-level `lib/*.php` units ([#534](https://github.com/PurHur/php-compiler/pull/534)) | +| Phase B lib AOT lint | `php bin/compile.php -l lib/*.php` (with `script/php-env.sh`) | ✅ **5831/5831** top-level `lib/*.php` units ([#534](https://github.com/PurHur/php-compiler/pull/534)) | | Phase B fixture lint | `php script/bootstrap-aot-lint.php` | ✅ **13** procedural targets under `test/bootstrap-aot/` + `examples/000-HelloWorld` | -| Phase C native run | `make bootstrap-aot-link` or `./script/bootstrap-aot-link.sh` | ✅ **5809/5809** link targets OK | +| Phase C native run | `make bootstrap-aot-link` or `./script/bootstrap-aot-link.sh` | ✅ **5831/5831** link targets OK | | Phase D `lib/` link | `make bootstrap-aot-link-lib` or `./script/bootstrap-aot-link-lib.sh` | ✅ `test/bootstrap-aot/lib_opcode/main.php` bundles `lib/OpCode.php` ([#540](https://github.com/PurHur/php-compiler/issues/540)) | | Bundled `lib/Compiler.php` lint | `./script/bootstrap-selfhost-lint.sh` | ✅ `test/selfhost/compiler_minimal/main.php` + literal `require_once` units toward `bin/vm.php` (no `vendor/`) ([#559](https://github.com/PurHur/php-compiler/issues/559)) | | Compiler compile smoke lint | `php bin/compile.php -l test/selfhost/compiler_compile_smoke/main.php` | ✅ `compiler_minimal` bundle + literal `require_once` of `test/bootstrap-aot/compiler_smoke.php` (named function CFG) | diff --git a/docs/pages/development-status.md b/docs/pages/development-status.md index 8eaa206c4fe..a438e423d72 100644 --- a/docs/pages/development-status.md +++ b/docs/pages/development-status.md @@ -14,8 +14,8 @@ permalink: /development-status.html | **What it is** | PHP → CFG → VM / LLVM JIT → AOT native binaries | | **North star** | Compiler compiles itself without Zend ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) | | **v1.1.0 theme** | M5 fast-path stability; enum/property hooks; `preg_match` JIT; `spl_autoload*`; php-in-PHP JIT helpers ([#78](https://github.com/PurHur/php-compiler/issues/78)) | -| **Wave 3** | Language **5809/5809** · Stdlib **5809/5809** on master ([#1380](https://github.com/PurHur/php-compiler/issues/1380)) | -| **Spine SSOT** | `php script/bootstrap-spine-count.php` → **5809** / **5809** | +| **Wave 3** | Language **5831/5831** · Stdlib **5831/5831** on master ([#1380](https://github.com/PurHur/php-compiler/issues/1380)) | +| **Spine SSOT** | `php script/bootstrap-spine-count.php` → **5831** / **5831** | | **Builtin matrix** | **852** functions ([`docs/capabilities.md`](https://github.com/PurHur/php-compiler/blob/master/docs/capabilities.md)) | | **Try it** | [`docs/GETTING-STARTED.md`](https://github.com/PurHur/php-compiler/blob/master/docs/GETTING-STARTED.md) | @@ -33,7 +33,7 @@ permalink: /development-status.html | M5 spine runtime + bootstrap | `fix/spine-aot-jit-blockers` | Native bundle-OK probe; inventory argv spine-lint fallback; gen-0 sidecars refreshed ([#8559](https://github.com/PurHur/php-compiler/issues/8559)) | | VM driver execute probe | [9493e806d](https://github.com/PurHur/php-compiler/commit/9493e806d) | **~20ms** feedback loop — no full relink on stale SHA; `BOOTSTRAP_VM_DRIVER_EXECUTE_PROBE_FULL_LINK=1` for rebuild ([#2201](https://github.com/PurHur/php-compiler/issues/2201)) | | M5 presenter | `make north-star5-verify-fast` | Daily PR gate (~1–2 min); `--strict` (~1h) pre-merge only ([#1492](https://github.com/PurHur/php-compiler/issues/1492)) | -| Gen-0 refresh | [a8cffaa0e](https://github.com/PurHur/php-compiler/commit/a8cffaa0e) | Spine runtime probe + gen-0 sidecars (**5809/5809**); inventory argv spine-lint fallback ([#8559](https://github.com/PurHur/php-compiler/issues/8559)) | +| Gen-0 refresh | [a8cffaa0e](https://github.com/PurHur/php-compiler/commit/a8cffaa0e) | Spine runtime probe + gen-0 sidecars (**5831/5831**); inventory argv spine-lint fallback ([#8559](https://github.com/PurHur/php-compiler/issues/8559)) | | Parallel compile jobs | [#10347](https://github.com/PurHur/php-compiler/pull/10347) | `PHP_COMPILER_COMPILE_JOBS` for vendor prelink + M3 sidecar warmup | | Spine coverage | [#10356](https://github.com/PurHur/php-compiler/pull/10356) | `GeneratorYieldSourceMarker.php` in spine; inventory **3276** Phase A files | | v1.1.0 docs sync | [#10369](https://github.com/PurHur/php-compiler/issues/10369) | README, development-status, examples README, capability matrix (**852** builtins) | @@ -50,7 +50,7 @@ permalink: /development-status.html ### Still open (high signal) - **MCJIT execute** — `bin/jit.php -r` SIGSEGV ([#98](https://github.com/PurHur/php-compiler/issues/98)) -- **Literal spine ratio** — **5809/5809** ✅ (Jul 2026) +- **Literal spine ratio** — **5831/5831** ✅ (Jul 2026) - **Compile-spine stub retirement** — shrink `PHP_COMPILER_SELFHOST_AOT` on M3 allowlist ([#1402](https://github.com/PurHur/php-compiler/issues/1402)) - **007-ThrowsWeb AOT execute** — invalid POST segfault at runtime (link OK; slice `EXAMPLES_AOT_SMOKE_ONLY=007`) - **LLVM 14+ upgrade** — experimental `script/install-llvm14.sh` ([#174](https://github.com/PurHur/php-compiler/issues/174)) @@ -62,7 +62,7 @@ permalink: /development-status.html - **`phpc` CLI** — `run`, `serve`, `build`, `deploy`, `lint`, `test`, `init`, `doctor` - **Examples 000–009** — VM and AOT link/execute for the curated web subset - **Self-host M0** — `compiler_minimal bundle OK` ✅ -- **Self-host M2** — spine **5809/5809** ✅; native link + lint ✅ +- **Self-host M2** — spine **5831/5831** ✅; native link + lint ✅ - **Self-host M3** — HelloWorld strict `emit_path=native` ✅ ([#1493](https://github.com/PurHur/php-compiler/issues/1493)); inventory argv `bin/compile.php` ✅ ([#3024](https://github.com/PurHur/php-compiler/issues/3024) closed); compile-smoke strict native ✅ ([#1937](https://github.com/PurHur/php-compiler/issues/1937)) - **Self-host M4** — `make bootstrap-loop-probe` full ladder ✅; gen-2→gen-3 full-spine recompile ✅ - **Self-host M5** — vendor prelink **3/3** ✅; **`make north-star5-verify-fast`** daily ✅; `--strict` pre-merge; gen-0 refreshed; VM probe ~**20ms** @@ -92,7 +92,7 @@ See [`docs/bootstrap-selfhost.md`](https://github.com/PurHur/php-compiler/blob/m |-----------|--------| | **M0** — Small `lib/` bundle runs | ✅ | | **M1** — Compiler-shaped bundle + compile-smoke | ✅ | -| **M2** — Spine toward full inventory | ✅ **5809** / **5809** | +| **M2** — Spine toward full inventory | ✅ **5831** / **5831** | | **M3** — Native compiles PHP (no Zend emit) | ✅ Smoke + inventory argv driver strict native | | **M4** — Bootstrap loop (next revision) | ✅ `bootstrap-loop-probe` full ladder | | **M5** — Full self-host, no `vendor/` cold boot | ✅ Presenter strict + compiled-only empty `build/` cold boot ([#3053](https://github.com/PurHur/php-compiler/issues/3053)) | diff --git a/docs/pages/index.html b/docs/pages/index.html index 7861e7f9d27..1932faa990b 100644 --- a/docs/pages/index.html +++ b/docs/pages/index.html @@ -70,7 +70,7 @@

A compiler for PHP in PHP that compiles itself

VM + JIT + AOT Closures · try/catch 321 builtins - Spine **5809** / **5809** + Spine **5831** / **5831** M5 strict ✅ M3 strict emit MCJIT execute @@ -391,7 +391,7 @@

Self-host progress

fix/spine-aot-jit-blockers @ a8cffaa0e (15 Jun 2026, LLVM 9). - M2 spine SSOT: php script/bootstrap-spine-count.php → **5809** / **5809** Phase A inventory (literal coverage ✅). + M2 spine SSOT: php script/bootstrap-spine-count.php → **5831** / **5831** Phase A inventory (literal coverage ✅). M4: make bootstrap-loop-probe full ladder ✅. M5: make north-star5-verify-fast ✅ daily; --strict pre-merge; VM driver probe ~20ms in CI loops. Remaining: MCJIT execute ([#98](https://github.com/PurHur/php-compiler/issues/98)); honest PHP main() in full spine AOT (native bundle-OK probe is bootstrap smoke). @@ -416,7 +416,7 @@

M0–M1

  • M2

    -

    Spine **5809** / **5809** Phase A inventory — literal coverage ✅; native link + lint ✅ +

    Spine **5831** / **5831** Phase A inventory — literal coverage ✅; native link + lint ✅ (#8559).

  • @@ -437,7 +437,7 @@

    M4

    M5

    Vendor prelink 3/3 ✅; committed .o cold boot ✅; - north-star5-verify-fast ✅ daily; --strict pre-merge; spine **5809** / **5809**; prelinked gen-0 refreshed; + north-star5-verify-fast ✅ daily; --strict pre-merge; spine **5831** / **5831**; prelinked gen-0 refreshed; fast VM execute probe (~20ms); compiled-only cold boot via BOOTSTRAP_M5_NO_ZEND=1 ✅ (#3053, #8559, @@ -494,7 +494,7 @@

    Get involved

    PHP compare · Getting started

    - + diff --git a/docs/roadmap-wave3.md b/docs/roadmap-wave3.md index e85d2115f60..b754f95b413 100644 --- a/docs/roadmap-wave3.md +++ b/docs/roadmap-wave3.md @@ -1,6 +1,6 @@ # Roadmap wave 3 tracker (#1354–#1379) -> **Wave 3 complete on master (May 2026):** language **5809/5809** + stdlib **5809/5809** ([#1380](https://github.com/PurHur/php-compiler/issues/1380)). Phase-2 / JIT-only deferrals: [#1936](https://github.com/PurHur/php-compiler/issues/1936) (attributes reflection), [#1776](https://github.com/PurHur/php-compiler/issues/1776) (stdlib JIT audit), [#1238](https://github.com/PurHur/php-compiler/issues/1238). +> **Wave 3 complete on master (May 2026):** language **5831/5831** + stdlib **5831/5831** ([#1380](https://github.com/PurHur/php-compiler/issues/1380)). Phase-2 / JIT-only deferrals: [#1936](https://github.com/PurHur/php-compiler/issues/1936) (attributes reflection), [#1776](https://github.com/PurHur/php-compiler/issues/1776) (stdlib JIT audit), [#1238](https://github.com/PurHur/php-compiler/issues/1238). Living status for the **25 issues** filed May 2026 toward full PHP language + stdlib coverage. Umbrella: [#1380](https://github.com/PurHur/php-compiler/issues/1380). North stars: [#1044](https://github.com/PurHur/php-compiler/issues/1044), [#1492](https://github.com/PurHur/php-compiler/issues/1492) (self-host; was [#1056](https://github.com/PurHur/php-compiler/issues/1056)). @@ -19,7 +19,7 @@ Regenerate capability truth: `php script/capability-matrix.php`, `php script/cap Related merges outside this wave: `goto` ([#1228](https://github.com/PurHur/php-compiler/issues/1228) / [#1333](https://github.com/PurHur/php-compiler/pull/1333)), anonymous classes ([#1233](https://github.com/PurHur/php-compiler/issues/1233) / [#1386](https://github.com/PurHur/php-compiler/pull/1386)). -**M2 spine:** **5809** / **5809** (`php script/bootstrap-spine-count.php`) — full Phase A inventory in `compiler_lib_spine_smoke`; coverage sync ✅ (`check-selfhost-spine-coverage-sync.php`). Native spine **link** + **lint** ✅ ([#2134](https://github.com/PurHur/php-compiler/issues/2134), [#8559](https://github.com/PurHur/php-compiler/issues/8559)). **M5 daily gate:** `make north-star5-verify-fast` + VM probe ~20ms ([#2201](https://github.com/PurHur/php-compiler/issues/2201)); `--strict` pre-merge only. M4 gen-2→gen-3 recompile ✅. Target doc: [self-host-target.md](self-host-target.md) +**M2 spine:** **5831** / **5831** (`php script/bootstrap-spine-count.php`) — full Phase A inventory in `compiler_lib_spine_smoke`; coverage sync ✅ (`check-selfhost-spine-coverage-sync.php`). Native spine **link** + **lint** ✅ ([#2134](https://github.com/PurHur/php-compiler/issues/2134), [#8559](https://github.com/PurHur/php-compiler/issues/8559)). **M5 daily gate:** `make north-star5-verify-fast` + VM probe ~20ms ([#2201](https://github.com/PurHur/php-compiler/issues/2201)); `--strict` pre-merge only. M4 gen-2→gen-3 recompile ✅. Target doc: [self-host-target.md](self-host-target.md) ## Language (#1354–#1366) @@ -69,4 +69,4 @@ Related merges outside this wave: `goto` ([#1228](https://github.com/PurHur/php- --- -**Wave 3 close-out (May 2026):** language **5809/5809**, stdlib **5809/5809** on master. Do not reopen [#1354](https://github.com/PurHur/php-compiler/issues/1354)–[#1379](https://github.com/PurHur/php-compiler/issues/1379) for phase-1 gaps — use phase-2 trackers [#1936](https://github.com/PurHur/php-compiler/issues/1936) (attributes reflection), [#1776](https://github.com/PurHur/php-compiler/issues/1776) (stdlib JIT audit), [#1238](https://github.com/PurHur/php-compiler/issues/1238). +**Wave 3 close-out (May 2026):** language **5831/5831**, stdlib **5831/5831** on master. Do not reopen [#1354](https://github.com/PurHur/php-compiler/issues/1354)–[#1379](https://github.com/PurHur/php-compiler/issues/1379) for phase-1 gaps — use phase-2 trackers [#1936](https://github.com/PurHur/php-compiler/issues/1936) (attributes reflection), [#1776](https://github.com/PurHur/php-compiler/issues/1776) (stdlib JIT audit), [#1238](https://github.com/PurHur/php-compiler/issues/1238). diff --git a/docs/self-host-target.md b/docs/self-host-target.md index 5ad18dc2815..44d3804ce74 100644 --- a/docs/self-host-target.md +++ b/docs/self-host-target.md @@ -35,7 +35,7 @@ That is **M5**. Everything below is the honest path from today’s bootstrap to |-------|-------|--------| | **Bootstrap driver** | Prelinked gen-0 refreshed via honest inventory argv emit; native `build/bin-compile-aot-inventory` for M4/M5 | Compiled `bin/compile.php` only | | **Bundle size** | **2643** literal Phase A inventory in spine smoke | Full vm.php closure | -| **Inventory coverage** | **5809** / **5809** ✅ | Full closure | +| **Inventory coverage** | **5831** / **5831** ✅ | Full closure | | **HelloWorld** | Strict probe **emit_path=native** ✅ | Native compile for arbitrary PHP | | **Bootstrap loop (M4)** | `make bootstrap-loop-probe` full ladder ✅ — gen-1→gen-2, gen-2→gen-3 full spine, full-revision argv | Native full revision rebuild | | **Vendor** | **3/3** vendor `object_ok`; committed `.o` cold boot without `vendor/` ✅; `make north-star5-verify-fast` daily; `--strict` pre-merge ✅ | No Zend `vendor/autoload.php` at bootstrap | @@ -56,7 +56,7 @@ That is **M5**. Everything below is the honest path from today’s bootstrap to | M4 `make bootstrap-selfhost-full-revision-probe` | ✅ gen-2 inventory argv → gen-3 + fixture smoke ([#2880](https://github.com/PurHur/php-compiler/issues/2880)) | | M4 `make bootstrap-loop-gen2-recompile-spine` | ✅ gen-2→gen-3 full spine native argv | | M4 `make bootstrap-loop-probe` | ✅ full ladder ([#1498](https://github.com/PurHur/php-compiler/issues/1498)) | -| `make bootstrap-aot-link` | ✅ **5809/5809** | +| `make bootstrap-aot-link` | ✅ **5831/5831** | | `make bootstrap-inventory-check` | ✅ **2643** Phase A files, **0** source blockers | | `make north-star5-verify-fast` | ✅ daily M5 PR gate (~1–2 min); `ARGS=--strict` pre-merge (~1h) | @@ -68,7 +68,7 @@ That is **M5**. Everything below is the honest path from today’s bootstrap to |-----------|----------------|--------|-----| | **M0** | AOT can link a **small** honest `lib/` subset | ✅ | 100% | | **M1** | Bundle is **compiler-shaped** (lint + compile-smoke) | ✅ | 100% | -| **M2** | Spine grows toward full `bin/vm.php` inventory | ✅ **5809** / **5809** | **100%** | +| **M2** | Spine grows toward full `bin/vm.php` inventory | ✅ **5831** / **5831** | **100%** | | **M3** | Self-host binary **compiles external PHP** (HelloWorld) without Zend emit | ✅ strict **native** + inventory argv | **~85%** | | **M4** | Self-host binary **rebuilds** the next compiler tree | ✅ full `bootstrap-loop-probe` ladder | **~90%** | | **M5** | Full self-host; Zend retired from loop | ✅ `north-star5-verify-fast` daily + `--strict` pre-merge; `BOOTSTRAP_M5_NO_ZEND=1` empty `build/` ([#3053](https://github.com/PurHur/php-compiler/issues/3053)) | **~90%** | @@ -79,7 +79,7 @@ That is **M5**. Everything below is the honest path from today’s bootstrap to | Indicator | Formula | Jun 2026 | |-----------|---------|----------| -| **M2 spine progress** | `require_once` units in `compiler_lib_spine_smoke` ÷ Phase A inventory file count | **5809** / **5809** (`php script/bootstrap-spine-count.php`) | +| **M2 spine progress** | `require_once` units in `compiler_lib_spine_smoke` ÷ Phase A inventory file count | **5831** / **5831** (`php script/bootstrap-spine-count.php`) | | **Public “Self-host” row** | Same M2 ratio until M3–M5 gates add weight ([`development-status.md`](pages/development-status.md)) | **~97%** | | **M5 vendor prelink** | `object_ok` packages ÷ 3 | **3 / 3** (cfg, types, llvm) | | **Composite (internal)** | Milestone weights in table above (M0–M1 = 100%, M2 = spine %, M3–M5 = gate %) | **~90%** | diff --git a/test/unit/BootstrapSelfhostBundleTest.php b/test/unit/BootstrapSelfhostBundleTest.php index 677b65ee649..44b8d1f85b6 100644 --- a/test/unit/BootstrapSelfhostBundleTest.php +++ b/test/unit/BootstrapSelfhostBundleTest.php @@ -526,7 +526,7 @@ public function testCompilerLibSpineSmokeBundleUnitCountAndKeyUnits(): void $this->assertFileExists($entry); $contents = (string) file_get_contents($entry); $count = bootstrap_spine_counts(self::$root)['spine']; - $this->assertSame(5809, $count, 'M2 spine require_once units track Phase A inventory (#8559, #9234, #11629, #18550)'); + $this->assertSame(5831, $count, 'M2 spine require_once units track Phase A inventory (#8559, #9234, #11629, #18550)'); foreach (self::LIB_SPINE_SMOKE_NEW_UNITS as $unit) { $this->assertStringContainsString( "require_once __DIR__.'/../../../{$unit}';", From 33cdd0e75eba6ac245a04c3d2b402c114221b6b4 Mon Sep 17 00:00:00 2001 From: PurHur Date: Sun, 19 Jul 2026 01:53:29 +0000 Subject: [PATCH 3/3] Docs: refresh bootstrap-inventory after rebase Regenerate construct flags so VmBreakIterator preceding APIs are listed. Co-authored-by: Cursor --- docs/bootstrap-inventory.md | 244 ++++++++++++++++++------------------ 1 file changed, 122 insertions(+), 122 deletions(-) diff --git a/docs/bootstrap-inventory.md b/docs/bootstrap-inventory.md index 0e148b03a3d..0427245e682 100644 --- a/docs/bootstrap-inventory.md +++ b/docs/bootstrap-inventory.md @@ -8,8 +8,8 @@ Regenerate: `php script/bootstrap-inventory.php` | Metric | Count | |--------|------:| -| PHP files on vm.php path | 5831 | -| Phase A inventory files (M2 ratio SSOT) | 5831 | +| PHP files on vm.php path | 5830 | +| Phase A inventory files (M2 ratio SSOT) | 5830 | | Phase A ratio-deferred paths | 0 | | Source constructs flagged (blockers) | 0 | | Source constructs flagged (warnings) | 17374 | @@ -41632,111 +41632,111 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag - new Variable (line 9115) - new Variable (line 9122) - new Variable (line 9139) -- new VM\NativeFiberStackOverflow (line 9972) -- new VM\BuiltinCallbackCatchRedirect (line 10023) -- new VM\BuiltinCallbackCatchRedirect (line 10041) -- new Variable (line 10144) -- new Variable (line 10252) -- new Variable (line 10385) -- new ScriptExit (line 10541) -- new Exception (line 10558) -- new ScriptExit (line 10566) -- new Error (line 10829) -- new VM\PropertyHookRefWriteSignal (line 10877) -- new Variable (line 10901) -- new VM\PropertyHookRefWriteSignal (line 10906) -- new VM\PropertyHookFiberSuspendSignal (line 10909) -- new VM\PropertyHookRefWriteSignal (line 11031) -- new Variable (line 11048) -- new VM\PropertyHookRefWriteSignal (line 11062) -- new VM\PropertyHookRefWriteSignal (line 11074) -- new Variable (line 11305) -- new Variable (line 11328) -- new Variable (line 11338) -- new Variable (line 11348) -- new VM\PropertyHookRefWriteSignal (line 11354) -- new VM\PropertyHookRefWriteSignal (line 11362) -- new VM\PropertyHookRefWriteSignal (line 11365) -- new Variable (line 11377) -- new Variable (line 11391) -- new VM\PropertyHookRefWriteSignal (line 11397) -- new Variable (line 11428) -- new VM\PropertyHookRefWriteSignal (line 11433) -- new VM\PropertyHookFiberSuspendSignal (line 11436) -- new Error (line 11935) -- new Error (line 11945) -- new Error (line 11955) -- new Error (line 11965) -- new ClassEntry (line 12735) -- new Variable (line 12736) -- new VM\ClassProperty (line 12737) -- new ObjectEntry (line 12740) -- new Variable (line 12743) -- new Variable (line 12824) -- new Error (line 12910) -- new Variable (line 13002) -- new VM\GeneratorUncaughtThrow (line 13004) -- new Error (line 13073) -- new Variable (line 13118) -- new VM\GeneratorUncaughtThrow (line 13132) -- new Variable (line 13221) -- new VM\GeneratorUncaughtThrow (line 13241) -- new Variable (line 13309) -- new Variable (line 13311) -- new Variable (line 13315) -- new Variable (line 13445) -- new Variable (line 13487) -- new Variable (line 13658) -- new Variable (line 13674) -- new Variable (line 13719) -- new Variable (line 13860) -- new Variable (line 13934) -- new Variable (line 14098) -- new VM\PropertyIsInitializedHandler (line 14107) -- new Error (line 14222) -- new VM\EnumFromHandler (line 14247) -- new CompileError (line 14973) -- new VM\ClassProperty (line 15138) -- new Variable (line 15446) -- new Variable (line 15641) -- new Variable (line 15643) -- new ClassEntry (line 15686) -- new Func\PHP (line 15693) -- new VM\ClassProperty (line 15821) -- new Func\PHP (line 15968) -- new Variable (line 16044) -- new Variable (line 16051) -- new Variable (line 16057) -- new Variable (line 16094) -- new Variable (line 16123) -- new Variable (line 16308) -- new Variable (line 16354) -- new VM\ClassProperty (line 16419) -- new Error (line 16465) -- new Error (line 16500) -- new Error (line 16503) -- new Error (line 16506) -- new Error (line 16509) -- new ObjectEntry (line 16511) -- new Error (line 16524) -- new Error (line 16527) +- new VM\NativeFiberStackOverflow (line 9953) +- new VM\BuiltinCallbackCatchRedirect (line 10004) +- new VM\BuiltinCallbackCatchRedirect (line 10022) +- new Variable (line 10125) +- new Variable (line 10233) +- new Variable (line 10366) +- new ScriptExit (line 10522) +- new Exception (line 10539) +- new ScriptExit (line 10547) +- new Error (line 10810) +- new VM\PropertyHookRefWriteSignal (line 10858) +- new Variable (line 10882) +- new VM\PropertyHookRefWriteSignal (line 10887) +- new VM\PropertyHookFiberSuspendSignal (line 10890) +- new VM\PropertyHookRefWriteSignal (line 11012) +- new Variable (line 11029) +- new VM\PropertyHookRefWriteSignal (line 11043) +- new VM\PropertyHookRefWriteSignal (line 11055) +- new Variable (line 11286) +- new Variable (line 11309) +- new Variable (line 11319) +- new Variable (line 11329) +- new VM\PropertyHookRefWriteSignal (line 11335) +- new VM\PropertyHookRefWriteSignal (line 11343) +- new VM\PropertyHookRefWriteSignal (line 11346) +- new Variable (line 11358) +- new Variable (line 11372) +- new VM\PropertyHookRefWriteSignal (line 11378) +- new Variable (line 11409) +- new VM\PropertyHookRefWriteSignal (line 11414) +- new VM\PropertyHookFiberSuspendSignal (line 11417) +- new Error (line 11916) +- new Error (line 11926) +- new Error (line 11936) +- new Error (line 11946) +- new ClassEntry (line 12716) +- new Variable (line 12717) +- new VM\ClassProperty (line 12718) +- new ObjectEntry (line 12721) +- new Variable (line 12724) +- new Variable (line 12805) +- new Error (line 12891) +- new Variable (line 12983) +- new VM\GeneratorUncaughtThrow (line 12985) +- new Error (line 13054) +- new Variable (line 13099) +- new VM\GeneratorUncaughtThrow (line 13113) +- new Variable (line 13202) +- new VM\GeneratorUncaughtThrow (line 13222) +- new Variable (line 13290) +- new Variable (line 13292) +- new Variable (line 13296) +- new Variable (line 13426) +- new Variable (line 13468) +- new Variable (line 13639) +- new Variable (line 13655) +- new Variable (line 13700) +- new Variable (line 13841) +- new Variable (line 13915) +- new Variable (line 14079) +- new VM\PropertyIsInitializedHandler (line 14088) +- new Error (line 14203) +- new VM\EnumFromHandler (line 14228) +- new CompileError (line 14954) +- new VM\ClassProperty (line 15119) +- new Variable (line 15427) +- new Variable (line 15622) +- new Variable (line 15624) +- new ClassEntry (line 15667) +- new Func\PHP (line 15674) +- new VM\ClassProperty (line 15802) +- new Func\PHP (line 15949) +- new Variable (line 16025) +- new Variable (line 16032) +- new Variable (line 16038) +- new Variable (line 16075) +- new Variable (line 16104) +- new Variable (line 16289) +- new Variable (line 16335) +- new VM\ClassProperty (line 16400) +- new Error (line 16446) +- new Error (line 16481) +- new Error (line 16484) +- new Error (line 16487) +- new Error (line 16490) +- new ObjectEntry (line 16492) +- new Error (line 16505) +- new Error (line 16508) +- new Error (line 16511) - new Error (line 16530) -- new Error (line 16549) -- new ObjectEntry (line 16553) -- new Variable (line 16555) -- new Variable (line 16569) -- new Variable (line 16596) -- new Variable (line 16609) -- new Error (line 16739) -- new Error (line 16744) -- new VM\ObjectEntry (line 16748) -- new Variable (line 16892) -- new Variable (line 16910) -- new NoDiscardMetadata (line 17079) -- new Variable (line 17248) -- new Variable (line 17250) -- new Variable (line 17350) -- 489 class method(s) +- new ObjectEntry (line 16534) +- new Variable (line 16536) +- new Variable (line 16550) +- new Variable (line 16577) +- new Variable (line 16590) +- new Error (line 16720) +- new Error (line 16725) +- new VM\ObjectEntry (line 16729) +- new Variable (line 16873) +- new Variable (line 16891) +- new NoDiscardMetadata (line 17060) +- new Variable (line 17229) +- new Variable (line 17231) +- new Variable (line 17331) +- 488 class method(s) - 25 closure(s) ### `lib/VM/AbstractPropertyHookCheck.php` @@ -44328,10 +44328,10 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag ### `lib/VM/BuiltinExceptionSupport.php` **Warnings** (review for bootstrap subset): -- new ObjectEntry (line 554) -- new Variable (line 558) -- new ObjectEntry (line 574) -- new Variable (line 578) +- new ObjectEntry (line 544) +- new Variable (line 548) +- new ObjectEntry (line 564) +- new Variable (line 568) - 37 class method(s) ### `lib/VM/BuiltinExecute.php` @@ -44766,18 +44766,18 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag ### `lib/VM/ExceptionSupport.php` **Warnings** (review for bootstrap subset): -- new ReflectionObject (line 365) -- new ScriptExit (line 387) -- new ScriptExit (line 417) -- new ErrorException (line 573) -- new SoapFault (line 603) -- new Error (line 616) -- new FiberStackOverflow (line 619) -- new Error (line 621) -- new Error (line 624) -- new Exception (line 626) -- new Exception (line 648) -- new Error (line 656) +- new ReflectionObject (line 364) +- new ScriptExit (line 386) +- new ScriptExit (line 416) +- new ErrorException (line 572) +- new SoapFault (line 602) +- new Error (line 615) +- new FiberStackOverflow (line 618) +- new Error (line 620) +- new Error (line 623) +- new Exception (line 625) +- new Exception (line 647) +- new Error (line 655) - 26 class method(s) ### `lib/VM/ExceptionTrace.php`