@@ -230,9 +230,7 @@ public static function invokeAmbiguous(RuntimeContext $cx, string $name, mixed &
230230 $ value = $ cx ->helpers [$ name ] ?? null ;
231231 if ($ value === null ) {
232232 if ($ compat ) {
233- $ value = $ strict
234- ? self ::compatStrictLookup ($ cx , $ _this , $ name )
235- : self ::compatLookup ($ cx , $ _this , $ name );
233+ $ value = self ::compatLookup ($ cx , $ _this , $ name , $ strict );
236234 } elseif ($ strict ) {
237235 $ value = self ::strictLookup ($ _this , $ name , $ name );
238236 } else {
@@ -249,40 +247,23 @@ public static function invokeAmbiguous(RuntimeContext $cx, string $name, mixed &
249247 }
250248
251249 /**
252- * Non-strict compat depths-walk for a single key, equivalent to HBS.js container.lookup(depths, name) .
250+ * Compat depths-walk for a single key, equivalent to HBS.js container.lookup / container.strictLookup .
253251 * Checks $in first, then walks $cx->depths from the closest ancestor outward.
254- * Null values are skipped (treated as not found), matching HBS.js container.lookup's `result != null` check.
252+ * Uses array_key_exists so explicit null values shadow parent contexts (Mustache semantics).
253+ * When $strict is true, throws for a key absent from all frames; otherwise returns null.
255254 */
256- public static function compatLookup (RuntimeContext $ cx , mixed $ in , string $ name ): mixed
257- {
258- if (is_array ($ in ) && ($ value = $ in [$ name ] ?? null ) !== null ) {
259- return $ value ;
260- }
261- for ($ i = count ($ cx ->depths ) - 1 ; $ i >= 0 ; $ i --) {
262- $ ctx = $ cx ->depths [$ i ];
263- if (is_array ($ ctx ) && ($ v = $ ctx [$ name ] ?? null ) !== null ) {
264- return $ v ;
265- }
266- }
267- return null ;
268- }
269-
270- /**
271- * Strict compat depths-walk for a single key, equivalent to HBS.js container.strictLookup(depths, name, loc).
272- * Checks $in first, then walks $cx->depths from the closest ancestor outward.
273- * Null values are treated as defined (array_key_exists), matching HBS.js container.strictLookup's `name in d` check.
274- */
275- public static function compatStrictLookup (RuntimeContext $ cx , mixed $ in , string $ name ): mixed
255+ public static function compatLookup (RuntimeContext $ cx , mixed $ in , string $ name , bool $ strict = false ): mixed
276256 {
277257 if (is_array ($ in ) && array_key_exists ($ name , $ in )) {
278- return self :: strictLookup ( $ in, $ name, $ name ) ;
258+ return $ in[ $ name] ;
279259 }
280260 for ($ i = count ($ cx ->depths ) - 1 ; $ i >= 0 ; $ i --) {
281- if (is_array ($ cx ->depths [$ i ]) && array_key_exists ($ name , $ cx ->depths [$ i ])) {
282- return self ::strictLookup ($ cx ->depths [$ i ], $ name , $ name );
261+ $ ctx = $ cx ->depths [$ i ];
262+ if (is_array ($ ctx ) && array_key_exists ($ name , $ ctx )) {
263+ return $ ctx [$ name ];
283264 }
284265 }
285- return self ::strictLookup (null , $ name , $ name );
266+ return $ strict ? self ::strictLookup (null , $ name , $ name ) : null ;
286267 }
287268
288269 /**
0 commit comments