Skip to content

Commit 63dc7a3

Browse files
committed
Fix the handling of call traces for exceptions of native functions
Due to the multiple prototypes being tried in chain, native functions are throwing errors even in valid code, which will be swallowed when finding a compatible prototype. In case of failure, the catched exception message is sent back to the throwError API. This has 2 effects: - due to the double usage of throwError, the details about the location and call trace get duplicated in the final message - computing the call trace message is very costly due to the size of the call trace. Computing it for exceptions which will be swallowed is an useless performance hit. Places catching exceptions are now toggling a flag which tells throwError to skip adding the details. This avoids both the performance hit of multiple prototypes and the duplicated details (as the first call to throwError is now done with the flag toggled).
1 parent c6626ee commit 63dc7a3

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

src/Compiler.php

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ class Compiler
161161
protected $stderr;
162162
protected $shouldEvaluate;
163163
protected $ignoreErrors;
164+
protected $ignoreCallStackMessage = false;
164165

165166
protected $callStack = [];
166167

@@ -255,6 +256,7 @@ public function compile($code, $path = null)
255256
$this->storeEnv = null;
256257
$this->charsetSeen = null;
257258
$this->shouldEvaluate = null;
259+
$this->ignoreCallStackMessage = false;
258260

259261
$this->parser = $this->parserFactory($path);
260262
$tree = $this->parser->parse($code);
@@ -1564,11 +1566,14 @@ protected function compileCommentValue($value, $pushEnv = false)
15641566
$this->pushEnv();
15651567
}
15661568

1569+
$ignoreCallStackMessage = $this->ignoreCallStackMessage;
1570+
$this->ignoreCallStackMessage = true;
15671571
try {
15681572
$c = $this->compileValue($value[2]);
15691573
} catch (\Exception $e) {
15701574
// ignore error in comment compilation which are only interpolation
15711575
}
1576+
$this->ignoreCallStackMessage = $ignoreCallStackMessage;
15721577

15731578
if ($pushEnv) {
15741579
$this->popEnv();
@@ -4737,23 +4742,25 @@ public function throwError($msg)
47374742
return;
47384743
}
47394744

4740-
$line = $this->sourceLine;
4741-
$column = $this->sourceColumn;
4742-
4743-
$loc = isset($this->sourceNames[$this->sourceIndex])
4744-
? $this->sourceNames[$this->sourceIndex] . " on line $line, at column $column"
4745-
: "line: $line, column: $column";
4746-
47474745
if (func_num_args() > 1) {
47484746
$msg = call_user_func_array('sprintf', func_get_args());
47494747
}
47504748

4751-
$msg = "$msg: $loc";
4749+
if (!$this->ignoreCallStackMessage) {
4750+
$line = $this->sourceLine;
4751+
$column = $this->sourceColumn;
4752+
4753+
$loc = isset($this->sourceNames[$this->sourceIndex])
4754+
? $this->sourceNames[$this->sourceIndex] . " on line $line, at column $column"
4755+
: "line: $line, column: $column";
47524756

4753-
$callStackMsg = $this->callStackMessage();
4757+
$msg = "$msg: $loc";
47544758

4755-
if ($callStackMsg) {
4756-
$msg .= "\nCall Stack:\n" . $callStackMsg;
4759+
$callStackMsg = $this->callStackMessage();
4760+
4761+
if ($callStackMsg) {
4762+
$msg .= "\nCall Stack:\n" . $callStackMsg;
4763+
}
47574764
}
47584765

47594766
throw new CompilerException($msg);
@@ -5026,6 +5033,9 @@ protected function sortNativeFunctionArgs($functionName, $prototypes, $args)
50265033
$argDef[] = [$name, $default, $isVariable];
50275034
}
50285035

5036+
$ignoreCallStackMessage = $this->ignoreCallStackMessage;
5037+
$this->ignoreCallStackMessage = true;
5038+
50295039
try {
50305040
$vars = $this->applyArguments($argDef, $args, false, false);
50315041

@@ -5063,6 +5073,7 @@ protected function sortNativeFunctionArgs($functionName, $prototypes, $args)
50635073
} catch (CompilerException $e) {
50645074
$exceptionMessage = $e->getMessage();
50655075
}
5076+
$this->ignoreCallStackMessage = $ignoreCallStackMessage;
50665077
}
50675078

50685079
if ($exceptionMessage && ! $prototypeHasMatch) {

0 commit comments

Comments
 (0)