You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
contenteditable, draggable, spellcheck, hidden are no longer treated as plain boolean attributes, because in HTML they are not. contenteditable={$editable} now renders contenteditable="true" or contenteditable="false", so false really turns editing off instead of silently inheriting it from the parent, and draggable can be set to true at all. hidden and popover stay flags but keep a value, so hidden="until-found" survives. With migration warnings on, Latte reports every place where the output changes; use |toggle to keep the old bare-name rendering
Sandbox – property names in a policy are case-sensitive, as they are in PHP: allowing visible no longer allows Visible
isPartialFunction() of the call nodes is renamed to isPartialApplication() – only matters for extensions working with the AST
✨ New Features
PHP 8.6 support
NodeHelpers::find() and findFirst() accept a node class as the filter: find($node, TextNode::class) returns a list<TextNode>, no type annotation needed
ExpressionNode::toValue() and hasValue() tell an extension whether an expression is a literal value and which; NodeHelpers::toValue() is deprecated in their favor
🔒 Security
The sandbox got a thorough review of its runtime checks: a dynamic property name is evaluated just once, so it cannot be checked with one value and accessed with another; (array) cast of an object is forbidden and foreach over an object checks its properties against the policy; $iterator no longer passes calls of unknown methods to the iterated object; and -> / ?-> method calls behave exactly as in PHP
A <script> whose type is anything the browser might execute (e.g. text/javascript1.5) is escaped as JavaScript; only a plain data type such as text/csv is escaped as text, and text/html or text/x-template as HTML
A custom sandbox policy without getCacheSignature() triggers a deprecation, because its instances with different rules would share compiled templates
🐛 Bug Fixes
{include parent} restores the block level after an exception and works in a block that includes itself
{capture $a[$i++]|filter} evaluates its target once
|slice with a negative start or length works on iterators the same way as on arrays, and |batch keeps every item of an iterator with repeated keys
An arrow function body swallows and, or and xor, as in PHP
The deprecation of an unqualified constant is no longer raised for class names written in capitals such as FOO::bar() or new FOO
🛡️ Robustness
Writing through ?-> anywhere in a chain ($a?->b->c = 1) is a compile error instead of a PHP error later
The linter writes errors to stderr outside CLI too and restores its error handler for an unreadable file