/s';
expect(preg_match($pattern, $source, $match))->toBe(1);
$parser = (new \PhpParser\ParserFactory())->createForNewestSupportedVersion();
$statements = $parser->parse('expr;
expect($expression)->toBeInstanceOf(\PhpParser\Node\Expr\Print_::class);
$encodedCall = $expression->expr;
expect($encodedCall)->toBeInstanceOf(\PhpParser\Node\Expr\FuncCall::class);
expect($encodedCall->name->toString())->toBe('cacti_js_encode');
$translatedCall = $encodedCall->args[0]->value;
expect($translatedCall)->toBeInstanceOf(\PhpParser\Node\Expr\FuncCall::class);
expect($translatedCall->name->toString())->toBe('__esc');
// Supply adversarial catalog text to the actual production expression;
// neither the translation helper nor the JSON encoder is replaced.
$translatedCall->args[0]->value = new \PhpParser\Node\Expr\Variable('catalogMessage');
$printer = new \PhpParser\PrettyPrinter\Standard();
$encoded = eval('return ' . $printer->prettyPrintExpr($encodedCall) . ';');
expect(json_decode($encoded, true, 512, JSON_THROW_ON_ERROR))->toBe(__esc($catalogMessage));
expect($encoded)->not->toContain('');
expect($encoded)->not->toContain("\u{2028}");
expect($encoded)->not->toContain("\u{2029}");
})->with([
['settings.php', 'permsHeader'],
['settings.php', 'permsMessage'],
['lib/html.php', 'tableConstraints'],
['lib/html.php', 'zoom_outOfRangeMessage'],
])->with([
'quotes and backslashes' => ["single' double\" backslash\\"],
'script closing text' => [''],
'line terminators' => ["first\nsecond\u{2028}third\u{2029}fourth"],
'HTML entities' => ['" ' caption'],
]);