@@ -124,8 +124,8 @@ private function accept(Node $node): string
124124 $ node instanceof PartialBlockStatement => $ this ->PartialBlockStatement ($ node ),
125125 $ node instanceof Decorator => $ this ->Decorator ($ node ),
126126 $ node instanceof MustacheStatement => $ this ->MustacheStatement ($ node ),
127- $ node instanceof ContentStatement => $ this -> ContentStatement ($ node ),
128- $ node instanceof CommentStatement => $ this -> CommentStatement ( $ node ) ,
127+ $ node instanceof ContentStatement => self :: quote ($ node-> value ),
128+ $ node instanceof CommentStatement => '' ,
129129 $ node instanceof SubExpression => $ this ->SubExpression ($ node ),
130130 default => throw new \Exception ('Unknown type: ' . (new \ReflectionClass ($ node ))->getShortName ()),
131131 };
@@ -136,11 +136,10 @@ private function compileExpression(Expression $expr): string
136136 return match (true ) {
137137 $ expr instanceof SubExpression => $ this ->SubExpression ($ expr ),
138138 $ expr instanceof PathExpression => $ this ->PathExpression ($ expr ),
139- $ expr instanceof StringLiteral => $ this ->StringLiteral ($ expr ),
140- $ expr instanceof NumberLiteral => $ this ->NumberLiteral ($ expr ),
141- $ expr instanceof BooleanLiteral => $ this ->BooleanLiteral ($ expr ),
142- $ expr instanceof NullLiteral => $ this ->NullLiteral ($ expr ),
143- $ expr instanceof UndefinedLiteral => $ this ->UndefinedLiteral ($ expr ),
139+ $ expr instanceof StringLiteral => self ::quote ($ expr ->value ),
140+ $ expr instanceof NumberLiteral => (string ) $ expr ->value ,
141+ $ expr instanceof BooleanLiteral => $ expr ->value ? 'true ' : 'false ' ,
142+ $ expr instanceof NullLiteral, $ expr instanceof UndefinedLiteral => 'null ' ,
144143 default => throw new \Exception ('Unknown expression type: ' . (new \ReflectionClass ($ expr ))->getShortName ()),
145144 };
146145 }
@@ -209,7 +208,7 @@ private function compileSection(BlockStatement $block, string $var, string $esca
209208 assert ($ block ->program !== null );
210209
211210 $ blockFn = $ this ->compileProgramWithBlockParams ($ block ->program );
212- $ else = $ this ->compileElseClause ($ block );
211+ $ else = $ this ->compileProgramOrNull ($ block-> inverse );
213212
214213 if ($ this ->context ->options ->knownHelpersOnly ) {
215214 return self ::getRuntimeFunc ('sec ' , "\$cx, $ var, \$in, $ blockFn, $ else " );
@@ -291,26 +290,29 @@ private function compileProgramWithBlockParams(Program $program): string
291290 private function compileBlockHelper (BlockStatement $ block , string $ name ): string
292291 {
293292 $ inverted = $ block ->program === null ;
294- if ($ inverted ) {
295- assert ($ block ->inverse !== null );
296- }
297293 // For inverted blocks the fn body comes from the inverse program; for normal blocks, the program.
298- $ fnProgram = $ inverted ? $ block ->inverse : $ block ->program ;
294+ $ fnProgram = $ block ->program ?? $ block ->inverse ;
295+ assert ($ fnProgram !== null );
299296
300297 // Inline if/unless as ternary — eliminates hbbch dispatch and HelperOptions allocation.
301298 // Safe because if/unless don't change scope, so $cx and $in are already correct.
302299 // Negate for 'unless' in a normal block, or 'if' in an inverted block (swapped semantics).
303300 if ($ this ->canInlineConditional ($ block , $ name , $ fnProgram ->blockParams )) {
304301 $ cond = $ this ->compileConditionalExpr ($ block ->params [0 ], $ name === ($ inverted ? 'if ' : 'unless ' ));
305302 $ body = $ this ->compileProgram ($ fnProgram );
306- $ elseBody = $ inverted ? " '' " : $ this -> compileProgramOrEmpty ( $ block ->inverse );
303+ $ elseBody = $ this -> compileProgramOrEmpty ( $ inverted ? null : $ block ->inverse );
307304 return "( $ cond ? $ body : $ elseBody) " ;
308305 }
309306
310307 $ blockFn = $ this ->compileProgramWithBlockParams ($ fnProgram );
311- [$ fn , $ else ] = $ inverted
312- ? ['null ' , $ blockFn ]
313- : [$ blockFn , $ this ->compileElseClause ($ block )];
308+ if ($ inverted ) {
309+ // no {{else}} clause, so there is nothing to compile for fn
310+ $ fn = 'null ' ;
311+ $ else = $ blockFn ;
312+ } else {
313+ $ fn = $ blockFn ;
314+ $ else = $ this ->compileProgramOrNull ($ block ->inverse );
315+ }
314316
315317 $ outerBp = $ this ->outerBlockParamsExpr ();
316318 $ params = $ this ->compileParams ($ block ->params , $ block ->hash );
@@ -372,7 +374,7 @@ private function compileDynamicBlockHelper(BlockStatement $block, string $name,
372374 $ blockFn = $ block ->program !== null
373375 ? $ this ->compileProgramWithBlockParams ($ block ->program )
374376 : 'null ' ;
375- $ else = $ this ->compileElseClause ($ block );
377+ $ else = $ this ->compileProgramOrNull ($ block-> inverse );
376378 $ outerBp = $ this ->outerBlockParamsExpr ();
377379 $ helperName = self ::quote ($ name );
378380 return self ::getRuntimeFunc ('dynhbbch ' , "\$cx, $ helperName, $ varPath, $ params, \$in, $ blockFn, $ else, " . count ($ bp ) . ", $ outerBp " );
@@ -385,7 +387,7 @@ private function DecoratorBlock(BlockStatement $block): string
385387 if ($ helperName !== 'inline ' ) {
386388 throw new \Exception ('Unknown decorator: " ' . $ helperName . '" ' );
387389 } elseif (!$ block ->params ) {
388- $ partialName = 'undefined ' ;
390+ $ partialName = 'undefined ' ; // match JS for {{#*inline}} without a name (params[0] on empty array is undefined)
389391 } else {
390392 $ firstArg = $ block ->params [0 ];
391393 if (!$ firstArg instanceof Literal) {
@@ -556,16 +558,6 @@ private function MustacheStatement(MustacheStatement $mustache): string
556558 return self ::getRuntimeFunc ($ fn , "\$in[ $ escapedKey] ?? $ miss " );
557559 }
558560
559- private function ContentStatement (ContentStatement $ statement ): string
560- {
561- return self ::quote ($ statement ->value );
562- }
563-
564- private function CommentStatement (CommentStatement $ statement ): string
565- {
566- return '' ;
567- }
568-
569561 // ── Expressions ─────────────────────────────────────────────────
570562
571563 private function SubExpression (SubExpression $ expression ): string
@@ -604,7 +596,8 @@ private function PathExpression(PathExpression $expression): string
604596 $ stringParts = $ expression ->tail ;
605597 } else {
606598 $ base = $ this ->buildBasePath ($ data , $ depth );
607- $ stringParts = self ::stringPartsOf ($ parts );
599+ /** @var string[] $parts */
600+ $ stringParts = $ parts ;
608601 }
609602
610603 // `this` with no parts or empty parts
@@ -652,31 +645,6 @@ private function PathExpression(PathExpression $expression): string
652645 return $ this ->compileModeAwareLookup ($ base , $ stringParts , $ expression ->original , $ miss );
653646 }
654647
655- private function StringLiteral (StringLiteral $ literal ): string
656- {
657- return self ::quote ($ literal ->value );
658- }
659-
660- private function NumberLiteral (NumberLiteral $ literal ): string
661- {
662- return (string ) $ literal ->value ;
663- }
664-
665- private function BooleanLiteral (BooleanLiteral $ literal ): string
666- {
667- return $ literal ->value ? 'true ' : 'false ' ;
668- }
669-
670- private function UndefinedLiteral (UndefinedLiteral $ literal ): string
671- {
672- return 'null ' ;
673- }
674-
675- private function NullLiteral (NullLiteral $ literal ): string
676- {
677- return 'null ' ;
678- }
679-
680648 /**
681649 * Get the string key name for a literal used in path (mustache/block) position.
682650 * e.g. {{12}} looks up $in['12'], {{"foo bar"}} looks up $in['foo bar'], {{true}} looks up $in['true'].
@@ -848,18 +816,6 @@ private function getSimpleHelperName(PathExpression|Literal $path): ?string
848816 return $ path ->parts [0 ];
849817 }
850818
851- /**
852- * Compile the else/inverse clause of a block as a trailing closure argument, or 'null' if absent.
853- */
854- private function compileElseClause (BlockStatement $ block ): string
855- {
856- if (!$ block ->inverse ) {
857- $ this ->lastCompileProgramHadDirectBpRef = false ;
858- return 'null ' ;
859- }
860- return $ this ->compileProgramWithBlockParams ($ block ->inverse );
861- }
862-
863819 /**
864820 * Build the base path expression for a given data flag and depth.
865821 */
@@ -929,6 +885,15 @@ private function missValue(string $key): string
929885 : 'null ' ;
930886 }
931887
888+ private function compileProgramOrNull (?Program $ program ): string
889+ {
890+ if (!$ program ) {
891+ $ this ->lastCompileProgramHadDirectBpRef = false ;
892+ return 'null ' ;
893+ }
894+ return $ this ->compileProgramWithBlockParams ($ program );
895+ }
896+
932897 private function compileProgramOrEmpty (?Program $ program ): string
933898 {
934899 if (!$ program ) {
@@ -986,14 +951,4 @@ private function buildInlineHelperCall(string $name, array $params, ?Hash $hash)
986951 }
987952 return self ::getRuntimeFunc ('dynhbch ' , "\$cx, $ helperName, $ compiledParams, \$in " );
988953 }
989-
990- /**
991- * Return only the string parts of a mixed parts array, re-indexed.
992- * @param array<string|SubExpression> $parts
993- * @return list<string>
994- */
995- private static function stringPartsOf (array $ parts ): array
996- {
997- return array_values (array_filter ($ parts , fn ($ p ) => is_string ($ p )));
998- }
999954}
0 commit comments