Skip to content

Released version 3.1.7

Latest

Choose a tag to compare

@dg dg released this 22 Oct 00:11

💥 Breaking Changes

  • 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