@@ -54,7 +54,7 @@ public static function defaultHelpers(): array
5454 $ context = $ context ($ options ->scope );
5555 }
5656 if (!is_iterable ($ context )) {
57- $ context = [];
57+ $ context = is_object ( $ context ) ? get_object_vars ( $ context ) : [];
5858 }
5959 return $ options ->iterate ($ context );
6060 },
@@ -109,7 +109,7 @@ public static function defaultHelpers(): array
109109 }
110110
111111 /**
112- * Strict-mode key lookup: throw if $base is not an array or $key is absent .
112+ * Strict-mode key lookup: throw if $key is absent from $base .
113113 * Unlike the null-coalescing pattern, this allows null values when the key exists.
114114 */
115115 public static function strictLookup (mixed $ base , string $ key ): mixed
@@ -118,6 +118,8 @@ public static function strictLookup(mixed $base, string $key): mixed
118118 if (array_key_exists ($ key , $ base )) {
119119 return $ base [$ key ];
120120 }
121+ } elseif (is_object ($ base ) && property_exists ($ base , $ key )) {
122+ return $ base ->$ key ;
121123 }
122124 $ desc = match (true ) {
123125 is_bool ($ base ) => $ base ? 'true ' : 'false ' ,
@@ -130,16 +132,29 @@ public static function strictLookup(mixed $base, string $key): mixed
130132
131133 /**
132134 * assumeObjects / strict-helper-arg key lookup: throw if $base is null (mirroring JS
133- * TypeError for null/undefined property access); return null silently for a missing key on a
134- * valid array (mirroring JS returning undefined for a missing object property); return null for
135- * non-array non-null bases (mirroring JS returning undefined for property access on primitives).
135+ * TypeError for null/undefined property access); return null silently for a missing key or
136+ * a non-array/object base (mirroring JS returning undefined for non-existent properties).
136137 */
137138 public static function nullCheck (mixed $ base , string $ key ): mixed
138139 {
139140 if ($ base === null ) {
140- throw new \ErrorException ("Cannot access property \"$ key \" on null " );
141+ throw new \Exception ("Cannot access property \"$ key \" on null " );
141142 }
142- return is_array ($ base ) ? ($ base [$ key ] ?? null ) : null ;
143+ return self ::prop ($ base , $ key );
144+ }
145+
146+ /**
147+ * Default key/property lookup for normal mode: $base[$key] for arrays, $base->$key for objects.
148+ */
149+ public static function prop (mixed $ base , string $ key ): mixed
150+ {
151+ if (is_array ($ base )) {
152+ return $ base [$ key ] ?? null ;
153+ }
154+ if (is_object ($ base )) {
155+ return $ base ->$ key ?? null ;
156+ }
157+ return null ;
143158 }
144159
145160 /**
@@ -157,7 +172,7 @@ public static function lookupLength(mixed $base, bool $strict = false): mixed
157172 } elseif (is_string ($ base )) {
158173 return strlen ($ base );
159174 } else {
160- $ v = $ strict ? self ::strictLookup ($ base , 'length ' ) : null ;
175+ $ v = $ strict ? self ::strictLookup ($ base , 'length ' ) : self :: prop ( $ base , ' length ' ) ;
161176 }
162177 return $ v instanceof Closure ? $ v () : $ v ;
163178 }
@@ -216,7 +231,7 @@ public static function lambda(mixed $v): mixed
216231 */
217232 public static function lookupValue (mixed $ _this , string $ name , bool $ strict = false ): mixed
218233 {
219- $ v = $ strict ? self ::strictLookup ($ _this , $ name ) : ($ _this[ $ name] ?? null );
234+ $ v = $ strict ? self ::strictLookup ($ _this , $ name ) : self :: prop ($ _this, $ name );
220235 return $ v instanceof Closure ? $ v ($ _this ) : $ v ;
221236 }
222237
@@ -237,7 +252,7 @@ public static function invokeAmbiguous(RuntimeContext $cx, string $name, mixed &
237252 } elseif ($ strict ) {
238253 $ value = self ::strictLookup ($ _this , $ name );
239254 } else {
240- $ value = $ assumeObjects ? self ::nullCheck ($ _this , $ name ) : ($ _this[ $ name] ?? null );
255+ $ value = $ assumeObjects ? self ::nullCheck ($ _this , $ name ) : self :: prop ($ _this, $ name );
241256 }
242257 if (!$ strict ) {
243258 $ value ??= $ cx ->helpers ['helperMissing ' ];
@@ -260,11 +275,17 @@ public static function compatLookup(RuntimeContext $cx, mixed $in, string $name,
260275 if (is_array ($ in ) && array_key_exists ($ name , $ in )) {
261276 return $ in [$ name ];
262277 }
278+ if (is_object ($ in ) && property_exists ($ in , $ name )) {
279+ return $ in ->$ name ;
280+ }
263281 for ($ i = count ($ cx ->depths ) - 1 ; $ i >= 0 ; $ i --) {
264282 $ ctx = $ cx ->depths [$ i ];
265283 if (is_array ($ ctx ) && array_key_exists ($ name , $ ctx )) {
266284 return $ ctx [$ name ];
267285 }
286+ if (is_object ($ ctx ) && property_exists ($ ctx , $ name )) {
287+ return $ ctx ->$ name ;
288+ }
268289 }
269290 return $ strict ? self ::strictLookup (null , $ name ) : null ;
270291 }
0 commit comments