cseiler         Tue Jun 30 17:14:38 2009 UTC

  Added files:                 (Branch: PHP_5_3)
    /php-src/ext/spl/tests      spl_autoload_013.phpt spl_autoload_014.phpt 

  Modified files:              
    /php-src    NEWS 
    /php-src/ext/spl    php_spl.c 
    /php-src/ext/spl/tests      spl_autoload_bug48541.phpt 
  Log:
  MFH: spl_autoload_unregister/spl_autoload_functions and closures
  
  
http://cvs.php.net/viewvc.cgi/php-src/NEWS?r1=1.2027.2.547.2.965.2.659&r2=1.2027.2.547.2.965.2.660&diff_format=u
Index: php-src/NEWS
diff -u php-src/NEWS:1.2027.2.547.2.965.2.659 
php-src/NEWS:1.2027.2.547.2.965.2.660
--- php-src/NEWS:1.2027.2.547.2.965.2.659       Tue Jun 30 16:17:30 2009
+++ php-src/NEWS        Tue Jun 30 17:14:37 2009
@@ -2,6 +2,9 @@
 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
 ?? ??? 2009, PHP 5.3.1
 
+- Fixed spl_autoload_unregister/spl_autoad_functions wrt. Closures and
+  Functors. (Christian Seiler)
+
 - Fixed bug #48681 (openssl signature verification for tar archives broken).
   (Greg)
 - Fixed bug #47351 (Memory leak in DateTime). (Derick, Tobias John)
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/php_spl.c?r1=1.52.2.28.2.17.2.38&r2=1.52.2.28.2.17.2.39&diff_format=u
Index: php-src/ext/spl/php_spl.c
diff -u php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.38 
php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.39
--- php-src/ext/spl/php_spl.c:1.52.2.28.2.17.2.38       Sat Jun 13 17:30:50 2009
+++ php-src/ext/spl/php_spl.c   Tue Jun 30 17:14:37 2009
@@ -16,7 +16,7 @@
    +----------------------------------------------------------------------+
  */
 
-/* $Id: php_spl.c,v 1.52.2.28.2.17.2.38 2009/06/13 17:30:50 cellog Exp $ */
+/* $Id: php_spl.c,v 1.52.2.28.2.17.2.39 2009/06/30 17:14:37 cseiler Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -509,10 +509,10 @@
                        alfi.closure = zcallable;
                        Z_ADDREF_P(zcallable);
 
-                       lc_name = erealloc(lc_name, func_name_len + 2 + 
sizeof(zcallable->value.obj.handle));
-                       memcpy(lc_name + func_name_len, 
&(zcallable->value.obj.handle),
-                               sizeof(zcallable->value.obj.handle));
-                       func_name_len += sizeof(zcallable->value.obj.handle);
+                       lc_name = erealloc(lc_name, func_name_len + 2 + 
sizeof(zend_object_handle));
+                       memcpy(lc_name + func_name_len, 
&Z_OBJ_HANDLE_P(zcallable),
+                               sizeof(zend_object_handle));
+                       func_name_len += sizeof(zend_object_handle);
                        lc_name[func_name_len] = '\0';
                }
 
@@ -579,6 +579,7 @@
 {
        char *func_name, *error = NULL;
        int func_name_len;
+       char *lc_name = NULL;
        zval *zcallable;
        int success = FAILURE;
        zend_function *spl_func_ptr;
@@ -604,10 +605,20 @@
                efree(error);
        }
 
-       zend_str_tolower(func_name, func_name_len);
+       lc_name = safe_emalloc(func_name_len, 1, sizeof(long) + 1);
+       zend_str_tolower_copy(lc_name, func_name, func_name_len);
+       efree(func_name);
+
+       if (Z_TYPE_P(zcallable) == IS_OBJECT) {
+               lc_name = erealloc(lc_name, func_name_len + 2 + 
sizeof(zend_object_handle));
+               memcpy(lc_name + func_name_len, &Z_OBJ_HANDLE_P(zcallable),
+                       sizeof(zend_object_handle));
+               func_name_len += sizeof(zend_object_handle);
+               lc_name[func_name_len] = '\0';
+       }
 
        if (SPL_G(autoload_functions)) {
-               if (func_name_len == sizeof("spl_autoload_call")-1 && 
!strcmp(func_name, "spl_autoload_call")) {
+               if (func_name_len == sizeof("spl_autoload_call")-1 && 
!strcmp(lc_name, "spl_autoload_call")) {
                        /* remove all */
                        zend_hash_destroy(SPL_G(autoload_functions));
                        FREE_HASHTABLE(SPL_G(autoload_functions));
@@ -616,16 +627,16 @@
                        success = SUCCESS;
                } else {
                        /* remove specific */
-                       success = zend_hash_del(SPL_G(autoload_functions), 
func_name, func_name_len+1);
+                       success = zend_hash_del(SPL_G(autoload_functions), 
lc_name, func_name_len+1);
                        if (success != SUCCESS && obj_ptr) {
-                               func_name = erealloc(func_name, func_name_len + 
1 + sizeof(zend_object_handle));
-                               memcpy(func_name + func_name_len, 
&Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle));
+                               lc_name = erealloc(lc_name, func_name_len + 2 + 
sizeof(zend_object_handle));
+                               memcpy(lc_name + func_name_len, 
&Z_OBJ_HANDLE_P(obj_ptr), sizeof(zend_object_handle));
                                func_name_len += sizeof(zend_object_handle);
-                               func_name[func_name_len] = '\0';
-                               success = 
zend_hash_del(SPL_G(autoload_functions), func_name, func_name_len+1);
+                               lc_name[func_name_len] = '\0';
+                               success = 
zend_hash_del(SPL_G(autoload_functions), lc_name, func_name_len+1);
                        }
                }
-       } else if (func_name_len == sizeof("spl_autoload")-1 && 
!strcmp(func_name, "spl_autoload")) {
+       } else if (func_name_len == sizeof("spl_autoload")-1 && 
!strcmp(lc_name, "spl_autoload")) {
                /* register single spl_autoload() */
                zend_hash_find(EG(function_table), "spl_autoload", 
sizeof("spl_autoload"), (void **) &spl_func_ptr);
 
@@ -635,7 +646,7 @@
                }
        }
 
-       efree(func_name);
+       efree(lc_name);
        RETURN_BOOL(success == SUCCESS);
 } /* }}} */
 
@@ -663,7 +674,10 @@
                zend_hash_internal_pointer_reset_ex(SPL_G(autoload_functions), 
&function_pos);
                while(zend_hash_has_more_elements_ex(SPL_G(autoload_functions), 
&function_pos) == SUCCESS) {
                        
zend_hash_get_current_data_ex(SPL_G(autoload_functions), (void **) &alfi, 
&function_pos);
-                       if (alfi->func_ptr->common.scope) {
+                       if (alfi->closure) {
+                               Z_ADDREF_P(alfi->closure);
+                               add_next_index_zval(return_value, 
alfi->closure);
+                       } else if (alfi->func_ptr->common.scope) {
                                zval *tmp;
                                MAKE_STD_ZVAL(tmp);
                                array_init(tmp);
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/spl_autoload_bug48541.phpt?r1=1.1.2.2&r2=1.1.2.3&diff_format=u
Index: php-src/ext/spl/tests/spl_autoload_bug48541.phpt
diff -u php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.1.2.2 
php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.1.2.3
--- php-src/ext/spl/tests/spl_autoload_bug48541.phpt:1.1.2.2    Sat Jun 13 
17:30:50 2009
+++ php-src/ext/spl/tests/spl_autoload_bug48541.phpt    Tue Jun 30 17:14:37 2009
@@ -2,23 +2,38 @@
 SPL: spl_autoload_register() Bug #48541: registering multiple closures fails 
with memleaks
 --FILE--
 <?php
+
+class X {
+  public function getClosure() {
+    return function($class) {
+      echo "a2 called\n";
+    };
+  }
+}
+
 $a = function ($class) {
     echo "a called\n";
 };
+$x = new X;
+$a2 = $x->getClosure();
 $b = function ($class) {
     eval('class ' . $class . '{function __construct(){echo "foo\n";}}');
     echo "b called\n";
 };
 spl_autoload_register($a);
+spl_autoload_register($a2);
 spl_autoload_register($b);
 
 $c = $a;
+$c2 = $a2;
 spl_autoload_register($c);
+spl_autoload_register($c2);
 $c = new foo;
 ?>
 ===DONE===
 --EXPECT--
 a called
+a2 called
 b called
 foo
 ===DONE===
\ No newline at end of file

http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/spl_autoload_013.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/spl_autoload_013.phpt
+++ php-src/ext/spl/tests/spl_autoload_013.phpt
--TEST--
SPL: spl_autoload_functions() with closures and invokables
--FILE--
<?php
$closure = function($class) {
  echo "a called\n";
};

class Autoloader {
  private $dir;
  public function __construct($dir) {
    $this->dir = $dir;
  }
  public function __invoke($class) {
    var_dump("{$this->dir}/$class.php");
  }
}

$al1 = new Autoloader('d1');
$al2 = new Autoloader('d2');

spl_autoload_register($closure);
spl_autoload_register($al1);
spl_autoload_register($al2);

var_dump(spl_autoload_functions());

?>
===DONE===
--EXPECTF--
array(3) {
  [0]=>
  object(Closure)#%d (2) {
    ["this"]=>
    NULL
    ["parameter"]=>
    array(1) {
      ["$class"]=>
      string(10) "<required>"
    }
  }
  [1]=>
  object(Autoloader)#%d (1) {
    [u"dir":u"Autoloader":private]=>
    unicode(2) "d1"
  }
  [2]=>
  object(Autoloader)#%d (1) {
    [u"dir":u"Autoloader":private]=>
    unicode(2) "d2"
  }
}
===DONE===
http://cvs.php.net/viewvc.cgi/php-src/ext/spl/tests/spl_autoload_014.phpt?view=markup&rev=1.1
Index: php-src/ext/spl/tests/spl_autoload_014.phpt
+++ php-src/ext/spl/tests/spl_autoload_014.phpt
--TEST--
SPL: spl_autoload_unregister() with closures and invokables
--FILE--
<?php
$closure = function($class) {
  echo "closure called with class $class\n";
};

class Autoloader {
  private $dir;
  public function __construct($dir) {
    $this->dir = $dir;
  }
  public function __invoke($class) {
    echo ("Autoloader('{$this->dir}') called with $class\n");
  }
}

class WorkingAutoloader {
  public function __invoke($class) {
    echo ("WorkingAutoloader() called with $class\n");
    eval("class $class { }");
  }
}

$al1 = new Autoloader('d1');
$al2 = new WorkingAutoloader('d2');

spl_autoload_register($closure);
spl_autoload_register($al1);
spl_autoload_register($al2);

$x = new TestX;

spl_autoload_unregister($closure);
spl_autoload_unregister($al1);

$y = new TestY;

?>
===DONE===
--EXPECT--
closure called with class TestX
Autoloader('d1') called with TestX
WorkingAutoloader() called with TestX
WorkingAutoloader() called with TestY
===DONE===
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to