Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 48 additions & 20 deletions src/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,13 @@ protected function pushCallStack($name = '')
Parser::SOURCE_LINE => $this->sourceLine,
Parser::SOURCE_COLUMN => $this->sourceColumn
];
// infinite calling loop
if (count($this->callStack) > 25000) {
// not displayed but you can var_dump it to deep debug
$msg = $this->callStackMessage(true, 100);
$msg = "Infinite calling loop";
$this->throwError($msg);
}
}

protected function popCallStack()
Expand All @@ -1462,18 +1469,21 @@ protected function popCallStack()
*
* @param array $stms
* @param \Leafo\ScssPhp\Formatter\OutputBlock $out
* @param string $traceName
*
* @return array|null
*/
protected function compileChildren($stms, OutputBlock $out)
protected function compileChildren($stms, OutputBlock $out, $traceName = '')
{
$this->pushCallStack($traceName);
foreach ($stms as $stm) {
$ret = $this->compileChild($stm, $out);

if (isset($ret)) {
return $ret;
}
}
$this->popCallStack();

return null;
}
Expand All @@ -1484,11 +1494,13 @@ protected function compileChildren($stms, OutputBlock $out)
* @param array $stms
* @param \Leafo\ScssPhp\Formatter\OutputBlock $out
* @param \Leafo\ScssPhp\Block $selfParent
* @param string $traceName
*
* @throws \Exception
*/
protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent = null)
protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent = null, $traceName = '')
{
$this->pushCallStack($traceName);
foreach ($stms as $stm) {
if ($selfParent && isset($stm[1]) && is_object($stm[1]) && $stm[1] instanceof Block) {
$stm[1]->selfParent = $selfParent;
Expand All @@ -1508,6 +1520,7 @@ protected function compileChildrenNoReturn($stms, OutputBlock $out, $selfParent
return;
}
}
$this->popCallStack();
}


Expand Down Expand Up @@ -2160,18 +2173,15 @@ protected function compileChild($child, OutputBlock $out)

$this->env->marker = 'mixin';

$this->pushCallStack($this->env->marker . " " . $name);
$this->compileChildrenNoReturn($mixin->children, $out, $selfParent);
$this->popCallStack();
$this->compileChildrenNoReturn($mixin->children, $out, $selfParent, $this->env->marker . " " . $name);

$this->storeEnv = $storeEnv;

$this->popEnv();
break;

case Type::T_MIXIN_CONTENT:
$content = $this->get(static::$namespaces['special'] . 'content', false, $this->getStoreEnv())
?: $this->get(static::$namespaces['special'] . 'content', false, $this->env);
$content = $this->get(static::$namespaces['special'] . 'content', false, isset($this->storeEnv) ? $this->storeEnv : $this->env);

if (! $content) {
$content = new \stdClass();
Expand Down Expand Up @@ -3904,20 +3914,41 @@ public function throwError($msg)
: "line: $line";
$msg = "$msg: $loc";

if ($this->callStack) {
$msg .= "\nCall Stack:\n";
$ncall = 0;
$callStackMsg = $this->callStackMessage();
if ($callStackMsg) {
$msg .= "\nCall Stack:\n" . $callStackMsg;
}

throw new CompilerException($msg);
}

/**
* @param bool $all
* @param null $limit
* @return string
*/
protected function callStackMessage($all = false, $limit = null)
{
$callStackMsg = [];
$ncall = 0;

if ($this->callStack) {
foreach (array_reverse($this->callStack) as $call) {
$msg .= "#" . $ncall++ . " " . $call['n'] . " ";
$msg .= (isset($this->sourceNames[$call[Parser::SOURCE_INDEX]])
? $this->sourceNames[$call[Parser::SOURCE_INDEX]]
: '(unknown file)');
$msg .= " on line " . $call[Parser::SOURCE_LINE] . "\n";
if ($all || (isset($call['n']) && $call['n'])) {
$msg = "#" . $ncall++ . " " . $call['n'] . " ";
$msg .= (isset($this->sourceNames[$call[Parser::SOURCE_INDEX]])
? $this->sourceNames[$call[Parser::SOURCE_INDEX]]
: '(unknown file)');
$msg .= " on line " . $call[Parser::SOURCE_LINE];
$callStackMsg[] = $msg;
if (!is_null($limit) && $ncall>$limit) {
break;
}
}
}
}

throw new CompilerException($msg);
return implode("\n", $callStackMsg);
}

/**
Expand Down Expand Up @@ -3984,11 +4015,8 @@ protected function callScssFunction($name, $argValues, &$returnValue)
$tmp->children = [];

$this->env->marker = 'function';
$this->pushCallStack($this->env->marker . " " . $name);

$ret = $this->compileChildren($func->children, $tmp);

$this->popCallStack();
$ret = $this->compileChildren($func->children, $tmp, $this->env->marker . " " . $name);

$this->storeEnv = $storeEnv;

Expand Down