@@ -170,10 +170,8 @@ private function BlockStatement(BlockStatement $block): string
170170 return $ this ->compileBlockHelper ($ block , $ literalKey );
171171 }
172172
173- $ escapedKey = addcslashes ($ literalKey , "' \\" );
174- $ miss = $ this ->context ->options ->strict
175- ? "LR::miss(' " . addcslashes ($ literalKey , "' \\" ) . "') "
176- : 'null ' ;
173+ $ escapedKey = $ this ->escape ($ literalKey );
174+ $ miss = $ this ->missValue ($ literalKey );
177175 $ var = "\$in[' $ escapedKey'] ?? $ miss " ;
178176
179177 if ($ block ->program === null ) {
@@ -264,8 +262,7 @@ private function compileEach(BlockStatement $block): string
264262 }
265263
266264 $ var = $ this ->compileExpression ($ block ->params [0 ]);
267- $ bp = $ block ->program ? $ block ->program ->blockParams : [];
268- $ bs = $ bp ? Expression::listString ($ bp ) : 'null ' ;
265+ [$ bp , $ bs ] = $ this ->getProgramBlockParams ($ block ->program );
269266
270267 $ body = $ block ->program ? $ this ->compileProgramWithBlockParams ($ block ->program , $ bp , true ) : "'' " ;
271268 $ else = $ this ->compileElseClause ($ block );
@@ -280,8 +277,7 @@ private function compileWith(BlockStatement $block): string
280277 }
281278
282279 $ var = $ this ->compileExpression ($ block ->params [0 ]);
283- $ bp = $ block ->program ? $ block ->program ->blockParams : [];
284- $ bs = $ bp ? Expression::listString ($ bp ) : 'null ' ;
280+ [$ bp , $ bs ] = $ this ->getProgramBlockParams ($ block ->program );
285281
286282 $ body = $ block ->program ? $ this ->compileProgram ($ block ->program ) : "'' " ;
287283 $ else = $ this ->compileElseClause ($ block );
@@ -353,7 +349,7 @@ private function DecoratorBlock(BlockStatement $block): string
353349 // Do NOT add to partialCode - `in()` handles runtime registration, keeping inline partials block-scoped.
354350 $ this ->context ->usedPartial [$ partialName ] = '' ;
355351
356- return "'. " . $ this ->getFuncName ('in ' , "\$cx, ' " . addcslashes ($ partialName, " ' \\" ) . "', function( \$cx, \$in, \$sp) {return $ body;} " ) . ").' " ;
352+ return "'. " . $ this ->getFuncName ('in ' , "\$cx, ' " . $ this -> escape ($ partialName ) . "', function( \$cx, \$in, \$sp) {return $ body;} " ) . ").' " ;
357353 }
358354
359355 private function Decorator (Decorator $ decorator ): never
@@ -366,25 +362,25 @@ private function PartialStatement(PartialStatement $statement): string
366362 $ name = $ statement ->name ;
367363
368364 if ($ name instanceof PathExpression) {
369- $ p = "' " . addcslashes ($ name ->original , " ' \\" ) . "' " ;
365+ $ p = "' " . $ this -> escape ($ name ->original ) . "' " ;
370366 $ this ->resolveAndCompilePartial ($ name ->original );
371367 } elseif ($ name instanceof SubExpression) {
372368 $ p = $ this ->SubExpression ($ name );
373369 $ this ->context ->usedDynPartial ++;
374370 } elseif ($ name instanceof NumberLiteral) {
375371 $ literalName = (string ) $ name ->value ;
376- $ p = "' " . addcslashes ($ literalName, " ' \\" ) . "' " ;
372+ $ p = "' " . $ this -> escape ($ literalName ) . "' " ;
377373 $ this ->resolveAndCompilePartial ($ literalName );
378374 } elseif ($ name instanceof StringLiteral) {
379375 $ literalName = $ name ->value ;
380- $ p = "' " . addcslashes ($ literalName, " ' \\" ) . "' " ;
376+ $ p = "' " . $ this -> escape ($ literalName ) . "' " ;
381377 $ this ->resolveAndCompilePartial ($ literalName );
382378 } else {
383379 $ p = $ this ->compileExpression ($ name );
384380 }
385381
386382 $ vars = $ this ->compilePartialParams ($ statement ->params , $ statement ->hash );
387- $ indent = addcslashes ($ statement ->indent , " ' \\" );
383+ $ indent = $ this -> escape ($ statement ->indent );
388384
389385 // When preventIndent is set, emit the indent as literal content (like handlebars.js
390386 // appendContent opcode) and invoke the partial with an empty indent so its lines are
@@ -418,10 +414,10 @@ private function PartialBlockStatement(PartialBlockStatement $statement): string
418414
419415 if ($ name instanceof PathExpression) {
420416 $ partialName = $ name ->original ;
421- $ p = "' " . addcslashes ($ partialName, " ' \\" ) . "' " ;
417+ $ p = "' " . $ this -> escape ($ partialName ) . "' " ;
422418 } elseif ($ name instanceof StringLiteral || $ name instanceof NumberLiteral) {
423- $ partialName = $ name instanceof StringLiteral ? $ name -> value : ( string ) $ name-> value ;
424- $ p = "' " . addcslashes ($ partialName, " ' \\" ) . "' " ;
419+ $ partialName = $ this -> getLiteralKeyName ( $ name) ;
420+ $ p = "' " . $ this -> escape ($ partialName ) . "' " ;
425421 } else {
426422 $ p = $ this ->compileExpression ($ name );
427423 $ partialName = null ;
@@ -509,7 +505,7 @@ private function MustacheStatement(MustacheStatement $mustache): string
509505
510506 if ($ this ->resolveHelper ($ literalKey )) {
511507 $ params = $ this ->compileParams ($ mustache ->params , $ mustache ->hash );
512- $ escapedKey = addcslashes ($ literalKey, " ' \\" );
508+ $ escapedKey = $ this -> escape ($ literalKey );
513509 $ call = "LR::hbch( \$cx, ' $ escapedKey', $ params, \$in) " ;
514510 return "'. " . $ this ->getFuncName ($ fn , $ call ) . ").' " ;
515511 }
@@ -518,17 +514,15 @@ private function MustacheStatement(MustacheStatement $mustache): string
518514 throw new \Exception ('Missing helper: " ' . $ literalKey . '" ' );
519515 }
520516
521- $ escapedKey = addcslashes ($ literalKey , "' \\" );
522- $ miss = $ this ->context ->options ->strict
523- ? "LR::miss(' " . addcslashes ($ literalKey , "' \\" ) . "') "
524- : 'null ' ;
517+ $ escapedKey = $ this ->escape ($ literalKey );
518+ $ miss = $ this ->missValue ($ literalKey );
525519 $ val = "\$in[' $ escapedKey'] ?? $ miss " ;
526520 return "'. " . $ this ->getFuncName ($ fn , $ val ) . ").' " ;
527521 }
528522
529523 private function ContentStatement (ContentStatement $ statement ): string
530524 {
531- return addcslashes ($ statement ->value , " ' \\" );
525+ return $ this -> escape ($ statement ->value );
532526 }
533527
534528 private function CommentStatement (CommentStatement $ statement ): string
@@ -552,7 +546,7 @@ private function SubExpression(SubExpression $expression): string
552546 // Registered helper
553547 if ($ helperName !== null && $ this ->resolveHelper ($ helperName )) {
554548 $ params = $ this ->compileParams ($ expression ->params , $ expression ->hash );
555- $ escapedName = addcslashes ($ helperName, " ' \\" );
549+ $ escapedName = $ this -> escape ($ helperName );
556550 return "LR::hbch( \$cx, ' $ escapedName', $ params, \$in) " ;
557551 }
558552
@@ -584,9 +578,7 @@ private function PathExpression(PathExpression $expression): string
584578 return $ base ;
585579 }
586580
587- $ miss = $ this ->context ->options ->strict
588- ? "LR::miss(' " . addcslashes ($ expression ->original , "' \\" ) . "') "
589- : 'null ' ;
581+ $ miss = $ this ->missValue ($ expression ->original );
590582
591583 // @partial-block as variable: truthy when an active partial block exists
592584 if ($ data && $ depth === 0 && count ($ stringParts ) === 1 && $ stringParts [0 ] === 'partial-block ' ) {
@@ -597,7 +589,7 @@ private function PathExpression(PathExpression $expression): string
597589 if (!$ data && $ depth === 0 && !self ::scopedId ($ expression )) {
598590 $ bpIdx = $ this ->lookupBlockParam ($ stringParts [0 ]);
599591 if ($ bpIdx !== null ) {
600- $ escapedName = addcslashes ($ stringParts [0 ], " ' \\" );
592+ $ escapedName = $ this -> escape ($ stringParts [0 ]);
601593 $ bpBase = "\$cx->blParam[ $ bpIdx][' $ escapedName'] " ;
602594 $ remaining = $ this ->buildKeyAccess (array_slice ($ stringParts , 1 ));
603595 return "$ bpBase$ remaining ?? $ miss " ;
@@ -638,7 +630,7 @@ private function PathExpression(PathExpression $expression): string
638630
639631 private function StringLiteral (StringLiteral $ literal ): string
640632 {
641- return "' " . addcslashes ($ literal ->value , " ' \\" ) . "' " ;
633+ return "' " . $ this -> escape ($ literal ->value ) . "' " ;
642634 }
643635
644636 private function NumberLiteral (NumberLiteral $ literal ): string
@@ -700,7 +692,7 @@ private function Hash(Hash $hash): string
700692 {
701693 $ pairs = [];
702694 foreach ($ hash ->pairs as $ pair ) {
703- $ key = addcslashes ($ pair ->key , " ' \\" );
695+ $ key = $ this -> escape ($ pair ->key );
704696 $ value = $ this ->compileExpression ($ pair ->value );
705697 $ pairs [] = "' $ key'=> $ value " ;
706698 }
@@ -905,7 +897,7 @@ private function buildKeyAccess(array $parts): string
905897 {
906898 $ n = '' ;
907899 foreach ($ parts as $ part ) {
908- $ n .= "[' " . addcslashes ($ part, " ' \\" ) . "'] " ;
900+ $ n .= "[' " . $ this -> escape ($ part ) . "'] " ;
909901 }
910902 return $ n ;
911903 }
@@ -923,6 +915,26 @@ private function getFuncName(string $name, string $args): string
923915 return "LR:: $ name( $ args " ;
924916 }
925917
918+ private function escape (string $ s ): string
919+ {
920+ return addcslashes ($ s , "' \\" );
921+ }
922+
923+ private function missValue (string $ key ): string
924+ {
925+ return $ this ->context ->options ->strict
926+ ? "LR::miss(' " . $ this ->escape ($ key ) . "') "
927+ : 'null ' ;
928+ }
929+
930+ /** @return array{list<string>, string} [$bp, $bs] */
931+ private function getProgramBlockParams (?Program $ program ): array
932+ {
933+ $ bp = $ program ? $ program ->blockParams : [];
934+ $ bs = $ bp ? Expression::listString ($ bp ) : 'null ' ;
935+ return [$ bp , $ bs ];
936+ }
937+
926938 /**
927939 * Get includeZero value from hash.
928940 */
@@ -982,9 +994,7 @@ private function compilePathWithLookup(PathExpression $path, string $lookupCode)
982994 $ base = $ this ->buildBasePath ($ data , $ depth );
983995 $ n = $ this ->buildKeyAccess ($ parts );
984996
985- $ miss = $ this ->context ->options ->strict
986- ? "LR::miss(' " . addcslashes ($ path ->original , "' \\" ) . "') "
987- : 'null ' ;
997+ $ miss = $ this ->missValue ($ path ->original );
988998
989999 return $ base . $ n . "[ $ lookupCode] ?? $ miss " ;
9901000 }
@@ -1006,7 +1016,7 @@ private function getWithLookup(AstExpression $itemsExpr, AstExpression $idxExpr)
10061016 $ varCode = $ this ->compilePathWithLookup ($ itemsExpr , $ idxCode );
10071017 } else {
10081018 $ itemsCode = $ this ->compileExpression ($ itemsExpr );
1009- $ miss = $ this ->context -> options -> strict ? " LR::miss ('lookup')" : ' null ' ;
1019+ $ miss = $ this ->missValue ('lookup ' );
10101020 $ varCode = $ itemsCode . "[ $ idxCode] ?? $ miss " ;
10111021 }
10121022 return $ varCode ;
0 commit comments