@@ -61,6 +61,7 @@ public function testLog(): void
6161 #[DataProvider("ifElseProvider " )]
6262 #[DataProvider("sectionProvider " )]
6363 #[DataProvider("contextProvider " )]
64+ #[DataProvider("objectProvider " )]
6465 #[DataProvider("lengthProvider " )]
6566 #[DataProvider("dataClosuresProvider " )]
6667 #[DataProvider("missingDataProvider " )]
@@ -2237,6 +2238,81 @@ public static function contextProvider(): array
22372238 ];
22382239 }
22392240
2241+ /** @return array<string, RegIssue> */
2242+ public static function objectProvider (): array
2243+ {
2244+ return [
2245+ 'object: single-property root context ' => [
2246+ 'template ' => '{{name}} ' ,
2247+ 'data ' => (object ) ['name ' => 'Alice ' ],
2248+ 'expected ' => 'Alice ' ,
2249+ ],
2250+ 'object: nested property lookup ' => [
2251+ 'template ' => '{{user.name}} ' ,
2252+ 'data ' => ['user ' => (object ) ['name ' => 'Bob ' ]],
2253+ 'expected ' => 'Bob ' ,
2254+ ],
2255+ 'object: deeply nested object properties ' => [
2256+ 'template ' => '{{a.b.c}} ' ,
2257+ 'data ' => ['a ' => (object ) ['b ' => (object ) ['c ' => 'deep ' ]]],
2258+ 'expected ' => 'deep ' ,
2259+ ],
2260+ 'object: missing property renders empty ' => [
2261+ 'template ' => '{{user.missing}} ' ,
2262+ 'data ' => ['user ' => (object ) ['name ' => 'Carol ' ]],
2263+ 'expected ' => '' ,
2264+ ],
2265+ 'object: {{#with}} scopes to object ' => [
2266+ 'template ' => '{{#with user}}{{name}}{{/with}} ' ,
2267+ 'data ' => ['user ' => (object ) ['name ' => 'Dan ' ]],
2268+ 'expected ' => 'Dan ' ,
2269+ ],
2270+ 'object: {{#each}} iterates public properties ' => [
2271+ 'template ' => '{{#each obj}}{{this}}{{/each}} ' ,
2272+ 'data ' => ['obj ' => (object ) ['x ' => '1 ' , 'y ' => '2 ' ]],
2273+ 'expected ' => '12 ' ,
2274+ ],
2275+ 'object: block section treats object as new scope ' => [
2276+ 'template ' => '{{#obj}}{{name}}{{/obj}} ' ,
2277+ 'data ' => ['obj ' => (object ) ['name ' => 'Eve ' ]],
2278+ 'expected ' => 'Eve ' ,
2279+ ],
2280+ 'object: ../path traversal from inside object scope ' => [
2281+ 'template ' => '{{#with user}}{{../title}}{{/with}} ' ,
2282+ 'data ' => ['title ' => 'Hello ' , 'user ' => (object ) ['name ' => 'Frank ' ]],
2283+ 'expected ' => 'Hello ' ,
2284+ ],
2285+ 'object: block params resolve properties on object items ' => [
2286+ 'template ' => '{{#each items as |item|}}{{item.name}}{{/each}} ' ,
2287+ 'data ' => ['items ' => [(object ) ['name ' => 'Grace ' ]]],
2288+ 'expected ' => 'Grace ' ,
2289+ ],
2290+ 'object: strict mode allows null-valued property ' => [
2291+ 'template ' => '{{user.name}} ' ,
2292+ 'options ' => new Options (strict: true ),
2293+ 'data ' => ['user ' => (object ) ['name ' => null ]],
2294+ 'expected ' => '' ,
2295+ ],
2296+ 'object: assumeObjects mode property access ' => [
2297+ 'template ' => '{{user.name}} ' ,
2298+ 'options ' => new Options (assumeObjects: true ),
2299+ 'data ' => ['user ' => (object ) ['name ' => 'Henry ' ]],
2300+ 'expected ' => 'Henry ' ,
2301+ ],
2302+ 'object: explicit length property ' => [
2303+ 'template ' => '{{obj.length}} ' ,
2304+ 'data ' => ['obj ' => (object ) ['length ' => 42 ]],
2305+ 'expected ' => '42 ' ,
2306+ ],
2307+ 'object: compat mode falls through to parent when property absent from object ' => [
2308+ 'template ' => '{{#each items}}{{name}}{{/each}} ' ,
2309+ 'options ' => new Options (compat: true ),
2310+ 'data ' => ['name ' => 'parent ' , 'items ' => [(object ) []]],
2311+ 'expected ' => 'parent ' ,
2312+ ],
2313+ ];
2314+ }
2315+
22402316 /** @return array<string, RegIssue> */
22412317 public static function lengthProvider (): array
22422318 {
0 commit comments