What happened?
Description
I'm trying to use the spread operator introduced in Twig 3.8.0. However, with the preloadSingles option enabled, the operator doesn't work as intended. Test case:
{% set one = { one: 'two' } %}
{% set two = {
...one,
foo: 'bar',
} %}
{% dd two %}
Example on Twig Fiddle
This should result in a flat array with keys one and foo. It does if preloadSingles is disabled. If the setting is enabled, you get a nested array instead.
Steps to reproduce
- Put the snippet above in your template and enable
preloadSingles.
Expected behavior
The behaviour with preloadSingles enabled should match the default behaviour.
Actual behavior
There seems to be an issue with the way Craft overwrites Twig's built-in nodes. You can see the issue in the generated templates:
With preloadSingles enabled:
$macros = $this->macros;
craft\helpers\Template::beginProfile("template", "elements/entries/home");
craft\helpers\Template::preloadSingles(['one', 'two']);
// line 1
$context["one"] = ["one" => "two"];
// line 2
$context["two"] = [ // line 3
(isset($context["one"]) || array_key_exists("one", $context) ? $context["one"] : (craft\helpers\Template::fallbackExists("one") ? craft\helpers\Template::fallback("one") : (function () { throw new RuntimeError('Variable "one" does not exist.', 3, $this->source); })())), "foo" => "bar"];
// line 6
Craft::dd((isset($context["two"]) || array_key_exists("two", $context) ? $context["two"] : (craft\helpers\Template::fallbackExists("two") ? craft\helpers\Template::fallback("two") : (function () { throw new RuntimeError('Variable "two" does not exist.', 6, $this->source); })())));
craft\helpers\Template::endProfile("template", "elements/entries/home");
Without preloadSingles:
craft\helpers\Template::beginProfile("template", "elements/entries/home");
// line 1
$context["one"] = ["one" => "two"];
// line 2
$context["two"] = [... // line 3
(isset($context["one"]) || array_key_exists("one", $context) ? $context["one"] : (function () { throw new RuntimeError('Variable "one" does not exist.', 3, $this->source); })()), "foo" => "bar"];
// line 6
Craft::dd((isset($context["two"]) || array_key_exists("two", $context) ? $context["two"] : (function () { throw new RuntimeError('Variable "two" does not exist.', 6, $this->source); })()));
craft\helpers\Template::endProfile("template", "elements/entries/home");
With preloadSingles, the spread operator (...) is missing from the compiled expression.
Craft CMS version
4.8.8
PHP version
8.2
Operating system and version
No response
Database type and version
No response
Image driver and version
No response
Installed plugins and versions
What happened?
Description
I'm trying to use the spread operator introduced in Twig 3.8.0. However, with the
preloadSinglesoption enabled, the operator doesn't work as intended. Test case:{% set one = { one: 'two' } %} {% set two = { ...one, foo: 'bar', } %} {% dd two %}Example on Twig Fiddle
This should result in a flat array with keys
oneandfoo. It does ifpreloadSinglesis disabled. If the setting is enabled, you get a nested array instead.Steps to reproduce
preloadSingles.Expected behavior
The behaviour with
preloadSinglesenabled should match the default behaviour.Actual behavior
There seems to be an issue with the way Craft overwrites Twig's built-in nodes. You can see the issue in the generated templates:
With
preloadSinglesenabled:Without
preloadSingles:With
preloadSingles, the spread operator (...) is missing from the compiled expression.Craft CMS version
4.8.8
PHP version
8.2
Operating system and version
No response
Database type and version
No response
Image driver and version
No response
Installed plugins and versions