@@ -27,7 +27,6 @@ zend_object_handlers php_ref_reference_object_handlers;
27
27
php_ref_reference_t * php_ref_reference_init (zval * this_ptr , zval * referent_zv , zval * notifier_zv );
28
28
29
29
static inline void php_ref_store_exceptions (zval * exceptions , zval * tmp );
30
- static int php_ref_reference_check_notifier (zval * notifier , zval * this );
31
30
32
31
//#define PHP_REF_DEBUG 1
33
32
@@ -122,22 +121,18 @@ static void php_ref_call_notifiers(HashTable *references, zval *exceptions, zval
122
121
reference -> referent = NULL ;
123
122
}
124
123
125
- switch (reference -> notifier_type ) {
126
- case PHP_REF_NOTIFIER_ARRAY :
127
- /* array notifier */
128
- add_next_index_zval (& reference -> notifier , & reference -> this_ptr );
129
- Z_ADDREF (reference -> this_ptr );
130
- break ;
131
- case PHP_REF_NOTIFIER_CALLBACK :
132
- /* callback notifier */
133
- php_ref_reference_call_notifier (& reference -> this_ptr , & reference -> notifier );
134
-
135
- if (EG (exception )) {
136
- php_ref_store_exceptions (exceptions , tmp );
137
- }
138
- break ;
139
- default :
140
- break ;
124
+ if (IS_NULL == Z_TYPE (reference -> notifier )) {
125
+ /* notifier is not set */
126
+ break ;
127
+ }
128
+
129
+ /* WeakRef could be destroyed during notifier call, so we need to increment decrement refcount to survive */
130
+ Z_ADDREF (reference -> this_ptr );
131
+ php_ref_reference_call_notifier (& reference -> this_ptr , & reference -> notifier );
132
+ Z_DELREF (reference -> this_ptr );
133
+
134
+ if (EG (exception )) {
135
+ php_ref_store_exceptions (exceptions , tmp );
141
136
}
142
137
143
138
if (!after_dtor && reference -> referent && Z_REFCOUNT (reference -> referent -> this_ptr ) > 1 ) {
@@ -157,8 +152,10 @@ static void php_ref_maybe_restore_handlers(php_ref_referent_t *referent)
157
152
return ;
158
153
}
159
154
160
- Z_OBJ (referent -> this_ptr )-> handlers = referent -> original_handlers ;
161
- referent -> original_handlers = NULL ;
155
+ if (referent -> original_handlers ) {
156
+ Z_OBJ (referent -> this_ptr )-> handlers = referent -> original_handlers ;
157
+ referent -> original_handlers = NULL ;
158
+ }
162
159
}
163
160
164
161
void php_ref_referent_object_dtor_obj (zend_object * object )
@@ -211,6 +208,7 @@ void php_ref_referent_object_dtor_obj(zend_object *object)
211
208
php_ref_create_notifier_exception (& exception , "One or more exceptions thrown during notifiers calling" , & exceptions );
212
209
213
210
zend_throw_exception_object (& exception );
211
+ zval_dtor (& exceptions );
214
212
}
215
213
}
216
214
@@ -238,6 +236,10 @@ void php_ref_referent_abstract_references_ht_dtor(zval *zv)
238
236
if (reference -> referent ) {
239
237
reference -> referent -> tracked -- ;
240
238
php_ref_maybe_restore_handlers (reference -> referent );
239
+
240
+ if (!reference -> referent -> tracked ) {
241
+ zend_hash_index_del (PHP_REF_G (referents ), reference -> referent -> handle );
242
+ }
241
243
}
242
244
243
245
/* clean links to ht & release callbacks as we don't need them already*/
@@ -335,12 +337,6 @@ php_ref_reference_t *php_ref_reference_init(zval *this_ptr, zval *referent_zv, z
335
337
336
338
PHP_REF_REFERENCE_FETCH_INTO (this_ptr , reference );
337
339
338
- int notifier_type = php_ref_reference_check_notifier (notifier_zv , this_ptr );
339
-
340
- if (PHP_REF_NOTIFIER_INVALID == notifier_type ) {
341
- return reference ;
342
- }
343
-
344
340
ZVAL_COPY_VALUE (& reference -> this_ptr , this_ptr );
345
341
346
342
referent = php_ref_referent_get_or_create (referent_zv );
@@ -353,8 +349,6 @@ php_ref_reference_t *php_ref_reference_init(zval *this_ptr, zval *referent_zv, z
353
349
ZVAL_NULL (& reference -> notifier );
354
350
}
355
351
356
- reference -> notifier_type = notifier_type ;
357
-
358
352
return reference ;
359
353
}
360
354
@@ -371,36 +365,6 @@ static inline void php_ref_store_exceptions(zval *exceptions, zval *tmp)
371
365
zend_clear_exception ();
372
366
}
373
367
374
- static int php_ref_reference_check_notifier (zval * notifier , zval * this )
375
- {
376
- if (NULL == notifier ) {
377
- /* no value provided at all, nothing to check */
378
- return PHP_REF_NOTIFIER_NULL ;
379
- }
380
-
381
- if (IS_NULL == Z_TYPE_P (notifier )) {
382
- /* no notifier */
383
- return PHP_REF_NOTIFIER_NULL ;
384
- }
385
-
386
- /* maybe callback notifier */
387
- if (!zend_is_callable (notifier , 0 , NULL )) {
388
-
389
- if (IS_ARRAY == Z_TYPE_P (notifier )) {
390
- /* array notifier */
391
- return PHP_REF_NOTIFIER_ARRAY ;
392
- }
393
-
394
- zend_throw_error (zend_ce_type_error ,
395
- "Argument 2 passed to %s::%s() must be callable, array or null, %s given" ,
396
- ZSTR_VAL (Z_OBJCE_P (this )-> name ), get_active_function_name (), zend_zval_type_name (notifier ));
397
-
398
- return PHP_REF_NOTIFIER_INVALID ;
399
- }
400
-
401
- return PHP_REF_NOTIFIER_CALLBACK ;
402
- }
403
-
404
368
static HashTable * php_ref_reference_gc (zval * object , zval * * table , int * n )
405
369
{
406
370
PHP_REF_REFERENCE_FETCH_INTO (object , reference );
@@ -508,7 +472,6 @@ static zend_object *php_ref_reference_clone_obj(zval *object)
508
472
509
473
ZVAL_OBJ (& new_reference -> this_ptr , new_object );
510
474
ZVAL_COPY (& new_reference -> notifier , & old_reference -> notifier );
511
- new_reference -> notifier_type = old_reference -> notifier_type ;
512
475
513
476
if (old_reference -> referent ) {
514
477
old_reference -> register_reference (new_reference , old_reference -> referent );
@@ -558,42 +521,6 @@ static HashTable *php_ref_get_debug_info(zval *object, int *is_temp)
558
521
return debug_info ;
559
522
}
560
523
561
- static int php_ref_compare_objects (zval * object1 , zval * object2 )
562
- {
563
- zval result ;
564
- int res ;
565
-
566
- PHP_REF_REFERENCE_FETCH_INTO (object1 , reference1 );
567
- PHP_REF_REFERENCE_FETCH_INTO (object2 , reference2 );
568
-
569
- /* Compare referent objects */
570
- if (NULL == reference1 -> referent && NULL == reference2 -> referent ) {
571
- /* skip */
572
- } else if (NULL == reference1 -> referent ) {
573
- return 1 ;
574
- } else if (NULL == reference2 -> referent ) {
575
- return -1 ;
576
- } else {
577
- res = std_object_handlers .compare_objects (& reference1 -> referent -> this_ptr , & reference2 -> referent -> this_ptr );
578
-
579
- if (res != 0 ) {
580
- return res ;
581
- }
582
- }
583
-
584
- /* Compare notifiers */
585
- ZVAL_LONG (& result , 0 );
586
-
587
- compare_function (& result , & reference1 -> notifier , & reference2 -> notifier );
588
-
589
- if (Z_LVAL (result ) != 0 ) {
590
- return (int ) Z_LVAL (result );
591
- }
592
-
593
- /* Compare standard objects */
594
- return std_object_handlers .compare_objects (object1 , object2 );
595
- }
596
-
597
524
static PHP_METHOD (WeakReference , __construct )
598
525
{
599
526
zval * referent_zv ;
@@ -647,29 +574,19 @@ static PHP_METHOD(WeakReference, notifier)
647
574
}
648
575
649
576
/* Change existent notifier */
650
-
651
- int notifier_type = php_ref_reference_check_notifier (notifier_zv , getThis ());
652
-
653
- if (PHP_REF_NOTIFIER_INVALID == notifier_type ) {
654
- return ;
655
- }
656
-
657
577
RETVAL_ZVAL (& reference -> notifier , 1 , 1 );
658
578
659
579
if (NULL == notifier_zv ) {
660
580
ZVAL_NULL (& reference -> notifier );
661
581
} else {
662
582
ZVAL_COPY (& reference -> notifier , notifier_zv );
663
583
}
664
-
665
- reference -> notifier_type = notifier_type ;
666
-
667
584
}
668
585
669
586
670
587
ZEND_BEGIN_ARG_INFO_EX (arginfo_ref_reference___construct , ZEND_SEND_BY_VAL , ZEND_RETURN_VALUE , 1 )
671
588
ZEND_ARG_INFO (0 , referent )
672
- ZEND_ARG_INFO (0 , notify )
589
+ ZEND_ARG_CALLABLE_INFO (0 , notify , 1 )
673
590
ZEND_END_ARG_INFO ()
674
591
675
592
ZEND_BEGIN_ARG_INFO_EX (arginfo_ref_reference_get , ZEND_SEND_BY_VAL , ZEND_RETURN_VALUE , 0 )
@@ -678,8 +595,8 @@ ZEND_END_ARG_INFO()
678
595
PHP_REF_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX (arginfo_ref_reference_valid , ZEND_RETURN_VALUE , 0 , _IS_BOOL , 0 )
679
596
ZEND_END_ARG_INFO ()
680
597
681
- ZEND_BEGIN_ARG_INFO_EX (arginfo_ref_reference_notifier , ZEND_SEND_BY_VAL , ZEND_RETURN_VALUE , 0 )
682
- ZEND_ARG_INFO (0 , notify )
598
+ PHP_REF_ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX (arginfo_ref_reference_notifier , ZEND_SEND_BY_VAL , 0 , IS_CALLABLE , 1 )
599
+ ZEND_ARG_CALLABLE_INFO (0 , notify , 1 )
683
600
ZEND_END_ARG_INFO ()
684
601
685
602
@@ -721,7 +638,6 @@ PHP_MINIT_FUNCTION (php_ref_reference)
721
638
php_ref_reference_object_handlers .get_gc = php_ref_reference_gc ;
722
639
php_ref_reference_object_handlers .clone_obj = php_ref_reference_clone_obj ;
723
640
php_ref_reference_object_handlers .get_debug_info = php_ref_get_debug_info ;
724
- php_ref_reference_object_handlers .compare_objects = php_ref_compare_objects ;
725
641
726
642
INIT_NS_CLASS_ENTRY (ce , PHP_REF_NS , "SoftReference" , php_ref_weak_reference_methods );
727
643
php_ref_soft_reference_class_entry = zend_register_internal_class_ex (& ce , php_ref_abstract_reference_class_entry );
0 commit comments