@@ -1521,6 +1521,13 @@ protected function pushCallStack($name = '')
15211521 Parser::SOURCE_LINE => $ this ->sourceLine ,
15221522 Parser::SOURCE_COLUMN => $ this ->sourceColumn
15231523 ];
1524+ // infinite calling loop
1525+ if (count ($ this ->callStack ) > 25000 ) {
1526+ // not displayed but you can var_dump it to deep debug
1527+ $ msg = $ this ->callStackMessage (true , 100 );
1528+ $ msg = "Infinite calling loop " ;
1529+ $ this ->throwError ($ msg );
1530+ }
15241531 }
15251532
15261533 protected function popCallStack ()
@@ -1533,18 +1540,21 @@ protected function popCallStack()
15331540 *
15341541 * @param array $stms
15351542 * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
1543+ * @param string $traceName
15361544 *
15371545 * @return array|null
15381546 */
1539- protected function compileChildren ($ stms , OutputBlock $ out )
1547+ protected function compileChildren ($ stms , OutputBlock $ out, $ traceName = '' )
15401548 {
1549+ $ this ->pushCallStack ($ traceName );
15411550 foreach ($ stms as $ stm ) {
15421551 $ ret = $ this ->compileChild ($ stm , $ out );
15431552
15441553 if (isset ($ ret )) {
15451554 return $ ret ;
15461555 }
15471556 }
1557+ $ this ->popCallStack ();
15481558
15491559 return null ;
15501560 }
@@ -1555,11 +1565,13 @@ protected function compileChildren($stms, OutputBlock $out)
15551565 * @param array $stms
15561566 * @param \Leafo\ScssPhp\Formatter\OutputBlock $out
15571567 * @param \Leafo\ScssPhp\Block $selfParent
1568+ * @param string $traceName
15581569 *
15591570 * @throws \Exception
15601571 */
1561- protected function compileChildrenNoReturn ($ stms , OutputBlock $ out , $ selfParent = null )
1572+ protected function compileChildrenNoReturn ($ stms , OutputBlock $ out , $ selfParent = null , $ traceName = '' )
15621573 {
1574+ $ this ->pushCallStack ($ traceName );
15631575 foreach ($ stms as $ stm ) {
15641576 if ($ selfParent && isset ($ stm [1 ]) && is_object ($ stm [1 ]) && $ stm [1 ] instanceof Block) {
15651577 $ stm [1 ]->selfParent = $ selfParent ;
@@ -1579,6 +1591,7 @@ protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent
15791591 return ;
15801592 }
15811593 }
1594+ $ this ->popCallStack ();
15821595 }
15831596
15841597
@@ -2235,18 +2248,15 @@ protected function compileChild($child, OutputBlock $out)
22352248
22362249 $ this ->env ->marker = 'mixin ' ;
22372250
2238- $ this ->pushCallStack ($ this ->env ->marker . " " . $ name );
2239- $ this ->compileChildrenNoReturn ($ mixin ->children , $ out , $ selfParent );
2240- $ this ->popCallStack ();
2251+ $ this ->compileChildrenNoReturn ($ mixin ->children , $ out , $ selfParent , $ this ->env ->marker . " " . $ name );
22412252
22422253 $ this ->storeEnv = $ storeEnv ;
22432254
22442255 $ this ->popEnv ();
22452256 break ;
22462257
22472258 case Type::T_MIXIN_CONTENT :
2248- $ content = $ this ->get (static ::$ namespaces ['special ' ] . 'content ' , false , $ this ->getStoreEnv ())
2249- ?: $ this ->get (static ::$ namespaces ['special ' ] . 'content ' , false , $ this ->env );
2259+ $ content = $ this ->get (static ::$ namespaces ['special ' ] . 'content ' , false , isset ($ this ->storeEnv ) ? $ this ->storeEnv : $ this ->env );
22502260
22512261 if (! $ content ) {
22522262 $ content = new \stdClass ();
@@ -3983,20 +3993,41 @@ public function throwError($msg)
39833993 : "line: $ line " ;
39843994 $ msg = "$ msg: $ loc " ;
39853995
3986- if ($ this ->callStack ) {
3987- $ msg .= "\nCall Stack: \n" ;
3988- $ ncall = 0 ;
3996+ $ callStackMsg = $ this ->callStackMessage ();
3997+ if ($ callStackMsg ) {
3998+ $ msg .= "\nCall Stack: \n" . $ callStackMsg ;
3999+ }
4000+
4001+ throw new CompilerException ($ msg );
4002+ }
4003+
4004+ /**
4005+ * @param bool $all
4006+ * @param null $limit
4007+ * @return string
4008+ */
4009+ protected function callStackMessage ($ all = false , $ limit = null )
4010+ {
4011+ $ callStackMsg = [];
4012+ $ ncall = 0 ;
39894013
4014+ if ($ this ->callStack ) {
39904015 foreach (array_reverse ($ this ->callStack ) as $ call ) {
3991- $ msg .= "# " . $ ncall ++ . " " . $ call ['n ' ] . " " ;
3992- $ msg .= (isset ($ this ->sourceNames [$ call [Parser::SOURCE_INDEX ]])
3993- ? $ this ->sourceNames [$ call [Parser::SOURCE_INDEX ]]
3994- : '(unknown file) ' );
3995- $ msg .= " on line " . $ call [Parser::SOURCE_LINE ] . "\n" ;
4016+ if ($ all || (isset ($ call ['n ' ]) && $ call ['n ' ])) {
4017+ $ msg = "# " . $ ncall ++ . " " . $ call ['n ' ] . " " ;
4018+ $ msg .= (isset ($ this ->sourceNames [$ call [Parser::SOURCE_INDEX ]])
4019+ ? $ this ->sourceNames [$ call [Parser::SOURCE_INDEX ]]
4020+ : '(unknown file) ' );
4021+ $ msg .= " on line " . $ call [Parser::SOURCE_LINE ];
4022+ $ callStackMsg [] = $ msg ;
4023+ if (!is_null ($ limit ) && $ ncall >$ limit ) {
4024+ break ;
4025+ }
4026+ }
39964027 }
39974028 }
39984029
3999- throw new CompilerException ( $ msg );
4030+ return implode ( "\n" , $ callStackMsg );
40004031 }
40014032
40024033 /**
@@ -4063,11 +4094,8 @@ protected function callScssFunction($name, $argValues, &$returnValue)
40634094 $ tmp ->children = [];
40644095
40654096 $ this ->env ->marker = 'function ' ;
4066- $ this ->pushCallStack ($ this ->env ->marker . " " . $ name );
40674097
4068- $ ret = $ this ->compileChildren ($ func ->children , $ tmp );
4069-
4070- $ this ->popCallStack ();
4098+ $ ret = $ this ->compileChildren ($ func ->children , $ tmp , $ this ->env ->marker . " " . $ name );
40714099
40724100 $ this ->storeEnv = $ storeEnv ;
40734101
0 commit comments